@@ -144,6 +144,14 @@ 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 if the PCCARD and PCMCIA kernel configuration options are
+ selected, so this option may not be necessary. Use apne.100mbit=0
+ should autoprobe mis-detect a 10 Mbit card as 100 Mbit.
+
config PCMCIA_PCNET
tristate "NE2000 compatible PCMCIA support"
depends on PCMCIA
@@ -119,6 +119,45 @@ 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 int apne_100_mbit = -1;
+module_param_named(100_mbit, apne_100_mbit, int, 0444);
+MODULE_PARM_DESC(100_mbit, "Enable 100 Mbit support");
+
+#if IS_REACHABLE(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;
+ else
+ print_hex_dump_debug("cftable: ", DUMP_PREFIX_NONE, 8,
+ sizeof(char), cftuple, cftuple_len, false);
+
+ /* 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, container_of(&cftable_entry,
+ cisparse_t, cftable_entry)))
+ return 0;
+
+ pr_debug("IO flags: %x\n", cftable_entry.io.flags);
+
+ if (cftable_entry.io.flags & CISTPL_IO_16BIT)
+ return 1;
+
+ return 0;
+}
+#endif
+
static struct net_device * __init apne_probe(void)
{
struct net_device *dev;
@@ -140,6 +179,17 @@ 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
+#if IS_REACHABLE(CONFIG_PCMCIA)
+ pr_cont(" (autoprobing 16 bit mode) ");
+#else
+ pr_cont(" (no 16 bit autoprobe support) ");
+#endif
+
/* check if a card is inserted */
if (!(PCMCIA_INSERTED)) {
pr_cont("NO PCMCIA card inserted\n");
@@ -167,6 +217,19 @@ static struct net_device * __init apne_probe(void)
pr_cont("ethernet PCMCIA card inserted\n");
+#if IS_REACHABLE(CONFIG_PCMCIA)
+ if (apne_100_mbit < 0) {
+ if (pcmcia_is_16bit()) {
+ pr_info("16-bit PCMCIA card detected!\n");
+ isa_type = ISA_TYPE_AG16;
+ apne_100_mbit = 1;
+ } else {
+ isa_type = ISA_TYPE_AG;
+ apne_100_mbit = 0;
+ }
+ }
+#endif
+
if (!init_pcmcia()) {
/* XXX: shouldn't we re-enable irq here? */
free_netdev(dev);
@@ -193,6 +256,10 @@ static struct net_device * __init apne_probe(void)
pcmcia_reset();
release_region(IOBASE, 0x20);
free_netdev(dev);
+#if IS_REACHABLE(CONFIG_PCMCIA)
+ isa_type = ISA_TYPE_AG;
+ apne_100_mbit = -1;
+#endif
return ERR_PTR(err);
}
@@ -570,6 +637,11 @@ static void __exit apne_module_exit(void)
release_region(IOBASE, 0x20);
free_netdev(apne_dev);
+
+#if IS_REACHABLE(CONFIG_PCMCIA)
+ isa_type = ISA_TYPE_AG;
+ apne_100_mbit = -1;
+#endif
}
module_init(apne_module_init);
module_exit(apne_module_exit);
@@ -583,6 +655,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);