From de57f159c48c79dcd66a871dc154853c50ac50f3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:27:24 -0500 Subject: [PATCH] Import 2.3.19pre1 --- CREDITS | 183 +++-- Documentation/CodingStyle | 23 + Documentation/networking/README.sb1000 | 340 +++++--- MAINTAINERS | 96 ++- arch/i386/defconfig | 1 + arch/i386/kernel/i8259.c | 2 +- arch/i386/kernel/mtrr.c | 117 ++- arch/i386/kernel/setup.c | 55 +- arch/i386/mm/init.c | 23 +- drivers/atm/ambassador.c | 2 +- drivers/char/bttv.c | 738 +++-------------- drivers/char/bttv.h | 1 + drivers/char/buz.c | 4 +- drivers/char/cyclades.c | 1038 ++++++++++++------------ drivers/char/pcxx.c | 5 +- drivers/char/radio-aimslab.c | 47 +- drivers/char/radio-aztech.c | 33 +- drivers/char/radio-gemtek.c | 38 +- drivers/char/radio-miropcm20.c | 16 +- drivers/char/radio-rtrack2.c | 17 +- drivers/char/radio-sf16fmi.c | 15 + drivers/char/radio-terratec.c | 10 + drivers/char/radio-trust.c | 354 ++++++++ drivers/char/radio-zoltrix.c | 29 +- drivers/char/random.c | 14 +- drivers/char/saa5249.c | 10 +- drivers/net/3c527.c | 111 ++- drivers/net/defxx.c | 2 +- drivers/net/e2100.c | 2 +- drivers/net/irda/Config.in | 12 +- drivers/net/irda/actisys.c | 6 +- drivers/net/irda/irport.c | 13 +- drivers/net/irda/irtty.c | 20 +- drivers/net/irda/pc87108.c | 2 +- drivers/net/irda/smc-ircc.c | 22 +- drivers/net/irda/toshoboe.c | 2 +- drivers/net/irda/uircc.c | 2 +- drivers/net/pcmcia/pcnet_cs.c | 2 +- drivers/net/pcnet32.c | 58 +- drivers/net/sb1000.c | 3 +- drivers/net/slip.c | 3 + drivers/net/tlan.c | 13 +- drivers/pci/quirks.c | 5 +- drivers/scsi/a2091.c | 2 +- drivers/scsi/eata.c | 282 +++---- drivers/scsi/eata.h | 21 +- drivers/scsi/ips.c | 8 +- drivers/scsi/ips.h | 2 +- drivers/scsi/wd33c93.h | 3 + drivers/sound/opl3sa.c | 2 +- drivers/sound/sb_audio.c | 8 + drivers/sound/sb_card.c | 2 +- drivers/sound/sb_common.c | 10 + fs/nfs/nfsroot.c | 3 +- fs/partitions/acorn.c | 18 + fs/partitions/msdos.c | 78 +- fs/proc/fd.c | 1 + include/asm-i386/e820.h | 4 + include/linux/cyclades.h | 29 +- include/linux/irda.h | 12 +- include/linux/videodev.h | 3 +- include/net/irda/ircomm_tty.h | 6 +- include/net/irda/ircomm_tty_attach.h | 8 +- include/net/irda/irda.h | 6 +- include/net/irda/irda_device.h | 18 +- include/net/irda/irlap.h | 7 +- include/net/irda/irlpt_cli.h | 49 -- include/net/irda/irlpt_cli_fsm.h | 36 - include/net/irda/irlpt_common.h | 190 ----- include/net/irda/irlpt_server.h | 42 - include/net/irda/irlpt_server_fsm.h | 35 - include/net/irda/irttp.h | 7 +- include/net/irda/irvtd.h | 95 --- include/net/irda/toshoboe.h | 8 + net/irda/Config.in | 42 +- net/irda/af_irda.c | 89 +- net/irda/compressors/Config.in | 14 +- net/irda/ircomm/Config.in | 2 +- net/irda/ircomm/Makefile | 2 +- net/irda/ircomm/ircomm_event.c | 9 +- net/irda/ircomm/ircomm_param.c | 80 +- net/irda/ircomm/ircomm_ttp.c | 8 +- net/irda/ircomm/ircomm_tty.c | 318 ++++---- net/irda/ircomm/ircomm_tty_attach.c | 146 ++-- net/irda/ircomm/ircomm_tty_ioctl.c | 28 +- net/irda/irda_device.c | 82 +- net/irda/irlan/Config.in | 2 +- net/irda/irlan/irlan_common.c | 6 +- net/irda/irlap.c | 33 +- net/irda/irlap_event.c | 154 ++-- net/irda/irlap_frame.c | 291 +++---- net/irda/irlmp.c | 21 +- net/irda/irlmp_event.c | 69 +- net/irda/irmod.c | 68 +- net/irda/irttp.c | 15 +- net/irda/qos.c | 4 +- net/irda/timer.c | 67 +- net/irda/wrapper.c | 10 +- 98 files changed, 3024 insertions(+), 3020 deletions(-) create mode 100644 drivers/char/radio-trust.c delete mode 100644 include/net/irda/irlpt_cli.h delete mode 100644 include/net/irda/irlpt_cli_fsm.h delete mode 100644 include/net/irda/irlpt_common.h delete mode 100644 include/net/irda/irlpt_server.h delete mode 100644 include/net/irda/irlpt_server_fsm.h delete mode 100644 include/net/irda/irvtd.h diff --git a/CREDITS b/CREDITS index dcc37e6986e0..6fb36135aef8 100644 --- a/CREDITS +++ b/CREDITS @@ -157,12 +157,6 @@ S: 633 South 550 East 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 @@ -174,6 +168,12 @@ S: ul. Koscielna 12a 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 @@ -482,11 +482,11 @@ S: Warrendale, Pennsylvania 15086 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 @@ -794,6 +794,10 @@ S: 77 Clarence Mews 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 @@ -801,10 +805,6 @@ S: Gen Stedmanstraat 212 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 @@ -858,6 +858,14 @@ S: Danckelmannstr. 48 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 @@ -1018,19 +1026,6 @@ S: Gelligaer, Hengoed, 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 @@ -1154,6 +1149,10 @@ S: Markham, Ontario 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/ @@ -1162,6 +1161,15 @@ S: Post Office Box 49458 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 @@ -1253,10 +1261,14 @@ D: Busmaster driver for HP 10/100 Mbit Network Adapters 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 @@ -1267,15 +1279,6 @@ S: 33 Ridgefield Cr 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 @@ -1283,6 +1286,11 @@ S: 8786 Niwot Road 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 @@ -1295,10 +1303,6 @@ S: Puistokaari 1 E 18 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 @@ -1343,6 +1347,10 @@ S: PO BOX 220, HFX. CENTRAL 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/ @@ -1399,11 +1407,13 @@ N: Arnaldo Carvalho de Melo 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 @@ -1500,13 +1510,6 @@ S: 30 White Tail Lane 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. @@ -1514,6 +1517,13 @@ S: Dagaliveien 31e 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 @@ -1628,6 +1638,13 @@ S: Demonstratsii 8-382 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/ @@ -1818,13 +1835,6 @@ S: Dag Hammerskjolds v. 3E 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 @@ -1834,6 +1844,13 @@ N: Michael Schmitz 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/ @@ -1954,13 +1971,21 @@ S: Willowdale, Ontario 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 @@ -1997,9 +2022,9 @@ W: http://lie-br.conectiva.com.br/~marcelo/ 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 @@ -2036,6 +2061,17 @@ D: Linux-Workshop K 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 @@ -2051,17 +2087,6 @@ S: 1 Amherst Street 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 @@ -2193,8 +2218,14 @@ D: The Linux Support Team Erlangen 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 diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index edba246996be..e0915bd2c350 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -210,3 +210,26 @@ options "-kr -i8" (stands for "K&R, 8 character indents"). "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). diff --git a/Documentation/networking/README.sb1000 b/Documentation/networking/README.sb1000 index 025a245f242c..37c39a0c86f8 100644 --- a/Documentation/networking/README.sb1000 +++ b/Documentation/networking/README.sb1000 @@ -1,133 +1,207 @@ -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 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)', 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)', (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 . 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 diff --git a/MAINTAINERS b/MAINTAINERS index 4321f92cb7b6..6532b058ed92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29,7 +29,7 @@ trivial patch so apply some common sense. 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 @@ -63,7 +63,7 @@ S: Status, one of the following: 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 @@ -131,12 +131,6 @@ M: Jay.Schulist@spacs.k12.wi.us 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 @@ -150,6 +144,12 @@ L: arm-linux@tardis.ed.ac.uk 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 @@ -182,6 +182,12 @@ M: jgarzik@pobox.com L: linux-fbdev@vuser.vu.union.edu S: Maintained +COMPAQ SMART2 RAID DRIVER +P: Charles White +M: Charles White +L: compaqandlinux@yps.org +S: Maintained + COMPUTONE INTELLIPORT MULTIPORT CARD P: Doug McNash P: Michael H. Warfield @@ -287,12 +293,6 @@ M: mike@i-Connect.Net L: linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu S: Maintained -COMPAQ SMART2 RAID DRIVER -P: Charles White -M: Charles White -L: compaqandlinux@yps.org -S: Maintained - EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio M: dario@milano.europe.dg.com @@ -369,7 +369,7 @@ S: Maintained HFS FILESYSTEM P: Adrian Sun -M: asun@u.washington.edu +M: asun@cobaltnet.com L: linux-kernel@vger.rutgers.edu S: Maintained @@ -390,17 +390,23 @@ P: Jaroslav Kysela 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 @@ -415,7 +421,7 @@ L: linux-kernel@vger.rutgers.edu 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 @@ -524,8 +530,9 @@ S: Maintained 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 @@ -571,7 +578,7 @@ L: netfilter@lists.samba.org S: Supported NETROM NETWORK LAYER -P: Tomi Manninen +P: Tomi Manninen M: Tomi.Manninen@hut.fi L: linux-hams@vger.rutgers.edu S: Maintained @@ -627,16 +634,6 @@ L: linux-tr@emissary.aus-etc.com 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 @@ -668,17 +665,23 @@ P: Jens Maurer 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 @@ -701,6 +704,12 @@ M: longyear@pobox.com 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 @@ -725,7 +734,7 @@ M: emoenke@gwdg.de 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 @@ -776,7 +785,7 @@ L: linux-net@vger.rutgers.edu S: Maintained SOUND -P: Alan Cox +P: Alan Cox M: alan@redhat.com S: Supported @@ -860,7 +869,7 @@ M: mnalis@jagor.srce.hr 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 @@ -888,6 +897,11 @@ 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 diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 58e116ce9861..9d9f99b55ecf 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -285,6 +285,7 @@ CONFIG_EEXPRESS_PRO100=y # PCMCIA network devices # # CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_3C589 is not set CONFIG_PCMCIA_RAYCS=y # diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index efd8e8bc0412..ce408284840a 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -385,7 +385,7 @@ void __init init_IRQ(void) #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 */ diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index 7a4c37236877..f76c68f594d2 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -201,6 +201,28 @@ 19990512 Richard Gooch Minor cleanups. v1.35 + 19990707 Zoltan Boszormenyi + 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 + 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 + 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 + Double check for Intel in mtrr_add()'s big switch() because + that revision check is only valid for Intel CPUs. + 19990819 Alan Cox + Tested Zoltan's changes on a pre production Athlon - 100% + success. */ #include #include @@ -309,6 +331,7 @@ struct set_mtrr_context 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) @@ -321,6 +344,8 @@ 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;*/ @@ -344,6 +369,7 @@ static void set_mtrr_prepare (struct set_mtrr_context *ctxt) 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); @@ -365,6 +391,8 @@ static void set_mtrr_done (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: __restore_flags (ctxt->flags); return; @@ -376,6 +404,7 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt) /* 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; @@ -406,6 +435,9 @@ static unsigned int get_num_var_ranges (void) 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); @@ -416,9 +448,6 @@ static unsigned int get_num_var_ranges (void) /* and Centaur has 8 MCR's */ return 8; /*break;*/ - case X86_VENDOR_AMD: - return 2; - /*break;*/ } return 0; } /* End Function get_num_var_ranges */ @@ -430,12 +459,14 @@ static int have_wrcomb (void) 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;*/ @@ -1030,6 +1061,7 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size) 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 */ @@ -1062,13 +1094,30 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type, 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: @@ -1105,18 +1154,6 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type, 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;*/ @@ -1221,6 +1258,15 @@ int mtrr_del (int reg, unsigned long base, unsigned long size) 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) { @@ -1585,22 +1631,22 @@ static void __init cyrix_arr_init(void) 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. */ @@ -1660,6 +1706,12 @@ static void __init mtrr_setup(void) 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; @@ -1669,10 +1721,6 @@ static void __init mtrr_setup(void) 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; @@ -1691,6 +1739,8 @@ void __init mtrr_init_boot_cpu(void) 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; @@ -1727,6 +1777,9 @@ void __init mtrr_init_secondary_cpu(void) 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; @@ -1752,6 +1805,8 @@ int __init mtrr_init(void) # 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); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 31a9c847faad..88ba3feeb9a2 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -61,6 +61,7 @@ #include #include #include +#include /* * Machine setup.. @@ -401,18 +402,49 @@ void __init add_memory_region(unsigned long start, 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, @@ -422,8 +454,8 @@ void __init setup_memory_region(void) 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 */ @@ -503,7 +535,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne */ 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 == '@') @@ -512,7 +544,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne 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++); @@ -531,7 +563,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne 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) @@ -856,6 +888,15 @@ static void __init cyrix_model(struct cpuinfo_x86 *c) 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 */ @@ -881,8 +922,8 @@ static void __init cyrix_model(struct cpuinfo_x86 *c) dir0_msn = 0; p = Cx486S_name[0]; break; - break; } + break; default: /* unknown (shouldn't happen, we know everyone ;-) */ dir0_msn = 7; diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 4f55a89f8969..05684997fa92 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -414,25 +414,23 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem) 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) @@ -446,14 +444,11 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem) * 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); } } diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 5664f0ea21ee..7c434938fc96 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -674,7 +674,7 @@ static inline int tx_take (amb_dev * dev) { return 0; } else { - spin_unlock_irqrestore (&dev->lock, flags); + spin_unlock_irqrestore (&txq->lock, flags); return -1; } } diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index e1d776efda14..a177e7de6217 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -29,9 +29,7 @@ #include #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include -#endif #include #include #include @@ -44,36 +42,8 @@ #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include #include -#else -#include -#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 #include @@ -83,19 +53,10 @@ copy_from_user(void *to, const void *from, unsigned long n) #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 */ @@ -243,6 +204,12 @@ static void rvfree(void * mem, unsigned long size) } } +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"); /* @@ -403,7 +370,7 @@ static void writeee(struct i2c_bus *bus, unsigned char *eedata) } } -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; @@ -422,7 +389,7 @@ void attach_inform(struct i2c_bus *bus, int id) } } -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; @@ -563,7 +530,7 @@ static struct tvcard tvcards[] = /* 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 */ @@ -1591,20 +1558,18 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in 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; ifbuffer=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; @@ -1612,14 +1577,20 @@ static int bttv_open(struct video_device *dev, int flags) 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; @@ -1649,6 +1620,7 @@ static void bttv_close(struct video_device *dev) if(btv->fbuffer) rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF); btv->fbuffer=0; + up(&btv->lock); MOD_DEC_USE_COUNT; } @@ -1769,14 +1741,16 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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: @@ -1821,7 +1795,9 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) &&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: @@ -1848,6 +1824,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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 */ @@ -1865,6 +1842,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if (fmtbppx2[format&0x0f]/2 == btv->win.bpp) btv->win.color_fmt = format; } + up(&btv->lock); return 0; } case VIDIOCSWIN: @@ -1878,7 +1856,9 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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) @@ -1888,6 +1868,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -1902,6 +1884,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) bt848_cap(btv,0); bt848_set_winsize(btv); + + up(&btv->lock); /* * Do any clips. @@ -1925,11 +1909,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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: @@ -1953,17 +1939,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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: @@ -1995,6 +1981,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -2006,6 +1993,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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: @@ -2072,13 +2060,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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); @@ -2142,6 +2134,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) MSP_SET_STEREO,&(v.mode)); } btv->audio_dev=v; + up(&btv->lock); return 0; } @@ -2168,26 +2161,21 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -2200,28 +2188,29 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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: @@ -2303,9 +2292,8 @@ static int bttv_init_done(struct video_device *dev) * 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; @@ -2329,6 +2317,17 @@ static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long si 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", @@ -2394,7 +2393,6 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, return count; } -#if LINUX_VERSION_CODE >= 0x020100 static unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -2408,15 +2406,16 @@ static unsigned int vbi_poll(struct video_device *dev, struct file *file, 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; @@ -2425,9 +2424,11 @@ static int vbi_open(struct video_device *dev, int flags) 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; } @@ -2463,25 +2464,34 @@ static int radio_open(struct video_device *dev, int flags) { 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; } @@ -2571,233 +2581,6 @@ static struct video_device radio_template= }; -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; ivendor == 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> 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> 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= 0x020100 - static void handle_chipset(void) { struct pci_dev *dev = NULL; @@ -2839,110 +2620,8 @@ static void handle_chipset(void) 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) { @@ -2956,14 +2635,14 @@ 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) @@ -3093,16 +2772,16 @@ static void idcard(int i) 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); @@ -3213,6 +2892,8 @@ static int init_bt848(int i) struct bttv *btv = &bttvs[i]; btv->user=0; + + init_MUTEX(&btv->lock); /* reset the bt848 */ btwrite(0, BT848_SRESET); @@ -3521,7 +3202,6 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) * 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; @@ -3550,22 +3230,6 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) 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); @@ -3660,170 +3324,6 @@ static int find_bt848(void) 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) { @@ -3848,17 +3348,11 @@ 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) diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index 847336116cb9..83c9f1e8feae 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -84,6 +84,7 @@ struct bttv 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]; diff --git a/drivers/char/buz.c b/drivers/char/buz.c index 509f18b134b6..b535ac05e181 100644 --- a/drivers/char/buz.c +++ b/drivers/char/buz.c @@ -374,13 +374,13 @@ static int i2c_getdataline(struct i2c_bus *bus) 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)); diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 94e7e2628058..d0bcd2a07ba4 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1,7 +1,7 @@ #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 @@ -9,9 +9,8 @@ static char rcsid[] = * 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. @@ -31,6 +30,16 @@ static char rcsid[] = * 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; @@ -655,7 +664,8 @@ static char rcsid[] = #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); @@ -829,6 +839,7 @@ static int cy_chip_offset [] = 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 */ @@ -840,7 +851,7 @@ static unsigned short cy_pci_dev_id[] = { 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 *); @@ -968,6 +979,9 @@ do_softint(void *private_) 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){ @@ -1016,7 +1030,8 @@ cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index) } /* 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; @@ -1151,7 +1166,19 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) j = (cy_readb(base_addr+(CyRIVR<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){ @@ -1159,9 +1186,10 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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<icount.rx++; if (info->flags & ASYNC_SAK){ do_SAK(tty); } @@ -1170,17 +1198,20 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) TTY_FRAME; *tty->flip.char_buf_ptr++ = cy_readb(base_addr+(CyRDSR<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<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. @@ -1192,6 +1223,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) TTY_NORMAL; *tty->flip.char_buf_ptr++ = cy_readb(base_addr+(CyRDSR<icount.rx++; } info->idle_stats.overruns++; /* These two conditions may imply */ @@ -1201,15 +1233,18 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) }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 */ @@ -1233,6 +1268,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) data = cy_readb(base_addr+(CyRDSR<flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.char_buf_ptr++ = data; + info->icount.rx++; #ifdef CY_16Y_HACK udelay(10L); #endif @@ -1286,11 +1322,11 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* 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<icount.tx++; info->x_char = 0; } @@ -1351,6 +1387,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); cy_writeb((u_long)base_addr+(CyTDR<icount.tx++; }else{ if(char_count > 1){ info->xmit_cnt--; @@ -1359,6 +1396,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) cy_writeb((u_long)base_addr+(CyTDR<icount.tx++; char_count--; }else{ } @@ -1397,6 +1435,16 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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){ @@ -1438,9 +1486,9 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) } } } - if(mdm_status & CyDSR){ + if(mdm_change & CyDSR){ } - if(mdm_status & CyRI){ + if(mdm_change & CyRI){ } } /* end of service */ @@ -1497,7 +1545,6 @@ cyz_fetch_msg( struct cyclades_card *cinfo, return 0; } /* cyz_fetch_msg */ - static int cyz_issue_cmd( struct cyclades_card *cinfo, uclong channel, ucchar cmd, uclong param) @@ -1532,12 +1579,181 @@ cyz_issue_cmd( struct cyclades_card *cinfo, 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; @@ -1548,264 +1764,135 @@ cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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 */ @@ -1815,272 +1902,43 @@ cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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; @@ -2220,20 +2078,20 @@ startup(struct cyclades_port * info) 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 */ @@ -2353,6 +2211,9 @@ shutdown(struct cyclades_port * info) 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; @@ -2419,7 +2280,7 @@ shutdown(struct cyclades_port * info) 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"); @@ -2707,6 +2568,10 @@ cy_open(struct tty_struct *tty, struct file * filp) 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){ @@ -2791,7 +2656,8 @@ cy_open(struct tty_struct *tty, struct file * filp) /* * 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; @@ -2873,9 +2739,9 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) * 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 @@ -2979,7 +2845,7 @@ cy_close(struct tty_struct * tty, struct file * filp) 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); @@ -2994,6 +2860,17 @@ cy_close(struct tty_struct * tty, struct file * filp) 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; @@ -3273,6 +3150,20 @@ set_line_char(struct cyclades_port * info) 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; @@ -3282,7 +3173,11 @@ set_line_char(struct cyclades_port * info) 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; } @@ -3483,6 +3378,7 @@ set_line_char(struct cyclades_port * info) 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 *) @@ -3498,7 +3394,11 @@ set_line_char(struct cyclades_port * info) 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; } @@ -3540,14 +3440,24 @@ set_line_char(struct cyclades_port * info) /* 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){ @@ -3562,14 +3472,6 @@ set_line_char(struct cyclades_port * info) 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); @@ -3595,20 +3497,6 @@ set_line_char(struct cyclades_port * info) } } - /* - * 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 */ @@ -3749,7 +3637,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value) } } - return cy_put_user(result,(unsigned int *) value); + return cy_put_user(result, value); } /* get_modem_info */ @@ -4208,7 +4096,10 @@ cy_ioctl(struct tty_struct *tty, struct file * file, 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; @@ -4264,6 +4155,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, if (copy_to_user((void *)arg, (void *)&cy_card[info->card], sizeof (struct cyclades_card))) { ret_val = -EFAULT; + break; } ret_val = 0; break; @@ -4300,6 +4192,77 @@ cy_ioctl(struct tty_struct *tty, struct file * file, 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; } @@ -4328,7 +4291,8 @@ cy_set_termios(struct tty_struct *tty, struct termios * old_termios) #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); @@ -4819,7 +4783,8 @@ cy_detect_isa(void) } /* 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); @@ -4851,6 +4816,7 @@ cy_detect_pci(void) 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); @@ -4872,8 +4838,8 @@ cy_detect_pci(void) /* 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; @@ -4892,7 +4858,7 @@ cy_detect_pci(void) 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__) @@ -5020,11 +4986,14 @@ cy_detect_pci(void) 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 @@ -5034,12 +5003,11 @@ cy_detect_pci(void) 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__) @@ -5053,6 +5021,7 @@ cy_detect_pci(void) } else { Ze_addr0[ZeIndex] = cy_pci_addr0; Ze_addr2[ZeIndex] = cy_pci_addr2; + Ze_irq[ZeIndex] = cy_pci_irq; ZeIndex++; } i--; @@ -5154,11 +5123,6 @@ cy_detect_pci(void) 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; } } @@ -5166,9 +5130,11 @@ cy_detect_pci(void) 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 *) @@ -5241,11 +5207,6 @@ cy_detect_pci(void) 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) { @@ -5501,6 +5462,11 @@ cy_init(void) 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; @@ -5519,6 +5485,7 @@ cy_init(void) 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; @@ -5552,6 +5519,11 @@ cy_init(void) 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]<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 = @@ -5650,13 +5623,16 @@ cleanup_module(void) 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) { diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index ad5a4270ebf1..36db3299d5a3 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -79,6 +79,7 @@ #include #include #include +#include #define VERSION "1.6.1" @@ -1588,8 +1589,8 @@ load_fep: 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; } diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c index fc3101f34730..ee986b3353c4 100644 --- a/drivers/char/radio-aimslab.c +++ b/drivers/char/radio-aimslab.c @@ -35,6 +35,7 @@ #include /* copy to/from user */ #include /* kernel radio structs */ #include /* CONFIG_RADIO_RTRACK_PORT */ +#include /* Lock for the I/O */ #ifndef CONFIG_RADIO_RTRACK_PORT #define CONFIG_RADIO_RTRACK_PORT -1 @@ -42,6 +43,7 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int users = 0; +static struct semaphore lock; struct rt_device { @@ -86,19 +88,23 @@ static void rt_incvol(void) 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; } @@ -107,6 +113,7 @@ static int rt_setvol(struct rt_device *dev, int vol) 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; } @@ -119,7 +126,7 @@ static int rt_setvol(struct rt_device *dev, int vol) rt_decvol(); dev->curvol = vol; - + up(&lock); return 0; } @@ -165,6 +172,8 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) 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 */ @@ -191,11 +200,13 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) 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; @@ -324,8 +335,14 @@ static struct video_device rtrack_radio= 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); @@ -340,6 +357,10 @@ int __init rtrack_init(struct video_init *v) 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 */ @@ -351,8 +372,6 @@ int __init rtrack_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("M.Kirkwood"); MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); MODULE_PARM(io, "i"); @@ -360,20 +379,12 @@ MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); 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); + diff --git a/drivers/char/radio-aztech.c b/drivers/char/radio-aztech.c index 1c26bba933d1..2fb8714adf2f 100644 --- a/drivers/char/radio-aztech.c +++ b/drivers/char/radio-aztech.c @@ -42,6 +42,7 @@ static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_wait_time = 1000; static int users = 0; +static struct semaphore lock; struct az_device { @@ -86,7 +87,9 @@ static void send_1_byte (struct az_device *dev) static int az_setvol(struct az_device *dev, int vol) { + down(&lock); outb (volconvert(vol), io); + up(&lock); return 0; } @@ -119,6 +122,8 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) 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) */ @@ -146,6 +151,8 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) udelay (radio_wait_time); outb_p(128+64+volconvert(dev->curvol), io); + + up(&lock); return 0; } @@ -279,14 +286,21 @@ static struct video_device aztech_radio= 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) @@ -299,8 +313,6 @@ int __init aztech_init(struct video_init *v) 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"); @@ -308,20 +320,11 @@ MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); 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); diff --git a/drivers/char/radio-gemtek.c b/drivers/char/radio-gemtek.c index 9cee2342e3fd..523ac09558c5 100644 --- a/drivers/char/radio-gemtek.c +++ b/drivers/char/radio-gemtek.c @@ -23,6 +23,7 @@ #include /* copy to/from user */ #include /* kernel radio structs */ #include /* CONFIG_RADIO_GEMTEK_PORT */ +#include #ifndef CONFIG_RADIO_GEMTEK_PORT #define CONFIG_RADIO_GEMTEK_PORT -1 @@ -30,6 +31,7 @@ static int io = CONFIG_RADIO_GEMTEK_PORT; static int users = 0; +static spinlock_t lock; struct gemtek_device { @@ -48,7 +50,9 @@ static void gemtek_mute(struct gemtek_device *dev) { if(dev->muted) return; + spin_lock(&lock); outb(0x10, io); + spin_unlock(&lock); dev->muted = 1; } @@ -56,7 +60,9 @@ static void gemtek_unmute(struct gemtek_device *dev) { if(dev->muted == 0) return; + spin_lock(&lock); outb(0x20, io); + spin_unlock(&lock); dev->muted = 0; } @@ -87,6 +93,8 @@ static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) freq *= 7825; freq /= 100000; + spin_lock(&lock); + /* 2 start bits */ outb_p(0x03, io); udelay(5); @@ -114,13 +122,17 @@ static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) 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 */ @@ -250,8 +262,14 @@ static struct video_device gemtek_radio= 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); @@ -266,6 +284,7 @@ int __init gemtek_init(struct video_init *v) 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); @@ -277,8 +296,6 @@ int __init gemtek_init(struct video_init *v) return 0; } -#ifdef MODULE - MODULE_AUTHOR("Jonas Munsin"); MODULE_DESCRIPTION("A driver for the GemTek Radio Card"); MODULE_PARM(io, "i"); @@ -286,23 +303,14 @@ MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x3 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: diff --git a/drivers/char/radio-miropcm20.c b/drivers/char/radio-miropcm20.c index 66314f72faa1..04beea2d540e 100644 --- a/drivers/char/radio-miropcm20.c +++ b/drivers/char/radio-miropcm20.c @@ -205,7 +205,7 @@ static struct video_device pcm20_radio= NULL }; -int __init pcm20_init(struct video_init *v) +static int __init pcm20_init(void) { pcm20_radio.priv=&pcm20_unit; @@ -224,22 +224,16 @@ int __init pcm20_init(struct video_init *v) 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); + diff --git a/drivers/char/radio-rtrack2.c b/drivers/char/radio-rtrack2.c index 7370f3a61600..8876d789d7be 100644 --- a/drivers/char/radio-rtrack2.c +++ b/drivers/char/radio-rtrack2.c @@ -16,6 +16,7 @@ #include /* copy to/from user */ #include /* kernel radio structs */ #include /* CONFIG_RADIO_RTRACK2_PORT */ +#include #ifndef CONFIG_RADIO_RTRACK2_PORT #define CONFIG_RADIO_RTRACK2_PORT -1 @@ -23,6 +24,7 @@ static int io = CONFIG_RADIO_RTRACK2_PORT; static int users = 0; +static spinlock_t lock; struct rt_device { @@ -38,7 +40,9 @@ static void rt_mute(struct rt_device *dev) { if(dev->muted) return; + spin_lock(&lock); outb(1, io); + spin_unlock(&lock); dev->muted = 1; } @@ -46,7 +50,9 @@ static void rt_unmute(struct rt_device *dev) { if(dev->muted == 0) return; + spin_lock(&lock); outb(0, io); + spin_unlock(&lock); dev->muted = 0; } @@ -69,6 +75,8 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) int i; freq = freq / 200 + 856; + + spin_lock(&lock); outb_p(0xc8, io); outb_p(0xc9, io); @@ -85,11 +93,13 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) 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; @@ -227,7 +237,8 @@ int __init rtrack2_init(struct video_init *v) } rtrack2_radio.priv=&rtrack2_unit; - + + spin_lock_init(&lock); if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1) return -EINVAL; diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c index c659cc7ba29e..ef73f2d77c97 100644 --- a/drivers/char/radio-sf16fmi.c +++ b/drivers/char/radio-sf16fmi.c @@ -22,6 +22,7 @@ #include /* copy to/from user */ #include /* kernel radio structs */ #include /* CONFIG_RADIO_SF16MI_PORT */ +#include struct fmi_device { @@ -37,6 +38,7 @@ 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), @@ -67,12 +69,16 @@ static void outbits(int bits, unsigned int data, int port) 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) @@ -81,6 +87,8 @@ 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++) @@ -93,6 +101,8 @@ static inline int fmi_setfreq(struct fmi_device *dev) current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ/7); */ + + up(&lock); if (dev->curvol) fmi_unmute(myport); return 0; } @@ -104,6 +114,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev) int myport = dev->port; int i; + down(&lock); val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ outb(val, myport); outb(val | 0x10, myport); @@ -119,6 +130,8 @@ static inline int fmi_getsigstr(struct fmi_device *dev) */ res = (int)inb(myport+1); outb(val, myport); + + up(&lock); return (res & 2) ? 0 : 0xFFFF; } @@ -290,6 +303,8 @@ int __init fmi_init(struct video_init *v) 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; diff --git a/drivers/char/radio-terratec.c b/drivers/char/radio-terratec.c index 34638c5d5def..9fb119c30642 100644 --- a/drivers/char/radio-terratec.c +++ b/drivers/char/radio-terratec.c @@ -31,6 +31,7 @@ #include /* copy to/from user */ #include /* kernel radio structs */ #include /* CONFIG_RADIO_TERRATEC_PORT */ +#include #ifndef CONFIG_RADIO_TERRATEC_PORT #define CONFIG_RADIO_TERRATEC_PORT 0x590 @@ -50,6 +51,7 @@ static int io = CONFIG_RADIO_TERRATEC_PORT; static int users = 0; +static spinlock_t lock; struct tt_device { @@ -66,12 +68,14 @@ static void cardWriteVol(int volume) { 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); } @@ -148,6 +152,8 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1) temp = temp/2; } + spin_lock(&lock); + for (i=24;i>-1;i--) /* bit shift the values to the radiocard */ { if (buffer[i]==1) @@ -163,6 +169,8 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1) } } outb(0x00, BASEPORT); + + spin_unlock(&lock); return 0; } @@ -309,6 +317,8 @@ int __init terratec_init(struct video_init *v) terratec_radio.priv=&terratec_unit; + spin_lock_init(&lock); + if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1) return -EINVAL; diff --git a/drivers/char/radio-trust.c b/drivers/char/radio-trust.c new file mode 100644 index 000000000000..15dee607ae79 --- /dev/null +++ b/drivers/char/radio-trust.c @@ -0,0 +1,354 @@ +/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 + * by Eric Lammerts + * + * Based on radio-aztech.c. Original notes: + * + * Adapted to support the Video for Linux API by + * Russell Kroll . 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 +#include +#include +#include +#include +#include +#include +#include /* 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); diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c index f0d8e37c7a95..a11de7ba8951 100644 --- a/drivers/char/radio-zoltrix.c +++ b/drivers/char/radio-zoltrix.c @@ -47,6 +47,7 @@ struct zol_device { unsigned long curfreq; int muted; unsigned int stereo; + struct semaphore lock; }; @@ -64,26 +65,30 @@ static int zol_setvol(struct zol_device *dev, int vol) 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) @@ -107,6 +112,8 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) bitmask = 0xc480402c10080000ull; i = 45; + down(&dev->lock); + outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ @@ -141,14 +148,21 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) 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; } @@ -158,6 +172,7 @@ int zol_getsigstr(struct zol_device *dev) { int a, b; + down(&dev->lock); outb(0x00, io); /* This stuff I found to do nothing */ outb(dev->curvol, io); sleep_delay(); @@ -167,6 +182,8 @@ int zol_getsigstr(struct zol_device *dev) sleep_delay(); b = inb(io); + up(&dev->lock); + if (a != b) return (0); @@ -180,6 +197,8 @@ int zol_is_stereo (struct zol_device *dev) { int x1, x2; + down(&dev->lock); + outb(0x00, io); outb(dev->curvol, io); sleep_delay(); @@ -189,6 +208,8 @@ int zol_is_stereo (struct zol_device *dev) sleep_delay(); x2 = inb(io); + up(&dev->lock); + if ((x1 == x2) && (x1 == 0xcf)) return 1; return 0; @@ -351,6 +372,8 @@ int __init zoltrix_init(struct video_init *v) 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 */ diff --git a/drivers/char/random.c b/drivers/char/random.c index b0e3c2357fce..d97304a1369c 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1,7 +1,7 @@ /* * 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. @@ -1329,8 +1329,14 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf, */ 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"); } /********************************************************************* @@ -2012,7 +2018,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, 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; } diff --git a/drivers/char/saa5249.c b/drivers/char/saa5249.c index 2e93553c55af..5ab107a0f23c 100644 --- a/drivers/char/saa5249.c +++ b/drivers/char/saa5249.c @@ -79,9 +79,9 @@ static const int disp_modes[8][3] = -#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 */ @@ -107,9 +107,9 @@ struct saa5249_device #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) */ diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 5881bc5fbfb1..ddb6d8bf8c02 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1,3 +1,4 @@ + /* 3c527.c: 3Com Etherlink/MC32 driver for Linux * * (c) Copyright 1998 Red Hat Software Inc @@ -15,7 +16,7 @@ */ 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 @@ -108,6 +109,7 @@ struct mc32_local 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. */ @@ -138,6 +140,8 @@ static void mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs); 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. @@ -445,16 +449,56 @@ static void mc32_ring_poll(struct net_device *dev) /* * 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; @@ -472,18 +516,20 @@ static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len) 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 */ @@ -1063,20 +1109,18 @@ static struct net_device_stats *mc32_get_stats(struct net_device *dev) * 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) { @@ -1087,24 +1131,47 @@ static void mc32_set_multicast_list(struct net_device *dev) int i; filt = 0; - block[1]=0; - block[0]=dev->mc_count; - bp=block+2; - for(i=0;imc_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;imc_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 diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index fbfd71d93369..be62ef741d80 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -3295,7 +3295,7 @@ int dfx_xmt_queue_pkt( * 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); /* diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index ca0a2144fbdf..4ea0e6b71b49 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -75,7 +75,7 @@ extern inline void mem_on(short port, volatile char *mem_base, { /* 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); } diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in index 8a6f50a36fdf..5be68c382353 100644 --- a/drivers/net/irda/Config.in +++ b/drivers/net/irda/Config.in @@ -15,12 +15,12 @@ dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA 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 diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c index 6bab577f5195..f83fce38c5f4 100644 --- a/drivers/net/irda/actisys.c +++ b/drivers/net/irda/actisys.c @@ -135,14 +135,14 @@ static void actisys_change_speed(struct irda_device *idev, __u32 speed) /* 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) @@ -174,7 +174,7 @@ static void actisys_reset(struct irda_device *idev) /* 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); diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 615592776696..b60241a40b61 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: serial.c by Linus Torvalds * @@ -280,7 +280,7 @@ void irport_change_speed(struct irda_device *idev, __u32 speed) 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;); @@ -472,8 +472,8 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) */ static void irport_receive(struct irda_device *idev) { - int iobase; int boguscount = 0; + int iobase; ASSERT(idev != NULL, return;); @@ -488,7 +488,7 @@ static void irport_receive(struct irda_device *idev) /* 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); @@ -530,9 +530,8 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) 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) diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c index 3d3e24f8a9ab..6a439a1a865a 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, @@ -25,11 +25,13 @@ ********************************************************************/ #include -#include #include #include -#include #include +#include + +#include +#include #include #include @@ -411,7 +413,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, */ 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; @@ -726,8 +728,13 @@ static int irtty_net_init(struct net_device *dev) 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; @@ -735,6 +742,11 @@ static int irtty_net_open(struct net_device *dev) 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; diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c index 162350c1bae7..3b575d01ea3f 100644 --- a/drivers/net/irda/pc87108.c +++ b/drivers/net/irda/pc87108.c @@ -1303,7 +1303,7 @@ static void pc87108_wait_until_sent( struct irda_device *idev) { /* Just delay 60 ms */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(6); + schedule_timeout(MSECS_TO_JIFFIES(60)); } /* diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c index 94df892ede34..00ab408d6af7 100644 --- a/drivers/net/irda/smc-ircc.c +++ b/drivers/net/irda/smc-ircc.c @@ -6,7 +6,7 @@ * 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 * * Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved. @@ -52,14 +52,16 @@ static char *driver_name = "smc-ircc"; #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); @@ -264,6 +266,7 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2) * Close driver instance * */ +#ifdef MODULE static int ircc_close( struct irda_device *idev) { int iobase; @@ -304,6 +307,7 @@ static int ircc_close( struct irda_device *idev) DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } +#endif /* MODULE */ /* * Function ircc_probe (iobase, board_addr, irq, dma) @@ -311,7 +315,7 @@ static int ircc_close( struct irda_device *idev) * 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; @@ -327,17 +331,17 @@ static int ircc_probe( int iobase, int iobase2) 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; } @@ -798,7 +802,7 @@ static void ircc_wait_until_sent( struct irda_device *idev) /* Just delay 60 ms */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(6); + schedule_timeout(MSECS_TO_JIFFIES(60)); DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c index 201b10b8365f..d0dbaa4f726b 100644 --- a/drivers/net/irda/toshoboe.c +++ b/drivers/net/irda/toshoboe.c @@ -542,7 +542,7 @@ toshoboe_wait_until_sent (struct irda_device *idev) while (self->taskfile->xmit[i].control) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout (6); + schedule_timeout (MSECS_TO_JIFFIES(60)); } } diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c index 978fc62d7c29..869ccd5d6094 100644 --- a/drivers/net/irda/uircc.c +++ b/drivers/net/irda/uircc.c @@ -767,7 +767,7 @@ static void uircc_wait_until_sent( struct irda_device *idev) { /* Just delay 60 ms */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(6); + schedule_timeout(MSECS_TO_JIFFIES(60)); } /* diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 055610824f52..b061559b8deb 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -40,7 +40,7 @@ #include #include -#include "../../drivers/net/8390.h" +#include "../8390.h" #include #include diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9bca412c8c8e..570fbbc0df14 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -13,13 +13,10 @@ * 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 #include -#ifdef MODVERSIONS -#include -#endif #include #include @@ -39,6 +36,7 @@ static const char *version = "pcnet32.c:v1.23 6.7.1999 tsbogend@alpha.franken.de #include #include #include +#include static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0}; @@ -156,6 +154,7 @@ static int full_duplex[MAX_UNITS] = {0, }; * Michael Richard ) * added chip id for 79c973/975 (thanks to Zach Brown ) * v1.23 fixed small bug, when manual selecting MII speed/duplex + * v1.23ac Added SMP spinlocking - Alan Cox */ @@ -255,14 +254,15 @@ struct pcnet32_private { 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 @@ -510,7 +510,7 @@ static int __init 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; @@ -551,11 +551,11 @@ pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_l 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"; @@ -588,6 +588,19 @@ pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_l 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); @@ -611,6 +624,9 @@ pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_l 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; @@ -933,9 +949,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) return 1; } - save_flags (flags); - cli (); - + spin_lock_irqsave(&lp->lock, flags); /* Fill in a Tx ring entry */ /* Mask to ring buffer boundary. */ @@ -964,7 +978,7 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) clear_bit (0, (void *)&dev->tbusy); else lp->tx_full = 1; - restore_flags(flags); + spin_unlock_irqrestore(&lp->lock, flags); return 0; } @@ -986,6 +1000,9 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) 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); @@ -1094,12 +1111,14 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) /* 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; } @@ -1248,12 +1267,11 @@ pcnet32_get_stats(struct net_device *dev) 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; } diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 346830ec6541..b0d8a9ad4d77 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -912,6 +912,7 @@ printk("cm0: IP identification: %02x%02x fragment offset: %02x%02x\n", buffer[3 /* 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; @@ -1257,7 +1258,7 @@ init_module(void) 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"); diff --git a/drivers/net/slip.c b/drivers/net/slip.c index c0bc40ff15ba..4fa976736c5e 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -831,6 +831,9 @@ slip_open(struct tty_struct *tty) struct slip *sl; int err; + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + MOD_INC_USE_COUNT; /* RTnetlink lock is misused here to serialize concurrent diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 4bad54ac9e39..cbbee85327ed 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -59,6 +59,13 @@ static int sa_int = 0; 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 @@ -352,7 +359,7 @@ extern int init_module(void) /* printk( "TLAN: Found %d device(s).\n", TLanDevicesInstalled ); */ - return ( ( TLanDevicesInstalled >= 0 ) ? 0 : -ENODEV ); + return ( ( TLanDevicesInstalled > 0 ) ? 0 : -ENODEV ); } /* init_module */ @@ -2528,13 +2535,13 @@ void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits ) 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 */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5b1c8e829728..ec8fcb7a8bb3 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -81,10 +81,11 @@ static struct pci_fixup pci_fixups[] __initdata = { { 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 } diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 49ace00b2bac..95b07bdad9e0 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -218,7 +218,7 @@ int __init a2091_detect(Scsi_Host_Template *tpnt) 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; diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index 985453a0c5e5..bce089b6ad2f 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1,6 +1,21 @@ /* * 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 @@ -181,7 +196,7 @@ * 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 @@ -207,6 +222,7 @@ * 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, @@ -272,7 +288,7 @@ * 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; @@ -359,7 +375,7 @@ #if defined(MODULE) #include -#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"); @@ -370,7 +386,6 @@ MODULE_PARM(use_new_eh_code, "i"); MODULE_PARM(ext_tran, "i"); MODULE_PARM(rev_scan, "i"); MODULE_AUTHOR("Dario Ballabio"); -#endif #endif @@ -393,46 +408,21 @@ MODULE_AUTHOR("Dario Ballabio"); #include #include #include - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93) -#include -#endif - -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36) #include +#include + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) +#include #else -#define __initfunc(A) A -#define __initdata -#define __init +#include #endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) -#include -#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", @@ -516,6 +506,10 @@ struct proc_dir_entry proc_scsi_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) @@ -529,8 +523,8 @@ struct proc_dir_entry proc_scsi_eata2x = { /* 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 */ @@ -543,8 +537,8 @@ struct eata_info { 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 */ @@ -593,8 +587,8 @@ struct mssp { 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]; }; @@ -629,13 +623,13 @@ struct mscp { 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; }; @@ -664,7 +658,7 @@ static char sha[MAX_BOARDS]; /* 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, @@ -704,6 +698,8 @@ static int link_statistics = 0; 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; @@ -726,9 +722,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN; 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) { @@ -781,7 +775,6 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { dev->queue_depth, link_suffix, tag_suffix); } - IRQ_UNLOCK_RESTORE return; } @@ -795,7 +788,7 @@ static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { 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; @@ -828,12 +821,42 @@ static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) { 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; @@ -849,9 +872,6 @@ get_pci_irq(unsigned long port_base, unsigned char *apic_irq){ 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; @@ -859,15 +879,13 @@ get_pci_irq(unsigned long port_base, unsigned char *apic_irq){ } -#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; @@ -881,7 +899,9 @@ static inline int __init port_detect \ 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; } @@ -992,7 +1012,7 @@ static inline int __init port_detect \ 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; } @@ -1105,14 +1125,10 @@ static inline int __init port_detect \ } 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)); @@ -1148,10 +1164,11 @@ static inline int __init port_detect \ 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; @@ -1187,14 +1204,28 @@ void __init eata2x_setup(char *str, int *ints){ 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; @@ -1218,48 +1249,18 @@ static void __init add_pci_ports(void){ (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) { @@ -1280,7 +1281,6 @@ int __init eata2x_detect(Scsi_Host_Template *tpnt){ } num_boards = j; - IRQ_UNLOCK_RESTORE return j; } @@ -1353,10 +1353,9 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { /* 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, @@ -1425,7 +1424,7 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { } /* 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); @@ -1438,11 +1437,8 @@ static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { 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; } @@ -1514,16 +1510,11 @@ static inline int do_old_abort(Scsi_Cmnd *SCarg) { 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; @@ -1601,8 +1592,6 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { 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; @@ -1689,10 +1678,8 @@ static inline int do_old_reset(Scsi_Cmnd *SCarg) { 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); @@ -1728,7 +1715,6 @@ static inline int do_old_reset(Scsi_Cmnd *SCarg) { continue; SCpnt->scsi_done(SCpnt); - IRQ_LOCK } HD(j)->in_reset = FALSE; @@ -1746,16 +1732,11 @@ static inline int do_old_reset(Scsi_Cmnd *SCarg) { 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; @@ -1836,10 +1817,8 @@ static inline int do_reset(Scsi_Cmnd *SCarg) { 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); @@ -1875,7 +1854,6 @@ static inline int do_reset(Scsi_Cmnd *SCarg) { continue; SCpnt->scsi_done(SCpnt); - IRQ_LOCK } HD(j)->in_reset = FALSE; @@ -1892,8 +1870,6 @@ int eata2x_reset(Scsi_Cmnd *SCarg) { return do_reset(SCarg); } -#endif /* new_eh_code */ - int eata2x_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { int size = disk->capacity; @@ -2058,7 +2034,7 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, 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); @@ -2112,25 +2088,21 @@ static inline void ihdlr(int irq, unsigned int j) { 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; @@ -2289,24 +2261,18 @@ static inline void ihdlr(int irq, unsigned int j) { 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++); @@ -2322,7 +2288,6 @@ int eata2x_release(struct Scsi_Host *shpnt) { release_region(sh[j]->io_port, sh[j]->n_io_port); scsi_unregister(sh[j]); - IRQ_UNLOCK_RESTORE return FALSE; } @@ -2330,4 +2295,15 @@ int eata2x_release(struct Scsi_Host *shpnt) { 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 */ diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h index f1641f42d469..6c00ca0a2b4d 100644 --- a/drivers/scsi/eata.h +++ b/drivers/scsi/eata.h @@ -16,12 +16,10 @@ int eata2x_reset(Scsi_Cmnd *); 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, \ @@ -40,21 +38,4 @@ int eata2x_biosparam(Disk *, kdev_t, int *); 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 diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index e3d2ea4b971b..450fc370e4aa 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -2531,9 +2531,9 @@ ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) { 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; @@ -2925,11 +2925,11 @@ ips_online(ips_ha_t *ha, ips_scb_t *scb) { /****************************************************************************/ 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; diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 3f80b3c91546..a4244234afb0 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -613,7 +613,7 @@ typedef struct { u8 ProductRevisionLevel[4]; u8 VendorSpecific[20]; u8 Reserved3[40]; -} INQUIRYDATA, *PINQUIRYDATA; +} IPS_INQUIRYDATA, *IPS_PINQUIRYDATA; /* * Read Capacity Data Format diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h index c67d5a129cf7..c54f5e351b83 100644 --- a/drivers/scsi/wd33c93.h +++ b/drivers/scsi/wd33c93.h @@ -190,6 +190,9 @@ typedef struct { volatile unsigned char SASR; char pad; +#ifdef CONFIG_SGI + char pad2,pad3; +#endif volatile unsigned char SCMD; } wd33c93_regs; diff --git a/drivers/sound/opl3sa.c b/drivers/sound/opl3sa.c index 341438748842..9e5fd5a6bd29 100644 --- a/drivers/sound/opl3sa.c +++ b/drivers/sound/opl3sa.c @@ -187,7 +187,7 @@ int probe_opl3sa_mpu(struct address_info *hw_config) { #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 }; diff --git a/drivers/sound/sb_audio.c b/drivers/sound/sb_audio.c index baca53992a34..f91d3dcdfd39 100644 --- a/drivers/sound/sb_audio.c +++ b/drivers/sound/sb_audio.c @@ -742,6 +742,14 @@ static void sb16_audio_output_block(int dev, unsigned long buf, int count, 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; diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 44b40e736476..a21da2d69528 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -179,7 +179,7 @@ int init_module(void) 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); diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index f51083d186a7..37dd03f4f364 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -1216,7 +1216,17 @@ int probe_sbmpu(struct address_info *hw_config) 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) diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 4e53fde1dc2d..d9a423f16cb5 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -320,7 +320,7 @@ int __init root_nfs_init(void) * 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')) { @@ -335,6 +335,7 @@ void __init nfs_root_setup(char *line, int *ints) root_nfs_parse_addr(nfs_root_name); } +__setup("nfsroot=", nfs_root_setup); /*************************************************************************** diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c index 33cef410925c..bce1d34aad70 100644 --- a/fs/partitions/acorn.c +++ b/fs/partitions/acorn.c @@ -69,6 +69,9 @@ static int riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_ struct buffer_head *bh; struct riscix_record *rr; unsigned int riscix_minor; + + if(get_ptable_blocksize(dev)!=1024) + return 0; printk(" [RISCiX]"); @@ -113,6 +116,9 @@ static int linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s 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); @@ -151,6 +157,9 @@ static int adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev, unsigned long f 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'. @@ -236,6 +245,9 @@ static int adfspart_check_ADFS(struct gendisk *hd, kdev_t dev, unsigned long fir struct buffer_head *bh; struct disc_record *dr; + if(get_ptable_blocksize(dev)!=1024) + return 0; + if (!(bh = bread(dev, 3, 1024))) return -1; @@ -287,6 +299,9 @@ static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block) 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) { @@ -319,6 +334,9 @@ static int adfspart_check_ICS(struct gendisk *hd, kdev_t dev, unsigned long firs 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. */ diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 6991a4b6dc52..a4ba9253be2a 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -77,6 +77,8 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) 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; @@ -84,6 +86,8 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) 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)))) @@ -121,8 +125,11 @@ static void extended_partition(struct gendisk *hd, kdev_t 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; } @@ -349,18 +356,30 @@ check_table: /* * 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; } @@ -368,48 +387,25 @@ 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 */ diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 4ea8d33cffc6..1862f6f5fd1f 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -90,6 +90,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) 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++; diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h index 618ed0aa56d6..50b708d91af0 100644 --- a/include/asm-i386/e820.h +++ b/include/asm-i386/e820.h @@ -16,6 +16,10 @@ #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__ diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h index 044433b2039a..53e3ea81bce9 100644 --- a/include/linux/cyclades.h +++ b/include/linux/cyclades.h @@ -1,9 +1,9 @@ /* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $ * linux/include/linux/cyclades.h * - * This file is maintained by Ivan Passos , - * Marcio Saito and - * Randolph Bentson . + * This file was initially written by + * Randolph Bentson and is maintained by + * Ivan Passos . * * This file contains the general definitions for the cyclades.c driver *$Log: cyclades.h,v $ @@ -317,6 +317,7 @@ struct FIRM_ID { #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 */ @@ -373,6 +374,8 @@ struct FIRM_ID { #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 */ @@ -410,6 +413,8 @@ struct CH_CTRL { uclong hw_overflow; /* hw overflow counter */ uclong sw_overflow; /* sw overflow counter */ uclong comm_error; /* frame/parity error counter */ + uclong ichar; + uclong filler[7]; }; @@ -504,7 +509,6 @@ struct cyclades_card { #else uclong filler; #endif - }; struct cyclades_chip { @@ -527,6 +531,15 @@ 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. * @@ -575,12 +588,14 @@ struct cyclades_port { 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; }; /* @@ -593,6 +608,7 @@ struct cyclades_port { #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 @@ -771,6 +787,7 @@ struct cyclades_port { #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) diff --git a/include/linux/irda.h b/include/linux/irda.h index 275d82fc9a36..5d547a99f1ca 100644 --- a/include/linux/irda.h +++ b/include/linux/irda.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irda.h - * Version: - * Description: + * Version: 1.0 + * Description: Exported IrDA sockets interface * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -83,8 +83,8 @@ struct sockaddr_irda { }; 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 */ @@ -92,7 +92,7 @@ struct irda_device_info { struct irda_device_list { unsigned int len; - struct irda_device_info dev[0]; + struct irda_device_info dev[1]; }; struct irda_ias_set { diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 590d4b10f878..bff574aac740 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -278,8 +278,9 @@ struct video_unit #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 diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index 6b45e54bb4e0..500baba378e9 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -83,9 +83,13 @@ struct ircomm_tty_cb { 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 */ diff --git a/include/net/irda/ircomm_tty_attach.h b/include/net/irda/ircomm_tty_attach.h index 8556dd741b6e..545bf20a60b3 100644 --- a/include/net/irda/ircomm_tty_attach.h +++ b/include/net/irda/ircomm_tty_attach.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -52,6 +52,8 @@ typedef enum { 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, @@ -66,6 +68,7 @@ struct ircomm_tty_info { 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); @@ -79,6 +82,9 @@ void ircomm_tty_connect_confirm(void *instance, void *sap, __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, diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index fb8874fef85b..5e00eec7ac35 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. @@ -73,7 +73,7 @@ if(!(expr)) { \ #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; @@ -245,7 +245,7 @@ typedef struct { 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 *); diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h index 7652b1512f73..5c5d2280e56e 100644 --- a/include/net/irda/irda_device.h +++ b/include/net/irda/irda_device.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -43,6 +43,11 @@ #include #include +/* 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 */ @@ -153,12 +158,13 @@ int irda_device_open(struct irda_device *, char *name, void *priv); 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); diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index 11241374076d..f21365188ba0 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -90,8 +90,7 @@ struct irlap_cb { 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 */ @@ -183,7 +182,7 @@ extern hashbin_t *irlap; 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, diff --git a/include/net/irda/irlpt_cli.h b/include/net/irda/irlpt_cli.h deleted file mode 100644 index 7525a2997ff2..000000000000 --- a/include/net/irda/irlpt_cli.h +++ /dev/null @@ -1,49 +0,0 @@ -/********************************************************************* - * - * Filename: irlpt_cli.h - * Version: 0.1 - * Description: - * Status: Experimental. - * Author: Dag Brattli - * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Wed Apr 21 16:46:26 1999 - * Modified by: Dag Brattli - * - * Copyright (c) 1998, Thomas Davis, - * 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 diff --git a/include/net/irda/irlpt_cli_fsm.h b/include/net/irda/irlpt_cli_fsm.h deleted file mode 100644 index b6fd153a5dbe..000000000000 --- a/include/net/irda/irlpt_cli_fsm.h +++ /dev/null @@ -1,36 +0,0 @@ -/********************************************************************* - * - * Filename: irlpt_cli_fsm.h - * Version: 0.1 - * Sources: irlan_event.h - * - * Copyright (c) 1997 Dag Brattli , - * All Rights Reserved. - * Copyright (c) 1998, Thomas Davis, , - * 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 -#include - -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 - diff --git a/include/net/irda/irlpt_common.h b/include/net/irda/irlpt_common.h deleted file mode 100644 index 25ad8ef0190b..000000000000 --- a/include/net/irda/irlpt_common.h +++ /dev/null @@ -1,190 +0,0 @@ -/********************************************************************* - * - * Filename: irlpt_common.h - * Version: - * Description: - * Status: Experimental. - * Author: Thomas Davis, - * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Sun Mar 8 23:44:19 1998 - * Modified by: Dag Brattli - * Sources: irlan.c - * - * Copyright (c) 1998, Thomas Davis, , - * 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_COMMON_H -#define IRLPT_COMMON_H - -#include -#include - -#include -#include -#include -#include -#include - -#include - -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 diff --git a/include/net/irda/irlpt_server.h b/include/net/irda/irlpt_server.h deleted file mode 100644 index f5713cc03365..000000000000 --- a/include/net/irda/irlpt_server.h +++ /dev/null @@ -1,42 +0,0 @@ -/********************************************************************* - * - * Filename: irlpt_server.h - * Version: 0.1 - * Description: - * Status: Experimental. - * Author: Dag Brattli - * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Tue Sep 22 11:41:42 1998 - * Modified by: Dag Brattli - * - * Copyright (c) 1998, Thomas Davis, - * 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 -#include -#include -#include -#include - -/* int server_init( struct net_device *dev); */ - -extern struct irlpt_cb *irlpt_server; - -#endif diff --git a/include/net/irda/irlpt_server_fsm.h b/include/net/irda/irlpt_server_fsm.h deleted file mode 100644 index c7ee3f871560..000000000000 --- a/include/net/irda/irlpt_server_fsm.h +++ /dev/null @@ -1,35 +0,0 @@ -/********************************************************************* - * - * Filename: server_server_fsm.h - * Version: 0.1 - * Sources: irlan_event.h - * - * Copyright (c) 1997 Dag Brattli , - * All Rights Reserved. - * Copyright (c) 1998, Thomas Davis, , - * 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 -#include - -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 diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h index 48ac3ee8e0e5..a44ab2b9f705 100644 --- a/include/net/irda/irttp.h +++ b/include/net/irda/irttp.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -141,6 +141,11 @@ static __inline __u32 irttp_get_daddr(struct tsap_cb *self) 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 */ diff --git a/include/net/irda/irvtd.h b/include/net/irda/irvtd.h deleted file mode 100644 index 68340087ad1e..000000000000 --- a/include/net/irda/irvtd.h +++ /dev/null @@ -1,95 +0,0 @@ -/********************************************************************* - * - * Filename: irvtd.h - * Version: 0.1 - * Sources: irlpt.h - * - * Copyright (c) 1998, Takahide Higuchi , - * 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 -#include -#include -#include - -#include -#include -#include - - -#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 diff --git a/include/net/irda/toshoboe.h b/include/net/irda/toshoboe.h index b2f5b953ba87..dc2ea1269562 100644 --- a/include/net/irda/toshoboe.h +++ b/include/net/irda/toshoboe.h @@ -25,6 +25,12 @@ /* * $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 *** * @@ -157,6 +163,8 @@ struct toshoboe_cb 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*/ }; diff --git a/net/irda/Config.in b/net/irda/Config.in index bf12552bf991..942182e353b2 100644 --- a/net/irda/Config.in +++ b/net/irda/Config.in @@ -2,30 +2,30 @@ # 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 diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 9cdc29525628..96060aa884f3 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc. * @@ -47,6 +47,8 @@ extern void irda_cleanup(void); 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; @@ -66,8 +68,6 @@ static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb) struct sock *sk; int err; - DEBUG(1, __FUNCTION__ "()\n"); - self = (struct irda_sock *) instance; ASSERT(self != NULL, return -1;); @@ -98,7 +98,7 @@ static void irda_disconnect_indication(void *instance, void *sap, struct irda_sock *self; struct sock *sk; - DEBUG(1, __FUNCTION__ "()\n"); + DEBUG(2, __FUNCTION__ "()\n"); self = (struct irda_sock *) instance; @@ -129,7 +129,7 @@ static void irda_connect_confirm(void *instance, void *sap, struct irda_sock *self; struct sock *sk; - DEBUG(1, __FUNCTION__ "()\n"); + DEBUG(2, __FUNCTION__ "()\n"); self = (struct irda_sock *) instance; @@ -141,7 +141,7 @@ static void irda_connect_confirm(void *instance, void *sap, /* 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; @@ -173,7 +173,7 @@ static void irda_connect_indication(void *instance, void *sap, struct irda_sock *self; struct sock *sk; - DEBUG(1, __FUNCTION__ "()\n"); + DEBUG(2, __FUNCTION__ "()\n"); self = (struct irda_sock *) instance; @@ -185,7 +185,7 @@ static void irda_connect_indication(void *instance, void *sap, /* 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; @@ -428,8 +428,6 @@ static int irda_listen( struct socket *sock, int backlog) { 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; @@ -495,6 +493,8 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) struct sk_buff *skb; int err; + DEBUG(0, __FUNCTION__ "()\n"); + self = sk->protinfo.irda; ASSERT(self != NULL, return -1;); @@ -1171,8 +1171,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCSIFNETMASK: case SIOCGIFMETRIC: case SIOCSIFMETRIC: - return -EINVAL; - + return -EINVAL; default: DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n"); return dev_ioctl(cmd, (void *) arg); @@ -1212,7 +1211,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, 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: @@ -1232,13 +1231,12 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, { 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; @@ -1261,7 +1259,15 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, 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 @@ -1271,36 +1277,43 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, 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; @@ -1370,7 +1383,7 @@ SOCKOPS_WRAP(irda_stream, PF_IRDA); /* * 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, @@ -1378,8 +1391,6 @@ 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; diff --git a/net/irda/compressors/Config.in b/net/irda/compressors/Config.in index 61500751b23e..1a4306dea02a 100644 --- a/net/irda/compressors/Config.in +++ b/net/irda/compressors/Config.in @@ -1,9 +1,11 @@ -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 diff --git a/net/irda/ircomm/Config.in b/net/irda/ircomm/Config.in index f384eb8d76df..67f967c5a875 100644 --- a/net/irda/ircomm/Config.in +++ b/net/irda/ircomm/Config.in @@ -1,3 +1,3 @@ -dep_tristate 'IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA +dep_tristate ' IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA diff --git a/net/irda/ircomm/Makefile b/net/irda/ircomm/Makefile index c439ffdabb6b..89e3294fded5 100644 --- a/net/irda/ircomm/Makefile +++ b/net/irda/ircomm/Makefile @@ -8,7 +8,7 @@ # 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 diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c index f2e8b2d46548..18f0b24db4ba 100644 --- a/net/irda/ircomm/ircomm_event.c +++ b/net/irda/ircomm/ircomm_event.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: ircomm_event.c - * Version: - * Description: + * Version: 1.0 + * Description: IrCOMM layer state machine * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -161,18 +161,15 @@ static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 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]); diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index 943dbd724ef0..4294dbdb2027 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -102,6 +102,7 @@ int ircomm_param_flush(struct ircomm_tty_cb *self) */ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) { + unsigned long flags; struct sk_buff *skb; int count; @@ -119,12 +120,16 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) 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); @@ -136,8 +141,13 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) */ 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); @@ -201,13 +211,25 @@ static int ircomm_param_service_type(void *instance, param_t *param, int get) /* * 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; } @@ -223,11 +245,13 @@ static int ircomm_param_port_name(void *instance, param_t *param, int get) 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; } @@ -273,8 +297,6 @@ static int ircomm_param_data_format(void *instance, param_t *param, int get) else self->session.data_format = param->pv.b; - DEBUG(1, __FUNCTION__ "(), data format = 0x%02x\n", param->pv.b); - return 0; } @@ -359,9 +381,6 @@ static int ircomm_param_dte(void *instance, param_t *param, int get) 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 | @@ -379,14 +398,9 @@ static int ircomm_param_dte(void *instance, param_t *param, int get) /* 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; } @@ -426,18 +440,24 @@ static int ircomm_param_dce(void *instance, param_t *param, int get) /* * 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; +} diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c index b3bd3744bc08..9c188aa495e5 100644 --- a/net/irda/ircomm/ircomm_ttp.c +++ b/net/irda/ircomm/ircomm_ttp.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -196,7 +196,7 @@ void ircomm_ttp_connect_confirm(void *instance, void *sap, 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; @@ -206,7 +206,7 @@ void ircomm_ttp_connect_confirm(void *instance, void *sap, /* * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size, - * max_header_size, skb) + * max_header_size, skb) * * * @@ -232,7 +232,7 @@ void ircomm_ttp_connect_indication(void *instance, void *sap, 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; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index f3642841a5d4..8df8d876e962 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: serial.c and previous IrCOMM work by Takahide Higuchi * @@ -60,11 +60,8 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty); 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, @@ -127,7 +124,6 @@ int __init ircomm_tty_init(void) 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; @@ -170,9 +166,12 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) 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; } @@ -181,10 +180,10 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) /* 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); @@ -201,7 +200,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self) /* 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; } @@ -227,7 +226,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, tty = self->tty; - DEBUG(1, __FUNCTION__ "()\n"); + DEBUG(2, __FUNCTION__ "()\n"); if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { /* this is a callout device */ @@ -283,7 +282,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, 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(); @@ -391,16 +390,25 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) 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++; @@ -413,12 +421,28 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) /* 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; } @@ -452,7 +476,6 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) 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"); @@ -484,7 +507,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) 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; @@ -494,6 +517,10 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) * 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); @@ -503,35 +530,47 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) 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 } /* @@ -544,18 +583,15 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty) { 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); } /* @@ -569,28 +605,31 @@ static void ircomm_tty_do_softint(void *private_) { 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)) && @@ -625,9 +664,9 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, 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; @@ -637,20 +676,19 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, * 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 @@ -663,25 +701,18 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, 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); @@ -694,12 +725,12 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, 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 @@ -710,8 +741,6 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, queue_task(&self->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); - /*restore_flags(flags);*/ - return len; } @@ -725,6 +754,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, 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;); @@ -734,10 +764,13 @@ static int ircomm_tty_write_room(struct tty_struct *tty) 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); @@ -753,8 +786,27 @@ static int ircomm_tty_write_room(struct tty_struct *tty) 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; } /* @@ -785,7 +837,6 @@ static void ircomm_tty_throttle(struct tty_struct *tty) ircomm_param_request(self, IRCOMM_DTE, TRUE); } - DEBUG(1, __FUNCTION__"(), FLOW_STOP\n"); ircomm_flow_request(self->ircomm, FLOW_STOP); } @@ -829,10 +880,21 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty) 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; } /* @@ -846,7 +908,10 @@ static void ircomm_tty_hangup(struct tty_struct *tty) { 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; @@ -889,8 +954,6 @@ void ircomm_tty_start(struct tty_struct *tty) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - DEBUG(2, __FUNCTION__"()\n"); - ircomm_flow_request(self->ircomm, FLOW_START); } @@ -904,24 +967,12 @@ void ircomm_tty_stop(struct tty_struct *tty) { 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) * @@ -934,8 +985,6 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) struct tty_struct *tty; int status; - DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(self != NULL, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); @@ -967,13 +1016,9 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) 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 { @@ -1044,35 +1089,6 @@ static int ircomm_tty_control_indication(void *instance, void *sap, 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) * @@ -1093,18 +1109,17 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, 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; } @@ -1114,6 +1129,8 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) { 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"); @@ -1125,12 +1142,15 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) 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: "); @@ -1142,7 +1162,8 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) 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: "); @@ -1171,7 +1192,8 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) 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: "); @@ -1189,7 +1211,8 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) 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); @@ -1197,7 +1220,6 @@ static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) ret += sprintf(buf+ret, "Hardware: %s\n", self->tty->hw_stopped ? "Stopped" : "Running"); - exit: ret += sprintf(buf+ret, "\n"); return ret; } @@ -1213,7 +1235,7 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, 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); diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c index e9618d848b65..f2466d68c7f2 100644 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ b/net/irda/ircomm/ircomm_tty_attach.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -96,6 +96,8 @@ char *ircomm_tty_event[] = { "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", @@ -167,8 +169,10 @@ void ircomm_tty_detach_cable(struct ircomm_tty_cb *self) 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); @@ -204,7 +208,8 @@ static void ircomm_tty_ias_register(struct ircomm_tty_cb *self) 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", @@ -257,8 +262,8 @@ static int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self) } /* 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 @@ -296,6 +301,30 @@ static void ircomm_tty_discovery_indication(discovery_t *discovery) } } +/* + * 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) * @@ -315,7 +344,7 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, /* Check if request succeeded */ if (result != IAS_SUCCESS) { - DEBUG(0, __FUNCTION__ "(), got NULL value!\n"); + DEBUG(4, __FUNCTION__ "(), got NULL value!\n"); return; } @@ -421,29 +450,35 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self) /* * 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); } @@ -458,7 +493,7 @@ void ircomm_tty_watchdog_timer_expired(void *data) { 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;); @@ -479,7 +514,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, { 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) { @@ -507,9 +542,11 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, /* 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 */ @@ -518,7 +555,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 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; } @@ -538,7 +575,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self, { 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) { @@ -568,8 +605,11 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self, /* 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 */ @@ -580,7 +620,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 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; } @@ -600,7 +640,7 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, { 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) { @@ -624,14 +664,17 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, /* 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; } @@ -651,7 +694,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, { 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) { @@ -673,14 +716,17 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, /* 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; } @@ -700,38 +746,20 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, { 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); @@ -739,6 +767,10 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, /* 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 */ @@ -750,7 +782,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 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; } @@ -774,14 +806,20 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 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; } @@ -813,7 +851,7 @@ void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state) { 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); } diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index e5981ecb239e..fdbe2b1f24fe 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -196,12 +196,12 @@ static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self, 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); } @@ -286,21 +286,19 @@ static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self, 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; diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index 1f4571a5d4ba..6937d62f31e8 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irda_device.c - * Version: 0.5 + * Version: 0.6 * Description: Abstract device driver layer and helper functions * Status: Experimental. * Author: Dag Brattli * 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 * Modified at: Fri May 28 3:11 CST 1999 * Modified by: Horst von Brand @@ -155,16 +155,16 @@ int irda_device_open(struct irda_device *self, char *name, void *priv) /* 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; @@ -191,14 +191,15 @@ int irda_device_open(struct irda_device *self, char *name, void *priv) /* 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; } @@ -213,12 +214,9 @@ int irda_device_open(struct irda_device *self, char *name, void *priv) 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; } @@ -238,8 +236,6 @@ void __irda_device_close(struct irda_device *self) /* 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); } @@ -284,10 +280,14 @@ void irda_device_close(struct irda_device *self) * 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;); @@ -359,7 +359,7 @@ static void __irda_device_change_speed(struct irda_device *self, int speed) * 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;); @@ -369,16 +369,24 @@ inline void irda_device_change_speed(struct irda_device *self, int speed) 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;); @@ -388,15 +396,21 @@ inline int irda_device_is_receiving( struct irda_device *self) 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; @@ -464,7 +478,7 @@ int irda_device_net_open(struct net_device *dev) * 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); @@ -508,7 +522,8 @@ static int irda_device_net_rebuild_header( struct sk_buff *skb) 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) { @@ -521,22 +536,21 @@ static int irda_device_net_hard_header(struct sk_buff *skb, struct net_device *d 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 */ @@ -548,16 +562,14 @@ static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */ #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); @@ -647,10 +659,16 @@ static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */ #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; } diff --git a/net/irda/irlan/Config.in b/net/irda/irlan/Config.in index 7951d90abc91..6b6061675a54 100644 --- a/net/irda/irlan/Config.in +++ b/net/irda/irlan/Config.in @@ -1 +1 @@ -dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA +dep_tristate ' IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index cccbbb412aa1..8940343536d6 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997, 1999 Dag Brattli , @@ -237,7 +237,7 @@ int irlan_register_netdev(struct irlan_cb *self) /* Get the first free irlan 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; @@ -615,7 +615,7 @@ void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel) 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"); diff --git a/net/irda/irlap.c b/net/irda/irlap.c index 68981d87cf33..2b59a1efce1e 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c @@ -6,7 +6,7 @@ * Status: Stable * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. @@ -106,15 +106,12 @@ void irlap_cleanup(void) * 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) @@ -124,8 +121,7 @@ struct irlap_cb *irlap_open(struct irda_device *irdev) 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); @@ -186,7 +182,6 @@ static void __irlap_close(struct irlap_cb *self) irlap_flush_all_queues(self); - self->irdev = NULL; self->magic = 0; kfree(self); @@ -277,7 +272,7 @@ void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 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; @@ -565,7 +560,7 @@ void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log) * 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); @@ -849,17 +844,24 @@ void irlap_flush_all_queues(struct irlap_cb *self) */ 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; @@ -922,7 +924,7 @@ void irlap_init_qos_capabilities(struct irlap_cb *self, { 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); @@ -933,7 +935,7 @@ void irlap_init_qos_capabilities(struct irlap_cb *self, /* 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 @@ -1112,8 +1114,7 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len, 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]); diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index c845ac8526f2..203b7360fc29 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -127,9 +127,9 @@ const char *irlap_state[] = { "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, @@ -257,7 +257,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, 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; @@ -310,16 +310,14 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, 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"); @@ -337,20 +335,25 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, 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; */ @@ -371,9 +374,8 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, 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) { @@ -422,6 +424,10 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, default: DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", irlap_event[event]); + + if (skb) + dev_kfree_skb(skb); + ret = -1; break; } @@ -499,7 +505,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event, irlap_event[event]); if (skb) - dev_kfree_skb( skb); + dev_kfree_skb(skb); ret = -1; break; @@ -525,7 +531,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, 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); @@ -593,7 +599,7 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event, /* 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); @@ -615,27 +621,21 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event, 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; } @@ -694,11 +694,11 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, * 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)); @@ -718,6 +718,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, 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; @@ -733,7 +734,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, skb_pull(skb, sizeof(struct ua_frame)); - ASSERT(self->irdev != NULL, return -1;); + ASSERT(self->netdev != NULL, return -1;); irlap_qos_negotiate(self, skb); @@ -756,10 +757,14 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, 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; } @@ -931,6 +936,10 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event, break; default: DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event); + + if (skb) + dev_kfree_skb(skb); + ret = -1; break; } @@ -1254,7 +1263,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, * 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)); @@ -1373,6 +1382,9 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event, default: DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", irlap_event[event]); + if (skb) + dev_kfree_skb(skb); + ret = -1; break; } @@ -1425,9 +1437,8 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event, 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!! */ @@ -1443,17 +1454,31 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event, } 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; } @@ -1482,14 +1507,13 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, /* * 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 @@ -1531,6 +1555,9 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, default: DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", irlap_event[event]); + if (skb) + dev_kfree_skb(skb); + ret = -EINVAL; break; } @@ -1586,7 +1613,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, * 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); @@ -1785,15 +1812,20 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, 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) diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 6e7b1e35eea5..303bc3b12599 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -161,27 +161,34 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb, { 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); } /* @@ -318,7 +325,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s, 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 { @@ -334,7 +341,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s, else frame->daddr = cpu_to_le32(discovery->daddr); - switch(S) { + switch (S) { case 1: frame->flags = 0x00; break; @@ -402,18 +409,24 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self, 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; @@ -462,17 +475,17 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, __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: @@ -567,7 +580,7 @@ void irlap_send_rr_frame(struct irlap_cb *self, int command) * * 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, @@ -642,21 +655,16 @@ static void irlap_recv_rnr_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; @@ -698,11 +706,11 @@ void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *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; @@ -779,12 +787,12 @@ void irlap_send_data_secondary_final(struct irlap_cb *self, { 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 @@ -792,17 +800,17 @@ void irlap_send_data_secondary_final(struct irlap_cb *self, */ 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; @@ -810,21 +818,21 @@ void irlap_send_data_secondary_final(struct irlap_cb *self, 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); } } @@ -834,16 +842,12 @@ void irlap_send_data_secondary_final(struct irlap_cb *self, * 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 @@ -851,25 +855,25 @@ void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb) */ 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; } } @@ -883,16 +887,14 @@ void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb) * * 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; @@ -900,22 +902,22 @@ void irlap_resend_rejected_frames( struct irlap_cb *self, int command) /* * 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 */ @@ -925,8 +927,8 @@ void irlap_resend_rejected_frames( struct irlap_cb *self, int command) /* * 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; @@ -934,18 +936,18 @@ void irlap_resend_rejected_frames( struct irlap_cb *self, int command) /* * 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; @@ -955,13 +957,13 @@ void irlap_resend_rejected_frames( struct irlap_cb *self, int command) */ 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 @@ -989,11 +991,11 @@ void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb, { __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; @@ -1012,16 +1014,12 @@ void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 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); } @@ -1030,7 +1028,7 @@ void irlap_send_i_frame(struct irlap_cb *self, struct sk_buff *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, @@ -1073,18 +1071,18 @@ static void irlap_recv_ui_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; @@ -1097,24 +1095,24 @@ static void irlap_recv_frmr_frame( struct irlap_cb *self, struct sk_buff *skb, 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); } /* @@ -1170,7 +1168,7 @@ void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb, { 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"); @@ -1183,6 +1181,12 @@ void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb, 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 @@ -1208,7 +1212,18 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, 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; @@ -1218,10 +1233,9 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, 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; } @@ -1259,7 +1273,8 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev, 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; } diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index d958d048c823..8b63351ed026 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -6,7 +6,7 @@ * Status: Stable. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -503,24 +503,21 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) */ 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); @@ -530,7 +527,7 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) 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); } } @@ -1118,6 +1115,10 @@ __u16 irlmp_service_to_hint(int service) 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; diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index d2408730ebd7..ee41e54f4f34 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -195,10 +195,10 @@ void irlmp_idle_timer_expired(void *data) 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); */ @@ -213,10 +213,10 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event, * 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"); @@ -224,11 +224,11 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event, /* 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; @@ -251,15 +251,15 @@ static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, 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); } @@ -267,33 +267,33 @@ static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, 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; } } @@ -359,9 +359,7 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, 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); @@ -638,7 +636,20 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event, 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); diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 0feec822647d..e5c5d72ef97c 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved. @@ -120,7 +120,9 @@ EXPORT_SYMBOL(irda_debug); 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); @@ -204,10 +206,10 @@ EXPORT_SYMBOL(irtty_set_packet_mode); 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 @@ -360,10 +362,10 @@ void irmanager_notify( struct irmanager_event *event) { 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; } @@ -374,14 +376,14 @@ void irmanager_notify( struct irmanager_event *event) 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) @@ -395,7 +397,7 @@ static int irda_open( struct inode * inode, struct file *file) irda.in_use = TRUE; MOD_INC_USE_COUNT; - + return 0; } @@ -411,9 +413,9 @@ static int irda_ioctl( struct inode *inode, struct file *filp, 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) @@ -424,43 +426,43 @@ static int irda_ioctl( struct inode *inode, struct file *filp, 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); @@ -473,7 +475,7 @@ static ssize_t irda_read( struct file *file, char *buffer, size_t count, * 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); @@ -481,25 +483,25 @@ static ssize_t irda_read( struct file *file, char *buffer, size_t count, 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; } diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 9d1288779f8d..43fb65380bdd 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -729,9 +729,8 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, * */ 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; @@ -747,7 +746,7 @@ static void irttp_connect_confirm(void *instance, void *sap, 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; /* @@ -797,11 +796,11 @@ static void irttp_connect_confirm(void *instance, void *sap, 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); } } @@ -870,8 +869,6 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos, 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, diff --git a/net/irda/qos.c b/net/irda/qos.c index 8d645740f686..6af865bacd46 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c @@ -7,7 +7,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998-1999 Dag Brattli , @@ -278,7 +278,7 @@ static int irlap_param_baud_rate(void *instance, param_t *param, int get) 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 diff --git a/net/irda/timer.c b/net/irda/timer.c index 57e3d25106c8..fab26fd37b8b 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * 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 * - * Copyright (c) 1997, 1999 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 1999 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 @@ -124,16 +125,14 @@ inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) * 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); } /* @@ -142,16 +141,14 @@ static void irlap_slot_timer_expired( void* data) * 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); } /* @@ -160,16 +157,14 @@ static void irlap_query_timer_expired( void* data) * * */ -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); } /* @@ -178,16 +173,14 @@ static void irlap_final_timer_expired( void* data) * * */ -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); } /* @@ -196,16 +189,14 @@ static void irlap_wd_timer_expired( void* data) * * */ -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); } @@ -214,14 +205,12 @@ static void irlap_backoff_timer_expired( void* data) * * */ -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); } diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c index 0d4e08e2d979..5f5ed14f3b02 100644 --- a/net/irda/wrapper.c +++ b/net/irda/wrapper.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Modified at: Fri May 28 3:11 CST 1999 * Modified by: Horst von Brand @@ -203,7 +203,7 @@ static void state_outside_frame(struct irda_device *idev, __u8 byte) /* idev->xbofs++; */ break; case EOF: - irda_device_set_media_busy( idev, TRUE); + irda_device_set_media_busy(&idev->netdev, TRUE); break; default: break; @@ -261,7 +261,7 @@ static void state_link_escape(struct irda_device *idev, __u8 byte) 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"); @@ -299,7 +299,7 @@ static void state_inside_frame(struct irda_device *idev, __u8 byte) 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; @@ -314,7 +314,7 @@ static void state_inside_frame(struct irda_device *idev, __u8 byte) 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++; -- 2.39.5