patch-2.4.0-test9 linux/drivers/net/cs89x0.c
Next file: linux/drivers/net/declance.c
Previous file: linux/drivers/net/bonding.c
Back to the patch index
Back to the overall index
- Lines: 242
- Date:
Tue Sep 19 08:31:53 2000
- Orig file:
v2.4.0-test8/linux/drivers/net/cs89x0.c
- Orig date:
Wed Jul 5 11:54:11 2000
diff -u --recursive --new-file v2.4.0-test8/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
@@ -61,6 +61,11 @@
: MOD_INC/DEC race fix (see
: http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
+ Andrew Morton : andrewm@uow.edu.au / Kernel 2.4.0-test7-pre2
+ : Enhanced EEPROM support to cover more devices,
+ : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
+ : (Jason Gunthorpe <jgg@ualberta.ca>)
+
*/
static char *version =
@@ -71,6 +76,7 @@
/* Always include 'config.h' first in case the user wants to turn on
or override something. */
+#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
@@ -128,10 +134,26 @@
#include "cs89x0.h"
-/* First, a few definitions that the brave might change. */
-/* A zero-terminated list of I/O addresses to be probed. */
+/* First, a few definitions that the brave might change.
+ A zero-terminated list of I/O addresses to be probed. Some special flags..
+ Addr & 1 = Read back the address port, look for signature and reset
+ the page window before probing
+ Addr & 3 = Reset the page window and probe
+ The CLPS eval board has the Cirrus chip at 0x80090300, in ARM IO space,
+ but it is possible that a Cirrus board could be plugged into the ISA
+ slots. */
+/* The cs8900 has 4 IRQ pins, software selectable. cs8900_irq_map maps
+ them to system IRQ numbers. This mapping is card specific and is set to
+ the configuration of the Cirrus Eval board for this chip. */
+#ifdef CONFIG_ARCH_CLPS7500
+static unsigned int netcard_portlist[] __initdata =
+ { 0x80090303, 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
+static unsigned int cs8900_irq_map[] = {12,0,0,0};
+#else
static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
+static unsigned int cs8900_irq_map[] = {10,11,12,5};
+#endif
#if DEBUGGING
static unsigned int net_debug = DEBUGGING;
@@ -343,7 +365,7 @@
dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
if (dev->priv == 0)
{
- retval = ENOMEM;
+ retval = -ENOMEM;
goto out;
}
lp = (struct net_local *)dev->priv;
@@ -362,18 +384,20 @@
/* if they give us an odd I/O address, then do ONE write to
the address port, to get it back to address zero, where we
- expect to find the EISA signature word. */
+ expect to find the EISA signature word. An IO with a base of 0x3
+ will skip the test for the ADD_PORT. */
if (ioaddr & 1) {
- ioaddr &= ~1;
- if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
- return -ENODEV;
+ if ((ioaddr & 2) != 2)
+ if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG)
+ return -ENODEV;
+ ioaddr &= ~3;
outw(PP_ChipID, ioaddr + ADD_PORT);
}
- if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
- {
- retval = ENODEV;
- goto out1;
+ if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
+ {
+ retval = -ENODEV;
+ goto out1;
}
/* Fill in the 'dev' fields. */
@@ -403,15 +427,77 @@
dev->base_addr);
reset_chip(dev);
-
- /* First check to see if an EEPROM is attached*/
+
+ /* Here we read the current configuration of the chip. If there
+ is no Extended EEPROM then the idea is to not disturb the chip
+ configuration, it should have been correctly setup by automatic
+ EEPROM read on reset. So, if the chip says it read the EEPROM
+ the driver will always do *something* instead of complain that
+ adapter_cnf is 0. */
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
+ (EEPROM_OK|EEPROM_PRESENT)) {
+ /* Load the MAC. */
+ for (i=0; i < ETH_ALEN/2; i++) {
+ unsigned int Addr;
+ Addr = readreg(dev, PP_IA+i*2);
+ dev->dev_addr[i*2] = Addr & 0xFF;
+ dev->dev_addr[i*2+1] = Addr >> 8;
+ }
+
+ /* Load the Adapter Configuration.
+ Note: Barring any more specific information from some
+ other source (ie EEPROM+Schematics), we would not know
+ how to operate a 10Base2 interface on the AUI port.
+ However, since we do read the status of HCB1 and use
+ settings that always result in calls to control_dc_dc(dev,0)
+ a BNC interface should work if the enable pin
+ (dc/dc converter) is on HCB1. It will be called AUI
+ however. */
+
+ lp->adapter_cnf = 0;
+ i = readreg(dev, PP_LineCTL);
+ /* Preserve the setting of the HCB1 pin. */
+ if ((i & (HCB1 | HCB1_ENBL)) == (HCB1 | HCB1_ENBL))
+ lp->adapter_cnf |= A_CNF_DC_DC_POLARITY;
+ /* Save the sqelch bit */
+ if ((i & LOW_RX_SQUELCH) == LOW_RX_SQUELCH)
+ lp->adapter_cnf |= A_CNF_EXTND_10B_2 | A_CNF_LOW_RX_SQUELCH;
+ /* Check if the card is in 10Base-t only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == 0)
+ lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T;
+ /* Check if the card is in AUI only mode */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUI_ONLY)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_MEDIA_AUI;
+ /* Check if the card is in Auto mode. */
+ if ((i & (AUI_ONLY | AUTO_AUI_10BASET)) == AUTO_AUI_10BASET)
+ lp->adapter_cnf |= A_CNF_AUI | A_CNF_10B_T |
+ A_CNF_MEDIA_AUI | A_CNF_MEDIA_10B_T | A_CNF_MEDIA_AUTO;
+
+ /* IRQ. Other chips already probe, see below. */
+ if (lp->chip_type == CS8900)
+ lp->isa_config = readreg(dev, PP_CS8900_ISAINT) & INT_NO_MASK;
+
+ printk( "[Cirrus EEPROM] ");
+ }
+
+ printk("\n");
+
+ /* First check to see if an EEPROM is attached. */
if ((readreg(dev, PP_SelfST) & EEPROM_PRESENT) == 0)
- printk(KERN_WARNING "\ncs89x0: No EEPROM, relying on command line....\n");
+ printk(KERN_WARNING "cs89x0: No EEPROM, relying on command line....\n");
else if (get_eeprom_data(dev, START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
printk(KERN_WARNING "\ncs89x0: EEPROM read failed, relying on command line.\n");
} else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN,eeprom_buff) < 0) {
- printk(KERN_WARNING "\ncs89x0: EEPROM checksum bad, relying on command line\n");
+ /* Check if the chip was able to read its own configuration starting
+ at 0 in the EEPROM*/
+ if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) !=
+ (EEPROM_OK|EEPROM_PRESENT))
+ printk(KERN_WARNING "cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command line\n");
+
} else {
+ /* This reads an extended EEPROM that is not documented
+ in the CS8900 datasheet. */
+
/* get transmission control word but keep the autonegotiation bits */
if (!lp->auto_neg_cnf) lp->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
/* Store adapter configuration */
@@ -464,17 +550,12 @@
} else {
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
- /* the table that follows is dependent upon how you wired up your cs8900
- * in your system. The table is the same as the cs8900 engineering demo
- * board. irq_map also depends on the contents of the table. Also see
- * write_irq, which is the reverse mapping of the table below. */
- switch(i) {
- case 0: i = 10; break;
- case 1: i = 11; break;
- case 2: i = 12; break;
- case 3: i = 5; break;
- default: printk("\ncs89x0: bug: isa_config is %d\n", i);
- }
+ /* Translate the IRQ using the IRQ mapping table. */
+ if (i > sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
+ printk("\ncs89x0: bug: isa_config is %d\n", i);
+ else
+ i = cs8900_irq_map[i];
+
lp->irq_map = CS8900_IRQ_MAP; /* fixed IRQ map for CS8900 */
} else {
int irq_map_buff[IRQ_MAP_LEN/2];
@@ -490,7 +571,7 @@
dev->irq = i;
}
- printk(", IRQ %d", dev->irq);
+ printk(" IRQ %d", dev->irq);
#if ALLOW_DMA
if (lp->use_dma)
@@ -741,7 +822,9 @@
struct net_local *lp = (struct net_local *)dev->priv;
unsigned int selfcontrol;
int timenow = jiffies;
- /* control the DC to DC convertor in the SelfControl register. */
+ /* control the DC to DC convertor in the SelfControl register.
+ Note: This is hooked up to a general purpose pin, might not
+ always be a DC to DC convertor. */
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
if (((lp->adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
@@ -753,7 +836,6 @@
/* Wait for the DC/DC converter to power up - 500ms */
while (jiffies - timenow < HZ)
;
-
}
#define DETECTED_NONE 0
@@ -916,13 +998,13 @@
int i;
if (chip_type == CS8900) {
- switch(irq) {
- case 10: i = 0; break;
- case 11: i = 1; break;
- case 12: i = 2; break;
- case 5: i = 3; break;
- default: i = 3; break;
- }
+ /* Search the mapping table for the corrisponding IRQ pin. */
+ for (i = 0; i != sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]); i++)
+ if (cs8900_irq_map[i] == irq)
+ break;
+ /* Not found */
+ if (i == sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
+ i = 3;
writereg(dev, PP_CS8900_ISAINT, i);
} else {
writereg(dev, PP_CS8920_ISAINT, irq);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)