diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /drivers/net/smc9194.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'drivers/net/smc9194.c')
-rw-r--r-- | drivers/net/smc9194.c | 808 |
1 files changed, 402 insertions, 406 deletions
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index dac1b9831..5b3e9b73c 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -1,24 +1,24 @@ /*------------------------------------------------------------------------ . smc9194.c - . This is a driver for SMC's 9000 series of Ethernet cards. + . This is a driver for SMC's 9000 series of Ethernet cards. . . Copyright (C) 1996 by Erik Stahlman . This software may be used and distributed according to the terms . of the GNU Public License, incorporated herein by reference. . - . "Features" of the SMC chip: - . 4608 byte packet memory. ( for the 91C92. Others have more ) + . "Features" of the SMC chip: + . 4608 byte packet memory. ( for the 91C92. Others have more ) . EEPROM for configuration . AUI/TP selection ( mine has 10Base2/10BaseT select ) . . Arguments: . io = for the base address - . irq = for the IRQ - . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 ) + . irq = for the IRQ + . ifport = 0 for autodetect, 1 for TP, 2 for AUI ( or 10base2 ) . - . author: + . author: . Erik Stahlman ( erik@vt.edu ) - . + . . Hardware multicast code from Peter Cammaert ( pc@denkart.be ) . . Sources: @@ -27,33 +27,33 @@ . o ( a LOT of advice from Becker as well ) . . History: - . 12/07/95 Erik Stahlman written, got receive/xmit handled + . 12/07/95 Erik Stahlman written, got receive/xmit handled . 01/03/96 Erik Stahlman worked out some bugs, actually usable!!! :-) - . 01/06/96 Erik Stahlman cleaned up some, better testing, etc + . 01/06/96 Erik Stahlman cleaned up some, better testing, etc . 01/29/96 Erik Stahlman fixed autoirq, added multicast . 02/01/96 Erik Stahlman 1. disabled all interrupts in smc_reset - . 2. got rid of post-decrementing bug -- UGH. + . 2. got rid of post-decrementing bug -- UGH. . 02/13/96 Erik Stahlman Tried to fix autoirq failure. Added more . descriptive error messages. . 02/15/96 Erik Stahlman Fixed typo that caused detection failure - . 02/23/96 Erik Stahlman Modified it to fit into kernel tree + . 02/23/96 Erik Stahlman Modified it to fit into kernel tree . Added support to change hardware address . Cleared stats on opens . 02/26/96 Erik Stahlman Trial support for Kernel 1.2.13 . Kludge for automatic IRQ detection - . 03/04/96 Erik Stahlman Fixed kernel 1.3.70 + - . Fixed bug reported by Gardner Buchanan in + . 03/04/96 Erik Stahlman Fixed kernel 1.3.70 + + . Fixed bug reported by Gardner Buchanan in . smc_enable, with outw instead of outb . 03/06/96 Erik Stahlman Added hardware multicast from Peter Cammaert ----------------------------------------------------------------------------*/ static const char *version = - "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; + "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; #ifdef MODULE #include <linux/module.h> #include <linux/version.h> -#endif +#endif #include <linux/kernel.h> #include <linux/sched.h> @@ -66,6 +66,7 @@ static const char *version = #include <linux/malloc.h> #include <linux/string.h> #include <linux/ioport.h> +#include <linux/init.h> #include <asm/bitops.h> #include <asm/io.h> #include <linux/errno.h> @@ -76,52 +77,52 @@ static const char *version = #include "smc9194.h" /*------------------------------------------------------------------------ - . - . Configuration options, for the experienced user to change. + . + . Configuration options, for the experienced user to change. . -------------------------------------------------------------------------*/ -/* - . this is for kernels > 1.2.70 +/* + . this is for kernels > 1.2.70 */ -#define REALLY_NEW_KERNEL +#define REALLY_NEW_KERNEL #ifndef REALLY_NEW_KERNEL #define free_irq( x, y ) free_irq( x ) #define request_irq( x, y, z, u, v ) request_irq( x, y, z, u ) #endif /* - . Do you want to use this with old kernels. - . WARNING: this is not well tested. + . Do you want to use this with old kernels. + . WARNING: this is not well tested. #define SUPPORT_OLD_KERNEL */ /* . Do you want to use 32 bit xfers? This should work on all chips, as - . the chipset is designed to accommodate them. + . the chipset is designed to accommodate them. */ #define USE_32_BIT 1 -/* +/* .the SMC9194 can be at any of the following port addresses. To change, - .for a slightly different card, you can add it to the array. Keep in + .for a slightly different card, you can add it to the array. Keep in .mind that the array must end in zero. */ -static unsigned int smc_portlist[] = +static unsigned int smc_portlist[] __initdata = { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0}; -/* - . Wait time for memory to be free. This probably shouldn't be - . tuned that much, as waiting for this means nothing else happens - . in the system +/* + . Wait time for memory to be free. This probably shouldn't be + . tuned that much, as waiting for this means nothing else happens + . in the system */ #define MEMORY_WAIT_TIME 16 /* . DEBUGGING LEVELS - . + . . 0 for normal operation . 1 for slightly more details . >2 for various levels of increasingly useless information @@ -131,13 +132,13 @@ static unsigned int smc_portlist[] = #define SMC_DEBUG 0 #if (SMC_DEBUG > 2 ) -#define PRINTK3(x) printk x -#else -#define PRINTK3(x) +#define PRINTK3(x) printk x +#else +#define PRINTK3(x) #endif -#if SMC_DEBUG > 1 -#define PRINTK2(x) printk x +#if SMC_DEBUG > 1 +#define PRINTK2(x) printk x #else #define PRINTK2(x) #endif @@ -146,7 +147,7 @@ static unsigned int smc_portlist[] = #define PRINTK(x) printk x #else #define PRINTK(x) -#endif +#endif /* the older versions of the kernel cannot support autoprobing */ @@ -157,30 +158,30 @@ static unsigned int smc_portlist[] = /*------------------------------------------------------------------------ . - . The internal workings of the driver. If you are changing anything - . here with the SMC stuff, you should have the datasheet and known - . what you are doing. - . + . The internal workings of the driver. If you are changing anything + . here with the SMC stuff, you should have the datasheet and known + . what you are doing. + . -------------------------------------------------------------------------*/ #define CARDNAME "SMC9194" #ifdef SUPPORT_OLD_KERNEL char kernel_version[] = UTS_RELEASE; -#endif +#endif -/* store this information for the driver.. */ +/* store this information for the driver.. */ struct smc_local { /* these are things that the kernel wants me to keep, so users can find out semi-useless statistics of how well the card is - performing + performing */ - struct enet_statistics stats; - - /* + struct net_device_stats stats; + + /* If I have to wait until memory is available to send a packet, I will store the skbuff here, until I get the - desired memory. Then, I'll send it out and free it. + desired memory. Then, I'll send it out and free it. */ struct sk_buff * saved_skb; @@ -196,14 +197,14 @@ struct smc_local { /*----------------------------------------------------------------- . . The driver can be entered at any of the following entry points. - . + . .------------------------------------------------------------------ */ /* - . This is called by register_netdev(). It is responsible for - . checking the portlist for the SMC9000 series chipset. If it finds + . This is called by register_netdev(). It is responsible for + . checking the portlist for the SMC9000 series chipset. If it finds . one, then it will initialize the device, find the hardware information, - . and sets up the appropriate device parameters. + . and sets up the appropriate device parameters. . NOTE: Interrupts are *OFF* when this procedure is called. . . NB:This shouldn't be static since it is referred to externally. @@ -212,32 +213,32 @@ int smc_init(struct device *dev); /* . The kernel calls this function when someone wants to use the device, - . typically 'ifconfig ethX up'. + . typically 'ifconfig ethX up'. */ static int smc_open(struct device *dev); /* . This is called by the kernel to send a packet out into the net. it's . responsible for doing a best-effort send, but if it's simply not possible - . to send it, the packet gets dropped. -*/ + . to send it, the packet gets dropped. +*/ static int smc_send_packet(struct sk_buff *skb, struct device *dev); -/* +/* . This is called by the kernel in response to 'ifconfig ethX down'. It - . is responsible for cleaning up everything that the open routine - . does, and maybe putting the card into a powerdown state. + . is responsible for cleaning up everything that the open routine + . does, and maybe putting the card into a powerdown state. */ static int smc_close(struct device *dev); /* - . This routine allows the proc file system to query the driver's - . statistics. + . This routine allows the proc file system to query the driver's + . statistics. */ -static struct enet_statistics * smc_query_statistics( struct device *dev); +static struct net_device_stats * smc_query_statistics( struct device *dev); /* - . Finally, a call to set promiscuous mode ( for TCPDUMP and related + . Finally, a call to set promiscuous mode ( for TCPDUMP and related . programs ) and multicast modes. */ #ifdef SUPPORT_OLD_KERNEL @@ -245,43 +246,43 @@ static void smc_set_multicast_list(struct device *dev, int num_addrs, void *addrs); #else static void smc_set_multicast_list(struct device *dev); -#endif +#endif /*--------------------------------------------------------------- - . - . Interrupt level calls.. + . + . Interrupt level calls.. . ----------------------------------------------------------------*/ /* - . Handles the actual interrupt + . Handles the actual interrupt */ #ifdef REALLY_NEW_KERNEL static void smc_interrupt(int irq, void *, struct pt_regs *regs); #else static void smc_interrupt(int irq, struct pt_regs *regs); -#endif +#endif /* . This is a separate procedure to handle the receipt of a packet, to - . leave the interrupt code looking slightly cleaner -*/ + . leave the interrupt code looking slightly cleaner +*/ inline static void smc_rcv( struct device *dev ); /* . This handles a TX interrupt, which is only called when an error - . relating to a packet is sent. + . relating to a packet is sent. */ inline static void smc_tx( struct device * dev ); /* ------------------------------------------------------------ - . + . . Internal routines . ------------------------------------------------------------ */ /* - . Test if a given location contains a chip, trying to cause as + . Test if a given location contains a chip, trying to cause as . little damage as possible if it's not a SMC chip. */ static int smc_probe( int ioaddr ); @@ -289,26 +290,26 @@ static int smc_probe( int ioaddr ); /* . this routine initializes the cards hardware, prints out the configuration . to the system log as well as the vanity message, and handles the setup - . of a device parameter. + . of a device parameter. . It will give an error if it can't initialize the card. */ -static int smc_initcard( struct device *, int ioaddr ); +static int smc_initcard( struct device *, int ioaddr ); /* . A rather simple routine to print out a packet for debugging purposes. -*/ -#if SMC_DEBUG > 2 +*/ +#if SMC_DEBUG > 2 static void print_packet( byte *, int ); -#endif +#endif #define tx_done(dev) 1 -/* this is called to actually send the packet to the chip */ +/* this is called to actually send the packet to the chip */ static void smc_hardware_send_packet( struct device * dev ); /* Since I am not sure if I will have enough room in the chip's ram - . to store the packet, I call this routine, which either sends it - . now, or generates an interrupt when the card is ready for the + . to store the packet, I call this routine, which either sends it + . now, or generates an interrupt when the card is ready for the . packet */ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device *dev ); @@ -328,7 +329,7 @@ static int smc_findirq( int ioaddr ); #endif /* - this routine will set the hardware multicast table to the specified + this routine will set the hardware multicast table to the specified values given it by the higher level routines */ #ifndef SUPPORT_OLD_KERNEL @@ -339,66 +340,66 @@ static int crc32( char *, int ); #ifdef SUPPORT_OLD_KERNEL extern struct device *init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp ); -#endif +#endif /* . Function: smc_reset( int ioaddr ) . Purpose: . This sets the SMC91xx chip to its normal state, hopefully from whatever - . mess that any other DOS driver has put it in. - . + . mess that any other DOS driver has put it in. + . . Maybe I should reset more registers to defaults in here? SOFTRESET should - . do that for me. - . + . do that for me. + . . Method: - . 1. send a SOFT RESET + . 1. send a SOFT RESET . 2. wait for it to finish . 3. enable autorelease mode . 4. reset the memory management unit . 5. clear all interrupts . -*/ -static void smc_reset( int ioaddr ) -{ +*/ +static void smc_reset( int ioaddr ) +{ /* This resets the registers mostly to defaults, but doesn't affect EEPROM. That seems unnecessary */ SMC_SELECT_BANK( 0 ); - outw( RCR_SOFTRESET, ioaddr + RCR ); - + outw( RCR_SOFTRESET, ioaddr + RCR ); + /* this should pause enough for the chip to be happy */ SMC_DELAY( ); - /* Set the transmit and receive configuration registers to + /* Set the transmit and receive configuration registers to default values */ outw( RCR_CLEAR, ioaddr + RCR ); outw( TCR_CLEAR, ioaddr + TCR ); /* set the control register to automatically - release successfully transmitted packets, to make the best + release successfully transmitted packets, to make the best use out of our limited memory */ SMC_SELECT_BANK( 1 ); - outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL ); + outw( inw( ioaddr + CONTROL ) | CTL_AUTO_RELEASE , ioaddr + CONTROL ); /* Reset the MMU */ SMC_SELECT_BANK( 2 ); outw( MC_RESET, ioaddr + MMU_CMD ); - /* Note: It doesn't seem that waiting for the MMU busy is needed here, + /* Note: It doesn't seem that waiting for the MMU busy is needed here, but this is a place where future chipsets _COULD_ break. Be wary of issuing another MMU command right after this */ outb( 0, ioaddr + INT_MASK ); } -/* +/* . Function: smc_enable . Purpose: let the chip talk to the outside work - . Method: + . Method: . 1. Enable the transmitter . 2. Enable the receiver . 3. Enable interrupts */ -static void smc_enable( int ioaddr ) +static void smc_enable( int ioaddr ) { SMC_SELECT_BANK( 0 ); /* see the header file for options in TCR/RCR NORMAL*/ @@ -408,23 +409,23 @@ static void smc_enable( int ioaddr ) /* now, enable interrupts */ SMC_SELECT_BANK( 2 ); outb( SMC_INTERRUPT_MASK, ioaddr + INT_MASK ); -} - +} + /* . Function: smc_shutdown . Purpose: closes down the SMC91xxx chip. - . Method: + . Method: . 1. zero the interrupt mask . 2. clear the enable receive flag . 3. clear the enable xmit flags . - . TODO: + . TODO: . (1) maybe utilize power down mode. . Why not yet? Because while the chip will go into power down mode, . the manual says that it will wake up in response to any I/O requests . in the register space. Empirical results do not show this working. */ -static void smc_shutdown( int ioaddr ) +static void smc_shutdown( int ioaddr ) { /* no more interrupts for me */ SMC_SELECT_BANK( 2 ); @@ -434,30 +435,30 @@ static void smc_shutdown( int ioaddr ) SMC_SELECT_BANK( 0 ); outb( RCR_CLEAR, ioaddr + RCR ); outb( TCR_CLEAR, ioaddr + TCR ); -#if 0 +#if 0 /* finally, shut the chip down */ - SMC_SELECT_BANK( 1 ); + SMC_SELECT_BANK( 1 ); outw( inw( ioaddr + CONTROL ), CTL_POWERDOWN, ioaddr + CONTROL ); -#endif +#endif } -#ifndef SUPPORT_OLD_KERNEL -/* +#ifndef SUPPORT_OLD_KERNEL +/* . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds ) . Purpose: . This sets the internal hardware table to filter out unwanted multicast - . packets before they take up memory. - . + . packets before they take up memory. + . . The SMC chip uses a hash table where the high 6 bits of the CRC of - . address are the offset into the table. If that bit is 1, then the + . address are the offset into the table. If that bit is 1, then the . multicast packet is accepted. Otherwise, it's dropped silently. - . + . . To use the 6 bits as an offset into the table, the high 3 bits are the . number of the 8 bit register, while the low 3 bits are the bit within . that register. . - . This routine is based very heavily on the one provided by Peter Cammaert. + . This routine is based very heavily on the one provided by Peter Cammaert. */ @@ -465,35 +466,35 @@ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs int i; unsigned char multicast_table[ 8 ]; struct dev_mc_list * cur_addr; - /* table for flipping the order of 3 bits */ + /* table for flipping the order of 3 bits */ unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - /* start with a table of all zeros: reject all */ + /* start with a table of all zeros: reject all */ memset( multicast_table, 0, sizeof( multicast_table ) ); cur_addr = addrs; for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { int position; - + /* do we have a pointer here? */ - if ( !cur_addr ) + if ( !cur_addr ) break; /* make sure this is a multicast address - shouldn't this - be a given if we have it here ? */ - if ( !( *cur_addr->dmi_addr & 1 ) ) - continue; + be a given if we have it here ? */ + if ( !( *cur_addr->dmi_addr & 1 ) ) + continue; - /* only use the low order bits */ + /* only use the low order bits */ position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f; - + /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert3[position&7]] |= + multicast_table[invert3[position&7]] |= (1<<invert3[(position>>3)&7]); } /* now, the table can be loaded into the chipset */ SMC_SELECT_BANK( 3 ); - + for ( i = 0; i < 8 ; i++ ) { outb( multicast_table[i], ioaddr + MULTICAST1 + i ); } @@ -501,20 +502,20 @@ static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs /* Finds the CRC32 of a set of bytes. - Again, from Peter Cammaert's code. + Again, from Peter Cammaert's code. */ -static int crc32( char * s, int length ) { +static int crc32( char * s, int length ) { /* indices */ int perByte; int perBit; /* crc polynomial for Ethernet */ const unsigned long poly = 0xedb88320; /* crc value - preinitialized to all 1's */ - unsigned long crc_value = 0xffffffff; + unsigned long crc_value = 0xffffffff; for ( perByte = 0; perByte < length; perByte ++ ) { unsigned char c; - + c = *(s++); for ( perBit = 0; perBit < 8; perBit++ ) { crc_value = (crc_value>>1)^ @@ -523,16 +524,16 @@ static int crc32( char * s, int length ) { } } return crc_value; -} +} -#endif +#endif -/* - . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) - . Purpose: +/* + . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct device * ) + . Purpose: . Attempt to allocate memory for a packet, if chip-memory is not - . available, then tell the card to generate an interrupt when it + . available, then tell the card to generate an interrupt when it . is available. . . Algorithm: @@ -540,18 +541,18 @@ static int crc32( char * s, int length ) { . o if the saved_skb is not currently null, then drop this packet . on the floor. This should never happen, because of TBUSY. . o if the saved_skb is null, then replace it with the current packet, - . o See if I can sending it now. + . o See if I can sending it now. . o (NO): Enable interrupts and let the interrupt handler deal with it. . o (YES):Send it now. */ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev ) -{ +{ struct smc_local *lp = (struct smc_local *)dev->priv; unsigned short ioaddr = dev->base_addr; word length; unsigned short numPages; - word time_out; - + word time_out; + if ( lp->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ lp->stats.tx_aborted_errors++; @@ -561,54 +562,54 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev ) lp->saved_skb = skb; length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - + /* - . the MMU wants the number of pages to be the number of 256 bytes - . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + . the MMU wants the number of pages to be the number of 256 bytes + . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) */ numPages = length / 256; if (numPages > 7 ) { printk(CARDNAME": Far too big packet error. \n"); - /* freeing the packet is a good thing here... but should + /* freeing the packet is a good thing here... but should . any packets of this size get down here? */ dev_kfree_skb (skb, FREE_WRITE); lp->saved_skb = NULL; /* this IS an error, but, i don't want the skb saved */ - return 0; + return 0; } /* either way, a packet is waiting now */ lp->packets_waiting++; - + /* now, try to allocate the memory */ SMC_SELECT_BANK( 2 ); outw( MC_ALLOC | numPages, ioaddr + MMU_CMD ); /* . Performance Hack - . + . . wait a short amount of time.. if I can send a packet now, I send . it now. Otherwise, I enable an interrupt and wait for one to be - . available. + . available. . . I could have handled this a slightly different way, by checking to . see if any memory was available in the FREE MEMORY register. However, . either way, I need to generate an allocation, and the allocation works - . no matter what, so I saw no point in checking free memory. - */ + . no matter what, so I saw no point in checking free memory. + */ time_out = MEMORY_WAIT_TIME; - do { + do { word status; status = inb( ioaddr + INTERRUPT ); - if ( status & IM_ALLOC_INT ) { + if ( status & IM_ALLOC_INT ) { /* acknowledge the interrupt */ outb( IM_ALLOC_INT, ioaddr + INTERRUPT ); - break; + break; } } while ( -- time_out ); if ( !time_out ) { - /* oh well, wait until the chip finds memory later */ + /* oh well, wait until the chip finds memory later */ SMC_ENABLE_INT( IM_ALLOC_INT ); PRINTK2((CARDNAME": memory allocation deferred. \n")); /* it's deferred, but I'll handle it later */ @@ -616,38 +617,38 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct device * dev ) } /* or YES! I can send the packet now.. */ smc_hardware_send_packet(dev); - + return 0; -} +} /* . Function: smc_hardware_send_packet(struct device * ) - . Purpose: - . This sends the actual packet to the SMC9xxx chip. - . + . Purpose: + . This sends the actual packet to the SMC9xxx chip. + . . Algorithm: - . First, see if a saved_skb is available. + . First, see if a saved_skb is available. . ( this should NOT be called if there is no 'saved_skb' . Now, find the packet number that the chip allocated - . Point the data pointers at it in memory + . Point the data pointers at it in memory . Set the length word in the chip's memory . Dump the packet to chip memory . Check if a last byte is needed ( odd length packet ) - . if so, set the control flag right - . Tell the card to send it + . if so, set the control flag right + . Tell the card to send it . Enable the transmit interrupt, so I know if it failed . Free the kernel data if I actually sent it. */ -static void smc_hardware_send_packet( struct device * dev ) +static void smc_hardware_send_packet( struct device * dev ) { struct smc_local *lp = (struct smc_local *)dev->priv; byte packet_no; struct sk_buff * skb = lp->saved_skb; - word length; + word length; unsigned short ioaddr; byte * buf; - ioaddr = dev->base_addr; + ioaddr = dev->base_addr; if ( !skb ) { PRINTK((CARDNAME": In XMIT with no packet to send \n")); @@ -657,8 +658,8 @@ static void smc_hardware_send_packet( struct device * dev ) buf = skb->data; /* If I get here, I _know_ there is a packet slot waiting for me */ - packet_no = inb( ioaddr + PNR_ARR + 1 ); - if ( packet_no & 0x80 ) { + packet_no = inb( ioaddr + PNR_ARR + 1 ); + if ( packet_no & 0x80 ) { /* or isn't there? BAD CHIP! */ printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n"); kfree(skb); @@ -670,7 +671,7 @@ static void smc_hardware_send_packet( struct device * dev ) /* we have a packet address, so tell the card to use it */ outb( packet_no, ioaddr + PNR_ARR ); - /* point to the beginning of the packet */ + /* point to the beginning of the packet */ outw( PTR_AUTOINC , ioaddr + POINTER ); PRINTK3((CARDNAME": Trying to xmit packet of length %x\n", length )); @@ -678,36 +679,36 @@ static void smc_hardware_send_packet( struct device * dev ) print_packet( buf, length ); #endif - /* send the packet length ( +6 for status, length and ctl byte ) - and the status word ( set to zeros ) */ + /* send the packet length ( +6 for status, length and ctl byte ) + and the status word ( set to zeros ) */ #ifdef USE_32_BIT outl( (length +6 ) << 16 , ioaddr + DATA_1 ); #else - outw( 0, ioaddr + DATA_1 ); - /* send the packet length ( +6 for status words, length, and ctl*/ + outw( 0, ioaddr + DATA_1 ); + /* send the packet length ( +6 for status words, length, and ctl*/ outb( (length+6) & 0xFF,ioaddr + DATA_1 ); outb( (length+6) >> 8 , ioaddr + DATA_1 ); -#endif +#endif - /* send the actual data - . I _think_ it's faster to send the longs first, and then - . mop up by sending the last word. It depends heavily - . on alignment, at least on the 486. Maybe it would be + /* send the actual data + . I _think_ it's faster to send the longs first, and then + . mop up by sending the last word. It depends heavily + . on alignment, at least on the 486. Maybe it would be . a good idea to check which is optimal? But that could take - . almost as much time as is saved? - */ -#ifdef USE_32_BIT - if ( length & 0x2 ) { - outsl(ioaddr + DATA_1, buf, length >> 2 ); + . almost as much time as is saved? + */ +#ifdef USE_32_BIT + if ( length & 0x2 ) { + outsl(ioaddr + DATA_1, buf, length >> 2 ); outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1); } else - outsl(ioaddr + DATA_1, buf, length >> 2 ); + outsl(ioaddr + DATA_1, buf, length >> 2 ); #else outsw(ioaddr + DATA_1 , buf, (length ) >> 1); #endif /* Send the last byte, if there is one. */ - + if ( (length & 1) == 0 ) { outw( 0, ioaddr + DATA_1 ); } else { @@ -721,7 +722,7 @@ static void smc_hardware_send_packet( struct device * dev ) /* and let the chipset deal with it */ outw( MC_ENQUEUE , ioaddr + MMU_CMD ); - PRINTK2((CARDNAME": Sent packet of length %d \n",length)); + PRINTK2((CARDNAME": Sent packet of length %d \n",length)); lp->saved_skb = NULL; dev_kfree_skb (skb, FREE_WRITE); @@ -737,38 +738,38 @@ static void smc_hardware_send_packet( struct device * dev ) /*------------------------------------------------------------------------- | - | smc_init( struct device * dev ) - | Input parameters: + | smc_init( struct device * dev ) + | Input parameters: | dev->base_addr == 0, try to find all possible locations | dev->base_addr == 1, return failure code | dev->base_addr == 2, always allocate space, and return success - | dev->base_addr == <anything else> this is the address to check + | dev->base_addr == <anything else> this is the address to check | - | Output: + | Output: | 0 --> there is a device - | anything else, error - | + | anything else, error + | --------------------------------------------------------------------------- -*/ -int smc_init(struct device *dev) +*/ +__initfunc(int smc_init(struct device *dev)) { int i; int base_addr = dev ? dev->base_addr : 0; /* try a specific location */ - if (base_addr > 0x1ff) { - int error; + if (base_addr > 0x1ff) { + int error; error = smc_probe(base_addr); if ( 0 == error ) { return smc_initcard( dev, base_addr ); } - return error; + return error; } else { if ( 0 != base_addr ) { return -ENXIO; } } - + /* check every ethernet address */ for (i = 0; smc_portlist[i]; i++) { int ioaddr = smc_portlist[i]; @@ -778,8 +779,8 @@ int smc_init(struct device *dev) continue; /* check this specific address */ - if ( smc_probe( ioaddr ) == 0) { - return smc_initcard( dev, ioaddr ); + if ( smc_probe( ioaddr ) == 0) { + return smc_initcard( dev, ioaddr ); } } @@ -789,19 +790,19 @@ int smc_init(struct device *dev) #ifndef NO_AUTOPROBE /*---------------------------------------------------------------------- - . smc_findirq - . - . This routine has a simple purpose -- make the SMC chip generate an + . smc_findirq + . + . This routine has a simple purpose -- make the SMC chip generate an . interrupt, so an auto-detect routine can detect it, and find the IRQ, ------------------------------------------------------------------------ */ -int smc_findirq( int ioaddr ) +__initfunc(int smc_findirq( int ioaddr )) { int timeout = 20; /* I have to do a STI() here, because this is called from - a routine that does an CLI during this process, making it + a routine that does an CLI during this process, making it rather difficult to get interrupts for auto detection */ sti(); @@ -813,16 +814,16 @@ int smc_findirq( int ioaddr ) * when done. */ - - SMC_SELECT_BANK(2); + + SMC_SELECT_BANK(2); /* enable ALLOCation interrupts ONLY */ - outb( IM_ALLOC_INT, ioaddr + INT_MASK ); + outb( IM_ALLOC_INT, ioaddr + INT_MASK ); /* - . Allocate 512 bytes of memory. Note that the chip was just + . Allocate 512 bytes of memory. Note that the chip was just . reset so all the memory is available */ - outw( MC_ALLOC | 1, ioaddr + MMU_CMD ); + outw( MC_ALLOC | 1, ioaddr + MMU_CMD ); /* . Wait until positive that the interrupt has been generated @@ -832,7 +833,7 @@ int smc_findirq( int ioaddr ) int_status = inb( ioaddr + INTERRUPT ); - if ( int_status & IM_ALLOC_INT ) + if ( int_status & IM_ALLOC_INT ) break; /* got the interrupt */ timeout--; } @@ -843,13 +844,13 @@ int smc_findirq( int ioaddr ) /* DELAY HERE! On a fast machine, the status might change before the interrupt - is given to the processor. This means that the interrupt was - never detected, and autoirq_report fails to report anything. - This should fix autoirq_* problems. + is given to the processor. This means that the interrupt was + never detected, and autoirq_report fails to report anything. + This should fix autoirq_* problems. */ SMC_DELAY(); - SMC_DELAY(); - + SMC_DELAY(); + /* and disable all interrupts again */ outb( 0, ioaddr + INT_MASK ); @@ -858,29 +859,29 @@ int smc_findirq( int ioaddr ) cli(); /* and return what I found */ - return autoirq_report( 0 ); + return autoirq_report( 0 ); } #endif - + /*---------------------------------------------------------------------- . Function: smc_probe( int ioaddr ) - . - . Purpose: + . + . Purpose: . Tests to see if a given ioaddr points to an SMC9xxx chip. - . Returns a 0 on success - . + . Returns a 0 on success + . . Algorithm: . (1) see if the high byte of BANK_SELECT is 0x33 . (2) compare the ioaddr with the base register's address . (3) see if I recognize the chip ID in the appropriate register - . + . .--------------------------------------------------------------------- - */ + */ -static int smc_probe( int ioaddr ) +__initfunc(static int smc_probe( int ioaddr )) { unsigned int bank; - word revision_register; + word revision_register; word base_address_register; /* First, see if the high byte is 0x33 */ @@ -896,12 +897,12 @@ static int smc_probe( int ioaddr ) return -ENODEV; } /* well, we've already written once, so hopefully another time won't - hurt. This time, I need to switch the bank register to bank 1, + hurt. This time, I need to switch the bank register to bank 1, so I can access the base address register */ SMC_SELECT_BANK(1); base_address_register = inw( ioaddr + BASE ); if ( ioaddr != ( base_address_register >> 3 & 0x3E0 ) ) { - printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)." + printk(CARDNAME ": IOADDR %x doesn't match configuration (%x)." "Probably not a SMC chip\n", ioaddr, base_address_register >> 3 & 0x3E0 ); /* well, the base address register didn't match. Must not have @@ -909,12 +910,12 @@ static int smc_probe( int ioaddr ) return -ENODEV; } - /* check if the revision register is something that I recognize. - These might need to be added to later, as future revisions + /* check if the revision register is something that I recognize. + These might need to be added to later, as future revisions could be added. */ SMC_SELECT_BANK(3); revision_register = inw( ioaddr + REVISION ); - if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) { + if ( !chip_ids[ ( revision_register >> 4 ) & 0xF ] ) { /* I don't recognize this chip, so... */ printk(CARDNAME ": IO %x: Unrecognized revision register:" " %x, Contact author. \n", ioaddr, revision_register ); @@ -922,35 +923,35 @@ static int smc_probe( int ioaddr ) return -ENODEV; } - /* at this point I'll assume that the chip is an SMC9xxx. - It might be prudent to check a listing of MAC addresses - against the hardware address, or do some other tests. */ + /* at this point I'll assume that the chip is an SMC9xxx. + It might be prudent to check a listing of MAC addresses + against the hardware address, or do some other tests. */ return 0; } /*--------------------------------------------------------------- - . Here I do typical initialization tasks. - . + . Here I do typical initialization tasks. + . . o Initialize the structure if needed . o print out my vanity message if not done so already . o print out what type of hardware is detected . o print out the ethernet address - . o find the IRQ - . o set up my private data + . o find the IRQ + . o set up my private data . o configure the dev structure with my subroutines . o actually GRAB the irq. - . o GRAB the region + . o GRAB the region .----------------------------------------------------------------- */ -static int smc_initcard(struct device *dev, int ioaddr) +__initfunc(static int smc_initcard(struct device *dev, int ioaddr)) { int i; static unsigned version_printed = 0; /* registers */ - word revision_register; - word configuration_register; + word revision_register; + word configuration_register; word memory_info_register; word memory_cfg_register; @@ -966,10 +967,10 @@ static int smc_initcard(struct device *dev, int ioaddr) #ifndef MODULE /* note: the old module interface does not support this call */ dev = init_etherdev( 0, sizeof( struct smc_local ), 0 ); -#endif +#endif #else dev = init_etherdev(0, 0); -#endif +#endif if (dev == NULL) return -ENOMEM; } @@ -984,12 +985,12 @@ static int smc_initcard(struct device *dev, int ioaddr) . Get the MAC address ( bank 1, regs 4 - 9 ) */ SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) { + for ( i = 0; i < 6; i += 2 ) { word address; address = inw( ioaddr + ADDR0 + i ); dev->dev_addr[ i + 1] = address >> 8; - dev->dev_addr[ i ] = address & 0xFF; + dev->dev_addr[ i ] = address & 0xFF; } /* get the memory information */ @@ -1000,16 +1001,16 @@ static int smc_initcard(struct device *dev, int ioaddr) memory = ( memory_cfg_register >> 9 ) & 0x7; /* multiplier */ memory *= 256 * ( memory_info_register & 0xFF ); - /* + /* Now, I want to find out more about the chip. This is sort of redundant, but it's cleaner to have it in both, rather than having one VERY long probe procedure. - */ + */ SMC_SELECT_BANK(3); revision_register = inw( ioaddr + REVISION ); version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ]; if ( !version_string ) { - /* I shouldn't get here because this call was done before.... */ + /* I shouldn't get here because this call was done before.... */ return -ENODEV; } @@ -1017,7 +1018,7 @@ static int smc_initcard(struct device *dev, int ioaddr) if ( dev->if_port == 0 ) { SMC_SELECT_BANK(1); configuration_register = inw( ioaddr + CONFIG ); - if ( configuration_register & CFG_AUI_SELECT ) + if ( configuration_register & CFG_AUI_SELECT ) dev->if_port = 2; else dev->if_port = 1; @@ -1029,17 +1030,17 @@ static int smc_initcard(struct device *dev, int ioaddr) /* . If dev->irq is 0, then the device has to be banged on to see - . what the IRQ is. - . + . what the IRQ is. + . . This banging doesn't always detect the IRQ, for unknown reasons. - . a workaround is to reset the chip and try again. - . + . a workaround is to reset the chip and try again. + . . Interestingly, the DOS packet driver *SETS* the IRQ on the card to . be what is requested on the command line. I don't do that, mostly . because the card that I have uses a non-standard method of accessing . the IRQs, and because this _should_ work in most configurations. . - . Specifying an IRQ is done with the assumption that the user knows + . Specifying an IRQ is done with the assumption that the user knows . what (s)he is doing. No checking is done!!!! . */ @@ -1048,14 +1049,14 @@ static int smc_initcard(struct device *dev, int ioaddr) int trials; trials = 3; - while ( trials-- ) { + while ( trials-- ) { dev->irq = smc_findirq( ioaddr ); - if ( dev->irq ) + if ( dev->irq ) break; /* kick the card and try again */ smc_reset( ioaddr ); } - } + } if (dev->irq == 0 ) { printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n"); return -ENODEV; @@ -1075,12 +1076,12 @@ static int smc_initcard(struct device *dev, int ioaddr) } /* now, print out the card info, in a short format.. */ - + printk(CARDNAME ": %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", - version_string, revision_register & 0xF, ioaddr, dev->irq, + version_string, revision_register & 0xF, ioaddr, dev->irq, if_string, memory ); /* - . Print the Ethernet address + . Print the Ethernet address */ printk("ADDR: "); for (i = 0; i < 5; i++) @@ -1124,21 +1125,21 @@ static int smc_initcard(struct device *dev, int ioaddr) } #if SMC_DEBUG > 2 -static void print_packet( byte * buf, int length ) -{ +static void print_packet( byte * buf, int length ) +{ #if 0 int i; int remainder; int lines; - + printk("Packet of length %d \n", length ); lines = length / 16; remainder = length % 16; - for ( i = 0; i < lines ; i ++ ) { + for ( i = 0; i < lines ; i ++ ) { int cur; - for ( cur = 0; cur < 8; cur ++ ) { + for ( cur = 0; cur < 8; cur ++ ) { byte a, b; a = *(buf ++ ); @@ -1157,12 +1158,12 @@ static void print_packet( byte * buf, int length ) printk("\n"); #endif } -#endif +#endif /* * Open and Initialize the board - * + * * Set up everything, reset the card, etc .. * */ @@ -1170,7 +1171,7 @@ static int smc_open(struct device *dev) { int ioaddr = dev->base_addr; - int i; /* used to set hw ethernet address */ + int i; /* used to set hw ethernet address */ /* clear out all the junk that was put here before... */ memset(dev->priv, 0, sizeof(struct smc_local)); @@ -1188,26 +1189,26 @@ static int smc_open(struct device *dev) smc_enable( ioaddr ); /* Select which interface to use */ - + SMC_SELECT_BANK( 1 ); - if ( dev->if_port == 1 ) { - outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT, - ioaddr + CONFIG ); - } - else if ( dev->if_port == 2 ) { - outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT, - ioaddr + CONFIG ); + if ( dev->if_port == 1 ) { + outw( inw( ioaddr + CONFIG ) & ~CFG_AUI_SELECT, + ioaddr + CONFIG ); + } + else if ( dev->if_port == 2 ) { + outw( inw( ioaddr + CONFIG ) | CFG_AUI_SELECT, + ioaddr + CONFIG ); } /* According to Becker, I have to set the hardware address at this point, because the (l)user can set it with an - ioctl. Easily done... + ioctl. Easily done... */ SMC_SELECT_BANK( 1 ); - for ( i = 0; i < 6; i += 2 ) { + for ( i = 0; i < 6; i += 2 ) { word address; - + address = dev->dev_addr[ i + 1 ] << 8 ; address |= dev->dev_addr[ i ]; outw( address, ioaddr + ADDR0 + i ); @@ -1217,8 +1218,8 @@ static int smc_open(struct device *dev) /*-------------------------------------------------------- . Called by the kernel to send a packet out into the void - . of the net. This routine is largely based on - . skeleton.c, from Becker. + . of the net. This routine is largely based on + . skeleton.c, from Becker. .-------------------------------------------------------- */ static int smc_send_packet(struct sk_buff *skb, struct device *dev) @@ -1230,7 +1231,7 @@ static int smc_send_packet(struct sk_buff *skb, struct device *dev) if (tickssofar < 5) return 1; printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n", - tx_done(dev) ? "IRQ conflict" : + tx_done(dev) ? "IRQ conflict" : "network cable problem"); /* "kick" the adaptor */ smc_reset( dev->base_addr ); @@ -1242,22 +1243,14 @@ static int smc_send_packet(struct sk_buff *skb, struct device *dev) ((struct smc_local *)dev->priv)->saved_skb = NULL; } - /* 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 transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) { printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n"); dev_kfree_skb (skb, FREE_WRITE); } else { - /* Well, I want to send the packet.. but I don't know - if I can send it right now... */ + /* Well, I want to send the packet.. but I don't know + if I can send it right now... */ return smc_wait_to_send_packet( skb, dev ); } return 0; @@ -1270,16 +1263,16 @@ static int smc_send_packet(struct sk_buff *skb, struct device *dev) . . So: . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge + . branch off into routines to handle each case, and acknowledge . each to the interrupt register - . and finally restore state. - . + . and finally restore state. + . ---------------------------------------------------------------------*/ #ifdef REALLY_NEW_KERNEL static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -#else +#else static void smc_interrupt(int irq, struct pt_regs * regs) -#endif +#endif { struct device *dev = (struct device *)(irq2dev_map[irq]); int ioaddr = dev->base_addr; @@ -1294,21 +1287,21 @@ static void smc_interrupt(int irq, struct pt_regs * regs) word saved_pointer; - + PRINTK3((CARDNAME": SMC interrupt started \n")); if (dev == NULL) { - printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n", + printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n", irq); return; } /* will Linux let this happen ?? If not, this costs some speed */ - if ( dev->interrupt ) { + if ( dev->interrupt ) { printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n"); return; } - + dev->interrupt = 1; saved_bank = inw( ioaddr + BANK_SELECT ); @@ -1325,14 +1318,14 @@ static void smc_interrupt(int irq, struct pt_regs * regs) timeout = 4; PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); - do { + do { /* read the status flag, and mask it */ status = inb( ioaddr + INTERRUPT ) & mask; if (!status ) break; PRINTK3((KERN_WARNING CARDNAME - ": Handling interrupt status %x \n", status )); + ": Handling interrupt status %x \n", status )); if (status & IM_RCV_INT) { /* Got a packet(s). */ @@ -1343,7 +1336,7 @@ static void smc_interrupt(int irq, struct pt_regs * regs) PRINTK2((KERN_WARNING CARDNAME ": TX ERROR handled\n")); smc_tx(dev); - outb(IM_TX_INT, ioaddr + INTERRUPT ); + outb(IM_TX_INT, ioaddr + INTERRUPT ); } else if (status & IM_TX_EMPTY_INT ) { /* update stats */ SMC_SELECT_BANK( 0 ); @@ -1355,14 +1348,14 @@ static void smc_interrupt(int irq, struct pt_regs * regs) lp->stats.collisions += card_stats & 0xF; /* these are for when linux supports these statistics */ -#if 0 +#if 0 card_stats >>= 4; /* deferred */ card_stats >>= 4; /* excess deferred */ -#endif +#endif SMC_SELECT_BANK( 2 ); - PRINTK2((KERN_WARNING CARDNAME + PRINTK2((KERN_WARNING CARDNAME ": TX_BUFFER_EMPTY handled\n")); outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); mask &= ~IM_TX_EMPTY_INT; @@ -1374,19 +1367,19 @@ static void smc_interrupt(int irq, struct pt_regs * regs) ": Allocation interrupt \n")); /* clear this interrupt so it doesn't happen again */ mask &= ~IM_ALLOC_INT; - + smc_hardware_send_packet( dev ); - + /* enable xmit interrupts based on this */ mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); /* and let the card send more packets to me */ mark_bh( NET_BH ); - PRINTK2((CARDNAME": Handoff done successfully.\n")); + PRINTK2((CARDNAME": Handoff done successfully.\n")); } else if (status & IM_RX_OVRN_INT ) { lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; + lp->stats.rx_fifo_errors++; outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); } else if (status & IM_EPH_INT ) { PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); @@ -1394,13 +1387,13 @@ static void smc_interrupt(int irq, struct pt_regs * regs) PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); outb( IM_ERCV_INT, ioaddr + INTERRUPT ); } - } while ( timeout -- ); + } while ( timeout -- ); + - /* restore state register */ SMC_SELECT_BANK( 2 ); outb( mask, ioaddr + INT_MASK ); - + PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); outw( saved_pointer, ioaddr + POINTER ); @@ -1417,10 +1410,10 @@ static void smc_interrupt(int irq, struct pt_regs * regs) . . There is ( at least ) a packet waiting to be read from . chip-memory. - . - . o Read the status - . o If an error, record it - . o otherwise, read in the packet + . + . o Read the status + . o If an error, record it + . o otherwise, read in the packet -------------------------------------------------------------- */ static void smc_rcv(struct device *dev) @@ -1429,8 +1422,8 @@ static void smc_rcv(struct device *dev) int ioaddr = dev->base_addr; int packet_number; word status; - word packet_length; - + word packet_length; + /* assume bank 2 */ packet_number = inw( ioaddr + FIFO_PORTS ); @@ -1441,51 +1434,51 @@ static void smc_rcv(struct device *dev) /* don't need to restore anything */ return; } - + /* start reading from the start of the packet */ outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER ); - /* First two words are status and packet_length */ + /* First two words are status and packet_length */ status = inw( ioaddr + DATA_1 ); packet_length = inw( ioaddr + DATA_1 ); - + packet_length &= 0x07ff; /* mask off top bits */ PRINTK2(("RCV: STATUS %4x LENGTH %4x\n", status, packet_length )); - /* - . the packet length contains 3 extra words : + /* + . the packet length contains 3 extra words : . status, length, and an extra word with an odd byte . */ - packet_length -= 6; - - if ( !(status & RS_ERRORS ) ){ + packet_length -= 6; + + if ( !(status & RS_ERRORS ) ){ /* do stuff to make a new packet */ struct sk_buff * skb; byte * data; /* read one extra byte */ - if ( status & RS_ODDFRAME ) - packet_length++; + if ( status & RS_ODDFRAME ) + packet_length++; - /* set multicast stats */ + /* set multicast stats */ if ( status & RS_MULTICAST ) lp->stats.multicast++; #ifdef SUPPORT_OLD_KERNEL skb = alloc_skb( packet_length + 5, GFP_ATOMIC ); -#else - skb = dev_alloc_skb( packet_length + 5); +#else + skb = dev_alloc_skb( packet_length + 5); #endif - if ( skb == NULL ) { + if ( skb == NULL ) { printk(KERN_NOTICE CARDNAME ": Low memory, packet dropped.\n"); lp->stats.rx_dropped++; } - /* + /* ! This should work without alignment, but it could be - ! in the worse case + ! in the worse case */ #ifndef SUPPORT_OLD_KERNEL /* TODO: Should I use 32bit alignment here ? */ @@ -1500,42 +1493,42 @@ static void smc_rcv(struct device *dev) data = skb_put( skb, packet_length); #endif #ifdef USE_32_BIT - /* QUESTION: Like in the TX routine, do I want + /* QUESTION: Like in the TX routine, do I want to send the DWORDs or the bytes first, or some mixture. A mixture might improve already slow PIO performance */ - PRINTK3((" Reading %d dwords (and %d bytes) \n", + PRINTK3((" Reading %d dwords (and %d bytes) \n", packet_length >> 2, packet_length & 3 )); - insl(ioaddr + DATA_1 , data, packet_length >> 2 ); + insl(ioaddr + DATA_1 , data, packet_length >> 2 ); /* read the left over bytes */ - insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC), + insb( ioaddr + DATA_1, data + (packet_length & 0xFFFFFC), packet_length & 0x3 ); #else - PRINTK3((" Reading %d words and %d byte(s) \n", + PRINTK3((" Reading %d words and %d byte(s) \n", (packet_length >> 1 ), packet_length & 1 ); - if ( packet_length & 1 ) - *(data++) = inb( ioaddr + DATA_1 ); + if ( packet_length & 1 ) + *(data++) = inb( ioaddr + DATA_1 ); insw(ioaddr + DATA_1 , data, (packet_length + 1 ) >> 1); if ( packet_length & 1 ) { data += packet_length & ~1; - *((data++) = inb( ioaddr + DATA_1 ); + *((data++) = inb( ioaddr + DATA_1 ); } -#endif -#if SMC_DEBUG > 2 +#endif +#if SMC_DEBUG > 2 print_packet( data, packet_length ); #endif #ifndef SUPPORT_OLD_KERNEL - skb->protocol = eth_type_trans(skb, dev ); + skb->protocol = eth_type_trans(skb, dev ); #endif netif_rx(skb); lp->stats.rx_packets++; } else { /* error ... */ lp->stats.rx_errors++; - - if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++; - if ( status & (RS_TOOSHORT | RS_TOOLONG ) ) + + if ( status & RS_ALGNERR ) lp->stats.rx_frame_errors++; + if ( status & (RS_TOOSHORT | RS_TOOLONG ) ) lp->stats.rx_length_errors++; if ( status & RS_BADCRC) lp->stats.rx_crc_errors++; } @@ -1547,22 +1540,22 @@ static void smc_rcv(struct device *dev) } -/************************************************************************* +/************************************************************************* . smc_tx - . + . . Purpose: Handle a transmit error message. This will only be called - . when an error, because of the AUTO_RELEASE mode. - . + . when an error, because of the AUTO_RELEASE mode. + . . Algorithm: . Save pointer and packet no . Get the packet no from the top of the queue . check if it's valid ( if not, is this an error??? ) - . read the status word + . read the status word . record the error . ( resend? Not really, since we don't want old packets around ) - . Restore saved values - ************************************************************************/ -static void smc_tx( struct device * dev ) + . Restore saved values + ************************************************************************/ +static void smc_tx( struct device * dev ) { int ioaddr = dev->base_addr; struct smc_local *lp = (struct smc_local *)dev->priv; @@ -1578,46 +1571,46 @@ static void smc_tx( struct device * dev ) packet_no &= 0x7F; /* select this as the packet to read from */ - outb( packet_no, ioaddr + PNR_ARR ); - - /* read the first word from this packet */ + outb( packet_no, ioaddr + PNR_ARR ); + + /* read the first word from this packet */ outw( PTR_AUTOINC | PTR_READ, ioaddr + POINTER ); tx_status = inw( ioaddr + DATA_1 ); PRINTK3((CARDNAME": TX DONE STATUS: %4x \n", tx_status )); - + lp->stats.tx_errors++; if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++; if ( tx_status & TS_LATCOL ) { - printk(KERN_DEBUG CARDNAME + printk(KERN_DEBUG CARDNAME ": Late collision occurred on last xmit.\n"); lp->stats.tx_window_errors++; } #if 0 if ( tx_status & TS_16COL ) { ... } -#endif +#endif - if ( tx_status & TS_SUCCESS ) { + if ( tx_status & TS_SUCCESS ) { printk(CARDNAME": Successful packet caused interrupt \n"); - } + } /* re-enable transmit */ SMC_SELECT_BANK( 0 ); outw( inw( ioaddr + TCR ) | TCR_ENABLE, ioaddr + TCR ); - /* kill the packet */ + /* kill the packet */ SMC_SELECT_BANK( 2 ); outw( MC_FREEPKT, ioaddr + MMU_CMD ); /* one less packet waiting for me */ lp->packets_waiting--; - + outb( saved_packet, ioaddr + PNR_ARR ); return; } /*---------------------------------------------------- . smc_close - . + . . this makes the board clean up everything that it can . and not talk to the outside world. Caused by . an 'ifconfig ethX down' @@ -1640,10 +1633,10 @@ static int smc_close(struct device *dev) } /*------------------------------------------------------------ - . Get the current statistics. - . This may be called with the card open or closed. + . Get the current statistics. + . This may be called with the card open or closed. .-------------------------------------------------------------*/ -static struct enet_statistics * smc_query_statistics(struct device *dev) { +static struct net_device_stats* smc_query_statistics(struct device *dev) { struct smc_local *lp = (struct smc_local *)dev->priv; return &lp->stats; @@ -1651,52 +1644,52 @@ static struct enet_statistics * smc_query_statistics(struct device *dev) { /*----------------------------------------------------------- . smc_set_multicast_list - . + . . This routine will, depending on the values passed to it, - . either make it accept multicast packets, go into + . either make it accept multicast packets, go into . promiscuous mode ( for TCPDUMP and cousins ) or accept - . a select set of multicast packets + . a select set of multicast packets */ #ifdef SUPPORT_OLD_KERNEL -static void smc_set_multicast_list( struct device * dev, - int num_addrs, void * addrs ) +static void smc_set_multicast_list( struct device * dev, + int num_addrs, void * addrs ) #else -static void smc_set_multicast_list(struct device *dev) -#endif +static void smc_set_multicast_list(struct device *dev) +#endif { short ioaddr = dev->base_addr; SMC_SELECT_BANK(0); #ifdef SUPPORT_OLD_KERNEL - if ( num_addrs < 0 ) + if ( num_addrs < 0 ) #else - if ( dev->flags & IFF_PROMISC ) -#endif + if ( dev->flags & IFF_PROMISC ) +#endif outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR ); -/* BUG? I never disable promiscuous mode if multicasting was turned on. +/* BUG? I never disable promiscuous mode if multicasting was turned on. Now, I turn off promiscuous mode, but I don't do anything to multicasting - when promiscuous mode is turned on. + when promiscuous mode is turned on. */ - /* Here, I am setting this to accept all multicast packets. + /* Here, I am setting this to accept all multicast packets. I don't need to zero the multicast table, because the flag is - checked before the table is + checked before the table is */ -#ifdef SUPPORT_OLD_KERNEL +#ifdef SUPPORT_OLD_KERNEL else if ( num_addrs > 20 ) /* arbitrary constant */ #else - else if (dev->flags & IFF_ALLMULTI) -#endif - outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR ); + else if (dev->flags & IFF_ALLMULTI) +#endif + outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR ); /* We just get all multicast packets even if we only want them . from one source. This will be changed at some future . point. */ #ifdef SUPPORT_OLD_KERNEL - else if (num_addrs > 0 ) { + else if (num_addrs > 0 ) { /* the old kernel support will not have hardware multicast support. It would - involve more kludges, and make the multicast setting code even worse. + involve more kludges, and make the multicast setting code even worse. Instead, just use the ALMUL method. This is reasonable, considering that it is seldom used */ @@ -1704,11 +1697,11 @@ static void smc_set_multicast_list(struct device *dev) outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR ); } #else - else if (dev->mc_count ) { + else if (dev->mc_count ) { /* support hardware multicasting */ - - /* be sure I get rid of flags I might have set */ - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), + + /* be sure I get rid of flags I might have set */ + outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), ioaddr + RCR ); /* NOTE: this has to set the bank, so make sure it is the last thing called. The bank is set to zero at the top */ @@ -1716,18 +1709,18 @@ static void smc_set_multicast_list(struct device *dev) } #endif else { - outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), + outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), ioaddr + RCR ); - /* - since I'm disabling all multicast entirely, I need to - clear the multicast list + /* + since I'm disabling all multicast entirely, I need to + clear the multicast list */ SMC_SELECT_BANK( 3 ); - outw( 0, ioaddr + MULTICAST1 ); - outw( 0, ioaddr + MULTICAST2 ); - outw( 0, ioaddr + MULTICAST3 ); - outw( 0, ioaddr + MULTICAST4 ); + outw( 0, ioaddr + MULTICAST1 ); + outw( 0, ioaddr + MULTICAST2 ); + outw( 0, ioaddr + MULTICAST3 ); + outw( 0, ioaddr + MULTICAST4 ); } } @@ -1744,12 +1737,16 @@ int io = 0; int irq = 0; int ifport = 0; +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(ifport, "i"); + int init_module(void) { int result; if (io == 0) - printk(KERN_WARNING + printk(KERN_WARNING CARDNAME": You shouldn't use auto-probing with insmod!\n" ); /* copy the parameters from insmod into the device structure */ @@ -1776,4 +1773,3 @@ void cleanup_module(void) } #endif /* MODULE */ - |