^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 */