Update of /cvsroot/alsa/alsa-kernel/drivers In directory sc8-pr-cvs1:/tmp/cvs-serv25373
Modified Files: serial-u16550.c Log Message: Steve deRosier <[EMAIL PROTECTED]>: * There is a user selectable flag "droponfull". Set to 1 and any new bytes delivered to the driver after the buffer fills up will be discarded until the buffer is able to flush some bytes. * If droponfull==0 (or is not set, the default is 0), the driver proceeds to block further input by not calling snd_rawmidi_transmit_ack() and aborting the attempt. It will try again later. * I've redone a bit of the interface for the buffer routines. This was done to support the proper blocking/non-blocking methods as spelled out above, and to try to protect the buffer data a bit. Index: serial-u16550.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/drivers/serial-u16550.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- serial-u16550.c 14 Oct 2003 13:08:13 -0000 1.22 +++ serial-u16550.c 3 Dec 2003 13:23:22 -0000 1.23 @@ -63,6 +63,9 @@ "Generic" }; +#define SNDRV_SERIAL_NORMALBUFF 0 /* Normal blocking buffer operation */ +#define SNDRV_SERIAL_DROPBUFF 1 /* Non-blocking discard operation */ + static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ @@ -73,6 +76,7 @@ static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS}; +static int droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF }; MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(index, "Index value for Serial MIDI."); @@ -99,6 +103,9 @@ MODULE_PARM_DESC(outs, "Number of MIDI outputs."); MODULE_PARM(ins, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(ins, "Number of MIDI inputs."); +MODULE_PARM(droponfull, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode"); +MODULE_PARM_SYNTAX(droponfull, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC); MODULE_PARM_SYNTAX(outs, SNDRV_ENABLED ",allows:{{1,16}},dialog:list"); MODULE_PARM_SYNTAX(ins, SNDRV_ENABLED ",allows:{{1,16}},dialog:list"); @@ -163,6 +170,7 @@ int buff_in_count; int buff_in; int buff_out; + int drop_on_full; // wait timer unsigned int timer_running:1; @@ -194,12 +202,14 @@ inline static void snd_uart16550_buffer_output(snd_uart16550_t *uart) { unsigned short buff_out = uart->buff_out; - outb(uart->tx_buff[buff_out], uart->base + UART_TX); - uart->fifo_count++; - buff_out++; - buff_out &= TX_BUFF_MASK; - uart->buff_out = buff_out; - uart->buff_in_count--; + if( uart->buff_in_count > 0 ) { + outb(uart->tx_buff[buff_out], uart->base + UART_TX); + uart->fifo_count++; + buff_out++; + buff_out &= TX_BUFF_MASK; + uart->buff_out = buff_out; + uart->buff_in_count--; + } } /* This loop should be called with interrupts disabled @@ -257,9 +267,11 @@ || uart->adaptor == SNDRV_SERIAL_GENERIC) { /* Can't use FIFO, must send only when CTS is true */ status = inb(uart->base + UART_MSR); - if (uart->fifo_count == 0 && (status & UART_MSR_CTS) - && uart->buff_in_count > 0) - snd_uart16550_buffer_output(uart); + while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) && + (uart->buff_in_count > 0) ) { + snd_uart16550_buffer_output(uart); + status = inb( uart->base + UART_MSR ); + } } else { /* Write loop */ while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ @@ -576,19 +588,31 @@ return 0; }; -inline static void snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) +inline static int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) +{ + if( uart->buff_in_count + Num < TX_BUFF_SIZE ) + return 1; + else + return 0; +} + +inline static int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) { unsigned short buff_in = uart->buff_in; - uart->tx_buff[buff_in] = byte; - buff_in++; - buff_in &= TX_BUFF_MASK; - uart->buff_in = buff_in; - uart->buff_in_count++; - if (uart->irq < 0) /* polling mode */ - snd_uart16550_add_timer(uart); + if( uart->buff_in_count < TX_BUFF_SIZE ) { + uart->tx_buff[buff_in] = byte; + buff_in++; + buff_in &= TX_BUFF_MASK; + uart->buff_in = buff_in; + uart->buff_in_count++; + if (uart->irq < 0) /* polling mode */ + snd_uart16550_add_timer(uart); + return 1; + } else + return 0; } -static void snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte) +static int snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte) { if (uart->buff_in_count == 0 /* Buffer empty? */ && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && @@ -611,13 +635,14 @@ } } } else { - if (uart->buff_in_count >= TX_BUFF_SIZE) { + if( !snd_uart16550_write_buffer(uart, midi_byte) ) { snd_printk("%s: Buffer overrun on device at 0x%lx\n", uart->rmidi->name, uart->base); - return; + return 0; } - snd_uart16550_write_buffer(uart, midi_byte); } + + return 1; } static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream) @@ -661,40 +686,38 @@ } } else { first = 0; - while (1) { - if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1) - break; + while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) { /* Also send F5 after 3 seconds with no data to handle device disconnect */ if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || uart->adaptor == SNDRV_SERIAL_GENERIC) && (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) { - /* We will need three bytes of data here (worst case). */ - if (uart->buff_in_count >= TX_BUFF_SIZE - 3) + if( snd_uart16550_buffer_can_write( uart, 3 ) ) { + /* Roland Soundcanvas part selection */ + /* If this substream of the data is different previous + substream in this uart, send the change part event */ + uart->prev_out = substream->number; + /* change part */ + snd_uart16550_output_byte(uart, substream, 0xf5); + /* data */ + snd_uart16550_output_byte(uart, substream, uart->prev_out + 1); + /* If midi_byte is a data byte, send the previous status byte */ + if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)) + snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); + } else if( !uart->drop_on_full ) break; - /* Roland Soundcanvas part selection */ - /* If this substream of the data is different previous - substream in this uart, send the change part event */ - uart->prev_out = substream->number; - /* change part */ - snd_uart16550_output_byte(uart, substream, 0xf5); - /* data */ - snd_uart16550_output_byte(uart, substream, uart->prev_out + 1); - /* If midi_byte is a data byte, send the previous status byte */ - if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)) - snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); } - /* buffer full? */ - if (uart->buff_in_count >= TX_BUFF_SIZE) + /* send midi byte */ + if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full ) break; - /* send midi byte */ - snd_uart16550_output_byte(uart, substream, midi_byte); if (midi_byte >= 0x80 && midi_byte < 0xf0) uart->prev_status[uart->prev_out] = midi_byte; first = 1; + + snd_rawmidi_transmit_ack( substream, 1 ); } lasttime = jiffies; } @@ -755,6 +778,7 @@ unsigned int speed, unsigned int base, int adaptor, + int droponfull, snd_uart16550_t **ruart) { static snd_device_ops_t ops = { @@ -771,6 +795,7 @@ spin_lock_init(&uart->open_lock); uart->irq = -1; uart->base = iobase; + uart->drop_on_full = droponfull; if ((err = snd_uart16550_detect(uart)) <= 0) { printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); @@ -900,6 +925,7 @@ speed[dev], base[dev], adaptor[dev], + droponfull[dev], &uart)) < 0) { snd_card_free(card); return err; @@ -910,7 +936,7 @@ return err; } - sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s", + sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", card->shortname, uart->base, uart->irq, @@ -918,7 +944,8 @@ (int)uart->divisor, outs[dev], ins[dev], - adaptor_names[uart->adaptor]); + adaptor_names[uart->adaptor], + uart->drop_on_full); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); @@ -964,7 +991,7 @@ /* format is: snd-serial=enable,index,id, port,irq,speed,base,outs, - ins,adaptor */ + ins,adaptor,droponfull */ static int __init alsa_card_serial_setup(char *str) { @@ -981,7 +1008,8 @@ get_option(&str,&base[nr_dev]) == 2 && get_option(&str,&outs[nr_dev]) == 2 && get_option(&str,&ins[nr_dev]) == 2 && - get_option(&str,&adaptor[nr_dev]) == 2); + get_option(&str,&adaptor[nr_dev]) == 2 && + get_option(&str,&droponfull[nr_dev]) == 2 ); nr_dev++; return 1; } ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog