Commit 7f13c9f8 authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] hamradio/scc -

Update hamradio/scc for 2.6.0-test5
	- use seq_file for /proc
	- get rid of dev_get()
	- use alloc_netdev

Don't have hardware, but can load/unload the module fine.
parent 5f179911
...@@ -171,6 +171,7 @@ ...@@ -171,6 +171,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/ax25.h> #include <net/ax25.h>
...@@ -202,8 +203,8 @@ static void scc_key_trx (struct scc_channel *scc, char tx); ...@@ -202,8 +203,8 @@ static void scc_key_trx (struct scc_channel *scc, char tx);
static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void scc_init_timer(struct scc_channel *scc); static void scc_init_timer(struct scc_channel *scc);
static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev); static int scc_net_alloc(const char *name, struct scc_channel *scc);
static int scc_net_init(struct net_device *dev); static void scc_net_setup(struct net_device *dev);
static int scc_net_open(struct net_device *dev); static int scc_net_open(struct net_device *dev);
static int scc_net_close(struct net_device *dev); static int scc_net_close(struct net_device *dev);
static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb); static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
...@@ -235,7 +236,7 @@ static io_port Vector_Latch; ...@@ -235,7 +236,7 @@ static io_port Vector_Latch;
/* These provide interrupt save 2-step access to the Z8530 registers */ /* These provide interrupt save 2-step access to the Z8530 registers */
static spinlock_t iolock; /* Guards paired accesses */ static spinlock_t iolock = SPIN_LOCK_UNLOCKED; /* Guards paired accesses */
static inline unsigned char InReg(io_port port, unsigned char reg) static inline unsigned char InReg(io_port port, unsigned char reg)
{ {
...@@ -1512,34 +1513,28 @@ static void z8530_init(void) ...@@ -1512,34 +1513,28 @@ static void z8530_init(void)
* Allocate device structure, err, instance, and register driver * Allocate device structure, err, instance, and register driver
*/ */
static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev) static int scc_net_alloc(const char *name, struct scc_channel *scc)
{ {
int err;
struct net_device *dev; struct net_device *dev;
if (dev_get(name)) dev = alloc_netdev(0, name, scc_net_setup);
{ if (!dev)
printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
return -EEXIST;
}
if ((scc->dev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL)
return -ENOMEM; return -ENOMEM;
dev = scc->dev; dev->priv = scc;
memset(dev, 0, sizeof(struct net_device)); scc->dev = dev;
strcpy(dev->name, name);
dev->priv = (void *) scc;
dev->init = scc_net_init;
spin_lock_init(&scc->lock); spin_lock_init(&scc->lock);
if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0) {
kfree(dev);
return -EIO;
}
SET_MODULE_OWNER(dev); err = register_netdev(dev);
if (err) {
printk(KERN_ERR "%s: can't register network device (%d)\n",
name, err);
free_netdev(dev);
scc->dev = NULL;
return err;
}
return 0; return 0;
} }
...@@ -1556,8 +1551,9 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] = ...@@ -1556,8 +1551,9 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] =
/* ----> Initialize device <----- */ /* ----> Initialize device <----- */
static int scc_net_init(struct net_device *dev) static void scc_net_setup(struct net_device *dev)
{ {
SET_MODULE_OWNER(dev);
dev->tx_queue_len = 16; /* should be enough... */ dev->tx_queue_len = 16; /* should be enough... */
dev->open = scc_net_open; dev->open = scc_net_open;
...@@ -1581,7 +1577,6 @@ static int scc_net_init(struct net_device *dev) ...@@ -1581,7 +1577,6 @@ static int scc_net_init(struct net_device *dev)
dev->mtu = AX25_DEF_PACLEN; dev->mtu = AX25_DEF_PACLEN;
dev->addr_len = AX25_ADDR_LEN; dev->addr_len = AX25_ADDR_LEN;
return 0;
} }
/* ----> open network device <---- */ /* ----> open network device <---- */
...@@ -1719,10 +1714,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -1719,10 +1714,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct scc_mem_config memcfg; struct scc_mem_config memcfg;
struct scc_hw_config hwcfg; struct scc_hw_config hwcfg;
struct scc_calibrate cal; struct scc_calibrate cal;
struct scc_channel *scc;
int chan; int chan;
unsigned char device_name[10]; unsigned char device_name[IFNAMSIZ];
void *arg; void *arg;
struct scc_channel *scc;
scc = (struct scc_channel *) dev->priv; scc = (struct scc_channel *) dev->priv;
arg = (void *) ifr->ifr_data; arg = (void *) ifr->ifr_data;
...@@ -1828,8 +1823,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -1828,8 +1823,10 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl"); request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data"); request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
if (Nchips+chan != 0) if (Nchips+chan != 0 &&
scc_net_setup(&SCC_Info[2*Nchips+chan], device_name, 1); scc_net_alloc(device_name,
&SCC_Info[2*Nchips+chan]))
return -EINVAL;
} }
} }
...@@ -1978,39 +1975,58 @@ static struct net_device_stats *scc_net_get_stats(struct net_device *dev) ...@@ -1978,39 +1975,58 @@ static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
/* * dump statistics to /proc/net/z8530drv * */ /* * dump statistics to /proc/net/z8530drv * */
/* ******************************************************************** */ /* ******************************************************************** */
#ifdef CONFIG_PROC_FS
static int scc_net_get_info(char *buffer, char **start, off_t offset, int length) static inline struct scc_channel *scc_net_seq_idx(loff_t pos)
{ {
struct scc_channel *scc;
struct scc_kiss *kiss;
struct scc_stat *stat;
int len = 0;
off_t pos = 0;
off_t begin = 0;
int k; int k;
len += sprintf(buffer, "z8530drv-"VERSION"\n"); for (k = 0; k < Nchips*2; ++k) {
if (!SCC_Info[k].init)
if (!Driver_Initialized) continue;
{ if (pos-- == 0)
len += sprintf(buffer+len, "not initialized\n"); return &SCC_Info[k];
goto done;
} }
return NULL;
}
if (!Nchips) static void *scc_net_seq_start(struct seq_file *seq, loff_t *pos)
{ {
len += sprintf(buffer+len, "chips missing\n"); return *pos ? scc_net_seq_idx(*pos - 1) : SEQ_START_TOKEN;
goto done;
}
static void *scc_net_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
unsigned k;
struct scc_channel *scc = v;
++*pos;
for (k = (v == SEQ_START_TOKEN) ? 0 : (scc - SCC_Info)+1;
k < Nchips*2; ++k) {
if (SCC_Info[k].init)
return &SCC_Info[k];
} }
return NULL;
}
for (k = 0; k < Nchips*2; k++) static void scc_net_seq_stop(struct seq_file *seq, void *v)
{ {
scc = &SCC_Info[k]; }
stat = &scc->stat;
kiss = &scc->kiss; static int scc_net_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "z8530drv-"VERSION"\n");
} else if (!Driver_Initialized) {
seq_puts(seq, "not initialized\n");
} else if (!Nchips) {
seq_puts(seq, "chips missing\n");
} else {
const struct scc_channel *scc = v;
const struct scc_stat *stat = &scc->stat;
const struct scc_kiss *kiss = &scc->kiss;
if (!scc->init)
continue;
/* dev data ctrl irq clock brand enh vector special option /* dev data ctrl irq clock brand enh vector special option
* baud nrz clocksrc softdcd bufsize * baud nrz clocksrc softdcd bufsize
...@@ -2021,24 +2037,24 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length ...@@ -2021,24 +2037,24 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length
* R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ## * R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
*/ */
len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n", seq_printf(seq, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
scc->dev->name, scc->dev->name,
scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand, scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
scc->enhanced, Vector_Latch, scc->special, scc->enhanced, Vector_Latch, scc->special,
scc->option); scc->option);
len += sprintf(buffer+len, "\t%lu %d %d %d %d\n", seq_printf(seq, "\t%lu %d %d %d %d\n",
scc->modem.speed, scc->modem.nrz, scc->modem.speed, scc->modem.nrz,
scc->modem.clocksrc, kiss->softdcd, scc->modem.clocksrc, kiss->softdcd,
stat->bufsize); stat->bufsize);
len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n", seq_printf(seq, "\t%lu %lu %lu %lu\n",
stat->rxints, stat->txints, stat->exints, stat->spints); stat->rxints, stat->txints, stat->exints, stat->spints);
len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d %d\n", seq_printf(seq, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
stat->rxframes, stat->rxerrs, stat->rx_over, stat->rxframes, stat->rxerrs, stat->rx_over,
stat->txframes, stat->txerrs, stat->tx_under, stat->txframes, stat->txerrs, stat->tx_under,
stat->nospace, stat->tx_state); stat->nospace, stat->tx_state);
#define K(x) kiss->x #define K(x) kiss->x
len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n", seq_printf(seq, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
K(txdelay), K(persist), K(slottime), K(tailtime), K(txdelay), K(persist), K(slottime), K(tailtime),
K(fulldup), K(waittime), K(mintime), K(maxkeyup), K(fulldup), K(waittime), K(mintime), K(maxkeyup),
K(idletime), K(maxdefer), K(tx_inhibit), K(group)); K(idletime), K(maxdefer), K(tx_inhibit), K(group));
...@@ -2047,43 +2063,49 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length ...@@ -2047,43 +2063,49 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length
{ {
int reg; int reg;
len += sprintf(buffer+len, "\tW "); seq_printf(seq, "\tW ");
for (reg = 0; reg < 16; reg++) for (reg = 0; reg < 16; reg++)
len += sprintf(buffer+len, "%2.2x ", scc->wreg[reg]); seq_printf(seq, "%2.2x ", scc->wreg[reg]);
len += sprintf(buffer+len, "\n"); seq_printf(seq, "\n");
len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1)); seq_printf(seq, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
for (reg = 3; reg < 8; reg++) for (reg = 3; reg < 8; reg++)
len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg)); seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
len += sprintf(buffer+len, "XX "); seq_printf(seq, "XX ");
for (reg = 9; reg < 16; reg++) for (reg = 9; reg < 16; reg++)
len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg)); seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
len += sprintf(buffer+len, "\n"); seq_printf(seq, "\n");
} }
#endif #endif
len += sprintf(buffer+len, "\n"); seq_putc(seq, '\n');
pos = begin + len;
if (pos < offset) {
len = 0;
begin = pos;
}
if (pos > offset + length)
break;
} }
done: return 0;
}
*start = buffer + (offset - begin); static struct seq_operations scc_net_seq_ops = {
len -= (offset - begin); .start = scc_net_seq_start,
.next = scc_net_seq_next,
.stop = scc_net_seq_stop,
.show = scc_net_seq_show,
};
if (len > length) len = length;
return len; static int scc_net_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &scc_net_seq_ops);
} }
static struct file_operations scc_net_seq_fops = {
.owner = THIS_MODULE,
.open = scc_net_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release_private,
};
#endif /* CONFIG_PROC_FS */
/* ******************************************************************** */ /* ******************************************************************** */
/* * Init SCC driver * */ /* * Init SCC driver * */
...@@ -2091,23 +2113,18 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length ...@@ -2091,23 +2113,18 @@ static int scc_net_get_info(char *buffer, char **start, off_t offset, int length
static int __init scc_init_driver (void) static int __init scc_init_driver (void)
{ {
int result; char devname[IFNAMSIZ];
char devname[10];
printk(banner); printk(banner);
spin_lock_init(&iolock);
sprintf(devname,"%s0", SCC_DriverName); sprintf(devname,"%s0", SCC_DriverName);
result = scc_net_setup(SCC_Info, devname, 0); if (scc_net_alloc(devname, SCC_Info)) {
if (result)
{
printk(KERN_ERR "z8530drv: cannot initialize module\n"); printk(KERN_ERR "z8530drv: cannot initialize module\n");
return result; return -EIO;
} }
proc_net_create("z8530drv", 0, scc_net_get_info); proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
return 0; return 0;
} }
...@@ -2117,11 +2134,12 @@ static void __exit scc_cleanup_driver(void) ...@@ -2117,11 +2134,12 @@ static void __exit scc_cleanup_driver(void)
io_port ctrl; io_port ctrl;
int k; int k;
struct scc_channel *scc; struct scc_channel *scc;
struct net_device *dev;
if (Nchips == 0) if (Nchips == 0 && (dev = SCC_Info[0].dev))
{ {
unregister_netdev(SCC_Info[0].dev); unregister_netdev(dev);
free_netdev(SCC_Info[0].dev); free_netdev(dev);
} }
/* Guard against chip prattle */ /* Guard against chip prattle */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment