diff options
Diffstat (limited to 'drivers/net/wan/cosa.c')
-rw-r--r-- | drivers/net/wan/cosa.c | 493 |
1 files changed, 260 insertions, 233 deletions
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 2369ca250cd6..43caab0b7dee 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -1,13 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* $Id: cosa.c,v 1.31 2000/03/08 17:47:16 kas Exp $ */ -/* - * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz> +/* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz> * Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl> */ -/* - * The driver for the SRP and COSA synchronous serial cards. +/* The driver for the SRP and COSA synchronous serial cards. * * HARDWARE INFO * @@ -90,7 +88,7 @@ #define COSA_MAX_ID_STRING 128 /* Maximum length of the channel name */ -#define COSA_MAX_NAME (sizeof("cosaXXXcXXX")+1) +#define COSA_MAX_NAME (sizeof("cosaXXXcXXX") + 1) /* Per-channel data structure */ @@ -124,9 +122,9 @@ struct channel_data { }; /* cosa->firmware_status bits */ -#define COSA_FW_RESET (1<<0) /* Is the ROM monitor active? */ -#define COSA_FW_DOWNLOAD (1<<1) /* Is the microcode downloaded? */ -#define COSA_FW_START (1<<2) /* Is the microcode running? */ +#define COSA_FW_RESET BIT(0) /* Is the ROM monitor active? */ +#define COSA_FW_DOWNLOAD BIT(1) /* Is the microcode downloaded? */ +#define COSA_FW_START BIT(2) /* Is the microcode running? */ struct cosa_data { int num; /* Card number */ @@ -152,28 +150,25 @@ struct cosa_data { char *type; /* card type */ }; -/* - * Define this if you want all the possible ports to be autoprobed. +/* Define this if you want all the possible ports to be autoprobed. * It is here but it probably is not a good idea to use this. */ -/* #define COSA_ISA_AUTOPROBE 1 */ +/* #define COSA_ISA_AUTOPROBE 1*/ -/* - * Character device major number. 117 was allocated for us. +/* Character device major number. 117 was allocated for us. * The value of 0 means to allocate a first free one. */ static DEFINE_MUTEX(cosa_chardev_mutex); static int cosa_major = 117; -/* - * Encoding of the minor numbers: +/* Encoding of the minor numbers: * The lowest CARD_MINOR_BITS bits means the channel on the single card, * the highest bits means the card number. */ #define CARD_MINOR_BITS 4 /* How many bits in minor number are reserved - * for the single card */ -/* - * The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING" + * for the single card + */ +/* The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING" * macro doesn't like anything other than the raw number as an argument :-( */ #define MAX_CARDS 16 @@ -184,8 +179,7 @@ static int cosa_major = 117; #define DRIVER_TXMAP_SHIFT 2 #define DRIVER_TXMAP_MASK 0x0c /* FIXME: 0xfc for 8-channel version */ -/* - * for cosa->rxtx - indicates whether either transmit or receive is +/* for cosa->rxtx - indicates whether either transmit or receive is * in progress. These values are mean number of the bit. */ #define TXBIT 0 @@ -198,22 +192,22 @@ static int cosa_major = 117; #undef DEBUG_IRQS //1 /* Print the message when the IRQ is received */ #undef DEBUG_IO //1 /* Dump the I/O traffic */ -#define TX_TIMEOUT (5*HZ) +#define TX_TIMEOUT (5 * HZ) /* Maybe the following should be allocated dynamically */ static struct cosa_data cosa_cards[MAX_CARDS]; static int nr_cards; #ifdef COSA_ISA_AUTOPROBE -static int io[MAX_CARDS+1] = { 0x220, 0x228, 0x210, 0x218, 0, }; +static int io[MAX_CARDS + 1] = {0x220, 0x228, 0x210, 0x218, 0,}; /* NOTE: DMA is not autoprobed!!! */ -static int dma[MAX_CARDS+1] = { 1, 7, 1, 7, 1, 7, 1, 7, 0, }; +static int dma[MAX_CARDS + 1] = {1, 7, 1, 7, 1, 7, 1, 7, 0,}; #else -static int io[MAX_CARDS+1]; -static int dma[MAX_CARDS+1]; +static int io[MAX_CARDS + 1]; +static int dma[MAX_CARDS + 1]; #endif /* IRQ can be safely autoprobed */ -static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, }; +static int irq[MAX_CARDS + 1] = {-1, -1, -1, -1, -1, -1, 0,}; /* for class stuff*/ static struct class *cosa_class; @@ -244,14 +238,14 @@ MODULE_LICENSE("GPL"); #define cosa_inw inw #endif -#define is_8bit(cosa) (!(cosa->datareg & 0x08)) +#define is_8bit(cosa) (!((cosa)->datareg & 0x08)) -#define cosa_getstatus(cosa) (cosa_inb(cosa->statusreg)) -#define cosa_putstatus(cosa, stat) (cosa_outb(stat, cosa->statusreg)) -#define cosa_getdata16(cosa) (cosa_inw(cosa->datareg)) -#define cosa_getdata8(cosa) (cosa_inb(cosa->datareg)) -#define cosa_putdata16(cosa, dt) (cosa_outw(dt, cosa->datareg)) -#define cosa_putdata8(cosa, dt) (cosa_outb(dt, cosa->datareg)) +#define cosa_getstatus(cosa) (cosa_inb((cosa)->statusreg)) +#define cosa_putstatus(cosa, stat) (cosa_outb(stat, (cosa)->statusreg)) +#define cosa_getdata16(cosa) (cosa_inw((cosa)->datareg)) +#define cosa_getdata8(cosa) (cosa_inb((cosa)->datareg)) +#define cosa_putdata16(cosa, dt) (cosa_outw(dt, (cosa)->datareg)) +#define cosa_putdata8(cosa, dt) (cosa_outb(dt, (cosa)->datareg)) /* Initialization stuff */ static int cosa_probe(int ioaddr, int irq, int dma); @@ -280,14 +274,14 @@ static char *chrdev_setup_rx(struct channel_data *channel, int size); static int chrdev_rx_done(struct channel_data *channel); static int chrdev_tx_done(struct channel_data *channel, int size); static ssize_t cosa_read(struct file *file, - char __user *buf, size_t count, loff_t *ppos); + char __user *buf, size_t count, loff_t *ppos); static ssize_t cosa_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); + const char __user *buf, size_t count, loff_t *ppos); static unsigned int cosa_poll(struct file *file, poll_table *poll); static int cosa_open(struct inode *inode, struct file *file); static int cosa_release(struct inode *inode, struct file *file); static long cosa_chardev_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); + unsigned long arg); #ifdef COSA_FASYNC_WORKING static int cosa_fasync(struct inode *inode, struct file *file, int on); #endif @@ -337,7 +331,7 @@ static void debug_status_in(struct cosa_data *cosa, int status); static void debug_status_out(struct cosa_data *cosa, int status); #endif -static inline struct channel_data* dev_to_chan(struct net_device *dev) +static inline struct channel_data *dev_to_chan(struct net_device *dev) { return (struct channel_data *)dev_to_hdlc(dev)->priv; } @@ -355,15 +349,16 @@ static int __init cosa_init(void) goto out; } } else { - if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) { + cosa_major = register_chrdev(0, "cosa", &cosa_fops); + if (!cosa_major) { pr_warn("unable to register chardev\n"); err = -EIO; goto out; } } - for (i=0; i<MAX_CARDS; i++) + for (i = 0; i < MAX_CARDS; i++) cosa_cards[i].num = -1; - for (i=0; io[i] != 0 && i < MAX_CARDS; i++) + for (i = 0; io[i] != 0 && i < MAX_CARDS; i++) cosa_probe(io[i], irq[i], dma[i]); if (!nr_cards) { pr_warn("no devices found\n"); @@ -426,7 +421,7 @@ static const struct net_device_ops cosa_ops = { static int cosa_probe(int base, int irq, int dma) { - struct cosa_data *cosa = cosa_cards+nr_cards; + struct cosa_data *cosa = cosa_cards + nr_cards; int i, err = 0; memset(cosa, 0, sizeof(struct cosa_data)); @@ -438,7 +433,8 @@ static int cosa_probe(int base, int irq, int dma) return -1; } /* I/O address should be between 0x100 and 0x3ff and should be - * multiple of 8. */ + * multiple of 8. + */ if (base < 0x100 || base > 0x3ff || base & 0x7) { pr_info("invalid I/O address 0x%x\n", base); return -1; @@ -448,8 +444,9 @@ static int cosa_probe(int base, int irq, int dma) pr_info("invalid DMA %d\n", dma); return -1; } - /* and finally, on 16-bit COSA DMA should be 4-7 and - * I/O base should not be multiple of 0x10 */ + /* and finally, on 16-bit COSA DMA should be 4-7 and + * I/O base should not be multiple of 0x10 + */ if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) { pr_info("8/16 bit base and DMA mismatch (base=0x%x, dma=%d)\n", base, dma); @@ -458,12 +455,12 @@ static int cosa_probe(int base, int irq, int dma) cosa->dma = dma; cosa->datareg = base; - cosa->statusreg = is_8bit(cosa)?base+1:base+2; + cosa->statusreg = is_8bit(cosa) ? base + 1 : base + 2; spin_lock_init(&cosa->lock); - if (!request_region(base, is_8bit(cosa)?2:4,"cosa")) + if (!request_region(base, is_8bit(cosa) ? 2 : 4, "cosa")) return -1; - + if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) { printk(KERN_DEBUG "probe at 0x%x failed.\n", base); err = -1; @@ -471,11 +468,11 @@ static int cosa_probe(int base, int irq, int dma) } /* Test the validity of identification string */ - if (!strncmp(cosa->id_string, "SRP", 3)) + if (!strncmp(cosa->id_string, "SRP", 3)) { cosa->type = "srp"; - else if (!strncmp(cosa->id_string, "COSA", 4)) - cosa->type = is_8bit(cosa)? "cosa8": "cosa16"; - else { + } else if (!strncmp(cosa->id_string, "COSA", 4)) { + cosa->type = is_8bit(cosa) ? "cosa8" : "cosa16"; + } else { /* Print a warning only if we are not autoprobing */ #ifndef COSA_ISA_AUTOPROBE pr_info("valid signature not found at 0x%x\n", base); @@ -483,9 +480,9 @@ static int cosa_probe(int base, int irq, int dma) err = -1; goto err_out; } - /* Update the name of the region now we know the type of card */ - release_region(base, is_8bit(cosa)?2:4); - if (!request_region(base, is_8bit(cosa)?2:4, cosa->type)) { + /* Update the name of the region now we know the type of card */ + release_region(base, is_8bit(cosa) ? 2 : 4); + if (!request_region(base, is_8bit(cosa) ? 2 : 4, cosa->type)) { printk(KERN_DEBUG "changing name at 0x%x failed.\n", base); return -1; } @@ -495,8 +492,7 @@ static int cosa_probe(int base, int irq, int dma) unsigned long irqs; /* pr_info("IRQ autoprobe\n"); */ irqs = probe_irq_on(); - /* - * Enable interrupt on tx buffer empty (it sure is) + /* Enable interrupt on tx buffer empty (it sure is) * really sure ? * FIXME: When this code is not used as module, we should * probably call udelay() instead of the interruptible sleep. @@ -536,8 +532,8 @@ static int cosa_probe(int base, int irq, int dma) err = -1; goto err_out1; } - - cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA); + + cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL | GFP_DMA); if (!cosa->bouncebuf) { err = -ENOMEM; goto err_out2; @@ -563,7 +559,8 @@ static int cosa_probe(int base, int irq, int dma) sema_init(&chan->wsem, 1); /* Register the network interface */ - if (!(chan->netdev = alloc_hdlcdev(chan))) { + chan->netdev = alloc_hdlcdev(chan); + if (!chan->netdev) { pr_warn("%s: alloc_hdlcdev failed\n", chan->name); err = -ENOMEM; goto err_hdlcdev; @@ -603,12 +600,11 @@ err_out2: err_out1: free_irq(cosa->irq, cosa); err_out: - release_region(cosa->datareg,is_8bit(cosa)?2:4); + release_region(cosa->datareg, is_8bit(cosa) ? 2 : 4); pr_notice("cosa%d: allocating resources failed\n", cosa->num); return err; } - /*---------- network device ---------- */ static int cosa_net_attach(struct net_device *dev, unsigned short encoding, @@ -659,7 +655,7 @@ static int cosa_net_open(struct net_device *dev) } static netdev_tx_t cosa_net_tx(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { struct channel_data *chan = dev_to_chan(dev); @@ -714,13 +710,12 @@ static int cosa_net_close(struct net_device *dev) static char *cosa_net_setup_rx(struct channel_data *chan, int size) { - /* - * We can safely fall back to non-dma-able memory, because we have + /* We can safely fall back to non-dma-able memory, because we have * the cosa->bouncebuf pre-allocated. */ kfree_skb(chan->rx_skb); chan->rx_skb = dev_alloc_skb(size); - if (chan->rx_skb == NULL) { + if (!chan->rx_skb) { pr_notice("%s: Memory squeeze, dropping packet\n", chan->name); chan->netdev->stats.rx_dropped++; return NULL; @@ -767,7 +762,7 @@ static int cosa_net_tx_done(struct channel_data *chan, int size) /*---------- Character device ---------- */ static ssize_t cosa_read(struct file *file, - char __user *buf, size_t count, loff_t *ppos) + char __user *buf, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); unsigned long flags; @@ -782,9 +777,9 @@ static ssize_t cosa_read(struct file *file, } if (mutex_lock_interruptible(&chan->rlock)) return -ERESTARTSYS; - - chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL); - if (chan->rxdata == NULL) { + + chan->rxdata = kmalloc(COSA_MTU, GFP_DMA | GFP_KERNEL); + if (!chan->rxdata) { mutex_unlock(&chan->rlock); return -ENOMEM; } @@ -840,9 +835,8 @@ static int chrdev_rx_done(struct channel_data *chan) return 1; } - static ssize_t cosa_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) + const char __user *buf, size_t count, loff_t *ppos) { DECLARE_WAITQUEUE(wait, current); struct channel_data *chan = file->private_data; @@ -860,10 +854,10 @@ static ssize_t cosa_write(struct file *file, if (count > COSA_MTU) count = COSA_MTU; - + /* Allocate the buffer */ - kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA); - if (kbuf == NULL) { + kbuf = kmalloc(count, GFP_KERNEL | GFP_DMA); + if (!kbuf) { up(&chan->wsem); return -ENOMEM; } @@ -872,7 +866,7 @@ static ssize_t cosa_write(struct file *file, kfree(kbuf); return -EFAULT; } - chan->tx_status=0; + chan->tx_status = 0; cosa_start_tx(chan, kbuf, count); spin_lock_irqsave(&cosa->lock, flags); @@ -927,20 +921,20 @@ static int cosa_open(struct inode *inode, struct file *file) int ret = 0; mutex_lock(&cosa_chardev_mutex); - if ((n=iminor(file_inode(file))>>CARD_MINOR_BITS) - >= nr_cards) { + n = iminor(file_inode(file)) >> CARD_MINOR_BITS; + if (n >= nr_cards) { ret = -ENODEV; goto out; } - cosa = cosa_cards+n; + cosa = cosa_cards + n; - if ((n=iminor(file_inode(file)) - & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels) { + n = iminor(file_inode(file)) & ((1 << CARD_MINOR_BITS) - 1); + if (n >= cosa->nchannels) { ret = -ENODEV; goto out; } chan = cosa->chan + n; - + file->private_data = chan; spin_lock_irqsave(&cosa->lock, flags); @@ -982,26 +976,25 @@ static struct fasync_struct *fasync[256] = { NULL, }; /* To be done ... */ static int cosa_fasync(struct inode *inode, struct file *file, int on) { - int port = iminor(inode); + int port = iminor(inode); return fasync_helper(inode, file, on, &fasync[port]); } #endif - /* ---------- Ioctls ---------- */ -/* - * Ioctl subroutines can safely be made inline, because they are called +/* Ioctl subroutines can safely be made inline, because they are called * only from cosa_ioctl(). */ static inline int cosa_reset(struct cosa_data *cosa) { char idstring[COSA_MAX_ID_STRING]; + if (cosa->usage > 1) pr_info("cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->num, cosa->usage); - cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_START); + cosa->firmware_status &= ~(COSA_FW_RESET | COSA_FW_START); if (cosa_reset_and_read_id(cosa, idstring) < 0) { pr_notice("cosa%d: reset failed\n", cosa->num); return -EIO; @@ -1025,7 +1018,7 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg) cosa->name, cosa->firmware_status); return -EPERM; } - + if (copy_from_user(&d, arg, sizeof(d))) return -EFAULT; @@ -1034,9 +1027,8 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg) if (d.len < 0 || d.len > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; - /* If something fails, force the user to reset the card */ - cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_DOWNLOAD); + cosa->firmware_status &= ~(COSA_FW_RESET | COSA_FW_DOWNLOAD); i = download(cosa, d.code, d.len, d.addr); if (i < 0) { @@ -1046,7 +1038,7 @@ static inline int cosa_download(struct cosa_data *cosa, void __user *arg) } pr_info("cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n", cosa->num, d.len, d.addr); - cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD; + cosa->firmware_status |= COSA_FW_RESET | COSA_FW_DOWNLOAD; return 0; } @@ -1091,14 +1083,15 @@ static inline int cosa_start(struct cosa_data *cosa, int address) pr_info("cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", cosa->num, cosa->usage); - if ((cosa->firmware_status & (COSA_FW_RESET|COSA_FW_DOWNLOAD)) - != (COSA_FW_RESET|COSA_FW_DOWNLOAD)) { + if ((cosa->firmware_status & (COSA_FW_RESET | COSA_FW_DOWNLOAD)) + != (COSA_FW_RESET | COSA_FW_DOWNLOAD)) { pr_notice("%s: download the microcode and/or reset the card first (status %d)\n", cosa->name, cosa->firmware_status); return -EPERM; } cosa->firmware_status &= ~COSA_FW_RESET; - if ((i=startmicrocode(cosa, address)) < 0) { + i = startmicrocode(cosa, address); + if (i < 0) { pr_notice("cosa%d: start microcode at 0x%04x failed: %d\n", cosa->num, address, i); return -EIO; @@ -1108,11 +1101,12 @@ static inline int cosa_start(struct cosa_data *cosa, int address) cosa->firmware_status |= COSA_FW_START; return 0; } - + /* Buffer of size at least COSA_MAX_ID_STRING is expected */ static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string) { - int l = strlen(cosa->id_string)+1; + int l = strlen(cosa->id_string) + 1; + if (copy_to_user(string, cosa->id_string, l)) return -EFAULT; return l; @@ -1121,16 +1115,19 @@ static inline int cosa_getidstr(struct cosa_data *cosa, char __user *string) /* Buffer of size at least COSA_MAX_ID_STRING is expected */ static inline int cosa_gettype(struct cosa_data *cosa, char __user *string) { - int l = strlen(cosa->type)+1; + int l = strlen(cosa->type) + 1; + if (copy_to_user(string, cosa->type, l)) return -EFAULT; return l; } static int cosa_ioctl_common(struct cosa_data *cosa, - struct channel_data *channel, unsigned int cmd, unsigned long arg) + struct channel_data *channel, unsigned int cmd, + unsigned long arg) { void __user *argp = (void __user *)arg; + switch (cmd) { case COSAIORSET: /* Reset the device */ if (!capable(CAP_NET_ADMIN)) @@ -1143,7 +1140,7 @@ static int cosa_ioctl_common(struct cosa_data *cosa, case COSAIODOWNLD: /* Download the firmware */ if (!capable(CAP_SYS_RAWIO)) return -EACCES; - + return cosa_download(cosa, argp); case COSAIORMEM: if (!capable(CAP_SYS_RAWIO)) @@ -1176,6 +1173,7 @@ static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int rv; struct channel_data *chan = dev_to_chan(dev); + rv = cosa_ioctl_common(chan->cosa, chan, cmd, (unsigned long)ifr->ifr_data); if (rv != -ENOIOCTLCMD) @@ -1184,7 +1182,7 @@ static int cosa_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } static long cosa_chardev_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) + unsigned long arg) { struct channel_data *channel = file->private_data; struct cosa_data *cosa; @@ -1197,11 +1195,9 @@ static long cosa_chardev_ioctl(struct file *file, unsigned int cmd, return ret; } - /*---------- HW layer interface ---------- */ -/* - * The higher layer can bind itself to the HW layer by setting the callbacks +/* The higher layer can bind itself to the HW layer by setting the callbacks * in the channel_data structure and by using these routines. */ static void cosa_enable_rx(struct channel_data *chan) @@ -1220,8 +1216,7 @@ static void cosa_disable_rx(struct channel_data *chan) put_driver_status(cosa); } -/* - * FIXME: This routine probably should check for cosa_start_tx() called when +/* FIXME: This routine probably should check for cosa_start_tx() called when * the previous transmit is still unfinished. In this case the non-zero * return value should indicate to the caller that the queuing(sp?) up * the transmit has failed. @@ -1235,7 +1230,7 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len) pr_info("cosa%dc%d: starting tx(0x%x)", chan->cosa->num, chan->num, len); - for (i=0; i<len; i++) + for (i = 0; i < len; i++) pr_cont(" %02x", buf[i]&0xff); pr_cont("\n"); #endif @@ -1262,10 +1257,10 @@ static void put_driver_status(struct cosa_data *cosa) status = (cosa->rxbitmap ? DRIVER_RX_READY : 0) | (cosa->txbitmap ? DRIVER_TX_READY : 0) - | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT) - &DRIVER_TXMAP_MASK : 0); + | (cosa->txbitmap ? ~(cosa->txbitmap << DRIVER_TXMAP_SHIFT) + & DRIVER_TXMAP_MASK : 0); if (!cosa->rxtx) { - if (cosa->rxbitmap|cosa->txbitmap) { + if (cosa->rxbitmap | cosa->txbitmap) { if (!cosa->enabled) { cosa_putstatus(cosa, SR_RX_INT_ENA); #ifdef DEBUG_IO @@ -1294,10 +1289,10 @@ static void put_driver_status_nolock(struct cosa_data *cosa) status = (cosa->rxbitmap ? DRIVER_RX_READY : 0) | (cosa->txbitmap ? DRIVER_TX_READY : 0) - | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT) - &DRIVER_TXMAP_MASK : 0); + | (cosa->txbitmap ? ~(cosa->txbitmap << DRIVER_TXMAP_SHIFT) + & DRIVER_TXMAP_MASK : 0); - if (cosa->rxbitmap|cosa->txbitmap) { + if (cosa->rxbitmap | cosa->txbitmap) { cosa_putstatus(cosa, SR_RX_INT_ENA); #ifdef DEBUG_IO debug_status_out(cosa, SR_RX_INT_ENA); @@ -1316,8 +1311,7 @@ static void put_driver_status_nolock(struct cosa_data *cosa) #endif } -/* - * The "kickme" function: When the DMA times out, this is called to +/* The "kickme" function: When the DMA times out, this is called to * clean up the driver status. * FIXME: Preliminary support, the interface is probably wrong. */ @@ -1344,7 +1338,7 @@ static void cosa_kick(struct cosa_data *cosa) udelay(100); cosa_putstatus(cosa, 0); udelay(100); - (void) cosa_getdata8(cosa); + (void)cosa_getdata8(cosa); udelay(100); cosa_putdata8(cosa, 0); udelay(100); @@ -1352,8 +1346,7 @@ static void cosa_kick(struct cosa_data *cosa) spin_unlock_irqrestore(&cosa->lock, flags); } -/* - * Check if the whole buffer is DMA-able. It means it is below the 16M of +/* Check if the whole buffer is DMA-able. It means it is below the 16M of * physical memory and doesn't span the 64k boundary. For now it seems * SKB's never do this, but we'll check this anyway. */ @@ -1361,9 +1354,10 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len) { static int count; unsigned long b = (unsigned long)buf; - if (b+len >= MAX_DMA_ADDRESS) + + if (b + len >= MAX_DMA_ADDRESS) return 0; - if ((b^ (b+len)) & 0x10000) { + if ((b ^ (b + len)) & 0x10000) { if (count++ < 5) pr_info("%s: packet spanning a 64k boundary\n", chan->name); @@ -1372,11 +1366,9 @@ static int cosa_dma_able(struct channel_data *chan, char *buf, int len) return 1; } - /* ---------- The SRP/COSA ROM monitor functions ---------- */ -/* - * Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=", +/* Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=", * drivers need to say 4-digit hex number meaning start address of the microcode * separated by a single space. Monitor replies by saying " =". Now driver * has to write 4-digit hex number meaning the last byte address ended @@ -1387,18 +1379,27 @@ static int download(struct cosa_data *cosa, const char __user *microcode, int le { int i; - if (put_wait_data(cosa, 'w') == -1) return -1; + if (put_wait_data(cosa, 'w') == -1) + return -1; if ((i=get_wait_data(cosa)) != 'w') { printk("dnld: 0x%04x\n",i); return -2;} - if (get_wait_data(cosa) != '=') return -3; - - if (puthexnumber(cosa, address) < 0) return -4; - if (put_wait_data(cosa, ' ') == -1) return -10; - if (get_wait_data(cosa) != ' ') return -11; - if (get_wait_data(cosa) != '=') return -12; - - if (puthexnumber(cosa, address+length-1) < 0) return -13; - if (put_wait_data(cosa, ' ') == -1) return -18; - if (get_wait_data(cosa) != ' ') return -19; + if (get_wait_data(cosa) != '=') + return -3; + + if (puthexnumber(cosa, address) < 0) + return -4; + if (put_wait_data(cosa, ' ') == -1) + return -10; + if (get_wait_data(cosa) != ' ') + return -11; + if (get_wait_data(cosa) != '=') + return -12; + + if (puthexnumber(cosa, address + length - 1) < 0) + return -13; + if (put_wait_data(cosa, ' ') == -1) + return -18; + if (get_wait_data(cosa) != ' ') + return -19; while (length--) { char c; @@ -1413,43 +1414,53 @@ static int download(struct cosa_data *cosa, const char __user *microcode, int le microcode++; } - if (get_wait_data(cosa) != '\r') return -21; - if (get_wait_data(cosa) != '\n') return -22; - if (get_wait_data(cosa) != '.') return -23; + if (get_wait_data(cosa) != '\r') + return -21; + if (get_wait_data(cosa) != '\n') + return -22; + if (get_wait_data(cosa) != '.') + return -23; #if 0 printk(KERN_DEBUG "cosa%d: download completed.\n", cosa->num); #endif return 0; } - -/* - * Starting microcode is done via the "g" command of the SRP monitor. +/* Starting microcode is done via the "g" command of the SRP monitor. * The chat should be the following: "g" "g=" "<addr><CR>" * "<CR><CR><LF><CR><LF>". */ static int startmicrocode(struct cosa_data *cosa, int address) { - if (put_wait_data(cosa, 'g') == -1) return -1; - if (get_wait_data(cosa) != 'g') return -2; - if (get_wait_data(cosa) != '=') return -3; - - if (puthexnumber(cosa, address) < 0) return -4; - if (put_wait_data(cosa, '\r') == -1) return -5; - - if (get_wait_data(cosa) != '\r') return -6; - if (get_wait_data(cosa) != '\r') return -7; - if (get_wait_data(cosa) != '\n') return -8; - if (get_wait_data(cosa) != '\r') return -9; - if (get_wait_data(cosa) != '\n') return -10; + if (put_wait_data(cosa, 'g') == -1) + return -1; + if (get_wait_data(cosa) != 'g') + return -2; + if (get_wait_data(cosa) != '=') + return -3; + + if (puthexnumber(cosa, address) < 0) + return -4; + if (put_wait_data(cosa, '\r') == -1) + return -5; + + if (get_wait_data(cosa) != '\r') + return -6; + if (get_wait_data(cosa) != '\r') + return -7; + if (get_wait_data(cosa) != '\n') + return -8; + if (get_wait_data(cosa) != '\r') + return -9; + if (get_wait_data(cosa) != '\n') + return -10; #if 0 printk(KERN_DEBUG "cosa%d: microcode started\n", cosa->num); #endif return 0; } -/* - * Reading memory is done via the "r" command of the SRP monitor. +/* Reading memory is done via the "r" command of the SRP monitor. * The chat is the following "r" "r=" "<addr> " " =" "<last_byte> " " " * Then driver can read the data and the conversation is finished * by SRP monitor sending "<CR><LF>." (dot at the end). @@ -1459,27 +1470,39 @@ static int startmicrocode(struct cosa_data *cosa, int address) */ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, int address) { - if (put_wait_data(cosa, 'r') == -1) return -1; - if ((get_wait_data(cosa)) != 'r') return -2; - if ((get_wait_data(cosa)) != '=') return -3; - - if (puthexnumber(cosa, address) < 0) return -4; - if (put_wait_data(cosa, ' ') == -1) return -5; - if (get_wait_data(cosa) != ' ') return -6; - if (get_wait_data(cosa) != '=') return -7; - - if (puthexnumber(cosa, address+length-1) < 0) return -8; - if (put_wait_data(cosa, ' ') == -1) return -9; - if (get_wait_data(cosa) != ' ') return -10; + if (put_wait_data(cosa, 'r') == -1) + return -1; + if ((get_wait_data(cosa)) != 'r') + return -2; + if ((get_wait_data(cosa)) != '=') + return -3; + + if (puthexnumber(cosa, address) < 0) + return -4; + if (put_wait_data(cosa, ' ') == -1) + return -5; + if (get_wait_data(cosa) != ' ') + return -6; + if (get_wait_data(cosa) != '=') + return -7; + + if (puthexnumber(cosa, address + length - 1) < 0) + return -8; + if (put_wait_data(cosa, ' ') == -1) + return -9; + if (get_wait_data(cosa) != ' ') + return -10; while (length--) { char c; int i; - if ((i=get_wait_data(cosa)) == -1) { + + i = get_wait_data(cosa); + if (i == -1) { pr_info("0x%04x bytes remaining\n", length); return -11; } - c=i; + c = i; #if 1 if (put_user(c, microcode)) return -23; /* ??? */ @@ -1489,22 +1512,24 @@ static int readmem(struct cosa_data *cosa, char __user *microcode, int length, i microcode++; } - if (get_wait_data(cosa) != '\r') return -21; - if (get_wait_data(cosa) != '\n') return -22; - if (get_wait_data(cosa) != '.') return -23; + if (get_wait_data(cosa) != '\r') + return -21; + if (get_wait_data(cosa) != '\n') + return -22; + if (get_wait_data(cosa) != '.') + return -23; #if 0 printk(KERN_DEBUG "cosa%d: readmem completed.\n", cosa->num); #endif return 0; } -/* - * This function resets the device and reads the initial prompt +/* This function resets the device and reads the initial prompt * of the device's ROM monitor. */ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring) { - int i=0, id=0, prev=0, curr=0; + int i = 0, id = 0, prev = 0, curr = 0; /* Reset the card ... */ cosa_putstatus(cosa, 0); @@ -1514,18 +1539,18 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring) /* Disable all IRQs from the card */ cosa_putstatus(cosa, 0); - /* - * Try to read the ID string. The card then prints out the + /* Try to read the ID string. The card then prints out the * identification string ended by the "\n\x2e". * * The following loop is indexed through i (instead of id) * to avoid looping forever when for any reason * the port returns '\r', '\n' or '\x2e' permanently. */ - for (i=0; i<COSA_MAX_ID_STRING-1; i++, prev=curr) { - if ((curr = get_wait_data(cosa)) == -1) { + for (i = 0; i < COSA_MAX_ID_STRING - 1; i++, prev = curr) { + curr = get_wait_data(cosa); + if (curr == -1) return -1; - } + curr &= 0xff; if (curr != '\r' && curr != '\n' && curr != 0x2e) idstring[id++] = curr; @@ -1537,11 +1562,9 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring) return id; } - /* ---------- Auxiliary routines for COSA/SRP monitor ---------- */ -/* - * This routine gets the data byte from the card waiting for the SR_RX_RDY +/* This routine gets the data byte from the card waiting for the SR_RX_RDY * bit to be set in a loop. It should be used in the exceptional cases * only (for example when resetting the card or downloading the firmware. */ @@ -1553,10 +1576,11 @@ static int get_wait_data(struct cosa_data *cosa) /* read data and return them */ if (cosa_getstatus(cosa) & SR_RX_RDY) { short r; + r = cosa_getdata8(cosa); #if 0 pr_info("get_wait_data returning after %d retries\n", - 999-retries); + 999 - retries); #endif return r; } @@ -1568,20 +1592,20 @@ static int get_wait_data(struct cosa_data *cosa) return -1; } -/* - * This routine puts the data byte to the card waiting for the SR_TX_RDY +/* This routine puts the data byte to the card waiting for the SR_TX_RDY * bit to be set in a loop. It should be used in the exceptional cases * only (for example when resetting the card or downloading the firmware). */ static int put_wait_data(struct cosa_data *cosa, int data) { int retries = 1000; + while (--retries) { /* read data and return them */ if (cosa_getstatus(cosa) & SR_TX_RDY) { cosa_putdata8(cosa, data); #if 0 - pr_info("Putdata: %d retries\n", 999-retries); + pr_info("Putdata: %d retries\n", 999 - retries); #endif return 0; } @@ -1594,9 +1618,8 @@ static int put_wait_data(struct cosa_data *cosa, int data) cosa->num, cosa_getstatus(cosa)); return -1; } - -/* - * The following routine puts the hexadecimal number into the SRP monitor + +/* The following routine puts the hexadecimal number into the SRP monitor * and verifies the proper echo of the sent bytes. Returns 0 on success, * negative number on failure (-1,-3,-5,-7) means that put_wait_data() failed, * (-2,-4,-6,-8) means that reading echo failed. @@ -1608,26 +1631,24 @@ static int puthexnumber(struct cosa_data *cosa, int number) /* Well, I should probably replace this by something faster. */ sprintf(temp, "%04X", number); - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { if (put_wait_data(cosa, temp[i]) == -1) { pr_notice("cosa%d: puthexnumber failed to write byte %d\n", cosa->num, i); - return -1-2*i; + return -1 - 2 * i; } if (get_wait_data(cosa) != temp[i]) { pr_notice("cosa%d: puthexhumber failed to read echo of byte %d\n", cosa->num, i); - return -2-2*i; + return -2 - 2 * i; } } return 0; } - /* ---------- Interrupt routines ---------- */ -/* - * There are three types of interrupt: +/* There are three types of interrupt: * At the beginning of transmit - this handled is in tx_interrupt(), * at the beginning of receive - it is in rx_interrupt() and * at the end of transmit/receive - it is the eot_interrupt() function. @@ -1635,14 +1656,13 @@ static int puthexnumber(struct cosa_data *cosa, int number) * COSA status byte. I have moved the rx/tx/eot interrupt handling into * separate functions to make it more readable. These functions are inline, * so there should be no overhead of function call. - * + * * In the COSA bus-master mode, we need to tell the card the address of a * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait. * It's time to use the bottom half :-( */ -/* - * Transmit interrupt routine - called when COSA is willing to obtain +/* 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 @@ -1667,7 +1687,8 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) set_bit(TXBIT, &cosa->rxtx); if (!test_bit(IRQBIT, &cosa->rxtx)) { /* flow control, see the comment above */ - int i=0; + int i = 0; + if (!cosa->txbitmap) { pr_warn("%s: No channel wants data in TX IRQ. Expect DMA timeout.\n", cosa->name); @@ -1681,9 +1702,10 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) i++; if (cosa->txchan >= cosa->nchannels) cosa->txchan = 0; - if (!(cosa->txbitmap & (1<<cosa->txchan))) + if (!(cosa->txbitmap & (1 << cosa->txchan))) continue; - if (~status & (1 << (cosa->txchan+DRIVER_TXMAP_SHIFT))) + if (~status & + (1 << (cosa->txchan + DRIVER_TXMAP_SHIFT))) break; /* in second pass, accept first ready-to-TX channel */ if (i > cosa->nchannels) { @@ -1698,12 +1720,13 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) } cosa->txsize = cosa->chan[cosa->txchan].txsize; - if (cosa_dma_able(cosa->chan+cosa->txchan, - cosa->chan[cosa->txchan].txbuf, cosa->txsize)) { + if (cosa_dma_able(cosa->chan + cosa->txchan, + cosa->chan[cosa->txchan].txbuf, + cosa->txsize)) { cosa->txbuf = cosa->chan[cosa->txchan].txbuf; } else { memcpy(cosa->bouncebuf, cosa->chan[cosa->txchan].txbuf, - cosa->txsize); + cosa->txsize); cosa->txbuf = cosa->bouncebuf; } } @@ -1711,12 +1734,12 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) if (is_8bit(cosa)) { if (!test_bit(IRQBIT, &cosa->rxtx)) { cosa_putstatus(cosa, SR_TX_INT_ENA); - cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)| + cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0) | ((cosa->txsize >> 8) & 0x1f)); #ifdef DEBUG_IO debug_status_out(cosa, SR_TX_INT_ENA); - debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)| - ((cosa->txsize >> 8) & 0x1f)); + debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0) | + ((cosa->txsize >> 8) & 0x1f)); debug_data_in(cosa, cosa_getdata8(cosa)); #else cosa_getdata8(cosa); @@ -1727,20 +1750,20 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) } else { clear_bit(IRQBIT, &cosa->rxtx); cosa_putstatus(cosa, 0); - cosa_putdata8(cosa, cosa->txsize&0xff); + cosa_putdata8(cosa, cosa->txsize & 0xff); #ifdef DEBUG_IO debug_status_out(cosa, 0); - debug_data_out(cosa, cosa->txsize&0xff); + debug_data_out(cosa, cosa->txsize & 0xff); #endif } } else { cosa_putstatus(cosa, SR_TX_INT_ENA); - cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000) + cosa_putdata16(cosa, ((cosa->txchan << 13) & 0xe000) | (cosa->txsize & 0x1fff)); #ifdef DEBUG_IO debug_status_out(cosa, SR_TX_INT_ENA); - debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000) - | (cosa->txsize & 0x1fff)); + debug_data_out(cosa, ((cosa->txchan << 13) & 0xe000) | + (cosa->txsize & 0x1fff)); debug_data_in(cosa, cosa_getdata8(cosa)); debug_status_out(cosa, 0); #else @@ -1751,25 +1774,28 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) if (cosa->busmaster) { unsigned long addr = virt_to_bus(cosa->txbuf); - int count=0; + int count = 0; + pr_info("busmaster IRQ\n"); - while (!(cosa_getstatus(cosa)&SR_TX_RDY)) { + while (!(cosa_getstatus(cosa) & SR_TX_RDY)) { count++; udelay(10); - if (count > 1000) break; + if (count > 1000) + break; } pr_info("status %x\n", cosa_getstatus(cosa)); pr_info("ready after %d loops\n", count); - cosa_putdata16(cosa, (addr >> 16)&0xffff); + cosa_putdata16(cosa, (addr >> 16) & 0xffff); count = 0; - while (!(cosa_getstatus(cosa)&SR_TX_RDY)) { + while (!(cosa_getstatus(cosa) & SR_TX_RDY)) { count++; - if (count > 1000) break; + if (count > 1000) + break; udelay(10); } pr_info("ready after %d loops\n", count); - cosa_putdata16(cosa, addr &0xffff); + cosa_putdata16(cosa, addr & 0xffff); flags1 = claim_dma_lock(); set_dma_mode(cosa->dma, DMA_MODE_CASCADE); enable_dma(cosa->dma); @@ -1785,9 +1811,9 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status) enable_dma(cosa->dma); release_dma_lock(flags1); } - cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA); + cosa_putstatus(cosa, SR_TX_DMA_ENA | SR_USR_INT_ENA); #ifdef DEBUG_IO - debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA); + debug_status_out(cosa, SR_TX_DMA_ENA | SR_USR_INT_ENA); #endif spin_unlock_irqrestore(&cosa->lock, flags); } @@ -1806,7 +1832,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status) if (!test_bit(IRQBIT, &cosa->rxtx)) { set_bit(IRQBIT, &cosa->rxtx); put_driver_status_nolock(cosa); - cosa->rxsize = cosa_getdata8(cosa) <<8; + cosa->rxsize = cosa_getdata8(cosa) << 8; #ifdef DEBUG_IO debug_data_in(cosa, cosa->rxsize >> 8); #endif @@ -1859,20 +1885,20 @@ reject: /* Reject the packet */ disable_dma(cosa->dma); clear_dma_ff(cosa->dma); set_dma_mode(cosa->dma, DMA_MODE_READ); - if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) { + if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) set_dma_addr(cosa->dma, virt_to_bus(cosa->rxbuf)); - } else { + else set_dma_addr(cosa->dma, virt_to_bus(cosa->bouncebuf)); - } - set_dma_count(cosa->dma, (cosa->rxsize&0x1fff)); + + set_dma_count(cosa->dma, (cosa->rxsize & 0x1fff)); enable_dma(cosa->dma); release_dma_lock(flags); spin_lock_irqsave(&cosa->lock, flags); - cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA); + cosa_putstatus(cosa, SR_RX_DMA_ENA | SR_USR_INT_ENA); if (!is_8bit(cosa) && (status & SR_TX_RDY)) cosa_putdata8(cosa, DRIVER_RX_READY); #ifdef DEBUG_IO - debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA); + debug_status_out(cosa, SR_RX_DMA_ENA | SR_USR_INT_ENA); if (!is_8bit(cosa) && (status & SR_TX_RDY)) debug_data_cmd(cosa, DRIVER_RX_READY); #endif @@ -1882,13 +1908,15 @@ reject: /* Reject the packet */ static inline void eot_interrupt(struct cosa_data *cosa, int status) { unsigned long flags, flags1; + spin_lock_irqsave(&cosa->lock, flags); flags1 = claim_dma_lock(); disable_dma(cosa->dma); clear_dma_ff(cosa->dma); release_dma_lock(flags1); if (test_bit(TXBIT, &cosa->rxtx)) { - struct channel_data *chan = cosa->chan+cosa->txchan; + struct channel_data *chan = cosa->chan + cosa->txchan; + if (chan->tx_done) if (chan->tx_done(chan, cosa->txsize)) clear_bit(chan->num, &cosa->txbitmap); @@ -1896,9 +1924,10 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status) #ifdef DEBUG_DATA { int i; + pr_info("cosa%dc%d: done rx(0x%x)", cosa->num, cosa->rxchan->num, cosa->rxsize); - for (i=0; i<cosa->rxsize; i++) + for (i = 0; i < cosa->rxsize; i++) pr_cont(" %02x", cosa->rxbuf[i]&0xff); pr_cont("\n"); } @@ -1914,8 +1943,7 @@ static inline void eot_interrupt(struct cosa_data *cosa, int status) } else { pr_notice("cosa%d: unexpected EOT interrupt\n", cosa->num); } - /* - * Clear the RXBIT, TXBIT and IRQBIT (the latest should be + /* Clear the RXBIT, TXBIT and IRQBIT (the latest should be * cleared anyway). We should do it as soon as possible * so that we can tell the COSA we are done and to give it a time * for recovery. @@ -1968,10 +1996,8 @@ again: return IRQ_HANDLED; } - /* ---------- I/O debugging routines ---------- */ -/* - * These routines can be used to monitor COSA/SRP I/O and to printk() +/* These routines can be used to monitor COSA/SRP I/O and to printk() * the data being transferred on the data and status I/O port in a * readable way. */ @@ -1980,6 +2006,7 @@ again: static void debug_status_in(struct cosa_data *cosa, int status) { char *s; + switch (status & SR_CMD_FROM_SRP_MASK) { case SR_UP_REQUEST: s = "RX_REQ"; |