/title>
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/apne.c
blob: c12cbdf368b1edbe37b3077e9debdcf4f93cc847 (plain) (tree)





































                                                                               
                          


















































                                                                                                        
                                                         










































                                                                     
 
                                                      
 












                                                    























































                                                                 
                         
 










                                                                        
                                                                       




























                                                                             
                                                       












                                                                           
                                                                             




                                                                        
 










































                                                                              
                               

                                       
                                                                          

                    
                                       
                                      
 


                                                   




























































                                                                                
                                                               


















































































































































                                                                                         
                                                                          










                                                                       
                                                        














                                                                                                 
                              







                                        
                            






                                         
                                


























































                                                                   
/*
 * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
 *
 * (C) Copyright 1997 Alain Malek
 *                    (Alain.Malek@cryogen.com)
 *
 * ----------------------------------------------------------------------------
 *
 * This program is based on
 *
 * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
 *             Written 1992-94 by Donald Becker.
 *
 * 8390.c:     A general NS8390 ethernet driver core for linux.
 *             Written 1992-94 by Donald Becker.
 *
 * cnetdevice: A Sana-II ethernet driver for AmigaOS
 *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
 *
 * ----------------------------------------------------------------------------
 *
 * 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.
 *
 * ----------------------------------------------------------------------------
 *
 */


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/jiffies.h>

#include <asm/system.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
#include <asm/amigayle.h>
#include <asm/amipcmcia.h>

#include "8390.h"

/* ---- No user-serviceable parts below ---- */

#define DRV_NAME "apne"

#define NE_BASE	 (dev->base_addr)
#define NE_CMD	 		0x00
#define NE_DATAPORT		0x10            /* NatSemi-defined port window offset. */
#define NE_RESET		0x1f            /* Issue a read to reset, a write to clear. */
#define NE_IO_EXTENT	        0x20

#define NE_EN0_ISR		0x07
#define NE_EN0_DCFG		0x0e

#define NE_EN0_RSARLO	        0x08
#define NE_EN0_RSARHI	        0x09
#define NE_EN0_RCNTLO	        0x0a
#define NE_EN0_RXCR		0x0c
#define NE_EN0_TXCR		0x0d
#define NE_EN0_RCNTHI	        0x0b
#define NE_EN0_IMR		0x0f

#define NE1SM_START_PG	0x20	/* First page of TX buffer */
#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
#define NESM_START_PG	0x40	/* First page of TX buffer */
#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */


struct net_device * __init apne_probe(int unit);
static int apne_probe1(struct net_device *dev, int ioaddr);

static int apne_open(struct net_device *dev);
static int apne_close(struct net_device *dev);

static void apne_reset_8390(struct net_device *dev);
static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
			  int ring_page);
static void apne_block_input(struct net_device *dev, int count,
								struct sk_buff *skb, int ring_offset);
static void apne_block_output(struct net_device *dev, const int count,
							const unsigned char *buf, const int start_page);
static irqreturn_t apne_interrupt(int irq, void *dev_id);

static int init_pcmcia(void);

/* IO base address used for nic */

#define IOBASE 0x300

/*
   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
   you can find the values to use by looking at the cnet.device
   config file example (the default values are for the CNET40BC card)
*/

/*
#define MANUAL_CONFIG 0x20
#define MANUAL_OFFSET 0x3f8

#define MANUAL_HWADDR0 0x00
#define MANUAL_HWADDR1 0x12
#define MANUAL_HWADDR2 0x34
#define MANUAL_HWADDR3 0x56
#define MANUAL_HWADDR4 0x78
#define MANUAL_HWADDR5 0x9a
*/

static const char version[] =
    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";

static int apne_owned;	/* signal if card already owned */

struct net_device * __init apne_probe(int unit)
{
	struct net_device *dev;
#ifndef MANUAL_CONFIG
	char tuple[8];
#endif
	int err;

	if (apne_owned)
		return ERR_PTR(-ENODEV);

	if ( !(AMIGAHW_PRESENT(PCMCIA)) )
		return ERR_PTR(-ENODEV);

	printk("Looking for PCMCIA ethernet card : ");

	/* check if a card is inserted */
	if (!(PCMCIA_INSERTED)) {
		printk("NO PCMCIA card inserted\n");
		return ERR_PTR(-ENODEV);
	}

	dev = alloc_ei_netdev();
	if (!dev)
		return ERR_PTR(-ENOMEM);
	if (unit >= 0) {
		sprintf(dev->name, "eth%d", unit);
		netdev_boot_setup_check(dev);
	}

	/* disable pcmcia irq for readtuple */
	pcmcia_disable_irq();

#ifndef MANUAL_CONFIG
	if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
		(tuple[2] != CISTPL_FUNCID_NETWORK)) {
		printk("not an ethernet card\n");
		/* XXX: shouldn't we re-enable irq here? */
		free_netdev(dev);
		return ERR_PTR(-ENODEV);
	}
#endif

	printk("ethernet PCMCIA card inserted\n");

	if (!init_pcmcia()) {
		/* XXX: shouldn't we re-enable irq here? */
		free_netdev(dev);
		return ERR_PTR(-ENODEV);
	}

	if (!request_region(IOBASE, 0x20, DRV_NAME)) {
		free_netdev(dev);
		return ERR_PTR(-EBUSY);
	}

	err = apne_probe1(dev, IOBASE);
	if (err) {
		release_region(IOBASE, 0x20);
		free_netdev(dev);
		return ERR_PTR(err);
	}
	err = register_netdev(dev);
	if (!err)
		return dev;

	pcmcia_disable_irq();
	free_irq(IRQ_AMIGA_PORTS, dev);
	pcmcia_reset();
	release_region(IOBASE, 0x20);
	free_netdev(dev);
	return ERR_PTR(err);
}

static int __init apne_probe1(struct net_device *dev, int ioaddr)
{
    int i;
    unsigned char SA_prom[32];
    int wordlength = 2;
    const char *name = NULL;
    int start_page, stop_page;
#ifndef MANUAL_HWADDR0
    int neX000, ctron;
#endif
    static unsigned version_printed;
    DECLARE_MAC_BUF(mac);

    if (ei_debug  &&  version_printed++ == 0)
	printk(version);

    printk("PCMCIA NE*000 ethercard probe");

    /* Reset card. Who knows what dain-bramaged state it was left in. */
    {	unsigned long reset_start_time = jiffies;

	outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);

	while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)