2005-04-17 02:20:36 +04:00
/*
* Amiga Linux / m68k and Linux / PPC Zorro NS8390 Ethernet Driver
*
* ( C ) Copyright 1998 - 2000 by some Elitist 680 x0 Users ( TM )
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* This program is based on all the other NE2000 drivers for Linux
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of the Linux
* distribution for more details .
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* The Ariadne II and X - Surf are Zorro - II boards containing Realtek RTL8019AS
* Ethernet Controllers .
*/
2011-06-23 00:39:00 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/netdevice.h>
# include <linux/etherdevice.h>
# include <linux/zorro.h>
2006-01-10 05:37:15 +03:00
# include <linux/jiffies.h>
2005-04-17 02:20:36 +04:00
# include <asm/irq.h>
# include <asm/amigaints.h>
# include <asm/amigahw.h>
2011-06-23 00:39:00 +04:00
# define EI_SHIFT(x) (ei_local->reg_offset[x])
# define ei_inb(port) in_8(port)
# define ei_outb(val, port) out_8(port, val)
# define ei_inb_p(port) in_8(port)
# define ei_outb_p(val, port) out_8(port, val)
2005-04-17 02:20:36 +04:00
2006-10-10 03:19:36 +04:00
static const char version [ ] =
2011-06-23 00:39:00 +04:00
" 8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov) \n " ;
2006-10-10 03:19:36 +04:00
# include "lib8390.c"
2005-04-17 02:20:36 +04:00
# define DRV_NAME "zorro8390"
# define NE_BASE (dev->base_addr)
2011-06-23 00:39:00 +04:00
# define NE_CMD (0x00 * 2)
# define NE_DATAPORT (0x10 * 2) /* NatSemi-defined port window offset */
# define NE_RESET (0x1f * 2) / * Issue a read to reset,
* a write to clear . */
# define NE_IO_EXTENT (0x20 * 2)
# define NE_EN0_ISR (0x07 * 2)
# define NE_EN0_DCFG (0x0e * 2)
# define NE_EN0_RSARLO (0x08 * 2)
# define NE_EN0_RSARHI (0x09 * 2)
# define NE_EN0_RCNTLO (0x0a * 2)
# define NE_EN0_RXCR (0x0c * 2)
# define NE_EN0_TXCR (0x0d * 2)
# define NE_EN0_RCNTHI (0x0b * 2)
# define NE_EN0_IMR (0x0f * 2)
2005-04-17 02:20:36 +04:00
# define NESM_START_PG 0x40 /* First page of TX buffer */
# define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
2011-06-23 00:39:00 +04:00
# define WORDSWAP(a) ((((a) >> 8) & 0xff) | ((a) << 8))
2005-04-17 02:20:36 +04:00
static struct card_info {
2011-06-23 00:39:00 +04:00
zorro_id id ;
const char * name ;
unsigned int offset ;
2012-12-03 18:22:51 +04:00
} cards [ ] = {
2011-06-23 00:39:00 +04:00
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2 , " Ariadne II " , 0x0600 } ,
{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF , " X-Surf " , 0x8600 } ,
2005-04-17 02:20:36 +04:00
} ;
2011-06-23 00:39:00 +04:00
/* Hard reset the card. This used to pause for the same period that a
* 8390 reset command required , but that shouldn ' t be necessary .
*/
static void zorro8390_reset_8390 ( struct net_device * dev )
{
unsigned long reset_start_time = jiffies ;
if ( ei_debug > 1 )
netdev_dbg ( dev , " resetting - t=%ld... \n " , jiffies ) ;
z_writeb ( z_readb ( NE_BASE + NE_RESET ) , NE_BASE + NE_RESET ) ;
ei_status . txing = 0 ;
ei_status . dmaing = 0 ;
/* This check _should_not_ be necessary, omit eventually. */
while ( ( z_readb ( NE_BASE + NE_EN0_ISR ) & ENISR_RESET ) = = 0 )
if ( time_after ( jiffies , reset_start_time + 2 * HZ / 100 ) ) {
netdev_warn ( dev , " %s: did not complete \n " , __func__ ) ;
break ;
}
z_writeb ( ENISR_RESET , NE_BASE + NE_EN0_ISR ) ; /* Ack intr */
}
/* Grab the 8390 specific header. Similar to the block_input routine, but
* we don ' t need to be concerned with ring wrap as the header will be at
* the start of a page , so we optimize accordingly .
*/
2005-04-17 02:20:36 +04:00
static void zorro8390_get_8390_hdr ( struct net_device * dev ,
2011-06-23 00:39:00 +04:00
struct e8390_pkt_hdr * hdr , int ring_page )
{
int nic_base = dev - > base_addr ;
int cnt ;
short * ptrs ;
/* This *shouldn't* happen.
* If it does , it ' s the last thing you ' ll see
*/
if ( ei_status . dmaing ) {
netdev_err ( dev , " %s: DMAing conflict [DMAstat:%d][irqlock:%d] \n " ,
__func__ , ei_status . dmaing , ei_status . irqlock ) ;
return ;
}
ei_status . dmaing | = 0x01 ;
z_writeb ( E8390_NODMA + E8390_PAGE0 + E8390_START , nic_base + NE_CMD ) ;
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ;
z_writeb ( sizeof ( struct e8390_pkt_hdr ) , nic_base + NE_EN0_RCNTLO ) ;
z_writeb ( 0 , nic_base + NE_EN0_RCNTHI ) ;
z_writeb ( 0 , nic_base + NE_EN0_RSARLO ) ; /* On page boundary */
z_writeb ( ring_page , nic_base + NE_EN0_RSARHI ) ;
z_writeb ( E8390_RREAD + E8390_START , nic_base + NE_CMD ) ;
ptrs = ( short * ) hdr ;
for ( cnt = 0 ; cnt < sizeof ( struct e8390_pkt_hdr ) > > 1 ; cnt + + )
* ptrs + + = z_readw ( NE_BASE + NE_DATAPORT ) ;
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ; /* Ack intr */
hdr - > count = WORDSWAP ( hdr - > count ) ;
ei_status . dmaing & = ~ 0x01 ;
}
/* Block input and output, similar to the Crynwr packet driver.
* If you are porting to a new ethercard , look at the packet driver source
* for hints . The NEx000 doesn ' t share the on - board packet memory - -
* you have to put the packet out through the " remote DMA " dataport
* using z_writeb .
*/
2005-04-17 02:20:36 +04:00
static void zorro8390_block_input ( struct net_device * dev , int count ,
2011-06-23 00:39:00 +04:00
struct sk_buff * skb , int ring_offset )
{
int nic_base = dev - > base_addr ;
char * buf = skb - > data ;
short * ptrs ;
int cnt ;
/* This *shouldn't* happen.
* If it does , it ' s the last thing you ' ll see
*/
if ( ei_status . dmaing ) {
netdev_err ( dev , " %s: DMAing conflict [DMAstat:%d][irqlock:%d] \n " ,
__func__ , ei_status . dmaing , ei_status . irqlock ) ;
return ;
}
ei_status . dmaing | = 0x01 ;
z_writeb ( E8390_NODMA + E8390_PAGE0 + E8390_START , nic_base + NE_CMD ) ;
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ;
z_writeb ( count & 0xff , nic_base + NE_EN0_RCNTLO ) ;
z_writeb ( count > > 8 , nic_base + NE_EN0_RCNTHI ) ;
z_writeb ( ring_offset & 0xff , nic_base + NE_EN0_RSARLO ) ;
z_writeb ( ring_offset > > 8 , nic_base + NE_EN0_RSARHI ) ;
z_writeb ( E8390_RREAD + E8390_START , nic_base + NE_CMD ) ;
ptrs = ( short * ) buf ;
for ( cnt = 0 ; cnt < count > > 1 ; cnt + + )
* ptrs + + = z_readw ( NE_BASE + NE_DATAPORT ) ;
if ( count & 0x01 )
buf [ count - 1 ] = z_readb ( NE_BASE + NE_DATAPORT ) ;
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ; /* Ack intr */
ei_status . dmaing & = ~ 0x01 ;
}
static void zorro8390_block_output ( struct net_device * dev , int count ,
2005-04-17 02:20:36 +04:00
const unsigned char * buf ,
2011-06-23 00:39:00 +04:00
const int start_page )
{
int nic_base = NE_BASE ;
unsigned long dma_start ;
short * ptrs ;
int cnt ;
/* Round the count up for word writes. Do we need to do this?
* What effect will an odd byte count have on the 8390 ?
* I should check someday .
*/
if ( count & 0x01 )
count + + ;
/* This *shouldn't* happen.
* If it does , it ' s the last thing you ' ll see
*/
if ( ei_status . dmaing ) {
netdev_err ( dev , " %s: DMAing conflict [DMAstat:%d][irqlock:%d] \n " ,
__func__ , ei_status . dmaing , ei_status . irqlock ) ;
return ;
}
ei_status . dmaing | = 0x01 ;
/* We should already be in page 0, but to be safe... */
z_writeb ( E8390_PAGE0 + E8390_START + E8390_NODMA , nic_base + NE_CMD ) ;
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ;
/* Now the normal output. */
z_writeb ( count & 0xff , nic_base + NE_EN0_RCNTLO ) ;
z_writeb ( count > > 8 , nic_base + NE_EN0_RCNTHI ) ;
z_writeb ( 0x00 , nic_base + NE_EN0_RSARLO ) ;
z_writeb ( start_page , nic_base + NE_EN0_RSARHI ) ;
z_writeb ( E8390_RWRITE + E8390_START , nic_base + NE_CMD ) ;
ptrs = ( short * ) buf ;
for ( cnt = 0 ; cnt < count > > 1 ; cnt + + )
z_writew ( * ptrs + + , NE_BASE + NE_DATAPORT ) ;
dma_start = jiffies ;
while ( ( z_readb ( NE_BASE + NE_EN0_ISR ) & ENISR_RDC ) = = 0 )
if ( time_after ( jiffies , dma_start + 2 * HZ / 100 ) ) {
/* 20ms */
netdev_err ( dev , " timeout waiting for Tx RDC \n " ) ;
zorro8390_reset_8390 ( dev ) ;
__NS8390_init ( dev , 1 ) ;
break ;
}
z_writeb ( ENISR_RDC , nic_base + NE_EN0_ISR ) ; /* Ack intr */
ei_status . dmaing & = ~ 0x01 ;
}
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
static int zorro8390_open ( struct net_device * dev )
{
__ei_open ( dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
static int zorro8390_close ( struct net_device * dev )
{
if ( ei_debug > 1 )
netdev_dbg ( dev , " Shutting down ethercard \n " ) ;
__ei_close ( dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2012-12-03 18:22:51 +04:00
static void zorro8390_remove_one ( struct zorro_dev * z )
2005-04-17 02:20:36 +04:00
{
2011-06-23 00:39:00 +04:00
struct net_device * dev = zorro_get_drvdata ( z ) ;
unregister_netdev ( dev ) ;
free_irq ( IRQ_AMIGA_PORTS , dev ) ;
release_mem_region ( ZTWO_PADDR ( dev - > base_addr ) , NE_IO_EXTENT * 2 ) ;
2005-04-17 02:20:36 +04:00
free_netdev ( dev ) ;
}
2012-12-03 18:22:51 +04:00
static struct zorro_device_id zorro8390_zorro_tbl [ ] = {
2011-06-23 00:39:00 +04:00
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2 , } ,
{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF , } ,
{ 0 }
} ;
MODULE_DEVICE_TABLE ( zorro , zorro8390_zorro_tbl ) ;
2008-12-04 09:09:30 +03:00
static const struct net_device_ops zorro8390_netdev_ops = {
. ndo_open = zorro8390_open ,
. ndo_stop = zorro8390_close ,
2011-05-12 13:11:38 +04:00
. ndo_start_xmit = __ei_start_xmit ,
. ndo_tx_timeout = __ei_tx_timeout ,
. ndo_get_stats = __ei_get_stats ,
2011-08-16 10:29:01 +04:00
. ndo_set_rx_mode = __ei_set_multicast_list ,
2008-12-04 09:09:30 +03:00
. ndo_validate_addr = eth_validate_addr ,
2011-06-23 00:39:00 +04:00
. ndo_set_mac_address = eth_mac_addr ,
2008-12-04 09:09:30 +03:00
. ndo_change_mtu = eth_change_mtu ,
# ifdef CONFIG_NET_POLL_CONTROLLER
2011-05-12 13:11:38 +04:00
. ndo_poll_controller = __ei_poll ,
2008-12-04 09:09:30 +03:00
# endif
} ;
2012-12-06 18:30:56 +04:00
static int zorro8390_init ( struct net_device * dev , unsigned long board ,
const char * name , unsigned long ioaddr )
2005-04-17 02:20:36 +04:00
{
2011-06-23 00:39:00 +04:00
int i ;
int err ;
unsigned char SA_prom [ 32 ] ;
int start_page , stop_page ;
static u32 zorro8390_offsets [ 16 ] = {
0x00 , 0x02 , 0x04 , 0x06 , 0x08 , 0x0a , 0x0c , 0x0e ,
0x10 , 0x12 , 0x14 , 0x16 , 0x18 , 0x1a , 0x1c , 0x1e ,
2005-04-17 02:20:36 +04:00
} ;
2011-06-23 00:39:00 +04:00
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
unsigned long reset_start_time = jiffies ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
z_writeb ( z_readb ( ioaddr + NE_RESET ) , ioaddr + NE_RESET ) ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
while ( ( z_readb ( ioaddr + NE_EN0_ISR ) & ENISR_RESET ) = = 0 )
if ( time_after ( jiffies ,
reset_start_time + 2 * HZ / 100 ) ) {
netdev_warn ( dev , " not found (no reset ack) \n " ) ;
return - ENODEV ;
}
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
z_writeb ( 0xff , ioaddr + NE_EN0_ISR ) ; /* Ack all intr. */
}
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
/* Read the 16 bytes of station address PROM.
* We must first initialize registers ,
* similar to NS8390_init ( eifdev , 0 ) .
* We can ' t reliably read the SAPROM address without this .
* ( I learned the hard way ! ) .
*/
{
static const struct {
u32 value ;
u32 offset ;
} program_seq [ ] = {
{ E8390_NODMA + E8390_PAGE0 + E8390_STOP , NE_CMD } ,
/* Select page 0 */
{ 0x48 , NE_EN0_DCFG } , /* 0x48: Set byte-wide access */
{ 0x00 , NE_EN0_RCNTLO } , /* Clear the count regs */
{ 0x00 , NE_EN0_RCNTHI } ,
{ 0x00 , NE_EN0_IMR } , /* Mask completion irq */
{ 0xFF , NE_EN0_ISR } ,
{ E8390_RXOFF , NE_EN0_RXCR } , /* 0x20 Set to monitor */
{ E8390_TXOFF , NE_EN0_TXCR } , /* 0x02 and loopback mode */
{ 32 , NE_EN0_RCNTLO } ,
{ 0x00 , NE_EN0_RCNTHI } ,
{ 0x00 , NE_EN0_RSARLO } , /* DMA starting at 0x0000 */
{ 0x00 , NE_EN0_RSARHI } ,
{ E8390_RREAD + E8390_START , NE_CMD } ,
} ;
for ( i = 0 ; i < ARRAY_SIZE ( program_seq ) ; i + + )
z_writeb ( program_seq [ i ] . value ,
ioaddr + program_seq [ i ] . offset ) ;
}
for ( i = 0 ; i < 16 ; i + + ) {
SA_prom [ i ] = z_readb ( ioaddr + NE_DATAPORT ) ;
( void ) z_readb ( ioaddr + NE_DATAPORT ) ;
}
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
/* We must set the 8390 for word mode. */
z_writeb ( 0x49 , ioaddr + NE_EN0_DCFG ) ;
start_page = NESM_START_PG ;
stop_page = NESM_STOP_PG ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
dev - > base_addr = ioaddr ;
dev - > irq = IRQ_AMIGA_PORTS ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
/* Install the Interrupt handler */
i = request_irq ( IRQ_AMIGA_PORTS , __ei_interrupt ,
IRQF_SHARED , DRV_NAME , dev ) ;
if ( i )
return i ;
2005-04-17 02:20:36 +04:00
2011-11-16 13:38:03 +04:00
for ( i = 0 ; i < ETH_ALEN ; i + + )
2011-06-23 00:39:00 +04:00
dev - > dev_addr [ i ] = SA_prom [ i ] ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
pr_debug ( " Found ethernet address: %pM \n " , dev - > dev_addr ) ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
ei_status . name = name ;
ei_status . tx_start_page = start_page ;
ei_status . stop_page = stop_page ;
ei_status . word16 = 1 ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
ei_status . rx_start_page = start_page + TX_PAGES ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
ei_status . reset_8390 = zorro8390_reset_8390 ;
ei_status . block_input = zorro8390_block_input ;
ei_status . block_output = zorro8390_block_output ;
ei_status . get_8390_hdr = zorro8390_get_8390_hdr ;
ei_status . reg_offset = zorro8390_offsets ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
dev - > netdev_ops = & zorro8390_netdev_ops ;
__NS8390_init ( dev , 0 ) ;
err = register_netdev ( dev ) ;
if ( err ) {
free_irq ( IRQ_AMIGA_PORTS , dev ) ;
return err ;
2005-04-17 02:20:36 +04:00
}
2011-06-23 00:39:00 +04:00
netdev_info ( dev , " %s at 0x%08lx, Ethernet Address %pM \n " ,
name , board , dev - > dev_addr ) ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2012-12-03 18:22:51 +04:00
static int zorro8390_init_one ( struct zorro_dev * z ,
2012-12-06 18:30:56 +04:00
const struct zorro_device_id * ent )
2005-04-17 02:20:36 +04:00
{
2011-06-23 00:39:00 +04:00
struct net_device * dev ;
unsigned long board , ioaddr ;
int err , i ;
for ( i = ARRAY_SIZE ( cards ) - 1 ; i > = 0 ; i - - )
if ( z - > id = = cards [ i ] . id )
break ;
if ( i < 0 )
return - ENODEV ;
2005-04-17 02:20:36 +04:00
2011-06-23 00:39:00 +04:00
board = z - > resource . start ;
ioaddr = board + cards [ i ] . offset ;
dev = ____alloc_ei_netdev ( 0 ) ;
if ( ! dev )
return - ENOMEM ;
if ( ! request_mem_region ( ioaddr , NE_IO_EXTENT * 2 , DRV_NAME ) ) {
free_netdev ( dev ) ;
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
2011-06-23 00:39:00 +04:00
err = zorro8390_init ( dev , board , cards [ i ] . name , ZTWO_VADDR ( ioaddr ) ) ;
if ( err ) {
release_mem_region ( ioaddr , NE_IO_EXTENT * 2 ) ;
free_netdev ( dev ) ;
return err ;
}
zorro_set_drvdata ( z , dev ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2011-06-23 00:39:00 +04:00
static struct zorro_driver zorro8390_driver = {
. name = " zorro8390 " ,
. id_table = zorro8390_zorro_tbl ,
. probe = zorro8390_init_one ,
2012-12-03 18:22:51 +04:00
. remove = zorro8390_remove_one ,
2011-06-23 00:39:00 +04:00
} ;
2005-04-17 02:20:36 +04:00
static int __init zorro8390_init_module ( void )
{
2011-06-23 00:39:00 +04:00
return zorro_register_driver ( & zorro8390_driver ) ;
2005-04-17 02:20:36 +04:00
}
static void __exit zorro8390_cleanup_module ( void )
{
2011-06-23 00:39:00 +04:00
zorro_unregister_driver ( & zorro8390_driver ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( zorro8390_init_module ) ;
module_exit ( zorro8390_cleanup_module ) ;
MODULE_LICENSE ( " GPL " ) ;