@@ -136,6 +136,8 @@ config NE2K_PCI
config APNE
tristate "PCMCIA NE2000 support"
depends on AMIGA_PCMCIA
+ select PCCARD
+ select PCMCIA
select CRC32
help
If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
@@ -144,6 +146,13 @@ config APNE
To compile this driver as a module, choose M here: the module
will be called apne.
+ The driver also supports 10/100Mbit cards (e.g. Netgear FA411,
+ CNet Singlepoint). To activate 100 Mbit support, use the kernel
+ option apne.100mbit=1 (builtin) at boot time, or the apne.100mbit
+ module parameter. The driver will attempt to autoprobe 100 Mbit
+ mode, so this option may not be necessary. Use apne.100mbit=0
+ should autoprobe mis-detect a 100 Mbit card.
+
config PCMCIA_PCNET
tristate "NE2000 compatible PCMCIA support"
depends on PCMCIA
@@ -38,6 +38,7 @@
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
+#include <pcmcia/cistpl.h>
#include <asm/io.h>
#include <asm/setup.h>
@@ -87,6 +88,7 @@ static void apne_block_output(struct net_device *dev, const int count,
static irqreturn_t apne_interrupt(int irq, void *dev_id);
static int init_pcmcia(void);
+static int pcmcia_is_16bit(void);
/* IO base address used for nic */
@@ -119,6 +121,10 @@ static u32 apne_msg_enable;
module_param_named(msg_enable, apne_msg_enable, uint, 0444);
MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
+static u32 apne_100_mbit = -1;
+module_param_named(100_mbit, apne_100_mbit, uint, 0444);
+MODULE_PARM_DESC(100_mbit, "Enable 100 Mbit support");
+
static struct net_device * __init apne_probe(void)
{
struct net_device *dev;
@@ -140,6 +146,13 @@ static struct net_device * __init apne_probe(void)
pr_info("Looking for PCMCIA ethernet card : ");
+ if (apne_100_mbit == 1)
+ isa_type = ISA_TYPE_AG16;
+ else if (apne_100_mbit == 0)
+ isa_type = ISA_TYPE_AG;
+ else
+ pr_cont(" (autoprobing 16 bit mode) ");
+
/* check if a card is inserted */
if (!(PCMCIA_INSERTED)) {
pr_cont("NO PCMCIA card inserted\n");
@@ -167,6 +180,14 @@ static struct net_device * __init apne_probe(void)
pr_cont("ethernet PCMCIA card inserted\n");
+#if IS_ENABLED(CONFIG_PCMCIA)
+ if (apne_100_mbit < 0 && pcmcia_is_16bit()) {
+ pr_info("16-bit PCMCIA card detected!\n");
+ isa_type = ISA_TYPE_AG16;
+ apne_100_mbit = 1;
+ }
+#endif
+
if (!init_pcmcia()) {
/* XXX: shouldn't we re-enable irq here? */
free_netdev(dev);
@@ -583,6 +604,16 @@ static int init_pcmcia(void)
#endif
u_long offset;
+ /* reset card (idea taken from CardReset by Artur Pogoda) */
+ if (isa_type == ISA_TYPE_AG16) {
+ u_char tmp = gayle.intreq;
+
+ gayle.intreq = 0xff;
+ mdelay(1);
+ gayle.intreq = tmp;
+ mdelay(300);
+ }
+
pcmcia_reset();
pcmcia_program_voltage(PCMCIA_0V);
pcmcia_access_speed(PCMCIA_SPEED_250NS);
@@ -616,4 +647,42 @@ static int init_pcmcia(void)
return 1;
}
+#if IS_ENABLED(CONFIG_PCMCIA)
+static int pcmcia_is_16bit(void)
+{
+ u_char cftuple[258];
+ int cftuple_len;
+ tuple_t cftable_tuple;
+ cistpl_cftable_entry_t cftable_entry;
+
+ cftuple_len = pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, cftuple, 256);
+ if (cftuple_len < 3)
+ return 0;
+#ifdef DEBUG
+ else
+ print_hex_dump(KERN_WARNING, "cftable: ", DUMP_PREFIX_NONE, 8,
+ sizeof(char), cftuple, cftuple_len, false);
+#endif
+
+ /* build tuple_t struct and call pcmcia_parse_tuple */
+ cftable_tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ cftable_tuple.TupleCode = CISTPL_CFTABLE_ENTRY;
+ cftable_tuple.TupleData = &cftuple[2];
+ cftable_tuple.TupleDataLen = cftuple_len - 2;
+ cftable_tuple.TupleDataMax = cftuple_len - 2;
+
+ if (pcmcia_parse_tuple(&cftable_tuple, (cisparse_t *)&cftable_entry))
+ return 0;
+
+#ifdef DEBUG
+ pr_info("IO flags: %x\n", cftable_entry.io.flags);
+#endif
+
+ if (cftable_entry.io.flags & CISTPL_IO_16BIT)
+ return 1;
+
+ return 0;
+}
+#endif
+
MODULE_LICENSE("GPL");