mips: declance: Driver model for the PMAD-A
This is a set of changes that converts the PMAD-A support to the driver model. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
d9a9720eab
commit
257b346d20
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
* adopted from sunlance.c by Richard van den Berg
|
* adopted from sunlance.c by Richard van den Berg
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki
|
* Copyright (C) 2002, 2003, 2005, 2006 Maciej W. Rozycki
|
||||||
*
|
*
|
||||||
* additional sources:
|
* additional sources:
|
||||||
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
|
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
|
||||||
|
@ -44,6 +44,8 @@
|
||||||
* v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
|
* v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the
|
||||||
* PMAX requirement to only use halfword accesses to the
|
* PMAX requirement to only use halfword accesses to the
|
||||||
* buffer. macro
|
* buffer. macro
|
||||||
|
*
|
||||||
|
* v0.011: Converted the PMAD to the driver model. macro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
@ -58,6 +60,7 @@
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/stddef.h>
|
#include <linux/stddef.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/tc.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include <asm/addrspace.h>
|
#include <asm/addrspace.h>
|
||||||
|
@ -69,15 +72,16 @@
|
||||||
#include <asm/dec/kn01.h>
|
#include <asm/dec/kn01.h>
|
||||||
#include <asm/dec/machtype.h>
|
#include <asm/dec/machtype.h>
|
||||||
#include <asm/dec/system.h>
|
#include <asm/dec/system.h>
|
||||||
#include <asm/dec/tc.h>
|
|
||||||
|
|
||||||
static char version[] __devinitdata =
|
static char version[] __devinitdata =
|
||||||
"declance.c: v0.010 by Linux MIPS DECstation task force\n";
|
"declance.c: v0.011 by Linux MIPS DECstation task force\n";
|
||||||
|
|
||||||
MODULE_AUTHOR("Linux MIPS DECstation task force");
|
MODULE_AUTHOR("Linux MIPS DECstation task force");
|
||||||
MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
|
MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
#define __unused __attribute__ ((unused))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* card types
|
* card types
|
||||||
*/
|
*/
|
||||||
|
@ -246,7 +250,6 @@ struct lance_init_block {
|
||||||
struct lance_private {
|
struct lance_private {
|
||||||
struct net_device *next;
|
struct net_device *next;
|
||||||
int type;
|
int type;
|
||||||
int slot;
|
|
||||||
int dma_irq;
|
int dma_irq;
|
||||||
volatile struct lance_regs *ll;
|
volatile struct lance_regs *ll;
|
||||||
|
|
||||||
|
@ -288,6 +291,7 @@ struct lance_regs {
|
||||||
|
|
||||||
int dec_lance_debug = 2;
|
int dec_lance_debug = 2;
|
||||||
|
|
||||||
|
static struct tc_driver dec_lance_tc_driver;
|
||||||
static struct net_device *root_lance_dev;
|
static struct net_device *root_lance_dev;
|
||||||
|
|
||||||
static inline void writereg(volatile unsigned short *regptr, short value)
|
static inline void writereg(volatile unsigned short *regptr, short value)
|
||||||
|
@ -1023,7 +1027,7 @@ static void lance_set_multicast_retry(unsigned long _opaque)
|
||||||
lance_set_multicast(dev);
|
lance_set_multicast(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init dec_lance_init(const int type, const int slot)
|
static int __init dec_lance_probe(struct device *bdev, const int type)
|
||||||
{
|
{
|
||||||
static unsigned version_printed;
|
static unsigned version_printed;
|
||||||
static const char fmt[] = "declance%d";
|
static const char fmt[] = "declance%d";
|
||||||
|
@ -1031,6 +1035,7 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct lance_private *lp;
|
struct lance_private *lp;
|
||||||
volatile struct lance_regs *ll;
|
volatile struct lance_regs *ll;
|
||||||
|
resource_size_t start = 0, len = 0;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
unsigned long esar_base;
|
unsigned long esar_base;
|
||||||
unsigned char *esar;
|
unsigned char *esar;
|
||||||
|
@ -1038,14 +1043,18 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
if (dec_lance_debug && version_printed++ == 0)
|
if (dec_lance_debug && version_printed++ == 0)
|
||||||
printk(version);
|
printk(version);
|
||||||
|
|
||||||
i = 0;
|
if (bdev)
|
||||||
dev = root_lance_dev;
|
snprintf(name, sizeof(name), "%s", bdev->bus_id);
|
||||||
while (dev) {
|
else {
|
||||||
i++;
|
i = 0;
|
||||||
lp = (struct lance_private *)dev->priv;
|
dev = root_lance_dev;
|
||||||
dev = lp->next;
|
while (dev) {
|
||||||
|
i++;
|
||||||
|
lp = (struct lance_private *)dev->priv;
|
||||||
|
dev = lp->next;
|
||||||
|
}
|
||||||
|
snprintf(name, sizeof(name), fmt, i);
|
||||||
}
|
}
|
||||||
snprintf(name, sizeof(name), fmt, i);
|
|
||||||
|
|
||||||
dev = alloc_etherdev(sizeof(struct lance_private));
|
dev = alloc_etherdev(sizeof(struct lance_private));
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
|
@ -1063,7 +1072,6 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
spin_lock_init(&lp->lock);
|
spin_lock_init(&lp->lock);
|
||||||
|
|
||||||
lp->type = type;
|
lp->type = type;
|
||||||
lp->slot = slot;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ASIC_LANCE:
|
case ASIC_LANCE:
|
||||||
dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
|
dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE);
|
||||||
|
@ -1110,12 +1118,22 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_TC
|
#ifdef CONFIG_TC
|
||||||
case PMAD_LANCE:
|
case PMAD_LANCE:
|
||||||
claim_tc_card(slot);
|
dev_set_drvdata(bdev, dev);
|
||||||
|
|
||||||
dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot));
|
start = to_tc_dev(bdev)->resource.start;
|
||||||
|
len = to_tc_dev(bdev)->resource.end - start + 1;
|
||||||
|
if (!request_mem_region(start, len, bdev->bus_id)) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Unable to reserve MMIO resource\n",
|
||||||
|
bdev->bus_id);
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto err_out_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->mem_start = CKSEG1ADDR(start);
|
||||||
dev->mem_end = dev->mem_start + 0x100000;
|
dev->mem_end = dev->mem_start + 0x100000;
|
||||||
dev->base_addr = dev->mem_start + 0x100000;
|
dev->base_addr = dev->mem_start + 0x100000;
|
||||||
dev->irq = get_tc_irq_nr(slot);
|
dev->irq = to_tc_dev(bdev)->interrupt;
|
||||||
esar_base = dev->mem_start + 0x1c0002;
|
esar_base = dev->mem_start + 0x1c0002;
|
||||||
lp->dma_irq = -1;
|
lp->dma_irq = -1;
|
||||||
|
|
||||||
|
@ -1174,7 +1192,7 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
printk(KERN_ERR "%s: declance_init called with unknown type\n",
|
printk(KERN_ERR "%s: declance_init called with unknown type\n",
|
||||||
name);
|
name);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_out_free_dev;
|
goto err_out_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
ll = (struct lance_regs *) dev->base_addr;
|
ll = (struct lance_regs *) dev->base_addr;
|
||||||
|
@ -1188,7 +1206,7 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
"%s: Ethernet station address prom not found!\n",
|
"%s: Ethernet station address prom not found!\n",
|
||||||
name);
|
name);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_out_free_dev;
|
goto err_out_resource;
|
||||||
}
|
}
|
||||||
/* Check the prom contents */
|
/* Check the prom contents */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
|
@ -1198,7 +1216,7 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
printk(KERN_ERR "%s: Something is wrong with the "
|
printk(KERN_ERR "%s: Something is wrong with the "
|
||||||
"ethernet station address prom!\n", name);
|
"ethernet station address prom!\n", name);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_out_free_dev;
|
goto err_out_resource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,48 +1273,51 @@ static int __init dec_lance_init(const int type, const int slot)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"%s: Unable to register netdev, aborting.\n", name);
|
"%s: Unable to register netdev, aborting.\n", name);
|
||||||
goto err_out_free_dev;
|
goto err_out_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->next = root_lance_dev;
|
if (!bdev) {
|
||||||
root_lance_dev = dev;
|
lp->next = root_lance_dev;
|
||||||
|
root_lance_dev = dev;
|
||||||
|
}
|
||||||
|
|
||||||
printk("%s: registered as %s.\n", name, dev->name);
|
printk("%s: registered as %s.\n", name, dev->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out_free_dev:
|
err_out_resource:
|
||||||
|
if (bdev)
|
||||||
|
release_mem_region(start, len);
|
||||||
|
|
||||||
|
err_out_dev:
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __exit dec_lance_remove(struct device *bdev)
|
||||||
|
{
|
||||||
|
struct net_device *dev = dev_get_drvdata(bdev);
|
||||||
|
resource_size_t start, len;
|
||||||
|
|
||||||
|
unregister_netdev(dev);
|
||||||
|
start = to_tc_dev(bdev)->resource.start;
|
||||||
|
len = to_tc_dev(bdev)->resource.end - start + 1;
|
||||||
|
release_mem_region(start, len);
|
||||||
|
free_netdev(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find all the lance cards on the system and initialize them */
|
/* Find all the lance cards on the system and initialize them */
|
||||||
static int __init dec_lance_probe(void)
|
static int __init dec_lance_platform_probe(void)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
/* Scan slots for PMAD-AA cards first. */
|
|
||||||
#ifdef CONFIG_TC
|
|
||||||
if (TURBOCHANNEL) {
|
|
||||||
int slot;
|
|
||||||
|
|
||||||
while ((slot = search_tc_card("PMAD-AA")) >= 0) {
|
|
||||||
if (dec_lance_init(PMAD_LANCE, slot) < 0)
|
|
||||||
break;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Then handle onboard devices. */
|
|
||||||
if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
|
if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
|
||||||
if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
|
if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
|
||||||
if (dec_lance_init(ASIC_LANCE, -1) >= 0)
|
if (dec_lance_probe(NULL, ASIC_LANCE) >= 0)
|
||||||
count++;
|
count++;
|
||||||
} else if (!TURBOCHANNEL) {
|
} else if (!TURBOCHANNEL) {
|
||||||
if (dec_lance_init(PMAX_LANCE, -1) >= 0)
|
if (dec_lance_probe(NULL, PMAX_LANCE) >= 0)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1304,21 +1325,70 @@ static int __init dec_lance_probe(void)
|
||||||
return (count > 0) ? 0 : -ENODEV;
|
return (count > 0) ? 0 : -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit dec_lance_cleanup(void)
|
static void __exit dec_lance_platform_remove(void)
|
||||||
{
|
{
|
||||||
while (root_lance_dev) {
|
while (root_lance_dev) {
|
||||||
struct net_device *dev = root_lance_dev;
|
struct net_device *dev = root_lance_dev;
|
||||||
struct lance_private *lp = netdev_priv(dev);
|
struct lance_private *lp = netdev_priv(dev);
|
||||||
|
|
||||||
unregister_netdev(dev);
|
unregister_netdev(dev);
|
||||||
#ifdef CONFIG_TC
|
|
||||||
if (lp->slot >= 0)
|
|
||||||
release_tc_card(lp->slot);
|
|
||||||
#endif
|
|
||||||
root_lance_dev = lp->next;
|
root_lance_dev = lp->next;
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(dec_lance_probe);
|
#ifdef CONFIG_TC
|
||||||
module_exit(dec_lance_cleanup);
|
static int __init dec_lance_tc_probe(struct device *dev);
|
||||||
|
static int __exit dec_lance_tc_remove(struct device *dev);
|
||||||
|
|
||||||
|
static const struct tc_device_id dec_lance_tc_table[] = {
|
||||||
|
{ "DEC ", "PMAD-AA " },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(tc, dec_lance_tc_table);
|
||||||
|
|
||||||
|
static struct tc_driver dec_lance_tc_driver = {
|
||||||
|
.id_table = dec_lance_tc_table,
|
||||||
|
.driver = {
|
||||||
|
.name = "declance",
|
||||||
|
.bus = &tc_bus_type,
|
||||||
|
.probe = dec_lance_tc_probe,
|
||||||
|
.remove = __exit_p(dec_lance_tc_remove),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init dec_lance_tc_probe(struct device *dev)
|
||||||
|
{
|
||||||
|
int status = dec_lance_probe(dev, PMAD_LANCE);
|
||||||
|
if (!status)
|
||||||
|
get_device(dev);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __exit dec_lance_tc_remove(struct device *dev)
|
||||||
|
{
|
||||||
|
put_device(dev);
|
||||||
|
dec_lance_remove(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int __init dec_lance_init(void)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = tc_register_driver(&dec_lance_tc_driver);
|
||||||
|
if (!status)
|
||||||
|
dec_lance_platform_probe();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit dec_lance_exit(void)
|
||||||
|
{
|
||||||
|
dec_lance_platform_remove();
|
||||||
|
tc_unregister_driver(&dec_lance_tc_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module_init(dec_lance_init);
|
||||||
|
module_exit(dec_lance_exit);
|
||||||
|
|
Loading…
Reference in New Issue