patch-2.1.25 linux/drivers/net/eth16i.c
Next file: linux/drivers/net/ewrk3.c
Previous file: linux/drivers/net/eql.c
Back to the patch index
Back to the overall index
- Lines: 1563
- Date:
Sun Feb 2 15:18:39 1997
- Orig file:
v2.1.24/linux/drivers/net/eth16i.c
- Orig date:
Tue Dec 31 21:41:04 1996
diff -u --recursive --new-file v2.1.24/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
@@ -275,21 +275,30 @@
#define RESET ID_ROM_0
/* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] =
- { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
+static unsigned int eth16i_portlist[] = {
+ 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
+};
-static unsigned int eth32i_portlist[] =
- { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
- 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
+static unsigned int eth32i_portlist[] = {
+ 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+ 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
+};
/* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15 };
+static unsigned int eth16i_irqmap[] = {
+ 9, 10, 5, 15
+};
/* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15 };
+static unsigned int eth32i_irqmap[] = {
+ 3, 5, 7, 9, 10, 11, 12, 15
+};
+
#define EISA_IRQ_REG 0xc89
-static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
+static unsigned int eth16i_tx_buf_map[] = {
+ 2048, 2048, 4096, 8192
+};
unsigned int boot = 1;
/* Use 0 for production, 1 for verification, >2 for debug */
@@ -299,13 +308,14 @@
static unsigned int eth16i_debug = ETH16I_DEBUG;
/* Information for each board */
-struct eth16i_local {
- struct enet_statistics stats;
- unsigned int tx_started:1;
- unsigned char tx_queue; /* Number of packets in transmit buffer */
- unsigned short tx_queue_len;
- unsigned int tx_buf_size;
- unsigned long open_time;
+struct eth16i_local
+{
+ struct net_device_stats stats;
+ unsigned int tx_started:1;
+ unsigned char tx_queue; /* Number of packets in transmit buffer */
+ unsigned short tx_queue_len;
+ unsigned int tx_buf_size;
+ unsigned long open_time;
};
/* Function prototypes */
@@ -330,7 +340,7 @@
static void eth16i_multicast(struct device *dev);
static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
static void eth16i_initialize(struct device *dev);
-static struct enet_statistics *eth16i_get_stats(struct device *dev);
+static struct net_device_stats *eth16i_get_stats(struct device *dev);
static char *cardname = "ICL EtherTeam 16i/32";
@@ -342,837 +352,845 @@
#else /* Not HAVE_DEVLIST */
int eth16i_probe(struct device *dev)
{
- int i;
- int ioaddr;
- int base_addr = dev ? dev->base_addr : 0;
-
- if(eth16i_debug > 4)
- printk("Probing started for %s\n", cardname);
-
- if(base_addr > 0x1ff) /* Check only single location */
- return eth16i_probe1(dev, base_addr);
- else if(base_addr != 0) /* Don't probe at all */
- return ENXIO;
-
- /* Seek card from the ISA io address space */
- for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) {
- if(check_region(ioaddr, ETH16I_IO_EXTENT))
- continue;
- if(eth16i_probe1(dev, ioaddr) == 0)
- return 0;
- }
-
- /* Seek card from the EISA io address space */
- for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
- if(check_region(ioaddr, ETH16I_IO_EXTENT))
+ int i;
+ int ioaddr;
+ int base_addr = dev ? dev->base_addr : 0;
+
+ if(eth16i_debug > 4)
+ printk("Probing started for %s\n", cardname);
+
+ if(base_addr > 0x1ff) /* Check only single location */
+ return eth16i_probe1(dev, base_addr);
+ else if(base_addr != 0) /* Don't probe at all */
+ return ENXIO;
+
+ /* Seek card from the ISA io address space */
+ for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) {
+ if(check_region(ioaddr, ETH16I_IO_EXTENT))
+ continue;
+ if(eth16i_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
+
+ /* Seek card from the EISA io address space */
+ for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
+ if(check_region(ioaddr, ETH16I_IO_EXTENT))
continue;
- if(eth16i_probe1(dev, ioaddr) == 0)
+ if(eth16i_probe1(dev, ioaddr) == 0)
return 0;
- }
+ }
- return ENODEV;
+ return ENODEV;
}
-#endif /* Not HAVE_DEVLIST */
+#endif /* Not HAVE_DEVLIST */
static int eth16i_probe1(struct device *dev, short ioaddr)
{
- static unsigned version_printed = 0;
- unsigned int irq = 0;
- boot = 1; /* To inform initialization that we are in boot probe */
-
- /*
- The MB86985 chip has on register which holds information in which
- io address the chip lies. First read this register and compare
- it to our current io address and if match then this could
- be our chip.
- */
-
- if(ioaddr < 0x1000) {
- if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
- return -ENODEV;
- }
-
- /* Now we will go a bit deeper and try to find the chip's signature */
-
- if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
- return -ENODEV;
-
- /*
- Now it seems that we have found an ethernet chip in this particular
- ioaddr. The MB86985 chip has this feature, that when you read a
- certain register it will increase its io base address to next
- configurable slot. Now when we have found the chip, first thing is
- to make sure that the chip's ioaddr will hold still here.
- */
-
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
-
- outb(0x00, ioaddr + RESET); /* Will reset some parts of chip */
- BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* This will disable the data link */
-
- if(dev == NULL)
- dev = init_etherdev(0, sizeof(struct eth16i_local));
-
- if( (eth16i_debug & version_printed++) == 0)
- printk(version);
-
- dev->base_addr = ioaddr;
-
- irq = eth16i_get_irq(ioaddr);
- dev->irq = irq;
-
- /* Try to obtain interrupt vector */
- if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i", NULL)) {
- printk("%s: %s at %#3x, but is unusable due
- conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
- return EAGAIN;
- }
+ static unsigned version_printed = 0;
+ unsigned int irq = 0;
+ boot = 1; /* To inform initialization that we are in boot probe */
+
+ /*
+ The MB86985 chip has on register which holds information in which
+ io address the chip lies. First read this register and compare
+ it to our current io address and if match then this could
+ be our chip.
+ */
+
+ if(ioaddr < 0x1000) {
+ if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
+ return -ENODEV;
+ }
+
+ /* Now we will go a bit deeper and try to find the chip's signature */
+
+ if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
+ return -ENODEV;
+
+ /*
+ Now it seems that we have found an ethernet chip in this particular
+ ioaddr. The MB86985 chip has this feature, that when you read a
+ certain register it will increase its io base address to next
+ configurable slot. Now when we have found the chip, first thing is
+ to make sure that the chip's ioaddr will hold still here.
+ */
+
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
+
+ outb(0x00, ioaddr + RESET); /* Will reset some parts of chip */
+ BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* This will disable the data link */
+
+ if(dev == NULL)
+ dev = init_etherdev(0, sizeof(struct eth16i_local));
+
+ if( (eth16i_debug & version_printed++) == 0)
+ printk(version);
+
+ dev->base_addr = ioaddr;
+
+ irq = eth16i_get_irq(ioaddr);
+ dev->irq = irq;
+
+ /* Try to obtain interrupt vector */
+ if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i", NULL)) {
+ printk("%s: %s at %#3x, but is unusable due
+ conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
+ return EAGAIN;
+ }
- printk("%s: %s at %#3x, IRQ %d, ",
+ printk("%s: %s at %#3x, IRQ %d, ",
dev->name, cardname, ioaddr, dev->irq);
- /* Let's grab the region */
- request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
+ /* Let's grab the region */
+ request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
- /* Now we will have to lock the chip's io address */
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+ /* Now we will have to lock the chip's io address */
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
- eth16i_initialize(dev); /* Initialize rest of the chip's registers */
+ eth16i_initialize(dev); /* Initialize rest of the chip's registers */
- /* Now let's same some energy by shutting down the chip ;) */
- BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+ /* Now let's same some energy by shutting down the chip ;) */
+ BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
- /* Initialize the device structure */
- if(dev->priv == NULL)
- dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
- memset(dev->priv, 0, sizeof(struct eth16i_local));
+ /* Initialize the device structure */
+ if(dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
+ memset(dev->priv, 0, sizeof(struct eth16i_local));
- dev->open = eth16i_open;
- dev->stop = eth16i_close;
- dev->hard_start_xmit = eth16i_tx;
- dev->get_stats = eth16i_get_stats;
- dev->set_multicast_list = ð16i_multicast;
+ dev->open = eth16i_open;
+ dev->stop = eth16i_close;
+ dev->hard_start_xmit = eth16i_tx;
+ dev->get_stats = eth16i_get_stats;
+ dev->set_multicast_list = ð16i_multicast;
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
+ /* Fill in the fields of the device structure with ethernet values. */
+ ether_setup(dev);
- boot = 0;
+ boot = 0;
- return 0;
+ return 0;
}
static void eth16i_initialize(struct device *dev)
{
- short ioaddr = dev->base_addr;
- int i, node_w = 0;
- unsigned char node_byte = 0;
-
- /* Setup station address */
- eth16i_select_regbank(NODE_ID_RB, ioaddr);
- for(i = 0 ; i < 3 ; i++) {
- unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
- ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
- }
+ short ioaddr = dev->base_addr;
+ int i, node_w = 0;
+ unsigned char node_byte = 0;
+
+ /* Setup station address */
+ eth16i_select_regbank(NODE_ID_RB, ioaddr);
+ for(i = 0 ; i < 3 ; i++) {
+ unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
+ ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
+ }
- for(i = 0; i < 6; i++) {
- outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
- if(boot) {
- printk("%02x", inb(ioaddr + NODE_ID_0 + i));
- if(i != 5)
- printk(":");
- }
- }
+ for(i = 0; i < 6; i++)
+ {
+ outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
+ if(boot)
+ {
+ printk("%02x", inb(ioaddr + NODE_ID_0 + i));
+ if(i != 5)
+ printk(":");
+ }
+ }
- /* Now we will set multicast addresses to accept none */
- eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
- for(i = 0; i < 8; i++)
- outb(0x00, ioaddr + HASH_TABLE_0 + i);
+ /* Now we will set multicast addresses to accept none */
+ eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
+ for(i = 0; i < 8; i++)
+ outb(0x00, ioaddr + HASH_TABLE_0 + i);
- /*
- Now let's disable the transmitter and receiver, set the buffer ram
- cycle time, bus width and buffer data path width. Also we shall
- set transmit buffer size and total buffer size.
- */
+ /*
+ Now let's disable the transmitter and receiver, set the buffer ram
+ cycle time, bus width and buffer data path width. Also we shall
+ set transmit buffer size and total buffer size.
+ */
- eth16i_select_regbank(2, ioaddr);
+ eth16i_select_regbank(2, ioaddr);
- node_byte = 0;
- node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
+ node_byte = 0;
+ node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
- if( (node_w & 0xFF00) == 0x0800)
- node_byte |= BUFFER_WIDTH_8;
+ if( (node_w & 0xFF00) == 0x0800)
+ node_byte |= BUFFER_WIDTH_8;
- node_byte |= MBS1;
+ node_byte |= MBS1;
- if( (node_w & 0x00FF) == 64)
- node_byte |= MBS0;
+ if( (node_w & 0x00FF) == 64)
+ node_byte |= MBS0;
- node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
+ node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
- outb(node_byte, ioaddr + CONFIG_REG_0);
+ outb(node_byte, ioaddr + CONFIG_REG_0);
- /* We shall halt the transmitting, if 16 collisions are detected */
- outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
+ /* We shall halt the transmitting, if 16 collisions are detected */
+ outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
- if(boot) /* Now set port type */
- {
- char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
+ if(boot) /* Now set port type */
+ {
+ char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
- ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
- dev->if_port = (ptype & 0x00FF);
+ ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+ dev->if_port = (ptype & 0x00FF);
- printk(" %s interface.\n", porttype[dev->if_port]);
+ printk(" %s interface.\n", porttype[dev->if_port]);
- if(ptype == E_PORT_AUTO)
- ptype = eth16i_probe_port(ioaddr);
+ if(ptype == E_PORT_AUTO)
+ ptype = eth16i_probe_port(ioaddr);
- eth16i_set_port(ioaddr, ptype);
- }
+ eth16i_set_port(ioaddr, ptype);
+ }
- /* Set Receive Mode to normal operation */
- outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
+ /* Set Receive Mode to normal operation */
+ outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
}
static int eth16i_probe_port(short ioaddr)
{
- int i;
- int retcode;
- unsigned char dummy_packet[64] = { 0 };
-
- /* Powerup the chip */
- outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-
- eth16i_select_regbank(NODE_ID_RB, ioaddr);
-
- for(i = 0; i < 6; i++) {
- dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
- dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
- }
-
- dummy_packet[12] = 0x00;
- dummy_packet[13] = 0x04;
-
- eth16i_select_regbank(2, ioaddr);
-
- for(i = 0; i < 3; i++) {
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
- eth16i_set_port(ioaddr, i);
-
- if(eth16i_debug > 1)
- printk("Set port number %d\n", i);
-
- retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
- if(retcode == 0) {
- retcode = eth16i_receive_probe_packet(ioaddr);
- if(retcode != -1) {
- if(eth16i_debug > 1)
- printk("Eth16i interface port found at %d\n", i);
- return i;
- }
- }
- else {
- if(eth16i_debug > 1)
- printk("TRANSMIT_DONE timeout\n");
- }
- }
+ int i;
+ int retcode;
+ unsigned char dummy_packet[64] = { 0 };
- if( eth16i_debug > 1)
- printk("Using default port\n");
+ /* Powerup the chip */
+ outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
- return E_PORT_BNC;
-}
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-static void eth16i_set_port(short ioaddr, int porttype)
-{
- unsigned short temp = 0;
+ eth16i_select_regbank(NODE_ID_RB, ioaddr);
+
+ for(i = 0; i < 6; i++) {
+ dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
+ dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
+ }
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
+ dummy_packet[12] = 0x00;
+ dummy_packet[13] = 0x04;
- temp |= DIS_AUTO_PORT_SEL;
+ eth16i_select_regbank(2, ioaddr);
- switch(porttype) {
+ for(i = 0; i < 3; i++) {
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+ eth16i_set_port(ioaddr, i);
+
+ if(eth16i_debug > 1)
+ printk("Set port number %d\n", i);
+
+ retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
+ if(retcode == 0)
+ {
+ retcode = eth16i_receive_probe_packet(ioaddr);
+ if(retcode != -1)
+ {
+ if(eth16i_debug > 1)
+ printk("Eth16i interface port found at %d\n", i);
+ return i;
+ }
+ }
+ else {
+ if(eth16i_debug > 1)
+ printk("TRANSMIT_DONE timeout\n");
+ }
+ }
- case E_PORT_BNC :
- temp |= AUI_SELECT;
- break;
+ if( eth16i_debug > 1)
+ printk("Using default port\n");
- case E_PORT_TP :
- break;
+ return E_PORT_BNC;
+}
- case E_PORT_DIX :
- temp |= AUI_SELECT;
- BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
- break;
- }
- outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
+static void eth16i_set_port(short ioaddr, int porttype)
+{
+ unsigned short temp = 0;
+
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
+
+ temp |= DIS_AUTO_PORT_SEL;
+ switch(porttype)
+ {
+
+ case E_PORT_BNC :
+ temp |= AUI_SELECT;
+ break;
+
+ case E_PORT_TP :
+ break;
+
+ case E_PORT_DIX :
+ temp |= AUI_SELECT;
+ BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+ break;
+ }
+ outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
- if(eth16i_debug > 1) {
- printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
- printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
- }
+ if(eth16i_debug > 1) {
+ printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+ printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
+ }
}
static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l)
{
- int starttime;
-
- outb(0xff, ioaddr + TX_STATUS_REG);
+ int starttime;
- outw(l, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
+ outb(0xff, ioaddr + TX_STATUS_REG);
- starttime = jiffies;
- outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
+ outw(l, ioaddr + DATAPORT);
+ outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
- while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
- break;
- }
- }
+ starttime = jiffies;
+ outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
- return(0);
+ while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0)
+ if( (jiffies - starttime) > TIMEOUT_TICKS)
+ break;
+ return(0);
}
static int eth16i_receive_probe_packet(short ioaddr)
{
- int starttime;
+ int starttime;
- starttime = jiffies;
+ starttime = jiffies;
- while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
+ while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0)
+ {
+ if( (jiffies - starttime) > TIMEOUT_TICKS)
+ {
+ if(eth16i_debug > 1)
+ printk("Timeout occurred waiting transmit packet received\n");
+ starttime = jiffies;
+ while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0)
+ {
+ if( (jiffies - starttime) > TIMEOUT_TICKS)
+ {
+ if(eth16i_debug > 1)
+ printk("Timeout occurred waiting receive packet\n");
+ return -1;
+ }
+ }
+
+ if(eth16i_debug > 1)
+ printk("RECEIVE_PACKET\n");
+ return(0); /* Found receive packet */
+ }
+ }
- if(eth16i_debug > 1)
- printk("Timeout occurred waiting transmit packet received\n");
- starttime = jiffies;
- while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
- if(eth16i_debug > 1)
- printk("Timeout occurred waiting receive packet\n");
- return -1;
- }
- }
-
- if(eth16i_debug > 1)
- printk("RECEIVE_PACKET\n");
- return(0); /* Found receive packet */
- }
- }
-
- if(eth16i_debug > 1) {
- printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
- printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
- }
+ if(eth16i_debug > 1) {
+ printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+ printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+ }
- return(0); /* Return success */
+ return(0); /* Return success */
}
static int eth16i_get_irq(short ioaddr)
{
- unsigned char cbyte;
+ unsigned char cbyte;
- if( ioaddr < 0x1000) {
- cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+ if( ioaddr < 0x1000) {
+ cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
- } else { /* Oh..the card is EISA so method getting IRQ different */
+ } else { /* Oh..the card is EISA so method getting IRQ different */
unsigned short index = 0;
cbyte = inb(ioaddr + EISA_IRQ_REG);
while( (cbyte & 0x01) == 0) {
cbyte = cbyte >> 1;
index++;
- }
+ }
return( eth32i_irqmap[ index ] );
- }
+ }
}
static int eth16i_check_signature(short ioaddr)
{
- int i;
- unsigned char creg[4] = { 0 };
+ int i;
+ unsigned char creg[4] = { 0 };
- for(i = 0; i < 4 ; i++) {
+ for(i = 0; i < 4 ; i++) {
- creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
+ creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
- if(eth16i_debug > 1)
+ if(eth16i_debug > 1)
printk("eth16i: read signature byte %x at %x\n", creg[i],
- ioaddr + TRANSMIT_MODE_REG + i);
- }
+ ioaddr + TRANSMIT_MODE_REG + i);
+ }
- creg[0] &= 0x0F; /* Mask collision cnr */
- creg[2] &= 0x7F; /* Mask DCLEN bit */
+ creg[0] &= 0x0F; /* Mask collision cnr */
+ creg[2] &= 0x7F; /* Mask DCLEN bit */
#ifdef 0
/*
This was removed because the card was sometimes left to state
from which it couldn't be find anymore. If there is need
- to more strict chech still this have to be fixed.
+ to have a more strict check still this have to be fixed.
*/
- if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) {
- if(creg[1] != 0x42)
- return -1;
- }
+ if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+ if(creg[1] != 0x42)
+ return -1;
+ }
#endif
- if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
- creg[2] &= 0x42;
- creg[3] &= 0x03;
-
- if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
- return -1;
- }
-
- if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
- return -1;
- if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
- return -1;
+ if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) )
+ {
+ creg[2] &= 0x42;
+ creg[3] &= 0x03;
+
+ if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+ return -1;
+ }
+
+ if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
+ return -1;
+ if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
+ return -1;
- return 0;
+ return 0;
}
static int eth16i_read_eeprom(int ioaddr, int offset)
{
- int data = 0;
+ int data = 0;
- eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
- outb(CS_1, ioaddr + EEPROM_CTRL_REG);
- data = eth16i_read_eeprom_word(ioaddr);
- outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
+ outb(CS_1, ioaddr + EEPROM_CTRL_REG);
+ data = eth16i_read_eeprom_word(ioaddr);
+ outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
- return(data);
+ return(data);
}
static int eth16i_read_eeprom_word(int ioaddr)
{
- int i;
- int data = 0;
+ int i;
+ int data = 0;
- for(i = 16; i > 0; i--) {
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
- eeprom_slow_io();
- }
+ for(i = 16; i > 0; i--) {
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+ eeprom_slow_io();
+ }
- return(data);
+ return(data);
}
static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
{
- int i;
+ int i;
- outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
- outb(DI_0, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- outb(DI_1, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-
- for(i = 7; i >= 0; i--) {
- short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
- outb(cmd, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- }
+ outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ outb(DI_0, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ outb(DI_1, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+
+ for(i = 7; i >= 0; i--) {
+ short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
+ outb(cmd, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ }
}
static int eth16i_open(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
- irq2dev_map[dev->irq] = dev;
+ irq2dev_map[dev->irq] = dev;
- /* Powerup the chip */
- outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+ /* Powerup the chip */
+ outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
- /* Initialize the chip */
- eth16i_initialize(dev);
+ /* Initialize the chip */
+ eth16i_initialize(dev);
- /* Set the transmit buffer size */
- lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
+ /* Set the transmit buffer size */
+ lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
- if(eth16i_debug > 3)
- printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
+ if(eth16i_debug > 3)
+ printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
- /* Now enable Transmitter and Receiver sections */
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+ /* Now enable Transmitter and Receiver sections */
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
- /* Now switch to register bank 2, for run time operation */
- eth16i_select_regbank(2, ioaddr);
+ /* Now switch to register bank 2, for run time operation */
+ eth16i_select_regbank(2, ioaddr);
- lp->open_time = jiffies;
- lp->tx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
+ lp->open_time = jiffies;
+ lp->tx_started = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
- /* Turn on interrupts*/
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ /* Turn on interrupts*/
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
#ifdef MODULE
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
#endif
- return 0;
+ return 0;
}
static int eth16i_close(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
- lp->open_time = 0;
+ lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
+ dev->tbusy = 1;
+ dev->start = 0;
- /* Disable transmit and receive */
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ /* Disable transmit and receive */
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- /* Reset the chip */
- outb(0xff, ioaddr + RESET);
+ /* Reset the chip */
+ outb(0xff, ioaddr + RESET);
- /* Save some energy by switching off power */
- BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+ /* Save some energy by switching off power */
+ BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
#ifdef MODULE
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
#endif
- return 0;
+ return 0;
}
static int eth16i_tx(struct sk_buff *skb, struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
- if(dev->tbusy) {
- /*
- If we get here, some higher level has decided that we are broken.
- There should really be a "kick me" function call instead.
- */
-
- int tickssofar = jiffies - dev->trans_start;
- if(tickssofar < TIMEOUT_TICKS) /* Let's not rush with our timeout, */
- return 1; /* wait a couple of ticks first */
-
- printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
- inw(ioaddr + TX_STATUS_REG),
- (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
- "IRQ conflict" : "network cable problem");
-
- /* Let's dump all registers */
- if(eth16i_debug > 0) {
- printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
- dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
- inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
- inb(ioaddr + 6), inb(ioaddr + 7));
-
-
- printk("lp->tx_queue = %d\n", lp->tx_queue);
- printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
- printk("lp->tx_started = %d\n", lp->tx_started);
-
- }
-
- lp->stats.tx_errors++;
-
- /* Now let's try to restart the adaptor */
-
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- outw(0xffff, ioaddr + RESET);
- eth16i_initialize(dev);
- outw(0xffff, ioaddr + TX_STATUS_REG);
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-
- lp->tx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
-
- /*
- If some higher layer thinks we've missed an tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself
- */
- if(skb == NULL) {
- dev_tint(dev);
- return 0;
- }
-
- /* Block a timer based transmitter from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-
- /* Turn off TX interrupts */
- outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
- if(set_bit(0, (void *)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
- outw(length, ioaddr + DATAPORT);
-
- if( ioaddr < 0x1000 )
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
- else {
- unsigned char frag = length % 4;
-
- outsl(ioaddr + DATAPORT, buf, length >> 2);
-
- if( frag != 0 ) {
- outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
- if( frag == 3 )
- outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
- }
- }
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
-
- if(lp->tx_started == 0) {
- /* If the transmitter is idle..always trigger a transmit */
- outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- dev->tbusy = 0;
- }
- else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
- /* There is still more room for one more packet in tx buffer */
- dev->tbusy = 0;
- }
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
- /* Turn TX interrupts back on */
- /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
- }
- dev_kfree_skb(skb, FREE_WRITE);
+ if(dev->tbusy) {
+ /*
+ If we get here, some higher level has decided that we are broken.
+ There should really be a "kick me" function call instead.
+ */
- return 0;
-}
+ int tickssofar = jiffies - dev->trans_start;
+ if(tickssofar < TIMEOUT_TICKS) /* Let's not rush with our timeout, */
+ return 1; /* wait a couple of ticks first */
-static void eth16i_rx(struct device *dev)
-{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
- int boguscount = MAX_RX_LOOP;
-
- /* Loop until all packets have been read */
- while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
-
- /* Read status byte from receive buffer */
- ushort status = inw(ioaddr + DATAPORT);
-
- if(eth16i_debug > 4)
- printk("%s: Receiving packet mode %02x status %04x.\n",
- dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
-
- if( !(status & PKT_GOOD) ) {
- /* Hmm..something went wrong. Let's check what error occurred */
- lp->stats.rx_errors++;
- if( status & PKT_SHORT ) lp->stats.rx_length_errors++;
- if( status & PKT_ALIGN_ERR ) lp->stats.rx_frame_errors++;
- if( status & PKT_CRC_ERR ) lp->stats.rx_crc_errors++;
- if( status & PKT_RX_BUF_OVERFLOW) lp->stats.rx_over_errors++;
- }
- else { /* Ok so now we should have a good packet */
- struct sk_buff *skb;
-
- /* Get the size of the packet from receive buffer */
- ushort pkt_len = inw(ioaddr + DATAPORT);
-
- if(pkt_len > ETH_FRAME_LEN) {
- printk("%s: %s claimed a very large packet, size of %d bytes.\n",
- dev->name, cardname, pkt_len);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- lp->stats.rx_dropped++;
- break;
- }
-
- skb = dev_alloc_skb(pkt_len + 3);
- if( skb == NULL ) {
- printk("%s: Couldn't allocate memory for packet (len %d)\n",
- dev->name, pkt_len);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- lp->stats.rx_dropped++;
- break;
+ printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
+ inw(ioaddr + TX_STATUS_REG),
+ (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
+ "IRQ conflict" : "network cable problem");
+
+ /* Let's dump all registers */
+ if(eth16i_debug > 0) {
+ printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+ dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
+ inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
+ inb(ioaddr + 6), inb(ioaddr + 7));
+
+
+ printk("lp->tx_queue = %d\n", lp->tx_queue);
+ printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
+ printk("lp->tx_started = %d\n", lp->tx_started);
+
+ }
+
+ lp->stats.tx_errors++;
+
+ /* Now let's try to restart the adaptor */
+
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ outw(0xffff, ioaddr + RESET);
+ eth16i_initialize(dev);
+ outw(0xffff, ioaddr + TX_STATUS_REG);
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+
+ lp->tx_started = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+ dev->tbusy = 0;
+ dev->trans_start = jiffies;
}
- skb->dev = dev;
- skb_reserve(skb,2);
- /*
- Now let's get the packet out of buffer.
- size is (pkt_len + 1) >> 1, cause we are now reading words
- and it have to be even aligned.
- */
+ /* Block a timer based transmitter from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if( ioaddr < 0x1000)
- insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
+ /* Turn off TX interrupts */
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+ if(set_bit(0, (void *)&dev->tbusy) != 0)
+ printk("%s: Transmitter access conflict.\n", dev->name);
else {
- unsigned char *buf = skb_put(skb, pkt_len);
- unsigned char frag = pkt_len % 4;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+
+ outw(length, ioaddr + DATAPORT);
- insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+ if( ioaddr < 0x1000 )
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+ else
+ {
+ unsigned char frag = length % 4;
+
+ outsl(ioaddr + DATAPORT, buf, length >> 2);
+
+ if( frag != 0 )
+ {
+ outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+ if( frag == 3 )
+ outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
+ }
+ }
+
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+
+ if(lp->tx_started == 0) {
+ /* If the transmitter is idle..always trigger a transmit */
+ outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ lp->tx_started = 1;
+ dev->tbusy = 0;
+ }
+ else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+ /* There is still more room for one more packet in tx buffer */
+ dev->tbusy = 0;
+ }
- if(frag != 0) {
- unsigned short rest[2];
- rest[0] = inw( ioaddr + DATAPORT );
- if(frag == 3)
- rest[1] = inw( ioaddr + DATAPORT );
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
- memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
- }
+ /* Turn TX interrupts back on */
+ /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
}
+ dev_kfree_skb(skb, FREE_WRITE);
- skb->protocol=eth_type_trans(skb, dev);
- netif_rx(skb);
- lp->stats.rx_packets++;
+ return 0;
+}
- if( eth16i_debug > 5 ) {
- int i;
- printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
- for(i = 0; i < 14; i++)
- printk(" %02x", skb->data[i]);
- printk(".\n");
- }
+static void eth16i_rx(struct device *dev)
+{
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int boguscount = MAX_RX_LOOP;
+
+ /* Loop until all packets have been read */
+ while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0)
+ {
+ /* Read status byte from receive buffer */
+ ushort status = inw(ioaddr + DATAPORT);
+
+ if(eth16i_debug > 4)
+ printk("%s: Receiving packet mode %02x status %04x.\n",
+ dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
+
+ if( !(status & PKT_GOOD) )
+ {
+ /* Hmm..something went wrong. Let's check what error occurred */
+ lp->stats.rx_errors++;
+ if( status & PKT_SHORT)
+ lp->stats.rx_length_errors++;
+ if( status & PKT_ALIGN_ERR )
+ lp->stats.rx_frame_errors++;
+ if( status & PKT_CRC_ERR )
+ lp->stats.rx_crc_errors++;
+ if( status & PKT_RX_BUF_OVERFLOW)
+ lp->stats.rx_over_errors++;
+ }
+ else
+ { /* Ok so now we should have a good packet */
+ struct sk_buff *skb;
+ /* Get the size of the packet from receive buffer */
+ ushort pkt_len = inw(ioaddr + DATAPORT);
+
+ if(pkt_len > ETH_FRAME_LEN)
+ {
+ printk("%s: %s claimed a very large packet, size of %d bytes.\n",
+ dev->name, cardname, pkt_len);
+ outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+ lp->stats.rx_dropped++;
+ break;
+ }
+
+ skb = dev_alloc_skb(pkt_len + 3);
+ if( skb == NULL )
+ {
+ printk("%s: Couldn't allocate memory for packet (len %d)\n",
+ dev->name, pkt_len);
+ outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+ lp->stats.rx_dropped++;
+ break;
+ }
+ skb->dev = dev;
+ skb_reserve(skb,2);
+ /*
+ Now let's get the packet out of buffer.
+ size is (pkt_len + 1) >> 1, cause we are now reading words
+ and it has to be even aligned.
+ */
+
+ if( ioaddr < 0x1000)
+ insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
+ else
+ {
+ unsigned char *buf = skb_put(skb, pkt_len);
+ unsigned char frag = pkt_len % 4;
+
+ insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+
+ if(frag != 0)
+ {
+ unsigned short rest[2];
+ rest[0] = inw( ioaddr + DATAPORT );
+ if(frag == 3)
+ rest[1] = inw( ioaddr + DATAPORT );
+
+ memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
+ }
+ }
+
+ skb->protocol=eth_type_trans(skb, dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+
+ if( eth16i_debug > 5 )
+ {
+ int i;
+ printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
+ for(i = 0; i < 14; i++)
+ printk(" %02x", skb->data[i]);
+ printk(".\n");
+ }
- } /* else */
+ } /* else */
- if(--boguscount <= 0)
- break;
+ if(--boguscount <= 0)
+ break;
- } /* while */
+ } /* while */
#if 0
- {
- int i;
+ {
+ int i;
+
+ for(i = 0; i < 20; i++)
+ {
+ if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
+ break;
+ inw(ioaddr + DATAPORT);
+ outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+ }
- for(i = 0; i < 20; i++) {
- if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
- break;
- inw(ioaddr + DATAPORT);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- }
-
- if(eth16i_debug > 1)
- printk("%s: Flushed receive buffer.\n", dev->name);
- }
+ if(eth16i_debug > 1)
+ printk("%s: Flushed receive buffer.\n", dev->name);
+ }
#endif
- return;
+ return;
}
static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct device *dev = (struct device *)(irq2dev_map[irq]);
- struct eth16i_local *lp;
- int ioaddr = 0,
- status;
-
- if(dev == NULL) {
- printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
- return;
- }
-
- /* Turn off all interrupts from adapter */
- outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
- dev->interrupt = 1;
-
- ioaddr = dev->base_addr;
- lp = (struct eth16i_local *)dev->priv;
- status = inw(ioaddr + TX_STATUS_REG); /* Get the status */
- outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */
-
- if(eth16i_debug > 3)
- printk("%s: Interrupt with status %04x.\n", dev->name, status);
-
- if( status & 0x00ff ) { /* Let's check the transmit status reg */
-
- if(status & TX_DONE) { /* The transmit has been done */
- lp->stats.tx_packets++;
-
- if(lp->tx_queue) { /* Is there still packets ? */
- /* There was packet(s) so start transmitting and write also
- how many packets there is to be sent */
- outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
- else {
- lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
- }
- }
-
- if( ( status & 0xff00 ) ||
- ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
- eth16i_rx(dev); /* We have packet in receive buffer */
- }
+ struct device *dev = (struct device *)(irq2dev_map[irq]);
+ struct eth16i_local *lp;
+ int ioaddr = 0,
+ status;
+
+ if(dev == NULL) {
+ printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
+ return;
+ }
+
+ /* Turn off all interrupts from adapter */
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+ dev->interrupt = 1;
- dev->interrupt = 0;
+ ioaddr = dev->base_addr;
+ lp = (struct eth16i_local *)dev->priv;
+ status = inw(ioaddr + TX_STATUS_REG); /* Get the status */
+ outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */
+
+ if(eth16i_debug > 3)
+ printk("%s: Interrupt with status %04x.\n", dev->name, status);
+
+ if( status & 0x00ff ) { /* Let's check the transmit status reg */
+ if(status & TX_DONE)
+ { /* The transmit has been done */
+ lp->stats.tx_packets++;
+ if(lp->tx_queue)
+ { /* Are there still packets ? */
+ /* There was packet(s) so start transmitting and write also
+ how many packets there is to be sent */
+ outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ else
+ {
+ lp->tx_started = 0;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+ }
+ }
+
+ if( ( status & 0xff00 ) ||
+ ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+ eth16i_rx(dev); /* We have packet in receive buffer */
+ }
- /* Turn interrupts back on */
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ dev->interrupt = 0;
- return;
+ /* Turn interrupts back on */
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+ return;
}
static void eth16i_multicast(struct device *dev)
{
- short ioaddr = dev->base_addr;
+ short ioaddr = dev->base_addr;
- if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
- {
- dev->flags|=IFF_PROMISC; /* Must do this */
- outb(3, ioaddr + RECEIVE_MODE_REG);
- } else {
- outb(2, ioaddr + RECEIVE_MODE_REG);
- }
+ if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+ {
+ dev->flags|=IFF_PROMISC; /* Must do this */
+ outb(3, ioaddr + RECEIVE_MODE_REG);
+ } else {
+ outb(2, ioaddr + RECEIVE_MODE_REG);
+ }
}
-static struct enet_statistics *eth16i_get_stats(struct device *dev)
+static struct net_device_stats *eth16i_get_stats(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- return &lp->stats;
+ return &lp->stats;
}
static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
{
- unsigned char data;
+ unsigned char data;
- data = inb(ioaddr + CONFIG_REG_1);
- outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
+ data = inb(ioaddr + CONFIG_REG_1);
+ outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
}
#ifdef MODULE
@@ -1181,7 +1199,8 @@
devicename,
0, 0, 0, 0,
0, 0,
- 0, 0, 0, NULL, eth16i_probe };
+ 0, 0, 0, NULL, eth16i_probe
+};
int io = 0x2a0;
int irq = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov