diff options
Diffstat (limited to 'drivers/net/hamradio/yam.c')
-rw-r--r-- | drivers/net/hamradio/yam.c | 132 |
1 files changed, 81 insertions, 51 deletions
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 5407f7486c9c..b06691937ce9 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -55,6 +55,8 @@ #include <asm/system.h> #include <linux/interrupt.h> #include <linux/ioport.h> +#include <linux/firmware.h> +#include <linux/platform_device.h> #include <linux/netdevice.h> #include <linux/if_arp.h> @@ -71,16 +73,18 @@ #include <linux/init.h> #include <linux/yam.h> -#include "yam9600.h" -#include "yam1200.h" /* --------------------------------------------------------------------- */ static const char yam_drvname[] = "yam"; -static char yam_drvinfo[] __initdata = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n"; +static const char yam_drvinfo[] __initdata = KERN_INFO \ + "YAM driver version 0.8 by F1OAT/F6FBB\n"; /* --------------------------------------------------------------------- */ +#define FIRMWARE_9600 "yam/9600.bin" +#define FIRMWARE_1200 "yam/1200.bin" + #define YAM_9600 1 #define YAM_1200 2 @@ -115,10 +119,6 @@ struct yam_port { struct net_device *dev; - /* Stats section */ - - struct net_device_stats stats; - int nb_rxint; int nb_mdint; @@ -345,9 +345,51 @@ static int fpga_write(int iobase, unsigned char wrd) return 0; } -static unsigned char *add_mcs(unsigned char *bits, int bitrate) +/* + * predef should be 0 for loading user defined mcs + * predef should be YAM_1200 for loading predef 1200 mcs + * predef should be YAM_9600 for loading predef 9600 mcs + */ +static unsigned char *add_mcs(unsigned char *bits, int bitrate, + unsigned int predef) { + const char *fw_name[2] = {FIRMWARE_9600, FIRMWARE_1200}; + const struct firmware *fw; + struct platform_device *pdev; struct yam_mcs *p; + int err; + + switch (predef) { + case 0: + fw = NULL; + break; + case YAM_1200: + case YAM_9600: + predef--; + pdev = platform_device_register_simple("yam", 0, NULL, 0); + if (IS_ERR(pdev)) { + printk(KERN_ERR "yam: Failed to register firmware\n"); + return NULL; + } + err = request_firmware(&fw, fw_name[predef], &pdev->dev); + platform_device_unregister(pdev); + if (err) { + printk(KERN_ERR "Failed to load firmware \"%s\"\n", + fw_name[predef]); + return NULL; + } + if (fw->size != YAM_FPGA_SIZE) { + printk(KERN_ERR "Bogus length %zu in firmware \"%s\"\n", + fw->size, fw_name[predef]); + release_firmware(fw); + return NULL; + } + bits = (unsigned char *)fw->data; + break; + default: + printk(KERN_ERR "yam: Invalid predef number %u\n", predef); + return NULL; + } /* If it already exists, replace the bit data */ p = yam_data; @@ -362,6 +404,7 @@ static unsigned char *add_mcs(unsigned char *bits, int bitrate) /* Allocate a new mcs */ if ((p = kmalloc(sizeof(struct yam_mcs), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "YAM: no memory to allocate mcs\n"); + release_firmware(fw); return NULL; } memcpy(p->bits, bits, YAM_FPGA_SIZE); @@ -369,6 +412,7 @@ static unsigned char *add_mcs(unsigned char *bits, int bitrate) p->next = yam_data; yam_data = p; + release_firmware(fw); return p->bits; } @@ -386,9 +430,11 @@ static unsigned char *get_mcs(int bitrate) /* Load predefined mcs data */ switch (bitrate) { case 1200: - return add_mcs(bits_1200, bitrate); + /* setting predef as YAM_1200 for loading predef 1200 mcs */ + return add_mcs(NULL, bitrate, YAM_1200); default: - return add_mcs(bits_9600, bitrate); + /* setting predef as YAM_9600 for loading predef 9600 mcs */ + return add_mcs(NULL, bitrate, YAM_9600); } } @@ -507,7 +553,7 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp) } else { if (!(skb = dev_alloc_skb(pkt_len))) { printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name); - ++yp->stats.rx_dropped; + ++dev->stats.rx_dropped; } else { unsigned char *cp; cp = skb_put(skb, pkt_len); @@ -515,7 +561,7 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp) memcpy(cp, yp->rx_buf, pkt_len - 1); skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); - ++yp->stats.rx_packets; + ++dev->stats.rx_packets; } } } @@ -677,7 +723,7 @@ static void yam_tx_byte(struct net_device *dev, struct yam_port *yp) yp->tx_count = 1; yp->tx_state = TX_HEAD; } - ++yp->stats.tx_packets; + ++dev->stats.tx_packets; break; case TX_TAIL: if (--yp->tx_count <= 0) { @@ -716,7 +762,7 @@ static irqreturn_t yam_interrupt(int irq, void *dev_id) handled = 1; if (lsr & LSR_OE) - ++yp->stats.rx_fifo_errors; + ++dev->stats.rx_fifo_errors; yp->dcd = (msr & RX_DCD) ? 1 : 0; @@ -778,16 +824,16 @@ static int yam_seq_show(struct seq_file *seq, void *v) seq_printf(seq, " TxTail %u\n", yp->txtail); seq_printf(seq, " SlotTime %u\n", yp->slot); seq_printf(seq, " Persist %u\n", yp->pers); - seq_printf(seq, " TxFrames %lu\n", yp->stats.tx_packets); - seq_printf(seq, " RxFrames %lu\n", yp->stats.rx_packets); + seq_printf(seq, " TxFrames %lu\n", dev->stats.tx_packets); + seq_printf(seq, " RxFrames %lu\n", dev->stats.rx_packets); seq_printf(seq, " TxInt %u\n", yp->nb_mdint); seq_printf(seq, " RxInt %u\n", yp->nb_rxint); - seq_printf(seq, " RxOver %lu\n", yp->stats.rx_fifo_errors); + seq_printf(seq, " RxOver %lu\n", dev->stats.rx_fifo_errors); seq_printf(seq, "\n"); return 0; } -static struct seq_operations yam_seqops = { +static const struct seq_operations yam_seqops = { .start = yam_seq_start, .next = yam_seq_next, .stop = yam_seq_stop, @@ -812,26 +858,6 @@ static const struct file_operations yam_info_fops = { /* --------------------------------------------------------------------- */ -static struct net_device_stats *yam_get_stats(struct net_device *dev) -{ - struct yam_port *yp; - - if (!dev) - return NULL; - - yp = netdev_priv(dev); - if (yp->magic != YAM_MAGIC) - return NULL; - - /* - * Get the current statistics. This may be called with the - * card open or closed. - */ - return &yp->stats; -} - -/* --------------------------------------------------------------------- */ - static int yam_open(struct net_device *dev) { struct yam_port *yp = netdev_priv(dev); @@ -877,10 +903,10 @@ static int yam_open(struct net_device *dev) /* Reset overruns for all ports - FPGA programming makes overruns */ for (i = 0; i < NR_PORTS; i++) { - struct net_device *dev = yam_devs[i]; - struct yam_port *yp = netdev_priv(dev); - inb(LSR(dev->base_addr)); - yp->stats.rx_fifo_errors = 0; + struct net_device *yam_dev = yam_devs[i]; + + inb(LSR(yam_dev->base_addr)); + yam_dev->stats.rx_fifo_errors = 0; } printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq, @@ -959,7 +985,8 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) kfree(ym); return -EINVAL; } - add_mcs(ym->bits, ym->bitrate); + /* setting predef as 0 for loading userdefined mcs data */ + add_mcs(ym->bits, ym->bitrate, 0); kfree(ym); break; @@ -1068,6 +1095,14 @@ static int yam_set_mac_address(struct net_device *dev, void *addr) /* --------------------------------------------------------------------- */ +static const struct net_device_ops yam_netdev_ops = { + .ndo_open = yam_open, + .ndo_stop = yam_close, + .ndo_start_xmit = yam_send_packet, + .ndo_do_ioctl = yam_ioctl, + .ndo_set_mac_address = yam_set_mac_address, +}; + static void yam_setup(struct net_device *dev) { struct yam_port *yp = netdev_priv(dev); @@ -1088,18 +1123,11 @@ static void yam_setup(struct net_device *dev) dev->base_addr = yp->iobase; dev->irq = yp->irq; - dev->open = yam_open; - dev->stop = yam_close; - dev->do_ioctl = yam_ioctl; - dev->hard_start_xmit = yam_send_packet; - dev->get_stats = yam_get_stats; - skb_queue_head_init(&yp->send_queue); + dev->netdev_ops = &yam_netdev_ops; dev->header_ops = &ax25_header_ops; - dev->set_mac_address = yam_set_mac_address; - dev->type = ARPHRD_AX25; dev->hard_header_len = AX25_MAX_HEADER_LEN; dev->mtu = AX25_MTU; @@ -1181,6 +1209,8 @@ static void __exit yam_cleanup_driver(void) MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr"); MODULE_DESCRIPTION("Yam amateur radio modem driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE_1200); +MODULE_FIRMWARE(FIRMWARE_9600); module_init(yam_init_driver); module_exit(yam_cleanup_driver); |