patch-2.2.0-pre1 linux/drivers/net/cosa.c
Next file: linux/drivers/net/cosa.h
Previous file: linux/drivers/net/Config.in
Back to the patch index
Back to the overall index
- Lines: 72
- Date:
Mon Dec 28 11:05:14 1998
- Orig file:
v2.1.132/linux/drivers/net/cosa.c
- Orig date:
Tue Dec 22 14:16:55 1998
diff -u --recursive --new-file v2.1.132/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.9 1998/12/08 02:24:23 kas Exp $ */
+/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
/*
* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -357,7 +357,7 @@
#endif
{
int i;
- printk(KERN_INFO "cosa v1.02 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+ printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
#ifdef __SMP__
printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
#endif
@@ -995,7 +995,9 @@
get_user_ret(len, &(d->len), -EFAULT);
get_user_ret(code, &(d->code), -EFAULT);
- if (d->len < 0)
+ if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
+ return -EINVAL;
+ if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE)
return -EINVAL;
if ((i=download(cosa, d->code, len, addr)) < 0) {
@@ -1555,6 +1557,15 @@
* separate functions to make it more readable. These functions are inline,
* so there should be no overhead of function call.
*/
+
+/*
+ * Transmit interrupt routine - called when COSA is willing to obtain
+ * data from the OS. The most tricky part of the routine is selection
+ * of channel we (OS) want to send packet for. For SRP we should probably
+ * use the round-robin approach. The newer COSA firmwares have a simple
+ * flow-control - in the status word has bits 2 and 3 set to 1 means that the
+ * channel 0 or 1 doesn't want to receive data.
+ */
static inline void tx_interrupt(struct cosa_data *cosa, int status)
{
unsigned long flags, flags1;
@@ -1564,16 +1575,24 @@
#endif
spin_lock_irqsave(&cosa->lock, flags);
set_bit(TXBIT, &cosa->rxtx);
- /*
- * Using a round-robin algorithm select a first channel that has
- * data ready for transmit.
- */
if (!test_bit(IRQBIT, &cosa->rxtx)) {
+ /* flow control */
+ int i=0;
do {
+ if (i++ > cosa->nchannels) {
+ printk(KERN_WARNING
+ "%s: No channel wants data in TX IRQ\n",
+ cosa->name);
+ clear_bit(TXBIT, &cosa->rxtx);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return;
+ }
cosa->txchan++;
if (cosa->txchan >= cosa->nchannels)
cosa->txchan = 0;
- } while(!(cosa->txbitmap & (1<<cosa->txchan)));
+ } while ((!(cosa->txbitmap & (1<<cosa->txchan)))
+ || status & (1<<(cosa->txchan+DRIVER_TXMAP_SHIFT)));
+
cosa->txsize = cosa->chan[cosa->txchan].txsize;
if (cosa_dma_able(cosa->chan+cosa->txchan,
cosa->chan[cosa->txchan].txbuf, cosa->txsize)) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov