^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define VERSION "3.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Please use z8530drv-utils-3.0 with this version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * ------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * You can find a subset of the documentation in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Documentation/networking/device_drivers/hamradio/z8530drv.rst.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) ********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * SCC.C - Linux driver for Z8530 based HDLC cards for AX.25 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) Copyright (c) 1993, 2000 Joerg Reuter DL1BKE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) portions (c) 1993 Guido ten Dolle PE1NNZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) ********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) The driver and the programs in the archive are UNDER CONSTRUCTION.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) The code is likely to fail, and so your kernel could --- even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) a whole network.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) This driver is intended for Amateur Radio use. If you are running it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) for commercial purposes, please drop me a note. I am nosy...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ...BUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ! You m u s t recognize the appropriate legislations of your country !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ! before you connect a radio to the SCC board and start to transmit or !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ! receive. The GPL allows you to use the d r i v e r, NOT the RADIO! !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) For non-Amateur-Radio use please note that you might need a special
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) allowance/licence from the designer of the SCC Board and/or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODEM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) it under the terms of the (modified) GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) delivered with the Linux kernel source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) You should find a copy of the GNU General Public License in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /usr/src/linux/COPYING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) ********************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) Incomplete history of z8530drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) -------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) 1994-09-13 started to write the driver, rescued most of my own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) code (and Hans Alblas' memory buffer pool concept) from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) an earlier project "sccdrv" which was initiated by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) Guido ten Dolle. Not much of the old driver survived,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) though. The first version I put my hands on was sccdrv1.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) from August 1993. The memory buffer pool concept
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) appeared in an unauthorized sccdrv version (1.5) from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) August 1994.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 1995-01-31 changed copyright notice to GPL without limitations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) . <SNIP>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 1996-10-05 New semester, new driver...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * KISS TNC emulator removed (TTY driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Source moved to drivers/net/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Includes Z8530 defines from drivers/net/z8530.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Uses sk_buffer memory management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Reduced overhead of /proc/net/z8530drv output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Streamlined quite a lot things
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Invents brand new bugs... ;-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) The move to version number 3.0 reflects theses changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) You can use 'kissbridge' if you need a KISS TNC emulator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 1996-12-13 Fixed for Linux networking changes. (G4KLX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 1997-01-08 Fixed the remaining problems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 1997-04-02 Hopefully fixed the problems with the new *_timer()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) routines, added calibration code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 1997-10-12 Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) 1998-01-29 Small fix to avoid lock-up on initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 1998-09-29 Fixed the "grouping" bugs, tx_inhibit works again,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) using dev->tx_queue_len now instead of MAXQUEUE now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) 1998-10-21 Postponed the spinlock changes, would need a lot of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) testing I currently don't have the time to. Softdcd doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 1998-11-04 Softdcd does not work correctly in DPLL mode, in fact it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) never did. The DPLL locks on noise, the SYNC unit sees
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) flags that aren't... Restarting the DPLL does not help
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) either, it resynchronizes too slow and the first received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) frame gets lost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 2000-02-13 Fixed for new network driver interface changes, still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) does TX timeouts itself since it uses its own queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) scheme.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) Thanks to all who contributed to this driver with ideas and bug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) reports!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) NB -- if you find errors, change something, please let me know
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) first before you distribute it... And please don't touch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) the version number. Just replace my callsign in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "v3.0.dl1bke" with your own. Just to avoid confusion...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) If you want to add your modification to the linux distribution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) please (!) contact me first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) New versions of the driver will be announced on the linux-hams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mailing list on vger.kernel.org. To subscribe send an e-mail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) to majordomo@vger.kernel.org with the following line in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) the body of the mail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) subscribe linux-hams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) The content of the "Subject" field will be ignored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) vy 73,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) AX-25 : DL1BKE @ DB0ABH.#BAY.DEU.EU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) Internet: jreuter@yaina.de
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) www : http://yaina.de/jreuter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #undef SCC_LDELAY /* slow it even a bit more down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #undef SCC_DONT_CHECK /* don't look if the SCCs you specified are available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define SCC_MAXCHIPS 4 /* number of max. supported chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define SCC_BUFSIZE 384 /* must not exceed 4096 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #undef SCC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SCC_DEFAULT_CLOCK 4915200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* default pclock if nothing is specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^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) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #include <linux/if_ether.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #include <linux/scc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #include <net/ax25.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #include "z8530.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static const char banner[] __initconst = KERN_INFO \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void t_dwait(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void t_txdelay(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void t_tail(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void t_busy(struct timer_list *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void t_maxkeyup(struct timer_list *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static void t_idle(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void scc_tx_done(struct scc_channel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void scc_start_tx_timer(struct scc_channel *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) void (*)(struct timer_list *), unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void scc_start_maxkeyup(struct scc_channel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void scc_start_defer(struct scc_channel *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static void z8530_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static void init_channel(struct scc_channel *scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void scc_key_trx (struct scc_channel *scc, char tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void scc_init_timer(struct scc_channel *scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int scc_net_alloc(const char *name, struct scc_channel *scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static void scc_net_setup(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int scc_net_open(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int scc_net_close(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static netdev_tx_t scc_net_tx(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int scc_net_set_mac_address(struct net_device *dev, void *addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static struct net_device_stats * scc_net_get_stats(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static unsigned char SCC_DriverName[] = "scc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static struct irqflags { unsigned char used : 1; } Ivec[NR_IRQS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static struct scc_channel SCC_Info[2 * SCC_MAXCHIPS]; /* information per channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static struct scc_ctrl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) io_port chan_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) io_port chan_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } SCC_ctrl[SCC_MAXCHIPS+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static unsigned char Driver_Initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static int Nchips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static io_port Vector_Latch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^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) /* * Port Access Functions * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* These provide interrupt save 2-step access to the Z8530 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static DEFINE_SPINLOCK(iolock); /* Guards paired accesses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline unsigned char InReg(io_port port, unsigned char reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned char r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) spin_lock_irqsave(&iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #ifdef SCC_LDELAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) Outb(port, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) udelay(SCC_LDELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) r=Inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) udelay(SCC_LDELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) Outb(port, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) r=Inb(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) spin_unlock_irqrestore(&iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static inline void OutReg(io_port port, unsigned char reg, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) spin_lock_irqsave(&iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) #ifdef SCC_LDELAY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) Outb(port, reg); udelay(SCC_LDELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) Outb(port, val); udelay(SCC_LDELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) Outb(port, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) Outb(port, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) spin_unlock_irqrestore(&iolock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static inline void wr(struct scc_channel *scc, unsigned char reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static inline void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static inline void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
^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) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* * Some useful macros * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static inline void scc_discard_buffers(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (scc->tx_buff != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dev_kfree_skb(scc->tx_buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) while (!skb_queue_empty(&scc->tx_queue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_kfree_skb(skb_dequeue(&scc->tx_queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* * Interrupt Service Routines * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* ----> subroutines for the interrupt handlers <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static inline void scc_notify(struct scc_channel *scc, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) char *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (scc->kiss.fulldup != KISS_DUPLEX_OPTIMA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) skb = dev_alloc_skb(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (skb != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) bp = skb_put(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *bp++ = PARAM_HWEVENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) *bp++ = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) scc_net_rx(scc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) scc->stat.nospace++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static inline void flush_rx_FIFO(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) for (k=0; k<3; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) Inb(scc->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if(scc->rx_buff != NULL) /* did we receive something? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) scc->stat.rxerrs++; /* then count it as an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) dev_kfree_skb_irq(scc->rx_buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) scc->rx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void start_hunt(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if ((scc->modem.clocksrc != CLK_EXTERNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* ----> four different interrupt handlers for Tx, Rx, changing of */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* DCD/CTS and Rx/Tx errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Transmitter interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static inline void scc_txint(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) scc->stat.txints++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) skb = scc->tx_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* send first octet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) skb = skb_dequeue(&scc->tx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) scc->tx_buff = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) netif_wake_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) scc_tx_done(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) Outb(scc->ctrl, RES_Tx_P);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (skb->len == 0) /* Paranoia... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) scc_tx_done(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) Outb(scc->ctrl, RES_Tx_P);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) scc->stat.tx_state = TXS_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) OutReg(scc->ctrl, R0, RES_Tx_CRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* reset CRC generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) or(scc,R10,ABUNDER); /* re-install underrun protection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) Outb(scc->data,*skb->data); /* send byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (!scc->enhanced) /* reset EOM latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) Outb(scc->ctrl,RES_EOM_L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return;
^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) /* End Of Frame... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (skb->len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) Outb(scc->ctrl, RES_Tx_P); /* reset pending int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) cl(scc, R10, ABUNDER); /* send CRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* send octet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) Outb(scc->data,*skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /* External/Status interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static inline void scc_exint(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) unsigned char status,changes,chg_and_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) scc->stat.exints++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) status = InReg(scc->ctrl,R0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) changes = status ^ scc->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) chg_and_stat = changes & status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* ABORT: generated whenever DCD drops while receiving */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (chg_and_stat & BRK_ABRT) /* Received an ABORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) flush_rx_FIFO(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if ((changes & SYNC_HUNT) && scc->kiss.softdcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (status & SYNC_HUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) scc->dcd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) flush_rx_FIFO(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if ((scc->modem.clocksrc != CLK_EXTERNAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) scc->dcd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) scc_notify(scc, scc->dcd? HWEV_DCD_OFF:HWEV_DCD_ON);
^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) /* DCD: on = start to receive packet, off = ABORT condition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* (a successfully received packet generates a special condition int) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if((changes & DCD) && !scc->kiss.softdcd) /* DCD input changed state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if(status & DCD) /* DCD is now ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) start_hunt(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) scc->dcd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) } else { /* DCD is now OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) flush_rx_FIFO(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) scc->dcd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) #ifdef notdef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* CTS: use external TxDelay (what's that good for?!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * Anyway: If we _could_ use it (BayCom USCC uses CTS for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * own purposes) we _should_ use the "autoenable" feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * of the Z8530 and not this interrupt...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (chg_and_stat & CTS) /* CTS is now ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (scc->kiss.txdelay == 0) /* zero TXDELAY = wait for CTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) scc_start_tx_timer(scc, t_txdelay, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (scc->stat.tx_state == TXS_ACTIVE && (status & TxEOM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) scc->stat.tx_under++; /* oops, an underrun! count 'em */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) Outb(scc->ctrl, RES_EXT_INT); /* reset ext/status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (scc->tx_buff != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dev_kfree_skb_irq(scc->tx_buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) or(scc,R10,ABUNDER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) scc_start_tx_timer(scc, t_txdelay, 0); /* restart transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) scc->status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) Outb(scc->ctrl,RES_EXT_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* Receiver interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static inline void scc_rxint(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) scc->stat.rxints++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if((scc->wreg[5] & RTS) && scc->kiss.fulldup == KISS_DUPLEX_HALF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) Inb(scc->data); /* discard char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) skb = scc->rx_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) skb = dev_alloc_skb(scc->stat.bufsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) scc->dev_stat.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) scc->stat.nospace++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) Inb(scc->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) or(scc, R3, ENT_HM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) scc->rx_buff = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) skb_put_u8(skb, 0); /* KISS data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (skb->len >= scc->stat.bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) #ifdef notdef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) scc->rx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) Inb(scc->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) or(scc, R3, ENT_HM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return;
^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) skb_put_u8(skb, Inb(scc->data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* Receive Special Condition interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static inline void scc_spint(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) unsigned char status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) scc->stat.spints++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) status = InReg(scc->ctrl,R1); /* read receiver status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) Inb(scc->data); /* throw away Rx byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) skb = scc->rx_buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if(status & Rx_OVR) /* receiver overrun */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) scc->stat.rx_over++; /* count them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (skb != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) scc->rx_buff = skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if(status & END_FR && skb != NULL) /* end of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* CRC okay, frame ends on 8 bit boundary and received something ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (!(status & CRC_ERR) && (status & 0xe) == RES8 && skb->len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* ignore last received byte (first of the CRC bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) skb_trim(skb, skb->len-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) scc_net_rx(scc, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) scc->rx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) scc->stat.rxframes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) } else { /* a bad frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) scc->rx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) scc->stat.rxerrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) Outb(scc->ctrl,ERR_RES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* ----> interrupt service routine for the Z8530 <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static void scc_isr_dispatch(struct scc_channel *scc, int vector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) spin_lock(&scc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) switch (vector & VECTOR_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case TXINT: scc_txint(scc); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) case EXINT: scc_exint(scc); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case RXINT: scc_rxint(scc); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) case SPINT: scc_spint(scc); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) spin_unlock(&scc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* If the card has a latch for the interrupt vector (like the PA0HZP card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) use it to get the number of the chip that generated the int.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) If not: poll all defined chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) #define SCC_IRQTIMEOUT 30000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static irqreturn_t scc_isr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int chip_irq = (long) dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) unsigned char vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct scc_channel *scc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct scc_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (Vector_Latch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) for(k=0; k < SCC_IRQTIMEOUT; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) Outb(Vector_Latch, 0); /* Generate INTACK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* Read the vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (vector & 0x01) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) scc=&SCC_Info[vector >> 3 ^ 0x01];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!scc->dev) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) scc_isr_dispatch(scc, vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) OutReg(scc->ctrl,R0,RES_H_IUS); /* Reset Highest IUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (k == SCC_IRQTIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* Find the SCC generating the interrupt by polling all attached SCCs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * reading RR3A (the interrupt pending register)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) ctrl = SCC_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) while (ctrl->chan_A)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ctrl->irq != chip_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ctrl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) continue;
^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) scc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) for (k = 0; InReg(ctrl->chan_A,R3) && k < SCC_IRQTIMEOUT; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) vector=InReg(ctrl->chan_B,R2); /* Read the vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (vector & 0x01) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) scc = &SCC_Info[vector >> 3 ^ 0x01];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (!scc->dev) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) scc_isr_dispatch(scc, vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (k == SCC_IRQTIMEOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* This looks weird and it is. At least the BayCom USCC doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * use the Interrupt Daisy Chain, thus we'll have to start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * all over again to be sure not to miss an interrupt from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * (any of) the other chip(s)...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * Honestly, the situation *is* braindamaged...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (scc != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) OutReg(scc->ctrl,R0,RES_H_IUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) ctrl = SCC_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ctrl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /* * Init Channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* ----> set SCC channel speed <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static inline void set_brg(struct scc_channel *scc, unsigned int tc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) cl(scc,R14,BRENABL); /* disable baudrate generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) wr(scc,R12,tc & 255); /* brg rate LOW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) wr(scc,R13,tc >> 8); /* brg rate HIGH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) or(scc,R14,BRENABL); /* enable baudrate generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static inline void set_speed(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (scc->modem.speed > 0) /* paranoia... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* ----> initialize a SCC channel <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static inline void init_brg(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) wr(scc, R14, BRSRC); /* BRG source = PCLK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]); /* DPLL source = BRG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * Initialization according to the Z8530 manual (SGS-Thomson's version):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * 1. Modes and constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * WR9 11000000 chip reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * WR4 XXXXXXXX Tx/Rx control, async or sync mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * WR1 0XX00X00 select W/REQ (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * WR2 XXXXXXXX program interrupt vector
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * WR3 XXXXXXX0 select Rx control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) * WR5 XXXX0XXX select Tx control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) * WR6 XXXXXXXX sync character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * WR7 XXXXXXXX sync character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * WR9 000X0XXX select interrupt control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * WR10 XXXXXXXX miscellaneous control (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * WR11 XXXXXXXX clock control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * WR12 XXXXXXXX time constant lower byte (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * WR13 XXXXXXXX time constant upper byte (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * WR14 XXXXXXX0 miscellaneous control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * WR14 XXXSSSSS commands (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * 2. Enables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * WR14 000SSSS1 baud rate enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * WR3 SSSSSSS1 Rx enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * WR5 SSSS1SSS Tx enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * WR0 10000000 reset Tx CRG (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) * WR1 XSS00S00 DMA enable (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * 3. Interrupt status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * WR15 XXXXXXXX enable external/status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * WR0 00010000 reset external status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * WR0 00010000 reset external status twice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * WR1 SSSXXSXX enable Rx, Tx and Ext/status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * WR9 000SXSSS enable master interrupt enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * 1 = set to one, 0 = reset to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * X = user defined, S = same as previous init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * Note that the implementation differs in some points from above scheme.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static void init_channel(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) del_timer(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) disable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) wr(scc,R4,X1CLK|SDLC); /* *1 clock, SDLC mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) wr(scc,R1,0); /* no W/REQ operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) wr(scc,R3,Rx8|RxCRC_ENAB); /* RX 8 bits/char, CRC, disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) wr(scc,R5,Tx8|DTR|TxCRC_ENAB); /* TX 8 bits/char, disabled, DTR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) wr(scc,R6,0); /* SDLC address zero (not used) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) wr(scc,R7,FLAG); /* SDLC flag value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) wr(scc,R9,VIS); /* vector includes status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) wr(scc,R14, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* set clock sources:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) CLK_DPLL: normal halfduplex operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) RxClk: use DPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) TxClk: use DPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) TRxC mode DPLL output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) BayCom: others:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) TxClk = pin RTxC TxClk = pin TRxC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) RxClk = pin TRxC RxClk = pin RTxC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) CLK_DIVIDER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) RxClk = use DPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) TxClk = pin RTxC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) BayCom: others:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) pin TRxC = DPLL pin TRxC = BRG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) (RxClk * 1) (RxClk * 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) */
^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) switch(scc->modem.clocksrc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case CLK_DPLL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) init_brg(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) case CLK_DIVIDER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) init_brg(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) case CLK_EXTERNAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) OutReg(scc->ctrl, R14, DISDPLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) set_speed(scc); /* set baudrate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if(scc->enhanced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) or(scc,R15,SHDLCE|FIFOE); /* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) wr(scc,R7,AUTOEOM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if(scc->kiss.softdcd || (InReg(scc->ctrl,R0) & DCD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /* DCD is now ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) start_hunt(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /* enable ABORT, DCD & SYNC/HUNT interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) wr(scc,R15, BRKIE|TxUIE|(scc->kiss.softdcd? SYNCIE:DCDIE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) Outb(scc->ctrl,RES_EXT_INT); /* must be done twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) scc->status = InReg(scc->ctrl,R0); /* read initial status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) or(scc,R9,MIE); /* master interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) scc_init_timer(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) enable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* * SCC timer functions * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /* ----> scc_key_trx sets the time constant for the baudrate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) generator and keys the transmitter <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) static void scc_key_trx(struct scc_channel *scc, char tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) unsigned int time_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (scc->brand & PRIMUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (scc->modem.speed < 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) scc->modem.speed = 1200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) disable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) or(scc, R1, TxINT_ENAB); /* t_maxkeyup may have reset these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) or(scc, R15, TxUIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (scc->modem.clocksrc == CLK_DPLL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) { /* force simplex operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) #ifdef CONFIG_SCC_TRXECHO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) cl(scc, R3, RxENABLE|ENT_HM); /* switch off receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) cl(scc, R15, DCDIE|SYNCIE); /* No DCD changes, please */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) set_brg(scc, time_const); /* reprogram baudrate generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* By popular demand: tx_inhibit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (scc->kiss.tx_inhibit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) or(scc,R5, TxENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) scc->wreg[R5] |= RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) or(scc,R5,RTS|TxENAB); /* set the RTS line and enable TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) cl(scc,R5,RTS|TxENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) set_brg(scc, time_const); /* reprogram baudrate generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) #ifndef CONFIG_SCC_TRXECHO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (scc->kiss.softdcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) or(scc,R15, scc->kiss.softdcd? SYNCIE:DCDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) start_hunt(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) #ifdef CONFIG_SCC_TRXECHO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) cl(scc, R3, RxENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) cl(scc, R15, DCDIE|SYNCIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (scc->kiss.tx_inhibit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) or(scc,R5, TxENAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) scc->wreg[R5] |= RTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) or(scc,R5,RTS|TxENAB); /* enable tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) cl(scc,R5,RTS|TxENAB); /* disable tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if ((scc->kiss.fulldup == KISS_DUPLEX_HALF) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) #ifndef CONFIG_SCC_TRXECHO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) scc->kiss.softdcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) or(scc, R15, scc->kiss.softdcd? SYNCIE:DCDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) start_hunt(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) enable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /* ----> SCC timer interrupt handler and friends. <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) static void __scc_start_tx_timer(struct scc_channel *scc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) void (*handler)(struct timer_list *t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) unsigned long when)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) del_timer(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (when == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) handler(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (when != TIMER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) scc->tx_t.function = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) scc->tx_t.expires = jiffies + (when*HZ)/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) add_timer(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static void scc_start_tx_timer(struct scc_channel *scc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) void (*handler)(struct timer_list *t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unsigned long when)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) __scc_start_tx_timer(scc, handler, when);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static void scc_start_defer(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) scc->tx_wdog.function = t_busy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxdefer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) add_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static void scc_start_maxkeyup(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) scc->tx_wdog.function = t_maxkeyup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) add_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * This is called from scc_txint() when there are no more frames to send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * Not exactly a timer function, but it is a close friend of the family...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static void scc_tx_done(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * trx remains keyed in fulldup mode 2 until t_idle expires.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) switch (scc->kiss.fulldup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) case KISS_DUPLEX_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) scc->stat.tx_state = TXS_IDLE2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (scc->kiss.idletime != TIMER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) scc_start_tx_timer(scc, t_idle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) scc->kiss.idletime*100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case KISS_DUPLEX_OPTIMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) scc_notify(scc, HWEV_ALL_SENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) scc->stat.tx_state = TXS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) netif_wake_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) static unsigned char Rand = 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static inline int is_grouped(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct scc_channel *scc2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) unsigned char grp1, grp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) grp1 = scc->kiss.group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) for (k = 0; k < (Nchips * 2); k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) scc2 = &SCC_Info[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) grp2 = scc2->kiss.group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (scc2 == scc || !(scc2->dev && grp2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if ((grp1 & 0x3f) == (grp2 & 0x3f))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if ( (grp1 & RXGROUP) && scc2->dcd )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* DWAIT and SLOTTIME expired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * fulldup == 0: DCD is active or Rand > P-persistence: start t_busy timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * else key trx and start txdelay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * fulldup == 1: key trx and start txdelay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * fulldup == 2: mintime expired, reset status or key trx and start txdelay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) static void t_dwait(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct scc_channel *scc = from_timer(scc, t, tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (scc->stat.tx_state == TXS_WAIT) /* maxkeyup or idle timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (skb_queue_empty(&scc->tx_queue)) { /* nothing to send */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) scc->stat.tx_state = TXS_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) netif_wake_queue(scc->dev); /* t_maxkeyup locked it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) scc->stat.tx_state = TXS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) Rand = Rand * 17 + 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (scc->dcd || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) scc_start_defer(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if ( !(scc->wreg[R5] & RTS) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) scc_key_trx(scc, TX_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) scc_start_tx_timer(scc, t_txdelay, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* TXDELAY expired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static void t_txdelay(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct scc_channel *scc = from_timer(scc, t, tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) scc_start_maxkeyup(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (scc->tx_buff == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) disable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) scc_txint(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) enable_irq(scc->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* TAILTIME expired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) * switch off transmitter. If we were stopped by Maxkeyup restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * transmission after 'mintime' seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static void t_tail(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) struct scc_channel *scc = from_timer(scc, t, tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) scc_key_trx(scc, TX_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (scc->stat.tx_state == TXS_TIMEOUT) /* we had a timeout? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) scc->stat.tx_state = TXS_WAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) scc->stat.tx_state = TXS_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) netif_wake_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* BUSY timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * throw away send buffers if DCD remains active too long.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static void t_busy(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct scc_channel *scc = from_timer(scc, t, tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) del_timer(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) netif_stop_queue(scc->dev); /* don't pile on the wabbit! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) scc_discard_buffers(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) scc->stat.txerrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) scc->stat.tx_state = TXS_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) netif_wake_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) /* MAXKEYUP timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * this is our watchdog.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static void t_maxkeyup(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct scc_channel *scc = from_timer(scc, t, tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * let things settle down before we start to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * accept new data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) netif_stop_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) scc_discard_buffers(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) del_timer(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) cl(scc, R1, TxINT_ENAB); /* force an ABORT, but don't */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) cl(scc, R15, TxUIE); /* count it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) OutReg(scc->ctrl, R0, RES_Tx_P);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) scc->stat.txerrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) scc->stat.tx_state = TXS_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /* IDLE timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * in fulldup mode 2 it keys down the transmitter after 'idle' seconds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * of inactivity. We will not restart transmission before 'mintime'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * expires.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static void t_idle(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct scc_channel *scc = from_timer(scc, t, tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) scc_key_trx(scc, TX_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if(scc->kiss.mintime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) scc->stat.tx_state = TXS_WAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) static void scc_init_timer(struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) scc->stat.tx_state = TXS_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /* * Set/get L1 parameters * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * this will set the "hardware" parameters through KISS commands or ioctl()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) #define CAST(x) (unsigned long)(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) switch (cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) case PARAM_TXDELAY: scc->kiss.txdelay=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) case PARAM_PERSIST: scc->kiss.persist=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) case PARAM_SLOTTIME: scc->kiss.slottime=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) case PARAM_TXTAIL: scc->kiss.tailtime=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) case PARAM_FULLDUP: scc->kiss.fulldup=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) case PARAM_DTR: break; /* does someone need this? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) case PARAM_GROUP: scc->kiss.group=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) case PARAM_IDLE: scc->kiss.idletime=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) case PARAM_MIN: scc->kiss.mintime=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) case PARAM_MAXKEY: scc->kiss.maxkeyup=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) case PARAM_WAIT: scc->kiss.waittime=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) case PARAM_MAXDEFER: scc->kiss.maxdefer=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) case PARAM_TX: scc->kiss.tx_inhibit=arg; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) case PARAM_SOFTDCD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) scc->kiss.softdcd=arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) or(scc, R15, SYNCIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) cl(scc, R15, DCDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) start_hunt(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) or(scc, R15, DCDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) cl(scc, R15, SYNCIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) case PARAM_SPEED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (arg < 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) scc->modem.speed=arg*100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) scc->modem.speed=arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (scc->stat.tx_state == 0) /* only switch baudrate on rx... ;-) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) set_speed(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) case PARAM_RTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if ( !(scc->wreg[R5] & RTS) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (arg != TX_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) scc_key_trx(scc, TX_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (arg == TX_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) scc->stat.tx_state = TXS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) case PARAM_HWEVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) static unsigned long scc_get_param(struct scc_channel *scc, unsigned int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) switch (cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) case PARAM_TXDELAY: return CAST(scc->kiss.txdelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) case PARAM_PERSIST: return CAST(scc->kiss.persist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) case PARAM_SLOTTIME: return CAST(scc->kiss.slottime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) case PARAM_TXTAIL: return CAST(scc->kiss.tailtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) case PARAM_FULLDUP: return CAST(scc->kiss.fulldup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) case PARAM_SOFTDCD: return CAST(scc->kiss.softdcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) case PARAM_DTR: return CAST((scc->wreg[R5] & DTR)? 1:0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) case PARAM_RTS: return CAST((scc->wreg[R5] & RTS)? 1:0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) case PARAM_SPEED: return CAST(scc->modem.speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) case PARAM_GROUP: return CAST(scc->kiss.group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) case PARAM_IDLE: return CAST(scc->kiss.idletime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) case PARAM_MIN: return CAST(scc->kiss.mintime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) case PARAM_MAXKEY: return CAST(scc->kiss.maxkeyup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) case PARAM_WAIT: return CAST(scc->kiss.waittime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) case PARAM_MAXDEFER: return CAST(scc->kiss.maxdefer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) case PARAM_TX: return CAST(scc->kiss.tx_inhibit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) default: return NO_SUCH_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) #undef CAST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) /* ******************************************************************* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /* * Send calibration pattern * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) /* ******************************************************************* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) static void scc_stop_calibrate(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct scc_channel *scc = from_timer(scc, t, tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) scc_key_trx(scc, TX_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) wr(scc, R6, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) wr(scc, R7, FLAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) Outb(scc->ctrl,RES_EXT_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) netif_wake_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) netif_stop_queue(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) scc_discard_buffers(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) del_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) scc->tx_wdog.function = scc_stop_calibrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) scc->tx_wdog.expires = jiffies + HZ*duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) add_timer(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) /* This doesn't seem to work. Why not? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) wr(scc, R6, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) wr(scc, R7, pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) * Don't know if this works.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) * Damn, where is my Z8530 programming manual...?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) Outb(scc->ctrl,RES_EXT_INT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) scc_key_trx(scc, TX_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) /* ******************************************************************* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) /* * Init channel structures, special HW, etc... * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) /* ******************************************************************* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) * Reset the Z8530s and setup special hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) static void z8530_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) struct scc_channel *scc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) int chip, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) char *flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) flag=" ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) for (k = 0; k < nr_irqs; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (Ivec[k].used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) printk("%s%d", flag, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) flag=",";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) /* reset and pre-init all chips in the system */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) for (chip = 0; chip < Nchips; chip++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) scc=&SCC_Info[2*chip];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (!scc->ctrl) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* Special SCC cards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if(scc->brand & EAGLE) /* this is an EAGLE card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) Outb(scc->special,0x08); /* enable interrupt on the board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if(scc->brand & (PC100 | PRIMUS)) /* this is a PC100/PRIMUS card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) Outb(scc->special,scc->option); /* set the MODEM mode (0x22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* Reset and pre-init Z8530 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) Outb(scc->ctrl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) OutReg(scc->ctrl,R9,FHWRES); /* force hardware reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) udelay(100); /* give it 'a bit' more time than required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) wr(scc, R2, chip*16); /* interrupt vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) wr(scc, R9, VIS); /* vector includes status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) Driver_Initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * Allocate device structure, err, instance, and register driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) static int scc_net_alloc(const char *name, struct scc_channel *scc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, scc_net_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) dev->ml_priv = scc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) scc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) spin_lock_init(&scc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) timer_setup(&scc->tx_t, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) timer_setup(&scc->tx_wdog, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) err = register_netdevice(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) printk(KERN_ERR "%s: can't register network device (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) name, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) scc->dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /* * Network driver methods * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) static const struct net_device_ops scc_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) .ndo_open = scc_net_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) .ndo_stop = scc_net_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) .ndo_start_xmit = scc_net_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) .ndo_set_mac_address = scc_net_set_mac_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) .ndo_get_stats = scc_net_get_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) .ndo_do_ioctl = scc_net_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /* ----> Initialize device <----- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) static void scc_net_setup(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) dev->tx_queue_len = 16; /* should be enough... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) dev->netdev_ops = &scc_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) dev->header_ops = &ax25_header_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) dev->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) dev->type = ARPHRD_AX25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) dev->mtu = AX25_DEF_PACLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) dev->addr_len = AX25_ADDR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) /* ----> open network device <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) static int scc_net_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if (!scc->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) skb_queue_head_init(&scc->tx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) init_channel(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /* ----> close network device <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) static int scc_net_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) Outb(scc->ctrl,0); /* Make sure pointer is written */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) wr(scc,R1,0); /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) wr(scc,R3,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) del_timer_sync(&scc->tx_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) del_timer_sync(&scc->tx_wdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) scc_discard_buffers(scc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) /* ----> receive frame, called from scc_rxint() <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if (skb->len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) dev_kfree_skb_irq(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) scc->dev_stat.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) scc->dev_stat.rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) skb->protocol = ax25_type_trans(skb, scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) /* ----> transmit frame <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static netdev_tx_t scc_net_tx(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) char kisscmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (skb->protocol == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) return ax25_ip_xmit(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (skb->len > scc->stat.bufsize || skb->len < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) scc->dev_stat.tx_dropped++; /* bogus frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) scc->dev_stat.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) scc->dev_stat.tx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) scc->stat.txframes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) kisscmd = *skb->data & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) if (kisscmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) scc_set_param(scc, kisscmd, *skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) spin_lock_irqsave(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) struct sk_buff *skb_del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) skb_del = skb_dequeue(&scc->tx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) dev_kfree_skb(skb_del);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) skb_queue_tail(&scc->tx_queue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) netif_trans_update(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) * Start transmission if the trx state is idle or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) * t_idle hasn't expired yet. Use dwait/persistence/slottime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) * algorithm for normal halfduplex operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) scc->stat.tx_state = TXS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) __scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) __scc_start_tx_timer(scc, t_dwait, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) spin_unlock_irqrestore(&scc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) /* ----> ioctl functions <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) * SIOCSCCCFG - configure driver arg: (struct scc_hw_config *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) * SIOCSCCINI - initialize driver arg: ---
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) * SIOCSCCCHANINI - initialize channel arg: (struct scc_modem *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) * SIOCSCCSMEM - set memory arg: (struct scc_mem_config *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) * SIOCSCCGKISS - get level 1 parameter arg: (struct scc_kiss_cmd *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) * SIOCSCCSKISS - set level 1 parameter arg: (struct scc_kiss_cmd *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * SIOCSCCGSTAT - get driver status arg: (struct scc_stat *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * SIOCSCCCAL - send calib. pattern arg: (struct scc_calibrate *) arg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) struct scc_kiss_cmd kiss_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) struct scc_mem_config memcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) struct scc_hw_config hwcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) struct scc_calibrate cal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) int chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) unsigned char device_name[IFNAMSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) void __user *arg = ifr->ifr_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) if (!Driver_Initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (cmd == SIOCSCCCFG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) int found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) if (!capable(CAP_SYS_RAWIO)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) if (!arg) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) if (Nchips >= SCC_MAXCHIPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) if (hwcfg.irq == 2) hwcfg.irq = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (!Ivec[hwcfg.irq].used && hwcfg.irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (request_irq(hwcfg.irq, scc_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 0, "AX.25 SCC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) (void *)(long) hwcfg.irq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) Ivec[hwcfg.irq].used = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) if (hwcfg.vector_latch && !Vector_Latch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (!request_region(hwcfg.vector_latch, 1, "scc vector latch"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%lx\n, disabled.", hwcfg.vector_latch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) Vector_Latch = hwcfg.vector_latch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) if (hwcfg.clock == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) hwcfg.clock = SCC_DEFAULT_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) #ifndef SCC_DONT_CHECK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) if(request_region(hwcfg.ctrl_a, 1, "scc-probe"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) disable_irq(hwcfg.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) Outb(hwcfg.ctrl_a, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) OutReg(hwcfg.ctrl_a, R9, FHWRES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) OutReg(hwcfg.ctrl_a,R13,0x55); /* is this chip really there? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) udelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (InReg(hwcfg.ctrl_a,R13) != 0x55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) enable_irq(hwcfg.irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) release_region(hwcfg.ctrl_a, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) SCC_Info[2*Nchips ].ctrl = hwcfg.ctrl_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) SCC_Info[2*Nchips ].data = hwcfg.data_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) SCC_Info[2*Nchips ].irq = hwcfg.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) SCC_Info[2*Nchips+1].data = hwcfg.data_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) SCC_Info[2*Nchips+1].irq = hwcfg.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) SCC_ctrl[Nchips].chan_A = hwcfg.ctrl_a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) SCC_ctrl[Nchips].chan_B = hwcfg.ctrl_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) SCC_ctrl[Nchips].irq = hwcfg.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) for (chan = 0; chan < 2; chan++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) sprintf(device_name, "%s%i", SCC_DriverName, 2*Nchips+chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) SCC_Info[2*Nchips+chan].special = hwcfg.special;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) SCC_Info[2*Nchips+chan].option = hwcfg.option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) #ifdef SCC_DONT_CHECK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) printk(KERN_INFO "%s: data port = 0x%3.3x control port = 0x%3.3x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) device_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) SCC_Info[2*Nchips+chan].data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) SCC_Info[2*Nchips+chan].ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) printk(KERN_INFO "%s: data port = 0x%3.3lx control port = 0x%3.3lx -- %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) device_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) chan? hwcfg.data_b : hwcfg.data_a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) found? "found" : "missing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) if (Nchips+chan != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) scc_net_alloc(device_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) &SCC_Info[2*Nchips+chan]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) if (found) Nchips++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) if (cmd == SIOCSCCINI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (!capable(CAP_SYS_RAWIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) if (Nchips == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) z8530_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) return -EINVAL; /* confuse the user */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (!scc->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (cmd == SIOCSCCCHANINI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (!capable(CAP_NET_ADMIN)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (!arg) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) scc->stat.bufsize = SCC_BUFSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) /* default KISS Params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) if (scc->modem.speed < 4800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) scc->kiss.txdelay = 36; /* 360 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) scc->kiss.persist = 42; /* 25% persistence */ /* was 25 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) scc->kiss.slottime = 16; /* 160 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) scc->kiss.tailtime = 4; /* minimal reasonable value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) scc->kiss.fulldup = 0; /* CSMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) scc->kiss.waittime = 50; /* 500 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) scc->kiss.maxkeyup = 10; /* 10 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) scc->kiss.mintime = 3; /* 3 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) scc->kiss.idletime = 30; /* 30 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) scc->kiss.maxdefer = 120; /* 2 min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) scc->kiss.softdcd = 0; /* hardware dcd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) scc->kiss.txdelay = 10; /* 100 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) scc->kiss.persist = 64; /* 25% persistence */ /* was 25 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) scc->kiss.slottime = 8; /* 160 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) scc->kiss.tailtime = 1; /* minimal reasonable value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) scc->kiss.fulldup = 0; /* CSMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) scc->kiss.waittime = 50; /* 500 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) scc->kiss.maxkeyup = 7; /* 7 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) scc->kiss.mintime = 3; /* 3 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) scc->kiss.idletime = 30; /* 30 s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) scc->kiss.maxdefer = 120; /* 2 min */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) scc->kiss.softdcd = 0; /* hardware dcd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) scc->tx_buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) skb_queue_head_init(&scc->tx_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) scc->init = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) switch(cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) case SIOCSCCRESERVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) case SIOCSCCSMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) if (!capable(CAP_SYS_RAWIO)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) scc->stat.bufsize = memcfg.bufsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) case SIOCSCCGSTAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (!arg || copy_to_user(arg, &scc->stat, sizeof(scc->stat)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) case SIOCSCCGKISS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) kiss_cmd.param = scc_get_param(scc, kiss_cmd.command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (copy_to_user(arg, &kiss_cmd, sizeof(kiss_cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) case SIOCSCCSKISS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) if (!capable(CAP_NET_ADMIN)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) return scc_set_param(scc, kiss_cmd.command, kiss_cmd.param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) case SIOCSCCCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) if (!capable(CAP_SYS_RAWIO)) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) if (!arg || copy_from_user(&cal, arg, sizeof(cal)) || cal.time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) scc_start_calibrate(scc, cal.time, cal.pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) /* ----> set interface callsign <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) static int scc_net_set_mac_address(struct net_device *dev, void *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) struct sockaddr *sa = (struct sockaddr *) addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) /* ----> get statistics <---- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) scc->dev_stat.tx_fifo_errors = scc->stat.tx_under;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) return &scc->dev_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) /* * dump statistics to /proc/net/z8530drv * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) static inline struct scc_channel *scc_net_seq_idx(loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) for (k = 0; k < Nchips*2; ++k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (!SCC_Info[k].init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (pos-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) return &SCC_Info[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) static void *scc_net_seq_start(struct seq_file *seq, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) return *pos ? scc_net_seq_idx(*pos - 1) : SEQ_START_TOKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) static void *scc_net_seq_next(struct seq_file *seq, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) unsigned k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) struct scc_channel *scc = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) ++*pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) for (k = (v == SEQ_START_TOKEN) ? 0 : (scc - SCC_Info)+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) k < Nchips*2; ++k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) if (SCC_Info[k].init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) return &SCC_Info[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) static void scc_net_seq_stop(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) static int scc_net_seq_show(struct seq_file *seq, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) if (v == SEQ_START_TOKEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) seq_puts(seq, "z8530drv-"VERSION"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) } else if (!Driver_Initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) seq_puts(seq, "not initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) } else if (!Nchips) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) seq_puts(seq, "chips missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) const struct scc_channel *scc = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) const struct scc_stat *stat = &scc->stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) const struct scc_kiss *kiss = &scc->kiss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) /* dev data ctrl irq clock brand enh vector special option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) * baud nrz clocksrc softdcd bufsize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) * rxints txints exints spints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) * rcvd rxerrs over / xmit txerrs under / nospace bufsize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) * txd pers slot tail ful wait min maxk idl defr txof grp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) * W ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) * R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) seq_printf(seq, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) scc->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) scc->enhanced, Vector_Latch, scc->special,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) scc->option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) seq_printf(seq, "\t%lu %d %d %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) scc->modem.speed, scc->modem.nrz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) scc->modem.clocksrc, kiss->softdcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) stat->bufsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) seq_printf(seq, "\t%lu %lu %lu %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) stat->rxints, stat->txints, stat->exints, stat->spints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) seq_printf(seq, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) stat->rxframes, stat->rxerrs, stat->rx_over,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) stat->txframes, stat->txerrs, stat->tx_under,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) stat->nospace, stat->tx_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) #define K(x) kiss->x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) seq_printf(seq, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) K(txdelay), K(persist), K(slottime), K(tailtime),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) K(fulldup), K(waittime), K(mintime), K(maxkeyup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) K(idletime), K(maxdefer), K(tx_inhibit), K(group));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) #undef K
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) #ifdef SCC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) seq_printf(seq, "\tW ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) for (reg = 0; reg < 16; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) seq_printf(seq, "%2.2x ", scc->wreg[reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) seq_printf(seq, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) seq_printf(seq, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) for (reg = 3; reg < 8; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) seq_printf(seq, "XX ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) for (reg = 9; reg < 16; reg++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) seq_printf(seq, "%2.2x ", InReg(scc->ctrl, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) seq_printf(seq, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) seq_putc(seq, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) static const struct seq_operations scc_net_seq_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) .start = scc_net_seq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) .next = scc_net_seq_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) .stop = scc_net_seq_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) .show = scc_net_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) #endif /* CONFIG_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) /* * Init SCC driver * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) /* ******************************************************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) static int __init scc_init_driver (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) char devname[IFNAMSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) printk(banner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) sprintf(devname,"%s0", SCC_DriverName);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) rtnl_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) if (scc_net_alloc(devname, SCC_Info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) printk(KERN_ERR "z8530drv: cannot initialize module\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) rtnl_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) proc_create_seq("z8530drv", 0, init_net.proc_net, &scc_net_seq_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) static void __exit scc_cleanup_driver(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) io_port ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) struct scc_channel *scc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) if (Nchips == 0 && (dev = SCC_Info[0].dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) /* Guard against chip prattle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) for (k = 0; k < Nchips; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) if ( (ctrl = SCC_ctrl[k].chan_A) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) Outb(ctrl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) OutReg(ctrl,R9,FHWRES); /* force hardware reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) /* To unload the port must be closed so no real IRQ pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) for (k = 0; k < nr_irqs ; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) if (Ivec[k].used) free_irq(k, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) /* Now clean up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) for (k = 0; k < Nchips*2; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) scc = &SCC_Info[k];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) if (scc->ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) release_region(scc->ctrl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) release_region(scc->data, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) if (scc->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) unregister_netdev(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) free_netdev(scc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) if (Vector_Latch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) release_region(Vector_Latch, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) remove_proc_entry("z8530drv", init_net.proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) MODULE_DESCRIPTION("AX.25 Device Driver for Z8530 based HDLC cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) MODULE_SUPPORTED_DEVICE("Z8530 based SCC cards for Amateur Radio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) module_init(scc_init_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) module_exit(scc_cleanup_driver);