diff options
Diffstat (limited to 'sound/drivers')
-rw-r--r-- | sound/drivers/serial-u16550.c | 221 |
1 files changed, 123 insertions, 98 deletions
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 74028b2219c2..3a86a5820726 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -117,13 +117,13 @@ MODULE_PARM_DESC(adaptor, "Type of adaptor."); | |||
117 | #define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) | 117 | #define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) |
118 | #define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) | 118 | #define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) |
119 | 119 | ||
120 | typedef struct _snd_uart16550 { | 120 | struct snd_uart16550 { |
121 | struct snd_card *card; | 121 | struct snd_card *card; |
122 | struct snd_rawmidi *rmidi; | 122 | struct snd_rawmidi *rmidi; |
123 | struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; | 123 | struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; |
124 | struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; | 124 | struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; |
125 | 125 | ||
126 | int filemode; //open status of file | 126 | int filemode; /* open status of file */ |
127 | 127 | ||
128 | spinlock_t open_lock; | 128 | spinlock_t open_lock; |
129 | 129 | ||
@@ -140,39 +140,39 @@ typedef struct _snd_uart16550 { | |||
140 | unsigned char old_divisor_msb; | 140 | unsigned char old_divisor_msb; |
141 | unsigned char old_line_ctrl_reg; | 141 | unsigned char old_line_ctrl_reg; |
142 | 142 | ||
143 | // parameter for using of write loop | 143 | /* parameter for using of write loop */ |
144 | short int fifo_limit; //used in uart16550 | 144 | short int fifo_limit; /* used in uart16550 */ |
145 | short int fifo_count; //used in uart16550 | 145 | short int fifo_count; /* used in uart16550 */ |
146 | 146 | ||
147 | // type of adaptor | 147 | /* type of adaptor */ |
148 | int adaptor; | 148 | int adaptor; |
149 | 149 | ||
150 | // inputs | 150 | /* inputs */ |
151 | int prev_in; | 151 | int prev_in; |
152 | unsigned char rstatus; | 152 | unsigned char rstatus; |
153 | 153 | ||
154 | // outputs | 154 | /* outputs */ |
155 | int prev_out; | 155 | int prev_out; |
156 | unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; | 156 | unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; |
157 | 157 | ||
158 | // write buffer and its writing/reading position | 158 | /* write buffer and its writing/reading position */ |
159 | unsigned char tx_buff[TX_BUFF_SIZE]; | 159 | unsigned char tx_buff[TX_BUFF_SIZE]; |
160 | int buff_in_count; | 160 | int buff_in_count; |
161 | int buff_in; | 161 | int buff_in; |
162 | int buff_out; | 162 | int buff_out; |
163 | int drop_on_full; | 163 | int drop_on_full; |
164 | 164 | ||
165 | // wait timer | 165 | /* wait timer */ |
166 | unsigned int timer_running:1; | 166 | unsigned int timer_running:1; |
167 | struct timer_list buffer_timer; | 167 | struct timer_list buffer_timer; |
168 | 168 | ||
169 | } snd_uart16550_t; | 169 | }; |
170 | 170 | ||
171 | static struct platform_device *devices[SNDRV_CARDS]; | 171 | static struct platform_device *devices[SNDRV_CARDS]; |
172 | 172 | ||
173 | static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) | 173 | static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) |
174 | { | 174 | { |
175 | if (! uart->timer_running) { | 175 | if (!uart->timer_running) { |
176 | /* timer 38600bps * 10bit * 16byte */ | 176 | /* timer 38600bps * 10bit * 16byte */ |
177 | uart->buffer_timer.expires = jiffies + (HZ+255)/256; | 177 | uart->buffer_timer.expires = jiffies + (HZ+255)/256; |
178 | uart->timer_running = 1; | 178 | uart->timer_running = 1; |
@@ -180,7 +180,7 @@ static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) | |||
180 | } | 180 | } |
181 | } | 181 | } |
182 | 182 | ||
183 | static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) | 183 | static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart) |
184 | { | 184 | { |
185 | if (uart->timer_running) { | 185 | if (uart->timer_running) { |
186 | del_timer(&uart->buffer_timer); | 186 | del_timer(&uart->buffer_timer); |
@@ -189,10 +189,10 @@ static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | /* This macro is only used in snd_uart16550_io_loop */ | 191 | /* This macro is only used in snd_uart16550_io_loop */ |
192 | static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) | 192 | static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart) |
193 | { | 193 | { |
194 | unsigned short buff_out = uart->buff_out; | 194 | unsigned short buff_out = uart->buff_out; |
195 | if( uart->buff_in_count > 0 ) { | 195 | if (uart->buff_in_count > 0) { |
196 | outb(uart->tx_buff[buff_out], uart->base + UART_TX); | 196 | outb(uart->tx_buff[buff_out], uart->base + UART_TX); |
197 | uart->fifo_count++; | 197 | uart->fifo_count++; |
198 | buff_out++; | 198 | buff_out++; |
@@ -206,7 +206,7 @@ static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) | |||
206 | * We don't want to interrupt this, | 206 | * We don't want to interrupt this, |
207 | * as we're already handling an interrupt | 207 | * as we're already handling an interrupt |
208 | */ | 208 | */ |
209 | static void snd_uart16550_io_loop(snd_uart16550_t * uart) | 209 | static void snd_uart16550_io_loop(struct snd_uart16550 * uart) |
210 | { | 210 | { |
211 | unsigned char c, status; | 211 | unsigned char c, status; |
212 | int substream; | 212 | int substream; |
@@ -220,9 +220,8 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) | |||
220 | c = inb(uart->base + UART_RX); | 220 | c = inb(uart->base + UART_RX); |
221 | 221 | ||
222 | /* keep track of last status byte */ | 222 | /* keep track of last status byte */ |
223 | if (c & 0x80) { | 223 | if (c & 0x80) |
224 | uart->rstatus = c; | 224 | uart->rstatus = c; |
225 | } | ||
226 | 225 | ||
227 | /* handle stream switch */ | 226 | /* handle stream switch */ |
228 | if (uart->adaptor == SNDRV_SERIAL_GENERIC) { | 227 | if (uart->adaptor == SNDRV_SERIAL_GENERIC) { |
@@ -230,14 +229,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) | |||
230 | if (c <= SNDRV_SERIAL_MAX_INS && c > 0) | 229 | if (c <= SNDRV_SERIAL_MAX_INS && c > 0) |
231 | substream = c - 1; | 230 | substream = c - 1; |
232 | if (c != 0xf5) | 231 | if (c != 0xf5) |
233 | uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */ | 232 | /* prevent future bytes from being |
234 | } | 233 | interpreted as streams */ |
235 | else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { | 234 | uart->rstatus = 0; |
236 | snd_rawmidi_receive(uart->midi_input[substream], &c, 1); | 235 | } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) |
237 | } | 236 | && uart->midi_input[substream]) |
238 | } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { | 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]) | ||
239 | snd_rawmidi_receive(uart->midi_input[substream], &c, 1); | 241 | snd_rawmidi_receive(uart->midi_input[substream], &c, 1); |
240 | } | ||
241 | 242 | ||
242 | if (status & UART_LSR_OE) | 243 | if (status & UART_LSR_OE) |
243 | snd_printk("%s: Overrun on device at 0x%lx\n", | 244 | snd_printk("%s: Overrun on device at 0x%lx\n", |
@@ -250,21 +251,20 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) | |||
250 | /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, | 251 | /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, |
251 | buffer is never filled. */ | 252 | buffer is never filled. */ |
252 | /* Check write status */ | 253 | /* Check write status */ |
253 | if (status & UART_LSR_THRE) { | 254 | if (status & UART_LSR_THRE) |
254 | uart->fifo_count = 0; | 255 | uart->fifo_count = 0; |
255 | } | ||
256 | if (uart->adaptor == SNDRV_SERIAL_MS124W_SA | 256 | if (uart->adaptor == SNDRV_SERIAL_MS124W_SA |
257 | || uart->adaptor == SNDRV_SERIAL_GENERIC) { | 257 | || uart->adaptor == SNDRV_SERIAL_GENERIC) { |
258 | /* Can't use FIFO, must send only when CTS is true */ | 258 | /* Can't use FIFO, must send only when CTS is true */ |
259 | status = inb(uart->base + UART_MSR); | 259 | status = inb(uart->base + UART_MSR); |
260 | while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) && | 260 | while (uart->fifo_count == 0 && (status & UART_MSR_CTS) && |
261 | (uart->buff_in_count > 0) ) { | 261 | uart->buff_in_count > 0) { |
262 | snd_uart16550_buffer_output(uart); | 262 | snd_uart16550_buffer_output(uart); |
263 | status = inb( uart->base + UART_MSR ); | 263 | status = inb(uart->base + UART_MSR); |
264 | } | 264 | } |
265 | } else { | 265 | } else { |
266 | /* Write loop */ | 266 | /* Write loop */ |
267 | while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ | 267 | while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ |
268 | && uart->buff_in_count > 0) /* Do we want to? */ | 268 | && uart->buff_in_count > 0) /* Do we want to? */ |
269 | snd_uart16550_buffer_output(uart); | 269 | snd_uart16550_buffer_output(uart); |
270 | } | 270 | } |
@@ -294,15 +294,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart) | |||
294 | */ | 294 | */ |
295 | static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) | 295 | static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) |
296 | { | 296 | { |
297 | snd_uart16550_t *uart; | 297 | struct snd_uart16550 *uart; |
298 | 298 | ||
299 | uart = (snd_uart16550_t *) dev_id; | 299 | uart = dev_id; |
300 | spin_lock(&uart->open_lock); | 300 | spin_lock(&uart->open_lock); |
301 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) { | 301 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) { |
302 | spin_unlock(&uart->open_lock); | 302 | spin_unlock(&uart->open_lock); |
303 | return IRQ_NONE; | 303 | return IRQ_NONE; |
304 | } | 304 | } |
305 | inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */ | 305 | /* indicate to the UART that the interrupt has been serviced */ |
306 | inb(uart->base + UART_IIR); | ||
306 | snd_uart16550_io_loop(uart); | 307 | snd_uart16550_io_loop(uart); |
307 | spin_unlock(&uart->open_lock); | 308 | spin_unlock(&uart->open_lock); |
308 | return IRQ_HANDLED; | 309 | return IRQ_HANDLED; |
@@ -312,9 +313,9 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) | |||
312 | static void snd_uart16550_buffer_timer(unsigned long data) | 313 | static void snd_uart16550_buffer_timer(unsigned long data) |
313 | { | 314 | { |
314 | unsigned long flags; | 315 | unsigned long flags; |
315 | snd_uart16550_t *uart; | 316 | struct snd_uart16550 *uart; |
316 | 317 | ||
317 | uart = (snd_uart16550_t *)data; | 318 | uart = (struct snd_uart16550 *)data; |
318 | spin_lock_irqsave(&uart->open_lock, flags); | 319 | spin_lock_irqsave(&uart->open_lock, flags); |
319 | snd_uart16550_del_timer(uart); | 320 | snd_uart16550_del_timer(uart); |
320 | snd_uart16550_io_loop(uart); | 321 | snd_uart16550_io_loop(uart); |
@@ -326,7 +327,7 @@ static void snd_uart16550_buffer_timer(unsigned long data) | |||
326 | * return 0 if found | 327 | * return 0 if found |
327 | * return negative error if not found | 328 | * return negative error if not found |
328 | */ | 329 | */ |
329 | static int __init snd_uart16550_detect(snd_uart16550_t *uart) | 330 | static int __init snd_uart16550_detect(struct snd_uart16550 *uart) |
330 | { | 331 | { |
331 | unsigned long io_base = uart->base; | 332 | unsigned long io_base = uart->base; |
332 | int ok; | 333 | int ok; |
@@ -343,7 +344,8 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart) | |||
343 | return -EBUSY; | 344 | return -EBUSY; |
344 | } | 345 | } |
345 | 346 | ||
346 | ok = 1; /* uart detected unless one of the following tests should fail */ | 347 | /* uart detected unless one of the following tests should fail */ |
348 | ok = 1; | ||
347 | /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ | 349 | /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ |
348 | outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ | 350 | outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ |
349 | c = inb(io_base + UART_IER); | 351 | c = inb(io_base + UART_IER); |
@@ -368,7 +370,7 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart) | |||
368 | return ok; | 370 | return ok; |
369 | } | 371 | } |
370 | 372 | ||
371 | static void snd_uart16550_do_open(snd_uart16550_t * uart) | 373 | static void snd_uart16550_do_open(struct snd_uart16550 * uart) |
372 | { | 374 | { |
373 | char byte; | 375 | char byte; |
374 | 376 | ||
@@ -460,7 +462,7 @@ static void snd_uart16550_do_open(snd_uart16550_t * uart) | |||
460 | inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ | 462 | inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ |
461 | } | 463 | } |
462 | 464 | ||
463 | static void snd_uart16550_do_close(snd_uart16550_t * uart) | 465 | static void snd_uart16550_do_close(struct snd_uart16550 * uart) |
464 | { | 466 | { |
465 | if (uart->irq < 0) | 467 | if (uart->irq < 0) |
466 | snd_uart16550_del_timer(uart); | 468 | snd_uart16550_del_timer(uart); |
@@ -514,7 +516,7 @@ static void snd_uart16550_do_close(snd_uart16550_t * uart) | |||
514 | static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) | 516 | static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) |
515 | { | 517 | { |
516 | unsigned long flags; | 518 | unsigned long flags; |
517 | snd_uart16550_t *uart = substream->rmidi->private_data; | 519 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
518 | 520 | ||
519 | spin_lock_irqsave(&uart->open_lock, flags); | 521 | spin_lock_irqsave(&uart->open_lock, flags); |
520 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) | 522 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) |
@@ -528,7 +530,7 @@ static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) | |||
528 | static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) | 530 | static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) |
529 | { | 531 | { |
530 | unsigned long flags; | 532 | unsigned long flags; |
531 | snd_uart16550_t *uart = substream->rmidi->private_data; | 533 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
532 | 534 | ||
533 | spin_lock_irqsave(&uart->open_lock, flags); | 535 | spin_lock_irqsave(&uart->open_lock, flags); |
534 | uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; | 536 | uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; |
@@ -539,24 +541,24 @@ static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) | |||
539 | return 0; | 541 | return 0; |
540 | } | 542 | } |
541 | 543 | ||
542 | static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up) | 544 | static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, |
545 | int up) | ||
543 | { | 546 | { |
544 | unsigned long flags; | 547 | unsigned long flags; |
545 | snd_uart16550_t *uart = substream->rmidi->private_data; | 548 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
546 | 549 | ||
547 | spin_lock_irqsave(&uart->open_lock, flags); | 550 | spin_lock_irqsave(&uart->open_lock, flags); |
548 | if (up) { | 551 | if (up) |
549 | uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; | 552 | uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; |
550 | } else { | 553 | else |
551 | uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; | 554 | uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; |
552 | } | ||
553 | spin_unlock_irqrestore(&uart->open_lock, flags); | 555 | spin_unlock_irqrestore(&uart->open_lock, flags); |
554 | } | 556 | } |
555 | 557 | ||
556 | static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) | 558 | static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) |
557 | { | 559 | { |
558 | unsigned long flags; | 560 | unsigned long flags; |
559 | snd_uart16550_t *uart = substream->rmidi->private_data; | 561 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
560 | 562 | ||
561 | spin_lock_irqsave(&uart->open_lock, flags); | 563 | spin_lock_irqsave(&uart->open_lock, flags); |
562 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) | 564 | if (uart->filemode == SERIAL_MODE_NOT_OPENED) |
@@ -570,7 +572,7 @@ static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) | |||
570 | static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) | 572 | static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) |
571 | { | 573 | { |
572 | unsigned long flags; | 574 | unsigned long flags; |
573 | snd_uart16550_t *uart = substream->rmidi->private_data; | 575 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
574 | 576 | ||
575 | spin_lock_irqsave(&uart->open_lock, flags); | 577 | spin_lock_irqsave(&uart->open_lock, flags); |
576 | uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; | 578 | uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; |
@@ -581,18 +583,20 @@ static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) | |||
581 | return 0; | 583 | return 0; |
582 | }; | 584 | }; |
583 | 585 | ||
584 | static inline int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) | 586 | static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart, |
587 | int Num) | ||
585 | { | 588 | { |
586 | if( uart->buff_in_count + Num < TX_BUFF_SIZE ) | 589 | if (uart->buff_in_count + Num < TX_BUFF_SIZE) |
587 | return 1; | 590 | return 1; |
588 | else | 591 | else |
589 | return 0; | 592 | return 0; |
590 | } | 593 | } |
591 | 594 | ||
592 | static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) | 595 | static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart, |
596 | unsigned char byte) | ||
593 | { | 597 | { |
594 | unsigned short buff_in = uart->buff_in; | 598 | unsigned short buff_in = uart->buff_in; |
595 | if( uart->buff_in_count < TX_BUFF_SIZE ) { | 599 | if (uart->buff_in_count < TX_BUFF_SIZE) { |
596 | uart->tx_buff[buff_in] = byte; | 600 | uart->tx_buff[buff_in] = byte; |
597 | buff_in++; | 601 | buff_in++; |
598 | buff_in &= TX_BUFF_MASK; | 602 | buff_in &= TX_BUFF_MASK; |
@@ -605,12 +609,14 @@ static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned cha | |||
605 | return 0; | 609 | return 0; |
606 | } | 610 | } |
607 | 611 | ||
608 | static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_substream *substream, unsigned char midi_byte) | 612 | static int snd_uart16550_output_byte(struct snd_uart16550 *uart, |
613 | struct snd_rawmidi_substream *substream, | ||
614 | unsigned char midi_byte) | ||
609 | { | 615 | { |
610 | if (uart->buff_in_count == 0 /* Buffer empty? */ | 616 | if (uart->buff_in_count == 0 /* Buffer empty? */ |
611 | && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && | 617 | && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && |
612 | uart->adaptor != SNDRV_SERIAL_GENERIC) || | 618 | uart->adaptor != SNDRV_SERIAL_GENERIC) || |
613 | (uart->fifo_count == 0 /* FIFO empty? */ | 619 | (uart->fifo_count == 0 /* FIFO empty? */ |
614 | && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ | 620 | && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ |
615 | 621 | ||
616 | /* Tx Buffer Empty - try to write immediately */ | 622 | /* Tx Buffer Empty - try to write immediately */ |
@@ -623,12 +629,13 @@ static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_s | |||
623 | uart->fifo_count++; | 629 | uart->fifo_count++; |
624 | outb(midi_byte, uart->base + UART_TX); | 630 | outb(midi_byte, uart->base + UART_TX); |
625 | } else { | 631 | } else { |
626 | /* Cannot write (buffer empty) - put char in buffer */ | 632 | /* Cannot write (buffer empty) - |
633 | * put char in buffer */ | ||
627 | snd_uart16550_write_buffer(uart, midi_byte); | 634 | snd_uart16550_write_buffer(uart, midi_byte); |
628 | } | 635 | } |
629 | } | 636 | } |
630 | } else { | 637 | } else { |
631 | if( !snd_uart16550_write_buffer(uart, midi_byte) ) { | 638 | if (!snd_uart16550_write_buffer(uart, midi_byte)) { |
632 | snd_printk("%s: Buffer overrun on device at 0x%lx\n", | 639 | snd_printk("%s: Buffer overrun on device at 0x%lx\n", |
633 | uart->rmidi->name, uart->base); | 640 | uart->rmidi->name, uart->base); |
634 | return 0; | 641 | return 0; |
@@ -642,9 +649,9 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) | |||
642 | { | 649 | { |
643 | unsigned long flags; | 650 | unsigned long flags; |
644 | unsigned char midi_byte, addr_byte; | 651 | unsigned char midi_byte, addr_byte; |
645 | snd_uart16550_t *uart = substream->rmidi->private_data; | 652 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
646 | char first; | 653 | char first; |
647 | static unsigned long lasttime=0; | 654 | static unsigned long lasttime = 0; |
648 | 655 | ||
649 | /* Interupts are disabled during the updating of the tx_buff, | 656 | /* Interupts are disabled during the updating of the tx_buff, |
650 | * since it is 'bad' to have two processes updating the same | 657 | * since it is 'bad' to have two processes updating the same |
@@ -653,7 +660,7 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) | |||
653 | 660 | ||
654 | spin_lock_irqsave(&uart->open_lock, flags); | 661 | spin_lock_irqsave(&uart->open_lock, flags); |
655 | 662 | ||
656 | if (uart->irq < 0) //polling | 663 | if (uart->irq < 0) /* polling */ |
657 | snd_uart16550_io_loop(uart); | 664 | snd_uart16550_io_loop(uart); |
658 | 665 | ||
659 | if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { | 666 | if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { |
@@ -671,7 +678,8 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) | |||
671 | /* select any combination of the four ports */ | 678 | /* select any combination of the four ports */ |
672 | addr_byte = (substream->number << 4) | 0x08; | 679 | addr_byte = (substream->number << 4) | 0x08; |
673 | /* ...except none */ | 680 | /* ...except none */ |
674 | if (addr_byte == 0x08) addr_byte = 0xf8; | 681 | if (addr_byte == 0x08) |
682 | addr_byte = 0xf8; | ||
675 | #endif | 683 | #endif |
676 | snd_uart16550_output_byte(uart, substream, addr_byte); | 684 | snd_uart16550_output_byte(uart, substream, addr_byte); |
677 | /* send midi byte */ | 685 | /* send midi byte */ |
@@ -679,31 +687,42 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) | |||
679 | } | 687 | } |
680 | } else { | 688 | } else { |
681 | first = 0; | 689 | first = 0; |
682 | while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) { | 690 | while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) { |
683 | /* Also send F5 after 3 seconds with no data to handle device disconnect */ | 691 | /* Also send F5 after 3 seconds with no data |
684 | if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || | 692 | * to handle device disconnect */ |
685 | uart->adaptor == SNDRV_SERIAL_GENERIC) && | 693 | if (first == 0 && |
686 | (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) { | 694 | (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || |
687 | 695 | uart->adaptor == SNDRV_SERIAL_GENERIC) && | |
688 | if( snd_uart16550_buffer_can_write( uart, 3 ) ) { | 696 | (uart->prev_out != substream->number || |
697 | jiffies-lasttime > 3*HZ)) { | ||
698 | |||
699 | if (snd_uart16550_buffer_can_write(uart, 3)) { | ||
689 | /* Roland Soundcanvas part selection */ | 700 | /* Roland Soundcanvas part selection */ |
690 | /* If this substream of the data is different previous | 701 | /* If this substream of the data is |
691 | substream in this uart, send the change part event */ | 702 | * different previous substream |
703 | * in this uart, send the change part | ||
704 | * event | ||
705 | */ | ||
692 | uart->prev_out = substream->number; | 706 | uart->prev_out = substream->number; |
693 | /* change part */ | 707 | /* change part */ |
694 | snd_uart16550_output_byte(uart, substream, 0xf5); | 708 | snd_uart16550_output_byte(uart, substream, |
709 | 0xf5); | ||
695 | /* data */ | 710 | /* data */ |
696 | snd_uart16550_output_byte(uart, substream, uart->prev_out + 1); | 711 | snd_uart16550_output_byte(uart, substream, |
697 | /* If midi_byte is a data byte, send the previous status byte */ | 712 | uart->prev_out + 1); |
698 | if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)) | 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) | ||
699 | snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); | 717 | snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); |
700 | } else if( !uart->drop_on_full ) | 718 | } else if (!uart->drop_on_full) |
701 | break; | 719 | break; |
702 | 720 | ||
703 | } | 721 | } |
704 | 722 | ||
705 | /* send midi byte */ | 723 | /* send midi byte */ |
706 | if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full ) | 724 | if (!snd_uart16550_output_byte(uart, substream, midi_byte) && |
725 | !uart->drop_on_full ) | ||
707 | break; | 726 | break; |
708 | 727 | ||
709 | if (midi_byte >= 0x80 && midi_byte < 0xf0) | 728 | if (midi_byte >= 0x80 && midi_byte < 0xf0) |
@@ -717,17 +736,17 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) | |||
717 | spin_unlock_irqrestore(&uart->open_lock, flags); | 736 | spin_unlock_irqrestore(&uart->open_lock, flags); |
718 | } | 737 | } |
719 | 738 | ||
720 | static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up) | 739 | static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, |
740 | int up) | ||
721 | { | 741 | { |
722 | unsigned long flags; | 742 | unsigned long flags; |
723 | snd_uart16550_t *uart = substream->rmidi->private_data; | 743 | struct snd_uart16550 *uart = substream->rmidi->private_data; |
724 | 744 | ||
725 | spin_lock_irqsave(&uart->open_lock, flags); | 745 | spin_lock_irqsave(&uart->open_lock, flags); |
726 | if (up) { | 746 | if (up) |
727 | uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; | 747 | uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; |
728 | } else { | 748 | else |
729 | uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; | 749 | uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; |
730 | } | ||
731 | spin_unlock_irqrestore(&uart->open_lock, flags); | 750 | spin_unlock_irqrestore(&uart->open_lock, flags); |
732 | if (up) | 751 | if (up) |
733 | snd_uart16550_output_write(substream); | 752 | snd_uart16550_output_write(substream); |
@@ -747,10 +766,10 @@ static struct snd_rawmidi_ops snd_uart16550_input = | |||
747 | .trigger = snd_uart16550_input_trigger, | 766 | .trigger = snd_uart16550_input_trigger, |
748 | }; | 767 | }; |
749 | 768 | ||
750 | static int snd_uart16550_free(snd_uart16550_t *uart) | 769 | static int snd_uart16550_free(struct snd_uart16550 *uart) |
751 | { | 770 | { |
752 | if (uart->irq >= 0) | 771 | if (uart->irq >= 0) |
753 | free_irq(uart->irq, (void *)uart); | 772 | free_irq(uart->irq, uart); |
754 | release_and_free_resource(uart->res_base); | 773 | release_and_free_resource(uart->res_base); |
755 | kfree(uart); | 774 | kfree(uart); |
756 | return 0; | 775 | return 0; |
@@ -758,7 +777,7 @@ static int snd_uart16550_free(snd_uart16550_t *uart) | |||
758 | 777 | ||
759 | static int snd_uart16550_dev_free(struct snd_device *device) | 778 | static int snd_uart16550_dev_free(struct snd_device *device) |
760 | { | 779 | { |
761 | snd_uart16550_t *uart = device->device_data; | 780 | struct snd_uart16550 *uart = device->device_data; |
762 | return snd_uart16550_free(uart); | 781 | return snd_uart16550_free(uart); |
763 | } | 782 | } |
764 | 783 | ||
@@ -769,12 +788,12 @@ static int __init snd_uart16550_create(struct snd_card *card, | |||
769 | unsigned int base, | 788 | unsigned int base, |
770 | int adaptor, | 789 | int adaptor, |
771 | int droponfull, | 790 | int droponfull, |
772 | snd_uart16550_t **ruart) | 791 | struct snd_uart16550 **ruart) |
773 | { | 792 | { |
774 | static struct snd_device_ops ops = { | 793 | static struct snd_device_ops ops = { |
775 | .dev_free = snd_uart16550_dev_free, | 794 | .dev_free = snd_uart16550_dev_free, |
776 | }; | 795 | }; |
777 | snd_uart16550_t *uart; | 796 | struct snd_uart16550 *uart; |
778 | int err; | 797 | int err; |
779 | 798 | ||
780 | 799 | ||
@@ -795,7 +814,7 @@ static int __init snd_uart16550_create(struct snd_card *card, | |||
795 | 814 | ||
796 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { | 815 | if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { |
797 | if (request_irq(irq, snd_uart16550_interrupt, | 816 | if (request_irq(irq, snd_uart16550_interrupt, |
798 | IRQF_DISABLED, "Serial MIDI", (void *) uart)) { | 817 | IRQF_DISABLED, "Serial MIDI", uart)) { |
799 | snd_printk("irq %d busy. Using Polling.\n", irq); | 818 | snd_printk("irq %d busy. Using Polling.\n", irq); |
800 | } else { | 819 | } else { |
801 | uart->irq = irq; | 820 | uart->irq = irq; |
@@ -843,23 +862,28 @@ static int __init snd_uart16550_create(struct snd_card *card, | |||
843 | 862 | ||
844 | static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream) | 863 | static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream) |
845 | { | 864 | { |
846 | struct list_head *list; | 865 | struct snd_rawmidi_substream *substream; |
847 | 866 | ||
848 | list_for_each(list, &stream->substreams) { | 867 | list_for_each_entry(substream, &stream->substreams, list) { |
849 | struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list); | ||
850 | sprintf(substream->name, "Serial MIDI %d", substream->number + 1); | 868 | sprintf(substream->name, "Serial MIDI %d", substream->number + 1); |
851 | } | 869 | } |
852 | } | 870 | } |
853 | 871 | ||
854 | static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, struct snd_rawmidi **rmidi) | 872 | static int __init snd_uart16550_rmidi(struct snd_uart16550 *uart, int device, |
873 | int outs, int ins, | ||
874 | struct snd_rawmidi **rmidi) | ||
855 | { | 875 | { |
856 | struct snd_rawmidi *rrawmidi; | 876 | struct snd_rawmidi *rrawmidi; |
857 | int err; | 877 | int err; |
858 | 878 | ||
859 | if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0) | 879 | err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, |
880 | outs, ins, &rrawmidi); | ||
881 | if (err < 0) | ||
860 | return err; | 882 | return err; |
861 | snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input); | 883 | snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, |
862 | snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output); | 884 | &snd_uart16550_input); |
885 | snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
886 | &snd_uart16550_output); | ||
863 | strcpy(rrawmidi->name, "Serial MIDI"); | 887 | strcpy(rrawmidi->name, "Serial MIDI"); |
864 | snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); | 888 | snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); |
865 | snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); | 889 | snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); |
@@ -875,7 +899,7 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out | |||
875 | static int __init snd_serial_probe(struct platform_device *devptr) | 899 | static int __init snd_serial_probe(struct platform_device *devptr) |
876 | { | 900 | { |
877 | struct snd_card *card; | 901 | struct snd_card *card; |
878 | snd_uart16550_t *uart; | 902 | struct snd_uart16550 *uart; |
879 | int err; | 903 | int err; |
880 | int dev = devptr->id; | 904 | int dev = devptr->id; |
881 | 905 | ||
@@ -929,7 +953,8 @@ static int __init snd_serial_probe(struct platform_device *devptr) | |||
929 | &uart)) < 0) | 953 | &uart)) < 0) |
930 | goto _err; | 954 | goto _err; |
931 | 955 | ||
932 | if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) | 956 | err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); |
957 | if (err < 0) | ||
933 | goto _err; | 958 | goto _err; |
934 | 959 | ||
935 | sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", | 960 | sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", |