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) /*      cops.c: LocalTalk driver for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *	Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *      - Jay Schulist <jschlst@samba.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *	With more than a little help from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *	- Alan Cox <alan@lxorguk.ukuu.org.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *      Derived from:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *      - skeleton.c: A network driver outline for linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *        Written 1993-94 by Donald Becker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *	- ltpc.c: A driver for the LocalTalk PC card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *	  Written by Bradford W. Johnson.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *      Copyright 1993 United States Government as represented by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *      Director, National Security Agency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  *      This software may be used and distributed according to the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  *      of the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  *	Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  *	19970608	Alan Cox	Allowed dual card type support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)  *					Can set board type in insmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)  *					Hooks for cops_setup routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)  *					(not yet implemented).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)  *	19971101	Jay Schulist	Fixes for multiple lt* devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)  *	19980607	Steven Hirsch	Fixed the badly broken support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)  *					for Tangent type cards. Only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)  *                                      tested on Daystar LT200. Some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)  *                                      cleanup of formatting and program
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)  *                                      logic.  Added emacs 'local-vars'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)  *                                      setup for Jay's brace style.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33)  *	20000211	Alan Cox	Cleaned up for softnet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) static const char *version =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) "cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39)  *  Sources:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40)  *      COPS Localtalk SDK. This provides almost all of the information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41)  *      needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45)  * insmod/modprobe configurable stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46)  *	- IO Port, choose one your card supports or 0 if you dare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47)  *	- IRQ, also choose one your card supports or nothing and let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  *	  the driver figure it out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #include <linux/if_ltalk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #include <linux/delay.h>	/* For udelay() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #include <linux/atalk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #include <net/Space.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #include "cops.h"		/* Our Stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #include "cops_ltdrv.h"		/* Firmware code for Tangent type cards. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #include "cops_ffdrv.h"		/* Firmware code for Dayna type cards. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83)  *      The name of the card. Is used for messages and in the requests for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84)  *      io regions, irqs and dma channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static const char *cardname = "cops";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #ifdef CONFIG_COPS_DAYNA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) static int board_type = DAYNA;	/* Module exported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) static int board_type = TANGENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) static int io = 0x240;		/* Default IO for Dayna */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static int irq = 5;		/* Default IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  *	COPS Autoprobe information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  *	Right now if port address is right but IRQ is not 5 this will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  *      return a 5 no matter what since we will still get a status response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  *      Need one more additional check to narrow down after we have gotten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  *      the ioaddr. But since only other possible IRQs is 3 and 4 so no real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  *	hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  *	this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  * 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  *	This driver has 2 modes and they are: Dayna mode and Tangent mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108)  *	Each mode corresponds with the type of card. It has been found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109)  *	that there are 2 main types of cards and all other cards are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110)  *	the same and just have different names or only have minor differences
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  *	such as more IO ports. As this driver is tested it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  *	become more clear on exactly what cards are supported. The driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113)  *	defaults to using Dayna mode. To change the drivers mode, simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114)  *	select Dayna or Tangent mode when configuring the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116)  *      This driver should support:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  *      TANGENT driver mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  *              Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  *		COPS LT-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  *      DAYNA driver mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  *              Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122)  *		Farallon PhoneNET PC III, Farallon PhoneNET PC II
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  *	Other cards possibly supported mode unknown though:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  *		Dayna DL2000 (Full length), COPS LT/M (Micro-Channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  *	Cards NOT supported by this driver but supported by the ltpc.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  *	driver written by Bradford W. Johnson <johns393@maroon.tc.umn.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  *		Farallon PhoneNET PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  *		Original Apple LocalTalk PC card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130)  * 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131)  *      N.B.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  *      The Daystar Digital LT200 boards do not support interrupt-driven
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  *      IO.  You must specify 'irq=0xff' as a module parameter to invoke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135)  *      polled mode.  I also believe that the port probing logic is quite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136)  *      dangerous at best and certainly hopeless for a polled card.  Best to 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)  *      specify both. - Steve H.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142)  * Zero terminated list of IO ports to probe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) static unsigned int ports[] = { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * Zero terminated list of IRQ ports to probe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) static int cops_irqlist[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	5, 4, 3, 0 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) static struct timer_list cops_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) static struct net_device *cops_timer_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) /* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) #ifndef COPS_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) #define COPS_DEBUG 1 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) static unsigned int cops_debug = COPS_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) /* The number of low I/O ports used by the card. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) #define COPS_IO_EXTENT       8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) /* Information that needs to be kept for each board. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) struct cops_local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)         int board;			/* Holds what board type is. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	int nodeid;			/* Set to 1 once have nodeid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)         unsigned char node_acquire;	/* Node ID when acquired. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)         struct atalk_addr node_addr;	/* Full node address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	spinlock_t lock;		/* RX/TX lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) /* Index to functions, as function prototypes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) static int  cops_probe1 (struct net_device *dev, int ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) static int  cops_irq (int ioaddr, int board);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) static int  cops_open (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) static int  cops_jumpstart (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) static void cops_reset (struct net_device *dev, int sleep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) static void cops_load (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) static int  cops_nodeid (struct net_device *dev, int nodeid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) static irqreturn_t cops_interrupt (int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) static void cops_poll(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) static void cops_timeout(struct net_device *dev, unsigned int txqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) static void cops_rx (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) static netdev_tx_t  cops_send_packet (struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 					    struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) static void set_multicast_list (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) static int  cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) static int  cops_close (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) static void cleanup_card(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	if (dev->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	release_region(dev->base_addr, COPS_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210)  *      Check for a network adaptor of this type, and return '0' iff one exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211)  *      If dev->base_addr == 0, probe all likely locations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212)  *      If dev->base_addr in [1..0x1ff], always return failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213)  *        otherwise go with what we pass in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) struct net_device * __init cops_probe(int unit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	unsigned *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	int base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	dev = alloc_ltalkdev(sizeof(struct cops_local));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	if (unit >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 		sprintf(dev->name, "lt%d", unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		netdev_boot_setup_check(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		irq = dev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		base_addr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 		base_addr = dev->base_addr = io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	if (base_addr > 0x1ff) {    /* Check a single specified location. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		err = cops_probe1(dev, base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	} else if (base_addr != 0) { /* Don't probe at all. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 		err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		/* FIXME  Does this really work for cards which generate irq?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		 * It's definitely N.G. for polled Tangent. sh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 		 * Dayna cards don't autoprobe well at all, but if your card is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 		 * at IRQ 5 & IO 0x240 we find it every time. ;) JS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 		for (port = ports; *port && cops_probe1(dev, *port) < 0; port++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 			;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 		if (!*port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 			err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	err = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	cleanup_card(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) static const struct net_device_ops cops_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	.ndo_open               = cops_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265)         .ndo_stop               = cops_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	.ndo_start_xmit   	= cops_send_packet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	.ndo_tx_timeout		= cops_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268)         .ndo_do_ioctl           = cops_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	.ndo_set_rx_mode	= set_multicast_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  *      This is the real probe routine. Linux has a history of friendly device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)  *      probes on the ISA bus. A good device probes avoids doing writes, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275)  *      verifies that the correct device exists and functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) static int __init cops_probe1(struct net_device *dev, int ioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279)         struct cops_local *lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	static unsigned version_printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	int board = board_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)         if(cops_debug && version_printed++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 		printk("%s", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	/* Grab the region so no one else tries to probe our ioports. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291)         /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292)          * Since this board has jumpered interrupts, allocate the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293)          * vector now. There is no point in waiting since no other device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294)          * can use the interrupt, and this marks the irq as busy. Jumpered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295)          * interrupts are typically not reported by the boards, and we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296)          * used AutoIRQ to find them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	dev->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	switch (dev->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 			/* COPS AutoIRQ routine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 			dev->irq = cops_irq(ioaddr, board);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 			if (dev->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 			fallthrough;	/* Once no IRQ found on this port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 			retval = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 			goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		/* Fixup for users that don't know that IRQ 2 is really
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		 * IRQ 9, or don't know which one to set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 			dev->irq = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 		/* Polled operation requested. Although irq of zero passed as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		 * a parameter tells the init routines to probe, we'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 		 * overload it to denote polled operation at runtime.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		case 0xff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 			dev->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	dev->base_addr = ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	/* Reserve any actual interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	if (dev->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339)         lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340)         spin_lock_init(&lp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	/* Copy local board variable to lp struct. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	lp->board               = board;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	dev->netdev_ops 	= &cops_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	dev->watchdog_timeo	= HZ * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	/* Tell the user where the card is and what mode we're in. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	if(board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 		printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 			dev->name, cardname, ioaddr, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	if(board==TANGENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		if(dev->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 			printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 				dev->name, cardname, ioaddr, dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 				dev->name, cardname, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362)         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	release_region(ioaddr, COPS_IO_EXTENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) static int __init cops_irq (int ioaddr, int board)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) {       /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371)          * This does not use the IRQ to determine where the IRQ is. We just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)          * assume that when we get a correct status response that it's the IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)          * This really just verifies the IO port but since we only have access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)          * to such a small number of IRQs (5, 4, 3) this is not bad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375)          * This will probably not work for more than one card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376)          */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377)         int irqaddr=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378)         int i, x, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)         if(board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382)                 outb(0, ioaddr+DAYNA_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)                 inb(ioaddr+DAYNA_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)                 mdelay(333);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386)         if(board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)                 inb(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)                 outb(0, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)                 outb(0, ioaddr+TANG_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393)         for(i=0; cops_irqlist[i] !=0; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)                 irqaddr = cops_irqlist[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)                 for(x = 0xFFFF; x>0; x --)    /* wait for response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)                         if(board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)                         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)                                 status = (inb(ioaddr+DAYNA_CARD_STATUS)&3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)                                 if(status == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)                                         return irqaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)                         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)                         if(board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)                         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)                                 if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407)                                         return irqaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408)                         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411)         return 0;       /* no IRQ found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415)  * Open/initialize the board. This is called (in the current kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416)  * sometime after booting when the 'ifconfig' program is run.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) static int cops_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420)     struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	if(dev->irq==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		 * I don't know if the Dayna-style boards support polled 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		 * operation.  For now, only allow it for Tangent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		if(lp->board==TANGENT)	/* Poll 20 times per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 		    cops_timer_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		    timer_setup(&cops_timer, cops_poll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		    cops_timer.expires 	= jiffies + HZ/20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		    add_timer(&cops_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		} 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		else 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 			printk(KERN_WARNING "%s: No irq line set\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 			return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	cops_jumpstart(dev);	/* Start the card up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445)         return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449)  *	This allows for a dynamic start/restart of the entire card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) static int cops_jumpstart(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456)          *      Once the card has the firmware loaded and has acquired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457)          *      the nodeid, if it is reset it will lose it all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458)          */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)         cops_reset(dev,1);	/* Need to reset card before load firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)         cops_load(dev);		/* Load the firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	 *	If atalkd already gave us a nodeid we will use that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	 *	one again, else we wait for atalkd to give us a nodeid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	 *	in cops_ioctl. This may cause a problem if someone steals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	 *	our nodeid while we are resetting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	 */	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	if(lp->nodeid == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		cops_nodeid(dev,lp->node_acquire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) static void tangent_wait_reset(int ioaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	int timeout=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		mdelay(1);   /* Wait 1 second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483)  *      Reset the LocalTalk board.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) static void cops_reset(struct net_device *dev, int sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)         int ioaddr=dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)         if(lp->board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)                 inb(ioaddr);		/* Clear request latch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493)                 outb(0,ioaddr);		/* Clear the TANG_TX_READY flop. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494)                 outb(0, ioaddr+TANG_RESET);	/* Reset the adapter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		tangent_wait_reset(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)                 outb(0, ioaddr+TANG_CLEAR_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)         if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)                 outb(0, ioaddr+DAYNA_RESET);	/* Assert the reset port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)                 inb(ioaddr+DAYNA_RESET);	/* Clear the reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		if (sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 			msleep(333);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			mdelay(333);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) static void cops_load (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514)         struct ifreq ifr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515)         struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517)         int ioaddr=dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	int length, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520)         strcpy(ifr.ifr_name,"lt0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522)         /* Get card's firmware code and do some checks on it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) #ifdef CONFIG_COPS_DAYNA        
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524)         if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526)                 ltf->length=sizeof(ffdrv_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527)                 ltf->data=ffdrv_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529)         else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) #endif        
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) #ifdef CONFIG_COPS_TANGENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532)         if(lp->board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534)                 ltf->length=sizeof(ltdrv_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535)                 ltf->data=ltdrv_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537)         else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		printk(KERN_INFO "%s; unsupported board type.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)         /* Check to make sure firmware is correct length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545)         if(lp->board==DAYNA && ltf->length!=5983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547)                 printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)         if(lp->board==TANGENT && ltf->length!=2501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)                 printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)         if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)                 /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)                  *      We must wait for a status response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)                  *      with the DAYNA board.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)                  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)                 while(++i<65536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564)                        if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565)                                 break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568)                 if(i==65536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569)                         return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572)         /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573)          *      Upload the firmware and kick. Byte-by-byte works nicely here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574)          */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	i=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576)         length = ltf->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577)         while(length--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579)                 outb(ltf->data[i], ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580)                 i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	if(cops_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		printk("%s: Uploaded firmware - %d bytes of %d bytes.\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 			dev->name, i, ltf->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587)         if(lp->board==DAYNA) 	/* Tell Dayna to run the firmware code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588)                 outb(1, ioaddr+DAYNA_INT_CARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	else			/* Tell Tang to run the firmware code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		inb(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592)         if(lp->board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594)                 tangent_wait_reset(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595)                 inb(ioaddr);	/* Clear initial ready signal. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600)  * 	Get the LocalTalk Nodeid from the card. We can suggest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601)  *	any nodeid 1-254. The card will try and get that exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)  *	address else we can specify 0 as the nodeid and the card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)  *	will autoprobe for a nodeid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) static int cops_nodeid (struct net_device *dev, int nodeid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	int ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	if(lp->board == DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)         	/* Empty any pending adapter responses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)                 while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616)         		if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617)                 		cops_rx(dev);	/* Kick any packets waiting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 			schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)                 outb(2, ioaddr);       	/* Output command packet length as 2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622)                 outb(0, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623)                 outb(LAP_INIT, ioaddr);	/* Send LAP_INIT command byte. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)                 outb(nodeid, ioaddr);  	/* Suggest node address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	if(lp->board == TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629)                 /* Empty any pending adapter responses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630)                 while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633)                 	cops_rx(dev);          	/* Kick out packets waiting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 			schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		/* Not sure what Tangent does if nodeid picked is used. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)                 if(nodeid == 0)	         		/* Seed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)                 	nodeid = jiffies&0xFF;		/* Get a random try */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)                 outb(2, ioaddr);        		/* Command length LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)                 outb(0, ioaddr);       			/* Command length MSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)                 outb(LAP_INIT, ioaddr); 		/* Send LAP_INIT byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)                 outb(nodeid, ioaddr); 		  	/* LAP address hint. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)                 outb(0xFF, ioaddr);     		/* Int. level to use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	lp->node_acquire=0;		/* Set nodeid holder to 0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648)         while(lp->node_acquire==0)	/* Get *True* nodeid finally. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear any interrupt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		if(lp->board == DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654)                 	if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655)                 		cops_rx(dev);	/* Grab the nodeid put in lp->node_acquire. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		if(lp->board == TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		{	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660)                                 cops_rx(dev);   /* Grab the nodeid put in lp->node_acquire. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	if(cops_debug > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			dev->name, lp->node_acquire);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	lp->nodeid=1;	/* Set got nodeid to 1. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671)         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)  *	Poll the Tangent type cards to see if we have work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) static void cops_poll(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	int ioaddr, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	int boguscount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	struct net_device *dev = cops_timer_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	del_timer(&cops_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	if(dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		return;	/* We've been downed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		status=inb(ioaddr+TANG_CARD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		if(status & TANG_RX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 			cops_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		if(status & TANG_TX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 			netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		status = inb(ioaddr+TANG_CARD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	/* poll 20 times per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	cops_timer.expires = jiffies + HZ/20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	add_timer(&cops_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) }
^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)  *      The typical workload of the driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706)  *      Handle the network interface interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) static irqreturn_t cops_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710)         struct net_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711)         struct cops_local *lp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712)         int ioaddr, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713)         int boguscount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715)         ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716)         lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 			outb(0, ioaddr + COPS_CLEAR_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722)                        	status=inb(ioaddr+DAYNA_CARD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723)                        	if((status&0x03)==DAYNA_RX_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724)                        	        cops_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725)                 	netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		} while(++boguscount < 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731)                        	status=inb(ioaddr+TANG_CARD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			if(status & TANG_RX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 				cops_rx(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 			if(status & TANG_TX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 				netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 			status=inb(ioaddr+TANG_CARD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
^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)         return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744)  *      We have a good packet(s), get it/them out of the buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) static void cops_rx(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748)         int pkt_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749)         int rsp_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750)         struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752)         int ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753)         int boguscount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754)         unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	spin_lock_irqsave(&lp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759)         if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761)                 outb(0, ioaddr);                /* Send out Zero length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762)                 outb(0, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763)                 outb(DATA_READ, ioaddr);        /* Send read command out. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765)                 /* Wait for DMA to turn around. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766)                 while(++boguscount<1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 			barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769)                         if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770)                                 break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)                 if(boguscount==1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)                 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)                         printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 			spin_unlock_irqrestore(&lp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)                         return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)                 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781)         /* Get response length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	pkt_len = inb(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783)         pkt_len |= (inb(ioaddr) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784)         /* Input IO code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785)         rsp_type=inb(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787)         /* Malloc up new buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788)         skb = dev_alloc_skb(pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789)         if(skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791)                 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793)                 dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794)                 while(pkt_len--)        /* Discard packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795)                         inb(ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796)                 spin_unlock_irqrestore(&lp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799)         skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800)         skb_put(skb, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801)         skb->protocol = htons(ETH_P_LOCALTALK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803)         insb(ioaddr, skb->data, pkt_len);               /* Eat the Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805)         if(lp->board==DAYNA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806)                 outb(1, ioaddr+DAYNA_INT_CARD);         /* Interrupt the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808)         spin_unlock_irqrestore(&lp->lock, flags);  /* Restore interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810)         /* Check for bad response length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811)         if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			dev->name, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815)                 dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816)                 dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820)         /* Set nodeid and then get out. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821)         if(rsp_type == LAP_INIT_RSP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822)         {	/* Nodeid taken from received packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823)                 lp->node_acquire = skb->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824)                 dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828)         /* One last check to make sure we have a good packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829)         if(rsp_type != LAP_RESPONSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831)                 printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832)                 dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833)                 dev_kfree_skb_any(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837)         skb_reset_mac_header(skb);    /* Point to entire packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838)         skb_pull(skb,3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839)         skb_reset_transport_header(skb);    /* Point to data (Skip header). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841)         /* Update the counters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842)         dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843)         dev->stats.rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845)         /* Send packet to a higher place. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846)         netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) static void cops_timeout(struct net_device *dev, unsigned int txqueue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852)         int ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855)         if(lp->board==TANGENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858)                		printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	cops_jumpstart(dev);	/* Restart the card. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	netif_trans_update(dev); /* prevent tx timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^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)  *	Make the card transmit a LocalTalk packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) static netdev_tx_t cops_send_packet(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 					  struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875)         int ioaddr = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876)         unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878)         /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879)          * Block a timer-based transmit from overlapping. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	spin_lock_irqsave(&lp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	if(lp->board == DAYNA)	 /* Wait for adapter transmit buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	/* Output IO length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	outb(skb->len, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	outb(skb->len >> 8, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	/* Output IO code. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	outb(LAP_WRITE, ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	if(lp->board == DAYNA)	/* Check the transmit buffer again. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900)         	while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	outsb(ioaddr, skb->data, skb->len);	/* Send out the data. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	if(lp->board==DAYNA)	/* Dayna requires you kick the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		outb(1, ioaddr+DAYNA_INT_CARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	spin_unlock_irqrestore(&lp->lock, flags);	/* Restore interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	/* Done sending packet, update counters and cleanup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	dev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	dev->stats.tx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	dev_kfree_skb (skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917)  *	Dummy function to keep the Appletalk layer happy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) static void set_multicast_list(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922)         if(cops_debug >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		printk("%s: set_multicast_list executed\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927)  *      System ioctls for the COPS LocalTalk card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932)         struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933)         struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934)         struct atalk_addr *aa = &lp->node_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936)         switch(cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937)         {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938)                 case SIOCSIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 			/* Get and set the nodeid and network # atalkd wants. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			cops_nodeid(dev, sa->sat_addr.s_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			aa->s_net               = sa->sat_addr.s_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942)                         aa->s_node              = lp->node_acquire;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 			/* Set broardcast address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945)                         dev->broadcast[0]       = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 			
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 			/* Set hardware address. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948)                         dev->dev_addr[0]        = aa->s_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949)                         dev->addr_len           = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950)                         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952)                 case SIOCGIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953)                         sa->sat_addr.s_net      = aa->s_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954)                         sa->sat_addr.s_node     = aa->s_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955)                         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957)                 default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958)                         return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963)  *	The inverse routine to cops_open().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) static int cops_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	struct cops_local *lp = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	/* If we were running polled, yank the timer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	if(lp->board==TANGENT && dev->irq==0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		del_timer(&cops_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976)         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) static struct net_device *cops_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) module_param_hw(io, int, ioport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) module_param_hw(irq, int, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) module_param_hw(board_type, int, other, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) static int __init cops_module_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	if (io == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 			cardname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	cops_dev = cops_probe(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	return PTR_ERR_OR_ZERO(cops_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) static void __exit cops_module_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	unregister_netdev(cops_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	cleanup_card(cops_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	free_netdev(cops_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) module_init(cops_module_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) module_exit(cops_module_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) #endif /* MODULE */