Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /* sb1000.c: A General Instruments SB1000 driver for linux. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4) 	Written 1998 by Franco Venturi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) 	Copyright 1998 by Franco Venturi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) 	Copyright 1994,1995 by Donald Becker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) 	Copyright 1993 United States Government as represented by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) 	Director, National Security Agency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) 	This driver is for the General Instruments SB1000 (internal SURFboard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 	The author may be reached as fventuri@mediaone.net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 	Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) 	981115 Steven Hirsch <shirsch@adelphia.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 	Linus changed the timer interface.  Should work on all recent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) 	development kernels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) 	980608 Steven Hirsch <shirsch@adelphia.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 	Small changes to make it work with 2.1.x kernels. Hopefully,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 	nothing major will change before official release of Linux 2.2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 	Merged with 2.2 - Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/if_cablemodem.h> /* for SIOGCM/SIOSCM stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <linux/delay.h>	/* for udelay() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #ifdef SB1000_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) static int sb1000_debug = SB1000_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) static const int sb1000_debug = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) static const int SB1000_IO_EXTENT = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) /* SB1000 Maximum Receive Unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) static const int SB1000_MRU = 1500; /* octects */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define NPIDS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) struct sb1000_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	struct sk_buff *rx_skb[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	short rx_dlen[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	unsigned int rx_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	short rx_error_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	short rx_error_dpc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 	unsigned char rx_session_id[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 	unsigned char rx_frame_id[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 	unsigned char rx_pkt_type[NPIDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) /* prototypes for Linux interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) extern int sb1000_probe(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) static int sb1000_open(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) static int sb1000_dev_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) static netdev_tx_t sb1000_start_xmit(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 				     struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) static irqreturn_t sb1000_interrupt(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) static int sb1000_close(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) /* SB1000 hardware routines to be used during open/configuration phases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) static int card_wait_for_busy_clear(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) static int card_wait_for_ready(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) static int card_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	const unsigned char out[], unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) /* SB1000 hardware routines to be used during frame rx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static int sb1000_wait_for_ready(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) static int sb1000_wait_for_ready_clear(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) static void sb1000_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	const unsigned char out[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static void sb1000_read_status(const int ioaddr[], unsigned char in[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) static void sb1000_issue_read_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) /* SB1000 commands for open/configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static int sb1000_reset(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static int sb1000_check_CRC(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static inline int sb1000_start_get_set_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) static int sb1000_end_get_set_command(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) static int sb1000_activate(const int ioaddr[], const char* name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) static int sb1000_get_firmware_version(const int ioaddr[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	const char* name, unsigned char version[], int do_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) static int sb1000_get_frequency(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	int* frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) static int sb1000_set_frequency(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	int frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) static int sb1000_get_PIDs(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	short PID[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) static int sb1000_set_PIDs(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	const short PID[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) /* SB1000 commands for frame rx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) static int sb1000_rx(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) static void sb1000_error_dpc(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) static const struct pnp_device_id sb1000_pnp_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	{ "GIC1000", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	{ "", 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static const struct net_device_ops sb1000_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	.ndo_open		= sb1000_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	.ndo_start_xmit		= sb1000_start_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	.ndo_do_ioctl		= sb1000_dev_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	.ndo_stop		= sb1000_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	.ndo_set_mac_address 	= eth_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	.ndo_validate_addr	= eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	unsigned short ioaddr[2], irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	unsigned int serial_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	int error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	if (pnp_device_attach(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	if (pnp_activate_dev(pdev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		goto out_detach;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	if (!pnp_irq_valid(pdev, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 		goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	serial_number = pdev->card->serial;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	ioaddr[0] = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	ioaddr[1] = pnp_port_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	irq = pnp_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	if (!request_region(ioaddr[0], 16, "sb1000"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 		goto out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	if (!request_region(ioaddr[1], 16, "sb1000"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 		goto out_release_region0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	dev = alloc_etherdev(sizeof(struct sb1000_private));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		goto out_release_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	dev->base_addr = ioaddr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	dev->mem_start = ioaddr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	dev->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	if (sb1000_debug > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 		printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 			"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 			dev->mem_start, serial_number, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	 * The SB1000 is an rx-only cable modem device.  The uplink is a modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	 * and we do not want to arp on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	dev->flags = IFF_POINTOPOINT|IFF_NOARP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	SET_NETDEV_DEV(dev, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	if (sb1000_debug > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 		printk(KERN_NOTICE "%s", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	dev->netdev_ops	= &sb1000_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	/* hardware address is 0:0:serial_number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	dev->dev_addr[2]	= serial_number >> 24 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	dev->dev_addr[3]	= serial_number >> 16 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	dev->dev_addr[4]	= serial_number >>  8 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	dev->dev_addr[5]	= serial_number >>  0 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	pnp_set_drvdata(pdev, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	error = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 		goto out_free_netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217)  out_free_netdev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219)  out_release_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	release_region(ioaddr[1], 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221)  out_release_region0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	release_region(ioaddr[0], 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223)  out_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	pnp_disable_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225)  out_detach:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	pnp_device_detach(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) sb1000_remove_one(struct pnp_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	struct net_device *dev = pnp_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	release_region(dev->base_addr, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	release_region(dev->mem_start, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) static struct pnp_driver sb1000_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	.name		= "sb1000",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	.id_table	= sb1000_pnp_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	.probe		= sb1000_probe_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	.remove		= sb1000_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)  * SB1000 hardware routines to be used during open/configuration phases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) static const int TimeOutJiffies = (875 * HZ) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) /* Card Wait For Busy Clear (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) card_wait_for_busy_clear(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	unsigned char a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	a = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	timeout = jiffies + TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	while (a & 0x80 || a & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 		/* a little sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		yield();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		a = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 			printk(KERN_WARNING "%s: card_wait_for_busy_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) /* Card Wait For Ready (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	unsigned char a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	a = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	timeout = jiffies + TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	while (a & 0x80 || !(a & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		/* a little sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		yield();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		a = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 			printk(KERN_WARNING "%s: card_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	in[1] = inb(ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	in[2] = inb(ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	in[3] = inb(ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	in[4] = inb(ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	in[0] = inb(ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	in[6] = inb(ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	in[5] = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) /* Card Send Command (cannot be used during an interrupt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) card_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	const unsigned char out[], unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	if ((status = card_wait_for_busy_clear(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	outb(out[2], ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	outb(out[3], ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	outb(out[4], ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	outb(out[5], ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	outb(out[1], ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	outb(out[0], ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	if (out[0] != 0x20 && out[0] != 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		if ((status = card_wait_for_ready(ioaddr, name, in)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			printk(KERN_DEBUG "%s: card_send_command "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 				"out: %02x%02x%02x%02x%02x%02x  "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 				"in: %02x%02x%02x%02x%02x%02x%02x\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 				out[0], out[1], out[2], out[3], out[4], out[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 				in[0], in[1], in[2], in[3], in[4], in[5], in[6]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 			printk(KERN_DEBUG "%s: card_send_command "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 				"out: %02x%02x%02x%02x%02x%02x\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 				out[0], out[1], out[2], out[3], out[4], out[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	if (out[1] != 0x1b) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		if (out[0] >= 0x80 && in[0] != (out[1] | 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353)  * SB1000 hardware routines to be used during frame rx interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) static const int Sb1000TimeOutJiffies = 7 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) /* Card Wait For Ready (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) sb1000_wait_for_ready(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	while (inb(ioaddr[1] + 6) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 			printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	while (!(inb(ioaddr[1] + 6) & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) /* Card Wait For Ready Clear (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) sb1000_wait_for_ready_clear(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 	while (inb(ioaddr[1] + 6) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 			printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	timeout = jiffies + Sb1000TimeOutJiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	while (inb(ioaddr[1] + 6) & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		if (time_after_eq(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 			printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 				name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 			return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) /* Card Send Command (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) sb1000_send_command(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	const unsigned char out[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	outb(out[2], ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	outb(out[3], ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	outb(out[4], ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	outb(out[5], ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	outb(out[1], ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	outb(out[0], ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		printk(KERN_DEBUG "%s: sb1000_send_command out: %02x%02x%02x%02x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 			"%02x%02x\n", name, out[0], out[1], out[2], out[3], out[4], out[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) /* Card Read Status (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) sb1000_read_status(const int ioaddr[], unsigned char in[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	in[1] = inb(ioaddr[0] + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	in[2] = inb(ioaddr[0] + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	in[3] = inb(ioaddr[0] + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	in[4] = inb(ioaddr[0] + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	in[0] = inb(ioaddr[0] + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) /* Issue Read Command (to be used during frame rx) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) sb1000_issue_read_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	static const unsigned char Command0[6] = {0x20, 0x00, 0x00, 0x01, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	outb(0xa0, ioaddr[0] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448)  * SB1000 commands for open/configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) /* reset SB1000 card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) sb1000_reset(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	static const unsigned char Command0[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	int port, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	port = ioaddr[1] + 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	outb(0x4, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	outb(0x0, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	outb(0x4, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	outb(0x0, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	udelay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	if (st[3] != 0xf0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) /* check SB1000 firmware CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) sb1000_check_CRC(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	static const unsigned char Command0[6] = {0x80, 0x1f, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	/* check CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	if (st[1] != st[3] || st[2] != st[4])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) sb1000_start_get_set_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	static const unsigned char Command0[6] = {0x80, 0x1b, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	return card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) sb1000_end_get_set_command(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	static const unsigned char Command0[6] = {0x80, 0x1b, 0x02, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	static const unsigned char Command1[6] = {0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	return card_send_command(ioaddr, name, Command1, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) sb1000_activate(const int ioaddr[], const char* name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	static const unsigned char Command0[6] = {0x80, 0x11, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	static const unsigned char Command1[6] = {0x80, 0x16, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	status = card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	status = card_send_command(ioaddr, name, Command1, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	if (st[3] != 0xf1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		status = sb1000_start_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	return sb1000_start_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) /* get SB1000 firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) sb1000_get_firmware_version(const int ioaddr[], const char* name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	unsigned char version[], int do_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	static const unsigned char Command0[6] = {0x80, 0x23, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	if (st[0] != 0xa3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	version[0] = st[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	version[1] = st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	if (do_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) /* get SB1000 frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	static const unsigned char Command0[6] = {0x80, 0x44, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	*frequency = ((st[1] << 8 | st[2]) << 8 | st[3]) << 8 | st[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) /* set SB1000 frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	unsigned char Command0[6] = {0x80, 0x29, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	const int FrequencyLowerLimit = 57000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	const int FrequencyUpperLimit = 804000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	if (frequency < FrequencyLowerLimit || frequency > FrequencyUpperLimit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		printk(KERN_ERR "%s: frequency chosen (%d kHz) is not in the range "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 			"[%d,%d] kHz\n", name, frequency, FrequencyLowerLimit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 			FrequencyUpperLimit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	Command0[5] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	Command0[4] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	Command0[3] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	frequency >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	Command0[2] = frequency & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	return card_send_command(ioaddr, name, Command0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) /* get SB1000 PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	static const unsigned char Command0[6] = {0x80, 0x40, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	static const unsigned char Command1[6] = {0x80, 0x41, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	static const unsigned char Command2[6] = {0x80, 0x42, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	static const unsigned char Command3[6] = {0x80, 0x43, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	PID[0] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	if ((status = card_send_command(ioaddr, name, Command1, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	PID[1] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	if ((status = card_send_command(ioaddr, name, Command2, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	PID[2] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	if ((status = card_send_command(ioaddr, name, Command3, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	PID[3] = st[1] << 8 | st[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) /* set SB1000 PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	static const unsigned char Command4[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	unsigned char st[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	short p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	unsigned char Command0[6] = {0x80, 0x31, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	unsigned char Command1[6] = {0x80, 0x32, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	unsigned char Command2[6] = {0x80, 0x33, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	unsigned char Command3[6] = {0x80, 0x34, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	if ((status = sb1000_start_get_set_command(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	p = PID[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	Command0[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	Command0[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	if ((status = card_send_command(ioaddr, name, Command0, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	p = PID[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	Command1[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	Command1[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	if ((status = card_send_command(ioaddr, name, Command1, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	p = PID[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	Command2[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	Command2[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	if ((status = card_send_command(ioaddr, name, Command2, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	p = PID[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	Command3[3] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	p >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	Command3[2] = p & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	if ((status = card_send_command(ioaddr, name, Command3, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	if ((status = card_send_command(ioaddr, name, Command4, st)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	return sb1000_end_get_set_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) sb1000_print_status_buffer(const char* name, unsigned char st[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	unsigned char buffer[], int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	int i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	printk(KERN_DEBUG "%s: status: %02x %02x\n", name, st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	if (buffer[24] == 0x08 && buffer[25] == 0x00 && buffer[26] == 0x45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		printk(KERN_DEBUG "%s: length: %d protocol: %d from: %d.%d.%d.%d:%d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 			"to %d.%d.%d.%d:%d\n", name, buffer[28] << 8 | buffer[29],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 			buffer[35], buffer[38], buffer[39], buffer[40], buffer[41],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717)             buffer[46] << 8 | buffer[47],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			buffer[42], buffer[43], buffer[44], buffer[45],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719)             buffer[48] << 8 | buffer[49]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		for (i = 0, k = 0; i < (size + 7) / 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 			printk(KERN_DEBUG "%s: %s", name, i ? "       " : "buffer:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 			for (j = 0; j < 8 && k < size; j++, k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 				printk(" %02x", buffer[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 			printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731)  * SB1000 commands for frame rx interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) /* receive a single frame and assemble datagram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734)  * (this is the heart of the interrupt routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) sb1000_rx(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) #define FRAMESIZE 184
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	unsigned char st[2], buffer[FRAMESIZE], session_id, frame_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	short dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	int ioaddr, ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	unsigned int skbsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	struct net_device_stats *stats = &dev->stats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	/* SB1000 frame constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	const int FrameSize = FRAMESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	const int NewDatagramHeaderSkip = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	const int NewDatagramHeaderSize = NewDatagramHeaderSkip + 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	const int NewDatagramDataSize = FrameSize - NewDatagramHeaderSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	const int ContDatagramHeaderSkip = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	const int ContDatagramHeaderSize = ContDatagramHeaderSkip + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	const int ContDatagramDataSize = FrameSize - ContDatagramHeaderSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	const int TrailerSize = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	insw(ioaddr, (unsigned short*) st, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) #ifdef XXXDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) printk("cm0: received: %02x %02x\n", st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) #endif /* XXXDEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	lp->rx_frames++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	/* decide if it is a good or bad frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	for (ns = 0; ns < NPIDS; ns++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		session_id = lp->rx_session_id[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		frame_id = lp->rx_frame_id[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 		if (st[0] == session_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 			if (st[1] == frame_id || (!frame_id && (st[1] & 0xf0) == 0x30)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 				goto good_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 			} else if ((st[1] & 0xf0) == 0x30 && (st[0] & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 				goto skipped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 				goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		} else if (st[0] == (session_id | 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			if ((st[1] & 0xf0) == 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 				goto skipped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 				goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	goto bad_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) skipped_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	stats->rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	skb = lp->rx_skb[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		printk(KERN_WARNING "%s: missing frame(s): got %02x %02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			"expecting %02x %02x\n", dev->name, st[0], st[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 			skb ? session_id : session_id | 0x40, frame_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) good_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	lp->rx_frame_id[ns] = 0x30 | ((st[1] + 1) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	/* new datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	if (st[0] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		/* get data length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		insw(ioaddr, buffer, NewDatagramHeaderSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) #ifdef XXXDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) printk("cm0: IP identification: %02x%02x  fragment offset: %02x%02x\n", buffer[30], buffer[31], buffer[32], buffer[33]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) #endif /* XXXDEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		if (buffer[0] != NewDatagramHeaderSkip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 				printk(KERN_WARNING "%s: new datagram header skip error: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 					"got %02x expecting %02x\n", dev->name, buffer[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 					NewDatagramHeaderSkip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 			insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 			goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		dlen = ((buffer[NewDatagramHeaderSkip + 3] & 0x0f) << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			buffer[NewDatagramHeaderSkip + 4]) - 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		if (dlen > SB1000_MRU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 			if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 				printk(KERN_WARNING "%s: datagram length (%d) greater "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 					"than MRU (%d)\n", dev->name, dlen, SB1000_MRU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 			stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 			goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		lp->rx_dlen[ns] = dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		/* compute size to allocate for datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		skbsize = dlen + FrameSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		if ((skb = alloc_skb(skbsize, GFP_ATOMIC)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 				printk(KERN_WARNING "%s: can't allocate %d bytes long "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 					"skbuff\n", dev->name, skbsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 			stats->rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 			insw(ioaddr, buffer, NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 			goto dropped_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		skb->protocol = (unsigned short) buffer[NewDatagramHeaderSkip + 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		insw(ioaddr, skb_put(skb, NewDatagramDataSize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 			NewDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		lp->rx_skb[ns] = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		/* continuation of previous datagram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		insw(ioaddr, buffer, ContDatagramHeaderSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		if (buffer[0] != ContDatagramHeaderSkip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 			if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 				printk(KERN_WARNING "%s: cont datagram header skip error: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 					"got %02x expecting %02x\n", dev->name, buffer[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 					ContDatagramHeaderSkip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 			stats->rx_length_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			insw(ioaddr, buffer, ContDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			goto bad_frame_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		skb = lp->rx_skb[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		insw(ioaddr, skb_put(skb, ContDatagramDataSize),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 			ContDatagramDataSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		dlen = lp->rx_dlen[ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	if (skb->len < dlen + TrailerSize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		lp->rx_session_id[ns] &= ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	/* datagram completed: send to upper level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	skb_trim(skb, dlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	stats->rx_bytes+=dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	stats->rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	lp->rx_skb[ns] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 	lp->rx_session_id[ns] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) bad_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	insw(ioaddr, buffer, FrameSize / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	if (sb1000_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		printk(KERN_WARNING "%s: frame error: got %02x %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 			dev->name, st[0], st[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	stats->rx_frame_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) bad_frame_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		sb1000_print_status_buffer(dev->name, st, buffer, FrameSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) dropped_frame:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	stats->rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	if (ns < NPIDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		if ((skb = lp->rx_skb[ns])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 			lp->rx_skb[ns] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		lp->rx_session_id[ns] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) sb1000_error_dpc(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	static const unsigned char Command0[6] = {0x80, 0x26, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	unsigned char st[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	const int ErrorDpcCounterInitialize = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	sb1000_read_status(ioaddr, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	if (st[1] & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		lp->rx_error_dpc_count = ErrorDpcCounterInitialize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)  * Linux interface functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) sb1000_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	int ioaddr[2], status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	const unsigned short FirmwareVersion[] = {0x01, 0x01};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	/* initialize sb1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	if ((status = sb1000_reset(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	if ((status = sb1000_check_CRC(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	/* initialize private data before board can catch interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	lp->rx_skb[0] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	lp->rx_skb[1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	lp->rx_skb[2] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	lp->rx_skb[3] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	lp->rx_dlen[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	lp->rx_dlen[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	lp->rx_dlen[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	lp->rx_dlen[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	lp->rx_frames = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	lp->rx_error_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	lp->rx_error_dpc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	lp->rx_session_id[0] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	lp->rx_session_id[1] = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	lp->rx_session_id[2] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	lp->rx_session_id[3] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	lp->rx_frame_id[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	lp->rx_frame_id[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	lp->rx_frame_id[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	lp->rx_frame_id[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	if (request_irq(dev->irq, sb1000_interrupt, 0, "sb1000", dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		printk(KERN_DEBUG "%s: Opening, IRQ %d\n", name, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	/* Activate board and check firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	if ((status = sb1000_activate(ioaddr, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	udelay(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	if ((status = sb1000_get_firmware_version(ioaddr, name, version, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	if (version[0] != FirmwareVersion[0] || version[1] != FirmwareVersion[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		printk(KERN_WARNING "%s: found firmware version %x.%02x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 			"(should be %x.%02x)\n", name, version[0], version[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			FirmwareVersion[0], FirmwareVersion[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	return 0;					/* Always succeed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) static int sb1000_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	char* name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	unsigned char version[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	short PID[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	int ioaddr[2], status, frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	unsigned int stats[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	if (!(dev && dev->flags & IFF_UP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	case SIOCGCMSTATS:		/* get statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		stats[0] = dev->stats.rx_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		stats[1] = lp->rx_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		stats[2] = dev->stats.rx_packets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		stats[3] = dev->stats.rx_errors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		stats[4] = dev->stats.rx_dropped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		if(copy_to_user(ifr->ifr_data, stats, sizeof(stats)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 		status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	case SIOCGCMFIRMWARE:		/* get firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		if ((status = sb1000_get_firmware_version(ioaddr, name, version, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 		if(copy_to_user(ifr->ifr_data, version, sizeof(version)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	case SIOCGCMFREQUENCY:		/* get frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		if ((status = sb1000_get_frequency(ioaddr, name, &frequency)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		if(put_user(frequency, (int __user *) ifr->ifr_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	case SIOCSCMFREQUENCY:		/* set frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 			return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		if(get_user(frequency, (int __user *) ifr->ifr_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		if ((status = sb1000_set_frequency(ioaddr, name, frequency)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	case SIOCGCMPIDS:			/* get PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		if ((status = sb1000_get_PIDs(ioaddr, name, PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 		if(copy_to_user(ifr->ifr_data, PID, sizeof(PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	case SIOCSCMPIDS:			/* set PIDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		if (!capable(CAP_NET_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 			return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 		if(copy_from_user(PID, ifr->ifr_data, sizeof(PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		if ((status = sb1000_set_PIDs(ioaddr, name, PID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 			return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		/* set session_id, frame_id and pkt_type too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		lp->rx_session_id[0] = 0x50 | (PID[0] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		lp->rx_session_id[1] = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		lp->rx_session_id[2] = 0x44;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 		lp->rx_session_id[3] = 0x42;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		lp->rx_frame_id[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		lp->rx_frame_id[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		lp->rx_frame_id[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		lp->rx_frame_id[3] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* transmit function: do nothing since SB1000 can't send anything out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static netdev_tx_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) sb1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	printk(KERN_WARNING "%s: trying to transmit!!!\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	/* sb1000 can't xmit datagrams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* SB1000 interrupt handler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) static irqreturn_t sb1000_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	static const unsigned char Command0[6] = {0x80, 0x2c, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	static const unsigned char Command1[6] = {0x80, 0x2e, 0x00, 0x00, 0x00, 0x00};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	unsigned char st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	struct net_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	const int MaxRxErrorCount = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	name = dev->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	/* is it a good interrupt? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	st = inb(ioaddr[1] + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	if (!(st & 0x08 && st & 0x20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	if (sb1000_debug > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		printk(KERN_DEBUG "%s: entering interrupt\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	st = inb(ioaddr[0] + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	if (sb1000_rx(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		lp->rx_error_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) #ifdef SB1000_DELAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	udelay(SB1000_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) #endif /* SB1000_DELAY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	if (st & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		sb1000_error_dpc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	if (lp->rx_error_dpc_count && !(--lp->rx_error_dpc_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		sb1000_send_command(ioaddr, name, Command0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	if (lp->rx_error_count >= MaxRxErrorCount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		sb1000_wait_for_ready_clear(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 		sb1000_send_command(ioaddr, name, Command1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		sb1000_wait_for_ready(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		sb1000_issue_read_command(ioaddr, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		lp->rx_error_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static int sb1000_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	int ioaddr[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	struct sb1000_private *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	if (sb1000_debug > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		printk(KERN_DEBUG "%s: Shutting down sb1000.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	ioaddr[0] = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	/* mem_start holds the second I/O address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	ioaddr[1] = dev->mem_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	/* If we don't do this, we can't re-insmod it later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	release_region(ioaddr[1], SB1000_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	release_region(ioaddr[0], SB1000_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	/* free rx_skb's if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	for (i=0; i<4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 		if (lp->rx_skb[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 			dev_kfree_skb(lp->rx_skb[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) MODULE_AUTHOR("Franco Venturi <fventuri@mediaone.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) MODULE_DESCRIPTION("General Instruments SB1000 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) module_pnp_driver(sb1000_driver);