S: Provo, Utah 84606
S: USA
-N: Paul Barton-Davis
-E: pbd@op.net
-D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
-D: Various bugfixes and changes to sound drivers
-S: USA
-
N: Krzysztof G. Baranowski
E: kgb@manjak.knm.org.pl
P: 1024/FA6F16D1 96 D1 1A CF 5F CA 69 EC F9 4F 36 1F 6D 60 7B DA
S: 62-300 Wrzesnia
S: Poland
+N: Paul Barton-Davis
+E: pbd@op.net
+D: Driver for WaveFront soundcards (Turtle Beach Maui, Tropez, Tropez+)
+D: Various bugfixes and changes to sound drivers
+S: USA
+
N: Carlos Henrique Bauer
E: chbauer@acm.org
E: bauer@atlas.unisinos.br
S: USA
N: Alex deVries
-E: puffin@redhat.com
-D: Various SGI parts, bits of HAL2 and Newport
-S: 18 Bernier Terrace
-S: Kanata, Ontario
-S: K2L 2V@
+E: adevries@thepuffingroup.com
+D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
+S: 41.5 William Street
+S: Ottawa, Ontario
+S: K1N 6Z9
S: CANADA
N: Eddie C. Dost
S: London SE16 1GD
S: United Kingdom
+N: Kai Harrekilde-Petersen
+E: khp@olicom.dk
+D: Original author of the ftape-HOWTO, i82078 fdc detection code.
+
N: Bart Hartgers
E: bart@etpmod.phys.tue.nl
D: MTRR emulation with Centaur MCRs
S: 5623 HZ Eindhoven
S: The Netherlands
-N: Kai Harrekilde-Petersen
-E: khp@olicom.dk
-D: Original author of the ftape-HOWTO, i82078 fdc detection code.
-
N: Andrew Haylett
E: ajh@primag.co.uk
D: Selection mechanism
S: 14059 Berlin
S: Germany
+N: David Hinds
+E: dhinds@zen.stanford.edu
+W: http://hyper.stanford.edu/~dhinds
+D: PCMCIA and CardBus stuff, PCMCIA-HOWTO, PCMCIA client drivers
+S: 2019 W. Middlefield Rd #1
+S: Mountain View, CA 94043
+S: USA
+
N: Michael Hipp
E: hippm@informatik.uni-tuebingen.de
D: drivers for the racal ni5210 & ni6510 Ethernet-boards
S: Mid Glamorgan, CF82 8EJ,
S: Wales, United Kingdom
-N: Andreas S. Krebs
-E: akrebs@altavista.net
-D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
-
-N: Andrzej M. Krzysztofowicz
-E: ankry@mif.pg.gda.pl
-D: XT disk driver
-D: Aladdin 1533/1543(C) chipset IDE
-D: PIIX chipset IDE
-S: ul. Matemblewska 1B/10
-S: 80-283 Gdansk
-S: Poland
-
N: Bernhard Kaindl
E: bkaindl@netway.at
E: edv@bartelt.via.at
S: L3R 8B2
S: Canada
+N: Andreas S. Krebs
+E: akrebs@altavista.net
+D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+
N: Russell Kroll
E: rkroll@exploits.org
W: http://www.exploits.org/
S: Colorado Springs, Colorado 80949-9458
S: USA
+N: Andrzej M. Krzysztofowicz
+E: ankry@mif.pg.gda.pl
+D: XT disk driver
+D: Aladdin 1533/1543(C) chipset IDE
+D: PIIX chipset IDE
+S: ul. Matemblewska 1B/10
+S: 80-283 Gdansk
+S: Poland
+
N: Gero Kuhlmann
E: gero@gkminix.han.de
D: mounting root via NFS
S: University of Stuttgart, Germany and
S: Ecole Nationale Superieure des Telecommunications, Paris
-N: Martin von Löwis
-E: loewis@informatik.hu-berlin.de
-D: script binary format
-D: NTFS driver
+N: Jamie Lokier
+E: jamie@imbolc.ucc.ie
+D: Reboot-through-BIOS for broken 486 motherboards
+S: 11 Goodson Walk
+S: Marston
+S: Oxford
+S: OX3 0HX
+S: United Kingdom
N: Mark Lord
E: mlord@pobox.com
S: Nepean, Ontario
S: Canada K2H 6S3
-N: Jamie Lokier
-E: jamie@imbolc.ucc.ie
-D: Reboot-through-BIOS for broken 486 motherboards
-S: 11 Goodson Walk
-S: Marston
-S: Oxford
-S: OX3 0HX
-S: United Kingdom
-
N: Warner Losh
E: imp@village.org
D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
S: Niwot, Colorado 80503
S: USA
+N: Martin von Löwis
+E: loewis@informatik.hu-berlin.de
+D: script binary format
+D: NTFS driver
+
N: H.J. Lu
E: hjl@gnu.ai.mit.edu
D: GCC + libraries hacker
S: 00200 Helsinki
S: Finland
-N: Kai Mäkisara
-E: Kai.Makisara@metla.fi
-D: SCSI Tape Driver
-
N: Hamish Macdonald
E: hamishm@lucent.com
D: Linux/68k port
S: Halifax, Nova Scotia
S: Canada B3J 3C8
+N: Kai Mäkisara
+E: Kai.Makisara@metla.fi
+D: SCSI Tape Driver
+
N: Martin Mares
E: mj@atrey.karlin.mff.cuni.cz
W: http://atrey.karlin.mff.cuni.cz/~mj/
E: acme@conectiva.com.br
W: http://www.conectiva.com.br/~acme
D: wanrouter hacking
+D: USB hacking
+D: miscellaneous Makefile & Config.in fixes
D: Cyclom 2X synchronous card driver
D: i18n for minicom, net-tools, util-linux, fetchmail, etc
-S: Conectiva Informatica LTDA
+S: Conectiva Informática LTDA
S: R. Prof. Rubens Elke Braga, 558 - Parolin
-S: 80220-320 Curitiba - Parana
+S: 80220-320 Curitiba - Paraná
S: Brazil
N: Michael Meskes
S: Lafayette, Indiana 47905
S: USA
-N: Johan Myreen
-E: jem@iki.fi
-D: PS/2 mouse driver writer etc.
-S: Dragonvagen 1 A 13
-S: FIN-00330 Helsingfors
-S: Finland
-
N: Trond Myklebust
E: trond.myklebust@fys.uio.no
D: current NFS client hacker.
S: N-0391 Oslo
S: Norway
+N: Johan Myreen
+E: jem@iki.fi
+D: PS/2 mouse driver writer etc.
+S: Dragonvagen 1 A 13
+S: FIN-00330 Helsingfors
+S: Finland
+
N: Matija Nalis
E: mnalis@jagor.srce.hr
E: mnalis@voyager.hr
S: Tula 300000
S: Russia
+N: Johnnie Peters
+E: jpeters@phx.mcd.mot.com
+D: Motorola PowerPC changes for PReP
+S: 2900 S. Diable Way
+S: Tempe, Arizona 85282
+S: USA
+
N: Kirk Petersen
E: kirk@speakeasy.org
W: http://www.speakeasy.org/~kirk/
S: S-226 64 LUND
S: Sweden
-N: Peter De Schrijver
-E: stud11@cc4.kuleuven.ac.be
-D: Mitsumi CD-ROM driver patches March version
-S: Molenbaan 29
-S: B2240 Zandhoven
-S: Belgium
-
N: Henning P. Schmiedehausen
E: hps@tanstaafl.de
D: added PCI support to the serial driver
E:
D: Macintosh IDE Driver
+N: Peter De Schrijver
+E: stud11@cc4.kuleuven.ac.be
+D: Mitsumi CD-ROM driver patches March version
+S: Molenbaan 29
+S: B2240 Zandhoven
+S: Belgium
+
N: Martin Schulze
E: joey@linux.de
W: http://home.pages.de/~joey/
S: Canada M2N 2Z1
N: Adrian Sun
-E: asun@u.washington.edu
+E: asun@cobaltnet.com
D: hfs support
D: alpha rtc port, random appletalk fixes
S: Department of Zoology, University of Washington
S: Seattle, WA 98195-1800
S: USA
+N: Corey Thomas
+E: corey@world.std.com
+W: http://world.std.com/~corey/index.html
+D: Raylink/WebGear wireless LAN device driver (ray_cs) author
+S: 145 Howard St.
+S: Northborough, MA 01532
+S: USA
+
N: Tommy Thorn
E: Tommy.Thorn@irisa.fr
W: http://www.irisa.fr/prive/thorn/index.html
D: Miscellaneous kernel hacker
D: Cyclom 2X driver hacker
D: linuxconf apache & proftpd module maintainer
-S: Conectiva Informatica LTDA
+S: Conectiva Informática LTDA
S: R. Prof. Rubens Elke Braga, 558 - Parolin
-S: 80220-320 Curitiba - Parana
+S: 80220-320 Curitiba - Paraná
S: Brazil
N: Stefan Traby
S: Tacitusstr. 6
S: D-50968 Köln
+N: Tsu-Sheng Tsao
+E: tsusheng@scf.usc.edu
+D: IGMP(Internet Group Management Protocol) version 2
+S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
+S: Taipei
+S: Taiwan 112
+S: Republic of China
+S: 24335 Delta Drive
+S: Diamond Bar, California 91765
+S: USA
+
N: Theodore Ts'o
E: tytso@mit.edu
D: Random Linux hacker
S: Cambridge, Massachusetts 02139
S: USA
-N: Tsu-Sheng Tsao
-E: tsusheng@scf.usc.edu
-D: IGMP(Internet Group Management Protocol) version 2
-S: 2F 14 ALY 31 LN 166 SEC 1 SHIH-PEI RD
-S: Taipei
-S: Taiwan 112
-S: Republic of China
-S: 24335 Delta Drive
-S: Diamond Bar, California 91765
-S: USA
-
N: Simmule Turner
E: sturner@tele-tv.com
D: Added swapping to filesystem
N: David Weinehall
E: tao@acc.umu.se
-D: NE/2-driver maintainer
+W: http://www.acc.umu.se/~tao/
+W: http://www.acc.umu.se/~mcalinux/
+D: Fixes for the NE/2-driver
D: Miscellaneous MCA-support
+D: Cleanup of the Config-files
+S: Axtorpsvagen 40:20
+S: S-903 37 UMEA
+S: Sweden
N: Matt Welsh
E: mdw@metalab.unc.edu
"indent" has a lot of options, and especially when it comes to comment
re-formatting you may want to take a look at the manual page. But
remember: "indent" is not a fix for bad programming.
+
+
+ Chapter 7: Configuration-files
+
+For configuration options (arch/xxx/config.in, and all the Config.in files),
+somewhat different indentation is used.
+
+An indention level of 3 is used in the code, while the text in the config-
+options should have an indention-level of 2 to indicate dependencies. The
+latter only applies to bool/tristate options. For other options, just use
+common sense. An example:
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM
+ if [ "$CONFIG_BOOM" != "n" ]; then
+ bool ' Output nice messages when you explode' CONFIG_CHEER
+ fi
+fi
+
+Generally, CONFIG_EXPERIMENTAL should surround all options not considered
+stable. All options that are known to trash data (experimental write-
+support for file-systems, for instance) should be denoted (DANGEROUS), other
+Experimental options should be denoted (EXPERIMENTAL).
-This is the new release of a module network device driver for General
-Instruments (also known as NextLevel) SB1000 cable modem board (also
-called internal SURFboard).
-I have tested and I am running this module on kernel 2.0.33.
-Steven N. Hirsch <shirsch@adelphia.net> gave me a diff patch
-(sb1000-1.1.2_127.patch to be applied with 'patch -p') that allows
-you to compile and run the driver with kernel versions 2.1.x.
-Thanks very much Steve!
-
-Here you'll the following files:
-
-- README
-- Makefile
-- sb1000.c the actual device driver
-- cmconfig.c an ifconfig-like program to correctly set the SB1000
-- cmping.c a ping-like program to test your connection
-- ftptest.c a small program to test your connection speed with FTP
- (requires ftplib version >= 3.0)
-
-The directory ppp/ contains the files I am using to connect to MediaOne
-here in Jacksonville, to show how you can use the driver and the cmconfig
-program.
-
-Clemmitt Sigler wrote a very good and useful web page and installation
-script (for Adelphia PowerLink users but easy to port to other ISPs)
-about this SB1000 driver for Linux.
-You can find it here:
- http://home.adelphia.net/~siglercm/sb1000.html
-Thanks very much Clemmitt!
-
-To install and run it:
-- cd sb1000-1.1.2
-- make
-- make install
-- configure the SB1000 card using the isapnp tools setting the correct
- I/O's and IRQ. You can find more info about the isapnp tools at:
- http://www.roestock.demon.co.uk/isapnptools/
- (once you're happy with it, you may want to set the configuration
- at boot time in one of the /etc/init.d/ scripts)
- IMPORTANT NOTICE: after configuring isapnp, please look in the file
- /etc/isapnp.conf for the line beginning with:
- (READPORT
- if it says: '(READPORT 0x0203)' (which should be the default), then
- go to the next step. If instead it says something like:
- '(READPORT 0x020b)' or '(READPORT 0x<another number>)', then please
- follow the instructions at the end of this README file before going
- to the next step.
-- install the PPP configuration files in the /etc/ppp directory; you
- definitely have to change the file ppp@gi-on (the start up file),
- setting the correct login name, the phone number for the PPP connection
- and the frequency (k stands for kHz, M for MHz) for the cablemodem.
- You'll also have to change the last line in the pap-secrets file
- writing your login and password there (read the whole file for more
- site specific configurations).
- You may have to change the firewall file to suit your needs (IPs and
- ports allowed to connect).
-- start the PPP connection with ppp@gi-on and see what happens; you may
- want to set 'pppd' (the last command in the ppp@gi-on file) to debug
- mode adding 'debug' at the end of the command ('pppd' prints its info in
- the file /var/log/messages and/or /var/log/ppp.log). To make sure 'chat'
- s not having problems you may want to add a '-v' (verbose) after the 'chat'
- command in 'ppp-on-dialer' and check the results in /var/log/messages)
-- if everything is working fine you should see after a few seconds a message
- likes this:
- cm0: sb1000 at (0x120,0x310), csn 1, S/N 0x2a0d16d8, IRQ 9.
- sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)
- and ifconfig -a should show you two new interfaces: ppp0 and cm0.
- Typing 'cmconfig cm0' will show you more info about the cablemodem interface.
-- please let me know if you see any other message coming from 'cm0' in
- your '/var/log/messages' or '/var/log/debug' file, to help me debug the
- code
-- also let me know if you have any problem; if everything works (hopefully),
- let me know which speed you can reach downloading the 5Mb test file using
- this driver.
-- if everything seems to work fine but your computer locks up after a while
- (and typically during a lengthy download through the cablemodem), you may
- need to add a short delay in the driver to 'slow down' the SURFboard
- because your PC might not be able to keep up with the transfer rate of
- the SB1000. To do this, edit the 'Makefile' and look for the 'SB1000_DELAY'
- define: uncomment those 'CFLAGS' lines (and comment the default ones)
- and try setting the delay to something like 60 microseconds with:
- '-DSB1000_DELAY=60'; if it still doesn't work or you like playing with
- the driver, you may try other numbers: remember though that the higher
- the delay, the slower the driver (which slows down the rest of the PC
- too when it is actively used). Thanks to Ed Daiga for this tip!
-
-This release has a few things fixed and a better handling of the frame errors.
-
-I also have slightly modified the 'cablemodem' script in the 'ppp' so
-you may interested in having a look at it: I basically have added filtering
-out broadcast messages (you shouldn't get them with a point-to-point
-interface and so far the ones I have received were from hosts trying to
-attack my system) and lower debug levels for the driver to avoid seeing
-the 'frame error' messages (so far noone has noticed any problem with the
-driver even with those messages).
-
-For questions, infos, etc, feel free to email me at:
- fventuri@mediaone.net
-
-Good luck,
-Franco Venturi
-
-Thanks to Edge for his useful comments and to Steven N. Hirsch
-for his patch to run the driver with 2.1.x kernels.
-Thanks also to Ed Daiga for his help in finding that adding a delay
-in the driver fixes some lock up problems with some slow PCs.
-Many thanks to Clemmitt Sigler for his (much needed) web page about the
-SB1000 driver for Linux.
-An interesting URL for Linux + MediaOne (although with an external modem)
-is: http://rlz.ne.mediaone.net/linux/home.shtml
-Today, Sep 22 1998, I finished writing a short utility (ftptest.c) to
-'measure' your cablemodem speed connection in Linux, downloading to
-memory the same file several times. To compile it you need ftplib, version
-3 or above. To run it, type:
- ftptest URL n
-where URL is in the form: ftp://ftp.site.local.isp/pub/testfile
-and n is the number of simultaneous FTP connections that you want to run
-
----------------------------------------------------------------------------
-IMPORTANT NOTICE: if in your file /etc/isapnp.conf, you found something
-like '(READPORT 0x020b)' or '(READPORT 0x<another number>)', (anything
-different from the default 0x0203), you have to change the READ_DATA_PORT
-parameter in the sb1000.c file as follows.
- - edit the sb1000.c file, look for:
- READ_DATA_PORT
- (it should be around line 127 in version 1.1.2)
- - change the value of READ_DATA_PORT to the same value found in
- /etc/isapnp.conf; for instance, if you found a: '(READPORT 0x020b)',
- then in sb1000.c you should have:
- static const int READ_DATA_PORT = 0x20b;
- - save sb1000.c
- - compile and install again the driver
- (i.e. do a 'make' and a 'make install').
+sb1000 is a module network device driver for the General Instrument (also known
+as NextLevel) SURFboard1000 internal cable modem board. This is an ISA card
+which is used by a number of cable TV companies to provide cable modem access.
+It's a one-way downstream-only cable modem, meaning that your upstream net link
+is provided by your regular phone modem.
+
+This driver was written by Franco Venturi <fventuri@mediaone.net>. He deserves
+a great deal of thanks for this wonderful piece of code!
+
+-----------------------------------------------------------------------------
+
+Support for this device is now a part of the standard Linux kernel. The
+driver source code file is drivers/net/sb1000.c. In addition to this
+you will need:
+
+1.) The "cmconfig" program. This is a utility which supplements "ifconfig"
+to configure the cable modem and network interface (usually called "cm0");
+and
+
+2.) Several PPP scripts which live in /etc/ppp to make connecting via your
+cable modem easy.
+
+ These utilities can be obtained from:
+
+ http://www.jacksonville.net/~fventuri/
+
+ in Franco's original source code distribution .tar.gz file. Support for
+ the sb1000 driver can be found at:
+
+ http://home.adelphia.net/~siglercm/sb1000.html
+ http://linuxpower.cx/~cable/
+
+ along with these utilties.
+
+3.) The standard isapnp tools. These are necessary to configure your SB1000
+card at boot time (or afterwards by hand) since it's a PnP card.
+
+ If you don't have these installed as a standard part of your Linux
+ distribution, you can find them at:
+
+ http://www.roestock.demon.co.uk/isapnptools/
+
+ or check your Linux distribution binary CD or their web site. For help with
+ isapnp, pnpdump, or /etc/isapnp.conf, go to:
+
+ http://www.roestock.demon.co.uk/isapnptools/isapnpfaq.html
+
+-----------------------------------------------------------------------------
+
+To make the SB1000 card work, follow these steps:
+
+1.) Run `make config', or `make menuconfig', or `make xconfig', whichever
+you prefer, in the top kernel tree directory to set up your kernel
+configuration. Make sure to say "Y" to "Prompt for development drivers"
+and to say "M" to the sb1000 driver. Also say "Y" or "M" to all the standard
+networking questions to get TCP/IP and PPP networking support.
+
+2.) *BEFORE* you build the kernel, edit drivers/net/sb1000.c. Make sure
+to redefine the value of READ_DATA_PORT to match the I/O address used
+by isapnp to access your PnP cards. This is the value of READPORT in
+/etc/isapnp.conf or given by the output of pnpdump.
+
+3.) Build and install the kernel and modules as usual.
+
+4.) Boot your new kernel following the usual procedures.
+
+5.) Set up to configure the new SB1000 PnP card by capturing the output
+of "pnpdump" to a file and editing this file to set the correct I/O ports,
+IRQ, and DMA settings for all your PnP cards. Make sure none of the settings
+conflict with one another. Then test this configuration by running the
+"isapnp" command with your new config file as the input. Check for
+errors and fix as necessary. (As an aside, I use I/O ports 0x110 and
+0x310 and IRQ 11 for my SB1000 card and these work well for me. YMMV.)
+Then save the finished config file as /etc/isapnp.conf for proper configuration
+on subsequent reboots.
+
+6.) Download the original file sb1000-1.1.2.tar.gz from Franco's site or one of
+the others referenced above. As root, unpack it into a temporary directory and
+do a `make cmconfig' and then `install -c cmconfig /usr/local/sbin'. Don't do
+`make install' because it expects to find all the utilities built and ready for
+installation, not just cmconfig.
+
+7.) As root, copy all the files under the ppp/ subdirectory in Franco's
+tar file into /etc/ppp, being careful not to overwrite any files that are
+already in there. Then modify ppp@gi-on to set the correct login name,
+phone number, and frequency for the cable modem. Also edit pap-secrets
+to specify your login name and password and any site-specific information
+you need.
+
+8.) Be sure to modify /etc/ppp/firewall to use ipchains instead of
+the older ipfwadm commands from the 2.0.x kernels. There's a neat utility to
+convert ipfwadm commands to ipchains commands:
+
+ http://users.dhp.com/~whisper/ipfwadm2ipchains/
+
+You may also wish to modify the firewall script to implement a different
+firewalling scheme.
+
+9.) Start the PPP connection via the script /etc/ppp/ppp@gi-on. You must be
+root to do this. It's better to use a utility like sudo to execute
+frequently used commands like this with root permissions if possible. If you
+connect successfully the cable modem interface will come up and you'll see a
+driver message like this at the console:
+
+ cm0: sb1000 at (0x110,0x310), csn 1, S/N 0x2a0d16d8, IRQ 11.
+ sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)
+
+The "ifconfig" command should show two new interfaces, ppp0 and cm0.
+The command "cmconfig cm0" will give you information about the cable modem
+interface.
+
+10.) Try pinging a site via `ping -c 5 www.yahoo.com', for example. You should
+see packets received.
+
+11.) If you can't get site names (like www.yahoo.com) to resolve into
+IP addresses (like 204.71.200.67), be sure your /etc/resolv.conf file
+has no syntax errors and has the right nameserver IP addresses in it.
+If this doesn't help, try something like `ping -c 5 204.71.200.67' to
+see if the networking is running but the DNS resolution is where the
+problem lies.
+
+12.) If you still have problems, go to the support web sites mentioned above
+and read the information and documentation there.
+
+-----------------------------------------------------------------------------
+
+Common problems:
+
+1.) Packets go out on the ppp0 interface but don't come back on the cm0
+interface. It looks like I'm connected but I can't even ping any
+numerical IP addresses. (This happens predominantly on Debian systems due
+to a default boot-time configuration script.)
+
+Solution -- As root `echo 0 > /proc/sys/net/ipv4/conf/cm0/rp_filter' so it
+can share the same IP address as the ppp0 interface. Note that this
+command should probably be added to the /etc/ppp/cablemodem script
+*right*between* the "/sbin/ifconfig" and "/sbin/cmconfig" commands.
+You may need to do this to /proc/sys/net/ipv4/conf/ppp0/rp_filter as well.
+If you do this to /proc/sys/net/ipv4/conf/default/rp_filter on each reboot
+(in rc.local or some such) then any interfaces can share the same IP
+addresses.
+
+2.) I get "unresolved symbol" error messages on executing `insmod sb1000.o'.
+
+Solution -- You probably have a non-matching kernel source tree and
+/usr/include/linux and /usr/include/asm header files. Make sure you
+install the correct versions of the header files in these two directories.
+Then rebuild and reinstall the kernel.
+
+3.) When isapnp runs it reports an error, and my SB1000 card isn't working.
+
+Solution -- There's a problem with later versions of isapnp using the "(CHECK)"
+option in the lines that allocate the two I/O addresses for the SB1000 card.
+This first popped up on RH 6.0. Delete "(CHECK)" for the SB1000 I/O addresses.
+Make sure they don't conflict with any other pieces of hardware first! Then
+rerun isapnp and go from there.
+
+4.) I can't execute the /etc/ppp/ppp@gi-on file.
+
+Solution -- As root do `chmod ug+x /etc/ppp/ppp@gi-on'.
+
+5.) The firewall script isn't working (with 2.2.x and higher kernels).
+
+Solution -- Use the ipfwadm2ipchains script referenced above to convert the
+/etc/ppp/firewall script from the deprecated ipfwadm commands to ipchains.
+
+6.) I'm getting *tons* of firewall deny messages in the /var/kern.log,
+/var/messages, and/or /var/syslog files, and they're filling up my /var
+partition!!!
+
+Solution -- First, tell your ISP that you're receiving DoS (Denial of Service)
+and/or portscanning (UDP connection attempts) attacks! Look over the deny
+messages to figure out what the attack is and where it's coming from. Next,
+edit /etc/ppp/cablemodem and make sure the ",nobroadcast" option is turned on
+to the "cmconfig" command (uncomment that line). If you're not receiving these
+denied packets on your broadcast interface (IP address xxx.yyy.zzz.255
+typically), then someone is attacking your machine in particular. Be careful
+out there....
+
+7.) Everything seems to work fine but my computer locks up after a while
+(and typically during a lengthy download through the cable modem)!
+
+Solution -- You may need to add a short delay in the driver to 'slow down' the
+SURFboard because your PC might not be able to keep up with the transfer rate
+of the SB1000. To do this, it's probably best to download Franco's
+sb1000-1.1.2.tar.gz archive and build and install sb1000.o manually. You'll
+want to edit the 'Makefile' and look for the 'SB1000_DELAY'
+define. Uncomment those 'CFLAGS' lines (and comment out the default ones)
+and try setting the delay to something like 60 microseconds with:
+'-DSB1000_DELAY=60'. Then do `make' and as root `make install' and try
+it out. If it still doesn't work or you like playing with the driver, you may
+try other numbers. Remember though that the higher the delay, the slower the
+driver (which slows down the rest of the PC too when it is actively
+used). Thanks to Ed Daiga for this tip!
+
+-----------------------------------------------------------------------------
+
+Credits: This README came from Franco Venturi's original README file which is
+still supplied with his driver .tar.gz archive. I and all other sb1000 users
+owe Franco a tremendous "Thank you!" Additional thanks goes to Carl Patten
+and Ralph Bonnell who are now managing the Linux SB1000 web site, and to
+the SB1000 users who reported and helped debug the common problems listed
+above.
+
+
+ Clemmitt Sigler
+ csigler@vt.edu
job the maintainers (and especially Linus) do is to keep things
looking the same. Sometimes this means that the clever hack in
your driver to get around a problem actually needs to become a
- generalized kernel feature ready for next time. See
+ generalized kernel feature ready for next time. See
Documentation/CodingStyle for guidance here.
PLEASE try to include any credit lines you want added with the
Maintained: Someone actually looks after it.
Odd Fixes: It has a maintainer but they don't have time to do
much other than throw the odd patch in. See below..
- Orphan: No current maintainer [but maybe you could take the
+ Orphan: No current maintainer [but maybe you could take the
role as you write your new code].
Obsolete: Old code. Something tagged obsolete generally means
it has been replaced by a better system and you
L: linux-atalk@netspace.org
S: Maintained
-ARPD SUPPORT
-P: Jonathan Layes
-M: layes@loran.com
-L: linux-net@vger.rutgers.edu
-S: Maintained
-
ARM MFM AND FLOPPY DRIVERS
P: Dave Gilbert
M: linux@treblig.org
W: http://www.arm.uk.linux.org/~rmk/armlinux.html
S: Maintained
+ARPD SUPPORT
+P: Jonathan Layes
+M: layes@loran.com
+L: linux-net@vger.rutgers.edu
+S: Maintained
+
AX.25 NETWORK LAYER
P: Matthias Welwarsky
M: dg2fef@afthd.tu-darmstadt.de
L: linux-fbdev@vuser.vu.union.edu
S: Maintained
+COMPAQ SMART2 RAID DRIVER
+P: Charles White
+M: Charles White <arrays@compaq.com>
+L: compaqandlinux@yps.org
+S: Maintained
+
COMPUTONE INTELLIPORT MULTIPORT CARD
P: Doug McNash
P: Michael H. Warfield
L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu
S: Maintained
-COMPAQ SMART2 RAID DRIVER
-P: Charles White
-M: Charles White <arrays@compaq.com>
-L: compaqandlinux@yps.org
-S: Maintained
-
EATA ISA/EISA/PCI SCSI DRIVER
P: Dario Ballabio
M: dario@milano.europe.dg.com
HFS FILESYSTEM
P: Adrian Sun
-M: asun@u.washington.edu
+M: asun@cobaltnet.com
L: linux-kernel@vger.rutgers.edu
S: Maintained
M: perex@suse.cz
S: Maintained
+HPFS FILESYSTEM
+P: Mikulas Patocka
+M: mikulas@artax.karlin.mff.cuni.cz
+W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
+S: Maintained
+
IBM MCA SCSI SUBSYSTEM DRIVER
P: Michael Lang
M: langa2@kph.uni-mainz.de
W: http://www.uni-mainz.de/~langm000/linux.html
S: Maintained
-HPFS FILESYSTEM
-P: Mikulas Patocka
-M: mikulas@artax.karlin.mff.cuni.cz
-W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
-S: Maintained
+IBM ServeRAID RAID DRIVER
+P: Keith Mitchell
+M: ipslinux@us.ibm.com
+W: http://www.developer.ibm.com/welcome/netfinity/serveraid_beta.html
+S: Supported
IBM ServeRAID RAID DRIVER
P: Keith Mitchell
W: http://linux.kernel.org/pub/linux/kernel/people/hedrick/
S: Supported
-IDE/ATAPI CDROM DRIVER
+IDE/ATAPI CDROM DRIVER
P: Jens Axboe
M: axboe@image.dk
L: linux-kernel@vger.rutgers.edu
MISCELLANEOUS MCA-SUPPORT
P: David Weinehall
-M: mcalinux@acc.umu.se (project MCA-team)
M: tao@acc.umu.se (personal)
+W: http://www.acc.umu.se/~tao/
+W: http://www.acc.umu.se/~mcalinux/
L: linux-kernel@vger.rutgers.edu
S: Maintained
S: Supported
NETROM NETWORK LAYER
-P: Tomi Manninen
+P: Tomi Manninen
M: Tomi.Manninen@hut.fi
L: linux-hams@vger.rutgers.edu
S: Maintained
W: http://www.linuxtr.net
S: Maintained
-OLYMPIC NETWORK DRIVER
-P: Peter De Shrijver
-M: p2@ace.ulyssis.sutdent.kuleuven.ac.be
-P: Mike Phillips
-M: phillim@amtrak.com
-L: linux-net@vger.rutgers.edu
-L: linux-tr@emissary.aus-etc.com
-W: http://www.linuxtr.net
-S: Maintained
-
OPL3-SA2, SA3, and SAx DRIVER
P: Scott Murray
M: scottm@interlog.com
M: jmaurer@cck.uni-kl.de
S: Maintained
+PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES)
+P: Thomas Sailer
+M: sailer@ife.ee.ethz.ch
+L: linux-sound@vger.rutgers.edu
+W: http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html
+S: Maintained
+
PCI SUBSYSTEM
P: Martin Mares
M: mj@atrey.karlin.mff.cuni.cz
L: linux-kernel@vger.rutgers.edu
S: Maintained
-PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES)
-P: Thomas Sailer
-M: sailer@ife.ee.ethz.ch
-L: linux-sound@vger.rutgers.edu
-W: http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html
+PCMCIA SUBSYSTEM
+P: David Hinds
+M: dhinds@zen.stanford.edu
+L: linux-kernel@vger.rutgers.edu
S: Maintained
PCNET32 NETWORK DRIVER
L: linux-ppp@vger.rutgers.edu
S: Maintained
+RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
+P: Corey Thomas
+M: corey@world.std.com
+L: linux-kernel@vger.rutgers.edu
+S: Maintained
+
REAL TIME CLOCK DRIVER
P: Paul Gortmaker
M: p_gortmaker@yahoo.com
L: linux-kernel@vger.rutgers.edu
S: Maintained
-SCSI CDROM DRIVER
+SCSI CDROM DRIVER
P: Jens Axboe
M: axboe@image.dk
L: linux-kernel@vger.rutgers.edu
S: Maintained
SOUND
-P: Alan Cox
+P: Alan Cox
M: alan@redhat.com
S: Supported
L: linux-kernel@vger.rutgers.edu
S: Maintained
-UNIFORM CDROM DRIVER
+UNIFORM CDROM DRIVER
P: Jens Axboe
M: axboe@image.dk
L: linux-kernel@vger.rutgers.edu
W: http://bmrc.berkeley.edu/people/chaffee
S: Maintained
+VIA 82Cxxx AUDIO DRIVER
+P: Jeff Garzik
+M: jgarzik@pobox.com
+S: Maintained
+
VIDEO FOR LINUX
P: Alan Cox
M: Alan.Cox@linux.org
# PCMCIA network devices
#
# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_3C589 is not set
CONFIG_PCMCIA_RAYCS=y
#
#endif
/*
- * Set the clock to 100 Hz, we already have a valid
+ * Set the clock to HZ Hz, we already have a valid
* vector now:
*/
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
19990512 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.35
+ 19990707 Zoltan Boszormenyi <zboszor@mol.hu>
+ Check whether ARR3 is protected in cyrix_get_free_region()
+ and mtrr_del(). The code won't attempt to delete or change it
+ from now on if the BIOS protected ARR3. It silently skips ARR3
+ in cyrix_get_free_region() or returns with an error code from
+ mtrr_del().
+ 19990711 Zoltan Boszormenyi <zboszor@mol.hu>
+ Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
+ if ARR3 isn't protected. This is needed because if SMM is active
+ and ARR3 isn't protected then deleting and setting ARR3 again
+ may lock up the processor. With SMM entirely disabled, it does
+ not happen.
+ 19990812 Zoltan Boszormenyi <zboszor@mol.hu>
+ Rearrange switch() statements so the driver accomodates to
+ the fact that the AMD Athlon handles its MTRRs the same way
+ as Intel does.
+ 19990814 Zoltan Boszormenyi <zboszor@mol.hu>
+ Double check for Intel in mtrr_add()'s big switch() because
+ that revision check is only valid for Intel CPUs.
+ 19990819 Alan Cox <alan@redhat.com>
+ Tested Zoltan's changes on a pre production Athlon - 100%
+ success.
*/
#include <linux/types.h>
#include <linux/errno.h>
unsigned long ccr3;
};
+static int arr3_protected;
/* Put the processor into a state where MTRRs can be safely set */
static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_CENTAUR:
return;
/*break;*/
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
/* Disable MTRRs, and set the default type to uncached */
rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_CENTAUR:
__restore_flags (ctxt->flags);
return;
/* Restore MTRRdefType */
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
case X86_VENDOR_INTEL:
wrmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
break;
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) return 2; /* pre-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_INTEL:
rdmsr (MTRRcap_MSR, config, dummy);
return (config & 0xff);
/* and Centaur has 8 MCR's */
return 8;
/*break;*/
- case X86_VENDOR_AMD:
- return 2;
- /*break;*/
}
return 0;
} /* End Function get_num_var_ranges */
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) return 1; /* pre-Athlon CPUs */
+ /* else fall through */
case X86_VENDOR_INTEL:
rdmsr (MTRRcap_MSR, config, dummy);
return (config & (1<<10));
/*break;*/
case X86_VENDOR_CYRIX:
- case X86_VENDOR_AMD:
case X86_VENDOR_CENTAUR:
return 1;
/*break;*/
for (i = 0; i < 7; i++)
{
cyrix_get_arr (i, &lbase, &lsize, <ype);
+ if ((i == 3) && arr3_protected) continue;
if (lsize < 1) return i;
}
/* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
+ /* Apply the K6 block alignment and size rules
+ In order
+ o Uncached or gathering only
+ o 128K or bigger block
+ o Power of 2 block
+ o base suitably aligned to the power
+ */
+ if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ (size & ~(size-1))-size || (base & (size-1)))
+ return -EINVAL;
+ break;
+ } /* else fall through */
case X86_VENDOR_INTEL:
- /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
- if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
- (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
- {
- printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
- return -EINVAL;
+ /* Double check for Intel, we may run on Athlon. */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+ /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
+ if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
+ (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
+ {
+ printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ return -EINVAL;
+ }
}
/* Fall through */
case X86_VENDOR_CYRIX:
return -EINVAL;
}
break;
- case X86_VENDOR_AMD:
- /* Apply the K6 block alignment and size rules
- In order
- o Uncached or gathering only
- o 128K or bigger block
- o Power of 2 block
- o base suitably aligned to the power
- */
- if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
- (size & ~(size-1))-size || (base & (size-1)))
- return -EINVAL;
- break;
default:
return -EINVAL;
/*break;*/
printk ("mtrr: register: %d too big\n", reg);
return -EINVAL;
}
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX)
+ {
+ if ((reg == 3) && arr3_protected)
+ {
+ spin_unlock (&main_lock);
+ printk ("mtrr: ARR3 cannot be changed\n");
+ return -EINVAL;
+ }
+ }
(*get_mtrr) (reg, &lbase, &lsize, <ype);
if (lsize < 1)
{
ccr[5] = getCx86 (CX86_CCR5);
ccr[6] = getCx86 (CX86_CCR6);
- if (ccr[3] & 1)
+ if (ccr[3] & 1) {
ccrc[3] = 1;
- else {
+ arr3_protected = 1;
+ } else {
/* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
* access to SMM memory through ARR3 (bit 7).
*/
-/*
if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
-*/
+ arr3_protected = 0;
if (ccr[6] & 0x02) {
ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3. */
setCx86 (CX86_CCR6, ccr[6]);
}
- /* Disable ARR3. */
+ /* Disable ARR3. This is safe now that we disabled SMM. */
/* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
}
/* If we changed CCR1 in memory, change it in the processor, too. */
printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION);
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
+ get_mtrr = amd_get_mtrr;
+ set_mtrr_up = amd_set_mtrr_up;
+ break;
+ } /* else fall through */
case X86_VENDOR_INTEL:
get_mtrr = intel_get_mtrr;
set_mtrr_up = intel_set_mtrr_up;
set_mtrr_up = cyrix_set_arr_up;
get_free_region = cyrix_get_free_region;
break;
- case X86_VENDOR_AMD:
- get_mtrr = amd_get_mtrr;
- set_mtrr_up = amd_set_mtrr_up;
- break;
case X86_VENDOR_CENTAUR:
get_mtrr = centaur_get_mcr;
set_mtrr_up = centaur_set_mcr_up;
mtrr_setup ();
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
case X86_VENDOR_INTEL:
get_mtrr_state (&smp_mtrr_state);
break;
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ /* Just for robustness: pre-Athlon CPUs cannot do SMP. */
+ if (boot_cpu_data.x86 < 6) break;
case X86_VENDOR_INTEL:
intel_mtrr_init_secondary_cpu ();
break;
# ifdef __SMP__
switch (boot_cpu_data.x86_vendor)
{
+ case X86_VENDOR_AMD:
+ if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
case X86_VENDOR_INTEL:
finalize_mtrr_state (&smp_mtrr_state);
mtrr_state_warn (smp_changes_mask);
#include <asm/msr.h>
#include <asm/desc.h>
#include <asm/e820.h>
+#include <asm/dma.h>
/*
* Machine setup..
void __init setup_memory_region(void)
{
+#define E820_DEBUG 0
+#ifdef E820_DEBUG
+ int i;
+#endif
+
/*
* If we're lucky and live on a modern system, the setup code
* will have given us a memory map that we can use to properly
* set up memory. If we aren't, we'll fake a memory map.
+ *
+ * We check to see that the memory map contains at least 2 elements
+ * before we'll use it, because the detection code in setup.S may
+ * not be perfect and most every PC known to man has two memory
+ * regions: one from 0 to 640k, and one from 1mb up. (The IBM
+ * thinkpad 560x, for example, does not cooperate with the memory
+ * detection code.)
*/
- if (E820_MAP_NR) {
+ if (E820_MAP_NR > 1) {
/* got a memory map; copy it into a safe place.
*/
e820.nr_map = E820_MAP_NR;
if (e820.nr_map > E820MAX)
e820.nr_map = E820MAX;
memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
+#ifdef E820_DEBUG
+ for (i=0; i < e820.nr_map; i++) {
+ printk("e820: %ld @ %08lx ",
+ (unsigned long)(e820.map[i].size),
+ (unsigned long)(e820.map[i].addr));
+ switch (e820.map[i].type) {
+ case E820_RAM: printk("(usable)\n");
+ break;
+ case E820_RESERVED:
+ printk("(reserved)\n");
+ break;
+ case E820_ACPI:
+ printk("(ACPI data)\n");
+ break;
+ default: printk("type %lu\n", e820.map[i].type);
+ break;
+ }
+ }
+#endif
}
else {
/* otherwise fake a memory map; one section from 0k->640k,
mem_size = (ALT_MEM_K < EXT_MEM_K) ? EXT_MEM_K : ALT_MEM_K;
- add_memory_region(0, LOWMEMSIZE(), 1);
- add_memory_region(HIGH_MEMORY, mem_size << 10, 1);
+ add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+ add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
}
} /* setup_memory_region */
*/
e820.nr_map = 0;
usermem = 1;
- add_memory_region(0, LOWMEMSIZE(), 1);
+ add_memory_region(0, LOWMEMSIZE(), E820_RAM);
}
mem_size = memparse(from+4, &from);
if (*from == '@')
start_at = HIGH_MEMORY;
mem_size -= HIGH_MEMORY;
}
- add_memory_region(start_at, mem_size, 1);
+ add_memory_region(start_at, mem_size, E820_RAM);
}
}
c = *(from++);
memory_end = 0;
for (i=0; i < e820.nr_map; i++) {
/* RAM? */
- if (e820.map[i].type == 1) {
+ if (e820.map[i].type == E820_RAM) {
unsigned long end = e820.map[i].addr + e820.map[i].size;
if (end > memory_end)
c->x86_model = (dir1 & 0x20) ? 1 : 2;
c->x86_capability&=~X86_FEATURE_TSC;
}
+#ifdef CONFIG_PCI
+ /* It isnt really a PCI quirk directly, but the cure is the
+ same. The MediaGX has deep magic SMM stuff that handles the
+ SB emulation. It thows away the fifo on disable_dma() which
+ is wrong and ruins the audio. */
+
+ printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bug.\n");
+ isa_dma_bridge_buggy = 1;
+#endif
break;
case 5: /* 6x86MX/M II */
dir0_msn = 0;
p = Cx486S_name[0];
break;
- break;
}
+ break;
default: /* unknown (shouldn't happen, we know everyone ;-) */
dir0_msn = 7;
for (avail = i = 0; i < e820.nr_map; i++) {
unsigned long addr, end, size;
- if (e820.map[i].type != 1) /* not usable memory */
+ if (e820.map[i].type != E820_RAM) /* not usable memory */
continue;
addr = e820.map[i].addr;
size = e820.map[i].size;
- /* Overflow large memory reasonably gracefully */
+ /* Silently ignore memory regions starting above 4gb */
if (addr != e820.map[i].addr)
continue;
printk("memory region: %luk @ %08lx\n", size >> 10, addr );
/* Make sure we don't get fractional pages */
- end = (addr + size) & PAGE_MASK;
- addr = PAGE_ALIGN(addr);
- if (end <= addr)
- continue;
+ end = PAGE_OFFSET + ((addr + size) & PAGE_MASK);
+ addr= PAGE_OFFSET + PAGE_ALIGN(addr);
+
+ for ( ; addr < end; addr += PAGE_SIZE) {
- size = end - addr;
- for (addr = addr + PAGE_OFFSET ; size ; addr += PAGE_SIZE, size -= PAGE_SIZE) {
/* this little bit of grossness is for dealing
* with memory borrowing for system bookkeeping
* (smp stacks, zero page, kernel code, etc)
* in any case, we don't want to hack mem_map
* entries above end_mem.
*/
- if ( addr < start_low_mem )
- continue;
- if ( addr > end_mem )
- continue;
- if ( addr >= HIGH_MEMORY && addr <= start_mem )
+ if ( (addr < start_low_mem)
+ || (addr >= (HIGH_MEMORY + PAGE_OFFSET)&& addr <= start_mem)
+ || (addr > end_mem) )
continue;
- avail++;
clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
}
}
return 0;
} else {
- spin_unlock_irqrestore (&dev->lock, flags);
+ spin_unlock_irqrestore (&txq->lock, flags);
return -1;
}
}
#include <linux/major.h>
#include <linux/malloc.h>
#include <linux/mm.h>
-#if LINUX_VERSION_CODE >= 0x020100
#include <linux/poll.h>
-#endif
#include <linux/pci.h>
#include <linux/signal.h>
#include <asm/io.h>
#include <linux/wrapper.h>
#include <linux/interrupt.h>
-#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
#include <linux/vmalloc.h>
-#else
-#include <linux/bios32.h>
-#define mdelay(x) udelay((x)*1000)
-#define signal_pending(current) (current->signal & ~current->blocked)
-#define sigfillset(set)
-
-static inline int time_before(unsigned long a, unsigned long b)
-{
- return((long)((a) - (b)) < 0L);
-}
-
-static inline unsigned long
-copy_to_user(void *to, const void *from, unsigned long n)
-{
- memcpy_tofs(to,from,n);
- return 0;
-}
-
-static inline unsigned long
-copy_from_user(void *to, const void *from, unsigned long n)
-{
- memcpy_fromfs(to,from,n);
- return 0;
-}
-#define ioremap vremap
-#define iounmap vfree
-#endif
#include <linux/videodev.h>
#include <linux/i2c.h>
#define DEBUG(x) /* Debug driver */
#define IDEBUG(x) /* Debug interrupt handler */
-#if LINUX_VERSION_CODE >= 0x020117
-MODULE_PARM(vidmem,"i");
-MODULE_PARM(triton1,"i");
-MODULE_PARM(remap,"1-4i");
-MODULE_PARM(radio,"1-4i");
-MODULE_PARM(card,"1-4i");
-MODULE_PARM(pll,"1-4i");
-#endif
/* Anybody who uses more than four? */
#define BTTV_MAX 4
-static int find_vga(void);
static void bt848_set_risc_jmps(struct bttv *btv);
static unsigned int vidmem=0; /* manually set video mem address */
}
}
+MODULE_PARM(vidmem,"i");
+MODULE_PARM(triton1,"i");
+MODULE_PARM(remap,"1-4i");
+MODULE_PARM(radio,"1-4i");
+MODULE_PARM(card,"1-4i");
+MODULE_PARM(pll,"1-4i");
/*
}
}
-void attach_inform(struct i2c_bus *bus, int id)
+static void attach_inform(struct i2c_bus *bus, int id)
{
struct bttv *btv = (struct bttv*)bus->data;
}
}
-void detach_inform(struct i2c_bus *bus, int id)
+static void detach_inform(struct i2c_bus *bus, int id)
{
struct bttv *btv = (struct bttv*)bus->data;
/* MIRO PCTV pro */
{ 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
/* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
- { 3, 4, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
+ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
/* AVerMedia TVCapture 98 */
{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
/* Aimslab VHX */
static int bttv_open(struct video_device *dev, int flags)
{
struct bttv *btv = (struct bttv *)dev;
- int users, i;
-
+ int i, ret;
+
+ ret = -EBUSY;
+ down(&btv->lock);
if (btv->user)
- return -EBUSY;
- audio(btv, AUDIO_UNMUTE);
- for (i=users=0; i<bttv_num; i++)
- users+=bttvs[i].user;
- if (users==1)
- find_vga();
- btv->fbuffer=NULL;
- if (!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+ goto out_unlock;
+
+ btv->fbuffer= (unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+ ret = -ENOMEM;
if (!btv->fbuffer)
- return -EINVAL;
+ goto out_unlock;
+ audio(btv, AUDIO_UNMUTE);
btv->grabbing = 0;
btv->grab = 0;
btv->lastgrab = 0;
btv->frame_stat[i] = GBUFFER_UNUSED;
btv->user++;
+ up(&btv->lock);
MOD_INC_USE_COUNT;
return 0;
+
+ out_unlock:
+ up(&btv->lock);
+ return ret;
}
static void bttv_close(struct video_device *dev)
{
struct bttv *btv=(struct bttv *)dev;
-
+
+ down(&btv->lock);
btv->user--;
audio(btv, AUDIO_INTERN);
btv->cap&=~3;
if(btv->fbuffer)
rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);
btv->fbuffer=0;
+ up(&btv->lock);
MOD_DEC_USE_COUNT;
}
if (v.channel>tvcards[btv->type].video_inputs)
return -EINVAL;
- bt848_muxsel(btv, v.channel);
if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
&&v.norm!=VIDEO_MODE_SECAM)
return -EOPNOTSUPP;
+ down(&btv->lock);
+ bt848_muxsel(btv, v.channel);
btv->win.norm = v.norm;
make_vbitab(btv);
bt848_set_winsize(btv);
btv->channel=v.channel;
+ up(&btv->lock);
return 0;
}
case VIDIOCGTUNER:
&&v.mode!=VIDEO_MODE_SECAM)
return -EOPNOTSUPP;
btv->win.norm = v.mode;
+ down(&btv->lock);
bt848_set_winsize(btv);
+ up(&btv->lock);
return 0;
}
case VIDIOCGPICT:
int format;
if(copy_from_user(&p, arg,sizeof(p)))
return -EFAULT;
+ down(&btv->lock);
/* We want -128 to 127 we get 0-65535 */
bt848_bright(btv, (p.brightness>>8)-128);
/* 0-511 for the colour */
if (fmtbppx2[format&0x0f]/2 == btv->win.bpp)
btv->win.color_fmt = format;
}
+ up(&btv->lock);
return 0;
}
case VIDIOCSWIN:
if(vw.flags || vw.width < 16 || vw.height < 16)
{
+ down(&btv->lock);
bt848_cap(btv,0);
+ up(&btv->lock);
return -EINVAL;
}
if (btv->win.bpp < 4)
i = vw.x - i;
vw.width -= i;
}
+
+ down(&btv->lock);
btv->win.x=vw.x;
btv->win.y=vw.y;
btv->win.width=vw.width;
bt848_cap(btv,0);
bt848_set_winsize(btv);
+
+ up(&btv->lock);
/*
* Do any clips.
return -EFAULT;
}
}
+ down(&btv->lock);
make_clip_tab(btv, vcp, vw.clipcount);
if (vw.clipcount != 0)
vfree(vcp);
if(on && btv->win.vidadr!=0)
bt848_cap(btv,1);
+ up(&btv->lock);
return 0;
}
case VIDIOCGWIN:
int v;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
+ if(v!=0 && (btv->win.vidadr==0 || btv->win.width==0
+ || btv->win.height==0))
+ return -EINVAL;
+
+ down(&btv->lock);
if(v==0)
- {
bt848_cap(btv,0);
- }
else
- {
- if(btv->win.vidadr==0 || btv->win.width==0
- || btv->win.height==0)
- return -EINVAL;
bt848_cap(btv,1);
- }
+ up(&btv->lock);
+
return 0;
}
case VIDIOCGFBUF:
v.depth!=24 && v.depth!=32 && v.width > 16 &&
v.height > 16 && v.bytesperline > 16)
return -EINVAL;
+ down(&btv->lock);
if (v.base)
btv->win.vidadr=(unsigned long)v.base;
btv->win.sheight=v.height;
DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
v.base, v.width,v.height, btv->win.bpp, btv->win.bpl));
bt848_set_winsize(btv);
+ up(&btv->lock);
return 0;
}
case VIDIOCKEY:
struct video_audio v;
if(copy_from_user(&v,arg, sizeof(v)))
return -EFAULT;
+ down(&btv->lock);
if(v.flags&VIDEO_AUDIO_MUTE)
audio(btv, AUDIO_MUTE);
/* One audio source per tuner */
/* if(v.audio!=0) */
/* ADSTech TV card has more than one */
if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
+ {
+ up(&btv->lock);
return -EINVAL;
+ }
bt848_muxsel(btv,v.audio);
if(!(v.flags&VIDEO_AUDIO_MUTE))
audio(btv, AUDIO_UNMUTE);
MSP_SET_STEREO,&(v.mode));
}
btv->audio_dev=v;
+ up(&btv->lock);
return 0;
}
return 0;
case BTTV_WRITEE:
-#if LINUX_VERSION_CODE >= 0x020100
- if(!capable(CAP_SYS_ADMIN)
- || !capable(CAP_SYS_RAWIO))
-#else
- if(!suser())
-#endif
+ if(!capable(CAP_SYS_ADMIN))
return -EPERM;
if(copy_from_user((void *) eedata, (void *) arg, 256))
return -EFAULT;
+ down(&btv->lock);
writeee(&(btv->i2c), eedata);
+ up(&btv->lock);
return 0;
case BTTV_READEE:
-#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
-#else
- if(!suser())
-#endif
return -EPERM;
+ down(&btv->lock);
readee(&(btv->i2c), eedata);
+ up(&btv->lock);
if(copy_to_user((void *) arg, (void *) eedata, 256))
return -EFAULT;
break;
case BTTV_PLLSET: {
struct bttv_pll_info p;
-#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
-#else
- if(!suser())
-#endif
return -EPERM;
if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
return -EFAULT;
+ down(&btv->lock);
btv->pll.pll_ifreq = p.pll_ifreq;
btv->pll.pll_ofreq = p.pll_ofreq;
btv->pll.pll_crystal = p.pll_crystal;
-
+ up(&btv->lock);
break;
}
case VIDIOCMCAPTURE:
{
struct video_mmap vm;
+ int v;
if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
return -EFAULT;
if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING)
return -EBUSY;
- return vgrab(btv, &vm);
+ down(&btv->lock);
+ v=vgrab(btv, &vm);
+ up(&btv->lock);
+ return v;
}
case VIDIOCGMBUF:
* But e.g. pte_alloc() does not work in modules ... :-(
*/
-static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size)
+static int do_bttv_mmap(struct bttv *btv, const char *adr, unsigned long size)
{
- struct bttv *btv=(struct bttv *)dev;
unsigned long start=(unsigned long) adr;
unsigned long page,pos;
return 0;
}
+static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+ struct bttv *btv=(struct bttv *)dev;
+ int r;
+
+ down(&btv->lock);
+ r=do_bttv_mmap(btv, adr, size);
+ up(&btv->lock);
+ return r;
+}
+
static struct video_device bttv_template=
{
"UNSET",
return count;
}
-#if LINUX_VERSION_CODE >= 0x020100
static unsigned int vbi_poll(struct video_device *dev, struct file *file,
poll_table *wait)
{
return mask;
}
-#endif
static int vbi_open(struct video_device *dev, int flags)
{
struct bttv *btv=(struct bttv *)(dev-2);
+ down(&btv->lock);
btv->vbip=VBIBUF_SIZE;
btv->cap|=0x0c;
bt848_set_risc_jmps(btv);
+ up(&btv->lock);
MOD_INC_USE_COUNT;
return 0;
static void vbi_close(struct video_device *dev)
{
struct bttv *btv=(struct bttv *)(dev-2);
-
+
+ down(&btv->lock);
btv->cap&=~0x0c;
bt848_set_risc_jmps(btv);
+ up(&btv->lock);
MOD_DEC_USE_COUNT;
}
{
struct bttv *btv = (struct bttv *)(dev-1);
+ down(&btv->lock);
if (btv->user)
- return -EBUSY;
+ goto busy_unlock;
btv->user++;
+
set_freq(btv,400*16);
btv->radio = 1;
bt848_muxsel(btv,0);
audio(btv, AUDIO_UNMUTE);
+ up(&btv->lock);
MOD_INC_USE_COUNT;
return 0;
+
+ busy_unlock:
+ up(&btv->lock);
+ return -EBUSY;
}
static void radio_close(struct video_device *dev)
{
struct bttv *btv=(struct bttv *)(dev-1);
+ down(&btv->lock);
btv->user--;
btv->radio = 0;
/*audio(btv, AUDIO_MUTE);*/
+ up(&btv->lock);
MOD_DEC_USE_COUNT;
}
};
-struct vidbases
-{
- unsigned short vendor, device;
- char *name;
- uint badr;
-};
-
-static struct vidbases vbs[] = {
- { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
- "Alliance AT3D", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,
- "ATI MACH64 CT", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
- "ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,
- "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
- "DEC DC21030", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,
- "Matrox Millennium", PCI_BASE_ADDRESS_1},
- { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2,
- "Matrox Millennium II", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
- "Matrox Millennium II AGP", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
- { PCI_VENDOR_ID_MATROX, 0x0521, "Matrox G200", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128,
- "Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2,
- "Number Nine Imagine 128 Series 2", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_S3, 0, "S3", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_TSENG, 0, "TSENG", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
- "Riva128", PCI_BASE_ADDRESS_1},
-};
-
-
-/* DEC TGA offsets stolen from XFree-3.2 */
-
-static uint dec_offsets[4] = {
- 0x200000,
- 0x804000,
- 0,
- 0x1004000
-};
-
-#define NR_CARDS (sizeof(vbs)/sizeof(struct vidbases))
-
-/* Scan for PCI display adapter
- if more than one card is present the last one is used for now */
-
-#if LINUX_VERSION_CODE >= 0x020100
-
-static int find_vga(void)
-{
- unsigned short badr;
- int found = 0, i, tga_type;
- unsigned int vidadr=0;
- struct pci_dev *dev;
-
-
- for (dev = pci_devices; dev != NULL; dev = dev->next)
- {
- if (dev->class != PCI_CLASS_NOT_DEFINED_VGA &&
- ((dev->class) >> 16 != PCI_BASE_CLASS_DISPLAY))
- {
- continue;
- }
- if (PCI_FUNC(dev->devfn) != 0)
- continue;
-
- badr=0;
- printk(KERN_INFO "bttv: PCI display adapter: ");
- for (i=0; i<NR_CARDS; i++)
- {
- if (dev->vendor == vbs[i].vendor)
- {
- if (vbs[i].device)
- if (vbs[i].device!=dev->device)
- continue;
- printk("%s.\n", vbs[i].name);
- badr=vbs[i].badr;
- break;
- }
- }
- if (!badr)
- {
- printk(KERN_ERR "bttv: Unknown video memory base address.\n");
- continue;
- }
- pci_read_config_dword(dev, badr, &vidadr);
- if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
- {
- printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
- printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
- continue;
- }
- vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
- if (!vidadr)
- {
- printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!");
- continue;
- }
-
- if (dev->vendor == PCI_VENDOR_ID_DEC &&
- dev->device == PCI_DEVICE_ID_DEC_TGA)
- {
- tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
- if (tga_type != 0 && tga_type != 1 && tga_type != 3)
- {
- printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
- found--;
- }
- vidadr+=dec_offsets[tga_type];
- }
- DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
- DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn));
- found++;
- }
-
- if (vidmem)
- {
- vidadr=vidmem<<20;
- printk(KERN_INFO "bttv: Video memory override: 0x%08x\n", vidadr);
- found=1;
- }
- for (i=0; i<BTTV_MAX; i++)
- bttvs[i].win.vidadr=vidadr;
-
- return found;
-}
-
-#else
-static int find_vga(void)
-{
- unsigned int devfn, class, vendev;
- unsigned short vendor, device, badr;
- int found=0, bus=0, i, tga_type;
- unsigned int vidadr=0;
-
-
- for (devfn = 0; devfn < 0xff; devfn++)
- {
- if (PCI_FUNC(devfn) != 0)
- continue;
- pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendev);
- if (vendev == 0xffffffff || vendev == 0x00000000)
- continue;
- pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &device);
- pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class);
- class = class >> 16;
-/* if (class == PCI_CLASS_DISPLAY_VGA) {*/
- if ((class>>8) == PCI_BASE_CLASS_DISPLAY ||
- /* Number 9 GXE64Pro needs this */
- class == PCI_CLASS_NOT_DEFINED_VGA)
- {
- badr=0;
- printk(KERN_INFO "bttv: PCI display adapter: ");
- for (i=0; i<NR_CARDS; i++)
- {
- if (vendor==vbs[i].vendor)
- {
- if (vbs[i].device)
- if (vbs[i].device!=device)
- continue;
- printk("%s.\n", vbs[i].name);
- badr=vbs[i].badr;
- break;
- }
- }
- if (NR_CARDS == i)
- printk("UNKNOWN.\n");
- if (!badr)
- {
- printk(KERN_ERR "bttv: Unknown video memory base address.\n");
- continue;
- }
- pcibios_read_config_dword(bus, devfn, badr, &vidadr);
- if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
- {
- printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
- printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
- continue;
- }
- vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
- if (!vidadr)
- {
- printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!\n");
- continue;
- }
-
- if (vendor==PCI_VENDOR_ID_DEC)
- if (device==PCI_DEVICE_ID_DEC_TGA)
- {
- tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
- if (tga_type != 0 && tga_type != 1 && tga_type != 3)
- {
- printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
- found--;
- }
- vidadr+=dec_offsets[tga_type];
- }
-
- DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
- DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", devfn));
- found++;
- }
- }
-
- if (vidmem)
- {
- if (vidmem < 0x1000)
- vidadr=vidmem<<20;
- else
- vidadr=vidmem;
- printk(KERN_INFO "bttv: Video memory override: 0x%08x\n", vidadr);
- found=1;
- }
- for (i=0; i<BTTV_MAX; i++)
- bttvs[i].win.vidadr=vidadr;
-
- return found;
-}
-#endif
-
#define TRITON_PCON 0x50
#define TRITON_BUS_CONCURRENCY (1<<0)
#define TRITON_PEER_CONCURRENCY (1<<3)
-#if LINUX_VERSION_CODE >= 0x020100
-
static void handle_chipset(void)
{
struct pci_dev *dev = NULL;
printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
triton1=BT848_INT_ETBF;
-
-#if 0
- /* The ETBF bit SHOULD make all this unnecessary */
- /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
-
- pci_read_config_byte(dev, TRITON_PCON, &b);
- bo=b;
- DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
- if(!(b & TRITON_BUS_CONCURRENCY))
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
- b |= TRITON_BUS_CONCURRENCY;
- }
- if(b & TRITON_PEER_CONCURRENCY)
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
- b &= ~TRITON_PEER_CONCURRENCY;
- }
- if(!(b & TRITON_STREAMING))
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
- b |= TRITON_STREAMING;
- }
-
- if (b!=bo)
- {
- pci_write_config_byte(dev, TRITON_PCON, b);
- printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
- }
-#endif
- }
-}
-#else
-static void handle_chipset(void)
-{
- int index;
-
- for (index = 0; index < 8; index++)
- {
- unsigned char bus, devfn;
- unsigned char b;
-
- /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
-
- if (!pcibios_find_device(PCI_VENDOR_ID_SI,
- PCI_DEVICE_ID_SI_496,
- index, &bus, &devfn))
- {
- printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
- }
-
- if (!pcibios_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82441,
- index, &bus, &devfn))
- {
- pcibios_read_config_byte(bus, devfn, 0x53, &b);
- DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
- DEBUG(printk("bufcon=0x%02x\n",b));
- }
-
- if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437,
- index, &bus, &devfn))
- {
- printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
- triton1=BT848_INT_ETBF;
-
-#if 0
- /* The ETBF bit SHOULD make all this unnecessary */
- /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
- {
- unsigned char bo;
-
- pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
- bo=b;
- DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
-
- if(!(b & TRITON_BUS_CONCURRENCY))
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
- b |= TRITON_BUS_CONCURRENCY;
- }
-
- if(b & TRITON_PEER_CONCURRENCY)
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
- b &= ~TRITON_PEER_CONCURRENCY;
- }
- if(!(b & TRITON_STREAMING))
- {
- printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
- b |= TRITON_STREAMING;
- }
-
- if (b!=bo)
- {
- pcibios_write_config_byte(bus, devfn, TRITON_PCON, b);
- printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
- }
- }
-#endif
- }
}
}
-#endif
static void init_tea6300(struct i2c_bus *bus)
{
static void init_tea6320(struct i2c_bus *bus)
{
- I2CWrite(bus, I2C_TEA6300, TEA6320_V, 0x28, 1); /* master volume */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FFL, 0x28, 1); /* volume left 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FFR, 0x28, 1); /* volume right 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FRL, 0x28, 1); /* volume rear left 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_FRR, 0x28, 1); /* volume rear right 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_BA, 0x11, 1); /* bass 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_TR, 0x11, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TEA6300, TEA6320_S, TEA6320_S_GMU, 1); /* mute off input A */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_V, 0x28, 1); /* master volume */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FFL, 0x28, 1); /* volume left 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FFR, 0x28, 1); /* volume right 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FRL, 0x28, 1); /* volume rear left 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_FRR, 0x28, 1); /* volume rear right 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_BA, 0x11, 1); /* bass 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_TR, 0x11, 1); /* treble 0dB */
+ I2CWrite(bus, I2C_TEA6300, TEA6320_S, TEA6320_S_GMU, 1); /* mute off input A */
}
static void init_tda8425(struct i2c_bus *bus)
if (I2CRead(&(btv->i2c), I2C_TEA6300) >=0)
{
- if(btv->type==BTTV_AVEC_INTERCAP)
- {
- printk(KERN_INFO "bttv%d: fader chip: TEA6320\n",btv->nr);
- btv->audio_chip = TEA6320;
- init_tea6320(&(btv->i2c));
- } else {
- printk(KERN_INFO "bttv%d: fader chip: TEA6300\n",btv->nr);
- btv->audio_chip = TEA6300;
- init_tea6300(&(btv->i2c));
- }
+ if(btv->type==BTTV_AVEC_INTERCAP)
+ {
+ printk(KERN_INFO "bttv%d: fader chip: TEA6320\n",btv->nr);
+ btv->audio_chip = TEA6320;
+ init_tea6320(&(btv->i2c));
+ } else {
+ printk(KERN_INFO "bttv%d: fader chip: TEA6300\n",btv->nr);
+ btv->audio_chip = TEA6300;
+ init_tea6300(&(btv->i2c));
+ }
} else
printk(KERN_INFO "bttv%d: NO fader chip: TEA6300\n",btv->nr);
struct bttv *btv = &bttvs[i];
btv->user=0;
+
+ init_MUTEX(&btv->lock);
/* reset the bt848 */
btwrite(0, BT848_SRESET);
* Scan for a Bt848 card, request the irq and map the io memory
*/
-#if LINUX_VERSION_CODE >= 0x020100
int configure_bt848(struct pci_dev *dev, int bttv_num)
{
int result;
else
btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
-#if 0
- if (remap[bttv_num])
- {
- unsigned int dw = btv->bt848_adr;
-
- if (remap[bttv_num] < 0x1000)
- remap[bttv_num]<<=20;
- remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
- printk(KERN_INFO "bttv%d: remapping to : 0x%lx.\n",
- bttv_num,remap[bttv_num]);
- remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]);
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dw);
- btv->dev->base_address[0] = btv->bt848_adr;
- }
-#endif
pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
bttv_num,btv->id, btv->revision);
printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
return bttv_num;
}
-#else
-static int find_bt848(void)
-{
- short pci_index;
- unsigned char command, latency;
- int result;
- unsigned char bus, devfn;
- struct bttv *btv;
-
- bttv_num=0;
-
- if (!pcibios_present())
- {
- DEBUG(printk(KERN_DEBUG "bttv%d: PCI-BIOS not present or not accessable!\n",bttv_num));
- return 0;
- }
-
- for (pci_index = 0;
- !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
- pci_index, &bus, &devfn)
- ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
- pci_index, &bus, &devfn)
- ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
- pci_index, &bus, &devfn)
- ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
- pci_index, &bus, &devfn);
- ++pci_index)
- {
- btv=&bttvs[bttv_num];
- btv->nr = bttv_num;
- btv->bus=bus;
- btv->devfn=devfn;
- btv->bt848_mem=NULL;
- btv->vbibuf=NULL;
- btv->risc_jmp=NULL;
- btv->vbi_odd=NULL;
- btv->vbi_even=NULL;
- btv->vbiq=NULL;
- btv->capq=NULL;
- btv->capqo=NULL;
- btv->capqe=NULL;
-
- btv->vbip=VBIBUF_SIZE;
-
- pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID,
- &btv->id);
- pcibios_read_config_byte(btv->bus, btv->devfn,
- PCI_INTERRUPT_LINE, &btv->irq);
- pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
- &btv->bt848_adr);
- if (btv->id >= 878)
- btv->i2c_command = 0x83;
- else
- btv->i2c_command=
- (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
-
- if (remap[bttv_num])
- {
- if (remap[bttv_num] < 0x1000)
- remap[bttv_num]<<=20;
- remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
- printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n",
- bttv_num,remap[bttv_num]);
- remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
- pcibios_write_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
- remap[bttv_num]);
- pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
- &btv->bt848_adr);
- }
-
- btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
- pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
- &btv->revision);
- printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
- bttv_num,btv->id, btv->revision);
- printk("bus: %d, devfn: %d, ",
- btv->bus, btv->devfn);
- printk("irq: %d, ",btv->irq);
- printk("memory: 0x%08x.\n", btv->bt848_adr);
-
- btv->pll.pll_crystal = 0;
- btv->pll.pll_ifreq = 0;
- btv->pll.pll_ofreq = 0;
- btv->pll.pll_current = 0;
- if (!(btv->id==848 && btv->revision==0x11)) {
- switch (pll[btv->nr]) {
- case 0:
- /* off */
- break;
- case 1:
- /* 28 MHz crystal installed */
- btv->pll.pll_ifreq=28636363;
- btv->pll.pll_crystal=BT848_IFORM_XT0;
- break;
- case 2:
- /* 35 MHz crystal installed */
- btv->pll.pll_ifreq=35468950;
- btv->pll.pll_crystal=BT848_IFORM_XT1;
- break;
- }
- }
-
- btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
-
- result = request_irq(btv->irq, bttv_irq,
- SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
- if (result==-EINVAL)
- {
- printk(KERN_ERR "bttv%d: Bad irq number or handler\n",
- bttv_num);
- return -EINVAL;
- }
- if (result==-EBUSY)
- {
- printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq);
- return result;
- }
- if (result < 0)
- return result;
-
- /* Enable bus-mastering */
- pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
- command|=PCI_COMMAND_MASTER;
- pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
- pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
- if (!(command&PCI_COMMAND_MASTER))
- {
- printk(KERN_ERR "bttv%d: PCI bus-mastering could not be enabled\n",bttv_num);
- return -1;
- }
- pcibios_read_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER,
- &latency);
- if (!latency)
- {
- latency=32;
- pcibios_write_config_byte(btv->bus, btv->devfn,
- PCI_LATENCY_TIMER, latency);
- }
- DEBUG(printk(KERN_DEBUG "bttv%d: latency: %02x\n",
- bttv_num, latency));
-
- btv->triton1=triton1 ? BT848_INT_ETBF : 0;
- if (triton1 && btv->id >= 878)
- {
- triton1 = 0;
- printk("bttv: Enabling 430FX compatibilty for bt878\n");
- pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
- command|=BT878_EN_TBFX;
- pcibios_write_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, command);
- pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
- if (!(command&BT878_EN_TBFX))
- {
- printk("bttv: 430FX compatibility could not be enabled\n");
- return -1;
- }
- }
-
- bttv_num++;
- }
- if(bttv_num)
- printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
- return bttv_num;
-}
-#endif
static void release_bttv(void)
{
i2c_unregister_bus((&btv->i2c));
/* disable PCI bus-mastering */
-#if LINUX_VERSION_CODE >= 0x020100
+
pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
/* Should this be &=~ ?? */
command&=~PCI_COMMAND_MASTER;
pci_write_config_byte(btv->dev, PCI_COMMAND, command);
-#else
- pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
- command&=~PCI_COMMAND_MASTER;
- pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
-
-#endif
/* unmap and free memory */
if (btv->grisc)
struct video_picture picture; /* Current picture params */
struct video_audio audio_dev; /* Current audio params */
+ struct semaphore lock;
int user;
int capuser;
struct device_open open_data[MAX_OPENS];
return (btread(ZR36057_I2CBR) >> 1) & 1;
}
-void attach_inform(struct i2c_bus *bus, int id)
+static void attach_inform(struct i2c_bus *bus, int id)
{
DEBUG(struct zoran *zr = (struct zoran *) bus->data);
DEBUG(printk(BUZ_DEBUG "-%u: i2c attach %02x\n", zr->id, id));
}
-void detach_inform(struct i2c_bus *bus, int id)
+static void detach_inform(struct i2c_bus *bus, int id)
{
DEBUG(struct zoran *zr = (struct zoran *) bus->data);
DEBUG(printk(BUZ_DEBUG "-%u: i2c detach %02x\n", zr->id, id));
#define BLOCKMOVE
#define Z_WAKE
static char rcsid[] =
-"$Revision: 2.3.1.1 $$Date: 1999/07/15 16:45:53 $";
+"$Revision: 2.3.2.1 $$Date: 1999/09/27 11:01:22 $";
/*
* linux/drivers/char/cyclades.c
* This file contains the driver for the Cyclades Cyclom-Y multiport
* serial boards.
*
- * Maintained by Ivan Passos (ivan@cyclades.com),
- * Marcio Saito (marcio@cyclades.com) and
- * Randolph Bentson (bentson@grieg.seaslug.org).
+ * Initially written by Randolph Bentson (bentson@grieg.seaslug.org).
+ * Maintained by Ivan Passos (ivan@cyclades.com).
*
* For Technical support and installation problems, please send e-mail
* to support@cyclades.com.
* void cleanup_module(void);
*
* $Log: cyclades.c,v $
+ * Revision 2.3.2.1 1999/09/27 11:01:22 ivan
+ * Revisited CONFIG_PCI conditional compilation for PCI board support;
+ * Implemented TIOCGICOUNT and TIOCMIWAIT ioctl support;
+ * _Major_ cleanup on the Cyclades-Z interrupt support code / logic;
+ * Removed CTS handling from the driver -- this is now completely handled
+ * by the firmware (Cyclades-Z only);
+ * Flush RX on-board buffers as well on close (Cyclades-Z only);
+ * Fixed handling of ASYNC_SPD_* TTY flags;
+ * Module unload now unmaps all memory area allocated by ioremap;
+ *
* Revision 2.3.1.1 1999/07/15 16:45:53 ivan
* Removed CY_PROC conditional compilation;
* Implemented SMP-awareness for the driver;
#define cy_put_user put_user
-static unsigned long cy_get_user(unsigned long *addr)
+static unsigned long
+cy_get_user(unsigned long *addr)
{
unsigned long result = 0;
int error = get_user (result, addr);
static unsigned short cy_pci_nboard = 0;
static unsigned short cy_isa_nboard = 0;
static unsigned short cy_nboard = 0;
+#ifdef CONFIG_PCI
static unsigned short cy_pci_dev_id[] = {
PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */
PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */
PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */
0 /* end of table */
};
-
+#endif
static void cy_start(struct tty_struct *);
static void set_line_char(struct cyclades_port *);
if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
wake_up_interruptible(&info->open_wait);
}
+ if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) {
+ wake_up_interruptible(&info->delta_msr_wait);
+ }
if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
&& tty->ldisc.write_wakeup){
} /* cyy_issue_cmd */
#ifndef CONFIG_COBALT_27 /* ISA interrupt detection code */
-static unsigned detect_isa_irq (volatile ucchar *address)
+static unsigned
+detect_isa_irq (volatile ucchar *address)
{
int irq;
unsigned long irqs, flags;
j = (cy_readb(base_addr+(CyRIVR<<index)) & CyIVRMask);
if ( j == CyIVRRxEx ) { /* exception */
data = cy_readb(base_addr+(CyRDSR<<index));
+
+ /* For statistics only */
+ if (data & CyBREAK)
+ info->icount.brk++;
+ else if(data & CyFRAME)
+ info->icount.frame++;
+ else if(data & CyPARITY)
+ info->icount.parity++;
+ else if(data & CyOVERRUN)
+ info->icount.overrun++;
+
if(data & info->ignore_status_mask){
+ info->icount.rx++;
continue;
}
if (tty->flip.count < TTY_FLIPBUF_SIZE){
if (data & info->read_status_mask){
if(data & CyBREAK){
*tty->flip.flag_buf_ptr++ =
- TTY_BREAK;
+ TTY_BREAK;
*tty->flip.char_buf_ptr++ =
cy_readb(base_addr+(CyRDSR<<index));
+ info->icount.rx++;
if (info->flags & ASYNC_SAK){
do_SAK(tty);
}
TTY_FRAME;
*tty->flip.char_buf_ptr++ =
cy_readb(base_addr+(CyRDSR<<index));
+ info->icount.rx++;
info->idle_stats.frame_errs++;
}else if(data & CyPARITY){
*tty->flip.flag_buf_ptr++ =
TTY_PARITY;
*tty->flip.char_buf_ptr++ =
cy_readb(base_addr+(CyRDSR<<index));
+ info->icount.rx++;
info->idle_stats.parity_errs++;
}else if(data & CyOVERRUN){
*tty->flip.flag_buf_ptr++ =
TTY_OVERRUN;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
/* If the flip buffer itself is
overflowing, we still lose
the next incoming character.
TTY_NORMAL;
*tty->flip.char_buf_ptr++ =
cy_readb(base_addr+(CyRDSR<<index));
+ info->icount.rx++;
}
info->idle_stats.overruns++;
/* These two conditions may imply */
}else{
*tty->flip.flag_buf_ptr++ = 0;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
}
}else{
*tty->flip.flag_buf_ptr++ = 0;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
}
}else{
/* there was a software buffer
overrun and nothing could be
done about it!!! */
+ info->icount.buf_overrun++;
info->idle_stats.overruns++;
}
} else { /* normal character reception */
data = cy_readb(base_addr+(CyRDSR<<index));
*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
*tty->flip.char_buf_ptr++ = data;
+ info->icount.rx++;
#ifdef CY_16Y_HACK
udelay(10L);
#endif
/* load the on-chip space for outbound data */
char_count = info->xmit_fifo_size;
-
if(info->x_char) { /* send special char */
outch = info->x_char;
cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
char_count--;
+ info->icount.tx++;
info->x_char = 0;
}
info->xmit_tail = (info->xmit_tail + 1)
& (SERIAL_XMIT_SIZE - 1);
cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
+ info->icount.tx++;
}else{
if(char_count > 1){
info->xmit_cnt--;
cy_writeb((u_long)base_addr+(CyTDR<<index),
outch);
cy_writeb((u_long)base_addr+(CyTDR<<index), 0);
+ info->icount.tx++;
char_count--;
}else{
}
if(info->tty == 0){/* no place for data, ignore it*/
;
}else{
+ if (mdm_change & CyANY_DELTA) {
+ /* For statistics only */
+ if (mdm_change & CyDCD) info->icount.dcd++;
+ if (mdm_change & CyCTS) info->icount.cts++;
+ if (mdm_change & CyDSR) info->icount.dsr++;
+ if (mdm_change & CyRI) info->icount.rng++;
+
+ cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ }
+
if((mdm_change & CyDCD)
&& (info->flags & ASYNC_CHECK_CD)){
if(mdm_status & CyDCD){
}
}
}
- if(mdm_status & CyDSR){
+ if(mdm_change & CyDSR){
}
- if(mdm_status & CyRI){
+ if(mdm_change & CyRI){
}
}
/* end of service */
return 0;
} /* cyz_fetch_msg */
-
static int
cyz_issue_cmd( struct cyclades_card *cinfo,
uclong channel, ucchar cmd, uclong param)
return(0);
} /* cyz_issue_cmd */
-#ifdef CONFIG_CYZ_INTR
static void
-cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+cyz_handle_rx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+{
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ struct tty_struct *tty = info->tty;
+ volatile int char_count;
+#ifdef BLOCKMOVE
+ int small_count;
+#else
+ char data;
+#endif
+ volatile uclong rx_put, rx_get, rx_bufsize;
+
+/* Removed due to compilation problems in Alpha systems */
+// if ((char_count = CHARS_IN_BUF(buf_ctrl))){
+
+ rx_get = cy_readl(&buf_ctrl->rx_get);
+ rx_put = cy_readl(&buf_ctrl->rx_put);
+ rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+ if (rx_put >= rx_get)
+ char_count = rx_put - rx_get;
+ else
+ char_count = rx_put - rx_get + rx_bufsize;
+
+ if ( char_count ) {
+ info->last_active = jiffies;
+ info->jiffies[1] = jiffies;
+
+#ifdef CY_ENABLE_MONITORING
+ info->mon.int_count++;
+ info->mon.char_count += char_count;
+ if (char_count > info->mon.char_max)
+ info->mon.char_max = char_count;
+ info->mon.char_last = char_count;
+#endif
+ if(tty == 0){
+ /* flush received characters */
+ rx_get = (rx_get + char_count) & (rx_bufsize - 1);
+ info->rflush_count++;
+ }else{
+#ifdef BLOCKMOVE
+ /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+ for performance, but because of buffer boundaries, there
+ may be several steps to the operation */
+ while(0 < (small_count =
+ cy_min((rx_bufsize - rx_get),
+ cy_min((TTY_FLIPBUF_SIZE - tty->flip.count), char_count))
+ )) {
+ memcpy_fromio(tty->flip.char_buf_ptr,
+ (char *)(cinfo->base_addr
+ + cy_readl(&buf_ctrl->rx_bufaddr)
+ + rx_get),
+ small_count);
+
+ tty->flip.char_buf_ptr += small_count;
+ memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count);
+ tty->flip.flag_buf_ptr += small_count;
+ rx_get = (rx_get + small_count) & (rx_bufsize - 1);
+ char_count -= small_count;
+ info->icount.rx += small_count;
+ info->idle_stats.recv_bytes += small_count;
+ tty->flip.count += small_count;
+ }
+#else
+ while(char_count--){
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE){
+ break;
+ }
+ data = cy_readb(cinfo->base_addr +
+ cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
+ rx_get = (rx_get + 1) & (rx_bufsize - 1);
+ tty->flip.count++;
+ *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+ *tty->flip.char_buf_ptr++ = data;
+ info->idle_stats.recv_bytes += small_count;
+ info->icount.rx++;
+ }
+#endif
+ info->idle_stats.recv_idle = jiffies;
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ }
+ /* Update rx_get */
+ cy_writel(&buf_ctrl->rx_get, rx_get);
+ }
+}
+
+static void
+cyz_handle_tx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+{
+ struct cyclades_card *cinfo = &cy_card[info->card];
+ struct tty_struct *tty = info->tty;
+ char data;
+ volatile int char_count;
+#ifdef BLOCKMOVE
+ int small_count;
+#endif
+ volatile uclong tx_put, tx_get, tx_bufsize;
+
+/* Removed due to compilation problems in Alpha systems */
+// if ((char_count = SPACE_IN_BUF(buf_ctrl))){
+
+ tx_get = cy_readl(&buf_ctrl->tx_get);
+ tx_put = cy_readl(&buf_ctrl->tx_put);
+ tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+ if (tx_put >= tx_get)
+ char_count = tx_get - tx_put - 1 + tx_bufsize;
+ else
+ char_count = tx_get - tx_put - 1;
+
+ if ( char_count ) {
+
+ if( tty == 0 ){
+ goto ztxdone;
+ }
+
+ if(info->x_char) { /* send special char */
+ data = info->x_char;
+
+ cy_writeb((cinfo->base_addr +
+ cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ info->x_char = 0;
+ char_count--;
+ info->icount.tx++;
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
+#ifdef BLOCKMOVE
+ while(0 < (small_count =
+ cy_min((tx_bufsize - tx_put),
+ cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
+ cy_min(info->xmit_cnt, char_count))))){
+
+ memcpy_toio((char *)(cinfo->base_addr
+ + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
+ &info->xmit_buf[info->xmit_tail],
+ small_count);
+
+ tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+ char_count -= small_count;
+ info->icount.tx += small_count;
+ info->xmit_cnt -= small_count;
+ info->xmit_tail =
+ (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
+#else
+ while (info->xmit_cnt && char_count){
+ data = info->xmit_buf[info->xmit_tail];
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+
+ cy_writeb(cinfo->base_addr +
+ cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ char_count--;
+ info->icount.tx++;
+ info->last_active = jiffies;
+ info->jiffies[2] = jiffies;
+ }
+#endif
+ ztxdone:
+ if (info->xmit_cnt < WAKEUP_CHARS) {
+ cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+ }
+ /* Update tx_put */
+ cy_writel(&buf_ctrl->tx_put, tx_put);
+ }
+}
+
+static void
+cyz_handle_cmd(struct cyclades_card *cinfo)
{
struct tty_struct *tty;
- struct cyclades_card *cinfo;
struct cyclades_port *info;
static volatile struct FIRM_ID *firm_id;
static volatile struct ZFW_CTRL *zfw_ctrl;
ucchar cmd;
uclong param;
uclong hw_ver, fw_ver;
- char data;
- volatile int char_count, special_count;
-#ifdef BLOCKMOVE
- int small_count;
-#endif
- volatile uclong tx_put, tx_get, tx_bufsize;
- volatile uclong rx_put, rx_get, rx_bufsize;
-
- if((cinfo = (struct cyclades_card *)dev_id) == 0){
-#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
-#endif
- return; /* spurious interrupt */
- }
+ int special_count;
+ int delta_count;
- firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
- if (!ISZLOADED(*cinfo)) {
-#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: board not yet loaded (INT %d).\n\r", irq);
-#endif
- return;
+ firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+ zfw_ctrl = (struct ZFW_CTRL *)
+ (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+ board_ctrl = &(zfw_ctrl->board_ctrl);
+ fw_ver = cy_readl(&board_ctrl->fw_version);
+ hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0);
+
+ while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) {
+ special_count = 0;
+ delta_count = 0;
+ info = &cy_port[channel + cinfo->first_line];
+ if((tty = info->tty) == 0) {
+ continue;
}
+ ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+ buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
- zfw_ctrl = (struct ZFW_CTRL *)
- (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
- board_ctrl = &(zfw_ctrl->board_ctrl);
- fw_ver = cy_readl(&board_ctrl->fw_version);
- hw_ver = cy_readl(&((struct RUNTIME_9060 *)
- (cinfo->ctl_addr))->mail_box_0);
-
- while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) {
- special_count = 0;
- info = &cy_port[channel + cinfo->first_line];
- if((tty = info->tty) == 0) continue;
- ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
- switch(cmd){
+ switch(cmd) {
case C_CM_PR_ERROR:
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_PARITY;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
special_count++;
- break;
+ break;
case C_CM_FR_ERROR:
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_FRAME;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
special_count++;
- break;
+ break;
case C_CM_RXBRK:
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_BREAK;
*tty->flip.char_buf_ptr++ = 0;
+ info->icount.rx++;
special_count++;
- break;
+ break;
case C_CM_MDCD:
+ info->icount.dcd++;
+ delta_count++;
if (info->flags & ASYNC_CHECK_CD){
if ((fw_ver > 241 ?
- ((u_long)param) :
- cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
- /* SP("Open Wakeup\n"); */
- cy_sched_event(info,
- Cy_EVENT_OPEN_WAKEUP);
- }else if(!((info->flags
- & ASYNC_CALLOUT_ACTIVE)
- &&(info->flags
- & ASYNC_CALLOUT_NOHUP))){
- /* SP("Hangup\n"); */
- cy_sched_event(info,
- Cy_EVENT_HANGUP);
+ ((u_long)param) :
+ cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
+ cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
+ }else if(!((info->flags & ASYNC_CALLOUT_ACTIVE)
+ &&(info->flags & ASYNC_CALLOUT_NOHUP))){
+ cy_sched_event(info, Cy_EVENT_HANGUP);
}
}
- break;
+ break;
case C_CM_MCTS:
- if (info->flags & ASYNC_CTS_FLOW) {
- if(info->tty->hw_stopped){
- if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
- /* cy_start isn't used because...
- HW flow is handled by the board */
- /* SP("Write Wakeup\n"); */
- cy_sched_event(info,
- Cy_EVENT_WRITE_WAKEUP);
- }
- }else{
- if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
- /* cy_stop isn't used because
- HW flow is handled by the board */
- /* SP("Write stop\n"); */
- }
- }
- }
- break;
+ info->icount.cts++;
+ delta_count++;
+ break;
case C_CM_MRI:
- break;
+ info->icount.rng++;
+ delta_count++;
+ break;
case C_CM_MDSR:
- break;
+ info->icount.dsr++;
+ delta_count++;
+ break;
#ifdef Z_WAKE
case C_CM_IOCTLW:
cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
- break;
+ break;
#endif
+#ifdef CONFIG_CYZ_INTR
case C_CM_RXHIWM:
case C_CM_RXNNDT:
/* Reception Interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r",
- info->card, channel);
-#endif
-
- rx_get = cy_readl(&buf_ctrl->rx_get);
- rx_put = cy_readl(&buf_ctrl->rx_put);
- rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
-
- if ( char_count ){
-
-#ifdef CY_ENABLE_MONITORING
- info->mon.int_count++;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
+ printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r",
+ info->card, channel);
#endif
- info->idle_stats.recv_bytes += char_count;
- info->idle_stats.recv_idle = jiffies;
- if( tty == 0){
- /* flush received characters */
- rx_get = (rx_get + char_count) & (rx_bufsize - 1);
- /* SP("-"); */
- info->rflush_count++;
- }else{
-#ifdef BLOCKMOVE
- /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
- for performance, but because of buffer boundaries, there
- may be several steps to the operation */
- while(0 < (small_count
- = cy_min((rx_bufsize - rx_get),
- cy_min((TTY_FLIPBUF_SIZE - tty->flip.count),
- char_count)))){
-
- memcpy_fromio(tty->flip.char_buf_ptr,
- (char *)(cinfo->base_addr
- + cy_readl(&buf_ctrl->rx_bufaddr)
- + rx_get),
- small_count);
-
- tty->flip.char_buf_ptr += small_count;
- memset(tty->flip.flag_buf_ptr,
- TTY_NORMAL,
- small_count);
- tty->flip.flag_buf_ptr += small_count;
- rx_get = (rx_get + small_count) & (rx_bufsize - 1);
- char_count -= small_count;
- tty->flip.count += small_count;
- }
-#else
- while(char_count--){
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- break;
- }
- data = cy_readb(cinfo->base_addr +
- cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
- rx_get = (rx_get + 1) & (rx_bufsize - 1);
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
- }
-#endif
- queue_task(&tty->flip.tqueue, &tq_timer);
- }
- /* Update rx_get */
- cy_writel(&buf_ctrl->rx_get, rx_get);
- }
+ cyz_handle_rx(info, buf_ctrl);
break;
case C_CM_TXBEMPTY:
case C_CM_TXLOWWM:
case C_CM_INTBACK:
/* Transmission Interrupt */
#ifdef CY_DEBUG_INTERRUPTS
- printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r",
- info->card, channel);
-#endif
-
- tx_get = cy_readl(&buf_ctrl->tx_get);
- tx_put = cy_readl(&buf_ctrl->tx_put);
- tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
- if (tx_put >= tx_get)
- char_count = tx_get - tx_put - 1 + tx_bufsize;
- else
- char_count = tx_get - tx_put - 1;
-
- if ( char_count ){
-
- if( tty == 0 ){
- goto ztxdone;
- }
-
- if(info->x_char) { /* send special char */
- data = info->x_char;
-
- cy_writeb((cinfo->base_addr +
- cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- info->x_char = 0;
- char_count--;
- }
-#ifdef BLOCKMOVE
- while(0 < (small_count
- = cy_min((tx_bufsize - tx_put),
- cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
- cy_min(info->xmit_cnt, char_count))))){
-
- memcpy_toio((char *)(cinfo->base_addr
- + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
- &info->xmit_buf[info->xmit_tail],
- small_count);
-
- tx_put = (tx_put + small_count) & (tx_bufsize - 1);
- char_count -= small_count;
- info->xmit_cnt -= small_count;
- info->xmit_tail =
- (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
- }
-#else
- while (info->xmit_cnt && char_count){
- data = info->xmit_buf[info->xmit_tail];
- info->xmit_cnt--;
- info->xmit_tail =
- (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
-
- cy_writeb(cinfo->base_addr +
- cy_readl(&buf_ctrl->tx_bufaddr) + tx_put,
- data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- char_count--;
- }
-
+ printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r",
+ info->card, channel);
#endif
- ztxdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
- }
- /* Update tx_put */
- cy_writel(&buf_ctrl->tx_put, tx_put);
- }
+ cyz_handle_tx(info, buf_ctrl);
break;
+#endif /* CONFIG_CYZ_INTR */
case C_CM_FATAL:
/* should do something with this !!! */
- break;
- }
- if(special_count){
- queue_task(&tty->flip.tqueue, &tq_timer);
- }
+ break;
+ default:
+ break;
}
+ if(delta_count)
+ cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+ if(special_count)
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ }
+}
+
+#ifdef CONFIG_CYZ_INTR
+static void
+cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct cyclades_card *cinfo;
+
+ if((cinfo = (struct cyclades_card *)dev_id) == 0){
+#ifdef CY_DEBUG_INTERRUPTS
+ printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+#endif
+ return; /* spurious interrupt */
+ }
+
+ if (!ISZLOADED(*cinfo)) {
+#ifdef CY_DEBUG_INTERRUPTS
+ printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq);
+#endif
+ return;
+ }
+
+ /* Handle the interrupts */
+ cyz_handle_cmd(cinfo);
return;
} /* cyz_interrupt */
static void
cyz_poll(unsigned long arg)
{
+ struct cyclades_card *cinfo;
+ struct cyclades_port *info;
+ struct tty_struct *tty;
static volatile struct FIRM_ID *firm_id;
static volatile struct ZFW_CTRL *zfw_ctrl;
static volatile struct BOARD_CTRL *board_ctrl;
static volatile struct CH_CTRL *ch_ctrl;
static volatile struct BUF_CTRL *buf_ctrl;
- struct cyclades_card *cinfo;
- struct cyclades_port *info;
- struct tty_struct *tty;
int card, port;
- int char_count;
-#ifdef BLOCKMOVE
- int small_count;
-#endif
- char data;
- uclong channel;
- ucchar cmd;
- uclong param;
- uclong hw_ver, fw_ver;
- volatile uclong tx_put, tx_get, tx_bufsize;
- volatile uclong rx_put, rx_get, rx_bufsize;
cyz_timerlist.expires = jiffies + (HZ);
for (card = 0 ; card < NR_CARDS ; card++){
cinfo = &cy_card[card];
- if (!IS_CYC_Z(*cinfo)) continue;
+ if (!IS_CYC_Z(*cinfo)) continue;
+ if (!ISZLOADED(*cinfo)) continue;
- firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
- if (!ISZLOADED(*cinfo)) {
+ /* Skip first polling cycle to avoid racing conditions with the FW */
+ if (!cinfo->intr_enabled) {
+ cinfo->intr_enabled = 1;
continue;
}
+ firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
zfw_ctrl = (struct ZFW_CTRL *)
- (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
- board_ctrl = &(zfw_ctrl->board_ctrl);
- fw_ver = cy_readl(&board_ctrl->fw_version);
- hw_ver = cy_readl(&((struct RUNTIME_9060 *)
- (cinfo->ctl_addr))->mail_box_0);
-
- while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1){
- char_count = 0;
- info = &cy_port[ channel + cinfo->first_line ];
- if((tty = info->tty) == 0) continue;
- ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
- buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
- info->jiffies[0] = jiffies;
-
- switch(cmd){
- case C_CM_PR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- *tty->flip.char_buf_ptr++ = 0;
- char_count++;
- break;
- case C_CM_FR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- *tty->flip.char_buf_ptr++ = 0;
- char_count++;
- break;
- case C_CM_RXBRK:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
- char_count++;
- break;
- case C_CM_MDCD:
- if (info->flags & ASYNC_CHECK_CD){
- if ((fw_ver > 241 ?
- ((u_long)param) :
- cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
- cy_sched_event(info,
- Cy_EVENT_OPEN_WAKEUP);
- }else if(!((info->flags
- & ASYNC_CALLOUT_ACTIVE)
- &&(info->flags
- & ASYNC_CALLOUT_NOHUP))){
- cy_sched_event(info,
- Cy_EVENT_HANGUP);
- }
- }
- break;
- case C_CM_MCTS:
- if (info->flags & ASYNC_CTS_FLOW) {
- if(info->tty->hw_stopped){
- if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
- /* cy_start isn't used because...
- HW flow is handled by the board */
- cy_sched_event(info,
- Cy_EVENT_WRITE_WAKEUP);
- }
- }else{
- if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
- /* cy_stop isn't used because
- HW flow is handled by the board */
- }
- }
- }
- break;
- case C_CM_MRI:
- break;
- case C_CM_MDSR:
- break;
-#ifdef Z_WAKE
- case C_CM_IOCTLW:
- cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
- break;
-#endif
- case C_CM_FATAL:
- /* should do something with this !!! */
- break;
- }
- if(char_count){
- queue_task(&tty->flip.tqueue, &tq_timer);
- }
- }
+ (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+
+ cyz_handle_cmd(cinfo);
+
for (port = 0; port < cy_readl(&board_ctrl->n_channel); port++){
info = &cy_port[ port + cinfo->first_line ];
tty = info->tty;
ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
-/* Removed due to compilation problems in Alpha systems */
-// if ((char_count = CHARS_IN_BUF(buf_ctrl))){
-
- rx_get = cy_readl(&buf_ctrl->rx_get);
- rx_put = cy_readl(&buf_ctrl->rx_put);
- rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
-
- if ( char_count ){
-
- info->last_active = jiffies;
- info->jiffies[1] = jiffies;
-
-#ifdef CY_ENABLE_MONITORING
- info->mon.int_count++;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
-#endif
- info->idle_stats.recv_bytes += char_count;
- info->idle_stats.recv_idle = jiffies;
- if( tty == 0){
- /* flush received characters */
- rx_get = (rx_get + char_count) & (rx_bufsize - 1);
- info->rflush_count++;
- }else{
-#ifdef BLOCKMOVE
- /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
- for performance, but because of buffer boundaries, there
- may be several steps to the operation */
- while(0 < (small_count
- = cy_min((rx_bufsize - rx_get),
- cy_min((TTY_FLIPBUF_SIZE - tty->flip.count),
- char_count)))){
-
- memcpy_fromio(tty->flip.char_buf_ptr,
- (char *)(cinfo->base_addr
- + cy_readl(&buf_ctrl->rx_bufaddr)
- + rx_get),
- small_count);
-
- tty->flip.char_buf_ptr += small_count;
- memset(tty->flip.flag_buf_ptr,
- TTY_NORMAL,
- small_count);
- tty->flip.flag_buf_ptr += small_count;
- rx_get = (rx_get + small_count) & (rx_bufsize - 1);
- char_count -= small_count;
- tty->flip.count += small_count;
- }
-#else
- while(char_count--){
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- break;
- }
- data = cy_readb(cinfo->base_addr +
- cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
- rx_get = (rx_get + 1) & (rx_bufsize - 1);
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
- }
-#endif
- queue_task(&tty->flip.tqueue, &tq_timer);
- }
- /* Update rx_get */
- cy_writel(&buf_ctrl->rx_get, rx_get);
- }
-
-/* Removed due to compilation problems in Alpha systems */
-// if ((char_count = SPACE_IN_BUF(buf_ctrl))){
-
- tx_get = cy_readl(&buf_ctrl->tx_get);
- tx_put = cy_readl(&buf_ctrl->tx_put);
- tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
- if (tx_put >= tx_get)
- char_count = tx_get - tx_put - 1 + tx_bufsize;
- else
- char_count = tx_get - tx_put - 1;
-
- if ( char_count ){
-
- if( tty == 0 ){
- goto ztxdone;
- }
-
- if(info->x_char) { /* send special char */
- data = info->x_char;
-
- cy_writeb((cinfo->base_addr +
- cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- info->x_char = 0;
- char_count--;
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
-#ifdef BLOCKMOVE
- while(0 < (small_count
- = cy_min((tx_bufsize - tx_put),
- cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
- cy_min(info->xmit_cnt, char_count))))){
-
- memcpy_toio((char *)(cinfo->base_addr
- + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
- &info->xmit_buf[info->xmit_tail],
- small_count);
-
- tx_put = (tx_put + small_count) & (tx_bufsize - 1);
- char_count -= small_count;
- info->xmit_cnt -= small_count;
- info->xmit_tail =
- (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
-#else
- while (info->xmit_cnt && char_count){
- data = info->xmit_buf[info->xmit_tail];
- info->xmit_cnt--;
- info->xmit_tail =
- (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
-
- cy_writeb(cinfo->base_addr +
- cy_readl(&buf_ctrl->tx_bufaddr) + tx_put,
- data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- char_count--;
- info->last_active = jiffies;
- info->jiffies[2] = jiffies;
- }
-
-#endif
- ztxdone:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
- }
- /* Update tx_put */
- cy_writel(&buf_ctrl->tx_put, tx_put);
- }
+ cyz_handle_rx(info, buf_ctrl);
+ cyz_handle_tx(info, buf_ctrl);
}
/* poll every 40 ms */
cyz_timerlist.expires = jiffies + cyz_polling_cycle;
cy_writel(&ch_ctrl[channel].intr_enable,
C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
C_IN_IOCTLW|
- C_IN_MDCD|C_IN_MCTS);
+ C_IN_MDCD);
#else
cy_writel(&ch_ctrl[channel].intr_enable,
C_IN_IOCTLW|
- C_IN_MDCD|C_IN_MCTS);
+ C_IN_MDCD);
#endif /* CONFIG_CYZ_INTR */
#else
#ifdef CONFIG_CYZ_INTR
cy_writel(&ch_ctrl[channel].intr_enable,
C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
- C_IN_MDCD|C_IN_MCTS);
+ C_IN_MDCD);
#else
cy_writel(&ch_ctrl[channel].intr_enable,
- C_IN_MDCD|C_IN_MCTS);
+ C_IN_MDCD);
#endif /* CONFIG_CYZ_INTR */
#endif /* Z_WAKE */
CY_LOCK(info, flags);
+ /* Clear delta_msr_wait queue to avoid mem leaks. */
+ wake_up_interruptible(&info->delta_msr_wait);
+
if (info->xmit_buf){
unsigned char * temp;
temp = info->xmit_buf;
retval = cyz_issue_cmd(&cy_card[info->card],
channel, C_CM_IOCTLM, 0L);
if (retval != 0){
- printk("cyc:shutdown retval (2) was %x\n", retval);
+ printk("cyc:shutdown retval was %x\n", retval);
}
#ifdef CY_DEBUG_DTR
printk("cyc:shutdown dropping Z DTR\n");
interrupts should be enabled as soon as the first open happens
to one of its ports. */
if (!cy_card[info->card].intr_enabled) {
+ /* Enable interrupts on the PLX chip */
+ cy_writew(cy_card[info->card].ctl_addr+0x68,
+ cy_readw(cy_card[info->card].ctl_addr+0x68)|0x0900);
+ /* Enable interrupts on the FW */
retval = cyz_issue_cmd(&cy_card[info->card],
0, C_CM_IRQ_ENBL, 0L);
if (retval != 0){
/*
* cy_wait_until_sent() --- wait until the transmitter is empty
*/
-static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+static void
+cy_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
unsigned char *base_addr;
* This routine is called when a particular tty device is closed.
*/
static void
-cy_close(struct tty_struct * tty, struct file * filp)
+cy_close(struct tty_struct *tty, struct file *filp)
{
- struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
unsigned long flags;
#ifdef CY_DEBUG_OTHER
retval = cyz_issue_cmd(&cy_card[info->card], channel,
C_CM_IOCTLW, 0L);
if (retval != 0){
- printk("cyc:shutdown retval (1) was %x\n", retval);
+ printk("cyc:cy_close retval (1) was %x\n", retval);
}
CY_UNLOCK(info, flags);
interruptible_sleep_on(&info->shutdown_wait);
tty->driver.flush_buffer(tty);
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
+ if (IS_CYC_Z(cy_card[info->card])) { /* If it is a Z card, flush the
+ on-board RX buffers as well */
+ int retval;
+ int channel = info->line - cy_card[info->card].first_line;
+
+ retval = cyz_issue_cmd(&cy_card[info->card], channel,
+ C_CM_FLUSH_RX, 0L);
+ if (retval != 0) {
+ printk("cyc: cy_close retval (2) was %x\n", retval);
+ }
+ }
CY_LOCK(info, flags);
tty->closing = 0;
cflag = info->tty->termios->c_cflag;
iflag = info->tty->termios->c_iflag;
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if (info->tty) {
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+
card = info->card;
channel = (info->line) - (cy_card[card].first_line);
chip_number = channel / 4;
index = cy_card[card].bus_index;
/* baud rate */
- baud = tty_get_baud_rate(info->tty);
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
+ baud = info->baud;
+ } else {
+ baud = tty_get_baud_rate(info->tty);
+ }
if (baud > CD1400_MAX_SPEED) {
baud = CD1400_MAX_SPEED;
}
struct BOARD_CTRL *board_ctrl;
struct CH_CTRL *ch_ctrl;
struct BUF_CTRL *buf_ctrl;
+ uclong sw_flow;
int retval;
firm_id = (struct FIRM_ID *)
buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
/* baud rate */
- baud = tty_get_baud_rate(info->tty);
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
+ baud = info->baud;
+ } else {
+ baud = tty_get_baud_rate(info->tty);
+ }
if (baud > CYZ_MAX_SPEED) {
baud = CYZ_MAX_SPEED;
}
/* CTS flow control flag */
if (cflag & CRTSCTS){
- info->flags |= ASYNC_CTS_FLOW;
cy_writel(&ch_ctrl->hw_flow,
cy_readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
}else{
- info->flags &= ~ASYNC_CTS_FLOW;
cy_writel(&ch_ctrl->hw_flow,
cy_readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS));
}
+ /* As the HW flow control is done in firmware, the driver doesn't
+ need to care about it */
+ info->flags &= ~ASYNC_CTS_FLOW;
+
+ /* XON/XOFF/XANY flow control flags */
+ sw_flow = 0;
+ if (iflag & IXON){
+ sw_flow |= C_FL_OXX;
+ if (iflag & IXANY)
+ sw_flow |= C_FL_OIXANY;
+ }
+ cy_writel(&ch_ctrl->sw_flow, sw_flow);
retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
if (retval != 0){
info->flags |= ASYNC_CHECK_CD;
}
- if (iflag & IXON){
- cy_writel(&ch_ctrl->sw_flow,
- cy_readl(&ch_ctrl->sw_flow) | C_FL_OXX);
- } else {
- cy_writel(&ch_ctrl->sw_flow,
- cy_readl(&ch_ctrl->sw_flow) & ~C_FL_OXX);
- }
-
if(baud == 0){ /* baud rate is zero, turn off line */
cy_writel(&ch_ctrl->rs_control,
cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
}
}
- /*
- * Set up the tty->alt_speed kludge
- */
- if (info->tty) {
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- }
-
} /* set_line_char */
}
}
- return cy_put_user(result,(unsigned int *) value);
+ return cy_put_user(result, value);
} /* get_modem_info */
unsigned int cmd, unsigned long arg)
{
struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_icount cprev, cnow; /* kernel counter temps */
+ struct serial_icounter_struct *p_cuser; /* user space */
int ret_val = 0;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->device, "cy_ioctl"))
return -ENODEV;
if (copy_to_user((void *)arg, (void *)&cy_card[info->card],
sizeof (struct cyclades_card))) {
ret_val = -EFAULT;
+ break;
}
ret_val = 0;
break;
case TIOCSSERIAL:
ret_val = set_serial_info(info, (struct serial_struct *) arg);
break;
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT:
+ CY_LOCK(info, flags);
+ /* note the counters on entry */
+ cprev = info->icount;
+ CY_UNLOCK(info, flags);
+ while (1) {
+ interruptible_sleep_on(&info->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ return -ERESTARTSYS;
+ }
+
+ CY_LOCK(info, flags);
+ cnow = info->icount; /* atomic copy */
+ CY_UNLOCK(info, flags);
+
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+ return -EIO; /* no change => error */
+ }
+ if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ CY_LOCK(info, flags);
+ cnow = info->icount;
+ CY_UNLOCK(info, flags);
+ p_cuser = (struct serial_icounter_struct *) arg;
+ ret_val = put_user(cnow.cts, &p_cuser->cts);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.dsr, &p_cuser->dsr);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.rng, &p_cuser->rng);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.dcd, &p_cuser->dcd);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.rx, &p_cuser->rx);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.tx, &p_cuser->tx);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.frame, &p_cuser->frame);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.overrun, &p_cuser->overrun);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.parity, &p_cuser->parity);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.brk, &p_cuser->brk);
+ if (ret_val) return ret_val;
+ ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+ if (ret_val) return ret_val;
+ ret_val = 0;
+ break;
default:
ret_val = -ENOIOCTLCMD;
}
#endif
if ((tty->termios->c_cflag == old_termios->c_cflag) &&
- ((tty->termios->c_iflag & IXON) == (old_termios->c_iflag & IXON)))
+ ((tty->termios->c_iflag & (IXON|IXANY)) ==
+ (old_termios->c_iflag & (IXON|IXANY))))
return;
set_line_char(info);
} /* cy_detect_isa */
#endif /* CONFIG_COBALT_27 */
-static void plx_init(uclong addr, uclong initctl)
+static void
+plx_init(uclong addr, uclong initctl)
{
/* Reset PLX */
cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
unsigned short device_id,dev_index = 0;
uclong mailbox;
uclong Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
+ unsigned char Ze_irq[NR_CARDS];
if(pci_present() == 0) { /* PCI bus not present */
return(0);
/* read PCI configuration area */
cy_pci_irq = pdev->irq;
cy_pci_addr0 = pdev->resource[0].start;
- cy_pci_addr1 = pdev->resource[1].start;
- cy_pci_addr2 = pdev->resource[2].start;
+ cy_pci_addr1 = pdev->resource[1].start;
+ cy_pci_addr2 = pdev->resource[2].start;
pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
device_id &= ~PCI_DEVICE_ID_MASK;
if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) {
printk(" Warning: PCI I/O bit incorrectly set. "
"Ignoring it...\n");
- cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+ pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK;
}
#if defined(__alpha__)
printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
(ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
#endif
- cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
#if !defined(__alpha__)
cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl);
#endif
+ /* Disable interrupts on the PLX before resetting it */
+ cy_writew(cy_pci_addr0+0x68,
+ cy_readw(cy_pci_addr0+0x68) & ~0x0900);
+
plx_init(cy_pci_addr0, 0x6c);
/* For some yet unknown reason, once the PLX9060 reloads
the EEPROM, the IRQ is lost and, thus, we have to
mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *)
cy_pci_addr0)->mail_box_0);
- cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
- if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) {
+ if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) {
printk(" Warning: PCI I/O bit incorrectly set. "
"Ignoring it...\n");
- cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
+ pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK;
}
if (mailbox == ZE_V1) {
#if !defined(__alpha__)
} else {
Ze_addr0[ZeIndex] = cy_pci_addr0;
Ze_addr2[ZeIndex] = cy_pci_addr2;
+ Ze_irq[ZeIndex] = cy_pci_irq;
ZeIndex++;
}
i--;
printk("%d channels starting from port %d.\n",
cy_pci_nchan,cy_next_channel);
-#ifdef CONFIG_CYZ_INTR
- /* Enable interrupts on the PLX chip */
- cy_writew(cy_pci_addr0+0x68,
- cy_readw(cy_pci_addr0+0x68)|0x0900);
-#endif /* CONFIG_CYZ_INTR */
cy_next_channel += cy_pci_nchan;
}
}
for (; ZeIndex != 0 && i < NR_CARDS; i++) {
cy_pci_addr0 = Ze_addr0[0];
cy_pci_addr2 = Ze_addr2[0];
+ cy_pci_irq = Ze_irq[0];
for (j = 0 ; j < ZeIndex-1 ; j++) {
Ze_addr0[j] = Ze_addr0[j+1];
Ze_addr2[j] = Ze_addr2[j+1];
+ Ze_irq[j] = Ze_irq[j+1];
}
ZeIndex--;
mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *)
printk("%d channels starting from port %d.\n",
cy_pci_nchan,cy_next_channel);
-#ifdef CONFIG_CYZ_INTR
- /* Enable interrupts on the PLX chip */
- cy_writew(cy_pci_addr0+0x68,
- cy_readw(cy_pci_addr0+0x68)|0x0900);
-#endif /* CONFIG_CYZ_INTR */
cy_next_channel += cy_pci_nchan;
}
if (ZeIndex != 0) {
info->rco = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
+ info->icount.cts = info->icount.dsr =
+ info->icount.rng = info->icount.dcd = 0;
+ info->icount.rx = info->icount.tx = 0;
+ info->icount.frame = info->icount.parity = 0;
+ info->icount.overrun = info->icount.brk = 0;
info->x_char = 0;
info->event = 0;
info->count = 0;
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->shutdown_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
/* info->session */
/* info->pgrp */
info->read_status_mask = 0;
info->cor5 = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = CLOSING_WAIT_DELAY;
+ info->icount.cts = info->icount.dsr =
+ info->icount.rng = info->icount.dcd = 0;
+ info->icount.rx = info->icount.tx = 0;
+ info->icount.frame = info->icount.parity = 0;
+ info->icount.overrun = info->icount.brk = 0;
chip_number = (port - cinfo->first_line) / 4;
if ((info->chip_rev = cy_readb(cinfo->base_addr +
(cy_chip_offset[chip_number]<<index) +
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->shutdown_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
/* info->session */
/* info->pgrp */
info->read_status_mask =
restore_flags(flags);
for (i = 0; i < NR_CARDS; i++) {
- if (cy_card[i].base_addr != 0
+ if (cy_card[i].base_addr != 0) {
+ iounmap((void *)cy_card[i].base_addr);
+ if (cy_card[i].ctl_addr != 0)
+ iounmap((void *)cy_card[i].ctl_addr);
+ if (cy_card[i].irq
#ifndef CONFIG_CYZ_INTR
- && cy_card[i].num_chips != -1 /* not a Z card */
+ && cy_card[i].num_chips != -1 /* not a Z card */
#endif /* CONFIG_CYZ_INTR */
- && cy_card[i].irq)
- {
- free_irq(cy_card[i].irq, &cy_card[i]);
+ )
+ free_irq(cy_card[i].irq, &cy_card[i]);
}
}
if (tmp_buf) {
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
+#include <asm/semaphore.h>
#define VERSION "1.6.1"
ch->blocked_open = 0;
ch->callout_termios = pcxe_callout.init_termios;
ch->normal_termios = pcxe_driver.init_termios;
- ch->open_wait = 0;
- ch->close_wait = 0;
+ init_waitqueue_head(ch->open_wait);
+ init_waitqueue_head(ch->close_wait);
ch->asyncflags = 0;
}
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_RTRACK_PORT */
+#include <asm/semaphore.h> /* Lock for the I/O */
#ifndef CONFIG_RADIO_RTRACK_PORT
#define CONFIG_RADIO_RTRACK_PORT -1
static int io = CONFIG_RADIO_RTRACK_PORT;
static int users = 0;
+static struct semaphore lock;
struct rt_device
{
static void rt_mute(struct rt_device *dev)
{
dev->muted = 1;
+ down(&lock);
outb(0xd0, io); /* volume steady, off */
+ up(&lock);
}
static int rt_setvol(struct rt_device *dev, int vol)
{
int i;
+ down(&lock);
+
if(vol == dev->curvol) { /* requested volume = current */
if (dev->muted) { /* user is unmuting the card */
dev->muted = 0;
outb (0xd8, io); /* enable card */
}
-
+ up(&lock);
return 0;
}
sleep_delay(2000000); /* make sure it's totally down */
outb(0xd0, io); /* volume steady, off */
dev->curvol = 0; /* track the volume state! */
+ up(&lock);
return 0;
}
rt_decvol();
dev->curvol = vol;
-
+ up(&lock);
return 0;
}
freq += 171200; /* Add 10.7 MHz IF */
freq /= 800; /* Convert to 50 kHz units */
+
+ down(&lock); /* Stop other ops interfering */
send_0_byte (io, dev); /* 0: LSB of frequency */
outb (0xd0, io); /* volume steady + sigstr */
else
outb (0xd8, io); /* volume steady + sigstr + on */
+
+ up(&lock);
return 0;
}
-int rt_getsigstr(struct rt_device *dev)
+static int rt_getsigstr(struct rt_device *dev)
{
if (inb(io) & 2) /* bit set = no signal present */
return 0;
NULL
};
-int __init rtrack_init(struct video_init *v)
+static int __init rtrack_init(void)
{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ return -EINVAL;
+ }
+
if (check_region(io, 2))
{
printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
request_region(io, 2, "rtrack");
printk(KERN_INFO "AIMSlab Radiotrack/radioreveal card driver.\n");
+ /* Set up the I/O locking */
+
+ init_MUTEX(&lock);
+
/* mute card - prevents noisy bootups */
/* this ensures that the volume is all the way down */
return 0;
}
-#ifdef MODULE
-
MODULE_AUTHOR("M.Kirkwood");
MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
MODULE_PARM(io, "i");
EXPORT_NO_SYMBOLS;
-int init_module(void)
-{
- if(io==-1)
- {
- printk(KERN_ERR "You must set an I/O address with io=0x???\n");
- return -EINVAL;
- }
- return rtrack_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit cleanup_rtrack_module(void)
{
video_unregister_device(&rtrack_radio);
release_region(io,2);
}
-#endif
+module_init(rtrack_init);
+module_exit(cleanup_rtrack_module);
+
static int io = CONFIG_RADIO_AZTECH_PORT;
static int radio_wait_time = 1000;
static int users = 0;
+static struct semaphore lock;
struct az_device
{
static int az_setvol(struct az_device *dev, int vol)
{
+ down(&lock);
outb (volconvert(vol), io);
+ up(&lock);
return 0;
}
frequency += 171200; /* Add 10.7 MHz IF */
frequency /= 800; /* Convert to 50 kHz units */
+ down(&lock);
+
send_0_byte (dev); /* 0: LSB of frequency */
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
udelay (radio_wait_time);
outb_p(128+64+volconvert(dev->curvol), io);
+
+ up(&lock);
return 0;
}
NULL
};
-int __init aztech_init(struct video_init *v)
+static int __init aztech_init(void)
{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ return -EINVAL;
+ }
+
if (check_region(io, 2))
{
printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
return -EBUSY;
}
+ init_MUTEX(&lock);
aztech_radio.priv=&aztech_unit;
if(video_register_device(&aztech_radio, VFL_TYPE_RADIO)==-1)
return 0;
}
-#ifdef MODULE
-
MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
MODULE_DESCRIPTION("A driver for the Aztech radio card.");
MODULE_PARM(io, "i");
EXPORT_NO_SYMBOLS;
-int init_module(void)
-{
- if(io==-1)
- {
- printk(KERN_ERR "You must set an I/O address with io=0x???\n");
- return -EINVAL;
- }
- return aztech_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit aztech_cleanup(void)
{
video_unregister_device(&aztech_radio);
release_region(io,2);
}
-#endif
+module_init(aztech_init);
+module_exit(aztech_cleanup);
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_GEMTEK_PORT */
+#include <linux/spinlock.h>
#ifndef CONFIG_RADIO_GEMTEK_PORT
#define CONFIG_RADIO_GEMTEK_PORT -1
static int io = CONFIG_RADIO_GEMTEK_PORT;
static int users = 0;
+static spinlock_t lock;
struct gemtek_device
{
{
if(dev->muted)
return;
+ spin_lock(&lock);
outb(0x10, io);
+ spin_unlock(&lock);
dev->muted = 1;
}
{
if(dev->muted == 0)
return;
+ spin_lock(&lock);
outb(0x20, io);
+ spin_unlock(&lock);
dev->muted = 0;
}
freq *= 7825;
freq /= 100000;
+ spin_lock(&lock);
+
/* 2 start bits */
outb_p(0x03, io);
udelay(5);
outb_p(0x07, io);
udelay(5);
+ spin_unlock(&lock);
+
return 0;
}
int gemtek_getsigstr(struct gemtek_device *dev)
{
+ spin_lock(&lock);
inb(io);
udelay(5);
+ spin_unlock(&lock);
if (inb(io) & 8) /* bit set = no signal present */
return 0;
return 1; /* signal present */
NULL
};
-int __init gemtek_init(struct video_init *v)
+static int __init gemtek_init(void)
{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (or io=0x248 for the combined sound/radiocard)\n");
+ return -EINVAL;
+ }
+
if (check_region(io, 4))
{
printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
request_region(io, 4, "gemtek");
printk(KERN_INFO "GemTek Radio Card driver.\n");
+ spin_lock_init(&lock);
/* mute card - prevents noisy bootups */
outb(0x10, io);
udelay(5);
return 0;
}
-#ifdef MODULE
-
MODULE_AUTHOR("Jonas Munsin");
MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
MODULE_PARM(io, "i");
EXPORT_NO_SYMBOLS;
-int init_module(void)
-{
- if(io==-1)
- {
- printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (or io=0x248 for the combined sound/radiocard)\n");
- return -EINVAL;
- }
- return gemtek_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit gemtek_cleanup(void)
{
video_unregister_device(&gemtek_radio);
release_region(io,4);
}
-#endif
+module_init(gemtek_init);
+module_exit(gemtek_cleanup);
/*
Local variables:
NULL
};
-int __init pcm20_init(struct video_init *v)
+static int __init pcm20_init(void)
{
pcm20_radio.priv=&pcm20_unit;
return 0;
}
-#ifdef MODULE
-
MODULE_AUTHOR("Ruurd Reitsma");
MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
EXPORT_NO_SYMBOLS;
-int init_module(void)
-{
-
- return pcm20_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit pcm20_cleanup(void)
{
video_unregister_device(&pcm20_radio);
}
-#endif
+module_init(pcm20_init);
+module_exit(pcm20_cleanup);
+
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_RTRACK2_PORT */
+#include <linux/spinlock.h>
#ifndef CONFIG_RADIO_RTRACK2_PORT
#define CONFIG_RADIO_RTRACK2_PORT -1
static int io = CONFIG_RADIO_RTRACK2_PORT;
static int users = 0;
+static spinlock_t lock;
struct rt_device
{
{
if(dev->muted)
return;
+ spin_lock(&lock);
outb(1, io);
+ spin_unlock(&lock);
dev->muted = 1;
}
{
if(dev->muted == 0)
return;
+ spin_lock(&lock);
outb(0, io);
+ spin_unlock(&lock);
dev->muted = 0;
}
int i;
freq = freq / 200 + 856;
+
+ spin_lock(&lock);
outb_p(0xc8, io);
outb_p(0xc9, io);
outb_p(0xc8, io);
if (!dev->muted)
- outb_p(0, io);
+ outb_p(0, io);
+
+ spin_unlock(&lock);
return 0;
}
-int rt_getsigstr(struct rt_device *dev)
+static int rt_getsigstr(struct rt_device *dev)
{
if (inb(io) & 2) /* bit set = no signal present */
return 0;
}
rtrack2_radio.priv=&rtrack2_unit;
-
+
+ spin_lock_init(&lock);
if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1)
return -EINVAL;
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_SF16MI_PORT */
+#include <asm/semaphore.h>
struct fmi_device
{
static int io = CONFIG_RADIO_SF16FMI_PORT;
static int users = 0;
+static struct semaphore lock;
/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
/* It is only usefull to give freq in intervall of 800 (=0.05Mhz),
static inline void fmi_mute(int port)
{
+ down(&lock);
outb(0x00, port);
+ up(&lock);
}
static inline void fmi_unmute(int port)
{
+ down(&lock);
outb(0x08, port);
+ up(&lock);
}
static inline int fmi_setfreq(struct fmi_device *dev)
unsigned long freq = dev->curfreq;
int i;
+ down(&lock);
+
outbits(16, RSF16_ENCODE(freq), myport);
outbits(8, 0xC0, myport);
for(i=0; i< 100; i++)
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ/7);
*/
+
+ up(&lock);
if (dev->curvol) fmi_unmute(myport);
return 0;
}
int myport = dev->port;
int i;
+ down(&lock);
val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */
outb(val, myport);
outb(val | 0x10, myport);
*/
res = (int)inb(myport+1);
outb(val, myport);
+
+ up(&lock);
return (res & 2) ? 0 : 0xFFFF;
}
fmi_unit.flags = VIDEO_TUNER_LOW;
fmi_radio.priv = &fmi_unit;
+ init_MUTEX(&lock);
+
if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1)
return -EINVAL;
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/config.h> /* CONFIG_RADIO_TERRATEC_PORT */
+#include <linux/spinlock.h>
#ifndef CONFIG_RADIO_TERRATEC_PORT
#define CONFIG_RADIO_TERRATEC_PORT 0x590
static int io = CONFIG_RADIO_TERRATEC_PORT;
static int users = 0;
+static spinlock_t lock;
struct tt_device
{
{
int i;
volume = volume+(volume * 32); // change both channels
+ spin_lock(&lock);
for (i=0;i<8;i++)
{
if (volume & (0x80>>i))
outb(0x80, VOLPORT);
else outb(0x00, VOLPORT);
}
+ spin_unlock(&lock);
}
temp = temp/2;
}
+ spin_lock(&lock);
+
for (i=24;i>-1;i--) /* bit shift the values to the radiocard */
{
if (buffer[i]==1)
}
}
outb(0x00, BASEPORT);
+
+ spin_unlock(&lock);
return 0;
}
terratec_radio.priv=&terratec_unit;
+ spin_lock_init(&lock);
+
if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1)
return -EINVAL;
--- /dev/null
+/* radio-trust.c - Trust FM Radio card driver for Linux 2.2
+ * by Eric Lammerts <eric@scintilla.utwente.nl>
+ *
+ * Based on radio-aztech.c. Original notes:
+ *
+ * Adapted to support the Video for Linux API by
+ * Russell Kroll <rkroll@exploits.org>. Based on original tuner code by:
+ *
+ * Quay Ly
+ * Donald Song
+ * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
+ * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
+ * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
+ *
+ * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
+ */
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/videodev.h>
+#include <linux/config.h> /* CONFIG_RADIO_TRUST_PORT */
+
+/* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
+
+#ifndef CONFIG_RADIO_TRUST_PORT
+#define CONFIG_RADIO_TRUST_PORT -1
+#endif
+
+static int io = CONFIG_RADIO_TRUST_PORT;
+static int ioval = 0xf;
+static int users = 0;
+static __u16 curvol;
+static __u16 curbass;
+static __u16 curtreble;
+static unsigned long curfreq;
+static int curstereo;
+static int curmute;
+
+/* i2c addresses */
+#define TDA7318_ADDR 0x88
+#define TSA6060T_ADDR 0xc4
+
+#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0)
+#define TR_SET_SCL outb(ioval |= 2, io)
+#define TR_CLR_SCL outb(ioval &= 0xfd, io)
+#define TR_SET_SDA outb(ioval |= 1, io)
+#define TR_CLR_SDA outb(ioval &= 0xfe, io)
+
+static void write_i2c(int n, ...)
+{
+ unsigned char val, mask;
+ va_list args;
+
+ va_start(args, n);
+
+ /* start condition */
+ TR_SET_SDA;
+ TR_SET_SCL;
+ TR_DELAY;
+ TR_CLR_SDA;
+ TR_CLR_SCL;
+ TR_DELAY;
+
+ for(; n; n--) {
+ val = va_arg(args, unsigned);
+ for(mask = 0x80; mask; mask >>= 1) {
+ if(val & mask)
+ TR_SET_SDA;
+ else
+ TR_CLR_SDA;
+ TR_SET_SCL;
+ TR_DELAY;
+ TR_CLR_SCL;
+ TR_DELAY;
+ }
+ /* acknowledge bit */
+ TR_SET_SDA;
+ TR_SET_SCL;
+ TR_DELAY;
+ TR_CLR_SCL;
+ TR_DELAY;
+ }
+
+ /* stop condition */
+ TR_CLR_SDA;
+ TR_DELAY;
+ TR_SET_SCL;
+ TR_DELAY;
+ TR_SET_SDA;
+ TR_DELAY;
+
+ va_end(args);
+}
+
+static void tr_setvol(__u16 vol)
+{
+ curvol = vol / 2048;
+ write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f);
+}
+
+static int basstreble2chip[15] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8
+};
+
+static void tr_setbass(__u16 bass)
+{
+ curbass = bass / 4370;
+ write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]);
+}
+
+static void tr_settreble(__u16 treble)
+{
+ curtreble = treble / 4370;
+ write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]);
+}
+
+static void tr_setstereo(int stereo)
+{
+ curstereo = !!stereo;
+ ioval = (ioval & 0xfb) | (!curstereo << 2);
+ outb(ioval, io);
+}
+
+static void tr_setmute(int mute)
+{
+ curmute = !!mute;
+ ioval = (ioval & 0xf7) | (curmute << 3);
+ outb(ioval, io);
+}
+
+static int tr_getsigstr(void)
+{
+ int i, v;
+
+ for(i = 0, v = 0; i < 100; i++) v |= inb(io);
+ return (v & 1)? 0 : 0xffff;
+}
+
+static int tr_getstereo(void)
+{
+ /* don't know how to determine it, just return the setting */
+ return curstereo;
+}
+
+static void tr_setfreq(unsigned long f)
+{
+ f /= 160; /* Convert to 10 kHz units */
+ f += 1070; /* Add 10.7 MHz IF */
+
+ write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0);
+}
+
+static int tr_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+
+ v.type=VID_TYPE_TUNER;
+ v.channels=1;
+ v.audios=1;
+
+ /* No we don't do pictures */
+ v.maxwidth=0;
+ v.maxheight=0;
+ v.minwidth=0;
+ v.minheight=0;
+
+ strcpy(v.name, "Trust FM Radio");
+
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+
+ if(copy_from_user(&v, arg,sizeof(v))!=0)
+ return -EFAULT;
+
+ if(v.tuner) /* Only 1 tuner */
+ return -EINVAL;
+
+ v.rangelow = 87500 * 16;
+ v.rangehigh = 108000 * 16;
+ v.flags = VIDEO_TUNER_LOW;
+ v.mode = VIDEO_MODE_AUTO;
+
+ v.signal = tr_getsigstr();
+ if(tr_getstereo())
+ v.flags |= VIDEO_TUNER_STEREO_ON;
+
+ strcpy(v.name, "FM");
+
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.tuner != 0)
+ return -EINVAL;
+
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ if(copy_to_user(arg, &curfreq, sizeof(curfreq)))
+ return -EFAULT;
+ return 0;
+
+ case VIDIOCSFREQ:
+ {
+ unsigned long f;
+
+ if(copy_from_user(&f, arg, sizeof(curfreq)))
+ return -EFAULT;
+ tr_setfreq(f);
+ return 0;
+ }
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+
+ memset(&v,0, sizeof(v));
+ v.flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME |
+ VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
+ v.mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ v.volume = curvol * 2048;
+ v.step = 2048;
+ v.bass = curbass * 4370;
+ v.treble = curtreble * 4370;
+
+ strcpy(v.name, "Trust FM Radio");
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.audio)
+ return -EINVAL;
+
+ tr_setvol(v.volume);
+ tr_setbass(v.bass);
+ tr_settreble(v.treble);
+ tr_setstereo(v.mode & VIDEO_SOUND_STEREO);
+ tr_setmute(v.flags & VIDEO_AUDIO_MUTE);
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int tr_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void tr_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+static struct video_device trust_radio=
+{
+ "Trust FM Radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_TRUST,
+ tr_open,
+ tr_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* No poll */
+ tr_ioctl,
+ NULL,
+ NULL
+};
+
+static int __init trust_init(void)
+{
+ if(io == -1) {
+ printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ return -EINVAL;
+ }
+ if(check_region(io, 2)) {
+ printk(KERN_ERR "trust: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
+ if(video_register_device(&trust_radio, VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io, 2, "Trust FM Radio");
+
+ printk(KERN_INFO "Trust FM Radio card driver v1.0.\n");
+
+ write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */
+ write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */
+ write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */
+ write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */
+ write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */
+
+ tr_setvol(0x8000);
+ tr_setbass(0x8000);
+ tr_settreble(0x8000);
+ tr_setstereo(1);
+
+ /* mute card - prevents noisy bootups */
+ tr_setmute(1);
+
+ return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
+
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
+
+static void __exit cleanup_trust_module(void)
+{
+ video_unregister_device(&trust_radio);
+ release_region(io, 2);
+}
+
+module_init(trust_init);
+module_exit(cleanup_trust_module);
unsigned long curfreq;
int muted;
unsigned int stereo;
+ struct semaphore lock;
};
if (dev->muted)
return 0;
+ down(&dev->lock);
if (vol == 0) {
outb(0, io);
outb(0, io);
inb(io + 3); /* Zoltrix needs to be read to confirm */
+ up(&dev->lock);
return 0;
}
outb(dev->curvol-1, io);
sleep_delay();
inb(io + 2);
-
+ up(&dev->lock);
return 0;
}
static void zol_mute(struct zol_device *dev)
{
dev->muted = 1;
+ down(&dev->lock);
outb(0, io);
outb(0, io);
inb(io + 3); /* Zoltrix needs to be read to confirm */
+ up(&dev->lock);
}
static void zol_unmute(struct zol_device *dev)
bitmask = 0xc480402c10080000ull;
i = 45;
+ down(&dev->lock);
+
outb(0, io);
outb(0, io);
inb(io + 3); /* Zoltrix needs to be read to confirm */
inb(io+2);
udelay(1000);
+
if (dev->muted)
{
outb(0, io);
outb(0, io);
inb(io + 3);
udelay(1000);
- } else
- zol_setvol(dev, dev->curvol);
+ }
+
+ up(&dev->lock);
+
+ if(!dev->muted)
+ {
+ zol_setvol(dev, dev->curvol);
+ }
return 0;
}
{
int a, b;
+ down(&dev->lock);
outb(0x00, io); /* This stuff I found to do nothing */
outb(dev->curvol, io);
sleep_delay();
sleep_delay();
b = inb(io);
+ up(&dev->lock);
+
if (a != b)
return (0);
{
int x1, x2;
+ down(&dev->lock);
+
outb(0x00, io);
outb(dev->curvol, io);
sleep_delay();
sleep_delay();
x2 = inb(io);
+ up(&dev->lock);
+
if ((x1 == x2) && (x1 == 0xcf))
return 1;
return 0;
request_region(io, 2, "zoltrix");
printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
+ init_MUTEX(&zoltrix_unit.lock);
+
/* mute card - prevents noisy bootups */
/* this ensures that the volume is all the way down */
/*
* random.c -- A strong random number generator
*
- * Version 1.88, last modified 30-Aug-99
+ * Version 1.89, last modified 19-Sep-99
*
* Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All
* rights reserved.
*/
void get_random_bytes(void *buf, int nbytes)
{
- extract_entropy(sec_random_state, (char *) buf, nbytes,
- EXTRACT_ENTROPY_SECONDARY);
+ if (sec_random_state)
+ extract_entropy(sec_random_state, (char *) buf, nbytes,
+ EXTRACT_ENTROPY_SECONDARY);
+ else if (random_state)
+ extract_entropy(random_state, (char *) buf, nbytes, 0);
+ else
+ printk(KERN_NOTICE "get_random_bytes called before "
+ "random driver initialization\n");
}
/*********************************************************************
if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
rekey_time = tv.tv_sec;
/* First three words are overwritten below. */
- get_random_bytes(&secret+3, sizeof(secret)-12);
+ get_random_bytes(&secret[3], sizeof(secret)-12);
count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;
}
-#define PAGE_WAIT 30 /* Time in jiffies between requesting page and */
+#define PAGE_WAIT (300*HZ/1000) /* Time between requesting page and */
/* checking status bits */
-#define PGBUF_EXPIRE 1500 /* Time in jiffies to wait before retransmitting */
+#define PGBUF_EXPIRE (15*HZ) /* Time to wait before retransmitting */
/* page regardless of infobits */
typedef struct {
u8 pgbuf[VTX_VIRTUALSIZE]; /* Page-buffer */
#define CCTWR 34 /* I²C write/read-address of vtx-chip */
#define CCTRD 35
#define NOACK_REPEAT 10 /* Retry access this many times on failure */
-#define CLEAR_DELAY 5 /* Time in jiffies required to clear a page */
-#define I2C_TIMEOUT 300 /* open/close/SDA-check timeout in jiffies */
-#define READY_TIMEOUT 3 /* Time in jiffies to wait for ready signal of I²C-bus interface */
+#define CLEAR_DELAY (HZ/20) /* Time required to clear a page */
+#define I2C_TIMEOUT (3*HZ) /* open/close/SDA-check timeout */
+#define READY_TIMEOUT (30*HZ/1000) /* Time to wait for ready signal of I²C-bus interface */
#define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */
#define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */
+
/* 3c527.c: 3Com Etherlink/MC32 driver for Linux
*
* (c) Copyright 1998 Red Hat Software Inc
*/
static const char *version =
- "3c527.c:v0.04 1999/03/16 Alan Cox (alan@redhat.com)\n";
+ "3c527.c:v0.05 1999/09/06 Alan Cox (alan@redhat.com)\n";
/*
* Things you need
u16 tx_skb_end;
struct sk_buff *rx_skb[RX_RING_MAX]; /* Receive ring */
void *rx_ptr[RX_RING_MAX]; /* Data pointers */
+ u32 mc_list_valid; /* True when the mclist is set */
};
/* The station (ethernet) address prefix, used for a sanity check. */
static int mc32_close(struct net_device *dev);
static struct net_device_stats *mc32_get_stats(struct net_device *dev);
static void mc32_set_multicast_list(struct net_device *dev);
+static void mc32_reset_multicast_list(struct net_device *dev);
+
/*
* Check for a network adaptor of this type, and return '0' iff one exists.
/*
* Send exec commands
*/
-
+
+
+/*
+ * Send command from interrupt state
+ */
+
+static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len)
+{
+ struct mc32_local *lp = (struct mc32_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if(lp->exec_pending)
+ return -1;
+
+ lp->exec_pending=1;
+ lp->exec_box->mbox=0;
+ lp->exec_box->mbox=cmd;
+ memcpy((void *)lp->exec_box->data, data, len);
+ barrier(); /* the memcpy forgot the volatile so be sure */
+
+ /* Send the command */
+ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
+ outb(1<<6, ioaddr+HOST_CMD);
+ return 0;
+}
+
+
+/*
+ * Send command and block for results. On completion spot and reissue
+ * multicasts
+ */
+
static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len)
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
int ioaddr = dev->base_addr;
unsigned long flags;
+ int ret = 0;
+ /*
+ * Wait for a command
+ */
+
while(lp->exec_pending)
sleep_on(&lp->event);
+ /*
+ * Issue mine
+ */
+
lp->exec_pending=1;
lp->exec_box->mbox=0;
lp->exec_box->mbox=cmd;
lp->exec_pending=0;
restore_flags(flags);
+
+ if(lp->exec_box->data[0]&(1<<13))
+ ret = -1;
/*
* A multicast set got blocked - do it now
*/
-
+
if(lp->mc_reload_wait)
- mc32_set_multicast_list(dev);
+ mc32_reset_multicast_list(dev);
- if(lp->exec_box->data[0]&(1<<13))
- return -1;
- return 0;
+ return ret;
}
+
/*
* RX abort
*/
* num_addrs > 0 Multicast mode, receive normal and MC packets,
* and do best-effort filtering.
*/
-static void mc32_set_multicast_list(struct net_device *dev)
+static void do_mc32_set_multicast_list(struct net_device *dev, int retry)
{
+ struct mc32_local *lp = (struct mc32_local *)dev->priv;
u16 filt;
+
if (dev->flags&IFF_PROMISC)
- {
/* Enable promiscuous mode */
filt = 1;
- mc32_command(dev, 0, &filt, 2);
- }
else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > 10)
{
dev->flags|=IFF_PROMISC;
filt = 1;
- mc32_command(dev, 0, &filt, 2);
}
else if(dev->mc_count)
{
int i;
filt = 0;
- block[1]=0;
- block[0]=dev->mc_count;
- bp=block+2;
- for(i=0;i<dev->mc_count;i++)
+ if(retry==0)
+ lp->mc_list_valid = 0;
+ if(!lp->mc_list_valid)
{
- memcpy(bp, dmc->dmi_addr, 6);
- bp+=6;
- dmc=dmc->next;
+ block[1]=0;
+ block[0]=dev->mc_count;
+ bp=block+2;
+
+ for(i=0;i<dev->mc_count;i++)
+ {
+ memcpy(bp, dmc->dmi_addr, 6);
+ bp+=6;
+ dmc=dmc->next;
+ }
+ if(mc32_command_nowait(dev, 2, block, 2+6*dev->mc_count)==-1)
+ {
+ lp->mc_reload_wait = 1;
+ return;
+ }
+ lp->mc_list_valid=1;
}
- mc32_command(dev, 2, block, 2+6*dev->mc_count);
- mc32_command(dev, 0, &filt, 2);
}
else
{
filt = 0;
- mc32_command(dev, 0, &filt, 2);
}
+ if(mc32_command_nowait(dev, 0, &filt, 2)==-1)
+ {
+ lp->mc_reload_wait = 1;
+ }
+}
+
+static void mc32_set_multicast_list(struct net_device *dev)
+{
+ do_mc32_set_multicast_list(dev,0);
+}
+
+static void mc32_reset_multicast_list(struct net_device *dev)
+{
+ do_mc32_set_multicast_list(dev,1);
}
#ifdef MODULE
* wide.
*/
- p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len + 3) << PI_XMT_DESCR_V_SEG_LEN));
+ p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
p_xmt_descr->long_1 = (u32) virt_to_bus(skb->data);
/*
{
/* This is a little weird: set the shared memory window by doing a
read. The low address bits specify the starting page. */
- mem_base[start_page];
+ readb(mem_base+start_page);
inb(port + E21_MEM_ENABLE);
outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
}
comment 'Dongle support'
bool 'Serial dongle support' CONFIG_DONGLE
if [ "$CONFIG_DONGLE" != "n" ]; then
- dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
- dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
- dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
- dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
- dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
- dep_tristate ' Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA
+ dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
+ dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
+ dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
+ dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
+ dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
+ dep_tristate ' Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA
fi
endmenu
/* Wait at a few ms */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2);
+ schedule_timeout(MSECS_TO_JIFFIES(20));
/* Set DTR, Set RTS */
irda_device_set_dtr_rts(idev, TRUE, TRUE);
/* Wait at a few ms again */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2);
+ schedule_timeout(MSECS_TO_JIFFIES(20));
/* Go to next baudrate */
if (idev->io.dongle_id == ACTISYS_DONGLE)
/* Sleep 10-20 ms*/
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2);
+ schedule_timeout(MSECS_TO_JIFFIES(20));
/* Go back to normal mode */
irda_device_set_dtr_rts(idev, TRUE, TRUE);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Wed Aug 11 09:24:46 1999
+ * Modified at: Tue Aug 31 13:54:27 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
int lcr; /* Line control reg */
int divisor;
- DEBUG(0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+ DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
*/
static void irport_receive(struct irda_device *idev)
{
- int iobase;
int boguscount = 0;
+ int iobase;
ASSERT(idev != NULL, return;);
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
- DEBUG(0,__FUNCTION__ "(), breaking!\n");
+ DEBUG(2,__FUNCTION__ "(), breaking!\n");
break;
}
} while (inb(iobase+UART_LSR) & UART_LSR_DR);
DEBUG(2, __FUNCTION__ "(), RLSI\n");
break;
case UART_IIR_RDI:
- //if (lsr & UART_LSR_DR)
- /* Receive interrupt */
- irport_receive(idev);
+ /* Receive interrupt */
+ irport_receive(idev);
break;
case UART_IIR_THRI:
if (lsr & UART_LSR_THRE)
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Tue Aug 24 13:32:24 1999
+ * Modified at: Tue Sep 28 08:39:29 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
********************************************************************/
#include <linux/module.h>
-#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/tty.h>
-#include <asm/segment.h>
#include <linux/init.h>
+#include <linux/skbuff.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <net/irda/irda.h>
#include <net/irda/irtty.h>
*/
if (fp && *fp++) {
DEBUG( 0, "Framing or parity error!\n");
- irda_device_set_media_busy(&self->idev, TRUE);
+ irda_device_set_media_busy(&self->idev.netdev, TRUE);
cp++;
continue;
static int irtty_net_open(struct net_device *dev)
{
+ struct irda_device *idev = dev->priv;
+
irda_device_net_open(dev);
+ /* Make sure we can receive more data */
+ irtty_stop_receiver(idev, FALSE);
+
MOD_INC_USE_COUNT;
return 0;
static int irtty_net_close(struct net_device *dev)
{
+ struct irda_device *idev = dev->priv;
+
+ /* Make sure we don't receive more data */
+ irtty_stop_receiver(idev, TRUE);
+
irda_device_net_close(dev);
MOD_DEC_USE_COUNT;
{
/* Just delay 60 ms */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(6);
+ schedule_timeout(MSECS_TO_JIFFIES(60));
}
/*
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
* Created at:
- * Modified at: Tue Aug 24 13:33:22 1999
+ * Modified at: Wed Sep 22 07:47:19 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
#define CHIP_IO_EXTENT 8
-static unsigned int io[] = { 0x2e8, 0x140, ~0, ~0 };
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0, 0};
+static unsigned int io[] = { 0x2e8, 0x140, 0x118, ~0 };
+static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0};
static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
/* Some prototypes */
static int ircc_open( int i, unsigned int iobase, unsigned int board_addr);
+#ifdef MODULE
static int ircc_close( struct irda_device *idev);
+#endif /* MODULE */
static int ircc_probe( int iobase, int board_addr);
static int ircc_dma_receive( struct irda_device *idev);
static int ircc_dma_receive_complete(struct irda_device *idev, int iobase);
* Close driver instance
*
*/
+#ifdef MODULE
static int ircc_close( struct irda_device *idev)
{
int iobase;
DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
+#endif /* MODULE */
/*
* Function ircc_probe (iobase, board_addr, irq, dma)
* Returns non-negative on success.
*
*/
-static int ircc_probe( int iobase, int iobase2)
+static int ircc_probe(int iobase, int iobase2)
{
int version = 1;
int low, high, chip, config, dma, irq;
irq = config >> 4 & 0x0f;
dma = config & 0x0f;
- if (high == 0x10 && low == 0xb8 && chip == 0xf1) {
- DEBUG(0, "SMC IrDA Controller found; version = %d, "
+ if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) {
+ DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
"port 0x%04x, dma %d, interrupt %d\n",
- version, iobase, dma, irq);
+ chip & 0x0f, version, iobase, dma, irq);
} else {
return -1;
}
serial_out(iobase, UART_MASTER, 0);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return config;
}
/* Just delay 60 ms */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(6);
+ schedule_timeout(MSECS_TO_JIFFIES(60));
DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
while (self->taskfile->xmit[i].control)
{
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout (6);
+ schedule_timeout (MSECS_TO_JIFFIES(60));
}
}
{
/* Just delay 60 ms */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(6);
+ schedule_timeout(MSECS_TO_JIFFIES(60));
}
/*
#include <asm/system.h>
#include <linux/netdevice.h>
-#include "../../drivers/net/8390.h"
+#include "../8390.h"
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
* This driver is for PCnet32 and PCnetPCI based ethercards
*/
-static const char *version = "pcnet32.c:v1.23 6.7.1999 tsbogend@alpha.franken.de\n";
+static const char *version = "pcnet32.c:v1.23ac 21.9.1999 tsbogend@alpha.franken.de\n";
#include <linux/config.h>
#include <linux/module.h>
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/spinlock.h>
static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
* Michael Richard <mcr@solidum.com>)
* added chip id for 79c973/975 (thanks to Zach Brown <zab@zabbo.net>)
* v1.23 fixed small bug, when manual selecting MII speed/duplex
+ * v1.23ac Added SMP spinlocking - Alan Cox <alan@redhat.com>
*/
struct sk_buff *rx_skbuff[RX_RING_SIZE];
struct pcnet32_access a;
void *origmem;
- int cur_rx, cur_tx; /* The next free ring entry */
- int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+ spinlock_t lock; /* Guard lock */
+ int cur_rx, cur_tx; /* The next free ring entry */
+ int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
char tx_full;
int options;
- int shared_irq:1, /* shared irq possible */
- full_duplex:1, /* full duplex possible */
- mii:1; /* mii port available */
+ int shared_irq:1, /* shared irq possible */
+ full_duplex:1, /* full duplex possible */
+ mii:1; /* mii port available */
#ifdef MODULE
struct net_device *next;
#endif
pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx)
{
struct pcnet32_private *lp;
- int i,media,fdx = 0, mii = 0;
+ int i,media,fdx = 0, mii = 0, fset = 0;
int chip_version;
char *chipname;
char *priv;
break;
case 0x2623:
chipname = "PCnet/FAST 79C971";
- fdx = 1; mii = 1;
+ fdx = 1; mii = 1; fset = 1;
break;
case 0x2624:
chipname = "PCnet/FAST+ 79C972";
- fdx = 1; mii = 1;
+ fdx = 1; mii = 1; fset = 1;
break;
case 0x2625:
chipname = "PCnet/FAST III 79C973";
printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version);
return ENODEV;
}
+
+ /*
+ * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
+ * starting until the packet is loaded. Strike one for reliability, lose
+ * one for latency - although on PCI this isnt a big loss. Older chips
+ * have FIFO's smaller than a packet, so you can't do this.
+ */
+
+ if(fset)
+ {
+ a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800));
+ a->write_csr(ioaddr, 80, a->read_csr(ioaddr, 80) | 0x0c00);
+ }
dev = init_etherdev(dev, 0);
lp = (struct pcnet32_private *)(((unsigned long)priv+15) & ~15);
memset(lp, 0, sizeof(*lp));
+
+ spin_lock_init(&lp->lock);
+
dev->priv = lp;
lp->name = chipname;
lp->shared_irq = shared;
return 1;
}
- save_flags (flags);
- cli ();
-
+ spin_lock_irqsave(&lp->lock, flags);
/* Fill in a Tx ring entry */
/* Mask to ring buffer boundary. */
clear_bit (0, (void *)&dev->tbusy);
else
lp->tx_full = 1;
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
ioaddr = dev->base_addr;
lp = (struct pcnet32_private *)dev->priv;
+
+ spin_lock(&lp->lock);
+
if (dev->interrupt)
printk("%s: Re-entering the interrupt handler.\n", dev->name);
/* Clear any other interrupt, and set interrupt enable. */
lp->a.write_csr (ioaddr, 0, 0x7940);
lp->a.write_rap(ioaddr,rap);
-
+
if (pcnet32_debug > 4)
printk("%s: exiting interrupt, csr0=%#4.4x.\n",
dev->name, lp->a.read_csr (ioaddr, 0));
dev->interrupt = 0;
+
+ spin_unlock(&lp->lock);
return;
}
u16 saved_addr;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&lp->lock, flags);
saved_addr = lp->a.read_rap(ioaddr);
lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
lp->a.write_rap(ioaddr, saved_addr);
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->lock, flags);
return &lp->stats;
}
/* datagram completed: send to upper level */
skb_trim(skb, dlen);
netif_rx(skb);
+ stats->rx_bytes+=dlen;
stats->rx_packets++;
lp->rx_bytes += dlen;
lp->rx_skb[ns] = 0;
int i;
for (i = 0; i < 100; i++) {
sprintf(devname, "cm%d", i);
- if (dev_get(devname) == NULL) break;
+ if (dev_get(devname) == 0) break;
}
if (i == 100) {
printk(KERN_ERR "sb1000: can't register any device cm<n>\n");
struct slip *sl;
int err;
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
MOD_INC_USE_COUNT;
/* RTnetlink lock is misused here to serialize concurrent
static int duplex = 0;
static int speed = 0;
+MODULE_PARM(aui, "i");
+MODULE_PARM(sa_int, "i");
+MODULE_PARM(duplex, "i");
+MODULE_PARM(speed, "i");
+MODULE_PARM(debug, "i");
+EXPORT_NO_SYMBOLS;
+
#endif
/* printk( "TLAN: Found %d device(s).\n", TLanDevicesInstalled ); */
- return ( ( TLanDevicesInstalled >= 0 ) ? 0 : -ENODEV );
+ return ( ( TLanDevicesInstalled > 0 ) ? 0 : -ENODEV );
} /* init_module */
for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) {
TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
- TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
+ (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
if ( data & i )
TLan_SetBit( TLAN_NET_SIO_MDATA, sio );
else
TLan_ClearBit( TLAN_NET_SIO_MDATA, sio );
TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
- TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
+ (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
}
} /* TLan_MiiSendData */
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release },
/*
* Its not totally clear which chipsets are the problematic ones
- * This is the 82C586 variants. At the moment the 596 is an unknown
- * quantity.
+ * We know 82C586 and 82C596 variants are affected.
+ *
*/
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M },
{ 0 }
if (num_a2091++ == 0) {
first_instance = instance;
a2091_template = instance->hostt;
- request_irq(IRQ_AMIGA_PORTS, a2091_intr, SA_SHORQ, "A2091 SCSI",
+ request_irq(IRQ_AMIGA_PORTS, a2091_intr, SA_SHIRQ, "A2091 SCSI",
a2091_intr);
}
DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
/*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters.
*
+ * 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18
+ * + Updated to the new __setup interface for boot command line options.
+ * + When loaded as a module, accepts the new parameter boot_options
+ * which value is a string with the same format of the kernel boot
+ * command line options. A valid example is:
+ * modprobe eata 'boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\"'
+ *
+ * 9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17
+ * + 64bit cleanup for Linux/Alpha platform support
+ * (contribution from H.J. Lu).
+ *
+ * 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11
+ * + Removed pre-2.2 source code compatibility.
+ * + Added call to pci_set_master.
+ *
* 26 Jul 1998 Rev. 4.33 for linux 2.0.35 and 2.1.111
* + Added command line option (rs:[y|n]) to reverse the scan order
* of PCI boards. The default is rs:y, which reverses the BIOS order
* This driver is based on the CAM (Common Access Method Committee)
* EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
*
- * Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
+ * Copyright (C) 1994-1999 Dario Ballabio (dario@milano.europe.dg.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that redistributions of source
* PM3021 - SmartRAID Adapter for ISA
* PM3222 - SmartRAID Adapter for EISA (PM3222W is 16-bit wide SCSI)
* PM3224 - SmartRAID Adapter for PCI (PM3224W is 16-bit wide SCSI)
+ * PM33340UW - SmartRAID Adapter for PCI ultra wide multichannel
*
* The above list is just an indication: as a matter of fact all DPT
* boards using the EATA/DMA protocol are supported by this driver,
* After the optional list of detection probes, other possible command line
* options are:
*
- * eh:y use new scsi code (linux 2.2 only);
+ * eh:y use new scsi code;
* eh:n use old scsi code;
* et:y force use of extended translation (255 heads, 63 sectors);
* et:n use disk geometry detected by scsicam_bios_param;
#if defined(MODULE)
#include <linux/module.h>
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26)
+MODULE_PARM(boot_options, "s");
MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i");
MODULE_PARM(linked_comm, "i");
MODULE_PARM(tagged_comm, "i");
MODULE_PARM(ext_tran, "i");
MODULE_PARM(rev_scan, "i");
MODULE_AUTHOR("Dario Ballabio");
-#endif
#endif
#include <linux/stat.h>
#include <linux/config.h>
#include <linux/pci.h>
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)
-#include <linux/bios32.h>
-#endif
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36)
#include <linux/init.h>
+#include <linux/ctype.h>
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
+#include <asm/spinlock.h>
#else
-#define __initfunc(A) A
-#define __initdata
-#define __init
+#include <linux/spinlock.h>
#endif
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)
-#include <linux/spinlock.h>
-#define IRQ_FLAGS
-#define IRQ_LOCK
-#define IRQ_LOCK_SAVE
-#define IRQ_UNLOCK
-#define IRQ_UNLOCK_RESTORE
#define SPIN_FLAGS unsigned long spin_flags;
#define SPIN_LOCK spin_lock_irq(&io_request_lock);
#define SPIN_LOCK_SAVE spin_lock_irqsave(&io_request_lock, spin_flags);
#define SPIN_UNLOCK spin_unlock_irq(&io_request_lock);
#define SPIN_UNLOCK_RESTORE \
spin_unlock_irqrestore(&io_request_lock, spin_flags);
-static int use_new_eh_code = TRUE;
-#else
-#define IRQ_FLAGS unsigned long irq_flags;
-#define IRQ_LOCK cli();
-#define IRQ_LOCK_SAVE do {save_flags(irq_flags); cli();} while (0);
-#define IRQ_UNLOCK sti();
-#define IRQ_UNLOCK_RESTORE do {restore_flags(irq_flags);} while (0);
-#define SPIN_FLAGS
-#define SPIN_LOCK
-#define SPIN_LOCK_SAVE
-#define SPIN_UNLOCK
-#define SPIN_UNLOCK_RESTORE
-static int use_new_eh_code = FALSE;
-#endif
struct proc_dir_entry proc_scsi_eata2x = {
PROC_SCSI_EATA2X, 6, "eata2x",
#define ASOK 0x00
#define ASST 0x01
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
+#define ARRAY_SIZE(x) (sizeof (x) / sizeof((x)[0]))
+#endif
+
#define YESNO(a) ((a) ? 'y' : 'n')
#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)
/* Board info structure */
struct eata_info {
- ulong data_len; /* Number of valid bytes after this field */
- ulong sign; /* ASCII "EATA" signature */
+ u_int32_t data_len; /* Number of valid bytes after this field */
+ u_int32_t sign; /* ASCII "EATA" signature */
unchar :4, /* unused low nibble */
version:4; /* EATA version, should be 0x1 */
unchar ocsena:1, /* Overlap Command Support Enabled */
haaval:1; /* Host Adapter Address Valid */
ushort cp_pad_len; /* Number of pad bytes after cp_len */
unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */
- ulong cp_len; /* Number of valid bytes in cp */
- ulong sp_len; /* Number of valid bytes in sp */
+ u_int32_t cp_len; /* Number of valid bytes in cp */
+ u_int32_t sp_len; /* Number of valid bytes in sp */
ushort queue_size; /* Max number of cp that can be queued */
ushort unused;
ushort scatt_size; /* Max number of entries in scatter/gather table */
eoc:1; /* End Of Command (1 = command completed) */
unchar target_status; /* SCSI status received after data transfer */
unchar unused[2];
- ulong inv_res_len; /* Number of bytes not transferred */
- struct mscp *cpp; /* Address set in cp */
+ u_int32_t inv_res_len; /* Number of bytes not transferred */
+ u_int32_t cpp_index; /* Index of address set in cp */
char mess[12];
};
one:1; /* 1 */
unchar mess[3]; /* Massage to/from Target */
unchar cdb[12]; /* Command Descriptor Block */
- ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */
- struct mscp *cpp; /* Address to be returned in sp */
- ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */
- ulong sp_addr; /* Address where sp is DMA'ed when cp completes */
- ulong sense_addr; /* Address where Sense Data is DMA'ed on error */
+ u_int32_t data_len; /* If sg=0 Data Length, if sg=1 sglist length */
+ u_int32_t cpp_index; /* Index of address to be returned in sp */
+ u_int32_t data_address; /* If sg=0 Data Address, if sg=1 sglist address */
+ u_int32_t sp_addr; /* Address where sp is DMA'ed when cp completes */
+ u_int32_t sense_addr; /* Address where Sense Data is DMA'ed on error */
+ /* Additional fields begin here. */
Scsi_Cmnd *SCpnt;
- unsigned int index; /* cp index */
struct sg_list *sglist;
};
/* Initialize num_boards so that ihdlr can work while detect is in progress */
static unsigned int num_boards = MAX_BOARDS;
-static unsigned long io_port[] __initdata = {
+static unsigned long io_port[] = {
/* Space for MAX_INT_PARAM ports usable while loading as a module */
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
static int tag_mode = TAG_MIXED;
static int ext_tran = FALSE;
static int rev_scan = TRUE;
+static int use_new_eh_code = TRUE;
+static char *boot_options = NULL;
#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE)
static int tagged_comm = TRUE;
static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
Scsi_Device *dev;
int j, ntag = 0, nuntag = 0, tqd, utqd;
- IRQ_FLAGS
- IRQ_LOCK_SAVE
j = ((struct hostdata *) host->hostdata)->board_number;
for(dev = devlist; dev; dev = dev->next) {
dev->queue_depth, link_suffix, tag_suffix);
}
- IRQ_UNLOCK_RESTORE
return;
}
return FALSE;
}
-static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) {
+static inline int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) {
if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE;
return FALSE;
}
-static inline int __init
-get_pci_irq(unsigned long port_base, unsigned char *apic_irq){
+static inline void tune_pci_port(unsigned long port_base) {
#if defined(CONFIG_PCI)
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
+ unsigned int addr, k;
+ struct pci_dev *dev = NULL;
+
+ if (!pci_present()) return;
+
+ for (k = 0; k < MAX_PCI; k++) {
+
+ if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break;
+
+ if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;
+
+#if defined(DEBUG_PCI_DETECT)
+ printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n",
+ driver_name, dev->bus->number, dev->devfn, addr);
+#endif
+
+ if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {
+ pci_set_master(dev);
+ return;
+ }
+
+ }
+
+#endif /* end CONFIG_PCI */
+
+ return;
+}
+
+static inline int
+ get_pci_irq(unsigned long port_base, unsigned char *apic_irq) {
+
+#if defined(CONFIG_PCI)
unsigned int addr;
struct pci_dev *dev = NULL;
driver_name, dev->bus->number, dev->devfn, addr, dev->irq);
#endif
- if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
- continue;
-
if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) {
*apic_irq = dev->irq;
return TRUE;
}
-#endif /* end new style PCI code */
-
#endif /* end CONFIG_PCI */
return FALSE;
}
-static inline int __init port_detect \
- (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt){
+static inline int port_detect \
+ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
unsigned char irq, dma_channel, subversion, i;
unsigned char protocol_rev, apic_irq;
struct eata_info info;
sprintf(name, "%s%d", driver_name, j);
if(check_region(port_base, REGION_SIZE)) {
+#if defined(DEBUG_DETECT)
printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
+#endif
return FALSE;
}
config.len = (ushort) htons((ushort)510);
config.ocena = TRUE;
- if (do_dma(port_base, (unsigned int)&config, SET_CONFIG_DMA)) {
+ if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
printk("%s: busy timeout sending configuration, detaching.\n", name);
return FALSE;
}
}
else tag_type = 'n';
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)
sh[j]->hostt->use_new_eh_code = use_new_eh_code;
-#else
- use_new_eh_code = FALSE;
-#endif
if (j == 0) {
- printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
+ printk("EATA/DMA 2.0x: Copyright (C) 1994-1999 Dario Ballabio.\n");
printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c, rs:%c, et:%c.\n",
driver_name, tag_type, YESNO(linked_comm), max_queue_depth,
YESNO(use_new_eh_code), YESNO(rev_scan), YESNO(ext_tran));
info.pci, info.eisa, info.raidnum);
#endif
+ tune_pci_port(sh[j]->io_port);
return TRUE;
}
-void __init eata2x_setup(char *str, int *ints){
+static void internal_setup(char *str, int *ints) {
int i, argc = ints[0];
char *cur = str, *pc;
return;
}
-static void __init add_pci_ports(void){
+static int option_setup(char *str) {
+ int ints[MAX_INT_PARAM];
+ char *cur = str;
+ int i = 1;
+
+ while (cur && isdigit(*cur) && i <= MAX_INT_PARAM) {
+ ints[i++] = simple_strtoul(cur, NULL, 0);
+
+ if ((cur = strchr(cur, ',')) != NULL) cur++;
+ }
+
+ ints[0] = i - 1;
+ internal_setup(cur, ints);
+ return 0;
+}
+
+static void add_pci_ports(void) {
#if defined(CONFIG_PCI)
unsigned int addr, k;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)
-
struct pci_dev *dev = NULL;
if (!pci_present()) return;
(addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
}
-#else /* else old style PCI code */
-
- unsigned short i = 0;
- unsigned char bus, devfn;
-
- if (!pcibios_present()) return;
-
- for (k = 0; k < MAX_PCI; k++) {
-
- if (pcibios_find_class(PCI_CLASS_STORAGE_SCSI << 8, i++, &bus, &devfn)
- != PCIBIOS_SUCCESSFUL) break;
-
- if (pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &addr)
- != PCIBIOS_SUCCESSFUL) continue;
-
-#if defined(DEBUG_PCI_DETECT)
- printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n",
- driver_name, k, bus, devfn, addr);
-#endif
-
- if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
- continue;
-
- /* Order addresses according to rev_scan value */
- io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] =
- (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
- }
-
-#endif /* end old style PCI code */
-
#endif /* end CONFIG_PCI */
return;
}
-int __init eata2x_detect(Scsi_Host_Template *tpnt){
+int eata2x_detect(Scsi_Host_Template *tpnt) {
unsigned int j = 0, k;
- IRQ_FLAGS
- IRQ_LOCK_SAVE
tpnt->proc_dir = &proc_scsi_eata2x;
+ if(boot_options) option_setup(boot_options);
+
#if defined(MODULE)
/* io_port could have been modified when loading as a module */
if(io_port[0] != SKIP) {
}
num_boards = j;
- IRQ_UNLOCK_RESTORE
return j;
}
/* The EATA protocol uses Big Endian format */
cpp->sp_addr = V2DEV(spp);
- cpp->cpp = cpp;
SCpnt->scsi_done = done;
- cpp->index = i;
- SCpnt->host_scribble = (unsigned char *) &cpp->index;
+ cpp->cpp_index = i;
+ SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
BN(j), i, SCpnt->channel, SCpnt->target,
}
/* Send control packet to the board */
- if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
+ if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",
BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
int rtn;
- IRQ_FLAGS
- IRQ_LOCK_SAVE
rtn = do_qcomm(SCpnt, done);
- IRQ_UNLOCK_RESTORE
return rtn;
}
int eata2x_old_abort(Scsi_Cmnd *SCarg) {
int rtn;
- IRQ_FLAGS
- IRQ_LOCK_SAVE
rtn = do_old_abort(SCarg);
- IRQ_UNLOCK_RESTORE
return rtn;
}
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)
-
static inline int do_abort(Scsi_Cmnd *SCarg) {
unsigned int i, j;
return do_abort(SCarg);
}
-#endif /* new_eh_code */
-
static inline int do_old_reset(Scsi_Cmnd *SCarg) {
unsigned int i, j, time, k, c, limit = 0;
int arg_done = FALSE;
HD(j)->in_reset = TRUE;
SPIN_UNLOCK
- IRQ_UNLOCK
time = jiffies;
while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
- IRQ_LOCK
SPIN_LOCK
printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
continue;
SCpnt->scsi_done(SCpnt);
- IRQ_LOCK
}
HD(j)->in_reset = FALSE;
int eata2x_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
int rtn;
- IRQ_FLAGS
- IRQ_LOCK_SAVE
rtn = do_old_reset(SCarg);
- IRQ_UNLOCK_RESTORE
return rtn;
}
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)
-
static inline int do_reset(Scsi_Cmnd *SCarg) {
unsigned int i, j, time, k, c, limit = 0;
int arg_done = FALSE;
HD(j)->in_reset = TRUE;
SPIN_UNLOCK
- IRQ_UNLOCK
time = jiffies;
while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
- IRQ_LOCK
SPIN_LOCK
printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
continue;
SCpnt->scsi_done(SCpnt);
- IRQ_LOCK
}
HD(j)->in_reset = FALSE;
return do_reset(SCarg);
}
-#endif /* new_eh_code */
-
int eata2x_biosparam(Disk *disk, kdev_t dev, int *dkinfo) {
int size = disk->capacity;
for (n = 0; n < n_ready; n++) {
k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
- if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
+ if (do_dma(sh[j]->io_port, (unsigned long) cpp, SEND_CP_DMA)) {
printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
" busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
if (spp->eoc == FALSE)
printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n",
BN(j), irq, reg, HD(j)->iocount);
- if (spp->cpp == NULL)
- printk("%s: ihdlr, spp->cpp == NULL, irq %d, reg 0x%x, count %d.\n",
- BN(j), irq, reg, HD(j)->iocount);
- if (spp->eoc == FALSE || spp->cpp == NULL) return;
+ if (spp->cpp_index < 0 || spp->cpp_index >= sh[j]->can_queue)
+ printk("%s: ihdlr, bad spp->cpp_index %d, irq %d, reg 0x%x, count %d.\n",
+ BN(j), spp->cpp_index, irq, reg, HD(j)->iocount);
+ if (spp->eoc == FALSE || spp->cpp_index < 0
+ || spp->cpp_index >= sh[j]->can_queue) return;
- cpp = spp->cpp;
+ /* Find the mailbox to be serviced on this board */
+ i = spp->cpp_index;
+
+ cpp = &(HD(j)->cp[i]);
#if defined(DEBUG_GENERATE_ABORTS)
if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;
#endif
- /* Find the mailbox to be serviced on this board */
- i = cpp - HD(j)->cp;
-
- if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
- || i >= sh[j]->can_queue)
- panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
- cpp, HD(j)->cp);
-
if (HD(j)->cp_stat[i] == IGNORE) {
HD(j)->cp_stat[i] = FREE;
return;
static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
unsigned int j;
- IRQ_FLAGS
SPIN_FLAGS
/* Check if the interrupt must be processed by this handler */
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
SPIN_LOCK_SAVE
- IRQ_LOCK_SAVE
ihdlr(irq, j);
- IRQ_UNLOCK_RESTORE
SPIN_UNLOCK_RESTORE
}
int eata2x_release(struct Scsi_Host *shpnt) {
unsigned int i, j;
- IRQ_FLAGS
-
- IRQ_LOCK_SAVE
for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
release_region(sh[j]->io_port, sh[j]->n_io_port);
scsi_unregister(sh[j]);
- IRQ_UNLOCK_RESTORE
return FALSE;
}
Scsi_Host_Template driver_template = EATA;
#include "scsi_module.c"
+
+#else
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18)
+void eata2x_setup(char *str, int *ints) {
+ internal_setup(str, ints);
+}
+#else
+__setup("eata=", option_setup);
#endif
+
+#endif /* end MODULE */
int eata2x_old_reset(Scsi_Cmnd *, unsigned int);
int eata2x_biosparam(Disk *, kdev_t, int *);
-#define EATA_VERSION "4.33.00"
+#define EATA_VERSION "5.11.00"
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)
-
#define EATA { \
name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \
detect: eata2x_detect, \
use_new_eh_code: 1 /* Enable new error code */ \
}
-#else /* Use old scsi code */
-
-#define EATA { \
- name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \
- detect: eata2x_detect, \
- release: eata2x_release, \
- queuecommand: eata2x_queuecommand, \
- abort: eata2x_old_abort, \
- reset: eata2x_old_reset, \
- bios_param: eata2x_biosparam, \
- this_id: 7, \
- unchecked_isa_dma: 1, \
- use_clustering: ENABLE_CLUSTERING \
- }
-
-#endif
-
#endif
scb->scsi_cmd->result = DID_OK << 16;
if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
- INQUIRYDATA inq;
+ IPS_INQUIRYDATA inq;
- memset(&inq, 0, sizeof(INQUIRYDATA));
+ memset(&inq, 0, sizeof(IPS_INQUIRYDATA));
inq.DeviceType = TYPE_PROCESSOR;
inq.DeviceTypeQualifier = 0;
/****************************************************************************/
static int
ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
- INQUIRYDATA inq;
+ IPS_INQUIRYDATA inq;
DBG("ips_inquiry");
- memset(&inq, 0, sizeof(INQUIRYDATA));
+ memset(&inq, 0, sizeof(IPS_INQUIRYDATA));
inq.DeviceType = TYPE_DISK;
inq.DeviceTypeQualifier = 0;
u8 ProductRevisionLevel[4];
u8 VendorSpecific[20];
u8 Reserved3[40];
-} INQUIRYDATA, *PINQUIRYDATA;
+} IPS_INQUIRYDATA, *IPS_PINQUIRYDATA;
/*
* Read Capacity Data Format
typedef struct {
volatile unsigned char SASR;
char pad;
+#ifdef CONFIG_SGI
+ char pad2,pad3;
+#endif
volatile unsigned char SCMD;
} wd33c93_regs;
{
#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
unsigned char conf;
- static char irq_bits[] = {
+ static signed char irq_bits[] = {
-1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
};
restore_flags(flags);
}
+
+/*
+ * This fails on the Cyrix MediaGX. If you don't have the DMA enabled
+ * before the first sample arrives it locks up. However even if you
+ * do enable the DMA in time you just get DMA timeouts and missing
+ * interrupts and stuff, so for now I've not bothered fixing this either.
+ */
+
static void sb16_audio_start_input(int dev, unsigned long buf, int count, int intrflag)
{
unsigned long flags, cnt;
return -ENODEV;
#ifdef CONFIG_MIDI
config_mpu.io_base = mpu_io;
- if (mpu_io && probe_sbmpu(&config_mpu))
+ if (probe_sbmpu(&config_mpu))
sbmpu = 1;
if (sbmpu)
attach_sbmpu(&config_mpu);
last_devc = 0;
if (hw_config->io_base <= 0)
+ {
+ /* The real vibra16 is fine about this, but we have to go
+ wipe up after Cyrix again */
+
+ if(devc->model == MDL_SB16 && devc->minor >= 12)
+ {
+ unsigned char bits = sb_getmixer(devc, 0x84) & ~0x06;
+ sb_setmixer(devc, 0x84, bits | 0x02); /* Disable MPU */
+ }
return 0;
+ }
#if defined(CONFIG_SOUND_MPU401)
if (devc->model == MDL_ESS)
* Parse NFS server and directory information passed on the kernel
* command line.
*/
-void __init nfs_root_setup(char *line, int *ints)
+void __init nfs_root_setup(char *line)
{
ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255);
if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
root_nfs_parse_addr(nfs_root_name);
}
+__setup("nfsroot=", nfs_root_setup);
/***************************************************************************
struct buffer_head *bh;
struct riscix_record *rr;
unsigned int riscix_minor;
+
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
printk(" [RISCiX]");
struct linux_part *linuxp;
unsigned int linux_minor, mask = (1 << hd->minor_shift) - 1;
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
+
printk(" [Linux]");
add_gd_partition(hd, linux_minor = minor++, first_sect, nr_sects);
char *name = "CUMANA/ADFS";
int first = 1;
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
+
/*
* Try Cumana style partitions - sector 3 contains ADFS boot block with pointer
* to next 'drive'.
struct buffer_head *bh;
struct disc_record *dr;
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
+
if (!(bh = bread(dev, 3, 1024)))
return -1;
unsigned int offset = block & 1 ? 512 : 0;
int result = 0;
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
+
bh = bread(dev, block >> 1, 1024);
if (bh != NULL) {
unsigned int i, mask = (1 << hd->minor_shift) - 1;
struct ics_part { unsigned long start; signed long size; } *p;
+ if(get_ptable_blocksize(dev)!=1024)
+ return 0;
+
/*
* Try ICS style partitions - sector 0 contains partition info.
*/
unsigned long first_sector, first_size, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = get_hardsect_size(dev) / 512;
+ int loopct = 0; /* number of links followed
+ without finding a data partition */
int i;
first_sector = hd->part[MINOR(dev)].start_sect;
this_sector = first_sector;
while (1) {
+ if (++loopct > 100)
+ return;
if ((current_minor & mask) == 0)
return;
if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
first_sector + first_size))
continue;
- add_gd_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+ add_gd_partition(hd, current_minor,
+ this_sector+START_SECT(p)*sector_size,
+ NR_SECTS(p)*sector_size);
current_minor++;
+ loopct = 0;
if ((current_minor & mask) == 0)
goto done;
}
/*
* Look for various forms of IDE disk geometry translation
*/
- extern int ide_xlate_1024(kdev_t, int, const char *);
+ extern int ide_xlate_1024(kdev_t, int, int, const char *);
unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
+ int heads = 0;
+ /*
+ * The i386 partition handling programs very often
+ * make partitions end on cylinder boundaries.
+ * There is no need to do so, and Linux fdisk doesnt always
+ * do this, and Windows NT on Alpha doesnt do this either,
+ * but still, this helps to guess #heads.
+ */
+ for (i = 0; i < 4; i++) {
+ struct partition *q = &p[i];
+ if (NR_SECTS(q)) {
+ if ((q->sector & 63) == 1 &&
+ (q->end_sector & 63) == 63)
+ heads = q->end_head + 1;
+ break;
+ }
+ }
if (SYS_IND(p) == EZD_PARTITION) {
/*
- * The remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
+ * Accesses to sector 0 must go to sector 1 instead.
*/
- if (ide_xlate_1024(dev, -1, " [EZD]")) {
+ if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
data += 512;
goto check_table;
}
/*
* Everything on the disk is offset by 63 sectors,
- * including a "new" MBR with its own partition table,
- * and the remainder of the disk must be accessed using
- * a translated geometry that reduces the number of
- * apparent cylinders to less than 1024 if possible.
- *
- * ide_xlate_1024() will take care of the necessary
- * adjustments to fool fdisk/LILO and partition check.
+ * including a "new" MBR with its own partition table.
*/
- if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
+ if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
bforget(bh);
goto read_mbr; /* start over with new MBR */
}
} else if (sig <= 0x1ae &&
- *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
- (1 & *(unsigned char *)(data + sig + 2))) {
+ data[sig] == 0xAA && data[sig+1] == 0x55 &&
+ (data[sig+2] & 1)) {
/* DM6 signature in MBR, courtesy of OnTrack */
- (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
- } else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
+ (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
+ } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
+ SYS_IND(p) == DM6_AUX3PARTITION) {
/*
* DM6 on other than the first (boot) drive
*/
- (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
+ (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
} else {
- /*
- * Examine the partition table for common translations.
- * This is useful for drives in situations where the
- * translated geometry is unavailable from the BIOS.
- */
- for (i = 0; i < 4; i++) {
- struct partition *q = &p[i];
- if (NR_SECTS(q)
- && (q->sector & 63) == 1
- && (q->end_sector & 63) == 63) {
- unsigned int heads = q->end_head + 1;
- if (heads == 32 || heads == 64 ||
- heads == 128 || heads == 240 ||
- heads == 255) {
- (void) ide_xlate_1024(dev, heads, " [PTBL]");
- break;
- }
- }
- }
+ (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
}
}
#endif /* CONFIG_BLK_DEV_IDE */
fd = 0;
len = dentry->d_name.len;
name = dentry->d_name.name;
+ if (len > 1 && *name == '0') goto out;
while (len-- > 0) {
c = *name - '0';
name++;
#define E820MAX 32 /* number of entries in E820MAP */
#define E820NR 0x1e8 /* # entries in E820MAP */
+#define E820_RAM 1
+#define E820_RESERVED 2
+#define E820_ACPI 3
+
#define HIGH_MEMORY (1024*1024)
#ifndef __ASSEMBLY__
/* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $
* linux/include/linux/cyclades.h
*
- * This file is maintained by Ivan Passos <ivan@cyclades.com>,
- * Marcio Saito <marcio@cyclades.com> and
- * Randolph Bentson <bentson@grieg.seaslug.org>.
+ * This file was initially written by
+ * Randolph Bentson <bentson@grieg.seaslug.org> and is maintained by
+ * Ivan Passos <ivan@cyclades.com>.
*
* This file contains the general definitions for the cyclades.c driver
*$Log: cyclades.h,v $
#define C_IN_RXOFL 0x00010000 /* RX buffer overflow */
#define C_IN_IOCTLW 0x00020000 /* I/O control w/ wait */
#define C_IN_MRTS 0x00040000 /* modem RTS drop */
+#define C_IN_ICHAR 0x00080000
/* flow control */
#define C_CM_TXLOWWM 0x61 /* Tx buffer low water mark */
#define C_CM_RXHIWM 0x62 /* Rx buffer high water mark */
#define C_CM_RXNNDT 0x63 /* rx no new data timeout */
+#define C_CM_TXFEMPTY 0x64
+#define C_CM_ICHAR 0x65
#define C_CM_MDCD 0x70 /* modem DCD change */
#define C_CM_MDSR 0x71 /* modem DSR change */
#define C_CM_MRI 0x72 /* modem RI change */
uclong hw_overflow; /* hw overflow counter */
uclong sw_overflow; /* sw overflow counter */
uclong comm_error; /* frame/parity error counter */
+ uclong ichar;
+ uclong filler[7];
};
#else
uclong filler;
#endif
-
};
struct cyclades_chip {
#define cy_readw(port) readw(port)
#define cy_readl(port) readl(port)
+/*
+ * Statistics counters
+ */
+struct cyclades_icount {
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
+};
+
/*
* This is our internal structure for each serial port's state.
*
unsigned long rflush_count;
struct termios normal_termios;
struct termios callout_termios;
- struct cyclades_monitor mon;
- struct cyclades_idle_stats idle_stats;
+ struct cyclades_monitor mon;
+ struct cyclades_idle_stats idle_stats;
+ struct cyclades_icount icount;
struct tq_struct tqueue;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
wait_queue_head_t shutdown_wait;
+ wait_queue_head_t delta_msr_wait;
};
/*
#define Cy_EVENT_BREAK 3
#define Cy_EVENT_OPEN_WAKEUP 4
#define Cy_EVENT_SHUTDOWN_WAKEUP 5
+#define Cy_EVENT_DELTA_WAKEUP 6
#define CLOSING_WAIT_DELAY 30*HZ
#define CY_CLOSING_WAIT_NONE 65535
#define CyRTPR (0x21*2)
#define CyMSVR1 (0x6C*2)
#define CyMSVR2 (0x6D*2)
+#define CyANY_DELTA (0xF0)
#define CyDSR (0x80)
#define CyCTS (0x40)
#define CyRI (0x20)
/*********************************************************************
*
* Filename: irda.h
- * Version:
- * Description:
+ * Version: 1.0
+ * Description: Exported IrDA sockets interface
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Mar 8 14:06:12 1999
- * Modified at: Mon Mar 22 14:14:54 1999
+ * Modified at: Mon Sep 27 12:11:49 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
};
struct irda_device_info {
- unsigned int saddr; /* Address of remote device */
- unsigned int daddr; /* Link where it was discovered */
+ unsigned int saddr; /* Address of remote device */
+ unsigned int daddr; /* Link where it was discovered */
char info[22]; /* Description */
unsigned char charset; /* Charset used for description */
unsigned char hints[2]; /* Hint bits */
struct irda_device_list {
unsigned int len;
- struct irda_device_info dev[0];
+ struct irda_device_info dev[1];
};
struct irda_ias_set {
#define VID_HARDWARE_TYPHOON 19
#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */
#define VID_HARDWARE_CADET 21 /* Cadet radio */
-#define VID_HARDWARE_CPIA 22
+#define VID_HARDWARE_TRUST 22 /* Trust FM Radio */
#define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */
+#define VID_HARDWARE_CPIA 24
/*
* Initialiser list
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 23:24:22 1999
- * Modified at: Fri Aug 13 07:31:35 1999
+ * Modified at: Tue Aug 31 10:22:02 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
struct termios callout_termios;
wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
struct timer_list watchdog_timer;
struct tq_struct tqueue;
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+
long pgrp; /* pgrp of opening process */
int open_count;
int blocked_open; /* # of blocked opens */
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Jun 9 15:55:18 1999
- * Modified at: Mon Jul 5 12:56:56 1999
+ * Modified at: Thu Sep 2 10:29:30 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
IRCOMM_TTY_DISCOVERY_INDICATION,
IRCOMM_TTY_CONNECT_CONFIRM,
IRCOMM_TTY_CONNECT_INDICATION,
+ IRCOMM_TTY_DISCONNECT_REQUEST,
+ IRCOMM_TTY_DISCONNECT_INDICATION,
IRCOMM_TTY_WD_TIMER_EXPIRED,
IRCOMM_TTY_GOT_PARAMETERS,
IRCOMM_TTY_GOT_LSAPSEL,
extern char *ircomm_state[];
extern char *ircomm_event[];
+extern char *ircomm_tty_state[];
int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
struct sk_buff *skb, struct ircomm_tty_info *info);
__u32 max_sdu_size,
__u8 max_header_size,
struct sk_buff *skb);
+void ircomm_tty_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason,
+ struct sk_buff *skb);
void ircomm_tty_connect_indication(void *instance, void *sap,
struct qos_info *qos,
__u32 max_sdu_size,
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:13:12 1997
- * Modified at: Thu Jul 8 12:53:35 1999
+ * Modified at: Mon Sep 27 11:13:18 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
/*
- * Magic numbers used by Linux/IR. Random numbers which must be unique to
+ * Magic numbers used by Linux-IrDA. Random numbers which must be unique to
* give the best protection
*/
typedef __u32 magic_t;
struct qos_info *qos, __u32 max_sdu_size,
__u8 max_header_size, struct sk_buff *skb);
void (*connect_indication)(void *instance, void *sap,
- struct qos_info *qos, __u32 max_sdu_size,
+ struct qos_info *qos, __u32 max_sdu_size,
__u8 max_header_size, struct sk_buff *skb);
void (*disconnect_indication)(void *instance, void *sap,
LM_REASON reason, struct sk_buff *);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Apr 14 12:41:42 1998
- * Modified at: Tue Aug 24 13:58:23 1999
+ * Modified at: Mon Sep 20 11:21:31 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
#include <net/irda/irqueue.h>
#include <net/irda/irlap_frame.h>
+/* Some private IOCTL's */
+#define SIOCSDONGLE (SIOCDEVPRIVATE + 0)
+#define SIOCSBANDWIDTH (SIOCDEVPRIVATE + 1)
+#define SIOCSMEDIABUSY (SIOCDEVPRIVATE + 2)
+
/* Some non-standard interface flags (should not conflict with any in if.h) */
#define IFF_SIR 0x0001 /* Supports SIR speeds */
#define IFF_MIR 0x0002 /* Supports MIR speeds */
void irda_device_close(struct irda_device *);
/* Interface to be uses by IrLAP */
-inline void irda_device_set_media_busy(struct irda_device *, int status);
-inline int irda_device_is_media_busy(struct irda_device *);
-inline int irda_device_is_receiving(struct irda_device *);
-inline void irda_device_change_speed(struct irda_device *, int);
+void irda_device_set_media_busy(struct net_device *dev, int status);
+int irda_device_is_media_busy(struct net_device *dev);
+int irda_device_is_receiving(struct net_device *dev);
+struct qos_info *irda_device_get_qos(struct net_device *dev);
-inline struct qos_info *irda_device_get_qos(struct irda_device *self);
+/* Interface for internal use */
+void irda_device_change_speed(struct irda_device *, int);
int irda_device_txqueue_empty(struct irda_device *self);
void irda_device_init_dongle(struct irda_device *self, int type);
void irda_device_unregister_dongle(struct dongle *dongle);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Thu Jul 8 21:22:50 1999
+ * Modified at: Mon Sep 20 10:14:47 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
QUEUE q; /* Must be first */
magic_t magic;
- struct irda_device *irdev;
- struct net_device *netdev;
+ struct net_device *netdev;
/* Connection state */
volatile IRLAP_STATE state; /* Current state */
int irlap_init(void);
void irlap_cleanup(void);
-struct irlap_cb *irlap_open(struct irda_device *dev);
+struct irlap_cb *irlap_open(struct net_device *dev);
void irlap_close(struct irlap_cb *self);
void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
+++ /dev/null
-/*********************************************************************
- *
- * Filename: irlpt_cli.h
- * Version: 0.1
- * Description:
- * Status: Experimental.
- * Author: Dag Brattli <dagb@cs.uit.no>
- * Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Wed Apr 21 16:46:26 1999
- * Modified by: Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
- * Copyright (c) 1998, Dag Brattli,
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software. This
- * material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_CLIENT_H
-#define IRLPT_CLIENT_H
-
-/* Debug function */
-
-/* int client_init( struct net_device *dev); */
-
-/*
- * if it's static, it doesn't go in here.
- */
-
-void irlpt_client_get_value_confirm(int result, __u16 obj_id,
- struct ias_value *value,
- void *priv);
-void irlpt_client_connect_indication( void *instance,
- void *sap,
- struct qos_info *qos,
- int max_seg_size,
- struct sk_buff *skb);
-void irlpt_client_connect_request( struct irlpt_cb *self);
-
-extern hashbin_t *irlpt_clients;
-
-#endif
+++ /dev/null
-/*********************************************************************
- *
- * Filename: irlpt_cli_fsm.h
- * Version: 0.1
- * Sources: irlan_event.h
- *
- * Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>,
- * All Rights Reserved.
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_EVENT_H
-#define IRLPT_EVENT_H
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-
-extern void irlpt_client_do_event( struct irlpt_cb *self,
- IRLPT_EVENT event,
- struct sk_buff *skb,
- struct irlpt_info *info);
-extern void irlpt_client_next_state( struct irlpt_cb *self,
- IRLPT_CLIENT_STATE state);
-
-#endif
-
+++ /dev/null
-/*********************************************************************
- *
- * Filename: irlpt_common.h
- * Version:
- * Description:
- * Status: Experimental.
- * Author: Thomas Davis, <ratbert@radiks.net>
- * Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Sun Mar 8 23:44:19 1998
- * Modified by: Dag Brattli <dagb@cs.uit.no>
- * Sources: irlan.c
- *
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- * Dag Brattli, <dagb@cs.uit.no>
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_COMMON_H
-#define IRLPT_COMMON_H
-
-#include <net/irda/qos.h>
-#include <net/irda/irmod.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/miscdevice.h>
-
-#include <linux/poll.h>
-
-extern char *irlpt_service_type[];
-extern char *irlpt_port_type[];
-extern char *irlpt_connected[];
-extern char *irlpt_reasons[];
-extern char *irlpt_client_fsm_state[];
-extern char *irlpt_server_fsm_state[];
-extern char *irlpt_fsm_event[];
-
-extern wait_queue_head_t lpt_wait;
-
-extern struct irlpt_cb *irlpt_find_handle(unsigned int minor);
-extern void irlpt_flow_control(struct sk_buff *skb);
-
-extern ssize_t irlpt_read( struct file *file, char *buffer,
- size_t count, loff_t *noidea);
-extern ssize_t irlpt_write(struct file *file, const char *buffer,
- size_t count, loff_t *noidea);
-extern loff_t irlpt_seek(struct file *, loff_t, int);
-extern int irlpt_open(struct inode * inode, struct file *file);
-extern int irlpt_close(struct inode *inode, struct file *file);
-extern u_int irlpt_poll(struct file *file, poll_table *wait);
-
-/* FSM definitions */
-
-typedef enum {
- IRLPT_CLIENT_IDLE,
- IRLPT_CLIENT_QUERY,
- IRLPT_CLIENT_READY,
- IRLPT_CLIENT_WAITI,
- IRLPT_CLIENT_CONN,
-} IRLPT_CLIENT_STATE;
-
-typedef enum {
- IRLPT_SERVER_IDLE,
- IRLPT_SERVER_CONN,
-} IRLPT_SERVER_STATE;
-
-/* IrLPT Events */
-
-typedef enum {
- QUERY_REMOTE_IAS,
- IAS_PROVIDER_AVAIL,
- IAS_PROVIDER_NOT_AVAIL,
- LAP_DISCONNECT,
- LMP_CONNECT,
- LMP_DISCONNECT,
- LMP_CONNECT_INDICATION,
- LMP_DISCONNECT_INDICATION,
- IRLPT_DISCOVERY_INDICATION,
- IRLPT_CONNECT_REQUEST,
- IRLPT_DISCONNECT_REQUEST,
- CLIENT_DATA_INDICATION,
-} IRLPT_EVENT;
-
-struct irlpt_info {
- struct lsap_cb *lsap;
- __u8 dlsap_sel;
- __u32 daddr;
- __u32 saddr;
-};
-
-/* Command packet types */
-
-#define IRLPT_MAX_PACKET 1024
-#define IRLPT_MAX_HEADER LMP_MAX_HEADER
-#define IRLPT_MAX_DEVICES 3
-#define IRLPT_MAGIC 0x0755
-
-typedef enum {
- IRLPT_DISCONNECTED,
- IRLPT_WAITING,
- IRLPT_CONNECTED,
- IRLPT_FLUSHED,
-} IRLPT_SERVER_STATUS;
-
-#define IRLPT_LSAP 0x09
-
-#define PI_SERVICE_TYPE 0x00
-
-#define IRLPT_UNKNOWN 0x00 /* not defined yet. */
-#define IRLPT_THREE_WIRE_RAW 0x01 /* bit 0 */
-#define IRLPT_THREE_WIRE 0x02 /* bit 1 */
-#define IRLPT_NINE_WIRE 0x04 /* bit 2 */
-#define IRLPT_CENTRONICS 0x08 /* bit 3 */
-#define IRLPT_SERVER_MODE 0xFF /* our own flag */
-
-#define PI_PORT_TYPE 0x01
-
-#define IRLPT_SERIAL 0x01 /* bit 0 */
-#define IRLPT_PARALLEL 0x02 /* bit 1 */
-
-#define PI_PORT_NAME 0x02
-
-#define PI_CRITICAL 0x80
-
-struct irlpt_cb {
- QUEUE queue; /* must be first. */
-
- int magic; /* magic used to detect corruption of
- the struct */
- __u32 daddr; /* address of remote printer */
- __u32 saddr; /* my local address. */
-
- struct timer_list retry_timer;
-
- int volatile state; /* Current state of IrCOMM layer */
- int open_retries;
- int in_use; /* flag to prevent re-use */
- char ifname[16]; /* name of the allocated instance,
- and registered device. */
- struct lsap_cb *lsap; /* lmp handle */
-
- __u8 dlsap_sel; /* remote LSAP selector address */
- __u8 slsap_sel; /* local LSAP selectoraddress */
- __u8 servicetype; /* Type of remote service, ie THREE_WIRE_RAW */
- __u8 porttype; /* type of remote port. */
-
- struct miscdevice ir_dev; /* used to register the misc device. */
-
- int count; /* open count */
- int max_data_size; /* max frame size we can send */
- int max_header_size; /* how much header space is needed */
- int pkt_count; /* how many packets are queued up */
-
- wait_queue_head_t read_wait; /* wait queues */
- wait_queue_head_t write_wait;
- wait_queue_head_t ex_wait;
-
- /* this is used to remove the printer when it's gone */
- struct timer_list lpt_timer;
- void (*timeout) (unsigned long data);
-
- void (*do_event) (struct irlpt_cb *self, IRLPT_EVENT event,
- struct sk_buff *skb,
- struct irlpt_info *info);
-
- /* this is used by the server side of the system */
-
- IRLPT_SERVER_STATE connected;
-
- int eof;
- int service_LSAP;
-
- struct sk_buff_head rx_queue; /* read buffer queue */
-};
-
-/* Debug function */
-void irlpt_dump_buffer(struct sk_buff *);
-
-#endif
+++ /dev/null
-/*********************************************************************
- *
- * Filename: irlpt_server.h
- * Version: 0.1
- * Description:
- * Status: Experimental.
- * Author: Dag Brattli <dagb@cs.uit.no>
- * Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Tue Sep 22 11:41:42 1998
- * Modified by: Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
- * Copyright (c) 1998, Dag Brattli,
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software. This
- * material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_SERVER_H
-#define IRLPT_SERVER_H
-
-#include "qos.h"
-#include "irmod.h"
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/miscdevice.h>
-
-/* int server_init( struct net_device *dev); */
-
-extern struct irlpt_cb *irlpt_server;
-
-#endif
+++ /dev/null
-/*********************************************************************
- *
- * Filename: server_server_fsm.h
- * Version: 0.1
- * Sources: irlan_event.h
- *
- * Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>,
- * All Rights Reserved.
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLPT_EVENT_H
-#define IRLPT_EVENT_H
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-
-void irlpt_server_do_event( struct irlpt_cb *self,
- IRLPT_EVENT event,
- struct sk_buff *skb,
- struct irlpt_info *info);
-void irlpt_server_next_state( struct irlpt_cb *self,
- IRLPT_SERVER_STATE state);
-
-#endif
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Tue Aug 24 09:27:05 1999
+ * Modified at: Mon Sep 27 11:38:01 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
return irlmp_get_daddr(self->lsap);
}
+static __inline __u32 irttp_get_max_seq_size(struct tsap_cb *self)
+{
+ return self->max_seg_size;
+}
+
extern struct irttp_cb *irttp;
#endif /* IRTTP_H */
+++ /dev/null
-/*********************************************************************
- *
- * Filename: irvtd.h
- * Version: 0.1
- * Sources: irlpt.h
- *
- * Copyright (c) 1998, Takahide Higuchi <thiguchi@pluto.dti.ne.jp>,
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * I, Takahide Higuchi, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRVTD_H
-#define IRVTD_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/tqueue.h>
-#include <linux/serial.h>
-
-#include <net/irda/irmod.h>
-#include <net/irda/qos.h>
-#include <net/irda/ircomm_common.h>
-
-
-#define IRVTD_MAGIC 0xff545943 /* random */
-#define COMM_MAX_TTY 1
-#define IRVTD_RX_QUEUE_HIGH 10
-#define IRVTD_RX_QUEUE_LOW 2
-
-#define IRCOMM_MAJOR 60; /* Zero means automatic allocation
- 60,61,62,and 63 is reserved for experiment */
-#define IRVTD_MINOR 64
-
-
-
-struct irvtd_cb {
-
- int magic; /* magic used to detect corruption of the struct */
-
- /* if daddr is NULL, remote device have not been discovered yet */
-
- int tx_disable;
- int rx_disable;
- struct sk_buff *txbuff;
- struct sk_buff_head rxbuff;
- struct ircomm_cb *comm; /* ircomm instance */
-
- __u32 tx_max_sdu_size;
- __u32 max_header_size;
- /*
- * These members are used for compatibility with usual serial device.
- * See linux/serial.h
- */
-
- int flags;
- struct tty_struct *tty;
-
- int line;
- int count; /* open count */
- int blocked_open;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
- wait_queue_head_t delta_msr_wait;
- wait_queue_head_t tx_wait;
-
- struct timer_list tx_timer;
- struct timer_list rx_timer;
-
- long pgrp;
- long session;
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short close_delay;
-
- int custom_divisor;
- int mcr;
- int msr;
- int cts_stoptx;
- int ttp_stoptx;
- int ttp_stoprx;
- int disconnect_pend;
- struct serial_icounter_struct icount;
- int read_status_mask;
- int ignore_status_mask;
-};
-
-
-#endif
/*
* $Log: toshoboe.h,v $
+ * Revision 1.4 1999/06/29 13:46:42 root
+ * ls
+ *
+ * Revision 1.3 1999/06/29 12:31:03 root
+ * *** empty log message ***
+ *
* Revision 1.2 1999/05/09 01:43:08 root
* *** empty log message ***
*
struct OboeTaskFile *taskfile; /*The taskfile */
void *xmit_bufs[TX_SLOTS]; /*The buffers */
void *recv_bufs[RX_SLOTS];
+ int open;
+ int stopped; /*Stopped by some or other APM stuff*/
};
# IrDA protocol configuration
#
-if [ "$CONFIG_NET" != "n" ] ; then
+if [ "$CONFIG_NET" != "n" ]; then
- mainmenu_option next_comment
- comment 'IrDA (infrared) support'
- dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
+ mainmenu_option next_comment
+ comment 'IrDA (infrared) support'
+ dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
- if [ "$CONFIG_IRDA" != "n" ] ; then
- comment 'IrDA protocols'
- source net/irda/irlan/Config.in
- source net/irda/ircomm/Config.in
+ if [ "$CONFIG_IRDA" != "n" ]; then
+ comment 'IrDA protocols'
+ source net/irda/irlan/Config.in
+ source net/irda/ircomm/Config.in
- bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
- if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
- comment ' IrDA options'
- bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
- bool ' Fast RRs' CONFIG_IRDA_FAST_RR
- bool ' Debug information' CONFIG_IRDA_DEBUG
- fi
- fi
+ bool ' IrDA protocol options' CONFIG_IRDA_OPTIONS
+ if [ "$CONFIG_IRDA_OPTIONS" != "n" ]; then
+ comment ' IrDA options'
+ bool ' Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+ bool ' Fast RRs' CONFIG_IRDA_FAST_RR
+ bool ' Debug information' CONFIG_IRDA_DEBUG
+ fi
+ fi
- if [ "$CONFIG_IRDA" != "n" ] ; then
- source net/irda/compressors/Config.in
- source drivers/net/irda/Config.in
- fi
- endmenu
+ if [ "$CONFIG_IRDA" != "n" ]; then
+ source net/irda/compressors/Config.in
+ source drivers/net/irda/Config.in
+ fi
+ endmenu
fi
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun May 31 10:12:43 1998
- * Modified at: Mon Aug 23 09:44:37 1999
+ * Modified at: Mon Sep 27 20:11:52 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
*
extern int irlap_driver_rcv(struct sk_buff *, struct net_device *,
struct packet_type *);
+static int irda_create(struct socket *sock, int protocol);
+
static struct proto_ops irda_stream_ops;
static struct proto_ops irda_dgram_ops;
static hashbin_t *cachelog = NULL;
struct sock *sk;
int err;
- DEBUG(1, __FUNCTION__ "()\n");
-
self = (struct irda_sock *) instance;
ASSERT(self != NULL, return -1;);
struct irda_sock *self;
struct sock *sk;
- DEBUG(1, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
self = (struct irda_sock *) instance;
struct irda_sock *self;
struct sock *sk;
- DEBUG(1, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
self = (struct irda_sock *) instance;
/* Find out what the largest chunk of data that we can transmit is */
if (max_sdu_size == SAR_DISABLE)
- self->max_data_size = qos->data_size.value - max_header_size;
+ self->max_data_size = irttp_get_max_seq_size(self->tsap);
else
self->max_data_size = max_sdu_size;
struct irda_sock *self;
struct sock *sk;
- DEBUG(1, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
self = (struct irda_sock *) instance;
/* Find out what the largest chunk of data that we can transmit is */
if (max_sdu_size == SAR_DISABLE)
- self->max_data_size = qos->data_size.value - max_header_size;
+ self->max_data_size = irttp_get_max_seq_size(self->tsap);
else
self->max_data_size = max_sdu_size;
{
struct sock *sk = sock->sk;
- DEBUG(1, __FUNCTION__ "()\n");
-
if (sk->type == SOCK_STREAM && sk->state != TCP_LISTEN) {
sk->max_ack_backlog = backlog;
sk->state = TCP_LISTEN;
struct sk_buff *skb;
int err;
+ DEBUG(0, __FUNCTION__ "()\n");
+
self = sk->protinfo.irda;
ASSERT(self != NULL, return -1;);
case SIOCSIFNETMASK:
case SIOCGIFMETRIC:
case SIOCSIFMETRIC:
- return -EINVAL;
-
+ return -EINVAL;
default:
DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
return dev_ioctl(cmd, (void *) arg);
DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
return 0;
case IRTTP_MAX_SDU_SIZE:
- DEBUG(0, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
+ DEBUG(2, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
self->max_sdu_size_rx = opt;
break;
default:
{
struct sock *sk = sock->sk;
struct irda_sock *self;
- struct irda_device_list *list;
- __u8 optbuf[sizeof(struct irda_device_list) +
- sizeof(struct irda_device_info)*10];
+ struct irda_device_list list;
+ struct irda_device_info *info;
discovery_t *discovery;
int val = 0;
int len = 0;
- int i = 0;
+ int offset, total;
self = sk->protinfo.irda;
if (!cachelog)
return -EAGAIN;
- list = (struct irda_device_list *) optbuf;
+ info = &list.dev[0];
+
+ /* Offset to first device entry */
+ offset = sizeof(struct irda_device_list) -
+ sizeof(struct irda_device_info);
+
+ total = offset; /* Initialized to size of the device list */
+ list.len = 0; /* Initialize lenght of list */
+
/*
* Now, check all discovered devices (if any), and notify
* client only about the services that the client is
while (discovery != NULL) {
/* Mask out the ones we don't want */
if (discovery->hints.word & self->mask) {
+
+ /* Check if room for this device entry */
+ if (len - total >= sizeof(struct irda_device_info))
+ break;
+
/* Copy discovery information */
- list->dev[i].saddr = discovery->saddr;
- list->dev[i].daddr = discovery->daddr;
- list->dev[i].charset = discovery->charset;
- list->dev[i].hints[0] = discovery->hints.byte[0];
- list->dev[i].hints[1] = discovery->hints.byte[1];
- strncpy(list->dev[i].info, discovery->nickname,
+ info->saddr = discovery->saddr;
+ info->daddr = discovery->daddr;
+ info->charset = discovery->charset;
+ info->hints[0] = discovery->hints.byte[0];
+ info->hints[1] = discovery->hints.byte[1];
+ strncpy(info->info, discovery->nickname,
NICKNAME_MAX_LEN);
- if (++i >= 10)
- break;
+
+ if (copy_to_user(optval+offset, &info,
+ sizeof(struct irda_device_info)))
+ return -EFAULT;
+ list.len++;
+ total += sizeof(struct irda_device_info);
}
discovery = (discovery_t *) hashbin_get_next(cachelog);
}
cachelog = NULL;
- list->len = i;
- len = sizeof(struct irda_device_list) +
- sizeof(struct irda_device_info) * i;
-
- DEBUG(1, __FUNCTION__ "(), len=%d, i=%d\n", len, i);
-
- if (put_user(len, optlen))
+ /* Write total number of bytes used back to client */
+ if (put_user(total, optlen))
return -EFAULT;
-
- if (copy_to_user(optval, &optbuf, len))
+
+ /* Write total list length back to client */
+ if (copy_to_user(optval, &list,
+ sizeof(struct irda_device_list) -
+ sizeof(struct irda_device_info)))
return -EFAULT;
break;
case IRTTP_MAX_SDU_SIZE:
val = self->max_data_size;
- DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
+ DEBUG(2, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
len = sizeof(int);
if (put_user(len, optlen))
return -EFAULT;
/*
* Function irda_device_event (this, event, ptr)
*
- *
+ * Called when a device is taken up or down
*
*/
static int irda_device_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = (struct net_device *) ptr;
- DEBUG(3, __FUNCTION__ "()\n");
-
/* Reject non IrDA devices */
if (dev->type != ARPHRD_IRDA)
return NOTIFY_DONE;
-bool 'IrLAP compression' CONFIG_IRDA_COMPRESSION
+bool ' IrLAP compression' CONFIG_IRDA_COMPRESSION
-if [ "$CONFIG_IRDA_COMPRESSION" != "n" ] ; then
- comment ' IrDA compressors'
- dep_tristate ' Deflate compression (experimental)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA
-# tristate ' BZIP2 compression' CONFIG_IRDA_BZIP2
-# tristate ' BSD compression' CONFIG_IRDA_BSD
+if [ "$CONFIG_IRDA_COMPRESSION" != "n" ]; then
+ comment ' IrDA compressors'
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' Deflate compression (EXPERIMENTAL)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA
+ fi
+# tristate ' BZIP2 compression' CONFIG_IRDA_BZIP2
+# tristate ' BSD compression' CONFIG_IRDA_BSD
fi
-dep_tristate 'IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA
+dep_tristate ' IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := ircomm_and_tty.o
-O_OBJS := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.c
+O_OBJS := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o
M_OBJS := ircomm.o ircomm-tty.o
MI_OBJS := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o
/*********************************************************************
*
* Filename: ircomm_event.c
- * Version:
- * Description:
+ * Version: 1.0
+ * Description: IrCOMM layer state machine
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 20:33:11 1999
- * Modified at: Wed Aug 25 12:58:27 1999
+ * Modified at: Thu Sep 2 10:09:25 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
ircomm_next_state(self, IRCOMM_CONN);
ret = self->issue.connect_response(self, skb);
break;
-
case IRCOMM_DISCONNECT_REQUEST:
ircomm_next_state(self, IRCOMM_IDLE);
ret = self->issue.disconnect_request(self, skb, info);
break;
-
case IRCOMM_TTP_DISCONNECT_INDICATION:
case IRCOMM_LMP_DISCONNECT_INDICATION:
ircomm_next_state(self, IRCOMM_IDLE);
ircomm_disconnect_indication(self, skb, info);
break;
-
default:
DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
ircomm_event[event]);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Jun 7 10:25:11 1999
- * Modified at: Wed Aug 25 13:48:14 1999
+ * Modified at: Fri Sep 3 09:28:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*/
int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
{
+ unsigned long flags;
struct sk_buff *skb;
int count;
if (self->service_type == IRCOMM_3_WIRE_RAW)
return 0;
- skb = self->ctrl_skb;
-
+ save_flags(flags);
+ cli();
+
+ skb = self->ctrl_skb;
if (!skb) {
skb = dev_alloc_skb(256);
- if (!skb)
- return -1;
+ if (!skb) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
skb_reserve(skb, self->max_header_size);
*/
count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
&ircomm_param_info);
- if (count > 0)
- skb_put(skb, count);
+ if (count < 0) {
+ DEBUG(0, __FUNCTION__ "(), no room for parameter!\n");
+ restore_flags(flags);
+ return -1;
+ }
+ skb_put(skb, count);
+ restore_flags(flags);
if (flush) {
ircomm_control_request(self->ircomm, skb);
/*
* Function ircomm_param_port_type (self, param)
*
- *
- *
+ * The port type parameter tells if the devices are serial or parallel.
+ * Since we only advertise serial service, this parameter should only
+ * be equal to IRCOMM_SERIAL.
*/
static int ircomm_param_port_type(void *instance, param_t *param, int get)
{
- DEBUG(0, __FUNCTION__ "(), not impl.\n");
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+ if (get)
+ param->pv.b = IRCOMM_SERIAL;
+ else {
+ self->session.port_type = param->pv.b;
+ DEBUG(0, __FUNCTION__ "(), port type=%d\n",
+ self->session.port_type);
+ }
return 0;
}
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-
- if (get)
+
+ if (get) {
DEBUG(0, __FUNCTION__ "(), not imp!\n");
- else
+ } else {
DEBUG(0, __FUNCTION__ "(), port-name=%s\n", param->pv.c);
+ strncpy(self->session.port_name, param->pv.c, 32);
+ }
return 0;
}
else
self->session.data_format = param->pv.b;
- DEBUG(1, __FUNCTION__ "(), data format = 0x%02x\n", param->pv.b);
-
return 0;
}
else {
dte = param->pv.b;
- /* Null modem cable emulator */
- self->session.null_modem = TRUE;
-
if (dte & IRCOMM_DELTA_DTR)
self->session.dce |= (IRCOMM_DELTA_DSR|
IRCOMM_DELTA_RI |
/* Take appropriate actions */
ircomm_tty_check_modem_status(self);
- /*
- * Send reply, and remember not to set delta values for the
- * initial parameters
- */
- self->session.dte = (IRCOMM_DTR| IRCOMM_RTS);
- ircomm_param_request(self, IRCOMM_DTE, TRUE);
+ /* Null modem cable emulator */
+ self->session.null_modem = TRUE;
}
- DEBUG(1, __FUNCTION__ "(), dte = 0x%02x\n", param->pv.b);
return 0;
}
/*
* Function ircomm_param_poll (instance, param)
*
- *
+ * Called when the peer device is polling for the line settings
*
*/
static int ircomm_param_poll(void *instance, param_t *param, int get)
{
- DEBUG(0, __FUNCTION__ "(), not impl.\n");
-
- return 0;
-}
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ /* Poll parameters are always of lenght 0 (just a signal) */
+ if (!get) {
+ /* Respond with DTE line settings */
+ ircomm_param_request(self, IRCOMM_DTE, TRUE);
+ }
+ return 0;
+}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 20:48:27 1999
- * Modified at: Tue Aug 17 10:28:26 1999
+ * Modified at: Mon Sep 27 11:17:23 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
return;
}
- info.max_data_size = qos->data_size.value - max_header_size
+ info.max_data_size = irttp_get_max_seq_size(self->tsap)
- IRCOMM_HEADER_SIZE;
info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
info.qos = qos;
/*
* Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size,
- * max_header_size, skb)
+ * max_header_size, skb)
*
*
*
return;
}
- info.max_data_size = qos->data_size.value - max_header_size
+ info.max_data_size = irttp_get_max_seq_size(self->tsap)
- IRCOMM_HEADER_SIZE;
info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
info.qos = qos;
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 21:00:56 1999
- * Modified at: Wed Aug 25 15:12:18 1999
+ * Modified at: Tue Sep 21 11:46:59 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c and previous IrCOMM work by Takahide Higuchi
*
static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
static void ircomm_tty_hangup(struct tty_struct *tty);
-static void ircomm_tty_break(struct tty_struct *tty, int break_state);
static void ircomm_tty_do_softint(void *private_);
-static void ircomm_tty_disconnect_indication(void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *skb);
+
static int ircomm_tty_data_indication(void *instance, void *sap,
struct sk_buff *skb);
static int ircomm_tty_control_indication(void *instance, void *sap,
driver.stop = ircomm_tty_stop;
driver.start = ircomm_tty_start;
driver.hangup = ircomm_tty_hangup;
- driver.break_ctl = ircomm_tty_break;
driver.wait_until_sent = ircomm_tty_wait_until_sent;
driver.read_proc = ircomm_tty_read_proc;
notify_t notify;
int ret;
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
/* Already open */
if (self->flags & ASYNC_INITIALIZED) {
- DEBUG(0, __FUNCTION__ "(), already open so break out!\n");
+ DEBUG(2, __FUNCTION__ "(), already open so break out!\n");
return 0;
}
/* These callbacks we must handle ourselves */
notify.data_indication = ircomm_tty_data_indication;
notify.udata_indication = ircomm_tty_control_indication;
- notify.disconnect_indication = ircomm_tty_disconnect_indication;
notify.flow_indication = ircomm_tty_flow_indication;
/* Use the ircomm_tty interface for these ones */
+ notify.disconnect_indication = ircomm_tty_disconnect_indication;
notify.connect_confirm = ircomm_tty_connect_confirm;
notify.connect_indication = ircomm_tty_connect_indication;
strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
/* Connect IrCOMM link with remote device */
ret = ircomm_tty_attach_cable(self);
if (ret < 0) {
- DEBUG(0, __FUNCTION__ "(), error attaching cable!\n");
+ ERROR(__FUNCTION__ "(), error attaching cable!\n");
return ret;
}
tty = self->tty;
- DEBUG(1, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
/* this is a callout device */
retval = 0;
add_wait_queue(&self->open_wait, &wait);
- DEBUG(1, "%s(%d):block_til_ready before block on %s open_count=%d\n",
+ DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
__FILE__,__LINE__, tty->driver.name, self->open_count );
save_flags(flags); cli();
self->tqueue.routine = ircomm_tty_do_softint;
self->tqueue.data = self;
self->max_header_size = 5;
- self->max_data_size = 2048-self->max_header_size;
+ self->max_data_size = 64-self->max_header_size;
+ self->close_delay = 5*HZ/10;
+ self->closing_wait = 30*HZ;
/* Init some important stuff */
init_timer(&self->watchdog_timer);
init_waitqueue_head(&self->open_wait);
- skb_queue_head_init(&self->tx_queue);
+ init_waitqueue_head(&self->close_wait);
+
+ /*
+ * Force TTY into raw mode by default which is usually what
+ * we want for IrCOMM and IrLPT. This way applications will
+ * not have to twiddle with printcap etc.
+ */
+ tty->termios->c_iflag = 0;
+ tty->termios->c_oflag = 0;
/* Insert into hash */
hashbin_insert(ircomm_tty, (QUEUE *) self, line, NULL);
-
}
self->open_count++;
/* Not really used by us, but lets do it anyway */
self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ /*
+ * If the port is the middle of closing, bail out now
+ */
+ if (tty_hung_up_p(filp) ||
+ (self->flags & ASYNC_CLOSING)) {
+ if (self->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&self->close_wait);
+ /* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+#ifdef SERIAL_DO_RESTART
+ return ((self->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+#else
+ return -EAGAIN;
+#endif
+ }
+
/* Check if this is a "normal" ircomm device, or an irlpt device */
if (line < 0x10) {
self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
- DEBUG(0, __FUNCTION__ "(), IrCOMM device\n");
+ DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");
} else {
- DEBUG(0, __FUNCTION__ "(), IrLPT device\n");
+ DEBUG(2, __FUNCTION__ "(), IrLPT device\n");
self->service_type = IRCOMM_3_WIRE_RAW;
}
static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- struct sk_buff *skb;
unsigned long flags;
DEBUG(2, __FUNCTION__ "()\n");
MOD_DEC_USE_COUNT;
restore_flags(flags);
- DEBUG(2, __FUNCTION__ "(), returning 2\n");
+ DEBUG(2, __FUNCTION__ "(), open count > 0\n");
return;
}
self->flags |= ASYNC_CLOSING;
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
+ if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, self->closing_wait);
+
+ self->flags &= ~ASYNC_INITIALIZED;
if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty);
tty->closing = 0;
self->tty = 0;
- wake_up_interruptible(&self->open_wait);
-
+ if (self->blocked_open) {
+ if (self->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(self->close_delay);
+ }
+ wake_up_interruptible(&self->open_wait);
+ }
+
self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
ASYNC_CLOSING);
+ wake_up_interruptible(&self->close_wait);
MOD_DEC_USE_COUNT;
- restore_flags(flags);
del_timer(&self->watchdog_timer);
- /* Free frames queued for transmission */
- while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
- dev_kfree_skb(skb);
-
/* Free parameter buffer */
if (self->ctrl_skb) {
dev_kfree_skb(self->ctrl_skb);
self->ctrl_skb = NULL;
}
+ /* Free transmit buffer */
+ if (self->tx_skb) {
+ dev_kfree_skb(self->tx_skb);
+ self->tx_skb = NULL;
+ }
+
+ restore_flags(flags);
+
ircomm_tty_detach_cable(self);
ircomm_close(self->ircomm);
-
self->ircomm = NULL;
+
+#if IRCOMM_TTY_CLOSE_WILL_DEALLOC
self->magic = 0;
hashbin_remove(ircomm_tty, self->line, NULL);
kfree(self);
+#endif
}
/*
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- DEBUG(2, __FUNCTION__ "()\n");
-
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- /* Flush transmit buffer if any */
- if ((self->tx_skb) && (!tty->hw_stopped)) {
- DEBUG(0, __FUNCTION__ "(), flushing!\n");
- ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST,
- self->tx_skb, NULL);
- self->tx_skb = NULL;
- }
+ /*
+ * Let do_softint() do this to avoid race condition with
+ * do_softint() ;-)
+ */
+ queue_task(&self->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
}
/*
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
struct tty_struct *tty;
+ unsigned long flags;
+ struct sk_buff *skb;
- DEBUG(2, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ if (!self || self->magic != IRCOMM_TTY_MAGIC)
+ return;
tty = self->tty;
if (!tty)
return;
- if (tty->hw_stopped) {
- DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
+ if (tty->hw_stopped)
return;
- }
+
+ /* Unlink transmit buffer */
+ save_flags(flags);
+ cli();
+
+ skb = self->tx_skb;
+ self->tx_skb = NULL;
+
+ restore_flags(flags);
/* Flush transmit buffer if any */
- if (self->tx_skb) {
- DEBUG(1, __FUNCTION__ "(), flushing!\n");
- ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST,
- self->tx_skb, NULL);
- self->tx_skb = NULL;
- }
+ if (skb)
+ ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
/* Check if user (still) wants to be waken up */
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
-/* save_flags(flags);
+ save_flags(flags);
cli();
-*/
+
/* Fetch current transmit buffer */
skb = self->tx_skb;
* max data size. The normal case however is just the opposite, and
* this function may be called multiple times, and will then actually
* defragment the data and send it out as one packet as soon as
- * possible, but at a safer point in time
+ * possible, but at a safer point in time
*/
- while (count && !tty->hw_stopped) {
+ while (count) {
size = count;
/* Adjust data size to the max data size */
- if (size > self->max_data_size) {
- DEBUG(1, __FUNCTION__
- "(), size %d to big, clipping to %d!\n",
- size, self->max_data_size);
+ if (size > self->max_data_size)
size = self->max_data_size;
- }
- /* Do we already have a buffer ready for transmit? */
+ /*
+ * Do we already have a buffer ready for transmit, or do
+ * we need to allocate a new frame
+ */
if (skb) {
/*
* Any room for more data at the end of the current
if (size > tailroom)
size = tailroom;
} else {
- /* Current transmit frame is full */
- DEBUG(1, __FUNCTION__ "(), flushing!\n");
- ircomm_tty_do_event(self,
- IRCOMM_TTY_DATA_REQUEST,
- skb, NULL);
- skb = self->tx_skb = NULL;
+ /*
+ * Current transmit frame is full, so break
+ * out, so we can send it as soon as possible
+ */
+ break;
}
- }
-
- /* Check if we need to allocate a new frame */
- if (!skb) {
- DEBUG(3, __FUNCTION__
- "(), allocating new buffer of size %d!\n",
- self->max_data_size+self->max_header_size);
+ } else {
/* Prepare a full sized frame */
skb = dev_alloc_skb(self->max_data_size+
self->max_header_size);
if (!skb) {
- /*restore_flags(flags);*/
+ restore_flags(flags);
return -ENOBUFS;
}
skb_reserve(skb, self->max_header_size);
else
memcpy(skb_put(skb,size), buf+len, size);
- DEBUG(1, __FUNCTION__ "(), size=%d\n", size);
-
count -= size;
len += size;
}
+ restore_flags(flags);
+
/*
* Schedule a new thread which will transmit the frame as soon
* as possible, but at a safe point in time. We do this so the
queue_task(&self->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
- /*restore_flags(flags);*/
-
return len;
}
static int ircomm_tty_write_room(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned long flags;
int ret;
ASSERT(self != NULL, return -1;);
if (tty->hw_stopped)
ret = 0;
else {
+ save_flags(flags);
+ cli();
if (self->tx_skb)
ret = self->max_data_size - self->tx_skb->len;
else
ret = self->max_data_size;
+ restore_flags(flags);
}
DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned long orig_jiffies, poll_time;
+
+ DEBUG(0, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
- DEBUG(2, __FUNCTION__ "(), not impl\n");
+ orig_jiffies = jiffies;
+
+ /* Set poll time to 200 ms */
+ poll_time = MIN(timeout, MSECS_TO_JIFFIES(200));
+
+ while (self->tx_skb && self->tx_skb->len) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(poll_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+ current->state = TASK_RUNNING;
}
/*
ircomm_param_request(self, IRCOMM_DTE, TRUE);
}
- DEBUG(1, __FUNCTION__"(), FLOW_STOP\n");
ircomm_flow_request(self->ircomm, FLOW_STOP);
}
static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+ unsigned long flags;
+ int len = 0;
- DEBUG(4, __FUNCTION__ "()\n");
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
- return 0; /* We don't have any "buffer" */
+ save_flags(flags);
+ cli();
+
+ if (self->tx_skb)
+ len = self->tx_skb->len;
+
+ restore_flags(flags);
+
+ return len;
}
/*
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- DEBUG(0, __FUNCTION__"()\n");
+ DEBUG(2, __FUNCTION__"()\n");
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
if (!tty)
return;
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- DEBUG(2, __FUNCTION__"()\n");
-
ircomm_flow_request(self->ircomm, FLOW_START);
}
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- DEBUG(2, __FUNCTION__"()\n");
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
ircomm_flow_request(self->ircomm, FLOW_STOP);
}
-/*
- * Function ircomm_tty_break (tty, break_state)
- *
- *
- *
- */
-static void ircomm_tty_break(struct tty_struct *tty, int break_state)
-{
- struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
-
- DEBUG(0, __FUNCTION__"(), not impl\n");
-}
-
/*
* Function ircomm_check_modem_status (self)
*
struct tty_struct *tty;
int status;
- DEBUG(4, __FUNCTION__ "()\n");
-
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
DEBUG(2, __FUNCTION__ "(), CTS tx start...\n");
tty->hw_stopped = 0;
-
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
- && tty->ldisc.write_wakeup)
- {
- (tty->ldisc.write_wakeup)(tty);
- }
- wake_up_interruptible(&tty->write_wait);
+
+ queue_task(&self->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
return;
}
} else {
return 0;
}
-/*
- * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
- *
- * Link disconnected
- *
- */
-static void ircomm_tty_disconnect_indication(void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *skb)
-{
- struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
-
- DEBUG(2, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-
- if (!self->tty)
- return;
-
- /* Drop carrier */
- self->session.dce = IRCOMM_DELTA_CD;
- ircomm_tty_check_modem_status(self);
-#if 0
- /* Disconnect */
- tty_hangup(self->tty);
-#endif
-}
-
/*
* Function ircomm_tty_flow_indication (instance, sap, cmd)
*
switch (cmd) {
case FLOW_START:
- DEBUG(1, __FUNCTION__ "(), hw start!\n");
+ DEBUG(2, __FUNCTION__ "(), hw start!\n");
tty->hw_stopped = 0;
-
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
- && tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
- wake_up_interruptible(&tty->write_wait);
+
+ /* ircomm_tty_do_softint will take care of the rest */
+ queue_task(&self->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
break;
default:
/* If we get here, something is very wrong, better stop */
case FLOW_STOP:
- DEBUG(1, __FUNCTION__ "(), hw stopped!\n");
+ DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
tty->hw_stopped = 1;
break;
}
{
int ret=0;
+ ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
+
ret += sprintf(buf+ret, "Service type: ");
if (self->service_type & IRCOMM_9_WIRE)
ret += sprintf(buf+ret, "9_WIRE");
ret += sprintf(buf+ret, "No common service type!\n");
ret += sprintf(buf+ret, "\n");
+ ret += sprintf(buf+ret, "Port name: %s\n", self->session.port_name);
+
ret += sprintf(buf+ret, "DTE status: ");
if (self->session.dte & IRCOMM_RTS)
ret += sprintf(buf+ret, "RTS|");
if (self->session.dte & IRCOMM_DTR)
ret += sprintf(buf+ret, "DTR|");
- ret--; /* remove the last | */
+ if (self->session.dte)
+ ret--; /* remove the last | */
ret += sprintf(buf+ret, "\n");
ret += sprintf(buf+ret, "DCE status: ");
ret += sprintf(buf+ret, "CD|");
if (self->session.dce & IRCOMM_RI)
ret += sprintf(buf+ret, "RI|");
- ret--; /* remove the last | */
+ if (self->session.dce)
+ ret--; /* remove the last | */
ret += sprintf(buf+ret, "\n");
ret += sprintf(buf+ret, "Configuration: ");
ret += sprintf(buf+ret, "ENQ_ACK_IN|");
if (self->session.flow_control & IRCOMM_ENQ_ACK_OUT)
ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
- ret--; /* remove the last | */
+ if (self->session.flow_control)
+ ret--; /* remove the last | */
ret += sprintf(buf+ret, "\n");
ret += sprintf(buf+ret, "Flags: ");
ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
if (self->flags & ASYNC_CALLOUT_ACTIVE)
ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
- ret--; /* remove the last | */
+ if (self->flags)
+ ret--; /* remove the last | */
ret += sprintf(buf+ret, "\n");
ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
ret += sprintf(buf+ret, "Hardware: %s\n",
self->tty->hw_stopped ? "Stopped" : "Running");
- exit:
ret += sprintf(buf+ret, "\n");
return ret;
}
int *eof, void *unused)
{
struct ircomm_tty_cb *self;
- int i, count = 0, l;
+ int count = 0, l;
off_t begin = 0;
self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Jun 5 17:42:00 1999
- * Modified at: Wed Aug 25 13:32:00 1999
+ * Modified at: Wed Sep 8 11:54:27 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
"IRCOMM_TTY_DISCOVERY_INDICATION",
"IRCOMM_TTY_CONNECT_CONFIRM",
"IRCOMM_TTY_CONNECT_INDICATION",
+ "IRCOMM_TTY_DISCONNECT_REQUEST",
+ "IRCOMM_TTY_DISCONNECT_INDICATION",
"IRCOMM_TTY_WD_TIMER_EXPIRED",
"IRCOMM_TTY_GOT_PARAMETERS",
"IRCOMM_TTY_GOT_LSAPSEL",
irlmp_unregister_service(self->skey);
/* Remove LM-IAS object */
- if (self->obj)
+ if (self->obj) {
irias_delete_object(self->obj);
+ self->obj = NULL;
+ }
ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL);
irias_insert_object(self->obj);
} else {
hints = irlmp_service_to_hint(S_COMM);
-
+ hints |= irlmp_service_to_hint(S_TELEPHONY);
+
/* Register IrCOMM with LM-IAS */
self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel",
}
/* Only 9-wire service types continue here */
-#if 0
ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE);
+#if 0
ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
#endif
}
}
+/*
+ * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
+ *
+ * Link disconnected
+ *
+ */
+void ircomm_tty_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason,
+ struct sk_buff *skb)
+{
+ struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+ DEBUG(2, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+ if (!self->tty)
+ return;
+
+ ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
+ NULL);
+}
+
/*
* Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv)
*
/* Check if request succeeded */
if (result != IAS_SUCCESS) {
- DEBUG(0, __FUNCTION__ "(), got NULL value!\n");
+ DEBUG(4, __FUNCTION__ "(), got NULL value!\n");
return;
}
/*
* IrCOMM link is now up, and if we are not using hardware
- * flow-control, then declare the hardware as running
+ * flow-control, then declare the hardware as running. Otherwise
+ * the client will have to wait for the CD to be set.
*/
if (!(self->flags & ASYNC_CTS_FLOW)) {
DEBUG(2, __FUNCTION__ "(), starting hardware!\n");
if (!self->tty)
return;
self->tty->hw_stopped = 0;
-
- /* Kick client */
- ircomm_tty_do_softint(self);
}
+ /* Wake up processes blocked on open */
+ wake_up_interruptible(&self->open_wait);
+
+ /*
+ * Wake up processes blocked on write, or waiting for a write
+ * wakeup notification
+ */
+ queue_task(&self->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
}
/*
* Function irlan_start_watchdog_timer (self, timeout)
*
- *
- *
+ * Start the watchdog timer. This timer is used to make sure that any
+ * connection attempt is successful, and if not, we will retry after
+ * the timeout
*/
void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout)
{
- DEBUG(4, __FUNCTION__ "()\n");
-
irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
ircomm_tty_watchdog_timer_expired);
}
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
- DEBUG(1, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
{
int ret = 0;
- DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+ DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
ircomm_tty_state[self->state], ircomm_tty_event[event]);
switch (event) {
/* Accept connection */
ircomm_connect_response(self->ircomm, NULL);
-
- ircomm_tty_link_established(self);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+ /* Init connection */
+ ircomm_tty_send_initial_parameters(self);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_WD_TIMER_EXPIRED:
/* Just stay idle */
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
{
int ret = 0;
- DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+ DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
ircomm_tty_state[self->state], ircomm_tty_event[event]);
switch (event) {
/* Accept connection */
ircomm_connect_response(self->ircomm, NULL);
- ircomm_tty_link_established(self);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+ /* Init connection */
+ ircomm_tty_send_initial_parameters(self);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_WD_TIMER_EXPIRED:
/* Try to discover any remote devices */
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
{
int ret = 0;
- DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+ DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
ircomm_tty_state[self->state], ircomm_tty_event[event]);
switch (event) {
/* Accept connection */
ircomm_connect_response(self->ircomm, NULL);
- ircomm_tty_link_established(self);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+ /* Init connection */
+ ircomm_tty_send_initial_parameters(self);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_DETACH_CABLE:
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
{
int ret = 0;
- DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+ DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
ircomm_tty_state[self->state], ircomm_tty_event[event]);
switch (event) {
/* Accept connection */
ircomm_connect_response(self->ircomm, NULL);
- ircomm_tty_link_established(self);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+ /* Init connection */
+ ircomm_tty_send_initial_parameters(self);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_DETACH_CABLE:
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
{
int ret = 0;
- DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+ DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
ircomm_tty_state[self->state], ircomm_tty_event[event]);
switch (event) {
case IRCOMM_TTY_CONNECT_CONFIRM:
- ircomm_tty_link_established(self);
+ del_timer(&self->watchdog_timer);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
+
/*
* Send initial parameters. This will also send out queued
* parameters waiting for the connection to come up
*/
ircomm_tty_send_initial_parameters(self);
-
- ASSERT(self->tty != NULL, return -1;);
-
- /* Send queued frames */
- while ((skb = skb_dequeue(&self->tx_queue))) {
- ret = ircomm_data_request(self->ircomm, skb);
- if (ret < 0)
- break;
- }
-
- /* Wake up processes blocked on open */
- wake_up_interruptible(&self->open_wait);
-
- /*
- * Wake up processes blocked on write, or waiting for a write
- * wakeup notification
- */
- queue_task(&self->tqueue, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_CONNECT_INDICATION:
del_timer(&self->watchdog_timer);
/* Accept connection */
ircomm_connect_response(self->ircomm, NULL);
ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+ /* Init connection */
+ ircomm_tty_send_initial_parameters(self);
+ ircomm_tty_link_established(self);
break;
case IRCOMM_TTY_WD_TIMER_EXPIRED:
/* Go back to search mode */
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
case IRCOMM_TTY_DATA_REQUEST:
ret = ircomm_data_request(self->ircomm, skb);
break;
- case IRCOMM_TTY_DATA_INDICATION:
- break;
case IRCOMM_TTY_DETACH_CABLE:
ircomm_disconnect_request(self->ircomm, NULL);
ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
break;
+ case IRCOMM_TTY_DISCONNECT_INDICATION:
+ ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+ ircomm_tty_start_watchdog_timer(self, 3*HZ);
+
+ /* Drop carrier */
+ self->session.dce = IRCOMM_DELTA_CD;
+ ircomm_tty_check_modem_status(self);
+ break;
default:
- DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+ DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
ircomm_tty_event[event]);
return -EINVAL;
}
{
self->state = state;
- DEBUG(1, __FUNCTION__": next state=%s, service type=%d\n",
+ DEBUG(2, __FUNCTION__": next state=%s, service type=%d\n",
ircomm_tty_state[self->state], self->service_type);
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Jun 10 14:39:09 1999
- * Modified at: Wed Aug 25 14:11:02 1999
+ * Modified at: Tue Aug 31 10:29:36 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
DEBUG(1, __FUNCTION__ "()\n");
- result = ((self->session.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
- | ((self->session.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
- | ((self->session.dce & IRCOMM_DELTA_CD) ? TIOCM_CAR : 0)
- | ((self->session.dce & IRCOMM_DELTA_RI) ? TIOCM_RNG : 0)
- | ((self->session.dce & IRCOMM_DELTA_DSR) ? TIOCM_DSR : 0)
- | ((self->session.dce & IRCOMM_DELTA_CTS) ? TIOCM_CTS : 0);
+ result = ((self->session.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
+ | ((self->session.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
+ | ((self->session.dce & IRCOMM_CD) ? TIOCM_CAR : 0)
+ | ((self->session.dce & IRCOMM_RI) ? TIOCM_RNG : 0)
+ | ((self->session.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
+ | ((self->session.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
return put_user(result, value);
}
memset(&info, 0, sizeof(info));
info.line = self->line;
- /* info.flags = self->flags; */
+ info.flags = self->flags;
info.baud_base = self->session.data_rate;
-#if 0
- info.close_delay = driver->close_delay;
- info.closing_wait = driver->closing_wait;
-#endif
+ info.close_delay = self->close_delay;
+ info.closing_wait = self->closing_wait;
+
/* For compatibility */
info.type = PORT_16550A;
info.port = 0;
info.irq = 0;
info.xmit_fifo_size = 0;
info.hub6 = 0;
-#if 0
- info.custom_divisor = driver->custom_divisor;
-#endif
+ info.custom_divisor = 0;
+
if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
return -EFAULT;
/*********************************************************************
*
* Filename: irda_device.c
- * Version: 0.5
+ * Version: 0.6
* Description: Abstract device driver layer and helper functions
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Sep 2 20:22:08 1998
- * Modified at: Tue Aug 24 14:31:13 1999
+ * Modified at: Tue Sep 28 08:40:31 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Modified at: Fri May 28 3:11 CST 1999
* Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
/* Allocate memory if needed */
if (self->rx_buff.truesize > 0) {
- self->rx_buff.head = ( __u8 *) kmalloc(self->rx_buff.truesize,
- self->rx_buff.flags);
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ self->rx_buff.flags);
if (self->rx_buff.head == NULL)
return -ENOMEM;
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
}
if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = ( __u8 *) kmalloc(self->tx_buff.truesize,
- self->tx_buff.flags);
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ self->tx_buff.flags);
if (self->tx_buff.head == NULL) {
kfree(self->rx_buff.head);
return -ENOMEM;
/* Initialize IrDA net device */
do {
sprintf(self->name, "%s%d", "irda", i++);
- } while (dev_get(self->name) != NULL);
+ } while (dev_get(self->name));
self->netdev.name = self->name;
self->netdev.priv = (void *) self;
self->netdev.next = NULL;
-
- if ((result = register_netdev(&self->netdev)) != 0) {
- DEBUG(0, __FUNCTION__ "(), register_netdev() failed!\n");
+
+ result = register_netdev(&self->netdev);
+ if (result) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
return -1;
}
hashbin_insert(irda_device, (QUEUE *) self, (int) self, NULL);
- /* Open network device */
- dev_open(&self->netdev);
-
MESSAGE("IrDA: Registered device %s\n", self->name);
- irda_device_set_media_busy(self, FALSE);
+ irda_device_set_media_busy(&self->netdev, FALSE);
return 0;
}
/* We do this test to know if the device has been registered at all */
if (self->netdev.type == ARPHRD_IRDA) {
- dev_close(&self->netdev);
-
/* Remove netdevice */
unregister_netdev(&self->netdev);
}
* Called when we have detected that another station is transmiting
* in contention mode.
*/
-void irda_device_set_media_busy(struct irda_device *self, int status)
+void irda_device_set_media_busy(struct net_device *dev, int status)
{
+ struct irda_device *self;
+
DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
+ self = dev->priv;
+
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
* Change the speed of the currently used irda_device
*
*/
-inline void irda_device_change_speed(struct irda_device *self, int speed)
+void irda_device_change_speed(struct irda_device *self, int speed)
{
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
speed);
}
-inline int irda_device_is_media_busy( struct irda_device *self)
+int irda_device_is_media_busy(struct net_device *dev)
{
+ struct irda_device *self;
+
+ self = dev->priv;
+
ASSERT(self != NULL, return FALSE;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
return self->media_busy;
}
-inline int irda_device_is_receiving( struct irda_device *self)
+int irda_device_is_receiving(struct net_device *dev)
{
+ struct irda_device *self;
+
+ self = dev->priv;
+
ASSERT(self != NULL, return FALSE;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
return FALSE;
}
-inline struct qos_info *irda_device_get_qos(struct irda_device *self)
+struct qos_info *irda_device_get_qos(struct net_device *dev)
{
+ struct irda_device *self;
+
+ ASSERT(dev != NULL, return NULL;);
+
+ self = dev->priv;
+
ASSERT(self != NULL, return NULL;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return NULL;);
return &self->qos;
}
-static struct enet_statistics *irda_device_get_stats( struct net_device *dev)
+static struct enet_statistics *irda_device_get_stats(struct net_device *dev)
{
struct irda_device *priv = (struct irda_device *) dev->priv;
* Open new IrLAP layer instance, now that everything should be
* initialized properly
*/
- self->irlap = irlap_open(self);
+ self->irlap = irlap_open(dev);
/* It's now safe to initilize the saddr */
memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
return 0;
}
-static int irda_device_net_hard_header(struct sk_buff *skb, struct net_device *dev,
+static int irda_device_net_hard_header(struct sk_buff *skb,
+ struct net_device *dev,
unsigned short type, void *daddr,
void *saddr, unsigned len)
{
return 0;
}
-static int irda_device_net_set_config( struct net_device *dev, struct ifmap *map)
+static int irda_device_net_set_config(struct net_device *dev,
+ struct ifmap *map)
{
DEBUG( 0, __FUNCTION__ "()\n");
return 0;
}
-static int irda_device_net_change_mtu( struct net_device *dev, int new_mtu)
+static int irda_device_net_change_mtu(struct net_device *dev, int new_mtu)
{
DEBUG( 0, __FUNCTION__ "()\n");
return 0;
}
-
-#define SIOCSDONGLE SIOCDEVPRIVATE
static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */
struct ifreq *rq, /* Data passed */
int cmd) /* Ioctl number */
#endif
struct irda_device *self;
- DEBUG(4, __FUNCTION__ "()\n");
-
ASSERT(dev != NULL, return -1;);
- self = (struct irda_device *) dev->priv;
+ self = dev->priv;
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
- DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd);
+ DEBUG(0, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
#endif
break;
#endif
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ irda_device_change_speed(self, rq->ifr_bandwidth);
+ break;
case SIOCSDONGLE: /* Set dongle */
/* Initialize dongle */
irda_device_init_dongle(self, (int) rq->ifr_data);
break;
+ case SIOCSMEDIABUSY: /* Set media busy */
+ irda_device_set_media_busy(&self->netdev, TRUE);
+ break;
default:
ret = -EOPNOTSUPP;
}
-dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
+dep_tristate ' IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Tue Aug 17 15:30:40 1999
+ * Modified at: Thu Sep 9 11:39:43 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
/* Get the first free irlan<x> name */
do {
sprintf(self->ifname, "%s%d", "irlan", i++);
- } while (dev_get(self->ifname) != NULL);
+ } while (dev_get(self->ifname));
}
self->dev.name = self->ifname;
irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
irias_add_integer_attrib(obj, "CompCnt", 1);
if (self->provider.access_type == ACCESS_PEER)
- irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+ irias_add_string_attrib(obj, "Comp#01", "PNP8389");
else
irias_add_string_attrib(obj, "Comp#01", "PNP8294");
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Mon Aug 23 12:05:26 1999
+ * Modified at: Mon Sep 20 11:04:32 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Initialize IrLAP layer
*
*/
-struct irlap_cb *irlap_open(struct irda_device *irdev)
+struct irlap_cb *irlap_open(struct net_device *dev)
{
struct irlap_cb *self;
DEBUG(4, __FUNCTION__ "()\n");
- ASSERT(irdev != NULL, return NULL;);
- ASSERT(irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
-
/* Initialize the irlap structure. */
self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
if (self == NULL)
self->magic = LAP_MAGIC;
/* Make a binding between the layers */
- self->irdev = irdev;
- self->netdev = &irdev->netdev;
+ self->netdev = dev;
irlap_next_state(self, LAP_OFFLINE);
irlap_flush_all_queues(self);
- self->irdev = NULL;
self->magic = 0;
kfree(self);
irlap_init_qos_capabilities(self, qos_user);
if ((self->state == LAP_NDM) &&
- !irda_device_is_media_busy(self->irdev))
+ !irda_device_is_media_busy(self->netdev))
irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
else
self->connect_pending = TRUE;
* connection attempts much easier.
*/
if (discovery_log && hashbin_get_size(discovery_log) > 0)
- irda_device_set_media_busy(self->irdev, FALSE);
+ irda_device_set_media_busy(self->netdev, FALSE);
/* Inform IrLMP */
irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
*/
void irlap_change_speed(struct irlap_cb *self, __u32 speed)
{
+ struct ifreq req;
+
DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
ASSERT(self != NULL, return;);
ASSERT(self->magic == LAP_MAGIC, return;);
- if (!self->irdev) {
+ if (!self->netdev) {
DEBUG(1, __FUNCTION__ "(), driver missing!\n");
return;
}
- irda_device_change_speed(self->irdev, speed);
+ /*
+ * Warning, ifr_bandwidth is only 16 bits on architectures where ints
+ * are 16 bits wide.
+ */
+ req.ifr_bandwidth = speed;
+ self->netdev->do_ioctl(self->netdev, &req, SIOCSBANDWIDTH);
self->qos_rx.baud_rate.value = speed;
self->qos_tx.baud_rate.value = speed;
{
ASSERT(self != NULL, return;);
ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(self->irdev != NULL, return;);
+ ASSERT(self->netdev != NULL, return;);
/* Start out with the maximum QoS support possible */
irda_init_max_qos_capabilies(&self->qos_rx);
/* Apply drivers QoS capabilities */
irda_qos_compute_intersection(&self->qos_rx,
- irda_device_get_qos(self->irdev));
+ irda_device_get_qos(self->netdev));
/*
* Check for user supplied QoS parameters. The service user is only
ASSERT(self != NULL, return -ENODEV;);
ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
- len += sprintf(buf+len, "irlap%d <-> %s ",
- i++, self->irdev->name);
+ len += sprintf(buf+len, "irlap%d ", i++);
len += sprintf(buf+len, "state: %s\n",
irlap_state[ self->state]);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Aug 16 00:59:29 1997
- * Modified at: Wed Aug 25 14:49:47 1999
+ * Modified at: Mon Sep 20 12:30:31 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
"LAP_RESET_CHECK",
};
-static int (*state[])( struct irlap_cb *self, IRLAP_EVENT event,
- struct sk_buff *skb, struct irlap_info *info) =
-{
+static int (*state[])(struct irlap_cb *self, IRLAP_EVENT event,
+ struct sk_buff *skb, struct irlap_info *info) =
+{
irlap_state_ndm,
irlap_state_query,
irlap_state_reply,
case LAP_NDM:
/* Check if we should try to connect */
if ((self->connect_pending) &&
- !irda_device_is_media_busy(self->irdev))
+ !irda_device_is_media_busy(self->netdev))
{
self->connect_pending = FALSE;
discovery_t *discovery_rsp;
int ret = 0;
- DEBUG(4, __FUNCTION__ "()\n");
-
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case CONNECT_REQUEST:
- ASSERT(self->irdev != NULL, return -1;);
+ ASSERT(self->netdev != NULL, return -1;);
- if (irda_device_is_media_busy(self->irdev)) {
+ if (irda_device_is_media_busy(self->netdev)) {
DEBUG(0, __FUNCTION__
"(), CONNECT_REQUEST: media busy!\n");
irlap_next_state(self, LAP_SETUP);
}
break;
-
case RECV_SNRM_CMD:
- self->daddr = info->daddr;
- self->caddr = info->caddr;
-
- irlap_next_state(self, LAP_CONN);
-
- irlap_connect_indication(self, skb);
+ /* Check if the frame contains and I field */
+ if (info) {
+ self->daddr = info->daddr;
+ self->caddr = info->caddr;
+
+ irlap_next_state(self, LAP_CONN);
+
+ irlap_connect_indication(self, skb);
+ } else {
+ DEBUG(0, __FUNCTION__ "(), SNRM frame does not contain"
+ " and I field!\n");
+ dev_kfree_skb(skb);
+ }
break;
-
case DISCOVERY_REQUEST:
ASSERT(info != NULL, return -1;);
- if (irda_device_is_media_busy(self->irdev)) {
+ if (irda_device_is_media_busy(self->netdev)) {
DEBUG(0, __FUNCTION__ "(), media busy!\n");
/* irlap->log.condition = MEDIA_BUSY; */
irlap_start_slot_timer(self, self->slot_timeout);
irlap_next_state(self, LAP_QUERY);
break;
-
case RECV_DISCOVERY_XID_CMD:
- ASSERT( info != NULL, return -1;);
+ ASSERT(info != NULL, return -1;);
/* Assert that this is not the final slot */
if (info->s <= info->S) {
default:
DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
+
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
irlap_event[event]);
if (skb)
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
ret = -1;
break;
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == LAP_MAGIC, return -1;);
- switch(event) {
+ switch (event) {
case QUERY_TIMER_EXPIRED:
DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
jiffies);
/* skb_pull(skb, 11); */
skb_pull(skb, sizeof(struct snrm_frame));
- ASSERT(self->irdev != NULL, return -1;);
+ ASSERT(self->netdev != NULL, return -1;);
irlap_qos_negotiate(self, skb);
irlap_start_wd_timer(self, self->wd_timeout);
irlap_next_state( self, LAP_NRM_S);
break;
-
- case RECV_SNRM_CMD:
- DEBUG( 3, __FUNCTION__ "(), event RECV_SNRM_CMD!\n");
-#if 0
- irlap_next_state( self, LAP_NDM);
-#endif
- break;
-
case RECV_DISCOVERY_XID_CMD:
DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
irlap_next_state( self, LAP_NDM);
- break;
-
+ break;
case DISCONNECT_REQUEST:
irlap_send_dm_frame( self);
irlap_next_state( self, LAP_CONN);
break;
-
default:
DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
irlap_event[event]);
+
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
* The device with the largest device address wins the battle
* (both have sent a SNRM command!)
*/
- if (info->daddr > self->saddr) {
+ if (info &&(info->daddr > self->saddr)) {
del_timer(&self->final_timer);
irlap_initiate_connection_state(self);
- ASSERT(self->irdev != NULL, return -1;);
+ ASSERT(self->netdev != NULL, return -1;);
skb_pull(skb, sizeof(struct snrm_frame));
irlap_next_state(self, LAP_NRM_S);
} else {
/* We just ignore the other device! */
+ dev_kfree_skb(skb);
irlap_next_state(self, LAP_SETUP);
}
break;
skb_pull(skb, sizeof(struct ua_frame));
- ASSERT(self->irdev != NULL, return -1;);
+ ASSERT(self->netdev != NULL, return -1;);
irlap_qos_negotiate(self, skb);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
break;
- /* DM handled in irlap_frame.c, irlap_input() */
-
+ /* DM handled in irlap_frame.c, irlap_driver_rcv() */
default:
- DEBUG( 4, "irlap_state_setup: Unknown event");
+ DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+ irlap_event[event]);
+
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
break;
default:
DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
+
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
* of receiving a frame (page 45, IrLAP). Check that
* we only do this once for each frame.
*/
- if (irda_device_is_receiving(self->irdev) && !self->add_wait) {
+ if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
DEBUG(4, "FINAL_TIMER_EXPIRED when receiving a "
"frame! Waiting a little bit more!\n");
irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
default:
DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
if (self->retry_count < 3) {
irlap_wait_min_turn_around(self, &self->qos_tx);
- ASSERT(self->irdev != NULL, return -1;);
- irlap_send_snrm_frame(self,
- irda_device_get_qos(self->irdev));
+ ASSERT(self->netdev != NULL, return -1;);
+ irlap_send_snrm_frame(self, irda_device_get_qos(self->netdev));
self->retry_count++; /* Experimental!! */
}
break;
case RECV_SNRM_CMD:
- DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
- irlap_initiate_connection_state(self);
- irlap_wait_min_turn_around(self, &self->qos_tx);
- irlap_send_ua_response_frame(self, &self->qos_rx);
- irlap_reset_confirm();
- irlap_start_wd_timer(self, self->wd_timeout);
- irlap_next_state(self, LAP_NDM);
+ /*
+ * SNRM frame is not allowed to contain an I-field in this
+ * state
+ */
+ if (!info) {
+ DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
+ irlap_initiate_connection_state(self);
+ irlap_wait_min_turn_around(self, &self->qos_tx);
+ irlap_send_ua_response_frame(self, &self->qos_rx);
+ irlap_reset_confirm();
+ irlap_start_wd_timer(self, self->wd_timeout);
+ irlap_next_state(self, LAP_NDM);
+ } else {
+ DEBUG(0, __FUNCTION__ "(), SNRM frame contained an I "
+ "field!\n");
+ dev_kfree_skb(skb);
+ }
break;
default:
DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
+
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -1;
break;
}
/*
* Send frame only if send window > 1
*/
- if ((self->window > 0) && ( !self->remote_busy)) {
+ if ((self->window > 0) && (!self->remote_busy)) {
/*
* Test if we have transmitted more bytes over the
* link than its possible to do with the current
* speed and turn-around-time.
*/
if ((skb->len+self->bofs_count) > self->bytes_left) {
- DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
skb_queue_head(&self->tx_list, skb);
/*
* Switch to NRM_S, this is only possible
default:
DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
+ if (skb)
+ dev_kfree_skb(skb);
+
ret = -EINVAL;
break;
}
* Starting WD-timer here is optional, but
* not recommended. Note 6 IrLAP p. 83
*/
- /* irda_start_timer( WD_TIMER, self->wd_timeout); */
+ /* irda_start_timer(WD_TIMER, self->wd_timeout); */
/* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_S);
break;
case RECV_SNRM_CMD:
- del_timer(&self->wd_timer);
- DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
- irlap_next_state(self, LAP_RESET_CHECK);
-
- irlap_reset_indication(self);
+ /* SNRM frame is not allowed to contain an I-field */
+ if (!info) {
+ del_timer(&self->wd_timer);
+ DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
+ irlap_next_state(self, LAP_RESET_CHECK);
+
+ irlap_reset_indication(self);
+ } else {
+ DEBUG(0, __FUNCTION__ "(), SNRM frame contained an "
+ "I-field!\n");
+ dev_kfree_skb(skb);
+ }
break;
case WD_TIMER_EXPIRED:
- DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies);
-
/*
* Wait until retry_count * n matches negotiated threshold/
* disconnect time (note 2 in IrLAP p. 82)
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Wed Aug 25 13:15:53 1999
+ * Modified at: Tue Sep 28 08:49:58 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
{
struct snrm_frame *frame;
- DEBUG(3, __FUNCTION__ "()\n");
-
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
-
frame = (struct snrm_frame *) skb->data;
-
- /* Copy peer device address */
- info->daddr = le32_to_cpu(frame->saddr);
-
- /* Copy connection address */
- info->caddr = frame->ncaddr;
-
- /* Check if connection address has got a valid value */
- if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
- DEBUG(3, __FUNCTION__ "(), invalid connection address!\n");
- dev_kfree_skb(skb);
- return;
- }
-
- irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+
+ if (skb->len >= sizeof(struct snrm_frame)) {
+ /* Copy the new connection address */
+ info->caddr = frame->ncaddr;
+
+ /* Check if the new connection address is valid */
+ if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
+ DEBUG(3, __FUNCTION__
+ "(), invalid connection address!\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /* Copy peer device address */
+ info->daddr = le32_to_cpu(frame->saddr);
+ info->saddr = le32_to_cpu(frame->daddr);
+
+ /* Only accept if addressed directly to us */
+ if (info->saddr != self->saddr) {
+ DEBUG(2, __FUNCTION__ "(), not addressed to us!\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+ irlap_do_event(self, RECV_SNRM_CMD, skb, info);
+ } else
+ /* Signal that this SNRM frame does not contain and I-field */
+ irlap_do_event(self, RECV_SNRM_CMD, skb, NULL);
}
/*
skb_put(skb, 14);
frame = (struct xid_frame *) skb->data;
- if ( command) {
+ if (command) {
frame->caddr = CBROADCAST | CMD_FRAME;
frame->control = XID_CMD | PF_BIT;
} else {
else
frame->daddr = cpu_to_le32(discovery->daddr);
- switch(S) {
+ switch (S) {
case 1:
frame->flags = 0x00;
break;
ASSERT(self != NULL, return;);
ASSERT(self->magic == LAP_MAGIC, return;);
+ xid = (struct xid_frame *) skb->data;
+
+ info->daddr = le32_to_cpu(xid->saddr);
+ info->saddr = le32_to_cpu(xid->daddr);
+
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ dev_kfree_skb(skb);
+ DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
+ return;
+ }
+
if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
- DEBUG(0, __FUNCTION__ "(), kmalloc failed!\n");
+ WARNING(__FUNCTION__ "(), kmalloc failed!\n");
return;
}
memset(discovery, 0, sizeof(discovery_t));
- xid = (struct xid_frame *) skb->data;
-
- /*
- * Copy peer device address and set the source address
- */
- info->daddr = le32_to_cpu(xid->saddr);
discovery->daddr = info->daddr;
discovery->saddr = self->saddr;
discovery->timestamp = jiffies;
__u8 *discovery_info;
char *text;
- DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
-
xid = (struct xid_frame *) skb->data;
-
- /* Copy peer device address */
+
info->daddr = le32_to_cpu(xid->saddr);
+ info->saddr = le32_to_cpu(xid->daddr);
+
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
+ dev_kfree_skb(skb);
+ return;
+ }
switch (xid->flags & 0x03) {
case 0x00:
*
* Received RR (Receive Ready) frame from peer station, no harm in
* making it inline since its called only from one single place
- * (irlap_input).
+ * (irlap_driver_rcv).
*/
static inline void irlap_recv_rr_frame(struct irlap_cb *self,
struct sk_buff *skb,
static void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb,
struct irlap_info *info)
{
- DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies);
-
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
-
irlap_do_event(self, RECV_UA_RSP, skb, info);
}
/*
* Function irlap_send_data_primary(self, skb)
*
- *
+ * Send I-frames as the primary station but without the poll bit set
*
*/
-void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
{
struct sk_buff *tx_skb;
}
}
/*
- * Function irlap_send_data_primary_poll ( self, skb)
+ * Function irlap_send_data_primary_poll (self, skb)
*
* Send I(nformation) frame as primary with poll bit set
*/
-void irlap_send_data_primary_poll( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
{
struct sk_buff *tx_skb;
{
struct sk_buff *tx_skb = NULL;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
/* Is this reliable or unreliable data? */
- if ( skb->data[1] == I_FRAME) {
+ if (skb->data[1] == I_FRAME) {
/*
* Insert frame sequence number (Vs) in control field before
*/
skb->data[1] = I_FRAME | (self->vs << 1);
- tx_skb = skb_clone( skb, GFP_ATOMIC);
- if ( tx_skb == NULL) {
- dev_kfree_skb( skb);
+ tx_skb = skb_clone(skb, GFP_ATOMIC);
+ if (tx_skb == NULL) {
+ dev_kfree_skb(skb);
return;
}
if (skb->sk != NULL)
- skb_set_owner_w( tx_skb, skb->sk);
+ skb_set_owner_w(tx_skb, skb->sk);
/* Insert frame in store */
- skb_queue_tail( &self->wx_list, skb);
+ skb_queue_tail(&self->wx_list, skb);
tx_skb->data[1] |= PF_BIT;
self->window = self->window_size;
self->ack_required = FALSE;
- irlap_start_wd_timer( self, self->wd_timeout);
+ irlap_start_wd_timer(self, self->wd_timeout);
- irlap_send_i_frame( self, tx_skb, RSP_FRAME);
+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
} else {
- if ( self->ack_required) {
- irlap_send_ui_frame( self, skb, RSP_FRAME);
- irlap_send_rr_frame( self, RSP_FRAME);
+ if (self->ack_required) {
+ irlap_send_ui_frame(self, skb, RSP_FRAME);
+ irlap_send_rr_frame(self, RSP_FRAME);
self->ack_required = FALSE;
} else {
skb->data[1] |= PF_BIT;
- irlap_send_ui_frame( self, skb, RSP_FRAME);
+ irlap_send_ui_frame(self, skb, RSP_FRAME);
}
self->window = self->window_size;
- irlap_start_wd_timer( self, self->wd_timeout);
+ irlap_start_wd_timer(self, self->wd_timeout);
}
}
* Send I(nformation) frame as secondary without final bit set
*
*/
-void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
{
struct sk_buff *tx_skb = NULL;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
-
/* Is this reliable or unreliable data? */
- if ( skb->data[1] == I_FRAME) {
+ if (skb->data[1] == I_FRAME) {
/*
* Insert frame sequence number (Vs) in control field before
*/
skb->data[1] = I_FRAME | (self->vs << 1);
- tx_skb = skb_clone( skb, GFP_ATOMIC);
- if ( tx_skb == NULL) {
- dev_kfree_skb( skb);
+ tx_skb = skb_clone(skb, GFP_ATOMIC);
+ if (tx_skb == NULL) {
+ dev_kfree_skb(skb);
return;
}
if (skb->sk != NULL)
- skb_set_owner_w( tx_skb, skb->sk);
+ skb_set_owner_w(tx_skb, skb->sk);
/* Insert frame in store */
- skb_queue_tail( &self->wx_list, skb);
+ skb_queue_tail(&self->wx_list, skb);
self->vs = (self->vs + 1) % 8;
self->ack_required = FALSE;
self->window -= 1;
- irlap_send_i_frame( self, tx_skb, RSP_FRAME);
+ irlap_send_i_frame(self, tx_skb, RSP_FRAME);
} else {
- irlap_send_ui_frame( self, skb, RSP_FRAME);
+ irlap_send_ui_frame(self, skb, RSP_FRAME);
self->window -= 1;
}
}
*
* FIXME: It is not safe to traverse a this list without locking it!
*/
-void irlap_resend_rejected_frames( struct irlap_cb *self, int command)
+void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
{
struct sk_buff *tx_skb;
struct sk_buff *skb;
int count;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-
- DEBUG(2, __FUNCTION__ "(), retry_count=%d\n", self->retry_count);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
/* Initialize variables */
skb = tx_skb = NULL;
/*
* Resend all unacknowledged frames
*/
- count = skb_queue_len( &self->wx_list);
- skb = skb_peek( &self->wx_list);
- while ( skb != NULL) {
- irlap_wait_min_turn_around( self, &self->qos_tx);
+ count = skb_queue_len(&self->wx_list);
+ skb = skb_peek(&self->wx_list);
+ while (skb != NULL) {
+ irlap_wait_min_turn_around(self, &self->qos_tx);
/* We copy the skb to be retransmitted since we will have to
* modify it. Cloning will confuse packet sniffers
*/
/* tx_skb = skb_clone( skb, GFP_ATOMIC); */
tx_skb = skb_copy(skb, GFP_ATOMIC);
- if ( tx_skb == NULL) {
+ if (tx_skb == NULL) {
/* Unlink tx_skb from list */
tx_skb->next = tx_skb->prev = NULL;
tx_skb->list = NULL;
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
return;
}
/* Unlink tx_skb from list */
/*
* make sure the skb->sk accounting of memory usage is sane
*/
- if ( skb->sk != NULL)
- skb_set_owner_w( tx_skb, skb->sk);
+ if (skb->sk != NULL)
+ skb_set_owner_w(tx_skb, skb->sk);
/* Clear old Nr field + poll bit */
tx_skb->data[1] &= 0x0f;
/*
* Set poll bit on the last frame retransmitted
*/
- if ( count-- == 1)
+ if (count-- == 1)
tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
else
tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
- irlap_send_i_frame( self, tx_skb, command);
+ irlap_send_i_frame(self, tx_skb, command);
/*
* If our skb is the last buffer in the list, then
* we are finished, if not, move to the next sk-buffer
*/
- if ( skb == skb_peek_tail( &self->wx_list))
+ if (skb == skb_peek_tail( &self->wx_list))
skb = NULL;
else
skb = skb->next;
*/
return; /* Skip this for now, DB */
- while ( skb_queue_len( &self->tx_list) > 0) {
+ while (skb_queue_len( &self->tx_list) > 0) {
- DEBUG( 0, __FUNCTION__ "(), sending additional frames!\n");
- if (( skb_queue_len( &self->tx_list) > 0) &&
- ( self->window > 0)) {
+ DEBUG(0, __FUNCTION__ "(), sending additional frames!\n");
+ if ((skb_queue_len( &self->tx_list) > 0) &&
+ (self->window > 0)) {
skb = skb_dequeue( &self->tx_list);
- ASSERT( skb != NULL, return;);
+ ASSERT(skb != NULL, return;);
/*
* If send window > 1 then send frame with pf
{
__u8 *frame;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
frame = skb->data;
void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *skb,
int command)
{
- __u8 *frame;
-
- frame = skb->data;
-
/* Insert connection address */
- frame[0] = self->caddr;
- frame[0] |= (command) ? CMD_FRAME : 0;
+ skb->data[0] = self->caddr;
+ skb->data[0] |= (command) ? CMD_FRAME : 0;
/* Insert next to receive (Vr) */
- frame[1] |= (self->vr << 5); /* insert nr */
+ skb->data[1] |= (self->vr << 5); /* insert nr */
irlap_queue_xmit(self, skb);
}
* Function irlap_recv_i_frame (skb, frame)
*
* Receive and parse an I (Information) frame, no harm in making it inline
- * since it's called only from one single place (irlap_input).
+ * since it's called only from one single place (irlap_driver_rcv).
*/
static inline void irlap_recv_i_frame(struct irlap_cb *self,
struct sk_buff *skb,
* Received Frame Reject response.
*
*/
-static void irlap_recv_frmr_frame( struct irlap_cb *self, struct sk_buff *skb,
- struct irlap_info *info)
+static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
+ struct irlap_info *info)
{
__u8 *frame;
int w, x, y, z;
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG(0, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
- ASSERT( info != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
+ ASSERT(info != NULL, return;);
frame = skb->data;
y = frame[3] & 0x04;
z = frame[3] & 0x08;
- if ( w) {
- DEBUG( 0, "Rejected control field is undefined or not "
- "implemented.\n");
+ if (w) {
+ DEBUG(0, "Rejected control field is undefined or not "
+ "implemented.\n");
}
- if ( x) {
- DEBUG( 0, "Rejected control field was invalid because it "
- "contained a non permitted I field.\n");
+ if (x) {
+ DEBUG(0, "Rejected control field was invalid because it "
+ "contained a non permitted I field.\n");
}
- if ( y) {
- DEBUG( 0, "Received I field exceeded the maximum negotiated "
- "for the existing connection or exceeded the maximum "
- "this station supports if no connection exists.\n");
+ if (y) {
+ DEBUG(0, "Received I field exceeded the maximum negotiated "
+ "for the existing connection or exceeded the maximum "
+ "this station supports if no connection exists.\n");
}
- if ( z) {
- DEBUG( 0, "Rejected control field control field contained an "
- "invalid Nr count.\n");
+ if (z) {
+ DEBUG(0, "Rejected control field control field contained an "
+ "invalid Nr count.\n");
}
- irlap_do_event( self, RECV_FRMR_RSP, skb, info);
+ irlap_do_event(self, RECV_FRMR_RSP, skb, info);
}
/*
{
struct test_frame *frame;
- DEBUG(0, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
if (skb->len < sizeof(struct test_frame)) {
DEBUG(0, __FUNCTION__ "() test frame to short!\n");
info->daddr = le32_to_cpu(frame->saddr);
info->saddr = le32_to_cpu(frame->daddr);
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
if (command)
irlap_do_event(self, RECV_TEST_CMD, skb, info);
else
idev = (struct irda_device *) dev->priv;
self = idev->irlap;
- ASSERT(skb->len > 1, return -1;);
+ /* If the net device is down, then IrLAP is gone! */
+ if (!self || self->magic != LAP_MAGIC) {
+ dev_kfree_skb(skb);
+ return -1;
+ }
+
+ /* Check if frame is large enough for parsing */
+ if (skb->len < 2) {
+ ERROR(__FUNCTION__ "(), frame to short!\n");
+ dev_kfree_skb(skb);
+ return -1;
+ }
command = skb->data[0] & CMD_FRAME;
info.caddr = skb->data[0] & CBROADCAST;
control = info.control;
- /* First check if this frame addressed to us */
+ /* First we check if this frame has a valid connection address */
if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
- DEBUG(2, __FUNCTION__ "(), Received frame is not for us!\n");
-
+ DEBUG(0, __FUNCTION__ "(), wrong connection address!\n");
dev_kfree_skb(skb);
return 0;
}
DEBUG( 0, "*** SREJ frame received! ***\n");
break;
default:
- WARNING(__FUNCTION__ "() Unknown S frame %02x received!\n",
+ WARNING(__FUNCTION__
+ "() Unknown S-frame %02x received!\n",
info.control);
break;
}
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 17 20:54:32 1997
- * Modified at: Mon Aug 23 09:30:56 1999
+ * Modified at: Mon Sep 27 11:15:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
*/
void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
{
- int max_seg_size;
int max_header_size;
int lap_header_size;
+ int max_seg_size;
DEBUG(3, __FUNCTION__ "()\n");
ASSERT(skb != NULL, return;);
ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-
+ ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
ASSERT(self->lap != NULL, return;);
- self->qos = *self->lap->qos;
- max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
- DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+ self->qos = *self->lap->qos;
- lap_header_size = irlap_get_header_size(self->lap->irlap);
-
+ max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
+ lap_header_size = irlap_get_header_size(self->lap->irlap);
max_header_size = LMP_HEADER + lap_header_size;
DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
if (self->notify.connect_confirm) {
self->notify.connect_confirm(self->notify.instance, self,
- &self->qos, max_seg_size,
+ &self->qos, max_seg_size,
max_header_size, skb);
}
}
hint.byte[0] |= HINT_EXTENSION;
hint.byte[1] |= HINT_OBEX;
break;
+ case S_TELEPHONY:
+ hint.byte[0] |= HINT_EXTENSION;
+ hint.byte[1] |= HINT_TELEPHONY;
+ break;
case S_ANY:
hint.word = 0xffff;
break;
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Wed Aug 25 14:38:49 1999
+ * Modified at: Tue Sep 21 13:04:33 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
- DEBUG( 4, __FUNCTION__ "()\n");
- ASSERT( self->irlap != NULL, return;);
+ DEBUG(4, __FUNCTION__ "()\n");
+ ASSERT(self->irlap != NULL, return;);
- switch( event) {
+ switch (event) {
case LM_LAP_DISCOVERY_REQUEST:
/* irlmp_next_station_state( LMP_DISCOVER); */
* think that the link is free since IrLMP may then start
* discovery before the connection is properly set up. DB.
*/
- irlmp_next_lap_state( self, LAP_ACTIVE);
+ irlmp_next_lap_state(self, LAP_ACTIVE);
/* Just accept connection TODO, this should be fixed */
- irlap_connect_response( self->irlap, skb);
+ irlap_connect_response(self->irlap, skb);
break;
case LM_LAP_CONNECT_REQUEST:
DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
/* FIXME: need to set users requested QoS */
irlap_connect_request(self->irlap, self->daddr, NULL, 0);
- irlmp_next_lap_state( self, LAP_U_CONNECT);
+ irlmp_next_lap_state(self, LAP_U_CONNECT);
break;
case LM_LAP_DISCONNECT_INDICATION:
- DEBUG( 4, __FUNCTION__
- "(), Error LM_LAP_DISCONNECT_INDICATION\n");
+ DEBUG(4, __FUNCTION__
+ "(), Error LM_LAP_DISCONNECT_INDICATION\n");
irlmp_next_lap_state( self, LAP_STANDBY);
break;
struct lsap_cb *lsap;
struct lsap_cb *lsap_current;
- DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[ event]);
+ DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
- switch( event) {
+ switch (event) {
case LM_LAP_CONNECT_CONFIRM:
/* For all lsap_ce E Associated do LS_Connect_confirm */
- irlmp_next_lap_state( self, LAP_ACTIVE);
+ irlmp_next_lap_state(self, LAP_ACTIVE);
- lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
- while ( lsap != NULL) {
+ lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+ while (lsap != NULL) {
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
case LM_LAP_DISCONNECT_INDICATION:
DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
- irlmp_next_lap_state( self, LAP_STANDBY);
+ irlmp_next_lap_state(self, LAP_STANDBY);
/* Send disconnect event to all LSAPs using this link */
- lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
- while ( lsap != NULL ) {
- ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+ lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
+ while (lsap != NULL ) {
+ ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
lsap_current = lsap;
/* Be sure to stay one item ahead */
- lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
- irlmp_do_lsap_event( lsap_current,
- LM_LAP_DISCONNECT_INDICATION,
- NULL);
+ lsap = (struct lsap_cb *) hashbin_get_next( self->lsaps);
+ irlmp_do_lsap_event(lsap_current,
+ LM_LAP_DISCONNECT_INDICATION,
+ NULL);
}
break;
case LM_LAP_DISCONNECT_REQUEST:
- DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
+ DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
- irlmp_next_lap_state( self, LAP_STANDBY);
+ irlmp_next_lap_state(self, LAP_STANDBY);
/* FIXME */
/* irlap_disconnect_request( self->irlap); */
break;
default:
- DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
+ DEBUG(4, __FUNCTION__ "(), Unknown event\n");
break;
}
}
if (hashbin_get_size(self->lsaps) == 0) {
irlmp_next_lap_state(self, LAP_STANDBY);
irlap_disconnect_request(self->irlap);
- } else
- /* Still not ready, so wait a little bit more */
- irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+ }
break;
case LM_LAP_DISCONNECT_INDICATION:
irlmp_next_lap_state(self, LAP_STANDBY);
irlmp_connect_confirm(self, skb);
break;
case LM_DISCONNECT_INDICATION:
- DEBUG(0, __FUNCTION__ "(), this should never happen!!\n");
+ irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+
+ ASSERT(self->lap != NULL, return -1;);
+ ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+
+ ASSERT(skb != NULL, return -1;);
+ ASSERT(skb->len > 3, return -1;);
+ reason = skb->data[3];
+
+ /* Try to close the LAP connection */
+ DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+ irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+
+ irlmp_disconnect_indication(self, reason, skb);
break;
case LM_LAP_DISCONNECT_INDICATION:
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Dec 15 13:55:39 1997
- * Modified at: Wed Aug 11 08:53:56 1999
+ * Modified at: Mon Sep 20 09:27:25 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
EXPORT_SYMBOL(irda_notify_init);
EXPORT_SYMBOL(irmanager_notify);
EXPORT_SYMBOL(irda_lock);
+#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(proc_irda);
+#endif
EXPORT_SYMBOL(irda_param_insert);
EXPORT_SYMBOL(irda_param_extract);
EXPORT_SYMBOL(irda_param_extract_all);
int __init irda_init(void)
{
printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.3 (Dag Brattli)\n");
-
+
irlmp_init();
irlap_init();
-
+
#ifdef MODULE
irda_device_init(); /* Called by init/main.c when non-modular */
#endif
{
struct irda_event *new;
- DEBUG( 4, __FUNCTION__ "()\n");
-
+ DEBUG(4, __FUNCTION__ "()\n");
+
/* Make sure irmanager is running */
- if ( !irda.in_use) {
+ if (!irda.in_use) {
printk( KERN_ERR "irmanager is not running!\n");
return;
}
if ( new == NULL) {
return;
}
- memset( new, 0, sizeof( struct irda_event));
+ memset(new, 0, sizeof( struct irda_event));
new->event = *event;
/* Queue event */
- enqueue_last( &irda.event_queue, (QUEUE *) new);
+ enqueue_last(&irda.event_queue, (QUEUE *) new);
/* Wake up irmanager sleeping on read */
- wake_up_interruptible( &irda.wait_queue);
+ wake_up_interruptible(&irda.wait_queue);
}
static int irda_open( struct inode * inode, struct file *file)
irda.in_use = TRUE;
MOD_INC_USE_COUNT;
-
+
return 0;
}
struct irda_todo *todo;
int err = 0;
int size = _IOC_SIZE(cmd);
-
- DEBUG( 4, __FUNCTION__ "()\n");
-
+
+ DEBUG(4, __FUNCTION__ "()\n");
+
if ( _IOC_DIR(cmd) & _IOC_READ)
err = verify_area( VERIFY_WRITE, (void *) arg, size);
else if ( _IOC_DIR(cmd) & _IOC_WRITE)
switch( cmd) {
case IRMGR_IOCTNPC:
/* Got process context! */
- DEBUG( 4, __FUNCTION__ "(), got process context!\n");
-
- while (( todo = (struct irda_todo *) dequeue_first(
+ DEBUG(4, __FUNCTION__ "(), got process context!\n");
+
+ while ((todo = (struct irda_todo *) dequeue_first(
&irda.todo_queue)) != NULL)
{
- todo->callback( todo->self, todo->param);
+ todo->callback(todo->self, todo->param);
- kfree( todo);
+ kfree(todo);
}
break;
default:
return -ENOIOCTLCMD;
}
-
+
return 0;
}
-static int irda_close( struct inode *inode, struct file *file)
+static int irda_close(struct inode *inode, struct file *file)
{
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
MOD_DEC_USE_COUNT;
-
+
irda.in_use = FALSE;
return 0;
}
-static ssize_t irda_read( struct file *file, char *buffer, size_t count,
- loff_t *noidea)
+static ssize_t irda_read(struct file *file, char *buffer, size_t count,
+ loff_t *noidea)
{
struct irda_event *event;
unsigned long flags;
int len;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
/* * Go to sleep and wait for event if there is no event to be read! */
save_flags( flags);
* Ensure proper reaction to signals, and screen out
* blocked signals (page 112. linux device drivers)
*/
- if ( signal_pending( current))
+ if (signal_pending( current))
return -ERESTARTSYS;
event = (struct irda_event *) dequeue_first( &irda.event_queue);
return 0;
len = sizeof(struct irmanager_event);
- copy_to_user( buffer, &event->event, len);
+ copy_to_user(buffer, &event->event, len);
/* Finished with event */
- kfree( event);
+ kfree(event);
return len;
}
-static ssize_t irda_write( struct file *file, const char *buffer,
- size_t count, loff_t *noidea)
+static ssize_t irda_write(struct file *file, const char *buffer,
+ size_t count, loff_t *noidea)
{
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG(0, __FUNCTION__ "()\n");
return 0;
}
-static u_int irda_poll( struct file *file, poll_table *wait)
+static u_int irda_poll(struct file *file, poll_table *wait)
{
- DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
+ DEBUG(0, __FUNCTION__ "(), Sorry not implemented yet!\n");
return 0;
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Thu Jul 8 21:25:31 1999
+ * Modified at: Mon Sep 27 12:02:52 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
*
*/
static void irttp_connect_confirm(void *instance, void *sap,
- struct qos_info *qos,
- __u32 max_seg_size, __u8 max_header_size,
- struct sk_buff *skb)
+ struct qos_info *qos, __u32 max_seg_size,
+ __u8 max_header_size, struct sk_buff *skb)
{
struct tsap_cb *self;
int parameters;
ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
ASSERT(skb != NULL, return;);
- self->max_seg_size = max_seg_size;
+ self->max_seg_size = max_seg_size - TTP_HEADER;
self->max_header_size = max_header_size + TTP_HEADER;
/*
DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
self->send_credit, self->avail_credit, self->remote_credit);
- DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
+ DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
if (self->notify.connect_confirm) {
self->notify.connect_confirm(self->notify.instance, self, qos,
- self->tx_max_sdu_size,
+ self->tx_max_sdu_size,
self->max_header_size, skb);
}
}
skb_pull(skb, MIN(skb->len, plen+1));
}
- DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
-
if (self->notify.connect_indication) {
self->notify.connect_indication(self->notify.instance, self,
qos, self->tx_max_sdu_size,
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Sep 9 00:00:26 1997
- * Modified at: Tue Aug 17 10:25:21 1999
+ * Modified at: Wed Sep 1 09:14:55 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
if (get) {
param->pv.i = self->qos_rx.baud_rate.bits;
- DEBUG(0, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);
+ DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);
} else {
/*
* Stations must agree on baud rate, so calculate
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Aug 16 00:59:29 1997
- * Modified at: Sat Jun 26 17:03:22 1999
+ * Modified at: Mon Sep 20 11:32:37 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* IrLAP slot timer has expired
*
*/
-static void irlap_slot_timer_expired( void* data)
+static void irlap_slot_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- DEBUG( 4, "Slot timer expired!\n");
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-
- irlap_do_event( self, SLOT_TIMER_EXPIRED, NULL, NULL);
+ irlap_do_event(self, SLOT_TIMER_EXPIRED, NULL, NULL);
}
/*
* IrLAP query timer has expired
*
*/
-static void irlap_query_timer_expired( void* data)
+static void irlap_query_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- DEBUG( 4, "Query timer expired!\n");
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
- irlap_do_event( self, QUERY_TIMER_EXPIRED, NULL, NULL);
+ irlap_do_event(self, QUERY_TIMER_EXPIRED, NULL, NULL);
}
/*
*
*
*/
-static void irlap_final_timer_expired( void* data)
+static void irlap_final_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- DEBUG( 4, "Final timer expired!\n");
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
- irlap_do_event( self, FINAL_TIMER_EXPIRED, NULL, NULL);
+ irlap_do_event(self, FINAL_TIMER_EXPIRED, NULL, NULL);
}
/*
*
*
*/
-static void irlap_wd_timer_expired( void* data)
+static void irlap_wd_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- DEBUG( 4, "WD timer expired!\n");
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
-
- irlap_do_event( self, WD_TIMER_EXPIRED, NULL, NULL);
+ irlap_do_event(self, WD_TIMER_EXPIRED, NULL, NULL);
}
/*
*
*
*/
-static void irlap_backoff_timer_expired( void* data)
+static void irlap_backoff_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- DEBUG( 0, "Backoff timer expired!\n");
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == LAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LAP_MAGIC, return;);
- irlap_do_event( self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
+ irlap_do_event(self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
}
*
*
*/
-void irda_device_media_busy_expired( void* data)
+void irda_device_media_busy_expired(void* data)
{
- struct irda_device *self = ( struct irda_device *) data;
+ struct irda_device *self = (struct irda_device *) data;
- DEBUG( 4, "Mediabusy timer expired!\n");
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
- irda_device_set_media_busy( self, FALSE);
+ irda_device_set_media_busy(&self->netdev, FALSE);
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Wed Aug 25 13:13:53 1999
+ * Modified at: Mon Sep 20 11:18:44 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Modified at: Fri May 28 3:11 CST 1999
* Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
/* idev->xbofs++; */
break;
case EOF:
- irda_device_set_media_busy( idev, TRUE);
+ irda_device_set_media_busy(&idev->netdev, TRUE);
break;
default:
break;
switch (byte) {
case BOF: /* New frame? */
idev->rx_buff.state = BEGIN_FRAME;
- irda_device_set_media_busy(idev, TRUE);
+ irda_device_set_media_busy(&idev->netdev, TRUE);
break;
case CE:
DEBUG(4, "WARNING: State not defined\n");
switch (byte) {
case BOF: /* New frame? */
idev->rx_buff.state = BEGIN_FRAME;
- irda_device_set_media_busy(idev, TRUE);
+ irda_device_set_media_busy(&idev->netdev, TRUE);
break;
case CE: /* Stuffed char */
idev->rx_buff.state = LINK_ESCAPE;
idev->rx_buff.len);
} else {
/* Wrong CRC, discard frame! */
- irda_device_set_media_busy(idev, TRUE);
+ irda_device_set_media_busy(&idev->netdev, TRUE);
idev->stats.rx_errors++;
idev->stats.rx_crc_errors++;