/* sb1000.c: A General Instruments SB1000 driver for linux. */
/*
Written 1998 by Franco Venturi.
Copyright 1998 by Franco Venturi.
Copyright 1994,1995 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
This driver is for the General Instruments SB1000 (internal SURFboard)
The author may be reached as fventuri@mediaone.net
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU General
Public License as published by the Free Software
Foundation; either version 2 of the License, or (at
your option) any later version.
Changes:
981115 Steven Hirsch <shirsch@adelphia.net>
Linus changed the timer interface. Should work on all recent
development kernels.
980608 Steven Hirsch <shirsch@adelphia.net>
Small changes to make it work with 2.1.x kernels. Hopefully,
nothing major will change before official release of Linux 2.2.
Merged with 2.2 - Alan Cox
*/
static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/if_cablemodem.h> /* for SIOGCM/SIOSCM stuff */
#include <linux/in.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/delay.h> /* for udelay() */
#include <linux/etherdevice.h>
#include <linux/pnp.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#ifdef SB1000_DEBUG
static int sb1000_debug = SB1000_DEBUG;
#else
static const int sb1000_debug = 1;
#endif
static const int SB1000_IO_EXTENT = 8;
/* SB1000 Maximum Receive Unit */
static const int SB1000_MRU = 1500; /* octects */
#define NPIDS 4
struct sb1000_private {
struct sk_buff *rx_skb[NPIDS];
short rx_dlen[NPIDS];
unsigned int rx_frames;
short rx_error_count;
short rx_error_dpc_count;
unsigned char rx_session_id[NPIDS];
unsigned char rx_frame_id[NPIDS];
unsigned char rx_pkt_type[NPIDS];
};
/* prototypes for Linux interface */
extern int sb1000_probe(struct net_device *dev);
static int sb1000_open(struct net_device *dev);
static int sb1000_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
static netdev_tx_t sb1000_start_xmit(struct sk_buff *skb,
struct net_device *dev);
static irqreturn_t sb1000_interrupt(int irq, void *dev_id);
static int sb1000_close(struct net_device *dev);
/* SB1000 hardware routines to be used during open/configuration phases */
static int card_wait_for_busy_clear(const int ioaddr[],
const char* name);
static int card_wait_for_ready(const int ioaddr[], const char* name,
unsigned char in[]);
static int card_send_command(const int ioaddr[], const char* name,
const unsigned char out[], unsigned char in[]);
/* SB1000 hardware routines to be used during frame rx interrupt */
static int sb1000_wait_for_ready(const int ioaddr[], const char* name);
static int sb1000_wait_for_ready_clear(const int ioaddr[],
const char* name);
static void sb1000_send_command(const int ioaddr[], const char* name,
const unsigned char out[]);
static void sb1000_read_status(const int ioaddr[], unsigned char in[]);
static void sb1000_issue_read_command(const int ioaddr[],
const char* name);
/* SB1000 commands for open/configuration */
static int sb1000_reset(const int ioadd