diff -u --recursive --new-file v2.1.36/linux/Documentation/00-INDEX linux/Documentation/00-INDEX --- v2.1.36/linux/Documentation/00-INDEX Wed Jan 15 18:46:05 1997 +++ linux/Documentation/00-INDEX Tue Apr 29 11:45:43 1997 @@ -26,6 +26,8 @@ - plain ASCII listing of all the nodes in /dev/ with major minor #'s digiboard.txt - info on the Digiboard PC/X{i,e,eve} multiport boards. +digiepca.txt + - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. exception.txt - how linux v2.1 handles exceptions without verify_area etc. ez.txt diff -u --recursive --new-file v2.1.36/linux/Documentation/Changes linux/Documentation/Changes --- v2.1.36/linux/Documentation/Changes Wed Apr 23 19:01:13 1997 +++ linux/Documentation/Changes Thu May 1 12:33:49 1997 @@ -29,7 +29,7 @@ Also, don't forget http://www.linuxhq.com/ for all your Linux kernel needs. -Last updated: April 17, 1997. +Last updated: April 24, 1997. Current Author: Chris Ricker (gt1355b@prism.gatech.edu). Current Minimal Requirements @@ -45,11 +45,11 @@ - Dynamic Linker (ld.so) 1.8.5 - Linux C++ Library 2.7.2.1 - Procps 1.01 -- Mount 2.6e +- Mount 2.6g - Net-tools 1.32-alpha - Loadlin 1.6a - Sh-utils 1.16 -- Autofs 970409 +- Autofs 0.3.0 - NFS 0.4.21 Upgrade notes @@ -295,14 +295,14 @@ Mount ===== -The 2.6e release: -ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6e.tar.gz +The 2.6g release: +ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6g.tar.gz Autofs ====== -The 970409 release: -ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-970409.tar.gz +The 0.3.0 release: +ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-0.3.0.tar.gz NFS === diff -u --recursive --new-file v2.1.36/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.36/linux/Documentation/Configure.help Wed Apr 23 19:01:14 1997 +++ linux/Documentation/Configure.help Mon May 5 10:00:26 1997 @@ -2072,6 +2072,20 @@ and read Documentation/modules.txt. The module will be called NCR53c406.o. +Tekram DC390W/U/F (T) SCSI support +CONFIG_SCSI_DC390W + This driver supports the Tekram DC390W/U/F (T) PCI SCSI host adapters with + the NCR/Symbios 53c825/875 chips. If you have a DC390 (T) adaptor with the + Am53C974A chip use the DC390(T) driver. + +Tekram DC390(T) (AMD PCscsi) SCSI support +CONFIG_SCSI_DC390T + This driver supports the Tekram DC390(T) PCI SCSI Hostadapter with + the Am53C974A chip, and perhaps other cards using the same chip. + + This driver does _not_ support the DC390W/U/F adaptor with the + NCR/Symbios chips. + AM53/79C974 PCI SCSI support CONFIG_SCSI_AM53C974 This is support for the AM53/79C974 SCSI host adapters. Please read @@ -4036,6 +4050,16 @@ N here so that they can use the serial port for modem, mouse or some other device. +Digi Intl. epca support +CONFIG_DIGIEPCA + This is a driver for Digi Internationals Xx, Xeve, and Xem + series of cards. This driver supports the original PC (ISA) boards as + well as PCI, and EISA. If you have a card like this, say Y here and read + the file Documentation/digiepca.txt. NOTE: This driver is seperate from + the driver written and copyrighted by Troy De Jongh. Because they both + attempt (In some cases) to access the same hardware only one of these + drivers (CONFIG_DIGIEPCA or CONFIG_DIGI) should be selected. + Digiboard PC/Xx Support CONFIG_DIGI This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards @@ -4918,9 +4942,13 @@ Amiga AutoConfig Identification CONFIG_ZORRO This enables support for automatic identification of Amiga expansion - cards that obey the AutoConfig(tm) specification. You should say Y - to this question unless you have no expansion cards and no intention - of getting any. + cards that obey the AutoConfig(tm) specification. + Say Y if you want your expansion cards to be identified on bootup; + it will enlarge your kernel by about 10KB. The identification + information is also available through /proc/zorro (say Y to + "/proc filesystem support"!). + Note that even if you say N here, you can still use your expansion + cards. If in doubt, say Y. Amiga OCS chipset support CONFIG_AMIFB_OCS @@ -4948,6 +4976,8 @@ Please note that its use is not all that intuitive (i.e. if you have any questions, be sure to ask!). Say N unless you have a Cybervision 64 or plan to get one before you next recompile the kernel. + Please note that this driver DOES NOT support the Cybervision 64 3D + card at present, as they use incompatible video chips. Amiga GSP (TMS340x0) support CONFIG_AMIGA_GSP @@ -5188,6 +5218,16 @@ want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +Atari DSP56k Digital Signal Processor support +CONFIG_ATARI_DSP56K + If you want to be able to use the DSP56001 in Falcons, say Y. + This driver is still experimental, and if you don't know what it is, + or if you don't have this processor, just say N. + This driver is also available as a module ( = code which can be inserted + in and removed from the running kernel whenever you want). If you + want to compile it as a module, say M here and read + Documentation/modules.txt. + Amiga builtin serial support CONFIG_AMIGA_BUILTIN_SERIAL If you want to use your Amiga's built-in serial port in Linux, say @@ -5317,7 +5357,7 @@ # LocalWords: mgetty sendfax gert greenie muc lowlevel Lasermate LanManager io # LocalWords: OOPSes trackball binghamton mobileip ncr IOMAPPED settags ns ser # LocalWords: setsync NEGO MPARITY autotuning prefetch PIIX cdwrite utils rc -# LocalWords: PCWATCHDOG berkprod bitgate boldt ucsb jf kyoto jp euc Tetsuyasu +# LocalWords: PCWATCHDOG berkprod bitgate boldt ucsb jf kyoto jp euc Tetsuyasu # LocalWords: YAMADA tetsu cauchy nslab ntt nevod perm su doc kaf kheops wsc # LocalWords: traduc Bourgin dbourgin helptext menuconfig kfill READMEs HOWTOs # LocalWords: IDEDISK IDEFLOPPY EIDE firewalls QMAGIC ZMAGIC LocalWords opti diff -u --recursive --new-file v2.1.36/linux/Documentation/devices.tex linux/Documentation/devices.tex --- v2.1.36/linux/Documentation/devices.tex Sun Apr 13 10:18:20 1997 +++ linux/Documentation/devices.tex Thu May 1 12:32:45 1997 @@ -15,6 +15,7 @@ % \begin{document} \newcommand{\file}{\tt} % Style to use for a filename +\newcommand{\url}{\it} % Style to use for an URL \newcommand{\hex}{\tt} % Style to use for a hex number \newcommand{\ud}{(Under development)} % Abbreviation \newcommand{\1}{\({}^1\)} @@ -46,7 +47,7 @@ % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: April 7, 1997} +\date{Last revised: May 1, 1997} \maketitle % \noindent @@ -60,17 +61,19 @@ \LaTeX\ version is authoritative. This document is included by reference into the Linux Filesystem -Standard (FSSTND). The FSSTND is available via FTP from -tsx-11.mit.edu in the directory {\file -/pub/linux/docs/linux-standards/fsstnd}. +Standard (FSSTND). The FSSTND is available from +{\url ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/}. To have a major number allocated, or a minor number in situations where that applies (e.g.\ busmice), please contact me with the -appropriate device information. Also, if you have additional -information regarding any of the devices listed below, or if I have -made a mistake, I would greatly appreciate a note. When sending me -mail, {\em please\/} include the word ``device'' in the subject so -your mail won't accidentally get buried! +appropriate device information. I *very* much appreciate if you send +me a device description in the same format as the ones already in this +file. Also, if you have additional information regarding any of the +devices listed below, or if I have made a mistake, I would greatly +appreciate a note. + +NOTE: When sending me mail, {\em please\/} include the word ``device'' +in the subject so your mail won't accidentally get buried! Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -207,7 +210,9 @@ \major{79}{}{char }{PAM Software's multimodem boards -- alternate devices} \major{80}{}{char }{Photometrics AT200 CCD camera} \major{81}{}{char }{Brooktree Bt848 frame grabbers} -\major{82}{--119}{}{Unallocated} +\major{82}{}{char }{WiNRADiO communications receiver card} +\major{83}{}{char }{Teletext/videotext interfaces} +\major{84}{--119}{}{Unallocated} \major{120}{--127}{}{Local/experimental use} \major{128}{--239}{}{Unallocated} \major{240}{--254}{}{Local/experimental use} @@ -1243,7 +1248,7 @@ \end{devicelist} \noindent -See {\em http://www.coda.cs.cmu.edu\/} for information about Coda. +See {\url http://www.coda.cs.cmu.edu\/} for information about Coda. \begin{devicelist} \major{68}{}{char }{CAPI 2.0 interface} @@ -1392,7 +1397,28 @@ \end{devicelist} \begin{devicelist} -\major{82}{--119}{}{Unallocated} +\major{82}{}{char }{WiNRADiO communications receiver card} + \major{0}{/dev/winradio0}{First WiNRADiO card} + \major{1}{/dev/winradio1}{Second WiNRADiO card} + \minordots +\end{devicelist} + +\noindent +The driver and documentation may be obtained from +{\url http://www.proximity.com.au/~brian/winradio/\/}. + +\begin{devicelist} +\major{83}{}{char }{Teletext/videotext interfaces} + \minor{0}{/dev/vtx}{Teletext decoder} + \minor{16}{/dev/vttuner}{TV tuner on teletext interface} +\end{devicelist} + +\noindent +Devices for the driver contained in the VideoteXt package. More information +on {\url http://home.pages.de/~videotext/\/}. + +\begin{devicelist} +\major{84}{--119}{}{Unallocated} \end{devicelist} \begin{devicelist} diff -u --recursive --new-file v2.1.36/linux/Documentation/devices.txt linux/Documentation/devices.txt --- v2.1.36/linux/Documentation/devices.txt Sun Apr 13 10:18:20 1997 +++ linux/Documentation/devices.txt Thu May 1 12:32:45 1997 @@ -1,7 +1,7 @@ LINUX ALLOCATED DEVICES Maintained by H. Peter Anvin - Last revised: April 7, 1997 + Last revised: May 1, 1997 This list is the successor to Rick Miller's Linux Device List, which he stopped maintaining when he got busy with other things in 1993. It @@ -18,11 +18,14 @@ To have a major number allocated, or a minor number in situations where that applies (e.g. busmice), please contact me with the -appropriate device information. Also, if you have additional -information regarding any of the devices listed below, or if I have -made a mistake, I would greatly appreciate a note. When sending me -mail, *please* include the word "device" in the subject so your mail -won't accidentally get buried! +appropriate device information. I *very* much appreciate if you send +me a device description in the same format as the ones already in this +file. Also, if you have additional information regarding any of the +devices listed below, or if I have made a mistake, I would greatly +appreciate a note. + +NOTE: When sending me mail, *please* include the word "device" in the +subject so your mail won't accidentally get buried! Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga platform only. Allocations marked (68k/Atari) apply to Linux/68k on @@ -979,7 +982,22 @@ 33 = /dev/bttv-vbi1 VBI data of second Bt848 card ... - 82-119 UNALLOCATED + 82 char WiNRADiO communications receiver card + 0 = /dev/winradio0 First WiNRADiO card + 1 = /dev/winradio1 Second WiNRADiO card + ... + + The driver and documentation may be obtained from + http://www.proximity.com.au/~brian/winradio/ + + 83 char Teletext/videotext interfaces + 0 = /dev/vtx Teletext decoder + 16 = /dev/vttuner TV tuner on teletext interface + + Devices for the driver contained in the VideoteXt package. + More information on http://home.pages.de/~videotext/ + + 84-119 UNALLOCATED 120-127 LOCAL/EXPERIMENTAL USE diff -u --recursive --new-file v2.1.36/linux/Documentation/digiepca.txt linux/Documentation/digiepca.txt --- v2.1.36/linux/Documentation/digiepca.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/digiepca.txt Tue Apr 29 11:45:43 1997 @@ -0,0 +1,96 @@ +The Digi Intl. epca driver. +---------------------------- +The Digi Intl. epca driver for Linux supports the following boards: + +Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve +Digi EISA/Xem, PCI/Xem, PCI/Xr + +Limitations: +------------ +Currently the driver only autoprobes for supported PCI boards. + +The Linux MAKEDEV command does not support generating the Digiboard +Devices. Users executing digiConfig to setup EISA and PC series cards +will have their device nodes automaticly constructed (cud?? for ~CLOCAL, +and ttyD?? for CLOCAL). Users wishing to boot their board from the LILO +prompt, or those users booting PCI cards may use buildDIGI to construct +the necessary nodes. + +Notes: +------ +This driver may be configured via LILO. For users who have already configured +their driver using digiConfig, configuring from lilo will override previous +settings. Multiple boards may be configured by issuing multiple LILO command +lines. For examples see the bottom of this document. + +Device names start at 0 and continue up. Beware of this as previous Digi +drivers started device names with 1. + +PCI boards are auto-detected and configured by the driver. PCI boards will +be allocated device numbers (internally) begining with the lowest PCI slot +first. In other words a PCI card in slot 3 will always have higher device +nodes than a PCI card in slot 1. + +LILO config examples: +--------------------- +Using LILO's APPEND command, a string of comma separated identifiers or +integers can be used to configure supported boards. The six values in order +are: + + Enable/Disable this card or Override, + Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2), + EISA/Xem (3), PC/64Xe (4), PC/Xi (5), + Enable/Disable alternate pin arrangement, + Number of ports on this card, + I/O Port where card is configured (in HEX if using string identifiers), + Base of memory window (in HEX if using string identifiers), + +NOTE : PCI boards are auto-detected and configured. Do not attempt to +configure PCI boards with the LILO append comand. If you wish to override +previous configuration data (As set by digiConfig), but you do not wish to +configure any specific card (Example if there are PCI cards in the system) +the following override command will accomplish this: +-> append="digi=2" + +Samples: + append="digiepca=E,PC/Xe,D,16,200,D0000" + or + append="digi=1,0,0,16,512,851968" + +Supporting Tools: +----------------- +Supporting tools include digiDload, digiConfig, buildPCI, and ditty. See +/usr/src/linux/Documentation/README.epca.dir/user.doc for more details. Note, +this driver REQUIRES that digiDload be executed prior to it being used. +Failure to do this will result in an ENODEV error. + +The latest version of the tool package is available at: +ftp://ftp.dgii.com/drivers/linux/released/async/ + +Documentation: +-------------- +Complete documentation for this product may be found in the tool package. + +Sources of information and support: +----------------------------------- +Digi Intl. support site for this product: +-> digilnux@dgii.com + +Related information and information concerning other drivers supporting +Digi Intl. products: + +-> FTP: ftp://dgii.com +-> Webpage: http://www.dgii.com +-> Webpage: http://private.fuller.edu/clameter/digi.html +-> Mailing List: digiboard@list.fuller.edu Note write e-mail to subscribe + common ListServ commands will not work. + +Acknowledgments: +---------------- +Much of this work (And even text) was derived from a similar document +supporting the original public domain DigiBoard driver Copyright (C) +1994,1995 Troy De Jongh. Many thanks to Christoph Lameter +(clameter@fuller.edu) and Mike McLagan (mike.mclagan@linux.org) who authored +and contributed to the original document. + + diff -u --recursive --new-file v2.1.36/linux/Documentation/m68k/00-INDEX linux/Documentation/m68k/00-INDEX --- v2.1.36/linux/Documentation/m68k/00-INDEX Wed Dec 31 16:00:00 1969 +++ linux/Documentation/m68k/00-INDEX Thu May 1 12:05:00 1997 @@ -0,0 +1,9 @@ +00-INDEX + - this file +amiboot.txt + - info and options for the Linux/m68k Amiga bootstrap (Amiboot) +framebuffer.txt + - info about the Linux/m68k frame buffer device +kernel-options.txt + - command line options for Linux/m68k + diff -u --recursive --new-file v2.1.36/linux/Documentation/m68k/amiboot.README linux/Documentation/m68k/amiboot.README --- v2.1.36/linux/Documentation/m68k/amiboot.README Fri Dec 20 01:19:57 1996 +++ linux/Documentation/m68k/amiboot.README Wed Dec 31 16:00:00 1969 @@ -1,241 +0,0 @@ - - Linux/m68k Amiga Bootstrap version 5.1 - -------------------------------------- - - -0. Introduction ---------------- - -Amiboot is used to boot Linux/m68k on Amiga from the CLI/Shell. - -Before you try to boot Linux/m68k for the first time, please read the FAQ - - http://www-agrw.informatik.uni-kl.de/~jmayer/linux68k/linux68k-faq - -and the Installation Guide - - http://www.informatik.uni-oldenburg.de/~amigo/inst.html - -first. Although the Installation Guide is getting a bit outdated, it's still a -good starting point. - -Amiboot 5.1 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo -interface versions 1.x and 2.x). Please use an older version for older kernels. - - -1. Running Amiboot ------------------- - -The Amiboot invocation syntax looks like - - amiboot [options] [kernel command line] - -Valid options are: - - --help Display the usage information - - --kernel file Use kernel image `file' (default is `vmlinux') - - --ramdisk file Use ramdisk image `file'. - - --debug Enable debug mode - - --baud Set the serial port speed (default is 9600) - - --memfile file Use memory file `file' - - --keep-video Don't reset the video mode - - --model id Set the Amiga model to `id'. - -The kernel command line contains the options you want to pass to the kernel and -to init, the process that's started first by Linux. Please read -linux/Documentation/m68k/kernel-options.txt for more information. - -Normally you only use the --kernel option to specify the file that contains the -Linux/m68k kernel image, and --ramdisk if you want to boot from a ramdisk file, -i.e. a file containing a complete file system, instead of from a hard disk -partition. - -Example: - - amiboot -k vmlinux-2.1.13 root=/dev/hda3 video=font:PEARL8x8 - -Amiboot will boot the kernel image `vmlinux-2.1.13' and will pass -`root=/dev/hda3 video=font:PEARL8x8' to the kernel. - - -The other options are more specialized. Don't use them unless you really have -to and you know what you're doing. - -The --baud option allows you to specify the serial port speed for initial boot -information and initial kernel messages. Note: this option does not work with -kernels with bootinfo interface versions prior to 2.0. - -The --memfile option is used to specify the blocks of memory that will be used -by Linux. - -The --keep-video option is necessary if you want to retain the current graphics -mode (on a graphics board) under Linux. Currently this is only useful if you -have a CyberVision 64 graphics board. - -Finally, --model allows you to specify your Amiga model, and --debug is for -debugging purposes. - - -2. The memory file ------------------- - -If you have some non-AutoConfig memory you want to use under Linux, or if you -want to disable some parts of your memory (e.g. Zorro II RAM on '040 based -systems), you have to use a memory file and the --memfile option. This file -contains information about the memory chunks you want to use under Linux. The -format for the file is: - - chipramsize - [0xfastchunkaddr fastchunksize] - [0xfastchunkaddr fastchunksize] - ... - -For example, if you don't want Linux to use your 2nd meg of chipram, you would -create a file that looks contains only: - - 1048576 - -If you had 1M of chip ram, 2M of 16 bit FAST ram at address 0x200000 and 16M of -32 bit FAST ram at address 0x80000000, and you didn't want Linux to use the -slow 16 bit FAST ram, you'd create a file that looks like: - - 1048576 - 0x80000000 16777216 - -The memory file can also be used to specify in which block of memory the kernel -will be put. Normally Amiboot will put the kernel in the first block of Fast -RAM it will find. If you use a memory file, it will put the kernel in the first -block of fast RAM you specify. - - -3. Amiga models ---------------- - -If Amiboot incorrectly detects the model of your Amiga, you can force it to -detect any model you want using the --model option. `id' must be one of the -numbers as defined in linux/include/asm-m68k/amigahw.h (AMI_*). Currently the -following models are known: - - Model ID - ----- -- - Amiga 500 1 - Amiga 500+ 2 - Amiga 600 3 - Amiga 1000 4 - Amiga 1200 5 - Amiga 2000 6 - Amiga 2500 7 - Amiga 3000 8 - Amiga 3000T 9 - Amiga 3000+ 10 - Amiga 4000 11 - Amiga 4000T 12 - CDTV 13 - CD32 14 - Draco 15 - -Note that Amiboot can't distinguish among Amiga models that are very similar to -each other (e.g. A500/A1000/A2000/A2500 and A3000/A3000T). Of course this is -harmless and there's no real need to use --model in that case. - -Please send me the output of amiboot used with the --debug option if your Amiga -model is detected incorrectly. - - -4. Abbreviations ----------------- - -All options also have a shorthand: - - --help -h - --kernel -k - --ramdisk -r - --debug -d - --baud -b - --memfile -m - --keep-video -v - --model -t - - -5. Miscellaneous ----------------- - -Some expansion boards keep on generating interrupts once they were initialized -under AmigaOS. This can cause an interrupt deadlock while booting Linux. The -following boards are recognized and disabled: - - o Helfrich Rainbow 3 Graphics Board - o Helfrich Piccolo Graphics Board - o Helfrich SD64 Graphics Board - o Village Tronic Ariadne Ethernet Board - o Hydra Systems Amiganet Ethernet Board - -The following boards are known to cause problems but we don't have a disable -routine for them yet: - - o Commodore A2060 Arcnet Card - o Ameristar A560 Arcnet Card - -If you write a routine to disable an expansion board, please let me know. - - -6. Troubleshooting ------------------- - - - Amiboot says - - This bootstrap is too old/new for this kernel - - This means that you're using a version of Amiboot that's not compatible - with the kernel you want to boot. - - Solution: use the correct Amiboot, or use another kernel. - - - Amiboot says - - Warning: too many AutoConfig devices. Ignoring device at 0x???????? - - or - - Warning: too many memory blocks. Ignoring block of ???K at 0x???????? - - This means that you have more AutoConfig devices or memory chunks than - Amiboot supports. Note that you can still boot Linux/m68k, but that the - additional devices or memory blocks can't be used. - - Solution: increase the ZORRO_NUM_AUTO (for AutoConfig devices) or - NUM_MEMINFO (for memory chunks) values in the kernel sources - (linux/include/asm-m68k/zorro.h and linux/include/asm-m68k/setup.h) and - recompile both Amiboot and the kernel. - - - If all you get is a grey screen, or if Linux/m68k suddenly locks up during - booting, try the following things: - - o Boot with the Startup-Sequence disabled, run SetPatch and try again. - - o If that doesn't work, remove any expansion devices and retry. - - o Look at the characters that are dumped to the serial port during - booting. - - -7. Amiga-Lilo -------------- - -Once you have a stable Linux/m68k installation, you may want to try Amiga-Lilo. -Amiga-Lilo allows you to boot Linux/m68k without the overhead of booting -AmigaOS first, and it provides you with a boot menu. - - -8. Credits ----------- - -This readme was written by Geert Uytterhoeven. A lot of information was taken -from the ANNOUNCE-* files by Hamish Macdonald. diff -u --recursive --new-file v2.1.36/linux/Documentation/m68k/amiboot.txt linux/Documentation/m68k/amiboot.txt --- v2.1.36/linux/Documentation/m68k/amiboot.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/m68k/amiboot.txt Thu May 1 12:05:00 1997 @@ -0,0 +1,282 @@ + + Linux/m68k Amiga Bootstrap version 5.5 + -------------------------------------- + +Maintained by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) +Last revised: March 27, 1997 + + +0. Introduction +--------------- + +Amiboot is used to boot Linux/m68k on Amiga from the CLI/Shell. + +Before you try to boot Linux/m68k for the first time, please read the FAQ + + http://www.clark.net/pub/lawrencc/linux/faq/faq.html + +and the Installation Guide + + http://www.informatik.uni-oldenburg.de/~amigo/inst.html + +first. Although the Installation Guide is getting a bit outdated, it's still a +good starting point. + +Amiboot 5.5 is meant for Linux/m68k 2.0.x, 2.1.x or higher (kernel bootinfo +interface versions 1.x and 2.x). Please use an older version for older kernels. + + +1. Running Amiboot +------------------ + +The Amiboot invocation syntax looks like + + amiboot [options] [kernel command line] + +Basic options: + + --help Display the usage information + + --kernel file Use kernel image `file' (default is `vmlinux') + + --ramdisk file Use ramdisk image `file' + +Advanced options: + + --debug Enable debug mode + + --baud speed Set the serial port speed (default is 9600 bps) + + --memfile file Use memory file `file' + + --keep-video Don't reset the video mode + + --model id Set the Amiga model to `id' + + --processor cfm Set the processor type to `cfm' + +The kernel command line contains the options you want to pass to the kernel and +to init, the process that's started first by Linux. Please read +linux/Documentation/m68k/kernel-options.txt for more information. + +Normally you only use the --kernel option to specify the file that contains the +Linux/m68k kernel image, and --ramdisk if you want to boot from a ramdisk file, +i.e. a file containing a complete file system, instead of from a hard disk +partition. + +Note that both the kernel image and the ramdisk image can be compressed with +gzip. Amiboot knows how to deal with gzipped kernel images, and the kernel +recognizes gzipped ramdisk images. + +Example: + + amiboot -k vmlinux-2.1.13 root=/dev/hda3 video=font:PEARL8x8 + +Amiboot will boot the kernel image `vmlinux-2.1.13' and will pass +`root=/dev/hda3 video=font:PEARL8x8' to the kernel. + + +The other options are more advanced. Don't use them unless you really have to +and you know what you're doing. + +The --baud option allows you to specify the serial port speed for initial boot +information and initial kernel messages. Note: this option does not work with +kernels with bootinfo interface versions prior to 2.0. + +The --memfile option is used to specify the blocks of memory that will be used +by Linux. + +The --keep-video option is necessary if you want to retain the current graphics +mode (on a graphics board) under Linux. Currently this is only useful if you +have a CyberVision 64 graphics board. + +Finally, --model and --processor allow you to specify your Amiga model and +processor type if they are detected incorrectly, and --debug dumps some +information which simplifies debugging. + + +2. The memory file +------------------ + +If you have some non-AutoConfig memory you want to use under Linux, or if you +want to disable some parts of your memory (e.g. Zorro II RAM on '040 based +systems), you have to use a memory file and the --memfile option. This file +contains information about the memory chunks you want to use under Linux. The +format for the file is: + + chipramsize + [0xfastchunkaddr fastchunksize] + [0xfastchunkaddr fastchunksize] + ... + +For example, if you don't want Linux to use your 2nd meg of chipram, you would +create a file that contains only: + + 1048576 + +If you had 1M of chip ram, 2M of 16 bit FAST ram at address 0x200000 and 16M of +32 bit FAST ram at address 0x80000000, and you didn't want Linux to use the +slow 16 bit FAST ram, you'd create a file that looks like: + + 1048576 + 0x80000000 16777216 + +The memory file can also be used to specify in which block of memory the kernel +will be put. Normally Amiboot will put the kernel in the first block of Fast +RAM it will find. If you use a memory file, it will put the kernel in the first +block of fast RAM you specify. + + +3. Amiga models +--------------- + +If Amiboot incorrectly detects the model of your Amiga, you can force it to +detect any model you want using the --model option. `id' must be one of the +numbers as defined in linux/include/asm-m68k/amigahw.h (AMI_*). Currently the +following models are known: + + Model ID + ----- -- + Amiga 500 1 + Amiga 500+ 2 + Amiga 600 3 + Amiga 1000 4 + Amiga 1200 5 + Amiga 2000 6 + Amiga 2500 7 + Amiga 3000 8 + Amiga 3000T 9 + Amiga 3000+ 10 + Amiga 4000 11 + Amiga 4000T 12 + CDTV 13 + CD32 14 + Draco 15 + +Note that Amiboot can't distinguish among Amiga models that are very similar to +each other (e.g. A500/A1000/A2000/A2500 and A3000/A3000T). Of course this is +harmless and there's no real need to use --model in that case. + +Please send me the output of amiboot used with the --debug option if your Amiga +model is detected incorrectly. + + +4. Processor types +------------------ + +If your processor is detected incorrectly, you can override this using the +`--processor cfm' option. `cfm' must be a three-digit number with + + - `c' the CPU (Central Processing Unit) type, + - 'f' the FPU (Floating Point Unit) type, + - 'm' the MMU (Memory Management Unit) type, + +from the table below: + + value | CPU | FPU | MMU + -------+-------+-------+------- + 0 | - | - | - + 1 | 68020 | 68881 | 68851 + 2 | 68030 | 68882 | 68030 + 3 | 68040 | 68040 | 68040 + 4 | 68060 | 68060 | 68060 + +e.g. `444' if you have a 68060 and `303' if you have a 68LC040. + +Note that normally you don't have to use this option. It's only needed for some +combinations of an old Kickstart ROM and a new processor (e.g. a 68060). + + +5. Abbreviations +---------------- + +All options also have a shorthand: + + --help -h + --kernel -k + --ramdisk -r + --debug -d + --baud -b + --memfile -m + --keep-video -v + --model -t + --processor -p + + +6. Miscellaneous +---------------- + +Some expansion boards keep on generating interrupts once they were initialized +under AmigaOS. This can cause an interrupt deadlock while booting Linux. The +following boards are recognized and disabled: + + o Helfrich Rainbow 3 Graphics Board + o Helfrich Piccolo Graphics Board + o Helfrich SD64 Graphics Board + o Village Tronic Ariadne Ethernet Board + o Hydra Systems Amiganet Ethernet Board + +The following boards are known to cause problems but we don't have a disable +routine for them yet: + + o Commodore A2060 Arcnet Card + o Ameristar A560 Arcnet Card + +If you write a routine to disable an expansion board, please let me know. + + +7. Troubleshooting +------------------ + + - Amiboot says + + This bootstrap is too old/new for this kernel + + This means that you're using a version of Amiboot that's not compatible + with the kernel you want to boot. + + Solution: use the correct Amiboot, or use another kernel. + + - Amiboot says + + Warning: too many AutoConfig devices. Ignoring device at 0x???????? + + or + + Warning: too many memory blocks. Ignoring block of ???K at 0x???????? + + This means that you have more AutoConfig devices or memory chunks than + Amiboot supports. Note that you can still boot Linux/m68k, but that the + additional devices or memory blocks can't be used. + + Solution: increase the ZORRO_NUM_AUTO (for AutoConfig devices) or + NUM_MEMINFO (for memory chunks) values in the kernel sources + (linux/include/asm-m68k/zorro.h and linux/include/asm-m68k/setup.h) and + recompile both Amiboot and the kernel. + + - If all you get is a grey screen, or if Linux/m68k suddenly locks up during + booting, try the following things: + + o Boot with the Startup-Sequence disabled, run SetPatch and try again. + + o If that doesn't work, remove any expansion devices and retry. + + o Check the detected Amiga model and processor type. + + o Look at the characters that are dumped to the serial port during + booting. + + +8. Amiga-Lilo +------------- + +Once you have a stable Linux/m68k installation, you may want to try Amiga-Lilo. +Amiga-Lilo allows you to boot Linux/m68k without the overhead of booting +AmigaOS first, and it provides you with a boot menu. + + +9. Credits +---------- + +This readme was written by Geert Uytterhoeven. A lot of information was taken +from the ANNOUNCE-* files by Hamish Macdonald. diff -u --recursive --new-file v2.1.36/linux/Documentation/m68k/framebuffer.txt linux/Documentation/m68k/framebuffer.txt --- v2.1.36/linux/Documentation/m68k/framebuffer.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/m68k/framebuffer.txt Thu May 1 12:05:00 1997 @@ -0,0 +1,370 @@ + + The Linux/m68k Frame Buffer Device + ---------------------------------- + +Maintained by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) +Last revised: March 23, 1997 + + +0. Introduction +--------------- + +The frame buffer device provides an abstraction for the graphics hardware. It +represents the frame buffer of some video hardware and allows application +software to access the graphics hardware through a well-defined interface, so +the software doesn't need to know anything about the low-level (hardware +register) stuff. + +The device is accessed through special device nodes, usually located in the +/dev directory, i.e. /dev/fb*. + + +1. User's View of /dev/fb* +-------------------------- + +From the user's point of view, the frame buffer device looks just like any +other device in /dev. It's a character device using major 29, the minor is +divided into a frame buffer number in the upper 3 bits (allowing max. 8 frame +buffers simultaneously) and a resolution code in the lower 5 bits of the minor. + +By convention, the following device nodes are used (numbers indicate the device +minor numbers): + + First frame buffer + 0 = /dev/fb0current Current resolution + 1 = /dev/fb0autodetect Default resolution + 2 = /dev/fb0predefined0 Predefined resolutions (22) + ... + 23 = /dev/fb0predefined21 + 24 = /dev/fb0user0 User defined resolutions (8) + ... + 31 = /dev/fb0user7 + + Second frame buffer + 32 = /dev/fb1current Current resolution + 33 = /dev/fb1autodetect Default resolution + 34 = /dev/fb1predefined0 Predefined resolutions (22) + ... + 55 = /dev/fb1predefined21 + 56 = /dev/fb1user0 User defined resolutions (8) + ... + 63 = /dev/fb1user7 + +and so on... + +The device with (minor & 31) == 0 (/dev/fb?current) stands for the frame buffer +together with the currently set video parameters; (minor & 31) == 1 +(/dev/fb?autodetect) is the video mode detected at boot time. Any other minor +stands for some predefined or user defined video mode. + +The predefined entries (/dev/fb?predefined*) usually have a device dependent +name, e.g. for major 29, minor 5, we have /dev/fb0multiscan on Amiga and +/dev/fb0ttmid on Atari. These are meant to contain hardware dependent +resolutions. + +The user defined resolutions (/dev/fb?user?) are meant to be filled in by the +user. This way the user can store his favorite 8 resolutions during boot up. + +Note: if you need more than 8 user defined resolutions, you can always override +the predefined resolutions by storing them in one of the predefined entries. +But this is not recommended. Similarly, if there are more than 22 predefined +resolutions, the device writer can decide to store them in the user defined +entries. + +If the device is opened (for writing), the frame buffer driver switches to the +selected video mode. Thus, you can switch video modes by writing to a frame +buffer device, e.g. + + > /dev/fb0ttlow + +will switch your video to TT low mode. Note: if you specify a resolution which +contains a value that's not possible on your hardware, the frame buffer device +will round it up (if possible) or return an error condition. + +The frame buffer devices are also `normal' memory devices, this means, you can +read and write their contents. You can, for example, make a screen snapshot by + + cp /dev/fb0current myfile + +There also can be more than one frame buffer at a time, e.g. if you have a +graphics card in addition to the built-in hardware. The corresponding frame +buffer devices (/dev/fb0* and /dev/fb1* etc.) work independently. + +Application software that uses the frame buffer device (e.g. the X server) will +use /dev/fb0current by default. You can specify an alternative resolution by +setting the environment variable $FRAMEBUFFER to the path name of a frame +buffer device, e.g. (for sh/bash users): + + export FRAMEBUFFER=/dev/fb0multiscan + +or (for csh users): + + setenv FRAMEBUFFER /dev/fb0multiscan + +After this the X server will use the multiscan video mode. + + +2. Programmer's View of /dev/fb* +-------------------------------- + +As you already know, a frame buffer device is a memory device like /dev/mem and +it has the same features. You can read it, write it, seek to some location in +it and mmap() it (the main usage). The difference is just that the memory that +appears in the special file is not the whole memory, but the frame buffer of +some video hardware. + +/dev/fb* also allows several ioctls on it, by which lots of information about +the hardware can be queried and set. The color map handling works via ioctls, +too. Look into for more information on what ioctls exist and on +which data structures they work. Here's just a brief overview: + + - You can request unchangeable information about the hardware, like name, + organization of the screen memory (planes, packed pixels, ...) and address + and length of the screen memory. + + - You can request and change variable information about the hardware, like + visible and virtual geometry, depth, color map format, timing, and so on. + If you try to change that informations, the driver maybe will round up some + values to meet the hardware's capabilities (or return EINVAL if that isn't + possible). + + - You can get and set parts of the color map. Communication is done with 16 + bit per color part (red, green, blue, transparency) to support all existing + hardware. The driver does all the computations needed to bring it into the + hardware (round it down to less bits, maybe throw away transparency). + +All this hardware abstraction makes the implementation of application programs +easier and more portable. E.g. the X server works completely on /dev/fb* and +thus doesn't need to know, for example, how the color registers of the concrete +hardware are organized. XF68_FBDev is a general X server for bitmapped, +unaccelerated video hardware. The only thing that has to be built into +application programs is the screen organization (bitplanes or chunky pixels +etc.), because it works on the frame buffer image data directly. + +For the future it is planned that frame buffer drivers for graphics cards and +the like can be implemented as kernel modules that are loaded at runtime. Such +a driver just has to call register_framebuffer() and supply some functions. +Writing and distributing such drivers independently from the kernel will save +much trouble... + + +3. Frame Buffer Resolution Maintenance +-------------------------------------- + +Frame buffer resolutions are maintained using the utility `fbset'. It allows to +change the video mode properties of the current or a user defined resolution. +It's main usage is to tune video modes and to store custom resolutions into one +of the /dev/fb?user? entries, e.g. during boot up in one of your /etc/rc.* or +/etc/init.d/* files, after which those resolutions can be used by applications. + +Fbset uses a video mode database stored in a configuration file, so you can +easily add your own modes and refer to them with a simple identifier. The fbset +install script also creates the special device nodes for the device dependent +predefined resolutions. + + +4. The X Server +--------------- + +The X server (XF68_FBDev) is the most notable application program for the frame +buffer device. The current X server is part of the XFree86/XFree68 release 3.2 +package and has 2 modes: + + - If the `Display' subsection for the `fbdev' driver in the /etc/XF86Config + file contains a + + Modes "default" + + line, the X server will use the scheme discussed above, i.e. it will start + up in the resolution determined by /dev/fb0current (or $FRAMEBUFFER, if + set). This is the default for the configuration file supplied with XFree68 + 3.2. It's the most simple configuration (and the only possible one if you + want to have a broadcast compatible display, e.g. PAL or NTSC), but it has + some limitations. + + - Therefore it's also possible to specify resolutions in the /etc/XF86Config + file. This allows for on-the-fly resolution switching while retaining the + same virtual desktop size. The frame buffer device that's used is still + /dev/fb0current (or $FRAMEBUFFER), but the available resolutions are + defined by /etc/XF86Config now. The disadvantage is that you have to + specify the timings in a different format (but `fbset -x' may help) and + that you can't have a broadcast compatible display (e.g. no PAL or NTSC). + +To tune a video mode, you can use fbset or xvidtune. Note that xvidtune doesn't +work 100% with XF68_FBDev: the reported clock values are always incorrect. + +There exists also an accelerated X server for the Cybervision 64 graphics +board, but that's not discussed here. + + +5. Video Mode Timings +--------------------- + +A monitor draws an image on the screen by using an electron beam (3 electron +beams for most color models, 1 electron beam for Trinitron color monitors and +monochrone monitors). The front of the screen is covered by a pattern of +colored phospors (pixels). If a phospor is hit by an electron, it emits a +photon and thus becomes visible. + +The electron beam draws horizontal lines (scanlines) from left to right, and +from the top to the bottom of the screen. By modifying the intensity of the +electron beam, pixels with various colors and intensities can be shown. + +After each scanline the electron beam has to move back to the left side of the +screen and to the next line: this is called the horizontal retrace. After the +whole screen (frame) was painted, the beam moves back to the upper left corner: +this is called the vertical retrace. During both the horizontal and vertical +retrace, the electron beam is turned off (blanked). + +The speed at which the electron beam paints the pixels is determined by the +dotclock in the graphics board. For a dotclock of e.g. 28.37516 MHz (millions +of cycles per second), each pixel is 35242 ps (picoseconds) long: + + 1/(28.37516E6 Hz) = 35.242E-9 s + +If the screen resolution is 640x480, it will take + + 640*35.242E-9 s = 22.555E-6 s + +to paint the 640 (xres) pixels on one scanline. But the horizontal retrace +also takes time (e.g. 272 `pixels'), so a full scanline takes + + (640+272)*35.242E-9 s = 32.141E-6 s + +We'll say that the horizontal scanrate is about 31 kHz: + + 1/(32.141E-6 s) = 31.113E3 Hz + +A full screen counts 480 (yres) lines, but we have to consider the vertical +retrace too (e.g. 49 `pixels'). So a full screen will take + + (480+49)*32.141E-6 s = 17.002E-3 s + +The vertical scanrate is about 59 Hz: + + 1/(17.002E-3 s) = 58.815 Hz + +This means the screen data is refreshed about 59 times per second. To have a +stable picture without visible flicker, VESA recommends a vertical scanrate of +at least 72 Hz. But the perceived flicker is very human dependent: some people +can use 50 Hz without any trouble, while I'll notice if it's less than 80 Hz. + +Since the monitor doesn't know when a new scanline starts, the graphics board +will supply a synchronization pulse (horizontal sync or hsync) for each +scanline. Similarly it supplies a synchronization pulse (vertical sync or +vsync) for each new frame. The position of the image on the screen is +influenced by the moments at which the synchronization pulses occur. + +The following picture summarizes all timings. The horizontal retrace time is +the sum of the left margin, the right margin and the hsync length, while the +vertical retrace time is the sum of the upper margin, the lower margin and the +vsync length. + + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |upper_margin | | | + | | ¥ | | | + +----------###############################################----------+-------+ + | # ^ # | | + | # | # | | + | # | # | | + | # | # | | + | left # | # right | hsync | + | margin # | xres # margin | len | + |<-------->#<---------------+--------------------------->#<-------->|<----->| + | # | # | | + | # | # | | + | # | # | | + | # |yres # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # ¥ # | | + +----------###############################################----------+-------+ + | | ^ | | | + | | |lower_margin | | | + | | ¥ | | | + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |vsync_len | | | + | | ¥ | | | + +----------+---------------------------------------------+----------+-------+ + +The frame buffer device expects all horizontal timings in number of dotclocks +(in picoseconds, 1E-12 s), and vertical timings in number of scanlines. + + +6. Converting XFree86 timing values info frame buffer device timings +-------------------------------------------------------------------- + +An XFree86 mode line consists of the following fields: + "800x600" 50 800 856 976 1040 600 637 643 666 + < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL + +The frame buffer device uses the following fields: + + - pixclock: pixel clock in ps (pico seconds) + - left_margin: time from sync to picture + - right_margin: time from picture to sync + - upper_margin: time from sync to picture + - lower_margin: time from picture to sync + - hsync_len: length of horizontal sync + - vsync_len: length of vertical sync + +1) Pixelclock: + xfree: in MHz + fb: In Picoseconds (ps) + + pixclock = 1000000 / DCF + +2) horizontal timings: + left_margin = HFL - SH2 + right_margin = SH1 - HR + hsync_len = SH2 - SH1 + +3) vertical timings: + upper_margin = VFL - SV2 + lower_margin = SV1 - VR + vsync_len = SV2 - SV1 + +Good examples for VESA timings can be found in the XFree86 source tree, +under "xc/programs/Xserver/hw/xfree86/doc/modeDB.txt". + + +7. References +------------- + +For more specific information about the frame buffer device and its +applications, please refer to the following documentation: + + - The manual pages for fbset: fbset(8), fb.modes(5) + - The manual pages for XFree68: XF68_FBDev(1), XF86Config(4/5) + - The mighty kernel sources: + o linux/include/linux/fb.h + o linux/drivers/char/fbmem.c + o linux/arch/m68k/*/*fb.c + + +8. Downloading +-------------- + +All necessary files can be found at + + ftp://ftp.uni-erlangen.de/pub/Linux/LOCAL/680x0/ + +and on its mirrors. + + +9. Credits +---------- + +This readme was written by Geert Uytterhoeven, partly based on the original +`X-framebuffer.README' by Roman Hodek and Martin Schaller. Section 6 was +provided by Frank Neumann. + +The frame buffer device abstraction was designed by Martin Schaller. diff -u --recursive --new-file v2.1.36/linux/Documentation/m68k/kernel-options.txt linux/Documentation/m68k/kernel-options.txt --- v2.1.36/linux/Documentation/m68k/kernel-options.txt Fri Dec 20 01:19:57 1996 +++ linux/Documentation/m68k/kernel-options.txt Thu May 1 12:05:00 1997 @@ -800,6 +800,18 @@ No argument. Used to separate blocks of keywords when there's more than one host adapter in the system. +5.3.7) nodma +------------ + +Syntax: nodma:x + + If x is 1 (or if the option is just written as "nodma"), the WD33c93 +controller will not use DMA (= direct memory access) to access the +Amiga's memory. This is useful for some systems (like A3000's and +A4000's with the A3640 accelerator, revision 3.0) that have problems +using DMA to chip memory. The default is 0, i.e. to use DMA if +possible. + 5.4) gvp11= ----------- diff -u --recursive --new-file v2.1.36/linux/Documentation/networking/net-modules.txt linux/Documentation/networking/net-modules.txt --- v2.1.36/linux/Documentation/networking/net-modules.txt Sat Dec 21 03:16:57 1996 +++ linux/Documentation/networking/net-modules.txt Thu May 1 12:05:00 1997 @@ -109,6 +109,10 @@ 8390.c: (No public options, several other modules need this one) +a2065.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) + ac3200.c: io = 0 (Checks 0x1000 to 0x8fff in 0x1000 intervals) irq = 0 (Read from config register) @@ -133,11 +137,24 @@ 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370, 0x380, 0x390, 0x3A0, 0x3E0, 0x3F0 ) +ariadne.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) + at1700.c: io = 0x260 irq = 0 (Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300) +atari_bionet.c: + Supports full autoprobing. (m68k/Atari) + +atari_pamsnet.c: + Supports full autoprobing. (m68k/Atari) + +atarilance.c: + Supports full autoprobing. (m68k/Atari) + atp.c: *Not modularized* (Probes ports: 0x378, 0x278, 0x3BC; fixed IRQs: 5 and 7 ) @@ -211,6 +228,10 @@ (Does EISA-probing, if on EISA-slot; On ISA-bus probes all ports from 0x100 thru to 0x3E0 in increments of 0x020) + +hydra.c: + Since this is a Zorro board, it supports full autoprobing, even for + multiple boards. (m68k/Amiga) ibmtr.c: io = 0xa20, 0xa24 (autoprobed by default) diff -u --recursive --new-file v2.1.36/linux/Documentation/serial-console.txt linux/Documentation/serial-console.txt --- v2.1.36/linux/Documentation/serial-console.txt Sun Feb 2 05:18:29 1997 +++ linux/Documentation/serial-console.txt Thu May 1 12:05:00 1997 @@ -47,7 +47,7 @@ Sysvinit remembers its stty settings in a file in /etc, called `/etc/ioctl.save'. REMOVE THIS FILE before using the serial console for the first time, because otherwise init will probably - set the baudrate to 38400 (bausdrate of the virtual console). + set the baudrate to 38400 (baudrate of the virtual console). 5. /dev/console and X Programs that want to do something with the virtual console usually diff -u --recursive --new-file v2.1.36/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.36/linux/MAINTAINERS Sun Apr 13 10:18:20 1997 +++ linux/MAINTAINERS Sun May 4 20:46:13 1997 @@ -336,11 +336,12 @@ W: http://www-plateau.cs.berkeley.edu/people/chaffee S: Maintained -DIGIBOARD DRIVER: -P: Christoph Lameter -M: clameter@fuller.edu -L: digiboard@list.fuller.edu -S: Maintained +DIGI INTL. EPCA DRIVER: +P: Daniel Taylor +M: support@dgii.com +M: digilnux@dgii.com +L: digiboard@list.fuller.edu +S: Maintained RISCOM8 DRIVER: P: Dmitry Gorodchanin diff -u --recursive --new-file v2.1.36/linux/Makefile linux/Makefile --- v2.1.36/linux/Makefile Wed Apr 23 19:01:14 1997 +++ linux/Makefile Thu May 1 12:32:45 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 36 +SUBLEVEL = 37 ARCH := $(shell uname -m | sed s/i.86/i386/) @@ -352,6 +352,8 @@ rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS + rm -f drivers/sound/Config.in + cp drivers/sound/Config.std drivers/sound/Config.in backup: mrproper cd .. && tar cf - linux/ | gzip -9 > backup.gz diff -u --recursive --new-file v2.1.36/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.1.36/linux/arch/alpha/defconfig Wed Apr 16 14:14:59 1997 +++ linux/arch/alpha/defconfig Sun May 4 17:51:05 1997 @@ -42,6 +42,13 @@ CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_EM86=y +# CONFIG_PNP_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set # # Floppy, IDE, and other block devices @@ -72,9 +79,10 @@ # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set CONFIG_INET=y -# CONFIG_IP_FORWARD is not set # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ACCT is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set # # (it is safe to leave these untouched) @@ -133,7 +141,6 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_PPA is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_QLOGIC_FAS is not set CONFIG_SCSI_QLOGIC_ISP=y @@ -155,19 +162,22 @@ # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y +# CONFIG_PCNET32 is not set # CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set CONFIG_DE4X5=y # CONFIG_DEC_ELCP is not set # CONFIG_DGRS is not set +# CONFIG_EEXPRESS_PRO100 is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set -# CONFIG_LAPBETHER is not set # CONFIG_SLIP is not set # CONFIG_TR is not set +# CONFIG_LAPBETHER is not set +# CONFIG_X25_ASY is not set # # ISDN subsystem @@ -192,12 +202,16 @@ CONFIG_PROC_FS=y CONFIG_NFS_FS=y # CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y # CONFIG_SMB_FS is not set CONFIG_ISO9660_FS=y # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ROMFS_FS is not set +# CONFIG_AUTOFS_FS is not set # CONFIG_UFS_FS is not set # @@ -206,12 +220,8 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y -# CONFIG_DIGI is not set -# CONFIG_CYCLADES is not set -# CONFIG_STALDRV is not set -# CONFIG_RISCOM8 is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_PRINTER is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set CONFIG_MOUSE=y # CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set @@ -224,7 +234,6 @@ # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set -CONFIG_RTC_ARC=y # # Sound diff -u --recursive --new-file v2.1.36/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.1.36/linux/arch/alpha/kernel/entry.S Wed Apr 23 19:01:14 1997 +++ linux/arch/alpha/kernel/entry.S Thu May 1 11:06:33 1997 @@ -126,7 +126,8 @@ .ent entInt entInt: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entInt br $31,ret_from_sys_call .end entInt @@ -147,7 +148,8 @@ stq $15,48($30) addq $30,56,$19 /* handle the fault */ - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_page_fault /* reload the registers after the exception code played. */ ldq $9,0($30) @@ -167,7 +169,8 @@ .ent entArith entArith: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 /* How much of a win is this clockwise? We are, after all, messing up the call/return prefetch stack. -- rth */ lda $27,do_entArith @@ -180,7 +183,8 @@ .ent entIF entIF: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 lda $27,do_entIF lda $26,ret_from_sys_call jsr $31,($27),do_entIF @@ -221,12 +225,13 @@ .globl __kernel_thread .ent __kernel_thread __kernel_thread: + ldgp $29,0($27) /* we can be called from a module */ .frame $30, 4*8, $26 subq $30,4*8,$30 stq $10,16($30) stq $9,8($30) stq $26,0($30) - .prologue 0 + .prologue 1 bis $17,$17,$9 /* save fn */ bis $18,$18,$10 /* save arg */ bsr $26,kernel_clone @@ -238,10 +243,9 @@ ret $31,($26),1 /* this is in child: look out as we don't have any stack here.. */ 1: bis $9,$9,$27 /* get fn */ - br $29,2f -2: ldgp $29,0($29) + lda $8,0x3fff bis $10,$10,$16 /* get arg */ - ldq $8,current_set + bic $30,$8,$8 /* get current */ jsr $26,($27) bis $0,$0,$16 jsr $26,sys_exit @@ -382,7 +386,8 @@ stq $29,232($30) stq $30,240($30) stq $31,248($30) - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entUna ldq $0,0($30) ldq $1,8($30) @@ -432,7 +437,8 @@ stq $14,40($30) stq $15,48($30) bis $31,$30,$19 - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 jsr $26,do_entUnaUser ldq $9,0($30) ldq $10,8($30) @@ -497,7 +503,8 @@ .ent entSys entSys: SAVE_ALL - ldq $8,current_set + lda $8,0x3fff + bic $30,$8,$8 lda $4,NR_SYSCALLS($31) stq $16,SP_OFF+24($30) lda $5,sys_call_table @@ -532,7 +539,7 @@ ret_from_reschedule: lda $0,need_resched ldl $2,0($0) - lda $4,init_task + lda $4,init_task_union bne $2,reschedule xor $4,$8,$4 beq $4,restore_all diff -u --recursive --new-file v2.1.36/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S --- v2.1.36/linux/arch/alpha/kernel/head.S Wed Apr 16 14:14:59 1997 +++ linux/arch/alpha/kernel/head.S Mon May 5 08:16:41 1997 @@ -23,9 +23,11 @@ __start: br $27,1f 1: ldgp $29,0($27) - /* We need to get current loaded up with our first task. */ - ldq $8,current_set - /* And then we can start the kernel. */ + /* We need to get current loaded up with our first task... */ + lda $8,init_task_union + /* ... and find our stack ... */ + lda $30,0x4000($8) + /* ... and then we can start the kernel. */ jsr $26,start_kernel halt .end __start @@ -61,22 +63,6 @@ call_pal PAL_rdusp ret ($26) .end rdusp - - .align 3 - .globl tbi - .ent tbi -tbi: - call_pal PAL_tbi - ret ($26) - .end tbi - - .align 3 - .globl imb - .ent imb -imb: - call_pal PAL_imb - ret ($26) - .end imb .align 3 .globl rdmces diff -u --recursive --new-file v2.1.36/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.1.36/linux/arch/alpha/kernel/process.c Wed Apr 23 19:01:14 1997 +++ linux/arch/alpha/kernel/process.c Thu May 1 11:06:33 1997 @@ -37,6 +37,24 @@ #include #include #include +#include + +/* + * Initial task structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ + +unsigned long init_user_stack[1024] = { STACK_MAGIC, }; +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +union task_union init_task_union __attribute__((section("init_task"))) + = { task: INIT_TASK }; /* * No need to acquire the kernel lock, we're entirely local.. @@ -186,7 +204,7 @@ stack_offset = PAGE_SIZE - sizeof(struct pt_regs); if (!(regs->ps & 8)) stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; - childregs = (struct pt_regs *) (p->kernel_stack_page + stack_offset); + childregs = (struct pt_regs *) (stack_offset + PAGE_SIZE + (unsigned long)p); *childregs = *regs; childregs->r0 = 0; diff -u --recursive --new-file v2.1.36/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.1.36/linux/arch/alpha/kernel/ptrace.c Sun Jan 26 03:40:45 1997 +++ linux/arch/alpha/kernel/ptrace.c Thu May 1 11:06:33 1997 @@ -67,7 +67,7 @@ * | | | * | | v * +================================+ <------------------------- - * task->kernel_stack_page + * task + PAGE_SIZE */ #define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + (long)&((struct pt_regs *)0)->reg) @@ -107,19 +107,6 @@ static long zero; - -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * Get contents of register REGNO in task TASK. */ @@ -133,7 +120,7 @@ zero = 0; addr = &zero; } else { - addr = (long *) (task->kernel_stack_page + regoff[regno]); + addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task); } return *addr; } @@ -150,7 +137,7 @@ } else if (regno == 31) { addr = &zero; } else { - addr = (long *) (task->kernel_stack_page + regoff[regno]); + addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task); } *addr = data; return 0; @@ -507,7 +494,7 @@ if (pid == 1) /* you may not mess with init */ goto out; ret = -ESRCH; - if (!(child = get_task(pid))) + if (!(child = find_task_by_pid(pid))) goto out; if (request == PTRACE_ATTACH) { ret = -EPERM; diff -u --recursive --new-file v2.1.36/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.1.36/linux/arch/alpha/kernel/setup.c Wed Apr 16 14:14:59 1997 +++ linux/arch/alpha/kernel/setup.c Thu May 1 11:06:33 1997 @@ -21,9 +21,9 @@ #include #include #include /* CONFIG_ALPHA_LCA etc */ +#include #ifdef CONFIG_RTC -#include #include #endif diff -u --recursive --new-file v2.1.36/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.1.36/linux/arch/alpha/mm/init.c Wed Apr 23 19:01:14 1997 +++ linux/arch/alpha/mm/init.c Thu May 1 11:06:33 1997 @@ -133,7 +133,6 @@ init_task.tss.ptbr = newptbr; init_task.tss.pal_flags = 1; /* set FEN, clear everything else */ init_task.tss.flags = 0; - init_task.kernel_stack_page = INIT_STACK; load_PCB(&init_task.tss); flush_tlb_all(); @@ -182,7 +181,7 @@ atomic_set(&mem_map[MAP_NR(addr)].count, 1); free_page(addr); } - printk ("Freeing unused kernel memory: %dk freed\n", + printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } diff -u --recursive --new-file v2.1.36/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds --- v2.1.36/linux/arch/alpha/vmlinux.lds Wed Apr 23 19:01:14 1997 +++ linux/arch/alpha/vmlinux.lds Thu May 1 11:06:33 1997 @@ -5,6 +5,7 @@ . = 0xfffffc0000310000; _text = .; .text : { *(.text) } + .text2 : { *(.text2) } _etext = .; /* Exception table */ @@ -25,8 +26,11 @@ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } - . = ALIGN(8192); + . = ALIGN(2*8192); /* Align double page for init_task_union */ __init_end = .; + + /* The initial task and kernel stack */ + init_task : { *(init_task) } /* Global data */ _data = .; diff -u --recursive --new-file v2.1.36/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v2.1.36/linux/arch/i386/Makefile Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/Makefile Sun May 4 09:29:39 1997 @@ -45,7 +45,7 @@ CFLAGS := $(CFLAGS) -D__SMP__ endif -HEAD := arch/i386/kernel/head.o +HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o SUBDIRS := $(SUBDIRS) arch/i386/kernel arch/i386/mm arch/i386/lib CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES) @@ -85,7 +85,7 @@ @$(MAKEBOOT) BOOTIMAGE=bzImage zdisk install: vmlinux - @$(MAKEBOOT) install + @$(MAKEBOOT) BOOTIMAGE=zImage install archclean: @$(MAKEBOOT) clean diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.1.36/linux/arch/i386/kernel/Makefile Sun Jan 26 02:07:04 1997 +++ linux/arch/i386/kernel/Makefile Sun Apr 27 16:38:00 1997 @@ -15,7 +15,7 @@ $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o endif -all: kernel.o head.o +all: kernel.o head.o init_task.o O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \ diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.1.36/linux/arch/i386/kernel/bios32.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/bios32.c Thu May 1 12:05:00 1997 @@ -52,6 +52,9 @@ * Feb 3, 1997 : Set internal functions to static, save/restore flags * avoid dead locks reading broken PCI BIOS, werner@suse.de * + * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS + * (mj@atrey.karlin.mff.cuni.cz) + * */ #include @@ -173,10 +176,10 @@ case 0: return address + entry; case 0x80: /* Not present */ - printk("bios32_service(%ld) : not present\n", service); + printk("bios32_service(0x%lx) : not present\n", service); return 0; default: /* Shouldn't happen */ - printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n", + printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n", service, return_code); return 0; } @@ -189,7 +192,7 @@ } pci_indirect = { 0, KERNEL_CS }; -__initfunc(static unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end)) +__initfunc(static int check_pcibios(void)) { unsigned long signature; unsigned char present_status; @@ -212,7 +215,7 @@ : "1" (PCIBIOS_PCI_BIOS_PRESENT), "D" (&pci_indirect) : "bx", "cx"); - restore_flags(flags); + restore_flags(flags); present_status = (pack >> 16) & 0xff; major_revision = (pack >> 8) & 0xff; @@ -232,9 +235,10 @@ if (pcibios_entry) { printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n", major_revision, minor_revision, pcibios_entry); + return 1; } } - return memory_start; + return 0; } @@ -912,13 +916,11 @@ bios32_entry = check->fields.entry; printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); bios32_indirect.address = bios32_entry + PAGE_OFFSET; - access_pci = &pci_bios_access; } } } - if (bios32_entry) { - memory_start = check_pcibios (memory_start, memory_end); - } + if (bios32_entry && check_pcibios()) + access_pci = &pci_bios_access; #endif return memory_start; } diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.1.36/linux/arch/i386/kernel/entry.S Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/entry.S Tue Apr 29 09:11:59 1997 @@ -110,62 +110,45 @@ addl $4,%esp; \ iret -#ifdef __SMP__ -/* Get the processor ID multiplied by 4 */ -#define GET_PROCESSOR_OFFSET(reg) \ - movl SYMBOL_NAME(apic_reg), reg; \ - movl 32(reg), reg; \ - shrl $22, reg; \ - andl $0x3C, reg; - -#define GET_CURRENT(reg) \ - GET_PROCESSOR_OFFSET(reg) \ - movl SYMBOL_NAME(current_set)(reg),reg - -#else - #define GET_CURRENT(reg) \ - movl SYMBOL_NAME(current_set),reg - -#endif + movl %esp, reg; \ + andl $-8192, reg; ENTRY(lcall7) pushfl # We get a different stack layout with call gates, pushl %eax # which has to be cleaned up later.. SAVE_ALL - GET_CURRENT(%ebx) movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # - movl %esp,%eax - GET_CURRENT(%edx) - pushl %eax - movl exec_domain(%edx),%edx # Get the execution domain + movl %esp,%ebx + pushl %ebx + andl $-8192,%ebx # GET_CURRENT + movl exec_domain(%ebx),%edx # Get the execution domain movl 4(%edx),%edx # Get the lcall7 handler for the domain call *%edx popl %eax jmp ret_from_sys_call + #ifdef __SMP__ ALIGN .globl ret_from_smpfork ret_from_smpfork: + GET_CURRENT(%ebx) btrl $0, SYMBOL_NAME(scheduler_lock) jmp ret_from_sys_call #endif /* __SMP__ */ - ALIGN -handle_bottom_half: - pushl $2f - jmp SYMBOL_NAME(do_bottom_half) - - ALIGN -reschedule: - pushl $ret_from_sys_call - jmp SYMBOL_NAME(schedule) # test +/* + * Return to user mode is not as complex as all this looks, + * but we want the default path for a system call return to + * go as quickly as possible which is why some of this is + * less clear than it otherwise should be. + */ ENTRY(system_call) pushl %eax # save orig_eax @@ -180,16 +163,11 @@ ALIGN .globl ret_from_sys_call .globl ret_from_intr -ret_from_intr: ret_from_sys_call: - GET_CURRENT(%ebx) movl SYMBOL_NAME(bh_mask),%eax andl SYMBOL_NAME(bh_active),%eax jne handle_bottom_half -2: movl EFLAGS(%esp),%eax # mix EFLAGS and CS - movb CS(%esp),%al - testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor? - je 1f +ret_with_reschedule: cmpl $0,SYMBOL_NAME(need_resched) jne reschedule movl blocked(%ebx),%eax @@ -197,7 +175,6 @@ notl %eax andl signal(%ebx),%eax jne signal_return -1: RESTORE_ALL ALIGN signal_return: @@ -230,6 +207,30 @@ movl $-ENOSYS,EAX(%esp) jmp ret_from_sys_call + ALIGN +ret_from_exception: + movl SYMBOL_NAME(bh_mask),%eax + andl SYMBOL_NAME(bh_active),%eax + jne handle_bottom_half + ALIGN +ret_from_intr: + GET_CURRENT(%ebx) + movl EFLAGS(%esp),%eax # mix EFLAGS and CS + movb CS(%esp),%al + testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor? + jne ret_with_reschedule + RESTORE_ALL + + ALIGN +handle_bottom_half: + pushl $ret_from_intr + jmp SYMBOL_NAME(do_bottom_half) + + ALIGN +reschedule: + pushl $ret_from_sys_call + jmp SYMBOL_NAME(schedule) # test + ENTRY(divide_error) pushl $0 # no error code @@ -260,7 +261,7 @@ GET_CURRENT(%ebx) call *%ecx addl $8,%esp - jmp ret_from_sys_call + jmp ret_from_exception ENTRY(coprocessor_error) pushl $0 @@ -271,7 +272,7 @@ pushl $-1 # mark this as an int SAVE_ALL GET_CURRENT(%ebx) - pushl $ret_from_sys_call + pushl $ret_from_exception movl %cr0,%eax testl $0x4,%eax # EM (math emulation bit) je SYMBOL_NAME(math_state_restore) diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.1.36/linux/arch/i386/kernel/head.S Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/head.S Fri May 2 16:32:02 1997 @@ -39,19 +39,21 @@ jz 1f /* * New page tables may be in 4Mbyte page mode and may - * be using the global pages. + * be using the global pages. + * + * NOTE! We have to correct for the fact that we're + * not yet offset 0xC0000000.. */ +#define cr4_bits mmu_cr4_features-0xC0000000 #ifdef GAS_KNOWS_CR4 movl %cr4,%eax # Turn on 4Mb pages - orl $16+128,%eax + orl cr4_bits,%eax movl %eax,%cr4 #else .byte 0x0f,0x20,0xe0 - orl $16+128,%eax + orl cr4_bits,%eax .byte 0x0f,0x22,0xe0 #endif - movl %eax,%cr3 /* flush TLB as per app note */ - movl %cr0,%eax #endif /* * Setup paging (the tables are already set up, just switch them on) @@ -67,24 +69,16 @@ movl $1f,%eax jmp *%eax /* make sure eip is relocated */ 1: + /* Set up the stack pointer */ + lss stack_start,%esp #ifdef __SMP__ orw %bx,%bx jz 1f /* Initial CPU cleans BSS */ -/* - * Set up the stack - */ - movl $(KERNEL_DS),%eax /* walken modif */ - mov %ax,%ss - xorl %eax,%eax - movw %cx, %ax - movl %eax,%esp - addl $0xC0000000, %esp /* shift it to the upper mapping */ pushl $0 popfl jmp checkCPUtype 1: - lss stack_start,%esp #endif __SMP__ /* * Clear BSS first so that there are no surprises... @@ -305,15 +299,53 @@ jne rp_sidt ret +ENTRY(stack_start) + .long SYMBOL_NAME(init_task_union)+8192 + .long KERNEL_DS + +/* This is the default interrupt "handler" :-) */ +int_msg: + .asciz "Unknown interrupt\n" + ALIGN +ignore_int: + cld + pushl %eax + pushl %ecx + pushl %edx + push %ds + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + pushl $int_msg + call SYMBOL_NAME(printk) + popl %eax + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +/* + * The interrupt descriptor table has room for 256 idt's + */ + ALIGN +.word 0 +idt_descr: + .word 256*8-1 # idt contains 256 entries + .long SYMBOL_NAME(idt) + + ALIGN +.word 0 +gdt_descr: +#ifdef CONFIG_APM + .word (11+2*NR_TASKS)*8-1 +#else + .word (8+2*NR_TASKS)*8-1 +#endif + .long SYMBOL_NAME(gdt) /* - * page 0 is made non-existent, so that kernel NULL pointer references get - * caught. Thus the swapper page directory has been moved to 0x101000 - * with the introduction of the compressed boot code. Theoretically, - * the original design of overlaying the startup code with the swapper - * page directory is still possible --- it would reduce the size of the kernel - * by 2-3k. This would be a good thing to do at some point..... - * * This is initialized to create a identity-mapping at 0-4M (for bootup * purposes) and another mapping of the 0-4M area at virtual address * 0xC0000000. @@ -471,63 +503,29 @@ ENTRY(empty_zero_page) .org 0x6000 - -stack_start: - .long SYMBOL_NAME(init_user_stack)+4096 - .long KERNEL_DS - -/* This is the default interrupt "handler" :-) */ -int_msg: - .asciz "Unknown interrupt\n" - ALIGN -ignore_int: - cld - pushl %eax - pushl %ecx - pushl %edx - push %ds - push %es - push %fs - movl $(KERNEL_DS),%eax - mov %ax,%ds - mov %ax,%es - mov %ax,%fs - pushl $int_msg - call SYMBOL_NAME(printk) - popl %eax - pop %fs - pop %es - pop %ds - popl %edx - popl %ecx - popl %eax - iret +ENTRY(this_must_match_init_task) /* - * The interrupt descriptor table has room for 256 idt's + * This starts the data section. Note that the above is all + * in the text section because it has alignment requirements + * that we cannot fulfill any other way. */ - ALIGN -.word 0 -idt_descr: - .word 256*8-1 # idt contains 256 entries - .long SYMBOL_NAME(idt) +.data +ALIGN +/* 256 quadwords - 2048 bytes of idt */ ENTRY(idt) .fill 256,8,0 # idt is uninitialized - ALIGN -.word 0 -gdt_descr: -#ifdef CONFIG_APM - .word (11+2*NR_TASKS)*8-1 -#else - .word (8+2*NR_TASKS)*8-1 -#endif - .long SYMBOL_NAME(gdt) - /* * This gdt setup gives the kernel a 1GB address space at virtual * address 0xC0000000 - space enough for expansion, I hope. + * + * This contains up to 8192 quadwords depending on NR_TASKS - 64kB of + * gdt entries. Ugh. + * + * NOTE! Make sure the gdt descriptor in head.S matches this if you + * change anything. */ ENTRY(gdt) .quad 0x0000000000000000 /* NULL descriptor */ diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.1.36/linux/arch/i386/kernel/i386_ksyms.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/i386_ksyms.c Tue Apr 29 10:00:14 1997 @@ -39,12 +39,13 @@ #ifdef __SMP__ EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */ EXPORT_SYMBOL(cpu_data); -EXPORT_SYMBOL(kernel_flag); -EXPORT_SYMBOL(active_kernel_processor); +EXPORT_SYMBOL_NOVERS(kernel_flag); +EXPORT_SYMBOL_NOVERS(active_kernel_processor); EXPORT_SYMBOL(smp_invalidate_needed); EXPORT_SYMBOL_NOVERS(__lock_kernel); /* Global SMP irq stuff */ +EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(__global_cli); EXPORT_SYMBOL(__global_sti); diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c --- v2.1.36/linux/arch/i386/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/kernel/init_task.c Sun Apr 27 16:40:09 1997 @@ -0,0 +1,22 @@ +#include +#include + +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +/* + * Initial task structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by making sure + * the linker maps this in the .text segment right after head.S, + * and making head.S ensure the proper alignment. + * + * The things we do for performance.. + */ +union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.36/linux/arch/i386/kernel/irq.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/irq.c Thu May 1 21:16:27 1997 @@ -44,9 +44,6 @@ #define CR0_NE 32 -static unsigned char cache_21 = 0xff; -static unsigned char cache_A1 = 0xff; - unsigned int local_irq_count[NR_CPUS]; #ifdef __SMP__ atomic_t __intel_bh_counter; @@ -58,51 +55,84 @@ static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},}; #endif -static inline void mask_irq(unsigned int irq_nr) -{ - unsigned char mask; +/* + * This contains the irq mask for both irq controllers + */ +static unsigned int cached_irq_mask = 0xffff; + +#define cached_21 (((char *)(&cached_irq_mask))[0]) +#define cached_A1 (((char *)(&cached_irq_mask))[1]) - mask = 1 << (irq_nr & 7); - if (irq_nr < 8) { - cache_21 |= mask; - outb(cache_21,0x21); +spinlock_t irq_controller_lock; + +/* + * This is always called from an interrupt context + * with local interrupts disabled. Don't worry about + * irq-safe locks. + * + * Note that we always ack the primary irq controller, + * even if the interrupt came from the secondary, as + * the primary will still have routed it. Oh, the joys + * of PC hardware. + */ +static inline void mask_and_ack_irq(int irq_nr) +{ + spin_lock(&irq_controller_lock); + cached_irq_mask |= 1 << irq_nr; + if (irq_nr & 8) { + inb(0xA1); /* DUMMY */ + outb(cached_A1,0xA1); + outb(0x20,0xA0); } else { - cache_A1 |= mask; - outb(cache_A1,0xA1); + inb(0x21); /* DUMMY */ + outb(cached_21,0x21); } + outb(0x20,0x20); + spin_unlock(&irq_controller_lock); } -static inline void unmask_irq(unsigned int irq_nr) +static inline void set_irq_mask(int irq_nr) { - unsigned char mask; - - mask = ~(1 << (irq_nr & 7)); - if (irq_nr < 8) { - cache_21 &= mask; - outb(cache_21,0x21); + if (irq_nr & 8) { + outb(cached_A1,0xA1); } else { - cache_A1 &= mask; - outb(cache_A1,0xA1); + outb(cached_21,0x21); } } +/* + * These have to be protected by the spinlock + * before being called. + */ +static inline void mask_irq(unsigned int irq_nr) +{ + cached_irq_mask |= 1 << irq_nr; + set_irq_mask(irq_nr); +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + cached_irq_mask &= ~(1 << irq_nr); + set_irq_mask(irq_nr); +} + void disable_irq(unsigned int irq_nr) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&irq_controller_lock, flags); mask_irq(irq_nr); - restore_flags(flags); + spin_unlock_irqrestore(&irq_controller_lock, flags); + synchronize_irq(); } void enable_irq(unsigned int irq_nr) { unsigned long flags; - save_flags(flags); - cli(); + + spin_lock_irqsave(&irq_controller_lock, flags); unmask_irq(irq_nr); - restore_flags(flags); + spin_unlock_irqrestore(&irq_controller_lock, flags); } /* @@ -133,7 +163,8 @@ #error make irq stub building NR_IRQS dependent and remove me. #endif -BUILD_TIMER_IRQ(FIRST,0,0x01) +BUILD_COMMON_IRQ() +BUILD_IRQ(FIRST,0,0x01) BUILD_IRQ(FIRST,1,0x02) BUILD_IRQ(FIRST,2,0x04) BUILD_IRQ(FIRST,3,0x08) @@ -157,10 +188,6 @@ BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt) #endif -/* - * Pointers to the low-level handlers: first the general ones, then the - * fast ones, then the bad ones. - */ static void (*interrupt[17])(void) = { IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt, IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt, @@ -168,28 +195,6 @@ IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt }; -static void (*fast_interrupt[16])(void) = { - fast_IRQ0_interrupt, fast_IRQ1_interrupt, - fast_IRQ2_interrupt, fast_IRQ3_interrupt, - fast_IRQ4_interrupt, fast_IRQ5_interrupt, - fast_IRQ6_interrupt, fast_IRQ7_interrupt, - fast_IRQ8_interrupt, fast_IRQ9_interrupt, - fast_IRQ10_interrupt, fast_IRQ11_interrupt, - fast_IRQ12_interrupt, fast_IRQ13_interrupt, - fast_IRQ14_interrupt, fast_IRQ15_interrupt -}; - -static void (*bad_interrupt[16])(void) = { - bad_IRQ0_interrupt, bad_IRQ1_interrupt, - bad_IRQ2_interrupt, bad_IRQ3_interrupt, - bad_IRQ4_interrupt, bad_IRQ5_interrupt, - bad_IRQ6_interrupt, bad_IRQ7_interrupt, - bad_IRQ8_interrupt, bad_IRQ9_interrupt, - bad_IRQ10_interrupt, bad_IRQ11_interrupt, - bad_IRQ12_interrupt, bad_IRQ13_interrupt, - bad_IRQ14_interrupt, bad_IRQ15_interrupt -}; - /* * Initial irq handlers. */ @@ -240,14 +245,10 @@ action = irq_action[i]; if (!action) continue; - len += sprintf(buf+len, "%2d: %10u %c %s", - i, kstat.interrupts[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); + len += sprintf(buf+len, "%2d: %10u %s", + i, kstat.interrupts[i], action->name); for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); + len += sprintf(buf+len, ", %s", action->name); } len += sprintf(buf+len, "\n"); } @@ -298,13 +299,9 @@ for (j=0;jflags & SA_INTERRUPT) ? '+' : ' ', - action->name); + len += sprintf(buf+len, " %s", action->name); for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); + len += sprintf(buf+len, ", %s", action->name); } len += sprintf(buf+len, "\n"); } @@ -519,7 +516,8 @@ { switch (flags) { case 0: - __global_sti(); + release_irqlock(smp_processor_id()); + __sti(); break; case 1: __global_cli(); @@ -533,56 +531,58 @@ #endif /* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +asmlinkage void do_IRQ(struct pt_regs regs) { + int irq = regs.orig_eax & 0xff; struct irqaction * action; - int do_random, cpu = smp_processor_id(); + int status, cpu; + + /* + * mask and ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + */ + mask_and_ack_irq(irq); + cpu = smp_processor_id(); irq_enter(cpu, irq); kstat.interrupts[irq]++; - /* slow interrupts run with interrupts enabled */ - __sti(); + /* Return with this interrupt masked if no action */ + status = 0; action = *(irq + irq_action); - do_random = 0; - while (action) { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - irq_exit(cpu, irq); -} - -/* - * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return - * stuff - the handler is also running with interrupts disabled unless - * it explicitly enables them later. - */ -asmlinkage void do_fast_IRQ(int irq) -{ - struct irqaction * action; - int do_random, cpu = smp_processor_id(); + if (action) { + do { + status |= action->flags; + action->handler(irq, action->dev_id, ®s); + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); - irq_enter(cpu, irq); - kstat.interrupts[irq]++; - action = *(irq + irq_action); - do_random = 0; - while (action) { - do_random |= action->flags; - action->handler(irq, action->dev_id, NULL); - action = action->next; + __cli(); + spin_lock(&irq_controller_lock); + unmask_irq(irq); + spin_unlock(&irq_controller_lock); } - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + irq_exit(cpu, irq); + /* + * This should be conditional: we should really get + * a return code from the irq handler to tell us + * whether the handler wants us to do software bottom + * half handling or not.. + */ + if (1) { + if (bh_active & bh_mask) + do_bottom_half(); + } } int setup_x86_irq(int irq, struct irqaction * new) @@ -597,10 +597,6 @@ if (!(old->flags & new->flags & SA_SHIRQ)) return -EBUSY; - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - /* add new interrupt at end of irq queue */ do { p = &old->next; @@ -617,11 +613,9 @@ *p = new; if (!shared) { - if (new->flags & SA_INTERRUPT) - set_intr_gate(0x20+irq,fast_interrupt[irq]); - else - set_intr_gate(0x20+irq,interrupt[irq]); + spin_lock(&irq_controller_lock); unmask_irq(irq); + spin_unlock(&irq_controller_lock); } restore_flags(flags); return 0; @@ -676,10 +670,6 @@ save_flags(flags); cli(); *p = action->next; - if (!irq[irq_action]) { - mask_irq(irq); - set_intr_gate(0x20+irq,bad_interrupt[irq]); - } restore_flags(flags); kfree(action); return; @@ -689,7 +679,7 @@ unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0, irqmask; + unsigned int i, irqs = 0; unsigned long delay; /* first, enable any unassigned irqs */ @@ -705,19 +695,17 @@ /* about 100ms delay */; /* now filter out any obviously spurious interrupts */ - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; - return irqs & ~irqmask; + return irqs & ~cached_irq_mask; } int probe_irq_off (unsigned long irqs) { - unsigned int i, irqmask; + unsigned int i; - irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21; #ifdef DEBUG - printk("probe_irq_off: irqs=0x%04lx irqmask=0x%04x\n", irqs, irqmask); + printk("probe_irq_off: irqs=0x%04lx irqmask=0x%04x\n", irqs, cached_irq_mask); #endif - irqs &= irqmask; + irqs &= cached_irq_mask; if (!irqs) return 0; i = ffz(~irqs); @@ -729,10 +717,6 @@ __initfunc(void init_IRQ(void)) { int i; - static unsigned char smptrap=0; - if(smptrap) - return; - smptrap=1; /* set the clock to 100 Hz */ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ @@ -740,7 +724,7 @@ outb(LATCH >> 8 , 0x40); /* MSB */ for (i = 0; i < NR_IRQS ; i++) - set_intr_gate(0x20+i,bad_interrupt[i]); + set_intr_gate(0x20+i,interrupt[i]); #ifdef __SMP__ /* diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h --- v2.1.36/linux/arch/i386/kernel/irq.h Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/irq.h Tue Apr 29 11:40:18 1997 @@ -33,7 +33,6 @@ static inline void irq_exit(int cpu, int irq) { - __cli(); hardirq_exit(cpu); release_irqlock(cpu); } @@ -64,18 +63,8 @@ "mov %dx,%es\n\t" /* - * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, - * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't - * call the routines that do signal handling etc on return, and can have - * more relaxed register-saving etc. They are also atomic, and are thus - * suited for small, fast interrupts like the serial lines or the harddisk - * drivers, which don't actually need signal handling etc. - * - * Also note that we actually save only those registers that are used in - * C subroutines (%eax, %edx and %ecx), so if you do something weird, - * you're on your own. The only segments that are saved (not counting the - * automatic stack and code segment handling) are %ds and %es, and they - * point to kernel space. No messing around with %fs here. + * These are used just for the "bad" interrupt handlers, + * which just clear the mask and return.. */ #define SAVE_MOST \ "cld\n\t" \ @@ -96,92 +85,13 @@ "pop %es\n\t" \ "iret" -/* - * Some fast irq handlers might want to access saved registers (mostly - * cs or flags) - */ - -struct fast_irq_regs { - long ecx; - long edx; - long eax; - int xds; - int xes; - long eip; - int xcs; - long eflags; - long esp; - int xss; -}; - -/* - * The "inb" instructions are not needed, but seem to change the timings - * a bit - without them it seems that the harddisk driver won't work on - * all hardware. Arghh. - */ -#define ACK_FIRST(mask,nr) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0x20\n\t" - -#define ACK_SECOND(mask,nr) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0xA0\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\toutb %al,$0x20\n\t" - -#define UNBLK_FIRST(mask) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" - -#define UNBLK_SECOND(mask) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" - #define IRQ_NAME2(nr) nr##_interrupt(void) #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) -#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) -#ifdef __SMP__ - #define GET_CURRENT \ - "movl "SYMBOL_NAME_STR(apic_reg)", %ebx\n\t" \ - "movl 32(%ebx), %ebx\n\t" \ - "shrl $22,%ebx\n\t" \ - "andl $0x3C,%ebx\n\t" \ - "movl " SYMBOL_NAME_STR(current_set) "(,%ebx),%ebx\n\t" - -#else - -#define GET_CURRENT \ - "movl " SYMBOL_NAME_STR(current_set) ",%ebx\n\t" - -#endif + "movl %esp, %ebx\n\t" \ + "andl $-8192, %ebx\n\t" #ifdef __SMP__ @@ -205,66 +115,30 @@ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(x) ":\n\t" \ "pushl $-1\n\t" \ - SAVE_ALL \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ + SAVE_ALL \ + "movl %esp,%eax\n\t" \ + "pushl %eax\n\t" \ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ - "addl $4,%esp\n\t" \ + "addl $4,%esp\n\t" \ "jmp ret_from_intr\n"); #endif /* __SMP__ */ -#define BUILD_IRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ +#define BUILD_COMMON_IRQ() \ __asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ + "\n" __ALIGN_STR"\n" \ + "common_interrupt:\n\t" \ SAVE_ALL \ - ACK_##chip(mask,(nr&7)) \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - UNBLK_##chip(mask) \ - "jmp ret_from_intr\n" \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask,(nr&7)) \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ - "addl $4,%esp\n\t" \ - UNBLK_##chip(mask) \ - RESTORE_MOST \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask,(nr&7)) \ - RESTORE_MOST); - -#define BUILD_TIMER_IRQ(chip,nr,mask) \ + "pushl $ret_from_intr\n\t" \ + "jmp "SYMBOL_NAME_STR(do_IRQ)); + +#define BUILD_IRQ(chip,nr,mask) \ asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ __asm__( \ "\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ACK_##chip(mask,(nr&7)) \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - UNBLK_##chip(mask) \ - "jmp ret_from_intr\n"); + "pushl $"#nr"-256\n\t" \ + "jmp common_interrupt"); /* * x86 profiling function, SMP safe. We might want to do this in diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.36/linux/arch/i386/kernel/process.c Sun Apr 13 10:18:20 1997 +++ linux/arch/i386/kernel/process.c Thu May 1 12:05:00 1997 @@ -30,6 +30,7 @@ #include #include #include +#include #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) #include #endif @@ -149,7 +150,8 @@ current->priority = -100; while(1) { - if(cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched) + if(cpu_data[hard_smp_processor_id()].hlt_works_ok && + !hlt_counter && !need_resched) __asm("hlt"); /* * tq_scheduler currently assumes we're running in a process @@ -183,7 +185,7 @@ static int reboot_mode = 0; static int reboot_thru_bios = 0; -void reboot_setup(char *str, int *ints) +__initfunc(void reboot_setup(char *str, int *ints)) { while(1) { switch (*str) { @@ -324,11 +326,14 @@ pg0 [0] = 7; - /* Use `swapper_pg_dir' as our page directory. Don't bother with - `SET_PAGE_DIR' because interrupts are disabled and we're rebooting. - This instruction flushes the TLB. */ + /* + * Use `swapper_pg_dir' as our page directory. We bother with + * `SET_PAGE_DIR' because although might be rebooting, but if we change + * the way we set root page dir in the future, then we wont break a + * seldom used feature ;) + */ - __asm__ __volatile__ ("movl %0,%%cr3" : : "a" (swapper_pg_dir) : "memory"); + SET_PAGE_DIR(current,swapper_pg_dir); /* Write 0x1234 to absolute memory location 0x472. The BIOS reads this on booting to tell it to "Bypass memory test (also warm @@ -473,6 +478,8 @@ int i; struct pt_regs * childregs; + p->tss.tr = _TSS(nr); + p->tss.ldt = _LDT(nr); p->tss.es = KERNEL_DS; p->tss.cs = KERNEL_CS; p->tss.ss = KERNEL_DS; @@ -480,9 +487,8 @@ p->tss.fs = USER_DS; p->tss.gs = USER_DS; p->tss.ss0 = KERNEL_DS; - p->tss.esp0 = p->kernel_stack_page + PAGE_SIZE; - p->tss.tr = _TSS(nr); - childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1; + p->tss.esp0 = 2*PAGE_SIZE + (unsigned long) p; + childregs = ((struct pt_regs *) (p->tss.esp0)) - 1; p->tss.esp = (unsigned long) childregs; #ifdef __SMP__ p->tss.eip = (unsigned long) ret_from_smpfork; @@ -496,7 +502,6 @@ childregs->eax = 0; childregs->esp = esp; p->tss.back_link = 0; - p->tss.ldt = _LDT(nr); if (p->ldt) { p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); if (p->ldt != NULL) @@ -512,6 +517,7 @@ p->tss.io_bitmap[i] = ~0; if (last_task_used_math == current) __asm__("clts ; fnsave %0 ; frstor %0":"=m" (p->tss.i387)); + return 0; } diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v2.1.36/linux/arch/i386/kernel/ptrace.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/ptrace.c Sun Apr 27 15:08:01 1997 @@ -34,18 +34,6 @@ */ #define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs)) -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the TSS. @@ -381,7 +369,7 @@ if (pid == 1) /* you may not mess with init */ goto out; ret = -ESRCH; - if (!(child = get_task(pid))) + if (!(child = find_task_by_pid(pid))) goto out; ret = -EPERM; if (request == PTRACE_ATTACH) { diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.1.36/linux/arch/i386/kernel/signal.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/signal.c Sat Apr 26 17:20:40 1997 @@ -318,6 +318,14 @@ unsigned long signr; struct sigaction * sa; + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if ((regs->xcs & 3) != 3) + return 1; mask = ~current->blocked; while ((signr = current->signal & mask)) { /* diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.1.36/linux/arch/i386/kernel/smp.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/kernel/smp.c Mon May 5 09:42:04 1997 @@ -1,5 +1,5 @@ /* - * Intel MP v1.1/v1.4 specification support routines for multi-pentium + * Intel MP v1.1/v1.4 specification support routines for multi-pentium * hosts. * * (c) 1995 Alan Cox, CymruNET Ltd @@ -46,14 +46,15 @@ #include #include +#define __KERNEL_SYSCALLS__ +#include + #include "irq.h" extern unsigned long start_kernel, _etext; extern void update_one_process( struct task_struct *p, - unsigned long ticks, unsigned long user, - unsigned long system); -void setup_APIC_clock (void); - + unsigned long ticks, unsigned long user, + unsigned long system); /* * Some notes on processor bugs: * @@ -67,7 +68,7 @@ * Pentium * There is a marginal case where REP MOVS on 100MHz SMP * machines with B stepping processors can fail. XXX should provide - * an L1cache=Writethrough or L1cache=off option. + * an L1cache=Writethrough or L1cache=off option. * * B stepping CPU's may hang. There are hardware work arounds * for this. We warn about it in case your board doesnt have the work @@ -91,12 +92,12 @@ * If this sounds worrying believe me these bugs are ___RARE___ and * there's about nothing of note with C stepping upwards. */ - - + + /* * Why isn't this somewhere standard ?? */ - + extern __inline int max(int a,int b) { if(a>b) @@ -121,7 +122,6 @@ static unsigned int num_processors = 1; /* Internal processor count */ static unsigned long io_apic_addr = 0xFEC00000; /* Address of the I/O apic (not yet used) */ unsigned char boot_cpu_id = 0; /* Processor that is doing the boot up */ -static unsigned char *kstack_base,*kstack_end; /* Kernel stack list pointers */ static int smp_activated = 0; /* Tripped once we need to start cross invalidating */ int apic_version[NR_CPUS]; /* APIC version number */ static volatile int smp_commenced=0; /* Tripped when we start scheduling */ @@ -129,7 +129,6 @@ unsigned long nlong = 0; /* dummy used for apic_reg address + 0x20 */ unsigned char *apic_reg=((unsigned char *)(&nlong))-0x20;/* Later set to the ioremap() of the APIC */ unsigned long apic_retval; /* Just debugging the assembler.. */ -unsigned char *kernel_stacks[NR_CPUS]; /* Kernel stack pointers for CPU's (debugging) */ static volatile unsigned char smp_cpu_in_msg[NR_CPUS]; /* True if this processor is sending an IPI */ @@ -195,10 +194,10 @@ apic_write(APIC_EOI, 0); } -/* +/* * Checksum an MP configuration block. */ - + static int mpf_checksum(unsigned char *mp, int len) { int sum=0; @@ -210,7 +209,7 @@ /* * Processor encoding in an MP configuration block */ - + static char *mpc_family(int family,int model) { static char n[32]; @@ -274,11 +273,11 @@ /* set the local APIC address */ apic_addr = (unsigned long)phys_to_virt((unsigned long)mpc->mpc_lapic); - + /* * Now process the configuration blocks. */ - + while(countmpc_length) { switch(*mpt) @@ -290,13 +289,13 @@ if(m->mpc_cpuflag&CPU_ENABLED) { printk("Processor #%d %s APIC version %d\n", - m->mpc_apicid, + m->mpc_apicid, mpc_family((m->mpc_cpufeature& CPU_FAMILY_MASK)>>8, (m->mpc_cpufeature& CPU_MODEL_MASK)>>4), m->mpc_apicver); -#ifdef SMP_DEBUG +#ifdef SMP_DEBUG if(m->mpc_featureflag&(1<<0)) printk(" Floating point unit present.\n"); if(m->mpc_featureflag&(1<<7)) @@ -305,7 +304,7 @@ printk(" 64 bit compare & exchange supported.\n"); if(m->mpc_featureflag&(1<<9)) printk(" Internal APIC present.\n"); -#endif +#endif if(m->mpc_cpuflag&CPU_BOOTPROCESSOR) { SMP_PRINTK((" Bootup CPU\n")); @@ -313,10 +312,10 @@ } else /* Boot CPU already counted */ num_processors++; - + if(m->mpc_apicid>NR_CPUS) printk("Processor #%d unused. (Max %d processors).\n",m->mpc_apicid, NR_CPUS); - else + else { cpu_present_map|=(1<mpc_apicid); apic_version[m->mpc_apicid]=m->mpc_apicver; @@ -337,7 +336,7 @@ str)); mpt+=sizeof(*m); count+=sizeof(*m); - break; + break; } case MP_IOAPIC: { @@ -346,20 +345,20 @@ if(m->mpc_flags&MPC_APIC_USABLE) { apics++; - printk("I/O APIC #%d Version %d at 0x%lX.\n", - m->mpc_apicid,m->mpc_apicver, - m->mpc_apicaddr); - io_apic_addr = (unsigned long)phys_to_virt(m->mpc_apicaddr); - } - mpt+=sizeof(*m); - count+=sizeof(*m); - break; + printk("I/O APIC #%d Version %d at 0x%lX.\n", + m->mpc_apicid,m->mpc_apicver, + m->mpc_apicaddr); + io_apic_addr = (unsigned long)phys_to_virt(m->mpc_apicaddr); + } + mpt+=sizeof(*m); + count+=sizeof(*m); + break; } case MP_INTSRC: { struct mpc_config_intsrc *m= (struct mpc_config_intsrc *)mpt; - + mpt+=sizeof(*m); count+=sizeof(*m); break; @@ -376,29 +375,29 @@ } if(apics>1) printk("Warning: Multiple APIC's not supported.\n"); - return num_processors; + return num_processors; } /* * Scan the memory blocks for an SMP configuration block. */ - + __initfunc(int smp_scan_config(unsigned long base, unsigned long length)) { unsigned long *bp=phys_to_virt(base); struct intel_mp_floating *mpf; - + SMP_PRINTK(("Scan SMP from %p for %ld bytes.\n", bp,length)); if(sizeof(*mpf)!=16) printk("Error: MPF size\n"); - + while(length>0) { if(*bp==SMP_MAGIC_IDENT) { mpf=(struct intel_mp_floating *)bp; - if(mpf->mpf_length==1 && + if(mpf->mpf_length==1 && !mpf_checksum((unsigned char *)bp,16) && (mpf->mpf_specification == 1 || mpf->mpf_specification == 4) ) @@ -433,7 +432,7 @@ * We know that page 0 is not * used. Steal it for now! */ - + cfg=pg0[0]; pg0[0] = (apic_addr | 7); local_flush_tlb(); @@ -451,7 +450,7 @@ * * END OF HACK END OF HACK END OF HACK END OF HACK END OF HACK * - */ + */ /* * 2 CPUs, numbered 0 & 1. */ @@ -513,6 +512,7 @@ nlong = boot_cpu_id<<24; /* Dummy 'self' for bootup */ cpu_logical_map[0] = boot_cpu_id; global_irq_holder = boot_cpu_id; + current->processor = boot_cpu_id; printk("Processors: %d\n", num_processors); /* @@ -534,61 +534,37 @@ extern unsigned char trampoline_data []; extern unsigned char trampoline_end []; +static unsigned char *trampoline_base; /* * Currently trivial. Write the real->protected mode * bootstrap into the page concerned. The caller * has made sure it's suitably aligned. */ - -__initfunc(static void install_trampoline(unsigned char *mp)) + +__initfunc(static unsigned long setup_trampoline(void)) { - memcpy(mp, trampoline_data, trampoline_end - trampoline_data); + memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); + return virt_to_phys(trampoline_base); } /* - * We are called very early to get the low memory for the trampoline/kernel stacks - * This has to be done by mm/init.c to parcel us out nice low memory. We allocate - * the kernel stacks at 4K, 8K, 12K... currently (0-03FF is preserved for SMM and - * other things). + * We are called very early to get the low memory for the + * SMP bootup trampoline page. */ - __initfunc(unsigned long smp_alloc_memory(unsigned long mem_base)) { - int size=(num_processors-1)*PAGE_SIZE; /* Number of stacks needed */ - - /* - * Our stacks have to be below the 1Mb line, and mem_base on entry - * is 4K aligned. - */ - - if(virt_to_phys((void *)(mem_base+size))>=0x9F000) - panic("smp_alloc_memory: Insufficient low memory for kernel stacks 0x%lx.\n", mem_base); - kstack_base=(void *)mem_base; - mem_base+=size; - kstack_end=(void *)mem_base; - return mem_base; -} - -/* - * Hand out stacks one at a time. - */ - -__initfunc(static void *get_kernel_stack(void)) -{ - void *stack=kstack_base; - if(kstack_base>=kstack_end) - return NULL; - kstack_base+=PAGE_SIZE; - return stack; + if (virt_to_phys((void *)mem_base) >= 0x9F000) + panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.\n", mem_base); + trampoline_base = (void *)mem_base; + return mem_base + PAGE_SIZE; } - /* * The bootstrap kernel entry code has set these up. Save them for * a given CPU */ - + __initfunc(void smp_store_cpu_info(int id)) { struct cpuinfo_x86 *c=&cpu_data[id]; @@ -615,7 +591,7 @@ * fired off. This allows the BP to have everything in order [we hope]. * At the end of this all the AP's will hit the system scheduling and off * we go. Each AP will load the system gdt's and jump through the kernel - * init into idle(). At this point the scheduler will one day take over + * init into idle(). At this point the scheduler will one day take over * and give them jobs to do. smp_callin is a standard routine * we use to track CPU's as they power up. */ @@ -634,74 +610,276 @@ extern void calibrate_delay(void); int cpuid=GET_APIC_ID(apic_read(APIC_ID)); unsigned long l; - + /* * Activate our APIC */ - - SMP_PRINTK(("CALLIN %d\n",smp_processor_id())); + + SMP_PRINTK(("CALLIN %d %d\n",hard_smp_processor_id(), smp_processor_id())); l=apic_read(APIC_SPIV); l|=(1<<8); /* Enable */ apic_write(APIC_SPIV,l); /* - * Set up our APIC timer. + * Set up our APIC timer. */ setup_APIC_clock (); sti(); /* * Get our bogomips. - */ + */ calibrate_delay(); SMP_PRINTK(("Stack at about %p\n",&cpuid)); - + /* * Save our processor parameters */ smp_store_cpu_info(cpuid); + /* * Allow the master to continue. - */ + */ set_bit(cpuid, (unsigned long *)&cpu_callin_map[0]); +} + +static int cpucount = 0; + +extern int cpu_idle(void * unused); + +/* + * Activate a secondary processor. + */ +__initfunc(int start_secondary(void *unused)) +{ + smp_callin(); + while (!smp_commenced) + barrier(); + cpu_idle(NULL); +} + +/* + * Everything has been set up for the secondary + * CPU's - they just need to reload everything + * from the task structure + */ +__initfunc(void initialize_secondary(void)) +{ + struct thread_struct * p = ¤t->tss; + /* - * Until we are ready for SMP scheduling + * We don't actually need to load the full TSS, + * basically just the stack pointer and the eip. */ - load_ldt(0); - local_flush_tlb(); - - while (cpu_number_map[cpuid] == -1) - barrier(); + asm volatile("lldt %%ax": :"a" (p->ldt)); + asm volatile("ltr %%ax": :"a" (p->tr)); + asm volatile( + "movl %0,%%esp\n\t" + "jmp *%1" + : + :"r" (p->esp),"r" (p->eip)); +} - while(!task[cpuid] || current_set[cpuid] != task[cpu_number_map[cpuid]]) - barrier(); +extern struct { + void * esp; + unsigned short ss; +} stack_start; - local_flush_tlb(); - load_TR(cpu_number_map[cpuid]); +__initfunc(static void do_boot_cpu(int i)) +{ + unsigned long cfg; + pgd_t maincfg; + struct task_struct *idle; + unsigned long send_status, accept_status; + int timeout, num_starts, j; + unsigned long start_eip; - while(!smp_commenced) - barrier(); - + /* + * We need an idle process for each processor. + */ + + kernel_thread(start_secondary, NULL, CLONE_PID); + cpucount++; + + idle = task[cpucount]; + if (!idle) + panic("No idle process for CPU %d\n", i); + + idle->processor = i; + cpu_logical_map[cpucount] = i; + cpu_number_map[i] = cpucount; + + /* start_eip had better be page-aligned! */ + start_eip = setup_trampoline(); + + printk("Booting processor %d eip %lx: ", i, start_eip); /* So we see what's up */ + stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); + + /* + * This grunge runs the startup process for + * the targeted processor. + */ + + SMP_PRINTK(("Setting warm reset code and vector.\n")); + + CMOS_WRITE(0xa, 0xf); local_flush_tlb(); + SMP_PRINTK(("1.\n")); + *((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4; + SMP_PRINTK(("2.\n")); + *((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf; + SMP_PRINTK(("3.\n")); + + maincfg=swapper_pg_dir[0]; + ((unsigned long *)swapper_pg_dir)[0]=0x102007; + + /* + * Be paranoid about clearing APIC errors. + */ + + if ( apic_version[i] & 0xF0 ) + { + apic_write(APIC_ESR, 0); + accept_status = (apic_read(APIC_ESR) & 0xEF); + } + + /* + * Status is now clean + */ - SMP_PRINTK(("Commenced..\n")); + send_status = 0; + accept_status = 0; + + /* + * Starting actual IPI sequence... + */ + + SMP_PRINTK(("Asserting INIT.\n")); + + /* + * Turn INIT on + */ + + cfg=apic_read(APIC_ICR2); + cfg&=0x00FFFFFF; + apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ + cfg=apic_read(APIC_ICR); + cfg&=~0xCDFFF; /* Clear bits */ + cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG + | APIC_DEST_ASSERT | APIC_DEST_DM_INIT); + apic_write(APIC_ICR, cfg); /* Send IPI */ + + udelay(200); + SMP_PRINTK(("Deasserting INIT.\n")); + + cfg=apic_read(APIC_ICR2); + cfg&=0x00FFFFFF; + apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ + cfg=apic_read(APIC_ICR); + cfg&=~0xCDFFF; /* Clear bits */ + cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG + | APIC_DEST_DM_INIT); + apic_write(APIC_ICR, cfg); /* Send IPI */ + + /* + * Should we send STARTUP IPIs ? + * + * Determine this based on the APIC version. + * If we don't have an integrated APIC, don't + * send the STARTUP IPIs. + */ + + if ( apic_version[i] & 0xF0 ) + num_starts = 2; + else + num_starts = 0; + + /* + * Run STARTUP IPI loop. + */ + + for (j = 1; !(send_status || accept_status) + && (j <= num_starts) ; j++) + { + SMP_PRINTK(("Sending STARTUP #%d.\n",j)); + apic_write(APIC_ESR, 0); + SMP_PRINTK(("After apic_write.\n")); + + /* + * STARTUP IPI + */ + + cfg=apic_read(APIC_ICR2); + cfg&=0x00FFFFFF; + apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ + cfg=apic_read(APIC_ICR); + cfg&=~0xCDFFF; /* Clear bits */ + cfg |= (APIC_DEST_FIELD + | APIC_DEST_DM_STARTUP + | (start_eip >> 12)); /* Boot on the stack */ + SMP_PRINTK(("Before start apic_write.\n")); + apic_write(APIC_ICR, cfg); /* Kick the second */ + + SMP_PRINTK(("Startup point 1.\n")); + timeout = 0; + do { + SMP_PRINTK(("Sleeping.\n")); udelay(1000000); + udelay(10); + } while ( (send_status = (apic_read(APIC_ICR) & 0x1000)) + && (timeout++ < 1000)); + udelay(200); + accept_status = (apic_read(APIC_ESR) & 0xEF); + } + SMP_PRINTK(("After Startup.\n")); + + if (send_status) /* APIC never delivered?? */ + printk("APIC never delivered???\n"); + if (accept_status) /* Send accept error */ + printk("APIC delivery error (%lx).\n", accept_status); + + if( !(send_status || accept_status) ) + { + for(timeout=0;timeout<50000;timeout++) + { + if(cpu_callin_map[0]&(1< cpucount+1)) { - unsigned long send_status, accept_status; - int timeout, num_starts, j; - - /* - * We need a kernel stack for each processor. - */ - - stack=get_kernel_stack(); /* We allocated these earlier */ - if(stack==NULL) - panic("No memory for processor stacks.\n"); - - kernel_stacks[i]=(void *)phys_to_virt((unsigned long)stack); - install_trampoline(stack); - - printk("Booting processor %d stack %p: ",i,stack); /* So we set what's up */ - - /* - * This grunge runs the startup process for - * the targeted processor. - */ - - SMP_PRINTK(("Setting warm reset code and vector.\n")); - - /* - * Install a writable page 0 entry. - */ - - cfg=pg0[0]; - - CMOS_WRITE(0xa, 0xf); - pg0[0]=7; - local_flush_tlb(); - SMP_PRINTK(("1.\n")); - *((volatile unsigned short *) phys_to_virt(0x469)) = ((unsigned long)stack)>>4; - SMP_PRINTK(("2.\n")); - *((volatile unsigned short *) phys_to_virt(0x467)) = 0; - SMP_PRINTK(("3.\n")); - - /* - * Protect it again - */ - - pg0[0]= cfg; - local_flush_tlb(); - - /* walken modif - * enable mapping of the first 4M at virtual - * address zero - */ - - maincfg=swapper_pg_dir[0]; - ((unsigned long *)swapper_pg_dir)[0]=0x102007; - - /* no need to local_flush_tlb : - we are setting this up for the slave processor ! */ - - /* - * Be paranoid about clearing APIC errors. - */ - - if ( apic_version[i] & 0xF0 ) - { - apic_write(APIC_ESR, 0); - accept_status = (apic_read(APIC_ESR) & 0xEF); - } - - /* - * Status is now clean - */ - - send_status = 0; - accept_status = 0; - - /* - * Starting actual IPI sequence... - */ - - SMP_PRINTK(("Asserting INIT.\n")); - - /* - * Turn INIT on - */ - - cfg=apic_read(APIC_ICR2); - cfg&=0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ - cfg=apic_read(APIC_ICR); - cfg&=~0xCDFFF; /* Clear bits */ - cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG - | APIC_DEST_ASSERT | APIC_DEST_DM_INIT); - apic_write(APIC_ICR, cfg); /* Send IPI */ - - udelay(200); - SMP_PRINTK(("Deasserting INIT.\n")); - - cfg=apic_read(APIC_ICR2); - cfg&=0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ - cfg=apic_read(APIC_ICR); - cfg&=~0xCDFFF; /* Clear bits */ - cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG - | APIC_DEST_DM_INIT); - apic_write(APIC_ICR, cfg); /* Send IPI */ - - /* - * Should we send STARTUP IPIs ? - * - * Determine this based on the APIC version. - * If we don't have an integrated APIC, don't - * send the STARTUP IPIs. - */ - - if ( apic_version[i] & 0xF0 ) - num_starts = 2; - else - num_starts = 0; - - /* - * Run STARTUP IPI loop. - */ - - for (j = 1; !(send_status || accept_status) - && (j <= num_starts) ; j++) - { - SMP_PRINTK(("Sending STARTUP #%d.\n",j)); - - apic_write(APIC_ESR, 0); - SMP_PRINTK(("After apic_write.\n")); - - /* - * STARTUP IPI - */ - - cfg=apic_read(APIC_ICR2); - cfg&=0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */ - cfg=apic_read(APIC_ICR); - cfg&=~0xCDFFF; /* Clear bits */ - cfg |= (APIC_DEST_FIELD - | APIC_DEST_DM_STARTUP - | (((int)virt_to_phys(stack)) >> 12)); /* Boot on the stack */ - SMP_PRINTK(("Before start apic_write.\n")); - apic_write(APIC_ICR, cfg); /* Kick the second */ - - SMP_PRINTK(("Startup point 1.\n")); - timeout = 0; - do { - SMP_PRINTK(("Sleeping.\n")); udelay(1000000); - udelay(10); - } while ( (send_status = (apic_read(APIC_ICR) & 0x1000)) - && (timeout++ < 1000)); - udelay(200); - - accept_status = (apic_read(APIC_ESR) & 0xEF); - } - SMP_PRINTK(("After Startup.\n")); - - if (send_status) /* APIC never delivered?? */ - printk("APIC never delivered???\n"); - if (accept_status) /* Send accept error */ - printk("APIC delivery error (%lx).\n", accept_status); - - if( !(send_status || accept_status) ) - { - for(timeout=0;timeout<50000;timeout++) - { - if(cpu_callin_map[0]&(1< #include #include +#include #include #include @@ -379,11 +380,15 @@ do_timer(regs); /* * In the SMP case we use the local APIC timer interrupt to do the - * profiling. + * profiling, except when we simulate SMP mode on a uniprocessor + * system, in that case we have to call the local interrupt handler. */ #ifndef __SMP__ if (!user_mode(regs)) x86_do_profile(regs->eip); +#else + if (!smp_found_config) + smp_local_timer_interrupt(regs); #endif /* diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/trampoline.S linux/arch/i386/kernel/trampoline.S --- v2.1.36/linux/arch/i386/kernel/trampoline.S Sun Jan 26 02:07:04 1997 +++ linux/arch/i386/kernel/trampoline.S Fri May 2 16:32:02 1997 @@ -21,13 +21,9 @@ * and IP is zero. Thus, data addresses need to be absolute * (no relocation) and are taken with regard to r_base. * - * On the transition to protected mode, this page appears at - * address 8192, so protected mode addresses are with regard - * to p_base. - * * If you work on this file, check the object module with objdump * --full-contents --reloc to make sure there are no relocation - * entries. + * entries except for the gdt one.. */ #include @@ -39,15 +35,10 @@ ENTRY(trampoline_data) r_base = . -p_base = . - 8192 mov %cs, %ax # Code and data in the same place mov %ax, %ds - mov %ax, %cx # Pass stack info to the 32bit boot - shl $4, %cx # Segment -> Offset - add $4096, %cx # End of page is wanted - mov $1, %bx # Flag an SMP trampoline cli # We should be safe anyway @@ -71,37 +62,7 @@ gdt_48: .word 0x0800 # gdt limit = 2048, 256 GDT entries - .word gdt - p_base, 0x0 # gdt base = gdt (first SMP CPU) - # we load the others with first table - # saves rewriting gdt_48 for each -gdt: - .word 0, 0, 0, 0 # dummy - - .word 0, 0, 0, 0 # unused - -# walken modif - - .word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb) - .word 0x0000 # base address = 0 - .word 0x9A00 # code read / exec - .word 0x00CF # granularity = 4096, 386 (+5th nibble of limit) - - .word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb) - .word 0x0000 # base address = 0 - .word 0x9200 # data read / write - .word 0x00CF # granularity = 4096, 386 (+5th nibble of limit) - -# walken modif - -# .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb) -# .word 0x0000 # base address = 0 -# .word 0x9A00 # code read / exec -# .word 0x00C0 # granularity = 4096, 386 - -# .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb) -# .word 0x0000 # base address = 0 -# .word 0x9200 # data read / write -# .word 0x00C0 # granularity = 4096, 386 + .long gdt-0xc0000000 # gdt base = gdt (first SMP CPU) .globl SYMBOL_NAME(trampoline_end) SYMBOL_NAME_LABEL(trampoline_end) diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.36/linux/arch/i386/kernel/traps.c Wed Apr 16 14:14:59 1997 +++ linux/arch/i386/kernel/traps.c Thu May 8 11:48:13 1997 @@ -27,6 +27,7 @@ #include #include #include +#include asmlinkage int system_call(void); asmlinkage void lcall7(void); @@ -121,7 +122,7 @@ unsigned long esp; unsigned short ss; unsigned long *stack, addr, module_start, module_end; - extern char start_kernel, _etext; + extern char _stext, _etext; esp = (unsigned long) ®s->esp; ss = KERNEL_DS; @@ -129,8 +130,8 @@ esp = regs->esp; ss = regs->xss & 0xffff; } - printk("CPU: %d\n", smp_processor_id()); - printk("EIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->xcs,regs->eip,regs->eflags); + printk("CPU: %d\nEIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", + smp_processor_id(), 0xffff & regs->xcs, regs->eip, regs->eflags); printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->eax, regs->ebx, regs->ecx, regs->edx); printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", @@ -138,10 +139,8 @@ printk("ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); store_TR(i); - if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) - printk("Corrupted stack page\n"); printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", - current->comm, current->pid, 0xffff & i, current->kernel_stack_page); + current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current); stack = (unsigned long *) esp; for(i=0; i < kstack_depth_to_print; i++) { if (((long) stack & 4095) == 0) @@ -166,7 +165,7 @@ * down the cause of the crash will be able to figure * out the call path that was taken. */ - if (((addr >= (unsigned long) &start_kernel) && + if (((addr >= (unsigned long) &_stext) && (addr <= (unsigned long) &_etext)) || ((addr >= module_start) && (addr <= module_end))) { if (i && ((i % 8) == 0)) @@ -181,13 +180,19 @@ printk("\n"); } +spinlock_t die_lock; + /*static*/ void die_if_kernel(const char * str, struct pt_regs * regs, long err) { if ((regs->eflags & VM_MASK) || (3 & regs->xcs) == 3) return; console_verbose(); + spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); show_registers(regs); +do { int i=2000000000; while (i) i--; } while (0); +do { int i=2000000000; while (i) i--; } while (0); + spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } @@ -235,9 +240,24 @@ unlock_kernel(); } +void enable_NMI(void) +{ + unsigned char reason; + unsigned long i; + + reason = inb(0x61); + printk("NMI reason = %02x\n", reason); + reason |= 8; + outb(reason, 0x61); + i = 400000000; + while (--i) ; + reason &= ~8; + outb(reason, 0x61); +} + asmlinkage void do_nmi(struct pt_regs * regs, long error_code) { - printk("NMI\n"); show_registers(regs); + show_registers(regs); #ifdef CONFIG_SMP_NMI_INVAL smp_flush_tlb_rcv(); #else @@ -247,6 +267,7 @@ printk("power saving mode enabled.\n"); #endif #endif + enable_NMI(); } asmlinkage void do_debug(struct pt_regs * regs, long error_code) @@ -380,15 +401,7 @@ { int i; struct desc_struct * p; - static int smptrap=0; - - if(smptrap) - { - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - load_ldt(0); - return; - } - smptrap++; + if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) EISA_bus = 1; set_call_gate(&default_ldt,lcall7); diff -u --recursive --new-file v2.1.36/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v2.1.36/linux/arch/i386/kernel/vm86.c Thu Feb 27 10:57:29 1997 +++ linux/arch/i386/kernel/vm86.c Mon Apr 28 20:46:56 1997 @@ -81,8 +81,8 @@ printk("vm86: could not access userspace vm86_info\n"); do_exit(SIGSEGV); } - current->tss.esp0 = current->saved_kernel_stack; - current->saved_kernel_stack = 0; + current->tss.esp0 = current->tss.saved_esp0; + current->tss.saved_esp0 = 0; ret = KVM86->regs32; unlock_kernel(); return ret; @@ -137,7 +137,7 @@ lock_kernel(); tsk = current; - if (tsk->saved_kernel_stack) + if (tsk->tss.saved_esp0) goto out; tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, @@ -187,7 +187,7 @@ /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */ ret = -EPERM; - if (tsk->saved_kernel_stack) + if (tsk->tss.saved_esp0) goto out; tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, @@ -247,7 +247,7 @@ * Save old state, set default return value (%eax) to 0 */ info->regs32->eax = 0; - tsk->saved_kernel_stack = tsk->tss.esp0; + tsk->tss.saved_esp0 = tsk->tss.esp0; tsk->tss.esp0 = (unsigned long) &info->VM86_TSS_ESP0; tsk->tss.screen_bitmap = info->screen_bitmap; @@ -601,11 +601,17 @@ static inline int task_valid(struct task_struct *tsk) { struct task_struct *p; + int ret = 0; + read_lock(&tasklist_lock); for_each_task(p) { - if ((p == tsk) && (p->sig)) return 1; + if ((p == tsk) && (p->sig)) { + ret = 1; + break; + } } - return 0; + read_unlock(&tasklist_lock); + return ret; } static inline void handle_irq_zombies(void) diff -u --recursive --new-file v2.1.36/linux/arch/i386/lib/locks.S linux/arch/i386/lib/locks.S --- v2.1.36/linux/arch/i386/lib/locks.S Sun Jan 26 02:07:05 1997 +++ linux/arch/i386/lib/locks.S Fri May 2 18:57:44 1997 @@ -10,7 +10,6 @@ * %eax contains callers PC and %edx holds this cpu ID. */ ENTRY(__lock_kernel) - pushl %eax ! return address 1: lock btsl $0, SYMBOL_NAME(kernel_flag) @@ -21,8 +20,10 @@ lock btrl %dl, SYMBOL_NAME(smp_invalidate_needed) jnc 0f + pushl %eax movl %cr3, %eax movl %eax, %cr3 + popl %eax 0: btl $0, SYMBOL_NAME(kernel_flag) jc 2b diff -u --recursive --new-file v2.1.36/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.36/linux/arch/i386/mm/fault.c Sun Apr 13 10:18:20 1997 +++ linux/arch/i386/mm/fault.c Sun Apr 27 10:16:30 1997 @@ -169,7 +169,10 @@ /* Are we prepared to handle this fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { - printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", regs->eip, fixup); + printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", + current->comm, + regs->eip, + fixup); regs->eip = fixup; goto out; } diff -u --recursive --new-file v2.1.36/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.36/linux/arch/i386/mm/init.c Wed Apr 23 19:01:14 1997 +++ linux/arch/i386/mm/init.c Sat Apr 26 10:40:16 1997 @@ -139,12 +139,23 @@ #define write_cr4 ".byte 0x0f,0x22,0xe0" #endif -#define set_in_cr4(x) \ -__asm__(read_cr4 "\n\t" \ - "orl %0,%%eax\n\t" \ - write_cr4 \ - : : "i" (x) \ - :"ax"); +/* + * Save the cr4 feature set we're using (ie + * Pentium 4MB enable and PPro Global page + * enable), so that any CPU's that boot up + * after us can get the correct flags. + */ +unsigned long mmu_cr4_features __initdata = 0; + +static inline void set_in_cr4(unsigned long mask) +{ + mmu_cr4_features |= mask; + __asm__(read_cr4 "\n\t" + "orl %0,%%eax\n\t" + write_cr4 + : : "irg" (mask) + :"ax"); +} /* * paging_init() sets up the page tables - note that the first 4MB are diff -u --recursive --new-file v2.1.36/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds --- v2.1.36/linux/arch/i386/vmlinux.lds Wed Apr 16 14:15:00 1997 +++ linux/arch/i386/vmlinux.lds Thu May 1 12:43:59 1997 @@ -13,6 +13,7 @@ *(.fixup) *(.gnu.warning) } = 0x9090 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ .rodata : { *(.rodata) } .kstrtab : { *(.kstrtab) } diff -u --recursive --new-file v2.1.36/linux/arch/m68k/Makefile linux/arch/m68k/Makefile --- v2.1.36/linux/arch/m68k/Makefile Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/Makefile Thu May 1 12:05:00 1997 @@ -24,17 +24,7 @@ CROSS_COMPILE = m68k-linux- endif -# -# Set these to indicate how to link it.. -# -# -zmagic: -# -# LINKFLAGS = -Ttext 0x100000 -# -# -qmagic (we need to remove the 32 byte header for bootup purposes) -# - -LINKFLAGS = -Ttext 0x1000 +LINKFLAGS = -T $(TOPDIR)/arch/m68k/vmlinux.lds CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/amifb.c linux/arch/m68k/amiga/amifb.c --- v2.1.36/linux/arch/m68k/amiga/amifb.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/amifb.c Thu May 1 12:05:00 1997 @@ -50,12 +50,14 @@ #include #include #include +#include +#include + #include #include #include #include #include -#include #define DEBUG @@ -1802,7 +1804,7 @@ * Initialisation */ -struct fb_info *amiga_fb_init(long *mem_start) +__initfunc(struct fb_info *amiga_fb_init(long *mem_start)) { int err, tag, i; u_long chipptr; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c --- v2.1.36/linux/arch/m68k/amiga/amiints.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/amiints.c Thu May 1 12:05:00 1997 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ * the amiga IRQ handling routines. */ -void amiga_init_IRQ(void) +__initfunc(void amiga_init_IRQ(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/amikeyb.c linux/arch/m68k/amiga/amikeyb.c --- v2.1.36/linux/arch/m68k/amiga/amikeyb.c Fri Dec 20 01:19:57 1996 +++ linux/arch/m68k/amiga/amikeyb.c Thu May 1 12:05:00 1997 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -295,7 +296,7 @@ } } -int amiga_keyb_init(void) +__initfunc(int amiga_keyb_init(void)) { if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -EIO; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/amisound.c linux/arch/m68k/amiga/amisound.c --- v2.1.36/linux/arch/m68k/amiga/amisound.c Fri Dec 20 01:19:57 1996 +++ linux/arch/m68k/amiga/amisound.c Thu May 1 12:05:00 1997 @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -39,7 +40,7 @@ static u_long clock_constant; -static void init_sound(void) +__initfunc(static void init_sound(void)) { snd_data = amiga_chip_alloc(sizeof(sine_data)); if (!snd_data) { @@ -84,7 +85,7 @@ custom.aud[2].audlc = snd_data; custom.aud[2].audlen = sizeof(sine_data)/2; custom.aud[2].audper = (u_short)period; - custom.aud[2].audvol = 64; /* maxvol */ + custom.aud[2].audvol = 32; /* 50% of maxvol */ if (ticks) { sound_timer.expires = jiffies + ticks; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/chipram.c linux/arch/m68k/amiga/chipram.c --- v2.1.36/linux/arch/m68k/amiga/chipram.c Fri Dec 20 01:19:57 1996 +++ linux/arch/m68k/amiga/chipram.c Thu May 1 12:05:00 1997 @@ -8,6 +8,7 @@ #include #include +#include #include struct chip_desc { @@ -21,19 +22,18 @@ #define DP(ptr) ((struct chip_desc *)(ptr)) u_long amiga_chip_size; -static unsigned long chipavail; /*MILAN*/ +static unsigned long chipavail; -/*MILAN*/ unsigned long amiga_chip_avail( void ) { #ifdef DEBUG - printk("chip_avail : %ld bytes\n",chipavail); + printk("chip_avail : %ld bytes\n",chipavail); #endif - return chipavail; + return chipavail; } -void amiga_chip_init (void) +__initfunc(void amiga_chip_init (void)) { struct chip_desc *dp; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c --- v2.1.36/linux/arch/m68k/amiga/cia.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/cia.c Thu May 1 12:05:00 1997 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -152,7 +153,7 @@ amiga_do_irq_list(base->server_irq, fp, &base->server); } -void cia_init_IRQ(struct ciabase *base) +__initfunc(void cia_init_IRQ(struct ciabase *base)) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c --- v2.1.36/linux/arch/m68k/amiga/config.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/config.c Thu May 1 12:05:00 1997 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -148,7 +149,7 @@ * Setup the Amiga configuration info */ -void config_amiga(void) +__initfunc(void config_amiga(void)) { /* Fill in some default values, if necessary */ if (amiga_eclock == 0) @@ -376,8 +377,8 @@ static unsigned short jiffy_ticks; -static void amiga_sched_init(void (*timer_routine)(int, void *, - struct pt_regs *)) +__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *, + struct pt_regs *))) { jiffy_ticks = (amiga_eclock+HZ/2)/HZ; @@ -796,7 +797,7 @@ } #endif -static void amiga_debug_init(void) +__initfunc(static void amiga_debug_init(void)) { if (!strcmp( m68k_debug_device, "ser" )) { /* no initialization required (?) */ diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/cyberfb.c linux/arch/m68k/amiga/cyberfb.c --- v2.1.36/linux/arch/m68k/amiga/cyberfb.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/cyberfb.c Thu May 1 12:05:00 1997 @@ -29,12 +29,13 @@ #include #include #include +#include +#include +#include #include #include #include -#include #include -#include #include "s3blit.h" @@ -1157,7 +1158,7 @@ * Initialization */ -struct fb_info *Cyber_fb_init(long *mem_start) +__initfunc(struct fb_info *Cyber_fb_init(long *mem_start)) { int err; struct Cyber_fb_par par; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/retz3fb.c linux/arch/m68k/amiga/retz3fb.c --- v2.1.36/linux/arch/m68k/amiga/retz3fb.c Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/retz3fb.c Thu May 1 12:05:00 1997 @@ -30,1762 +30,11 @@ #include #include #include +#include +#include #include #include #include -#include -#include - -#include "retz3fb.h" - -/* #define DEBUG if(1) */ -#define DEBUG if(0) - -/* - * Reserve space for one pattern line. - * - * For the time being we only support 4MB boards! - */ - -#define PAT_MEM_SIZE 16*3 -#define PAT_MEM_OFF (4*1024*1024 - PAT_MEM_SIZE) - -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - -struct retz3_fb_par { - int xres; - int yres; - int xres_vir; - int yres_vir; - int xoffset; - int yoffset; - int bpp; - - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; - - int pixclock; - int left_margin; /* time from sync to picture */ - int right_margin; /* time from picture to sync */ - int upper_margin; /* time from sync to picture */ - int lower_margin; - int hsync_len; /* length of horizontal sync */ - int vsync_len; /* length of vertical sync */ - int vmode; -}; - -struct display_data { - long h_total; /* Horizontal Total */ - long h_sstart; /* Horizontal Sync Start */ - long h_sstop; /* Horizontal Sync Stop */ - long h_bstart; /* Horizontal Blank Start */ - long h_bstop; /* Horizontal Blank Stop */ - long h_dispend; /* Horizontal Display End */ - long v_total; /* Vertical Total */ - long v_sstart; /* Vertical Sync Start */ - long v_sstop; /* Vertical Sync Stop */ - long v_bstart; /* Vertical Blank Start */ - long v_bstop; /* Vertical Blank Stop */ - long v_dispend; /* Horizontal Display End */ -}; - -static struct retz3_fb_par current_par; - -static int current_par_valid = 0; -static int currcon = 0; - -static struct display disp[MAX_NR_CONSOLES]; -static struct fb_info fb_info; - -static int node; /* node of the /dev/fb?current file */ - - -/* - * Switch for Chipset Independency - */ - -static struct fb_hwswitch { - - /* Initialisation */ - - int (*init)(void); - - /* Display Control */ - - int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par); - int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par); - int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par); - int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned - int *green, unsigned int *blue, unsigned int *transp); - int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int - green, unsigned int blue, unsigned int transp); - void (*blank)(int blank); -} *fbhw; - - -/* - * Frame Buffer Name - */ - -static char retz3_fb_name[16] = "RetinaZ3"; - - -static int z3_key = 0; -static unsigned char retz3_color_table [256][4]; -static unsigned long z3_mem; -static unsigned long z3_fbmem; -static unsigned long z3_size; -static volatile unsigned char *z3_regs; - -static long *memstart; - - -/* - * Predefined Video Mode Names - */ - -static char *retz3_fb_modenames[] = { - - /* - * Autodetect (Default) Video Mode - */ - - "default", - - /* - * Predefined Video Modes - */ - - "640x480", /* RetinaZ3 8 bpp */ - "800x600", /* RetinaZ3 8 bpp */ - "1024x768i", - "640x480-16", /* RetinaZ3 16 bpp */ - "640x480-24", /* RetinaZ3 24 bpp */ - - /* - * Dummy Video Modes - */ - - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - - /* - * User Defined Video Modes - * - * This doesn't work yet!! - */ - - "user0", "user1", "user2", "user3", - "user4", "user5", "user6", "user7" -}; - -/* - * A small info on how to convert XFree86 timing values into fb - * timings - by Frank Neumann: - * -An XFree86 mode line consists of the following fields: - "800x600" 50 800 856 976 1040 600 637 643 666 - < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL - -The fields in the fb_var_screeninfo structure are: - unsigned long pixclock; * pixel clock in ps (pico seconds) * - unsigned long left_margin; * time from sync to picture * - unsigned long right_margin; * time from picture to sync * - unsigned long upper_margin; * time from sync to picture * - unsigned long lower_margin; - unsigned long hsync_len; * length of horizontal sync * - unsigned long vsync_len; * length of vertical sync * - -1) Pixelclock: - xfree: in MHz - fb: In Picoseconds (ps) - - pixclock = 1000000 / DCF - -2) horizontal timings: - left_margin = HFL - SH2 - right_margin = SH1 - HR - hsync_len = SH2 - SH1 - -3) vertical timings: - upper_margin = VFL - SV2 - lower_margin = SV1 - VR - vsync_len = SV2 - SV1 - -Good examples for VESA timings can be found in the XFree86 source tree, -under "programs/Xserver/hw/xfree86/doc/modeDB.txt". -*/ - -/* - * Predefined Video Mode Definitions - */ - -static struct fb_var_screeninfo retz3_fb_predefined[] = { - - /* - * Autodetect (Default) Video Mode - */ - - { 0, }, - - /* - * Predefined Video Modes - */ - - /* - * NB: it is very important to adjust the pixel-clock to the color-depth. - */ - - { - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - /* - ModeLine "800x600" 36 800 824 896 1024 600 601 603 625 - < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL - */ - { - /* 800 x 600, 8 bpp */ - 800, 600, 800, 600, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - /* - ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace - < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL - */ - { - /* 1024 x 768, 8 bpp, interlaced */ - 1024, 768, 1024, 768, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED - }, - { - 640, 480, 640, 480, 0, 0, 16, 0, - {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - { - 640, 480, 640, 480, 0, 0, 24, 0, - {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - - /* - * Dummy Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - { 0, }, { 0, }, - - /* - * User Defined Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, } -}; - - -#define NUM_TOTAL_MODES arraysize(retz3_fb_predefined) -#define NUM_PREDEF_MODES (5) - - -static int z3fb_inverse = 0; -static int z3fb_mode = 0; - - -/* - * Interface used by the world - */ - -int retz3_probe(void); -void retz3_video_setup(char *options, int *ints); - -static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con); -static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con); -static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con); -static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int retz3_fb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con); - - -/* - * Interface to the low level console driver - */ - -struct fb_info *retz3_fb_init(long *mem_start); /* Through amiga_fb_init() */ -static int z3fb_switch(int con); -static int z3fb_updatevar(int con); -static void z3fb_blank(int blank); -static int z3fb_setcmap(struct fb_cmap *cmap, int con); - - -/* - * Accelerated Functions used by the low level console driver - */ - -void retz3_bitblt(struct fb_var_screeninfo *scr, - unsigned short curx, unsigned short cury, unsigned - short destx, unsigned short desty, unsigned short - width, unsigned short height, unsigned short cmd, - unsigned short mask); -void retz3_fill(unsigned short x, unsigned short y, unsigned short - width, unsigned short height, unsigned short mode, - unsigned short color); - -/* - * Hardware Specific Routines - */ - -static int retz3_init(void); -static int retz3_encode_fix(struct fb_fix_screeninfo *fix, - struct retz3_fb_par *par); -static int retz3_decode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par); -static int retz3_encode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par); -static int retz3_getcolreg(unsigned int regno, unsigned int *red, - unsigned int *green, unsigned int *blue, - unsigned int *transp); -static int retz3_setcolreg(unsigned int regno, unsigned int red, - unsigned int green, unsigned int blue, - unsigned int transp); -static void retz3_blank(int blank); - - -/* - * Internal routines - */ - -static void retz3_fb_get_par(struct retz3_fb_par *par); -static void retz3_fb_set_par(struct retz3_fb_par *par); -static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive); -static struct fb_cmap *get_default_colormap(int bpp); -static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, - int kspc); -static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, - int kspc); -static void do_install_cmap(int con); -static void memcpy_fs(int fsfromto, void *to, void *from, int len); -static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto); -static int alloc_cmap(struct fb_cmap *cmap, int len, int transp); -static void retz3_fb_set_disp(int con); -static int get_video_mode(const char *name); - - -/* -------------------- Hardware specific routines -------------------------- */ - -static unsigned short find_fq(unsigned int freq) -{ - unsigned long f; - long tmp; - long prev = 0x7fffffff; - long n2, n1 = 3; - unsigned long m; - unsigned short res = 0; - - if (freq <= 31250000) - n2 = 3; - else if (freq <= 62500000) - n2 = 2; - else if (freq <= 125000000) - n2 = 1; - else if (freq <= 250000000) - n2 = 0; - else - return(0); - - - do { - f = freq >> (10 - n2); - - m = (f * n1) / (14318180/1024); - - if (m > 129) - break; - - tmp = (((m * 14318180) >> n2) / n1) - freq; - if (tmp < 0) - tmp = -tmp; - - if (tmp < prev) { - prev = tmp; - res = (((n2 << 5) | (n1-2)) << 8) | (m-2); - } - - } while ( (++n1) <= 21); - - return res; -} - - -static int retz3_set_video(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) -{ - float freq_f; - long freq; - - int xres, hfront, hsync, hback; - int yres, vfront, vsync, vback; - unsigned char tmp; - unsigned short best_freq; - struct display_data data; - - short clocksel = 0; /* Apparantly this is always zero */ - - int bpp = var->bits_per_pixel; - - /* - * XXX - */ - if (bpp == 24) - return 0; - - if ((bpp != 8) && (bpp != 16) && (bpp != 24)) - return -EFAULT; - - par->xoffset = 0; - par->yoffset = 0; - - xres = var->xres * bpp / 4; - hfront = var->right_margin * bpp / 4; - hsync = var->hsync_len * bpp / 4; - hback = var->left_margin * bpp / 4; - - if (var->vmode & FB_VMODE_DOUBLE) - { - yres = var->yres * 2; - vfront = var->lower_margin * 2; - vsync = var->vsync_len * 2; - vback = var->upper_margin * 2; - } - else if (var->vmode & FB_VMODE_INTERLACED) - { - yres = (var->yres + 1) / 2; - vfront = (var->lower_margin + 1) / 2; - vsync = (var->vsync_len + 1) / 2; - vback = (var->upper_margin + 1) / 2; - } - else - { - yres = var->yres; /* -1 ? */ - vfront = var->lower_margin; - vsync = var->vsync_len; - vback = var->upper_margin; - } - - data.h_total = (hback / 8) + (xres / 8) - + (hfront / 8) + (hsync / 8) - 1 /* + 1 */; - data.h_dispend = ((xres + bpp - 1)/ 8) - 1; - data.h_bstart = xres / 8 /* + 1 */; - - data.h_bstop = data.h_total+1 + 2 + 1; - data.h_sstart = (xres / 8) + (hfront / 8) + 1; - data.h_sstop = (xres / 8) + (hfront / 8) + (hsync / 8) + 1; - - data.v_total = yres + vfront + vsync + vback - 1; - - data.v_dispend = yres - 1; - data.v_bstart = yres; - - data.v_bstop = data.v_total; - data.v_sstart = yres + vfront - 1 - 2; - data.v_sstop = yres + vfront + vsync - 1; - -#if 0 /* testing */ - - printk("HBS: %i\n", data.h_bstart); - printk("HSS: %i\n", data.h_sstart); - printk("HSE: %i\n", data.h_sstop); - printk("HBE: %i\n", data.h_bstop); - printk("HT: %i\n", data.h_total); - - printk("hsync: %i\n", hsync); - printk("hfront: %i\n", hfront); - printk("hback: %i\n", hback); - - printk("VBS: %i\n", data.v_bstart); - printk("VSS: %i\n", data.v_sstart); - printk("VSE: %i\n", data.v_sstop); - printk("VBE: %i\n", data.v_bstop); - printk("VT: %i\n", data.v_total); - - printk("vsync: %i\n", vsync); - printk("vfront: %i\n", vfront); - printk("vback: %i\n", vback); -#endif - - if (data.v_total >= 1024) - printk("MAYDAY: v_total >= 1024; bailing out!\n"); - - reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04)); - reg_w(GREG_FEATURE_CONTROL_W, 0x00); - - seq_w(SEQ_RESET, 0x00); - seq_w(SEQ_RESET, 0x03); /* reset sequencer logic */ - - /* - * CLOCKING_MODE bits: - * 2: This one is only set for certain text-modes, wonder if - * it may be for EGA-lines? (it was referred to as CLKDIV2) - * (The CL drivers sets it to 0x21 with the comment: - * FullBandwidth (video off) and 8/9 dot clock) - */ - seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */); - - seq_w(SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */ - seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */ - seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/ - seq_w(SEQ_RESET, 0x01); - seq_w(SEQ_RESET, 0x03); - - seq_w(SEQ_EXTENDED_ENABLE, 0x05); - - seq_w(SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */ - seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00); - seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00); - seq_w(SEQ_LINEAR_0, 0x4a); - seq_w(SEQ_LINEAR_1, 0x00); - - seq_w(SEQ_SEC_HOST_OFF_HI, 0x00); - seq_w(SEQ_SEC_HOST_OFF_LO, 0x00); - seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40); - - /* - * The lower 4 bits (0-3) are used to set the font-width for - * text-mode - DON'T try to set this for gfx-mode. - */ - seq_w(SEQ_EXT_CLOCK_MODE, 0x10); - seq_w(SEQ_EXT_VIDEO_ADDR, 0x03); - - /* - * Extended Pixel Control: - * bit 0: text-mode=0, gfx-mode=1 (Graphics Byte ?) - * bit 1: (Packed/Nibble Pixel Format ?) - * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp - */ - seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4)); - - seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04); - seq_w(SEQ_COLOR_EXP_WFG, 0x01); - seq_w(SEQ_COLOR_EXP_WBG, 0x00); - seq_w(SEQ_EXT_RW_CONTROL, 0x00); - seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8))); - seq_w(SEQ_COLOR_KEY_CNTL, 0x40); - seq_w(SEQ_COLOR_KEY_MATCH0, 0x00); - seq_w(SEQ_COLOR_KEY_MATCH1, 0x00); - seq_w(SEQ_COLOR_KEY_MATCH2, 0x00); - seq_w(SEQ_CRC_CONTROL, 0x00); - seq_w(SEQ_PERF_SELECT, 0x10); - seq_w(SEQ_ACM_APERTURE_1, 0x00); - seq_w(SEQ_ACM_APERTURE_2, 0x30); - seq_w(SEQ_ACM_APERTURE_3, 0x00); - seq_w(SEQ_MEMORY_MAP_CNTL, 0x03); - - - /* unlock register CRT0..CRT7 */ - crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20); - - /* Zuerst zu schreibende Werte nur per printk ausgeben */ - DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total); - crt_w(CRT_HOR_TOTAL, data.h_total & 0xff); - - DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend); - crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff); - - DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart); - crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff); - - DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32); - crt_w(CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f)); - - DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart); - crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff); - - tmp = (data.h_sstop & 0x1f); - if (data.h_bstop & 0x20) - tmp |= 0x80; - DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp); - crt_w(CRT_END_HOR_RETR, tmp); - - DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff); - crt_w(CRT_VER_TOTAL, (data.v_total & 0xff)); - - tmp = 0x10; /* LineCompare bit #9 */ - if (data.v_total & 256) - tmp |= 0x01; - if (data.v_dispend & 256) - tmp |= 0x02; - if (data.v_sstart & 256) - tmp |= 0x04; - if (data.v_bstart & 256) - tmp |= 0x08; - if (data.v_total & 512) - tmp |= 0x20; - if (data.v_dispend & 512) - tmp |= 0x40; - if (data.v_sstart & 512) - tmp |= 0x80; - DEBUG printk("CRT_OVERFLOW: %d\n", tmp); - crt_w(CRT_OVERFLOW, tmp); - - crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */ - - tmp = 0x40; /* LineCompare bit #8 */ - if (data.v_bstart & 512) - tmp |= 0x20; - if (var->vmode & FB_VMODE_DOUBLE) - tmp |= 0x80; - DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp); - crt_w(CRT_MAX_SCAN_LINE, tmp); - - crt_w(CRT_CURSOR_START, 0x00); - crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */ - - crt_w(CRT_START_ADDR_HIGH, 0x00); - crt_w(CRT_START_ADDR_LOW, 0x00); - - crt_w(CRT_CURSOR_LOC_HIGH, 0x00); - crt_w(CRT_CURSOR_LOC_LOW, 0x00); - - DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff); - crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff)); - -#if 1 - /* 5 refresh cycles per scanline */ - DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16); - crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20)); -#else - DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16); - crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32)); -#endif - DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff); - crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff)); - - DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff); - crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff)); - - DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff); - crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff)); - - DEBUG printk("CRT_MODE_CONTROL: 0xe3\n"); - crt_w(CRT_MODE_CONTROL, 0xe3); - - DEBUG printk("CRT_LINE_COMPARE: 0xff\n"); - crt_w(CRT_LINE_COMPARE, 0xff); - - tmp = (var->xres_virtual / 8) * (bpp / 8); - crt_w(CRT_OFFSET, tmp); - - crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */ - - tmp = 0x20; /* Enable extended end bits */ - if (data.h_total & 0x100) - tmp |= 0x01; - if ((data.h_dispend) & 0x100) - tmp |= 0x02; - if (data.h_bstart & 0x100) - tmp |= 0x04; - if (data.h_sstart & 0x100) - tmp |= 0x08; - if (var->vmode & FB_VMODE_INTERLACED) - tmp |= 0x10; - DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp); - crt_w(CRT_EXT_HOR_TIMING1, tmp); - - tmp = 0x00; - if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100) - tmp |= 0x10; - crt_w(CRT_EXT_START_ADDR, tmp); - - tmp = 0x00; - if (data.h_total & 0x200) - tmp |= 0x01; - if ((data.h_dispend) & 0x200) - tmp |= 0x02; - if (data.h_bstart & 0x200) - tmp |= 0x04; - if (data.h_sstart & 0x200) - tmp |= 0x08; - tmp |= ((data.h_bstop & 0xc0) >> 2); - tmp |= ((data.h_sstop & 0x60) << 1); - crt_w(CRT_EXT_HOR_TIMING2, tmp); - DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp); - - tmp = 0x10; /* Line compare bit 10 */ - if (data.v_total & 0x400) - tmp |= 0x01; - if ((data.v_dispend) & 0x400) - tmp |= 0x02; - if (data.v_bstart & 0x400) - tmp |= 0x04; - if (data.v_sstart & 0x400) - tmp |= 0x08; - tmp |= ((data.v_bstop & 0x300) >> 3); - if (data.v_sstop & 0x10) - tmp |= 0x80; - crt_w(CRT_EXT_VER_TIMING, tmp); - DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp); - - crt_w(CRT_MONITOR_POWER, 0x00); - - /* - * Convert from ps to Hz. - */ - freq_f = (1.0/(float)var->pixclock) * 1000000000; - freq = ((long)freq_f) * 1000; - - best_freq = find_fq(freq); - pll_w(0x02, best_freq); - best_freq = find_fq(61000000); - pll_w(0x0a, best_freq); - pll_w(0x0e, 0x22); - - gfx_w(GFX_SET_RESET, 0x00); - gfx_w(GFX_ENABLE_SET_RESET, 0x00); - gfx_w(GFX_COLOR_COMPARE, 0x00); - gfx_w(GFX_DATA_ROTATE, 0x00); - gfx_w(GFX_READ_MAP_SELECT, 0x00); - gfx_w(GFX_GRAPHICS_MODE, 0x00); - gfx_w(GFX_MISC, 0x05); - gfx_w(GFX_COLOR_XCARE, 0x0f); - gfx_w(GFX_BITMASK, 0xff); - - reg_r(ACT_ADDRESS_RESET); - attr_w(ACT_PALETTE0 , 0x00); - attr_w(ACT_PALETTE1 , 0x01); - attr_w(ACT_PALETTE2 , 0x02); - attr_w(ACT_PALETTE3 , 0x03); - attr_w(ACT_PALETTE4 , 0x04); - attr_w(ACT_PALETTE5 , 0x05); - attr_w(ACT_PALETTE6 , 0x06); - attr_w(ACT_PALETTE7 , 0x07); - attr_w(ACT_PALETTE8 , 0x08); - attr_w(ACT_PALETTE9 , 0x09); - attr_w(ACT_PALETTE10, 0x0a); - attr_w(ACT_PALETTE11, 0x0b); - attr_w(ACT_PALETTE12, 0x0c); - attr_w(ACT_PALETTE13, 0x0d); - attr_w(ACT_PALETTE14, 0x0e); - attr_w(ACT_PALETTE15, 0x0f); - reg_r(ACT_ADDRESS_RESET); - - attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */ - - attr_w(ACT_OVERSCAN_COLOR, 0x00); - attr_w(ACT_COLOR_PLANE_ENA, 0x0f); - attr_w(ACT_HOR_PEL_PANNING, 0x00); - attr_w(ACT_COLOR_SELECT, 0x00); - - reg_r(ACT_ADDRESS_RESET); - reg_w(ACT_DATA, 0x20); - - reg_w(VDAC_MASK, 0xff); - - /* - * Extended palette adressing ??? - */ - switch (bpp){ - case 8: - reg_w(0x83c6, 0x00); - break; - case 16: - reg_w(0x83c6, 0x60); - break; - case 24: - reg_w(0x83c6, 0xe0); - break; - default: - printk("Illegal color-depth: %i\n", bpp); - } - - reg_w(VDAC_ADDRESS, 0x00); - - seq_w(SEQ_MAP_MASK, 0x0f ); - - return 0; -} - -/* - * Initialization - * - * Set the default video mode for this chipset. If a video mode was - * specified on the command line, it will override the default mode. - */ - -static int retz3_init(void) -{ - int i; -#if 0 - volatile unsigned long *CursorBase; -#endif - unsigned long board_addr, board_size; - struct ConfigDev *cd; - - cd = zorro_get_board (z3_key); - zorro_config_board (z3_key, 0); - board_addr = (unsigned long)cd->cd_BoardAddr; - board_size = (unsigned long)cd->cd_BoardSize; - - for (i = 0; i < 256; i++){ - for (i = 0; i < 256; i++){ - retz3_color_table [i][0] = i; - retz3_color_table [i][1] = i; - retz3_color_table [i][2] = i; - retz3_color_table [i][3] = 0; - } - } - - *memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - - z3_mem = kernel_map (board_addr, board_size, - KERNELMAP_NOCACHE_SER, memstart); - - z3_regs = (char*) z3_mem; - z3_fbmem = z3_mem + VIDEO_MEM_OFFSET; - - /* Get memory size - for now we asume its a 4MB board */ - - z3_size = 0x00400000; /* 4 MB */ - - memset ((char*)z3_fbmem, 0, z3_size); - - /* Disable hardware cursor */ - - seq_w(SEQ_CURSOR_Y_INDEX, 0x00); - - -#if 0 - /* Initialize hardware cursor */ - CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400); - for (i=0; i < 8; i++){ - *(CursorBase +(i*4)) = 0xffffff00; - *(CursorBase+1+(i*4)) = 0xffff0000; - *(CursorBase+2+(i*4)) = 0xffff0000; - *(CursorBase+3+(i*4)) = 0xffff0000; - } - for (i=8; i < 64; i++){ - *(CursorBase +(i*4)) = 0xffff0000; - *(CursorBase+1+(i*4)) = 0xffff0000; - *(CursorBase+2+(i*4)) = 0xffff0000; - *(CursorBase+3+(i*4)) = 0xffff0000; - } -#endif - - retz3_setcolreg (255, 56, 100, 160, 0); - retz3_setcolreg (254, 0, 0, 0, 0); - - return 0; -} - - -/* - * This function should fill in the `fix' structure based on the - * values in the `par' structure. - */ - -static int retz3_encode_fix(struct fb_fix_screeninfo *fix, - struct retz3_fb_par *par) -{ - int i; - - strcpy(fix->id, retz3_fb_name); - fix->smem_start = z3_fbmem; - fix->smem_len = z3_size; - - fix->type = FB_TYPE_PACKED_PIXELS; - fix->type_aux = 0; - if (par->bpp == 8) - fix->visual = FB_VISUAL_PSEUDOCOLOR; - else - fix->visual = FB_VISUAL_DIRECTCOLOR; - - fix->xpanstep = 0; - fix->ypanstep = 0; - fix->ywrapstep = 0; - fix->line_length = 0; - - for (i = 0; i < arraysize(fix->reserved); i++) - fix->reserved[i] = 0; - - return 0; -} - - -/* - * Get the video params out of `var'. If a value doesn't fit, round - * it up, if it's too big, return -EINVAL. - */ - -static int retz3_decode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) -{ - par->xres = var->xres; - par->yres = var->yres; - par->xres_vir = var->xres_virtual; - par->yres_vir = var->yres_virtual; - par->bpp = var->bits_per_pixel; - par->pixclock = var->pixclock; - par->vmode = var->vmode; - - par->red = var->red; - par->green = var->green; - par->blue = var->blue; - par->transp = var->transp; - - par->left_margin = var->left_margin; - par->right_margin = var->right_margin; - par->upper_margin = var->upper_margin; - par->lower_margin = var->lower_margin; - par->hsync_len = var->hsync_len; - par->vsync_len = var->vsync_len; - - return 0; -} - - -/* - * Fill the `var' structure based on the values in `par' and maybe - * other values read out of the hardware. - */ - -static int retz3_encode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) -{ - int i; - - var->xres = par->xres; - var->yres = par->yres; - var->xres_virtual = par->xres_vir; - var->yres_virtual = par->yres_vir; - var->xoffset = 0; - var->yoffset = 0; - - var->bits_per_pixel = par->bpp; - var->grayscale = 0; - - var->red = par->red; - var->green = par->green; - var->blue = par->blue; - var->transp = par->transp; - - var->nonstd = 0; - var->activate = 0; - - var->height = -1; - var->width = -1; - - var->accel = FB_ACCEL_RETINAZ3; - - var->pixclock = par->pixclock; - - var->sync = 0; /* ??? */ - var->left_margin = par->left_margin; - var->right_margin = par->right_margin; - var->upper_margin = par->upper_margin; - var->lower_margin = par->lower_margin; - var->hsync_len = par->hsync_len; - var->vsync_len = par->vsync_len; - - for (i = 0; i < arraysize(var->reserved); i++) - var->reserved[i] = 0; - - var->vmode = par->vmode; - return 0; -} - - -/* - * Set a single color register. The values supplied are already - * rounded down to the hardware's capabilities (according to the - * entries in the var structure). Return != 0 for invalid regno. - */ - -static int retz3_setcolreg(unsigned int regno, unsigned int red, - unsigned int green, unsigned int blue, - unsigned int transp) -{ - /* We'll get to this */ - - if (regno > 255) - return 1; - - retz3_color_table [regno][0] = red & 0xff; - retz3_color_table [regno][1] = green & 0xff; - retz3_color_table [regno][2] = blue & 0xff; - retz3_color_table [regno][3] = transp; - - reg_w(VDAC_ADDRESS_W, regno); - reg_w(VDAC_DATA, (red & 0xff) >> 2); - reg_w(VDAC_DATA, (green & 0xff) >> 2); - reg_w(VDAC_DATA, (blue & 0xff) >> 2); - - return 0; -} - - -/* - * Read a single color register and split it into - * colors/transparent. Return != 0 for invalid regno. - */ - -static int retz3_getcolreg(unsigned int regno, unsigned int *red, - unsigned int *green, unsigned int *blue, - unsigned int *transp) -{ - if (regno > 255) - return 1; - *red = retz3_color_table [regno][0]; - *green = retz3_color_table [regno][1]; - *blue = retz3_color_table [regno][2]; - *transp = retz3_color_table [regno][3]; - return 0; -} - - -/* - * (Un)Blank the screen - */ - -void retz3_blank(int blank) -{ - int i; - - if (blank) - for (i = 0; i < 256; i++){ - reg_w(VDAC_ADDRESS_W, i); - reg_w(VDAC_DATA, 0); - reg_w(VDAC_DATA, 0); - reg_w(VDAC_DATA, 0); - } - else - for (i = 0; i < 256; i++){ - reg_w(VDAC_ADDRESS_W, i); - reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2); - reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2); - reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2); - } -} - - -void retz3_bitblt (struct fb_var_screeninfo *var, - unsigned short srcx, unsigned short srcy, unsigned - short destx, unsigned short desty, unsigned short - width, unsigned short height, unsigned short cmd, - unsigned short mask) -{ - - volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET); - unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF); - - unsigned short mod; - unsigned long tmp; - unsigned long pat, src, dst; - unsigned char blt_status; - - int i, xres_virtual = var->xres_virtual; - short bpp = (var->bits_per_pixel & 0xff); - - if (bpp < 8) - bpp = 8; - - tmp = mask | (mask << 16); - -#if 0 - /* - * Check for blitter finished before we start messing with the - * pattern. - */ - do{ - blt_status = *(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)); - }while ((blt_status & 1) == 0); -#endif - - i = 0; - do{ - *pattern++ = tmp; - }while(i++ < bpp/4); - - tmp = cmd << 8; - *(acm + ACM_RASTEROP_ROTATION/4) = tmp; - - mod = 0xc0c2; - - pat = 8 * PAT_MEM_OFF; - dst = bpp * (destx + desty * xres_virtual); - - /* - * Source is not set for clear. - */ - if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) { - src = bpp * (srcx + srcy * xres_virtual); - - if (destx > srcx) { - mod &= ~0x8000; - src += bpp * (width - 1); - dst += bpp * (width - 1); - pat += bpp * 2; - } - if (desty > srcy) { - mod &= ~0x4000; - src += bpp * (height - 1) * xres_virtual; - dst += bpp * (height - 1) * xres_virtual; - pat += bpp * 4; - } - - *(acm + ACM_SOURCE/4) = cpu_to_le32(src); - } - - *(acm + ACM_PATTERN/4) = cpu_to_le32(pat); - - *(acm + ACM_DESTINATION/4) = cpu_to_le32(dst); - - tmp = mod << 16; - *(acm + ACM_CONTROL/4) = tmp; - - tmp = width | (height << 16); - - *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp); - - *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; - *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; - - /* - * No reason to wait for the blitter to finish, it is better - * just to check if it has finished before we use it again. - */ -#if 1 -#if 0 - while ((*(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)) & 1) == 0); -#else - do{ - blt_status = *(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)); - } - while ((blt_status & 1) == 0); -#endif -#endif -} - -#if 0 -void retz3_fill (unsigned short x, unsigned short y, unsigned - short width, unsigned short height, - unsigned short mode, unsigned short color) -{ - -} -#endif - - -/************************************************************** - * Move cursor to x, y - */ -void retz3_MoveCursor (unsigned short x, unsigned short y) -{ - /* Guess we gotta deal with the cursor at some point */ -} - - -/* -------------------- Interfaces to hardware functions -------------------- */ - - -static struct fb_hwswitch retz3_switch = { - retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var, - retz3_getcolreg, retz3_setcolreg, retz3_blank -}; - - -/* -------------------- Generic routines ------------------------------------ */ - - -/* - * Fill the hardware's `par' structure. - */ - -static void retz3_fb_get_par(struct retz3_fb_par *par) -{ - if (current_par_valid) - *par = current_par; - else - fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par); -} - - -static void retz3_fb_set_par(struct retz3_fb_par *par) -{ - current_par = *par; - current_par_valid = 1; -} - - -static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) -{ - int err, activate; - struct retz3_fb_par par; - - if ((err = fbhw->decode_var(var, &par))) - return err; - activate = var->activate; - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) - retz3_fb_set_par(&par); - fbhw->encode_var(var, &par); - var->activate = activate; - -#if 1 - retz3_set_video(var, ¤t_par); -#endif - return 0; -} - - -/* - * Default Colormaps - */ - -static unsigned short red16[] = - { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000, - 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff }; -static unsigned short green16[] = - { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000, - 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff }; -static unsigned short blue16[] = - { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, - 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff }; - - -static struct fb_cmap default_16_colors = - { 0, 16, red16, green16, blue16, NULL }; - - -static struct fb_cmap *get_default_colormap(int bpp) -{ - return &default_16_colors; -} - - -#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16) -#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \ - ((1<<(width))-1)) : 0)) - -static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, - int kspc) -{ - int i, start; - unsigned short *red, *green, *blue, *transp; - unsigned int hred, hgreen, hblue, htransp; - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; - - if (start < 0) - return -EINVAL; - for (i = 0; i < cmap->len; i++) { - if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp)) - return 0; - hred = CNVT_FROMHW(hred, var->red.length); - hgreen = CNVT_FROMHW(hgreen, var->green.length); - hblue = CNVT_FROMHW(hblue, var->blue.length); - htransp = CNVT_FROMHW(htransp, var->transp.length); - if (kspc) { - *red = hred; - *green = hgreen; - *blue = hblue; - if (transp) - *transp = htransp; - } else { - put_user(hred, red); - put_user(hgreen, green); - put_user(hblue, blue); - if (transp) - put_user(htransp, transp); - } - red++; - green++; - blue++; - if (transp) - transp++; - } - return 0; -} - - -static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, - int kspc) -{ - int i, start; - unsigned short *red, *green, *blue, *transp; - unsigned int hred, hgreen, hblue, htransp; - - red = cmap->red; - green = cmap->green; - blue = cmap->blue; - transp = cmap->transp; - start = cmap->start; - - if (start < 0) - return -EINVAL; - for (i = 0; i < cmap->len; i++) { - if (kspc) { - hred = *red; - hgreen = *green; - hblue = *blue; - htransp = transp ? *transp : 0; - } else { - get_user(hred, red); - get_user(hgreen, green); - get_user(hblue, blue); - if (transp) - get_user(htransp, transp); - else - htransp = 0; - } - hred = CNVT_TOHW(hred, var->red.length); - hgreen = CNVT_TOHW(hgreen, var->green.length); - hblue = CNVT_TOHW(hblue, var->blue.length); - htransp = CNVT_TOHW(htransp, var->transp.length); - red++; - green++; - blue++; - if (transp) - transp++; - if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp)) - return 0; - } - return 0; -} - - -static void do_install_cmap(int con) -{ - if (con != currcon) - return; - if (disp[con].cmap.len) - do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1); - else - do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel), - &disp[con].var, 1); -} - - -static void memcpy_fs(int fsfromto, void *to, void *from, int len) -{ - switch (fsfromto) { - case 0: - memcpy(to, from, len); - return; - case 1: - copy_from_user(to, from, len); - return; - case 2: - copy_to_user(to, from, len); - return; - } -} - - -static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) -{ - int size; - int tooff = 0, fromoff = 0; - - if (to->start > from->start) - fromoff = to->start-from->start; - else - tooff = from->start-to->start; - size = to->len-tooff; - if (size > from->len-fromoff) - size = from->len-fromoff; - if (size < 0) - return; - size *= sizeof(unsigned short); - memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size); - memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size); - memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size); - if (from->transp && to->transp) - memcpy_fs(fsfromto, to->transp+tooff, - from->transp+fromoff, size); -} - - -static int alloc_cmap(struct fb_cmap *cmap, int len, int transp) -{ - int size = len*sizeof(unsigned short); - - if (cmap->len != len) { - if (cmap->red) - kfree(cmap->red); - if (cmap->green) - kfree(cmap->green); - if (cmap->blue) - kfree(cmap->blue); - if (cmap->transp) - kfree(cmap->transp); - cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; - cmap->len = 0; - if (!len) - return 0; - if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) - return -1; - if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) - return -1; - if (!(cmap->blue = kmalloc(size, GFP_ATOMIC))) - return -1; - if (transp) { - if (!(cmap->transp = kmalloc(size, GFP_ATOMIC))) - return -1; - } else - cmap->transp = NULL; - } - cmap->start = 0; - cmap->len = len; - copy_cmap(get_default_colormap(len), cmap, 0); - return 0; -} - - -/* - * Get the Fixed Part of the Display - */ - -static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con) -{ - struct retz3_fb_par par; - int error = 0; - - if (con == -1) - retz3_fb_get_par(&par); - else - error = fbhw->decode_var(&disp[con].var, &par); - return(error ? error : fbhw->encode_fix(fix, &par)); -} - - -/* - * Get the User Defined Part of the Display - */ - -static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con) -{ - struct retz3_fb_par par; - int error = 0; - - if (con == -1) { - retz3_fb_get_par(&par); - error = fbhw->encode_var(var, &par); - } else - *var = disp[con].var; - return error; -} - - -static void retz3_fb_set_disp(int con) -{ - struct fb_fix_screeninfo fix; - - retz3_fb_get_fix(&fix, con); - if (con == -1) - con = 0; - disp[con].screen_base = (unsigned char *)fix.smem_start; - disp[con].visual = fix.visual; - disp[con].type = fix.type; - disp[con].type_aux = fix.type_aux; - disp[con].ypanstep = fix.ypanstep; - disp[con].ywrapstep = fix.ywrapstep; - disp[con].can_soft_blank = 1; - disp[con].inverse = z3fb_inverse; -} - - -/* - * Set the User Defined Part of the Display - */ - -static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) -{ - int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; - - if ((err = do_fb_set_var(var, con == currcon))) - return err; - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { - oldxres = disp[con].var.xres; - oldyres = disp[con].var.yres; - oldvxres = disp[con].var.xres_virtual; - oldvyres = disp[con].var.yres_virtual; - oldbpp = disp[con].var.bits_per_pixel; - disp[con].var = *var; - if (oldxres != var->xres || oldyres != var->yres || - oldvxres != var->xres_virtual || - oldvyres != var->yres_virtual || - oldbpp != var->bits_per_pixel) { - retz3_fb_set_disp(con); - (*fb_info.changevar)(con); - alloc_cmap(&disp[con].cmap, 0, 0); - do_install_cmap(con); - } - } - var->activate = 0; - return 0; -} - - -/* - * Get the Colormap - */ - -static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) -{ - if (con == currcon) /* current console? */ - return(do_fb_get_cmap(cmap, &disp[con].var, kspc)); - else if (disp[con].cmap.len) /* non default colormap? */ - copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2); - else - copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), - cmap, kspc ? 0 : 2); - return 0; -} - - -/* - * Set the Colormap - */ - -static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) -{ - int err; - - if (!disp[con].cmap.len) { /* no colormap allocated? */ - if ((err = alloc_cmap(&disp[con].cmap, - 1<init(); - - if (z3fb_mode == -1) - z3fb_mode = 1; - - fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par); - fbhw->encode_var(&retz3_fb_predefined[0], &par); - - strcpy(fb_info.modename, retz3_fb_name); - fb_info.disp = disp; - fb_info.switch_con = &z3fb_switch; - fb_info.updatevar = &z3fb_updatevar; - fb_info.blank = &z3fb_blank; - fb_info.setcmap = &z3fb_setcmap; - - do_fb_set_var(&retz3_fb_predefined[0], 0); - retz3_fb_get_var(&disp[0].var, -1); - retz3_fb_set_disp(-1); - do_install_cmap(0); - - return &fb_info; -} - - -static int z3fb_switch(int con) -{ - /* Do we have to save the colormap? */ - if (disp[currcon].cmap.len) - do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1); - - do_fb_set_var(&disp[con].var, 1); - currcon = con; - /* Install new colormap */ - do_install_cmap(con); - return 0; -} - - -/* - * Update the `var' structure (called by fbcon.c) - * - * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. - * Since it's called by a kernel driver, no range checking is done. - */ - -static int z3fb_updatevar(int con) -{ - return 0; -} - - -/* - * Blank the display. - */ - -static void z3fb_blank(int blank) -{ - fbhw->blank(blank); -} - - -/* - * Set the colormap - */ - -static int z3fb_setcmap(struct fb_cmap *cmap, int con) -{ - return(retz3_fb_set_cmap(cmap, 1, con)); -} - - -/* - * Get a Video Mode - */ - -static int get_video_mode(const char *name) -{ - int i; - - for (i = 1; i <= NUM_PREDEF_MODES; i++) - if (!strcmp(name, retz3_fb_modenames[i])){ - retz3_fb_predefined[0] = retz3_fb_predefined[i]; - return i; - } - return -1; -} -/* - * Linux/arch/m68k/amiga/retz3fb.c -- Low level implementation of the - * RetinaZ3 frame buffer device - * - * Copyright (C) 1997 Jes Sorensen - * - * This file is based on the CyberVision64 frame buffer device and - * the generic Cirrus Logic driver. - * - * cyberfb.c: Copyright (C) 1996 Martin Apel, - * Geert Uytterhoeven - * clgen.c: Copyright (C) 1996 Frank Neumann - * - * History: - * - 22 Jan 97: Initial work - * - 14 Feb 97: Screen initialization works somewhat, still only - * 8-bit packed pixel is supported. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include "retz3fb.h" @@ -3402,7 +1651,7 @@ * Initialization */ -struct fb_info *retz3_fb_init(long *mem_start) +__initfunc(struct fb_info *retz3_fb_init(long *mem_start)) { int err; struct retz3_fb_par par; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/retz3fb.h linux/arch/m68k/amiga/retz3fb.h --- v2.1.36/linux/arch/m68k/amiga/retz3fb.h Wed Apr 23 19:01:14 1997 +++ linux/arch/m68k/amiga/retz3fb.h Sun Apr 27 15:13:50 1997 @@ -284,289 +284,3 @@ #define Z3BLTorInverted 0xb0 /* NOT src OR dst */ #define Z3BLTnand 0x70 /* NOT src OR NOT dst */ #define Z3BLTset 0xf0 /* 1 */ -/* - * Linux/arch/m68k/amiga/retz3fb.h -- Defines and macros for the - * RetinaZ3 frame buffer device - * - * Copyright (C) 1997 Jes Sorensen - * - * History: - * - 22 Jan 97: Initial work - * - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -/* - * Macros to read and write to registers. - */ -#define reg_w(reg,dat) (*(z3_regs + reg) = dat) -#define reg_r(reg) (*(z3_regs + reg)) - -/* - * Macro to access the sequencer. - */ -#define seq_w(sreg,sdat) \ - do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0) - -/* - * Macro to access the CRT controller. - */ -#define crt_w(creg,cdat) \ - do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0) - -/* - * Macro to access the graphics controller. - */ -#define gfx_w(greg,gdat) \ - do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0) - -/* - * Macro to access the attribute controller. - */ -#define attr_w(areg,adat) \ - do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0) - -/* - * Macro to access the pll. - */ -#define pll_w(preg,pdat) \ - do{ reg_w(PLL_IDX, preg); \ - reg_w(PLL_DATA, (pdat & 0xff)); \ - reg_w(PLL_DATA, (pdat >> 8));\ - } while(0) - -/* - * Offsets - */ -#define VIDEO_MEM_OFFSET 0x00c00000 -#define ACM_OFFSET 0x00b00000 - -/* - * Accelerator Control Menu - */ -#define ACM_PRIMARY_OFFSET 0x00 -#define ACM_SECONDARY_OFFSET 0x04 -#define ACM_MODE_CONTROL 0x08 -#define ACM_CURSOR_POSITION 0x0c -#define ACM_START_STATUS 0x30 -#define ACM_CONTROL 0x34 -#define ACM_RASTEROP_ROTATION 0x38 -#define ACM_BITMAP_DIMENSION 0x3c -#define ACM_DESTINATION 0x40 -#define ACM_SOURCE 0x44 -#define ACM_PATTERN 0x48 -#define ACM_FOREGROUND 0x4c -#define ACM_BACKGROUND 0x50 - -/* - * Video DAC addresses - */ -#define VDAC_ADDRESS 0x03c8 -#define VDAC_ADDRESS_W 0x03c8 -#define VDAC_ADDRESS_R 0x03c7 -#define VDAC_STATE 0x03c7 -#define VDAC_DATA 0x03c9 -#define VDAC_MASK 0x03c6 - -/* - * Sequencer - */ -#define SEQ_IDX 0x03c4 /* Sequencer Index */ -#define SEQ_DATA 0x03c5 -#define SEQ_RESET 0x00 -#define SEQ_CLOCKING_MODE 0x01 -#define SEQ_MAP_MASK 0x02 -#define SEQ_CHAR_MAP_SELECT 0x03 -#define SEQ_MEMORY_MODE 0x04 -#define SEQ_EXTENDED_ENABLE 0x05 /* NCR extensions */ -#define SEQ_UNKNOWN1 0x06 -#define SEQ_UNKNOWN2 0x07 -#define SEQ_CHIP_ID 0x08 -#define SEQ_UNKNOWN3 0x09 -#define SEQ_CURSOR_COLOR1 0x0a -#define SEQ_CURSOR_COLOR0 0x0b -#define SEQ_CURSOR_CONTROL 0x0c -#define SEQ_CURSOR_X_LOC_HI 0x0d -#define SEQ_CURSOR_X_LOC_LO 0x0e -#define SEQ_CURSOR_Y_LOC_HI 0x0f -#define SEQ_CURSOR_Y_LOC_LO 0x10 -#define SEQ_CURSOR_X_INDEX 0x11 -#define SEQ_CURSOR_Y_INDEX 0x12 -#define SEQ_CURSOR_STORE_HI 0x13 -#define SEQ_CURSOR_STORE_LO 0x14 -#define SEQ_CURSOR_ST_OFF_HI 0x15 -#define SEQ_CURSOR_ST_OFF_LO 0x16 -#define SEQ_CURSOR_PIXELMASK 0x17 -#define SEQ_PRIM_HOST_OFF_HI 0x18 -#define SEQ_PRIM_HOST_OFF_LO 0x19 -#define SEQ_LINEAR_0 0x1a -#define SEQ_LINEAR_1 0x1b -#define SEQ_SEC_HOST_OFF_HI 0x1c -#define SEQ_SEC_HOST_OFF_LO 0x1d -#define SEQ_EXTENDED_MEM_ENA 0x1e -#define SEQ_EXT_CLOCK_MODE 0x1f -#define SEQ_EXT_VIDEO_ADDR 0x20 -#define SEQ_EXT_PIXEL_CNTL 0x21 -#define SEQ_BUS_WIDTH_FEEDB 0x22 -#define SEQ_PERF_SELECT 0x23 -#define SEQ_COLOR_EXP_WFG 0x24 -#define SEQ_COLOR_EXP_WBG 0x25 -#define SEQ_EXT_RW_CONTROL 0x26 -#define SEQ_MISC_FEATURE_SEL 0x27 -#define SEQ_COLOR_KEY_CNTL 0x28 -#define SEQ_COLOR_KEY_MATCH0 0x29 -#define SEQ_COLOR_KEY_MATCH1 0x2a -#define SEQ_COLOR_KEY_MATCH2 0x2b -#define SEQ_UNKNOWN6 0x2c -#define SEQ_CRC_CONTROL 0x2d -#define SEQ_CRC_DATA_LOW 0x2e -#define SEQ_CRC_DATA_HIGH 0x2f -#define SEQ_MEMORY_MAP_CNTL 0x30 -#define SEQ_ACM_APERTURE_1 0x31 -#define SEQ_ACM_APERTURE_2 0x32 -#define SEQ_ACM_APERTURE_3 0x33 -#define SEQ_BIOS_UTILITY_0 0x3e -#define SEQ_BIOS_UTILITY_1 0x3f - -/* - * Graphics Controller - */ -#define GFX_IDX 0x03ce -#define GFX_DATA 0x03cf -#define GFX_SET_RESET 0x00 -#define GFX_ENABLE_SET_RESET 0x01 -#define GFX_COLOR_COMPARE 0x02 -#define GFX_DATA_ROTATE 0x03 -#define GFX_READ_MAP_SELECT 0x04 -#define GFX_GRAPHICS_MODE 0x05 -#define GFX_MISC 0x06 -#define GFX_COLOR_XCARE 0x07 -#define GFX_BITMASK 0x08 - -/* - * CRT Controller - */ -#define CRT_IDX 0x03d4 -#define CRT_DATA 0x03d5 -#define CRT_HOR_TOTAL 0x00 -#define CRT_HOR_DISP_ENA_END 0x01 -#define CRT_START_HOR_BLANK 0x02 -#define CRT_END_HOR_BLANK 0x03 -#define CRT_START_HOR_RETR 0x04 -#define CRT_END_HOR_RETR 0x05 -#define CRT_VER_TOTAL 0x06 -#define CRT_OVERFLOW 0x07 -#define CRT_PRESET_ROW_SCAN 0x08 -#define CRT_MAX_SCAN_LINE 0x09 -#define CRT_CURSOR_START 0x0a -#define CRT_CURSOR_END 0x0b -#define CRT_START_ADDR_HIGH 0x0c -#define CRT_START_ADDR_LOW 0x0d -#define CRT_CURSOR_LOC_HIGH 0x0e -#define CRT_CURSOR_LOC_LOW 0x0f -#define CRT_START_VER_RETR 0x10 -#define CRT_END_VER_RETR 0x11 -#define CRT_VER_DISP_ENA_END 0x12 -#define CRT_OFFSET 0x13 -#define CRT_UNDERLINE_LOC 0x14 -#define CRT_START_VER_BLANK 0x15 -#define CRT_END_VER_BLANK 0x16 -#define CRT_MODE_CONTROL 0x17 -#define CRT_LINE_COMPARE 0x18 -#define CRT_UNKNOWN1 0x19 -#define CRT_UNKNOWN2 0x1a -#define CRT_UNKNOWN3 0x1b -#define CRT_UNKNOWN4 0x1c -#define CRT_UNKNOWN5 0x1d -#define CRT_UNKNOWN6 0x1e -#define CRT_UNKNOWN7 0x1f -#define CRT_UNKNOWN8 0x20 -#define CRT_UNKNOWN9 0x21 -#define CRT_UNKNOWN10 0x22 -#define CRT_UNKNOWN11 0x23 -#define CRT_UNKNOWN12 0x24 -#define CRT_UNKNOWN13 0x25 -#define CRT_UNKNOWN14 0x26 -#define CRT_UNKNOWN15 0x27 -#define CRT_UNKNOWN16 0x28 -#define CRT_UNKNOWN17 0x29 -#define CRT_UNKNOWN18 0x2a -#define CRT_UNKNOWN19 0x2b -#define CRT_UNKNOWN20 0x2c -#define CRT_UNKNOWN21 0x2d -#define CRT_UNKNOWN22 0x2e -#define CRT_UNKNOWN23 0x2f -#define CRT_EXT_HOR_TIMING1 0x30 /* NCR crt extensions */ -#define CRT_EXT_START_ADDR 0x31 -#define CRT_EXT_HOR_TIMING2 0x32 -#define CRT_EXT_VER_TIMING 0x33 -#define CRT_MONITOR_POWER 0x34 - -/* - * General Registers - */ -#define GREG_STATUS0_R 0x03c2 -#define GREG_STATUS1_R 0x03da -#define GREG_MISC_OUTPUT_R 0x03cc -#define GREG_MISC_OUTPUT_W 0x03c2 -#define GREG_FEATURE_CONTROL_R 0x03ca -#define GREG_FEATURE_CONTROL_W 0x03da -#define GREG_POS 0x0102 - -/* - * Attribute Controller - */ -#define ACT_IDX 0x03C0 -#define ACT_ADDRESS_R 0x03C0 -#define ACT_DATA 0x03C0 -#define ACT_ADDRESS_RESET 0x03DA -#define ACT_PALETTE0 0x00 -#define ACT_PALETTE1 0x01 -#define ACT_PALETTE2 0x02 -#define ACT_PALETTE3 0x03 -#define ACT_PALETTE4 0x04 -#define ACT_PALETTE5 0x05 -#define ACT_PALETTE6 0x06 -#define ACT_PALETTE7 0x07 -#define ACT_PALETTE8 0x08 -#define ACT_PALETTE9 0x09 -#define ACT_PALETTE10 0x0A -#define ACT_PALETTE11 0x0B -#define ACT_PALETTE12 0x0C -#define ACT_PALETTE13 0x0D -#define ACT_PALETTE14 0x0E -#define ACT_PALETTE15 0x0F -#define ACT_ATTR_MODE_CNTL 0x10 -#define ACT_OVERSCAN_COLOR 0x11 -#define ACT_COLOR_PLANE_ENA 0x12 -#define ACT_HOR_PEL_PANNING 0x13 -#define ACT_COLOR_SELECT 0x14 - -/* - * PLL - */ -#define PLL_IDX 0x83c8 -#define PLL_DATA 0x83c9 - -/* - * Blitter operations - */ -#define Z3BLTclear 0x00 /* 0 */ -#define Z3BLTand 0x80 /* src AND dst */ -#define Z3BLTandReverse 0x40 /* src AND NOT dst */ -#define Z3BLTcopy 0xc0 /* src */ -#define Z3BLTandInverted 0x20 /* NOT src AND dst */ -#define Z3BLTnoop 0xa0 /* dst */ -#define Z3BLTxor 0x60 /* src XOR dst */ -#define Z3BLTor 0xe0 /* src OR dst */ -#define Z3BLTnor 0x10 /* NOT src AND NOT dst */ -#define Z3BLTequiv 0x90 /* NOT src XOR dst */ -#define Z3BLTinvert 0x50 /* NOT dst */ -#define Z3BLTorReverse 0xd0 /* src OR NOT dst */ -#define Z3BLTcopyInverted 0x30 /* NOT src */ -#define Z3BLTorInverted 0xb0 /* NOT src OR dst */ -#define Z3BLTnand 0x70 /* NOT src OR NOT dst */ -#define Z3BLTset 0xf0 /* 1 */ diff -u --recursive --new-file v2.1.36/linux/arch/m68k/amiga/zorro.c linux/arch/m68k/amiga/zorro.c --- v2.1.36/linux/arch/m68k/amiga/zorro.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/amiga/zorro.c Thu May 1 12:05:00 1997 @@ -13,10 +13,11 @@ #include #include #include +#include +#include #include #include #include -#include #ifdef CONFIG_ZORRO @@ -415,10 +416,6 @@ PROD("MVD 819", MVD_819) END -BEGIN_PROD(DELACOMP) - PROD("RAM Expansion 2000", DELACOMP_RAM_2000) -END - BEGIN_PROD(VILLAGE_TRONIC) PROD("Domino Graphics Board (RAM)", DOMINO_RAM) PROD("Domino Graphics Board (REG)", DOMINO_REG) @@ -656,7 +653,6 @@ MANUF("Helfrich", HELFRICH1) MANUF("Software Result Enterprises", SW_RESULT_ENTS) MANUF("Masoboshi", MASOBOSHI) - MANUF("DelaComp", DELACOMP) MANUF("Village Tronic", VILLAGE_TRONIC) MANUF("Utilities Unlimited", UTILITIES_ULTD) MANUF("Amitrix", AMITRIX) @@ -992,7 +988,7 @@ * Initialization */ -void zorro_init(void) +__initfunc(void zorro_init(void)) { int i; struct ConfigDev *cd; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/atafb.c linux/arch/m68k/atari/atafb.c --- v2.1.36/linux/arch/m68k/atari/atafb.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/atari/atafb.c Thu May 1 12:05:00 1997 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -2911,8 +2912,8 @@ return(atari_fb_set_cmap(cmap, 1, con)); } -struct fb_info * -atari_fb_init(long *mem_start) +__initfunc(struct fb_info * +atari_fb_init(long *mem_start)) { int err; int pad; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c --- v2.1.36/linux/arch/m68k/atari/ataints.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/atari/ataints.c Thu May 1 12:05:00 1997 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -331,7 +332,7 @@ * the atari IRQ handling routines. */ -void atari_init_IRQ(void) +__initfunc(void atari_init_IRQ(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c --- v2.1.36/linux/arch/m68k/atari/atakeyb.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/atari/atakeyb.c Thu May 1 12:05:00 1997 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -804,7 +805,7 @@ * Martin Rogge, 20 Aug 1995 */ -int atari_keyb_init(void) +__initfunc(int atari_keyb_init(void)) { /* setup key map */ key_maps[0] = ataplain_map; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c --- v2.1.36/linux/arch/m68k/atari/config.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/atari/config.c Thu May 1 12:05:00 1997 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -106,7 +107,7 @@ * a temporary VBR and a vector table for the duration of the test. */ -static int hwreg_present( volatile void *regp ) +__initfunc(static int hwreg_present( volatile void *regp )) { int ret = 0; long save_sp, save_vbr; @@ -132,9 +133,8 @@ } #if 0 -static int hwreg_present_bywrite( volatile void *regp, - unsigned char val ) - +__initfunc(static int +hwreg_present_bywrite(volatile void *regp, unsigned char val)) { int ret; long save_sp, save_vbr; @@ -166,7 +166,7 @@ /* Basically the same, but writes a value into a word register, protected * by a bus error handler */ -static int hwreg_write( volatile void *regp, unsigned short val ) +__initfunc(static int hwreg_write( volatile void *regp, unsigned short val )) { int ret; long save_sp, save_vbr; @@ -201,7 +201,7 @@ * should be readable without trouble (from channel A!). */ -static int scc_test( volatile char *ctla ) +__initfunc(static int scc_test( volatile char *ctla )) { if (!hwreg_present( ctla )) return( 0 ); @@ -228,7 +228,7 @@ * Parse an Atari-specific record in the bootinfo */ -int atari_parse_bootinfo(const struct bi_record *record) +__initfunc(int atari_parse_bootinfo(const struct bi_record *record)) { int unknown = 0; const u_long *data = record->data; @@ -247,7 +247,7 @@ * Setup the Atari configuration info */ -void config_atari(void) +__initfunc(void config_atari(void)) { memset(&atari_hw_present, 0, sizeof(atari_hw_present)); @@ -493,7 +493,8 @@ } } -static void atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +__initfunc(static void +atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))) { /* set Timer C data Register */ mfp.tim_dt_c = INT_TICKS; @@ -976,7 +977,7 @@ } -static void atari_debug_init(void) +__initfunc(static void atari_debug_init(void)) { #ifdef CONFIG_KGDB /* if the m68k_debug_device is used by the GDB stub, do nothing here */ diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c --- v2.1.36/linux/arch/m68k/atari/joystick.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/atari/joystick.c Thu May 1 12:05:00 1997 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -128,7 +129,7 @@ release_joystick }; -int atari_joystick_init(void) +__initfunc(int atari_joystick_init(void)) { joystick[0].active = joystick[1].active = 0; joystick[0].ready = joystick[1].ready = 0; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/stdma.c linux/arch/m68k/atari/stdma.c --- v2.1.36/linux/arch/m68k/atari/stdma.c Fri Dec 20 01:19:58 1996 +++ linux/arch/m68k/atari/stdma.c Thu May 1 12:05:00 1997 @@ -32,6 +32,8 @@ #include #include #include +#include + #include #include #include @@ -171,7 +173,7 @@ * */ -void stdma_init(void) +__initfunc(void stdma_init(void)) { stdma_isr = NULL; request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW, diff -u --recursive --new-file v2.1.36/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.1.36/linux/arch/m68k/atari/stram.c Fri Dec 20 01:19:58 1996 +++ linux/arch/m68k/atari/stram.c Thu May 1 12:05:00 1997 @@ -149,6 +149,7 @@ #else #include +#include /* ++roman: * @@ -190,7 +191,7 @@ /* Overall end of ST-Ram */ -void atari_stram_init( void ) +__initfunc(void atari_stram_init( void )) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/boot/amiga/linuxboot.c linux/arch/m68k/boot/amiga/linuxboot.c --- v2.1.36/linux/arch/m68k/boot/amiga/linuxboot.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/boot/amiga/linuxboot.c Thu May 1 12:05:00 1997 @@ -22,6 +22,8 @@ * for more details. * * History: + * 27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo + * interface version 1.0 (Geert) * 03 Feb 1997 Implemented kernel decompression (Geert, based on Roman's * code for ataboot) * 30 Dec 1996 Reverted the CPU detection to the old scheme @@ -791,6 +793,7 @@ static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu) { *cpu = *fpu = 0; + if (SysBase->AttnFlags & AFF_68060) *cpu = CPU_68060; else if (SysBase->AttnFlags & AFF_68040) @@ -799,15 +802,15 @@ *cpu = CPU_68030; else if (SysBase->AttnFlags & AFF_68020) *cpu = CPU_68020; + if (*cpu == CPU_68040 || *cpu == CPU_68060) { if (SysBase->AttnFlags & AFF_FPU40) *fpu = *cpu; - } else { - if (SysBase->AttnFlags & AFF_68882) - *fpu = FPU_68882; - else if (SysBase->AttnFlags & AFF_68881) - *fpu = FPU_68881; - } + } else if (SysBase->AttnFlags & AFF_68882) + *fpu = FPU_68882; + else if (SysBase->AttnFlags & AFF_68881) + *fpu = FPU_68881; + *mmu = *cpu; } @@ -1047,7 +1050,7 @@ compat_bootinfo.cputype |= COMPAT_FPU_68040; else if (bi.fputype & FPU_68060) compat_bootinfo.cputype |= COMPAT_FPU_68060; - else { + else if (bi.fputype) { Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype); return(0); } diff -u --recursive --new-file v2.1.36/linux/arch/m68k/boot/amiga/linuxboot.h linux/arch/m68k/boot/amiga/linuxboot.h --- v2.1.36/linux/arch/m68k/boot/amiga/linuxboot.h Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/boot/amiga/linuxboot.h Thu May 1 12:05:00 1997 @@ -31,7 +31,7 @@ * Amiboot Version */ -#define AMIBOOT_VERSION "5.4" +#define AMIBOOT_VERSION "5.5" /* diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c --- v2.1.36/linux/arch/m68k/kernel/ints.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/ints.c Thu May 1 12:05:00 1997 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -79,7 +80,7 @@ * the IRQ handling routines. */ -void init_IRQ(void) +__initfunc(void init_IRQ(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.1.36/linux/arch/m68k/kernel/m68k_ksyms.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/m68k_ksyms.c Thu May 1 12:05:00 1997 @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include asmlinkage long long __ashrdi3 (long long, int); extern char m68k_debug_device[]; @@ -40,6 +43,7 @@ EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(local_irq_count); +EXPORT_SYMBOL(__m68k_bh_counter); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.1.36/linux/arch/m68k/kernel/process.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/process.c Thu May 1 12:05:00 1997 @@ -10,6 +10,7 @@ * This file handles the architecture-dependent parts of process handling.. */ +#include #include #include #include @@ -30,6 +31,22 @@ #include #include +/* + * Initial task structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ +static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; +unsigned long init_user_stack[1024] = { STACK_MAGIC, }; +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; + +struct mm_struct init_mm = INIT_MM; +struct task_struct init_task = INIT_TASK; + asmlinkage void ret_from_exception(void); /* @@ -46,8 +63,16 @@ /* endless idle loop with no priority at all */ current->priority = -100; current->counter = -100; - for (;;) + for (;;){ + if (!need_resched) +#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) + /* block out HSYNC on the atari (falcon) */ + __asm__("stop #0x2200" : : : "cc"); +#else /* portable version */ + __asm__("stop #0x2000" : : : "cc"); +#endif /* machine compilation types */ schedule(); + } ret = 0; out: unlock_kernel(); diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.1.36/linux/arch/m68k/kernel/ptrace.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/ptrace.c Sun Apr 27 15:08:01 1997 @@ -52,18 +52,6 @@ PT_REG(orig_d0), PT_REG(sr), PT_REG(pc), }; -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * Get contents of register REGNO in task TASK. */ @@ -340,7 +328,7 @@ if (pid == 1) /* you may not mess with init */ goto out; ret = -ESRCH; - if (!(child = get_task(pid))) + if (!(child = find_task_by_pid(pid))) goto out; ret = -EPERM; if (request == PTRACE_ATTACH) { diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c --- v2.1.36/linux/arch/m68k/kernel/setup.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/setup.c Thu May 1 12:05:00 1997 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -55,13 +56,13 @@ static char m68k_command_line[CL_SIZE]; char saved_command_line[CL_SIZE]; -void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)); +void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata; /* machine dependent keyboard functions */ -int (*mach_keyb_init) (void); +int (*mach_keyb_init) (void) __initdata; int (*mach_kbdrate) (struct kbd_repeat *) = NULL; void (*mach_kbd_leds) (unsigned int) = NULL; /* machine dependent irq functions */ -void (*mach_init_IRQ) (void); +void (*mach_init_IRQ) (void) __initdata; void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; void (*mach_get_model) (char *model) = NULL; int (*mach_get_hardware_list) (char *buffer) = NULL; @@ -73,12 +74,12 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL; int (*mach_set_clock_mmss) (unsigned long) = NULL; void (*mach_reset)( void ); -struct fb_info *(*mach_fb_init)(long *); +struct fb_info *(*mach_fb_init)(long *) __initdata; long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ -void (*mach_video_setup) (char *, int *); +void (*mach_video_setup) (char *, int *) __initdata; #ifdef CONFIG_BLK_DEV_FD -int (*mach_floppy_init) (void) = NULL; -void (*mach_floppy_setup) (char *, int *) = NULL; +int (*mach_floppy_init) (void) __initdata = NULL; +void (*mach_floppy_setup) (char *, int *) __initdata = NULL; void (*mach_floppy_eject) (void) = NULL; #endif @@ -94,7 +95,7 @@ #define MASK_256K 0xfffc0000 -static void m68k_parse_bootinfo(const struct bi_record *record) +__initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) { while (record->tag != BI_LAST) { int unknown = 0; @@ -141,8 +142,8 @@ } } -void setup_arch(char **cmdline_p, unsigned long * memory_start_p, - unsigned long * memory_end_p) + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, + unsigned long * memory_end_p)) { unsigned long memory_start, memory_end; extern int _etext, _edata, _end; @@ -337,7 +338,7 @@ } #ifdef CONFIG_BLK_DEV_FD -int floppy_init(void) +__initfunc(int floppy_init(void)) { if (mach_floppy_init) return mach_floppy_init(); @@ -345,7 +346,7 @@ return 0; } -void floppy_setup(char *str, int *ints) +__initfunc(void floppy_setup(char *str, int *ints)) { if (mach_floppy_setup) mach_floppy_setup (str, ints); @@ -358,7 +359,7 @@ } #endif -unsigned long arch_kbd_init(void) +__initfunc(unsigned long arch_kbd_init(void)) { return mach_keyb_init(); } @@ -372,7 +373,7 @@ *year = *mon = *day = *hour = *min = *sec = 0; } -void video_setup (char *options, int *ints) +__initfunc(void video_setup (char *options, int *ints)) { if (mach_video_setup) mach_video_setup (options, ints); diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.1.36/linux/arch/m68k/kernel/signal.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/signal.c Thu May 1 12:05:00 1997 @@ -42,7 +42,9 @@ #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) -asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); + asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); const int frame_extra_sizes[16] = { @@ -466,7 +468,7 @@ if (signr != SIGCHLD) continue; /* check for SIGCHLD: it's special */ - while (sys_waitpid(-1,NULL,WNOHANG) > 0) + while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) /* nothing */; continue; } diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/time.c linux/arch/m68k/kernel/time.c --- v2.1.36/linux/arch/m68k/kernel/time.c Fri Nov 22 05:56:35 1996 +++ linux/arch/m68k/kernel/time.c Thu May 1 12:05:00 1997 @@ -27,6 +27,24 @@ return -1; } +static inline void do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + extern int _stext; + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + if (pc < prof_len) + ++prof_buffer[pc]; + else + /* + * Dont ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + ++prof_buffer[prof_len-1]; + } +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -37,6 +55,9 @@ static long last_rtc_update=0; do_timer(regs); + + if (!user_mode(regs)) + do_profile(regs->pc); /* * If we have an externally synchronized Linux clock, then update diff -u --recursive --new-file v2.1.36/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c --- v2.1.36/linux/arch/m68k/kernel/traps.c Wed Apr 23 19:01:15 1997 +++ linux/arch/m68k/kernel/traps.c Thu May 1 12:05:00 1997 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ __ALIGN_STR "\n" SYMBOL_NAME_STR(nmihandler) ": rte"); -void trap_init (void) +__initfunc(void trap_init (void)) { int i; diff -u --recursive --new-file v2.1.36/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.1.36/linux/arch/m68k/mm/init.c Wed Apr 23 19:01:16 1997 +++ linux/arch/m68k/mm/init.c Thu May 1 12:05:00 1997 @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM #include #endif @@ -116,9 +117,8 @@ return ptablep; } -static unsigned long map_chunk (unsigned long addr, - unsigned long size, - unsigned long *memavailp) +__initfunc(static unsigned long +map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp)) { #define ONEMEG (1024*1024) #define L3TREESIZE (256*1024) @@ -283,6 +283,11 @@ extern unsigned long free_area_init(unsigned long, unsigned long); +/* References to section boundaries */ + +extern char _text, _etext, _edata, __bss_start, _end; +extern char __init_begin, __init_end; + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* @@ -291,7 +296,7 @@ * The parameters are pointers to where to stick the starting and ending * addresses of available kernel virtual memory. */ -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) { int chunk; unsigned long mem_avail = 0; @@ -395,12 +400,12 @@ return PAGE_ALIGN(free_area_init (start_mem, end_mem)); } -void mem_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { int codepages = 0; int datapages = 0; + int initpages = 0; unsigned long tmp; - extern int _etext; end_mem &= PAGE_MASK; high_memory = (void *) end_mem; @@ -448,8 +453,15 @@ if (VTOP (tmp) >= mach_max_dma_address) clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); if (PageReserved(mem_map+MAP_NR(tmp))) { - if (tmp < (unsigned long)&_etext) - codepages++; + if (tmp >= (unsigned long)&_text + && tmp < (unsigned long)&_edata) { + if (tmp < (unsigned long) &_etext) + codepages++; + else + datapages++; + } else if (tmp >= (unsigned long) &__init_begin + && tmp < (unsigned long) &__init_end) + initpages++; else datapages++; continue; @@ -461,16 +473,26 @@ #endif free_page(tmp); } - printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n", + printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10)); + datapages << (PAGE_SHIFT-10), + initpages << (PAGE_SHIFT-10)); } void free_initmem(void) { - /* To be written */ + unsigned long addr; + + addr = (unsigned long)&__init_begin; + for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + } + printk ("Freeing unused kernel memory: %dk freed\n", + (&__init_end - &__init_begin) >> 10); } void si_meminfo(struct sysinfo *val) diff -u --recursive --new-file v2.1.36/linux/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds --- v2.1.36/linux/arch/m68k/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/vmlinux.lds Thu May 1 12:05:00 1997 @@ -0,0 +1,56 @@ +/* ld script to make m68k Linux kernel */ +OUTPUT_FORMAT("elf32-m68k", "elf32-m68k", "elf32-m68k") +OUTPUT_ARCH(m68k) +ENTRY(_start) +SECTIONS +{ + . = 0x1000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x4e75 + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -u --recursive --new-file v2.1.36/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.1.36/linux/arch/mips/kernel/process.c Thu Dec 19 06:48:08 1996 +++ linux/arch/mips/kernel/process.c Sun Apr 27 09:58:44 1997 @@ -29,6 +29,22 @@ #include #include +/* + * Initial task structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ +static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; +unsigned long init_user_stack[1024] = { STACK_MAGIC, }; +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; + +struct mm_struct init_mm = INIT_MM; +struct task_struct init_task = INIT_TASK; + asmlinkage void ret_from_sys_call(void); /* diff -u --recursive --new-file v2.1.36/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.1.36/linux/arch/mips/kernel/ptrace.c Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/kernel/ptrace.c Sun Apr 27 15:08:01 1997 @@ -33,18 +33,6 @@ */ #define MAGICNUMBER 68 -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * this routine will get a word off of the processes privileged stack. * the offset is how far from the base addr as stored in the TSS. @@ -295,7 +283,7 @@ } if (pid == 1) /* you may not mess with init */ return -EPERM; - if (!(child = get_task(pid))) + if (!(child = find_task_by_pid(pid))) return -ESRCH; if (request == PTRACE_ATTACH) { if (child == current) diff -u --recursive --new-file v2.1.36/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.1.36/linux/arch/mips/kernel/syscalls.h Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/kernel/syscalls.h Sun Apr 27 15:08:01 1997 @@ -174,3 +174,4 @@ SYS(sys_munlock, 2) /* 4155 */ SYS(sys_mlockall, 1) SYS(sys_munlockall, 0) +SYS(sys_nfsservctl, 3) diff -u --recursive --new-file v2.1.36/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.1.36/linux/arch/mips/kernel/traps.c Wed Dec 13 02:39:44 1995 +++ linux/arch/mips/kernel/traps.c Sun Apr 27 15:08:01 1997 @@ -178,6 +178,7 @@ void do_ades(struct pt_regs *regs) { + struct task_struct *p; unsigned long pc = regs->cp0_epc; int i; @@ -187,12 +188,14 @@ return; } while(1); - for(i=0; ipid >= 2) - { - printk("Process %d\n", task[i]->pid); - dump_list_process(task[i], pc); + read_lock(&tasklist_lock); + for_each_task(p) { + if(p->pid >= 2) { + printk("Process %d\n", p->pid); + dump_list_process(p, pc); } + } + read_unlock(&tasklist_lock); show_regs(regs); dump_tlb_nonwired(); send_sig(SIGSEGV, current, 1); @@ -251,14 +254,16 @@ void do_ri(struct pt_regs *regs) { + struct task_struct *p; int i; - for(i=0; ipid >= 2) - { - printk("Process %d\n", task[i]->pid); - dump_list_process(task[i], 0x7ffff000); + read_lock(&tasklist_lock); + for_each_task(p) { + if(p->pid >= 2) { + printk("Process %d\n", p->pid); + dump_list_process(p, 0x7ffff000); } + } show_regs(regs); while(1); send_sig(SIGILL, current, 1); diff -u --recursive --new-file v2.1.36/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.1.36/linux/arch/ppc/kernel/misc.S Wed Dec 18 00:49:52 1996 +++ linux/arch/ppc/kernel/misc.S Sun Apr 27 15:08:01 1997 @@ -855,5 +855,6 @@ .long sys_mremap .long SYMBOL_NAME(sys_setresuid) .long SYMBOL_NAME(sys_getresuid) - .space (NR_syscalls-165)*4 + .long SYMBOL_NAME(sys_nfsservctl) + .space (NR_syscalls-166)*4 diff -u --recursive --new-file v2.1.36/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.1.36/linux/arch/ppc/kernel/process.c Sun Jan 26 02:07:05 1997 +++ linux/arch/ppc/kernel/process.c Sun Apr 27 09:58:44 1997 @@ -29,6 +29,24 @@ #include #include + +/* + * Initial task structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ +static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; +unsigned long init_user_stack[1024] = { STACK_MAGIC, }; +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; + +struct mm_struct init_mm = INIT_MM; +struct task_struct init_task = INIT_TASK; + + int dump_fpu(void); void hard_reset_now(void); void switch_to(struct task_struct *, struct task_struct *); diff -u --recursive --new-file v2.1.36/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.1.36/linux/arch/ppc/kernel/ptrace.c Sun Jan 26 02:07:05 1997 +++ linux/arch/ppc/kernel/ptrace.c Sun Apr 27 15:08:01 1997 @@ -42,18 +42,6 @@ static int regoff[] = { }; -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * Get contents of register REGNO in task TASK. */ @@ -394,7 +382,7 @@ if (pid == 1) /* you may not mess with init */ goto out; ret = -ESRCH; - if (!(child = get_task(pid))) + if (!(child = find_task_by_pid(pid))) goto out; ret = -EPERM; if (request == PTRACE_ATTACH) { diff -u --recursive --new-file v2.1.36/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.1.36/linux/arch/ppc/mm/init.c Mon Apr 14 16:28:06 1997 +++ linux/arch/ppc/mm/init.c Sun Apr 27 15:08:01 1997 @@ -58,69 +58,62 @@ void show_mem(void) { - unsigned long i,free = 0,total = 0,reserved = 0; - unsigned long shared = 0; - PTE *ptr; - unsigned long full = 0, overflow = 0; - unsigned int ti; + struct task_struct *p; + unsigned long i,free = 0,total = 0,reserved = 0; + unsigned long shared = 0; + PTE *ptr; + unsigned long full = 0, overflow = 0; + unsigned int ti; - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = MAP_NR(high_memory); - while (i-- > 0) { - total++; - if (PageReserved(mem_map+i)) - reserved++; - else if (!atomic_read(&mem_map[i].count)) - free++; - else - shared += atomic_read(&mem_map[i].count) - 1; - } - printk("%lu pages of RAM\n",total); - printk("%lu free pages\n",free); - printk("%lu reserved pages\n",reserved); - printk("%lu pages shared\n",shared); - show_buffers(); + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = MAP_NR(high_memory); + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (!atomic_read(&mem_map[i].count)) + free++; + else + shared += atomic_read(&mem_map[i].count) - 1; + } + printk("%lu pages of RAM\n",total); + printk("%lu free pages\n",free); + printk("%lu reserved pages\n",reserved); + printk("%lu pages shared\n",shared); + show_buffers(); #ifdef CONFIG_NET - show_net_buffers(); + show_net_buffers(); #endif #ifdef HASHSTATS - printk("Hash Hits %u entries (buckets)\n",(Hash_size/sizeof(struct _PTE))/8); - for ( i = 0; i < (Hash_size/sizeof(struct _PTE))/8; i++ ) - { - if ( hashhits[i] >= 20 ) - { - printk("[%lu] \t %lu\n", i,hashhits[i]); - } - } + printk("Hash Hits %u entries (buckets)\n",(Hash_size/sizeof(struct _PTE))/8); + for ( i = 0; i < (Hash_size/sizeof(struct _PTE))/8; i++ ) { + if ( hashhits[i] >= 20 ) + printk("[%lu] \t %lu\n", i,hashhits[i]); + } #endif - for ( ptr = Hash ; ptr <= Hash+Hash_size ; ptr++) - { - if (ptr->v) - { - full++; - if (ptr->h == 1) - overflow++; - } - } - printk("Hash Table: %dkB Buckets: %dk PTEs: %d/%d (%%%d full) %d overflowed\n", - Hash_size>>10, (Hash_size/(sizeof(PTE)*8)) >> 10, - full,Hash_size/sizeof(PTE), - (full*100)/(Hash_size/sizeof(PTE)), - overflow); - printk(" Task context vsid0\n"); - for ( ti = 0; ti < NR_TASKS ; ti++ ); - { - if ( task[ti] ) - { - printk("%5d %8x %8x\n", - task[ti]->pid,task[ti]->mm->context, - ((SEGREG *)task[ti]->tss.segs)[0].vsid); - } - } - + for ( ptr = Hash ; ptr <= Hash+Hash_size ; ptr++) { + if (ptr->v) { + full++; + if (ptr->h == 1) + overflow++; + } + } + printk("Hash Table: %dkB Buckets: %dk PTEs: %d/%d (%%%d full) %d overflowed\n", + Hash_size>>10, (Hash_size/(sizeof(PTE)*8)) >> 10, + full,Hash_size/sizeof(PTE), + (full*100)/(Hash_size/sizeof(PTE)), + overflow); + printk(" Task context vsid0\n"); + read_lock(&tasklist_lock); + for_each_task(p) { + printk("%5d %8x %8x\n", + p->pid,p->mm->context, + ((SEGREG *)p->tss.segs)[0].vsid); + } + read_unlock(&tasklist_lock); } extern unsigned long free_area_init(unsigned long, unsigned long); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/Makefile linux/arch/sparc/Makefile --- v2.1.36/linux/arch/sparc/Makefile Mon Apr 14 16:28:06 1997 +++ linux/arch/sparc/Makefile Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.27 1997/04/07 06:54:08 davem Exp $ +# $Id: Makefile,v 1.28 1997/05/01 01:41:21 davem Exp $ # sparc/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -21,7 +21,7 @@ #LINKFLAGS = -N -Ttext 0xf0004000 LINKFLAGS = -T arch/sparc/vmlinux.lds -HEAD := arch/sparc/kernel/head.o +HEAD := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/mm \ arch/sparc/prom diff -u --recursive --new-file v2.1.36/linux/arch/sparc/ap1000/bnet.c linux/arch/sparc/ap1000/bnet.c --- v2.1.36/linux/arch/sparc/ap1000/bnet.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/bnet.c Sun Apr 27 15:08:01 1997 @@ -872,12 +872,12 @@ len = req->size - sizeof(*req); if (len == 0) { int pid = req->data[1]; - for_each_task(p) - if (p->pid == pid) { - send_sig(sig,p,1); - return; - } - printk("cell %d: no task with pid %d\n",mpp_cid(),pid); + p = find_task_by_pid(pid); + + if(p) + send_sig(sig, p, 1); + else + printk("cell %d: no task with pid %d\n",mpp_cid(),pid); return; } @@ -889,9 +889,11 @@ read_bif(name,len); name[len] = 0; + read_lock(&tasklist_lock); for_each_task(p) if (strcmp(name,p->comm) == 0) send_sig(sig,p,1); + read_unlock(&tasklist_lock); } diff -u --recursive --new-file v2.1.36/linux/arch/sparc/ap1000/hw.c linux/arch/sparc/ap1000/hw.c --- v2.1.36/linux/arch/sparc/ap1000/hw.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/hw.c Sun Apr 27 15:08:01 1997 @@ -86,14 +86,21 @@ static void show_ptasks(void) { extern struct task_struct *task[]; + struct task_struct *p; int i; int count=0; - for (i=MPP_TASK_BASE;itarray_ptr; + + if(tp >= &task[MPP_TASK_BASE]) { + show_task(p); count++; } + } + read_unlock(&tasklist_lock); + if (count == 0) printk("no parallel tasks on cell %d\n",mpp_cid()); } @@ -101,14 +108,18 @@ static void show_utasks(void) { extern struct task_struct *task[]; + struct task_struct *p; int i; int count=0; - for (i=0;iuid > 1) { + read_lock(&tasklist_lock); + for_each_task(p) { + if(p->uid > 1) { show_task(task[i]); count++; } + } + read_unlock(&tasklist_lock); if (count == 0) printk("no user tasks on cell %d\n",mpp_cid()); @@ -118,15 +129,19 @@ static void show_otasks(void) { extern struct task_struct *task[]; + struct task_struct *p; int i; int count=0; extern int ap_current_uid; - for (i=0;iuid == ap_current_uid) { + read_lock(&tasklist_lock); + for_each_task(p) { + if(p->uid == ap_current_uid) { show_task(task[i]); count++; } + } + read_unlock(&tasklist_lock); if (count == 0) printk("no tasks on cell %d\n",mpp_cid()); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/ap1000/mpp.c linux/arch/sparc/ap1000/mpp.c --- v2.1.36/linux/arch/sparc/ap1000/mpp.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/mpp.c Sun Apr 27 15:08:01 1997 @@ -66,6 +66,7 @@ if (block_parallel_tasks) return -1000; + /* XXX task[] fixme */ if (last_task && last_task != tsk->taskid && task[last_task] && !msc_switch_ok()) return -1000; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.1.36/linux/arch/sparc/kernel/Makefile Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/Makefile Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.39 1997/04/01 02:21:44 davem Exp $ +# $Id: Makefile,v 1.40 1997/05/01 01:40:36 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -28,7 +28,7 @@ CHECKASM_CC = $(CC) endif -all: kernel.o head.o +all: kernel.o head.o init_task.o O_TARGET := kernel.o IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/etrap.S linux/arch/sparc/kernel/etrap.S --- v2.1.36/linux/arch/sparc/kernel/etrap.S Mon Mar 17 14:54:20 1997 +++ linux/arch/sparc/kernel/etrap.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.23 1997/03/04 16:26:25 jj Exp $ +/* $Id: etrap.S,v 1.26 1997/05/01 08:53:32 davem Exp $ * etrap.S: Sparc trap window preparation for entry into the * Linux kernel. * @@ -129,15 +129,23 @@ trap_setup_from_user: /* We can't use %curptr yet. */ LOAD_CURRENT(t_kstack, t_twinmask) + + mov 1, %t_twinmask + sll %t_twinmask, (PAGE_SHIFT + 1), %t_twinmask + sub %t_twinmask, (TRACEREG_SZ + REGWIN_SZ), %t_twinmask + add %t_kstack, %t_twinmask, %t_kstack + mov 1, %t_twinmask - ld [%t_kstack + AOFF_task_saved_kernel_stack], %t_kstack sll %t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr) /* Build pt_regs frame. */ STORE_PT_ALL(t_kstack, t_psr, t_pc, t_npc, g2) /* Clear current->tss.w_saved */ - LOAD_CURRENT(curptr, g1) + mov 1, %curptr + sll %curptr, (PAGE_SHIFT + 1), %curptr + sub %curptr, (TRACEREG_SZ + REGWIN_SZ), %curptr + sub %t_kstack, %curptr, %curptr st %g0, [%curptr + AOFF_task_tss + AOFF_thread_w_saved] /* See if we are in the trap window. */ diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v2.1.36/linux/arch/sparc/kernel/head.S Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/kernel/head.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.81 1997/04/16 07:15:48 davem Exp $ +/* $Id: head.S,v 1.82 1997/05/01 01:40:38 davem Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -393,12 +393,6 @@ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) - .globl C_LABEL(cpu0_stack), C_LABEL(cpu1_stack), C_LABEL(cpu2_stack) - .globl C_LABEL(cpu3_stack) -C_LABEL(cpu0_stack): .skip 0x2000 -C_LABEL(cpu1_stack): .skip 0x2000 -C_LABEL(cpu2_stack): .skip 0x2000 -C_LABEL(cpu3_stack): .skip 0x2000 #endif .skip 4096 @@ -742,6 +736,9 @@ jmpl %g1, %g0 nop + /* This is to align init_task_union properly, be careful. -DaveM */ + .align 8192 + /* The code above should be at beginning and we have to take care about * short jumps, as branching to .text.init section from .text is usually * impossible */ @@ -986,12 +983,10 @@ /* Initialize the umask value for init_task just in case. * But first make current_set[0] point to something useful. */ - set C_LABEL(init_task), %g6 + set C_LABEL(init_task_union), %g6 set C_LABEL(current_set), %g2 st %g6, [%g2] - set C_LABEL(bootup_kernel_stack), %g3 - st %g3, [%g6 + AOFF_task_kernel_stack_page] st %g0, [%g6 + AOFF_task_tss + AOFF_thread_uwinmask] /* Compute NWINDOWS and stash it away. Now uses %wim trick explained diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/init_task.c linux/arch/sparc/kernel/init_task.c --- v2.1.36/linux/arch/sparc/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc/kernel/init_task.c Thu May 1 12:05:00 1997 @@ -0,0 +1,18 @@ +#include +#include + +#include +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +/* .text section in head.S is aligned at 2 page boundry and this gets linked + * right after that so that the init_task_union is aligned properly as well. + * We really don't need this special alignment like the Intel does, but + * I do it anyways for completeness. + */ +union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.1.36/linux/arch/sparc/kernel/process.c Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/process.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.93 1997/04/11 08:55:40 davem Exp $ +/* $Id: process.c,v 1.96 1997/05/01 08:53:33 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -441,12 +441,12 @@ if(regs->psr & PSR_PS) stack_offset -= REGWIN_SZ; - childregs = ((struct pt_regs *) (p->kernel_stack_page + stack_offset)); + childregs = ((struct pt_regs *) (((unsigned long)p) + stack_offset)); copy_regs(childregs, regs); new_stack = (((struct reg_window *) childregs) - 1); copy_regwin(new_stack, (((struct reg_window *) regs) - 1)); - p->tss.ksp = p->saved_kernel_stack = (unsigned long) new_stack; + p->tss.ksp = (unsigned long) new_stack; #ifdef __SMP__ p->tss.kpc = (((unsigned long) ret_from_smpfork) - 0x8); p->tss.kpsr = current->tss.fork_kpsr | PSR_PIL; @@ -467,7 +467,7 @@ p->tss.flags &= ~SPARC_FLAG_KTHREAD; p->tss.current_ds = USER_DS; - if (sp != current->tss.kregs->u_regs[UREG_FP]) { + if (sp != regs->u_regs[UREG_FP]) { struct sparc_stackf *childstack; struct sparc_stackf *parentstack; @@ -475,9 +475,8 @@ * This is a clone() call with supplied user stack. * Set some valid stack frames to give to the child. */ - childstack = (struct sparc_stackf *)sp; - parentstack = (struct sparc_stackf *) - current->tss.kregs->u_regs[UREG_FP]; + childstack = (struct sparc_stackf *) sp; + parentstack = (struct sparc_stackf *) regs->u_regs[UREG_FP]; #if 0 printk("clone: parent stack:\n"); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c --- v2.1.36/linux/arch/sparc/kernel/ptrace.c Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/kernel/ptrace.c Sun Apr 27 15:08:01 1997 @@ -24,18 +24,6 @@ #define MAGIC_CONSTANT 0x80000000 -/* change a pid into a task struct. */ -static inline struct task_struct * get_task(int pid) -{ - int i; - - for (i = 1; i < NR_TASKS; i++) { - if (task[i] != NULL && (task[i]->pid == pid)) - return task[i]; - } - return NULL; -} - /* * This routine gets a long from any process space by following the page * tables. NOTE! You should check that the long isn't on a page boundary, @@ -533,7 +521,7 @@ goto out; } #endif - if(!(child = get_task(pid))) { + if(!(child = find_task_by_pid(pid))) { pt_error_return(regs, ESRCH); goto out; } diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.1.36/linux/arch/sparc/kernel/smp.c Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/kernel/smp.c Thu May 1 12:05:00 1997 @@ -4,16 +4,18 @@ */ #include -#include -#include #include +#include #include #include #include #include #include +#include +#include + #include #include #include @@ -24,6 +26,9 @@ #include #include +#define __KERNEL_SYSCALLS__ +#include + #define IRQ_RESCHEDULE 13 #define IRQ_STOP_CPU 14 #define IRQ_CROSS_CALL 15 @@ -118,16 +123,6 @@ cpu_data[id].udelay_val = loops_per_sec; /* this is it on sparc. */ } -/* - * Architecture specific routine called by the kernel just before init is - * fired off. This allows the BP to have everything in order [we hope]. - * At the end of this all the AP's will hit the system scheduling and off - * we go. Each AP will load the system gdt's and jump through the kernel - * init into idle(). At this point the scheduler will one day take over - * and give them jobs to do. smp_callin is a standard routine - * we use to track CPU's as they power up. - */ - void smp_commence(void) { /* @@ -144,7 +139,7 @@ void smp_callin(void) { - int cpuid = smp_processor_id(); + int cpuid = hard_smp_processor_id(); local_flush_cache_all(); local_flush_tlb_all(); @@ -183,6 +178,25 @@ __sti(); } +extern int cpu_idle(void *unused); +extern void init_IRQ(void); + +/* Only broken Intel needs this, thus it should not even be referenced + * globally... + */ +void initialize_secondary(void) +{ +} + +/* Activate a secondary processor. */ +int start_secondary(void *unused) +{ + trap_init(); + init_IRQ(); + smp_callin(); + return cpu_idle(NULL); +} + void cpu_panic(void) { printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id()); @@ -220,6 +234,7 @@ cpu_number_map[boot_cpu_id] = 0; cpu_logical_map[0] = boot_cpu_id; klock_info.akp = boot_cpu_id; + current->processor = boot_cpu_id; smp_store_cpu_info(boot_cpu_id); set_irq_udt(mid_xlate[boot_cpu_id]); smp_setup_percpu_timer(); @@ -233,10 +248,19 @@ if(cpu_present_map & (1 << i)) { extern unsigned long sparc_cpu_startup; unsigned long *entry = &sparc_cpu_startup; + struct task_struct *p; int timeout; + /* Cook up an idler for this guy. */ + kernel_thread(start_secondary, NULL, CLONE_PID); + + p = task[++cpucount]; + + p->processor = i; + current_set[i] = p; + /* See trampoline.S for details... */ - entry += ((i-1) * 6); + entry += ((i-1) * 3); /* whirrr, whirrr, whirrrrrrrrr... */ printk("Starting CPU %d at %p\n", i, entry); @@ -253,10 +277,10 @@ } if(cpu_callin_map[i]) { /* Another "Red Snapper". */ - cpucount++; cpu_number_map[i] = i; cpu_logical_map[i] = i; } else { + cpucount--; printk("Processor %d is stuck.\n", i); } } @@ -376,14 +400,11 @@ void smp_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - unsigned long me = smp_processor_id(); - unsigned long flags, mask; - int i, timeout; - if(smp_processors_ready) { - __save_flags(flags); - __cli(); - spin_lock(&cross_call_lock); + register int ncpus = smp_num_cpus; + unsigned long flags; + + spin_lock_irqsave(&cross_call_lock, flags); /* Init function glue. */ ccall_info.func = func; @@ -393,56 +414,47 @@ ccall_info.arg4 = arg4; ccall_info.arg5 = arg5; - /* Init receive/complete mapping. */ - for(i = 0; i < smp_num_cpus; i++) { - ccall_info.processors_in[i] = 0; - ccall_info.processors_out[i] = 0; - } - ccall_info.processors_in[me] = 1; - ccall_info.processors_out[me] = 1; - - /* Fire it off. */ - mask = (cpu_present_map & ~(1 << me)); - for(i = 0; i < 4; i++) { - if(mask & (1 << i)) - set_cpu_int(mid_xlate[i], IRQ_CROSS_CALL); - } - - /* For debugging purposes right now we can timeout - * on both callin and callexit. - */ - timeout = CCALL_TIMEOUT; - for(i = 0; i < smp_num_cpus; i++) { - while(!ccall_info.processors_in[i] && timeout-- > 0) - barrier(); - if(!ccall_info.processors_in[i]) - goto procs_time_out; + /* Init receive/complete mapping, plus fire the IPI's off. */ + { + register void (*send_ipi)(int,int) = set_cpu_int; + register unsigned long mask; + register int i; + + mask = (cpu_present_map & ~(1 << smp_processor_id())); + for(i = 0; i < ncpus; i++) { + if(mask & (1 << i)) { + ccall_info.processors_in[i] = 0; + ccall_info.processors_out[i] = 0; + send_ipi(mid_xlate[i], IRQ_CROSS_CALL); + } else { + ccall_info.processors_in[i] = 1; + ccall_info.processors_out[i] = 1; + } + } } - /* Run local copy. */ + /* First, run local copy. */ func(arg1, arg2, arg3, arg4, arg5); - /* Spin on proc dispersion. */ - timeout = CCALL_TIMEOUT; - for(i = 0; i < smp_num_cpus; i++) { - while(!ccall_info.processors_out[i] && timeout-- > 0) - barrier(); - if(!ccall_info.processors_out[i]) - goto procs_time_out; + { + register int i; + + i = 0; + do { + while(!ccall_info.processors_in[i]) + barrier(); + } while(++i < ncpus); + + i = 0; + do { + while(!ccall_info.processors_out[i]) + barrier(); + } while(++i < ncpus); } - spin_unlock(&cross_call_lock); - __restore_flags(flags); - return; /* made it... */ - -procs_time_out: - printk("smp: Wheee, penguin drops off the bus\n"); - spin_unlock(&cross_call_lock); - __restore_flags(flags); - return; /* why me... why me... */ - } - /* Just need to run local copy. */ - func(arg1, arg2, arg3, arg4, arg5); + spin_unlock_irqrestore(&cross_call_lock, flags); + } else + func(arg1, arg2, arg3, arg4, arg5); /* Just need to run local copy. */ } void smp_flush_cache_all(void) diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.1.36/linux/arch/sparc/kernel/sys_sunos.c Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/kernel/sys_sunos.c Sun Apr 27 15:08:01 1997 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.78 1997/04/16 05:56:12 davem Exp $ +/* $Id: sys_sunos.c,v 1.79 1997/04/23 23:01:15 ecd Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1031,7 +1032,48 @@ unlock_kernel(); return ret; } - + +extern asmlinkage int sys_msgget (key_t key, int msgflg); +extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, + size_t msgsz, long msgtyp, int msgflg); +extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, + size_t msgsz, int msgflg); +extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf); + +asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4) +{ + struct sparc_stackf *sp; + unsigned long arg5; + int rval; + + lock_kernel(); + switch(op) { + case 0: + rval = sys_msgget((key_t)arg1, (int)arg2); + break; + case 1: + rval = sys_msgctl((int)arg1, (int)arg2, + (struct msqid_ds *)arg3); + break; + case 2: + sp = (struct sparc_stackf *)current->tss.kregs->u_regs[UREG_FP]; + arg5 = sp->xxargs[0]; + rval = sys_msgrcv((int)arg1, (struct msgbuf *)arg2, + (size_t)arg3, (long)arg4, (int)arg5); + break; + case 3: + rval = sys_msgsnd((int)arg1, (struct msgbuf *)arg2, + (size_t)arg3, (int)arg4); + break; + default: + rval = -EINVAL; + break; + } + unlock_kernel(); + return rval; +} + extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr); extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf); extern asmlinkage int sys_shmdt (char *shmaddr); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S --- v2.1.36/linux/arch/sparc/kernel/systbls.S Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/kernel/systbls.S Sun Apr 27 15:08:01 1997 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.60 1997/04/19 08:52:15 jj Exp $ +/* $Id: systbls.S,v 1.62 1997/04/23 23:01:08 ecd Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -106,15 +106,26 @@ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_stime), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_llseek) /* "We are the Knights of the Forest of Ni!!" */ - .long C_LABEL(sys_mlock), C_LABEL(sys_munlock), C_LABEL(sys_mlockall) - .long C_LABEL(sys_munlockall), C_LABEL(sys_sched_setparam) - .long C_LABEL(sys_sched_getparam), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_sched_get_priority_max), C_LABEL(sys_sched_get_priority_min) - .long C_LABEL(sys_sched_rr_get_interval), C_LABEL(sys_nanosleep) + .long C_LABEL(sys_mlock) + .long C_LABEL(sys_munlock) + .long C_LABEL(sys_mlockall) +/*240*/ .long C_LABEL(sys_munlockall) + .long C_LABEL(sys_sched_setparam) + .long C_LABEL(sys_sched_getparam) + .long C_LABEL(sys_sched_setscheduler) + .long C_LABEL(sys_sched_getscheduler) +/*245*/ .long C_LABEL(sys_sched_yield) + .long C_LABEL(sys_sched_get_priority_max) + .long C_LABEL(sys_sched_get_priority_min) + .long C_LABEL(sys_sched_rr_get_interval) + .long C_LABEL(sys_nanosleep) /*250*/ .long C_LABEL(sys_mremap) .long C_LABEL(sys_sysctl) - .long C_LABEL(sys_getsid), C_LABEL(sys_fdatasync), C_LABEL(sys_nfsservctl) - .long C_LABEL(sys_aplib), C_LABEL(sys_nis_syscall) + .long C_LABEL(sys_getsid) + .long C_LABEL(sys_fdatasync) + .long C_LABEL(sys_nfsservctl) +/*255*/ .long C_LABEL(sys_aplib) + .long C_LABEL(sys_nis_syscall) /* Now the SunOS syscall table. */ @@ -179,7 +190,7 @@ .long C_LABEL(sunos_getdomainname), C_LABEL(sys_setdomainname) .long C_LABEL(sunos_nosys), C_LABEL(sys_quotactl), C_LABEL(sunos_nosys) .long C_LABEL(sunos_mount), C_LABEL(sys_ustat), C_LABEL(sunos_semsys) - .long C_LABEL(sunos_nosys), C_LABEL(sunos_shmsys), C_LABEL(sunos_audit) + .long C_LABEL(sunos_msgsys), C_LABEL(sunos_shmsys), C_LABEL(sunos_audit) .long C_LABEL(sunos_nosys), C_LABEL(sunos_getdents), C_LABEL(sys_setsid) .long C_LABEL(sys_fchdir), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/tadpole.c linux/arch/sparc/kernel/tadpole.c --- v2.1.36/linux/arch/sparc/kernel/tadpole.c Sat Nov 9 00:11:50 1996 +++ linux/arch/sparc/kernel/tadpole.c Thu May 1 12:05:00 1997 @@ -4,6 +4,8 @@ */ #include +#include +#include #include #include diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/trampoline.S linux/arch/sparc/kernel/trampoline.S --- v2.1.36/linux/arch/sparc/kernel/trampoline.S Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/trampoline.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.6 1997/04/14 05:38:33 davem Exp $ +/* $Id: trampoline.S,v 1.9 1997/05/01 08:53:34 davem Exp $ * trampoline.S: SMP cpu boot-up trampoline code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -25,27 +26,18 @@ C_LABEL(sparc_cpu_startup): cpu1_startup: sethi %hi(C_LABEL(trapbase_cpu1)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu1)), %g3 - sethi %hi(C_LABEL(cpu1_stack)), %g2 - or %g2, %lo(C_LABEL(cpu1_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu1)), %g3 cpu2_startup: sethi %hi(C_LABEL(trapbase_cpu2)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu2)), %g3 - sethi %hi(C_LABEL(cpu2_stack)), %g2 - or %g2, %lo(C_LABEL(cpu2_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu2)), %g3 cpu3_startup: sethi %hi(C_LABEL(trapbase_cpu3)), %g3 - or %g3, %lo(C_LABEL(trapbase_cpu3)), %g3 - sethi %hi(C_LABEL(cpu3_stack)), %g2 - or %g2, %lo(C_LABEL(cpu3_stack)), %g2 b 1f - nop + or %g3, %lo(C_LABEL(trapbase_cpu3)), %g3 1: /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ @@ -62,14 +54,16 @@ wr %g3, 0x0, %tbr WRITE_PAUSE - /* Give ourselves a stack. */ - set 0x2000, %g5 - add %g2, %g5, %g2 ! end of stack - sub %g2, REGWIN_SZ, %sp - mov 0, %fp - - /* Set up curptr. */ - set C_LABEL(init_task), %g6 + /* Give ourselves a stack and curptr. */ + set C_LABEL(current_set), %g5 + srl %g3, 10, %g4 + and %g4, 0xc, %g4 + ld [%g5 + %g4], %g6 + + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, REGWIN_SZ, %sp + add %g6, %sp, %sp /* Turn on traps (PSR_ET). */ rd %psr, %g1 diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/wof.S linux/arch/sparc/kernel/wof.S --- v2.1.36/linux/arch/sparc/kernel/wof.S Mon Mar 17 14:54:21 1997 +++ linux/arch/sparc/kernel/wof.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: wof.S,v 1.33 1997/03/04 16:26:35 jj Exp $ +/* $Id: wof.S,v 1.36 1997/05/01 08:53:35 davem Exp $ * wof.S: Sparc window overflow handler. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -234,15 +234,20 @@ spnwin_patch3: and %twin_tmp, 0xff, %twin_tmp ! patched on 7win Sparcs st %twin_tmp, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask] - /* Jump onto kernel stack for this process... */ - ld [%curptr + AOFF_task_saved_kernel_stack], %sp + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, (TRACEREG_SZ + REGWIN_SZ), %sp + add %curptr, %sp, %sp /* Restore the saved globals and build a pt_regs frame. */ mov %saved_g5, %g5 - mov %g6, %l4 mov %saved_g6, %g6 STORE_PT_ALL(sp, t_psr, t_pc, t_npc, g1) - mov %l4, %g6 + + mov 1, %g6 + sll %g6, (PAGE_SHIFT + 1), %g6 + sub %g6, (TRACEREG_SZ + REGWIN_SZ), %g6 + sub %sp, %g6, %g6 /* Turn on traps and call c-code to deal with it. */ wr %t_psr, PSR_ET, %psr diff -u --recursive --new-file v2.1.36/linux/arch/sparc/kernel/wuf.S linux/arch/sparc/kernel/wuf.S --- v2.1.36/linux/arch/sparc/kernel/wuf.S Mon Mar 17 14:54:21 1997 +++ linux/arch/sparc/kernel/wuf.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: wuf.S,v 1.31 1997/03/04 16:26:37 jj Exp $ +/* $Id: wuf.S,v 1.34 1997/05/01 08:53:36 davem Exp $ * wuf.S: Window underflow trap handler for the Sparc. * * Copyright (C) 1995 David S. Miller @@ -145,14 +145,17 @@ * to the trap window and call c-code to deal with this. */ LOAD_CURRENT(l4, l5) - ld [%l4 + AOFF_task_saved_kernel_stack], %l5 + + mov 1, %l5 + sll %l5, (PAGE_SHIFT + 1), %l5 + sub %l5, (TRACEREG_SZ + REGWIN_SZ), %l5 + add %l4, %l5, %l5 /* Store globals into pt_regs frame. */ STORE_PT_GLOBALS(l5) STORE_PT_YREG(l5, g3) - /* Save kernel %sp in global while we change windows. */ - mov %l5, %g2 + /* Save current in a global while we change windows. */ mov %l4, %curptr save %g0, %g0, %g0 @@ -166,7 +169,10 @@ /* LOCATION: Window 'T' */ - mov %g2, %sp /* Jump onto kernel %sp being held */ + mov 1, %sp + sll %sp, (PAGE_SHIFT + 1), %sp + sub %sp, (TRACEREG_SZ + REGWIN_SZ), %sp + add %curptr, %sp, %sp /* Build rest of pt_regs. */ STORE_PT_INS(sp) diff -u --recursive --new-file v2.1.36/linux/arch/sparc/lib/irqlock.S linux/arch/sparc/lib/irqlock.S --- v2.1.36/linux/arch/sparc/lib/irqlock.S Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/lib/irqlock.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: irqlock.S,v 1.2 1997/04/19 04:33:37 davem Exp $ +/* $Id: irqlock.S,v 1.4 1997/05/01 02:26:54 davem Exp $ * irqlock.S: High performance IRQ global locking and interrupt entry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.1.36/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.36/linux/arch/sparc/mm/srmmu.c Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc/mm/srmmu.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.136 1997/04/20 14:11:51 ecd Exp $ +/* $Id: srmmu.c,v 1.140 1997/05/01 08:53:39 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -659,27 +659,6 @@ srmmu_set_entry(ptep, pte_val(pteval)); } -static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) -{ - unsigned long page = ((unsigned long)ptep) & PAGE_MASK; - - srmmu_set_entry(ptep, pte_val(pteval)); - __asm__ __volatile__(" - lda [%0] %2, %%g4 - orcc %%g4, 0x0, %%g0 - be 2f - sethi %%hi(%7), %%g5 -1: subcc %%g5, %6, %%g5 ! hyper_flush_cache_page - bne 1b - sta %%g0, [%1 + %%g5] %3 - lda [%4] %5, %%g0 -2:" : /* no outputs */ - : "r" (page | 0x400), "r" (page), "i" (ASI_M_FLUSH_PROBE), - "i" (ASI_M_FLUSH_PAGE), "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS), - "r" (vac_line_size), "i" (PAGE_SIZE) - : "g4", "g5", "cc"); -} - static void srmmu_set_pte_nocache_cypress(pte_t *ptep, pte_t pteval) { register unsigned long a, b, c, d, e, f, g; @@ -860,30 +839,12 @@ */ struct task_struct *srmmu_alloc_task_struct(void) { - return (struct task_struct *) kmalloc(sizeof(struct task_struct), GFP_KERNEL); -} - -unsigned long srmmu_alloc_kernel_stack(struct task_struct *tsk) -{ - unsigned long kstk = __get_free_pages(GFP_KERNEL, 1, 0); - - if(!kstk) - kstk = (unsigned long) vmalloc(PAGE_SIZE << 1); - - return kstk; + return (struct task_struct *) __get_free_pages(GFP_KERNEL, 1, 0); } static void srmmu_free_task_struct(struct task_struct *tsk) { - kfree(tsk); -} - -static void srmmu_free_kernel_stack(unsigned long stack) -{ - if(stack < VMALLOC_START) - free_pages(stack, 1); - else - vfree((char *)stack); + free_pages((unsigned long)tsk, 1); } /* Tsunami flushes. It's page level tlb invalidation is not very @@ -1365,17 +1326,28 @@ extern void hypersparc_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); extern void hypersparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); +static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) +{ + unsigned long page = ((unsigned long)ptep) & PAGE_MASK; + + srmmu_set_entry(ptep, pte_val(pteval)); + hypersparc_flush_page_to_ram(page); +} + static void hypersparc_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) { + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); hyper_flush_whole_icache(); - set_pte((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)))); } static void hypersparc_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) { unsigned long page = ((unsigned long) pgdp) & PAGE_MASK; - hypersparc_flush_page_to_ram(page); + if(pgdp != swapper_pg_dir) + hypersparc_flush_page_to_ram(page); + if(tsk->mm->context != NO_CONTEXT) { flush_cache_mm(tsk->mm); ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); @@ -1429,26 +1401,29 @@ static void hypersparc_switch_to_context(struct task_struct *tsk) { - hyper_flush_whole_icache(); if(tsk->mm->context == NO_CONTEXT) { + ctxd_t *ctxp; + alloc_context(tsk->mm); - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd); - flush_tlb_mm(tsk->mm); + ctxp = &srmmu_context_table[tsk->mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); } + hyper_flush_whole_icache(); srmmu_set_context(tsk->mm->context); } static void hypersparc_init_new_context(struct mm_struct *mm) { - hyper_flush_whole_icache(); + ctxd_t *ctxp; alloc_context(mm); - flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], mm->pgd); - flush_tlb_mm(mm); + ctxp = &srmmu_context_table[mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); + hyper_flush_whole_icache(); if(mm == current->mm) srmmu_set_context(mm->context); } @@ -2355,13 +2330,19 @@ static void hypersparc_destroy_context(struct mm_struct *mm) { if(mm->context != NO_CONTEXT && mm->count == 1) { + ctxd_t *ctxp; + /* HyperSparc is copy-back, any data for this * process in a modified cache line is stale * and must be written back to main memory now * else we eat shit later big time. */ flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir); + + ctxp = &srmmu_context_table[mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) swapper_pg_dir) >> 4)))); + hypersparc_flush_page_to_ram((unsigned long)ctxp); + flush_tlb_mm(mm); free_context(mm->context); mm->context = NO_CONTEXT; @@ -3014,9 +2995,7 @@ mmu_p2v = srmmu_p2v; /* Task struct and kernel stack allocating/freeing. */ - alloc_kernel_stack = srmmu_alloc_kernel_stack; alloc_task_struct = srmmu_alloc_task_struct; - free_kernel_stack = srmmu_free_kernel_stack; free_task_struct = srmmu_free_task_struct; quick_kernel_fault = srmmu_quick_kernel_fault; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.1.36/linux/arch/sparc/mm/sun4c.c Mon Apr 14 16:28:08 1997 +++ linux/arch/sparc/mm/sun4c.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.143 1997/04/11 00:42:14 davem Exp $ +/* $Id: sun4c.c,v 1.147 1997/05/01 08:53:42 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -1093,8 +1093,7 @@ panic("sun4c kernel fault handler bolixed..."); } -/* - * 4 page buckets for task struct and kernel stack allocation. +/* 2 page buckets for task struct and kernel stack allocation. * * TASK_STACK_BEGIN * bucket[0] @@ -1105,24 +1104,17 @@ * * Each slot looks like: * - * page 1 -- task struct - * page 2 -- unmapped, for stack redzone (maybe use for pgd) - * page 3/4 -- kernel stack + * page 1 -- task struct + beginning of kernel stack + * page 2 -- rest of kernel stack */ -struct task_bucket { - struct task_struct task; - char _unused1[PAGE_SIZE - sizeof(struct task_struct)]; - char kstack[(PAGE_SIZE*3)]; -}; - -struct task_bucket *sun4c_bucket[NR_TASKS]; +union task_union *sun4c_bucket[NR_TASKS]; static int sun4c_lowbucket_avail; -#define BUCKET_EMPTY ((struct task_bucket *) 0) -#define BUCKET_SIZE (PAGE_SIZE << 2) -#define BUCKET_SHIFT 14 /* log2(sizeof(struct task_bucket)) */ +#define BUCKET_EMPTY ((union task_union *) 0) +#define BUCKET_SHIFT (PAGE_SHIFT + 1) /* log2(sizeof(struct task_bucket)) */ +#define BUCKET_SIZE (1 << BUCKET_SHIFT) #define BUCKET_NUM(addr) ((((addr) - SUN4C_LOCK_VADDR) >> BUCKET_SHIFT)) #define BUCKET_ADDR(num) (((num) << BUCKET_SHIFT) + SUN4C_LOCK_VADDR) #define BUCKET_PTE(page) \ @@ -1177,10 +1169,10 @@ { int start, end; - /* 16 buckets per segment... */ - entry &= ~15; + /* 32 buckets per segment... */ + entry &= ~31; start = entry; - for(end = (start + 16); start < end; start++) + for(end = (start + 32); start < end; start++) if(sun4c_bucket[start] != BUCKET_EMPTY) return; @@ -1190,121 +1182,70 @@ static struct task_struct *sun4c_alloc_task_struct(void) { - unsigned long addr, page; + unsigned long addr, pages; int entry; - page = get_free_page(GFP_KERNEL); - if(!page) + pages = __get_free_pages(GFP_KERNEL, 1, 0); + if(!pages) return (struct task_struct *) 0; for(entry = sun4c_lowbucket_avail; entry < NR_TASKS; entry++) if(sun4c_bucket[entry] == BUCKET_EMPTY) break; if(entry == NR_TASKS) { - free_page(page); + free_pages(pages, 1); return (struct task_struct *) 0; } if(entry >= sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry + 1; addr = BUCKET_ADDR(entry); - sun4c_bucket[entry] = (struct task_bucket *) addr; + sun4c_bucket[entry] = (union task_union *) addr; if(sun4c_get_segmap(addr) == invalid_segment) get_locked_segment(addr); - sun4c_put_pte(addr, BUCKET_PTE(page)); + sun4c_put_pte(addr, BUCKET_PTE(pages)); + sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); return (struct task_struct *) addr; } -static unsigned long sun4c_alloc_kernel_stack(struct task_struct *tsk) -{ - unsigned long saddr = (unsigned long) tsk; - unsigned long page[2]; - - if(!saddr) - return 0; - page[0] = __get_free_page(GFP_KERNEL); - if(!page[0]) - return 0; - page[1] = __get_free_page(GFP_KERNEL); - if(!page[1]) { - free_page(page[0]); - return 0; - } - - saddr += PAGE_SIZE << 1; - sun4c_put_pte(saddr, BUCKET_PTE(page[0])); - sun4c_put_pte(saddr + PAGE_SIZE, BUCKET_PTE(page[1])); - return saddr; -} - -static void sun4c_free_kernel_stack_hw(unsigned long stack) -{ - unsigned long page[2]; - - page[0] = BUCKET_PTE_PAGE(sun4c_get_pte(stack)); - page[1] = BUCKET_PTE_PAGE(sun4c_get_pte(stack+PAGE_SIZE)); - - /* We are deleting a mapping, so the flushes here are mandatory. */ - sun4c_flush_page_hw(stack); - sun4c_flush_page_hw(stack + PAGE_SIZE); - - sun4c_put_pte(stack, 0); - sun4c_put_pte(stack + PAGE_SIZE, 0); - free_page(page[0]); - free_page(page[1]); -} - static void sun4c_free_task_struct_hw(struct task_struct *tsk) { unsigned long tsaddr = (unsigned long) tsk; - unsigned long page = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); + unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); /* We are deleting a mapping, so the flush here is mandatory. */ sun4c_flush_page_hw(tsaddr); + sun4c_flush_page_hw(tsaddr + PAGE_SIZE); sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); sun4c_bucket[entry] = BUCKET_EMPTY; if(entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; - free_page(page); + free_pages(pages, 1); garbage_collect(entry); } -static void sun4c_free_kernel_stack_sw(unsigned long stack) -{ - unsigned long page[2]; - - page[0] = BUCKET_PTE_PAGE(sun4c_get_pte(stack)); - page[1] = BUCKET_PTE_PAGE(sun4c_get_pte(stack+PAGE_SIZE)); - - /* We are deleting a mapping, so the flushes here are mandatory. */ - sun4c_flush_page_sw(stack); - sun4c_flush_page_sw(stack + PAGE_SIZE); - - sun4c_put_pte(stack, 0); - sun4c_put_pte(stack + PAGE_SIZE, 0); - free_page(page[0]); - free_page(page[1]); -} - static void sun4c_free_task_struct_sw(struct task_struct *tsk) { unsigned long tsaddr = (unsigned long) tsk; - unsigned long page = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); + unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); /* We are deleting a mapping, so the flush here is mandatory. */ sun4c_flush_page_sw(tsaddr); + sun4c_flush_page_sw(tsaddr + PAGE_SIZE); sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); sun4c_bucket[entry] = BUCKET_EMPTY; if(entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; - free_page(page); + free_pages(pages, 1); garbage_collect(entry); } @@ -1312,8 +1253,8 @@ { int entry; - if(sizeof(struct task_bucket) != (PAGE_SIZE << 2)) { - prom_printf("task bucket not 4 pages!\n"); + if(sizeof(union task_union) != (PAGE_SIZE << 1)) { + prom_printf("task union not 2 pages!\n"); prom_halt(); } for(entry = 0; entry < NR_TASKS; entry++) @@ -2645,7 +2586,6 @@ flush_tlb_mm = sun4c_flush_tlb_mm_hw; flush_tlb_range = sun4c_flush_tlb_range_hw; flush_tlb_page = sun4c_flush_tlb_page_hw; - free_kernel_stack = sun4c_free_kernel_stack_hw; free_task_struct = sun4c_free_task_struct_hw; switch_to_context = sun4c_switch_to_context_hw; destroy_context = sun4c_destroy_context_hw; @@ -2658,7 +2598,6 @@ flush_tlb_mm = sun4c_flush_tlb_mm_sw; flush_tlb_range = sun4c_flush_tlb_range_sw; flush_tlb_page = sun4c_flush_tlb_page_sw; - free_kernel_stack = sun4c_free_kernel_stack_sw; free_task_struct = sun4c_free_task_struct_sw; switch_to_context = sun4c_switch_to_context_sw; destroy_context = sun4c_destroy_context_sw; @@ -2736,7 +2675,6 @@ mmu_p2v = sun4c_p2v; /* Task struct and kernel stack allocating/freeing. */ - alloc_kernel_stack = sun4c_alloc_kernel_stack; alloc_task_struct = sun4c_alloc_task_struct; quick_kernel_fault = sun4c_quick_kernel_fault; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c --- v2.1.36/linux/arch/sparc/prom/console.c Thu Mar 27 14:40:00 1997 +++ linux/arch/sparc/prom/console.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.11 1997/03/18 17:58:10 jj Exp $ +/* $Id: console.c,v 1.12 1997/05/01 01:41:30 davem Exp $ * console.c: Routines that deal with sending and receiving IO * to/from the current console device using the PROM. * @@ -42,7 +42,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ @@ -83,7 +83,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ @@ -130,7 +130,7 @@ save_flags(flags); cli(); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); if(prom_node_has_property(st_p, "keyboard")) @@ -177,7 +177,7 @@ save_flags(flags); cli(); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/devmap.c linux/arch/sparc/prom/devmap.c --- v2.1.36/linux/arch/sparc/prom/devmap.c Sat Nov 9 00:12:24 1996 +++ linux/arch/sparc/prom/devmap.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: devmap.c,v 1.3 1996/09/19 20:27:19 davem Exp $ +/* $Id: devmap.c,v 1.4 1997/05/01 01:41:31 davem Exp $ * promdevmap.c: Map device/IO areas to virtual addresses. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -33,7 +33,7 @@ ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, num_bytes); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return ret; @@ -49,7 +49,7 @@ save_flags(flags); cli(); (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/devops.c linux/arch/sparc/prom/devops.c --- v2.1.36/linux/arch/sparc/prom/devops.c Thu Mar 27 14:40:00 1997 +++ linux/arch/sparc/prom/devops.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: devops.c,v 1.7 1997/03/18 17:58:19 jj Exp $ +/* $Id: devops.c,v 1.8 1997/05/01 01:41:31 davem Exp $ * devops.c: Device operations using the PROM. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -35,7 +35,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -60,7 +60,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return 0; @@ -86,7 +86,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/misc.c linux/arch/sparc/prom/misc.c --- v2.1.36/linux/arch/sparc/prom/misc.c Mon Apr 14 16:28:08 1997 +++ linux/arch/sparc/prom/misc.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.13 1997/04/10 05:12:59 davem Exp $ +/* $Id: misc.c,v 1.14 1997/05/01 01:41:32 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -22,7 +22,7 @@ (*(romvec->pv_reboot))(bcommand); /* Never get here. */ __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); } @@ -40,7 +40,7 @@ else (*(romvec->pv_fortheval.v2_eval))(fstring); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); } @@ -72,7 +72,7 @@ save_flags(flags); cli(); (*(romvec->pv_abort))(); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); install_linux_ticker(); @@ -97,7 +97,7 @@ (*(romvec->pv_halt))(); /* Never get here. */ __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); goto again; /* PROM is out to get me -DaveM */ diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/mp.c linux/arch/sparc/prom/mp.c --- v2.1.36/linux/arch/sparc/prom/mp.c Thu Mar 27 14:40:00 1997 +++ linux/arch/sparc/prom/mp.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: mp.c,v 1.7 1997/03/18 17:58:23 jj Exp $ +/* $Id: mp.c,v 1.8 1997/05/01 01:41:32 davem Exp $ * mp.c: OpenBoot Prom Multiprocessor support routines. Don't call * these on a UP or else you will halt and catch fire. ;) * @@ -36,7 +36,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -65,7 +65,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -94,7 +94,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); @@ -123,7 +123,7 @@ break; }; __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/segment.c linux/arch/sparc/prom/segment.c --- v2.1.36/linux/arch/sparc/prom/segment.c Sat Nov 9 00:12:30 1996 +++ linux/arch/sparc/prom/segment.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: segment.c,v 1.3 1996/09/19 20:27:28 davem Exp $ +/* $Id: segment.c,v 1.4 1997/05/01 01:41:33 davem Exp $ * segment.c: Prom routine to map segments in other contexts before * a standalone is completely mapped. This is for sun4 and * sun4c architectures only. @@ -22,7 +22,7 @@ save_flags(flags); cli(); (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); __asm__ __volatile__("ld [%0], %%g6\n\t" : : - "r" (¤t_set[smp_processor_id()]) : + "r" (¤t_set[hard_smp_processor_id()]) : "memory"); restore_flags(flags); return; diff -u --recursive --new-file v2.1.36/linux/arch/sparc/prom/tree.c linux/arch/sparc/prom/tree.c --- v2.1.36/linux/arch/sparc/prom/tree.c Thu Mar 27 14:40:00 1997 +++ linux/arch/sparc/prom/tree.c Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.16 1997/03/19 14:53:16 davem Exp $ +/* $Id: tree.c,v 1.17 1997/05/01 01:41:33 davem Exp $ * tree.c: Basic device tree traversal/scanning for the Linux * prom library. * @@ -18,7 +18,7 @@ /* Macro to restore "current" to the g6 register. */ #define restore_current() __asm__ __volatile__("ld [%0], %%g6\n\t" : : \ - "r" (¤t_set[smp_processor_id()]) : \ + "r" (¤t_set[hard_smp_processor_id()]) : \ "memory") static char promlib_buf[128]; diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.1.36/linux/arch/sparc64/kernel/entry.S Mon Apr 14 16:28:09 1997 +++ linux/arch/sparc64/kernel/entry.S Thu May 1 12:05:00 1997 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.14 1997/04/14 06:56:54 davem Exp $ +/* $Id: entry.S,v 1.15 1997/04/28 14:57:08 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -34,21 +34,37 @@ call sparc64_dtlb_fault_handler nop + /* Note, DMMU SFAR not updated for fast tlb data access miss + * traps, so we must use tag access to find the right page. + */ sparc64_dtlb_refbit_catch: + wr %g0, ASI_DMMU, %asi rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 + srlx %g5, PAGE_SHIFT, %g5 + ldxa [%g0 + TLB_SFSR] %asi, %g4 + sllx %g5, PAGE_SHIFT, %g5 ba,pt %xcc, etrap rd %pc, %g7 - call sparc64_dtlb_refbit_handler - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + + clr %o1 ! text_fault == 0 + mov %l5, %o3 ! address == sfar + and %l4, 0x4, %o2 ! write == sfsr.W + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr sparc64_itlb_refbit_catch: rdpr %pstate, %g1 wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate ba,pt %xcc, etrap rd %pc, %g7 - call sparc64_dtlb_refbit_handler - nop + + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3 + mov 1, %o1 ! text_fault == 1 + clr %o2 ! write == 0 + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr /* Note check out head.h, this code isn't even used for UP, * for SMP things will be different. In particular the data diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.1.36/linux/arch/sparc64/kernel/etrap.S Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc64/kernel/etrap.S Thu May 1 12:05:00 1997 @@ -1,7 +1,7 @@ -/* $Id: etrap.S,v 1.11 1997/04/14 17:04:45 jj Exp $ +/* $Id: etrap.S,v 1.12 1997/04/28 14:57:07 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ @@ -11,24 +11,28 @@ #include #include -/* We assume that pstate, when entering this, has AG and IE bits set, MG and IG clear */ + /* We assume that pstate, when entering this, has AG and + * IE bits set, MG and IG clear. + * + * We also guarentee for caller that AG %g4 and %g5 will have + * their values preserved and left in %l4 and %l5 respectively + * for him (fault handling needs this). + */ .text .align 32 .globl etrap, etrap_irq etrap: - rdpr %pil, %g4 + rdpr %pil, %g2 etrap_irq: rdpr %tstate, %g1 - sllx %g4, 20, %g4 - rdpr %tpc, %g2 - or %g1, %g4, %g1 - rdpr %tnpc, %g3 + sllx %g2, 20, %g2 + or %g1, %g2, %g1 /* What happens more often? etrap when already in priv or from userland? */ andcc %g1, TSTATE_PRIV, %g0 bne,a,pn %xcc, 1f - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g5 + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 /* Just when going from userland to privileged mode, * we have to change this stuff. @@ -38,41 +42,47 @@ * trap level until PRIMARY_CONTEXT is set to zero, else * we fall out of NUCLEUS too soon and crash hard. */ - rdpr %wstate, %g5 - mov PRIMARY_CONTEXT, %g7 - ldxa [%g7] ASI_DMMU, %g4 - mov SECONDARY_CONTEXT, %g6 - stxa %g0, [%g7] ASI_DMMU - stxa %g4, [%g6] ASI_DMMU - wrpr %g0, 0x0, %tl - - sll %g5, 3, %g5 - sethi %uhi(KERNBASE), %g4 - or %g4, %ulo(KERNBASE), %g4 - sethi %hi(current_set), %g6 - or %g6, %lo(current_set), %g6 - sllx %g4, 32, %g4 - wrpr %g5, %wstate - rdpr %canrestore, %g5 - ldx [%g6 + %g4], %g6 + mov PRIMARY_CONTEXT, %g1 + ldxa [%g1] ASI_DMMU, %g2 + stxa %g0, [%g1] ASI_DMMU + + mov SECONDARY_CONTEXT, %g1 + stxa %g2, [%g1] ASI_DMMU + + rdpr %wstate, %g1 + sll %g1, 3, %g1 + wrpr %g1, %wstate + + sethi %uhi(KERNBASE), %g2 + or %g2, %ulo(KERNBASE), %g2 + sethi %hi(current_set), %g1 + or %g1, %lo(current_set), %g1 + sllx %g2, 32, %g2 + ldx [%g1 + %g2], %g1 #ifdef __SMP__ /* FIXME: Fix the above insn for SMP */ #endif + rdpr %canrestore, %g2 wrpr %g0, 0, %canrestore - wrpr %g5, 0, %otherwin - ba,pt %xcc, 2f - ldx [%g6 + AOFF_task_saved_kernel_stack], %g5 + wrpr %g2, 0, %otherwin + + ldx [%g1 + AOFF_task_saved_kernel_stack], %g2 1: + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] + rdpr %tpc, %g1 + rdpr %tnpc, %g3 + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TPC] + rd %y, %g1 + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TNPC] + stx %g1, [%g2 + REGWIN_SZ + PT_V9_Y] + wrpr %g0, 0x0, %tl -2: - rd %y, %g4 - stx %g1, [%g5 + REGWIN_SZ + PT_V9_TSTATE] - stx %g2, [%g5 + REGWIN_SZ + PT_V9_TPC] - stx %g3, [%g5 + REGWIN_SZ + PT_V9_TNPC] - stx %g4, [%g5 + REGWIN_SZ + PT_V9_Y] + rdpr %pstate, %g1 - save %g5, -STACK_BIAS, %sp + save %g2, -STACK_BIAS, %sp mov %g1, %l1 + mov %g4, %l4 + mov %g5, %l5 mov %g7, %l2 wrpr %l1, PSTATE_AG, %pstate stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] @@ -104,11 +114,6 @@ .globl etraptl1 etraptl1: - rdpr %tl, %g4 rdpr %tstate, %g1 - sub %g4, 1, %g4 - rdpr %tpc, %g2 - rdpr %tnpc, %g3 - wrpr %g4, 0x0, %tl ba,pt %xcc, 1b - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g5 + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S --- v2.1.36/linux/arch/sparc64/lib/checksum.S Wed Apr 23 19:01:16 1997 +++ linux/arch/sparc64/lib/checksum.S Thu May 1 12:05:00 1997 @@ -555,7 +555,7 @@ add %i1, %i2, %i1 2: mov %i1, %o0 - wr %%g0, ASI_S, %%asi + wr %g0, ASI_S, %asi call __bzero_noasi mov %i3, %o1 1: diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/lib/copy_from_user.S linux/arch/sparc64/lib/copy_from_user.S --- v2.1.36/linux/arch/sparc64/lib/copy_from_user.S Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/lib/copy_from_user.S Thu May 1 12:05:00 1997 @@ -15,12 +15,16 @@ #include #include +#include + +#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4; #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ +99: PRE_RETL \ + retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ .align 4; \ @@ -33,6 +37,7 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ + PRE_RETL \ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ @@ -234,6 +239,7 @@ EX(lduba [%o1] %asi, %g2, add %g0, 1,#) stb %g2, [%o0] 1: + PRE_RETL retl clr %o0 @@ -332,6 +338,7 @@ EX(lduba [%o1] %asi, %g2, add %g0, 1,#) stb %g2, [%o0] 1: + PRE_RETL retl clr %o0 @@ -355,6 +362,7 @@ .section .fixup,#alloc,#execinstr .align 4 97: + PRE_RETL retl mov %o2, %o0 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ @@ -388,6 +396,7 @@ 1: and %g1, 0x7f, %o0 add %o0, %g7, %o0 + PRE_RETL retl sub %o0, %g2, %o0 51: @@ -413,6 +422,7 @@ 3: sll %g2, 2, %g2 2: + PRE_RETL retl add %g1, %g2, %o0 52: @@ -431,6 +441,7 @@ add %g2, %g4, %g2 and %o2, 0xf, %o0 add %o0, %o3, %o0 + PRE_RETL retl sub %o0, %g2, %o0 54: @@ -441,6 +452,7 @@ and %o2, 0xf, %o2 sub %o3, %o1, %o3 sub %o2, %o4, %o2 + PRE_RETL retl add %o2, %o3, %o0 55: @@ -452,5 +464,6 @@ and %g2, 1, %g2 sll %o1, 1, %o1 add %o2, %g2, %o0 + PRE_RETL retl add %o0, %o1, %o0 diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/lib/copy_to_user.S linux/arch/sparc64/lib/copy_to_user.S --- v2.1.36/linux/arch/sparc64/lib/copy_to_user.S Mon Apr 14 16:28:10 1997 +++ linux/arch/sparc64/lib/copy_to_user.S Thu May 1 12:05:00 1997 @@ -14,13 +14,17 @@ */ #include +#include #include +#define PRE_RETL sethi %uhi(KERNBASE), %g4; sllx %g4, 32, %g4; + #define EX(x,y,a,b,z) \ 98: x,y; \ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ -99: retl; \ +99: PRE_RETL \ + retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ .align 4; \ @@ -33,6 +37,7 @@ .section .fixup,z##alloc,z##execinstr; \ .align 4; \ 99: c, d, e; \ + PRE_RETL \ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ @@ -234,6 +239,7 @@ ldub [%o1], %g2 EX(stba %g2, [%o0] %asi, add %g0, 1,#) 1: + PRE_RETL retl clr %o0 @@ -332,6 +338,7 @@ ldub [%o1], %g2 EX(stba %g2, [%o0] %asi, add %g0, 1,#) 1: + PRE_RETL retl clr %o0 @@ -355,6 +362,7 @@ .section .fixup,#alloc,#execinstr .align 4 97: + PRE_RETL retl mov %o2, %o0 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ @@ -388,6 +396,7 @@ 1: and %g1, 0x7f, %o0 add %o0, %g7, %o0 + PRE_RETL retl sub %o0, %g2, %o0 51: @@ -413,6 +422,7 @@ 3: sll %g2, 2, %g2 2: + PRE_RETL retl add %g1, %g2, %o0 52: @@ -431,6 +441,7 @@ add %g2, %g4, %g2 and %o2, 0xf, %o0 add %o0, %o3, %o0 + PRE_RETL retl sub %o0, %g2, %o0 54: @@ -441,6 +452,7 @@ and %o2, 0xf, %o2 sub %o3, %o1, %o3 sub %o2, %o4, %o2 + PRE_RETL retl add %o2, %o3, %o0 55: @@ -452,5 +464,6 @@ and %g2, 1, %g2 sll %o1, 1, %o1 add %o2, %g2, %o0 + PRE_RETL retl add %o0, %o1, %o0 diff -u --recursive --new-file v2.1.36/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.36/linux/arch/sparc64/mm/init.c Wed Apr 23 19:01:17 1997 +++ linux/arch/sparc64/mm/init.c Thu May 1 12:05:01 1997 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.24 1997/04/17 21:49:41 jj Exp $ +/* $Id: init.c,v 1.25 1997/04/28 14:57:11 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -694,6 +694,11 @@ min_free_pages = 16; free_pages_low = min_free_pages + (min_free_pages >> 1); free_pages_high = min_free_pages + min_free_pages; + +#if 0 + printk("Testing fault handling...\n"); + *(char *)0x00000deadbef0000UL = 0; +#endif } void free_initmem (void) diff -u --recursive --new-file v2.1.36/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c --- v2.1.36/linux/drivers/block/amiflop.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/amiflop.c Thu May 1 12:05:01 1997 @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -1712,7 +1713,7 @@ } -static void probe_drives(void) +__initfunc(static void probe_drives(void)) { int drive,found; @@ -1860,7 +1861,7 @@ } -int amiga_floppy_init(void) +__initfunc(int amiga_floppy_init(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.1.36/linux/drivers/block/ataflop.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/ataflop.c Thu May 1 12:05:01 1997 @@ -75,6 +75,7 @@ #include #include #include +#include #include #include @@ -1777,7 +1778,7 @@ /* Initialize the 'unit' variable for drive 'drive' */ -static void fd_probe( int drive ) +__initfunc(static void fd_probe( int drive )) { UD.connected = 0; UDT = NULL; @@ -1820,7 +1821,7 @@ * declared absent. */ -static int fd_test_drive_present( int drive ) +__initfunc(static int fd_test_drive_present( int drive )) { unsigned long timeout; unsigned char status; @@ -1867,7 +1868,7 @@ * floppies, additionally start the disk-change and motor-off timers. */ -static void config_types( void ) +__initfunc(static void config_types( void )) { int drive, cnt = 0; @@ -2010,7 +2011,7 @@ floppy_revalidate, /* revalidate */ }; -int atari_floppy_init (void) +__initfunc(int atari_floppy_init (void)) { int i; @@ -2070,7 +2071,7 @@ } -void atari_floppy_setup( char *str, int *ints ) +__initfunc(void atari_floppy_setup( char *str, int *ints )) { int i; diff -u --recursive --new-file v2.1.36/linux/drivers/block/ez.c linux/drivers/block/ez.c --- v2.1.36/linux/drivers/block/ez.c Wed Dec 18 05:57:28 1996 +++ linux/drivers/block/ez.c Thu May 1 12:05:01 1997 @@ -101,6 +101,7 @@ #include #include #include +#include #include #include @@ -256,7 +257,7 @@ ez_revalidate /* revalidate new media */ }; -int ez_init (void) /* preliminary initialisation */ +__initfunc(int ez_init (void)) /* preliminary initialisation */ { if (register_blkdev(MAJOR_NR,"ez",&ez_fops)) { @@ -271,7 +272,7 @@ return 0; } -static void ez_geninit (struct gendisk *ignored) /* real init */ +__initfunc(static void ez_geninit (struct gendisk *ignored)) /* real init */ { int i; @@ -507,7 +508,7 @@ syntax: ez=base[,irq[,rep[,nybble]]] */ -void ez_setup(char *str, int *ints) +__initfunc(void ez_setup(char *str, int *ints)) { if (ints[0] > 0) ez_base = ints[1]; if (ints[0] > 1) ez_irq = ints[2]; @@ -748,7 +749,7 @@ /* ez_media_check: check for and acknowledge the MC flag */ -static void ez_media_check( void ) +__initfunc(static void ez_media_check( void )) { int r; @@ -768,7 +769,7 @@ disconnect(); } -static int ez_identify( void ) +__initfunc(static int ez_identify( void )) { int k, r; @@ -800,7 +801,7 @@ #define word_val(n) (ez_scratch[2*n]+256*ez_scratch[2*n+1]) -static void ez_get_capacity( void ) +__initfunc(static void ez_get_capacity( void )) { int ez_cylinders; @@ -821,7 +822,7 @@ ez_heads,ez_sectors); } -static void ez_standby_off( void ) +__initfunc(static void ez_standby_off( void )) { connect(); wait_for(0,NULL); @@ -830,7 +831,7 @@ disconnect(); } -static int ez_port_check( void ) /* check for 8-bit port */ +__initfunc(static int ez_port_check( void )) /* check for 8-bit port */ { int r; @@ -843,7 +844,7 @@ return 0; } -static int ez_detect( void ) +__initfunc(static int ez_detect( void )) { int j, k; char sig[EZ_SIGLEN] = EZ_SIG; diff -u --recursive --new-file v2.1.36/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.36/linux/drivers/block/floppy.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/floppy.c Fri May 2 09:20:51 1997 @@ -140,6 +140,7 @@ #include /* CMOS defines */ #include #include +#include #include #include @@ -3726,7 +3727,7 @@ /* Determine the floppy disk controller type */ /* This routine was written by David C. Niemi */ -static char get_fdc_version(void) +__initfunc(static char get_fdc_version(void)) { int r; @@ -3804,7 +3805,7 @@ /* lilo configuration */ -static void floppy_set_flags(int *ints,int param, int param2) +__initfunc(static void floppy_set_flags(int *ints,int param, int param2)) { int i; @@ -3817,7 +3818,7 @@ DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); } -static void daring(int *ints,int param, int param2) +__initfunc(static void daring(int *ints,int param, int param2)) { int i; @@ -3833,7 +3834,7 @@ DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); } -static void set_cmos(int *ints, int dummy, int dummy2) +__initfunc(static void set_cmos(int *ints, int dummy, int dummy2)) { int current_drive=0; @@ -3894,7 +3895,7 @@ { "L40SX", 0, &print_unex, 0, 0 } }; #define FLOPPY_SETUP -void floppy_setup(char *str, int *ints) +__initfunc(void floppy_setup(char *str, int *ints)) { int i; int param; @@ -3930,7 +3931,7 @@ static int have_no_fdc= -EIO; -int floppy_init(void) +__initfunc(int floppy_init(void)) { int i,unit,drive; @@ -4135,7 +4136,7 @@ char *floppy=NULL; -static void parse_floppy_cfg_string(char *cfg) +__initfunc(static void parse_floppy_cfg_string(char *cfg)) { char *ptr; int ints[11]; @@ -4151,7 +4152,7 @@ } } -static void mod_setup(char *pattern, void (*setup)(char *, int *)) +__initfunc(static void mod_setup(char *pattern, void (*setup)(char *, int *))) { unsigned long i; char c; diff -u --recursive --new-file v2.1.36/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.1.36/linux/drivers/block/genhd.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/genhd.c Thu May 1 12:05:01 1997 @@ -191,7 +191,7 @@ */ bh->b_state = 0; - if (le16_to_cpu(*(unsigned short *) (bh->b_data+510)) != MSDOS_LABEL_MAGIC) + if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC)) goto done; p = (struct partition *) (0x1BE + bh->b_data); @@ -316,7 +316,7 @@ #ifdef CONFIG_BLK_DEV_IDE check_table: #endif - if (le16_to_cpu(*(unsigned short *) (0x1fe + data)) != MSDOS_LABEL_MAGIC) { + if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) { brelse(bh); return 0; } @@ -359,7 +359,7 @@ goto read_mbr; /* start over with new MBR */ } } else if (sig <= 0x1ae && - le16_to_cpu(*(unsigned short *)(data + sig)) == 0x55AA && + *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) && (1 & *(unsigned char *)(data + sig + 2))) { /* DM6 signature in MBR, courtesy of OnTrack */ (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]"); @@ -424,7 +424,7 @@ /* * Check for old-style Disk Manager partition table */ - if (le16_to_cpu(*(unsigned short *) (data+0xfc)) == MSDOS_LABEL_MAGIC) { + if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) { p = (struct partition *) (0x1be + data); for (i = 4 ; i < 16 ; i++, current_minor++) { p--; @@ -603,7 +603,7 @@ } static int -amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector) +amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector) { struct buffer_head *bh; struct RigidDiskBlock *rdb; @@ -618,13 +618,15 @@ for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { if(!(bh = bread(dev,blk,512))) { - printk("Dev %d: unable to read RDB block %d\n",dev,blk); + printk("Dev %s: unable to read RDB block %d\n", + kdevname(dev),blk); goto rdb_done; } - if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { + if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { rdb = (struct RigidDiskBlock *)bh->b_data; - if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { - printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk); + if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { + printk("Dev %s: RDB in block %d has bad checksum\n", + kdevname(dev),blk); brelse(bh); continue; } @@ -633,14 +635,14 @@ brelse(bh); for (part = 1; blk > 0 && part <= 16; part++) { if (!(bh = bread(dev,blk,512))) { - printk("Dev %d: unable to read partition block %d\n", - dev,blk); + printk("Dev %s: unable to read partition block %d\n", + kdevname(dev),blk); goto rdb_done; } pb = (struct PartitionBlock *)bh->b_data; blk = htonl(pb->pb_Next); if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block( - (__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { + (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { /* Tell Kernel about it */ diff -u --recursive --new-file v2.1.36/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v2.1.36/linux/drivers/block/hd.c Fri Apr 4 08:52:17 1997 +++ linux/drivers/block/hd.c Thu May 1 12:05:01 1997 @@ -39,6 +39,7 @@ #include #include #include /* CMOS defines */ +#include #define REALLY_SLOW_IO #include @@ -110,7 +111,7 @@ } #endif -void hd_setup(char *str, int *ints) +__initfunc(void hd_setup(char *str, int *ints)) { int hdind = 0; @@ -792,7 +793,7 @@ block_fsync /* fsync */ }; -int hd_init(void) +__initfunc(int hd_init(void)) { if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { printk("hd: unable to get major %d for harddisk\n",MAJOR_NR); diff -u --recursive --new-file v2.1.36/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c --- v2.1.36/linux/drivers/block/ide-disk.c Wed Dec 11 06:45:54 1996 +++ linux/drivers/block/ide-disk.c Sun Apr 27 19:59:02 1997 @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -59,6 +58,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.1.36/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.1.36/linux/drivers/block/ide-probe.c Sat Jan 25 10:51:17 1997 +++ linux/drivers/block/ide-probe.c Sun Apr 27 19:59:02 1997 @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -58,6 +57,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.1.36/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.36/linux/drivers/block/ide.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/ide.c Thu May 1 12:05:01 1997 @@ -294,7 +294,6 @@ #include #include #include -#include #include #include #include @@ -307,6 +306,8 @@ #include #include #include +#include +#include #include #include @@ -2144,7 +2145,7 @@ * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. */ -static int stridx (const char *s, char c) +__initfunc(static int stridx (const char *s, char c)) { char *i = strchr(s, c); return (i && c) ? i - s : -1; @@ -2162,7 +2163,7 @@ * and base16 is allowed when prefixed with "0x". * 4. otherwise, zero is returned. */ -static int match_parm (char *s, const char *keywords[], int vals[], int max_vals) +__initfunc(static int match_parm (char *s, const char *keywords[], int vals[], int max_vals)) { static const char *decimal = "0123456789"; static const char *hex = "0123456789abcdef"; @@ -2261,7 +2262,7 @@ * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) * "ide0=umc8672" : probe/support umc8672 chipsets */ -void ide_setup (char *s) +__initfunc(void ide_setup (char *s)) { int i, vals[3]; ide_hwif_t *hwif; @@ -2558,7 +2559,7 @@ * ide_probe_pci() scans PCI for a specific vendor/device function, * and invokes the supplied init routine for each instance detected. */ -static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj) +__initfunc(static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init, int func_adj)) { unsigned long flags; unsigned index; @@ -2581,7 +2582,7 @@ * This routine should ideally be using pcibios_find_class() to find all * PCI IDE interfaces, but that function causes some systems to "go weird". */ -static void probe_for_hwifs (void) +__initfunc(static void probe_for_hwifs (void)) { #ifdef CONFIG_PCI /* @@ -2620,7 +2621,7 @@ #endif } -void ide_init_builtin_drivers (void) +__initfunc(void ide_init_builtin_drivers (void)) { /* * Probe for special "known" interface chipsets @@ -2889,7 +2890,7 @@ /* * This is gets invoked once during initialization, to set *everything* up */ -int ide_init (void) +__initfunc(int ide_init (void)) { init_ide_data (); @@ -2904,7 +2905,7 @@ char *options = NULL; MODULE_PARM(options,"s"); -static void parse_options (char *line) +__initfunc(static void parse_options (char *line)) { char *next = line; diff -u --recursive --new-file v2.1.36/linux/drivers/block/linear.c linux/drivers/block/linear.c --- v2.1.36/linux/drivers/block/linear.c Fri Nov 22 06:07:23 1996 +++ linux/drivers/block/linear.c Thu May 1 12:05:01 1997 @@ -21,6 +21,7 @@ #include #include +#include #include "linear.h" @@ -180,7 +181,7 @@ #ifndef MODULE -void linear_init (void) +__initfunc(void linear_init (void)) { register_md_personality (LINEAR, &linear_personality); } diff -u --recursive --new-file v2.1.36/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.1.36/linux/drivers/block/loop.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/block/loop.c Thu May 1 12:05:01 1997 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -537,8 +538,8 @@ #define loop_init init_module #endif -int -loop_init( void ) { +__initfunc(int +loop_init( void )) { int i; if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) { diff -u --recursive --new-file v2.1.36/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.1.36/linux/drivers/block/md.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/block/md.c Thu May 1 12:05:01 1997 @@ -35,6 +35,7 @@ #include #endif #include +#include #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -546,7 +547,7 @@ void raid1_init (void); void raid5_init (void); -int md_init (void) +__initfunc(int md_init (void)) { printk ("md driver %s MAX_MD_DEV=%d, MAX_REAL=%d\n", MD_VERSION, MAX_MD_DEV, MAX_REAL); diff -u --recursive --new-file v2.1.36/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.1.36/linux/drivers/block/ps2esdi.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/block/ps2esdi.c Thu May 1 12:05:01 1997 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -176,7 +177,7 @@ }; /* initialization routine called by ll_rw_blk.c */ -int ps2esdi_init(void) +__initfunc(int ps2esdi_init(void)) { /* register the device - pass the name, major number and operations @@ -197,7 +198,7 @@ } /* ps2esdi_init */ /* handles boot time command line parameters */ -void tp720_setup(char *str, int *ints) +__initfunc(void tp720_setup(char *str, int *ints)) { /* no params, just sets the tp720esdi flag if it exists */ @@ -205,7 +206,7 @@ tp720esdi = 1; } -void ed_setup(char *str, int *ints) +__initfunc(void ed_setup(char *str, int *ints)) { int hdind = 0; @@ -252,10 +253,9 @@ } /* ps2 esdi specific initialization - called thru the gendisk chain */ -static void ps2esdi_geninit(struct gendisk *ignored) +__initfunc(static void ps2esdi_geninit(struct gendisk *ignored)) { /* - The first part contains the initialization code for the ESDI disk subsystem. All we really do is search for the POS registers of the controller @@ -386,7 +386,7 @@ } /* ps2esdi_geninit */ -static void ps2esdi_get_device_cfg(void) +__initfunc(static void ps2esdi_get_device_cfg(void)) { u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; diff -u --recursive --new-file v2.1.36/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.1.36/linux/drivers/block/rd.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/rd.c Thu May 1 12:05:01 1997 @@ -51,9 +51,11 @@ #include #include #include +#include #include #include +#include extern void wait_for_keypress(void); @@ -269,7 +271,7 @@ }; /* This is the registration and initialization section of the ramdisk driver */ -int rd_init(void) +__initfunc(int rd_init(void)) { int i; @@ -334,8 +336,8 @@ * romfs * gzip */ -int -identify_ramdisk_image(kdev_t device, struct file *fp, int start_block) +__initfunc(int +identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) { const int size = 512; struct minix_super_block *minixsb; @@ -440,7 +442,7 @@ /* * This routine loads in the ramdisk image. */ -static void rd_load_image(kdev_t device,int offset) +__initfunc(static void rd_load_image(kdev_t device,int offset)) { struct inode inode, out_inode; struct file infile, outfile; @@ -527,7 +529,7 @@ } -void rd_load() +__initfunc(void rd_load(void)) { if (rd_doload == 0) return; @@ -549,7 +551,7 @@ #ifdef CONFIG_BLK_DEV_INITRD -void initrd_load(void) +__initfunc(void initrd_load(void)) { rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0); } @@ -608,21 +610,21 @@ #include "../../lib/inflate.c" -static void *malloc(int size) +__initfunc(static void *malloc(int size)) { return kmalloc(size, GFP_KERNEL); } -static void free(void *where) +__initfunc(static void free(void *where)) { kfree(where); } -static void gzip_mark(void **ptr) +__initfunc(static void gzip_mark(void **ptr)) { } -static void gzip_release(void **ptr) +__initfunc(static void gzip_release(void **ptr)) { } @@ -631,7 +633,7 @@ * Fill the input buffer. This is called only when the buffer is empty * and at least one byte is really needed. */ -static int fill_inbuf() +__initfunc(static int fill_inbuf(void)) { if (exit_code) return -1; @@ -648,7 +650,7 @@ * Write the output window window[0..outcnt-1] and update crc and bytes_out. * (Used for the decompressed data only.) */ -static void flush_window() +__initfunc(static void flush_window(void)) { ulg c = crc; /* temporary variable */ unsigned n; @@ -666,14 +668,14 @@ outcnt = 0; } -static void error(char *x) +__initfunc(static void error(char *x)) { printk(KERN_ERR "%s", x); exit_code = 1; } -static int -crd_load(struct file * fp, struct file *outfp) +__initfunc(static int +crd_load(struct file * fp, struct file *outfp)) { int result; diff -u --recursive --new-file v2.1.36/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.1.36/linux/drivers/block/xd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/block/xd.c Thu May 1 12:05:01 1997 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -126,7 +127,7 @@ static u_short xd_iobase = 0; /* xd_init: register the block device number and set up pointer tables */ -int xd_init (void) +__initfunc(int xd_init (void)) { if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd_init: unable to get major number %d\n",MAJOR_NR); @@ -141,7 +142,7 @@ } /* xd_detect: scan the possible BIOS ROM locations for the signature strings */ -static u_char xd_detect (u_char *controller, unsigned int *address) +__initfunc(static u_char xd_detect (u_char *controller, unsigned int *address)) { u_char i,j,found = 0; @@ -164,7 +165,7 @@ /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */ /* and set up the "raw" device entries in the table */ -static void xd_geninit (struct gendisk *ignored) +__initfunc(static void xd_geninit (struct gendisk *ignored)) { u_char i,controller; unsigned int address; @@ -527,7 +528,7 @@ return (csb & CSB_ERROR); } -static u_char xd_initdrives (void (*init_drive)(u_char drive)) +__initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive))) { u_char cmdblk[6],i,count = 0; @@ -541,7 +542,7 @@ return (count); } -static void xd_dtc_init_controller (unsigned int address) +__initfunc(static void xd_dtc_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -556,7 +557,7 @@ outb(0,XD_RESET); /* reset the controller */ } -static void xd_dtc_init_drive (u_char drive) +__initfunc(static void xd_dtc_init_drive (u_char drive)) { u_char cmdblk[6],buf[64]; @@ -581,7 +582,7 @@ printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive); } -static void xd_wd_init_controller (unsigned int address) +__initfunc(static void xd_wd_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -600,7 +601,7 @@ /* outb(0,XD_RESET); */ /* reset the controller */ } -static void xd_wd_init_drive (u_char drive) +__initfunc(static void xd_wd_init_drive (u_char drive)) { u_char cmdblk[6],buf[0x200]; @@ -622,7 +623,7 @@ printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive); } -static void xd_seagate_init_controller (unsigned int address) +__initfunc(static void xd_seagate_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -639,7 +640,7 @@ outb(0,XD_RESET); /* reset the controller */ } -static void xd_seagate_init_drive (u_char drive) +__initfunc(static void xd_seagate_init_drive (u_char drive)) { u_char cmdblk[6],buf[0x200]; @@ -655,7 +656,7 @@ } /* Omti support courtesy Dirk Melchers */ -static void xd_omti_init_controller (unsigned int address) +__initfunc(static void xd_omti_init_controller (unsigned int address)) { switch (address) { case 0xC8000: xd_iobase = 0x320; break; @@ -673,7 +674,7 @@ outb(0,XD_RESET); /* reset the controller */ } -static void xd_omti_init_drive (u_char drive) +__initfunc(static void xd_omti_init_drive (u_char drive)) { /* gets infos from drive */ xd_override_init_drive(drive); @@ -684,7 +685,7 @@ /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */ -static void xd_override_init_drive (u_char drive) +__initfunc(static void xd_override_init_drive (u_char drive)) { u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 }; u_char cmdblk[6],i; @@ -707,7 +708,7 @@ } /* xd_setup: initialise from command line parameters */ -void xd_setup (char *command,int *integers) +__initfunc(void xd_setup (char *command,int *integers)) { xd_override = 1; @@ -720,7 +721,7 @@ } /* xd_setparam: set the drive characteristics */ -static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc) +__initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)) { u_char cmdblk[14]; diff -u --recursive --new-file v2.1.36/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c --- v2.1.36/linux/drivers/block/z2ram.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/block/z2ram.c Thu May 1 12:05:01 1997 @@ -28,6 +28,7 @@ #include #include #include +#include #if defined(MODULE) #include @@ -282,8 +283,8 @@ block_fsync /* fsync */ }; -int -z2_init( void ) +__initfunc(int +z2_init( void )) { if ( !MACH_IS_AMIGA ) diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c --- v2.1.36/linux/drivers/cdrom/aztcd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/aztcd.c Thu May 1 12:05:01 1997 @@ -166,6 +166,7 @@ #include #include #include +#include #include #include @@ -1049,7 +1050,7 @@ Kernel Interface Functions ########################################################################## */ -void aztcd_setup(char *str, int *ints) +__initfunc(void aztcd_setup(char *str, int *ints)) { if (ints[0] > 0) azt_port = ints[1]; if (ints[0] > 1) @@ -1567,7 +1568,7 @@ * Test for presence of drive and initialize it. Called at boot time. */ -int aztcd_init(void) +__initfunc(int aztcd_init(void)) { long int count, max_count; unsigned char result[50]; int st; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/bpcd.c linux/drivers/cdrom/bpcd.c --- v2.1.36/linux/drivers/cdrom/bpcd.c Sun Jan 26 02:07:11 1997 +++ linux/drivers/cdrom/bpcd.c Thu May 1 12:05:01 1997 @@ -113,6 +113,7 @@ #include #include #include +#include #include #include @@ -201,7 +202,7 @@ nybble value. The following function initialises the table. */ -static void init_nyb_map( void ) +__initfunc(static void init_nyb_map( void )) { int i, j; @@ -212,7 +213,7 @@ } } -int bpcd_init (void) /* preliminary initialisation */ +__initfunc(int bpcd_init (void)) /* preliminary initialisation */ { init_nyb_map(); @@ -327,7 +328,7 @@ syntax: bpcd=base[,nybble[,rep]] */ -void bpcd_setup(char *str, int *ints) +__initfunc(void bpcd_setup(char *str, int *ints)) { if (ints[0] > 0) bp_base = ints[1]; if (ints[0] > 1) bp_nybble = ints[2]; @@ -425,7 +426,7 @@ if (bp_mode == 2) { t2(1); t2(0x20); } } -static int probe( int id ) +__initfunc(static int probe( int id )) { int l, h, t; int r = -1; @@ -588,7 +589,7 @@ bp_atapi(ej_cmd,0,"eject"); } -static int bp_reset( void ) +__initfunc(static int bp_reset( void )) /* the ATAPI standard actually specifies the contents of all 7 registers after a reset, but the specification is ambiguous concerning the last @@ -615,7 +616,7 @@ return flg-1; } -static int bp_identify( char * id ) +__initfunc(static int bp_identify( char * id )) { int k; char id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0}; @@ -627,7 +628,7 @@ return 0; } -static int bp_port_check( void ) /* check for 8-bit port */ +__initfunc(static int bp_port_check( void )) /* check for 8-bit port */ { int r; @@ -640,7 +641,7 @@ return 0; } -static int bp_locate( void ) +__initfunc(static int bp_locate( void )) { int k; @@ -652,7 +653,7 @@ return -1; } -static int bp_do_detect( int autop ) +__initfunc(static int bp_do_detect( int autop )) { char id[18]; @@ -705,7 +706,7 @@ add it here .... */ -static int bp_detect( void ) +__initfunc(static int bp_detect( void )) { if (bp_base) return bp_do_detect(0); if (!bp_do_detect(0x378)) return 0; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/cdi.c linux/drivers/cdrom/cdi.c --- v2.1.36/linux/drivers/cdrom/cdi.c Tue Feb 13 00:30:25 1996 +++ linux/drivers/cdrom/cdi.c Thu May 1 12:05:01 1997 @@ -28,6 +28,7 @@ #include #include /* where the proto type of cdi_init() is */ +#include #ifdef CONFIG_ISP16_CDI #include #endif CONFIG_ISP16_CDI @@ -35,8 +36,8 @@ /* * Cdrom interface configuration. */ -int -cdi_init(void) +__initfunc(int +cdi_init(void)) { int ret_val = -1; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c --- v2.1.36/linux/drivers/cdrom/cdu31a.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/cdu31a.c Thu May 1 12:05:01 1997 @@ -190,6 +190,7 @@ #include #include #include +#include #include #include @@ -220,7 +221,7 @@ unsigned short base; /* I/O Base Address */ short int_num; /* Interrupt Number (-1 means scan for it, 0 means don't use) */ -} cdu31a_addresses[] = +} cdu31a_addresses[] __initdata = { #if 0 /* No autoconfig any more. See Note at beginning of this file. */ @@ -2963,12 +2964,12 @@ /* The different types of disc loading mechanisms supported */ -static const char *load_mech[] = { "caddy", "tray", "pop-up", "unknown" }; +static const char *load_mech[] __initdata = { "caddy", "tray", "pop-up", "unknown" }; -static void +__initfunc(static void get_drive_configuration(unsigned short base_io, unsigned char res_reg[], - unsigned int *res_size) + unsigned int *res_size)) { int retry_count; @@ -3032,9 +3033,9 @@ /* * Set up base I/O and interrupts, called from main.c. */ -void +__initfunc(void cdu31a_setup(char *strings, - int *ints) + int *ints)) { if (ints[0] > 0) { @@ -3063,8 +3064,8 @@ /* * Initialize the driver. */ -int -cdu31a_init(void) +__initfunc(int +cdu31a_init(void)) { struct s_sony_drive_config drive_config; unsigned int res_size; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c --- v2.1.36/linux/drivers/cdrom/cm206.c Fri Dec 27 02:03:20 1996 +++ linux/drivers/cdrom/cm206.c Thu May 1 12:05:01 1997 @@ -138,6 +138,7 @@ #include #include #include +#include #include @@ -1186,7 +1187,7 @@ check_region, 15 bits of one port and 6 of another make things likely enough to accept the region on the first hit... */ -int probe_base_port(int base) +__initfunc(int probe_base_port(int base)) { int b=0x300, e=0x370; /* this is the range of start addresses */ volatile int fool, i; @@ -1206,7 +1207,7 @@ #if !defined(MODULE) || defined(AUTO_PROBE_MODULE) /* Probe for irq# nr. If nr==0, probe for all possible irq's. */ -int probe_irq(int nr) { +__initfunc(int probe_irq(int nr)) { int irqs, irq; outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */ sti(); @@ -1220,7 +1221,7 @@ } #endif -int cm206_init(void) +__initfunc(int cm206_init(void)) { uch e=0; long int size=sizeof(struct cm206_struct); @@ -1303,7 +1304,7 @@ static int cm206[2] = {0,0}; /* for compatible `insmod' parameter passing */ -void parse_options(void) +__initfunc(void parse_options(void)) { int i; for (i=0; i<2; i++) { @@ -1337,7 +1338,7 @@ /* This setup function accepts either `auto' or numbers in the range * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */ -void cm206_setup(char *s, int *p) +__initfunc(void cm206_setup(char *s, int *p)) { int i; if (!strcmp(s, "auto")) auto_probe=1; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c --- v2.1.36/linux/drivers/cdrom/gscd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/gscd.c Thu May 1 12:05:01 1997 @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -191,7 +192,7 @@ } -void gscd_setup (char *str, int *ints) +__initfunc(void gscd_setup (char *str, int *ints)) { if (ints[0] > 0) { @@ -848,7 +849,7 @@ return; } -int find_drives (void) +__initfunc(int find_drives (void)) { int *pdrv; int drvnum; @@ -899,7 +900,7 @@ return drvnum; } -void init_cd_drive ( int num ) +__initfunc(void init_cd_drive ( int num )) { char resp [50]; int i; @@ -991,7 +992,7 @@ /* Test for presence of drive and initialize it. Called only at boot time. */ -int gscd_init (void) +__initfunc(int gscd_init (void)) { return my_gscd_init (); } @@ -999,7 +1000,7 @@ /* This is the common initialisation for the GoldStar drive. */ /* It is called at boot time AND for module init. */ -int my_gscd_init (void) +__initfunc(int my_gscd_init (void)) { int i; int result; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/isp16.c linux/drivers/cdrom/isp16.c --- v2.1.36/linux/drivers/cdrom/isp16.c Sun Feb 2 05:18:30 1997 +++ linux/drivers/cdrom/isp16.c Thu May 1 12:05:01 1997 @@ -48,6 +48,7 @@ #include #include #include +#include #include static short isp16_detect(void); @@ -76,8 +77,8 @@ #define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p)) -void -isp16_setup(char *str, int *ints) +__initfunc(void +isp16_setup(char *str, int *ints)) { if ( ints[0] > 0 ) isp16_cdrom_base = ints[1]; @@ -93,8 +94,8 @@ * ISP16 initialisation. * */ -int -isp16_init(void) +__initfunc(int +isp16_init(void)) { u_char expected_drive; @@ -143,8 +144,8 @@ return(0); } -static short -isp16_detect(void) +__initfunc(static short +isp16_detect(void)) { if ( isp16_c929__detect() >= 0 ) @@ -153,8 +154,8 @@ return(isp16_c928__detect()); } -static short -isp16_c928__detect(void) +__initfunc(static short +isp16_c928__detect(void)) { u_char ctrl; u_char enable_cdrom; @@ -202,8 +203,8 @@ return(i); } -static short -isp16_c929__detect(void) +__initfunc(static short +isp16_c929__detect(void)) { u_char ctrl; u_char tmp; @@ -229,8 +230,8 @@ return(2); } -static short -isp16_cdi_config(int base, u_char drive_type, int irq, int dma) +__initfunc(static short +isp16_cdi_config(int base, u_char drive_type, int irq, int dma)) { u_char base_code; u_char irq_code; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c --- v2.1.36/linux/drivers/cdrom/mcd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/mcd.c Thu May 1 12:05:01 1997 @@ -80,6 +80,7 @@ #include #include #include +#include /* #define REALLY_SLOW_IO */ #include @@ -196,7 +197,7 @@ static int getValue(unsigned char *result); -void mcd_setup(char *str, int *ints) +__initfunc(void mcd_setup(char *str, int *ints)) { if (ints[0] > 0) mcd_port = ints[1]; @@ -1175,7 +1176,7 @@ * Test for presence of drive and initialize it. Called at boot time. */ -int mcd_init(void) +__initfunc(int mcd_init(void)) { int count; unsigned char result[3]; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- v2.1.36/linux/drivers/cdrom/mcdx.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/mcdx.c Thu May 1 12:05:01 1997 @@ -63,6 +63,7 @@ #include #include #include +#include #include #include @@ -910,7 +911,7 @@ return 1; } -void mcdx_setup(char *str, int *pi) +__initfunc(void mcdx_setup(char *str, int *pi)) { if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1]; if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2]; @@ -1160,7 +1161,7 @@ /* Support functions ************************************************/ -int mcdx_init(void) +__initfunc(int mcdx_init(void)) { int drive; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c --- v2.1.36/linux/drivers/cdrom/optcd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/optcd.c Thu May 1 12:05:01 1997 @@ -65,6 +65,7 @@ #include #include #include +#include #include #define MAJOR_NR OPTICS_CDROM_MAJOR @@ -1961,7 +1962,7 @@ /* Returns 1 if a drive is detected with a version string starting with "DOLPHIN". Otherwise 0. */ -static int version_ok(void) +__initfunc(static int version_ok(void)) { char devname[100]; int count, i, ch, status; @@ -2016,7 +2017,7 @@ /* Get kernel parameter when used as a kernel driver */ -void optcd_setup(char *str, int *ints) +__initfunc(void optcd_setup(char *str, int *ints)) { if (ints[0] > 0) optcd_port = ints[1]; @@ -2024,7 +2025,7 @@ /* Test for presence of drive and initialize it. Called at boot time or during module initialisation. */ -int optcd_init(void) +__initfunc(int optcd_init(void)) { int status; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c --- v2.1.36/linux/drivers/cdrom/sbpcd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/sbpcd.c Sun May 4 21:40:32 1997 @@ -328,6 +328,7 @@ #include #include #include +#include #include #include @@ -3052,7 +3053,7 @@ } #endif FUTURE /*==========================================================================*/ -static void check_datarate(void) +__initfunc(static void check_datarate(void)) { int i=0; @@ -3122,7 +3123,7 @@ } #endif /*==========================================================================*/ -static void ask_mail(void) +__initfunc(static void ask_mail(void)) { int i; @@ -3141,7 +3142,7 @@ msg(DBG_INF,"infobuf =%s\n", msgbuf); } /*==========================================================================*/ -static int check_version(void) +__initfunc(static int check_version(void)) { int i, j, l; int teac_possible=0; @@ -3439,7 +3440,7 @@ /* * probe for the presence of an interface card */ -static int check_card(int port) +__initfunc(static int check_card(int port)) { #undef N_RESPO #define N_RESPO 20 @@ -3543,7 +3544,7 @@ /* * probe for the presence of drives on the selected controller */ -static int check_drives(void) +__initfunc(static int check_drives(void)) { int i, j; @@ -5285,9 +5286,10 @@ * */ #if (SBPCD_ISSUE-1) -static +__initfunc(static void sbpcd_setup(const char *s, int *p)) +#else +__initfunc(void sbpcd_setup(const char *s, int *p)) #endif -void sbpcd_setup(const char *s, int *p) { setup_done++; msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s); @@ -5338,7 +5340,7 @@ * port 0x330, we have to use an offset of 8; so, the real CDROM port * address is 0x338. */ -static int config_spea(void) +__initfunc(static int config_spea(void)) { /* * base address offset between configuration port and CDROM port, @@ -5397,7 +5399,7 @@ #ifdef MODULE int init_module(void) #else -int SBPCD_INIT(void) +__initfunc(int SBPCD_INIT(void)) #endif MODULE { int i=0, j=0; diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c --- v2.1.36/linux/drivers/cdrom/sjcd.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/sjcd.c Thu May 1 12:05:01 1997 @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -159,7 +160,7 @@ * Set up device, i.e., use command line data to set * base address. */ -void sjcd_setup( char *str, int *ints ) +__initfunc(void sjcd_setup( char *str, int *ints )) { if (ints[0] > 0) sjcd_base = ints[1]; @@ -1449,7 +1450,7 @@ * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */ -int sjcd_init( void ){ +__initfunc(int sjcd_init( void )){ int i; printk(KERN_INFO "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR, diff -u --recursive --new-file v2.1.36/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c --- v2.1.36/linux/drivers/cdrom/sonycd535.c Fri Apr 4 08:52:18 1997 +++ linux/drivers/cdrom/sonycd535.c Thu May 1 12:05:01 1997 @@ -120,6 +120,7 @@ #include #include #include +#include #define REALLY_SLOW_IO #include @@ -1484,8 +1485,8 @@ /* * Initialize the driver. */ -int -sony535_init(void) +__initfunc(int +sony535_init(void)) { struct s535_sony_drive_config drive_config; Byte cmd_buff[3]; @@ -1649,8 +1650,8 @@ * * the address value has to be the existing CDROM port address. */ -void -sonycd535_setup(char *strings, int *ints) +__initfunc(void +sonycd535_setup(char *strings, int *ints)) { /* if IRQ change and default io base desired, * then call with io base of 0 diff -u --recursive --new-file v2.1.36/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.1.36/linux/drivers/char/Config.in Sun Apr 13 10:18:20 1997 +++ linux/drivers/char/Config.in Sun May 4 20:48:43 1997 @@ -19,7 +19,10 @@ fi bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then - tristate 'Digiboard PC/Xx Support' CONFIG_DIGI + tristate 'Digiboard Intelligent Async Support' CONFIG_DIGIEPCA + if [ "$CONFIG_DIGIEPCA" = "n" ]; then + tristate 'Digiboard PC/Xx Support' CONFIG_DIGI + fi tristate 'Cyclades async mux support' CONFIG_CYCLADES bool 'Stallion multiport serial support' CONFIG_STALDRV if [ "$CONFIG_STALDRV" = "y" ]; then diff -u --recursive --new-file v2.1.36/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.1.36/linux/drivers/char/Makefile Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/Makefile Sun May 4 20:48:03 1997 @@ -61,6 +61,14 @@ endif endif +ifeq ($(CONFIG_DIGIEPCA),y) +L_OBJS += epca.o +else + ifeq ($(CONFIG_DIGIEPCA),m) + M_OBJS += epca.o + endif +endif + ifeq ($(CONFIG_CYCLADES),y) L_OBJS += cyclades.o else diff -u --recursive --new-file v2.1.36/linux/drivers/char/README.epca linux/drivers/char/README.epca --- v2.1.36/linux/drivers/char/README.epca Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/README.epca Tue Apr 29 11:45:43 1997 @@ -0,0 +1,506 @@ +user.doc +Digi International driver package for the PC/Xe, PC/Xi, PC/Xr, PC/Xem as well +the EISA and PCI variants of these boards where applicable. +Copyright (C) 1996 Digi International. Written by Ronnie Sanford digilnux@dgii.com + + 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. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not write to the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA. + + +This document describes the software used with the Digi/Linux driver package. +The four user programs listed below are described in this document: + + 1. digiConfig -> Application that configures the Digi driver. + + 2. digiDload -> Application which initializes the Digi hardware. + + 3. buildPCI -> Application which provides the user a method of + building device nodes for PCI devices. + + 4. ditty -> Application which provides the user a method of + configuring terminal options on Digi hardware. + + + +-------------------------------------------------------------------------- +1. Configuring driver/kernel for Digi products +-------------------------------------------------------------------------- + + The Digi driver must be configured each time Digi hardware is added + or removed. There are two supported methods of doing this. The + first method configures the driver dynamically at boot time but requires + the user to utilize the lilo loader. This method is the preffered method + as it does not require the rebuilding of the kernel. In order to use lilo + to configure Digi boards at boot time an appropriate append command should + be added to /etc/lilo.conf below the appropriate label decleration. + See footer 4. The append commands format is a string of comma seperated + identifiers or integers used to configure supported boards. These six + values in order are: + + Enable/Disable this card or Override, + Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2), + EISA/Xem (3), PC/Xe (64K) (4), PC/Xi (5). + Enable/Disable alternate pin arrangement, + Number of ports on this card, + I/O Port where card is configured (in HEX if using string identifiers), + Base of memory window (in HEX if using string identifiers) + + A sample append command is given below which if used would configure and + enable a PC/Xe with 8 ports, at i/o address 200, memory address 0xd0000 + with alt pin turned off. The lilo.conf file should look like this: + + image = /vmlinuz + root = /dev/hda2 + label = vmlinuz + append="digiepca=E,PC/Xe,D,8,200,D0000" + + likewise the below will perform the same function: + + image = /vmlinuz + root = /dev/hda2 + label = vmlinuz + append="digiepca=1,0,0,8,512,851968" + + Note: + + PCI boards are auto-detected and configured (Hence their codes are + not given here). Do not attempt to configure PCI boards with the lilo + append command. + + If configuration data has been specified by using digiConfig (Described + below), and you wish to override this configuration using lilo without + specifying a specific card (Example if there are PCI cards in the system) + the following override command will accomplish this: + + -> append="digiepca=2" + + If lilo is not enabled, the second method of configuring Digi hardware + will have to be used. digiConfig is an application that can be used + to inform the system of any additions, deletions, or modifications + involving Digi hardware. To use this method the operator executes + digiConfig anytime an EISA or ISA card is added that he wishes to use. + This routine is also used to remove cards from the system, and to modify + parameters of those cards already present in the system. Upon being + executed digiConfig modifies files accessed by the Digi driver. To make + these changes permanent; the operating system must be recompiled. After + the operating system has been recompiled and booted, the changes made with + digiConfig will be introduced to the user. This program MUST be executed + every time Digi EISA/ISA hardware configuration changes. Note, it is not + necessary to execute digiConfig in order to configure the Digi PCI cards. + These cards are self-identifying and will be recognized by the driver. + They cannot be displayed using digiConfig nor will digiConfig build the + device nodes their device nodes. See footer 1. + + To execute digiConfig; simply type: digiConfig + + The application will query you for the type, memory address, port + address, number of ports, alt pin disposition and status of each board + that exist on the system. Note, currently this driver only supports + PC/Xe, PC/Xeve, PC/Xi, PC/Xr, and PC/Xem as well as their EISA and PCI + implementations if applicable. All supported cards (Other than PCI) that + are present should be registered via digiConfig. See footer 2. + + After all cards have been configured select exit. The system will then + inform you if any changes have been made, and ask you if it is okay to + make these changes permanent. If the data entered is correct, select okay. + Selecting cancel will prevent the changes from becoming active. digiConfig + can then be re-executed to configure the system again. + +-------------------------------------------------------------------------- +2. Initializing Digi hardware with digiDload +-------------------------------------------------------------------------- + + digiDload is the application executed after the Digi driver has been + loaded. It is responsible for initializing the hardware and leaving + it in a state such that the Digi board may be operated by the user. + The application may be placed anywhere on the path, but its related + support files must be located in /etc/digi. The related files are: + + sxfep.bin + sxbios.bin + xxfep.bin + xxbios.bin + + The format for this command is "digiDload [v]". If given the "v" + option turns on verbosity. If not given the application runs in quite + mode. To execute the program simply type: + + digiDload + + Upon completion digiDload will generate the below message: + + "digiDload complete: Card initialized" + + At this point the card is configured and ready for normal usage. See + technotes.doc for information on how how ports are determined and + assigned. + +-------------------------------------------------------------------------- +3. Build PCI device nodes with buildPCI +-------------------------------------------------------------------------- + + buildPCI is an application useful for building the necessary device nodes + for Digi PCI cards. It is reccomended that this tool be used because the + current digiConfig application does not provide this function for PCI cards + (Though it does build device nodes for non-PCI cards). To use this program + execute the following:first install the driver, and execute digiDload (See above). After digiDload + has sucessfully loaded, execute the following: + + buildPCI + + Where arg1 is the number of ports connected to Digi cards that are not PCI + (As shown by the digiConfig utility), and arg2 is the number of ports + connected to Digi cards that are PCI. + + Note, buildPCI only has to be ran once to build the necessary device + nodes. Though this program may be executed at anytime, we reccomend + delaying execution until the first time you install the package and after + digiDload has been executed. + +-------------------------------------------------------------------------- +4. Setting Terminal Options with ditty +-------------------------------------------------------------------------- + +ditty is a utility program that sets and displays the terminal options +for Digi intelligent serial products. See man ditty for detailed information. + + +Footnotes: + +1. The 1.2.x kernel does not provide a method of mapping the high + addresses (Normally higher than RAM) associated with PCI. For this + reason, this driver disables PCI support while running under the 1.2.x + kernels. + +2. PCI cards should not and cannot be registered with digiConfig. After + the driver has been loaded buildPCI may be executed to construct the + necessary device nodes. This step is not necessary for system not + having Digi PCI cards. + +3. This is because we forsee a time when buildPCI may auto-detect the + available Digi PCI cards and this would only work if the program is + executed after digiDload. + +4. A complete example is given in install.doc. + +-------------CHANGES-------------------- + +All changes should be recorded here. All changes should be explained in +verbose detail. +----------------------------------------------------------------------- +Programmer : Ronnie Sanford +Date : June 1, 1996 +Description (Verbose) : Initial release of driver package. +Files affected : all +Release version : 1.0.0f (BETA) +----------------------------------------------------------------------- +----------------------------------------------------------------------- +Programmer : Ronnie Sanford +Date : August 7, 1996 +Description (Verbose) : Made several modifications to provide PCI and EISA + support: + + 1. We now allocate the termios structures based on + the maximum number of channels that COULD be + available to the system. We no longer use the + number of channels declared in epcaconfig.h + (NBDEVS) as the total channel number. This is + because this value does not represent channels + available to potential PCI cards. This new + larger value is also passed back to the os in + the num field of tty_driver. + + 2. Added code to copy the previous board structure + (Now called static_boards) into a new local + copy of the boards structure. This has been + done so that PCI cards may be added to this + board array and later referenced (And even + queried.). + + 3. Added code to pc_init that checks for supported + PCI cards. If found this code initializes a new + entry into the drivers local board structure + with the PCI cards address, and type, etc.. It + also bumps the card count (num_cards). + + 4. Modified code in post_fep_init so that when this + routine is executed the number of ports supported + by a particular PCI card will be determined and + loaded into the board structure. It would be + much better if this code was placed in pc_init + (Because we could then report to the os the true + number of ports available; not just the max), but + since the card has to be booted to determine the + number of ports it supports, we are forced to do it + after DIGI_INIT has called post_fep_init. In the + future we may attempt to read the num ports + attached directly (address 0x1ac). + + 5. Added board types to epca.h in support of various + PCI boards (Some of which do not exist yet). + Added procedures for these boards throughout the + code. Note, windowing is not necessary for PCI + boards. + + 6. Added code supporting the EISA/XEM. This included + modifying epca.h with the new board type and + adding this type into the driver. The EISA/XEM + is basically identical to the PC/XEM, other than + it's base address does not have to be (And cannot + be configured directly). + + 7. Modified digiConfig to prompt for EISA/XEM cards. + +Files affected : epca.c, epca.h, digi1.h, digiConfig +Release version : 1.0.0g (BETA) +----------------------------------------------------------------------- +----------------------------------------------------------------------- +Programmer : Ronnie Sanford +Date : August 21, 1996 +Description (Verbose) : Made the following modifications: + + 1. A problem affecting hard flow control was found + in the termios2digi_h routine. Specifically, + when the user activated hard flow control using + the CRTSCTS specification, the values used to + program hard flow control on the board were + incorrect. The solution was to change a line + that read "res |= ((ch->m_dtr) | (ch->m_rts));" + to "res |= ((ch->m_cts) | (ch->m_rts));" This + line only applies if cflag & CRTSCTS. Special + thanks to Matt Robinson (matt@mania.com.au) who + found and fixed this problem. + + 2. In previous betas the cud device was set to CLOCAL + on driver boot up. Likewise the ttyD device was + set to ~CLOCAL. This has been fixed in this driver. + Now ttyD is CLOCAL and cud is ~CLOCAL. The fix + for this can be found in pc_init. + + 3. In ditty.c many changes were made to eliminate bugs + and warning messages. Two ioctl calls were eliminated + as well a problem involving using the returned baud + index to determine the drivers baud rate. Newer + Linux kernels support higher baud rates by using + 0x1000 bit. When the returned value (ored with + 0x1000) was used to reference our fbaud table a + serious memory problem occured. This has been fixed. + + 4. Added a request_region call to post_fep_init. This + should cause the i/o ports being used to be + registered with proc. + + 5. Modified digiConfig to set all cud and ttyD devices + to read/write all permission. + + 6. Developed a new apps called buildPCI that provides + an easy way to build device nodes for PCI cards. + + 7. Modified user.doc and technotes.doc document the + use of buildPCI. + +Files affected : epca.c, ditty.c, digiConfig, user.doc, technotes.doc +Release version : 1.0.0 (Official release) +----------------------------------------------------------------------- +Programmer : Ronnie Sanford +Date : August 21, 1996 +Description (Verbose) : Made the following modifications: + + 1. Removed code from pc_close which closes the + drivers line discipline and restores its original + line discipline. This is currently unecessary, + though future fast cook enhancements may require + this. + + 2. Removed code in block_til_ready that set the + asyncflags to either ASYNC_CALLOUT_ACTIVE, or + ASYNC_NORMAL_ACTIVE. This code was redundant + as it already existed in block_til_ready. + + 3. Added code in block_til_ready to cause a return + prior to schedule being called if the device + was a CALLOUT device. CALLOUT devices never + block on CD. (This was a serious bug that + prevented the CALLOUT devices (ttyD) from + functioning properly in some instances. + + Make a change in the MODEMCHG_IND case of doevent + such that it does not require ASYNC_CALLOUT_ACTIVE + or ASYNC_NORMAL_ACTIVE to be set in order to + unblock an open (Using wait_interruptible). + + Thanks to Mike McLagan (mike.mclagan@linux.org) + for diagnosing and fixing this problem. + + 4. Made changes to the disposition of CLOCAL on + both SERIAL NORMAL and CALLOUT devices. Both + device types now have CLOCAL active at default. + This may be changed with a stty command. + + 5. Made changes to digiConfig such that it checks + major.h (If valid) for the correct major + numbers to use. + +Files affected : epca.c, digiConfig +Release version : 1.0.1a + + +----------------------------------------------------------------------- +Programmer : Ronnie Sanford +Date : September 17, 1996 +Description (Verbose) : Made the following modifications: + + 1. Modified pc_open such that it no longer checks + the cflag value returned by termios2digi_c for + CLOCAL. Digi hardware does not use this value + and thus termios2digi_c rightly screens this + value out. This driver checks for CLOCAL using + the drivers cflag value as known by the Linux OS. + (The value passed into termios2digi_c) + + 2. Modified termios2digi_c to screen out the + CBAUDEX in CBAUD. This error caused parity to + automaticaly be enabled on at higher baud rates. + + + 3. Added the "disable_bh()" call to the shutdown + subroutine. Hopefully this will allow the driver + to correctly clean up after itself when used as a + module. + + 4. Added support for the PC/XI and 64K PC/XE cards. + This involved primarily modifying digiDload to + initialize and boot the new cards; however + driver modifications were also required to + provide the proper windowing for the newly + supported cards. (Code was also added to + determine the memory segment of the XI card as + that card may have more than 64K. Currently + digiDload assumes a 64K XI card.) + + 5. Added subroutine called epca_setup that can be + called during LILO boot up. This provides the + user an easy way to change cards; without + running digiConfig and without recompiling the + kernel. Added code in pc_init and pc_open to + support the epca_setup routine. pc_init checks + the liloconfig flag (Which is set by epca_setup) + to determine if the driver is using the LILO + arguments. If not pc_init loads the board data + found in epcaconfig.h; if so it DOESN'T load + epcaconfig data depending on epca_setup to handle + board configuration. pc_open has been modified + such that it checks to insure that no errors + occured during the LILO boot process. If a + user attempts to boot the driver (via. LILO) + with incorrect data, the open will fail. + + 6. Modified the windowing routines pcxe_rxwinon + and pcxe_txwinon routines. A bug existed such + that those routines checked to see if the rxwin + and txwin flags were reset. If so they assumed + the board was an XI or 64K XE. Furthermore since + these flags were never initialized in our driver + sometimes they were 0 and therefore caused a + memory fault (Or at least a window overrun). This + code has been removed since the pcxe shares + nothing in common with the 64K XI and XE. + + 7. Added code in pc_init to set the memory_seg for + the various boards. This code was necessary to + correct a bug in the PCXE, PCXEVE code where + receive and transmit pointers were being calculated + from an uninitialized variable (memory_seg). + + 8. Modified digiConfig to allow 64K PC/XI and 64K + PC/XE cards to be configured. + + 9. Made changes to support the new 2.1.x development + kernel. In particular this required changing all + references to vremap to ioremap. + + 10. Modified digiConfig such that it now generates + node names corresponding to their internal + as opposed to the label on the port itself. Nodes + (ttyD?? and cud??) now start at 0. Example: + ttyD0 and cud0 represent port 1 on any supported + Digi product. A similar change has been made + in buildPCI.c. + + 12. At the early portion of post_fep_init if a PCI + card is detected a warning message could be given + incorrectly if 64 ports were attached to a PCI + card. The below line : + + epcaassert(bd->numports > 64,"PCI returned a invalid number of ports"); + + was changed to : + + epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports"); + + Remember that epcaassert checks for NOT true. + Special thanks to Daniel Taylor for fixing this. + + 13. Modified the epcaparam routine. In version 100 + and 101a there was a line that looked like the + below: + + if (ch->omodem != mval) + + The problem with this line was that the first time + through omodem was not initialized. Secondly, since + many TIOC commands did not alter mval (They use + a different variable) changes made by these commands + could be lost. This line was changed to: + + mval ^= ch->modemfake & (mval ^ ch->modem); + + if (ch->omodem ^ mval) + + 14. Modified digiConfig in such a way that it checks + the version number of the kernel and if it finds + a 2.x.x kernel or higher it reads the necessary + major numbers for cud and ttyD devices from major.h. + This was also done in prior versions but these + versions required a #define which identified the + kernel as a version which did not have major numbers + assigned to Digi systems. This #define is no + longer required allowing the same source tree for + multiple kernel releases. + + 15. Used macros to replace kernel specific calls such + as put_fs_long, get_fs_long, put_user, and get_user + the kernel version is now detected and the macro + is defined as to correspond with the kernel it + is being compiled into. Again this was done to + allow one source tree for multiple kernel releases. + + 16. Added support for the new 2.1.x development kernels + to digiInstall. + +Files affected : epca.c, digiConfig +Release version : 1.1.0 +----------------------------------------------------------------------- +Programmer : Daniel Taylor +Date : April 25, 1997 +Description (Verbose) : Updated driver: + 1. Fixed DCD bug. (&tq_scheduler) + 2. Removed BH handler code, as it was only handling + hangups, and not being called for that. + 3. Namespace cleanup (DIGI_TIMER2 => DIGI_TIMER) + 4. Updated to 2.1.36, removed #ifdefs for earlier + kernel revisions. +Files affected : epca.c +Release version : 1.1.1 (BETA) +----------------------------------------------------------------------- diff -u --recursive --new-file v2.1.36/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v2.1.36/linux/drivers/char/busmouse.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/busmouse.c Thu May 1 12:05:01 1997 @@ -56,7 +56,7 @@ static struct mouse_status mouse; static int mouse_irq = MOUSE_IRQ; -void bmouse_setup(char *str, int *ints) +__initfunc(void bmouse_setup(char *str, int *ints)) { if (ints[0] > 0) mouse_irq=ints[1]; diff -u --recursive --new-file v2.1.36/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.1.36/linux/drivers/char/console.c Sun Apr 13 10:18:20 1997 +++ linux/drivers/char/console.c Thu May 1 12:05:01 1997 @@ -101,6 +101,7 @@ #include #include #include +#include #ifdef CONFIG_APM #include #endif @@ -1979,7 +1980,7 @@ * Reads the information preserved by setup.s to determine the current display * type and sets everything accordingly. */ -unsigned long con_init(unsigned long kmem_start) +__initfunc(unsigned long con_init(unsigned long kmem_start)) { const char *display_desc = "????"; int currcons = 0; diff -u --recursive --new-file v2.1.36/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c --- v2.1.36/linux/drivers/char/consolemap.c Sun Apr 13 10:18:20 1997 +++ linux/drivers/char/consolemap.c Thu May 1 12:05:01 1997 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "consolemap.h" @@ -483,8 +484,8 @@ * initialized. It must be possible to call kmalloc(..., GFP_KERNEL) * from this function, hence the call from sys_setup. */ -void -console_map_init(void) +__initfunc(void +console_map_init(void)) { con_set_default_unimap(); } diff -u --recursive --new-file v2.1.36/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.1.36/linux/drivers/char/cyclades.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/cyclades.c Mon May 5 08:35:07 1997 @@ -1,5 +1,7 @@ +#define BLOCKMOVE static char rcsid[] = -"$Revision: 1.36.3.9 $$Date: 1996/10/07 19:47:13 $"; +"$Revision: 1.36.4.27 $$Date: 1997/03/26 10:30:00 $"; + /* * linux/drivers/char/cyclades.c * @@ -22,11 +24,128 @@ * This module exports the following rs232 io functions: * int cy_init(void); * int cy_open(struct tty_struct *tty, struct file *filp); + * and the following functions for modularization. + * int init_module(void); + * void cleanup_module(void); * * $Log: cyclades.c,v $ - * Revision 1.36.3.9 1996/10/07 19:47:13 bentson - * add MOD_DEC_USE_COUNT in one return from cy_close (as - * noted by Jon Lewis ) + * Revision 1.36.4.27 1997/03/26 10:30:00 daniel + * Changed for suport linux versions 2.1.X. + * Backward compatible with linux versions 2.0.X. + * Corrected illegal use of filler field in + * CH_CTRL struct. + * Deleted some debug messages. + * + * Revision 1.36.4.26 1997/02/27 12:00:00 daniel + * Included check for NULL tty pointer in cyz_poll. + * + * Revision 1.36.4.25 1997/02/26 16:28:30 bentson + * Bill Foster at Blarg! Online services noticed that + * some of the switch elements of -Z modem control + * lacked a closing "break;" + * + * Revision 1.36.4.24 1997/02/24 11:00:00 daniel + * Changed low water threshold for buffer xmit_buf + * + * Revision 1.36.4.23 1996/12/02 21:50:16 bentson + * Marcio provided fix to modem status fetch for -Z + * + * Revision 1.36.4.22 1996/10/28 22:41:17 bentson + * improve mapping of -Z control page (thanks to Steve + * Price for help on this) + * + * Revision 1.36.4.21 1996/09/10 17:00:10 bentson + * shift from cpu-bound to memcopy in cyz_polling operation + * + * Revision 1.36.4.20 1996/09/09 18:30:32 Bentson + * Added support to set and report higher speeds. + * + * Revision 1.36.4.19c 1996/08/09 10:00:00 Marcio Saito + * Some fixes in the HW flow control for the BETA release. + * Don't try to register the IRQ. + * + * Revision 1.36.4.19 1996/08/08 16:23:18 Bentson + * make sure "cyc" appears in all kernel messages; all soft interrupts + * handled by same routine; recognize out-of-band reception; comment + * out some diagnostic messages; leave RTS/CTS flow control to hardware; + * fix race condition in -Z buffer management; only -Y needs to explictly + * flush chars; tidy up some startup messages; + * + * Revision 1.36.4.18 1996/07/25 18:57:31 bentson + * shift MOD_INC_USE_COUNT location to match + * serial.c; purge some diagnostic messages; + * + * Revision 1.36.4.17 1996/07/25 18:01:08 bentson + * enable modem status messages and fetch & process them; note + * time of last activity type for each port; set_line_char now + * supports more than line 0 and treats 0 baud correctly; + * get_modem_info senses rs_status; + * + * Revision 1.36.4.16 1996/07/20 08:43:15 bentson + * barely works--now's time to turn on + * more features 'til it breaks + * + * Revision 1.36.4.15 1996/07/19 22:30:06 bentson + * check more -Z board status; shorten boot message + * + * Revision 1.36.4.14 1996/07/19 22:20:37 bentson + * fix reference to ch_ctrl in startup; verify return + * values from cyz_issue_cmd and cyz_update_channel; + * more stuff to get modem control correct; + * + * Revision 1.36.4.13 1996/07/11 19:53:33 bentson + * more -Z stuff folded in; re-order changes to put -Z stuff + * after -Y stuff (to make changes clearer) + * + * Revision 1.36.4.12 1996/07/11 15:40:55 bentson + * Add code to poll Cyclom-Z. Add code to get & set RS-232 control. + * Add code to send break. Clear firmware ID word at startup (so + * that other code won't talk to inactive board). + * + * Revision 1.36.4.11 1996/07/09 05:28:29 bentson + * add code for -Z in set_line_char + * + * Revision 1.36.4.10 1996/07/08 19:28:37 bentson + * fold more -Z stuff (or in some cases, error messages) + * into driver; add text to "don't know what to do" messages. + * + * Revision 1.36.4.9 1996/07/08 18:38:38 bentson + * moved compile-time flags near top of file; cosmetic changes + * to narrow text (to allow 2-up printing); changed many declarations + * to "static" to limit external symbols; shuffled code order to + * coalesce -Y and -Z specific code, also to put internal functions + * in order of tty_driver structure; added code to recognize -Z + * ports (and for moment, do nothing or report error); add cy_startup + * to parse boot command line for extra base addresses for ISA probes; + * + * Revision 1.36.4.8 1996/06/25 17:40:19 bentson + * reorder some code, fix types of some vars (int vs. long), + * add cy_setup to support user declared ISA addresses + * + * Revision 1.36.4.7 1996/06/21 23:06:18 bentson + * dump ioctl based firmware load (it's now a user level + * program); ensure uninitialzed ports cannot be used + * + * Revision 1.36.4.6 1996/06/20 23:17:19 bentson + * rename vars and restructure some code + * + * Revision 1.36.4.5 1996/06/14 15:09:44 bentson + * get right status back after boot load + * + * Revision 1.36.4.4 1996/06/13 19:51:44 bentson + * successfully loads firmware + * + * Revision 1.36.4.3 1996/06/13 06:08:33 bentson + * add more of the code for the boot/load ioctls + * + * Revision 1.36.4.2 1996/06/11 21:00:51 bentson + * start to add Z functionality--starting with ioctl + * for loading firmware + * + * Revision 1.36.4.1 1996/06/10 18:03:02 bentson + * added code to recognize Z/PCI card at initialization; report + * presence, but card is not initialized (because firmware needs + * to be loaded) * * Revision 1.36.3.8 1996/06/07 16:29:00 bentson * starting minor number at zero; added missing verify_area @@ -38,7 +157,7 @@ * remove unused diagnostic statements; minor 0 is first; * * Revision 1.36.3.6 1996/03/13 13:21:17 marcio - * The kernel function ioremap (available only in later 1.3.xx kernels) + * The kernel function vremap (available only in later 1.3.xx kernels) * allows the access to memory addresses above the RAM. This revision * of the driver supports PCI boards below 1Mb (device id 0x100) and * above 1Mb (device id 0x101). @@ -261,6 +380,52 @@ * */ +/* If you need to install more boards than NR_CARDS, change the constant + in the definition below. No other change is necessary to support up to + eight boards. Beyond that you'll have to extend cy_isa_addresses. */ + +#define NR_CARDS 4 + +/* + If the total number of ports is larger than NR_PORTS, change this + constant in the definition below. No other change is necessary to + support more boards/ports. */ + +#define NR_PORTS 64 + +#define SERIAL_PARANOIA_CHECK +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_THROTTLE +#undef SERIAL_DEBUG_OTHER +#undef SERIAL_DEBUG_IO +#undef SERIAL_DEBUG_COUNT +#undef SERIAL_DEBUG_DTR +#undef CYCLOM_16Y_HACK +#undef CYCLOM_ENABLE_MONITORING +#undef CY_PCI_DEBUG + + +#if 0 +#define PAUSE __asm__("nop"); +#else +#define PAUSE ; +#endif + +#define cy_min(a,b) (((a)<(b))?(a):(b)) + +#define CHARS_IN_BUF(buf_ctrl) \ + ((buf_ctrl->rx_put - \ + buf_ctrl->rx_get + \ + buf_ctrl->rx_bufsize) % \ + buf_ctrl->rx_bufsize) + +#define SPACE_IN_BUF(buf_ctrl) \ + ((buf_ctrl->tx_get - \ + buf_ctrl->tx_put + \ + buf_ctrl->tx_bufsize - 1) % \ + buf_ctrl->tx_bufsize) + + #include #include @@ -280,7 +445,7 @@ #include #include -#include +#include #include #include @@ -290,24 +455,34 @@ #include #include -#define small_delay(x) for(j=0;j +#if LINUX_VERSION_CODE >= 131328 -#define SERIAL_PARANOIA_CHECK -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_THROTTLE -#undef SERIAL_DEBUG_OTHER -#undef SERIAL_DEBUG_IO -#undef SERIAL_DEBUG_COUNT -#undef SERIAL_DEBUG_DTR -#undef CYCLOM_16Y_HACK -#undef CYCLOM_ENABLE_MONITORING +#include + +#define memcpy_fromfs copy_from_user +#define memcpy_tofs copy_to_user +#define put_fs_long put_user +#define vremap ioremap + +static unsigned long get_fs_long(unsigned long *addr) +{ + unsigned long result = 0; + int error = get_user (result, addr); + if (error) + printk ("cyclades: get_fs_long: error == %d\n", error); + return result; +} + +#endif #ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#define IS_CYC_Z(card) ((card).num_chips == 1) -#define WAKEUP_CHARS 256 +#define WAKEUP_CHARS (SERIAL_XMIT_SIZE-256) #define STD_COM_FLAGS (0) @@ -325,72 +500,39 @@ static unsigned char *intr_base_addr; -/* This is the address lockup table. The driver will probe for Cyclom-Y/ISA - boards at all addresses in here. If you want the driver to probe addresses - in a different address, add it to this table. - If the driver is probing some other board and causing problems, remove the - address from this table. */ +/* This is the address lookup table. The driver will probe for + Cyclom-Y/ISA boards at all addresses in here. If you want the + driver to probe addresses at a different address, add it to + this table. If the driver is probing some other board and + causing problems, remove the offending address from this table. + The cy_setup function extracts additional addresses from the + boot options line. The form is "cyclades=address,address..." +*/ static unsigned char *cy_isa_addresses[] = { - (unsigned char *) 0xD0000, - (unsigned char *) 0xD2000, - (unsigned char *) 0xD4000, - (unsigned char *) 0xD6000, - (unsigned char *) 0xD8000, - (unsigned char *) 0xDA000, - (unsigned char *) 0xDC000, - (unsigned char *) 0xDE000, + (unsigned char *) 0xD0000, + (unsigned char *) 0xD2000, + (unsigned char *) 0xD4000, + (unsigned char *) 0xD6000, + (unsigned char *) 0xD8000, + (unsigned char *) 0xDA000, + (unsigned char *) 0xDC000, + (unsigned char *) 0xDE000, + 0,0,0,0,0,0,0,0 }; -#define NR_ISA_ADDRESSES (sizeof(cy_isa_addresses)/sizeof(unsigned char *)) +#define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*)) /* This is the per-card data structure containing address, irq, number of - channels, etc. This driver supports a maximum of NR_CARDS cards. If - you need to install more boards, change this constant in the definition - below. No other change is necessary to support more boards. */ - -#define NR_CARDS 4 - + channels, etc. This driver supports a maximum of NR_CARDS cards. +*/ static struct cyclades_card cy_card[NR_CARDS]; /* This is the per-channel data structure containing pointers, flags - and variables for the port. This driver supports a maximum of NR_PORTS. - If the total number of ports is larger than NR_PORTS, change this - constant in the definition below. No other change is necessary to - support more boards/ports. */ - -#define NR_PORTS 64 - + and variables for the port. This driver supports a maximum of NR_PORTS. +*/ static struct cyclades_port cy_port[NR_PORTS]; -/* The Cyclom-Ye has placed the sequential chips in non-sequential - * address order. This look-up table overcomes that problem. - */ -static int cy_chip_offset [] = - { 0x0000, - 0x0400, - 0x0800, - 0x0C00, - 0x0200, - 0x0600, - 0x0A00, - 0x0E00 - }; - -/* PCI related definitions */ - -static unsigned short cy_pci_nboard = 0; -static unsigned short cy_isa_nboard = 0; -static unsigned short cy_nboard = 0; -static unsigned short cy_pci_dev_id[] = { - PCI_DEVICE_ID_CYCLOM_Y_Lo,/* PCI below 1Mb */ - PCI_DEVICE_ID_CYCLOM_Y_Hi,/* PCI above 1Mb */ - 0 /* end of table */ - }; - -int cy_detect_isa(void); -int cy_detect_pci(void); - -static int cy_next_channel = 0; /* next minor available */ +static int cy_next_channel = 0; /* next minor available */ static int serial_refcount; @@ -401,17 +543,18 @@ /* This is the per-irq data structure, it maps an irq to the corresponding card */ -struct cyclades_card *IRQ_cards[16]; +static struct cyclades_card *IRQ_cards[16]; /* * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, + * lock it in case the memcpy_fromfs blocks while swapping in a page, * and some other program tries to do a serial write at the same time. * Since the lock will only come under contention when the system is * swapping and available memory is low, it makes sense to share one * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. + * memory if large numbers of serial ports are open. This buffer is + * allocated when the first cy_open occurs. */ static unsigned char *tmp_buf = 0; static struct semaphore tmp_buf_sem = MUTEX; @@ -420,83 +563,127 @@ * This is used to look up the divisor speeds and the timeouts * We're normally limited to 15 distinct baud rates. The extra * are accessed via settings in info->flags. - * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - * HI VHI + * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + * HI VHI */ static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, - 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, - 0}; + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, + 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, + 0}; static char baud_co[] = { /* 25 MHz clock option table */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static char baud_bpr[] = { /* 25 MHz baud rate period table */ - 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, - 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; + 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, + 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; static char baud_cor3[] = { /* receive threshold */ - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07}; + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07}; +/* The Cyclom-Ye has placed the sequential chips in non-sequential + * address order. This look-up table overcomes that problem. + */ +static int cy_chip_offset [] = + { 0x0000, + 0x0400, + 0x0800, + 0x0C00, + 0x0200, + 0x0600, + 0x0A00, + 0x0E00 + }; + +/* PCI related definitions */ -static void shutdown(struct cyclades_port *); -static int startup (struct cyclades_port *); -static void cy_throttle(struct tty_struct *); -static void cy_unthrottle(struct tty_struct *); -static void config_setup(struct cyclades_port *); +static unsigned short cy_pci_nboard = 0; +static unsigned short cy_isa_nboard = 0; +static unsigned short cy_nboard = 0; +static unsigned short cy_pci_dev_id[] = { + PCI_DEVICE_ID_CYCLOM_Y_Lo,/* PCI below 1Mb */ + PCI_DEVICE_ID_CYCLOM_Y_Hi,/* PCI above 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Lo,/* PCI below 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Hi,/* PCI above 1Mb */ + 0 /* end of table */ + }; + + +static void cy_start(struct tty_struct *); +static void set_line_char(struct cyclades_port *); +static void cy_probe(int, void *, struct pt_regs *); +static void cyz_poll(unsigned long); #ifdef CYCLOM_SHOW_STATUS static void show_status(int); #endif +static int cyz_timeron = 0; +static struct timer_list +cyz_timerlist = { + NULL, NULL, 0, 0, cyz_poll +}; + + +/************************************************** +error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); +memcpy_tofs (to, from, count); +*************************************************************** +error = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned long *)); +memcpy_fromfs(to, from, count); +**************************************************/ + + static inline int serial_paranoia_check(struct cyclades_port *info, - kdev_t device, const char *routine) + kdev_t device, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; + "cyc Warning: bad magic number for serial struct (%s) in %s\n"; static const char *badinfo = - "Warning: null cyclades_port for (%s) in %s\n"; + "cyc Warning: null cyclades_port for (%s) in %s\n"; static const char *badrange = - "Warning: cyclades_port out of range for (%s) in %s\n"; + "cyc Warning: cyclades_port out of range for (%s) in %s\n"; if (!info) { - printk(badinfo, kdevname(device), routine); - return 1; + printk(badinfo, kdevname(device), routine); + return 1; } if( (long)info < (long)(&cy_port[0]) || (long)(&cy_port[NR_PORTS]) < (long)info ){ - printk(badrange, kdevname(device), routine); - return 1; + printk(badrange, kdevname(device), routine); + return 1; } if (info->magic != CYCLADES_MAGIC) { - printk(badmagic, kdevname(device), routine); - return 1; + printk(badmagic, kdevname(device), routine); + return 1; } #endif - return 0; + return 0; } /* serial_paranoia_check */ + /* The following diagnostic routines allow the driver to spew information on the screen, even (especially!) during interrupts. */ -void +static void SP(char *data){ unsigned long flags; save_flags(flags); cli(); console_print(data); restore_flags(flags); -} -void +}/* SP */ + +static void CP(char data){ unsigned long flags; char scrn[2]; @@ -507,161 +694,312 @@ restore_flags(flags); }/* CP */ -void CP1(int data) { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP1 */ -void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */ -void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */ -void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */ +static void CP4(int data) + { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP4 */ +static void CP8(int data) + { CP4((data>>4) & 0x0f); CP4( data & 0x0f); }/* CP8 */ +static void CP16(int data) + { CP8((data>>8) & 0xff); CP8(data & 0xff); }/* CP16 */ +static void CP32(long data) + { CP16((data>>16) & 0xffff); CP16(data & 0xffff); }/* CP32 */ -/* This routine waits up to 1000 micro-seconds for the previous - command to the Cirrus chip to complete and then issues the - new command. An error is returned if the previous command - didn't finish within the time limit. + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver + * (also known as the "bottom half"). This can be called any + * number of times for any channel without harm. */ -u_short -write_cy_cmd(u_char *base_addr, u_char cmd, int index) +static inline void +cy_sched_event(struct cyclades_port *info, int event) { - unsigned long flags; - volatile int i; - - save_flags(flags); cli(); - /* Check to see that the previous command has completed */ - for(i = 0 ; i < 100 ; i++){ - if (base_addr[CyCCR<event |= 1 << event; /* remember what kind of event and who */ + queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */ + mark_bh(CYCLADES_BH); /* then trigger event */ +} /* cy_sched_event */ - /* Issue the new command */ - base_addr[CyCCR<driver_data; - unsigned char *base_addr; - int chip,channel,index; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *) private_; + struct tty_struct *tty; -#ifdef SERIAL_DEBUG_OTHER - printk("cy_stop ttyC%d\n", info->line); /* */ -#endif + tty = info->tty; + if (!tty) + return; - if (serial_paranoia_check(info, tty->device, "cy_stop")) - return; - - cinfo = &cy_card[info->card]; - index = cinfo->bus_index; - channel = info->line - cinfo->first_line; - chip = channel>>2; - channel &= 0x03; - base_addr = (unsigned char*) - (cy_card[info->card].base_addr + (cy_chip_offset[chip]<event)) { + tty_hangup(info->tty); + wake_up_interruptible(&info->open_wait); + info->flags &= ~(ASYNC_NORMAL_ACTIVE| + ASYNC_CALLOUT_ACTIVE); + } + if (clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { + wake_up_interruptible(&info->open_wait); + } + if (clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { + if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup){ + (tty->ldisc.write_wakeup)(tty); + } + wake_up_interruptible(&tty->write_wait); + } +} /* do_softint */ - save_flags(flags); cli(); - base_addr[CyCAR<driver_data; - unsigned char *base_addr; - int chip,channel,index; unsigned long flags; - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_start ttyC%d\n", info->line); /* */ -#endif - - if (serial_paranoia_check(info, tty->device, "cy_start")) - return; - - cinfo = &cy_card[info->card]; - index = cinfo->bus_index; - channel = info->line - cinfo->first_line; - chip = channel>>2; - channel &= 0x03; - base_addr = (unsigned char*) - (cy_card[info->card].base_addr + (cy_chip_offset[chip]<event |= 1 << event; /* remember what kind of event and who */ - queue_task_irq_off(&info->tqueue, &tq_cyclades); /* it belongs to */ - mark_bh(CYCLADES_BH); /* then trigger event */ -} /* cy_sched_event */ - - -static int probe_ready; + int irq_lines = 0; + int i, mask; + + for (i = 0, mask = 1; i < 16; i++, mask <<= 1) { + if (!(mask & dontgrab) + && !request_irq(i, cy_probe, + SA_INTERRUPT, "serial probe", NULL)) { + irq_lines |= mask; + } + } + return irq_lines; +} /* grab_all_interrupts */ /* - * This interrupt routine is used - * while we are probing for submarines. + * Release all interrupts grabbed by grab_all_interrupts */ static void -cy_probe(int irq, void *dev_id, struct pt_regs *regs) +free_all_interrupts(int irq_lines) { - int save_xir, save_car; - int index = 0; /* probing interrupts is only for ISA */ + int i; + + for (i = 0; i < 16; i++) { + if (irq_lines & (1 << i)) + free_irq(i,NULL); + } +} /* free_all_interrupts */ + +/* + * This routine returns a bitfield of "wild interrupts". Basically, + * any unclaimed interrupts which is flapping around. + */ +static int +check_wild_interrupts(void) +{ + int i, mask; + int wild_interrupts = 0; + int irq_lines; + unsigned long timeout; + unsigned long flags; + + /*Turn on interrupts (they may be off) */ + save_flags(flags); sti(); + + irq_lines = grab_all_interrupts(0); + + /* + * Delay for 0.1 seconds -- we use a busy loop since this may + * occur during the bootup sequence + */ + timeout = jiffies+10; + while (timeout >= jiffies) + ; + + cy_triggered = 0; /* Reset after letting things settle */ + + timeout = jiffies+10; + while (timeout >= jiffies) + ; + + for (i = 0, mask = 1; i < 16; i++, mask <<= 1) { + if ((cy_triggered & (1 << i)) && + (irq_lines & (1 << i))) { + wild_interrupts |= mask; + } + } + free_all_interrupts(irq_lines); + restore_flags(flags); + return wild_interrupts; +} /* check_wild_interrupts */ + +/* + * This routine is called by do_auto_irq(); it attempts to determine + * which interrupt a serial port is configured to use. It is not + * fool-proof, but it works a large part of the time. + */ +static int +get_auto_irq(unsigned char *address) +{ + unsigned long timeout; + unsigned char *base_addr; + int index; + + index = 0; /* IRQ probing is only for ISA */ + base_addr = address; + intr_base_addr = address; + + /* + * Enable interrupts and see who answers + */ + cy_irq_triggered = 0; + cli(); + base_addr[CyCAR<= jiffies) { + if (cy_irq_triggered) + break; + } + probe_ready = 0; + return(cy_irq_triggered); +} /* get_auto_irq */ + +/* + * Calls get_auto_irq() multiple times, to make sure we don't get + * faked out by random interrupts + */ +static int +do_auto_irq(unsigned char *address) +{ + int irq_lines = 0; + int irq_try_1 = 0, irq_try_2 = 0; + int retries; + unsigned long flags; + + /* Turn on interrupts (they may be off) */ + save_flags(flags); sti(); + + probe_ready = 0; + + cy_wild_int_mask = check_wild_interrupts(); + + irq_lines = grab_all_interrupts(cy_wild_int_mask); + + for (retries = 0; retries < 5; retries++) { + if (!irq_try_1) + irq_try_1 = get_auto_irq(address); + if (!irq_try_2) + irq_try_2 = get_auto_irq(address); + if (irq_try_1 && irq_try_2) { + if (irq_try_1 == irq_try_2) + break; + irq_try_1 = irq_try_2 = 0; + } + } + restore_flags(flags); + free_all_interrupts(irq_lines); + return (irq_try_1 == irq_try_2) ? irq_try_1 : 0; +} /* do_auto_irq */ + + +/* + * This interrupt routine is used + * while we are probing for submarines. + */ +static void +cy_probe(int irq, void *dev_id, struct pt_regs *regs) +{ + int save_xir, save_car; + int index = 0; /* probing interrupts is only for ISA */ if (!probe_ready) { - *(intr_base_addr + (Cy_ClrIntr<num_chips ; chip ++) { - base_addr = (unsigned char *) - (cinfo->base_addr + (cy_chip_offset[chip]<base_addr + (cy_chip_offset[chip]<first_line; @@ -746,82 +1084,84 @@ continue; } if (tty->flip.count < TTY_FLIPBUF_SIZE){ - tty->flip.count++; - if (data & info->read_status_mask){ - if(data & CyBREAK){ - *tty->flip.flag_buf_ptr++ = - TTY_BREAK; - *tty->flip.char_buf_ptr++ = - base_addr[CyRDSR<flags & ASYNC_SAK){ - do_SAK(tty); - } - }else if(data & CyFRAME){ - *tty->flip.flag_buf_ptr++ = - TTY_FRAME; - *tty->flip.char_buf_ptr++ = - base_addr[CyRDSR<flip.flag_buf_ptr++ = - TTY_PARITY; - *tty->flip.char_buf_ptr++ = - base_addr[CyRDSR<flip.flag_buf_ptr++ = - TTY_OVERRUN; - *tty->flip.char_buf_ptr++ = 0; - /* If the flip buffer itself is - overflowing, we still loose - the next incoming character. - */ - if(tty->flip.count < TTY_FLIPBUF_SIZE){ - tty->flip.count++; - *tty->flip.flag_buf_ptr++ = - TTY_NORMAL; - *tty->flip.char_buf_ptr++ = - base_addr[CyRDSR<flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = 0; - } - }else{ - *tty->flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = 0; - } + tty->flip.count++; + if (data & info->read_status_mask){ + if(data & CyBREAK){ + *tty->flip.flag_buf_ptr++ = + TTY_BREAK; + *tty->flip.char_buf_ptr++ = + base_addr[CyRDSR<flags & ASYNC_SAK){ + do_SAK(tty); + } + }else if(data & CyFRAME){ + *tty->flip.flag_buf_ptr++ = + TTY_FRAME; + *tty->flip.char_buf_ptr++ = + base_addr[CyRDSR<flip.flag_buf_ptr++ = + TTY_PARITY; + *tty->flip.char_buf_ptr++ = + base_addr[CyRDSR<flip.flag_buf_ptr++ = + TTY_OVERRUN; + *tty->flip.char_buf_ptr++ = 0; + /* If the flip buffer itself is + overflowing, we still loose + the next incoming character. + */ + if(tty->flip.count + < TTY_FLIPBUF_SIZE){ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = + TTY_NORMAL; + *tty->flip.char_buf_ptr++ = + base_addr[CyRDSR<flip.flag_buf_ptr++ = 0; + *tty->flip.char_buf_ptr++ = 0; + } + }else{ + *tty->flip.flag_buf_ptr++ = 0; + *tty->flip.char_buf_ptr++ = 0; + } }else{ - /* there was a software buffer overrun - and nothing could be done about it!!! */ + /* there was a software buffer + overrun and nothing could be + done about it!!! */ } } else { /* normal character reception */ - /* load # characters available from the chip */ + /* load # chars available from the chip */ char_count = base_addr[CyRDCR<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; + ++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 while(char_count--){ - if (tty->flip.count >= TTY_FLIPBUF_SIZE){ + if (tty->flip.count >= TTY_FLIPBUF_SIZE){ break; } - tty->flip.count++; + tty->flip.count++; data = base_addr[CyRDSR<flip.flag_buf_ptr++ = TTY_NORMAL; - *tty->flip.char_buf_ptr++ = data; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = data; #ifdef CYCLOM_16Y_HACK - udelay(10L); + udelay(10L); #endif } } - queue_task_irq_off(&tty->flip.tqueue, &tq_timer); + queue_task(&tty->flip.tqueue, &tq_timer); } /* end of service */ base_addr[CyRIR<first_line; save_car = base_addr[CyCAR<xmit_fifo_size; @@ -863,64 +1204,65 @@ info->x_char = 0; } - if (info->x_break){ - /* The Cirrus chip requires the "Embedded Transmit - Commands" of start break, delay, and end break - sequences to be sent. The duration of the - break is given in TICs, which runs at HZ - (typically 100) and the PPR runs at 200 Hz, - so the delay is duration * 200/HZ, and thus a - break can run from 1/100 sec to about 5/4 sec. - */ - base_addr[CyTDR<x_break*200/HZ; - base_addr[CyTDR<x_break = 0; - } + if (info->x_break){ + /* The Cirrus chip requires the "Embedded + Transmit Commands" of start break, delay, + and end break sequences to be sent. The + duration of the break is given in TICs, + which runs at HZ (typically 100) and the + PPR runs at 200 Hz, so the delay is + duration * 200/HZ, and thus a break can + run from 1/100 sec to about 5/4 sec. + */ + base_addr[CyTDR<x_break*200/HZ; + base_addr[CyTDR<x_break = 0; + } while (char_count-- > 0){ if (!info->xmit_cnt){ - base_addr[CySRER<xmit_buf == 0){ - base_addr[CySRER<tty->stopped || info->tty->hw_stopped){ - base_addr[CySRER<xmit_buf == 0){ + base_addr[CySRER<tty->stopped || info->tty->hw_stopped){ + base_addr[CySRER<xmit_buf[info->xmit_tail]; if( outch ){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (PAGE_SIZE - 1); - base_addr[CyTDR<xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) + & (PAGE_SIZE - 1); + base_addr[CyTDR< 1){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (PAGE_SIZE - 1); - base_addr[CyTDR<xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) + & (PAGE_SIZE - 1); + base_addr[CyTDR<first_line]; + info = &cy_port[channel + chip * 4 + + cinfo->first_line]; info->last_active = jiffies; save_car = base_addr[CyCAR<tty == 0){ /* nowhere to put the data, ignore it */ + if(info->tty == 0){/* no place for data, ignore it*/ ; }else{ if((mdm_change & CyDCD) && (info->flags & ASYNC_CHECK_CD)){ if(mdm_status & CyDCD){ - 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); + 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); } } if((mdm_change & CyCTS) && (info->flags & ASYNC_CTS_FLOW)){ if(info->tty->hw_stopped){ if(mdm_status & CyCTS){ - /* !!! cy_start isn't used because... */ + /* cy_start isn't used + because... !!! */ info->tty->hw_stopped = 0; - base_addr[CySRER<tty->hw_stopped = 1; - base_addr[CySRER<tty; - if (!tty) - return; +} /* cyy_interrupt */ - if (clear_bit(Cy_EVENT_HANGUP, &info->event)) { - tty_hangup(info->tty); - wake_up_interruptible(&info->open_wait); - info->flags &= ~(ASYNC_NORMAL_ACTIVE| - ASYNC_CALLOUT_ACTIVE); - } - if (clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->open_wait); - } - if (clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup){ - (tty->ldisc.write_wakeup)(tty); - } - wake_up_interruptible(&tty->write_wait); - } -} /* do_softint */ +/***********************************************************/ +/********* End of block of Cyclom-Y specific code **********/ +/******** Start of block of Cyclom-Z specific code *********/ +/***********************************************************/ -/* - * Grab all interrupts in preparation for doing an automatic irq - * detection. dontgrab is a mask of irq's _not_ to grab. Returns a - * mask of irq's which were grabbed and should therefore be freed - * using free_all_interrupts(). - */ static int -grab_all_interrupts(int dontgrab) +cyz_fetch_msg( struct cyclades_card *cinfo, + u_long *channel, u_char *cmd, u_long **param) { - int irq_lines = 0; - int i, mask; - - for (i = 0, mask = 1; i < 16; i++, mask <<= 1) { - if (!(mask & dontgrab) - && !request_irq(i, cy_probe, SA_INTERRUPT, "serial probe", NULL)) { - irq_lines |= mask; - } + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + unsigned long loc_doorbell; + + firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + return (-1); + } + zfw_ctrl = (struct ZFW_CTRL *) + (cinfo->base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + + loc_doorbell = ((struct RUNTIME_9060 *) + (cinfo->ctl_addr))->loc_doorbell; + if (loc_doorbell){ + *cmd = (char)(0xff & loc_doorbell); + *channel = board_ctrl->fwcmd_channel; + *param = board_ctrl->fwcmd_param; + ((struct RUNTIME_9060 *) + (cinfo->ctl_addr))->loc_doorbell = 0xffffffff; + return 1; } - return irq_lines; -} /* grab_all_interrupts */ + return 0; +} /* cyz_fetch_msg */ -/* - * Release all interrupts grabbed by grab_all_interrupts - */ -static void -free_all_interrupts(int irq_lines) -{ - int i; - - for (i = 0; i < 16; i++) { - if (irq_lines & (1 << i)) - free_irq(i,NULL); - } -} /* free_all_interrupts */ -/* - * This routine returns a bitfield of "wild interrupts". Basically, - * any unclaimed interrupts which is flapping around. - */ static int -check_wild_interrupts(void) +cyz_issue_cmd( struct cyclades_card *cinfo, + u_long channel, u_char cmd, u_long *param) { - int i, mask; - int wild_interrupts = 0; - int irq_lines; - unsigned long timeout; - unsigned long flags; - - /*Turn on interrupts (they may be off) */ - save_flags(flags); sti(); - - irq_lines = grab_all_interrupts(0); - - /* - * Delay for 0.1 seconds -- we use a busy loop since this may - * occur during the bootup sequence - */ - timeout = jiffies+10; - while (timeout >= jiffies) - ; - - cy_triggered = 0; /* Reset after letting things settle */ - - timeout = jiffies+10; - while (timeout >= jiffies) - ; - - for (i = 0, mask = 1; i < 16; i++, mask <<= 1) { - if ((cy_triggered & (1 << i)) && - (irq_lines & (1 << i))) { - wild_interrupts |= mask; - } - } - free_all_interrupts(irq_lines); - restore_flags(flags); - return wild_interrupts; -} /* check_wild_interrupts */ + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + volatile unsigned long *pci_doorbell; + int index; + + firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + return (-1); + } + zfw_ctrl = (struct ZFW_CTRL *) + (cinfo->base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + + index = 0; + pci_doorbell = &((struct RUNTIME_9060 *) + (cinfo->ctl_addr))->pci_doorbell; + while( (*pci_doorbell & 0xff) != 0){ + if (index++ == 100){ + return(-1); + } + udelay(50L); + } + board_ctrl->hcmd_channel = channel; + board_ctrl->hcmd_param = param; + *pci_doorbell = (long)cmd; -/* - * This routine is called by do_auto_irq(); it attempts to determine - * which interrupt a serial port is configured to use. It is not - * fool-proof, but it works a large part of the time. - */ -static int -get_auto_irq(unsigned char *address) -{ - unsigned long timeout; - unsigned char *base_addr; - int index; + return(0); +} /* cyz_issue_cmd */ - index = 0; /* IRQ probing is only for ISA */ - base_addr = address; - intr_base_addr = address; - - /* - * Enable interrupts and see who answers - */ - cy_irq_triggered = 0; - cli(); - base_addr[CyCAR<= jiffies) { - if (cy_irq_triggered) - break; - } - probe_ready = 0; - return(cy_irq_triggered); -} /* get_auto_irq */ -/* - * Calls get_auto_irq() multiple times, to make sure we don't get - * faked out by random interrupts - */ static int -do_auto_irq(unsigned char *address) -{ - int irq_lines = 0; - int irq_try_1 = 0, irq_try_2 = 0; - int retries; - unsigned long flags; - - /* Turn on interrupts (they may be off) */ - save_flags(flags); sti(); +cyz_update_channel( struct cyclades_card *cinfo, + u_long channel, u_char mode, u_char cmd) +{ + struct FIRM_ID *firm_id = + (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); + struct ZFW_CTRL *zfw_ctrl; + struct CH_CTRL *ch_ctrl; + + if (firm_id->signature != ZFIRM_ID){ + return (-1); + } + zfw_ctrl = + (struct ZFW_CTRL *)(cinfo->base_addr + firm_id->zfwctrl_addr); + ch_ctrl = zfw_ctrl->ch_ctrl; - probe_ready = 0; + ch_ctrl[channel].op_mode = (long)mode; - cy_wild_int_mask = check_wild_interrupts(); + return cyz_issue_cmd(cinfo, channel, cmd, 0L); - irq_lines = grab_all_interrupts(cy_wild_int_mask); - - for (retries = 0; retries < 5; retries++) { - if (!irq_try_1) - irq_try_1 = get_auto_irq(address); - if (!irq_try_2) - irq_try_2 = get_auto_irq(address); - if (irq_try_1 && irq_try_2) { - if (irq_try_1 == irq_try_2) - break; - irq_try_1 = irq_try_2 = 0; - } - } - restore_flags(flags); - free_all_interrupts(irq_lines); - return (irq_try_1 == irq_try_2) ? irq_try_1 : 0; -} /* do_auto_irq */ +} /* cyz_update_channel */ -/* This is called whenever a port becomes active; - interrupts are enabled and DTR & RTS are turned on. - */ -static int -startup(struct cyclades_port * info) +static void +cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long flags; - unsigned char *base_addr; - int card,chip,channel,index; +} /* cyz_interrupt */ - if (info->flags & ASYNC_INITIALIZED){ - return 0; - } - if (!info->type){ - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - return 0; - } - if (!info->xmit_buf){ - info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL); - if (!info->xmit_buf){ - return -ENOMEM; +static void +cyz_poll(unsigned long arg) +{ + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + struct BUF_CTRL *buf_ctrl; + struct cyclades_card *cinfo; + struct cyclades_port *info; + struct tty_struct *tty; + int card, port; + int char_count, small_count; + char data; + u_long channel; + u_char cmd; + u_long *param; + + cyz_timerlist.expires = jiffies + 100; + + for (card = 0 ; card < NR_CARDS ; card++){ + cinfo = &cy_card[card]; + if (!IS_CYC_Z(*cinfo)) continue; + + firm_id = (struct FIRM_ID *) + (cinfo->base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + continue; } - } - - config_setup(info); - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) + zfw_ctrl = + (struct ZFW_CTRL *) + (cinfo->base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + + 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( 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); + } + } + break; + case C_CM_MCTS: + if (info->flags & ASYNC_CTS_FLOW) { + if(info->tty->hw_stopped){ + if( 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(!(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; + case C_CM_MRI: + break; + case C_CM_MDSR: + break; + case C_CM_FATAL: + /* should do something with this !!! */ + break; + } + if(char_count){ + queue_task(&tty->flip.tqueue, &tq_timer); + } + } + + for (port = 0; port < 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]); + + if ((char_count = CHARS_IN_BUF(buf_ctrl))){ + info->last_active = jiffies; + info->jiffies[1] = jiffies; + +#ifdef CYCLOM_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 */ + buf_ctrl->rx_get = + (buf_ctrl->rx_get + char_count) + % buf_ctrl->rx_bufsize; + /* 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( (buf_ctrl->rx_bufsize - buf_ctrl->rx_get), + cy_min( (TTY_FLIPBUF_SIZE - tty->flip.count), + char_count)))){ + memcpy(tty->flip.char_buf_ptr, + (char *)(cinfo->base_addr + + buf_ctrl->rx_bufaddr + + buf_ctrl->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; + buf_ctrl->rx_get = + (buf_ctrl->rx_get + small_count) + % buf_ctrl->rx_bufsize; + char_count -= small_count; + tty->flip.count += small_count; + } +#else + while(char_count--){ + if (tty->flip.count >= TTY_FLIPBUF_SIZE){ + break; + } + data = *(char *) (cinfo->base_addr + + buf_ctrl->rx_bufaddr + + buf_ctrl->rx_get); + buf_ctrl->rx_get = + (buf_ctrl->rx_get + 1) + % buf_ctrl->rx_bufsize; + + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = data; + } +#endif + queue_task(&tty->flip.tqueue, &tq_timer); + } + } + + if ((char_count = SPACE_IN_BUF(buf_ctrl))){ + if( tty == 0){ + goto ztxdone; + } + + if(info->x_char) { /* send special char */ + data = info->x_char; + + *(char *) (cinfo->base_addr + + buf_ctrl->tx_bufaddr + + buf_ctrl->tx_put) = data; + buf_ctrl->tx_put = + (buf_ctrl->tx_put + 1) + % buf_ctrl->tx_bufsize; + info->x_char = 0; + char_count--; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } + if (info->x_break){ + printk("cyc cyz_poll shouldn't see x_break\n"); + info->x_break = 0; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } +#ifdef BLOCKMOVE + while(0 < (small_count + = cy_min( (buf_ctrl->tx_bufsize - buf_ctrl->tx_put), + cy_min ( (PAGE_SIZE - info->xmit_tail), + cy_min( info->xmit_cnt, char_count))))){ + memcpy((char *)(cinfo->base_addr + + buf_ctrl->tx_bufaddr + + buf_ctrl->tx_put), + &info->xmit_buf[info->xmit_tail], + small_count); + buf_ctrl->tx_put = + (buf_ctrl->tx_put + small_count) + % buf_ctrl->tx_bufsize; + char_count -= small_count; + info->xmit_cnt -= small_count; + info->xmit_tail = + (info->xmit_tail + small_count) & (PAGE_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) & (PAGE_SIZE - 1); + + *(char *) (cinfo->base_addr + + buf_ctrl->tx_bufaddr + + buf_ctrl->tx_put) = data; + buf_ctrl->tx_put = + (buf_ctrl->tx_put + 1) + % buf_ctrl->tx_bufsize; + 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); + } + } + } + + /* poll every 40 ms */ + cyz_timerlist.expires = jiffies + 4; + } + add_timer(&cyz_timerlist); + + return; +} /* cyz_poll */ + + +/********** End of block of Cyclom-Z specific code *********/ +/***********************************************************/ + + +/* This is called whenever a port becomes active; + interrupts are enabled and DTR & RTS are turned on. + */ +static int +startup(struct cyclades_port * info) +{ + unsigned long flags; + unsigned char *base_addr; + int card,chip,channel,index; + + if (info->flags & ASYNC_INITIALIZED){ + return 0; + } + + if (!info->type){ + if (info->tty){ + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + return 0; + } + if (!info->xmit_buf){ + info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL); + if (!info->xmit_buf){ + return -ENOMEM; + } + } + + set_line_char(info); + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) (cy_card[card].base_addr + (cy_chip_offset[chip]<default_timeout + ? info->default_timeout + : 0x02); /* 10ms rx timeout */ + + cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); + + base_addr[CyCAR<default_timeout - ? info->default_timeout - : 0x02); /* 10ms rx timeout */ +#ifdef SERIAL_DEBUG_DTR + printk("cyc:startup raising DTR\n"); + printk(" status: 0x%x, 0x%x\n", + base_addr[CyMSVR1<flags |= ASYNC_INITIALIZED; + + if (info->tty){ + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + restore_flags(flags); + } else { + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + int retval; + + base_addr = (unsigned char*) (cy_card[card].base_addr); + + firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + return -ENODEV; + } - base_addr[CyCAR<zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; +#ifdef SERIAL_DEBUG_OPEN + printk("cyc startup Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr);/**/ +#endif + + ch_ctrl[channel].op_mode = C_CH_ENABLE; + ch_ctrl[channel].intr_enable = C_IN_MDCD|C_IN_MCTS; + retval = cyz_issue_cmd( &cy_card[card], + channel, C_CM_IOCTL, 0L); /* was C_CM_RESET */ + if (retval != 0){ + printk("cyc:startup(1) retval was %x\n", retval); + } + + /* set timeout !!! */ + /* set RTS and DTR !!! */ + ch_ctrl[channel].rs_control |= + C_RS_RTS | C_RS_DTR ; + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0){ + printk("cyc:startup(2) retval was %x\n", retval); + } #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<flags |= ASYNC_INITIALIZED; + /* enable send, recv, modem !!! */ + info->flags |= ASYNC_INITIALIZED; if (info->tty){ clear_bit(TTY_IO_ERROR, &info->tty->flags); } info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - restore_flags(flags); + } #ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); + printk(" cyc startup done\n"); #endif - return 0; + return 0; } /* startup */ -void + +static void start_xmit( struct cyclades_port *info ) { unsigned long flags; @@ -1291,18 +1856,24 @@ card = info->card; channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<flags & ASYNC_INITIALIZED)){ - return; + return; } card = info->card; channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<xmit_buf){ + unsigned char * temp; + temp = info->xmit_buf; + info->xmit_buf = 0; + free_page((unsigned long) temp); + } + + base_addr[CyCAR<tty || (info->tty->termios->c_cflag & HUPCL)) { + base_addr[CyMSVR1<tty){ + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + restore_flags(flags); + } else { + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + int retval; + + base_addr = (unsigned char*) (cy_card[card].base_addr); #ifdef SERIAL_DEBUG_OPEN - printk("shutdown card %d, chip %d, channel %d, base_addr %lx\n", - card, chip, channel, (long)base_addr); + printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr); #endif - /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE - SENT BEFORE DROPPING THE LINE !!! (Perhaps - set some flag that is read when XMTY happens.) - Other choices are to delay some fixed interval - or schedule some later processing. + firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + return; + } + + zfw_ctrl = + (struct ZFW_CTRL *) + (cy_card[card].base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + save_flags(flags); cli(); + if (info->xmit_buf){ + unsigned char * temp; + temp = info->xmit_buf; + info->xmit_buf = 0; + free_page((unsigned long) temp); + } + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + ch_ctrl[channel].rs_control &= + ~(C_RS_RTS | C_RS_DTR ); + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0){ + printk("cyc:shutdown retval was %x\n", + retval); + } +#ifdef SERIAL_DEBUG_DTR + printk("cyc:shutdown dropping Z DTR\n"); +#endif + } + + if (info->tty){ + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + + restore_flags(flags); + } + +#ifdef SERIAL_DEBUG_OPEN + printk(" cyc shutdown done\n"); +#endif + return; +} /* shutdown */ + + +/* + * ------------------------------------------------------------ + * cy_open() and friends + * ------------------------------------------------------------ + */ + +static int +block_til_ready(struct tty_struct *tty, struct file * filp, + struct cyclades_port *info) +{ + struct wait_queue wait = { current, NULL }; + struct cyclades_card *cinfo; + unsigned long flags; + int chip, channel,index; + int retval; + char *base_addr; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. */ - save_flags(flags); cli(); - if (info->xmit_buf){ - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = 0; - free_page((unsigned long) temp); + if (info->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&info->close_wait); + if (info->flags & ASYNC_HUP_NOTIFY){ + return -EAGAIN; + }else{ + return -ERESTARTSYS; + } + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE){ + return -EBUSY; + } + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)){ + return -EBUSY; + } + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)){ + return -EBUSY; + } + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, then make the check up front + * and then exit. + */ + if (filp->f_flags & O_NONBLOCK) { + if (info->flags & ASYNC_CALLOUT_ACTIVE){ + return -EBUSY; + } + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * cy_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("cyc block_til_ready before block: ttyC%d, count = %d\n", + info->line, info->count);/**/ +#endif + info->count--; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc block_til_ready: (%d): decrementing count to %d\n", + current->pid, info->count); +#endif + info->blocked_open++; + + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + if (!IS_CYC_Z(*cinfo)) { + chip = channel>>2; + channel &= 0x03; + index = cinfo->bus_index; + base_addr = (char *)(cinfo->base_addr + + (cy_chip_offset[chip]<flags & ASYNC_CALLOUT_ACTIVE)){ + base_addr[CyCAR<state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) + || !(info->flags & ASYNC_INITIALIZED) ){ + if (info->flags & ASYNC_HUP_NOTIFY) { + retval = -EAGAIN; + }else{ + retval = -ERESTARTSYS; + } + break; + } + save_flags(flags); cli(); + base_addr[CyCAR<flags & ASYNC_CALLOUT_ACTIVE) + && !(info->flags & ASYNC_CLOSING) + && (C_CLOCAL(tty) + || (base_addr[CyMSVR1<signal & ~current->blocked) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", + info->line, info->count);/**/ +#endif + schedule(); + } + } else { + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + int retval; + + base_addr = (char *)(cinfo->base_addr); + firm_id = (struct FIRM_ID *) + (base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + return -EINVAL; } - base_addr[CyCAR<tty || (info->tty->termios->c_cflag & HUPCL)) { - base_addr[CyMSVR1<zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + while (1) { + ch_ctrl[channel].rs_control |= + C_RS_RTS | C_RS_DTR ; + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0){ + printk("cyc:block_til_ready retval was %x\n", retval); + } #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: dropping DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) + || !(info->flags & ASYNC_INITIALIZED) ){ + if (info->flags & ASYNC_HUP_NOTIFY) { + retval = -EAGAIN; + }else{ + retval = -ERESTARTSYS; + } + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) + && !(info->flags & ASYNC_CLOSING) + && (C_CLOCAL(tty) + || (ch_ctrl[channel].rs_status & C_RS_DCD))) { + break; + } + if (current->signal & ~current->blocked) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", + info->line, info->count);/**/ +#endif + schedule(); + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)){ + info->count++; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:block_til_ready (%d): incrementing count to %d\n", + current->pid, info->count); +#endif + } + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", + info->line, info->count);/**/ +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} /* block_til_ready */ + + +/* + * This routine is called whenever a serial port is opened. It + * performs the serial-specific initialization for the tty structure. + */ +int +cy_open(struct tty_struct *tty, struct file * filp) +{ + struct cyclades_port *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (NR_PORTS <= line)){ + return -ENODEV; + } + info = &cy_port[line]; + if (info->line < 0){ + return -ENODEV; + } + + /* If the card's firmware hasn't been loaded, + treat it as absent from the system. This + will make the user pay attention. + */ + if (IS_CYC_Z(cy_card[info->card])) { + struct FIRM_ID *firm_id = + (struct FIRM_ID *) + (cy_card[info->card].base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ + printk("Cyclom-Z firmware not yet loaded\n"); + return -ENODEV; + } + } +#ifdef SERIAL_DEBUG_OTHER + printk("cyc:cy_open ttyC%d\n", info->line); /* */ +#endif + if (serial_paranoia_check(info, tty->device, "cy_open")){ + return -ENODEV; + } +#ifdef SERIAL_DEBUG_OPEN + printk("cyc:cy_open ttyC%d, count = %d\n", + info->line, info->count);/**/ +#endif + info->count++; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:cy_open (%d): incrementing count to %d\n", + current->pid, info->count); +#endif + tty->driver_data = info; + info->tty = tty; + + /* Some drivers have (incorrect/incomplete) code to test + against a race condition. Should add good code here!!! */ + if (!tmp_buf) { + tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (!tmp_buf){ + return -ENOMEM; + } + } + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + } + /* + * Start up serial port + */ + retval = startup(info); + if (retval){ + return retval; + } + + MOD_INC_USE_COUNT; + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("cyc:cy_open returning after block_til_ready with %d\n", + retval); #endif - } - write_cy_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index); - /* it may be appropriate to clear _XMIT at - some later date (after testing)!!! */ + return retval; + } - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + info->session = current->session; + info->pgrp = current->pgrp; #ifdef SERIAL_DEBUG_OPEN - printk(" done\n"); + printk(" cyc:cy_open done\n");/**/ #endif - return; -} /* shutdown */ + return 0; +} /* cy_open */ + /* - * This routine finds or computes the various line characteristics. + * This routine is called when a particular tty device is closed. */ static void -config_setup(struct cyclades_port * info) +cy_close(struct tty_struct * tty, struct file * filp) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; unsigned long flags; - unsigned char *base_addr; - int card,chip,channel,index; - unsigned cflag; - int i; - if (!info->tty || !info->tty->termios){ +#ifdef SERIAL_DEBUG_OTHER + printk("cyc:cy_close ttyC%d\n", info->line); +#endif + + if (!info + || serial_paranoia_check(info, tty->device, "cy_close")){ return; } - if (info->line == -1){ +#ifdef SERIAL_DEBUG_OPEN + printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); +#endif + + save_flags(flags); cli(); + + /* If the TTY is being hung up, nothing to do */ + if (tty_hung_up_p(filp)) { + restore_flags(flags); return; } - cflag = info->tty->termios->c_cflag; - - /* baud rate */ - i = cflag & CBAUD; -#ifdef CBAUDEX -/* Starting with kernel 1.1.65, there is direct support for - higher baud rates. The following code supports those - changes. The conditional aspect allows this driver to be - used for earlier as well as later kernel versions. (The - mapping is slightly different from serial.c because there - is still the possibility of supporting 75 kbit/sec with - the Cyclades board.) - */ - if (i & CBAUDEX) { - if (i == B57600) - i = 16; - else if(i == B115200) - i = 18; -#ifdef B78600 - else if(i == B78600) - i = 17; -#endif - else - info->tty->termios->c_cflag &= ~CBAUDEX; + + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("cyc:cy_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; } +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:cy_close at (%d): decrementing count to %d\n", + current->pid, info->count - 1); #endif - if (i == 15) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - i += 1; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - i += 3; - } - info->tbpr = baud_bpr[i]; /* Tx BPR */ - info->tco = baud_co[i]; /* Tx CO */ - info->rbpr = baud_bpr[i]; /* Rx BPR */ - info->rco = baud_co[i]; /* Rx CO */ - if (baud_table[i] == 134) { - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - /* get it right for 134.5 baud */ - } else if (baud_table[i]) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; - /* this needs to be propagated into the card info */ - } else { - info->timeout = 0; + if (--info->count < 0) { +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:cyc_close setting count to 0\n"); +#endif + info->count = 0; } - /* By tradition (is it a standard?) a baud rate of zero - implies the line should be/has been closed. A bit - later in this routine such a test is performed. */ - - /* byte size and parity */ - info->cor5 = 0; - info->cor4 = 0; - info->cor3 = (info->default_threshold - ? info->default_threshold - : baud_cor3[i]); /* receive threshold */ - info->cor2 = CyETC; - switch(cflag & CSIZE){ - case CS5: - info->cor1 = Cy_5_BITS; - break; - case CS6: - info->cor1 = Cy_6_BITS; - break; - case CS7: - info->cor1 = Cy_7_BITS; - break; - case CS8: - info->cor1 = Cy_8_BITS; - break; - } - if(cflag & CSTOPB){ - info->cor1 |= Cy_2_STOP; - } - if (cflag & PARENB){ - if (cflag & PARODD){ - info->cor1 |= CyPARITY_O; - }else{ - info->cor1 |= CyPARITY_E; - } - }else{ - info->cor1 |= CyPARITY_NONE; + if (info->count) { + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; } - - /* CTS flow control flag */ - if (cflag & CRTSCTS){ - info->flags |= ASYNC_CTS_FLOW; - info->cor2 |= CyCtsAE; - }else{ - info->flags &= ~ASYNC_CTS_FLOW; - info->cor2 &= ~CyCtsAE; + info->flags |= ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + if (info->flags & ASYNC_INITIALIZED) + tty_wait_until_sent(tty, 5*HZ); /* 5 seconds timeout */ + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + info->close_delay; + schedule(); + } + wake_up_interruptible(&info->open_wait); } - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; - - /*********************************************** - The hardware option, CyRtsAO, presents RTS when - the chip has characters to send. Since most modems - use RTS as reverse (inbound) flow control, this - option is not used. If inbound flow control is - necessary, DTR can be programmed to provide the - appropriate signals for use with a non-standard - cable. Contact Marcio Saito for details. - ***********************************************/ - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); - /* tx and rx baud rate */ +#ifdef SERIAL_DEBUG_OTHER + printk(" cyc:cy_close done\n"); +#endif - base_addr[CyTCOR<tco; - base_addr[CyTBPR<tbpr; - base_addr[CyRCOR<rco; - base_addr[CyRBPR<rbpr; + MOD_DEC_USE_COUNT; + restore_flags(flags); + return; +} /* cy_close */ - /* set line characteristics according configuration */ - base_addr[CySCHR1<tty); - base_addr[CySCHR2<tty); - base_addr[CyCOR1<cor1; - base_addr[CyCOR2<cor2; - base_addr[CyCOR3<cor3; - base_addr[CyCOR4<cor4; - base_addr[CyCOR5<cor5; +/* This routine gets called when tty_write has put something into + * the write_queue. The characters may come from user space or + * kernel space. + * + * This routine will return the number of characters actually + * accepted for writing. + * + * If the port is not already transmitting stuff, start it off by + * enabling interrupts. The interrupt service routine will then + * ensure that the characters are sent. + * If the port is already active, there is no need to kick it. + * + */ +static int +cy_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + int c, total = 0; - write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index); +#ifdef SERIAL_DEBUG_IO + printk("cyc:cy_write ttyC%d\n", info->line); /* */ +#endif - base_addr[CyCAR<device, "cy_write")){ + return 0; + } + + if (!tty || !info->xmit_buf || !tmp_buf){ + return 0; + } - base_addr[CyRTPR<default_timeout - ? info->default_timeout - : 0x02); /* 10ms rx timeout */ - - if (C_CLOCAL(info->tty)) { - base_addr[CySRER<0 modem transitions */ - base_addr[CyMCOR1<1 modem transitions */ - base_addr[CyMCOR2<0 modem transitions */ - base_addr[CyMCOR1<1 modem transitions */ - base_addr[CyMCOR2<xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0){ + restore_flags(flags); + break; + } - if(i == 0){ /* baud rate is zero, turn off line */ - base_addr[CyMSVR2<xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; +#if 0 + SP("CW"); + CP16(c); + SP(" "); #endif - } - - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } + } + if (from_user) + up(&tmp_buf_sem); - restore_flags(flags); -} /* config_setup */ + if (info->xmit_cnt + && !tty->stopped + && !tty->hw_stopped ) { + start_xmit(info); + } + return total; +} /* cy_write */ +/* + * This routine is called by the kernel to write a single + * character to the tty device. If the kernel uses this routine, + * it must call the flush_chars() routine (if defined) when it is + * done stuffing characters into the driver. If there is no room + * in the queue, the character is ignored. + */ static void cy_put_char(struct tty_struct *tty, unsigned char ch) { @@ -1574,28 +2493,35 @@ unsigned long flags; #ifdef SERIAL_DEBUG_IO - printk("cy_put_char ttyC%d\n", info->line); + printk("cyc:cy_put_char ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->device, "cy_put_char")) - return; + return; if (!tty || !info->xmit_buf) - return; + return; save_flags(flags); cli(); - if (info->xmit_cnt >= PAGE_SIZE - 1) { - restore_flags(flags); - return; - } + if (info->xmit_cnt >= PAGE_SIZE - 1) { + restore_flags(flags); + return; + } - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= PAGE_SIZE - 1; - info->xmit_cnt++; + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= PAGE_SIZE - 1; + info->xmit_cnt++; restore_flags(flags); +#if 0 + SP("+"); +#endif } /* cy_put_char */ +/* + * This routine is called by the kernel after it has written a + * series of characters to the tty device using put_char(). + */ static void cy_flush_chars(struct tty_struct *tty) { @@ -1603,110 +2529,60 @@ unsigned long flags; unsigned char *base_addr; int card,chip,channel,index; - + #ifdef SERIAL_DEBUG_IO - printk("cy_flush_chars ttyC%d\n", info->line); /* */ + printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ #endif if (serial_paranoia_check(info, tty->device, "cy_flush_chars")) - return; + return; if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) - return; + return; card = info->card; channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<driver_data; - unsigned long flags; - int c, total = 0; - -#ifdef SERIAL_DEBUG_IO - printk("cy_write ttyC%d\n", info->line); /* */ -#endif - - if (serial_paranoia_check(info, tty->device, "cy_write")){ - return 0; - } - - if (!tty || !info->xmit_buf || !tmp_buf){ - return 0; - } - - while (1) { - save_flags(flags); cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0){ - restore_flags(flags); - break; - } + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - up(&tmp_buf_sem); - } else - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; + save_flags(flags); cli(); + base_addr[CyCAR<xmit_cnt - && !tty->stopped - && !tty->hw_stopped ) { - start_xmit(info); + } else { + /* Since polling is already in place, + nothing further need be done. */ } - return total; -} /* cy_write */ +} /* cy_flush_chars */ +/* + * This routine returns the numbers of characters the tty driver + * will accept for queuing to be written. This number is subject + * to change as output buffers get emptied, or if the output flow + * control is activated. + */ static int cy_write_room(struct tty_struct *tty) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int ret; - + int ret; + #ifdef SERIAL_DEBUG_IO - printk("cy_write_room ttyC%d\n", info->line); /* */ + printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ #endif if (serial_paranoia_check(info, tty->device, "cy_write_room")) - return 0; + return 0; ret = PAGE_SIZE - info->xmit_cnt - 1; if (ret < 0) - ret = 0; + ret = 0; return ret; } /* cy_write_room */ @@ -1715,126 +2591,351 @@ cy_chars_in_buffer(struct tty_struct *tty) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - + #ifdef SERIAL_DEBUG_IO - printk("cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ + printk("cyc:cy_chars_in_buffer ttyC%d %d\n", + info->line, info->xmit_cnt); /* */ #endif if (serial_paranoia_check(info, tty->device, "cy_chars_in_buffer")) - return 0; + return 0; return info->xmit_cnt; } /* cy_chars_in_buffer */ -static void -cy_flush_buffer(struct tty_struct *tty) -{ - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - -#ifdef SERIAL_DEBUG_IO - printk("cy_flush_buffer ttyC%d\n", info->line); /* */ -#endif - - if (serial_paranoia_check(info, tty->device, "cy_flush_buffer")) - return; - save_flags(flags); cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - restore_flags(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} /* cy_flush_buffer */ +/* + * ------------------------------------------------------------ + * cy_ioctl() and friends + * ------------------------------------------------------------ + */ -/* This routine is called by the upper-layer tty layer to signal - that incoming characters should be throttled or that the - throttle should be released. +/* + * This routine finds or computes the various line characteristics. + * It used to be called config_setup */ static void -cy_throttle(struct tty_struct * tty) +set_line_char(struct cyclades_port * info) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; unsigned char *base_addr; int card,chip,channel,index; + unsigned cflag; + int i; + + if (!info->tty || !info->tty->termios){ + return; + } + if (info->line == -1){ + return; + } + cflag = info->tty->termios->c_cflag; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + + if (!IS_CYC_Z(cy_card[card])) { + /* baud rate */ + i = cflag & CBAUD; + + if (i & CBAUDEX) { + if (i == B57600) + i = 16; + else if(i == B115200) + i = 18; +#ifdef B76800 + else if(i == B76800) + i = 17; +#endif + else + info->tty->termios->c_cflag &= ~CBAUDEX; + } + + if (i == 15) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + i += 1; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + i += 3; + } + info->tbpr = baud_bpr[i]; /* Tx BPR */ + info->tco = baud_co[i]; /* Tx CO */ + info->rbpr = baud_bpr[i]; /* Rx BPR */ + info->rco = baud_co[i]; /* Rx CO */ + if (baud_table[i] == 134) { + info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; + /* get it right for 134.5 baud */ + } else if (baud_table[i]) { + info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } + /* By tradition (is it a standard?) a baud rate of zero + implies the line should be/has been closed. A bit + later in this routine such a test is performed. */ + + /* byte size and parity */ + info->cor5 = 0; + info->cor4 = 0; + info->cor3 = (info->default_threshold + ? info->default_threshold + : baud_cor3[i]); /* receive threshold */ + info->cor2 = CyETC; + switch(cflag & CSIZE){ + case CS5: + info->cor1 = Cy_5_BITS; + break; + case CS6: + info->cor1 = Cy_6_BITS; + break; + case CS7: + info->cor1 = Cy_7_BITS; + break; + case CS8: + info->cor1 = Cy_8_BITS; + break; + } + if(cflag & CSTOPB){ + info->cor1 |= Cy_2_STOP; + } + if (cflag & PARENB){ + if (cflag & PARODD){ + info->cor1 |= CyPARITY_O; + }else{ + info->cor1 |= CyPARITY_E; + } + }else{ + info->cor1 |= CyPARITY_NONE; + } + + /* CTS flow control flag */ + if (cflag & CRTSCTS){ + info->flags |= ASYNC_CTS_FLOW; + info->cor2 |= CyCtsAE; + }else{ + info->flags &= ~ASYNC_CTS_FLOW; + info->cor2 &= ~CyCtsAE; + } + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; + + /*********************************************** + The hardware option, CyRtsAO, presents RTS when + the chip has characters to send. Since most modems + use RTS as reverse (inbound) flow control, this + option is not used. If inbound flow control is + necessary, DTR can be programmed to provide the + appropriate signals for use with a non-standard + cable. Contact Marcio Saito for details. + ***********************************************/ + + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<ldisc.chars_in_buffer(tty)); - printk("cy_throttle ttyC%d\n", info->line); + /* tx and rx baud rate */ + + base_addr[CyTCOR<tco; + base_addr[CyTBPR<tbpr; + base_addr[CyRCOR<rco; + base_addr[CyRBPR<rbpr; + + /* set line characteristics according configuration */ + + base_addr[CySCHR1<tty); + base_addr[CySCHR2<tty); + base_addr[CyCOR1<cor1; + base_addr[CyCOR2<cor2; + base_addr[CyCOR3<cor3; + base_addr[CyCOR4<cor4; + base_addr[CyCOR5<cor5; + + cyy_issue_cmd(base_addr, + CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index); + + base_addr[CyCAR<default_timeout + ? info->default_timeout + : 0x02); /* 10ms rx timeout */ + + if (C_CLOCAL(info->tty)) { + base_addr[CySRER<0 modem transitions */ + base_addr[CyMCOR1<1 modem transitions */ + base_addr[CyMCOR2<0 modem transitions */ + base_addr[CyMCOR1<1 modem transitions */ + base_addr[CyMCOR2<device, "cy_nthrottle")){ + if (info->tty){ + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + + restore_flags(flags); + } else { + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + struct BUF_CTRL *buf_ctrl; + int retval; + + firm_id = (struct FIRM_ID *) + (cy_card[card].base_addr + ID_ADDRESS); + if (firm_id->signature != ZFIRM_ID){ return; - } + } - if (I_IXOFF(tty)) { - info->x_char = STOP_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ - } + zfw_ctrl = + (struct ZFW_CTRL *) + (cy_card[card].base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = &zfw_ctrl->ch_ctrl[channel]; + buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; - card = info->card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<comm_baud = 0; break; + */ + case B50: ch_ctrl->comm_baud = 50; break; + case B75: ch_ctrl->comm_baud = 75; break; + case B110: ch_ctrl->comm_baud = 110; break; + case B134: ch_ctrl->comm_baud = 134; break; + case B150: ch_ctrl->comm_baud = 150; break; + case B200: ch_ctrl->comm_baud = 200; break; + case B300: ch_ctrl->comm_baud = 300; break; + case B600: ch_ctrl->comm_baud = 600; break; + case B1200: ch_ctrl->comm_baud = 1200; break; + case B1800: ch_ctrl->comm_baud = 1800; break; + case B2400: ch_ctrl->comm_baud = 2400; break; + case B4800: ch_ctrl->comm_baud = 4800; break; + case B9600: ch_ctrl->comm_baud = 9600; break; + case B19200: ch_ctrl->comm_baud = 19200; break; + case B38400: + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI){ + ch_ctrl->comm_baud = 57600; + }else if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI){ + ch_ctrl->comm_baud = 115200; + }else{ + ch_ctrl->comm_baud = 38400; + } + break; + case B57600: ch_ctrl->comm_baud = 57600; break; +#ifdef B76800 + case B76800: ch_ctrl->comm_baud = 76800; break; +#endif + case B115200: ch_ctrl->comm_baud = 115200; break; + case B230400: ch_ctrl->comm_baud = 230400; break; + case B460800: ch_ctrl->comm_baud = 460800; break; + } + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST){ + ch_ctrl->comm_baud = info->baud; + } - save_flags(flags); cli(); - base_addr[CyCAR<comm_data_l = C_DL_CS5; break; + case CS6: ch_ctrl->comm_data_l = C_DL_CS6; break; + case CS7: ch_ctrl->comm_data_l = C_DL_CS7; break; + case CS8: ch_ctrl->comm_data_l = C_DL_CS8; break; + } + if(cflag & CSTOPB){ + ch_ctrl->comm_data_l |= C_DL_2STOP; + }else{ + ch_ctrl->comm_data_l |= C_DL_1STOP; + } + if (cflag & PARENB){ + if (cflag & PARODD){ + ch_ctrl->comm_parity = C_PR_ODD; + }else{ + ch_ctrl->comm_parity = C_PR_EVEN; + } + }else{ + ch_ctrl->comm_parity = C_PR_NONE; + } - return; -} /* cy_throttle */ + /* CTS flow control flag */ + if (cflag & CRTSCTS){ + info->flags |= ASYNC_CTS_FLOW; + ch_ctrl->hw_flow |= C_RS_CTS | C_RS_RTS; + }else{ + info->flags &= ~ASYNC_CTS_FLOW; + ch_ctrl->hw_flow &= ~(C_RS_CTS | C_RS_RTS); + } + retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTL, 0L); + if (retval != 0){ + printk("cyc:set_line_char retval at %d was %x\n", + __LINE__, retval); + } -static void -cy_unthrottle(struct tty_struct * tty) -{ - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - unsigned char *base_addr; - int card,chip,channel,index; + /* CD sensitivity */ + if (cflag & CLOCAL){ + info->flags &= ~ASYNC_CHECK_CD; + }else{ + info->flags |= ASYNC_CHECK_CD; + } -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", _tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); - printk("cy_unthrottle ttyC%d\n", info->line); + if(i == 0){ /* baud rate is zero, turn off line */ + ch_ctrl->rs_control &= ~C_RS_DTR; +#ifdef SERIAL_DEBUG_DTR + printk("cyc:set_line_char dropping Z DTR\n"); +#endif + }else{ + ch_ctrl->rs_control |= C_RS_DTR; +#ifdef SERIAL_DEBUG_DTR + printk("cyc:set_line_char raising Z DTR\n"); #endif + } - if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){ - return; - } + retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L); + if (retval != 0){ + printk("cyc:set_line_char retval at %d was %x\n", + __LINE__, retval); + } - if (I_IXOFF(tty)) { - info->x_char = START_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ + if (info->tty){ + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } } - card = info->card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<card * 0x100 + info->line - cinfo->first_line; tmp.irq = cinfo->irq; tmp.flags = info->flags; - tmp.baud_base = 0; /*!!!*/ tmp.close_delay = info->close_delay; + tmp.baud_base = info->baud; tmp.custom_divisor = 0; /*!!!*/ tmp.hub6 = 0; /*!!!*/ - copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + memcpy_tofs(retinfo,&tmp,sizeof(*retinfo)); return 0; } /* get_serial_info */ + static int set_serial_info(struct cyclades_port * info, struct serial_struct * new_info) @@ -1867,18 +2969,19 @@ struct cyclades_port old_info; if (!new_info) - return -EFAULT; - copy_from_user(&new_serial,new_info,sizeof(new_serial)); + return -EFAULT; + memcpy_fromfs(&new_serial,new_info,sizeof(new_serial)); old_info = *info; if (!suser()) { - if ((new_serial.close_delay != info->close_delay) || - ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != - (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) - return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - goto check_and_exit; + if ((new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != + (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->baud = new_serial.baud_base; + goto check_and_exit; } @@ -1888,19 +2991,21 @@ */ info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); + (new_serial.flags & ASYNC_FLAGS)); + info->baud = new_serial.baud_base; info->close_delay = new_serial.close_delay; check_and_exit: if (info->flags & ASYNC_INITIALIZED){ - config_setup(info); - return 0; + set_line_char(info); + return 0; }else{ return startup(info); } } /* set_serial_info */ + static int get_modem_info(struct cyclades_port * info, unsigned int *value) { @@ -1908,259 +3013,423 @@ unsigned char *base_addr; unsigned long flags; unsigned char status; + unsigned long lstatus; unsigned int result; + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; card = info->card; channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<signature == ZFIRM_ID){ + zfw_ctrl = + (struct ZFW_CTRL *) + (cy_card[card].base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + lstatus = ch_ctrl[channel].rs_status; + result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) + | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) + | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) + | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) + | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) + | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); + }else{ + result = 0; + return -ENODEV; + } - result = ((status & CyRTS) ? TIOCM_RTS : 0) - | ((status & CyDTR) ? TIOCM_DTR : 0) - | ((status & CyDCD) ? TIOCM_CAR : 0) - | ((status & CyRI) ? TIOCM_RNG : 0) - | ((status & CyDSR) ? TIOCM_DSR : 0) - | ((status & CyCTS) ? TIOCM_CTS : 0); - put_user(result,(unsigned int *) value); + } + put_fs_long(result,(unsigned long *) value); return 0; } /* get_modem_info */ + static int set_modem_info(struct cyclades_port * info, unsigned int cmd, unsigned int *value) { - int card,chip,channel,index; - unsigned char *base_addr; - unsigned long flags; - unsigned int arg; - int error; - - error = get_user(arg, value); - if (error) - return error; + int card,chip,channel,index; + unsigned char *base_addr; + unsigned long flags; + unsigned int arg = get_fs_long((unsigned long *) value); + struct FIRM_ID *firm_id; + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + struct CH_CTRL *ch_ctrl; + int retval; card = info->card; channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<signature == ZFIRM_ID){ + zfw_ctrl = + (struct ZFW_CTRL *) + (cy_card[card].base_addr + firm_id->zfwctrl_addr); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS){ + ch_ctrl[channel].rs_control |= C_RS_RTS; + } + if (arg & TIOCM_DTR){ + ch_ctrl[channel].rs_control |= C_RS_DTR; #ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<card], + channel, C_CM_IOCTLM,0L); + if (retval != 0){ + printk("cyc:set_modem_info retval at %d was %x\n", + __LINE__, retval); + } + } return 0; } /* set_modem_info */ + static void send_break( struct cyclades_port * info, int duration) -{ /* Let the transmit ISR take care of this (since it - requires stuffing characters into the output stream). - */ - info->x_break = duration; - if (!info->xmit_cnt ) { - start_xmit(info); +{ + + if (!IS_CYC_Z(cy_card[info->card])) { + /* Let the transmit ISR take care of this (since it + requires stuffing characters into the output stream). + */ + info->x_break = duration; + if (!info->xmit_cnt ) { + start_xmit(info); + } + } else { + /* For the moment we ignore the duration parameter!!! + A better implementation will use C_CM_SET_BREAK + and C_CM_CLR_BREAK with the appropriate delay. + */ +#if 0 +this appears to wedge the output data stream +int retval; + retval = cyz_issue_cmd(&cy_card[info->card], + (info->line) - (cy_card[info->card].first_line), + C_CM_SENDBRK, 0L); + if (retval != 0){ + printk("cyc:send_break retval at %d was %x\n", + __LINE__, retval); + } +#endif } } /* send_break */ + static int get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) { - copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)); - info->mon.int_count = 0; - info->mon.char_count = 0; - info->mon.char_max = 0; - info->mon.char_last = 0; - return 0; -} + memcpy_tofs(mon, &info->mon, sizeof(struct cyclades_monitor)); + info->mon.int_count = 0; + info->mon.char_count = 0; + info->mon.char_max = 0; + info->mon.char_last = 0; + return 0; +}/* get_mon_info */ + static int set_threshold(struct cyclades_port * info, unsigned long value) { - unsigned char *base_addr; - int card,channel,chip,index; + unsigned char *base_addr; + int card,channel,chip,index; - card = info->card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<cor3 &= ~CyREC_FIFO; + info->cor3 |= value & CyREC_FIFO; + base_addr[CyCOR3<cor3; + cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); + } else { + // Nothing to do! + } + return 0; +}/* set_threshold */ - info->cor3 &= ~CyREC_FIFO; - info->cor3 |= value & CyREC_FIFO; - base_addr[CyCOR3<cor3; - write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); - return 0; -} static int get_threshold(struct cyclades_port * info, unsigned long *value) { - unsigned char *base_addr; - int card,channel,chip,index; - unsigned long tmp; + unsigned char *base_addr; + int card,channel,chip,index; + unsigned long tmp; - card = info->card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<default_threshold = value & 0x0f; - return 0; -} + info->default_threshold = value & 0x0f; + return 0; +}/* set_default_threshold */ + static int get_default_threshold(struct cyclades_port * info, unsigned long *value) { - put_user(info->default_threshold,value); - return 0; -} + put_fs_long(info->default_threshold,value); + return 0; +}/* get_default_threshold */ + static int set_timeout(struct cyclades_port * info, unsigned long value) { - unsigned char *base_addr; - int card,channel,chip,index; + unsigned char *base_addr; + int card,channel,chip,index; - card = info->card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<card; - channel = info->line - cy_card[card].first_line; - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<default_timeout = value & 0xff; - return 0; -} + info->default_timeout = value & 0xff; + return 0; +}/* set_default_timeout */ + static int get_default_timeout(struct cyclades_port * info, unsigned long *value) { - put_user(info->default_timeout,value); - return 0; -} + put_fs_long(info->default_timeout,value); + return 0; +}/* get_default_timeout */ + +/* + * This routine allows the tty driver to implement device- + * specific ioctl's. If the ioctl number passed in cmd is + * not recognized by the driver, it should return ENOIOCTLCMD. + */ static int cy_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -2170,7 +3439,8 @@ int ret_val = 0; #ifdef SERIAL_DEBUG_OTHER - printk("cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */ + printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", + info->line, cmd, arg); /* */ #endif switch (cmd) { @@ -2182,7 +3452,7 @@ break; } ret_val = get_mon_info(info, (struct cyclades_monitor *)arg); - break; + break; case CYGETTHRESH: error = verify_area(VERIFY_WRITE, (void *) arg ,sizeof(unsigned long)); @@ -2190,11 +3460,11 @@ ret_val = error; break; } - ret_val = get_threshold(info, (unsigned long *)arg); - break; + ret_val = get_threshold(info, (unsigned long *)arg); + break; case CYSETTHRESH: ret_val = set_threshold(info, (unsigned long)arg); - break; + break; case CYGETDEFTHRESH: error = verify_area(VERIFY_WRITE, (void *) arg ,sizeof(unsigned long)); @@ -2202,11 +3472,11 @@ ret_val = error; break; } - ret_val = get_default_threshold(info, (unsigned long *)arg); - break; + ret_val = get_default_threshold(info, (unsigned long *)arg); + break; case CYSETDEFTHRESH: ret_val = set_default_threshold(info, (unsigned long)arg); - break; + break; case CYGETTIMEOUT: error = verify_area(VERIFY_WRITE, (void *) arg ,sizeof(unsigned long)); @@ -2214,11 +3484,11 @@ ret_val = error; break; } - ret_val = get_timeout(info, (unsigned long *)arg); - break; + ret_val = get_timeout(info, (unsigned long *)arg); + break; case CYSETTIMEOUT: ret_val = set_timeout(info, (unsigned long)arg); - break; + break; case CYGETDEFTIMEOUT: error = verify_area(VERIFY_WRITE, (void *) arg ,sizeof(unsigned long)); @@ -2226,23 +3496,23 @@ ret_val = error; break; } - ret_val = get_default_timeout(info, (unsigned long *)arg); - break; + ret_val = get_default_timeout(info, (unsigned long *)arg); + break; case CYSETDEFTIMEOUT: ret_val = set_default_timeout(info, (unsigned long)arg); - break; + break; case TCSBRK: /* SVID version: non-zero arg --> no break */ - ret_val = tty_check_change(tty); - if (ret_val) - return ret_val; + ret_val = tty_check_change(tty); + if (ret_val) + return ret_val; tty_wait_until_sent(tty,0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ break; case TCSBRKP: /* support for POSIX tcsendbreak() */ - ret_val = tty_check_change(tty); - if (ret_val) - return ret_val; + ret_val = tty_check_change(tty); + if (ret_val) + return ret_val; tty_wait_until_sent(tty,0); send_break(info, arg ? arg*(HZ/10) : HZ/4); break; @@ -2254,19 +3524,31 @@ /* The following commands are incompletely implemented!!! */ case TIOCGSOFTCAR: - ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *) arg); - break; + error = verify_area(VERIFY_WRITE, (void *) arg + ,sizeof(unsigned int *)); + if (error){ + ret_val = error; + break; + } + put_fs_long(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg); + break; case TIOCSSOFTCAR: - ret_val = get_user(arg,(unsigned int *) arg); - if (ret_val) - break; + error = verify_area(VERIFY_READ, (void *) arg + ,sizeof(unsigned long *)); + if (error) { + ret_val = error; + break; + } + + arg = get_fs_long((unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); break; case TIOCMGET: error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned int)); + ,sizeof(unsigned int *)); if (error){ ret_val = error; break; @@ -2294,31 +3576,35 @@ (struct serial_struct *) arg); break; default: - ret_val = -ENOIOCTLCMD; + ret_val = -ENOIOCTLCMD; } #ifdef SERIAL_DEBUG_OTHER - printk("cy_ioctl done\n"); + printk(" cyc:cy_ioctl done\n"); #endif return ret_val; } /* cy_ioctl */ - - +/* + * This routine allows the tty driver to be notified when + * device's termios settings have changed. Note that a + * well-designed tty driver should be prepared to accept the case + * where old == NULL, and try to do something rational. + */ static void cy_set_termios(struct tty_struct *tty, struct termios * old_termios) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; #ifdef SERIAL_DEBUG_OTHER - printk("cy_set_termios ttyC%d\n", info->line); + printk("cyc:cy_set_termios ttyC%d\n", info->line); #endif if (tty->termios->c_cflag == old_termios->c_cflag) return; - config_setup(info); + set_line_char(info); if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { @@ -2335,353 +3621,243 @@ } /* cy_set_termios */ +/* + * void (*set_ldisc)(struct tty_struct *tty); + * + * This routine allows the tty driver to be notified when the + * device's termios settings have changed. + * + */ + + +/* This routine is called by the upper-layer tty layer to signal + that incoming characters should be throttled because the input + buffers are close to full. + */ static void -cy_close(struct tty_struct * tty, struct file * filp) +cy_throttle(struct tty_struct * tty) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; + unsigned char *base_addr; + int card,chip,channel,index; -#ifdef SERIAL_DEBUG_OTHER - printk("cy_close ttyC%d\n", info->line); +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("cyc:throttle %s: %d....ttyC%d\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); #endif - if (!info - || serial_paranoia_check(info, tty->device, "cy_close")){ - return; + if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){ + return; } -#ifdef SERIAL_DEBUG_OPEN - printk("cy_close ttyC%d, count = %d\n", info->line, info->count); -#endif - - save_flags(flags); cli(); - /* If the TTY is being hung up, nothing to do */ - if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("cy_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d(%d): decrementing count to %d\n", __LINE__, current->pid, info->count - 1); -#endif - if (--info->count < 0) { -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); -#endif - info->count = 0; + if (I_IXOFF(tty)) { + info->x_char = STOP_CHAR(tty); + /* Should use the "Send Special Character" feature!!! */ } - if (info->count) - { - MOD_DEC_USE_COUNT; + + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<flags |= ASYNC_CLOSING; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; - if (info->flags & ASYNC_CALLOUT_ACTIVE) - info->callout_termios = *tty->termios; - if (info->flags & ASYNC_INITIALIZED) - tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */ - shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - info->event = 0; - info->tty = 0; - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + info->close_delay; - schedule(); - } - wake_up_interruptible(&info->open_wait); + } else { + // Nothing to do! } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| - ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_close done\n"); -#endif - MOD_DEC_USE_COUNT; - restore_flags(flags); return; -} /* cy_close */ - -/* - * cy_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void -cy_hangup(struct tty_struct *tty) -{ - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - -#ifdef SERIAL_DEBUG_OTHER - printk("cy_hangup ttyC%d\n", info->line); /* */ -#endif - - if (serial_paranoia_check(info, tty->device, "cy_hangup")) - return; - - shutdown(info); - info->event = 0; - info->count = 0; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d(%d): setting count to 0\n", __LINE__, current->pid); -#endif - info->tty = 0; - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); - wake_up_interruptible(&info->open_wait); -} /* cy_hangup */ - +} /* cy_throttle */ /* - * ------------------------------------------------------------ - * cy_open() and friends - * ------------------------------------------------------------ + * This routine notifies the tty driver that it should signal + * that characters can now be sent to the tty without fear of + * overrunning the input buffers of the line disciplines. */ - -static int -block_til_ready(struct tty_struct *tty, struct file * filp, - struct cyclades_port *info) +static void +cy_unthrottle(struct tty_struct * tty) { - struct wait_queue wait = { current, NULL }; - struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; - int chip, channel,index; - int retval; - char *base_addr; + unsigned char *base_addr; + int card,chip,channel,index; - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); - if (info->flags & ASYNC_HUP_NOTIFY){ - return -EAGAIN; - }else{ - return -ERESTARTSYS; - } - } +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("cyc:throttle %s: %d....ttyC%d\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); +#endif - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { - if (info->flags & ASYNC_NORMAL_ACTIVE){ - return -EBUSY; - } - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_SESSION_LOCKOUT) && - (info->session != current->session)){ - return -EBUSY; - } - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)){ - return -EBUSY; - } - info->flags |= ASYNC_CALLOUT_ACTIVE; - return 0; + if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){ + return; } - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if (filp->f_flags & O_NONBLOCK) { - if (info->flags & ASYNC_CALLOUT_ACTIVE){ - return -EBUSY; - } - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; + if (I_IXOFF(tty)) { + info->x_char = START_CHAR(tty); + /* Should use the "Send Special Character" feature!!! */ } - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * cy_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttyC%d, count = %d\n", - info->line, info->count);/**/ -#endif - info->count--; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d(%d): decrementing count to %d\n", __LINE__, current->pid, info->count); -#endif - info->blocked_open++; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - chip = channel>>2; - channel &= 0x03; - index = cinfo->bus_index; - base_addr = (char *) (cinfo->base_addr + (cy_chip_offset[chip]<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<flags & ASYNC_CALLOUT_ACTIVE)){ - base_addr[CyCAR<state = TASK_INTERRUPTIBLE; - if (tty_hung_up_p(filp) - || !(info->flags & ASYNC_INITIALIZED) ){ - if (info->flags & ASYNC_HUP_NOTIFY) { - retval = -EAGAIN; - }else{ - retval = -ERESTARTSYS; - } - break; - } save_flags(flags); cli(); base_addr[CyCAR<flags & ASYNC_CALLOUT_ACTIVE) - && !(info->flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (base_addr[CyMSVR1<signal & ~current->blocked) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ -#endif - schedule(); + }else{ + // Nothing to do! } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)){ - info->count++; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d(%d): incrementing count to %d\n", __LINE__, current->pid, info->count); + + return; +} /* cy_unthrottle */ + + +/* cy_start and cy_stop provide software output flow control as a + function of XON/XOFF, software CTS, and other such stuff. +*/ +static void +cy_stop(struct tty_struct *tty) +{ + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned char *base_addr; + int chip,channel,index; + unsigned long flags; + +#ifdef SERIAL_DEBUG_OTHER + printk("cyc:cy_stop ttyC%d\n", info->line); /* */ #endif + + if (serial_paranoia_check(info, tty->device, "cy_stop")) + return; + + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + if (!IS_CYC_Z(*cinfo)) { + index = cinfo->bus_index; + chip = channel>>2; + channel &= 0x03; + base_addr = (unsigned char*) + (cy_card[info->card].base_addr + + (cy_chip_offset[chip]<blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} /* block_til_ready */ -/* - * This routine is called whenever a serial port is opened. It - * performs the serial-specific initialization for the tty structure. - */ -int -cy_open(struct tty_struct *tty, struct file * filp) + return; +} /* cy_stop */ + + +static void +cy_start(struct tty_struct *tty) { - struct cyclades_port *info; - int retval, line; + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned char *base_addr; + int chip,channel,index; + unsigned long flags; - line = MINOR(tty->device) - tty->driver.minor_start; - if ((line < 0) || (NR_PORTS <= line)){ - return -ENODEV; - } - info = &cy_port[line]; - if (info->line < 0){ - return -ENODEV; - } #ifdef SERIAL_DEBUG_OTHER - printk("cy_open ttyC%d\n", info->line); /* */ -#endif - if (serial_paranoia_check(info, tty->device, "cy_open")){ - return -ENODEV; - } -#ifdef SERIAL_DEBUG_OPEN - printk("cy_open ttyC%d, count = %d\n", info->line, info->count);/**/ -#endif - info->count++; -#ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d(%d): incrementing count to %d\n", __LINE__, current->pid, info->count); + printk("cyc:cy_start ttyC%d\n", info->line); /* */ #endif - tty->driver_data = info; - info->tty = tty; - if (!tmp_buf) { - tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); - if (!tmp_buf){ - return -ENOMEM; - } + if (serial_paranoia_check(info, tty->device, "cy_start")) + return; + + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + index = cinfo->bus_index; + if (!IS_CYC_Z(*cinfo)) { + chip = channel>>2; + channel &= 0x03; + base_addr = (unsigned char*) + (cy_card[info->card].base_addr + + (cy_chip_offset[chip]<count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->normal_termios; - else - *tty->termios = info->callout_termios; - } - /* - * Start up serial port - */ - retval = startup(info); - if (retval){ - return retval; - } + return; +} /* cy_start */ - MOD_INC_USE_COUNT; - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("cy_open returning after block_til_ready with %d\n", - retval); +/* + * cy_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void +cy_hangup(struct tty_struct *tty) +{ + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; + +#ifdef SERIAL_DEBUG_OTHER + printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ #endif - return retval; - } - info->session = current->session; - info->pgrp = current->pgrp; + if (serial_paranoia_check(info, tty->device, "cy_hangup")) + return; + + shutdown(info); + info->event = 0; + info->count = 0; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); +#endif + info->tty = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + wake_up_interruptible(&info->open_wait); +} /* cy_hangup */ -#ifdef SERIAL_DEBUG_OPEN - printk("cy_open done\n");/**/ + +static void +cy_flush_buffer(struct tty_struct *tty) +{ + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + +#ifdef SERIAL_DEBUG_IO + printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ #endif - return 0; -} /* cy_open */ + if (serial_paranoia_check(info, tty->device, "cy_flush_buffer")) + return; + save_flags(flags); cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + restore_flags(flags); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} /* cy_flush_buffer */ /* @@ -2692,21 +3868,11 @@ * --------------------------------------------------------------------- */ -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static inline void -show_version(void) -{ - printk("Cyclom driver %s\n",rcsid); -} /* show_version */ -/* initialize chips on card -- return number of valid +/* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ __initfunc(static int -cy_init_card(unsigned char *true_base_addr,int index)) +cyy_init_card(unsigned char *true_base_addr,int index)) { unsigned int chip_number; unsigned char* base_addr; @@ -2716,7 +3882,8 @@ udelay(500L); for(chip_number=0; chip_number= 131328 + cy_isa_address = vremap((unsigned int)cy_isa_address,0x2000); +#endif + cy_isa_nchan = 4 * cyy_init_card(cy_isa_address,0); + if (cy_isa_nchan == 0) { + continue; + } + + /* find out the board's irq by probing */ + cy_isa_irq = do_auto_irq(cy_isa_address); + if (cy_isa_irq == 0) { + printk("Cyclom-Y/ISA found at 0x%x ", + (unsigned int) cy_isa_address); + printk("but the IRQ could not be detected.\n"); + continue; + } + + if((cy_next_channel+cy_isa_nchan) > NR_PORTS) { + printk("Cyclom-Y/ISA found at 0x%x ", + (unsigned int) cy_isa_address); + printk("but no more channels are available.\n"); + return(nboard); + } + /* fill the next cy_card structure available */ + for (j = 0 ; j < NR_CARDS ; j++) { + if (cy_card[j].base_addr == 0) break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/ISA found at 0x%x ", + (unsigned int) cy_isa_address); + printk("but no more cards can be used .\n"); + return(nboard); + } + + /* allocate IRQ */ + if(request_irq(cy_isa_irq, cyy_interrupt, + SA_INTERRUPT, "cyclomY", NULL)) + { + printk("Cyclom-Y/ISA found at 0x%x ", + (unsigned int) cy_isa_address); + printk("but could not allocate IRQ#%d.\n", + cy_isa_irq); + return(nboard); + } + + /* set cy_card */ + cy_card[j].base_addr = (int) cy_isa_address; + cy_card[j].ctl_addr = 0; + cy_card[j].irq = (int) cy_isa_irq; + cy_card[j].bus_index = 0; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_isa_nchan/4; + IRQ_cards[cy_isa_irq] = &cy_card[j]; + nboard++; + + /* print message */ + printk("Cyclom-Y/ISA #%d: 0x%x-0x%x, IRQ%d, ", + j+1, (unsigned int) cy_isa_address, + (unsigned int)(cy_isa_address + 0x1fff), + cy_isa_irq); + printk("%d channels starting from port %d.\n", + cy_isa_nchan, cy_next_channel); + cy_next_channel += cy_isa_nchan; + } + return(nboard); + +} /* cy_detect_isa */ + +/* + * --------------------------------------------------------------------- + * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. + * sets global variables and return the number of PCI boards found. + * --------------------------------------------------------------------- + */ +__initfunc(static int +cy_detect_pci(void)) +{ +#ifdef CONFIG_PCI + unsigned char cyy_bus, cyy_dev_fn, cyy_rev_id; + unsigned long pci_intr_ctrl; + unsigned char cy_pci_irq; + unsigned int cy_pci_addr0, cy_pci_addr1, cy_pci_addr2; + unsigned short i,j,cy_pci_nchan; + unsigned short device_id,dev_index = 0,board_index = 0; + + if(pcibios_present() == 0) { /* PCI bus not present */ + return(0); + } + for (i = 0; i < NR_CARDS; i++) { + /* look for a Cyclades card by vendor and device id */ + while((device_id = cy_pci_dev_id[dev_index]) != 0) { + if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES, + device_id,board_index, + &cyy_bus, &cyy_dev_fn) != 0) + { + dev_index++; /* try next device id */ + board_index = 0; + } else { + board_index++; + break; /* found a board */ + } + } + + /* read PCI configuration area */ + pcibios_read_config_byte(cyy_bus, cyy_dev_fn, + PCI_INTERRUPT_LINE, &cy_pci_irq); + pcibios_read_config_dword(cyy_bus, cyy_dev_fn, + PCI_BASE_ADDRESS_0, &cy_pci_addr0); + pcibios_read_config_dword(cyy_bus, cyy_dev_fn, + PCI_BASE_ADDRESS_1, &cy_pci_addr1); + pcibios_read_config_dword(cyy_bus, cyy_dev_fn, + PCI_BASE_ADDRESS_2, &cy_pci_addr2); + pcibios_read_config_byte(cyy_bus, cyy_dev_fn, + PCI_REVISION_ID, &cyy_rev_id); + if (device_id == 0){ + break; + }else if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) + || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){ +#ifdef CY_PCI_DEBUG + printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", + cyy_bus, cyy_dev_fn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Y/PCI:found winaddr=0x%x ioaddr=0x%x\n", + cy_pci_addr2, cy_pci_addr1); +#endif + cy_pci_addr1 &= 0xfffffffc; + cy_pci_addr2 &= 0xfffffff0; + +#if LINUX_VERSION_CODE < 131328 + if ((ulong)cy_pci_addr2 >= 0x100000) /* above 1M? */ +#endif + cy_pci_addr2 = + (unsigned int) vremap(cy_pci_addr2,CyPCI_Ywin); + +#ifdef CY_PCI_DEBUG + printk("Cyclom-Y/PCI: relocate winaddr=0x%x ioaddr=0x%x\n", + cy_pci_addr2, cy_pci_addr1); +#endif + cy_pci_nchan = 4 * cyy_init_card((unsigned char *) + cy_pci_addr2,1); + if(cy_pci_nchan == 0) { + printk("Cyclom-Y PCI host card with "); + printk("no Serial-Modules at 0x%x.\n", + (unsigned int) cy_pci_addr2); + continue; + } + if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { + printk("Cyclom-Y/PCI found at 0x%x ", + (unsigned int) cy_pci_addr2); + printk("but no channels are available.\n"); + return(i); + } + /* fill the next cy_card structure available */ + for (j = 0 ; j < NR_CARDS ; j++) { + if (cy_card[j].base_addr == 0) break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/PCI found at 0x%x ", + (unsigned int) cy_pci_addr2); + printk("but no more cards can be used.\n"); + return(i); + } + + /* allocate IRQ */ + if(request_irq(cy_pci_irq, cyy_interrupt, + SA_INTERRUPT, "cyclomY", NULL)) + { + printk("Cyclom-Y/PCI found at 0x%x ", + (unsigned int) cy_pci_addr2); + printk("but could not allocate IRQ%d.\n", + cy_pci_irq); + return(i); + } + + /* set cy_card */ + cy_card[j].base_addr = (int) cy_pci_addr2; + cy_card[j].ctl_addr = 0; + cy_card[j].irq = (int) cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_pci_nchan/4; + IRQ_cards[cy_pci_irq] = &cy_card[j]; + + /* enable interrupts in the PCI interface */ + outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68); + pci_intr_ctrl = (unsigned long) + (inw(cy_pci_addr1+0x68) + | inw(cy_pci_addr1+0x6a)<<16); + + /* print message */ + printk("Cyclom-Y/PCI #%d: 0x%x-0x%x, IRQ%d, ", + j+1, cy_pci_addr2, (cy_pci_addr2 + CyPCI_Ywin - 1), + (int)cy_pci_irq); + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + + cy_next_channel += cy_pci_nchan; + }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){ + /* print message */ + printk("Cyclom-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + cyy_bus, cyy_dev_fn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Z/PCI: found winaddr=0x%x ctladdr=0x%x\n", + cy_pci_addr2, cy_pci_addr0); + printk("Cyclom-Z/PCI not supported for low addresses\n"); + break; + }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ +#ifdef CY_PCI_DEBUG + printk("Cyclom-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + cyy_bus, cyy_dev_fn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Z/PCI: found winaddr=0x%x ctladdr=0x%x\n", + cy_pci_addr2, cy_pci_addr0); +#endif + cy_pci_addr2 &= 0xfffffff0; + cy_pci_addr2 = (unsigned int) vremap( + cy_pci_addr2 & PAGE_MASK, + PAGE_ALIGN(CyPCI_Zwin)) + + (cy_pci_addr2 & (PAGE_SIZE-1)); + cy_pci_addr0 &= 0xfffffff0; + cy_pci_addr0 = (unsigned int) vremap( + cy_pci_addr0 & PAGE_MASK, + PAGE_ALIGN(CyPCI_Zctl)) + + (cy_pci_addr0 & (PAGE_SIZE-1)); +#ifdef CY_PCI_DEBUG + printk("Cyclom-Z/PCI: relocate winaddr=0x%x ctladdr=0x%x\n", + cy_pci_addr2, cy_pci_addr0); + ((struct RUNTIME_9060 *)(cy_pci_addr0)) + ->loc_addr_base = WIN_CREG; + PAUSE + printk("Cyclom-Z/PCI: FPGA id %lx, ver %lx\n", + 0xff & ((struct CUSTOM_REG *)(cy_pci_addr2))->fpga_id, + 0xff & ((struct CUSTOM_REG *)(cy_pci_addr2))->fpga_version); + ((struct RUNTIME_9060 *)(cy_pci_addr0)) + ->loc_addr_base = WIN_RAM; +#endif + /* The following clears the firmware id word. This ensures + that the driver will not attempt to talk to the board + until it has been properly initialized. + */ + PAUSE + *(unsigned long *)(cy_pci_addr2+ID_ADDRESS) = 0L; + + /* This must be a Cyclom-8Zo/PCI. The extendable + version will have a different device_id and will + be allocated its maximum number of ports. */ + cy_pci_nchan = 8; + + /* fill the next cy_card structure available */ + for (j = 0 ; j < NR_CARDS ; j++) { + if (cy_card[j].base_addr == 0) break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Z/PCI found at 0x%x ", + (unsigned int) cy_pci_addr2); + printk("but no more cards can be used.\n"); + return(i); + } + + /* allocate IRQ only if board has an IRQ */ + if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) { + if(request_irq(cy_pci_irq,cyz_interrupt, + SA_INTERRUPT,"cyclomZ",NULL)) + { + printk("Could not allocate IRQ%d ", + (unsigned int) cy_pci_addr2); + printk("for Cyclom-Z/PCI at 0x%x.\n", + cy_pci_irq); + return(i); + } + } + + /* set cy_card */ + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int) cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = 1; + IRQ_cards[cy_pci_irq] = &cy_card[j]; + + /* print message */ + /* don't report IRQ if board is no IRQ */ + if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) { + printk("Cyclom-Z/PCI #%d: 0x%x-0x%x, IRQ%d, ", + j+1,cy_pci_addr2, + (cy_pci_addr2 + CyPCI_Zwin - 1), + (int)cy_pci_irq); + }else{ + printk("Cyclom-Z/PCI #%d: 0x%x-0x%x, ", + j+1,cy_pci_addr2, + (cy_pci_addr2 + CyPCI_Zwin - 1)); + } + printk("%d channels starting from port %d.\n", + cy_pci_nchan,cy_next_channel); + cy_next_channel += cy_pci_nchan; + } + } + return(i); +#else + return(0); +#endif /* ifdef CONFIG_PCI */ +} /* cy_detect_pci */ + + +/* + * This routine prints out the appropriate serial driver version number + * and identifies which options were configured into this driver. + */ +static inline void +show_version(void) +{ + char *rcsvers, *rcsdate, *tmp; + rcsvers = strchr(rcsid, ' '); rcsvers++; + tmp = strchr(rcsvers, ' '); *tmp++ = '\0'; + rcsdate = strchr(tmp, ' '); rcsdate++; + tmp = strrchr(rcsdate, ' '); *tmp = '\0'; + printk("Cyclom driver %s %s\n", + rcsvers, rcsdate); + printk("\tbuilt %s %s\n", + __DATE__, __TIME__); +} /* show_version */ + /* The serial driver boot-time initialization code! Hardware I/O ports are mapped to character special devices on a @@ -2783,15 +4307,18 @@ device driver because the Cyclom is more properly a multiplexer, not just an aggregation of serial ports on one card. - If there are more cards with more ports than have been statically - allocated above, a warning is printed and the extra ports are ignored. + If there are more cards with more ports than have been + statically allocated above, a warning is printed and the + extra ports are ignored. */ + __initfunc(int cy_init(void)) { - struct cyclades_port *info; + struct cyclades_port *info; struct cyclades_card *cinfo; - int board,port,i; + int number_z_boards = 0; + int board,port,i; show_version(); @@ -2807,7 +4334,7 @@ cy_serial_driver.subtype = SERIAL_TYPE_NORMAL; cy_serial_driver.init_termios = tty_std_termios; cy_serial_driver.init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; + B9600 | CS8 | CREAD | HUPCL | CLOCAL; cy_serial_driver.flags = TTY_DRIVER_REAL_RAW; cy_serial_driver.refcount = &serial_refcount; cy_serial_driver.table = serial_table; @@ -2839,27 +4366,27 @@ cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT; if (tty_register_driver(&cy_serial_driver)) - panic("Couldn't register Cyclom serial driver\n"); + panic("Couldn't register Cyclom serial driver\n"); if (tty_register_driver(&cy_callout_driver)) - panic("Couldn't register Cyclom callout driver\n"); + panic("Couldn't register Cyclom callout driver\n"); init_bh(CYCLADES_BH, do_cyclades_bh); for (i = 0; i < 16; i++) { - IRQ_cards[i] = 0; + IRQ_cards[i] = 0; } for (i = 0; i < NR_CARDS; i++) { - /* base_addr=0 indicates board not found */ - cy_card[i].base_addr = 0; + /* base_addr=0 indicates board not found */ + cy_card[i].base_addr = 0; } /* the code below is responsible to find the boards. Each different type of board has its own detection routine. If a board is found, the next cy_card structure available is set by the detection - routine. These functions are responsible for checking the availability - of cy_card and cy_port data structures and updating the - cy_next_channel. */ + routine. These functions are responsible for checking the + availability of cy_card and cy_port data structures and updating + the cy_next_channel. */ /* look for isa boards */ cy_isa_nboard = cy_detect_isa(); @@ -2871,289 +4398,195 @@ /* invalidate remaining cy_card structures */ for (i = 0 ; i < NR_CARDS ; i++) { - if (cy_card[i].base_addr == 0) { - cy_card[i].first_line = -1; - } + if (cy_card[i].base_addr == 0) { + cy_card[i].first_line = -1; + cy_card[i].ctl_addr = 0; + cy_card[i].irq = 0; + cy_card[i].bus_index = 0; + cy_card[i].first_line = 0; + cy_card[i].num_chips = 0; + } } /* invalidate remaining cy_port structures */ for (i = cy_next_channel ; i < NR_PORTS ; i++) { - cy_port[i].line = -1; - cy_port[i].magic = -1; + cy_port[i].line = -1; + cy_port[i].magic = -1; } /* initialize per-port data structures for each valid board found */ for (board = 0 ; board < cy_nboard ; board++) { - cinfo = &cy_card[board]; - for (port = cinfo->first_line ; - port < cinfo->first_line + 4*cinfo->num_chips ; - port++) - { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_CIRRUS; - info->card = board; - info->line = port; - info->flags = STD_COM_FLAGS; - info->tty = 0; - info->xmit_fifo_size = 12; - info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = 0x08; /* _very_ small receive threshold */ - info->cor4 = 0; - info->cor5 = 0; - info->tbpr = baud_bpr[13]; /* Tx BPR */ - info->tco = baud_co[13]; /* Tx CO */ - info->rbpr = baud_bpr[13]; /* Rx BPR */ - info->rco = baud_co[13]; /* Rx CO */ - info->close_delay = 0; - info->x_char = 0; - info->event = 0; - info->count = 0; + cinfo = &cy_card[board]; + if (cinfo->num_chips == 1){ /* Cyclom-8Zo/PCI */ + number_z_boards++; + for (port = cinfo->first_line ; + port < cinfo->first_line + 8; + port++) + { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_STARTECH; + info->card = board; + info->line = port; + info->flags = STD_COM_FLAGS; + info->tty = 0; + info->xmit_fifo_size = 0; + info->cor1 = 0; + info->cor2 = 0; + info->cor3 = 0; + info->cor4 = 0; + info->cor5 = 0; + info->tbpr = 0; + info->tco = 0; + info->rbpr = 0; + info->rco = 0; + info->close_delay = 0; + info->x_char = 0; + info->event = 0; + info->count = 0; #ifdef SERIAL_DEBUG_COUNT - printk("cyc: %d: setting count to 0\n", __LINE__); + printk("cyc:cy_init(1) setting Z count to 0\n"); +#endif + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->callout_termios = + cy_callout_driver.init_termios; + info->normal_termios = + cy_serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + /* info->session */ + /* info->pgrp */ + info->read_status_mask = 0; + /* info->timeout */ + /* Bentson's vars */ + info->jiffies[0] = 0; + info->jiffies[1] = 0; + info->jiffies[2] = 0; + info->rflush_count = 0; + } + continue; + }else{ /* Cyclom-Y of some kind*/ + for (port = cinfo->first_line ; + port < cinfo->first_line + 4*cinfo->num_chips ; + port++) + { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_CIRRUS; + info->card = board; + info->line = port; + info->flags = STD_COM_FLAGS; + info->tty = 0; + info->xmit_fifo_size = 12; + info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = 0x08; /* _very_ small rcv threshold */ + info->cor4 = 0; + info->cor5 = 0; + info->tbpr = baud_bpr[13]; /* Tx BPR */ + info->tco = baud_co[13]; /* Tx CO */ + info->rbpr = baud_bpr[13]; /* Rx BPR */ + info->rco = baud_co[13]; /* Rx CO */ + info->close_delay = 0; + info->x_char = 0; + info->event = 0; + info->count = 0; +#ifdef SERIAL_DEBUG_COUNT + printk("cyc:cy_init(2) setting Y count to 0\n"); +#endif + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->callout_termios = + cy_callout_driver.init_termios; + info->normal_termios = + cy_serial_driver.init_termios; + info->open_wait = 0; + info->close_wait = 0; + /* info->session */ + /* info->pgrp */ + info->read_status_mask = + CyTIMEOUT| CySPECHAR| CyBREAK + | CyPARITY| CyFRAME| CyOVERRUN; + /* info->timeout */ + } + } + } + + if ( number_z_boards && !cyz_timeron){ + cyz_timeron++; + cyz_timerlist.expires = jiffies + 1; + add_timer(&cyz_timerlist); +#ifdef CY_PCI_DEBUG + printk("Cyclom-Z polling initialized\n"); #endif - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->callout_termios =cy_callout_driver.init_termios; - info->normal_termios = cy_serial_driver.init_termios; - info->open_wait = 0; - info->close_wait = 0; - /* info->session */ - /* info->pgrp */ - info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK - | CyPARITY| CyFRAME| CyOVERRUN; - /* info->timeout */ - } } + return 0; } /* cy_init */ #ifdef MODULE +/* See linux/drivers/char/riscom.c for ideas on how to + pass additional base addresses to the driver!!! */ int init_module(void) { return(cy_init()); -} +} /* init_module */ void cleanup_module(void) { - unsigned long flags; int i; + unsigned long flags; + + + if (cyz_timeron){ + cyz_timeron = 0; + del_timer(&cyz_timerlist); + } save_flags(flags); cli(); - remove_bh(CYCLADES_BH); + remove_bh(CYCLADES_BH); if (tty_unregister_driver(&cy_callout_driver)) - printk("Couldn't unregister Cyclom callout driver\n"); + printk("Couldn't unregister Cyclom callout driver\n"); if (tty_unregister_driver(&cy_serial_driver)) - printk("Couldn't unregister Cyclom serial driver\n"); + printk("Couldn't unregister Cyclom serial driver\n"); restore_flags(flags); for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr != 0) - { - free_irq(cy_card[i].irq,NULL); - } + if (cy_card[i].base_addr != 0 + && cy_card[i].irq) + { + free_irq(cy_card[i].irq,NULL); + } } -} -#endif - -/* - * --------------------------------------------------------------------- - * cy_detect_isa() - Probe for Cyclom-Y/ISA boards. - * sets global variables and return the number of ISA boards found. - * --------------------------------------------------------------------- - */ -__initfunc(int -cy_detect_isa()) -{ - unsigned int cy_isa_irq,nboard; - unsigned char *cy_isa_address; - unsigned short i,j,cy_isa_nchan; - - nboard = 0; - - /* scan the address table probing for Cyclom-Y/ISA boards */ - for (i = 0 ; i < NR_ISA_ADDRESSES ; i++) { - cy_isa_address = cy_isa_addresses[i]; - if (cy_isa_address == 0x0000) { - return(nboard); - } - - /* probe for CD1400... */ - cy_isa_nchan = 4 * cy_init_card(cy_isa_address,0); - if (cy_isa_nchan == 0) { - continue; - } - - /* find out the board's irq by probing */ - cy_isa_irq = do_auto_irq(cy_isa_address); - if (cy_isa_irq == 0) { - printk("Cyclom-Y/ISA found at 0x%x but the IRQ could not be detected.\n", - (unsigned int) cy_isa_address); - continue; - } - - if((cy_next_channel+cy_isa_nchan) > NR_PORTS) { - printk("Cyclom-Y/ISA found at 0x%x but no more channel structures are available.\n", - (unsigned int) cy_isa_address); - return(nboard); - } - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/ISA found at 0x%x but no more card structures are available.\n", - (unsigned int) cy_isa_address); - return(nboard); - } - - /* allocate IRQ */ - if(request_irq(cy_isa_irq,cy_interrupt,SA_INTERRUPT,"cyclades",NULL)) - { - printk("Cyclom-Y/ISA found at 0x%x but could not allocate interrupt IRQ#%d.\n", - (unsigned int) cy_isa_address,cy_isa_irq); - return(nboard); - } - - /* set cy_card */ - cy_card[j].base_addr = (int) cy_isa_address; - cy_card[j].irq = (int) cy_isa_irq; - cy_card[j].bus_index = 0; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_isa_nchan/4; - IRQ_cards[cy_isa_irq] = &cy_card[j]; - nboard++; - - /* print message */ - printk("Cyclom-Y/ISA #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n", - j+1,(unsigned int) cy_isa_address, - (unsigned int)(cy_isa_address + 0x1fff), - cy_isa_irq,cy_isa_nchan,cy_next_channel); - cy_next_channel += cy_isa_nchan; - } - return(nboard); - -} - -/* - * --------------------------------------------------------------------- - * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. - * sets global variables and return the number of PCI boards found. - * --------------------------------------------------------------------- - */ -__initfunc(int -cy_detect_pci()) +} /* cleanup_module */ +#else +/* called by linux/init/main.c to parse command line options */ +void +cy_setup(char *str, int *ints) { -#ifdef CONFIG_PCI - unsigned char cyy_bus, cyy_dev_fn, cyy_rev_id; - unsigned long pci_intr_ctrl; - unsigned char cy_pci_irq; - unsigned int cy_pci_address, cy_pci_io; - unsigned short i,j,cy_pci_nchan; - unsigned short device_id,dev_index = 0,board_index = 0; - - if(pcibios_present() == 0) { /* PCI bus not present */ - return(0); - } - for (i = 0; i < NR_CARDS; i++) { - /* look for a Cyclom-Y card by vendor and device id */ - while((device_id = cy_pci_dev_id[dev_index]) != 0) { - if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES, - device_id,board_index, - &cyy_bus, &cyy_dev_fn) != 0) - { - dev_index++; /* try next device id */ - board_index = 0; - } else { - board_index++; - break; /* found a board */ - } - } - if (device_id == 0) break; - - /* read PCI configuration area */ - pcibios_read_config_byte(cyy_bus, cyy_dev_fn, - PCI_INTERRUPT_LINE, &cy_pci_irq); - pcibios_read_config_dword(cyy_bus, cyy_dev_fn, - PCI_BASE_ADDRESS_1, &cy_pci_io); - pcibios_read_config_dword(cyy_bus, cyy_dev_fn, - PCI_BASE_ADDRESS_2, &cy_pci_address); - pcibios_read_config_byte(cyy_bus, cyy_dev_fn, - PCI_REVISION_ID, &cyy_rev_id); - cy_pci_address &= 0xfffffff0; - if ((ulong)cy_pci_address >= 0x100000) { /* above 1M? */ - cy_pci_address = - (unsigned int) ioremap(cy_pci_address,0x4000); - } - cy_pci_io &= 0xfffffffc; - cy_pci_nchan = 4 * cy_init_card((unsigned char *) - cy_pci_address,1); - if(cy_pci_nchan == 0) { - printk("Cyclom-Y PCI host card with no Serial-Modules at 0x%x.\n", - (unsigned int) cy_pci_address); - continue; - } - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclom-Y/PCI found at 0x%x but no more channel structures are available.\n", - (unsigned int) cy_pci_address); - return(i); - } -#ifdef CY_PCI_DEBUG - printk("Cyclom-Ye/PCI #%d (bus=0x0%x, pci_id=0x%x, rev_id=%d).\n", - i+1,cyy_bus,cyy_dev_fn,cyy_rev_id); - printk("Cyclom-Ye/PCI: found at 0x%x, IRQ%d, ioaddr = 0x%lx.\n", - cy_pci_address,(int)cy_pci_irq,cy_pci_io); -#endif - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/PCI found at 0x%x but no more card structures are available.\n", - (unsigned int) cy_pci_address); - return(i); - } - - /* allocate IRQ */ - if(request_irq(cy_pci_irq,cy_interrupt,SA_INTERRUPT,"cyclades",NULL)) - { - printk("Cyclom-Y/PCI found at 0x%x but could not allocate interrupt IRQ%d.\n", - (unsigned int) cy_pci_address,cy_pci_irq); - return(i); - } + int i, j; - /* set cy_card */ - cy_card[j].base_addr = (int) cy_pci_address; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_pci_nchan/4; - IRQ_cards[cy_pci_irq] = &cy_card[j]; - - /* enable interrupts in the PCI interface */ - outw(inw(cy_pci_io+0x68)|0x0900,cy_pci_io+0x68); - pci_intr_ctrl = (unsigned long)(inw(cy_pci_io+0x68) | inw(cy_pci_io+0x6a)<<16); - - /* print message */ - printk("Cyclom-Y/PCI #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n", - j+1,(unsigned int) cy_pci_address, - (unsigned int)(cy_pci_address + 0x3fff), - (int)cy_pci_irq,cy_pci_nchan,cy_next_channel); + for (i = 0 ; i < NR_ISA_ADDRS ; i++) { + if (cy_isa_addresses[i] == 0) break; + } + for (j = 1; j <= ints[0]; j++){ + if ( i < NR_ISA_ADDRS ){ + cy_isa_addresses[i++] = (unsigned char *)(ints[j]); + } + } - cy_next_channel += cy_pci_nchan; - } - return(i); -#else - return(0); -#endif /* ifdef CONFIG_PCI */ -} +} /* cy_setup */ +#endif #ifdef CYCLOM_SHOW_STATUS @@ -3181,7 +4614,8 @@ printk(" cy_port\n"); printk(" card line flags = %d %d %x\n", info->card, info->line, info->flags); - printk(" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n", + printk(" *tty read_status_mask timeout xmit_fifo_size ", + printk("= %lx %x %x %x\n", (long)info->tty, info->read_status_mask, info->timeout, info->xmit_fifo_size); printk(" cor1,cor2,cor3,cor4,cor5 = %x %x %x %x %x\n", @@ -3198,59 +4632,60 @@ save_flags(flags); cli(); - base_addr = (unsigned char*) - (cy_card[card].base_addr + (cy_chip_offset[chip]< /* guess what */ #include #include +#include #include #include @@ -529,582 +530,7 @@ static int init_error = 0; -void dsp56k_init(void) -{ - if(!ATARIHW_PRESENT(DSP56K)) { - init_error = 1; - printk("DSP56k driver: Hardware not present\n"); - return; - } - -#ifndef MODULE - if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) { - printk("DSP56k driver: Unable to register driver\n"); - return; - } -#endif /* !MODULE */ - - dsp56k.in_use = 0; - - printk("DSP56k driver installed\n"); -} - -#ifdef MODULE -int init_module(void) -{ - int r; - - init_error = 0; - dsp56k_init(); - if(init_error) - return -EPERM; - - r = register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops); - if(r) { - printk("DSP56k driver: Unable to register driver\n"); - return r; - } - - return 0; -} - -void cleanup_module(void) -{ - unregister_chrdev(DSP56K_MAJOR, "dsp56k"); -} -#endif /* MODULE */ -/* - * The DSP56001 Device Driver, saviour of the Free World(tm) - * - * Authors: Fredrik Noring - * lars brinkhoff - * Tomas Berndtsson - * - * First version May 1996 - * - * History: - * 97-01-29 Tomas Berndtsson, - * Integrated with Linux 2.1.21 kernel sources. - * 97-02-15 Tomas Berndtsson, - * Fixed for kernel 2.1.26 - * - * BUGS: - * Hmm... there must be something here :) - * - * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include /* for kmalloc() and kfree() */ -#include /* for struct wait_queue etc */ -#include -#include -#include -#include /* guess what */ -#include -#include - -#include -#include -#include -#include /* For put_user and get_user */ - -#include - -/* minor devices */ -#define DSP56K_DEV_56001 0 /* The only device so far */ - -#define TIMEOUT 10 /* Host port timeout in number of tries */ -#define MAXIO 2048 /* Maximum number of words before sleep */ -#define DSP56K_MAX_BINARY_LENGTH (3*64*1024) - -#define DSP56K_TX_INT_ON dsp56k_host_interface.icr |= DSP56K_ICR_TREQ -#define DSP56K_RX_INT_ON dsp56k_host_interface.icr |= DSP56K_ICR_RREQ -#define DSP56K_TX_INT_OFF dsp56k_host_interface.icr &= ~DSP56K_ICR_TREQ -#define DSP56K_RX_INT_OFF dsp56k_host_interface.icr &= ~DSP56K_ICR_RREQ - -#define DSP56K_TRANSMIT (dsp56k_host_interface.isr & DSP56K_ISR_TXDE) -#define DSP56K_RECEIVE (dsp56k_host_interface.isr & DSP56K_ISR_RXDF) - -#define max(a,b) ((a) > (b) ? (a) : (b)) -#define min(a,b) ((a) < (b) ? (a) : (b)) - -#define wait_some(n) \ -{ \ - current->state = TASK_INTERRUPTIBLE; \ - current->timeout = jiffies + n; \ - schedule(); \ -} - -#define handshake(count, maxio, timeout, ENABLE, f) \ -{ \ - long i, t, m; \ - while (count > 0) { \ - m = min(count, maxio); \ - for (i = 0; i < m; i++) { \ - for (t = 0; t < timeout && !ENABLE; t++) \ - wait_some(2); \ - if(!ENABLE) \ - return -EIO; \ - f; \ - } \ - count -= m; \ - if (m == maxio) wait_some(2); \ - } \ -} - -#define tx_wait(n) \ -{ \ - int t; \ - for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \ - wait_some(1); \ - if(!DSP56K_TRANSMIT) { \ - return -EIO; \ - } \ -} - -#define rx_wait(n) \ -{ \ - int t; \ - for(t = 0; t < n && !DSP56K_RECEIVE; t++) \ - wait_some(1); \ - if(!DSP56K_RECEIVE) { \ - return -EIO; \ - } \ -} - -/* DSP56001 bootstrap code */ -static char bootstrap[] = { - 0x0c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x60, 0xf4, 0x00, 0x00, 0x00, 0x4f, 0x61, 0xf4, - 0x00, 0x00, 0x7e, 0xa9, 0x06, 0x2e, 0x80, 0x00, 0x00, 0x47, - 0x07, 0xd8, 0x84, 0x07, 0x59, 0x84, 0x08, 0xf4, 0xa8, 0x00, - 0x00, 0x04, 0x08, 0xf4, 0xbf, 0x00, 0x0c, 0x00, 0x00, 0xfe, - 0xb8, 0x0a, 0xf0, 0x80, 0x00, 0x7e, 0xa9, 0x08, 0xf4, 0xa0, - 0x00, 0x00, 0x01, 0x08, 0xf4, 0xbe, 0x00, 0x00, 0x00, 0x0a, - 0xa9, 0x80, 0x00, 0x7e, 0xad, 0x08, 0x4e, 0x2b, 0x44, 0xf4, - 0x00, 0x00, 0x00, 0x03, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x01, - 0x0e, 0xa0, 0x00, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb5, 0x08, - 0x50, 0x2b, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb8, 0x08, 0x46, - 0x2b, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x02, 0x0a, 0xf0, 0xaa, - 0x00, 0x7e, 0xc9, 0x20, 0x00, 0x45, 0x0a, 0xf0, 0xaa, 0x00, - 0x7e, 0xd0, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xc6, 0x0a, 0xa9, - 0x80, 0x00, 0x7e, 0xc4, 0x08, 0x58, 0x6b, 0x0a, 0xf0, 0x80, - 0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xcd, 0x0a, - 0xa9, 0x80, 0x00, 0x7e, 0xcb, 0x08, 0x58, 0xab, 0x0a, 0xf0, - 0x80, 0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xd4, - 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xd2, 0x08, 0x58, 0xeb, 0x0a, - 0xf0, 0x80, 0x00, 0x7e, 0xad}; -static int sizeof_bootstrap = 375; - - -static struct dsp56k_device { - int in_use; - long maxio, timeout; - int tx_wsize, rx_wsize; -} dsp56k; - -static int dsp56k_reset(void) -{ - u_char status; - - /* Power down the DSP */ - sound_ym.rd_data_reg_sel = 14; - status = sound_ym.rd_data_reg_sel & 0xef; - sound_ym.wd_data = status; - sound_ym.wd_data = status | 0x10; - - udelay(10); - - /* Power up the DSP */ - sound_ym.rd_data_reg_sel = 14; - sound_ym.wd_data = sound_ym.rd_data_reg_sel & 0xef; - - return 0; -} - -static int dsp56k_upload(u_char *bin, int len) -{ - int i; - u_char *p; - - dsp56k_reset(); - - p = bootstrap; - for (i = 0; i < sizeof_bootstrap/3; i++) { - /* tx_wait(10); */ - dsp56k_host_interface.data.b[1] = *p++; - dsp56k_host_interface.data.b[2] = *p++; - dsp56k_host_interface.data.b[3] = *p++; - } - for (; i < 512; i++) { - /* tx_wait(10); */ - dsp56k_host_interface.data.b[1] = 0; - dsp56k_host_interface.data.b[2] = 0; - dsp56k_host_interface.data.b[3] = 0; - } - - for (i = 0; i < len; i++) { - tx_wait(10); - get_user(dsp56k_host_interface.data.b[1], bin++); - get_user(dsp56k_host_interface.data.b[2], bin++); - get_user(dsp56k_host_interface.data.b[3], bin++); - } - - tx_wait(10); - dsp56k_host_interface.data.l = 3; /* Magic execute */ - - return 0; -} - -static long dsp56k_read(struct inode *inode, struct file *file, - char *buf, unsigned long count) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - { - - long n; - - /* Don't do anything if nothing is to be done */ - if (!count) return 0; - - n = 0; - switch (dsp56k.rx_wsize) { - case 1: /* 8 bit */ - { - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, - put_user(dsp56k_host_interface.data.b[3], buf+n++)); - return n; - } - case 2: /* 16 bit */ - { - short *data; - - count /= 2; - data = (short*) buf; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, - put_user(dsp56k_host_interface.data.w[1], data+n++)); - return 2*n; - } - case 3: /* 24 bit */ - { - count /= 3; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, - put_user(dsp56k_host_interface.data.b[1], buf+n++); - put_user(dsp56k_host_interface.data.b[2], buf+n++); - put_user(dsp56k_host_interface.data.b[3], buf+n++)); - return 3*n; - } - case 4: /* 32 bit */ - { - long *data; - - count /= 4; - data = (long*) buf; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, - put_user(dsp56k_host_interface.data.l, data+n++)); - return 4*n; - } - } - return -EFAULT; - } - - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return -ENXIO; - } -} - -static long dsp56k_write(struct inode *inode, struct file *file, - const char *buf, unsigned long count) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - { - long n; - - /* Don't do anything if nothing is to be done */ - if (!count) return 0; - - n = 0; - switch (dsp56k.tx_wsize) { - case 1: /* 8 bit */ - { - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, - get_user(dsp56k_host_interface.data.b[3], buf+n++)); - return n; - } - case 2: /* 16 bit */ - { - short *data; - - count /= 2; - data = (short*) buf; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, - get_user(dsp56k_host_interface.data.w[1], data+n++)); - return 2*n; - } - case 3: /* 24 bit */ - { - count /= 3; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, - get_user(dsp56k_host_interface.data.b[1], buf+n++); - get_user(dsp56k_host_interface.data.b[2], buf+n++); - get_user(dsp56k_host_interface.data.b[3], buf+n++)); - return 3*n; - } - case 4: /* 32 bit */ - { - long *data; - - count /= 4; - data = (long*) buf; - handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, - get_user(dsp56k_host_interface.data.l, data+n++)); - return 4*n; - } - } - - return -EFAULT; - } - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return -ENXIO; - } -} - -static int dsp56k_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - - switch(cmd) { - case DSP56K_UPLOAD: - { - char *bin; - int r, len; - struct dsp56k_upload *binary = (struct dsp56k_upload *) arg; - - if(get_user(len, &binary->len) < 0) - return -EFAULT; - if(get_user(bin, &binary->bin) < 0) - return -EFAULT; - - if (len == 0) { - return -EINVAL; /* nothing to upload?!? */ - } - if (len > DSP56K_MAX_BINARY_LENGTH) { - return -EINVAL; - } - - r = dsp56k_upload(bin, len); - if (r < 0) { - return r; - } - - break; - } - case DSP56K_SET_TX_WSIZE: - if (arg > 4 || arg < 1) - return -EINVAL; - dsp56k.tx_wsize = (int) arg; - break; - case DSP56K_SET_RX_WSIZE: - if (arg > 4 || arg < 1) - return -EINVAL; - dsp56k.rx_wsize = (int) arg; - break; - case DSP56K_HOST_FLAGS: - { - int dir, out, status; - struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg; - - if(get_user(dir, &hf->dir) < 0) - return -EFAULT; - if(get_user(out, &hf->out) < 0) - return -EFAULT; - - if ((dir & 0x1) && (out & 0x1)) - dsp56k_host_interface.icr |= DSP56K_ICR_HF0; - else if (dir & 0x1) - dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0; - if ((dir & 0x2) && (out & 0x2)) - dsp56k_host_interface.icr |= DSP56K_ICR_HF1; - else if (dir & 0x2) - dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1; - - status = 0; - if (dsp56k_host_interface.icr & DSP56K_ICR_HF0) status |= 0x1; - if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; - if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; - if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; - - if(put_user(status, &hf->status) < 0) - return -EFAULT; - break; - } - case DSP56K_HOST_CMD: - if (arg > 31 || arg < 0) - return -EINVAL; - dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | - DSP56K_CVR_HC); - break; - default: - return -EINVAL; - } - return 0; - - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return -ENXIO; - } -} - -/* As of 2.1.26 this should be dsp56k_poll, - * but how do I then check device minor number? - * Do I need this function at all??? - */ -#ifdef 0 -static int dsp56k_select(struct inode *inode, struct file *file, int sel_type, - select_table *wait) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - - switch(sel_type) { - case SEL_IN: /* read */ - return 1; - case SEL_OUT: /* write */ - return 1; - default: - return 1; - } - - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return -ENXIO; - } -} -#endif - -static int dsp56k_open(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - - if (dsp56k.in_use) - return -EBUSY; - - dsp56k.in_use = 1; - dsp56k.timeout = TIMEOUT; - dsp56k.maxio = MAXIO; - dsp56k.rx_wsize = dsp56k.tx_wsize = 4; - - DSP56K_TX_INT_OFF; - DSP56K_RX_INT_OFF; - - /* Zero host flags */ - dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0; - dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1; - - break; - - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return -ENXIO; - } - -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif /* MODULE */ - - return 0; -} - -static void dsp56k_release(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch(dev) - { - case DSP56K_DEV_56001: - - dsp56k.in_use = 0; - - break; - default: - printk("DSP56k driver: Unknown minor device: %d\n", dev); - return; - } - -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif /* MODULE */ -} - -static struct file_operations dsp56k_fops = { - NULL, /* no special dsp56k_lseek */ - dsp56k_read, - dsp56k_write, - NULL, /* no special dsp56k_readdir */ - NULL, /* dsp56k_poll? */ - dsp56k_ioctl, - NULL, /* no special dsp56k_mmap */ - dsp56k_open, - dsp56k_release, - NULL, /* no special dsp56k_fsync */ - NULL, /* no special dsp56k_fasync */ - NULL, /* no special dsp56k_check_media_change */ - NULL /* no special dsp56k_revalidate */ -}; - - -/****** Init and module functions ******/ - -static int init_error = 0; - -void dsp56k_init(void) +__initfunc(void dsp56k_init(void)) { if(!ATARIHW_PRESENT(DSP56K)) { init_error = 1; diff -u --recursive --new-file v2.1.36/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.1.36/linux/drivers/char/epca.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/epca.c Tue Apr 29 11:45:43 1997 @@ -0,0 +1,4313 @@ +/* + + + Copyright (C) 1996 Digi International. + + For technical support please email digiLinux@dgii.com or + call Digi tech support at (612) 912-3456 + + Much of this design and code came from epca.c which was + copyright (C) 1994, 1995 Troy De Jongh, and subsquently + modified by David Nugent, Christoph Lameter, Mike McLagan. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +--------------------------------------------------------------------------- */ +/* See README.epca for change history --DAT*/ + + +#ifdef MODVERSIONS +#define MODULE +#endif + +/* ----------------------------------------------------------------------- + This way modules should work regardless if they defined MODULE or + MODVERSIONS. (MODVERSIONS is for the newer kernels ... +-------------------------------------------------------------------------- */ + +#ifdef MODULE +#include +#endif /* MODULE */ + +#include + +#define NEW_MODULES + +#ifdef NEW_MODULES +#ifdef MODVERSIONS +#include +#endif /* MODVERSIONS */ +#endif /* NEW_MODULES */ + +#ifdef MODULE +#include +#endif /* MODULE */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MODULE +#ifndef NEW_MODULES +char kernel_version[]=UTS_RELEASE; +#endif /* NEW_MODULE */ +#endif /* MODULE */ + + +#ifdef CONFIG_PCI +#define ENABLE_PCI +#endif /* CONFIG_PCI */ + + + +#include +#define putUser(arg1, arg2) put_user(arg1, (unsigned long *)arg2) +#define getUser(arg1, arg2) get_user(arg1, (unsigned int *)arg2) + + + +#ifdef ENABLE_PCI +#include +#include +#include +#endif /* ENABLE_PCI */ + +#include +#include +#include +#include + +/* ---------------------- Begin defines ------------------------ */ + +#define VERSION "1.1.0" + +/* This major needs to be submitted to Linux to join the majors list */ + +#define DIGIINFOMAJOR 35 /* For Digi specific ioctl */ + + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAXCARDS 7 +#define epcaassert(x, msg) if (!(x)) epca_error(__LINE__, msg) + +/* ----------------- Begin global definitions ------------------- */ + +static char mesg[100]; +static int pc_refcount, nbdevs = 0, num_cards = 0, liloconfig = 0; +static int digi_poller_inhibited = 1 ; + +static int setup_error_code = 0; +static int invalid_lilo_config = 0; + +/* ----------------------------------------------------------------------- + MAXBOARDS is typically 12, but ISA and EISA cards are restricted to + 7 below. +--------------------------------------------------------------------------*/ +static struct board_info boards[7]; + + +/* ------------- Begin structures used for driver registeration ---------- */ + +struct tty_driver pc_driver; +struct tty_driver pc_callout; +struct tty_driver pc_info; + +/* The below structures are used to initialize the tty_driver structures. */ + +/* ------------------------------------------------------------------------- + Note : MAX_ALLOC is currently limited to 0x100. This restriction is + placed on us by Linux not Digi. +----------------------------------------------------------------------------*/ +static struct tty_struct *pc_table[MAX_ALLOC]; +static struct termios *pc_termios[MAX_ALLOC]; +static struct termios *pc_termios_locked[MAX_ALLOC]; + + +/* ------------------ Begin Digi specific structures -------------------- */ + +/* ------------------------------------------------------------------------ + digi_channels represents an array of structures that keep track of + each channel of the Digi product. Information such as transmit and + receive pointers, termio data, and signal definitions (DTR, CTS, etc ...) + are stored here. This structure is NOT used to overlay the cards + physical channel structure. +-------------------------------------------------------------------------- */ + +static struct channel digi_channels[MAX_ALLOC]; + +/* ------------------------------------------------------------------------ + card_ptr is an array used to hold the address of the + first channel structure of each card. This array will hold + the addresses of various channels located in digi_channels. +-------------------------------------------------------------------------- */ +static struct channel *card_ptr[MAXCARDS]; + +/* ---------------------- Begin function prototypes --------------------- */ + +/* ---------------------------------------------------------------------- + Begin generic memory functions. These functions will be alias + (point at) more specific functions dependant on the board being + configured. +----------------------------------------------------------------------- */ + + +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +#endif /* MODULE */ + +static inline void memwinon(struct board_info *b, unsigned int win); +static inline void memwinoff(struct board_info *b, unsigned int win); +static inline void globalwinon(struct channel *ch); +static inline void rxwinon(struct channel *ch); +static inline void txwinon(struct channel *ch); +static inline void memoff(struct channel *ch); +static inline void assertgwinon(struct channel *ch); +static inline void assertmemoff(struct channel *ch); + +/* ---- Begin more 'specific' memory functions for cx_like products --- */ + +static inline void pcxem_memwinon(struct board_info *b, unsigned int win); +static inline void pcxem_memwinoff(struct board_info *b, unsigned int win); +static inline void pcxem_globalwinon(struct channel *ch); +static inline void pcxem_rxwinon(struct channel *ch); +static inline void pcxem_txwinon(struct channel *ch); +static inline void pcxem_memoff(struct channel *ch); + +/* ------ Begin more 'specific' memory functions for the pcxe ------- */ + +static inline void pcxe_memwinon(struct board_info *b, unsigned int win); +static inline void pcxe_memwinoff(struct board_info *b, unsigned int win); +static inline void pcxe_globalwinon(struct channel *ch); +static inline void pcxe_rxwinon(struct channel *ch); +static inline void pcxe_txwinon(struct channel *ch); +static inline void pcxe_memoff(struct channel *ch); + +/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ +/* Note : pc64xe and pcxi share the same windowing routines */ + +static inline void pcxi_memwinon(struct board_info *b, unsigned int win); +static inline void pcxi_memwinoff(struct board_info *b, unsigned int win); +static inline void pcxi_globalwinon(struct channel *ch); +static inline void pcxi_rxwinon(struct channel *ch); +static inline void pcxi_txwinon(struct channel *ch); +static inline void pcxi_memoff(struct channel *ch); + +/* - Begin 'specific' do nothing memory functions needed for some cards - */ + +static inline void dummy_memwinon(struct board_info *b, unsigned int win); +static inline void dummy_memwinoff(struct board_info *b, unsigned int win); +static inline void dummy_globalwinon(struct channel *ch); +static inline void dummy_rxwinon(struct channel *ch); +static inline void dummy_txwinon(struct channel *ch); +static inline void dummy_memoff(struct channel *ch); +static inline void dummy_assertgwinon(struct channel *ch); +static inline void dummy_assertmemoff(struct channel *ch); + +/* ------------------- Begin declare functions ----------------------- */ + +static inline struct channel *verifyChannel(register struct tty_struct *); +static inline void pc_sched_event(struct channel *, int); +static void epca_error(int, char *); +static void pc_close(struct tty_struct *, struct file *); +static void shutdown(struct channel *); +static void pc_hangup(struct tty_struct *); +static void pc_put_char(struct tty_struct *, unsigned char); +static int pc_write_room(struct tty_struct *); +static int pc_chars_in_buffer(struct tty_struct *); +static void pc_flush_buffer(struct tty_struct *); +static void pc_flush_chars(struct tty_struct *); +static int block_til_ready(struct tty_struct *, struct file *, + struct channel *); +static int pc_open(struct tty_struct *, struct file *); +static void post_fep_init(unsigned int crd); +static void epcapoll(unsigned long); +static void doevent(int); +static void fepcmd(struct channel *, int, int, int, int, int); +static unsigned termios2digi_h(struct channel *ch, unsigned); +static unsigned termios2digi_i(struct channel *ch, unsigned); +static unsigned termios2digi_c(struct channel *ch, unsigned); +static void epcaparam(struct tty_struct *, struct channel *); +static void receive_data(struct channel *); +static int pc_ioctl(struct tty_struct *, struct file *, + unsigned int, unsigned long); +static void pc_set_termios(struct tty_struct *, struct termios *); +static void do_softint(void *); +static void pc_stop(struct tty_struct *); +static void pc_start(struct tty_struct *); +static void pc_throttle(struct tty_struct * tty); +static void pc_unthrottle(struct tty_struct *tty); +static void digi_send_break(struct channel *ch, int msec); +static void setup_empty_event(struct tty_struct *tty, struct channel *ch); +void epca_setup(char *, int *); +void console_print(const char *); + +static int get_termio(struct tty_struct *, struct termio *); +static int pc_write(struct tty_struct *, int, const unsigned char *, int); +int pc_init(void); + +#ifdef ENABLE_PCI +static int init_PCI(int); +static int get_PCI_configuration(char, char, unsigned int *, unsigned int *, + unsigned int *, unsigned int *, + unsigned int *, unsigned int *); +#endif /* ENABLE_PCI */ + + +/* ------------------------------------------------------------------ + Table of functions for each board to handle memory. Mantaining + parallelism is a *very* good idea here. The idea is for the + runtime code to blindly call these functions, not knowing/caring + about the underlying hardware. This stuff should contain no + conditionals; if more functionality is needed a different entry + should be established. These calls are the interface calls and + are the only functions that should be accessed. Anyone caught + making direct calls deserves what they get. +-------------------------------------------------------------------- */ + +static inline void memwinon(struct board_info *b, unsigned int win) +{ + (b->memwinon)(b, win); +} + +static inline void memwinoff(struct board_info *b, unsigned int win) +{ + (b->memwinoff)(b, win); +} + +static inline void globalwinon(struct channel *ch) +{ + (ch->board->globalwinon)(ch); +} + +static inline void rxwinon(struct channel *ch) +{ + (ch->board->rxwinon)(ch); +} + +static inline void txwinon(struct channel *ch) +{ + (ch->board->txwinon)(ch); +} + +static inline void memoff(struct channel *ch) +{ + (ch->board->memoff)(ch); +} +static inline void assertgwinon(struct channel *ch) +{ + (ch->board->assertgwinon)(ch); +} + +static inline void assertmemoff(struct channel *ch) +{ + (ch->board->assertmemoff)(ch); +} + +/* --------------------------------------------------------- + PCXEM windowing is the same as that used in the PCXR + and CX series cards. +------------------------------------------------------------ */ + +static inline void pcxem_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(FEPWIN|win, (int)b->port + 1); +} + +static inline void pcxem_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(0, (int)b->port + 1); +} + +static inline void pcxem_globalwinon(struct channel *ch) +{ + outb_p( FEPWIN, (int)ch->board->port + 1); +} + +static inline void pcxem_rxwinon(struct channel *ch) +{ + outb_p(ch->rxwin, (int)ch->board->port + 1); +} + +static inline void pcxem_txwinon(struct channel *ch) +{ + outb_p(ch->txwin, (int)ch->board->port + 1); +} + +static inline void pcxem_memoff(struct channel *ch) +{ + outb_p(0, (int)ch->board->port + 1); +} + +/* ----------------- Begin pcxe memory window stuff ------------------ */ + +static inline void pcxe_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(FEPWIN | win, (int)b->port + 1); +} + +static inline void pcxe_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(inb((int)b->port) & ~FEPMEM, + (int)b->port + 1); + outb_p(0, (int)b->port + 1); +} + +static inline void pcxe_globalwinon(struct channel *ch) +{ + outb_p( FEPWIN, (int)ch->board->port + 1); +} + +static inline void pcxe_rxwinon(struct channel *ch) +{ + outb_p(ch->rxwin, (int)ch->board->port + 1); +} + +static inline void pcxe_txwinon(struct channel *ch) +{ + outb_p(ch->txwin, (int)ch->board->port + 1); +} + +static inline void pcxe_memoff(struct channel *ch) +{ + outb_p(0, (int)ch->board->port); + outb_p(0, (int)ch->board->port + 1); +} + +/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ + +static inline void pcxi_memwinon(struct board_info *b, unsigned int win) +{ + outb_p(inb((int)b->port) | FEPMEM, (int)b->port); +} + +static inline void pcxi_memwinoff(struct board_info *b, unsigned int win) +{ + outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port); +} + +static inline void pcxi_globalwinon(struct channel *ch) +{ + outb_p(FEPMEM, (int)ch->board->port); +} + +static inline void pcxi_rxwinon(struct channel *ch) +{ + outb_p(FEPMEM, (int)ch->board->port); +} + +static inline void pcxi_txwinon(struct channel *ch) +{ + outb_p(FEPMEM, (int)ch->board->port); +} + +static inline void pcxi_memoff(struct channel *ch) +{ + outb_p(0, (int)ch->board->port); +} + +static inline void pcxi_assertgwinon(struct channel *ch) +{ + epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off"); +} + +static inline void pcxi_assertmemoff(struct channel *ch) +{ + epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on"); +} + + +/* ---------------------------------------------------------------------- + Not all of the cards need specific memory windowing routines. Some + cards (Such as PCI) needs no windowing routines at all. We provide + these do nothing routines so that the same code base can be used. + The driver will ALWAYS call a windowing routine if it thinks it needs + to; regardless of the card. However, dependant on the card the routine + may or may not do anything. +---------------------------------------------------------------------------*/ + +static inline void dummy_memwinon(struct board_info *b, unsigned int win) +{ +} + +static inline void dummy_memwinoff(struct board_info *b, unsigned int win) +{ +} + +static inline void dummy_globalwinon(struct channel *ch) +{ +} + +static inline void dummy_rxwinon(struct channel *ch) +{ +} + +static inline void dummy_txwinon(struct channel *ch) +{ +} + +static inline void dummy_memoff(struct channel *ch) +{ +} + +static inline void dummy_assertgwinon(struct channel *ch) +{ +} + +static inline void dummy_assertmemoff(struct channel *ch) +{ +} + +/* ----------------- Begin verifyChannel function ----------------------- */ +static inline struct channel *verifyChannel(register struct tty_struct *tty) +{ /* Begin verifyChannel */ + + /* -------------------------------------------------------------------- + This routine basically provides a sanity check. It insures that + the channel returned is within the proper range of addresses as + well as properly initialized. If some bogus info gets passed in + through tty->driver_data this should catch it. + --------------------------------------------------------------------- */ + + if (tty) + { /* Begin if tty */ + + register struct channel *ch = (struct channel *)tty->driver_data; + + if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) + { + if (ch->magic == EPCA_MAGIC) + return ch; + } + + } /* End if tty */ + + /* Else return a NULL for invalid */ + return NULL; + +} /* End verifyChannel */ + +/* ------------------ Begin pc_sched_event ------------------------- */ + +static inline void pc_sched_event(struct channel *ch, int event) +{ /* Begin pc_sched_event */ + + + /* ---------------------------------------------------------------------- + We call this to schedule interrupt processing on some event. The + kernel sees our request and calls the related routine in OUR driver. + -------------------------------------------------------------------------*/ + + ch->event |= 1 << event; + queue_task(&ch->tqueue, &tq_scheduler); + + +} /* End pc_sched_event */ + +/* ------------------ Begin epca_error ------------------------- */ + +static void epca_error(int line, char *msg) +{ /* Begin epca_error */ + + printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg); + return; + +} /* End epca_error */ + +/* ------------------ Begin pc_close ------------------------- */ +static void pc_close(struct tty_struct * tty, struct file * filp) +{ /* Begin pc_close */ + + struct channel *ch; + unsigned long flags; + + if (tty->driver.subtype == SERIAL_TYPE_INFO) + { + return; + } + + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if ch != NULL */ + + save_flags(flags); + cli(); + + if (tty_hung_up_p(filp)) + { + restore_flags(flags); + return; + } + + /* Check to see if the channel is open more than once */ + if (ch->count-- > 1) + { /* Begin channel is open more than once */ + + /* ------------------------------------------------------------- + Return without doing anything. Someone might still be using + the channel. + ---------------------------------------------------------------- */ + + restore_flags(flags); + return; + } /* End channel is open more than once */ + + /* Port open only once go ahead with shutdown & reset */ + + if (ch->count < 0) + { + ch->count = 0; + } + + /* --------------------------------------------------------------- + Let the rest of the driver know the channel is being closed. + This becomes important if an open is attempted before close + is finished. + ------------------------------------------------------------------ */ + + ch->asyncflags |= ASYNC_CLOSING; + + /* ------------------------------------------------------------- + Save the termios structure, since this port may have + separate termios for callout and dialin. + --------------------------------------------------------------- */ + + if (ch->asyncflags & ASYNC_NORMAL_ACTIVE) + ch->normal_termios = *tty->termios; + + if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) + ch->callout_termios = *tty->termios; + + tty->closing = 1; + + if (ch->asyncflags & ASYNC_INITIALIZED) + { + /* Setup an event to indicate when the transmit buffer empties */ + setup_empty_event(tty, ch); + tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ + } + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + shutdown(ch); + tty->closing = 0; + ch->event = 0; + ch->tty = NULL; + + if (ch->blocked_open) + { /* Begin if blocked_open */ + + if (ch->close_delay) + { + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + ch->close_delay; + schedule(); + } + + wake_up_interruptible(&ch->open_wait); + + } /* End if blocked_open */ + + ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | + ASYNC_CALLOUT_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&ch->close_wait); + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + restore_flags(flags); + + } /* End if ch != NULL */ + +} /* End pc_close */ + +/* ------------------ Begin shutdown ------------------------- */ + +static void shutdown(struct channel *ch) +{ /* Begin shutdown */ + + unsigned long flags; + struct tty_struct *tty; + volatile struct board_chan *bc; + + if (!(ch->asyncflags & ASYNC_INITIALIZED)) + return; + + save_flags(flags); + cli(); + globalwinon(ch); + + bc = ch->brdchan; + + /* ------------------------------------------------------------------ + In order for an event to be generated on the receipt of data the + idata flag must be set. Since we are shutting down, this is not + necessary clear this flag. + --------------------------------------------------------------------- */ + + if (bc) + bc->idata = 0; + + tty = ch->tty; + + /* ---------------------------------------------------------------- + If we're a modem control device and HUPCL is on, drop RTS & DTR. + ------------------------------------------------------------------ */ + + if (tty->termios->c_cflag & HUPCL) + { + ch->omodem &= ~(ch->m_rts | ch->m_dtr); + fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); + } + + memoff(ch); + + /* ------------------------------------------------------------------ + The channel has officialy been closed. The next time it is opened + it will have to reinitialized. Set a flag to indicate this. + ---------------------------------------------------------------------- */ + + /* Prevent future Digi programmed interrupts from coming active */ + + ch->asyncflags &= ~ASYNC_INITIALIZED; + restore_flags(flags); + +} /* End shutdown */ + +/* ------------------ Begin pc_hangup ------------------------- */ + +static void pc_hangup(struct tty_struct *tty) +{ /* Begin pc_hangup */ + + struct channel *ch; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if ch != NULL */ + + unsigned long flags; + + save_flags(flags); + cli(); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + shutdown(ch); + +#ifdef MODULE + if (ch->count) + MOD_DEC_USE_COUNT; +#endif /* MODULE */ + + + ch->tty = NULL; + ch->event = 0; + ch->count = 0; + restore_flags(flags); + ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | ASYNC_CALLOUT_ACTIVE); + wake_up_interruptible(&ch->open_wait); + + } /* End if ch != NULL */ + +} /* End pc_hangup */ + +/* ------------------ Begin pc_write ------------------------- */ + +static int pc_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int bytesAvailable) +{ /* Begin pc_write */ + + register unsigned int head, tail; + register int dataLen; + register int size; + register int amountCopied; + + + struct channel *ch; + unsigned long flags; + int remain; + volatile struct board_chan *bc; + + + /* ---------------------------------------------------------------- + pc_write is primarily called directly by the kernel routine + tty_write (Though it can also be called by put_char) found in + tty_io.c. pc_write is passed a line discipline buffer where + the data to be written out is stored. The line discipline + implementation itself is done at the kernel level and is not + brought into the driver. + ------------------------------------------------------------------- */ + + /* Stop users from hurting themselves on control minor */ + + if (tty->driver.subtype == SERIAL_TYPE_INFO) + { + return (0) ; + } + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) == NULL) + return 0; + + /* Make a pointer to the channel data structure found on the board. */ + + bc = ch->brdchan; + size = ch->txbufsize; + + if (from_user) + { /* Begin from_user */ + + save_flags(flags); + cli(); + + globalwinon(ch); + + /* ----------------------------------------------------------------- + Anding against size will wrap the pointer back to its begining + position if it is necessary. This will only work if size is + a power of 2 which should always be the case. Size is determined + by the cards on board FEP/OS. + -------------------------------------------------------------------- */ + + /* head refers to the next empty location in which data may be stored */ + + head = bc->tin & (size - 1); + + /* tail refers to the next data byte to be transmitted */ + + tail = bc->tout; + + /* Consider changing this to a do statement to make sure */ + + if (tail != bc->tout) + tail = bc->tout; + + /* ------------------------------------------------------------------ + Anding against size will wrap the pointer back to its begining + position if it is necessary. This will only work if size is + a power of 2 which should always be the case. Size is determined + by the cards on board FEP/OS. + --------------------------------------------------------------------- */ + + tail &= (size - 1); + + /* ----------------------------------------------------------------- + Two situations can affect how space in the transmit buffer + is calculated. You can have a situation where the transmit + in pointer (tin) head has wrapped around and actually has a + lower address than the transmit out pointer (tout) tail; or + the transmit in pointer (tin) head will not be wrapped around + yet, and have a higher address than the transmit out pointer + (tout) tail. Obviously space available in the transmit buffer + is calculated differently for each case. + + Example 1: + + Consider a 10 byte buffer where head is a pointer to the next + empty location in the buffer and tail is a pointer to the next + byte to transmit. In this example head will not have wrapped + around and therefore head > tail. + + 0 1 2 3 4 5 6 7 8 9 + tail head + + The above diagram shows that buffer locations 2,3,4,5 and 6 have + data to be transmited, while head points at the next empty + location. To calculate how much space is available first we have + to determine if the head pointer (tin) has wrapped. To do this + compare the head pointer to the tail pointer, If head is equal + or greater than tail; then it has not wrapped; and the space may + be calculated by subtracting tail from head and then subtracting + that value from the buffers size. A one is subtracted from the + new value to indicate how much space is available between the + head pointer and end of buffer; as well as the space between the + begining of the buffer and the tail. If the head is not greater + or equal to the tail this indicates that the head has wrapped + around to the begining of the buffer. To calculate the space + available in this case simply subtract head from tail. This new + value minus one represents the space available betwwen the head + and tail pointers. In this example head (7) is greater than tail (2) + and therefore has not wrapped around. We find the space by first + subtracting tail from head (7-2=5). We then subtract this value + from the buffer size of ten and subtract one (10-5-1=4). The space + remaining is 4 bytes. + + Example 2: + + Consider a 10 byte buffer where head is a pointer to the next + empty location in the buffer and tail is a pointer to the next + byte to transmit. In this example head will wrapped around and + therefore head < tail. + + 0 1 2 3 4 5 6 7 8 9 + head tail + + The above diagram shows that buffer locations 7,8,9,0 and 1 have + data to be transmited, while head points at the next empty + location. To find the space available we compare head to tail. If + head is not equal to, or greater than tail this indicates that head + has wrapped around. In this case head (2) is not equal to, or + greater than tail (7) and therefore has already wrapped around. To + calculate the available space between the two pointers we subtract + head from tail (7-2=5). We then subtract one from this new value + (5-1=4). We have 5 bytes empty remaining in the buffer. Unlike the + previous example these five bytes are located between the head and + tail pointers. + + ----------------------------------------------------------------------- */ + + dataLen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1); + + /* ---------------------------------------------------------------------- + In this case bytesAvailable has been passed into pc_write and + represents the amount of data that needs to be written. dataLen + represents the amount of space available on the card. Whichever + value is smaller will be the amount actually written. + bytesAvailable will then take on this newly calculated value. + ---------------------------------------------------------------------- */ + + bytesAvailable = MIN(dataLen, bytesAvailable); + + /* First we read the data in from the file system into a temp buffer */ + + if (bytesAvailable) + { /* Begin bytesAvailable */ + + /* Can the user buffer be accessed at the moment ? */ + if (verify_area(VERIFY_READ, (char*)buf, bytesAvailable)) + bytesAvailable = 0; /* Can't do; try again later */ + else /* Evidently it can, began transmission */ + { /* Begin if area verified */ + /* --------------------------------------------------------------- + The below function reads data from user memory. This routine + can not be used in an interrupt routine. (Because it may + generate a page fault) It can only be called while we can the + user context is accessible. + + The prototype is : + inline void copy_from_user(void * to, const void * from, + unsigned long count); + + You must include + I also think (Check hackers guide) that optimization must + be turned ON. (Which sounds strange to me...) + + Remember copy_from_user WILL generate a page fault if the + user memory being accessed has been swapped out. This can + cause this routine to temporarily sleep while this page + fault is occuring. + + ----------------------------------------------------------------- */ + + copy_from_user(ch->tmp_buf, buf, bytesAvailable); + + } /* End if area verified */ + + } /* End bytesAvailable */ + + /* ------------------------------------------------------------------ + Set buf to this address for the moment. tmp_buf was allocated in + post_fep_init. + --------------------------------------------------------------------- */ + buf = ch->tmp_buf; + memoff(ch); + restore_flags(flags); + + } /* End from_user */ + + /* All data is now local */ + + amountCopied = 0; + save_flags(flags); + cli(); + + globalwinon(ch); + + head = bc->tin & (size - 1); + tail = bc->tout; + + if (tail != bc->tout) + tail = bc->tout; + tail &= (size - 1); + + /* If head >= tail, head has not wrapped around. */ + if (head >= tail) + { /* Begin head has not wrapped */ + + /* --------------------------------------------------------------- + remain (much like dataLen above) represents the total amount of + space available on the card for data. Here dataLen represents + the space existing between the head pointer and the end of + buffer. This is important because a memcpy cannot be told to + automatically wrap around when it hits the buffer end. + ------------------------------------------------------------------ */ + + dataLen = size - head; + remain = size - (head - tail) - 1; + + } /* End head has not wrapped */ + else + { /* Begin head has wrapped around */ + + remain = tail - head - 1; + dataLen = remain; + + } /* End head has wrapped around */ + + /* ------------------------------------------------------------------- + Check the space on the card. If we have more data than + space; reduce the amount of data to fit the space. + ---------------------------------------------------------------------- */ + + bytesAvailable = MIN(remain, bytesAvailable); + + txwinon(ch); + while (bytesAvailable > 0) + { /* Begin while there is data to copy onto card */ + + /* ----------------------------------------------------------------- + If head is not wrapped, the below will make sure the first + data copy fills to the end of card buffer. + ------------------------------------------------------------------- */ + + dataLen = MIN(bytesAvailable, dataLen); + memcpy(ch->txptr + head, buf, dataLen); + buf += dataLen; + head += dataLen; + amountCopied += dataLen; + bytesAvailable -= dataLen; + + if (head >= size) + { + head = 0; + dataLen = tail; + } + + } /* End while there is data to copy onto card */ + + ch->statusflags |= TXBUSY; + globalwinon(ch); + bc->tin = head; + + if ((ch->statusflags & LOWWAIT) == 0) + { + ch->statusflags |= LOWWAIT; + bc->ilow = 1; + } + memoff(ch); + restore_flags(flags); + + return(amountCopied); + +} /* End pc_write */ + +/* ------------------ Begin pc_put_char ------------------------- */ + +static void pc_put_char(struct tty_struct *tty, unsigned char c) +{ /* Begin pc_put_char */ + + + pc_write(tty, 0, &c, 1); + return; + +} /* End pc_put_char */ + +/* ------------------ Begin pc_write_room ------------------------- */ + +static int pc_write_room(struct tty_struct *tty) +{ /* Begin pc_write_room */ + + int remain; + struct channel *ch; + unsigned long flags; + unsigned int head, tail; + volatile struct board_chan *bc; + + remain = 0; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { + save_flags(flags); + cli(); + globalwinon(ch); + + bc = ch->brdchan; + head = bc->tin & (ch->txbufsize - 1); + tail = bc->tout; + + if (tail != bc->tout) + tail = bc->tout; + /* Wrap tail if necessary */ + tail &= (ch->txbufsize - 1); + + if ((remain = tail - head - 1) < 0 ) + remain += ch->txbufsize; + + if (remain && (ch->statusflags & LOWWAIT) == 0) + { + ch->statusflags |= LOWWAIT; + bc->ilow = 1; + } + memoff(ch); + restore_flags(flags); + } + + /* Return how much room is left on card */ + return remain; + +} /* End pc_write_room */ + +/* ------------------ Begin pc_chars_in_buffer ---------------------- */ + +static int pc_chars_in_buffer(struct tty_struct *tty) +{ /* Begin pc_chars_in_buffer */ + + int chars; + unsigned int ctail, head, tail; + int remain; + unsigned long flags; + struct channel *ch; + volatile struct board_chan *bc; + + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) == NULL) + return(0); + + save_flags(flags); + cli(); + globalwinon(ch); + + bc = ch->brdchan; + tail = bc->tout; + head = bc->tin; + ctail = ch->mailbox->cout; + + if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0) + chars = 0; + else + { /* Begin if some space on the card has been used */ + + head = bc->tin & (ch->txbufsize - 1); + tail &= (ch->txbufsize - 1); + + /* -------------------------------------------------------------- + The logic here is basically opposite of the above pc_write_room + here we are finding the amount of bytes in the buffer filled. + Not the amount of bytes empty. + ------------------------------------------------------------------- */ + + if ((remain = tail - head - 1) < 0 ) + remain += ch->txbufsize; + + chars = (int)(ch->txbufsize - remain); + + /* ------------------------------------------------------------- + Make it possible to wakeup anything waiting for output + in tty_ioctl.c, etc. + + If not already set. Setup an event to indicate when the + transmit buffer empties + ----------------------------------------------------------------- */ + + if (!(ch->statusflags & EMPTYWAIT)) + setup_empty_event(tty,ch); + + } /* End if some space on the card has been used */ + + memoff(ch); + restore_flags(flags); + + /* Return number of characters residing on card. */ + return(chars); + +} /* End pc_chars_in_buffer */ + +/* ------------------ Begin pc_flush_buffer ---------------------- */ + +static void pc_flush_buffer(struct tty_struct *tty) +{ /* Begin pc_flush_buffer */ + + unsigned int tail; + unsigned long flags; + struct channel *ch; + volatile struct board_chan *bc; + + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) == NULL) + return; + + save_flags(flags); + cli(); + + globalwinon(ch); + + bc = ch->brdchan; + tail = bc->tout; + + /* Have FEP move tout pointer; effectively flushing transmit buffer */ + + fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); + + memoff(ch); + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + +} /* End pc_flush_buffer */ + +/* ------------------ Begin pc_flush_chars ---------------------- */ + +static void pc_flush_chars(struct tty_struct *tty) +{ /* Begin pc_flush_chars */ + + struct channel * ch; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { + unsigned long flags; + + save_flags(flags); + cli(); + + /* ---------------------------------------------------------------- + If not already set and the transmitter is busy setup an event + to indicate when the transmit empties. + ------------------------------------------------------------------- */ + + if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) + setup_empty_event(tty,ch); + + restore_flags(flags); + } + +} /* End pc_flush_chars */ + +/* ------------------ Begin block_til_ready ---------------------- */ + +static int block_til_ready(struct tty_struct *tty, + struct file *filp, struct channel *ch) +{ /* Begin block_til_ready */ + + struct wait_queue wait = {current, NULL}; + int retval, do_clocal = 0; + unsigned long flags; + + + if (tty_hung_up_p(filp)) + { + if (ch->asyncflags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + return(retval); + } + + /* ----------------------------------------------------------------- + If the device is in the middle of being closed, then block + until it's done, and then try again. + -------------------------------------------------------------------- */ + if (ch->asyncflags & ASYNC_CLOSING) + { + interruptible_sleep_on(&ch->close_wait); + + if (ch->asyncflags & ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; + } + + /* ----------------------------------------------------------------- + If this is a callout device, then just make sure the normal + device isn't being used. + -------------------------------------------------------------------- */ + + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) + { /* A cud device has been opened */ + if (ch->asyncflags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + + if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && + (ch->asyncflags & ASYNC_SESSION_LOCKOUT) && + (ch->session != current->session)) + return -EBUSY; + + if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && + (ch->asyncflags & ASYNC_PGRP_LOCKOUT) && + (ch->pgrp != current->pgrp)) + return -EBUSY; + + ch->asyncflags |= ASYNC_CALLOUT_ACTIVE; + + return 0; + } /* End a cud device has been opened */ + + if (filp->f_flags & O_NONBLOCK) + { + /* ----------------------------------------------------------------- + If non-blocking mode is set, then make the check up front + and then exit. + -------------------------------------------------------------------- */ + + if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + + ch->asyncflags |= ASYNC_NORMAL_ACTIVE; + + return 0; + } + + + if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) + { + if (ch->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } + else + { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* Block waiting for the carrier detect and the line to become free */ + + retval = 0; + add_wait_queue(&ch->open_wait, &wait); + save_flags(flags); + cli(); + + + /* We dec count so that pc_close will know when to free things */ + if (!tty_hung_up_p(filp)) + ch->count--; + + restore_flags(flags); + + ch->blocked_open++; + + while(1) + { /* Begin forever while */ + + current->state = TASK_INTERRUPTIBLE; + + if (tty_hung_up_p(filp) || + !(ch->asyncflags & ASYNC_INITIALIZED)) + { + if (ch->asyncflags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + + if (!(ch->asyncflags & ASYNC_CLOSING) && + !(ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && + (do_clocal || (ch->imodem & ch->dcd))) + break; + + if (current->signal & ~current->blocked) + { + retval = -ERESTARTSYS; + break; + } + + /* --------------------------------------------------------------- + Allow someone else to be scheduled. We will occasionaly go + through this loop until one of the above conditions change. + The below schedule call will allow other processes to enter and + prevent this loop from hogging the cpu. + ------------------------------------------------------------------ */ + schedule(); + + } /* End forever while */ + + current->state = TASK_RUNNING; + remove_wait_queue(&ch->open_wait, &wait); + cli(); + if (!tty_hung_up_p(filp)) + ch->count++; + restore_flags(flags); + + ch->blocked_open--; + + if (retval) + return retval; + + ch->asyncflags |= ASYNC_NORMAL_ACTIVE; + + return 0; + +} /* End block_til_ready */ + +/* ------------------ Begin pc_open ---------------------- */ + +static int pc_open(struct tty_struct *tty, struct file * filp) +{ /* Begin pc_open */ + + struct channel *ch; + unsigned long flags; + int line, retval, boardnum; + volatile struct board_chan *bc; + volatile unsigned int head; + + /* Nothing "real" happens in open of control device */ + + if (tty->driver.subtype == SERIAL_TYPE_INFO) + { + return (0) ; + } + + line = MINOR(tty->device) - tty->driver.minor_start; + if (line < 0 || line >= nbdevs) + { + printk(KERN_ERR " - pc_open : line out of range in pc_open\n"); + tty->driver_data = NULL; + return(-ENODEV); + } + +#ifdef MODULE + + MOD_INC_USE_COUNT; + +#endif + + ch = &digi_channels[line]; + boardnum = ch->boardnum; + + /* Check status of board configured in system. */ + + /* ----------------------------------------------------------------- + I check to see if the epca_setup routine detected an user error. + It might be better to put this in pc_init, but for the moment it + goes here. + ---------------------------------------------------------------------- */ + + if (invalid_lilo_config) + { + if (setup_error_code & INVALID_BOARD_TYPE) + printk(KERN_ERR " - pc_open: Invalid board type specified in LILO command\n"); + + if (setup_error_code & INVALID_NUM_PORTS) + printk(KERN_ERR " - pc_open: Invalid number of ports specified in LILO command\n"); + + if (setup_error_code & INVALID_MEM_BASE) + printk(KERN_ERR " - pc_open: Invalid board memory address specified in LILO command\n"); + + if (setup_error_code & INVALID_PORT_BASE) + printk(KERN_ERR " - pc_open: Invalid board port address specified in LILO command\n"); + + if (setup_error_code & INVALID_BOARD_STATUS) + printk(KERN_ERR " - pc_open: Invalid board status specified in LILO command\n"); + + if (setup_error_code & INVALID_ALTPIN) + printk(KERN_ERR " - pc_open: Invalid board altpin specified in LILO command\n"); + + tty->driver_data = NULL; /* Mark this device as 'down' */ + return(-ENODEV); + } + + if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED)) + { + tty->driver_data = NULL; /* Mark this device as 'down' */ + return(-ENODEV); + } + + if (( bc = ch->brdchan) == 0) + { + tty->driver_data = NULL; + return(-ENODEV); + } + + /* ------------------------------------------------------------------ + Every time a channel is opened, increment a counter. This is + necessary because we do not wish to flush and shutdown the channel + until the last app holding the channel open, closes it. + --------------------------------------------------------------------- */ + + ch->count++; + + /* ---------------------------------------------------------------- + Set a kernel structures pointer to our local channel + structure. This way we can get to it when passed only + a tty struct. + ------------------------------------------------------------------ */ + + tty->driver_data = ch; + + /* ---------------------------------------------------------------- + If this is the first time the channel has been opened, initialize + the tty->termios struct otherwise let pc_close handle it. + -------------------------------------------------------------------- */ + + /* Should this be here except for SPLIT termios ? */ + if (ch->count == 1) + { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = ch->normal_termios; + else + *tty->termios = ch->callout_termios; + } + + ch->session = current->session; + ch->pgrp = current->pgrp; + + save_flags(flags); + cli(); + + globalwinon(ch); + ch->statusflags = 0; + + /* Save boards current modem status */ + ch->imodem = bc->mstat; + + /* ---------------------------------------------------------------- + Set receive head and tail ptrs to each other. This indicates + no data available to read. + ----------------------------------------------------------------- */ + head = bc->rin; + bc->rout = head; + + /* Set the channels associated tty structure */ + ch->tty = tty; + + /* ----------------------------------------------------------------- + The below routine generally sets up parity, baud, flow control + issues, etc.... It effect both control flags and input flags. + -------------------------------------------------------------------- */ + epcaparam(tty,ch); + + ch->asyncflags |= ASYNC_INITIALIZED; + memoff(ch); + + restore_flags(flags); + + retval = block_til_ready(tty, filp, ch); + if (retval) + { + return retval; + } + + /* ------------------------------------------------------------- + Set this again in case a hangup set it to zero while this + open() was waiting for the line... + --------------------------------------------------------------- */ + ch->tty = tty; + + save_flags(flags); + cli(); + globalwinon(ch); + + /* Enable Digi Data events */ + bc->idata = 1; + + memoff(ch); + restore_flags(flags); + + return 0; + +} /* End pc_open */ + +#ifdef MODULE +/* -------------------- Begin init_module ---------------------- */ +int init_module() +{ /* Begin init_module */ + + unsigned long flags; + + save_flags(flags); + cli(); + + pc_init(); + + restore_flags(flags); + + return(0); +} /* End init_module */ + +#endif +#ifdef MODULE +/* -------------------- Begin cleanup_module ---------------------- */ +void cleanup_module() +{ /* Begin cleanup_module */ + + int count, crd; + struct board_info *bd; + struct channel *ch; + unsigned long flags; + + + save_flags(flags); + cli(); + + timer_table[DIGI_TIMER].fn = 0; + + if ((tty_unregister_driver(&pc_driver)) || + (tty_unregister_driver(&pc_callout))) + { + printk(KERN_WARNING " - DIGI : cleanup_module failed to un-register tty driver\n"); + restore_flags(flags); + return; + } + + for (crd = 0; crd < num_cards; crd++) + { /* Begin for each card */ + + bd = &boards[crd]; + + if (!bd) + { /* Begin sanity check */ + printk(KERN_ERR " - Digi : cleanup_module failed\n"); + return; + } /* End sanity check */ + + ch = card_ptr[crd]; + + for (count = 0; count < bd->numports; count++, ch++) + { /* Begin for each port */ + + if (ch) + { + if (ch->tty) + tty_hangup(ch->tty); + kfree_s(ch->tmp_buf, ch->txbufsize); + } + + } /* End for each port */ + } /* End for each card */ + + + restore_flags(flags); + +} /* End cleanup_module */ +#endif /* MODULE */ + +/* ------------------ Begin pc_init ---------------------- */ + +int pc_init(void) +{ /* Begin pc_init */ + + /* ---------------------------------------------------------------- + pc_init is called by the operating system during boot up prior to + any open calls being made. In the older versions of Linux (Prior + to 2.0.0) an entry is made into tty_io.c. A pointer to the last + memory location (from kernel space) used (kmem_start) is passed + to pc_init. It is pc_inits responsibility to modify this value + for any memory that the Digi driver might need and then return + this value to the operating system. For example if the driver + wishes to allocate 1K of kernel memory, pc_init would return + (kmem_start + 1024). This memory (Between kmem_start and kmem_start + + 1024) would then be available for use exclusively by the driver. + In this case our driver does not allocate any of this kernel + memory. + ------------------------------------------------------------------*/ + + ulong flags, save_loops_per_sec; + int crd; + struct board_info *bd; + unsigned char board_id = 0; + + +#ifdef ENABLE_PCI + int pci_boards_found, pci_count; + + pci_count = 0; +#endif /* ENABLE_PCI */ + + /* ----------------------------------------------------------------------- + If epca_setup has not been ran by LILO set num_cards to defaults; copy + board structure defined by digiConfig into drivers board structure. + Note : If LILO has ran epca_setup then epca_setup will handle defining + num_cards as well as copying the data into the board structure. + -------------------------------------------------------------------------- */ + if (!liloconfig) + { /* Begin driver has been configured via. epcaconfig */ + + nbdevs = NBDEVS; + num_cards = NUMCARDS; + memcpy((void *)&boards, (void *)&static_boards, + (sizeof(struct board_info) * NUMCARDS)); + } /* End driver has been configured via. epcaconfig */ + + /* ----------------------------------------------------------------- + Note : If lilo was used to configure the driver and the + ignore epcaconfig option was choosen (digiepca=2) then + nbdevs and num_cards will equal 0 at this point. This is + okay; PCI cards will still be picked up if detected. + --------------------------------------------------------------------- */ + + /* ----------------------------------------------------------- + Set up interrupt, we will worry about memory allocation in + post_fep_init. + --------------------------------------------------------------- */ + + + printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION); + +#ifdef ENABLE_PCI + + /* ------------------------------------------------------------------ + NOTE : This code assumes that the number of ports found in + the boards array is correct. This could be wrong if + the card in question is PCI (And therefore has no ports + entry in the boards structure.) The rest of the + information will be valid for PCI because the begining + of pc_init scans for PCI and determines i/o and base + memory addresses. I am not sure if it is possible to + read the number of ports supported by the card prior to + it being booted (Since that is the state it is in when + pc_init is run). Because it is not possible to query the + number of supported ports until after the card has booted; + we are required to calculate the card_ptrs as the card is + is initialized (Inside post_fep_init). The negative thing + about this approach is that digiDload's call to GET_INFO + will have a bad port value. (Since this is called prior + to post_fep_init.) + + --------------------------------------------------------------------- */ + + pci_boards_found = 0; + if (pcibios_present()) + { + if(num_cards < MAXBOARDS) + pci_boards_found += init_PCI(num_cards); + num_cards += pci_boards_found; + } + else + { + printk(KERN_ERR " - No PCI BIOS found\n"); + } + +#endif /* ENABLE_PCI */ + + memset(&pc_driver, 0, sizeof(struct tty_driver)); + memset(&pc_callout, 0, sizeof(struct tty_driver)); + memset(&pc_info, 0, sizeof(struct tty_driver)); + + pc_driver.magic = TTY_DRIVER_MAGIC; + pc_driver.name = "ttyD"; + pc_driver.major = DIGI_MAJOR; + pc_driver.minor_start = 0; + pc_driver.num = MAX_ALLOC; + pc_driver.type = TTY_DRIVER_TYPE_SERIAL; + pc_driver.subtype = SERIAL_TYPE_NORMAL; + pc_driver.init_termios = tty_std_termios; + pc_driver.init_termios.c_iflag = 0; + pc_driver.init_termios.c_oflag = 0; + + pc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + pc_driver.init_termios.c_lflag = 0; + pc_driver.flags = TTY_DRIVER_REAL_RAW; + pc_driver.refcount = &pc_refcount; + pc_driver.table = pc_table; + + /* pc_termios is an array of pointers pointing at termios structs */ + /* The below should get the first pointer */ + pc_driver.termios = pc_termios; + pc_driver.termios_locked = pc_termios_locked; + + /* ------------------------------------------------------------------ + Setup entry points for the driver. These are primarily called by + the kernel in tty_io.c and n_tty.c + --------------------------------------------------------------------- */ + + pc_driver.open = pc_open; + pc_driver.close = pc_close; + pc_driver.write = pc_write; + pc_driver.write_room = pc_write_room; + pc_driver.flush_buffer = pc_flush_buffer; + pc_driver.chars_in_buffer = pc_chars_in_buffer; + pc_driver.flush_chars = pc_flush_chars; + pc_driver.put_char = pc_put_char; + pc_driver.ioctl = pc_ioctl; + pc_driver.set_termios = pc_set_termios; + pc_driver.stop = pc_stop; + pc_driver.start = pc_start; + pc_driver.throttle = pc_throttle; + pc_driver.unthrottle = pc_unthrottle; + pc_driver.hangup = pc_hangup; + pc_callout = pc_driver; + + pc_callout.name = "cud"; + pc_callout.major = DIGICU_MAJOR; + pc_callout.minor_start = 0; + pc_callout.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; + pc_callout.subtype = SERIAL_TYPE_CALLOUT; + + pc_info = pc_driver; + pc_info.name = "digiCtl"; + pc_info.major = DIGIINFOMAJOR; + pc_info.minor_start = 0; + pc_info.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + pc_info.subtype = SERIAL_TYPE_INFO; + + + /* --------------------------------------------------------------------- + loops_per_sec hasn't been set at this point :-(, so fake it out... + I set it, so that I can use the __delay() function. + ------------------------------------------------------------------------ */ + save_loops_per_sec = loops_per_sec; + loops_per_sec = 13L * 500000L; + + save_flags(flags); + cli(); + + for (crd = 0; crd < num_cards; crd++) + { /* Begin for each card */ + + /* ------------------------------------------------------------------ + This is where the appropriate memory handlers for the hardware is + set. Everything at runtime blindly jumps through these vectors. + ---------------------------------------------------------------------- */ + + /* defined in epcaconfig.h */ + bd = &boards[crd]; + + switch (bd->type) + { /* Begin switch on bd->type {board type} */ + case PCXEM: + case EISAXEM: + bd->memwinon = pcxem_memwinon ; + bd->memwinoff = pcxem_memwinoff ; + bd->globalwinon = pcxem_globalwinon ; + bd->txwinon = pcxem_txwinon ; + bd->rxwinon = pcxem_rxwinon ; + bd->memoff = pcxem_memoff ; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCIXEM: + case PCIXRJ: + case PCIXR: + bd->memwinon = dummy_memwinon; + bd->memwinoff = dummy_memwinoff; + bd->globalwinon = dummy_globalwinon; + bd->txwinon = dummy_txwinon; + bd->rxwinon = dummy_rxwinon; + bd->memoff = dummy_memoff; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCXE: + case PCXEVE: + + bd->memwinon = pcxe_memwinon; + bd->memwinoff = pcxe_memwinoff; + bd->globalwinon = pcxe_globalwinon; + bd->txwinon = pcxe_txwinon; + bd->rxwinon = pcxe_rxwinon; + bd->memoff = pcxe_memoff; + bd->assertgwinon = dummy_assertgwinon; + bd->assertmemoff = dummy_assertmemoff; + break; + + case PCXI: + case PC64XE: + + bd->memwinon = pcxi_memwinon; + bd->memwinoff = pcxi_memwinoff; + bd->globalwinon = pcxi_globalwinon; + bd->txwinon = pcxi_txwinon; + bd->rxwinon = pcxi_rxwinon; + bd->memoff = pcxi_memoff; + bd->assertgwinon = pcxi_assertgwinon; + bd->assertmemoff = pcxi_assertmemoff; + break; + + default: + break; + + } /* End switch on bd->type */ + + /* --------------------------------------------------------------- + Some cards need a memory segment to be defined for use in + transmit and receive windowing operations. These boards + are listed in the below switch. In the case of the XI the + amount of memory on the board is variable so the memory_seg + is also variable. This code determines what they segment + should be. + ----------------------------------------------------------------- */ + + switch (bd->type) + { /* Begin switch on bd->type {board type} */ + + case PCXE: + case PCXEVE: + case PC64XE: + bd->memory_seg = 0xf000; + break; + + case PCXI: + board_id = inb((int)bd->port); + if ((board_id & 0x1) == 0x1) + { /* Begin its an XI card */ + + /* Is it a 64K board */ + if ((board_id & 0x30) == 0) + bd->memory_seg = 0xf000; + + /* Is it a 128K board */ + if ((board_id & 0x30) == 0x10) + bd->memory_seg = 0xe000; + + /* Is is a 256K board */ + if ((board_id & 0x30) == 0x20) + bd->memory_seg = 0xc000; + + /* Is it a 512K board */ + if ((board_id & 0x30) == 0x30) + bd->memory_seg = 0x8000; + + } /* End it is an XI card */ + else + { + printk(KERN_ERR " - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port); + } + break; + + } /* End switch on bd->type */ + + } /* End for each card */ + + if (tty_register_driver(&pc_driver)) + panic("Couldn't register Digi PC/ driver"); + + if (tty_register_driver(&pc_callout)) + panic("Couldn't register Digi PC/ callout"); + + if (tty_register_driver(&pc_info)) + panic("Couldn't register Digi PC/ info "); + + loops_per_sec = save_loops_per_sec; /* reset it to what it should be */ + + /* ------------------------------------------------------------------- + Start up the poller to check for events on all enabled boards + ---------------------------------------------------------------------- */ + + timer_table[DIGI_TIMER].fn = (void *)epcapoll; + timer_table[DIGI_TIMER].expires = 0; + + restore_flags(flags); + + timer_active |= 1 << DIGI_TIMER; + return 0; + +} /* End pc_init */ + +/* ------------------ Begin post_fep_init ---------------------- */ + +static void post_fep_init(unsigned int crd) +{ /* Begin post_fep_init */ + + int i; + unchar *memaddr; + volatile struct global_data *gd; + struct board_info *bd; + volatile struct board_chan *bc; + struct channel *ch; + int shrinkmem = 0, lowwater ; + + /* ------------------------------------------------------------- + This call is made by the user via. the ioctl call DIGI_INIT. + It is resposible for setting up all the card specific stuff. + ---------------------------------------------------------------- */ + bd = &boards[crd]; + + /* ----------------------------------------------------------------- + If this is a PCI board, get the port info. Remember PCI cards + do not have entries into the epcaconfig.h file, so we can't get + the number of ports from it. Unfortunetly, this means that anyone + doing a DIGI_GETINFO before the board has booted will get an invalid + number of ports returned (It should return 0). Calls to DIGI_GETINFO + after DIGI_INIT has been called will return the proper values. + ------------------------------------------------------------------- */ + + if (bd->type >= PCIXEM) /* If the board in question is PCI */ + { /* Begin get PCI number of ports */ + + /* -------------------------------------------------------------------- + Below we use XEMPORTS as a memory offset regardless of which PCI + card it is. This is because all of the supported PCI cards have + the same memory offset for the channel data. This will have to be + changed if we ever develop a PCI/XE card. NOTE : The FEP manual + states that the port offset is 0xC22 as opposed to 0xC02. This is + only true for PC/XE, and PC/XI cards; not for the XEM, or CX series. + On the PCI cards the number of ports is determined by reading a + ID PROM located in the box attached to the card. The card can then + determine the index the id to determine the number of ports available. + (FYI - The id should be located at 0x1ac (And may use up to 4 bytes + if the box in question is a XEM or CX)). + ------------------------------------------------------------------------ */ + + bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long) + (bd->re_map_membase + XEMPORTS)); + + + epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports"); + nbdevs += (bd->numports); + + } /* End get PCI number of ports */ + + if (crd != 0) + card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; + else + card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ + + ch = card_ptr[crd]; + + + epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); + + if (bd->membase < (unsigned char *)0x100000) + memaddr = (unchar *) bd->membase; + else /* Else get special mapped memory above RAM */ + memaddr = (unchar *)bd->re_map_membase; + + /* + The below command is necessary because newer kernels (2.1.x and + up) do not have a 1:1 virtual to physical mapping. The below + call adjust for that. + */ + + memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); + + /* ----------------------------------------------------------------- + The below assignment will set bc to point at the BEGINING of + the cards channel structures. For 1 card there will be between + 8 and 64 of these structures. + -------------------------------------------------------------------- */ + + bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT); + + /* ------------------------------------------------------------------- + The below assignment will set gd to point at the BEGINING of + global memory address 0xc00. The first data in that global + memory actually starts at address 0xc1a. The command in + pointer begins at 0xd10. + ---------------------------------------------------------------------- */ + + gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL); + + /* -------------------------------------------------------------------- + XEPORTS (address 0xc22) points at the number of channels the + card supports. (For 64XE, XI, XEM, and XR use 0xc02) + ----------------------------------------------------------------------- */ + + if (((bd->type == PCXEVE) | (bd->type == PCXE)) && + (*(ushort *)((ulong)memaddr + XEPORTS) < 3)) + shrinkmem = 1; + if (bd->type < PCIXEM) + request_region((int)bd->port, 4, board_desc[bd->type]); + + memwinon(bd, 0); + + /* -------------------------------------------------------------------- + Remember ch is the main drivers channels structure, while bc is + the cards channel structure. + ------------------------------------------------------------------------ */ + + /* For every port on the card do ..... */ + + for (i = 0; i < bd->numports; i++, ch++, bc++) + { /* Begin for each port */ + + ch->brdchan = bc; + ch->mailbox = gd; + ch->tqueue.routine = do_softint; + ch->tqueue.data = ch; + ch->board = &boards[crd]; + + switch (bd->type) + { /* Begin switch bd->type */ + + /* ---------------------------------------------------------------- + Since some of the boards use different bitmaps for their + control signals we cannot hard code these values and retain + portability. We virtualize this data here. + ------------------------------------------------------------------- */ + case EISAXEM: + case PCXEM: + case PCIXEM: + case PCIXRJ: + case PCIXR: + ch->m_rts = 0x02 ; + ch->m_dcd = 0x80 ; + ch->m_dsr = 0x20 ; + ch->m_cts = 0x10 ; + ch->m_ri = 0x40 ; + ch->m_dtr = 0x01 ; + break; + + case PCXE: + case PCXEVE: + case PCXI: + case PC64XE: + ch->m_rts = 0x02 ; + ch->m_dcd = 0x08 ; + ch->m_dsr = 0x10 ; + ch->m_cts = 0x20 ; + ch->m_ri = 0x40 ; + ch->m_dtr = 0x80 ; + break; + + } /* End switch bd->type */ + + if (boards[crd].altpin) + { + ch->dsr = ch->m_dcd; + ch->dcd = ch->m_dsr; + ch->digiext.digi_flags |= DIGI_ALTPIN; + } + else + { + ch->dcd = ch->m_dcd; + ch->dsr = ch->m_dsr; + } + + ch->boardnum = crd; + ch->channelnum = i; + ch->magic = EPCA_MAGIC; + ch->tty = 0; + + if (shrinkmem) + { + fepcmd(ch, SETBUFFER, 32, 0, 0, 0); + shrinkmem = 0; + } + + switch (bd->type) + { /* Begin switch bd->type */ + + case PCIXEM: + case PCIXRJ: + case PCIXR: + /* Cover all the 2MEG cards */ + ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff); + ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff); + ch->txwin = FEPWIN | ((bc->tseg) >> 11); + ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + break; + + case PCXEM: + case EISAXEM: + /* Cover all the 32K windowed cards */ + /* Mask equal to window size - 1 */ + ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff); + ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff); + ch->txwin = FEPWIN | ((bc->tseg) >> 11); + ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + break; + + case PCXEVE: + case PCXE: + ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff); + ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9); + ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff); + ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 ); + break; + + case PCXI: + case PC64XE: + ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4); + ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4); + ch->txwin = ch->rxwin = 0; + break; + + } /* End switch bd->type */ + + ch->txbufhead = 0; + ch->txbufsize = bc->tmax + 1; + + ch->rxbufhead = 0; + ch->rxbufsize = bc->rmax + 1; + + lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); + + /* Set transmitter low water mark */ + fepcmd(ch, STXLWATER, lowwater, 0, 10, 0); + + /* Set receiver low water mark */ + + fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0); + + /* Set receiver high water mark */ + + fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); + + bc->edelay = 100; + bc->idata = 1; + + ch->startc = bc->startc; + ch->stopc = bc->stopc; + ch->startca = bc->startca; + ch->stopca = bc->stopca; + + ch->fepcflag = 0; + ch->fepiflag = 0; + ch->fepoflag = 0; + ch->fepstartc = 0; + ch->fepstopc = 0; + ch->fepstartca = 0; + ch->fepstopca = 0; + + ch->close_delay = 50; + ch->count = 0; + ch->blocked_open = 0; + ch->callout_termios = pc_callout.init_termios; + ch->normal_termios = pc_driver.init_termios; + ch->open_wait = 0; + ch->close_wait = 0; + ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL); + if (!(ch->tmp_buf)) + { + printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i); + + } + memset((void *)ch->tmp_buf,0,ch->txbufsize); + } /* End for each port */ + + printk(KERN_INFO + "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", + VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); + sprintf(mesg, + "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", + VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); + console_print(mesg); + + memwinoff(bd, 0); + +} /* End post_fep_init */ + +/* --------------------- Begin epcapoll ------------------------ */ + +static void epcapoll(unsigned long ignored) +{ /* Begin epcapoll */ + + unsigned long flags; + int crd; + volatile unsigned int head, tail; + struct channel *ch; + struct board_info *bd; + + /* ------------------------------------------------------------------- + This routine is called upon every timer interrupt. Even though + the Digi series cards are capable of generating interupts this + method of non-looping polling is more efficient. This routine + checks for card generated events (Such as receive data, are transmit + buffer empty) and acts on those events. + ----------------------------------------------------------------------- */ + + save_flags(flags); + cli(); + + for (crd = 0; crd < num_cards; crd++) + { /* Begin for each card */ + + bd = &boards[crd]; + ch = card_ptr[crd]; + + if ((bd->status == DISABLED) || digi_poller_inhibited) + continue; /* Begin loop next interation */ + + /* ----------------------------------------------------------- + assertmemoff is not needed here; indeed it is an empty subroutine. + It is being kept because future boards may need this as well as + some legacy boards. + ---------------------------------------------------------------- */ + + assertmemoff(ch); + + globalwinon(ch); + + /* --------------------------------------------------------------- + In this case head and tail actually refer to the event queue not + the transmit or receive queue. + ------------------------------------------------------------------- */ + + head = ch->mailbox->ein; + tail = ch->mailbox->eout; + + /* If head isn't equal to tail we have an event */ + + if (head != tail) + doevent(crd); + + memoff(ch); + + } /* End for each card */ + + timer_table[DIGI_TIMER].fn = (void *)epcapoll; + timer_table[DIGI_TIMER].expires = jiffies + (HZ / 25); + timer_active |= 1 << DIGI_TIMER; + + restore_flags(flags); + +} /* End epcapoll */ + +/* --------------------- Begin doevent ------------------------ */ + +static void doevent(int crd) +{ /* Begin doevent */ + + volatile unchar *eventbuf; + struct channel *ch, *chan0; + static struct tty_struct *tty; + volatile struct board_info *bd; + volatile struct board_chan *bc; + register volatile unsigned int tail, head; + register int event, channel; + register int mstat, lstat; + + /* ------------------------------------------------------------------- + This subroutine is called by epcapoll when an event is detected + in the event queue. This routine responds to those events. + --------------------------------------------------------------------- */ + + bd = &boards[crd]; + + chan0 = card_ptr[crd]; + epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); + + assertgwinon(chan0); + + while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) + { /* Begin while something in event queue */ + + assertgwinon(chan0); + + if (bd->membase < (unsigned char *)0x100000) + eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->membase + tail + ISTART)); + else + { + eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART)); + } + + /* Get the channel the event occured on */ + channel = eventbuf[0]; + + /* Get the actual event code that occured */ + event = eventbuf[1]; + + /* ---------------------------------------------------------------- + The two assignments below get the current modem status (mstat) + and the previous modem status (lstat). These are useful becuase + an event could signal a change in modem signals itself. + ------------------------------------------------------------------- */ + + mstat = eventbuf[2]; + lstat = eventbuf[3]; + + ch = chan0 + channel; + + if ((unsigned)channel >= bd->numports || !ch) + { + if (channel >= bd->numports) + ch = chan0; + bc = ch->brdchan; + goto next; + } + + if ((bc = ch->brdchan) == NULL) + goto next; + + if (event & DATA_IND) + { /* Begin DATA_IND */ + + receive_data(ch); + assertgwinon(ch); + + } /* End DATA_IND */ + else + if (event & MODEMCHG_IND) + { /* Begin MODEMCHG_IND */ + + /* A modem signal change has been indicated */ + + ch->imodem = mstat; + + if (ch->asyncflags & ASYNC_CHECK_CD) + { + if (mstat & ch->dcd) /* We are now receiving dcd */ + wake_up_interruptible(&ch->open_wait); + else + pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ + } + + } /* End MODEMCHG_IND */ + + tty = ch->tty; + if (tty) + { /* Begin if valid tty */ + + if (event & BREAK_IND) + { /* Begin if BREAK_IND */ + + /* A break has been indicated */ + + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_BREAK; + + *tty->flip.char_buf_ptr++ = 0; + + tty_schedule_flip(tty); + + } /* End if BREAK_IND */ + else + if (event & LOWTX_IND) + { /* Begin LOWTX_IND */ + + if (ch->statusflags & LOWWAIT) + { /* Begin if LOWWAIT */ + + ch->statusflags &= ~LOWWAIT; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + + } /* End if LOWWAIT */ + + } /* End LOWTX_IND */ + else + if (event & EMPTYTX_IND) + { /* Begin EMPTYTX_IND */ + + /* This event is generated by setup_empty_event */ + + ch->statusflags &= ~TXBUSY; + if (ch->statusflags & EMPTYWAIT) + { /* Begin if EMPTYWAIT */ + + ch->statusflags &= ~EMPTYWAIT; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + + wake_up_interruptible(&tty->write_wait); + + } /* End if EMPTYWAIT */ + + } /* End EMPTYTX_IND */ + + } /* End if valid tty */ + + + next: + globalwinon(ch); + + if (!bc) + printk(KERN_ERR " - bc == NULL in doevent!\n"); + else + bc->idata = 1; + + chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4); + globalwinon(chan0); + + } /* End while something in event queue */ + +} /* End doevent */ + +/* --------------------- Begin fepcmd ------------------------ */ + +static void fepcmd(struct channel *ch, int cmd, int word_or_byte, + int byte2, int ncmds, int bytecmd) +{ /* Begin fepcmd */ + + unchar *memaddr; + unsigned int head, cmdTail, cmdStart, cmdMax; + long count; + int n; + + /* This is the routine in which commands may be passed to the card. */ + + if (ch->board->status == DISABLED) + { + return; + } + + assertgwinon(ch); + + /* Remember head (As well as max) is just an offset not a base addr */ + head = ch->mailbox->cin; + + /* cmdStart is a base address */ + cmdStart = ch->mailbox->cstart; + + /* ------------------------------------------------------------------ + We do the addition below because we do not want a max pointer + relative to cmdStart. We want a max pointer that points at the + physical end of the command queue. + -------------------------------------------------------------------- */ + + cmdMax = (cmdStart + 4 + (ch->mailbox->cmax)); + + if (ch->board->membase < (unsigned char *)0x100000) + memaddr = ch->board->membase; + else + memaddr = ch->board->re_map_membase; + + /* + The below command is necessary because newer kernels (2.1.x and + up) do not have a 1:1 virtual to physical mapping. The below + call adjust for that. + */ + + memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); + + if (head >= (cmdMax - cmdStart) || (head & 03)) + { + printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, + cmd, head); + printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, + cmdMax, cmdStart); + return; + } + + if (bytecmd) + { + *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; + + *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; + /* Below word_or_byte is bits to set */ + *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte; + /* Below byte2 is bits to reset */ + *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2; + + } + else + { + *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; + *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; + *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte; + } + + head = (head + 4) & (cmdMax - cmdStart - 4); + ch->mailbox->cin = head; + + count = FEPTIMEOUT; + + for (;;) + { /* Begin forever loop */ + + count--; + if (count == 0) + { + printk(KERN_ERR " - Fep not responding in fepcmd()\n"); + return; + } + + head = ch->mailbox->cin; + cmdTail = ch->mailbox->cout; + + n = (head - cmdTail) & (cmdMax - cmdStart - 4); + + /* ---------------------------------------------------------- + Basically this will break when the FEP acknowledges the + command by incrementing cmdTail (Making it equal to head). + ------------------------------------------------------------- */ + + if (n <= ncmds * (sizeof(short) * 4)) + break; /* Well nearly forever :-) */ + + } /* End forever loop */ + +} /* End fepcmd */ + +/* --------------------------------------------------------------------- + Digi products use fields in their channels structures that are very + similar to the c_cflag and c_iflag fields typically found in UNIX + termios structures. The below three routines allow mappings + between these hardware "flags" and their respective Linux flags. +------------------------------------------------------------------------- */ + +/* --------------------- Begin termios2digi_h -------------------- */ + +static unsigned termios2digi_h(struct channel *ch, unsigned cflag) +{ /* Begin termios2digi_h */ + + unsigned res = 0; + + if (cflag & CRTSCTS) + { + ch->digiext.digi_flags |= (RTSPACE | CTSPACE); + res |= ((ch->m_cts) | (ch->m_rts)); + } + + if (ch->digiext.digi_flags & RTSPACE) + res |= ch->m_rts; + + if (ch->digiext.digi_flags & DTRPACE) + res |= ch->m_dtr; + + if (ch->digiext.digi_flags & CTSPACE) + res |= ch->m_cts; + + if (ch->digiext.digi_flags & DSRPACE) + res |= ch->dsr; + + if (ch->digiext.digi_flags & DCDPACE) + res |= ch->dcd; + + if (res & (ch->m_rts)) + ch->digiext.digi_flags |= RTSPACE; + + if (res & (ch->m_cts)) + ch->digiext.digi_flags |= CTSPACE; + + return res; + +} /* End termios2digi_h */ + +/* --------------------- Begin termios2digi_i -------------------- */ +static unsigned termios2digi_i(struct channel *ch, unsigned iflag) +{ /* Begin termios2digi_i */ + + unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | + INPCK | ISTRIP|IXON|IXANY|IXOFF); + + if (ch->digiext.digi_flags & DIGI_AIXON) + res |= IAIXON; + return res; + +} /* End termios2digi_i */ + +/* --------------------- Begin termios2digi_c -------------------- */ + +static unsigned termios2digi_c(struct channel *ch, unsigned cflag) +{ /* Begin termios2digi_c */ + + unsigned res = 0; + +#ifdef SPEED_HACK + /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */ + if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200; + if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600; +#endif /* SPEED_HACK */ + + if (cflag & CBAUDEX) + { /* Begin detected CBAUDEX */ + + ch->digiext.digi_flags |= DIGI_FAST; + + /* ------------------------------------------------------------- + HUPCL bit is used by FEP to indicate fast baud + table is to be used. + ----------------------------------------------------------------- */ + + res |= FEP_HUPCL; + + } /* End detected CBAUDEX */ + else ch->digiext.digi_flags &= ~DIGI_FAST; + + /* ------------------------------------------------------------------- + CBAUD has bit position 0x1000 set these days to indicate Linux + baud rate remap. Digi hardware can't handle the bit assignment. + (We use a different bit assignment for high speed.). Clear this + bit out. + ---------------------------------------------------------------------- */ + res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); + + /* ------------------------------------------------------------- + This gets a little confusing. The Digi cards have their own + representation of c_cflags controling baud rate. For the most + part this is identical to the Linux implementation. However; + Digi supports one rate (76800) that Linux doesn't. This means + that the c_cflag entry that would normally mean 76800 for Digi + actually means 115200 under Linux. Without the below mapping, + a stty 115200 would only drive the board at 76800. Since + the rate 230400 is also found after 76800, the same problem afflicts + us when we choose a rate of 230400. Without the below modificiation + stty 230400 would actually give us 115200. + + There are two additional differences. The Linux value for CLOCAL + (0x800; 0004000) has no meaning to the Digi hardware. Also in + later releases of Linux; the CBAUD define has CBAUDEX (0x1000; + 0010000) ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX + should be checked for a screened out prior to termios2digi_c + returning. Since CLOCAL isn't used by the board this can be + ignored as long as the returned value is used only by Digi hardware. + ----------------------------------------------------------------- */ + + if (cflag & CBAUDEX) + { + /* ------------------------------------------------------------- + The below code is trying to guarantee that only baud rates + 115200 and 230400 are remapped. We use exclusive or because + the various baud rates share common bit positions and therefore + can't be tested for easily. + ----------------------------------------------------------------- */ + + + if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || + (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) + { + res += 1; + } + } + + return res; + +} /* End termios2digi_c */ + +/* --------------------- Begin epcaparam ----------------------- */ + +static void epcaparam(struct tty_struct *tty, struct channel *ch) +{ /* Begin epcaparam */ + + unsigned int cmdHead; + struct termios *ts; + volatile struct board_chan *bc; + unsigned mval, hflow, cflag, iflag; + + bc = ch->brdchan; + epcaassert(bc !=0, "bc out of range"); + + assertgwinon(ch); + + ts = tty->termios; + + if ((ts->c_cflag & CBAUD) == 0) + { /* Begin CBAUD detected */ + + cmdHead = bc->rin; + bc->rout = cmdHead; + cmdHead = bc->tin; + + /* Changing baud in mid-stream transmission can be wonderful */ + /* --------------------------------------------------------------- + Flush current transmit buffer by setting cmdTail pointer (tout) + to cmdHead pointer (tin). Hopefully the transmit buffer is empty. + ----------------------------------------------------------------- */ + + fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); + mval = 0; + + } /* End CBAUD detected */ + else + { /* Begin CBAUD not detected */ + + /* ------------------------------------------------------------------- + c_cflags have changed but that change had nothing to do with BAUD. + Propagate the change to the card. + ---------------------------------------------------------------------- */ + + cflag = termios2digi_c(ch, ts->c_cflag); + + if (cflag != ch->fepcflag) + { + ch->fepcflag = cflag; + /* Set baud rate, char size, stop bits, parity */ + fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); + } + + + /* ---------------------------------------------------------------- + If the user has not forced CLOCAL and if the device is not a + CALLOUT device (Which is always CLOCAL) we set flags such that + the driver will wait on carrier detect. + ------------------------------------------------------------------- */ + + if ((ts->c_cflag & CLOCAL) || (tty->driver.subtype == SERIAL_TYPE_CALLOUT)) + { /* Begin it is a cud device or a ttyD device with CLOCAL on */ + ch->asyncflags &= ~ASYNC_CHECK_CD; + } /* End it is a cud device or a ttyD device with CLOCAL on */ + else + { /* Begin it is a ttyD device */ + ch->asyncflags |= ASYNC_CHECK_CD; + } /* End it is a ttyD device */ + + mval = ch->m_dtr | ch->m_rts; + + } /* End CBAUD not detected */ + + iflag = termios2digi_i(ch, ts->c_iflag); + + /* Check input mode flags */ + + if (iflag != ch->fepiflag) + { + ch->fepiflag = iflag; + + /* --------------------------------------------------------------- + Command sets channels iflag structure on the board. Such things + as input soft flow control, handeling of parity errors, and + break handeling are all set here. + ------------------------------------------------------------------- */ + + /* break handeling, parity handeling, input stripping, flow control chars */ + fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); + } + + /* --------------------------------------------------------------- + Set the board mint value for this channel. This will cause hardware + events to be generated each time the DCD signal (Described in mint) + changes. + ------------------------------------------------------------------- */ + bc->mint = ch->dcd; + + if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) + if (ch->digiext.digi_flags & DIGI_FORCEDCD) + bc->mint = 0; + + ch->imodem = bc->mstat; + + hflow = termios2digi_h(ch, ts->c_cflag); + + if (hflow != ch->hflow) + { + ch->hflow = hflow; + + /* -------------------------------------------------------------- + Hard flow control has been selected but the board is not + using it. Activate hard flow control now. + ----------------------------------------------------------------- */ + + fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); + } + + + mval ^= ch->modemfake & (mval ^ ch->modem); + + if (ch->omodem ^ mval) + { + ch->omodem = mval; + + /* -------------------------------------------------------------- + The below command sets the DTR and RTS mstat structure. If + hard flow control is NOT active these changes will drive the + output of the actual DTR and RTS lines. If hard flow control + is active, the changes will be saved in the mstat structure and + only asserted when hard flow control is turned off. + ----------------------------------------------------------------- */ + + /* First reset DTR & RTS; then set them */ + fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); + fepcmd(ch, SETMODEM, mval, 0, 0, 1); + + } + + if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) + { + ch->fepstartc = ch->startc; + ch->fepstopc = ch->stopc; + + /* ------------------------------------------------------------ + The XON / XOFF characters have changed; propogate these + changes to the card. + --------------------------------------------------------------- */ + + fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); + } + + if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) + { + ch->fepstartca = ch->startca; + ch->fepstopca = ch->stopca; + + /* --------------------------------------------------------------- + Similar to the above, this time the auxilarly XON / XOFF + characters have changed; propogate these changes to the card. + ------------------------------------------------------------------ */ + + fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); + } + +} /* End epcaparam */ + +/* --------------------- Begin receive_data ----------------------- */ + +static void receive_data(struct channel *ch) +{ /* Begin receive_data */ + + unchar *rptr; + struct termios *ts = 0; + struct tty_struct *tty; + volatile struct board_chan *bc; + register int dataToRead, wrapgap, bytesAvailable; + register unsigned int tail, head; + unsigned int wrapmask; + int rc; + + + /* --------------------------------------------------------------- + This routine is called by doint when a receive data event + has taken place. + ------------------------------------------------------------------- */ + + globalwinon(ch); + + if (ch->statusflags & RXSTOPPED) + return; + + tty = ch->tty; + if (tty) + ts = tty->termios; + + bc = ch->brdchan; + + if (!bc) + { + printk(KERN_ERR " - bc is NULL in receive_data!\n"); + return; + } + + wrapmask = ch->rxbufsize - 1; + + /* --------------------------------------------------------------------- + Get the head and tail pointers to the receiver queue. Wrap the + head pointer if it has reached the end of the buffer. + ------------------------------------------------------------------------ */ + + head = bc->rin; + head &= wrapmask; + tail = bc->rout & wrapmask; + + bytesAvailable = (head - tail) & wrapmask; + + if (bytesAvailable == 0) + return; + + /* ------------------------------------------------------------------ + If CREAD bit is off or device not open, set TX tail to head + --------------------------------------------------------------------- */ + + if (!tty || !ts || !(ts->c_cflag & CREAD)) + { + bc->rout = head; + return; + } + + if (tty->flip.count == TTY_FLIPBUF_SIZE) + return; + + if (bc->orun) + { + bc->orun = 0; + printk(KERN_WARNING "overrun! DigiBoard device minor = %d\n",MINOR(tty->device)); + } + + rxwinon(ch); + rptr = tty->flip.char_buf_ptr; + rc = tty->flip.count; + + while (bytesAvailable > 0) + { /* Begin while there is data on the card */ + + wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; + + /* --------------------------------------------------------------- + Even if head has wrapped around only report the amount of + data to be equal to the size - tail. Remember memcpy can't + automaticly wrap around the receive buffer. + ----------------------------------------------------------------- */ + + dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; + + /* -------------------------------------------------------------- + Make sure we don't overflow the buffer + ----------------------------------------------------------------- */ + + if ((rc + dataToRead) > TTY_FLIPBUF_SIZE) + dataToRead = TTY_FLIPBUF_SIZE - rc; + + if (dataToRead == 0) + break; + + /* --------------------------------------------------------------- + Move data read from our card into the line disciplines buffer + for translation if necessary. + ------------------------------------------------------------------ */ + + if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr) + printk(KERN_ERR " - receive_data : memcpy failed\n"); + + rc += dataToRead; + rptr += dataToRead; + tail = (tail + dataToRead) & wrapmask; + bytesAvailable -= dataToRead; + + } /* End while there is data on the card */ + + + tty->flip.count = rc; + tty->flip.char_buf_ptr = rptr; + globalwinon(ch); + bc->rout = tail; + + /* Must be called with global data */ + tty_schedule_flip(ch->tty); + return; + +} /* End receive_data */ + +/* --------------------- Begin pc_ioctl ----------------------- */ + +static int pc_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ /* Begin pc_ioctl */ + + digiflow_t dflow; + int retval, error; + unsigned long flags; + unsigned int mflag, mstat; + unsigned char startc, stopc; + volatile struct board_chan *bc; + struct channel *ch = (struct channel *) tty->driver_data; + + /* The control device has it's own set of commands */ + if (tty->driver.subtype == SERIAL_TYPE_INFO) + { /* Begin if subtype is the control device */ + + switch (cmd) + { /* Begin switch cmd */ + + case DIGI_GETINFO: + { /* Begin case DIGI_GETINFO */ + + struct digi_info di ; + int brd; + + getUser(brd, (unsigned int *)arg); + + if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di)))) + { + printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di)); + return(error); + } + + if ((brd < 0) || (brd >= num_cards) || (num_cards == 0)) + return (-ENODEV); + + memset(&di, 0, sizeof(di)); + + di.board = brd ; + di.status = boards[brd].status; + di.type = boards[brd].type ; + di.numports = boards[brd].numports ; + di.port = boards[brd].port ; + di.membase = boards[brd].membase ; + + copy_to_user((char *)arg, &di, sizeof (di)); + break; + + } /* End case DIGI_GETINFO */ + + case DIGI_POLLER: + { /* Begin case DIGI_POLLER */ + + int brd = arg & 0xff000000 >> 16 ; + unsigned char state = arg & 0xff ; + + if ((brd < 0) || (brd >= num_cards)) + { + printk(KERN_ERR " - DIGI POLLER : brd not valid!\n"); + return (-ENODEV); + } + + digi_poller_inhibited = state ; + break ; + + } /* End case DIGI_POLLER */ + + case DIGI_INIT: + { /* Begin case DIGI_INIT */ + + /* ------------------------------------------------------------ + This call is made by the apps to complete the initilization + of the board(s). This routine is responsible for setting + the card to its initial state and setting the drivers control + fields to the sutianle settings for the card in question. + ---------------------------------------------------------------- */ + + int crd ; + for (crd = 0; crd < num_cards; crd++) + post_fep_init (crd); + + break ; + + } /* End case DIGI_INIT */ + + + default: + return -ENOIOCTLCMD; + + } /* End switch cmd */ + return (0) ; + + } /* End if subtype is the control device */ + + if (ch) + bc = ch->brdchan; + else + { + printk(KERN_ERR " - ch is NULL in pc_ioctl!\n"); + return(-EINVAL); + } + + save_flags(flags); + + /* ------------------------------------------------------------------- + For POSIX compliance we need to add more ioctls. See tty_ioctl.c + in /usr/src/linux/drivers/char for a good example. In particular + think about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS. + ---------------------------------------------------------------------- */ + + switch (cmd) + { /* Begin switch cmd */ + + case TCGETS: + retval = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(struct termios)); + + if (retval) + return(retval); + + copy_to_user((struct termios *)arg, + tty->termios, sizeof(struct termios)); + return(0); + + case TCGETA: + return get_termio(tty, (struct termio *)arg); + + case TCSBRK: /* SVID version: non-zero arg --> no break */ + + retval = tty_check_change(tty); + if (retval) + return retval; + + /* Setup an event to indicate when the transmit buffer empties */ + + setup_empty_event(tty,ch); + tty_wait_until_sent(tty, 0); + if (!arg) + digi_send_break(ch, HZ/4); /* 1/4 second */ + return 0; + + case TCSBRKP: /* support for POSIX tcsendbreak() */ + + retval = tty_check_change(tty); + if (retval) + return retval; + + /* Setup an event to indicate when the transmit buffer empties */ + + setup_empty_event(tty,ch); + tty_wait_until_sent(tty, 0); + digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); + return 0; + + case TIOCGSOFTCAR: + + error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); + if (error) + return error; + + putUser(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg); + return 0; + + case TIOCSSOFTCAR: + /*RONNIE PUT VERIFY_READ (See above) check here */ + { + unsigned int value; + + getUser(value, (unsigned int *)arg); + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (value ? CLOCAL : 0)); + return 0; + } + + case TIOCMODG: + case TIOCMGET: + + mflag = 0; + + cli(); + globalwinon(ch); + mstat = bc->mstat; + memoff(ch); + restore_flags(flags); + + if (mstat & ch->m_dtr) + mflag |= TIOCM_DTR; + + if (mstat & ch->m_rts) + mflag |= TIOCM_RTS; + + if (mstat & ch->m_cts) + mflag |= TIOCM_CTS; + + if (mstat & ch->dsr) + mflag |= TIOCM_DSR; + + if (mstat & ch->m_ri) + mflag |= TIOCM_RI; + + if (mstat & ch->dcd) + mflag |= TIOCM_CD; + + error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); + + if (error) + return error; + + putUser(mflag, (unsigned long *) arg); + + break; + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMODS: + case TIOCMSET: + + getUser(mstat, (unsigned int *)arg); + + mflag = 0; + if (mstat & TIOCM_DTR) + mflag |= ch->m_dtr; + + if (mstat & TIOCM_RTS) + mflag |= ch->m_rts; + + switch (cmd) + { /* Begin switch cmd */ + + case TIOCMODS: + case TIOCMSET: + ch->modemfake = ch->m_dtr|ch->m_rts; + ch->modem = mflag; + break; + + case TIOCMBIS: + ch->modemfake |= mflag; + ch->modem |= mflag; + break; + + case TIOCMBIC: + ch->modemfake |= mflag; + ch->modem &= ~mflag; + break; + + } /* End switch cmd */ + + cli(); + globalwinon(ch); + + /* -------------------------------------------------------------- + The below routine generally sets up parity, baud, flow control + issues, etc.... It effect both control flags and input flags. + ------------------------------------------------------------------ */ + + epcaparam(tty,ch); + memoff(ch); + restore_flags(flags); + break; + + case TIOCSDTR: + ch->omodem |= ch->m_dtr; + cli(); + globalwinon(ch); + fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); + memoff(ch); + restore_flags(flags); + break; + + case TIOCCDTR: + ch->omodem &= ~ch->m_dtr; + cli(); + globalwinon(ch); + fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); + memoff(ch); + restore_flags(flags); + break; + + case DIGI_GETA: + if ((error= + verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t)))) + { + printk(KERN_ERR " - Digi GETA failed\n"); + return(error); + } + + copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)); + break; + + case DIGI_SETAW: + case DIGI_SETAF: + if ((cmd) == (DIGI_SETAW)) + { + /* Setup an event to indicate when the transmit buffer empties */ + + setup_empty_event(tty,ch); + tty_wait_until_sent(tty, 0); + } + else + { + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + } + + /* Fall Thru */ + + case DIGI_SETA: + if ((error = + verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t)))) + return(error); + + copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)); + + if (ch->digiext.digi_flags & DIGI_ALTPIN) + { + ch->dcd = ch->m_dsr; + ch->dsr = ch->m_dcd; + } + else + { + ch->dcd = ch->m_dcd; + ch->dsr = ch->m_dsr; + } + + cli(); + globalwinon(ch); + + /* ----------------------------------------------------------------- + The below routine generally sets up parity, baud, flow control + issues, etc.... It effect both control flags and input flags. + ------------------------------------------------------------------- */ + + epcaparam(tty,ch); + memoff(ch); + restore_flags(flags); + break; + + case DIGI_GETFLOW: + case DIGI_GETAFLOW: + cli(); + globalwinon(ch); + if ((cmd) == (DIGI_GETFLOW)) + { + dflow.startc = bc->startc; + dflow.stopc = bc->stopc; + } + else + { + dflow.startc = bc->startca; + dflow.stopc = bc->stopca; + } + memoff(ch); + restore_flags(flags); + + if ((error = verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow)))) + return(error); + + copy_to_user((char*)arg, &dflow, sizeof(dflow)); + break; + + case DIGI_SETAFLOW: + case DIGI_SETFLOW: + if ((cmd) == (DIGI_SETFLOW)) + { + startc = ch->startc; + stopc = ch->stopc; + } + else + { + startc = ch->startca; + stopc = ch->stopca; + } + + if ((error = verify_area(VERIFY_READ, (char*)arg,sizeof(dflow)))) + return(error); + + copy_from_user(&dflow, (char*)arg, sizeof(dflow)); + + if (dflow.startc != startc || dflow.stopc != stopc) + { /* Begin if setflow toggled */ + cli(); + globalwinon(ch); + + if ((cmd) == (DIGI_SETFLOW)) + { + ch->fepstartc = ch->startc = dflow.startc; + ch->fepstopc = ch->stopc = dflow.stopc; + fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); + } + else + { + ch->fepstartca = ch->startca = dflow.startc; + ch->fepstopca = ch->stopca = dflow.stopc; + fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); + } + + if (ch->statusflags & TXSTOPPED) + pc_start(tty); + + memoff(ch); + restore_flags(flags); + + } /* End if setflow toggled */ + break; + + default: + return -ENOIOCTLCMD; + + } /* End switch cmd */ + + return 0; + +} /* End pc_ioctl */ + +/* --------------------- Begin pc_set_termios ----------------------- */ + +static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ /* Begin pc_set_termios */ + + struct channel *ch; + unsigned long flags; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if channel valid */ + + save_flags(flags); + cli(); + globalwinon(ch); + epcaparam(tty, ch); + memoff(ch); + + if ((old_termios->c_cflag & CRTSCTS) && + ((tty->termios->c_cflag & CRTSCTS) == 0)) + tty->hw_stopped = 0; + + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&ch->open_wait); + + restore_flags(flags); + + } /* End if channel valid */ + +} /* End pc_set_termios */ + +/* --------------------- Begin do_softint ----------------------- */ + +static void do_softint(void *private_) +{ /* Begin do_softint */ + + struct channel *ch = (struct channel *) private_; + + + /* Called in response to a modem change event */ + + if (ch && ch->magic == EPCA_MAGIC) + { /* Begin EPCA_MAGIC */ + + struct tty_struct *tty = ch->tty; + + if (tty && tty->driver_data) + { + if (clear_bit(EPCA_EVENT_HANGUP, &ch->event)) + { /* Begin if clear_bit */ + + tty_hangup(tty); + wake_up_interruptible(&ch->open_wait); + ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); + + } /* End if clear_bit */ + } + + } /* End EPCA_MAGIC */ + +} /* End do_softint */ + +/* ------------------------------------------------------------ + pc_stop and pc_start provide software flow control to the + routine and the pc_ioctl routine. +---------------------------------------------------------------- */ + +/* --------------------- Begin pc_stop ----------------------- */ + +static void pc_stop(struct tty_struct *tty) +{ /* Begin pc_stop */ + + struct channel *ch; + unsigned long flags; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if valid channel */ + + save_flags(flags); + cli(); + + if ((ch->statusflags & TXSTOPPED) == 0) + { /* Begin if transmit stop requested */ + + globalwinon(ch); + + /* STOP transmitting now !! */ + + fepcmd(ch, PAUSETX, 0, 0, 0, 0); + + ch->statusflags |= TXSTOPPED; + memoff(ch); + + } /* End if transmit stop requested */ + + restore_flags(flags); + + } /* End if valid channel */ + +} /* End pc_stop */ + +/* --------------------- Begin pc_start ----------------------- */ + +static void pc_start(struct tty_struct *tty) +{ /* Begin pc_start */ + + struct channel *ch; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if channel valid */ + + unsigned long flags; + + save_flags(flags); + cli(); + + /* Just in case output was resumed because of a change in Digi-flow */ + if (ch->statusflags & TXSTOPPED) + { /* Begin transmit resume requested */ + + volatile struct board_chan *bc; + + globalwinon(ch); + bc = ch->brdchan; + if (ch->statusflags & LOWWAIT) + bc->ilow = 1; + + /* Okay, you can start transmitting again... */ + + fepcmd(ch, RESUMETX, 0, 0, 0, 0); + + ch->statusflags &= ~TXSTOPPED; + memoff(ch); + + } /* End transmit resume requested */ + + restore_flags(flags); + + } /* End if channel valid */ + +} /* End pc_start */ + +/* ------------------------------------------------------------------ + The below routines pc_throttle and pc_unthrottle are used + to slow (And resume) the receipt of data into the kernels + receive buffers. The exact occurence of this depends on the + size of the kernels receive buffer and what the 'watermarks' + are set to for that buffer. See the n_ttys.c file for more + details. +______________________________________________________________________ */ +/* --------------------- Begin throttle ----------------------- */ + +static void pc_throttle(struct tty_struct * tty) +{ /* Begin pc_throttle */ + + struct channel *ch; + unsigned long flags; + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if channel valid */ + + + save_flags(flags); + cli(); + + if ((ch->statusflags & RXSTOPPED) == 0) + { + globalwinon(ch); + fepcmd(ch, PAUSERX, 0, 0, 0, 0); + + ch->statusflags |= RXSTOPPED; + memoff(ch); + } + restore_flags(flags); + + } /* End if channel valid */ + +} /* End pc_throttle */ + +/* --------------------- Begin unthrottle ----------------------- */ + +static void pc_unthrottle(struct tty_struct *tty) +{ /* Begin pc_unthrottle */ + + struct channel *ch; + unsigned long flags; + volatile struct board_chan *bc; + + + /* --------------------------------------------------------- + verifyChannel returns the channel from the tty struct + if it is valid. This serves as a sanity check. + ------------------------------------------------------------- */ + + if ((ch = verifyChannel(tty)) != NULL) + { /* Begin if channel valid */ + + + /* Just in case output was resumed because of a change in Digi-flow */ + save_flags(flags); + cli(); + + if (ch->statusflags & RXSTOPPED) + { + + globalwinon(ch); + bc = ch->brdchan; + fepcmd(ch, RESUMERX, 0, 0, 0, 0); + + ch->statusflags &= ~RXSTOPPED; + memoff(ch); + } + restore_flags(flags); + + } /* End if channel valid */ + +} /* End pc_unthrottle */ + +/* --------------------- Begin digi_send_break ----------------------- */ + +void digi_send_break(struct channel *ch, int msec) +{ /* Begin digi_send_break */ + + unsigned long flags; + + save_flags(flags); + cli(); + globalwinon(ch); + + /* -------------------------------------------------------------------- + Maybe I should send an infinite break here, schedule() for + msec amount of time, and then stop the break. This way, + the user can't screw up the FEP by causing digi_send_break() + to be called (i.e. via an ioctl()) more than once in msec amount + of time. Try this for now... + ------------------------------------------------------------------------ */ + + fepcmd(ch, SENDBREAK, msec, 0, 10, 0); + memoff(ch); + + restore_flags(flags); + +} /* End digi_send_break */ + +/* --------------------- Begin setup_empty_event ----------------------- */ + +static void setup_empty_event(struct tty_struct *tty, struct channel *ch) +{ /* Begin setup_empty_event */ + + volatile struct board_chan *bc = ch->brdchan; + unsigned long int flags; + + save_flags(flags); + cli(); + globalwinon(ch); + ch->statusflags |= EMPTYWAIT; + + /* ------------------------------------------------------------------ + When set the iempty flag request a event to be generated when the + transmit buffer is empty (If there is no BREAK in progress). + --------------------------------------------------------------------- */ + + bc->iempty = 1; + memoff(ch); + restore_flags(flags); + +} /* End setup_empty_event */ + +/* --------------------- Begin get_termio ----------------------- */ + +static int get_termio(struct tty_struct * tty, struct termio * termio) +{ /* Begin get_termio */ + int error; + + error = verify_area(VERIFY_WRITE, termio, sizeof (struct termio)); + if (error) + return error; + + kernel_termios_to_user_termio(termio, tty->termios); + + return 0; +} /* End get_termio */ +/* ---------------------- Begin epca_setup -------------------------- */ +void epca_setup(char *str, int *ints) +{ /* Begin epca_setup */ + + struct board_info board; + int index, loop, last; + char *temp, *t2; + unsigned len; + + /* ---------------------------------------------------------------------- + If this routine looks a little strange it is because it is only called + if a LILO append command is given to boot the kernel with parameters. + In this way, we can provide the user a method of changing his board + configuration without rebuilding the kernel. + ----------------------------------------------------------------------- */ + if (!liloconfig) + liloconfig = 1; + + memset(&board, 0, sizeof(board)); + + /* Assume the data is int first, later we can change it */ + /* I think that array position 0 of ints holds the number of args */ + for (last = 0, index = 1; index <= ints[0]; index++) + switch(index) + { /* Begin parse switch */ + + case 1: + board.status = ints[index]; + + /* --------------------------------------------------------- + We check for 2 (As opposed to 1; because 2 is a flag + instructing the driver to ignore epcaconfig.) For this + reason we check for 2. + ------------------------------------------------------------ */ + if (board.status == 2) + { /* Begin ignore epcaconfig as well as lilo cmd line */ + nbdevs = 0; + num_cards = 0; + return; + } /* End ignore epcaconfig as well as lilo cmd line */ + + if (board.status > 2) + { + printk(KERN_ERR " - epca_setup: Invalid board status 0x%x\n", board.status); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_STATUS; + return; + } + last = index; + break; + + case 2: + board.type = ints[index]; + if (board.type >= PCIXEM) + { + printk(KERN_ERR " - epca_setup: Invalid board type 0x%x\n", board.type); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_TYPE; + return; + } + last = index; + break; + + case 3: + board.altpin = ints[index]; + if (board.altpin > 1) + { + printk(KERN_ERR " - epca_setup: Invalid board altpin 0x%x\n", board.altpin); + invalid_lilo_config = 1; + setup_error_code |= INVALID_ALTPIN; + return; + } + last = index; + break; + + case 4: + board.numports = ints[index]; + if ((board.numports < 2) || (board.numports > 256)) + { + printk(KERN_ERR " - epca_setup: Invalid board numports 0x%x\n", board.numports); + invalid_lilo_config = 1; + setup_error_code |= INVALID_NUM_PORTS; + return; + } + nbdevs += board.numports; + last = index; + break; + + case 5: + board.port = (unsigned char *)ints[index]; + if (board.port <= 0) + { + printk(KERN_ERR " - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); + invalid_lilo_config = 1; + setup_error_code |= INVALID_PORT_BASE; + return; + } + last = index; + break; + + case 6: + board.membase = (unsigned char *)ints[index]; + if (board.membase <= 0) + { + printk(KERN_ERR " - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); + invalid_lilo_config = 1; + setup_error_code |= INVALID_MEM_BASE; + return; + } + last = index; + break; + + default: + printk(KERN_ERR " - epca_setup: Too many integer parms\n"); + return; + + } /* End parse switch */ + + while (str && *str) + { /* Begin while there is a string arg */ + + /* find the next comma or terminator */ + temp = str; + + /* While string is not null, and a comma hasn't been found */ + while (*temp && (*temp != ',')) + temp++; + + if (!*temp) + temp = NULL; + else + *temp++ = 0; + + /* Set index to the number of args + 1 */ + index = last + 1; + + switch(index) + { + case 1: + len = strlen(str); + if (strncmp("Disable", str, len) == 0) + board.status = 0; + else + if (strncmp("Enable", str, len) == 0) + board.status = 1; + else + { + printk(KERN_ERR " - epca_setup: Invalid status %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_STATUS; + return; + } + last = index; + break; + + case 2: + + for(loop = 0; loop < EPCA_NUM_TYPES; loop++) + if (strcmp(board_desc[loop], str) == 0) + break; + + + /* --------------------------------------------------------------- + If the index incremented above refers to a legitamate board + type set it here. + ------------------------------------------------------------------*/ + + if (index < EPCA_NUM_TYPES) + board.type = loop; + else + { + printk(KERN_ERR " - epca_setup: Invalid board type: %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_BOARD_TYPE; + return; + } + last = index; + break; + + case 3: + len = strlen(str); + if (strncmp("Disable", str, len) == 0) + board.altpin = 0; + else + if (strncmp("Enable", str, len) == 0) + board.altpin = 1; + else + { + printk(KERN_ERR " - epca_setup: Invalid altpin %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_ALTPIN; + return; + } + last = index; + break; + + case 4: + t2 = str; + while (isdigit(*t2)) + t2++; + + if (*t2) + { + printk(KERN_ERR " - epca_setup: Invalid port count %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_NUM_PORTS; + return; + } + + /* ------------------------------------------------------------ + There is not a man page for simple_strtoul but the code can be + found in vsprintf.c. The first argument is the string to + translate (To an unsigned long obviously), the second argument + can be the address of any character variable or a NULL. If a + variable is given, the end pointer of the string will be stored + in that variable; if a NULL is given the the end pointer will + not be returned. The last argument is the base to use. If + a 0 is indicated, the routine will attempt to determine the + proper base by looking at the values prefix (A '0' for octal, + a 'x' for hex, etc ... If a value is given it will use that + value as the base. + ---------------------------------------------------------------- */ + board.numports = simple_strtoul(str, NULL, 0); + nbdevs += board.numports; + last = index; + break; + + case 5: + t2 = str; + while (isxdigit(*t2)) + t2++; + + if (*t2) + { + printk(KERN_ERR " - epca_setup: Invalid i/o address %s\n", str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_PORT_BASE; + return; + } + + board.port = (unsigned char *)simple_strtoul(str, NULL, 16); + last = index; + break; + + case 6: + t2 = str; + while (isxdigit(*t2)) + t2++; + + if (*t2) + { + printk(KERN_ERR " - epca_setup: Invalid memory base %s\n",str); + invalid_lilo_config = 1; + setup_error_code |= INVALID_MEM_BASE; + return; + } + + board.membase = (unsigned char *)simple_strtoul(str, NULL, 16); + last = index; + break; + + default: + printk(KERN_ERR "PC/Xx: Too many string parms\n"); + return; + } + str = temp; + + } /* End while there is a string arg */ + + + if (last < 6) + { + printk(KERN_ERR "PC/Xx: Insufficient parms specified\n"); + return; + } + + /* I should REALLY validate the stuff here */ + + /* Copies our local copy of board into boards */ + memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board)); + + + /* Does this get called once per lilo arg are what ? */ + + printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", + num_cards, board_desc[board.type], + board.numports, (int)board.port, (unsigned int) board.membase); + + num_cards++; + +} /* End epca_setup */ + + + +#ifdef ENABLE_PCI +/* --------------------- Begin get_PCI_configuration ---------------------- */ + +int get_PCI_configuration(char bus, char device_fn, + unsigned int *base_addr0, unsigned int *base_addr1, + unsigned int *base_addr2, unsigned int *base_addr3, + unsigned int *base_addr4, unsigned int *base_addr5) +{ /* Begin get_PCI_configuration */ + + int error; + + error = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, + base_addr0); + + error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, + base_addr1); + + error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, + base_addr2); + + error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_3, + base_addr3); + + error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_4, + base_addr4); + + error |= pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_5, + base_addr5); + + /* ------------------------------------------------------------------------ + NOTE - The code below mask out either the 2 or 4 bits dependant on the + space being addressed. (base_addr value reflecting io space, have their + first 2 bits mask out, while base_addr value reflecting mem space, have + their first 4 bits mask out.) These bits are flag bits and should always + be 0 when used as an address. + ---------------------------------------------------------------------------- */ + + if ((*base_addr0) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr0) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr0) &= PCI_BASE_ADDRESS_MEM_MASK; + + if ((*base_addr1) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr1) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr1) &= PCI_BASE_ADDRESS_MEM_MASK; + + if ((*base_addr2) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr2) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr2) &= PCI_BASE_ADDRESS_MEM_MASK; + + if ((*base_addr3) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr3) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr3) &= PCI_BASE_ADDRESS_MEM_MASK; + + if ((*base_addr4) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr4) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr4) &= PCI_BASE_ADDRESS_MEM_MASK; + + if ((*base_addr5) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ + (*base_addr5) &= PCI_BASE_ADDRESS_IO_MASK; + else + (*base_addr5) &= PCI_BASE_ADDRESS_MEM_MASK; + + if (error) + { + printk(KERN_ERR " - DIGI PCI error: board not initializing due to error\n"); + return(0); + } + return(1); +} /* End get_PCI_configuration */ + +/* ------------------------ Begin init_PCI --------------------------- */ + +int init_PCI(int boards_found) +{ /* Begin init_PCI */ + + unsigned char bus, device_fn; + int i, pci_count = 0; + unsigned int base_addr0, base_addr1, base_addr2, + base_addr3, base_addr4, base_addr5; + + base_addr0 = base_addr1 = base_addr2 = 0; + base_addr3 = base_addr4 = base_addr5 = 0; + + for(i = 0; i < (MAXBOARDS - boards_found); i++) + { /* Begin for each POSSIBLE remaining board */ + + if (!pcibios_find_device(PCI_VENDOR_DIGI, PCI_DEVICE_XR, + i, &bus, &device_fn)) + { /* Begin found XR */ + if (get_PCI_configuration(bus, device_fn, &base_addr0, &base_addr1, + &base_addr2, &base_addr3, + &base_addr4, &base_addr5)) + { /* Store a PCI/XR into the boards structure */ + + + boards[boards_found + pci_count].status = ENABLED; + boards[boards_found + pci_count].type = PCIXR; + + boards[boards_found + pci_count].numports = 0x0; + + boards[boards_found + pci_count].port = (unsigned char *)((char *)base_addr0 + PCI_IO_OFFSET); + /* Most cards use base_addr0, but some use base_addr2 */ + boards[boards_found + pci_count].membase = (unsigned char *)base_addr0; + + if (base_addr0 >= 0x100000) + { + /* ------------------------------------------------------------ + Standard physical addresses are valid to the kernel as long + as they aren't above RAM. Higher addresses (Such as are + typical of a PCI system) need to be mapped in with the + ioremap command. For boards using such high addresses the + driver will store both addresses. One address (The physical) + will be held for the apps use (And mmap) and the other (The + ioremapped address) will be used in the kernel. + + ---------------------------------------------------------------- */ + boards[boards_found + pci_count].re_map_port = ioremap((base_addr0 + PCI_IO_OFFSET),0x200000); + boards[boards_found + pci_count].re_map_membase = ioremap(base_addr0, 0x200000); + } + + pci_count++; + + /* -------------------------------------------------------------- + I don't know what the below does, but the hardware guys say + its required on everything except PLX (In this case XRJ). + ---------------------------------------------------------------- */ + pcibios_write_config_byte(bus, device_fn, 0x40, 0); + pcibios_write_config_byte(bus, device_fn, 0x46, 0); + + } /* End store a PCI/XR into the board structure */ + + } /* End found XR */ + + if (!pcibios_find_device(PCI_VENDOR_DIGI, PCI_DEVICE_XEM, + i, &bus, &device_fn)) + { /* Begin found XEM */ + + if (get_PCI_configuration(bus, device_fn, &base_addr0, &base_addr1, + &base_addr2, &base_addr3, + &base_addr4, &base_addr5)) + { /* Begin store a PCI/XEM into the boards structure */ + + boards[boards_found + pci_count].status = ENABLED; + boards[boards_found + pci_count].type = PCIXEM; + + boards[boards_found + pci_count].numports = 0x0; + boards[boards_found + pci_count].port = (char *)((char *)base_addr0 + PCI_IO_OFFSET); + /* Most cards use base_addr0, but some use base_addr2 */ + boards[boards_found + pci_count].membase = (unsigned char *)base_addr0; + + if (base_addr0 >= 0x100000) + { + /* ------------------------------------------------------------ + Standard physical addresses are valid to the kernel as long + as they aren't above RAM. Higher addresses (Such as are + typical of a PCI system) need to be mapped in with the + ioremap command. For boards using such high addresses the + driver will store both addresses. One address (The physical) + will be held for the apps use (And mmap) and the other (The + vremapped address) will be used in the kernel. + + ---------------------------------------------------------------- */ + boards[boards_found + pci_count].re_map_port = ioremap((base_addr0 + PCI_IO_OFFSET),0x200000); + boards[boards_found + pci_count].re_map_membase = ioremap(base_addr0, 0x200000); + } + + pci_count++; + /* -------------------------------------------------------------- + I don't know what the below does, but the hardware guys say + its required on everything except PLX (In this case XRJ). + ---------------------------------------------------------------- */ + pcibios_write_config_byte(bus, device_fn, 0x40, 0); + pcibios_write_config_byte(bus, device_fn, 0x46, 0); + + } /* End store a PCI/XEM into the boards structure */ + + } /* End found XEM */ + + + if (!pcibios_find_device(PCI_VENDOR_DIGI, PCI_DEVICE_CX, + i, &bus, &device_fn)) + { /* Begin found CX */ + + if (get_PCI_configuration(bus, device_fn, &base_addr0, &base_addr1, + &base_addr2, &base_addr3, + &base_addr4, &base_addr5)) + { /* Begin store a PCI/CX into the boards structure */ + + boards[boards_found + pci_count].status = ENABLED; + boards[boards_found + pci_count].type = PCICX; + + boards[boards_found + pci_count].numports = 0x0; + boards[boards_found + pci_count].port = (char *)((char *)base_addr0 + PCI_IO_OFFSET); + /* Most cards use base_addr0, but some use base_addr2 */ + boards[boards_found + pci_count].membase = (unsigned char *)base_addr0; + + if (base_addr0 >= 0x100000) + { + /* ------------------------------------------------------------ + Standard physical addresses are valid to the kernel as long + as they aren't above RAM. Higher addresses (Such as are + typical of a PCI system) need to be mapped in with the + ioremap command. For boards using such high addresses the + driver will store both addresses. One address (The physical) + will be held for the apps use (And mmap) and the other (The + vremapped address) will be used in the kernel. + + ---------------------------------------------------------------- */ + boards[boards_found + pci_count].re_map_port = ioremap((base_addr0 + PCI_IO_OFFSET),0x200000); + boards[boards_found + pci_count].re_map_membase = ioremap(base_addr0, 0x200000); + } + + pci_count++; + /* -------------------------------------------------------------- + I don't know what the below does, but the hardware guys say + its required on everything except PLX (In this case XRJ). + ---------------------------------------------------------------- */ + pcibios_write_config_byte(bus, device_fn, 0x40, 0); + pcibios_write_config_byte(bus, device_fn, 0x46, 0); + + } /* End store a PCI/CX into the boards structure */ + + } /* End found CX */ + + if (!pcibios_find_device(PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, + i, &bus, &device_fn)) + { /* Begin found XRJ */ + + if (get_PCI_configuration(bus, device_fn, &base_addr0, &base_addr1, + &base_addr2, &base_addr3, + &base_addr4, &base_addr5)) + { /* Begin store a PCI/XRJ into the boards structure */ + + boards[boards_found + pci_count].status = ENABLED; + boards[boards_found + pci_count].type = PCIXRJ; + + boards[boards_found + pci_count].numports = 0x0; + boards[boards_found + pci_count].port = (unsigned char *)(base_addr2 + PCI_IO_OFFSET); + /* Most cards use base_addr0, but some use base_addr2 */ + boards[boards_found + pci_count].membase = (unsigned char *)base_addr2; + + if (base_addr2 >= 0x100000) + { + /* ------------------------------------------------------------ + Standard physical addresses are valid to the kernel as long + as they aren't above RAM. Higher addresses (Such as are + typical of a PCI system) need to be mapped in with the + ioremap command. For boards using such high addresses the + driver will store both addresses. One address (The physical) + will be held for the apps use (And mmap) and the other (The + vremapped address) will be used in the kernel. + + ---------------------------------------------------------------- */ + boards[boards_found + pci_count].re_map_port = ioremap((base_addr2 + PCI_IO_OFFSET),0x200000); + boards[boards_found + pci_count].re_map_membase = ioremap(base_addr2, 0x200000); + } + + pci_count++; + + } /* End store a PCI/XRJ into the boards structure */ + + } /* End found XRJ */ + + } /* End for each POSSIBLE remaining board */ + + return(pci_count); + +} /* End init_PCI */ + +#endif /* ENABLE_PCI */ + + diff -u --recursive --new-file v2.1.36/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c --- v2.1.36/linux/drivers/char/fbmem.c Fri Apr 4 08:52:19 1997 +++ linux/drivers/char/fbmem.c Thu May 1 12:05:01 1997 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -300,8 +301,8 @@ return 0; } -void -fbmem_init(void) +__initfunc(void +fbmem_init(void)) { if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) printk("unable to get major %d for fb devs\n", FB_MAJOR); diff -u --recursive --new-file v2.1.36/linux/drivers/char/ftape/kernel-interface.c linux/drivers/char/ftape/kernel-interface.c --- v2.1.36/linux/drivers/char/ftape/kernel-interface.c Fri Apr 4 08:52:19 1997 +++ linux/drivers/char/ftape/kernel-interface.c Thu May 1 12:05:01 1997 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -120,7 +121,7 @@ #define ftape_init init_module #endif -int ftape_init(void) +__initfunc(int ftape_init(void)) { int n; int order; diff -u --recursive --new-file v2.1.36/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.1.36/linux/drivers/char/lp.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/lp.c Thu May 1 12:05:01 1997 @@ -631,7 +631,7 @@ static int parport_ptr = 0; -void lp_setup(char *str, int *ints) +__initfunc(void lp_setup(char *str, int *ints)) { /* Ugh. */ if (!strncmp(str, "parport", 7)) { diff -u --recursive --new-file v2.1.36/linux/drivers/char/lp_intern.c linux/drivers/char/lp_intern.c --- v2.1.36/linux/drivers/char/lp_intern.c Fri Dec 20 01:20:00 1996 +++ linux/drivers/char/lp_intern.c Thu May 1 12:05:01 1997 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_AMIGA @@ -33,7 +34,6 @@ #endif #include -static int my_inter = 0; static int minor = -1; static void lp_int_out(int, int); @@ -126,24 +126,18 @@ } } -static int lp_int_my_interrupt(int dev) -{ - return my_inter; -} - static void lp_int_interrupt(int irq, void *data, struct pt_regs *fp) { - my_inter = 1; - lp_interrupt(irq, data, fp); - my_inter = 0; + lp_interrupt(minor); } -static void lp_int_open(void) +static int lp_int_open(int dev) { MOD_INC_USE_COUNT; + return 0; } -static void lp_int_release(void) +static void lp_int_release(int dev) { MOD_DEC_USE_COUNT; } @@ -155,7 +149,7 @@ lp_int_busy, lp_int_pout, lp_int_online, - lp_int_my_interrupt, + 0, NULL, /* ioctl */ lp_int_open, lp_int_release, @@ -167,7 +161,7 @@ NULL, }; -int lp_internal_init(void) +__initfunc(int lp_internal_init(void)) { #ifdef CONFIG_AMIGA if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) diff -u --recursive --new-file v2.1.36/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c --- v2.1.36/linux/drivers/char/lp_m68k.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/lp_m68k.c Thu May 1 12:05:01 1997 @@ -41,6 +41,7 @@ #include #include #include +#include #include #ifdef CONFIG_KERNELD #include @@ -465,7 +466,7 @@ EXPORT_SYMBOL(register_parallel); EXPORT_SYMBOL(unregister_parallel); -int lp_init(void) +__initfunc(int lp_init(void)) { extern char m68k_debug_device[]; @@ -498,7 +499,7 @@ /* * Currently we do not accept any lp-parameters, but that may change. */ -void lp_setup(char *str, int *ints) +__initfunc(void lp_setup(char *str, int *ints)) { } diff -u --recursive --new-file v2.1.36/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.1.36/linux/drivers/char/mem.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/mem.c Thu May 1 12:05:01 1997 @@ -139,7 +139,8 @@ else tmp = count; read = tmp; -#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */ +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ while (p < PAGE_SIZE && tmp > 0) { put_user(0,buf); buf++; @@ -172,7 +173,8 @@ if (count > (unsigned long) high_memory - p) count = (unsigned long) high_memory - p; written = 0; -#if defined(__sparc__) /* we don't have page 0 mapped on sparc.. */ +#if defined(__sparc__) || defined(__mc68000__) + /* we don't have page 0 mapped on sparc and m68k.. */ while (p < PAGE_SIZE && count > 0) { /* Hmm. Do something? */ buf++; diff -u --recursive --new-file v2.1.36/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.1.36/linux/drivers/char/misc.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/misc.c Thu May 1 12:05:01 1997 @@ -73,6 +73,7 @@ extern void wdt_init(void); extern void pcwatchdog_init(void); extern int rtc_init(void); +extern int dsp56k_init(void); #ifdef CONFIG_PROC_FS static int misc_read_proc(char *buf, char **start, off_t offset, @@ -234,6 +235,9 @@ #endif #ifdef CONFIG_RTC rtc_init(); +#endif +#ifdef CONFIG_ATARI_DSP56K + dsp56k_init(); #endif #endif /* !MODULE */ if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { diff -u --recursive --new-file v2.1.36/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c --- v2.1.36/linux/drivers/char/msbusmouse.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/msbusmouse.c Thu May 1 12:05:01 1997 @@ -51,7 +51,7 @@ static struct mouse_status mouse; static int mouse_irq = MOUSE_IRQ; -void msmouse_setup(char *str, int *ints) +__initfunc(void msmouse_setup(char *str, int *ints)) { if (ints[0] > 0) mouse_irq=ints[1]; diff -u --recursive --new-file v2.1.36/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c --- v2.1.36/linux/drivers/char/pcxx.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/pcxx.c Thu May 1 12:05:01 1997 @@ -895,7 +895,7 @@ * Driver setup function when linked into the kernel to optionally parse multible * "digi="-lines and initialize the driver at boot time. No probing. */ -void pcxx_setup(char *str, int *ints) +__initfunc(void pcxx_setup(char *str, int *ints)) { struct board_info board; diff -u --recursive --new-file v2.1.36/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.1.36/linux/drivers/char/random.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/random.c Sat Apr 26 10:31:36 1997 @@ -1,7 +1,7 @@ /* * random.c -- A strong random number generator * - * Version 1.01, last modified 13-Feb-97 + * Version 1.02, last modified 15-Apr-97 * * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997. All rights reserved. * @@ -839,6 +839,18 @@ digest[ 4 ] += E; } +#undef ROTL +#undef f1 +#undef f2 +#undef f3 +#undef f4 +#undef K1 +#undef K2 +#undef K3 +#undef K4 +#undef expand +#undef subRound + #else #define HASH_BUFFER_SIZE 4 #define HASH_TRANSFORM MD5Transform @@ -1324,22 +1336,90 @@ * attacks which rely on guessing the initial TCP sequence number. * This algorithm was suggested by Steve Bellovin. */ + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) + +/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) \ + {(a) += F ((b), (c), (d)) + (x); \ + (a) = ROTL ((s), (a));} +#define GG(a, b, c, d, x, s) \ + {(a) += G ((b), (c), (d)) + (x) + 013240474631UL; \ + (a) = ROTL ((s), (a));} +#define HH(a, b, c, d, x, s) \ + {(a) += H ((b), (c), (d)) + (x) + 015666365641UL; \ + (a) = ROTL ((s), (a));} + +/* + * Basic cut-down MD4 transform + */ +static void halfMD4Transform (__u32 buf[4], __u32 in[8]) +{ + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + FF (a, b, c, d, in[ 0], 3); + FF (d, a, b, c, in[ 1], 7); + FF (c, d, a, b, in[ 2], 11); + FF (b, c, d, a, in[ 3], 19); + FF (a, b, c, d, in[ 4], 3); + FF (d, a, b, c, in[ 5], 7); + FF (c, d, a, b, in[ 6], 11); + FF (b, c, d, a, in[ 7], 19); + + /* Round 2 */ + GG (a, b, c, d, in[ 0], 3); + GG (d, a, b, c, in[ 4], 5); + GG (a, b, c, d, in[ 1], 9); + GG (d, a, b, c, in[ 5], 13); + GG (a, b, c, d, in[ 2], 3); + GG (d, a, b, c, in[ 6], 5); + GG (a, b, c, d, in[ 3], 9); + GG (d, a, b, c, in[ 7], 13); + + /* Round 3 */ + HH (a, b, c, d, in[ 0], 3); + HH (c, d, a, b, in[ 4], 9); + HH (a, b, c, d, in[ 2], 11); + HH (c, d, a, b, in[ 6], 15); + HH (a, b, c, d, in[ 1], 3); + HH (c, d, a, b, in[ 5], 9); + HH (a, b, c, d, in[ 3], 11); + HH (c, d, a, b, in[ 7], 15); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#define REKEY_INTERVAL 300 + __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport) { - static int is_init = 0; - static __u32 secret[16]; + static __u32 rekey_time = 0; + static __u32 secret[12]; + static char count = 0; struct timeval tv; - __u32 tmp[16]; + __u32 tmp[12]; __u32 seq; /* - * Pick a random secret the first time we open a TCP - * connection. + * Pick a random secret every REKEY_INTERVAL seconds */ - if (is_init == 0) { + do_gettimeofday(&tv); + if (!rekey_time || + (tv.tv_sec - rekey_time) > REKEY_INTERVAL) { get_random_bytes(&secret, sizeof(secret)); - is_init = 1; + rekey_time = tv.tv_sec; + count++; } memcpy(tmp, secret, sizeof(tmp)); @@ -1350,7 +1430,7 @@ tmp[8]=saddr; tmp[9]=daddr; tmp[10]=(sport << 16) + dport; - HASH_TRANSFORM(tmp, tmp); + halfMD4Transform(tmp, tmp+4); /* * As close as possible to RFC 793, which @@ -1359,8 +1439,8 @@ * For 10MB/s ethernet, a 1MHz clock is appropriate. * That's funny, Linux has one built in! Use it! */ - do_gettimeofday(&tv); - seq = tmp[1] + tv.tv_usec+tv.tv_sec*1000000; + seq = (tmp[1]&0xFFFFFF) + (tv.tv_usec+tv.tv_sec*1000000) + + (count << 24); #if 0 printk("init_seq(%lx, %lx, %d, %d) = %d\n", saddr, daddr, sport, dport, seq); diff -u --recursive --new-file v2.1.36/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c --- v2.1.36/linux/drivers/char/riscom8.c Wed Apr 23 19:01:17 1997 +++ linux/drivers/char/riscom8.c Thu May 1 12:05:01 1997 @@ -1821,7 +1821,7 @@ * addresses in this case. * */ -void riscom8_setup(char *str, int * ints) +__initfunc(void riscom8_setup(char *str, int * ints)) { int i; diff -u --recursive --new-file v2.1.36/linux/drivers/char/tga.c linux/drivers/char/tga.c --- v2.1.36/linux/drivers/char/tga.c Mon Apr 14 16:28:11 1997 +++ linux/drivers/char/tga.c Sun May 4 17:51:05 1997 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -140,35 +141,35 @@ unsigned long tga_regs_base; unsigned int tga_bpp, tga_fb_width, tga_fb_height, tga_fb_stride; -static unsigned int fb_offset_presets[4] = { +static unsigned int fb_offset_presets[4] __initdata = { TGA_8PLANE_FB_OFFSET, TGA_24PLANE_FB_OFFSET, 0xffffffff, TGA_24PLUSZ_FB_OFFSET }; -static unsigned int deep_presets[4] = { +static unsigned int deep_presets[4] __initdata = { 0x00014000, 0x0001440d, 0xffffffff, 0x0001441d }; -static unsigned int rasterop_presets[4] = { +static unsigned int rasterop_presets[4] __initdata = { 0x00000003, 0x00000303, 0xffffffff, 0x00000303 }; -static unsigned int mode_presets[4] = { +static unsigned int mode_presets[4] __initdata = { 0x00002000, 0x00002300, 0xffffffff, 0x00002300 }; -static unsigned int base_addr_presets[4] = { +static unsigned int base_addr_presets[4] __initdata = { 0x00000000, 0x00000001, 0xffffffff, @@ -304,8 +305,8 @@ restore_flags(flags); } -unsigned long -con_type_init(unsigned long kmem_start, const char **display_desc) +__initfunc(unsigned long +con_type_init(unsigned long kmem_start, const char **display_desc)) { can_do_color = 1; @@ -323,8 +324,8 @@ return kmem_start; } -void -con_type_init_finish(void) +__initfunc(void +con_type_init_finish(void)) { } @@ -447,8 +448,8 @@ * when TGA console is configured, at the end of the probing code, * we call here to look for a TGA device, and proceed... */ -void -tga_console_init(void) +__initfunc(void +tga_console_init(void)) { unsigned char pci_bus, pci_devfn; int status; @@ -490,9 +491,9 @@ #endif } -unsigned char PLLbits[7] = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; +unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; -const unsigned long bt485_cursor_source[64] = { +const unsigned long bt485_cursor_source[64] __initdata = { 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, @@ -502,7 +503,7 @@ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -const unsigned int bt463_cursor_source[256] = { +const unsigned int bt463_cursor_source[256] __initdata = { 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x00000000, 0x00000000, 0x00000000, @@ -533,8 +534,8 @@ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -void -tga_init_video() +__initfunc(void +tga_init_video(void)) { int i, j, temp; unsigned char *cbp; @@ -750,8 +751,8 @@ tga_fb_stride = tga_fb_width / sizeof(int); } -void -tga_clear_screen() +__initfunc(void +tga_clear_screen(void)) { register int i, j; register unsigned int *dst; diff -u --recursive --new-file v2.1.36/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v2.1.36/linux/drivers/char/tpqic02.c Fri Apr 4 08:52:19 1997 +++ linux/drivers/char/tpqic02.c Thu May 1 12:05:01 1997 @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -2866,10 +2867,7 @@ return 0; } /* qic02_get_resources */ -#ifdef MODULE -static -#endif -int qic02_tape_init(void) +__initfunc(static int qic02_tape_init(void)) { if (TPSTATSIZE != 6) { diff -u --recursive --new-file v2.1.36/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.36/linux/drivers/char/tty_io.c Wed Apr 23 19:01:18 1997 +++ linux/drivers/char/tty_io.c Tue Apr 29 11:45:43 1997 @@ -166,14 +166,11 @@ { #ifdef CHECK_TTY_COUNT struct file *f; - int i, count = 0; + int count = 0; - for (f = first_file, i=0; if_next) { - if (!f->f_count) - continue; - if (f->private_data == tty) { + for(f = inuse_filps; f; f = f->f_next) { + if(f->private_data == tty) count++; - } } if (tty->driver.type == TTY_DRIVER_TYPE_PTY && tty->driver.subtype == PTY_TYPE_SLAVE && @@ -363,16 +360,14 @@ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops) { - int i; + struct file * filp; struct task_struct *p; if (!tty) return; check_tty_count(tty, "do_tty_hangup"); - for (filp = first_file, i=0; if_next) { - if (!filp->f_count) - continue; + for (filp = inuse_filps; filp; filp = filp->f_next) { if (filp->private_data != tty) continue; if (!filp->f_inode) @@ -405,13 +400,14 @@ tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { - i = (tty->ldisc.open)(tty); + int i = (tty->ldisc.open)(tty); if (i < 0) printk("do_tty_hangup: N_TTY open: error %d\n", -i); } } + read_lock(&tasklist_lock); for_each_task(p) { if ((tty->session > 0) && (p->session == tty->session) && p->leader) { @@ -423,6 +419,8 @@ if (p->tty == tty) p->tty = NULL; } + read_unlock(&tasklist_lock); + tty->flags = 0; tty->session = 0; tty->pgrp = -1; @@ -494,9 +492,11 @@ tty->session = 0; tty->pgrp = -1; + read_lock(&tasklist_lock); for_each_task(p) if (p->session == current->session) p->tty = NULL; + read_unlock(&tasklist_lock); } void wait_for_keypress(void) @@ -1338,9 +1338,11 @@ */ struct task_struct *p; + read_lock(&tasklist_lock); for_each_task(p) if (p->tty == tty) p->tty = NULL; + read_unlock(&tasklist_lock); } else return -EPERM; } @@ -1760,6 +1762,9 @@ #endif #ifdef CONFIG_DIGI pcxe_init(); +#endif +#ifdef CONFIG_DIGIEPCA + pc_init(); #endif #ifdef CONFIG_RISCOM8 riscom8_init(); diff -u --recursive --new-file v2.1.36/linux/drivers/char/vga.c linux/drivers/char/vga.c --- v2.1.36/linux/drivers/char/vga.c Mon Apr 7 11:35:29 1997 +++ linux/drivers/char/vga.c Thu May 1 12:05:01 1997 @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -146,8 +147,8 @@ hide_cursor(); } -unsigned long -con_type_init(unsigned long kmem_start, const char **display_desc) +__initfunc(unsigned long +con_type_init(unsigned long kmem_start, const char **display_desc)) { if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */ { @@ -239,8 +240,8 @@ return kmem_start; } -void -con_type_init_finish(void) +__initfunc(void +con_type_init_finish(void)) { } diff -u --recursive --new-file v2.1.36/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.1.36/linux/drivers/char/vt.c Wed Apr 23 19:01:18 1997 +++ linux/drivers/char/vt.c Sun Apr 27 15:08:01 1997 @@ -123,6 +123,7 @@ } } + read_lock(&tasklist_lock); for_each_task(p) { if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR && @@ -131,6 +132,7 @@ send_sig(SIGWINCH, p, 1); } } + read_unlock(&tasklist_lock); return 0; } diff -u --recursive --new-file v2.1.36/linux/drivers/char/wdt.c linux/drivers/char/wdt.c --- v2.1.36/linux/drivers/char/wdt.c Wed Apr 23 19:01:18 1997 +++ linux/drivers/char/wdt.c Thu May 1 12:05:01 1997 @@ -61,7 +61,7 @@ * Setup options */ -void wdt_setup(char *str, int *ints) +__initfunc(void wdt_setup(char *str, int *ints)) { if(ints[0]>0) { diff -u --recursive --new-file v2.1.36/linux/drivers/isdn/sc/Makefile linux/drivers/isdn/sc/Makefile --- v2.1.36/linux/drivers/isdn/sc/Makefile Thu Feb 27 10:57:30 1997 +++ linux/drivers/isdn/sc/Makefile Thu May 1 12:05:01 1997 @@ -1,5 +1,5 @@ # -# $Id: Makefile.kernel,v 1.1 1996/11/07 13:07:40 fritz Exp $ +# $Id: Makefile,v 1.2 1997/05/01 08:53:47 davem Exp $ # Copyright (C) 1996 SpellCaster Telecommunications Inc. # # This program is free software; you can redistribute it and/or modify diff -u --recursive --new-file v2.1.36/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v2.1.36/linux/drivers/net/eexpress.c Wed Apr 23 19:01:19 1997 +++ linux/drivers/net/eexpress.c Thu May 1 12:05:01 1997 @@ -94,6 +94,7 @@ #include #include #include +#include #include #include @@ -301,7 +302,7 @@ * checks for presence of EtherExpress card */ -int express_probe(struct device *dev) +__initfunc(int express_probe(struct device *dev)) { unsigned short *port; static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 }; @@ -913,7 +914,7 @@ * than one card in a machine. */ -static int eexp_hw_probe(struct device *dev, unsigned short ioaddr) +__initfunc(static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)) { unsigned short hw_addr[3]; unsigned char buswidth; @@ -1034,8 +1035,8 @@ * Read a word from the EtherExpress on-board serial EEPROM. * The EEPROM contains 64 words of 16 bits. */ -static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, - unsigned char location) +__initfunc(static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, + unsigned char location)) { unsigned short cmd = 0x180|(location&0x7f); unsigned short rval = 0,wval = EC_CS|i586_RST; diff -u --recursive --new-file v2.1.36/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c --- v2.1.36/linux/drivers/net/ltpc.c Wed Apr 23 19:01:19 1997 +++ linux/drivers/net/ltpc.c Fri Apr 25 15:25:56 1997 @@ -1259,7 +1259,7 @@ if(debug&DEBUG_VERBOSE) printk("waiting\n"); /* if it's in process, wait a bit for it to finish */ timeout = jiffies+HZ; - add_timer(<pc_timer) + add_timer(<pc_timer); while(del_timer(<pc_timer) && (timeout > jiffies)) { add_timer(<pc_timer); diff -u --recursive --new-file v2.1.36/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v2.1.36/linux/drivers/net/sk_g16.c Fri Apr 4 08:52:21 1997 +++ linux/drivers/net/sk_g16.c Thu May 1 12:05:01 1997 @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -532,7 +533,7 @@ * (detachable devices only). */ -int SK_init(struct device *dev) +__initfunc(int SK_init(struct device *dev)) { int ioaddr = 0; /* I/O port address used for POS regs */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ @@ -616,7 +617,7 @@ * 94/06/30 pwe SK_ADDR now checked and at the correct place -*/ -int SK_probe(struct device *dev, short ioaddr) +__initfunc(int SK_probe(struct device *dev, short ioaddr)) { int i,j; /* Counters */ int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ @@ -1740,7 +1741,7 @@ * YY/MM/DD uid Description -*/ -unsigned int SK_rom_addr(void) +__initfunc(unsigned int SK_rom_addr(void)) { int i,j; int rom_found = 0; diff -u --recursive --new-file v2.1.36/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- v2.1.36/linux/drivers/net/skeleton.c Sun Feb 2 05:18:42 1997 +++ linux/drivers/net/skeleton.c Thu May 1 12:05:01 1997 @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,7 @@ /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int netcard_portlist[] = +static unsigned int netcard_portlist[] __initdata = { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; /* use 0 for production, 1 for verification, >2 for debug */ @@ -126,8 +127,8 @@ struct netdev_entry netcard_drv = {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist}; #else -int -netcard_probe(struct device *dev) +__initfunc(int +netcard_probe(struct device *dev)) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -154,7 +155,7 @@ * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */ -static int netcard_probe1(struct device *dev, int ioaddr) +__initfunc(static int netcard_probe1(struct device *dev, int ioaddr)) { static unsigned version_printed = 0; int i; diff -u --recursive --new-file v2.1.36/linux/drivers/net/soundmodem/sm.c linux/drivers/net/soundmodem/sm.c --- v2.1.36/linux/drivers/net/soundmodem/sm.c Fri Apr 4 08:52:22 1997 +++ linux/drivers/net/soundmodem/sm.c Thu May 1 12:05:01 1997 @@ -56,6 +56,7 @@ #include #include #include +#include #include "sm.h" /* --------------------------------------------------------------------- */ @@ -662,10 +663,7 @@ /* --------------------------------------------------------------------- */ -#ifdef MODULE -static -#endif /* MODULE */ -int sm_init(void) +__initfunc(int sm_init(void)) { int i, j, found = 0; char set_hw = 1; @@ -800,7 +798,7 @@ * modem: afsk1200, fsk9600 */ -void sm_setup(char *str, int *ints) +__initfunc(void sm_setup(char *str, int *ints)) { int i; diff -u --recursive --new-file v2.1.36/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.1.36/linux/drivers/net/wavelan.c Wed Apr 23 19:01:20 1997 +++ linux/drivers/net/wavelan.c Thu May 1 12:05:01 1997 @@ -64,8 +64,8 @@ /* * Translate PSA irq parameter to irq number */ -static int -wv_psa_to_irq(u_char irqval) +__initfunc(static int +wv_psa_to_irq(u_char irqval)) { int irq; @@ -3999,8 +3999,8 @@ * device structure * (called by wavelan_probe() & via init_module()) */ -static int -wavelan_config(device * dev) +__initfunc(static int +wavelan_config(device * dev)) { u_long ioaddr = dev->base_addr; u_char irq_mask; @@ -4112,11 +4112,9 @@ * the initial value of dev->base_addr. * We follow the example in drivers/net/ne.c.) * (called in "Space.c") - * As this function is called outside the wavelan module, it should be - * declared extern, but it seem to cause troubles... */ -/* extern */ int -wavelan_probe(device * dev) +__initfunc(int +wavelan_probe(device * dev)) { short base_addr; mac_addr mac; /* Mac address (check wavelan existence) */ diff -u --recursive --new-file v2.1.36/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h --- v2.1.36/linux/drivers/net/wavelan.p.h Wed Apr 23 19:01:20 1997 +++ linux/drivers/net/wavelan.p.h Thu May 1 12:05:01 1997 @@ -305,6 +305,7 @@ #include #include #include +#include #include /* Wireless extensions */ diff -u --recursive --new-file v2.1.36/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.36/linux/drivers/pci/pci.c Wed Apr 23 19:01:21 1997 +++ linux/drivers/pci/pci.c Thu May 1 12:05:01 1997 @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -576,8 +577,8 @@ /* * Turn on/off PCI bridge optimization. This should allow benchmarking. */ -static void burst_bridge(unsigned char bus, unsigned char devfn, - unsigned char pos, int turn_on) +__initfunc(static void burst_bridge(unsigned char bus, unsigned char devfn, + unsigned char pos, int turn_on)) { #ifdef CONFIG_PCI_OPTIMIZE struct bridge_mapping_type *bmap; @@ -791,7 +792,7 @@ * pci_malloc() returns initialized memory of size SIZE. Can be * used only while pci_init() is active. */ -static void *pci_malloc(long size, unsigned long *mem_startp) +__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp)) { void *mem; @@ -805,7 +806,7 @@ } -static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) +__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)) { unsigned int devfn, l, max; unsigned char cmd, tmp, hdr_type = 0; @@ -980,12 +981,12 @@ } -unsigned long pci_init (unsigned long mem_start, unsigned long mem_end) +__initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_end)) { mem_start = pcibios_init(mem_start, mem_end); if (!pcibios_present()) { - printk("pci_init: no BIOS32 detected\n"); + printk("pci_init: no PCI BIOS detected\n"); return mem_start; } diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c --- v2.1.36/linux/drivers/sbus/audio/amd7930.c Mon Mar 17 14:54:27 1997 +++ linux/drivers/sbus/audio/amd7930.c Thu May 1 12:05:01 1997 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.1.36/linux/drivers/sbus/audio/cs4231.c Mon Mar 17 14:54:28 1997 +++ linux/drivers/sbus/audio/cs4231.c Thu May 1 12:05:01 1997 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c --- v2.1.36/linux/drivers/sbus/char/creator.c Wed Apr 23 19:01:21 1997 +++ linux/drivers/sbus/char/creator.c Sun Apr 27 15:13:50 1997 @@ -47,52 +47,3 @@ fb->unblank = 0; fb->type.fb_depth = 8; } -/* - * creator.c: Linux/Sun Ultra Creator console support. - * - * Copyright (C) 1997 MIguel de Icaza (miguel@nuclecu.unam.mx) - * - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../char/vt_kern.h" -#include "../../char/selection.h" -#include "../../char/console_struct.h" -#include "fb.h" - -__initfunc(void creator_setup (fbinfo_t *fb, int slot, int con_node, unsigned long creator, int creator_io)) -{ - uint bases [2]; - unsigned long *p; - - if (!creator) { - prom_getproperty (con_node, "address", (char *) &bases[0], 4); - prom_printf ("Bases: %x %x\n", bases [0], bases [1]); - p = (unsigned long *) creator = bases[0]; - fb->base = creator; - fb->base = 0xff168000; - } - - fb->type.fb_cmsize = 256; - fb->mmap = 0; - fb->loadcmap = 0; - fb->setcursor = 0; - fb->setcursormap = 0; - fb->setcurshape = 0; - fb->ioctl = 0; - fb->switch_from_graph = 0; - fb->postsetup = sun_cg_postsetup; - fb->reset = 0; - fb->blank = 0; - fb->unblank = 0; - fb->type.fb_depth = 8; -} diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c --- v2.1.36/linux/drivers/sbus/char/sunserial.c Wed Apr 23 19:01:21 1997 +++ linux/drivers/sbus/char/sunserial.c Sun Apr 27 15:08:01 1997 @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.38 1997/04/14 17:05:00 jj Exp $ +/* $Id: sunserial.c,v 1.39 1997/04/23 07:45:26 ecd Exp $ * serial.c: Serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -866,10 +866,10 @@ i = cflag & CBAUD; if (cflag & CBAUDEX) { i &= ~CBAUDEX; - if (i != 1) + if (i != 5) info->tty->termios->c_cflag &= ~CBAUDEX; else - i += 15; + i = 16; } if (i == 15) { if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_HI) @@ -1857,7 +1857,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.38 $"; + char *revision = "$Revision: 1.39 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/char/vfc.h linux/drivers/sbus/char/vfc.h --- v2.1.36/linux/drivers/sbus/char/vfc.h Mon Apr 14 16:28:14 1997 +++ linux/drivers/sbus/char/vfc.h Thu May 1 12:05:01 1997 @@ -157,10 +157,16 @@ #define VFC_STATUS_CAPTURE 0x08000000 -#ifdef VFC_DEBUG -#define VFC_DEBUG_PRINTK(a) printk a +#ifdef VFC_IOCTL_DEBUG +#define VFC_IOCTL_DEBUG_PRINTK(a) printk a #else -#define VFC_DEBUG_PRINTK(a) +#define VFC_IOCTL_DEBUG_PRINTK(a) +#endif + +#ifdef VFC_I2C_DEBUG +#define VFC_I2C_DEBUG_PRINTK(a) printk a +#else +#define VFC_I2C_DEBUG_PRINTK(a) #endif #endif /* _LINUX_VFC_H_ */ diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c --- v2.1.36/linux/drivers/sbus/char/vfc_dev.c Mon Apr 14 16:28:14 1997 +++ linux/drivers/sbus/char/vfc_dev.c Thu May 1 12:05:01 1997 @@ -3,11 +3,11 @@ * * Driver for the Videopix Frame Grabber. * - * In order to use the VFC you need to progeam the video controller + * In order to use the VFC you need to program the video controller * chip. This chip is the Phillips SAA9051. You need to call their * documentation ordering line to get the docs. * - * Their is very little documentation on the VFC itself. There is + * There is very little documentation on the VFC itself. There is * some useful info that can be found in the manuals that come with * the card. I will hopefully write some better docs at a later date. * @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,12 +31,11 @@ #include #include #include -#include #define VFC_MAJOR (60) #if 0 -#define VFC_DEBUG +#define VFC_IOCTL_DEBUG #endif #include "vfc.h" @@ -133,30 +133,27 @@ dev->control_reg=0; dev->poll_wait=NULL; dev->busy=0; - /* initialize the timer struct */ return 0; } int init_vfc_device(struct linux_sbus_device *sdev,struct vfc_dev *dev, int instance) { - struct linux_prom_registers reg; if(!dev) { printk(KERN_ERR "VFC: Bogus pointer passed\n"); return -ENOMEM; } printk("Initializing vfc%d\n",instance); dev->regs=NULL; - memcpy(®,&sdev->reg_addrs[0],sizeof(struct linux_prom_registers)); - prom_apply_sbus_ranges(sdev->my_bus, ®, sdev->num_registers, sdev); - dev->regs=sparc_alloc_io(reg.phys_addr, 0, + prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev); + dev->regs=sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, sizeof(struct vfc_regs), vfcstr, - reg.which_io, 0x0); - dev->which_io=reg.which_io; - dev->phys_regs=(struct vfc_regs *)reg.phys_addr; + sdev->reg_addrs[0].which_io, 0x0); + dev->which_io=sdev->reg_addrs[0].which_io; + dev->phys_regs=(struct vfc_regs *)sdev->reg_addrs[0].phys_addr; if(!dev->regs) return -EIO; printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", - instance,(unsigned long)reg.phys_addr,(unsigned long)dev->regs); + instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); if(init_vfc_devstruct(dev,instance)) return -EINVAL; if(init_vfc_hw(dev)) return -EIO; @@ -191,52 +188,58 @@ return 0; } -static int vfc_release(struct inode *inode,struct file *file) +static void vfc_release(struct inode *inode,struct file *file) { struct vfc_dev *dev; dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return -EINVAL; - if(!dev->busy) return 0; + if(!dev) return; + if(!dev->busy) return; dev->busy=0; MOD_DEC_USE_COUNT; - return 0; + return; } static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) { struct vfc_debug_inout inout; unsigned char *buffer; + int ret; + + if(!suser()) return -EPERM; switch(cmd) { case VFC_I2C_SEND: - if(copy_from_user(&inout, (void *)arg, sizeof(inout))) + if(copy_from_user(&inout, (void *)arg, sizeof(inout))) { return -EFAULT; + } buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL); if (!buffer) return -ENOMEM; - if(copy_from_user(buffer, inout.buffer, inout.len*sizeof(char))) { - kfree_s(buffer,inout.len); + + if(copy_from_user(buffer, inout.buffer, + inout.len*sizeof(char));) { + kfree_s(buffer,inout.len*sizeof(char)); return -EFAULT; } + vfc_lock_device(dev); inout.ret= vfc_i2c_sendbuf(dev,inout.addr & 0xff, inout.buffer,inout.len); - if(copy_to_user((void *)arg,&inout,sizeof(inout))) { - kfree_s(buffer,inout.len); + + if (copy_to_user((void *)arg,&inout,sizeof(inout))) { + kfree_s(buffer, inout.len); return -EFAULT; } vfc_unlock_device(dev); - kfree_s(buffer, inout.len); - break; case VFC_I2C_RECV: - - if(copy_from_user(&inout, (void *)arg, sizeof(inout))) + if (copy_from_user(&inout, (void *)arg, sizeof(inout))) { return -EFAULT; + } buffer = kmalloc(inout.len, GFP_KERNEL); if (!buffer) @@ -248,11 +251,11 @@ ,buffer,inout.len); vfc_unlock_device(dev); - if(copy_to_user(inout.buffer, buffer, inout.len)) { + if (copy_to_user(inout.buffer, buffer, inout.len)) { kfree_s(buffer,inout.len); return -EFAULT; } - if(copy_to_user((void *)arg,&inout,sizeof(inout))) { + if (copy_to_user((void *)arg,&inout,sizeof(inout))) { kfree_s(buffer,inout.len); return -EFAULT; } @@ -306,12 +309,10 @@ struct vfc_dev *dev, unsigned long arg) { int setcmd,ret=0; - if(copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int))) + if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int))) return -EFAULT; -#if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", - dev->instance,setcmd)); -#endif + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", + dev->instance,setcmd)); switch(setcmd) { case MEMPRST: vfc_lock_device(dev); @@ -359,13 +360,14 @@ { int ret=0; int cmd; + if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_port_change_ioctl\n",dev->instance)); return -EFAULT; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", dev->instance,cmd)); switch(cmd) { @@ -424,12 +426,12 @@ int ret=0; int cmd; if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_set_video_ioctl\n",dev->instance)); - return -EFAULT; + return ret; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", dev->instance,cmd)); switch(cmd) { @@ -490,12 +492,12 @@ else status=PAL_NOCOLOR; } - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance, + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance, status,buf[0])); - if(copy_to_user((void *)arg,&status,sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " + if (copy_to_user((void *)arg,&status,sizeof(unsigned int))) { + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " "vfc_get_video_ioctl\n",dev->instance)); - return -EFAULT; + return ret; } return ret; } @@ -513,11 +515,13 @@ switch(cmd & 0x0000ffff) { case VFCGCTRL: #if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance)); #endif tmp=dev->regs->control; - if(copy_to_user((void *)arg,&tmp,sizeof(unsigned int))) - return -EFAULT; + if(copy_to_user((void *)arg,&tmp, sizeof(unsigned int))) { + ret=-EFAULT; + break; + } ret=0; break; case VFCSCTRL: @@ -530,12 +534,9 @@ ret=vfc_set_video_ioctl(inode,file,dev,arg); break; case VFCHUE: -#if 0 - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance)); -#endif - + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance)); if(copy_from_user(&tmp,(void *)arg,sizeof(unsigned int))) { - VFC_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " "to IOCTL(VFCHUE)",dev->instance)); ret=-EFAULT; } else { @@ -549,7 +550,7 @@ break; case VFCRDINFO: ret=-EINVAL; - VFC_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance)); break; default: ret=vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)), @@ -584,8 +585,9 @@ return 0; } -static long long vfc_lseek(struct inode *inode, struct file *file, - long long offset, int origin) + +static int vfc_lseek(struct inode *inode, struct file *file, + off_t offset, int origin) { return -ESPIPE; } @@ -595,13 +597,12 @@ NULL, /* vfc_write */ NULL, /* vfc_read */ NULL, /* vfc_readdir */ - NULL, /* vfc_poll */ + NULL, /* vfc_select */ vfc_ioctl, vfc_mmap, vfc_open, vfc_release, }; - static int vfc_probe(void) { diff -u --recursive --new-file v2.1.36/linux/drivers/sbus/char/vfc_i2c.c linux/drivers/sbus/char/vfc_i2c.c --- v2.1.36/linux/drivers/sbus/char/vfc_i2c.c Mon Apr 14 16:28:14 1997 +++ linux/drivers/sbus/char/vfc_i2c.c Thu May 1 12:05:01 1997 @@ -31,8 +31,8 @@ #include #include -#if 0 -#define VFC_DEBUG +#if 0 +#define VFC_I2C_DEBUG #endif #include "vfc.h" @@ -72,6 +72,8 @@ void vfc_i2c_delay_wakeup(struct vfc_dev *dev) { + /* Used to profile code and eliminate too many delays */ + VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n",dev->instance)); wake_up(&dev->poll_wait); } @@ -95,14 +97,14 @@ int vfc_init_i2c_bus(struct vfc_dev *dev) { - dev->regs->i2c_s1= ENABLE_SERIAL | ACK; + dev->regs->i2c_s1= ENABLE_SERIAL | SELECT(S0) | ACK; vfc_i2c_reset_bus(dev); return 0; } int vfc_i2c_reset_bus(struct vfc_dev *dev) { - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", + VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", dev->instance)); if(!dev) return -EINVAL; if(!dev->regs) return -EINVAL; @@ -110,7 +112,7 @@ dev->regs->i2c_s1=SEND_I2C_STOP | ACK; vfc_i2c_delay(dev); dev->regs->i2c_s1=CLEAR_I2C_BUS; - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", + VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", dev->instance, dev->regs->i2c_s1)); return 0; } @@ -146,7 +148,7 @@ { int ret,raddr; #if 1 - dev->regs->i2c_s1=SEND_I2C_STOP; + dev->regs->i2c_s1=SEND_I2C_STOP | ACK; dev->regs->i2c_s1=SELECT(S0) | ENABLE_SERIAL; vfc_i2c_delay(dev); #endif @@ -154,12 +156,12 @@ switch(mode) { case VFC_I2C_READ: dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1); - VFC_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n", dev->instance,addr | 0x1)); break; case VFC_I2C_WRITE: dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr & ~0x1); - VFC_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", dev->instance,addr & ~0x1)); break; default: @@ -215,7 +217,7 @@ int ret; if(last) { dev->regs->i2c_reg=NEGATIVE_ACK; - VFC_DEBUG_PRINTK((KERN_DEBUG "vfc%d: sending negative ack\n", + VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", dev->instance)); } else { dev->regs->i2c_s1=ACK; @@ -255,6 +257,8 @@ printk(KERN_ERR "vfc%d: " "VFC error while recieving byte\n", dev->instance); + dev->regs->i2c_s1=SEND_I2C_STOP; + ret=-EINVAL; } buf++; } @@ -286,7 +290,7 @@ ret=vfc_i2c_xmit_byte(dev,buf); switch(ret) { case XMIT_LAST_BYTE: - VFC_DEBUG_PRINTK(("vfc%d: " + VFC_I2C_DEBUG_PRINTK(("vfc%d: " "Reciever ended transmission with " " %d bytes remaining\n", dev->instance,count)); diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.36/linux/drivers/scsi/Config.in Mon Apr 14 16:28:15 1997 +++ linux/drivers/scsi/Config.in Mon May 5 10:00:25 1997 @@ -82,10 +82,13 @@ fi dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI -if [ "$CONFIG_PCI" = "y" ]; then +if [ "$CONFIG_PCI" = "y"]; then dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI fi dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI +if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_AM53C974" != "y"]; then + dep_tristate 'Tekram DC-390(T) (AMD PCscsi) SCSI support' CONFIG_SCSI_DC390T $CONFIG_SCSI +fi dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.36/linux/drivers/scsi/Makefile Mon Apr 14 16:28:15 1997 +++ linux/drivers/scsi/Makefile Mon May 5 10:00:25 1997 @@ -185,6 +185,14 @@ endif endif +ifeq ($(CONFIG_SCSI_DC390T),y) +L_OBJS += tmscsim.o +else + ifeq ($(CONFIG_SCSI_DC390T),m) + M_OBJS += tmscsim.o + endif +endif + ifeq ($(CONFIG_SCSI_AM53C974),y) L_OBJS += AM53C974.o else diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c --- v2.1.36/linux/drivers/scsi/a2091.c Wed Apr 23 19:01:21 1997 +++ linux/drivers/scsi/a2091.c Thu May 1 12:05:01 1997 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -190,7 +191,7 @@ static int num_a2091 = 0; -int a2091_detect(Scsi_Host_Template *tpnt) +__initfunc(int a2091_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; struct Scsi_Host *instance; @@ -243,13 +244,11 @@ int a2091_release(struct Scsi_Host *instance) { #ifdef MODULE -DMA(instance)->CNTR = 0; -zorro_unconfig_board(instance->unique_id, 0); -if (--num_a2091 == 0) - free_irq(IRQ_AMIGA_PORTS, a2091_intr); -wd33c93_release(); + DMA(instance)->CNTR = 0; + zorro_unconfig_board(instance->unique_id, 0); + if (--num_a2091 == 0) + free_irq(IRQ_AMIGA_PORTS, a2091_intr); + wd33c93_release(); #endif -return 1; + return 1; } - - diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c --- v2.1.36/linux/drivers/scsi/a3000.c Wed Apr 23 19:01:21 1997 +++ linux/drivers/scsi/a3000.c Thu May 1 12:05:02 1997 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -166,7 +167,7 @@ } } -int a3000_detect(Scsi_Host_Template *tpnt) +__initfunc(int a3000_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/atari_NCR5380.c linux/drivers/scsi/atari_NCR5380.c --- v2.1.36/linux/drivers/scsi/atari_NCR5380.c Wed Apr 23 19:01:22 1997 +++ linux/drivers/scsi/atari_NCR5380.c Thu May 1 12:05:02 1997 @@ -323,7 +323,7 @@ static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */ -static void init_tags( void ) +__initfunc(static void init_tags( void )) { int target, lun; TAG_ALLOC *ta; @@ -665,7 +665,7 @@ } -static void NCR5380_all_init (void) +static inline void NCR5380_all_init (void) { static int done = 0; if (!done) { @@ -684,7 +684,7 @@ * Inputs : instance, pointer to this instance. Unused. */ -static void NCR5380_print_options (struct Scsi_Host *instance) +__initfunc(static void NCR5380_print_options (struct Scsi_Host *instance)) { printk(" generic options" #ifdef AUTOSENSE @@ -848,7 +848,7 @@ * */ -static void NCR5380_init (struct Scsi_Host *instance, int flags) +__initfunc(static void NCR5380_init (struct Scsi_Host *instance, int flags)) { int i; SETUP_HOSTDATA(instance); diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c --- v2.1.36/linux/drivers/scsi/atari_scsi.c Wed Apr 23 19:01:22 1997 +++ linux/drivers/scsi/atari_scsi.c Thu May 1 12:05:02 1997 @@ -89,6 +89,7 @@ #include #include #include +#include #include #include @@ -765,7 +766,7 @@ } #endif -void atari_scsi_setup( char *str, int *ints ) +__initfunc(void atari_scsi_setup( char *str, int *ints )) { /* Format of atascsi parameter is: * atascsi=,,,, @@ -869,7 +870,7 @@ } -static void atari_scsi_reset_boot( void ) +__initfunc(static void atari_scsi_reset_boot( void )) { unsigned long end; diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/dc390.h linux/drivers/scsi/dc390.h --- v2.1.36/linux/drivers/scsi/dc390.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/dc390.h Thu May 8 13:54:23 1997 @@ -0,0 +1,147 @@ +/*********************************************************************** + * FILE NAME : DC390.H * + * BY : C.L. Huang * + * Description: Device Driver for Tekram DC-390(T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + +/* Kernel version autodetection */ + +#include +/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ +#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) + +#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,50) +#define VERSION_ELF_1_2_13 +#elseif LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,95) +#define VERSION_1_3_85 +#else +#define VERSION_2_0_0 +#endif + +/* + * AMD 53C974 driver, header file + */ + +#ifndef DC390_H +#define DC390_H + +#if defined(HOSTS_C) || defined(MODULE) + +#ifdef VERSION_2_0_0 +#include +#else +#include +#endif + +extern int DC390_detect(Scsi_Host_Template *psht); +extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); +extern int DC390_abort(Scsi_Cmnd *cmd); + +#ifdef VERSION_2_0_0 +extern int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags); +#else +extern int DC390_reset(Scsi_Cmnd *cmd); +#endif + +#ifdef VERSION_ELF_1_2_13 +extern int DC390_bios_param(Disk *disk, int devno, int geom[]); +#else +extern int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]); +#endif + +#ifdef MODULE +static int DC390_release(struct Scsi_Host *); +#else +#define DC390_release NULL +#endif + +#ifndef VERSION_ELF_1_2_13 +extern struct proc_dir_entry proc_scsi_tmscsim; +extern int tmscsim_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); +#endif + +#ifdef VERSION_2_0_0 + +#define DC390_T { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsim, /* *proc_dir */ \ + tmscsim_proc_info, /* (*proc_info)() */ \ + "Tekram DC390(T) V1.10 Dec-05-1996", /* *name */ \ + DC390_detect, \ + DC390_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + SG_ALL, \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + + +#ifdef VERSION_1_3_85 + +#define DC390_T { \ + NULL, /* *next */ \ + NULL, /* *usage_count */ \ + &proc_scsi_tmscsim, /* *proc_dir */ \ + tmscsim_proc_info, /* (*proc_info)() */ \ + "Tekram DC390(T) V1.10 Dec-05-1996", /* *name */ \ + DC390_detect, \ + DC390_release, /* (*release)() */ \ + NULL, /* *(*info)() */ \ + NULL, /* (*command)() */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + SG_ALL, \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + + +#ifdef VERSION_ELF_1_2_13 + +#define DC390_T { \ + NULL, \ + NULL, \ + "Tekram DC390(T) V1.10 Dec-05-1996",\ + DC390_detect, \ + DC390_release, \ + NULL, /* info */ \ + NULL, /* command, deprecated */ \ + DC390_queue_command, \ + DC390_abort, \ + DC390_reset, \ + NULL, /* slave attach */\ + DC390_bios_param, \ + 10,/* can queue(-1) */ \ + 7, /* id(-1) */ \ + 16,/* old (SG_ALL) */ \ + 2, /* cmd per lun(2) */ \ + 0, /* present */ \ + 0, /* unchecked isa dma */ \ + DISABLE_CLUSTERING \ + } +#endif + +#endif /* defined(HOSTS_C) || defined(MODULE) */ + +#endif /* DC390_H */ diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c --- v2.1.36/linux/drivers/scsi/gvp11.c Wed Apr 23 19:01:22 1997 +++ linux/drivers/scsi/gvp11.c Thu May 1 12:05:02 1997 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -198,7 +199,7 @@ static int num_gvp11 = 0; -int gvp11_detect(Scsi_Host_Template *tpnt) +__initfunc(int gvp11_detect(Scsi_Host_Template *tpnt)) { static unsigned char called = 0; struct Scsi_Host *instance; diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.36/linux/drivers/scsi/hosts.c Wed Apr 23 19:01:22 1997 +++ linux/drivers/scsi/hosts.c Mon May 5 10:00:25 1997 @@ -158,6 +158,10 @@ #include "NCR53c406a.h" #endif +#ifdef CONFIG_SCSI_DC390T +#include "dc390.h" +#endif + #ifdef CONFIG_SCSI_AM53C974 #include "AM53C974.h" #endif @@ -309,6 +313,9 @@ #endif #ifdef CONFIG_SCSI_EATA EATA, +#endif +#ifdef CONFIG_SCSI_DC390T + DC390_T, #endif #ifdef CONFIG_SCSI_AM53C974 AM53C974, diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/scsiiom.c linux/drivers/scsi/scsiiom.c --- v2.1.36/linux/drivers/scsi/scsiiom.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/scsiiom.c Mon May 5 10:00:25 1997 @@ -0,0 +1,1540 @@ +/*********************************************************************** + * FILE NAME : SCSIIOM.C * + * BY : C.L. Huang, ching@tekram.com.tw * + * Description: Device Driver for Tekram DC-390 (T) PCI SCSI * + * Bus Master Host Adapter * + ***********************************************************************/ + + +static USHORT +DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + USHORT ioport, rc; + UCHAR bval, bval1, i, cnt; + PUCHAR ptr; + ULONG wlval; + + pSRB->TagNumber = 31; + ioport = pACB->IOPortBase; + bval = pDCB->UnitSCSIID; + outb(bval,ioport+Scsi_Dest_ID); + bval = pDCB->SyncPeriod; + outb(bval,ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb(bval,ioport+Sync_Offset); + bval = pDCB->CtrlR1; + outb(bval,ioport+CtrlReg1); + bval = pDCB->CtrlR3; + outb(bval,ioport+CtrlReg3); + bval = pDCB->CtrlR4; + outb(bval,ioport+CtrlReg4); + bval = CLEAR_FIFO_CMD; /* Flush FIFO */ + outb(bval,ioport+ScsiCmd); + + pSRB->ScsiPhase = SCSI_NOP0; + bval = pDCB->IdentifyMsg; + if( !(pDCB->SyncMode & EN_ATN_STOP) ) + { + if( (pSRB->CmdBlock[0] == INQUIRY) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + bval &= 0xBF; /* NO disconnection */ + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + if( pDCB->SyncMode & SYNC_ENABLE ) + { + if( !(pDCB->IdentifyMsg & 7) || + (pSRB->CmdBlock[0] != INQUIRY) ) + { + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_MSGOUT; + } + } + } + else + { + if(pDCB->SyncMode & EN_TAG_QUEUING) + { + outb(bval,ioport+ScsiFifo); + bval = MSG_SIMPLE_QTAG; + outb(bval,ioport+ScsiFifo); + wlval = 1; + bval = 0; + while( wlval & pDCB->TagMask ) + { + wlval = wlval << 1; + bval++; + } + outb(bval,ioport+ScsiFifo); + pDCB->TagMask |= wlval; + pSRB->TagNumber = bval; + bval1 = SEL_W_ATN2; + pSRB->SRBState = SRB_START_; + } + else + { + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + } + } + + if( pSRB->SRBFlag & AUTO_REQSENSE ) + { + bval = REQUEST_SENSE; + outb(bval,ioport+ScsiFifo); + bval = pDCB->IdentifyMsg << 5; + outb(bval,ioport+ScsiFifo); + bval = 0; + outb(bval,ioport+ScsiFifo); + outb(bval,ioport+ScsiFifo); + bval = sizeof(pSRB->pcmd->sense_buffer); + outb(bval,ioport+ScsiFifo); + bval = 0; + outb(bval,ioport+ScsiFifo); + } + else + { + cnt = pSRB->ScsiCmdLen; + ptr = (PUCHAR) pSRB->CmdBlock; + for(i=0; iCmdBlock[0] == INQUIRY) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + bval &= 0xBF; + outb(bval,ioport+ScsiFifo); + bval1 = SELECT_W_ATN; + pSRB->SRBState = SRB_START_; + if( pDCB->SyncMode & SYNC_ENABLE ) + { + if( !(pDCB->IdentifyMsg & 7) || + (pSRB->CmdBlock[0] != INQUIRY) ) + { + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_MSGOUT; + } + } + } + else + { + if(pDCB->SyncMode & EN_TAG_QUEUING) + { + outb(bval,ioport+ScsiFifo); + pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG; + wlval = 1; + bval = 0; + while( wlval & pDCB->TagMask ) + { + wlval = wlval << 1; + bval++; + } + pDCB->TagMask |= wlval; + pSRB->TagNumber = bval; + pSRB->MsgOutBuf[1] = bval; + pSRB->MsgCnt = 2; + bval1 = SEL_W_ATN_STOP; + pSRB->SRBState = SRB_START_; + } + else + { + outb(bval,ioport+ScsiFifo); + pSRB->MsgOutBuf[0] = MSG_NOP; + pSRB->MsgCnt = 1; + pSRB->SRBState = SRB_START_; + bval1 = SEL_W_ATN_STOP; + } + } + } + bval = inb( ioport+Scsi_Status ); + if( bval & INTERRUPT ) + { + pSRB->SRBState = SRB_READY; + pDCB->TagMask &= ~( 1 << pSRB->TagNumber ); + rc = 1; + } + else + { + pSRB->ScsiPhase = SCSI_NOP1; + pACB->pActiveDCB = pDCB; + pDCB->pActiveSRB = pSRB; + rc = 0; + outb(bval1,ioport+ScsiCmd); + } + return( rc ); +} + + +#ifndef VERSION_ELF_1_2_13 +static void +DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) +#else +static void +DC390_Interrupt( int irq, struct pt_regs *regs) +#endif +{ + PACB pACB; + PDCB pDCB; + PSRB pSRB; + USHORT ioport = 0; + USHORT phase, i; + void (*stateV)( PACB, PSRB, PUCHAR ); + UCHAR istate = 0; + UCHAR sstatus=0, istatus; + + pACB = pACB_start; + if( pACB == NULL ) + return; + for( i=0; i < adapterCnt; i++ ) + { + if( pACB->IRQLevel == (UCHAR) irq ) + { + ioport = pACB->IOPortBase; + sstatus = inb( ioport+Scsi_Status ); + if( sstatus & INTERRUPT ) + break; + else + pACB = pACB->pNextACB; + } + else + { + pACB = pACB->pNextACB; + } + } + +#ifdef DC390_DEBUG1 + printk("sstatus=%2x,",sstatus); +#endif + + if( pACB == (PACB )-1 ) + { + printk("DC390: Spurious interrupt detected!\n"); + return; + } + + istate = inb( ioport+Intern_State ); + istatus = inb( ioport+INT_Status ); + +#ifdef DC390_DEBUG1 + printk("Istatus=%2x,",istatus); +#endif + + if(istatus & DISCONNECTED) + { + DC390_Disconnect( pACB ); + return; + } + + if(istatus & RESELECTED) + { + DC390_Reselect( pACB ); + return; + } + + if(istatus & INVALID_CMD) + { + DC390_InvalidCmd( pACB ); + return; + } + + if(istatus & SCSI_RESET) + { + DC390_ScsiRstDetect( pACB ); + return; + } + + if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) ) + { + pDCB = pACB->pActiveDCB; + pSRB = pDCB->pActiveSRB; + if( pDCB ) + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + EnableMsgOut( pACB, pSRB ); + } + + phase = (USHORT) pSRB->ScsiPhase; + stateV = (void *) DC390_phase0[phase]; + stateV( pACB, pSRB, &sstatus ); + + pSRB->ScsiPhase = sstatus & 7; + phase = (USHORT) sstatus & 7; + stateV = (void *) DC390_phase1[phase]; + stateV( pACB, pSRB, &sstatus ); + } +} + + +static void +DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR sstatus, bval; + USHORT ioport; + PSGL psgl; + ULONG ResidCnt, xferCnt; + + ioport = pACB->IOPortBase; + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & PARITY_ERR ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + bval = inb(ioport+DMA_Status); + while( !(bval & DMA_XFER_DONE) ) + bval = inb(ioport+DMA_Status); + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else + { + bval = inb( ioport+Current_Fifo ); + bval &= 0x1f; + ResidCnt = (ULONG) inb(ioport+CtcReg_High); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Low); + ResidCnt += (ULONG) bval; + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGPhysAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + } + } + bval = WRITE_DIRECTION+DMA_IDLE_CMD; + outb( bval, ioport+DMA_Cmd); +} + +static void +DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR sstatus, bval; + USHORT i, ioport, residual; + PSGL psgl; + ULONG ResidCnt, xferCnt; + PUCHAR ptr; + + + ioport = pACB->IOPortBase; + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & PARITY_ERR ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + bval = inb(ioport+DMA_Status); + while( !(bval & DMA_XFER_DONE) ) + bval = inb(ioport+DMA_Status); + + bval = READ_DIRECTION+DMA_IDLE_CMD; + outb( bval, ioport+DMA_Cmd); + + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else /* phase changed */ + { + residual = 0; + bval = inb(ioport+Current_Fifo); + while( bval & 0x1f ) + { + if( (bval & 0x1f) == 1 ) + { + for(i=0; i< 0x100; i++) + { + bval = inb(ioport+Current_Fifo); + if( !(bval & 0x1f) ) + goto din_1; + else if( i == 0x0ff ) + { + residual = 1; /* ;1 residual byte */ + goto din_1; + } + } + } + else + bval = inb(ioport+Current_Fifo); + } +din_1: + bval = READ_DIRECTION+DMA_BLAST_CMD; + outb(bval, ioport+DMA_Cmd); + for(i=0; i<0x8000; i++) + { + bval = inb(ioport+DMA_Status); + if(bval & BLAST_COMPLETE) + break; + } + bval = READ_DIRECTION+DMA_IDLE_CMD; + outb(bval, ioport+DMA_Cmd); + + ResidCnt = (ULONG) inb(ioport+CtcReg_High); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid); + ResidCnt = ResidCnt << 8; + ResidCnt |= (ULONG) inb(ioport+CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGPhysAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + + if( residual ) + { + bval = inb(ioport+ScsiFifo); /* get residual byte */ +#ifndef VERSION_ELF_1_2_13 + ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr ); +#else + ptr = (PUCHAR) pSRB->SGPhysAddr; +#endif + *ptr = bval; + pSRB->SGPhysAddr++; + pSRB->TotalXferredLen++; + pSRB->SGToBeXferLen--; + } + } + } +} + +static void +DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + +static void +DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = inb(ioport+ScsiFifo); + pSRB->TargetStatus = bval; + bval++; + bval = inb(ioport+ScsiFifo); /* get message */ + pSRB->EndMessage = bval; + + *psstatus = SCSI_NOP0; + pSRB->SRBState = SRB_COMPLETED; + bval = MSG_ACCEPTED_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) ) + *psstatus = SCSI_NOP0; +} + +static void +DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport, wval, wval1; + PDCB pDCB; + PSRB psrb; + + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + + bval = inb( ioport+ScsiFifo ); + if( !(pSRB->SRBState & SRB_MSGIN_MULTI) ) + { + if(bval == MSG_DISCONNECT) + { + pSRB->SRBState = SRB_DISCONNECT; + } + else if( bval == MSG_SAVE_PTR ) + goto min6; + else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) && + (bval <= MSG_ORDER_QTAG)) ) + { + pSRB->SRBState |= SRB_MSGIN_MULTI; + pSRB->MsgInBuf[0] = bval; + pSRB->MsgCnt = 1; + pSRB->pMsgPtr = &pSRB->MsgInBuf[1]; + } + else if(bval == MSG_REJECT_) + { + bval = RESET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + if( pSRB->SRBState & DO_SYNC_NEGO) + goto set_async; + } + else if( bval == MSG_RESTORE_PTR) + goto min6; + else + goto min6; + } + else + { /* minx: */ + + *pSRB->pMsgPtr = bval; + pSRB->MsgCnt++; + pSRB->pMsgPtr++; + if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) && + (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) ) + { + if( pSRB->MsgCnt == 2) + { + pSRB->SRBState = 0; + bval = pSRB->MsgInBuf[1]; + pSRB = pDCB->pGoingSRB; + psrb = pDCB->pGoingLast; + if( pSRB ) + { + for( ;; ) + { + if(pSRB->TagNumber != bval) + { + if( pSRB == psrb ) + goto mingx0; + pSRB = pSRB->pNextSRB; + } + else + break; + } + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + EnableMsgOut( pACB, pSRB ); + } + if( !(pSRB->SRBState & SRB_DISCONNECT) ) + goto mingx0; + pDCB->pActiveSRB = pSRB; + pSRB->SRBState = SRB_DATA_XFER; + } + else + { +mingx0: + pSRB = pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; + EnableMsgOut2( pACB, pSRB ); + } + } + } + else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) ) + { + pSRB->SRBState &= ~(SRB_MSGIN_MULTI+DO_SYNC_NEGO); + if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != 1) ) + { /* reject_msg: */ + pSRB->MsgCnt = 1; + pSRB->MsgInBuf[0] = MSG_REJECT_; + bval = SET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + } + else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) ) + { +set_async: + pDCB = pSRB->pSRBDCB; + pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->CtrlR3 = FAST_CLK; /* ;non_fast */ + pDCB->CtrlR4 &= 0x3f; + pDCB->CtrlR4 |= EATER_25NS; /* ; 25ns glitch eater */ + goto re_prog; + } + else + { /* set_sync: */ + + pDCB = pSRB->pSRBDCB; + pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; + pDCB->SyncOffset &= 0x0f0; + pDCB->SyncOffset |= pSRB->MsgInBuf[4]; + pDCB->NegoPeriod = pSRB->MsgInBuf[3]; + wval = (USHORT) pSRB->MsgInBuf[3]; + wval = wval << 2; + wval--; + wval1 = wval / 25; + if( (wval1 * 25) != wval) + wval1++; + bval = FAST_CLK+FAST_SCSI; + pDCB->CtrlR4 &= 0x3f; + if(wval1 >= 8) + { + wval1--; + bval = FAST_CLK; /* ;fast clock/normal scsi */ + pDCB->CtrlR4 |= EATER_25NS; /* ;25 ns glitch eater */ + } + pDCB->CtrlR3 = bval; + pDCB->SyncPeriod = (UCHAR)wval1; +re_prog: + bval = pDCB->SyncPeriod; + outb(bval, ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb(bval, ioport+Sync_Offset); + bval = pDCB->CtrlR3; + outb(bval, ioport+CtrlReg3); + bval = pDCB->CtrlR4; + outb(bval, ioport+CtrlReg4); + SetXferRate( pACB, pDCB); + } + } + } +min6: + *psstatus = SCSI_NOP0; + bval = MSG_ACCEPTED_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir) +{ + PSGL psgl; + UCHAR bval; + USHORT ioport; + ULONG lval; + + + ioport = pACB->IOPortBase; + if( pSRB->SGIndex < pSRB->SGcount ) + { + bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */ + outb( bval, ioport+DMA_Cmd); + if( !pSRB->SGToBeXferLen ) + { + psgl = pSRB->pSegmentList; +#ifndef VERSION_ELF_1_2_13 + pSRB->SGPhysAddr = virt_to_phys( psgl->address ); +#else + pSRB->SGPhysAddr = (ULONG) psgl->address; +#endif + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + lval = pSRB->SGToBeXferLen; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_Low); + lval = lval >> 8; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_Mid); + lval = lval >> 8; + bval = (UCHAR) lval; + outb(bval,ioport+CtcReg_High); + + lval = pSRB->SGToBeXferLen; + outl(lval, ioport+DMA_XferCnt); + + lval = pSRB->SGPhysAddr; + outl( lval, ioport+DMA_XferAddr); + + bval = DMA_COMMAND+INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); + + pSRB->SRBState = SRB_DATA_XFER; + + bval = DMA_IDLE_CMD | ioDir; /* ;+EN_DMA_INT */ + outb(bval, ioport+DMA_Cmd); + + bval = DMA_START_CMD | ioDir; /* ;+EN_DMA_INT */ + outb(bval, ioport+DMA_Cmd); + } + else /* xfer pad */ + { + if( pSRB->SGcount ) + { + pSRB->AdaptStatus = H_OVER_UNDER_RUN; + pSRB->SRBStatus |= OVER_RUN; + } + bval = 0; + outb(bval,ioport+CtcReg_Low); + outb(bval,ioport+CtcReg_Mid); + outb(bval,ioport+CtcReg_High); + + pSRB->SRBState |= SRB_XFERPAD; + bval = DMA_COMMAND+XFER_PAD_BYTE; + outb(bval, ioport+ScsiCmd); +/* + bval = DMA_IDLE_CMD | ioDir; ;+EN_DMA_INT + outb(bval, ioport+DMA_Cmd); + bval = DMA_START_CMD | ioDir; ;+EN_DMA_INT + outb(bval, ioport+DMA_Cmd); +*/ + } +} + + +static void +DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR ioDir; + + ioDir = WRITE_DIRECTION; + DataIO_Comm( pACB, pSRB, ioDir); +} + +static void +DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR ioDir; + + ioDir = READ_DIRECTION; + DataIO_Comm( pACB, pSRB, ioDir); +} + +static void +DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + PDCB pDCB; + UCHAR bval; + PUCHAR ptr; + USHORT ioport, i, cnt; + + + ioport = pACB->IOPortBase; + bval = RESET_ATN_CMD; + outb(bval, ioport+ScsiCmd); + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) + { + cnt = (USHORT) pSRB->ScsiCmdLen; + ptr = (PUCHAR) pSRB->CmdBlock; + for(i=0; i < cnt; i++) + { + outb(*ptr, ioport+ScsiFifo); + ptr++; + } + } + else + { + bval = REQUEST_SENSE; + outb(bval, ioport+ScsiFifo); + pDCB = pACB->pActiveDCB; + bval = pDCB->IdentifyMsg << 5; + outb(bval, ioport+ScsiFifo); + bval = 0; + outb(bval, ioport+ScsiFifo); + outb(bval, ioport+ScsiFifo); + bval = sizeof(pSRB->pcmd->sense_buffer); + outb(bval, ioport+ScsiFifo); + bval = 0; + outb(bval, ioport+ScsiFifo); + } + pSRB->SRBState = SRB_COMMAND; + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + pSRB->SRBState = SRB_STATUS; + bval = INITIATOR_CMD_CMPLTE; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport, i, cnt; + PUCHAR ptr; + PDCB pDCB; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + pDCB = pACB->pActiveDCB; + if( !(pSRB->SRBState & SRB_MSGOUT) ) + { + cnt = pSRB->MsgCnt; + if( cnt ) + { + ptr = (PUCHAR) pSRB->MsgOutBuf; + for(i=0; i < cnt; i++) + { + outb(*ptr, ioport+ScsiFifo); + ptr++; + } + pSRB->MsgCnt = 0; + if( (pDCB->DCBFlag & ABORT_DEV_) && + (pSRB->MsgOutBuf[0] == MSG_ABORT) ) + pSRB->SRBState = SRB_ABORT_SENT; + } + else + { + bval = MSG_ABORT; /* ??? MSG_NOP */ + if( (pSRB->CmdBlock[0] == INQUIRY ) || + (pSRB->CmdBlock[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + if( pDCB->SyncMode & SYNC_ENABLE ) + goto mop1; + } + outb(bval, ioport+ScsiFifo); + } + bval = INFO_XFER_CMD; + outb( bval, ioport+ScsiCmd); + } + else + { +mop1: + bval = MSG_EXTENDED; + outb(bval, ioport+ScsiFifo); + bval = 3; /* ;length of extended msg */ + outb(bval, ioport+ScsiFifo); + bval = 1; /* ; sync nego */ + outb(bval, ioport+ScsiFifo); + bval = pDCB->NegoPeriod; + outb(bval, ioport+ScsiFifo); + bval = SYNC_NEGO_OFFSET; + outb(bval, ioport+ScsiFifo); + pSRB->SRBState |= DO_SYNC_NEGO; + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); + } +} + +static void +DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + UCHAR bval; + USHORT ioport; + + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval, ioport+ScsiCmd); + if( !(pSRB->SRBState & SRB_MSGIN) ) + { + pSRB->SRBState &= SRB_DISCONNECT; + pSRB->SRBState |= SRB_MSGIN; + } + bval = INFO_XFER_CMD; + outb(bval, ioport+ScsiCmd); +} + +static void +DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + +static void +DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ +} + + +static void +SetXferRate( PACB pACB, PDCB pDCB ) +{ + UCHAR bval; + USHORT cnt, i; + PDCB ptr; + + if( !(pDCB->IdentifyMsg & 0x07) ) + { + if( pACB->scan_devices ) + { + CurrSyncOffset = pDCB->SyncOffset; + } + else + { + ptr = pACB->pLinkDCB; + cnt = pACB->DeviceCnt; + bval = pDCB->UnitSCSIID; + for(i=0; iUnitSCSIID == bval ) + { + ptr->SyncPeriod = pDCB->SyncPeriod; + ptr->SyncOffset = pDCB->SyncOffset; + ptr->CtrlR3 = pDCB->CtrlR3; + ptr->CtrlR4 = pDCB->CtrlR4; + ptr->SyncMode = pDCB->SyncMode; + } + ptr = ptr->pNextDCB; + } + } + } + return; +} + + +static void +DC390_Disconnect( PACB pACB ) +{ + PDCB pDCB; + PSRB pSRB, psrb; + ULONG flags; + USHORT ioport, i, cnt; + UCHAR bval; + +#ifdef DC390_DEBUG0 + printk("DISC,"); +#endif + + save_flags(flags); + cli(); + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + if (!pDCB) + { +#ifdef DC390_DEBUG0 + printk("ACB:%08lx->ActiveDCB:%08lx !,",(ULONG)pACB,(ULONG)pDCB); +#endif + restore_flags(flags); return; + } + pSRB = pDCB->pActiveSRB; + pACB->pActiveDCB = 0; + pSRB->ScsiPhase = SCSI_NOP0; + bval = EN_SEL_RESEL; + outb(bval, ioport+ScsiCmd); + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + { + pSRB->SRBState = 0; + DoWaitingSRB( pACB ); + } + else if( pSRB->SRBState & SRB_ABORT_SENT ) + { + pDCB->TagMask = 0; + pDCB->DCBFlag = 0; + cnt = pDCB->GoingSRBCnt; + pDCB->GoingSRBCnt = 0; + pSRB = pDCB->pGoingSRB; + for( i=0; i < cnt; i++) + { + psrb = pSRB->pNextSRB; + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pSRB = psrb; + } + pDCB->pGoingSRB = 0; + DoWaitingSRB( pACB ); + } + else + { + if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || + !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) + { /* Selection time out */ + if( !(pACB->scan_devices) ) + { + pSRB->SRBState = SRB_READY; + RewaitSRB( pDCB, pSRB); + } + else + { + pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; + goto disc1; + } + } + else if( pSRB->SRBState & SRB_DISCONNECT ) + { + DoWaitingSRB( pACB ); + } + else if( pSRB->SRBState & SRB_COMPLETED ) + { +disc1: + if(pDCB->MaxCommand > 1) + { + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* free tag mask */ + } + pDCB->pActiveSRB = 0; + pSRB->SRBState = SRB_FREE; + SRBdone( pACB, pDCB, pSRB); + } + } + restore_flags(flags); + return; +} + + +static void +DC390_Reselect( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB pSRB; + USHORT ioport, wval; + UCHAR bval, bval1; + + +#ifdef DC390_DEBUG0 + printk("RSEL,"); +#endif + ioport = pACB->IOPortBase; + pDCB = pACB->pActiveDCB; + if( pDCB ) + { /* Arbitration lost but Reselection win */ + pSRB = pDCB->pActiveSRB; + if( !( pACB->scan_devices ) ) + { + pSRB->SRBState = SRB_READY; + RewaitSRB( pDCB, pSRB); + } + } + bval = inb(ioport+ScsiFifo); /* get ID */ + bval = bval ^ pACB->HostID_Bit; + wval = 0; + bval1 = 1; + for(;;) + { + if( !(bval & bval1) ) + { + bval1 = bval1 << 1; + wval++; + } + else + break; + } + wval |= ( (USHORT) inb(ioport+ScsiFifo) & 7) << 8; /* get LUN */ + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( wval != *((PUSHORT) &pDCB->UnitSCSIID) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + return; + } + pACB->pActiveDCB = pDCB; + if( pDCB->SyncMode & EN_TAG_QUEUING ) + { + pSRB = pACB->pTmpSRB; + pDCB->pActiveSRB = pSRB; + } + else + { + pSRB = pDCB->pActiveSRB; + if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) + { + pSRB= pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + EnableMsgOut( pACB, pSRB ); + } + else + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + EnableMsgOut( pACB, pSRB ); + } + else + pSRB->SRBState = SRB_DATA_XFER; + } + } + pSRB->ScsiPhase = SCSI_NOP0; + bval = pDCB->UnitSCSIID; + outb( bval, ioport+Scsi_Dest_ID); + bval = pDCB->SyncPeriod; + outb(bval, ioport+Sync_Period); + bval = pDCB->SyncOffset; + outb( bval, ioport+Sync_Offset); + bval = pDCB->CtrlR1; + outb(bval, ioport+CtrlReg1); + bval = pDCB->CtrlR3; + outb(bval, ioport+CtrlReg3); + bval = pDCB->CtrlR4; /* ; Glitch eater */ + outb(bval, ioport+CtrlReg4); + bval = MSG_ACCEPTED_CMD; /* ;to rls the /ACK signal */ + outb(bval, ioport+ScsiCmd); +} + + +static void +SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb; + UCHAR bval, bval1, i, j, status; + PSCSICMD pcmd; + PSCSI_INQDATA ptr; + USHORT disable_tag; + ULONG flags; + PSGL ptr2; + ULONG swlval; + + pcmd = pSRB->pcmd; + status = pSRB->TargetStatus; + if(pSRB->SRBFlag & AUTO_REQSENSE) + { + pSRB->SRBFlag &= ~AUTO_REQSENSE; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = SCSI_STAT_CHECKCOND; + if(status == SCSI_STAT_CHECKCOND) + { + pcmd->result = DID_BAD_TARGET << 16; + goto ckc_e; + } + if(pSRB->RetryCnt == 0) + { + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + pSRB->TotalXferredLen = pSRB->Segment1[1]; + if( (pSRB->TotalXferredLen) && + (pSRB->TotalXferredLen >= pcmd->underflow) ) + pcmd->result |= (DID_OK << 16); + else + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; +#ifdef DC390_DEBUG0 + printk("Cmd=%2x,Result=%8x,XferL=%8x,",pSRB->CmdBlock[0], + (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen); +#endif + goto ckc_e; + } + else + { + pSRB->RetryCnt--; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | + SCSI_STAT_CHECKCOND; + goto ckc_e; + } + pcmd->result |= (DRIVER_SENSE << 24); + pSRB->SGcount = (UCHAR) pSRB->Segment1[0]; + pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); + return; + } + } + if( status ) + { + if( status == SCSI_STAT_CHECKCOND) + { + if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) ) + { + bval = pSRB->SGcount; + swlval = 0; + ptr2 = pSRB->pSegmentList; + for( i=pSRB->SGIndex; i < bval; i++) + { + swlval += ptr2->length; + ptr2++; + } +#ifdef DC390_DEBUG0 + printk("XferredLen=%8x,NotXferLen=%8x,", + (UINT) pSRB->TotalXferredLen, (UINT) swlval); +#endif + } + RequestSense( pACB, pDCB, pSRB ); + return; + } + else if( status == SCSI_STAT_QUEUEFULL ) + { + bval = (UCHAR) pDCB->GoingSRBCnt; + bval--; + pDCB->MaxCommand = bval; + RewaitSRB( pDCB, pSRB ); + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + return; + } + else if(status == SCSI_STAT_SEL_TIMEOUT) + { + pSRB->AdaptStatus = H_SEL_TIMEOUT; + pSRB->TargetStatus = 0; + pcmd->result = DID_BAD_TARGET << 16; + } + else + { + pSRB->AdaptStatus = 0; + if( pSRB->RetryCnt ) + { + pSRB->RetryCnt--; + pSRB->TargetStatus = 0; + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); + return; + } + else + { + pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) | + (ULONG) status; + } + } + } + else + { + status = pSRB->AdaptStatus; + if(status & H_OVER_UNDER_RUN) + { + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8); + } + else if( pSRB->SRBStatus & PARITY_ERROR) + { + pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8); + } + else /* No error */ + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pcmd->result |= (DID_OK << 16); + } + } + +ckc_e: + if( pACB->scan_devices ) + { + if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + { + if(pcmd->result != (DID_OK << 16)) + { + if( pcmd->result & SCSI_STAT_CHECKCOND ) + { + goto RTN_OK; + } + else + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && + ((pcmd->lun == 0) || (pcmd->lun == pACB->max_lun)) ) + { + pACB->scan_devices = 0; + } + } + } + else + { +RTN_OK: + pPrevDCB->pNextDCB = pDCB; + pDCB->pNextDCB = pACB->pLinkDCB; + if( (pcmd->target == pACB->max_id) && (pcmd->lun == pACB->max_lun) ) + pACB->scan_devices = END_SCAN; + } + } + else if( pSRB->CmdBlock[0] == INQUIRY ) + { + if( (pcmd->target == pACB->max_id) && + (pcmd->lun == pACB->max_lun) ) + { + pACB->scan_devices = 0; + } + ptr = (PSCSI_INQDATA) (pcmd->request_buffer); + if( pcmd->use_sg ) + ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); + bval1 = ptr->DevType & SCSI_DEVTYPE; + if(bval1 == SCSI_NODEV) + { + pACB->DCBmap[pcmd->target] &= ~(1 << pcmd->lun); + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else + { + pACB->DeviceCnt++; + pPrevDCB = pDCB; + pACB->pDCB_free = (PDCB) ((ULONG) (pACB->pDCB_free) + sizeof( DC390_DCB )); + pDCB->DevType = bval1; + if(bval1 == TYPE_DISK || bval1 == TYPE_MOD) + { + if( (((ptr->Vers & 0x07) >= 2) || ((ptr->RDF & 0x0F) == 2)) && + (ptr->Flags & SCSI_INQ_CMDQUEUE) && + (pDCB->DevMode & TAG_QUEUING_) && + (pDCB->DevMode & EN_DISCONNECT_) ) + { + disable_tag = 0; + for(i=0; iMaxCommand = pACB->TagMaxNum; + pDCB->SyncMode |= EN_TAG_QUEUING; + pDCB->TagMask = 0; + } + else + { + pDCB->SyncMode |= EN_ATN_STOP; + } + } + } + } + } + } + + save_flags( flags ); + cli(); +/* ReleaseSRB( pDCB, pSRB ); */ + + if(pSRB == pDCB->pGoingSRB ) + { + pDCB->pGoingSRB = pSRB->pNextSRB; + } + else + { + psrb = pDCB->pGoingSRB; + while( psrb->pNextSRB != pSRB ) + psrb = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb; + } + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + pDCB->GoingSRBCnt--; + + DoWaitingSRB( pACB ); + restore_flags(flags); + +/* Notify cmd done */ + pcmd->scsi_done( pcmd ); + + if( pDCB->QIORBCnt ) + DoNextCmd( pACB, pDCB ); + return; +} + + +static void +DoingSRB_Done( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + PSCSICMD pcmd; + + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for( i=0; ipNextSRB; + pcmd = psrb->pcmd; + pcmd->result = DID_RESET << 16; + +/* ReleaseSRB( pDCB, pSRB ); */ + + psrb->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = psrb; + + pcmd->scsi_done( pcmd ); + psrb = psrb2; + } + pdcb->GoingSRBCnt = 0;; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +DC390_ResetSCSIBus( PACB pACB ) +{ + USHORT ioport; + UCHAR bval; + ULONG flags; + + save_flags(flags); + cli(); + pACB->ACBFlag |= RESET_DEV; + ioport = pACB->IOPortBase; + + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + + bval = RST_SCSI_BUS_CMD; + outb(bval,ioport+ScsiCmd); + + restore_flags(flags); + return; +} + + +static void +DC390_ScsiRstDetect( PACB pACB ) +{ + ULONG wlval, flags; + USHORT ioport; + UCHAR bval; + +#ifdef DC390_DEBUG0 + printk("RST_DETEC"); +#endif + save_flags(flags); + sti(); + wlval = jiffies + HZ; + while( jiffies < wlval ); /* delay 1 sec */ + + cli(); + ioport = pACB->IOPortBase; + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + bval = CLEAR_FIFO_CMD; + outb(bval,ioport+ScsiCmd); + + if( pACB->ACBFlag & RESET_DEV ) + pACB->ACBFlag |= RESET_DONE; + else + { + pACB->ACBFlag |= RESET_DETECT; + + ResetDevParam( pACB ); +/* DoingSRB_Done( pACB ); ???? */ + RecoverSRB( pACB ); + pACB->pActiveDCB = NULL; + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + } + restore_flags(flags); + return; +} + + +static void +RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) +{ + PSCSICMD pcmd; + + pSRB->SRBFlag |= AUTO_REQSENSE; + pSRB->Segment0[0] = *((PULONG) &(pSRB->CmdBlock[0])); + pSRB->Segment0[1] = *((PULONG) &(pSRB->CmdBlock[4])); + pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount); + pSRB->Segment1[1] = pSRB->TotalXferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + + pcmd = pSRB->pcmd; + + pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); + pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + pSRB->pSegmentList = &pSRB->Segmentx; + pSRB->SGcount = 1; + pSRB->SGIndex = 0; + + *((PULONG) &(pSRB->CmdBlock[0])) = 0x00000003; + pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; + *((PUSHORT) &(pSRB->CmdBlock[4])) = sizeof(pcmd->sense_buffer); + pSRB->ScsiCmdLen = 6; + + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( DC390_StartSCSI( pACB, pDCB, pSRB ) ) + RewaitSRB( pDCB, pSRB ); +} + + +static void +EnableMsgOut2( PACB pACB, PSRB pSRB ) +{ + USHORT ioport; + UCHAR bval; + + ioport = pACB->IOPortBase; + pSRB->MsgCnt = 1; + bval = SET_ATN_CMD; + outb(bval, ioport+ScsiCmd); +} + + +static void +EnableMsgOut( PACB pACB, PSRB pSRB ) +{ + pSRB->MsgOutBuf[0] = MSG_ABORT; + EnableMsgOut2( pACB, pSRB ); +} + + +static void +DC390_InvalidCmd( PACB pACB ) +{ + UCHAR bval; + USHORT ioport; + PSRB pSRB; + + pSRB = pACB->pActiveDCB->pActiveSRB; + if( pSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) + { + ioport = pACB->IOPortBase; + bval = CLEAR_FIFO_CMD; + outb(bval,(ioport+ScsiCmd)); + } +} + diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.1.36/linux/drivers/scsi/sd.c Mon Apr 7 11:35:30 1997 +++ linux/drivers/scsi/sd.c Thu May 1 12:40:30 1997 @@ -1047,7 +1047,7 @@ spintime = 0; /* Spin up drives, as required. Only do this at boot time */ - if (!MODULE_FLAG){ + /* Spinup needs to be done for module loads too. */ do{ retries = 0; while(retries < 3) @@ -1120,7 +1120,6 @@ else printk( "ready\n" ); } - } /* !MODULE_FLAG */ retries = 3; do { diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c --- v2.1.36/linux/drivers/scsi/tmscsim.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/tmscsim.c Mon May 5 10:00:25 1997 @@ -0,0 +1,1928 @@ +/*********************************************************************** + * FILE NAME : TMSCSIM.C * + * BY : C.L. Huang, ching@tekram.com.tw * + * Description: Device Driver for Tekram DC-390(T) PCI SCSI * + * Bus Master Host Adapter * + * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * + ***********************************************************************/ +/* Minor enhancements and bugfixes by * + * Kurt Garloff * + ***********************************************************************/ +/* HISTORY: * + * * + * REV# DATE NAME DESCRIPTION * + * 1.00 04/24/96 CLH First release * + * 1.01 06/12/96 CLH Fixed bug of Media Change for Removable * + * Device, scan all LUN. Support Pre2.0.10 * + * 1.02 06/18/96 CLH Fixed bug of Command timeout ... * + * 1.03 09/25/96 KG Added tmscsim_proc_info() * + * 1.04 10/11/96 CLH Updating for support KV 2.0.x * + * 1.05 10/18/96 KG Fixed bug in DC390_abort(null ptr deref)* + * 1.06 10/25/96 KG Fixed module support * + * 1.07 11/09/96 KG Fixed tmscsim_proc_info() * + * 1.08 11/18/96 KG Fixed null ptr in DC390_Disconnect() * + * 1.09 11/30/96 KG Added register the allocated IO space * + * 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset * + * pending interrupt in DC390_detect() * + ***********************************************************************/ + + +#define DC390_DEBUG + +#define SCSI_MALLOC + +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#if LINUX_VERSION_CODE < 66354 /* 1.3.50 */ +#include "../block/blk.h" +#else +#include +#endif + +#include "scsi.h" +#include "hosts.h" +#include "tmscsim.h" +#include "constants.h" +#include "sd.h" +#include + +#include "dc390.h" + +#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI + + +#ifndef VERSION_ELF_1_2_13 +struct proc_dir_entry proc_scsi_tmscsim ={ + PROC_SCSI_DC390T, 7 ,"tmscsim", + S_IFDIR | S_IRUGO | S_IXUGO, 2 + }; +#endif + +static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); + +static void SetXferRate( PACB pACB, PDCB pDCB ); +static void DC390_Disconnect( PACB pACB ); +static void DC390_Reselect( PACB pACB ); +static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void DoingSRB_Done( PACB pACB ); +static void DC390_ScsiRstDetect( PACB pACB ); +static void DC390_ResetSCSIBus( PACB pACB ); +static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void EnableMsgOut2( PACB pACB, PSRB pSRB ); +static void EnableMsgOut( PACB pACB, PSRB pSRB ); +static void DC390_InvalidCmd( PACB pACB ); + +int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ); +void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ); + +#ifdef MODULE +static int DC390_release(struct Scsi_Host *host); +static int DC390_shutdown (struct Scsi_Host *host); +#endif + + +static PSHT pSHT_start = NULL; +static PSH pSH_start = NULL; +static PSH pSH_current = NULL; +static PACB pACB_start= NULL; +static PACB pACB_current = NULL; +static PDCB pPrevDCB = NULL; +static USHORT adapterCnt = 0; +static USHORT InitialTime = 0; +static USHORT CurrSyncOffset = 0; +static ULONG mech1addr; +static UCHAR mech2bus, mech2Agent, mech2CfgSPenR; + +static PVOID DC390_phase0[]={ + DC390_DataOut_0, + DC390_DataIn_0, + DC390_Command_0, + DC390_Status_0, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOut_0, + DC390_MsgIn_0, + DC390_Nop_1 + }; + +static PVOID DC390_phase1[]={ + DC390_DataOutPhase, + DC390_DataInPhase, + DC390_CommandPhase, + DC390_StatusPhase, + DC390_Nop_0, + DC390_Nop_0, + DC390_MsgOutPhase, + DC390_MsgInPhase, + DC390_Nop_1, + }; + +UCHAR eepromBuf[MAX_ADAPTER_NUM][128]; + + +UCHAR clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; + +UCHAR baddevname1[2][28] ={ + "SEAGATE ST3390N 9546", + "HP C3323-300 4269"}; + +#define BADDEVCNT 2 + + +/*********************************************************************** + * + * + * + **********************************************************************/ +static void +QLinkcmd( PSCSICMD cmd, PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + if( !pDCB->QIORBCnt ) + { + pDCB->pQIORBhead = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + else + { + pcmd = pDCB->pQIORBtail; + pcmd->next = cmd; + pDCB->pQIORBtail = cmd; + pDCB->QIORBCnt++; + cmd->next = NULL; + } + + restore_flags(flags); +} + + +static PSCSICMD +Getcmd( PDCB pDCB ) +{ + ULONG flags; + PSCSICMD pcmd; + + save_flags(flags); + cli(); + + pcmd = pDCB->pQIORBhead; + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + + restore_flags(flags); + return( pcmd ); +} + + +static PSRB +GetSRB( PACB pACB ) +{ + ULONG flags; + PSRB pSRB; + + save_flags(flags); + cli(); + + pSRB = pACB->pFreeSRB; + if( pSRB ) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + restore_flags(flags); + return( pSRB ); +} + + +static void +RewaitSRB0( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + ULONG flags; + + save_flags(flags); + cli(); + + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + restore_flags(flags); +} + + +static void +RewaitSRB( PDCB pDCB, PSRB pSRB ) +{ + PSRB psrb1; + ULONG flags; + UCHAR bval; + + save_flags(flags); + cli(); + pDCB->GoingSRBCnt--; + psrb1 = pDCB->pGoingSRB; + if( pSRB == psrb1 ) + { + pDCB->pGoingSRB = psrb1->pNextSRB; + } + else + { + while( pSRB != psrb1->pNextSRB ) + psrb1 = psrb1->pNextSRB; + psrb1->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pGoingLast ) + pDCB->pGoingLast = psrb1; + } + if( (psrb1 = pDCB->pWaitingSRB) ) + { + pSRB->pNextSRB = psrb1; + pDCB->pWaitingSRB = pSRB; + } + else + { + pSRB->pNextSRB = NULL; + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } + + bval = pSRB->TagNumber; + pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ + restore_flags(flags); +} + + +static void +DoWaitingSRB( PACB pACB ) +{ + ULONG flags; + PDCB ptr, ptr1; + PSRB pSRB; + + save_flags(flags); + cli(); + + if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + { + ptr = pACB->pDCBRunRobin; + if( !ptr ) + { + ptr = pACB->pLinkDCB; + pACB->pDCBRunRobin = ptr; + } + ptr1 = ptr; + for( ;ptr1; ) + { + pACB->pDCBRunRobin = ptr1->pNextDCB; + if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || + !( pSRB = ptr1->pWaitingSRB ) ) + { + if(pACB->pDCBRunRobin == ptr) + break; + ptr1 = ptr1->pNextDCB; + } + else + { + if( !DC390_StartSCSI(pACB, ptr1, pSRB) ) + { + ptr1->GoingSRBCnt++; + if( ptr1->pWaitLast == pSRB ) + { + ptr1->pWaitingSRB = NULL; + ptr1->pWaitLast = NULL; + } + else + { + ptr1->pWaitingSRB = pSRB->pNextSRB; + } + pSRB->pNextSRB = NULL; + + if( ptr1->pGoingSRB ) + ptr1->pGoingLast->pNextSRB = pSRB; + else + ptr1->pGoingSRB = pSRB; + ptr1->pGoingLast = pSRB; + } + break; + } + } + } + restore_flags(flags); + return; +} + + +static void +SRBwaiting( PDCB pDCB, PSRB pSRB) +{ + if( pDCB->pWaitingSRB ) + { + pDCB->pWaitLast->pNextSRB = pSRB; + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + } + else + { + pDCB->pWaitingSRB = pSRB; + pDCB->pWaitLast = pSRB; + } +} + + +static void +SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ) +{ + ULONG flags; + PDCB pDCB; + + save_flags(flags); + cli(); + + pDCB = pSRB->pSRBDCB; + if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) + { + SRBwaiting(pDCB, pSRB); + goto SND_EXIT; + } + + if( pDCB->pWaitingSRB ) + { + SRBwaiting(pDCB, pSRB); +/* pSRB = GetWaitingSRB(pDCB); */ + pSRB = pDCB->pWaitingSRB; + pDCB->pWaitingSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } + + if( !DC390_StartSCSI(pACB, pDCB, pSRB) ) + { + pDCB->GoingSRBCnt++; + if( pDCB->pGoingSRB ) + { + pDCB->pGoingLast->pNextSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + else + { + pDCB->pGoingSRB = pSRB; + pDCB->pGoingLast = pSRB; + } + } + else + RewaitSRB0( pDCB, pSRB ); + +SND_EXIT: + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, + * void (*done)(Scsi_Cmnd *)) + * + * Purpose : enqueues a SCSI command + * + * Inputs : cmd - SCSI command, done - function called on completion, with + * a pointer to the command descriptor. + * + * Returns : 0 + * + ***********************************************************************/ + +int +DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +{ + USHORT ioport, i; + Scsi_Cmnd *pcmd; + struct Scsi_Host *psh; + PACB pACB; + PDCB pDCB; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + + psh = cmd->host; + pACB = (PACB ) psh->hostdata; + ioport = pACB->IOPortBase; + +#ifdef DC390_DEBUG0 +/* if(pACB->scan_devices) */ + printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun); +#endif + + if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) ) + { + pACB->scan_devices = 0; + pPrevDCB->pNextDCB = pACB->pLinkDCB; + } + + if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) ) + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return( 0 ); + } + + if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { + if( pACB->DeviceCnt < MAX_DEVICES ) + { + pACB->DCBmap[cmd->target] |= (1 << cmd->lun); + pDCB = pACB->pDCB_free; +#ifdef DC390_DEBUG0 + printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); +#endif + DC390_initDCB( pACB, pDCB, cmd ); + } + else /* ???? */ + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + } + else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) + { +/* printk("DC390: Ignore target %d lun %d\n", + cmd->target, cmd->lun); */ + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return(0); + } + else + { + pDCB = pACB->pLinkDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + } +#ifdef DC390_DEBUG0 + printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target); +#endif + } + + cmd->scsi_done = done; + cmd->result = 0; + + save_flags(flags); + cli(); + + if( pDCB->QIORBCnt ) + { + QLinkcmd( cmd, pDCB ); + pcmd = Getcmd( pDCB ); + } + else + pcmd = cmd; + + pSRB = GetSRB( pACB ); + + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return(0); + } + +/* BuildSRB(pSRB); */ + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + pSRB->ScsiCmdLen = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGPhysAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return(0); +} + + +static void +DoNextCmd( PACB pACB, PDCB pDCB ) +{ + Scsi_Cmnd *pcmd; + PSRB pSRB; + ULONG flags; + PUCHAR ptr,ptr1; + USHORT i; + + + if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) + return; + save_flags(flags); + cli(); + + pcmd = Getcmd( pDCB ); + pSRB = GetSRB( pACB ); + if( !pSRB ) + { + QLinkcmd( pcmd, pDCB ); + restore_flags(flags); + return; + } + + pSRB->pSRBDCB = pDCB; + pSRB->pcmd = pcmd; + ptr = (PUCHAR) pSRB->CmdBlock; + ptr1 = (PUCHAR) pcmd->cmnd; + pSRB->ScsiCmdLen = pcmd->cmd_len; + for(i=0; i< pcmd->cmd_len; i++) + { + *ptr = *ptr1; + ptr++; + ptr1++; + } + if( pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + } + else if( pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + else + pSRB->SGcount = 0; + + pSRB->SGIndex = 0; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + pSRB->MsgCnt = 0; + if( pDCB->DevType != TYPE_TAPE ) + pSRB->RetryCnt = 1; + else + pSRB->RetryCnt = 0; + pSRB->SRBStatus = 0; + pSRB->SRBFlag = 0; + pSRB->SRBState = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGPhysAddr = 0; + pSRB->SGToBeXferLen = 0; + pSRB->ScsiPhase = 0; + pSRB->EndMessage = 0; + SendSRB( pcmd, pACB, pSRB ); + + restore_flags(flags); + return; +} + + +/*********************************************************************** + * Function: + * DC390_bios_param + * + * Description: + * Return the disk geometry for the given SCSI device. + ***********************************************************************/ +#ifdef VERSION_ELF_1_2_13 +int DC390_bios_param(Disk *disk, int devno, int geom[]) +#else +int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]) +#endif +{ + int heads, sectors, cylinders; + PACB pACB; + + pACB = (PACB) disk->device->host->hostdata; + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); + + if ( cylinders > 1024) + { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (255 * 63); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return (0); +} + + +/*********************************************************************** + * Function : int DC390_abort (Scsi_Cmnd *cmd) + * + * Purpose : Abort an errant SCSI command + * + * Inputs : cmd - command to abort + * + * Returns : 0 on success, -1 on failure. + ***********************************************************************/ + +int +DC390_abort (Scsi_Cmnd *cmd) +{ + ULONG flags; + PACB pACB; + PDCB pDCB, pdcb; + PSRB pSRB, psrb; + USHORT count, i; + PSCSICMD pcmd, pcmd1; + int status; + + +#ifdef DC390_DEBUG0 + printk("DC390 : Abort Cmd."); +#endif + + save_flags(flags); + cli(); + + pACB = (PACB) cmd->host->hostdata; + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + while( (pDCB->UnitSCSIID != cmd->target) || + (pDCB->UnitSCSILUN != cmd->lun) ) + { + pDCB = pDCB->pNextDCB; + if( pDCB == pdcb ) + goto NOT_RUN; + } + + if( pDCB->QIORBCnt ) + { + pcmd = pDCB->pQIORBhead; + if( pcmd == cmd ) + { + pDCB->pQIORBhead = pcmd->next; + pcmd->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + for( count = pDCB->QIORBCnt, i=0; inext == cmd ) + { + pcmd1 = pcmd->next; + pcmd->next = pcmd1->next; + pcmd1->next = NULL; + pDCB->QIORBCnt--; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + else + { + pcmd = pcmd->next; + } + } + } + + pSRB = pDCB->pWaitingSRB; + if( !pSRB ) + goto ON_GOING; + if( pSRB->pcmd == cmd ) + { + pDCB->pWaitingSRB = pSRB->pNextSRB; + goto IN_WAIT; + } + else + { + psrb = pSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + while( psrb->pNextSRB->pcmd != cmd ) + { + psrb = psrb->pNextSRB; + if( !(psrb->pNextSRB) ) + goto ON_GOING; + } + pSRB = psrb->pNextSRB; + psrb->pNextSRB = pSRB->pNextSRB; + if( pSRB == pDCB->pWaitLast ) + pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */ +IN_WAIT: + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; + cmd->next = NULL; + status = SCSI_ABORT_SUCCESS; + goto ABO_X; + } + +ON_GOING: + pSRB = pDCB->pGoingSRB; + for( count = pDCB->GoingSRBCnt, i=0; ipcmd != cmd ) + pSRB = pSRB->pNextSRB; + else + { + if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) ) + { + status = SCSI_ABORT_BUSY; + goto ABO_X; + } + else + { + status = SCSI_ABORT_SNOOZE; + goto ABO_X; + } + } + } + +NOT_RUN: + status = SCSI_ABORT_NOT_RUNNING; + +ABO_X: + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); + restore_flags(flags); + return( status ); +} + + +static void +ResetDevParam( PACB pACB ) +{ + PDCB pDCB, pdcb; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + pDCB->SyncMode &= ~SYNC_NEGO_DONE; + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->CtrlR3 = FAST_CLK; + pDCB->CtrlR4 &= NEGATE_REQACKDATA; + pDCB->CtrlR4 |= EATER_25NS; + pDCB = pDCB->pNextDCB; + } + while( pdcb != pDCB ); +} + + +static void +RecoverSRB( PACB pACB ) +{ + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + USHORT cnt, i; + + pDCB = pACB->pLinkDCB; + if( pDCB == NULL ) + return; + pdcb = pDCB; + do + { + cnt = pdcb->GoingSRBCnt; + psrb = pdcb->pGoingSRB; + for (i=0; ipNextSRB; +/* RewaitSRB( pDCB, psrb ); */ + if( pdcb->pWaitingSRB ) + { + psrb2->pNextSRB = pdcb->pWaitingSRB; + pdcb->pWaitingSRB = psrb2; + } + else + { + pdcb->pWaitingSRB = psrb2; + pdcb->pWaitLast = psrb2; + psrb2->pNextSRB = NULL; + } + } + pdcb->GoingSRBCnt = 0; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } + while( pdcb != pDCB ); +} + + +/*********************************************************************** + * Function : int DC390_reset (Scsi_Cmnd *cmd, ...) + * + * Purpose : perform a hard reset on the SCSI bus + * + * Inputs : cmd - command which caused the SCSI RESET + * + * Returns : 0 on success. + ***********************************************************************/ + +#ifdef VERSION_2_0_0 +int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) +#else +int DC390_reset (Scsi_Cmnd *cmd) +#endif +{ + USHORT ioport; + unsigned long flags; + PACB pACB; + UCHAR bval; + USHORT i; + + +#ifdef DC390_DEBUG1 + printk("DC390: RESET,"); +#endif + + pACB = (PACB ) cmd->host->hostdata; + ioport = pACB->IOPortBase; + save_flags(flags); + cli(); + bval = inb(ioport+CtrlReg1); + bval |= DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* disable interrupt */ + DC390_ResetSCSIBus( pACB ); + for( i=0; i<500; i++ ) + udelay(1000); + bval = inb(ioport+CtrlReg1); + bval &= ~DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* re-enable interrupt */ + + bval = DMA_IDLE_CMD; + outb(bval,ioport+DMA_Cmd); + bval = CLEAR_FIFO_CMD; + outb(bval,ioport+ScsiCmd); + + ResetDevParam( pACB ); + DoingSRB_Done( pACB ); + pACB->pActiveDCB = NULL; + + pACB->ACBFlag = 0; + DoWaitingSRB( pACB ); + + restore_flags(flags); +#ifdef DC390_DEBUG1 + printk("DC390: RESET1,"); +#endif + return( SCSI_RESET_SUCCESS ); +} + + +#include "scsiiom.c" + + +/*********************************************************************** + * Function : static void DC390_initDCB + * + * Purpose : initialize the internal structures for a given DCB + * + * Inputs : cmd - pointer to this scsi cmd request block structure + * + ***********************************************************************/ +void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd ) +{ + PEEprom prom; + UCHAR bval; + USHORT index; + + if( pACB->DeviceCnt == 0 ) + { + pACB->pLinkDCB = pDCB; + pACB->pDCBRunRobin = pDCB; + pDCB->pNextDCB = pDCB; + pPrevDCB = pDCB; + } + else + pPrevDCB->pNextDCB = pDCB; + + pDCB->pDCBACB = pACB; + pDCB->QIORBCnt = 0; + pDCB->UnitSCSIID = cmd->target; + pDCB->UnitSCSILUN = cmd->lun; + pDCB->pWaitingSRB = NULL; + pDCB->pGoingSRB = NULL; + pDCB->GoingSRBCnt = 0; + pDCB->pActiveSRB = NULL; + pDCB->TagMask = 0; + pDCB->MaxCommand = 1; + pDCB->AdaptIndex = pACB->AdapterIndex; + index = pACB->AdapterIndex; + pDCB->DCBFlag = 0; + + prom = (PEEprom) &eepromBuf[index][cmd->target << 2]; + pDCB->DevMode = prom->EE_MODE1; + pDCB->AdpMode = eepromBuf[index][EE_MODE2]; + + if( pDCB->DevMode & EN_DISCONNECT_ ) + bval = 0xC0; + else + bval = 0x80; + bval |= cmd->lun; + pDCB->IdentifyMsg = bval; + + pDCB->SyncMode = 0; + if( pDCB->DevMode & SYNC_NEGO_ ) + { + if( !(cmd->lun) || CurrSyncOffset ) + pDCB->SyncMode = SYNC_ENABLE; + } + + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2; + + pDCB->CtrlR1 = pACB->AdaptSCSIID; + if( pDCB->DevMode & PARITY_CHK_ ) + pDCB->CtrlR1 |= PARITY_ERR_REPO; + + pDCB->CtrlR3 = FAST_CLK; + + pDCB->CtrlR4 = EATER_25NS; + if( pDCB->AdpMode & ACTIVE_NEGATION) + pDCB->CtrlR4 |= NEGATE_REQACKDATA; +} + + +/*********************************************************************** + * Function : static void DC390_initSRB + * + * Purpose : initialize the internal structures for a given SRB + * + * Inputs : psrb - pointer to this scsi request block structure + * + ***********************************************************************/ +void DC390_initSRB( PSRB psrb ) +{ +#ifndef VERSION_ELF_1_2_13 +#ifdef DC390_DEBUG0 + printk("DC390 init: %08lx %08lx,",(ULONG)psrb,(ULONG)virt_to_bus(psrb)); +#endif + psrb->PhysSRB = virt_to_bus( psrb ); +#else + psrb->PhysSRB = (ULONG) psrb; +#endif +} + + +void DC390_linkSRB( PACB pACB ) +{ + USHORT count, i; + PSRB psrb; + + count = pACB->SRBCount; + + for( i=0; i< count; i++) + { + if( i != count - 1) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + else + pACB->SRB_array[i].pNextSRB = NULL; + psrb = (PSRB) &pACB->SRB_array[i]; + DC390_initSRB( psrb ); + } +} + + +/*********************************************************************** + * Function : static void DC390_initACB + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +void DC390_initACB( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) +{ + PACB pACB; + USHORT i; + + psh->can_queue = MAX_CMD_QUEUE; + psh->cmd_per_lun = MAX_CMD_PER_LUN; + psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID]; + psh->io_port = io_port; + psh->n_io_port = 0x80; + psh->irq = Irq; + + pACB = (PACB) psh->hostdata; + +#ifndef VERSION_ELF_1_2_13 + psh->max_id = 8; +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + psh->max_lun = 8; + else +#endif + psh->max_lun = 1; +#endif + + pACB->max_id = 7; + if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] ) + pACB->max_id--; +#ifdef CONFIG_SCSI_MULTI_LUN + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->max_lun = 7; + else +#endif + pACB->max_lun = 0; + + pACB->pScsiHost = psh; + pACB->IOPortBase = (USHORT) io_port; + pACB->pLinkDCB = NULL; + pACB->pDCBRunRobin = NULL; + pACB->pActiveDCB = NULL; + pACB->pFreeSRB = pACB->SRB_array; + pACB->SRBCount = MAX_SRB_CNT; + pACB->AdapterIndex = index; + pACB->status = 0; + pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID]; + pACB->HostID_Bit = (1 << pACB->AdaptSCSIID); + pACB->AdaptSCSILUN = 0; + pACB->DeviceCnt = 0; + pACB->IRQLevel = Irq; + pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2; + pACB->ACBFlag = 0; + pACB->scan_devices = 1; + pACB->Gmode2 = eepromBuf[index][EE_MODE2]; + if( eepromBuf[index][EE_MODE2] & LUN_CHECK ) + pACB->LUNchk = 1; + pACB->pDCB_free = &pACB->DCB_array[0]; + DC390_linkSRB( pACB ); + pACB->pTmpSRB = &pACB->TmpSRB; + DC390_initSRB( pACB->pTmpSRB ); + for(i=0; iDCBmap[i] = 0; +} + + +/*********************************************************************** + * Function : static int DC390_initAdapter + * + * Purpose : initialize the SCSI chip ctrl registers + * + * Inputs : psh - pointer to this host adapter's structure + * + ***********************************************************************/ +int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index ) +{ + USHORT ioport; + UCHAR bval; + PACB pACB, pacb; + USHORT used_irq = 0; + + pacb = pACB_start; + if( pacb != NULL ) + { + for ( ; (pacb != (PACB) -1) ; ) + { + if( pacb->IRQLevel == Irq ) + { + used_irq = 1; + break; + } + else + pacb = pacb->pNextACB; + } + } + + if( !used_irq ) + { +#ifdef VERSION_ELF_1_2_13 + if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim")) +#else + if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim", NULL)) +#endif + { + printk("DC390: register IRQ error!\n"); + return( -1 ); + } + } + + request_region(io_port,psh->n_io_port,"tmscsim"); + + ioport = (USHORT) io_port; + + pACB = (PACB) psh->hostdata; + bval = SEL_TIMEOUT; /* 250ms selection timeout */ + outb(bval,ioport+Scsi_TimeOut); + + bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */ + outb(bval,ioport+Clk_Factor); + + bval = NOP_CMD; /* NOP cmd - clear command register */ + outb(bval,ioport+ScsiCmd); + + bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */ + outb(bval,ioport+CtrlReg2); + + bval = FAST_CLK; /* fast clock */ + outb(bval,ioport+CtrlReg3); + + bval = EATER_25NS; + if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION ) + bval |= NEGATE_REQACKDATA; + outb(bval,ioport+CtrlReg4); + + bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */ + outb(bval,ioport+CtrlReg1); + + return(0); +} + + +void +DC390_EnableCfg( USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + + if(mechnum == 2) + { + outb(mech2bus, PCI_CFG2_FORWARD_REG); + outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG); + } + else + { + regval &= 0xFC; + wlval = mech1addr; + wlval |= (((ULONG)regval) & 0xff); + outl(wlval, PCI_CFG1_ADDRESS_REG); + } +} + + +void +DC390_DisableCfg( USHORT mechnum ) +{ + + if(mechnum == 2) + outb(0, PCI_CFG2_ENABLE_REG); + else + outl(0, PCI_CFG1_ADDRESS_REG); +} + + +UCHAR +DC390_inByte( USHORT mechnum, UCHAR regval ) +{ + UCHAR bval; + ULONG wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg( mechnum, regval ); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= ((USHORT) regval) & 0xff; + bval = inb(wval); + } + else + { + regval &= 3; + bval = inb(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(bval); +} + + +USHORT +DC390_inWord( USHORT mechnum, UCHAR regval ) +{ + USHORT wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wval = inw(wval); + } + else + { + regval &= 3; + wval = inw(PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(wval); +} + + +ULONG +DC390_inDword(USHORT mechnum, UCHAR regval ) +{ + ULONG wlval; + ULONG flags; + USHORT wval; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + wlval = inl(wval); + } + else + { + wlval = inl(PCI_CFG1_DATA_REG); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); + return(wlval); +} + + +void +DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ) +{ + + USHORT wval; + ULONG flags; + + save_flags(flags); + cli(); + DC390_EnableCfg(mechnum,regval); + if(mechnum == 2) + { + wval = mech2Agent; + wval <<= 8; + wval |= regval; + outb(bval, wval); + } + else + { + regval &= 3; + outb(bval, PCI_CFG1_DATA_REG | regval); + } + DC390_DisableCfg(mechnum); + restore_flags(flags); +} + + +void +DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ) +{ + + UCHAR bval; + + bval = 0; + if(mode == ENABLE_CE) + *regval = 0xc0; + else + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + if(mode == DISABLE_CE) + DC390_OutB(mechnum,*regval,bval); + udelay(160); +} + + +void +DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ) +{ + UCHAR bval; + + bval = 0; + if(Carry) + { + bval = 0x40; + *regval = 0x80; + DC390_OutB(mechnum,*regval,bval); + } + udelay(160); + bval |= 0x80; + DC390_OutB(mechnum,*regval,bval); + udelay(160); + bval = 0; + DC390_OutB(mechnum,*regval,bval); + udelay(160); +} + + +UCHAR +DC390_EEpromInDO( USHORT mechnum ) +{ + UCHAR bval,regval; + + regval = 0x80; + bval = 0x80; + DC390_OutB(mechnum,regval,bval); + udelay(160); + bval = 0x40; + DC390_OutB(mechnum,regval,bval); + udelay(160); + regval = 0x0; + bval = DC390_inByte(mechnum,regval); + if(bval == 0x22) + return(1); + else + return(0); +} + + +USHORT +EEpromGetData1( USHORT mechnum ) +{ + UCHAR i; + UCHAR carryFlag; + USHORT wval; + + wval = 0; + for(i=0; i<16; i++) + { + wval <<= 1; + carryFlag = DC390_EEpromInDO(mechnum); + wval |= carryFlag; + } + return(wval); +} + + +void +DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ) +{ + UCHAR i,j; + USHORT carryFlag; + + carryFlag = 1; + j = 0x80; + for(i=0; i<9; i++) + { + DC390_EEpromOutDI(mechnum,regval,carryFlag); + carryFlag = (EEpromCmd & j) ? 1 : 0; + j >>= 1; + } +} + + +void +DC390_ReadEEprom( USHORT mechnum, USHORT index ) +{ + UCHAR regval,cmd; + PUSHORT ptr; + USHORT i; + + ptr = (PUSHORT) &eepromBuf[index][0]; + cmd = EEPROM_READ; + for(i=0; i<0x40; i++) + { + DC390_EnDisableCE(ENABLE_CE, mechnum, ®val); + DC390_Prepare(mechnum, ®val, cmd); + *ptr = EEpromGetData1(mechnum); + ptr++; + cmd++; + DC390_EnDisableCE(DISABLE_CE,mechnum,®val); + } +} + + +USHORT +DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ) +{ + USHORT wval, rc, *ptr; + UCHAR i; + + DC390_ReadEEprom( MechNum, index ); + wval = 0; + ptr = (PUSHORT) &eepromBuf[index][0]; + for(i=0; i<128 ;i+=2, ptr++) + wval += *ptr; + if( wval == 0x1234 ) + rc = 0; + else + rc = -1; + return( rc ); +} + + +USHORT +DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum ) +{ + USHORT devnum; + + devnum = BusDevFunNum; + + if(Mechnum == 2) + { + if(devnum & 0x80) + return(-1); + mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */ + mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */ + mech2Agent |= 0xc0; + mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */ + mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20; + } + else /* use mech #1 method */ + { + mech1addr = 0x80000000 | ((ULONG)devnum << 8); + } + return(0); +} + +/*********************************************************************** + * Function : static int DC390_init (struct Scsi_Host *host) + * + * Purpose : initialize the internal structures for a given SCSI host + * + * Inputs : host - pointer to this host adapter's structure/ + * + * Preconditions : when this function is called, the chip_type + * field of the pACB structure MUST have been set. + ***********************************************************************/ + +static int +DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum) +{ + PSH psh; + PACB pACB; + + if( !DC390_CheckEEpromCheckSum( MechNum, index) ) + { + psh = scsi_register( psht, sizeof(DC390_ACB) ); + if( !psh ) + return( -1 ); + if( !pSH_start ) + { + pSH_start = psh; + pSH_current = psh; + } + else + { + pSH_current->next = psh; + pSH_current = psh; + } + +#ifdef DC390_DEBUG0 + printk("DC390: pSH = %8x,", (UINT) psh); + printk("DC390: Index %02i,", index); +#endif + + DC390_initACB( psh, io_port, Irq, index ); + if( !DC390_initAdapter( psh, io_port, Irq, index ) ) + { + pACB = (PACB) psh->hostdata; + if( !pACB_start ) + { + pACB_start = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + else + { + pACB_current->pNextACB = pACB; + pACB_current = pACB; + pACB->pNextACB = (PACB) -1; + } + +#ifdef DC390_DEBUG0 + printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", + (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); + printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n", + sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) ); +#endif + + } + else + { + pSH_start = NULL; + scsi_unregister( psh ); + return( -1 ); + } + return( 0 ); + } + else + { + printk("DC390_init: EEPROM reading error!\n"); + return( -1 ); + } +} + + +/*********************************************************************** + * Function : int DC390_detect(Scsi_Host_Template *psht) + * + * Purpose : detects and initializes AMD53C974 SCSI chips + * that were autoprobed, overridden on the LILO command line, + * or specified at compile time. + * + * Inputs : psht - template for this SCSI adapter + * + * Returns : number of host adapters detected + * + ***********************************************************************/ + +int +DC390_detect(Scsi_Host_Template *psht) +{ +#ifdef FOR_PCI_OK + UCHAR pci_bus, pci_device_fn; + int error = 0; + USHORT chipType = 0; + USHORT i; +#endif + + UCHAR irq; + UCHAR istatus; +#ifndef VERSION_ELF_1_2_13 + UINT io_port; +#else + ULONG io_port; +#endif + USHORT adaptCnt = 0; /* Number of boards detected */ + USHORT pci_index = 0; /* Device index to PCI BIOS calls */ + USHORT MechNum, BusDevFunNum; + ULONG wlval; + +#ifndef VERSION_ELF_1_2_13 + psht->proc_dir = &proc_scsi_tmscsim; +#endif + + InitialTime = 1; + pSHT_start = psht; + pACB_start = NULL; + + MechNum = 1; + for( ; (MechNum < 3) && (!adaptCnt); MechNum++) + { + BusDevFunNum = 0; + for (; adaptCnt < MAX_ADAPTER_NUM ;) + { + if( !DC390_ToMech( MechNum, BusDevFunNum) ) + { + wlval = DC390_inDword( MechNum, PCI_VENDOR_ID); + if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+ + PCI_VENDOR_ID_AMD) ) + { + io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE; + irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE); +#ifdef DC390_DEBUG0 + printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); +#endif + if( !DC390_init(psht, io_port, irq, pci_index, MechNum) ) + { + adaptCnt++; + pci_index++; + istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */ +#ifdef DC390_DEBUG0 + printk("DC390: Mech=%2x,\n",(UCHAR) MechNum); +#endif + } + } + } + if( BusDevFunNum != 0xfff8 ) + BusDevFunNum += 8; /* next device # */ + else + break; + } + } + +#ifdef FOR_PCI_OK + if ( pcibios_present() ) + { + for (i = 0; i < MAX_ADAPTER_NUM; ++i) + { + if( !pcibios_find_device( PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD53C974, + pci_index, &pci_bus, &pci_device_fn) ) + { + chipType = PCI_DEVICE_ID_AMD53C974; + pci_index++; + } + + if( chipType ) + { + + error = pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &io_port); + error |= pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &irq); + if( error ) + { + printk("DC390_detect: reading configuration registers error!\n"); + InitialTime = 0; + return( 0 ); + } + + (USHORT) io_port = (USHORT) io_port & 0xFFFE; +#ifdef DC390_DEBUG0 + printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq); +#endif + if( !DC390_init(psht, io_port, irq, i) ) + adaptCnt++; + chipType = 0; + } + else + break; + } + } +#endif + + InitialTime = 0; + adapterCnt = adaptCnt; + return( adaptCnt ); +} + + +#ifndef VERSION_ELF_1_2_13 + +/******************************************************************** + * Function: tmscsim_set_info() + * + * Purpose: Set adapter info (!) + * + * Not yet implemented + * + *******************************************************************/ + +int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt) +{ + return(-ENOSYS); /* Currently this is a no-op */ +} + +/******************************************************************** + * Function: tmscsim_proc_info(char* buffer, char **start, + * off_t offset, int length, int hostno, int inout) + * + * Purpose: return SCSI Adapter/Device Info + * + * Input: buffer: Pointer to a buffer where to write info + * start : + * offset: + * hostno: Host adapter index + * inout : Read (=0) or set(!=0) info + * + * Output: buffer: contains info + * length; length of info in buffer + * + * return value: length + * + ********************************************************************/ + +/* KG: proc_info taken from driver aha152x.c */ + +#undef SPRINTF +#define SPRINTF(args...) pos += sprintf(pos, ## args) + +#define YESNO(YN)\ +if (YN) SPRINTF(" Yes ");\ +else SPRINTF(" No ") + +int tmscsim_proc_info(char *buffer, char **start, + off_t offset, int length, int hostno, int inout) +{ + int dev, spd, spd1; + char *pos = buffer; + PSH shpnt; + PACB acbpnt; + PDCB dcbpnt; + unsigned long flags; +/* Scsi_Cmnd *ptr; */ + + acbpnt = pACB_start; + + while(acbpnt != (PACB)-1) + { + shpnt = acbpnt->pScsiHost; + if (shpnt->host_no == hostno) break; + acbpnt = acbpnt->pNextACB; + } + + if (acbpnt == (PACB)-1) return(-ESRCH); + if(!shpnt) return(-ESRCH); + + if(inout) // Has data been written to the file ? + return(tmscsim_set_info(buffer, length, shpnt)); + + SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, "); + SPRINTF("Driver Version 1.10, 1996/12/05\n"); + + save_flags(flags); + cli(); + + SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); + SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex); + SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase); + SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel); + + SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun); + SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); + + SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); + + SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); + + SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n"); + + dcbpnt = acbpnt->pLinkDCB; + for (dev = 0; dev < acbpnt->DeviceCnt; dev++) + { + SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); + YESNO(dcbpnt->DevMode & PARITY_CHK_); + YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE); + YESNO(dcbpnt->DevMode & EN_DISCONNECT_); + YESNO(dcbpnt->DevMode & SEND_START_); + YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING); + SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); + if (dcbpnt->SyncOffset & 0x0f) + { + spd = 1000/(dcbpnt->NegoPeriod <<2); + spd1 = 1000%(dcbpnt->NegoPeriod <<2); + spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2); + SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f)); + } + else SPRINTF("\n"); + /* Add more info ...*/ + dcbpnt = dcbpnt->pNextDCB; + } + + restore_flags(flags); + *start = buffer + offset; + + if (pos - buffer < offset) + return 0; + else if (pos - buffer - offset < length) + return pos - buffer - offset; + else + return length; +} +#endif /* VERSION_ELF_1_2_13 */ + + +#ifdef MODULE + +/*********************************************************************** + * Function : static int DC390_shutdown (struct Scsi_Host *host) + * + * Purpose : does a clean (we hope) shutdown of the SCSI chip. + * Use prior to dumping core, unloading the driver, etc. + * + * Returns : 0 on success + ***********************************************************************/ +static int +DC390_shutdown (struct Scsi_Host *host) +{ + UCHAR bval; + USHORT ioport; + unsigned long flags; + PACB pACB = (PACB)(host->hostdata); + + ioport = (unsigned int) pACB->IOPortBase; + + save_flags (flags); + cli(); + +/* pACB->soft_reset(host); */ + +#ifdef DC390_DEBUG0 + printk("DC390: shutdown,"); +#endif + + bval = inb(ioport+CtrlReg1); + bval |= DIS_INT_ON_SCSI_RST; + outb(bval,ioport+CtrlReg1); /* disable interrupt */ + DC390_ResetSCSIBus( pACB ); + + restore_flags (flags); + return( 0 ); +} + + +int DC390_release(struct Scsi_Host *host) +{ + int irq_count; + struct Scsi_Host *tmp; + + DC390_shutdown (host); + + if (host->irq != IRQ_NONE) + { + for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) + { + if ( tmp->irq == host->irq ) + ++irq_count; + } + if (irq_count == 1) + { +#ifdef DC390_DEBUG0 + printk("DC390: Free IRQ %i.",host->irq); +#endif +#ifndef VERSION_ELF_1_2_13 + free_irq(host->irq,NULL); +#else + free_irq(host->irq); +#endif + } + } + + release_region(host->io_port,host->n_io_port); + + return( 1 ); +} + +Scsi_Host_Template driver_template = DC390_T; +#include "scsi_module.c" +#endif /* def MODULE */ + diff -u --recursive --new-file v2.1.36/linux/drivers/scsi/tmscsim.h linux/drivers/scsi/tmscsim.h --- v2.1.36/linux/drivers/scsi/tmscsim.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/tmscsim.h Mon May 5 10:00:25 1997 @@ -0,0 +1,680 @@ +/*********************************************************************** +;* File Name : TMSCSIM.H * +;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter * +;* Device Driver * +;***********************************************************************/ + +#ifndef TMSCSIM_H +#define TMSCSIM_H + +#define IRQ_NONE 255 + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef unsigned int UINT; + +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef ULONG *PULONG; +typedef Scsi_Host_Template *PSHT; +typedef struct Scsi_Host *PSH; +typedef Scsi_Device *PSCSIDEV; +typedef Scsi_Cmnd *PSCSICMD; +typedef void *PVOID; +typedef struct scatterlist *PSGL, SGL; + + +/*;-----------------------------------------------------------------------*/ +typedef struct _SyncMsg +{ +UCHAR ExtendMsg; +UCHAR ExtMsgLen; +UCHAR SyncXferReq; +UCHAR Period; +UCHAR ReqOffset; +} SyncMsg; +/*;-----------------------------------------------------------------------*/ +typedef struct _Capacity +{ +ULONG BlockCount; +ULONG BlockLength; +} Capacity; +/*;-----------------------------------------------------------------------*/ +typedef struct _SGentry +{ +ULONG SGXferDataPtr; +ULONG SGXferDataLen; +} SGentry; + +typedef struct _SGentry1 +{ +ULONG SGXLen; +ULONG SGXPtr; +} SGentry1, *PSGE; + + +#define MAX_ADAPTER_NUM 4 +#define MAX_DEVICES 10 +#define MAX_SG_LIST_BUF 16 +#define MAX_CMD_QUEUE 20 +#define MAX_CMD_PER_LUN 8 +#define MAX_SCSI_ID 8 +#define MAX_SRB_CNT MAX_CMD_QUEUE+4 +#define END_SCAN 2 + +#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ + +/* +;----------------------------------------------------------------------- +; SCSI Request Block +;----------------------------------------------------------------------- +*/ +struct _SRB +{ +UCHAR CmdBlock[12]; + +struct _SRB *pNextSRB; +struct _DCB *pSRBDCB; +PSCSICMD pcmd; +PSGL pSegmentList; + +ULONG PhysSRB; +ULONG TotalXferredLen; +ULONG SGPhysAddr; /*;a segment starting address */ +ULONG SGToBeXferLen; /*; to be xfer length */ + +SGL Segmentx; /* make a one entry of S/G list table */ + +PUCHAR pMsgPtr; +USHORT SRBState; +USHORT Revxx2; /* ??? */ + +UCHAR MsgInBuf[6]; +UCHAR MsgOutBuf[6]; + +UCHAR AdaptStatus; +UCHAR TargetStatus; +UCHAR MsgCnt; +UCHAR EndMessage; +UCHAR TagNumber; +UCHAR SGcount; +UCHAR SGIndex; +UCHAR IORBFlag; /*;81h-Reset, 2-retry */ + +UCHAR SRBStatus; +UCHAR RetryCnt; +UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ + /*; b4-settimeout,b5-Residual valid */ +UCHAR ScsiCmdLen; +UCHAR ScsiPhase; +UCHAR Reserved3[3]; /*;for dword alignment */ +ULONG Segment0[2]; +ULONG Segment1[2]; +}; + +typedef struct _SRB DC390_SRB, *PSRB; + +/* +;----------------------------------------------------------------------- +; Device Control Block +;----------------------------------------------------------------------- +*/ +struct _DCB +{ +struct _DCB *pNextDCB; +struct _ACB *pDCBACB; + +PSCSICMD pQIORBhead; +PSCSICMD pQIORBtail; +PSCSICMD AboIORBhead; +PSCSICMD AboIORBtail; +USHORT QIORBCnt; +USHORT AboIORBcnt; + +PSRB pWaitingSRB; +PSRB pWaitLast; +PSRB pGoingSRB; +PSRB pGoingLast; +PSRB pActiveSRB; +USHORT GoingSRBCnt; +USHORT WaitSRBCnt; /* ??? */ + +ULONG TagMask; + +USHORT MaxCommand; +USHORT AdaptIndex; /*; UnitInfo struc start */ +USHORT UnitIndex; /*; nth Unit on this card */ +UCHAR UnitSCSIID; /*; SCSI Target ID (SCSI Only) */ +UCHAR UnitSCSILUN; /*; SCSI Log. Unit (SCSI Only) */ + +UCHAR IdentifyMsg; +UCHAR CtrlR1; +UCHAR CtrlR3; +UCHAR CtrlR4; + +UCHAR InqDataBuf[8]; +UCHAR CapacityBuf[8]; +UCHAR DevMode; +UCHAR AdpMode; +UCHAR SyncMode; /*; 0:async mode */ +UCHAR NegoPeriod; /*;for nego. */ +UCHAR SyncPeriod; /*;for reg. */ +UCHAR SyncOffset; /*;for reg. and nego.(low nibble) */ +UCHAR UnitCtrlFlag; +UCHAR DCBFlag; +UCHAR DevType; +UCHAR Reserved2[3]; /*;for dword alignment */ +}; + +typedef struct _DCB DC390_DCB, *PDCB; +/* +;----------------------------------------------------------------------- +; Adapter Control Block +;----------------------------------------------------------------------- +*/ +struct _ACB +{ +ULONG PhysACB; +PSH pScsiHost; +struct _ACB *pNextACB; +USHORT IOPortBase; +USHORT Revxx1; /* ??? */ + +PDCB pLinkDCB; +PDCB pDCBRunRobin; +PDCB pActiveDCB; +PDCB pDCB_free; +PSRB pFreeSRB; +PSRB pTmpSRB; +USHORT SRBCount; +USHORT AdapterIndex; /*; nth Adapter this driver */ +USHORT max_id; +USHORT max_lun; + +UCHAR msgin123[4]; +UCHAR status; +UCHAR AdaptSCSIID; /*; Adapter SCSI Target ID */ +UCHAR AdaptSCSILUN; /*; Adapter SCSI LUN */ +UCHAR DeviceCnt; +UCHAR IRQLevel; +UCHAR TagMaxNum; +UCHAR ACBFlag; +UCHAR Gmode2; +UCHAR LUNchk; +UCHAR scan_devices; +UCHAR HostID_Bit; +UCHAR Reserved1[1]; /*;for dword alignment */ +UCHAR DCBmap[MAX_SCSI_ID]; +DC390_DCB DCB_array[MAX_DEVICES]; /* +74h, Len=3E8 */ +DC390_SRB SRB_array[MAX_SRB_CNT]; /* +45Ch, Len= */ +DC390_SRB TmpSRB; +}; + +typedef struct _ACB DC390_ACB, *PACB; + +/*;-----------------------------------------------------------------------*/ + + +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 + +/*;---UnitCtrlFlag */ +#define UNIT_ALLOCATED BIT0 +#define UNIT_INFO_CHANGED BIT1 +#define FORMATING_MEDIA BIT2 +#define UNIT_RETRY BIT3 + +/*;---UnitFlags */ +#define DASD_SUPPORT BIT0 +#define SCSI_SUPPORT BIT1 +#define ASPI_SUPPORT BIT2 + +/*;----SRBState machine definition */ +#define SRB_FREE 0 +#define SRB_WAIT BIT0 +#define SRB_READY BIT1 +#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/ +#define SRB_MSGIN BIT3 +#define SRB_MSGIN_MULTI BIT4 +#define SRB_COMMAND BIT5 +#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/ +#define SRB_DISCONNECT BIT7 +#define SRB_DATA_XFER BIT8 +#define SRB_XFERPAD BIT9 +#define SRB_STATUS BIT10 +#define SRB_COMPLETED BIT11 +#define SRB_ABORT_SENT BIT12 +#define DO_SYNC_NEGO BIT13 +#define SRB_UNEXPECT_RESEL BIT14 + +/*;---ACBFlag */ +#define RESET_DEV BIT0 +#define RESET_DETECT BIT1 +#define RESET_DONE BIT2 + +/*;---DCBFlag */ +#define ABORT_DEV_ BIT0 + +/*;---SRBstatus */ +#define SRB_OK BIT0 +#define ABORTION BIT1 +#define OVER_RUN BIT2 +#define UNDER_RUN BIT3 +#define PARITY_ERROR BIT4 +#define SRB_ERROR BIT5 + +/*;---SRBFlag */ +#define DATAOUT BIT7 +#define DATAIN BIT6 +#define RESIDUAL_VALID BIT5 +#define ENABLE_TIMER BIT4 +#define RESET_DEV0 BIT2 +#define ABORT_DEV BIT1 +#define AUTO_REQSENSE BIT0 + +/*;---Adapter status */ +#define H_STATUS_GOOD 0 +#define H_SEL_TIMEOUT 0x11 +#define H_OVER_UNDER_RUN 0x12 +#define H_UNEXP_BUS_FREE 0x13 +#define H_TARGET_PHASE_F 0x14 +#define H_INVALID_CCB_OP 0x16 +#define H_LINK_CCB_BAD 0x17 +#define H_BAD_TARGET_DIR 0x18 +#define H_DUPLICATE_CCB 0x19 +#define H_BAD_CCB_OR_SG 0x1A +#define H_ABORT 0x0FF + +/*; SCSI Status byte codes*/ +#define SCSI_STAT_GOOD 0x0 /*; Good status */ +#define SCSI_STAT_CHECKCOND 0x02 /*; SCSI Check Condition */ +#define SCSI_STAT_CONDMET 0x04 /*; Condition Met */ +#define SCSI_STAT_BUSY 0x08 /*; Target busy status */ +#define SCSI_STAT_INTER 0x10 /*; Intermediate status */ +#define SCSI_STAT_INTERCONDMET 0x14 /*; Intermediate condition met */ +#define SCSI_STAT_RESCONFLICT 0x18 /*; Reservation conflict */ +#define SCSI_STAT_CMDTERM 0x22 /*; Command Terminated */ +#define SCSI_STAT_QUEUEFULL 0x28 /*; Queue Full */ + +#define SCSI_STAT_UNEXP_BUS_F 0xFD /*; Unexpect Bus Free */ +#define SCSI_STAT_BUS_RST_DETECT 0xFE /*; Scsi Bus Reset detected */ +#define SCSI_STAT_SEL_TIMEOUT 0xFF /*; Selection Time out */ + +/*;---Sync_Mode */ +#define SYNC_DISABLE 0 +#define SYNC_ENABLE BIT0 +#define SYNC_NEGO_DONE BIT1 +#define WIDE_ENABLE BIT2 +#define WIDE_NEGO_DONE BIT3 +#define EN_TAG_QUEUING BIT4 +#define EN_ATN_STOP BIT5 + +#define SYNC_NEGO_OFFSET 15 + +/*;---SCSI bus phase*/ +#define SCSI_DATA_OUT 0 +#define SCSI_DATA_IN 1 +#define SCSI_COMMAND 2 +#define SCSI_STATUS_ 3 +#define SCSI_NOP0 4 +#define SCSI_NOP1 5 +#define SCSI_MSG_OUT 6 +#define SCSI_MSG_IN 7 + +/*;----SCSI MSG BYTE*/ +#define MSG_COMPLETE 0x00 +#define MSG_EXTENDED 0x01 +#define MSG_SAVE_PTR 0x02 +#define MSG_RESTORE_PTR 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_INITIATOR_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT_ 0x07 +#define MSG_NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define MSG_LINK_CMD_COMPL 0x0A +#define MSG_LINK_CMD_COMPL_FLG 0x0B +#define MSG_BUS_RESET 0x0C +#define MSG_ABORT_TAG 0x0D +#define MSG_SIMPLE_QTAG 0x20 +#define MSG_HEAD_QTAG 0x21 +#define MSG_ORDER_QTAG 0x22 +#define MSG_IDENTIFY 0x80 +#define MSG_HOST_ID 0x0C0 + +/*;----SCSI STATUS BYTE*/ +#define STATUS_GOOD 0x00 +#define CHECK_CONDITION_ 0x02 +#define STATUS_BUSY 0x08 +#define STATUS_INTERMEDIATE 0x10 +#define RESERVE_CONFLICT 0x18 + +/* cmd->result */ +#define STATUS_MASK_ 0xFF +#define MSG_MASK 0xFF00 +#define RETURN_MASK 0xFF0000 + +/* +** Inquiry Data format +*/ + +typedef struct _SCSIInqData { /* INQ */ + + UCHAR DevType; /* Periph Qualifier & Periph Dev Type*/ + UCHAR RMB_TypeMod; /* rem media bit & Dev Type Modifier */ + UCHAR Vers; /* ISO, ECMA, & ANSI versions */ + UCHAR RDF; /* AEN, TRMIOP, & response data format*/ + UCHAR AddLen; /* length of additional data */ + UCHAR Res1; /* reserved */ + UCHAR Res2; /* reserved */ + UCHAR Flags; /* RelADr,Wbus32,Wbus16,Sync,etc. */ + UCHAR VendorID[8]; /* Vendor Identification */ + UCHAR ProductID[16]; /* Product Identification */ + UCHAR ProductRev[4]; /* Product Revision */ + + +} SCSI_INQDATA, *PSCSI_INQDATA; + + +/* Inquiry byte 0 masks */ + + +#define SCSI_DEVTYPE 0x1F /* Peripheral Device Type */ +#define SCSI_PERIPHQUAL 0xE0 /* Peripheral Qualifier */ + + +/* Inquiry byte 1 mask */ + +#define SCSI_REMOVABLE_MEDIA 0x80 /* Removable Media bit (1=removable) */ + + +/* Peripheral Device Type definitions */ + +#define SCSI_DASD 0x00 /* Direct-access Device */ +#define SCSI_SEQACESS 0x01 /* Sequential-access device */ +#define SCSI_PRINTER 0x02 /* Printer device */ +#define SCSI_PROCESSOR 0x03 /* Processor device */ +#define SCSI_WRITEONCE 0x04 /* Write-once device */ +#define SCSI_CDROM 0x05 /* CD-ROM device */ +#define SCSI_SCANNER 0x06 /* Scanner device */ +#define SCSI_OPTICAL 0x07 /* Optical memory device */ +#define SCSI_MEDCHGR 0x08 /* Medium changer device */ +#define SCSI_COMM 0x09 /* Communications device */ +#define SCSI_NODEV 0x1F /* Unknown or no device type */ + +/* +** Inquiry flag definitions (Inq data byte 7) +*/ + +#define SCSI_INQ_RELADR 0x80 /* device supports relative addressing*/ +#define SCSI_INQ_WBUS32 0x40 /* device supports 32 bit data xfers */ +#define SCSI_INQ_WBUS16 0x20 /* device supports 16 bit data xfers */ +#define SCSI_INQ_SYNC 0x10 /* device supports synchronous xfer */ +#define SCSI_INQ_LINKED 0x08 /* device supports linked commands */ +#define SCSI_INQ_CMDQUEUE 0x02 /* device supports command queueing */ +#define SCSI_INQ_SFTRE 0x01 /* device supports soft resets */ + + +/* +;========================================================== +; EEPROM byte offset +;========================================================== +*/ +typedef struct _EEprom +{ +UCHAR EE_MODE1; +UCHAR EE_SPEED; +UCHAR xx1; +UCHAR xx2; +} EEprom, *PEEprom; + +#define EE_ADAPT_SCSI_ID 64 +#define EE_MODE2 65 +#define EE_DELAY 66 +#define EE_TAG_CMD_NUM 67 + +/*; EE_MODE1 bits definition*/ +#define PARITY_CHK_ BIT0 +#define SYNC_NEGO_ BIT1 +#define EN_DISCONNECT_ BIT2 +#define SEND_START_ BIT3 +#define TAG_QUEUING_ BIT4 + +/*; EE_MODE2 bits definition*/ +#define MORE2_DRV BIT0 +#define GREATER_1G BIT1 +#define RST_SCSI_BUS BIT2 +#define ACTIVE_NEGATION BIT3 +#define NO_SEEK BIT4 +#define LUN_CHECK BIT5 + +#define ENABLE_CE 1 +#define DISABLE_CE 0 +#define EEPROM_READ 0x80 + +/* +;========================================================== +; AMD 53C974 Registers bit Definition +;========================================================== +*/ +/* +;==================== +; SCSI Register +;==================== +*/ + +/*; Command Reg.(+0CH) */ +#define DMA_COMMAND BIT7 +#define NOP_CMD 0 +#define CLEAR_FIFO_CMD 1 +#define RST_DEVICE_CMD 2 +#define RST_SCSI_BUS_CMD 3 +#define INFO_XFER_CMD 0x10 +#define INITIATOR_CMD_CMPLTE 0x11 +#define MSG_ACCEPTED_CMD 0x12 +#define XFER_PAD_BYTE 0x18 +#define SET_ATN_CMD 0x1A +#define RESET_ATN_CMD 0x1B +#define SELECT_W_ATN 0x42 +#define SEL_W_ATN_STOP 0x43 +#define EN_SEL_RESEL 0x44 +#define SEL_W_ATN2 0x46 +#define DATA_XFER_CMD INFO_XFER_CMD + + +/*; SCSI Status Reg.(+10H) */ +#define INTERRUPT BIT7 +#define ILLEGAL_OP_ERR BIT6 +#define PARITY_ERR BIT5 +#define COUNT_2_ZERO BIT4 +#define GROUP_CODE_VALID BIT3 +#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0) + +/*; Interrupt Status Reg.(+14H) */ +#define SCSI_RESET BIT7 +#define INVALID_CMD BIT6 +#define DISCONNECTED BIT5 +#define SERVICE_REQUEST BIT4 +#define SUCCESSFUL_OP BIT3 +#define RESELECTED BIT2 +#define SEL_ATTENTION BIT1 +#define SELECTED BIT0 + +/*; Internal State Reg.(+18H) */ +#define SYNC_OFFSET_FLAG BIT3 +#define INTRN_STATE_MASK (BIT2+BIT1+BIT0) + +/*; Clock Factor Reg.(+24H) */ +#define CLK_FREQ_40MHZ 0 +#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0) +#define CLK_FREQ_30MHZ (BIT2+BIT1) +#define CLK_FREQ_25MHZ (BIT2+BIT0) +#define CLK_FREQ_20MHZ BIT2 +#define CLK_FREQ_15MHZ (BIT1+BIT0) +#define CLK_FREQ_10MHZ BIT1 + +/*; Control Reg. 1(+20H) */ +#define EXTENDED_TIMING BIT7 +#define DIS_INT_ON_SCSI_RST BIT6 +#define PARITY_ERR_REPO BIT4 +#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0) + +/*; Control Reg. 2(+2CH) */ +#define EN_FEATURE BIT6 +#define EN_SCSI2_CMD BIT3 + +/*; Control Reg. 3(+30H) */ +#define ID_MSG_CHECK BIT7 +#define EN_QTAG_MSG BIT6 +#define EN_GRP2_CMD BIT5 +#define FAST_SCSI BIT4 /* ;10MB/SEC */ +#define FAST_CLK BIT3 /* ;25 - 40 MHZ */ + +/*; Control Reg. 4(+34H) */ +#define EATER_12NS 0 +#define EATER_25NS BIT7 +#define EATER_35NS BIT6 +#define EATER_0NS (BIT7+BIT6) +#define NEGATE_REQACKDATA BIT2 +#define NEGATE_REQACK BIT3 +/* +;==================== +; DMA Register +;==================== +*/ +/*; DMA Command Reg.(+40H) */ +#define READ_DIRECTION BIT7 +#define WRITE_DIRECTION 0 +#define EN_DMA_INT BIT6 +#define MAP_TO_MDL BIT5 +#define DIAGNOSTIC BIT4 +#define DMA_IDLE_CMD 0 +#define DMA_BLAST_CMD BIT0 +#define DMA_ABORT_CMD BIT1 +#define DMA_START_CMD (BIT1+BIT0) + +/*; DMA Status Reg.(+54H) */ +#define PCI_MS_ABORT BIT6 +#define BLAST_COMPLETE BIT5 +#define SCSI_INTERRUPT BIT4 +#define DMA_XFER_DONE BIT3 +#define DMA_XFER_ABORT BIT2 +#define DMA_XFER_ERROR BIT1 +#define POWER_DOWN BIT0 + +/* +; DMA SCSI Bus and Ctrl.(+70H) +;EN_INT_ON_PCI_ABORT +*/ + +/* +;========================================================== +; SCSI Chip register address offset +;========================================================== +*/ +#define CtcReg_Low 0x00 +#define CtcReg_Mid 0x04 +#define ScsiFifo 0x08 +#define ScsiCmd 0x0C +#define Scsi_Status 0x10 +#define INT_Status 0x14 +#define Sync_Period 0x18 +#define Sync_Offset 0x1C +#define CtrlReg1 0x20 +#define Clk_Factor 0x24 +#define CtrlReg2 0x2C +#define CtrlReg3 0x30 +#define CtrlReg4 0x34 +#define CtcReg_High 0x38 +#define DMA_Cmd 0x40 +#define DMA_XferCnt 0x44 +#define DMA_XferAddr 0x48 +#define DMA_Wk_ByteCntr 0x4C +#define DMA_Wk_AddrCntr 0x50 +#define DMA_Status 0x54 +#define DMA_MDL_Addr 0x58 +#define DMA_Wk_MDL_Cntr 0x5C +#define DMA_ScsiBusCtrl 0x70 + +#define StcReg_Low CtcReg_Low +#define StcReg_Mid CtcReg_Mid +#define Scsi_Dest_ID Scsi_Status +#define Scsi_TimeOut INT_Status +#define Intern_State Sync_Period +#define Current_Fifo Sync_Offset +#define StcReg_High CtcReg_High + +#define am_target Scsi_Status +#define am_timeout INT_Status +#define am_seq_step Sync_Period +#define am_fifo_count Sync_Offset + + +#define DC390_read8(address) \ + inb(DC390_ioport + (address))) + +#define DC390_read16(address) \ + inw(DC390_ioport + (address))) + +#define DC390_read32(address) \ + inl(DC390_ioport + (address))) + +#define DC390_write8(address,value) \ + outb((value), DC390_ioport + (address))) + +#define DC390_write16(address,value) \ + outw((value), DC390_ioport + (address))) + +#define DC390_write32(address,value) \ + outl((value), DC390_ioport + (address))) + + +/* Configuration method #1 */ +#define PCI_CFG1_ADDRESS_REG 0xcf8 +#define PCI_CFG1_DATA_REG 0xcfc +#define PCI_CFG1_ENABLE 0x80000000 +#define PCI_CFG1_TUPPLE(bus, device, function, register) \ + (PCI_CFG1_ENABLE | (((bus) << 16) & 0xff0000) | \ + (((device) << 11) & 0xf800) | (((function) << 8) & 0x700)| \ + (((register) << 2) & 0xfc)) + +/* Configuration method #2 */ +#define PCI_CFG2_ENABLE_REG 0xcf8 +#define PCI_CFG2_FORWARD_REG 0xcfa +#define PCI_CFG2_ENABLE 0x0f0 +#define PCI_CFG2_TUPPLE(function) \ + (PCI_CFG2_ENABLE | (((function) << 1) & 0xe)) + + +#endif /* TMSCSIM_H */ diff -u --recursive --new-file v2.1.36/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.1.36/linux/drivers/sound/Config.in Tue Mar 4 10:25:24 1997 +++ linux/drivers/sound/Config.in Mon May 5 10:56:46 1997 @@ -1,15 +1,277 @@ -# -# Sound driver configuration -# -#-------- -# There is another confic script which is compatible with rest of -# the kernel. It can be activated by running 'make mkscript' in this -# directory. Please note that this is an _experimental_ feature which -# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui). -#-------- -# -$MAKE -C drivers/sound config || exit 1 +bool 'ProAudioSpectrum 16 support' CONFIG_PAS +bool '_TRUE_ Sound Blaster (SB, SBPro, SB16/32/64, ESS, Jazz16) support' CONFIG_SB +bool 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB +bool 'Gravis Ultrasound support' CONFIG_GUS +bool 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 +bool 'PSS (ECHO-ADI2111) support' CONFIG_PSS +bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 +bool 'GUS MAX support' CONFIG_GUSMAX +bool 'Microsoft Sound System support' CONFIG_MSS +bool 'Ensoniq SoundScape support' CONFIG_SSCAPE +bool 'MediaTrix AudioTrix Pro support' CONFIG_TRIX +bool 'Support for MAD16 and/or Mozart based cards' CONFIG_MAD16 +bool 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232 +bool 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI +bool 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 + +if [ "$CONFIG_AEDSP16" = "y" ]; then +hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220 +fi + +if [ "$CONFIG_SB" = "y" ]; then +hex 'I/O base for SB Check from manual of the card' SBC_BASE 220 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1 +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5 +fi + +if [ "$CONFIG_SB" = "y" ]; then +hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330 +fi + + +if [ "$CONFIG_SB" = "y" ]; then +comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.' +fi + + +if [ "$CONFIG_SB" = "y" ]; then +comment 'Enter -1 to the following question if you have something else such as SB16/32.' +fi + +if [ "$CONFIG_SB" = "y" ]; then +int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1 +fi + +if [ "$CONFIG_PAS" = "y" ]; then +int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10 +fi + +if [ "$CONFIG_PAS" = "y" ]; then +int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6 +fi + +if [ "$CONFIG_GUS" = "y" ]; then +int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7 +fi + +if [ "$CONFIG_GUS16" = "y" ]; then +int 'GUS DMA 0, 1 or 3' GUS16_DMA 3 +fi + +if [ "$CONFIG_MPU401" = "y" ]; then +hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330 +fi + +if [ "$CONFIG_MPU401" = "y" ]; then +int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9 +fi + + +if [ "$CONFIG_MAUI" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with Maui.' +fi + +if [ "$CONFIG_MAUI" = "y" ]; then +hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330 +fi + +if [ "$CONFIG_MAUI" = "y" ]; then +int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9 +fi + +if [ "$CONFIG_UART6850" = "y" ]; then +hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0 +fi + +if [ "$CONFIG_UART6850" = "y" ]; then +int 'UART6850 IRQ (Unknown)' U6850_IRQ -1 +fi + + +if [ "$CONFIG_PSS" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with PSS cards.' +fi + +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS I/O base 220 or 240' PSS_BASE 220 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11 +fi +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330 +fi + +if [ "$CONFIG_PSS" = "y" ]; then +int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3 +fi + +if [ "$CONFIG_MSS" = "y" ]; then +int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534 +fi + +if [ "$CONFIG_SSCAPE" = "y" ]; then +int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11 +fi + + +if [ "$CONFIG_TRIX" = "y" ]; then +comment 'ERROR! You have to use old sound configuration method with AudioTrix.' +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix audio I/O base 530, 604, E80 or F40' TRIX_BASE 530 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix audio DMA 0, 1 or 3' TRIX_DMA 0 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +hex 'AudioTrix SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7 +fi + +if [ "$CONFIG_TRIX" = "y" ]; then +int 'AudioTrix SB DMA 1 or 3' TRIX_SB_DMA 1 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330 +fi + +if [ "$CONFIG_CS4232" = "y" ]; then +int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330 +fi + +if [ "$CONFIG_MAD16" = "y" ]; then +int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9 +fi +# +$MAKE -C drivers/sound kernelconfig || exit 1 bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then diff -u --recursive --new-file v2.1.36/linux/fs/affs/Changes linux/fs/affs/Changes --- v2.1.36/linux/fs/affs/Changes Wed Dec 31 16:00:00 1969 +++ linux/fs/affs/Changes Thu May 1 12:05:02 1997 @@ -0,0 +1,95 @@ +(Note: I consider version numbers as cheap. That means +that I do not like numbers like 0.1 and the like for +things that can be used since quite some time. But +then, 3.1 doesn't mean 'perfectly stable', too.) + +Known bugs: +----------- + +- Doesn't work on the alpha. The only 64/32-bit + problem that I'm aware of (pointer/int conversion + in readdir()) gives compiler warnings but is + apparently not causing the failure, as directory + reads basically work (but all files are of size 0). + Alas, I've got no alpha to debug. :-( +- If an affs mounted filesystem is exported via + nfs, it cannot be written to. No networking to + test that, either. :-( + +Please direct bug reports to: hjw@zvw.de + +Version 3.4 +----------- + +- Hash chains are now sorted by block numbers. + (Thanks to Kars de Jong for finding this.) +- Removed all unnecessary external symbols. + +Version 3.3 +----------- + +- Tried to make all types 'correct' and consistent. +- Errors and warnings are now reported via a + function. They are all prefixed by a severity + and have the same appearance: + "AFFS: : " + (There's one exception to this, as in that function + is no pointer to the super block available.) +- The filesystem is remounted read-only after an + error. +- The names of newly created filesystem objects are + now checked for validity. +- Minor cleanups in comments. +- Added this Changes file. At last! + +Version 3.2 +----------- + +- Extension block cache: Reading/writing of huge files + (several MB) is much faster (of course the added + overhead slows down opening, but this is hardly + noticeable). +- The same get_block()-routine can now be used for + both OFS and FFS. +- The super block is now searched in the block that + was calculated and in the one following. This + should remedy the round-off error introduced by + the 1-k blocks that Linux uses. +- Minor changes to adhere to the new VFS interface. +- The number of used blocks is now also calculated + if the filesystem is mounted read-only. +- Prefixed some constants with AFFS_ to avoid name + clashes. +- Removed 'EXPERIMENTAL' status. + +Version 3.1 +----------- + +- Fixed a nasty bug which didn't allow read-only + mounts. +- Allow dir-cache filesystems to be mounted + read only. +- OFS support. +- Several other changes I just cannot remember + any more. + +Version 3.0 +----------- + +- Almost complete rewrite for the new VFS + interface in Linux 1.3. +- Write support. +- Support for hard and symbolic links. +- Lots of things I remeber even less ... + +Version 2.0 +----------- + +- Fixed a few things to get it compiled. +- Automatic root block calculation. +- Partition checker for genhd.c + +======================================== + +Let's just call Ray Burr's original affs +'Version 1.0'. diff -u --recursive --new-file v2.1.36/linux/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c --- v2.1.36/linux/fs/affs/amigaffs.c Sun May 19 05:22:19 1996 +++ linux/fs/affs/amigaffs.c Thu May 1 12:05:02 1997 @@ -5,8 +5,10 @@ * * (C) 1993 Ray Burr - Amiga FFS filesystem. * + * Please send bug reports to: hjw@zvw.de */ +#include #include #include #include @@ -17,6 +19,8 @@ extern struct timezone sys_tz; +static char ErrorBuffer[256]; + /* * Functions for accessing Amiga-FFS structures. * @@ -28,7 +32,7 @@ 0 is returned. Otherwise, the key number in the next used hash slot is returned. */ -int +static int affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos) { struct dir_front *dir_front = dir_data; @@ -54,24 +58,23 @@ file_end = GET_END_PTR(struct file_end, fh_data, bsize); if (file_end->file_name[0] == 0 || file_end->file_name[0] > 30) { - printk ("affs_get_file_name: OOPS! bad filename\n"); - printk (" file_end->file_name[0] = %d\n", + printk(KERN_WARNING "AFFS: bad filename (length=%d chars)\n", file_end->file_name[0]); *name = "***BAD_FILE***"; return 14; } - *name = (char *) &file_end->file_name[1]; + *name = (char *)&file_end->file_name[1]; return file_end->file_name[0]; } /* Find the predecessor in the hash chain */ int -affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) +affs_fix_hash_pred(struct inode *startino, int startoffset, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; - int ptype, stype; + s32 nextkey; + s32 ptype, stype; int retval; nextkey = startino->i_ino; @@ -87,14 +90,14 @@ || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR && stype != ST_LINKFILE && stype != ST_LINKDIR && stype != ST_ROOT && stype != ST_SOFTLINK)) { - printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(startino->i_sb,"affs_fix_hash_pred", + "Bad block in link chain (ptype=%d, stype=%d)",ptype,stype); affs_brelse(bh); break; } - nextkey = htonl(((__u32 *)bh->b_data)[startoffset]); + nextkey = htonl(((s32 *)bh->b_data)[startoffset]); if (nextkey == key) { - ((__u32 *)bh->b_data)[startoffset] = newkey; + ((s32 *)bh->b_data)[startoffset] = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); @@ -112,13 +115,13 @@ /* Remove inode from link chain */ int -affs_fix_link_pred(struct inode *startino, int key, int newkey) +affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey) { struct buffer_head *bh = NULL; - int nextkey; + s32 nextkey; int offset; - int etype = 0; - int ptype, stype; + s32 etype = 0; + s32 ptype, stype; int retval; offset = AFFS_I2BSIZE(startino) / 4 - 10; @@ -150,7 +153,7 @@ retval = -EPERM; break; } - nextkey = htonl(((__u32 *)bh->b_data)[offset]); + nextkey = htonl(((s32 *)bh->b_data)[offset]); if (nextkey == key) { FILE_END(bh->b_data,startino)->link_chain = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); @@ -172,17 +175,17 @@ (which lets us calculate the block size). Returns non-zero if the block is not consistent. */ -__u32 -affs_checksum_block(int bsize, void *data, int *ptype, int *stype) +u32 +affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype) { - __u32 sum; - __u32 *p; + u32 sum; + u32 *p; bsize /= 4; if (ptype) - *ptype = htonl(((__s32 *)data)[0]); + *ptype = htonl(((s32 *)data)[0]); if (stype) - *stype = htonl(((__s32 *)data)[bsize - 1]); + *stype = htonl(((s32 *)data)[bsize - 1]); sum = 0; p = data; @@ -194,20 +197,20 @@ void affs_fix_checksum(int bsize, void *data, int cspos) { - __u32 ocs; - __u32 cs; + u32 ocs; + u32 cs; cs = affs_checksum_block(bsize,data,NULL,NULL); - ocs = htonl (((__u32 *)data)[cspos]); + ocs = htonl (((u32 *)data)[cspos]); ocs -= cs; - ((__u32 *)data)[cspos] = htonl(ocs); + ((u32 *)data)[cspos] = htonl(ocs); } void -secs_to_datestamp(int secs, struct DateStamp *ds) +secs_to_datestamp(time_t secs, struct DateStamp *ds) { - __u32 days; - __u32 minute; + u32 days; + u32 minute; secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60); if (secs < 0) @@ -223,7 +226,7 @@ } int -prot_to_mode(__u32 prot) +prot_to_mode(u32 prot) { int mode = 0; @@ -249,10 +252,10 @@ return mode; } -unsigned int +u32 mode_to_prot(int mode) { - unsigned int prot = 0; + u32 prot = 0; if (mode & S_IXUSR) prot |= FIBF_SCRIPT; @@ -270,4 +273,33 @@ prot |= FIBF_OTR_WRITE; return prot; +} + +void +affs_error(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); + if (!(sb->s_flags & MS_RDONLY)) + printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n"); + sb->s_flags |= MS_RDONLY; +} + +void +affs_warning(struct super_block *sb, const char *function, const char *fmt, ...) +{ + va_list args; + + va_start(args,fmt); + vsprintf(ErrorBuffer,fmt,args); + va_end(args); + + printk(KERN_WARNING "AFFS error (device %s): %s(): %s\n",kdevname(sb->s_dev), + function,ErrorBuffer); } diff -u --recursive --new-file v2.1.36/linux/fs/affs/bitmap.c linux/fs/affs/bitmap.c --- v2.1.36/linux/fs/affs/bitmap.c Sun Nov 10 04:05:48 1996 +++ linux/fs/affs/bitmap.c Thu May 1 12:05:02 1997 @@ -3,7 +3,6 @@ * * (c) 1996 Hans-Joachim Widmaier * - * * bitmap.c contains the code that handles all bitmap related stuff - * block allocation, deallocation, calculation of free space. */ @@ -54,7 +53,7 @@ } void -affs_free_block(struct super_block *sb, int block) +affs_free_block(struct super_block *sb, s32 block) { int bmap; int bit; @@ -70,7 +69,7 @@ zone_no = (bmap << (sb->s_blocksize_bits - 7)) + bit / 1024; bm = &sb->u.affs_sb.s_bitmap[bmap]; if (bmap >= sb->u.affs_sb.s_bm_count) { - printk("AFFS: free_block(): block %d outside partition.\n",block); + affs_error(sb,"affs_free_block","Block %d outside partition",block); return; } blk = 0; @@ -83,15 +82,16 @@ if (!bm->bm_bh) { bm->bm_count--; unlock_super(sb); - printk("AFFS: free_block(): Cannot read bitmap block %d\n",bm->bm_key); + affs_error(sb,"affs_free_block","Cannot read bitmap block %d",bm->bm_key); return; } } if (set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4)) - printk("AFFS: free_block(): block %d is already free.\n",block); + affs_warning(sb,"affs_free_block","Trying to free block %d which is already free", + block); else { sb->u.affs_sb.s_alloc[zone_no].az_free++; - ((__u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((__u32 *)bm->bm_bh->b_data)[0]) - blk); + ((u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((u32 *)bm->bm_bh->b_data)[0]) - blk); mark_buffer_dirty(bm->bm_bh,1); sb->s_dirt = 1; } @@ -102,15 +102,15 @@ unlock_super(sb); } -static int +static s32 affs_balloc(struct inode *inode, int zone_no) { - __u32 w; - __u32 *bm; + u32 w; + u32 *bm; int fb; int i; int fwb; - int block; + s32 block; struct affs_zone *zone; struct affs_alloc_zone *az; struct super_block *sb; @@ -124,7 +124,7 @@ pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no); az = &sb->u.affs_sb.s_alloc[zone->z_az_no]; - bm = (__u32 *)zone->z_bm->bm_bh->b_data; + bm = (u32 *)zone->z_bm->bm_bh->b_data; repeat: for (i = zone->z_start; i < zone->z_end; i++) { if (bm[i]) @@ -140,7 +140,7 @@ fb = find_first_zero_bit(&w,32); if (fb > 31 || !clear_bit(fb ^ BO_EXBITS,&bm[i])) { unlock_super(sb); - printk("AFFS: balloc(): empty block disappeared somehow\n"); + affs_warning(sb,"balloc","Empty block disappeared somehow"); goto repeat; } block = fwb + fb; @@ -154,7 +154,7 @@ if (fb > 31) break; if (!clear_bit(fb ^ BO_EXBITS,&bm[i])) { - printk("AFFS: balloc(): empty block disappeared\n"); + affs_warning(sb,"balloc","Empty block disappeared somehow"); break; } inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb; @@ -204,7 +204,7 @@ if (az->az_count) az->az_count--; else - printk("AFFS: find_new_zone(): az_count=0, but bm used\n"); + affs_error(sb,"find_new_zone","az_count=0, but bm used"); } while (1) { @@ -247,7 +247,7 @@ bm->bm_count--; az->az_count--; unlock_super(sb); - printk("AFFS: find_new_zone(): Cannot read bitmap\n"); + affs_error(sb,"find_new_zone","Cannot read bitmap"); return 0; } zone->z_bm = bm; @@ -261,16 +261,16 @@ return az->az_free; } -int +s32 affs_new_header(struct inode *inode) { - int block; + s32 block; struct buffer_head *bh; pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino); if (!(block = affs_balloc(inode,0))) { - while(affs_find_new_zone(inode->i_sb,0)) { + while (affs_find_new_zone(inode->i_sb,0)) { if ((block = affs_balloc(inode,0))) goto init_block; schedule(); @@ -279,7 +279,7 @@ } init_block: if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: balloc(): cannot read block %d\n",block); + affs_error(inode->i_sb,"new_header","Cannot read block %d",block); return 0; } memset(bh->b_data,0,AFFS_I2BSIZE(inode)); @@ -290,7 +290,7 @@ return block; } -int +s32 affs_new_data(struct inode *inode) { int empty, old; @@ -299,7 +299,7 @@ struct super_block *sb; struct buffer_head *bh; int i = 0; - int block; + s32 block; pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino); @@ -345,7 +345,7 @@ found: zone = &sb->u.affs_sb.s_zones[i]; if (!(block = affs_balloc(inode,i))) { /* No data zones left */ - while(affs_find_new_zone(sb,i)) { + while (affs_find_new_zone(sb,i)) { if ((block = affs_balloc(inode,i))) goto init_block; schedule(); @@ -357,7 +357,7 @@ init_block: if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) { - printk("AFFS: balloc(): cannot read block %u\n",block); + affs_error(inode->i_sb,"new_data","Cannot read block %d",block); return 0; } memset(bh->b_data,0,sb->s_blocksize); diff -u --recursive --new-file v2.1.36/linux/fs/affs/dir.c linux/fs/affs/dir.c --- v2.1.36/linux/fs/affs/dir.c Sun Jan 26 02:07:24 1997 +++ linux/fs/affs/dir.c Thu May 1 12:05:02 1997 @@ -64,7 +64,7 @@ }; static long -affs_dir_read(struct inode * inode, struct file * filp, char * buf, unsigned long count) +affs_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count) { return -EISDIR; } @@ -73,19 +73,18 @@ affs_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) { int j, namelen; - int i; + s32 i; int hash_pos; int chain_pos; unsigned long ino; unsigned long old; - int stored; - char *name; - struct buffer_head *dir_bh; - struct buffer_head *fh_bh; - struct inode *dir; + int stored; + char *name; + struct buffer_head *dir_bh; + struct buffer_head *fh_bh; + struct inode *dir; pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos); - if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; @@ -122,7 +121,7 @@ chain_pos = (filp->f_pos - 2) & 0xffff; hash_pos = (filp->f_pos - 2) >> 16; if (chain_pos == 0xffff) { - printk("AFFS: more than 65535 entries in chain\n"); + affs_warning(inode->i_sb,"readdir","More than 65535 entries in chain"); chain_pos = 0; hash_pos++; filp->f_pos = ((hash_pos << 16) | chain_pos) + 2; @@ -143,15 +142,15 @@ * we can jump directly to where we left off. */ if (filp->private_data && filp->f_version == dir->i_version) { - i = (int)filp->private_data; + i = (s32)filp->private_data; j = 0; pr_debug("AFFS: readdir() left off=%d\n",i); } filp->f_version = dir->i_version; - pr_debug("AFFS: hash_pos=%lu chain_pos=%lu\n", hash_pos, chain_pos); + pr_debug("AFFS: hash_pos=%d chain_pos=%d\n",hash_pos,chain_pos); while (i) { if (!(fh_bh = affs_bread(inode->i_dev,i,AFFS_I2BSIZE(inode)))) { - printk("AFFS: readdir: Can't get block %d\n",i); + affs_error(inode->i_sb,"readdir","Cannot read block %d",i); goto readdir_done; } ino = i; @@ -164,7 +163,7 @@ } if (fh_bh) { namelen = affs_get_file_name(AFFS_I2BSIZE(inode),fh_bh->b_data,&name); - pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%lu\n", + pr_debug("AFFS: readdir(): filldir(..,\"%.*s\",ino=%lu), i=%d\n", namelen,name,ino,i); filp->private_data = (void *)ino; if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0) diff -u --recursive --new-file v2.1.36/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.1.36/linux/fs/affs/file.c Fri Apr 4 08:52:23 1997 +++ linux/fs/affs/file.c Thu May 1 12:05:02 1997 @@ -35,6 +35,8 @@ #error PAGE_SIZE must be at least 4096 #endif +static int affs_bmap(struct inode *inode, int block); +static struct buffer_head * affs_getblock(struct inode *inode, s32 block); static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count); static long affs_file_write(struct inode *inode, struct file *filp, const char *buf, @@ -200,7 +202,7 @@ return 128 + 192 * 2 + 128 * 4 + 64 * 16 + 32 * 64 + 64 * 256 + (index << 9); } -static int __inline__ +static s32 __inline__ calc_key(struct inode *inode, int *ext) { int index; @@ -226,28 +228,30 @@ return inode->u.affs_i.i_ec->ec[index]; } -int +static int affs_bmap(struct inode *inode, int block) { struct buffer_head *bh; - int ext, key, nkey; - int ptype, stype; + s32 key, nkey; + s32 ptype, stype; + int ext; int index; int keycount; struct key_cache *kc; struct key_cache *tkc; struct timeval tv; - __s32 *keyp; + s32 *keyp; int i; pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block); if (block < 0) { - printk("affs_bmap: block < 0\n"); + affs_error(inode->i_sb,"bmap","Block < 0"); return 0; } if (!inode->u.affs_i.i_ec) { - printk("affs_bmap(): No ext_cache!?\n"); + affs_error(inode->i_sb,"bmap","No extension cache for open file (inode=%lu)", + inode->i_ino); return 0; } @@ -334,14 +338,14 @@ return key; } -struct buffer_head * -affs_getblock(struct inode *inode, int block) +static struct buffer_head * +affs_getblock(struct inode *inode, s32 block) { struct buffer_head *bh; struct buffer_head *ebh; struct buffer_head *pbh; struct key_cache *kc; - int key, nkey; + s32 key, nkey; int ext; int cf, j, pt; int index; @@ -372,7 +376,7 @@ return NULL; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j) || cf != pt || j != ST_FILE) { - printk("AFFS: getblock(): inode %d is not a valid %s\n",key, + affs_error(inode->i_sb,"getblock","Inode %d is not a valid %s",key, pt == T_SHORT ? "file header" : "extension block"); affs_brelse(bh); return NULL; @@ -387,7 +391,8 @@ else pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock); if (!pbh) { - printk("AFFS: getblock(): cannot get last block in file\n"); + affs_error(inode->i_sb,"getblock", + "Cannot get last block in file"); break; } } @@ -397,7 +402,7 @@ lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { unlock_super(inode->i_sb); - printk("AFFS: getblock(): block already allocated\n"); + affs_warning(inode->i_sb,"getblock","Block already allocated"); affs_free_block(inode->i_sb,nkey); j++; continue; @@ -407,7 +412,8 @@ if (ofs) { ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode)); if (!ebh) { - printk("AFFS: getblock(): cannot get block %d\n",nkey); + affs_error(inode->i_sb,"getblock", + "Cannot get block %d",nkey); affs_free_block(inode->i_sb,nkey); AFFS_BLOCK(bh->b_data,inode,j) = 0; break; @@ -492,10 +498,6 @@ return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); } -/* This could be made static, regardless of what the former comment said. - * You cannot directly read affs directories. - */ - static long affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, unsigned long count) { @@ -508,12 +510,12 @@ pr_debug("AFFS: file_read_ofs(ino=%lu,pos=%lu,%d)\n",inode->i_ino,(long)filp->f_pos,count); if (!inode) { - printk("affs_file_read: inode = NULL\n"); + affs_error(inode->i_sb,"file_read_ofs","Inode = NULL"); return -EINVAL; } blocksize = AFFS_I2BSIZE(inode) - 24; if (!(S_ISREG(inode->i_mode))) { - pr_debug("affs_file_read: mode = %07o\n",inode->i_mode); + pr_debug("affs_file_read: mode = %07o",inode->i_mode); return -EINVAL; } if (filp->f_pos >= inode->i_size || count <= 0) @@ -524,10 +526,10 @@ left = MIN (inode->i_size - filp->f_pos,count - (buf - start)); if (!left) break; - sector = affs_bmap(inode,(__u32)filp->f_pos / blocksize); + sector = affs_bmap(inode,(u32)filp->f_pos / blocksize); if (!sector) break; - offset = (__u32)filp->f_pos % blocksize; + offset = (u32)filp->f_pos % blocksize; bh = affs_bread(inode->i_dev,sector,AFFS_I2BSIZE(inode)); if (!bh) break; @@ -554,25 +556,31 @@ struct inode *ino; char *p; + /* Not that I wanted to be POSIX compliant ... */ + if (!count) + return 0; pr_debug("AFFS: file_write(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); ino = NULL; if (!inode) { - printk("AFFS: file_write(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write","Inode = NULL"); return -EINVAL; } if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -636,22 +644,27 @@ pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino, (unsigned long)filp->f_pos,count); + if (!count) + return 0; if (!inode) { - printk("AFFS: file_write_ofs(): inode=NULL\n"); + affs_error(inode->i_sb,"file_write_ofs","Inode = NULL"); return -EINVAL; } ino = NULL; if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: could not follow link from inode %lu to %d\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"file_write_ofs", + "Could not follow link from inode %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return -EINVAL; } inode = ino; } if (!S_ISREG(inode->i_mode)) { - printk("AFFS: file_write_ofs(): mode=%07o\n",inode->i_mode); + affs_error(inode->i_sb,"file_write_ofs", + "Trying to write to non-regular file (mode=%07o)", + inode->i_mode); iput(inode); return -EINVAL; } @@ -714,10 +727,10 @@ struct affs_zone *zone; int first; int block; - int key; - int *keyp; - int ekey; - int ptype, stype; + s32 key; + s32 *keyp; + s32 ekey; + s32 ptype, stype; int freethis; int blocksize; int rem; @@ -729,8 +742,8 @@ if (inode->u.affs_i.i_original) { ino = iget(inode->i_sb,inode->u.affs_i.i_original); if (!ino) { - printk("AFFS: truncate(): cannot follow link from %lu to %u\n", - inode->i_ino,inode->u.affs_i.i_original); + affs_error(inode->i_sb,"truncate","Cannot follow link from %lu to %d", + inode->i_ino,inode->u.affs_i.i_original); return; } inode = ino; @@ -754,7 +767,7 @@ unlock_super(inode->i_sb); } if (!bh) { - printk("AFFS: truncate(): Cannot extend file\n"); + affs_error(inode->i_sb,"truncate","Cannot extend file"); inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1); } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) { rem = inode->i_size % blocksize; @@ -771,7 +784,7 @@ while (ekey) { if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) { - printk("AFFS: truncate(): Can't read block %d\n",ekey); + affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey); break; } ptype = htonl(((struct file_front *)bh->b_data)->primary_type); @@ -783,14 +796,14 @@ break; } if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) { - printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n", - ptype,stype); + affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)", + ptype,stype); affs_brelse(bh); break; } /* Do not throw away file header */ freethis = first == 0 && ekey != inode->i_ino; - for ( block = first; block < AFFS_I2HSIZE(inode); block++) { + for (block = first; block < AFFS_I2HSIZE(inode); block++) { keyp = &AFFS_BLOCK(bh->b_data,inode,block); key = htonl(*keyp); if (key) { @@ -853,7 +866,7 @@ affs_open_file(struct inode *inode, struct file *filp) { int error; - int key; + u32 key; int i; pr_debug("AFFS: open_file(ino=%lu)\n",inode->i_ino); @@ -864,7 +877,7 @@ if (!inode->u.affs_i.i_ec) { inode->u.affs_i.i_ec = (struct ext_cache *)get_free_page(GFP_KERNEL); if (!inode->u.affs_i.i_ec) { - printk("AFFS: cache allocation failed\n"); + affs_error(inode->i_sb,"open_file","Cache allocation failed"); error = ENOMEM; } else { /* We only have to initialize non-zero values. diff -u --recursive --new-file v2.1.36/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.1.36/linux/fs/affs/inode.c Wed Apr 23 19:01:22 1997 +++ linux/fs/affs/inode.c Thu May 1 12:05:02 1997 @@ -30,12 +30,26 @@ #include #include +/* AmigaOS allows file names with up to 30 characters length. + * Names longer than that will be silently truncated. If you + * want to disallow this, comment out the following #define. + * Creating filesystem objects with longer names will then + * result in an error (ENAMETOOLONG). + */ +/*#define NO_TRUNCATE */ + extern int *blk_size[]; extern struct timezone sys_tz; #define MIN(a,b) (((a)<(b))?(a):(b)) -void +static int affs_notify_change(struct inode *inode, struct iattr *attr); +static void affs_put_inode(struct inode *inode); +static void affs_read_inode(struct inode *inode); +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); +static void affs_write_inode(struct inode *inode); + +static void affs_put_super(struct super_block *sb) { int i; @@ -110,13 +124,13 @@ NULL /* remount */ }; -int +unsigned long affs_parent_ino(struct inode *dir) { int root_ino = (dir->i_sb->u.affs_sb.s_root_block); if (!S_ISDIR (dir->i_mode)) { - printk ("affs_parent_ino: argument is not a directory\n"); + affs_error(dir->i_sb,"parent_ino","Trying to get parent of non-directory"); return root_ino; } if (dir->i_ino == root_ino) @@ -125,7 +139,7 @@ } static int -parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root, +parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root, int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) { char *this_char, *value; @@ -150,14 +164,14 @@ *value++ = 0; if (!strcmp(this_char,"protect")) { if (value) { - printk("AFFS: option protect does not take an argument\n"); + printk("AFFS: Option protect does not take an argument\n"); return 0; } *mount_opts |= SF_IMMUTABLE; } else if (!strcmp(this_char,"verbose")) { if (value) { - printk("AFFS: option verbose does not take an argument\n"); + printk("AFFS: Option verbose does not take an argument\n"); return 0; } *mount_opts |= SF_VERBOSE; @@ -166,7 +180,7 @@ if (!value) *uid = current->uid; else if (!*value) { - printk("AFFS: argument for uid option missing\n"); + printk("AFFS: Argument for uid option missing\n"); return 0; } else { *uid = simple_strtoul(value,&value,0); @@ -180,7 +194,7 @@ if (!value) *gid = current->gid; else if (!*value) { - printk("AFFS: argument for gid option missing\n"); + printk("AFFS: Argument for gid option missing\n"); return 0; } else { *gid = simple_strtoul(value,&value,0); @@ -248,7 +262,7 @@ return 0; if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048 && *blocksize != 4096) { - printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed).\n"); + printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); return 0; } } @@ -270,21 +284,21 @@ * hopefully have the guts to do so. Until then: sorry for the mess. */ -struct super_block * +static struct super_block * affs_read_super(struct super_block *s,void *data, int silent) { struct buffer_head *bh = NULL; struct buffer_head *bb; kdev_t dev = s->s_dev; - int root_block; + s32 root_block; int size; - __u32 chksum; - __u32 *bm; - int ptype, stype; + u32 chksum; + u32 *bm; + s32 ptype, stype; int mapidx; int num_bm; int i, j; - int key; + s32 key; int blocksize; uid_t uid; gid_t gid; @@ -300,7 +314,7 @@ if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) { s->s_dev = 0; - printk("AFFS: error parsing options.\n"); + printk(KERN_ERR "AFFS: Error parsing options\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -324,13 +338,13 @@ if (size == 0) { s->s_dev = 0; unlock_super(s); - printk("affs_read_super: could not determine device size\n"); + printk(KERN_ERR "AFFS: Could not determine device size\n"); goto out; } s->u.affs_sb.s_partition_size = size; s->u.affs_sb.s_reserved = reserved; - /* Try to find root block. Its location may depend on the block size. */ + /* Try to find root block. Its location depends on the block size. */ s->u.affs_sb.s_hashsize = 0; if (blocksize > 0) { @@ -358,12 +372,12 @@ * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { - pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, " + pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %u, " "size=%d blocks, %d reserved\n",kdevname(dev),blocksize, s->u.affs_sb.s_root_block + num_bm,size,reserved); bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize); if (!bh) { - printk("AFFS: unable to read root block\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) && @@ -383,7 +397,8 @@ if (!key) { affs_brelse(bh); if (!silent) - printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev)); + printk(KERN_ERR "AFFS: Cannot find a valid root block on device %s\n", + kdevname(dev)); goto out; } root_block = s->u.affs_sb.s_root_block; @@ -396,7 +411,7 @@ /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); if (bb) { - chksum = htonl(*(__u32 *)bb->b_data); + chksum = htonl(*(u32 *)bb->b_data); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is @@ -404,7 +419,8 @@ */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } switch (chksum) { @@ -436,22 +452,22 @@ s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; break; default: - printk("AFFS: Unknown filesystem on device %s: %08X\n", - kdevname(dev),chksum); + printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", + kdevname(dev),chksum); affs_brelse(bb); goto out; } affs_brelse(bb); } else { - printk("AFFS: Can't get boot block.\n"); + printk(KERN_ERR "AFFS: Cannot read boot block\n"); goto out; } if (mount_flags & SF_VERBOSE) { chksum = ntohl(chksum); - printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", - GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], - &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], - (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); + printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", + GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], + &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], + (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } s->s_magic = AFFS_SUPER_MAGIC; @@ -459,7 +475,7 @@ /* Keep super block in cache */ if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) { - printk("AFFS: Can't read root block a second time\n"); + printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out; } @@ -473,7 +489,7 @@ MAX_ZONES * sizeof(struct affs_zone); pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) { - printk("AFFS: Not enough memory.\n"); + printk(KERN_ERR "AFFS: Not enough memory\n"); goto out; } memset(s->u.affs_sb.s_bitmap,0,ptype); @@ -486,7 +502,8 @@ if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) { if (!(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev)); + printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n", + kdevname(dev)); s->s_flags |= MS_RDONLY; } affs_brelse(bh); @@ -504,17 +521,17 @@ offset = s->u.affs_sb.s_reserved; az_no = 0; while (bh) { - bm = (__u32 *)bh->b_data; + bm = (u32 *)bh->b_data; for (i = ptype; i < stype && bm[i]; i++, mapidx++) { if (mapidx >= num_bm) { - printk("AFFS: Not enough bitmap space!?\n"); + printk(KERN_ERR "AFFS: Not enough bitmap space!?\n"); goto out; } bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize); if (bb) { if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && !(s->s_flags & MS_RDONLY)) { - printk("AFFS: Bitmap (%d,key=%lu) invalid - " + printk(KERN_WARNING "AFFS: Bitmap (%d,key=%lu) invalid - " "mounting %s read only.\n",mapidx,htonl(bm[i]), kdevname(dev)); s->s_flags |= MS_RDONLY; @@ -525,7 +542,7 @@ key = size & 0x1F; /* used bits */ if (key) { chksum = ntohl(0x7FFFFFFF >> (31 - key)); - ((__u32 *)bb->b_data)[ptype] &= chksum; + ((u32 *)bb->b_data)[ptype] &= chksum; affs_fix_checksum(s->s_blocksize,bb->b_data,0); mark_buffer_dirty(bb,1); } @@ -551,7 +568,7 @@ } affs_brelse(bb); } else { - printk("AFFS: Can't read bitmap.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap\n"); goto out; } } @@ -561,14 +578,14 @@ affs_brelse(bh); if (key) { if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) { - printk("AFFS: Can't read bitmap extension.\n"); + printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); goto out; } } else bh = NULL; } if (mapidx != num_bm) { - printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); + printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); goto out; } nobitmap: @@ -584,7 +601,7 @@ if (!(s->s_mounted)) { s->s_dev = 0; - printk("AFFS: get root inode failed\n"); + printk(KERN_ERR "AFFS: get root inode failed\n"); MOD_DEC_USE_COUNT; return NULL; } @@ -615,7 +632,7 @@ return NULL; } -void +static void affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { int free; @@ -635,15 +652,15 @@ copy_to_user(buf,&tmp,bufsiz); } -void +static void affs_read_inode(struct inode *inode) { struct buffer_head *bh, *lbh; struct file_front *file_front; struct file_end *file_end; - int block; + s32 block; unsigned long prot; - int ptype, stype; + s32 ptype, stype; unsigned short id; pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino); @@ -651,12 +668,12 @@ lbh = NULL; block = inode->i_ino; if (!(bh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) { - printk("AFFS: unable to read i-node block %d\n",block); + affs_error(inode->i_sb,"read_inode","Cannot read block %d",block); return; } if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) { - printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n", - ptype,block); + affs_error(inode->i_sb,"read_inode", + "Checksum or type (ptype=%d) error on inode %d",ptype,block); affs_brelse(bh); return; } @@ -735,7 +752,8 @@ if (!(lbh = affs_bread(inode->i_dev,inode->u.affs_i.i_original, AFFS_I2BSIZE(inode)))) { affs_brelse(bh); - printk("AFFS: unable to read i-node block %ld\n",inode->i_ino); + affs_error(inode->i_sb,"read_inode","Cannot read block %lu", + inode->i_ino); return; } file_end = GET_END_PTR(struct file_end,lbh->b_data,AFFS_I2BSIZE(inode)); @@ -776,12 +794,13 @@ inode->i_op = &affs_symlink_inode_operations; } -void +static void affs_write_inode(struct inode *inode) { - struct buffer_head *bh; - struct file_end *file_end; - short uid, gid; + struct buffer_head *bh; + struct file_end *file_end; + uid_t uid; + gid_t gid; pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino); @@ -789,8 +808,7 @@ if (!inode->i_nlink) return; if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) { - printk("AFFS: Unable to read block of inode %ld on %s\n", - inode->i_ino,kdevname(inode->i_dev)); + affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino); return; } file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode)); @@ -820,7 +838,7 @@ brelse(bh); } -int +static int affs_notify_change(struct inode *inode, struct iattr *attr) { int error; @@ -848,7 +866,7 @@ return 0; } -void +static void affs_put_inode(struct inode *inode) { pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink); @@ -867,7 +885,7 @@ { struct inode *inode; struct super_block *sb; - int block; + s32 block; if (!dir || !(inode = get_empty_inode())) return NULL; @@ -918,7 +936,10 @@ struct buffer_head *dir_bh; struct buffer_head *inode_bh; struct buffer_head *link_bh; - int hash; + struct buffer_head *ibh; + int retval; + int i; + s32 next; pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d\n",dir->i_ino,inode->i_ino, len,name,type); @@ -926,34 +947,60 @@ dir_bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); inode_bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); link_bh = NULL; - if (!dir_bh || !inode_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -ENOSPC; - } + retval = -EIO; + if (!dir_bh || !inode_bh) + goto addentry_done; if (link) { link_bh = affs_bread(link->i_dev,link->i_ino,AFFS_I2BSIZE(link)); - if (!link_bh) { - affs_brelse(dir_bh); - affs_brelse(inode_bh); - return -EINVAL; - } + if (!link_bh) + goto addentry_done; } ((struct dir_front *)inode_bh->b_data)->primary_type = ntohl(T_SHORT); ((struct dir_front *)inode_bh->b_data)->own_key = ntohl(inode->i_ino); - if (len > 30) /* truncate name quietly */ + retval = -ENAMETOOLONG; + if (len > 30) +#ifdef NO_TRUNCATE + goto addentry_done; +#else len = 30; +#endif + + /* Check if name is valid */ + retval = -EINVAL; + for (i = 0; i < len; i++) { + if (name[i] < ' ' || name[i] == ':' + || ((unsigned char)name[i] > 0x7e && (unsigned char)name[i] < 0xa0)) + goto addentry_done; + } + retval = 0; DIR_END(inode_bh->b_data,inode)->dir_name[0] = len; strncpy(DIR_END(inode_bh->b_data,inode)->dir_name + 1,name,len); DIR_END(inode_bh->b_data,inode)->secondary_type = ntohl(type); DIR_END(inode_bh->b_data,inode)->parent = ntohl(dir->i_ino); - hash = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)); + + i = affs_hash_name(name,len,AFFS_I2FSTYPE(dir),AFFS_I2HSIZE(dir)) + 6; + next = dir->i_ino; + + /* Alas, we have to search the insertion point with a locked sb */ lock_super(inode->i_sb); - DIR_END(inode_bh->b_data,inode)->hash_chain = - ((struct dir_front *)dir_bh->b_data)->hashtable[hash]; - ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino); + while (1) { + if (!(ibh = affs_bread(dir->i_dev,next,AFFS_I2BSIZE(dir)))) + goto addentry_done; + next = htonl(((s32 *)ibh->b_data)[i]); + if (!next || next > inode->i_ino) + break; + i = AFFS_I2BSIZE(dir) / 4 - 4; + affs_brelse(ibh); + } + + DIR_END(inode_bh->b_data,inode)->hash_chain = next; + ((s32 *)ibh->b_data)[i] = ntohl(inode->i_ino); + affs_fix_checksum(AFFS_I2BSIZE(dir),ibh->b_data,5); + mark_buffer_dirty(ibh,1); + affs_brelse(ibh); + if (link_bh) { LINK_END(inode_bh->b_data,inode)->original = ntohl(link->i_ino); LINK_END(inode_bh->b_data,inode)->link_chain = @@ -974,11 +1021,13 @@ inode->i_dirt = 1; mark_buffer_dirty(dir_bh,1); mark_buffer_dirty(inode_bh,1); + +addentry_done: affs_brelse(dir_bh); affs_brelse(inode_bh); affs_brelse(link_bh); - return 0; + return retval; } static struct file_system_type affs_fs_type = { @@ -999,7 +1048,7 @@ int init_module(void) { - return init_affs_fs(); + return register_filesystem(&affs_fs_type); } void diff -u --recursive --new-file v2.1.36/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.36/linux/fs/affs/namei.c Sat Nov 30 02:24:01 1996 +++ linux/fs/affs/namei.c Thu May 1 12:05:02 1997 @@ -20,6 +20,8 @@ #include +static int affs_fixup(struct buffer_head *bh, struct inode *inode); + /* Simple toupper() for DOS\1 */ static inline unsigned int @@ -100,7 +102,7 @@ { struct buffer_head *bh; int intl; - int key; + s32 key; pr_debug("AFFS: find_entry(%.*s)=\n",namelen,name); @@ -222,9 +224,7 @@ pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,len,name,mode); - *result = NULL; - if (!dir || !dir->i_sb) { iput(dir); return -EINVAL; @@ -472,7 +472,7 @@ iput(oldinode); oldinode = iget(dir->i_sb,i); if (!oldinode) { - printk("AFFS: link(): original does not exist.\n"); + affs_error(oldinode->i_sb,"link","Cannot get original from link"); iput(dir); return -ENOENT; } @@ -507,7 +507,7 @@ } static int -subdir(struct inode * new_inode, struct inode * old_inode) +subdir(struct inode *new_inode, struct inode *old_inode) { int ino; int result; @@ -650,11 +650,11 @@ return retval; } -int +static int affs_fixup(struct buffer_head *bh, struct inode *inode) { - int key, link_key; - int type; + s32 key, link_key; + s32 type; struct buffer_head *nbh; struct inode *ofinode; @@ -663,7 +663,8 @@ key = htonl(LINK_END(bh->b_data,inode)->original); LINK_END(bh->b_data,inode)->original = 0; if (!key) { - printk("AFFS: fixup(): hard link without original: ino=%lu\n",inode->i_ino); + affs_error(inode->i_sb,"fixup","Hard link without original: ino=%lu", + inode->i_ino); return -ENOENT; } if (!(ofinode = iget(inode->i_sb,key))) @@ -676,17 +677,18 @@ if ((key = htonl(FILE_END(bh->b_data,inode)->link_chain))) { /* Get first link, turn it to a file */ if (!(ofinode = iget(inode->i_sb,key))) { - printk("AFFS: fixup(): cannot read inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); return -ENOENT; } if (!ofinode->u.affs_i.i_hlink) { - printk("AFFS: fixup(): first link to %lu (%u) is not a link?\n", - inode->i_ino,key); + affs_error(inode->i_sb,"fixup", + "First link to %lu (%d) is not a link", + inode->i_ino,key); iput(ofinode); return -ENOENT; } if (!(nbh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)))) { - printk("AFFS: fixup(): cannot read block %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); iput(ofinode); return -ENOENT; } @@ -719,13 +721,14 @@ break; if ((ofinode = iget(inode->i_sb,key))) { if (!ofinode->u.affs_i.i_hlink) - printk("AFFS: fixup() inode %u in link chain is " - "not a link\n",key); + affs_error(inode->i_sb,"fixup", + "Inode %d in link chain is not a link", + key); ofinode->u.affs_i.i_original = link_key; ofinode->i_dirt = 1; FILE_END(nbh->b_data,inode)->original = htonl(link_key); } else - printk("AFFS: fixup(): cannot get inode %u\n",key); + affs_error(inode->i_sb,"fixup","Cannot read block %d",key); } /* Turn old inode to a link */ inode->u.affs_i.i_hlink = 1; @@ -735,7 +738,7 @@ } else if (type == ST_SOFTLINK) { return 0; } else { - printk("AFFS: fixup(): secondary type=%d\n",type); + affs_error(inode->i_sb,"fixup","Bad secondary type (%d)",type); return -EBADF; } } diff -u --recursive --new-file v2.1.36/linux/fs/affs/symlink.c linux/fs/affs/symlink.c --- v2.1.36/linux/fs/affs/symlink.c Mon Oct 28 04:29:25 1996 +++ linux/fs/affs/symlink.c Thu May 1 12:05:02 1997 @@ -82,7 +82,7 @@ i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"follow_link","Cannot read block %lu\n",inode->i_ino); kfree(buffer); iput(inode); iput(dir); @@ -138,7 +138,7 @@ i = 0; j = 0; if (!bh) { - printk("AFFS: unable to read i-node block %lu\n",inode->i_ino); + affs_error(inode->i_sb,"readlink","Cannot read block %lu\n",inode->i_ino); goto symlink_end; } lf = (struct slink_front *)bh->b_data; diff -u --recursive --new-file v2.1.36/linux/fs/autofs/Makefile linux/fs/autofs/Makefile --- v2.1.36/linux/fs/autofs/Makefile Fri Apr 4 08:52:24 1997 +++ linux/fs/autofs/Makefile Thu May 1 12:32:45 1997 @@ -1,11 +1,7 @@ # # Makefile for the linux autofs-filesystem routines. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... +# We can build this either out of the kernel tree or the autofs tools tree. # O_TARGET := autofs.o @@ -13,4 +9,27 @@ M_OBJS := $(O_TARGET) +ifdef TOPDIR +# +# Part of the kernel code +# include $(TOPDIR)/Rules.make +else +# +# Standalone (handy for development) +# +include ../Makefile.rules + +CFLAGS += -D__KERNEL__ -DMODULE $(KFLAGS) -I../include -I$(KINCLUDE) $(MODFLAGS) + +all: $(O_TARGET) + +$(O_TARGET): $(O_OBJS) + $(LD) -r -o $(O_TARGET) $(O_OBJS) + +install: $(O_TARGET) + install -c $(O_TARGET) /lib/modules/`uname -r`/fs + +clean: + rm -f *.o *.s +endif diff -u --recursive --new-file v2.1.36/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h --- v2.1.36/linux/fs/autofs/autofs_i.h Wed Dec 31 16:00:00 1969 +++ linux/fs/autofs/autofs_i.h Thu May 8 13:55:40 1997 @@ -0,0 +1,157 @@ +/* -*- linux-c -*- ------------------------------------------------------- * + * + * linux/fs/autofs/autofs_i.h + * + * Copyright 1997 Transmeta Corporation - All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* Internal header file for autofs */ + +#include + +/* This is the range of ioctl() numbers we claim as ours */ +#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY +#define AUTOFS_IOC_COUNT 32 + +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < 0x20100 + +/* Segmentation stuff for pre-2.1 kernels */ +#include +#define copy_to_user memcpy_tofs +#define copy_from_user memcpy_fromfs + +#else + +/* Segmentation stuff for post-2.1 kernels */ +#include +#define register_symtab(x) ((void)0) + +#endif + +#ifdef DEBUG +#define DPRINTK(D) printk D; +#else +#define DPRINTK(D) +#endif + +#define AUTOFS_SUPER_MAGIC 0x0187 + +/* Structures associated with the root directory hash */ + +#define AUTOFS_HASH_SIZE 67 + +typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */ + +struct autofs_dir_ent { + autofs_hash_t hash; + struct autofs_dir_ent *next; + struct autofs_dir_ent **back; + char *name; + int len; + ino_t ino; + /* The following entries are for the expiry system */ + unsigned long last_usage; + struct autofs_dir_ent *exp_next; + struct autofs_dir_ent *exp_prev; +}; + +struct autofs_dirhash { + struct autofs_dir_ent *h[AUTOFS_HASH_SIZE]; + struct autofs_dir_ent expiry_head; +}; + +struct autofs_wait_queue { + unsigned long wait_queue_token; + struct wait_queue *queue; + struct autofs_wait_queue *next; + /* We use the following to see what we are waiting for */ + autofs_hash_t hash; + int len; + char *name; + /* This is for status reporting upon return */ + int status; + int wait_ctr; +}; + +struct autofs_symlink { + int len; + char *data; + time_t mtime; +}; + +#define AUTOFS_MAX_SYMLINKS 256 + +#define AUTOFS_ROOT_INO 1 +#define AUTOFS_FIRST_SYMLINK 2 +#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) + +#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) + +#ifndef END_OF_TIME +#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) +#endif + +struct autofs_sb_info { + struct file *pipe; + pid_t oz_pgrp; + int catatonic; + unsigned long exp_timeout; + ino_t next_dir_ino; + struct autofs_wait_queue *queues; /* Wait queue pointer */ + struct autofs_dirhash dirhash; /* Root directory hash */ + struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; + u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; +}; + +/* autofs_oz_mode(): do we see the man behind the curtain? */ +static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { + return sbi->catatonic || current->pgrp == sbi->oz_pgrp; +} + +/* Hash operations */ + +autofs_hash_t autofs_hash(const char *,int); +void autofs_initialize_hash(struct autofs_dirhash *); +struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int); +void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); +void autofs_hash_delete(struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *); +void autofs_hash_nuke(struct autofs_dirhash *); + +/* Expiration-handling functions */ + +void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *); +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *,unsigned long); + +/* Operations structures */ + +extern struct inode_operations autofs_root_inode_operations; +extern struct inode_operations autofs_symlink_inode_operations; +extern struct inode_operations autofs_dir_inode_operations; + +/* Initializing function */ + +struct super_block *autofs_read_super(struct super_block *, void *,int); + +/* Queue management functions */ + +int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int); +int autofs_wait_release(struct autofs_sb_info *,unsigned long,int); +void autofs_catatonic_mode(struct autofs_sb_info *); + +#ifdef DEBUG +void autofs_say(const char *name, int len); +#else +#define autofs_say(n,l) +#endif diff -u --recursive --new-file v2.1.36/linux/fs/autofs/dir.c linux/fs/autofs/dir.c --- v2.1.36/linux/fs/autofs/dir.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/dir.c Thu May 1 12:32:45 1997 @@ -10,7 +10,7 @@ * * ------------------------------------------------------------------------- */ -#include +#include "autofs_i.h" static int autofs_dir_readdir(struct inode *inode, struct file *filp, void *dirent, filldir_t filldir) diff -u --recursive --new-file v2.1.36/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c --- v2.1.36/linux/fs/autofs/dirhash.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/dirhash.c Thu May 1 12:32:45 1997 @@ -10,9 +10,43 @@ * * ------------------------------------------------------------------------- */ -#include -#include -#include +#include "autofs_i.h" + +/* Functions for maintenance of expiry queue */ + +static void autofs_init_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + ent->exp_next = &dh->expiry_head; + ent->exp_prev = dh->expiry_head.exp_prev; + dh->expiry_head.exp_prev->exp_next = ent; + dh->expiry_head.exp_prev = ent; + ent->last_usage = jiffies; +} + +static void autofs_delete_usage(struct autofs_dir_ent *ent) +{ + ent->exp_prev->exp_next = ent->exp_next; + ent->exp_next->exp_prev = ent->exp_prev; +} + +void autofs_update_usage(struct autofs_dirhash *dh, + struct autofs_dir_ent *ent) +{ + autofs_delete_usage(ent); /* Unlink from current position */ + autofs_init_usage(dh,ent); /* Relink at queue tail */ +} + +struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *dh, + unsigned long timeout) +{ + struct autofs_dir_ent *ent; + + ent = dh->expiry_head.exp_next; + + if ( ent == &(dh->expiry_head) ) return NULL; + return (jiffies - ent->last_usage >= timeout) ? ent : NULL; +} /* Adapted from the Dragon Book, page 436 */ /* This particular hashing algorithm requires autofs_hash_t == u32 */ @@ -28,6 +62,8 @@ void autofs_initialize_hash(struct autofs_dirhash *dh) { memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *)); + dh->expiry_head.exp_next = dh->expiry_head.exp_prev = + &dh->expiry_head; } struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, autofs_hash_t hash, const char *name, int len) @@ -54,6 +90,8 @@ DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash)); autofs_say(ent->name,ent->len); + autofs_init_usage(dh,ent); + dhnp = &dh->h[ent->hash % AUTOFS_HASH_SIZE]; ent->next = *dhnp; ent->back = dhnp; @@ -63,6 +101,9 @@ void autofs_hash_delete(struct autofs_dir_ent *ent) { *(ent->back) = ent->next; + + autofs_delete_usage(ent); + kfree(ent->name); kfree(ent); } @@ -114,6 +155,8 @@ return ent; } +/* Delete everything. This is used on filesystem destruction, so we + make no attempt to keep the pointers valid */ void autofs_hash_nuke(struct autofs_dirhash *dh) { int i; diff -u --recursive --new-file v2.1.36/linux/fs/autofs/init.c linux/fs/autofs/init.c --- v2.1.36/linux/fs/autofs/init.c Wed Apr 23 19:01:22 1997 +++ linux/fs/autofs/init.c Thu May 1 12:32:45 1997 @@ -10,24 +10,20 @@ * * ------------------------------------------------------------------------- */ +#include #include -#include +#include "autofs_i.h" -struct file_system_type autofs_fs_type = { +static struct file_system_type autofs_fs_type = { autofs_read_super, "autofs", 0, NULL }; -int init_autofs_fs(void) -{ - return register_filesystem(&autofs_fs_type); -} - #ifdef MODULE int init_module(void) { int status; - if ((status = init_autofs_fs()) == 0) + if ((status = register_filesystem(&autofs_fs_type)) == 0) register_symtab(0); return status; } @@ -36,7 +32,15 @@ { unregister_filesystem(&autofs_fs_type); } -#endif + +#else /* MODULE */ + +__initfunc(int init_autofs_fs(void)) +{ + return register_filesystem(&autofs_fs_type); +} + +#endif /* !MODULE */ #ifdef DEBUG void autofs_say(const char *name, int len) diff -u --recursive --new-file v2.1.36/linux/fs/autofs/inode.c linux/fs/autofs/inode.c --- v2.1.36/linux/fs/autofs/inode.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/inode.c Thu May 1 12:32:45 1997 @@ -15,7 +15,7 @@ #include #include #include -#include +#include "autofs_i.h" #define __NO_VERSION__ #include @@ -28,17 +28,19 @@ static void autofs_put_super(struct super_block *sb) { - struct autofs_sb_info *sbi; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *) sb->u.generic_sbp; unsigned int n; + if ( !sbi->catatonic ) + autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ + lock_super(sb); - sbi = (struct autofs_sb_info *) sb->u.generic_sbp; autofs_hash_nuke(&sbi->dirhash); for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) { if ( test_bit(n, sbi->symlink_bitmap) ) kfree(sbi->symlink[n].data); } - fput(sbi->pipe, sbi->pipe->f_inode); sb->s_dev = 0; kfree(sb->u.generic_sbp); @@ -149,6 +151,7 @@ s->u.generic_sbp = sbi; sbi->catatonic = 0; + sbi->exp_timeout = 0; sbi->oz_pgrp = current->pgrp; autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; diff -u --recursive --new-file v2.1.36/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.1.36/linux/fs/autofs/root.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/root.c Thu May 1 12:32:45 1997 @@ -12,9 +12,8 @@ #include #include -#include -#include -#include +#include +#include "autofs_i.h" static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t); static int autofs_root_lookup(struct inode *,const char *,int,struct inode **); @@ -171,7 +170,8 @@ } } } while(!res); - + autofs_update_usage(&sbi->dirhash,ent); + *result = res; iput(dir); return 0; @@ -229,7 +229,6 @@ ent->ino = AUTOFS_FIRST_SYMLINK + n; ent->hash = hash; memcpy(ent->name,name,ent->len = len); - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); @@ -322,7 +321,6 @@ ent->hash = hash; memcpy(ent->name, name, ent->len = len); ent->ino = sbi->next_dir_ino++; - ent->expiry = END_OF_TIME; autofs_hash_insert(dh,ent); dir->i_nlink++; iput(dir); @@ -330,6 +328,52 @@ return 0; } +/* Get/set timeout ioctl() operation */ +static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi, + unsigned long *p) +{ + int rv; + unsigned long ntimeout; + + if ( (rv = get_user(ntimeout, p)) || + (rv = put_user(sbi->exp_timeout/HZ, p)) ) + return rv; + + if ( ntimeout > ULONG_MAX/HZ ) + sbi->exp_timeout = 0; + else + sbi->exp_timeout = ntimeout * HZ; + + return 0; +} + +/* Perform an expiry operation */ +static inline int autofs_expire_run(struct autofs_sb_info *sbi, + struct autofs_packet_expire *pkt_p) +{ + struct autofs_dir_ent *ent; + struct autofs_packet_expire pkt; + struct autofs_dirhash *dh = &(sbi->dirhash); + + pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; + pkt.hdr.type = autofs_ptype_expire; + + if ( !sbi->exp_timeout || + !(ent = autofs_expire(dh,sbi->exp_timeout)) ) + return -EAGAIN; + + pkt.len = ent->len; + memcpy(pkt.name, ent->name, pkt.len); + pkt.name[pkt.len] = '\0'; + + if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) + return -EFAULT; + + autofs_update_usage(dh,ent); + + return 0; +} + /* * ioctl()'s on the root directory is the chief method for the daemon to * generate kernel reactions @@ -337,26 +381,33 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct autofs_sb_info *sbi = (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; + struct autofs_sb_info *sbi = + (struct autofs_sb_info *)inode->i_sb->u.generic_sbp; - DPRINTK(("autofs_ioctl: cmd = %04x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || + _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) + return -ENOTTY; + + if ( !autofs_oz_mode(sbi) && !fsuser() ) + return -EPERM; + switch(cmd) { case AUTOFS_IOC_READY: /* Wait queue: go ahead and retry */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,0); case AUTOFS_IOC_FAIL: /* Wait queue: fail with ENOENT */ - /* Optional: add to failure cache */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; return autofs_wait_release(sbi,arg,-ENOENT); case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */ - if ( !autofs_oz_mode(sbi) && !fsuser() ) - return -EPERM; autofs_catatonic_mode(sbi); return 0; + case AUTOFS_IOC_PROTOVER: /* Get protocol version */ + return put_user(AUTOFS_PROTO_VERSION, (int *)arg); + case AUTOFS_IOC_SETTIMEOUT: + return autofs_get_set_timeout(sbi,(unsigned long *)arg); + case AUTOFS_IOC_EXPIRE: + return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg); default: - return -ENOTTY; /* Should this be ENOSYS? */ + return -ENOSYS; } } diff -u --recursive --new-file v2.1.36/linux/fs/autofs/symlink.c linux/fs/autofs/symlink.c --- v2.1.36/linux/fs/autofs/symlink.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/symlink.c Thu May 1 12:32:45 1997 @@ -12,7 +12,7 @@ #include #include -#include +#include "autofs_i.h" static int autofs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, struct inode **res_inode) diff -u --recursive --new-file v2.1.36/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c --- v2.1.36/linux/fs/autofs/waitq.c Mon Apr 7 11:35:30 1997 +++ linux/fs/autofs/waitq.c Thu May 1 12:32:45 1997 @@ -11,9 +11,10 @@ * ------------------------------------------------------------------------- */ #include -#include #include -#include +#include +#include +#include "autofs_i.h" /* We make this a static variable rather than a part of the superblock; it is better if we don't reassign numbers easily even across filesystems */ @@ -36,6 +37,7 @@ wake_up(&wq->queue); wq = nwq; } + fput(sbi->pipe, sbi->pipe->f_inode); /* Close the pipe */ } static int autofs_write(struct file *file, const void *addr, int bytes) diff -u --recursive --new-file v2.1.36/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.1.36/linux/fs/binfmt_elf.c Wed Apr 23 19:01:22 1997 +++ linux/fs/binfmt_elf.c Sun Apr 27 18:13:35 1997 @@ -210,14 +210,16 @@ /* Now read in all of the header information */ - if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) + if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) { return ~0UL; + } elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); - if (!elf_phdata) + if (!elf_phdata) { return ~0UL; + } /* * If the size of this structure has changed, then punt, since @@ -278,6 +280,7 @@ /* Real error */ sys_close(elf_exec_fileno); kfree(elf_phdata); +printk("%d", error); return ~0UL; } @@ -359,7 +362,9 @@ interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); - if (retval < 0) return ~0UL; + if (retval < 0) { + return ~0UL; + } return elf_entry; } diff -u --recursive --new-file v2.1.36/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.36/linux/fs/dcache.c Wed Apr 23 19:01:22 1997 +++ linux/fs/dcache.c Wed Apr 23 21:06:52 1997 @@ -153,17 +153,24 @@ /* * Find a directory cache entry given all the necessary info. */ -static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, int len, struct dir_cache_entry ** hash) +static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, unsigned char len, struct dir_cache_entry ** hash) { struct dir_cache_entry *de; - for(de = *hash; de; de = de->next) + de = *hash; + goto inside; + for (;;) { + de = de->next; +inside: + if (!de) + break; if((de->name_len == (unsigned char) len) && (de->dc_dev == dir->i_dev) && (de->dir == dir->i_ino) && (de->version == dir->i_version) && (!memcmp(de->name, name, len))) break; + } return de; } @@ -195,7 +202,7 @@ struct dir_cache_entry *de; spin_lock(&dcache_lock); - de = find_entry(dir, name, len, hash); + de = find_entry(dir, name, (unsigned char) len, hash); if(de) { *ino = de->ino; move_to_level2(de, hash); @@ -213,7 +220,7 @@ struct dir_cache_entry *de; spin_lock(&dcache_lock); - de = find_entry(dir, name, len, hash); + de = find_entry(dir, name, (unsigned char) len, hash); if (de) { de->ino = ino; update_lru(de); diff -u --recursive --new-file v2.1.36/linux/fs/dquot.c linux/fs/dquot.c --- v2.1.36/linux/fs/dquot.c Sun Jan 26 02:07:30 1997 +++ linux/fs/dquot.c Sun Apr 27 15:08:01 1997 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -989,7 +990,7 @@ } } else error = -EIO; - filp->f_count--; + put_filp(filp); } else error = -EMFILE; iput(inode); diff -u --recursive --new-file v2.1.36/linux/fs/exec.c linux/fs/exec.c --- v2.1.36/linux/fs/exec.c Wed Apr 23 19:01:22 1997 +++ linux/fs/exec.c Sun Apr 27 18:32:17 1997 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -148,7 +148,7 @@ if (f->f_op->open) { int error = f->f_op->open(inode,f); if (error) { - f->f_count--; + put_filp(f); put_unused_fd(fd); return error; } @@ -384,7 +384,7 @@ * (the oom is wrong there, too, IMHO) */ if (current->mm->count > 1) { - struct mm_struct *mm = kmalloc(sizeof(*mm), GFP_KERNEL); + struct mm_struct *mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (!mm) { /* this is wrong, I think. */ oom(current); @@ -394,8 +394,7 @@ init_new_context(mm); mm->def_flags = 0; /* should future lockings be kept? */ mm->count = 1; - mm->mmap = NULL; - mm->mmap_avl = NULL; + mm->mmap = mm->mmap_cache = NULL; mm->total_vm = 0; mm->rss = 0; current->mm->count--; diff -u --recursive --new-file v2.1.36/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c --- v2.1.36/linux/fs/ext2/balloc.c Thu Nov 14 00:27:37 1996 +++ linux/fs/ext2/balloc.c Sat Apr 26 12:35:58 1997 @@ -177,6 +177,7 @@ unsigned long bit; unsigned long i; int bitmap_nr; + unsigned long overflow; struct super_block * sb; struct ext2_group_desc * gdp; struct ext2_super_block * es; @@ -199,14 +200,20 @@ ext2_debug ("freeing block %lu\n", block); +do_more: + overflow = 0; block_group = (block - le32_to_cpu(es->s_first_data_block)) / EXT2_BLOCKS_PER_GROUP(sb); - bit = (block - le32_to_cpu(es->s_first_data_block)) % EXT2_BLOCKS_PER_GROUP(sb); - if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) - ext2_panic (sb, "ext2_free_blocks", - "Freeing blocks across group boundary - " - "Block = %lu, count = %lu", - block, count); + bit = (block - le32_to_cpu(es->s_first_data_block)) % + EXT2_BLOCKS_PER_GROUP(sb); + /* + * Check to see if we are freeing blocks across a group + * boundary. + */ + if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) { + overflow = bit + count - EXT2_BLOCKS_PER_GROUP(sb); + count -= overflow; + } bitmap_nr = load_block_bitmap (sb, block_group); bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; gdp = get_group_desc (sb, block_group, &bh2); @@ -246,6 +253,11 @@ ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } + if (overflow) { + block += count; + count = overflow; + goto do_more; + } sb->s_dirt = 1; unlock_super (sb); return; @@ -546,6 +558,19 @@ EXT2_BLOCKS_PER_GROUP(sb), map); } +static int test_root(int a, int b) +{ + if (a == 0) + return 1; + while (1) { + if (a == 1) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + void ext2_check_blocks_bitmap (struct super_block * sb) { struct buffer_head * bh; @@ -569,15 +594,21 @@ bitmap_nr = load_block_bitmap (sb, i); bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr]; - if (!ext2_test_bit (0, bh->b_data)) - ext2_error (sb, "ext2_check_blocks_bitmap", - "Superblock in group %d is marked free", i); - - for (j = 0; j < desc_blocks; j++) - if (!ext2_test_bit (j + 1, bh->b_data)) + if (!(sb->u.ext2_sb.s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || + (test_root(i, 3) || test_root(i, 5) || test_root(i, 7))) { + if (!ext2_test_bit (0, bh->b_data)) ext2_error (sb, "ext2_check_blocks_bitmap", + "Superblock in group %d " + "is marked free", i); + + for (j = 0; j < desc_blocks; j++) + if (!ext2_test_bit (j + 1, bh->b_data)) + ext2_error (sb, + "ext2_check_blocks_bitmap", "Descriptor block #%d in group " "%d is marked free", j, i); + } if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data)) ext2_error (sb, "ext2_check_blocks_bitmap", diff -u --recursive --new-file v2.1.36/linux/fs/ext2/inode.c linux/fs/ext2/inode.c --- v2.1.36/linux/fs/ext2/inode.c Sun Dec 22 06:16:53 1996 +++ linux/fs/ext2/inode.c Sat Apr 26 12:35:58 1997 @@ -503,12 +503,23 @@ inode->i_op = &blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); - if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) + inode->i_attr_flags = 0; + if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) { + inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; inode->i_flags |= MS_SYNCHRONOUS; - if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) + } + if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) { + inode->i_attr_flags |= ATTR_FLAG_APPEND; inode->i_flags |= S_APPEND; - if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) + } + if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) { + inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; inode->i_flags |= S_IMMUTABLE; + } + if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) { + inode->i_attr_flags |= ATTR_FLAG_NOATIME; + inode->i_flags |= MS_NOATIME; + } } static int ext2_update_inode(struct inode * inode, int do_sync) @@ -597,11 +608,71 @@ void ext2_write_inode (struct inode * inode) { +#if 0 + printk("ext2_write(%04x:%06d)...", inode->i_dev, inode->i_ino); +#endif ext2_update_inode (inode, 0); } int ext2_sync_inode (struct inode *inode) { +#if 0 + printk("ext2_sync(%04x:%06d)...", inode->i_dev, inode->i_ino); +#endif return ext2_update_inode (inode, 1); +} + +int ext2_notify_change(struct inode *inode, struct iattr *iattr) +{ + int retval; + unsigned int flags; + + if ((iattr->ia_attr_flags & + (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^ + (inode->u.ext2_i.i_flags & + (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) { + if (!fsuser() || securelevel > 0) + return -EPERM; + } else + if ((current->fsuid != inode->i_uid) && !fsuser()) + return -EPERM; + + if ((retval = inode_change_ok(inode, iattr)) != 0) + return retval; + + inode_setattr(inode, iattr); + + flags = iattr->ia_attr_flags; + if (flags & ATTR_FLAG_SYNCRONOUS) { + inode->i_flags |= MS_SYNCHRONOUS; + inode->u.ext2_i.i_flags = EXT2_SYNC_FL; + } else { + inode->i_flags &= ~MS_SYNCHRONOUS; + inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL; + } + if (flags & ATTR_FLAG_NOATIME) { + inode->i_flags |= MS_NOATIME; + inode->u.ext2_i.i_flags = EXT2_NOATIME_FL; + } else { + inode->i_flags &= ~MS_NOATIME; + inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL; + } + if (flags & ATTR_FLAG_APPEND) { + inode->i_flags |= S_APPEND; + inode->u.ext2_i.i_flags = EXT2_APPEND_FL; + } else { + inode->i_flags &= ~S_APPEND; + inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL; + } + if (flags & ATTR_FLAG_IMMUTABLE) { + inode->i_flags |= S_IMMUTABLE; + inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL; + } else { + inode->i_flags &= ~S_IMMUTABLE; + inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL; + } + inode->i_dirt = 1; + + return 0; } diff -u --recursive --new-file v2.1.36/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c --- v2.1.36/linux/fs/ext2/ioctl.c Tue Dec 31 11:19:32 1996 +++ linux/fs/ext2/ioctl.c Sat Apr 26 12:35:58 1997 @@ -45,6 +45,10 @@ if (IS_RDONLY(inode)) return -EROFS; inode->u.ext2_i.i_flags = flags; + if (flags & EXT2_SYNC_FL) + inode->i_flags |= MS_SYNCHRONOUS; + else + inode->i_flags &= ~MS_SYNCHRONOUS; if (flags & EXT2_APPEND_FL) inode->i_flags |= S_APPEND; else @@ -53,6 +57,10 @@ inode->i_flags |= S_IMMUTABLE; else inode->i_flags &= ~S_IMMUTABLE; + if (flags & EXT2_NOATIME_FL) + inode->i_flags |= MS_NOATIME; + else + inode->i_flags &= ~MS_NOATIME; inode->i_ctime = CURRENT_TIME; inode->i_dirt = 1; return 0; diff -u --recursive --new-file v2.1.36/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.36/linux/fs/ext2/namei.c Sat Nov 30 02:24:01 1996 +++ linux/fs/ext2/namei.c Sun Apr 27 15:08:01 1997 @@ -583,7 +583,7 @@ offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); de = (struct ext2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len)); while (offset < inode->i_size ) { - if ((void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { + if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, &err); if (!bh) { diff -u --recursive --new-file v2.1.36/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v2.1.36/linux/fs/ext2/super.c Wed Apr 23 19:01:22 1997 +++ linux/fs/ext2/super.c Sat Apr 26 12:35:58 1997 @@ -508,6 +508,9 @@ goto failed_mount; } } + sb->u.ext2_sb.s_feature_compat = es->s_feature_compat; + sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat; + sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat; sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE << (__s32) le32_to_cpu(es->s_log_frag_size); if (sb->u.ext2_sb.s_frag_size) diff -u --recursive --new-file v2.1.36/linux/fs/fcntl.c linux/fs/fcntl.c --- v2.1.36/linux/fs/fcntl.c Sun Jan 26 02:07:44 1997 +++ linux/fs/fcntl.c Sun Apr 27 15:08:01 1997 @@ -163,6 +163,7 @@ if (current->pgrp == -arg || current->pid == arg) goto fasync_ok; + read_lock(&tasklist_lock); for_each_task(p) { if ((p->pid == arg) || (p->pid == -arg) || (p->pgrp == -arg)) { @@ -171,11 +172,14 @@ if ((p->session != current->session) && (p->uid != current->uid) && (p->euid != current->euid) && - !suser()) + !suser()) { + read_unlock(&tasklist_lock); goto out; + } break; } } + read_unlock(&tasklist_lock); err = -EINVAL; if ((task_found == 0) && !suser()) break; diff -u --recursive --new-file v2.1.36/linux/fs/file_table.c linux/fs/file_table.c --- v2.1.36/linux/fs/file_table.c Sat Aug 3 00:43:18 1996 +++ linux/fs/file_table.c Sun Apr 27 15:08:01 1997 @@ -2,143 +2,104 @@ * linux/fs/file_table.c * * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ #include +#include +#include #include +#include #include #include +#include -/* - * first_file points to a doubly linked list of all file structures in - * the system. - * nr_files holds the length of this list. - */ -struct file * first_file = NULL; +/* SLAB cache for filp's. */ +static kmem_cache_t *filp_cache; + +/* sysctl tunables... */ int nr_files = 0; int max_files = NR_FILE; -/* - * Insert a new file structure at the head of the list of available ones. - */ -static inline void insert_file_free(struct file *file) -{ - struct file *next, *prev; +/* Free list management, if you are here you must have f_count == 0 */ +static struct file * free_filps = NULL; - next = first_file; - first_file = file; - file->f_count = 0; - prev = next->f_prev; - file->f_next = next; - next->f_prev = file; - file->f_prev = prev; - prev->f_next = file; -} - -/* - * Remove a file structure from the list of available ones. - */ -static inline void remove_file_free(struct file *file) +void insert_file_free(struct file *file) { - struct file *next, *prev; - - next = file->f_next; - prev = file->f_prev; - file->f_next = file->f_prev = NULL; - if (first_file == file) - first_file = next; - next->f_prev = prev; - prev->f_next = next; + if((file->f_next = free_filps) != NULL) + free_filps->f_pprev = &file->f_next; + free_filps = file; + file->f_pprev = &free_filps; } -/* - * Insert a file structure at the end of the list of available ones. - */ -static inline void put_last_free(struct file *file) +/* The list of in-use filp's must be exported (ugh...) */ +struct file *inuse_filps = NULL; + +static inline void put_inuse(struct file *file) { - struct file *next, *prev; + if((file->f_next = inuse_filps) != NULL) + inuse_filps->f_pprev = &file->f_next; + inuse_filps = file; + file->f_pprev = &inuse_filps; +} - next = first_file; - file->f_next = next; - prev = next->f_prev; - next->f_prev = file; - file->f_prev = prev; - prev->f_next = file; -} - -/* - * Allocate a new memory page for file structures and - * insert the new structures into the global list. - * Returns 0, if there is no more memory, 1 otherwise. - */ +/* Get more free filp's. */ static int grow_files(void) { - struct file * file; - int i; - - /* - * We don't have to clear the page because we only look into - * f_count, f_prev and f_next and they get initialized in - * insert_file_free. The rest of the file structure is cleared - * by get_empty_filp before it is returned. - */ - file = (struct file *) __get_free_page(GFP_KERNEL); - - if (!file) - return 0; - - nr_files += i = PAGE_SIZE/sizeof(struct file); - - if (!first_file) - file->f_count = 0, - file->f_next = file->f_prev = first_file = file++, - i--; + int i = 16; - for (; i ; i--) - insert_file_free(file++); + while(i--) { + struct file * file = kmem_cache_alloc(filp_cache, SLAB_KERNEL); + if(!file) { + if(i == 15) + return 0; + goto got_some; + } + insert_file_free(file); + nr_files++; + } +got_some: return 1; } -unsigned long file_table_init(unsigned long start, unsigned long end) +void file_table_init(void) { - return start; + filp_cache = kmem_cache_create("filp", sizeof(struct file), + sizeof(unsigned long) * 8, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!filp_cache) + panic("VFS: Cannot alloc filp SLAB cache."); } -/* - * Find an unused file structure and return a pointer to it. +/* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. */ struct file * get_empty_filp(void) { - int i; - int max = max_files; struct file * f; - /* - * Reserve a few files for the super-user.. - */ - if (current->euid) - max -= 10; - - /* if the return is taken, we are in deep trouble */ - if (!first_file && !grow_files()) - return NULL; - - do { - for (f = first_file, i=0; i < nr_files; i++, f = f->f_next) - if (!f->f_count) { - remove_file_free(f); - memset(f,0,sizeof(*f)); - put_last_free(f); - f->f_count = 1; - f->f_version = ++event; - return f; - } - } while (nr_files < max && grow_files()); +again: + if((f = free_filps) != NULL) { + remove_filp(f); + memset(f, 0, sizeof(*f)); + f->f_count = 1; + f->f_version = ++event; + put_inuse(f); + } else { + int max = max_files; + + /* Reserve a few files for the super-user.. */ + if (current->euid) + max -= 10; - return NULL; + if (nr_files < max && grow_files()) + goto again; + + /* Big problems... */ + } + return f; } #ifdef CONFIG_QUOTA @@ -146,10 +107,9 @@ void add_dquot_ref(kdev_t dev, short type) { struct file *filp; - int cnt; - for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) { - if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev) + for (filp = inuse_filps; filp; filp = filp->f_next) { + if (!filp->f_inode || filp->f_inode->i_dev != dev) continue; if (filp->f_mode & FMODE_WRITE && filp->f_inode->i_sb->dq_op) { filp->f_inode->i_sb->dq_op->initialize(filp->f_inode, type); @@ -161,10 +121,9 @@ void reset_dquot_ptrs(kdev_t dev, short type) { struct file *filp; - int cnt; - for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) { - if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev) + for (filp = inuse_filps; filp; filp = filp->f_next) { + if (!filp->f_inode || filp->f_inode->i_dev != dev) continue; if (IS_WRITABLE(filp->f_inode)) { filp->f_inode->i_dquot[type] = NODQUOT; diff -u --recursive --new-file v2.1.36/linux/fs/inode.c linux/fs/inode.c --- v2.1.36/linux/fs/inode.c Wed Apr 23 19:01:24 1997 +++ linux/fs/inode.c Sun Apr 27 15:08:01 1997 @@ -232,12 +232,10 @@ int fs_may_remount_ro(kdev_t dev) { struct file * file; - int i; /* Check that no files are currently opened for writing. */ - for (file = first_file, i=0; if_next) { - if (!file->f_count || !file->f_inode || - file->f_inode->i_dev != dev) + for (file = inuse_filps; file; file = file->f_next) { + if (!file->f_inode || file->f_inode->i_dev != dev) continue; if (S_ISREG(file->f_inode->i_mode) && (file->f_mode & 2)) return 0; @@ -288,7 +286,7 @@ ((attr->ia_valid & ATTR_GID) && (!in_group_p(attr->ia_gid) && - (attr->ia_gid != inode->i_gid))) || + (attr->ia_gid != inode->i_gid)) && not_fsuser) || ((attr->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)) && (fsuid != iuid) && not_fsuser)) @@ -325,6 +323,8 @@ if (!fsuser() && !in_group_p(inode->i_gid)) inode->i_mode &= ~S_ISGID; } + if (attr->ia_valid & ATTR_ATTR_FLAG) + inode->i_attr_flags = attr->ia_attr_flags; inode->i_dirt = 1; } diff -u --recursive --new-file v2.1.36/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c --- v2.1.36/linux/fs/lockd/svcsubs.c Mon Apr 7 11:35:30 1997 +++ linux/fs/lockd/svcsubs.c Sun Apr 27 15:08:02 1997 @@ -228,12 +228,12 @@ down(&nlm_file_sema); /* If there are no more locks etc, delete the file */ - if (--(file->f_count) == 0 - && !nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) - nlm_delete_file(file); + if(--file->f_count == 0) { + if(!nlm_inspect_file(NULL, file, NLM_ACT_CHECK)) + nlm_delete_file(file); + } up(&nlm_file_sema); - return; } /* diff -u --recursive --new-file v2.1.36/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c --- v2.1.36/linux/fs/msdos/msdosfs_syms.c Wed Apr 23 19:01:26 1997 +++ linux/fs/msdos/msdosfs_syms.c Fri Apr 25 15:25:56 1997 @@ -30,7 +30,7 @@ EXPORT_SYMBOL(msdos_put_super); -static struct file_system_type msdos_fs_type = { +struct file_system_type msdos_fs_type = { msdos_read_super, "msdos", 1, NULL }; diff -u --recursive --new-file v2.1.36/linux/fs/namei.c linux/fs/namei.c --- v2.1.36/linux/fs/namei.c Thu Mar 27 14:40:06 1997 +++ linux/fs/namei.c Fri May 2 13:14:12 1997 @@ -124,24 +124,16 @@ * put_write_access() releases this write permission. * This is used for regular files. * We cannot support write (and maybe mmap read-write shared) accesses and - * MAP_DENYWRITE mmappings simultaneously. + * MAP_DENYWRITE mmappings simultaneously. The i_writecount field of an inode + * can have the following values: + * 0: no writers, no VM_DENYWRITE mappings + * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist + * > 0: (i_writecount) users are writing to the file. */ int get_write_access(struct inode * inode) { - struct task_struct * p; - - if ((inode->i_count > 1) && S_ISREG(inode->i_mode)) /* shortcut */ - for_each_task(p) { - struct vm_area_struct * mpnt; - if (!p->mm) - continue; - for(mpnt = p->mm->mmap; mpnt; mpnt = mpnt->vm_next) { - if (inode != mpnt->vm_inode) - continue; - if (mpnt->vm_flags & VM_DENYWRITE) - return -ETXTBSY; - } - } + if (inode->i_writecount < 0) + return -ETXTBSY; inode->i_writecount++; return 0; } diff -u --recursive --new-file v2.1.36/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.1.36/linux/fs/ncpfs/inode.c Wed Apr 23 19:01:26 1997 +++ linux/fs/ncpfs/inode.c Sun Apr 27 15:08:02 1997 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -177,7 +178,7 @@ printk("ncp_read_super: could not alloc ncp_server\n"); return NULL; } - ncp_filp->f_count += 1; + ncp_filp->f_count++; lock_super(sb); @@ -256,7 +257,7 @@ ncp_unlock_server(server); ncp_kfree_s(server->packet, server->packet_size); fail: - ncp_filp->f_count -= 1; + put_filp(ncp_filp); ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server)); return NULL; } diff -u --recursive --new-file v2.1.36/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.36/linux/fs/nfsd/vfs.c Wed Apr 23 19:01:27 1997 +++ linux/fs/nfsd/vfs.c Sun Apr 27 15:08:02 1997 @@ -285,6 +285,10 @@ if (err) { if (wflag) put_write_access(inode); + + /* I nearly added put_filp() call here, but this filp + * is really on callers stack frame. -DaveM + */ filp->f_count--; return nfserrno(-err); } diff -u --recursive --new-file v2.1.36/linux/fs/open.c linux/fs/open.c --- v2.1.36/linux/fs/open.c Fri Apr 4 08:52:24 1997 +++ linux/fs/open.c Sun Apr 27 15:08:02 1997 @@ -605,7 +605,7 @@ cleanup_inode: iput(inode); cleanup_file: - f->f_count--; + put_filp(f); return error; } diff -u --recursive --new-file v2.1.36/linux/fs/pipe.c linux/fs/pipe.c --- v2.1.36/linux/fs/pipe.c Fri Apr 4 08:52:24 1997 +++ linux/fs/pipe.c Sun Apr 27 15:08:02 1997 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,10 @@ PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); if (read) { - inode->i_atime = CURRENT_TIME; + if (DO_UPDATE_ATIME(inode)) { + inode->i_atime = CURRENT_TIME; + inode->i_dirt = 1; + } return read; } if (PIPE_WRITERS(*inode)) @@ -128,6 +132,7 @@ free = 1; } inode->i_ctime = inode->i_mtime = CURRENT_TIME; + inode->i_dirt = 1; return written; } @@ -440,9 +445,9 @@ inode->i_count--; iput(inode); close_f12: - f2->f_count--; + put_filp(f2); close_f1: - f1->f_count--; + put_filp(f1); no_files: return error; } diff -u --recursive --new-file v2.1.36/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.36/linux/fs/proc/array.c Mon Apr 14 16:28:18 1997 +++ linux/fs/proc/array.c Thu May 1 11:06:33 1997 @@ -154,9 +154,7 @@ return read; } -#ifdef __SMP__ -extern int setup_profiling_timer (unsigned int multiplier); /* * Writing to /proc/profile resets the counters @@ -168,6 +166,8 @@ const char * buf, unsigned long count) { int i=prof_len; +#ifdef __SMP__ + extern int setup_profiling_timer (unsigned int multiplier); if (count==sizeof(int)) { unsigned int multiplier; @@ -178,14 +178,12 @@ if (setup_profiling_timer(multiplier)) return -EINVAL; } +#endif while (i--) prof_buffer[i]=0UL; return count; } -#else -#define write_profile NULL -#endif static struct file_operations proc_profile_operations = { NULL, /* lseek */ @@ -344,18 +342,6 @@ return sprintf(buffer, "%s\n", saved_command_line); } -static struct task_struct ** get_task(pid_t pid) -{ - struct task_struct ** p; - - p = task; - while (++p < task+NR_TASKS) { - if (*p && (*p)->pid == pid) - return p; - } - return NULL; -} - static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr) { pgd_t *page_dir; @@ -386,7 +372,7 @@ return pte_page(pte) + (ptr & ~PAGE_MASK); } -static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer) +static int get_array(struct task_struct *p, unsigned long start, unsigned long end, char * buffer) { unsigned long addr; int size = 0, result = 0; @@ -395,7 +381,7 @@ if (start >= end) return result; for (;;) { - addr = get_phys_addr(*p, start); + addr = get_phys_addr(p, start); if (!addr) return result; do { @@ -417,20 +403,20 @@ static int get_env(int pid, char * buffer) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); - if (!p || !*p || !(*p)->mm) + if (!p || !p->mm) return 0; - return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer); + return get_array(p, p->mm->env_start, p->mm->env_end, buffer); } static int get_arg(int pid, char * buffer) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); - if (!p || !*p || !(*p)->mm) + if (!p || !p->mm) return 0; - return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer); + return get_array(p, p->mm->arg_start, p->mm->arg_end, buffer); } static unsigned long get_wchan(struct task_struct *p) @@ -443,7 +429,7 @@ unsigned long stack_page; int count = 0; - stack_page = p->kernel_stack_page; + stack_page = 4096 + (unsigned long)p; if (!stack_page) return 0; ebp = p->tss.ebp; @@ -507,15 +493,16 @@ } #if defined(__i386__) -# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019]) -# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022]) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) #elif defined(__alpha__) /* * See arch/alpha/kernel/ptrace.c for details. */ # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + (long)&((struct pt_regs *)0)->reg) -# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc))) +# define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) #elif defined(__mc68000__) #define KSTK_EIP(tsk) \ @@ -681,9 +668,9 @@ static int get_status(int pid, char * buffer) { char * orig = buffer; - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; buffer = task_name(tsk, buffer); buffer = task_state(tsk, buffer); @@ -694,14 +681,14 @@ static int get_stat(int pid, char * buffer) { - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); unsigned long sigignore=0, sigcatch=0, wchan; unsigned long vsize, eip, esp; long priority, nice; int i,tty_pgrp; char state; - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; if (tsk->state < 0 || tsk->state > 5) state = '.'; @@ -714,10 +701,8 @@ vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } - if (tsk->kernel_stack_page) { - eip = KSTK_EIP(tsk); - esp = KSTK_ESP(tsk); - } + eip = KSTK_EIP(tsk); + esp = KSTK_ESP(tsk); } wchan = get_wchan(tsk); if (tsk->sig) { @@ -864,10 +849,10 @@ static int get_statm(int pid, char * buffer) { - struct task_struct ** p = get_task(pid), *tsk; + struct task_struct *tsk = find_task_by_pid(pid); int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; - if (!p || (tsk = *p) == NULL) + if (!tsk) return 0; if (tsk->mm && tsk->mm != &init_mm) { struct vm_area_struct * vma = tsk->mm->mmap; @@ -932,17 +917,17 @@ static long read_maps (int pid, struct file * file, char * buf, unsigned long count) { - struct task_struct ** p = get_task(pid); + struct task_struct *p = find_task_by_pid(pid); char * destptr; loff_t lineno; int column; struct vm_area_struct * map; int i; - if (!p || !*p) + if (!p) return -EINVAL; - if (!(*p)->mm || (*p)->mm == &init_mm || count == 0) + if (!p->mm || p->mm == &init_mm || count == 0) return 0; /* decode f_pos */ @@ -950,7 +935,7 @@ column = file->f_pos & (MAPS_LINE_LENGTH-1); /* quickly go to line lineno */ - for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) + for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++) continue; destptr = buf; @@ -1011,7 +996,7 @@ /* By writing to user space, we might have slept. * Stop the loop, to avoid a race condition. */ - if (*p != current) + if (p != current) break; } diff -u --recursive --new-file v2.1.36/linux/fs/proc/base.c linux/fs/proc/base.c --- v2.1.36/linux/fs/proc/base.c Sun Jan 26 02:07:45 1997 +++ linux/fs/proc/base.c Sun Apr 27 15:08:02 1997 @@ -52,17 +52,14 @@ static void proc_pid_fill_inode(struct inode * inode) { - struct task_struct * p; + struct task_struct *p; int pid = inode->i_ino >> 16; int ino = inode->i_ino & 0xffff; - for_each_task(p) { - if (p->pid == pid) { - if (p->dumpable || ino == PROC_PID_INO) { - inode->i_uid = p->euid; - inode->i_gid = p->gid; - } - return; + if ((p = find_task_by_pid(pid)) != NULL) { + if (p->dumpable || ino == PROC_PID_INO) { + inode->i_uid = p->euid; + inode->i_gid = p->gid; } } } diff -u --recursive --new-file v2.1.36/linux/fs/proc/fd.c linux/fs/proc/fd.c --- v2.1.36/linux/fs/proc/fd.c Thu Mar 27 14:40:06 1997 +++ linux/fs/proc/fd.c Sun Apr 27 15:08:02 1997 @@ -58,7 +58,6 @@ unsigned int ino, pid, fd, c; struct task_struct * p; struct super_block * sb; - int i; *result = NULL; ino = dir->i_ino; @@ -100,10 +99,8 @@ break; } } - for (i = 0 ; i < NR_TASKS ; i++) - if ((p = task[i]) && p->pid == pid) - break; - if (!pid || i >= NR_TASKS) + p = find_task_by_pid(pid); + if (!pid || !p) return -ENOENT; /* @@ -112,8 +109,11 @@ * is NULL */ - if (fd >= NR_OPEN || !p->files || !p->files->fd[fd] || !p->files->fd[fd]->f_inode) - return -ENOENT; + if (fd >= NR_OPEN || + !p->files || + !p->files->fd[fd] || + !p->files->fd[fd]->f_inode) + return -ENOENT; ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; @@ -128,8 +128,7 @@ void * dirent, filldir_t filldir) { char buf[NUMBUF]; - int task_nr; - struct task_struct * p; + struct task_struct * p, **tarrayp; unsigned int fd, pid, ino; unsigned long i,j; @@ -149,13 +148,10 @@ return 0; } - task_nr = 1; - for (;;) { - if ((p = task[task_nr]) && p->pid == pid) - break; - if (++task_nr >= NR_TASKS) - return 0; - } + p = find_task_by_pid(pid); + if(!p) + return 0; + tarrayp = p->tarray_ptr; for (fd -= 2 ; fd < NR_OPEN; fd++, filp->f_pos++) { if (!p->files) @@ -176,7 +172,7 @@ break; /* filldir() might have slept, so we must re-validate "p" */ - if (p != task[task_nr] || p->pid != pid) + if (p != *tarrayp || p->pid != pid) break; } return 0; diff -u --recursive --new-file v2.1.36/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v2.1.36/linux/fs/proc/inode.c Mon Mar 17 14:54:30 1997 +++ linux/fs/proc/inode.c Sun Apr 27 15:08:02 1997 @@ -81,7 +81,6 @@ struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de) { struct inode * inode = iget(s, ino); - struct task_struct *p; #ifdef CONFIG_SUN_OPENPROMFS_MODULE if ((inode->i_ino >= PROC_OPENPROM_FIRST) @@ -111,9 +110,14 @@ * Fixup the root inode's nlink value */ if (inode->i_ino == PROC_ROOT_INO) { - for_each_task(p) - if (p && p->pid) + struct task_struct *p; + + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->pid) inode->i_nlink++; + } + read_unlock(&tasklist_lock); } return inode; } @@ -155,7 +159,6 @@ { unsigned long ino, pid; struct task_struct * p; - int i; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; @@ -170,13 +173,8 @@ inode->i_nlink = 1; inode->i_size = 0; pid = ino >> 16; - if (!pid) - return; - p = task[0]; - for (i = 0; i < NR_TASKS ; i++) - if ((p = task[i]) && (p->pid == pid)) - break; - if (!p || i >= NR_TASKS) + + if (!pid || ((p = find_task_by_pid(pid)) == NULL)) return; ino &= 0x0000ffff; @@ -198,7 +196,6 @@ inode->i_mode |= S_IWUSR | S_IXUSR; return; } - return; } void proc_write_inode(struct inode * inode) diff -u --recursive --new-file v2.1.36/linux/fs/proc/link.c linux/fs/proc/link.c --- v2.1.36/linux/fs/proc/link.c Sun Jan 26 02:07:45 1997 +++ linux/fs/proc/link.c Sun Apr 27 15:08:02 1997 @@ -68,7 +68,7 @@ unsigned int pid, ino; struct task_struct * p; struct inode * new_inode; - int i, error; + int error; *res_inode = NULL; if (dir) @@ -82,10 +82,9 @@ ino = inode->i_ino; pid = ino >> 16; ino &= 0x0000ffff; - for (i = 0 ; i < NR_TASKS ; i++) - if ((p = task[i]) && p->pid == pid) - break; - if (i >= NR_TASKS) { + + p = find_task_by_pid(pid); + if (!p) { iput(inode); return -ENOENT; } diff -u --recursive --new-file v2.1.36/linux/fs/proc/mem.c linux/fs/proc/mem.c --- v2.1.36/linux/fs/proc/mem.c Mon Apr 14 16:28:18 1997 +++ linux/fs/proc/mem.c Sun Apr 27 15:08:02 1997 @@ -55,16 +55,10 @@ struct task_struct * tsk = current; if (pid != tsk->pid) { - int i; - tsk = NULL; - for (i = 1 ; i < NR_TASKS ; i++) - if (task[i] && task[i]->pid == pid) { - tsk = task[i]; - break; - } - /* - * allow accesses only under the same circumstances - * that we would allow ptrace to work + tsk = find_task_by_pid(pid); + + /* Allow accesses only under the same circumstances + * that we would allow ptrace to work. */ if (tsk) { if (!(tsk->flags & PF_PTRACED) diff -u --recursive --new-file v2.1.36/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.36/linux/fs/proc/root.c Wed Apr 23 19:01:27 1997 +++ linux/fs/proc/root.c Sun Apr 27 15:08:02 1997 @@ -683,16 +683,20 @@ struct inode ** result) { unsigned int pid, c; - int i, ino, retval; + int ino, retval; struct task_struct *p; dir->i_count++; if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */ dir->i_nlink = proc_root.nlink; - for_each_task(p) - if (p && p->pid) + + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->pid) dir->i_nlink++; + } + read_unlock(&tasklist_lock); } retval = proc_lookup(dir, name, len, result); @@ -716,10 +720,8 @@ break; } } - for (i = 0 ; i < NR_TASKS ; i++) - if (task[i] && task[i]->pid == pid) - break; - if (!pid || i >= NR_TASKS) { + p = find_task_by_pid(pid); + if (!pid || !p) { iput(dir); return -ENOENT; } @@ -796,34 +798,40 @@ static int proc_root_readdir(struct inode * inode, struct file * filp, void * dirent, filldir_t filldir) { + struct task_struct *p; char buf[NUMBUF]; - unsigned int nr,pid; - unsigned long i,j; + unsigned int nr = filp->f_pos; - nr = filp->f_pos; if (nr < FIRST_PROCESS_ENTRY) { int error = proc_readdir(inode, filp, dirent, filldir); if (error <= 0) return error; - filp->f_pos = nr = FIRST_PROCESS_ENTRY; + filp->f_pos = FIRST_PROCESS_ENTRY; } + nr = FIRST_PROCESS_ENTRY; - for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) { - struct task_struct * p = task[nr]; + read_lock(&tasklist_lock); + for_each_task(p) { + unsigned int pid; - if (!p || !(pid = p->pid)) + if(nr++ < filp->f_pos) continue; - j = NUMBUF; - i = pid; - do { - j--; - buf[j] = '0' + (i % 10); - i /= 10; - } while (i); + if((pid = p->pid) != 0) { + unsigned long j = NUMBUF, i = pid; - if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) - break; + do { + j--; + buf[j] = '0' + (i % 10); + i /= 10; + } while (i); + + if (filldir(dirent, buf+j, NUMBUF-j, + filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + break; + } + filp->f_pos++; } + read_unlock(&tasklist_lock); return 0; } diff -u --recursive --new-file v2.1.36/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.1.36/linux/fs/smbfs/inode.c Wed Apr 23 19:01:27 1997 +++ linux/fs/smbfs/inode.c Sun Apr 27 15:08:02 1997 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -242,7 +243,7 @@ printk("smb_read_super: could not alloc smb_sb_info\n"); return NULL; } - filp->f_count += 1; + filp->f_count++; lock_super(sb); @@ -319,7 +320,7 @@ smb_vfree(server->packet); server->packet = NULL; } - filp->f_count -= 1; + put_filp(filp); smb_dont_catch_keepalive(server); smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info)); return NULL; diff -u --recursive --new-file v2.1.36/linux/fs/super.c linux/fs/super.c --- v2.1.36/linux/fs/super.c Mon Apr 14 16:28:18 1997 +++ linux/fs/super.c Thu May 1 12:05:02 1997 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -937,7 +938,11 @@ return retval; } +#ifdef CONFIG_BLK_DEV_INITRD static void do_mount_root(void) +#else +__initfunc(static void do_mount_root(void)) +#endif { struct file_system_type * fs_type; struct super_block * sb; @@ -1046,7 +1051,7 @@ } -void mount_root(void) +__initfunc(void mount_root(void)) { memset(super_blocks, 0, sizeof(super_blocks)); do_mount_root(); diff -u --recursive --new-file v2.1.36/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c --- v2.1.36/linux/fs/umsdos/namei.c Sat Nov 30 02:24:02 1996 +++ linux/fs/umsdos/namei.c Sun Apr 27 10:48:43 1997 @@ -301,6 +301,9 @@ ,*(unsigned long *)current->kernel_stack_page \ ,__LINE__); \ } + +#undef chkstk +#define chkstk() do { } while (0) /* Rename a file (move) in the file system. diff -u --recursive --new-file v2.1.36/linux/fs/vfat/namei.c linux/fs/vfat/namei.c --- v2.1.36/linux/fs/vfat/namei.c Wed Apr 23 19:01:27 1997 +++ linux/fs/vfat/namei.c Sun Apr 27 10:49:01 1997 @@ -174,10 +174,12 @@ printk("------- vfat kstack ok in %s line %d: SL=%d\n", fname, lineno, stack_level); #endif +#if 0 if (*(unsigned long *) current->kernel_stack_page != STACK_MAGIC) { printk("******* vfat stack corruption detected in %s at line %d\n", fname, lineno); } +#endif } static int debug = 0; diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/atomic.h linux/include/asm-alpha/atomic.h --- v2.1.36/linux/include/asm-alpha/atomic.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-alpha/atomic.h Thu May 1 11:06:33 1997 @@ -41,9 +41,9 @@ " addl %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)) :"Ir" (i), "m" (__atomic_fool_gcc(v))); } @@ -56,9 +56,9 @@ " subl %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)) :"Ir" (i), "m" (__atomic_fool_gcc(v))); } @@ -75,9 +75,9 @@ " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)), "=&r" (result) :"Ir" (i), "m" (__atomic_fool_gcc(v))); return result; @@ -92,9 +92,9 @@ " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (__atomic_fool_gcc(v)), "=&r" (result) :"Ir" (i), "m" (__atomic_fool_gcc(v))); return result; diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h --- v2.1.36/linux/include/asm-alpha/bitops.h Fri Apr 4 08:52:24 1997 +++ linux/include/asm-alpha/bitops.h Thu May 1 11:06:33 1997 @@ -31,9 +31,9 @@ " stl_c %0,%1\n" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); @@ -54,9 +54,9 @@ " stl_c %0,%1\n\t" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); @@ -75,9 +75,9 @@ " xor %0,%3,%0\n\t" " stl_c %0,%1\n\t" " beq %0,3f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (*m), "=&r" (oldbit) :"Ir" (1UL << (nr & 31)), "m" (*m)); diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/current.h linux/include/asm-alpha/current.h --- v2.1.36/linux/include/asm-alpha/current.h Thu Feb 6 04:42:35 1997 +++ linux/include/asm-alpha/current.h Thu May 1 11:08:18 1997 @@ -1,12 +1,6 @@ #ifndef _ALPHA_CURRENT_H #define _ALPHA_CURRENT_H -/* Some architectures may want to do something "clever" here since - * this is the most frequently accessed piece of data in the entire - * kernel. - */ -extern struct task_struct *current_set[NR_CPUS]; - register struct task_struct *current __asm__("$8"); #endif /* !(_ALPHA_CURRENT_H) */ diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h --- v2.1.36/linux/include/asm-alpha/io.h Mon Apr 14 16:28:18 1997 +++ linux/include/asm-alpha/io.h Mon May 5 08:16:41 1997 @@ -39,7 +39,7 @@ extern inline void set_hae(unsigned long new_hae) { unsigned long ipl; - swpipl(ipl,7); + ipl = swpipl(7); hae.cache = new_hae; *hae.reg = new_hae; mb(); diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v2.1.36/linux/include/asm-alpha/processor.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-alpha/processor.h Thu May 1 11:06:33 1997 @@ -49,7 +49,7 @@ }; #define INIT_MMAP { &init_mm, 0xfffffc0000000000, 0xfffffc0010000000, \ - PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC } + PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ 0, 0, 0, \ @@ -85,10 +85,12 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* Allocation and freeing of basic task resources. */ -#define alloc_task_struct() kmalloc(sizeof(struct task_struct), GFP_KERNEL) -#define alloc_kernel_stack(p) __get_free_page(GFP_KERNEL) -#define free_task_struct(p) kfree(p) -#define free_kernel_stack(page) free_page((page)) +/* NOTE: The task struct and the stack go together! */ +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) #endif /* __ASM_ALPHA_PROCESSOR_H */ diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h --- v2.1.36/linux/include/asm-alpha/semaphore.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-alpha/semaphore.h Thu May 1 11:06:33 1997 @@ -47,9 +47,9 @@ " stl_c %0,%2\n" " beq %0,3f\n" "2:\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "3: br 1b\n" - ".text" + ".previous" : "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking)) : "0"(0)); diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h --- v2.1.36/linux/include/asm-alpha/softirq.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-alpha/softirq.h Thu May 1 11:06:33 1997 @@ -17,9 +17,9 @@ " and %0,%2,%0\n" " stq_c %0,%1\n" " beq %0,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" :"=&r" (temp), "=m" (bh_active) :"Ir" (x), "m" (bh_active)); } diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h --- v2.1.36/linux/include/asm-alpha/spinlock.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-alpha/spinlock.h Mon May 5 08:16:41 1997 @@ -3,8 +3,9 @@ #ifndef __SMP__ -typedef struct { } spinlock_t; -#define SPIN_LOCK_UNLOCKED { } +/* gcc 2.7.2 can crash initializing an empty structure. */ +typedef struct { int dummy; } spinlock_t; +#define SPIN_LOCK_UNLOCKED { 0 } #define spin_lock_init(lock) do { } while(0) #define spin_lock(lock) do { } while(0) @@ -14,7 +15,7 @@ #define spin_lock_irq(lock) setipl(7) #define spin_unlock_irq(lock) setipl(0) -#define spin_lock_irqsave(lock, flags) swpipl(flags,7) +#define spin_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0) #define spin_unlock_irqrestore(lock, flags) setipl(flags) /* @@ -27,8 +28,8 @@ * irq-safe write-lock, but readers can get non-irqsafe * read-locks. */ -typedef struct { } rwlock_t; -#define RW_LOCK_UNLOCKED { } +typedef struct { int dummy; } rwlock_t; +#define RW_LOCK_UNLOCKED { 0 } #define read_lock(lock) do { } while(0) #define read_unlock(lock) do { } while(0) @@ -39,10 +40,10 @@ #define write_lock_irq(lock) cli() #define write_unlock_irq(lock) sti() -#define read_lock_irqsave(lock, flags) save_and_cli(flags) -#define read_unlock_irqrestore(lock, flags) restore_flags(flags) -#define write_lock_irqsave(lock, flags) save_and_cli(flags) -#define write_unlock_irqrestore(lock, flags) restore_flags(flags) +#define read_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0) +#define read_unlock_irqrestore(lock, flags) setipl(flags) +#define write_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0) +#define write_unlock_irqrestore(lock, flags) setipl(flags) #else @@ -89,13 +90,13 @@ " stq_c %0,%1\n" " beq %0,3f\n" "4: mb\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: ldq %0,%1\n" " subq %2,1,%2\n" "3: blt %2,4b\n" " blbs %0,2b\n" " br 1b\n" - ".text" + ".previous" : "=r" (tmp), "=m" (__dummy_lock(lock)), "=r" (stuck) @@ -116,7 +117,7 @@ do { spin_unlock(lock); __sti(); } while (0) #define spin_lock_irqsave(lock, flags) \ - do { swpipl(flags,7); spin_lock(lock); } while (0) + do { flags = swpipl(7); spin_lock(lock); } while (0) #define spin_unlock_irqrestore(lock, flags) \ do { spin_unlock(lock); setipl(flags); } while (0) diff -u --recursive --new-file v2.1.36/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.1.36/linux/include/asm-alpha/system.h Fri Apr 4 08:52:25 1997 +++ linux/include/asm-alpha/system.h Mon May 5 08:16:41 1997 @@ -56,63 +56,95 @@ #define halt() __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_halt) : "memory") #define switch_to(prev,next) do { \ - current_set[0] = current = next; \ + current = next; \ alpha_switch_to((unsigned long) ¤t->tss - 0xfffffc0000000000); \ } while (0) extern void alpha_switch_to(unsigned long pctxp); -extern void imb(void); - #define mb() \ __asm__ __volatile__("mb": : :"memory") +#define imb() \ +__asm__ __volatile__ ("call_pal %0" : : "i" (PAL_imb) : "memory") + #define draina() \ __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_draina) : "memory") -#define getipl(__old_ipl) \ -__asm__ __volatile__( \ - "call_pal 54\n\t" \ - "bis $0,$0,%0" \ - : "=r" (__old_ipl) \ - : : "$0", "$1", "$16", "$22", "$23", "$24", "$25") - -#define setipl(__new_ipl) \ -__asm__ __volatile__( \ - "bis %0,%0,$16\n\t" \ - "call_pal 53" \ - : : "r" (__new_ipl) \ - : "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory") - -#define swpipl(__old_ipl,__new_ipl) \ -__asm__ __volatile__( \ - "bis %1,%1,$16\n\t" \ - "call_pal 53\n\t" \ - "bis $0,$0,%0" \ - : "=r" (__old_ipl) \ - : "r" (__new_ipl) \ - : "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory") +#define call_pal1(palno,arg) \ +({ \ + register unsigned long __r0 __asm__("$0"); \ + register unsigned long __r16 __asm__("$16"); __r16 = arg; \ + __asm__ __volatile__( \ + "call_pal %3" \ + :"=r" (__r0),"=r" (__r16) \ + :"1" (__r16),"i" (palno) \ + :"$1", "$22", "$23", "$24", "$25", "memory"); \ + __r0; \ +}) + +#define getipl() \ +({ \ + register unsigned long r0 __asm__("$0"); \ + __asm__ __volatile__( \ + "call_pal %1" \ + :"=r" (r0) \ + :"i" (PAL_rdps) \ + :"$1", "$16", "$22", "$23", "$24", "$25", "memory"); \ + r0; \ +}) + +#define setipl(ipl) \ +do { \ + register unsigned long __r16 __asm__("$16") = (ipl); \ + __asm__ __volatile__( \ + "call_pal %2" \ + :"=r" (__r16) \ + :"0" (__r16),"i" (PAL_swpipl) \ + :"$0", "$1", "$22", "$23", "$24", "$25", "memory"); \ +} while (0) + +#define swpipl(ipl) \ +({ \ + register unsigned long __r0 __asm__("$0"); \ + register unsigned long __r16 __asm__("$16") = (ipl); \ + __asm__ __volatile__( \ + "call_pal %3" \ + :"=r" (__r0),"=r" (__r16) \ + :"1" (__r16),"i" (PAL_swpipl) \ + :"$1", "$22", "$23", "$24", "$25", "memory"); \ + __r0; \ +}) #define __cli() setipl(7) #define __sti() setipl(0) -#define __save_flags(flags) getipl(flags) +#define __save_flags(flags) do { (flags) = getipl(); } while (0) #define __restore_flags(flags) setipl(flags) #define cli() setipl(7) #define sti() setipl(0) -#define save_flags(flags) getipl(flags) +#define save_flags(flags) do { (flags) = getipl(); } while (0) #define restore_flags(flags) setipl(flags) /* * TB routines.. */ -extern void tbi(long type, ...); +#define __tbi(nr,arg,arg1...) do { \ + register unsigned long __r16 __asm__("$16") = (nr); \ + register unsigned long __r17 __asm__("$17"); arg; \ + __asm__ __volatile__( \ + "call_pal %3" \ + :"=r" (__r16),"=r" (__r17) \ + :"0" (__r16),"i" (PAL_tbi) ,##arg1 \ + :"$0", "$1", "$22", "$23", "$24", "$25"); \ +} while (0) -#define tbisi(x) tbi(1,(x)) -#define tbisd(x) tbi(2,(x)) -#define tbis(x) tbi(3,(x)) -#define tbiap() tbi(-1) -#define tbia() tbi(-2) +#define tbi(x,y) __tbi(x,__r17=(y),"1" (__r17)) +#define tbisi(x) __tbi(1,__r17=(x),"1" (__r17)) +#define tbisd(x) __tbi(2,__r17=(x),"1" (__r17)) +#define tbis(x) __tbi(3,__r17=(x),"1" (__r17)) +#define tbiap() __tbi(-1, /* no second argument */) +#define tbia() __tbi(-2, /* no second argument */) /* * Give prototypes to shut up gcc. @@ -129,9 +161,9 @@ " bis %3,%3,%1\n" " stl_c %1,%2\n" " beq %1,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) : "r" (val), "m" (*m)); @@ -147,9 +179,9 @@ " bis %3,%3,%1\n" " stq_c %1,%2\n" " beq %1,2f\n" - ".text 2\n" + ".section .text2,\"ax\"\n" "2: br 1b\n" - ".text" + ".previous" : "=&r" (val), "=&r" (dummy), "=m" (*m) : "r" (val), "m" (*m)); diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/current.h linux/include/asm-i386/current.h --- v2.1.36/linux/include/asm-i386/current.h Mon Dec 30 01:58:34 1996 +++ linux/include/asm-i386/current.h Wed Apr 30 15:38:34 1997 @@ -1,12 +1,14 @@ #ifndef _I386_CURRENT_H #define _I386_CURRENT_H -/* Some architectures may want to do something "clever" here since - * this is the most frequently accessed piece of data in the entire - * kernel. For an example, see the Sparc implementation where an - * entire register is hard locked to contain the value of current. - */ -extern struct task_struct *current_set[NR_CPUS]; -#define current (current_set[smp_processor_id()]) /* Current on this processor */ +static inline unsigned long get_esp(void) +{ + unsigned long esp; + __asm__("movl %%esp,%0":"=r" (esp)); + return esp; +} + +#define current ((struct task_struct *)(get_esp() & ~8191UL)) + #endif /* !(_I386_CURRENT_H) */ diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/delay.h linux/include/asm-i386/delay.h --- v2.1.36/linux/include/asm-i386/delay.h Sun Jan 26 05:36:05 1997 +++ linux/include/asm-i386/delay.h Mon Apr 28 13:57:56 1997 @@ -36,7 +36,7 @@ __asm__("mull %0" :"=d" (usecs) #ifdef __SMP__ - :"a" (usecs),"0" (cpu_data[smp_processor_id()].udelay_val) + :"a" (usecs),"0" (cpu_data[hard_smp_processor_id()].udelay_val) #else :"a" (usecs),"0" (loops_per_sec) #endif diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h --- v2.1.36/linux/include/asm-i386/hardirq.h Mon Apr 14 16:28:18 1997 +++ linux/include/asm-i386/hardirq.h Sun Apr 27 19:59:03 1997 @@ -4,7 +4,7 @@ #include extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) +#define in_interrupt() (local_irq_count[hard_smp_processor_id()] != 0) #ifndef __SMP__ diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.1.36/linux/include/asm-i386/processor.h Sun Jan 26 02:07:46 1997 +++ linux/include/asm-i386/processor.h Mon Apr 28 20:49:32 1997 @@ -119,14 +119,15 @@ /* virtual 86 mode info */ struct vm86_struct * vm86_info; unsigned long screen_bitmap; - unsigned long v86flags, v86mask, v86mode; + unsigned long v86flags, v86mask, v86mode, saved_esp0; }; -#define INIT_MMAP { &init_mm, 0xC0000000, 0xFFFFF000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC } +#define INIT_MMAP \ +{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ 0,0, \ - sizeof(init_kernel_stack) + (long) &init_kernel_stack, \ + sizeof(init_stack) + (long) &init_stack, \ KERNEL_DS, 0, \ 0,0,0,0,0,0, \ (long) &swapper_pg_dir - PAGE_OFFSET, \ @@ -137,7 +138,7 @@ {~0, }, /* ioperm */ \ _TSS(0), 0, 0, 0, KERNEL_DS, \ { { 0, }, }, /* 387 state */ \ - NULL, 0, 0, 0, 0 /* vm86_info */, \ + NULL, 0, 0, 0, 0, 0 /* vm86_info */, \ } #define start_thread(regs, new_eip, new_esp) do {\ @@ -164,9 +165,14 @@ } /* Allocation and freeing of basic task resources. */ -#define alloc_task_struct() kmalloc(sizeof(struct task_struct), GFP_KERNEL) -#define alloc_kernel_stack(p) __get_free_page(GFP_KERNEL) -#define free_task_struct(p) kfree(p) -#define free_kernel_stack(page) free_page((page)) +/* + * NOTE! The task struct and the stack go together + */ +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) #endif /* __ASM_I386_PROCESSOR_H */ diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h --- v2.1.36/linux/include/asm-i386/smp.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-i386/smp.h Mon Apr 28 13:46:56 1997 @@ -178,7 +178,6 @@ extern int smp_scan_config(unsigned long, unsigned long); extern unsigned long smp_alloc_memory(unsigned long mem_base); extern unsigned char *apic_reg; -extern unsigned char *kernel_stacks[NR_CPUS]; extern unsigned char boot_cpu_id; extern unsigned long cpu_present_map; extern volatile int cpu_number_map[NR_CPUS]; @@ -192,6 +191,9 @@ extern void smp_reschedule_irq(int cpl, struct pt_regs *regs); extern unsigned long ipi_count; extern void smp_invalidate_rcv(void); /* Process an NMI */ +extern void smp_local_timer_interrupt(struct pt_regs * regs); +extern void setup_APIC_clock (void); + /* * General functions that each host system must provide. @@ -228,7 +230,9 @@ * the apic we get the right answer). Hopefully other processors are more sensible 8) */ -extern __inline int smp_processor_id(void) +#define smp_processor_id() (current->processor) + +extern __inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ return GET_APIC_ID(*(unsigned long *)(apic_reg+APIC_ID)); diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/smp_lock.h linux/include/asm-i386/smp_lock.h --- v2.1.36/linux/include/asm-i386/smp_lock.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-i386/smp_lock.h Fri May 2 19:13:06 1997 @@ -31,14 +31,11 @@ #define reacquire_kernel_lock(task, cpu, depth) \ do { if (depth) __asm__ __volatile__( \ "cli\n\t" \ - "movl $0f,%%eax\n\t" \ - "jmp __lock_kernel\n" \ - "0:\t" \ + "call __lock_kernel\n\t" \ "movl %2,%0\n\t" \ "sti" \ : "=m" (task->lock_depth) \ - : "d" (cpu), "c" (depth) \ - : "ax"); \ + : "d" (cpu), "c" (depth)); \ } while (0) @@ -62,14 +59,12 @@ cli cmpl $0, %0 jne 0f - movl $0f, %%eax - jmp __lock_kernel -0: - incl %0 + call __lock_kernel +0: incl %0 popfl " : - : "m" (current_set[cpu]->lock_depth), "d" (cpu) - : "ax", "memory"); + : "m" (current->lock_depth), "d" (cpu) + : "memory"); } extern __inline__ void unlock_kernel(void) diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h --- v2.1.36/linux/include/asm-i386/spinlock.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-i386/spinlock.h Thu May 8 13:51:55 1997 @@ -77,13 +77,15 @@ #define spin_lock(lock) \ __asm__ __volatile__( \ - "jmp 2f\n" \ - "1:\t" \ - "testb $1,%0\n\t" \ - "jne 1b\n" \ - "2:\t" \ + "\n1:\t" \ "lock ; btsl $0,%0\n\t" \ - "jc 1b" \ + "jc 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\t" \ + "testb $1,%0\n\t" \ + "jne 2b\n\t" \ + "jmp 1b\n" \ + ".previous" \ :"=m" (__dummy_lock(lock))) #define spin_unlock(lock) \ @@ -91,32 +93,6 @@ "lock ; btrl $0,%0" \ :"=m" (__dummy_lock(lock))) -#undef spin_lock -static inline void spin_lock(spinlock_t * lock) -{ - __label__ l1; - int stuck = 10000000; -l1: - __asm__ __volatile__( - "jmp 2f\n" - "1:\t" - "decl %1\n\t" - "je 3f\n\t" - "testb $1,%0\n\t" - "jne 1b\n" - "2:\t" - "lock ; btsl $0,%0\n\t" - "jc 1b\n" - "3:" - :"=m" (__dummy_lock(lock)), - "=r" (stuck) - :"1" (stuck)); - if (!stuck) { - printk("spinlock stuck at %p (%lx)\n",&&l1,lock->previous); - } else - lock->previous = (unsigned long) &&l1; -} - #define spin_trylock(lock) (!set_bit(0,(lock))) #define spin_lock_irq(lock) \ @@ -158,12 +134,12 @@ asm volatile("\n1:\t" \ "lock ; incl %0\n\t" \ "js 2f\n" \ - ".text 2\n" \ + ".section .text.lock,\"ax\"\n" \ "2:\tlock ; decl %0\n" \ "3:\tcmpl $0,%0\n\t" \ "js 3b\n\t" \ "jmp 1b\n" \ - ".text" \ + ".previous" \ :"=m" (__dummy_lock(&(rw)->lock))) #define read_unlock(rw) \ @@ -173,19 +149,15 @@ #define write_lock(rw) \ asm volatile("\n1:\t" \ "lock ; btsl $31,%0\n\t" \ - "jc 3f\n\t" \ - "testl $0x7fffffff,%0\n\t" \ - "jne 4f\n" \ - "2:\n" \ - ".text 2\n" \ - "3:\ttestl $-1,%0\n\t" \ - "js 3b\n\t" \ - "lock ; btsl $31,%0\n\t" \ - "jc 3b\n" \ - "4:\ttestl $0x7fffffff,%0\n\t" \ + "jc 4f\n" \ + "2:\ttestl $0x7fffffff,%0\n\t" \ + "jne 3f\n" \ + ".section .text.lock,\"ax\"\n" \ + "3:\tlock ; btrl $31,%0\n" \ + "4:\tcmp $0,%0\n\t" \ "jne 4b\n\t" \ - "jmp 2b\n" \ - ".text" \ + "jmp 1b\n" \ + ".previous" \ :"=m" (__dummy_lock(&(rw)->lock))) #define write_unlock(rw) \ diff -u --recursive --new-file v2.1.36/linux/include/asm-i386/system.h linux/include/asm-i386/system.h --- v2.1.36/linux/include/asm-i386/system.h Mon Apr 14 16:28:19 1997 +++ linux/include/asm-i386/system.h Wed Apr 30 15:37:32 1997 @@ -73,7 +73,6 @@ __asm__ __volatile__("fwait"); \ prev->flags&=~PF_USEDFPU; \ } \ - current_set[this_cpu] = next; \ __asm__("ljmp %0\n\t" \ : /* no output */ \ :"m" (*(((char *)&next->tss.tr)-4)), \ @@ -91,8 +90,7 @@ #else #define switch_to(prev,next) do { \ -__asm__("movl %2,"SYMBOL_NAME_STR(current_set)"\n\t" \ - "ljmp %0\n\t" \ +__asm__("ljmp %0\n\t" \ "cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \ "jne 1f\n\t" \ "clts\n" \ diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/dsp56k.h linux/include/asm-m68k/dsp56k.h --- v2.1.36/linux/include/asm-m68k/dsp56k.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/dsp56k.h Sun Apr 27 15:13:50 1997 @@ -33,38 +33,3 @@ #define DSP56K_SET_RX_WSIZE 3 /* Host receive word size (1-4) */ #define DSP56K_HOST_FLAGS 4 /* Host flag registers */ #define DSP56K_HOST_CMD 5 /* Trig Host Command (0-31) */ -/* - * linux/include/asm-m68k/dsp56k.h - defines and declarations for - * DSP56k device driver - * - * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - - -/* Used for uploading DSP binary code */ -struct dsp56k_upload { - int len; - char *bin; -}; - -/* For the DSP host flags */ -struct dsp56k_host_flags { - int dir; /* Bit field. 1 = write output bit, 0 = do nothing. - * 0x0000 means reading only, 0x0011 means - * writing the bits stored in `out' on HF0 and HF1. - * Note that HF2 and HF3 can only be read. - */ - int out; /* Bit field like above. */ - int status; /* Host register's current state is returned */ -}; - -/* ioctl command codes */ -#define DSP56K_UPLOAD 1 /* Upload DSP binary program */ -#define DSP56K_SET_TX_WSIZE 2 /* Host transmit word size (1-4) */ -#define DSP56K_SET_RX_WSIZE 3 /* Host receive word size (1-4) */ -#define DSP56K_HOST_FLAGS 4 /* Host flag registers */ -#define DSP56K_HOST_CMD 5 /* Trig Host Command (0-31) */ diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/fpu.h linux/include/asm-m68k/fpu.h --- v2.1.36/linux/include/asm-m68k/fpu.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/fpu.h Thu May 1 12:05:02 1997 @@ -18,23 +18,3 @@ #endif #endif /* __M68K_FPU_H */ -#ifndef __M68K_FPU_H -#define __M68K_FPU_H - -#include - -/* - * MAX floating point unit state size (FSAVE/FRESTORE) - */ - -#if defined(CONFIG_M68020) || defined(CONFIG_M68030) -#define FPSTATESIZE (216/sizeof(unsigned char)) -#elif defined(CONFIG_M68040) -#define FPSTATESIZE (96/sizeof(unsigned char)) -#elif defined(CONFIG_M68060) -#define FPSTATESIZE (12/sizeof(unsigned char)) -#else -#define FPSTATESIZE error no_cpu_type_configured -#endif - -#endif /* __M68K_FPU_H */ diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/hardirq.h linux/include/asm-m68k/hardirq.h --- v2.1.36/linux/include/asm-m68k/hardirq.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/hardirq.h Thu May 1 12:05:02 1997 @@ -11,16 +11,3 @@ #define hardirq_exit(cpu) (local_irq_count[cpu]--) #endif -#ifndef __M68K_HARDIRQ_H -#define __M68K_HARDIRQ_H - -extern unsigned int local_irq_count[NR_CPUS]; -#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) - -#define hardirq_trylock(cpu) ((cpu)==0) /* always true */ -#define hardirq_endlock(cpu) do { } while (0) - -#define hardirq_enter(cpu) (local_irq_count[cpu]++) -#define hardirq_exit(cpu) (local_irq_count[cpu]--) - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/init.h linux/include/asm-m68k/init.h --- v2.1.36/linux/include/asm-m68k/init.h Wed Apr 16 14:15:00 1997 +++ linux/include/asm-m68k/init.h Thu May 1 12:05:02 1997 @@ -1,14 +1,14 @@ #ifndef _M68K_INIT_H #define _M68K_INIT_H -/* Throwing the initialization code and data out is not supported yet... */ - -#define __init -#define __initdata -#define __initfunc(__arginit) __arginit +#define __init __attribute__ ((__section__ (".text.init"))) +#define __initdata __attribute__ ((__section__ (".data.init"))) +#define __initfunc(__arginit) \ + __arginit __init; \ + __arginit /* For assembly routines */ -#define __INIT -#define __FINIT -#define __INITDATA +#define __INIT .section ".text.init",#alloc,#execinstr +#define __FINIT .previous +#define __INITDATA .section ".data.init",#alloc,#write #endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/namei.h linux/include/asm-m68k/namei.h --- v2.1.36/linux/include/asm-m68k/namei.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/namei.h Sun Apr 27 15:13:50 1997 @@ -19,24 +19,3 @@ do { } while (0) #endif -/* - * linux/include/asm-m68k/namei.h - * - * Included from linux/fs/namei.c - */ - -#ifndef __M68K_NAMEI_H -#define __M68K_NAMEI_H - -/* These dummy routines maybe changed to something useful - * for /usr/gnemul/ emulation stuff. - * Look at asm-sparc/namei.h for details. - */ - -#define translate_namei(pathname, base, follow_links, res_inode) \ - do { } while (0) - -#define translate_open_namei(pathname, flag, mode, res_inode, base) \ - do { } while (0) - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/poll.h linux/include/asm-m68k/poll.h --- v2.1.36/linux/include/asm-m68k/poll.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/poll.h Sun Apr 27 15:13:50 1997 @@ -19,24 +19,3 @@ }; #endif -#ifndef __m68k_POLL_H -#define __m68k_POLL_H - -#define POLLIN 1 -#define POLLPRI 2 -#define POLLOUT 4 -#define POLLERR 8 -#define POLLHUP 16 -#define POLLNVAL 32 -#define POLLRDNORM 64 -#define POLLWRNORM POLLOUT -#define POLLRDBAND 128 -#define POLLWRBAND 256 - -struct pollfd { - int fd; - short events; - short revents; -}; - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h --- v2.1.36/linux/include/asm-m68k/processor.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/processor.h Sun Apr 27 15:08:02 1997 @@ -44,7 +44,7 @@ unsigned char fpstate[FPSTATESIZE]; /* floating point state */ }; -#define INIT_MMAP { &init_mm, 0, 0x40000000, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED), VM_READ | VM_WRITE | VM_EXEC } +#define INIT_MMAP { &init_mm, 0, 0x40000000, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED), VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ sizeof(init_kernel_stack) + (long) init_kernel_stack, 0, \ diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h --- v2.1.36/linux/include/asm-m68k/semaphore.h Wed Apr 23 19:01:27 1997 +++ linux/include/asm-m68k/semaphore.h Thu May 1 12:05:02 1997 @@ -1,6 +1,7 @@ #ifndef _M68K_SEMAPHORE_H #define _M68K_SEMAPHORE_H +#include #include #include #include @@ -38,6 +39,7 @@ static inline int waking_non_zero(struct semaphore *sem) { +#ifndef CONFIG_RMW_INSNS unsigned long flags; int ret = 0; @@ -48,6 +50,21 @@ ret = 1; } restore_flags(flags); +#else + int ret, tmp; + + __asm__ __volatile__ + ("1: movel %2,%0\n" + " jeq 3f\n" + "2: movel %0,%1\n" + " subql #1,%1\n" + " casl %0,%1,%2\n" + " jeq 3f\n" + " tstl %0\n" + " jne 2b\n" + "3:" + : "=d" (ret), "=d" (tmp), "=m" (sem->waking)); +#endif return ret; } diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/sigcontext.h linux/include/asm-m68k/sigcontext.h --- v2.1.36/linux/include/asm-m68k/sigcontext.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-m68k/sigcontext.h Thu May 1 12:05:02 1997 @@ -1,8 +1,6 @@ #ifndef _ASM_M68k_SIGCONTEXT_H #define _ASM_M68k_SIGCONTEXT_H -#include - struct sigcontext { unsigned long sc_mask; /* old sigmask */ unsigned long sc_usp; /* old user stack pointer */ @@ -15,7 +13,7 @@ unsigned short sc_formatvec; unsigned long sc_fpregs[2*3]; /* room for two fp registers */ unsigned long sc_fpcntl[3]; - unsigned char sc_fpstate[FPSTATESIZE]; + unsigned char sc_fpstate[216]; }; #endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/smp_lock.h linux/include/asm-m68k/smp_lock.h --- v2.1.36/linux/include/asm-m68k/smp_lock.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-m68k/smp_lock.h Sun Apr 27 15:13:50 1997 @@ -12,17 +12,3 @@ #define reacquire_kernel_lock(task, cpu, depth) do { } while(0) #endif -#ifndef __M68K_SMPLOCK_H -#define __M68K_SMPLOCK_H - -/* - * We don't do SMP so this is again one of these silly dummy files - * to keep the kernel source looking nice ;-(. - */ - -#define lock_kernel() do { } while(0) -#define unlock_kernel() do { } while(0) -#define release_kernel_lock(task, cpu, depth) ((depth) = 1) -#define reaquire_kernel_lock(task, cpu, depth) do { } while(0) - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/softirq.h linux/include/asm-m68k/softirq.h --- v2.1.36/linux/include/asm-m68k/softirq.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-m68k/softirq.h Sun Apr 27 15:13:50 1997 @@ -60,59 +60,3 @@ #define softirq_endlock() (__m68k_bh_counter = 0) #endif -#ifndef __M68K_SOFTIRQ_H -#define __M68K_SOFTIRQ_H - -/* - * Software interrupts.. no SMP here either. - */ -#define get_active_bhs() (bh_mask & bh_active) -#define clear_active_bhs(x) atomic_clear_mask((x),&bh_active) - -extern inline void init_bh(int nr, void (*routine)(void)) -{ - bh_base[nr] = routine; - bh_mask_count[nr] = 0; - bh_mask |= 1 << nr; -} - -extern inline void mark_bh(int nr) -{ - set_bit(nr, &bh_active); -} - -/* - * These use a mask count to correctly handle - * nested disable/enable calls - */ -extern inline void disable_bh(int nr) -{ - bh_mask &= ~(1 << nr); - bh_mask_count[nr]++; -} - -extern inline void enable_bh(int nr) -{ - if (!--bh_mask_count[nr]) - bh_mask |= 1 << nr; -} - -extern int __m68k_bh_counter; - -extern inline void start_bh_atomic(void) -{ - __m68k_bh_counter++; - barrier(); -} - -extern inline void end_bh_atomic(void) -{ - barrier(); - __m68k_bh_counter--; -} - -/* These are for the irq's testing the lock */ -#define softirq_trylock() (__m68k_bh_counter ? 0 : (__m68k_bh_counter=1)) -#define softirq_endlock() (__m68k_bh_counter = 0) - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-m68k/spinlock.h linux/include/asm-m68k/spinlock.h --- v2.1.36/linux/include/asm-m68k/spinlock.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-m68k/spinlock.h Sun Apr 27 15:13:50 1997 @@ -49,26 +49,3 @@ #define write_unlock_irqrestore(lock, flags) restore_flags(flags) #endif -#ifndef __M68K_SPINLOCK_H -#define __M68K_SPINLOCK_H - -/* - * We don't do SMP on the m68k .... at least not yet. - */ - -typedef struct { } spinlock_t; -#define SPIN_LOCK_UNLOCKED { } - -#define spin_lock_init(lock) do { } while(0) -#define spin_lock(lock) do { } while(0) -#define spin_trylock(lock) do { } while(0) -#define spin_unlock(lock) do { } while(0) -#define spin_lock_irq(lock) cli() -#define spin_unlock_irq(lock) sti() - -#define spin_lock_irqsave(lock, flags) \ - do { save_flags(flags); cli(); } while (0) -#define spin_unlock_irqrestore(lock, flags) \ - restore_flags(flags) - -#endif diff -u --recursive --new-file v2.1.36/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v2.1.36/linux/include/asm-mips/processor.h Mon Apr 14 16:28:19 1997 +++ linux/include/asm-mips/processor.h Sun Apr 27 15:08:02 1997 @@ -139,7 +139,7 @@ #if !defined (__LANGUAGE_ASSEMBLY__) #define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \ - VM_READ | VM_WRITE | VM_EXEC } + VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ /* \ diff -u --recursive --new-file v2.1.36/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h --- v2.1.36/linux/include/asm-mips/unistd.h Fri Apr 4 08:52:25 1997 +++ linux/include/asm-mips/unistd.h Sun Apr 27 15:08:02 1997 @@ -1149,7 +1149,7 @@ /* * Offset of the last Linux flavoured syscall */ -#define __NR_Linux_syscalls 157 +#define __NR_Linux_syscalls 158 #ifndef __LANGUAGE_ASSEMBLY__ diff -u --recursive --new-file v2.1.36/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.1.36/linux/include/asm-ppc/processor.h Sun Jan 26 02:07:47 1997 +++ linux/include/asm-ppc/processor.h Sun Apr 27 15:08:02 1997 @@ -116,7 +116,7 @@ } #define INIT_MMAP { &init_mm, 0, 0x40000000, \ - PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC } + PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h --- v2.1.36/linux/include/asm-sparc/asm_offsets.h Thu Mar 27 14:40:07 1997 +++ linux/include/asm-sparc/asm_offsets.h Thu May 1 12:05:02 1997 @@ -30,123 +30,125 @@ #define ASIZ_task_next_run 0x00000004 #define AOFF_task_prev_run 0x00000050 #define ASIZ_task_prev_run 0x00000004 -#define AOFF_task_saved_kernel_stack 0x00000054 -#define ASIZ_task_saved_kernel_stack 0x00000004 -#define AOFF_task_kernel_stack_page 0x00000058 -#define ASIZ_task_kernel_stack_page 0x00000004 -#define AOFF_task_exit_code 0x0000005c +#define AOFF_task_exit_code 0x00000054 #define ASIZ_task_exit_code 0x00000004 -#define AOFF_task_exit_signal 0x00000060 +#define AOFF_task_exit_signal 0x00000058 #define ASIZ_task_exit_signal 0x00000004 -#define AOFF_task_personality 0x00000064 +#define AOFF_task_personality 0x0000005c #define ASIZ_task_personality 0x00000004 -#define AOFF_task_pid 0x0000006c +#define AOFF_task_pid 0x00000064 #define ASIZ_task_pid 0x00000004 -#define AOFF_task_pgrp 0x00000070 +#define AOFF_task_pgrp 0x00000068 #define ASIZ_task_pgrp 0x00000004 -#define AOFF_task_tty_old_pgrp 0x00000074 +#define AOFF_task_tty_old_pgrp 0x0000006c #define ASIZ_task_tty_old_pgrp 0x00000004 -#define AOFF_task_session 0x00000078 +#define AOFF_task_session 0x00000070 #define ASIZ_task_session 0x00000004 -#define AOFF_task_leader 0x0000007c +#define AOFF_task_leader 0x00000074 #define ASIZ_task_leader 0x00000004 -#define AOFF_task_ngroups 0x00000080 +#define AOFF_task_ngroups 0x00000078 #define ASIZ_task_ngroups 0x00000004 -#define AOFF_task_groups 0x00000084 +#define AOFF_task_groups 0x0000007c #define ASIZ_task_groups 0x00000040 -#define AOFF_task_p_opptr 0x000000c4 +#define AOFF_task_p_opptr 0x000000bc #define ASIZ_task_p_opptr 0x00000004 -#define AOFF_task_p_pptr 0x000000c8 +#define AOFF_task_p_pptr 0x000000c0 #define ASIZ_task_p_pptr 0x00000004 -#define AOFF_task_p_cptr 0x000000cc +#define AOFF_task_p_cptr 0x000000c4 #define ASIZ_task_p_cptr 0x00000004 -#define AOFF_task_p_ysptr 0x000000d0 +#define AOFF_task_p_ysptr 0x000000c8 #define ASIZ_task_p_ysptr 0x00000004 -#define AOFF_task_p_osptr 0x000000d4 +#define AOFF_task_p_osptr 0x000000cc #define ASIZ_task_p_osptr 0x00000004 -#define AOFF_task_wait_chldexit 0x000000d8 +#define AOFF_task_pidhash_next 0x000000d0 +#define ASIZ_task_pidhash_next 0x00000004 +#define AOFF_task_pidhash_pprev 0x000000d4 +#define ASIZ_task_pidhash_pprev 0x00000004 +#define AOFF_task_tarray_ptr 0x000000d8 +#define ASIZ_task_tarray_ptr 0x00000004 +#define AOFF_task_wait_chldexit 0x000000dc #define ASIZ_task_wait_chldexit 0x00000004 -#define AOFF_task_uid 0x000000dc +#define AOFF_task_uid 0x000000e0 #define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x000000de +#define AOFF_task_euid 0x000000e2 #define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x000000e0 +#define AOFF_task_suid 0x000000e4 #define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x000000e2 +#define AOFF_task_fsuid 0x000000e6 #define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000000e4 +#define AOFF_task_gid 0x000000e8 #define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000000e6 +#define AOFF_task_egid 0x000000ea #define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000000e8 +#define AOFF_task_sgid 0x000000ec #define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000000ea +#define AOFF_task_fsgid 0x000000ee #define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000000ec +#define AOFF_task_timeout 0x000000f0 #define ASIZ_task_timeout 0x00000004 -#define AOFF_task_policy 0x000000f0 +#define AOFF_task_policy 0x000000f4 #define ASIZ_task_policy 0x00000004 -#define AOFF_task_rt_priority 0x000000f4 +#define AOFF_task_rt_priority 0x000000f8 #define ASIZ_task_rt_priority 0x00000004 -#define AOFF_task_it_real_value 0x000000f8 +#define AOFF_task_it_real_value 0x000000fc #define ASIZ_task_it_real_value 0x00000004 -#define AOFF_task_it_prof_value 0x000000fc +#define AOFF_task_it_prof_value 0x00000100 #define ASIZ_task_it_prof_value 0x00000004 -#define AOFF_task_it_virt_value 0x00000100 +#define AOFF_task_it_virt_value 0x00000104 #define ASIZ_task_it_virt_value 0x00000004 -#define AOFF_task_it_real_incr 0x00000104 +#define AOFF_task_it_real_incr 0x00000108 #define ASIZ_task_it_real_incr 0x00000004 -#define AOFF_task_it_prof_incr 0x00000108 +#define AOFF_task_it_prof_incr 0x0000010c #define ASIZ_task_it_prof_incr 0x00000004 -#define AOFF_task_it_virt_incr 0x0000010c +#define AOFF_task_it_virt_incr 0x00000110 #define ASIZ_task_it_virt_incr 0x00000004 -#define AOFF_task_real_timer 0x00000110 +#define AOFF_task_real_timer 0x00000114 #define ASIZ_task_real_timer 0x00000014 -#define AOFF_task_utime 0x00000124 +#define AOFF_task_utime 0x00000128 #define ASIZ_task_utime 0x00000004 -#define AOFF_task_stime 0x00000128 +#define AOFF_task_stime 0x0000012c #define ASIZ_task_stime 0x00000004 -#define AOFF_task_cutime 0x0000012c +#define AOFF_task_cutime 0x00000130 #define ASIZ_task_cutime 0x00000004 -#define AOFF_task_cstime 0x00000130 +#define AOFF_task_cstime 0x00000134 #define ASIZ_task_cstime 0x00000004 -#define AOFF_task_start_time 0x00000134 +#define AOFF_task_start_time 0x00000138 #define ASIZ_task_start_time 0x00000004 -#define AOFF_task_min_flt 0x00000138 +#define AOFF_task_min_flt 0x0000013c #define ASIZ_task_min_flt 0x00000004 -#define AOFF_task_maj_flt 0x0000013c +#define AOFF_task_maj_flt 0x00000140 #define ASIZ_task_maj_flt 0x00000004 -#define AOFF_task_nswap 0x00000140 +#define AOFF_task_nswap 0x00000144 #define ASIZ_task_nswap 0x00000004 -#define AOFF_task_cmin_flt 0x00000144 +#define AOFF_task_cmin_flt 0x00000148 #define ASIZ_task_cmin_flt 0x00000004 -#define AOFF_task_cmaj_flt 0x00000148 +#define AOFF_task_cmaj_flt 0x0000014c #define ASIZ_task_cmaj_flt 0x00000004 -#define AOFF_task_cnswap 0x0000014c +#define AOFF_task_cnswap 0x00000150 #define ASIZ_task_cnswap 0x00000004 -#define AOFF_task_swap_address 0x00000154 +#define AOFF_task_swap_address 0x00000158 #define ASIZ_task_swap_address 0x00000004 -#define AOFF_task_old_maj_flt 0x00000158 +#define AOFF_task_old_maj_flt 0x0000015c #define ASIZ_task_old_maj_flt 0x00000004 -#define AOFF_task_dec_flt 0x0000015c +#define AOFF_task_dec_flt 0x00000160 #define ASIZ_task_dec_flt 0x00000004 -#define AOFF_task_swap_cnt 0x00000160 +#define AOFF_task_swap_cnt 0x00000164 #define ASIZ_task_swap_cnt 0x00000004 -#define AOFF_task_rlim 0x00000164 +#define AOFF_task_rlim 0x00000168 #define ASIZ_task_rlim 0x00000050 -#define AOFF_task_used_math 0x000001b4 +#define AOFF_task_used_math 0x000001b8 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x000001b6 +#define AOFF_task_comm 0x000001ba #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x000001c8 +#define AOFF_task_link_count 0x000001cc #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x000001cc +#define AOFF_task_tty 0x000001d0 #define ASIZ_task_tty 0x00000004 -#define AOFF_task_semundo 0x000001d0 +#define AOFF_task_semundo 0x000001d4 #define ASIZ_task_semundo 0x00000004 -#define AOFF_task_semsleeping 0x000001d4 +#define AOFF_task_semsleeping 0x000001d8 #define ASIZ_task_semsleeping 0x00000004 -#define AOFF_task_ldt 0x000001d8 +#define AOFF_task_ldt 0x000001dc #define ASIZ_task_ldt 0x00000004 #define AOFF_task_tss 0x000001e0 #define ASIZ_task_tss 0x00000390 @@ -158,56 +160,60 @@ #define ASIZ_task_mm 0x00000004 #define AOFF_task_sig 0x0000057c #define ASIZ_task_sig 0x00000004 -#define AOFF_task_processor 0x00000580 +#define AOFF_task_has_cpu 0x00000580 +#define ASIZ_task_has_cpu 0x00000004 +#define AOFF_task_processor 0x00000584 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x00000584 +#define AOFF_task_last_processor 0x00000588 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x00000588 +#define AOFF_task_lock_depth 0x0000058c #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_mm_count 0x00000000 -#define ASIZ_mm_count 0x00000004 -#define AOFF_mm_pgd 0x00000004 +#define AOFF_task_sigmask_lock 0x00000590 +#define ASIZ_task_sigmask_lock 0x00000000 +#define AOFF_mm_mmap 0x00000000 +#define ASIZ_mm_mmap 0x00000004 +#define AOFF_mm_mmap_cache 0x00000004 +#define ASIZ_mm_mmap_cache 0x00000004 +#define AOFF_mm_pgd 0x00000008 #define ASIZ_mm_pgd 0x00000004 -#define AOFF_mm_context 0x00000008 +#define AOFF_mm_count 0x0000000c +#define ASIZ_mm_count 0x00000004 +#define AOFF_mm_mmap_sem 0x00000010 +#define ASIZ_mm_mmap_sem 0x0000000c +#define AOFF_mm_context 0x0000001c #define ASIZ_mm_context 0x00000004 -#define AOFF_mm_start_code 0x0000000c +#define AOFF_mm_start_code 0x00000020 #define ASIZ_mm_start_code 0x00000004 -#define AOFF_mm_end_code 0x00000010 +#define AOFF_mm_end_code 0x00000024 #define ASIZ_mm_end_code 0x00000004 -#define AOFF_mm_start_data 0x00000014 +#define AOFF_mm_start_data 0x00000028 #define ASIZ_mm_start_data 0x00000004 -#define AOFF_mm_end_data 0x00000018 +#define AOFF_mm_end_data 0x0000002c #define ASIZ_mm_end_data 0x00000004 -#define AOFF_mm_start_brk 0x0000001c +#define AOFF_mm_start_brk 0x00000030 #define ASIZ_mm_start_brk 0x00000004 -#define AOFF_mm_brk 0x00000020 +#define AOFF_mm_brk 0x00000034 #define ASIZ_mm_brk 0x00000004 -#define AOFF_mm_start_stack 0x00000024 +#define AOFF_mm_start_stack 0x00000038 #define ASIZ_mm_start_stack 0x00000004 -#define AOFF_mm_start_mmap 0x00000028 +#define AOFF_mm_start_mmap 0x0000003c #define ASIZ_mm_start_mmap 0x00000004 -#define AOFF_mm_arg_start 0x0000002c +#define AOFF_mm_arg_start 0x00000040 #define ASIZ_mm_arg_start 0x00000004 -#define AOFF_mm_arg_end 0x00000030 +#define AOFF_mm_arg_end 0x00000044 #define ASIZ_mm_arg_end 0x00000004 -#define AOFF_mm_env_start 0x00000034 +#define AOFF_mm_env_start 0x00000048 #define ASIZ_mm_env_start 0x00000004 -#define AOFF_mm_env_end 0x00000038 +#define AOFF_mm_env_end 0x0000004c #define ASIZ_mm_env_end 0x00000004 -#define AOFF_mm_rss 0x0000003c +#define AOFF_mm_rss 0x00000050 #define ASIZ_mm_rss 0x00000004 -#define AOFF_mm_total_vm 0x00000040 +#define AOFF_mm_total_vm 0x00000054 #define ASIZ_mm_total_vm 0x00000004 -#define AOFF_mm_locked_vm 0x00000044 +#define AOFF_mm_locked_vm 0x00000058 #define ASIZ_mm_locked_vm 0x00000004 -#define AOFF_mm_def_flags 0x00000048 +#define AOFF_mm_def_flags 0x0000005c #define ASIZ_mm_def_flags 0x00000004 -#define AOFF_mm_mmap 0x0000004c -#define ASIZ_mm_mmap 0x00000004 -#define AOFF_mm_mmap_avl 0x00000050 -#define ASIZ_mm_mmap_avl 0x00000004 -#define AOFF_mm_mmap_sem 0x00000054 -#define ASIZ_mm_mmap_sem 0x0000000c #define AOFF_thread_uwinmask 0x00000000 #define ASIZ_thread_uwinmask 0x00000004 #define AOFF_thread_kregs 0x00000004 diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/asmmacro.h linux/include/asm-sparc/asmmacro.h --- v2.1.36/linux/include/asm-sparc/asmmacro.h Sun Jan 26 02:07:47 1997 +++ linux/include/asm-sparc/asmmacro.h Thu May 1 12:05:02 1997 @@ -6,22 +6,22 @@ #ifndef _SPARC_ASMMACRO_H #define _SPARC_ASMMACRO_H -/* #define SMP_DEBUG */ - #define GET_PROCESSOR_ID(reg) \ rd %tbr, %reg; \ srl %reg, 12, %reg; \ and %reg, 3, %reg; #define GET_PROCESSOR_MID(reg, tmp) \ - GET_PROCESSOR_ID(reg) \ - set C_LABEL(mid_xlate), %tmp; \ + rd %tbr, %reg; \ + sethi C_LABEL(mid_xlate), %tmp; \ + srl %reg, 12, %reg; \ + or %tmp, %lo(C_LABEL(mid_xlate)), %tmp; \ + and %reg, 3, %reg; \ ldub [%tmp + %reg], %reg; #define GET_PROCESSOR_OFFSET(reg) \ - rd %tbr, %reg; \ - srl %reg, 10, %reg; \ - and %reg, 0xc, %reg; + GET_PROCESSOR_ID(reg) \ + sll %reg, 2, %reg; #define PROCESSOR_OFFSET_TO_ID(reg) \ srl %reg, 2, %reg; diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/auxio.h linux/include/asm-sparc/auxio.h --- v2.1.36/linux/include/asm-sparc/auxio.h Mon Mar 17 14:54:31 1997 +++ linux/include/asm-sparc/auxio.h Thu May 1 12:05:02 1997 @@ -1,4 +1,4 @@ -/* $Id: auxio.h,v 1.16 1997/01/31 23:26:05 tdyas Exp $ +/* $Id: auxio.h,v 1.17 1997/05/01 01:42:02 davem Exp $ * auxio.h: Definitions and code for the Auxiliary I/O register. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -43,30 +43,27 @@ #define FLPY_TCNTOFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT)) #ifndef __ASSEMBLY__ -extern __inline__ void set_auxio(unsigned char bits_on, unsigned char bits_off) -{ - unsigned char regval; - unsigned long flags; - - save_flags(flags); cli(); - - switch(sparc_cpu_model) { - case sun4c: - regval = *AUXREG; - *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; - break; - case sun4m: - if(!AUXREG) - break; /* VME chassic sun4m, no auxio. */ - regval = *AUXREG; - *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; - break; - default: - panic("Can't set AUXIO register on this machine."); - }; - - restore_flags(flags); -} +#define set_auxio(bits_on, bits_off) \ +do { \ + unsigned char regval; \ + unsigned long flags; \ + save_flags(flags); cli(); \ + switch(sparc_cpu_model) { \ + case sun4c: \ + regval = *AUXREG; \ + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; \ + break; \ + case sun4m: \ + if(!AUXREG) \ + break; /* VME chassic sun4m, no auxio. */ \ + regval = *AUXREG; \ + *AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; \ + break; \ + default: \ + panic("Can't set AUXIO register on this machine."); \ + }; \ + restore_flags(flags); \ +} while(0) #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h --- v2.1.36/linux/include/asm-sparc/linux_logo.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/linux_logo.h Sun Apr 27 15:13:50 1997 @@ -1043,1048 +1043,3 @@ "'!!!!!!!W..e$$!!!!!!` %s\n" " \"~^^~ ^~~^\n" "\n"; -/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $ - * include/asm-sparc/linux_logo.h: This is a linux logo - * to be displayed on boot. - * - * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) - * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * You can put anything here, but: - * LINUX_LOGO_COLORS has to be less than 224 - * image size has to be 80x80 - * values have to start from 0x20 - * (i.e. RGB(linux_logo_red[0], - * linux_logo_green[0], - * linux_logo_blue[0]) is color 0x20) - * BW image has to be 80x80 as well, with MS bit - * on the left - * Serial_console ascii image can be any size, - * but should contain %s to display the version - */ - -#include -#include - -#define linux_logo_banner "Linux/SPARC version " UTS_RELEASE - -#define LINUX_LOGO_COLORS 221 - -unsigned char linux_logo_red[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5, - 0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5, - 0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03, - 0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6, - 0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2, - 0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A, - 0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4, - 0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2, - 0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC, - 0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC, - 0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7, - 0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3, - 0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4, - 0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4, - 0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87, - 0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E, - 0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_green[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3, - 0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3, - 0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9, - 0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02, - 0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD, - 0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6, - 0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C, - 0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4, - 0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E, - 0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC, - 0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5, - 0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96, - 0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80, - 0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F, - 0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C, - 0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54, - 0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E, - 0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo_blue[] __initdata = { - 0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE, - 0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5, - 0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84, - 0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6, - 0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD, - 0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87, - 0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99, - 0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D, - 0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7, - 0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77, - 0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59, - 0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E, - 0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14, - 0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D, - 0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14, - 0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08, - 0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E, - 0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E, - 0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20, - 0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06, - 0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17, - 0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78, - 0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62, - 0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46, - 0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14, - 0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A, - 0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09, - 0x1D, 0x14, 0x06, 0x02, 0x00 -}; - -unsigned char linux_logo[] __initdata = { - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61, - 0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E, - 0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58, - 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57, - 0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C, - 0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A, - 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52, - 0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53, - 0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, - 0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49, - 0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B, - 0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, - 0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB, - 0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C, - 0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49, - 0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5, - 0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58, - 0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48, - 0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51, - 0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54, - 0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5, - 0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61, - 0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C, - 0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B, - 0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53, - 0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC, - 0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59, - 0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48, - 0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51, - 0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61, - 0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63, - 0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48, - 0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51, - 0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52, - 0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB, - 0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B, - 0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53, - 0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53, - 0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC, - 0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F, - 0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61, - 0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57, - 0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D, - 0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57, - 0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC, - 0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC, - 0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48, - 0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52, - 0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61, - 0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A, - 0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, - 0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B, - 0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC, - 0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC, - 0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49, - 0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F, - 0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB, - 0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47, - 0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54, - 0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D, - 0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC, - 0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC, - 0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45, - 0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44, - 0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64, - 0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48, - 0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D, - 0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC, - 0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA, - 0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55, - 0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45, - 0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D, - 0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B, - 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57, - 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54, - 0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A, - 0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC, - 0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8, - 0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD, - 0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F, - 0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A, - 0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56, - 0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, - 0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54, - 0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC, - 0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB, - 0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34, - 0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F, - 0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E, - 0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60, - 0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51, - 0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57, - 0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51, - 0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC, - 0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE, - 0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30, - 0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41, - 0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65, - 0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C, - 0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, - 0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A, - 0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC, - 0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C, - 0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1, - 0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32, - 0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30, - 0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41, - 0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC, - 0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A, - 0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, - 0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E, - 0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC, - 0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88, - 0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB, - 0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33, - 0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31, - 0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E, - 0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63, - 0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49, - 0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, - 0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55, - 0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC, - 0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C, - 0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8, - 0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F, - 0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F, - 0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48, - 0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A, - 0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A, - 0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57, - 0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53, - 0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC, - 0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88, - 0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4, - 0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, - 0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E, - 0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47, - 0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D, - 0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58, - 0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55, - 0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC, - 0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E, - 0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9, - 0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73, - 0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70, - 0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF, - 0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E, - 0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57, - 0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58, - 0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C, - 0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC, - 0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C, - 0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC, - 0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78, - 0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73, - 0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1, - 0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C, - 0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D, - 0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58, - 0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E, - 0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC, - 0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8, - 0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42, - 0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73, - 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73, - 0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2, - 0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41, - 0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62, - 0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B, - 0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60, - 0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC, - 0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7, - 0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41, - 0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73, - 0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74, - 0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB, - 0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41, - 0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64, - 0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E, - 0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C, - 0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB, - 0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE, - 0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20, - 0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75, - 0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76, - 0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D, - 0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C, - 0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64, - 0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, - 0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58, - 0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC, - 0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81, - 0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23, - 0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76, - 0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76, - 0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48, - 0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40, - 0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61, - 0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C, - 0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52, - 0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB, - 0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E, - 0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22, - 0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8, - 0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, - 0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C, - 0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57, - 0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D, - 0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A, - 0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65, - 0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC, - 0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40, - 0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47, - 0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF, - 0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A, - 0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57, - 0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5, - 0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C, - 0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26, - 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6, - 0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52, - 0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9, - 0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42, - 0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51, - 0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6, - 0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7, - 0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93, - 0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D, - 0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF, - 0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40, - 0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52, - 0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1, - 0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21, - 0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8, - 0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93, - 0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40, - 0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0, - 0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F, - 0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59, - 0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E, - 0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23, - 0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7, - 0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93, - 0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F, - 0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC, - 0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47, - 0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54, - 0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D, - 0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24, - 0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24, - 0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A, - 0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5, - 0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93, - 0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60, - 0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC, - 0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47, - 0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B, - 0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D, - 0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28, - 0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D, - 0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD, - 0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93, - 0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7, - 0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44, - 0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45, - 0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B, - 0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20, - 0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6, - 0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90, - 0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0, - 0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44, - 0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45, - 0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51, - 0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF, - 0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7, - 0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5, - 0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2, - 0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58, - 0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C, - 0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55, - 0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1, - 0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB, - 0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, - 0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3, - 0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58, - 0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58, - 0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C, - 0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC, - 0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7, - 0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, - 0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0, - 0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58, - 0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60, - 0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60, - 0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB, - 0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7, - 0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7, - 0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE, - 0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B, - 0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61, - 0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64, - 0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC, - 0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8, - 0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5, - 0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C, - 0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E, - 0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62, - 0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC, - 0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB, - 0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7, - 0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5, - 0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57, - 0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47, - 0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60, - 0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0, - 0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0, - 0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8, - 0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6, - 0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57, - 0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B, - 0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C, - 0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3, - 0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB, - 0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8, - 0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7, - 0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57, - 0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C, - 0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58, - 0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1, - 0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC, - 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED, - 0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, - 0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58, - 0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60, - 0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56, - 0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0, - 0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC, - 0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6, - 0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, - 0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B, - 0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C, - 0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59, - 0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0, - 0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC, - 0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6, - 0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6, - 0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B, - 0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56, - 0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60, - 0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF, - 0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9, - 0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9, - 0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, - 0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52, - 0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B, - 0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD, - 0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE, - 0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65, - 0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6, - 0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D, - 0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58, - 0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F, - 0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4, - 0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE, - 0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0, - 0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D, - 0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57, - 0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40, - 0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9, - 0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE, - 0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC, - 0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9, - 0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38, - 0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52, - 0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40, - 0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF, - 0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99, - 0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, - 0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6, - 0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, - 0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B, - 0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43, - 0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC, - 0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0, - 0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C, - 0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23, - 0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, - 0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49, - 0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A, - 0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC, - 0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2, - 0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94, - 0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA, - 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7, - 0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E, - 0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D, - 0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC, - 0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4, - 0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B, - 0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7, - 0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E, - 0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0, - 0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA, - 0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9, - 0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89, - 0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA, - 0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2, - 0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E, - 0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA, - 0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA, - 0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6, - 0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97, - 0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D, - 0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22, - 0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9, - 0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D, - 0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45, - 0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB, - 0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6, - 0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99, - 0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A, - 0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC, - 0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23, - 0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4, - 0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C, - 0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47, - 0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD, - 0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4, - 0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A, - 0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98, - 0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC, - 0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23, - 0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4, - 0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89, - 0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B, - 0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD, - 0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0, - 0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0, - 0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A, - 0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC, - 0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2, - 0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A, - 0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49, - 0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC, - 0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63, - 0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B, - 0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84, - 0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC, - 0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23, - 0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99, - 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B, - 0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51, - 0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC, - 0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A, - 0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95, - 0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E, - 0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA, - 0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22, - 0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99, - 0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94, - 0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B, - 0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA, - 0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D, - 0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C, - 0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A, - 0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB, - 0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23, - 0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99, - 0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E, - 0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87, - 0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3, - 0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48, - 0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94, - 0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95, - 0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6, - 0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40, - 0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99, - 0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95, - 0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98, - 0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC, - 0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45, - 0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89, - 0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C, - 0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4, - 0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23, - 0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99, - 0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87, - 0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC, - 0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58, - 0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40, - 0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94, - 0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B, - 0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6, - 0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20, - 0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C, - 0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94, - 0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE, - 0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C, - 0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41, - 0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98, - 0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C, - 0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6, - 0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B, - 0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B, - 0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0, - 0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62, - 0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44, - 0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6, - 0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89, - 0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8, - 0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99, - 0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98, - 0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1, - 0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB, - 0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49, - 0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA, - 0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2, - 0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA, - 0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2, - 0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0, - 0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF, - 0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD, - 0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52, - 0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA, - 0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA, - 0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1, - 0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, - 0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8, - 0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0, - 0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9, - 0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD, - 0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53, - 0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56, - 0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0, - 0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9, - 0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0, - 0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3, - 0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF, - 0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2, - 0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3, - 0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE, - 0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56, - 0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57, - 0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC, - 0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA, - 0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4, - 0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3, - 0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1, - 0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6, - 0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE, - 0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD, - 0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58, - 0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D, - 0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47, - 0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6, - 0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4, - 0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5, - 0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9, - 0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC, - 0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3, - 0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64, - 0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C, - 0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A, - 0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A, - 0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0, - 0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE, - 0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6, - 0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6, - 0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE, - 0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5, - 0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E, - 0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D, - 0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E, - 0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E, - 0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8, - 0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5, - 0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1, - 0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60, - 0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9, - 0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5, - 0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47, - 0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E, - 0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45, - 0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51, - 0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB, - 0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0, - 0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D, - 0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0, - 0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5, - 0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2, - 0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D, - 0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60, - 0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45, - 0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63, - 0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7, - 0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3, - 0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E, - 0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2, - 0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0, - 0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC, - 0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C, - 0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61, - 0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45, - 0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2, - 0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3, - 0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2, - 0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47, - 0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2, - 0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E, - 0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3, - 0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63, - 0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62, - 0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49, - 0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3, - 0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF, - 0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2, - 0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58, - 0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE, - 0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B, - 0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4, - 0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE, - 0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62, - 0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A, - 0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5, - 0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE, - 0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3, - 0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53, - 0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3, - 0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48, - 0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3, - 0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF, - 0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57, -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29, - 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19, - 0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E, - 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06, - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23, - 0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - -/* Painted by Johnny Stenback */ - -unsigned char *linux_serial_image __initdata = "\n" -" .u$e.\n" -" .$$$$$:S\n" -" $\"*$/\"*$$\n" -" $.`$ . ^F\n" -" 4k+#+T.$F\n" -" 4P+++\"$\"$\n" -" :R\"+ t$$B\n" -" ___# $$$\n" -" | | R$$k\n" -" dd. | Linux $!$\n" -" ddd | Sparc $9$F\n" -" '!!!!!$ !!#!`\n" -" !!!!!* .!!!!!`\n" -"'!!!!!!!W..e$$!!!!!!` %s\n" -" \"~^^~ ^~~^\n" -"\n"; diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h --- v2.1.36/linux/include/asm-sparc/processor.h Mon Mar 17 14:54:31 1997 +++ linux/include/asm-sparc/processor.h Thu May 1 12:05:02 1997 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.57 1997/03/04 16:27:22 jj Exp $ +/* $Id: processor.h,v 1.59 1997/05/01 01:42:03 davem Exp $ * include/asm-sparc/processor.h * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) @@ -83,7 +83,7 @@ #define SPARC_FLAG_UNALIGNED 0x2 /* is allowed to do unaligned accesses */ #define INIT_MMAP { &init_mm, (0), (0), \ - __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC } + __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ /* uwinmask, kregs, sig_address, sig_desc, ksp, kpc, kpsr, kwim */ \ @@ -144,11 +144,14 @@ #define release_thread(tsk) do { } while(0) #ifdef __KERNEL__ + /* Allocation and freeing of basic task resources. */ -extern unsigned long (*alloc_kernel_stack)(struct task_struct *tsk); -extern void (*free_kernel_stack)(unsigned long stack); extern struct task_struct *(*alloc_task_struct)(void); extern void (*free_task_struct)(struct task_struct *tsk); + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) + #endif #endif /* __ASM_SPARC_PROCESSOR_H */ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/semaphore.h linux/include/asm-sparc/semaphore.h --- v2.1.36/linux/include/asm-sparc/semaphore.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/semaphore.h Thu May 1 12:05:02 1997 @@ -28,20 +28,18 @@ * XXX spinlock can allow this to be done without grabbing the IRQ * XXX global lock. */ -static inline int waking_non_zero(struct semaphore *sem) -{ - unsigned long flags; - int ret = 0; - - save_flags(flags); - cli(); - if (atomic_read(&sem->waking) > 0) { - atomic_dec(&sem->waking); - ret = 1; - } - restore_flags(flags); - return ret; -} +#define waking_non_zero(sem) \ +({ unsigned long flags; \ + int ret = 0; \ + save_flags(flags); \ + cli(); \ + if (atomic_read(&sem->waking) > 0) { \ + atomic_dec(&sem->waking); \ + ret = 1; \ + } \ + restore_flags(flags); \ + ret; \ +}) /* This isn't quite as clever as the x86 side, I'll be fixing this * soon enough. diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h --- v2.1.36/linux/include/asm-sparc/smp.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/smp.h Thu May 1 12:05:02 1997 @@ -85,7 +85,7 @@ extern __volatile__ int cpu_logical_map[NR_CPUS]; extern unsigned long smp_proc_in_lock[NR_CPUS]; -extern __inline__ int smp_processor_id(void) +extern __inline__ int hard_smp_processor_id(void) { int cpuid; @@ -95,6 +95,8 @@ "=&r" (cpuid)); return cpuid; } + +#define smp_processor_id() hard_smp_processor_id() #endif /* !(__ASSEMBLY__) */ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h --- v2.1.36/linux/include/asm-sparc/spinlock.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/spinlock.h Thu May 1 12:05:02 1997 @@ -151,7 +151,7 @@ "b,a 1b\n\t" \ ".previous\n" \ : "=r" (flags) \ - : "i" (PSR_PIL), "r" (lock) \ + : "i" (PSR_PIL), "r" (lp) \ : "g2", "memory", "cc"); \ } while(0) @@ -198,7 +198,7 @@ * * Unfortunately this scheme limits us to ~65,000 cpus. */ -extern __inline__ void read_lock(rwlock_t *rw) +extern __inline__ void _read_lock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); lp = rw; @@ -211,7 +211,14 @@ : "g2", "g4", "g7", "memory", "cc"); } -extern __inline__ void read_unlock(rwlock_t *rw) +#define read_lock(lock) \ +do { unsigned long flags; \ + __save_and_cli(flags); \ + _read_lock(lock); \ + __restore_flags(flags); \ +} while(0) + +extern __inline__ void _read_unlock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); lp = rw; @@ -224,6 +231,13 @@ : "g2", "g4", "g7", "memory", "cc"); } +#define read_unlock(lock) \ +do { unsigned long flags; \ + __save_and_cli(flags); \ + _read_unlock(lock); \ + __restore_flags(flags); \ +} while(0) + extern __inline__ void write_lock(rwlock_t *rw) { register rwlock_t *lp asm("g1"); @@ -238,15 +252,15 @@ } #define write_unlock(rw) do { (rw)->lock = 0; } while(0) -#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0) -#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0) +#define read_lock_irq(lock) do { __cli(); _read_lock(lock); } while (0) +#define read_unlock_irq(lock) do { _read_unlock(lock); __sti(); } while (0) #define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0) #define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0) #define read_lock_irqsave(lock, flags) \ - do { __save_and_cli(flags); read_lock(lock); } while (0) + do { __save_and_cli(flags); _read_lock(lock); } while (0) #define read_unlock_irqrestore(lock, flags) \ - do { read_unlock(lock); __restore_flags(flags); } while (0) + do { _read_unlock(lock); __restore_flags(flags); } while (0) #define write_lock_irqsave(lock, flags) \ do { __save_and_cli(flags); write_lock(lock); } while (0) #define write_unlock_irqrestore(lock, flags) \ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h --- v2.1.36/linux/include/asm-sparc/system.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc/system.h Thu May 1 12:05:02 1997 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.58 1997/04/18 05:44:54 davem Exp $ */ +/* $Id: system.h,v 1.60 1997/05/01 02:26:56 davem Exp $ */ #ifndef __SPARC_SYSTEM_H #define __SPARC_SYSTEM_H @@ -108,7 +108,7 @@ "nop\n\t" \ "nop\n\t" \ "jmpl %%o7 + 0x8, %%g0\n\t" \ - " nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next), \ + " nop\n\t" : : "r" (&(current_set[hard_smp_processor_id()])), "r" (next), \ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \ "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \ "r" (task_pc) \ @@ -233,12 +233,8 @@ extern unsigned char global_irq_holder; #define save_flags(x) \ -do { int cpuid; \ - __asm__ __volatile__("rd %%tbr, %0; srl %0, 12, %0; and %0, 3, %0" \ - : "=r" (cpuid)); \ - ((x) = ((global_irq_holder == (unsigned char) cpuid) ? 1 : \ - ((getipl() & PSR_PIL) ? 2 : 0))); \ -} while(0) +do { ((x) = ((global_irq_holder == (unsigned char) smp_processor_id()) ? 1 : \ + ((getipl() & PSR_PIL) ? 2 : 0))); } while(0) #define restore_flags(flags) \ do { register unsigned long bits asm("g7"); \ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/termbits.h linux/include/asm-sparc/termbits.h --- v2.1.36/linux/include/asm-sparc/termbits.h Mon Apr 14 16:28:21 1997 +++ linux/include/asm-sparc/termbits.h Sun Apr 27 15:08:02 1997 @@ -146,7 +146,13 @@ #define HUPCL 0x00000400 #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 -#define B76800 0x00001001 +/* We'll never see these speeds with the Zilogs, but for completeness... */ +#define B57600 0x00001001 +#define B115200 0x00001002 +#define B230400 0x00001003 +#define B460800 0x00001004 +/* This is what we can do with the Zilogs. */ +#define B76800 0x00001005 #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc/winmacro.h linux/include/asm-sparc/winmacro.h --- v2.1.36/linux/include/asm-sparc/winmacro.h Mon Mar 17 14:54:33 1997 +++ linux/include/asm-sparc/winmacro.h Thu May 1 12:05:02 1997 @@ -1,4 +1,4 @@ -/* $Id: winmacro.h,v 1.18 1997/03/04 16:27:27 jj Exp $ +/* $Id: winmacro.h,v 1.19 1997/05/01 01:42:05 davem Exp $ * winmacro.h: Window loading-unloading macros. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -114,12 +114,11 @@ #ifdef __SMP__ #define LOAD_CURRENT(dest_reg, idreg) \ rd %tbr, %idreg; \ - srl %idreg, 10, %idreg; \ - and %idreg, 0xc, %idreg; \ sethi %hi(C_LABEL(current_set)), %dest_reg; \ + srl %idreg, 10, %idreg; \ or %dest_reg, %lo(C_LABEL(current_set)), %dest_reg; \ - add %dest_reg, %idreg, %idreg; \ - ld [%idreg], %dest_reg; + and %idreg, 0xc, %idreg; \ + ld [%idreg + %dest_reg], %dest_reg; #else #define LOAD_CURRENT(dest_reg, idreg) \ sethi %hi(C_LABEL(current_set)), %idreg; \ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h --- v2.1.36/linux/include/asm-sparc64/asm_offsets.h Mon Apr 14 16:28:21 1997 +++ linux/include/asm-sparc64/asm_offsets.h Thu May 1 12:05:02 1997 @@ -64,150 +64,158 @@ #define ASIZ_task_p_ysptr 0x00000008 #define AOFF_task_p_osptr 0x00000188 #define ASIZ_task_p_osptr 0x00000008 -#define AOFF_task_wait_chldexit 0x00000190 +#define AOFF_task_pidhash_next 0x00000190 +#define ASIZ_task_pidhash_next 0x00000008 +#define AOFF_task_pidhash_pprev 0x00000198 +#define ASIZ_task_pidhash_pprev 0x00000008 +#define AOFF_task_tarray_ptr 0x000001a0 +#define ASIZ_task_tarray_ptr 0x00000008 +#define AOFF_task_wait_chldexit 0x000001a8 #define ASIZ_task_wait_chldexit 0x00000008 -#define AOFF_task_uid 0x00000198 +#define AOFF_task_uid 0x000001b0 #define ASIZ_task_uid 0x00000002 -#define AOFF_task_euid 0x0000019a +#define AOFF_task_euid 0x000001b2 #define ASIZ_task_euid 0x00000002 -#define AOFF_task_suid 0x0000019c +#define AOFF_task_suid 0x000001b4 #define ASIZ_task_suid 0x00000002 -#define AOFF_task_fsuid 0x0000019e +#define AOFF_task_fsuid 0x000001b6 #define ASIZ_task_fsuid 0x00000002 -#define AOFF_task_gid 0x000001a0 +#define AOFF_task_gid 0x000001b8 #define ASIZ_task_gid 0x00000002 -#define AOFF_task_egid 0x000001a2 +#define AOFF_task_egid 0x000001ba #define ASIZ_task_egid 0x00000002 -#define AOFF_task_sgid 0x000001a4 +#define AOFF_task_sgid 0x000001bc #define ASIZ_task_sgid 0x00000002 -#define AOFF_task_fsgid 0x000001a6 +#define AOFF_task_fsgid 0x000001be #define ASIZ_task_fsgid 0x00000002 -#define AOFF_task_timeout 0x000001a8 +#define AOFF_task_timeout 0x000001c0 #define ASIZ_task_timeout 0x00000008 -#define AOFF_task_policy 0x000001b0 +#define AOFF_task_policy 0x000001c8 #define ASIZ_task_policy 0x00000008 -#define AOFF_task_rt_priority 0x000001b8 +#define AOFF_task_rt_priority 0x000001d0 #define ASIZ_task_rt_priority 0x00000008 -#define AOFF_task_it_real_value 0x000001c0 +#define AOFF_task_it_real_value 0x000001d8 #define ASIZ_task_it_real_value 0x00000008 -#define AOFF_task_it_prof_value 0x000001c8 +#define AOFF_task_it_prof_value 0x000001e0 #define ASIZ_task_it_prof_value 0x00000008 -#define AOFF_task_it_virt_value 0x000001d0 +#define AOFF_task_it_virt_value 0x000001e8 #define ASIZ_task_it_virt_value 0x00000008 -#define AOFF_task_it_real_incr 0x000001d8 +#define AOFF_task_it_real_incr 0x000001f0 #define ASIZ_task_it_real_incr 0x00000008 -#define AOFF_task_it_prof_incr 0x000001e0 +#define AOFF_task_it_prof_incr 0x000001f8 #define ASIZ_task_it_prof_incr 0x00000008 -#define AOFF_task_it_virt_incr 0x000001e8 +#define AOFF_task_it_virt_incr 0x00000200 #define ASIZ_task_it_virt_incr 0x00000008 -#define AOFF_task_real_timer 0x000001f0 +#define AOFF_task_real_timer 0x00000208 #define ASIZ_task_real_timer 0x00000028 -#define AOFF_task_utime 0x00000218 +#define AOFF_task_utime 0x00000230 #define ASIZ_task_utime 0x00000008 -#define AOFF_task_stime 0x00000220 +#define AOFF_task_stime 0x00000238 #define ASIZ_task_stime 0x00000008 -#define AOFF_task_cutime 0x00000228 +#define AOFF_task_cutime 0x00000240 #define ASIZ_task_cutime 0x00000008 -#define AOFF_task_cstime 0x00000230 +#define AOFF_task_cstime 0x00000248 #define ASIZ_task_cstime 0x00000008 -#define AOFF_task_start_time 0x00000238 +#define AOFF_task_start_time 0x00000250 #define ASIZ_task_start_time 0x00000008 -#define AOFF_task_min_flt 0x00000240 +#define AOFF_task_min_flt 0x00000258 #define ASIZ_task_min_flt 0x00000008 -#define AOFF_task_maj_flt 0x00000248 +#define AOFF_task_maj_flt 0x00000260 #define ASIZ_task_maj_flt 0x00000008 -#define AOFF_task_nswap 0x00000250 +#define AOFF_task_nswap 0x00000268 #define ASIZ_task_nswap 0x00000008 -#define AOFF_task_cmin_flt 0x00000258 +#define AOFF_task_cmin_flt 0x00000270 #define ASIZ_task_cmin_flt 0x00000008 -#define AOFF_task_cmaj_flt 0x00000260 +#define AOFF_task_cmaj_flt 0x00000278 #define ASIZ_task_cmaj_flt 0x00000008 -#define AOFF_task_cnswap 0x00000268 +#define AOFF_task_cnswap 0x00000280 #define ASIZ_task_cnswap 0x00000008 -#define AOFF_task_swap_address 0x00000278 +#define AOFF_task_swap_address 0x00000290 #define ASIZ_task_swap_address 0x00000008 -#define AOFF_task_old_maj_flt 0x00000280 +#define AOFF_task_old_maj_flt 0x00000298 #define ASIZ_task_old_maj_flt 0x00000008 -#define AOFF_task_dec_flt 0x00000288 +#define AOFF_task_dec_flt 0x000002a0 #define ASIZ_task_dec_flt 0x00000008 -#define AOFF_task_swap_cnt 0x00000290 +#define AOFF_task_swap_cnt 0x000002a8 #define ASIZ_task_swap_cnt 0x00000008 -#define AOFF_task_rlim 0x00000298 +#define AOFF_task_rlim 0x000002b0 #define ASIZ_task_rlim 0x000000a0 -#define AOFF_task_used_math 0x00000338 +#define AOFF_task_used_math 0x00000350 #define ASIZ_task_used_math 0x00000002 -#define AOFF_task_comm 0x0000033a +#define AOFF_task_comm 0x00000352 #define ASIZ_task_comm 0x00000010 -#define AOFF_task_link_count 0x0000034c +#define AOFF_task_link_count 0x00000364 #define ASIZ_task_link_count 0x00000004 -#define AOFF_task_tty 0x00000350 +#define AOFF_task_tty 0x00000368 #define ASIZ_task_tty 0x00000008 -#define AOFF_task_semundo 0x00000358 +#define AOFF_task_semundo 0x00000370 #define ASIZ_task_semundo 0x00000008 -#define AOFF_task_semsleeping 0x00000360 +#define AOFF_task_semsleeping 0x00000378 #define ASIZ_task_semsleeping 0x00000008 -#define AOFF_task_ldt 0x00000368 +#define AOFF_task_ldt 0x00000380 #define ASIZ_task_ldt 0x00000008 -#define AOFF_task_tss 0x00000380 +#define AOFF_task_tss 0x000003c0 #define ASIZ_task_tss 0x00000600 -#define AOFF_task_fs 0x00000980 +#define AOFF_task_fs 0x000009c0 #define ASIZ_task_fs 0x00000008 -#define AOFF_task_files 0x00000988 +#define AOFF_task_files 0x000009c8 #define ASIZ_task_files 0x00000008 -#define AOFF_task_mm 0x00000990 +#define AOFF_task_mm 0x000009d0 #define ASIZ_task_mm 0x00000008 -#define AOFF_task_sig 0x00000998 +#define AOFF_task_sig 0x000009d8 #define ASIZ_task_sig 0x00000008 -#define AOFF_task_processor 0x000009a0 +#define AOFF_task_processor 0x000009e0 #define ASIZ_task_processor 0x00000004 -#define AOFF_task_last_processor 0x000009a4 +#define AOFF_task_last_processor 0x000009e4 #define ASIZ_task_last_processor 0x00000004 -#define AOFF_task_lock_depth 0x000009a8 +#define AOFF_task_lock_depth 0x000009e8 #define ASIZ_task_lock_depth 0x00000004 -#define AOFF_mm_count 0x00000000 -#define ASIZ_mm_count 0x00000004 -#define AOFF_mm_pgd 0x00000008 +#define AOFF_task_sigmask_lock 0x000009ec +#define ASIZ_task_sigmask_lock 0x00000000 +#define AOFF_mm_mmap 0x00000000 +#define ASIZ_mm_mmap 0x00000008 +#define AOFF_mm_mmap_cache 0x00000008 +#define ASIZ_mm_mmap_cache 0x00000008 +#define AOFF_mm_pgd 0x00000010 #define ASIZ_mm_pgd 0x00000008 -#define AOFF_mm_context 0x00000010 +#define AOFF_mm_count 0x00000018 +#define ASIZ_mm_count 0x00000004 +#define AOFF_mm_mmap_sem 0x00000020 +#define ASIZ_mm_mmap_sem 0x00000010 +#define AOFF_mm_context 0x00000030 #define ASIZ_mm_context 0x00000008 -#define AOFF_mm_start_code 0x00000018 +#define AOFF_mm_start_code 0x00000038 #define ASIZ_mm_start_code 0x00000008 -#define AOFF_mm_end_code 0x00000020 +#define AOFF_mm_end_code 0x00000040 #define ASIZ_mm_end_code 0x00000008 -#define AOFF_mm_start_data 0x00000028 +#define AOFF_mm_start_data 0x00000048 #define ASIZ_mm_start_data 0x00000008 -#define AOFF_mm_end_data 0x00000030 +#define AOFF_mm_end_data 0x00000050 #define ASIZ_mm_end_data 0x00000008 -#define AOFF_mm_start_brk 0x00000038 +#define AOFF_mm_start_brk 0x00000058 #define ASIZ_mm_start_brk 0x00000008 -#define AOFF_mm_brk 0x00000040 +#define AOFF_mm_brk 0x00000060 #define ASIZ_mm_brk 0x00000008 -#define AOFF_mm_start_stack 0x00000048 +#define AOFF_mm_start_stack 0x00000068 #define ASIZ_mm_start_stack 0x00000008 -#define AOFF_mm_start_mmap 0x00000050 +#define AOFF_mm_start_mmap 0x00000070 #define ASIZ_mm_start_mmap 0x00000008 -#define AOFF_mm_arg_start 0x00000058 +#define AOFF_mm_arg_start 0x00000078 #define ASIZ_mm_arg_start 0x00000008 -#define AOFF_mm_arg_end 0x00000060 +#define AOFF_mm_arg_end 0x00000080 #define ASIZ_mm_arg_end 0x00000008 -#define AOFF_mm_env_start 0x00000068 +#define AOFF_mm_env_start 0x00000088 #define ASIZ_mm_env_start 0x00000008 -#define AOFF_mm_env_end 0x00000070 +#define AOFF_mm_env_end 0x00000090 #define ASIZ_mm_env_end 0x00000008 -#define AOFF_mm_rss 0x00000078 +#define AOFF_mm_rss 0x00000098 #define ASIZ_mm_rss 0x00000008 -#define AOFF_mm_total_vm 0x00000080 +#define AOFF_mm_total_vm 0x000000a0 #define ASIZ_mm_total_vm 0x00000008 -#define AOFF_mm_locked_vm 0x00000088 +#define AOFF_mm_locked_vm 0x000000a8 #define ASIZ_mm_locked_vm 0x00000008 -#define AOFF_mm_def_flags 0x00000090 +#define AOFF_mm_def_flags 0x000000b0 #define ASIZ_mm_def_flags 0x00000008 -#define AOFF_mm_mmap 0x00000098 -#define ASIZ_mm_mmap 0x00000008 -#define AOFF_mm_mmap_avl 0x000000a0 -#define ASIZ_mm_mmap_avl 0x00000008 -#define AOFF_mm_mmap_sem 0x000000a8 -#define ASIZ_mm_mmap_sem 0x00000010 #define AOFF_thread_float_regs 0x00000000 #define ASIZ_thread_float_regs 0x00000100 #define AOFF_thread_fsr 0x00000100 diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/fs_mount.h linux/include/asm-sparc64/fs_mount.h --- v2.1.36/linux/include/asm-sparc64/fs_mount.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-sparc64/fs_mount.h Sun Apr 27 15:08:02 1997 @@ -0,0 +1,44 @@ +/* $Id: fs_mount.h,v 1.2 1997/04/18 14:34:46 jj Exp $ + * fs_mount.h: Definitions for mount structure conversions. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + */ + +#ifndef __ASM_FS_MOUNT_H +#define __ASM_FS_MOUNT_H + +#if defined(CONFIG_SPARC32_COMPAT) || defined(CONFIG_SPARC32_COMPAT_MODULE) + +#include + +/* We need this to convert 32bit mount structures to 64bit */ + +extern void *do_ncp_super_data_conv(void *raw_data); +extern void *do_smb_super_data_conv(void *raw_data); + +extern __inline__ void *ncp_super_data_conv(void *raw_data) +{ + if (current->tss.flags & SPARC_FLAG_32BIT) + return do_ncp_super_data_conv(raw_data); + else + return raw_data; +} + +extern __inline__ void *smb_super_data_conv(void *raw_data) +{ + if (current->tss.flags & SPARC_FLAG_32BIT) + return do_smb_super_data_conv(raw_data); + else + return raw_data; +} + +#else /* CONFIG_SPARC32_COMPAT* */ + +#define ncp_super_data_conv(__x) __x +#define smb_super_data_conv(__x) __x + +#endif /* CONFIG_SPARC32_COMPAT* */ + +#define nfs_super_data_conv(__x) __x + +#endif /* __ASM_FS_MOUNT_H */ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/head.h linux/include/asm-sparc64/head.h --- v2.1.36/linux/include/asm-sparc64/head.h Mon Apr 14 16:28:22 1997 +++ linux/include/asm-sparc64/head.h Thu May 1 12:05:02 1997 @@ -1,4 +1,4 @@ -/* $Id: head.h,v 1.16 1997/04/08 11:03:13 davem Exp $ */ +/* $Id: head.h,v 1.17 1997/04/28 14:57:13 davem Exp $ */ #ifndef _SPARC64_HEAD_H #define _SPARC64_HEAD_H @@ -113,7 +113,7 @@ #define INDIRECT_SOLARIS_SYSCALL(tlvl) TRAP_ARG(indirect_syscall, tlvl) #define TRAP_IRQ(routine, level) \ - rdpr %pil, %g4; \ + rdpr %pil, %g2; \ wrpr %g0, 15, %pil; \ ba,pt %xcc, etrap_irq; \ rd %pc, %g7; \ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/linux_logo.h linux/include/asm-sparc64/linux_logo.h --- v2.1.36/linux/include/asm-sparc64/linux_logo.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc64/linux_logo.h Sun Apr 27 15:13:50 1997 @@ -1040,1045 +1040,3 @@ "'!!!!!!!W..e$$!!!!!!` %s\n" " \"~^^~ ^~~^\n" "\n"; -/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:37 jj Exp $ - * include/asm-sparc64/linux_logo.h: This is a linux logo - * to be displayed on boot. - * - * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * You can put anything here, but: - * LINUX_LOGO_COLORS has to be less than 224 - * image size has to be 80x80 - * values have to start from 0x20 - * (i.e. RGB(linux_logo_red[0], - * linux_logo_green[0], - * linux_logo_blue[0]) is color 0x20) - * BW image has to be 80x80 as well, with MS bit - * on the left - * Serial_console ascii image can be any size, - * but should contain %s to display the version - */ - -#include -#include - -#define linux_logo_banner "Linux/UltraSPARC version " UTS_RELEASE - -#define LINUX_LOGO_COLORS 215 - -unsigned char linux_logo_red[] __initdata = { - 0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00, - 0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25, - 0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xB0, - 0x0C, 0xB1, 0xD4, 0xCE, 0x04, 0x06, 0x16, 0xB6, - 0xCD, 0xB2, 0x42, 0x46, 0x4B, 0xA8, 0xF3, 0xCA, - 0xC5, 0x1C, 0xDC, 0xA0, 0xD4, 0xE6, 0xED, 0xF3, - 0xC2, 0x8E, 0xCC, 0xA5, 0x7E, 0x52, 0xF7, 0xE3, - 0x56, 0x79, 0x68, 0x8D, 0xAF, 0xFC, 0x8E, 0x3E, - 0x6B, 0x11, 0x37, 0x79, 0x5C, 0x3C, 0x3F, 0x3C, - 0x48, 0x47, 0x3D, 0xB9, 0x62, 0xE1, 0x4D, 0x57, - 0x84, 0x78, 0xA6, 0x58, 0x99, 0xCD, 0xB7, 0xE3, - 0x6D, 0x5A, 0xAF, 0x79, 0x79, 0xF2, 0x42, 0x46, - 0xDD, 0x89, 0xC3, 0xF2, 0xF0, 0xE0, 0xD1, 0x90, - 0x76, 0x6B, 0x4A, 0xBE, 0xBD, 0xE3, 0xF6, 0xE9, - 0xEC, 0xE8, 0xEC, 0xC0, 0x66, 0x63, 0xCB, 0xAB, - 0x49, 0x5C, 0xAD, 0xD6, 0xEE, 0xF5, 0xF5, 0xE9, - 0x6E, 0x00, 0x69, 0x6A, 0xA1, 0x7A, 0xB4, 0xDE, - 0xF1, 0xF6, 0xDD, 0x00, 0x73, 0xDB, 0x4C, 0x53, - 0x6A, 0xF5, 0xF5, 0xD6, 0xC3, 0x6A, 0x4B, 0x4B, - 0x60, 0xF8, 0x9B, 0xD7, 0xD7, 0x71, 0xB3, 0xA4, - 0xCA, 0xAB, 0xB4, 0xB2, 0x76, 0xBA, 0x8B, 0xA0, - 0xA5, 0xEE, 0xE7, 0x67, 0x5F, 0x08, 0x94, 0xDB, - 0xE5, 0x4F, 0x00, 0x34, 0xEE, 0xEC, 0xE2, 0x48, - 0xF3, 0xEB, 0xF4, 0xF4, 0xEF, 0xD6, 0xB6, 0xE6, - 0xE6, 0xED, 0xE7, 0xE6, 0x3D, 0xE7, 0xCD, 0x44, - 0xEF, 0xEC, 0xF5, 0x66, 0xF3, 0xA9, 0x77, 0x58, - 0x75, 0x6C, 0x53, 0x24, 0xAC, 0x0D, 0x3C -}; - -unsigned char linux_logo_green[] __initdata = { - 0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00, - 0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25, - 0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xAD, - 0x0C, 0xB1, 0x92, 0xAB, 0x03, 0x06, 0x16, 0xB6, - 0xCD, 0x88, 0x42, 0x46, 0x4B, 0x94, 0xBB, 0xCA, - 0xC5, 0x1C, 0xAB, 0xA0, 0xD4, 0xE6, 0xED, 0xF3, - 0xC2, 0x73, 0xCA, 0x91, 0x7E, 0x52, 0xF7, 0xE3, - 0x56, 0x5A, 0x49, 0x56, 0x6E, 0xFC, 0x6B, 0x3E, - 0x6B, 0x0D, 0x37, 0x79, 0x51, 0x44, 0x3F, 0x43, - 0x38, 0x3D, 0x48, 0xB9, 0x62, 0xA5, 0x47, 0x48, - 0x49, 0x4A, 0x97, 0x48, 0x81, 0x95, 0x8E, 0xE3, - 0x6D, 0x57, 0x51, 0x51, 0x47, 0xB2, 0x42, 0x46, - 0xDD, 0x5B, 0x87, 0xBE, 0xC7, 0xC8, 0x56, 0x75, - 0x5D, 0x4B, 0x4D, 0xBE, 0x85, 0xA6, 0xBC, 0xC7, - 0xCA, 0xCD, 0xCC, 0xA4, 0x53, 0x4D, 0x9F, 0x55, - 0x52, 0x5E, 0x75, 0x9C, 0xB6, 0xC3, 0xD7, 0xCC, - 0x55, 0x00, 0x6A, 0x59, 0x7D, 0x55, 0x7C, 0xA3, - 0xB7, 0xBF, 0xA5, 0x00, 0x67, 0xC6, 0x47, 0x54, - 0x46, 0xB8, 0xBE, 0xB2, 0x87, 0x52, 0x4B, 0x43, - 0x41, 0xF8, 0x69, 0x96, 0x9B, 0x66, 0xB0, 0x6C, - 0x8E, 0x81, 0xB4, 0x76, 0x76, 0xB9, 0x65, 0x77, - 0x6D, 0xED, 0xE7, 0x67, 0x5F, 0x06, 0x54, 0x6C, - 0xCB, 0x4F, 0x00, 0x2F, 0xC2, 0xB5, 0xB6, 0x30, - 0xC3, 0xAE, 0xC4, 0xCA, 0xC6, 0xB4, 0x7B, 0xAD, - 0xAD, 0xB6, 0xB6, 0xAD, 0x29, 0xAB, 0x93, 0x2E, - 0xBC, 0xBC, 0xC9, 0x53, 0xBF, 0x77, 0x54, 0x3B, - 0x4B, 0x3F, 0x39, 0x19, 0x76, 0x08, 0x2C -}; - -unsigned char linux_logo_blue[] __initdata = { - 0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0xD6, 0x00, - 0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x39, 0x25, - 0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xA7, - 0x0C, 0xB1, 0x58, 0x8A, 0x03, 0x07, 0x16, 0xB6, - 0xCD, 0x5A, 0x42, 0x46, 0x4F, 0x6F, 0x77, 0xCA, - 0xC5, 0x1C, 0x6F, 0xA5, 0xD4, 0xE6, 0xF5, 0xF3, - 0xC2, 0x4D, 0xD1, 0x64, 0x7E, 0x52, 0xF7, 0xE3, - 0x56, 0x49, 0x3C, 0x47, 0x45, 0xFE, 0x3B, 0x41, - 0x6B, 0x09, 0x37, 0x79, 0x39, 0x39, 0x3F, 0x42, - 0x3A, 0x42, 0x5F, 0xB9, 0x62, 0x4C, 0x39, 0x44, - 0x3B, 0x3A, 0xA0, 0x3D, 0x08, 0x08, 0x09, 0xDE, - 0x6D, 0x48, 0x3B, 0x3F, 0x42, 0xF3, 0x36, 0x3C, - 0xDD, 0x06, 0x16, 0x08, 0x13, 0x0A, 0x4B, 0x71, - 0x5D, 0x44, 0x47, 0xBE, 0x08, 0x0C, 0x0D, 0x0C, - 0x19, 0x29, 0x36, 0x06, 0x43, 0x44, 0xBA, 0x45, - 0x50, 0x58, 0x07, 0x07, 0x0D, 0x0E, 0x10, 0x50, - 0x06, 0x42, 0x40, 0x44, 0x79, 0x06, 0x06, 0x0C, - 0x08, 0x08, 0x07, 0x36, 0x4C, 0xE5, 0x42, 0x55, - 0x03, 0x0F, 0x12, 0x06, 0x07, 0x3C, 0x4B, 0x3D, - 0x01, 0xF8, 0x08, 0x0E, 0x0A, 0x69, 0xAC, 0x0C, - 0x0A, 0x27, 0xBB, 0x36, 0x76, 0xC0, 0x04, 0x08, - 0x08, 0xED, 0xEE, 0x68, 0x5F, 0xB2, 0x3B, 0x52, - 0xAC, 0x4F, 0x6F, 0x2D, 0x16, 0x08, 0x59, 0x04, - 0x13, 0x0E, 0x14, 0x17, 0x16, 0x2E, 0x08, 0x0D, - 0x11, 0x14, 0x0D, 0x06, 0x04, 0x08, 0x25, 0x8E, - 0x0E, 0x14, 0x25, 0x9B, 0x1C, 0x16, 0x78, 0x06, - 0x04, 0x03, 0x79, 0x8C, 0x0B, 0xC8, 0x48 -}; - -unsigned char linux_logo[] __initdata = { - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x21, 0x21, 0x22, 0x23, 0x24, 0x24, - 0x25, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25, - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x23, 0x23, - 0x23, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x26, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x26, 0x28, - 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x28, 0x28, 0x28, 0x2A, 0x2A, 0x2B, 0x2B, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2B, 0x2B, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x29, - 0x29, 0x29, 0x29, 0x2C, 0x29, 0x29, 0x29, 0x28, - 0x28, 0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2A, 0x2A, - 0x2A, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x2D, 0x2E, 0x2F, 0x27, - 0x27, 0x26, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x28, - 0x28, 0x29, 0x29, 0x29, 0x29, 0x2C, 0x2C, 0x29, - 0x29, 0x29, 0x28, 0x28, 0x2A, 0x2B, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x2F, 0x30, 0x31, 0x32, - 0x27, 0x27, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20, - 0x20, 0x20, 0x2B, 0x2A, 0x28, 0x29, 0x29, 0x29, - 0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x28, 0x2A, 0x2B, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x2B, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x32, 0x33, 0x34, 0x35, - 0x36, 0x27, 0x27, 0x33, 0x25, 0x25, 0x24, 0x24, - 0x24, 0x24, 0x23, 0x21, 0x20, 0x20, 0x2B, 0x2A, - 0x28, 0x29, 0x29, 0x37, 0x2C, 0x2C, 0x29, 0x28, - 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, - 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2A, 0x2B, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x2F, 0x32, 0x36, 0x27, - 0x27, 0x27, 0x27, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x25, 0x25, 0x24, 0x23, 0x21, - 0x20, 0x2B, 0x2A, 0x29, 0x29, 0x2C, 0x2C, 0x2C, - 0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, - 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x38, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x23, 0x23, 0x24, 0x24, - 0x25, 0x25, 0x33, 0x33, 0x33, 0x33, 0x33, 0x25, - 0x24, 0x22, 0x20, 0x20, 0x2A, 0x28, 0x29, 0x2C, - 0x2C, 0x2C, 0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x22, 0x23, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x2A, 0x2A, 0x2B, 0x2B, - 0x20, 0x21, 0x22, 0x24, 0x20, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x3A, 0x3B, 0x22, 0x20, 0x2A, 0x28, - 0x29, 0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x20, 0x21, 0x22, 0x22, 0x23, 0x24, 0x27, - 0x27, 0x27, 0x3C, 0x36, 0x3C, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x3D, 0x3E, 0x32, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x3D, 0x39, 0x3F, 0x3F, - 0x39, 0x2C, 0x20, 0x20, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x40, 0x40, 0x41, 0x22, 0x20, - 0x2A, 0x28, 0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x2A, - 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20, - 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x22, 0x27, - 0x27, 0x3C, 0x3C, 0x3D, 0x42, 0x3C, 0x27, 0x27, - 0x3C, 0x27, 0x3C, 0x43, 0x44, 0x36, 0x42, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x3D, 0x28, 0x29, 0x2C, - 0x2C, 0x45, 0x20, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x46, 0x40, 0x47, 0x40, 0x47, 0x3A, 0x40, - 0x22, 0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x2C, 0x29, - 0x28, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x22, - 0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x20, 0x27, - 0x27, 0x44, 0x28, 0x24, 0x27, 0x2F, 0x3C, 0x27, - 0x27, 0x38, 0x24, 0x2C, 0x2C, 0x48, 0x49, 0x36, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x29, 0x29, - 0x4A, 0x20, 0x3A, 0x40, 0x47, 0x40, 0x47, 0x40, - 0x40, 0x47, 0x40, 0x40, 0x39, 0x39, 0x39, 0x4A, - 0x25, 0x24, 0x22, 0x2B, 0x28, 0x29, 0x2C, 0x2C, - 0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x21, 0x20, 0x2B, 0x2A, 0x27, - 0x3D, 0x4B, 0x48, 0x4C, 0x2B, 0x3C, 0x27, 0x3C, - 0x3C, 0x23, 0x4D, 0x4E, 0x4F, 0x50, 0x33, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x39, 0x3F, 0x39, - 0x51, 0x20, 0x39, 0x39, 0x47, 0x40, 0x4D, 0x4D, - 0x40, 0x52, 0x4D, 0x40, 0x47, 0x40, 0x39, 0x39, - 0x53, 0x54, 0x25, 0x24, 0x20, 0x2A, 0x29, 0x2C, - 0x2C, 0x2C, 0x29, 0x2A, 0x2B, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x21, 0x20, 0x2B, 0x28, 0x2A, 0x20, 0x27, - 0x36, 0x4F, 0x55, 0x48, 0x56, 0x3D, 0x3C, 0x3C, - 0x32, 0x57, 0x56, 0x58, 0x49, 0x56, 0x56, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x20, 0x20, - 0x41, 0x39, 0x39, 0x3A, 0x59, 0x5A, 0x59, 0x5B, - 0x5C, 0x3A, 0x4D, 0x5D, 0x57, 0x39, 0x39, 0x4A, - 0x5E, 0x33, 0x54, 0x33, 0x24, 0x22, 0x2B, 0x28, - 0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21, - 0x20, 0x2B, 0x2A, 0x2A, 0x20, 0x22, 0x22, 0x27, - 0x5F, 0x2D, 0x3C, 0x60, 0x56, 0x54, 0x61, 0x49, - 0x35, 0x56, 0x34, 0x27, 0x62, 0x27, 0x56, 0x39, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x63, 0x54, - 0x40, 0x64, 0x65, 0x66, 0x67, 0x67, 0x68, 0x5F, - 0x2E, 0x69, 0x6A, 0x67, 0x5F, 0x3A, 0x39, 0x2C, - 0x53, 0x23, 0x25, 0x54, 0x33, 0x25, 0x23, 0x20, - 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, - 0x2B, 0x2A, 0x20, 0x22, 0x22, 0x21, 0x2B, 0x27, - 0x62, 0x36, 0x27, 0x33, 0x6B, 0x54, 0x3D, 0x3C, - 0x49, 0x57, 0x27, 0x27, 0x27, 0x27, 0x56, 0x57, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x6C, 0x31, 0x6D, - 0x64, 0x51, 0x6E, 0x2E, 0x2E, 0x6F, 0x5A, 0x70, - 0x70, 0x71, 0x72, 0x67, 0x67, 0x69, 0x73, 0x46, - 0x4A, 0x2A, 0x21, 0x25, 0x33, 0x54, 0x33, 0x24, - 0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x2B, - 0x2B, 0x22, 0x22, 0x22, 0x2B, 0x28, 0x2A, 0x27, - 0x27, 0x39, 0x3C, 0x3D, 0x45, 0x74, 0x75, 0x76, - 0x76, 0x45, 0x27, 0x27, 0x27, 0x27, 0x56, 0x77, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x78, 0x78, 0x5E, - 0x79, 0x7A, 0x7B, 0x6E, 0x5A, 0x5A, 0x70, 0x7C, - 0x70, 0x5B, 0x7D, 0x5A, 0x66, 0x7E, 0x7F, 0x79, - 0x48, 0x6B, 0x2C, 0x20, 0x24, 0x33, 0x54, 0x33, - 0x24, 0x21, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, - 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x21, 0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x21, - 0x22, 0x22, 0x20, 0x28, 0x2B, 0x20, 0x22, 0x27, - 0x27, 0x80, 0x27, 0x81, 0x82, 0x83, 0x84, 0x85, - 0x74, 0x85, 0x84, 0x27, 0x3C, 0x4F, 0x4F, 0x66, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x23, 0x5E, - 0x64, 0x86, 0x79, 0x73, 0x87, 0x88, 0x7C, 0x5A, - 0x5A, 0x71, 0x7D, 0x71, 0x89, 0x79, 0x8A, 0x8A, - 0x51, 0x8B, 0x48, 0x39, 0x2A, 0x22, 0x33, 0x54, - 0x33, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x2C, 0x29, - 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x22, 0x23, - 0x21, 0x2A, 0x2A, 0x20, 0x21, 0x23, 0x25, 0x27, - 0x27, 0x55, 0x8C, 0x8D, 0x8E, 0x83, 0x8F, 0x90, - 0x91, 0x92, 0x92, 0x85, 0x85, 0x93, 0x51, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0x29, 0x51, - 0x79, 0x79, 0x94, 0x89, 0x89, 0x89, 0x5A, 0x95, - 0x64, 0x88, 0x96, 0x97, 0x7A, 0x73, 0x98, 0x98, - 0x99, 0x50, 0x50, 0x48, 0x6B, 0x28, 0x21, 0x25, - 0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x29, - 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2B, 0x20, 0x22, 0x22, 0x20, - 0x2B, 0x2B, 0x20, 0x22, 0x24, 0x25, 0x33, 0x27, - 0x27, 0x9A, 0x9B, 0x9C, 0x9D, 0x83, 0x9E, 0x85, - 0x9F, 0x92, 0x85, 0x85, 0x85, 0x85, 0x92, 0xA0, - 0x27, 0x27, 0x27, 0x27, 0x27, 0xA1, 0x47, 0xA2, - 0xA2, 0x94, 0xA3, 0x94, 0x95, 0x95, 0x73, 0x73, - 0x95, 0x87, 0xA4, 0x5B, 0x97, 0x7B, 0x88, 0x98, - 0xA2, 0x50, 0x48, 0x48, 0x48, 0x8B, 0x29, 0x20, - 0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x29, - 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x2B, 0x2B, - 0x20, 0x21, 0x23, 0x24, 0x25, 0x25, 0x33, 0x27, - 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0x8F, 0x90, 0x90, - 0x9F, 0x90, 0x85, 0x90, 0x85, 0x74, 0xAA, 0x81, - 0x27, 0x27, 0x27, 0x27, 0x27, 0xAB, 0x40, 0xAC, - 0x79, 0xA3, 0x89, 0xAD, 0x95, 0x6F, 0xAE, 0xAE, - 0xAE, 0x5B, 0x59, 0x88, 0x7B, 0x89, 0x79, 0xAF, - 0xA2, 0x6B, 0x48, 0x48, 0x48, 0x48, 0x50, 0x2C, - 0x20, 0x24, 0x33, 0x54, 0x25, 0x22, 0x2A, 0x2A, - 0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x21, 0x23, 0x22, 0x2B, 0x20, 0x20, - 0x22, 0x23, 0x24, 0x25, 0x24, 0x24, 0x22, 0x27, - 0xB0, 0x8C, 0xAA, 0xB1, 0xB2, 0x84, 0x85, 0x9F, - 0x85, 0x85, 0x85, 0xB3, 0xB4, 0xAA, 0xAA, 0xA0, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0xB5, - 0xA3, 0xA3, 0xAC, 0x5D, 0xB6, 0xAE, 0xB7, 0x69, - 0x73, 0x5B, 0x88, 0x89, 0x95, 0x73, 0x99, 0x99, - 0x59, 0x2A, 0x39, 0x48, 0x48, 0x50, 0x48, 0x50, - 0x2C, 0x20, 0x24, 0x33, 0x54, 0x25, 0x21, 0x20, - 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x23, 0x21, 0x2B, 0x20, 0x20, 0x22, - 0x22, 0x24, 0x24, 0x23, 0x22, 0x20, 0x2A, 0x27, - 0x27, 0xB0, 0x8C, 0xA9, 0xB2, 0x9E, 0x91, 0x85, - 0x85, 0x93, 0xB8, 0x75, 0xAA, 0xA7, 0x8C, 0x27, - 0x27, 0x27, 0x33, 0x3C, 0x27, 0x27, 0x2C, 0x7B, - 0x55, 0x79, 0xA3, 0x5D, 0xB9, 0x43, 0x7F, 0x7E, - 0x5F, 0x5A, 0x5A, 0x95, 0x64, 0x73, 0x58, 0x64, - 0x5C, 0x25, 0x2B, 0x3F, 0x48, 0x48, 0x8B, 0x48, - 0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x24, 0x22, - 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x21, 0x23, 0x21, 0x20, 0x20, 0x20, 0x21, 0x22, - 0x24, 0x23, 0x22, 0x21, 0x2B, 0x20, 0x54, 0x27, - 0x27, 0x8B, 0x81, 0xA5, 0x93, 0x93, 0x74, 0xA5, - 0xBA, 0x75, 0xBB, 0xBC, 0xB4, 0x6D, 0x50, 0x6B, - 0x27, 0x27, 0x30, 0x33, 0x49, 0x27, 0x27, 0x5E, - 0x6F, 0x73, 0x94, 0xBD, 0x4E, 0x5D, 0x7F, 0x7F, - 0xB7, 0x68, 0x73, 0x6E, 0xB7, 0x7F, 0x95, 0x97, - 0x47, 0x63, 0x25, 0x20, 0x3F, 0x48, 0x8B, 0x8B, - 0x48, 0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x25, - 0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x21, - 0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, - 0x22, 0x21, 0x20, 0x2A, 0x33, 0x30, 0x30, 0x27, - 0x27, 0x50, 0xBE, 0xBF, 0x9A, 0xB3, 0x9B, 0xBB, - 0xBB, 0xC0, 0x8C, 0xC1, 0x8B, 0xC2, 0x47, 0x8B, - 0x27, 0x27, 0x38, 0x63, 0x63, 0x27, 0x27, 0xC3, - 0xB5, 0x95, 0x72, 0x95, 0x6F, 0x69, 0x7E, 0x66, - 0x7E, 0x7F, 0x6E, 0x7E, 0x95, 0x95, 0x73, 0x70, - 0x30, 0x30, 0x30, 0x33, 0x20, 0x3F, 0x48, 0x8B, - 0x6B, 0x48, 0x50, 0x29, 0x21, 0x33, 0x54, 0x33, - 0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x21, 0x21, 0x23, - 0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x22, - 0x20, 0x2B, 0x21, 0xC4, 0x30, 0x60, 0x30, 0x27, - 0x27, 0xC5, 0x8B, 0x39, 0xC6, 0xC7, 0xA6, 0xA6, - 0xC8, 0x9A, 0x3B, 0x39, 0x50, 0x56, 0x56, 0x4F, - 0x33, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x48, - 0x59, 0x94, 0x73, 0xAE, 0xB7, 0xB7, 0x7E, 0x7E, - 0x7E, 0x7E, 0x7E, 0x5A, 0x70, 0x7C, 0x71, 0xC3, - 0x63, 0x30, 0x60, 0x78, 0x54, 0x20, 0x6B, 0x48, - 0x6B, 0x6B, 0x50, 0x50, 0x29, 0x22, 0x33, 0x33, - 0x2A, 0x2B, 0x20, 0x20, 0x21, 0x22, 0x22, 0x22, - 0x21, 0x20, 0x20, 0x20, 0x24, 0x24, 0x20, 0x20, - 0x2B, 0x24, 0x30, 0x60, 0x60, 0x30, 0xAB, 0x27, - 0x27, 0x40, 0x4C, 0x50, 0x39, 0x87, 0xC3, 0x53, - 0x37, 0x48, 0x37, 0x48, 0xC9, 0x56, 0xB9, 0x56, - 0xCA, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x3C, - 0x51, 0x5A, 0x6E, 0xB7, 0xB7, 0x7E, 0x7E, 0x7E, - 0x7E, 0x7E, 0x7F, 0xB7, 0x5A, 0x7C, 0x5B, 0x37, - 0x23, 0x63, 0x31, 0x6C, 0xCB, 0x63, 0x20, 0x6B, - 0x50, 0x3F, 0x39, 0x50, 0x8B, 0x28, 0x24, 0x24, - 0x2B, 0x2B, 0x20, 0x21, 0x22, 0x22, 0x22, 0x21, - 0x20, 0x20, 0x20, 0x23, 0x23, 0x20, 0x20, 0x2B, - 0x33, 0x78, 0xCB, 0x60, 0x30, 0x22, 0x3D, 0x27, - 0x2F, 0x56, 0x4E, 0x8B, 0x6B, 0x39, 0x48, 0x8B, - 0x6B, 0x8B, 0x80, 0xC9, 0xB9, 0xB9, 0x56, 0xB9, - 0x56, 0x34, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x48, 0xB5, 0xB7, 0xB7, 0x7E, 0x7E, 0x2E, 0x7E, - 0x7E, 0x7E, 0x7F, 0x7C, 0x65, 0x71, 0x3A, 0x48, - 0x2C, 0x24, 0x30, 0x6C, 0x34, 0x6C, 0xC4, 0x20, - 0x8B, 0x50, 0x39, 0x39, 0x48, 0x6B, 0x2B, 0x22, - 0x2B, 0x20, 0x21, 0x22, 0x23, 0x23, 0x22, 0x21, - 0x20, 0x2B, 0x23, 0x22, 0x20, 0x2B, 0x2B, 0x54, - 0x60, 0x31, 0xCB, 0x54, 0x20, 0x3D, 0x36, 0x27, - 0x4E, 0xB9, 0x56, 0x56, 0x8B, 0x6B, 0x50, 0x6B, - 0x40, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, - 0x56, 0x56, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x7B, 0x6E, 0xB7, 0xB7, 0xB7, 0x7E, 0x7F, - 0xB7, 0xB7, 0x7F, 0x7E, 0x6F, 0x5B, 0x29, 0x2C, - 0x48, 0x39, 0x24, 0x60, 0x58, 0xAF, 0xCC, 0x63, - 0x20, 0x8B, 0x8B, 0x39, 0x39, 0x48, 0x3F, 0x28, - 0x20, 0x20, 0x22, 0x23, 0x23, 0x23, 0x22, 0x20, - 0x2B, 0x22, 0x22, 0x2B, 0x2B, 0x20, 0x54, 0xCB, - 0x31, 0xCB, 0x25, 0x20, 0x27, 0x27, 0x27, 0x48, - 0xB9, 0x56, 0xB9, 0x56, 0x4F, 0x48, 0x47, 0x57, - 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, - 0xB9, 0x56, 0x62, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x48, 0x6F, 0x69, 0xB7, 0xB7, 0xB7, 0x7F, - 0xB7, 0xB7, 0xB7, 0x73, 0x59, 0x50, 0x29, 0x2B, - 0x28, 0x8B, 0x39, 0x25, 0x31, 0x55, 0xB6, 0x34, - 0x63, 0x2B, 0x48, 0x6B, 0x2C, 0x39, 0x47, 0x6B, - 0x22, 0x22, 0x23, 0x24, 0x23, 0x22, 0x20, 0x2B, - 0x20, 0x22, 0x2A, 0x2B, 0x20, 0x33, 0xCB, 0x31, - 0x78, 0x24, 0x21, 0xCD, 0x27, 0x27, 0x27, 0x56, - 0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x56, 0xB9, - 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, - 0xB9, 0x56, 0xC9, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x41, 0x64, 0xB7, 0xB7, 0xB7, 0x7F, - 0x68, 0xB7, 0xAE, 0xA3, 0x23, 0x39, 0x8B, 0x2A, - 0x20, 0x20, 0x39, 0x6B, 0x25, 0xCC, 0x43, 0x43, - 0x34, 0x63, 0x2A, 0x48, 0x3F, 0x39, 0x6B, 0x6B, - 0x24, 0x23, 0x24, 0x24, 0x23, 0x21, 0x2B, 0x2B, - 0x22, 0x2B, 0x2B, 0x20, 0x24, 0x78, 0x31, 0x30, - 0x23, 0x21, 0x21, 0x27, 0x27, 0x27, 0x80, 0x56, - 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, - 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, - 0x56, 0xB9, 0x56, 0x3C, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xCE, 0x8A, 0xAE, 0x6F, 0xB7, - 0x6F, 0x89, 0x71, 0x78, 0x63, 0x23, 0x39, 0x6B, - 0x2B, 0x20, 0x20, 0x2C, 0x6B, 0x25, 0x34, 0x42, - 0x42, 0x34, 0x54, 0x29, 0x48, 0x3F, 0x39, 0x3F, - 0x25, 0x24, 0x25, 0x24, 0x22, 0x20, 0x2A, 0x21, - 0x2B, 0x2A, 0x20, 0x22, 0x30, 0x60, 0x30, 0x22, - 0x21, 0x22, 0x27, 0x27, 0x27, 0x2D, 0x4C, 0x56, - 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0x56, 0x2E, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x40, 0x97, 0x95, 0x5A, 0x71, - 0x7C, 0xCE, 0x40, 0x60, 0x31, 0x30, 0x23, 0x3F, - 0x3F, 0x20, 0x20, 0x20, 0x29, 0x8B, 0x33, 0x58, - 0x66, 0x43, 0xCC, 0x25, 0x39, 0x50, 0x6B, 0x2C, - 0x33, 0x25, 0x25, 0x23, 0x20, 0x2A, 0x2B, 0x20, - 0x2A, 0x2B, 0x22, 0x54, 0x30, 0x30, 0x24, 0x22, - 0x21, 0x27, 0x27, 0x27, 0x27, 0xAF, 0x29, 0x4E, - 0x4F, 0xB9, 0x56, 0xB9, 0x4D, 0x4D, 0x77, 0xC9, - 0xB9, 0xB9, 0xB9, 0x56, 0xC9, 0x4D, 0x4D, 0x80, - 0x4C, 0x40, 0xC9, 0x4D, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0xCF, 0x97, 0x97, 0xCE, - 0x86, 0xD0, 0x54, 0x6C, 0x58, 0x34, 0x60, 0x23, - 0x6B, 0x39, 0x20, 0x20, 0x20, 0x28, 0x6B, 0x54, - 0xD1, 0x66, 0xB6, 0x60, 0x22, 0x6B, 0x8B, 0x2C, - 0x54, 0x33, 0x24, 0x22, 0x2B, 0x28, 0x20, 0x28, - 0x2B, 0x20, 0x25, 0xC4, 0x30, 0x25, 0x22, 0x21, - 0x26, 0x27, 0x27, 0x27, 0x27, 0x20, 0x4B, 0x52, - 0x80, 0x4F, 0xB9, 0x56, 0xB9, 0x80, 0x56, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0x4D, 0x80, 0x50, 0x48, - 0x50, 0x50, 0x50, 0x56, 0x3D, 0x27, 0x36, 0x27, - 0x27, 0x27, 0x27, 0x3C, 0x46, 0xC3, 0x86, 0x86, - 0xD0, 0x39, 0x24, 0x6C, 0xD1, 0x43, 0x43, 0x6C, - 0x24, 0x6B, 0x2C, 0x20, 0x20, 0x20, 0x29, 0x39, - 0x63, 0xD1, 0x42, 0x55, 0xC4, 0x2B, 0x8B, 0x39, - 0x54, 0x25, 0x24, 0x20, 0x2A, 0x2A, 0x28, 0x28, - 0x20, 0x22, 0x54, 0x63, 0x25, 0x24, 0x22, 0x22, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x77, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xC9, 0x56, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x4F, - 0x77, 0x47, 0x8B, 0x40, 0x56, 0x27, 0x27, 0x49, - 0x2D, 0x27, 0x27, 0x27, 0x39, 0x40, 0x39, 0x39, - 0x28, 0x3F, 0x39, 0x33, 0x58, 0x66, 0x35, 0x2E, - 0x58, 0x24, 0x8B, 0x29, 0x20, 0x20, 0x20, 0x39, - 0x29, 0x30, 0x55, 0xB6, 0xCC, 0x25, 0x29, 0x39, - 0x54, 0x25, 0x22, 0x2B, 0x29, 0x2A, 0x29, 0x2B, - 0x22, 0x24, 0x54, 0x33, 0x25, 0x22, 0x2B, 0x54, - 0x27, 0x27, 0x62, 0x27, 0x30, 0x80, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x4D, 0x8B, 0x77, 0x36, 0x27, 0x27, - 0x3C, 0x2F, 0x27, 0x27, 0x39, 0x39, 0x39, 0x47, - 0x20, 0x2B, 0x2C, 0x39, 0x33, 0xB6, 0x35, 0x35, - 0x35, 0xAF, 0x24, 0x48, 0x2A, 0x20, 0x20, 0x20, - 0x8B, 0x2B, 0x78, 0xAF, 0x58, 0x30, 0x21, 0x28, - 0x33, 0x25, 0x21, 0x28, 0x29, 0x29, 0x28, 0x20, - 0x24, 0x33, 0x54, 0x33, 0x23, 0x20, 0x24, 0xD2, - 0x27, 0x49, 0x27, 0x27, 0x56, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0xC9, 0x50, 0x56, 0x27, 0x27, - 0x3D, 0x38, 0x3D, 0x27, 0x27, 0x47, 0x39, 0x39, - 0x28, 0x20, 0x20, 0x2A, 0x39, 0x54, 0x43, 0x35, - 0x35, 0x35, 0xAF, 0x23, 0x48, 0x2B, 0x20, 0x20, - 0x2B, 0x48, 0x22, 0x60, 0x34, 0xCB, 0x25, 0x21, - 0x33, 0x24, 0x2B, 0x29, 0x29, 0x29, 0x2B, 0x22, - 0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x33, 0x27, - 0x27, 0x32, 0x27, 0x30, 0x56, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x56, 0xC9, 0x4C, 0x36, 0x3C, - 0x62, 0x2F, 0x2E, 0x27, 0x27, 0x54, 0x47, 0x47, - 0x8B, 0x2B, 0x20, 0x20, 0x20, 0x3F, 0x54, 0x2E, - 0x35, 0x35, 0x35, 0x34, 0x21, 0x8B, 0x2A, 0x20, - 0x20, 0x2C, 0x6B, 0x25, 0x60, 0x60, 0x54, 0x23, - 0x25, 0x22, 0x2A, 0x2C, 0x29, 0x28, 0x20, 0x24, - 0x54, 0x63, 0x54, 0x24, 0x2B, 0x22, 0x24, 0x27, - 0x36, 0x27, 0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x4C, 0x36, - 0x66, 0xD3, 0x27, 0x2F, 0x27, 0x54, 0x54, 0x27, - 0x26, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x6B, 0x63, - 0x35, 0x35, 0x35, 0x62, 0xCB, 0x2A, 0x3F, 0x28, - 0x2B, 0x2A, 0x50, 0x29, 0x33, 0x30, 0x54, 0x25, - 0x24, 0x20, 0x29, 0x2C, 0x2C, 0x2A, 0x21, 0x33, - 0xC4, 0xC4, 0x33, 0x21, 0x29, 0x22, 0x27, 0x27, - 0x99, 0x27, 0x31, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x3D, - 0x3D, 0x3C, 0x3C, 0x55, 0x54, 0x54, 0x54, 0x20, - 0x27, 0x2C, 0x39, 0x20, 0x20, 0x20, 0x20, 0x48, - 0x30, 0x62, 0x35, 0x35, 0x42, 0x54, 0x39, 0x39, - 0x2C, 0x28, 0x3F, 0x8B, 0x20, 0x33, 0x54, 0x24, - 0x22, 0x2B, 0x2C, 0x2C, 0x2C, 0x2B, 0x24, 0x54, - 0x30, 0xC4, 0x25, 0x2B, 0x28, 0x2B, 0x27, 0x3D, - 0x27, 0x27, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x27, - 0x20, 0x20, 0x20, 0x54, 0x54, 0x54, 0x54, 0x20, - 0x20, 0x2D, 0x2D, 0x29, 0x20, 0x20, 0x20, 0x20, - 0x48, 0x60, 0x66, 0x35, 0x62, 0x34, 0x22, 0x2C, - 0x2C, 0x3F, 0x6B, 0x48, 0x2C, 0x22, 0x23, 0x23, - 0x20, 0x2A, 0x2C, 0x29, 0x29, 0x20, 0x25, 0xC4, - 0x30, 0x54, 0x22, 0x29, 0x28, 0xD2, 0x27, 0x35, - 0x27, 0x49, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x4F, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x40, 0x20, - 0x20, 0x54, 0x54, 0x54, 0x20, 0x20, 0x20, 0x20, - 0x2D, 0x2D, 0x2D, 0x49, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x6B, 0x6C, 0x42, 0x2E, 0xB6, 0x54, 0x28, - 0x29, 0x2C, 0x6B, 0x48, 0x3F, 0x2A, 0x20, 0x22, - 0x2B, 0x28, 0x2C, 0x28, 0x29, 0x20, 0x33, 0x30, - 0x30, 0x54, 0x20, 0x2C, 0x29, 0x27, 0x27, 0x3D, - 0x27, 0x40, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x56, 0x63, 0x56, 0x54, 0x54, - 0x54, 0x54, 0x20, 0xD3, 0x45, 0x51, 0x51, 0x49, - 0x7C, 0x2D, 0x2D, 0x49, 0x49, 0x20, 0x20, 0x20, - 0x20, 0x2A, 0x2A, 0xCC, 0xB6, 0x8A, 0x60, 0x22, - 0x28, 0x29, 0x3F, 0x6B, 0x39, 0x29, 0x2B, 0x20, - 0x28, 0x2C, 0x28, 0x2A, 0x2A, 0x24, 0xC4, 0x30, - 0xC4, 0x33, 0x2B, 0x39, 0xCD, 0x27, 0x3C, 0x27, - 0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x63, 0x63, 0x49, 0x2D, 0x20, - 0x20, 0x2D, 0xD3, 0x49, 0x66, 0x2D, 0x49, 0x49, - 0x49, 0x49, 0x49, 0x49, 0x49, 0x8B, 0x2B, 0x20, - 0x20, 0x20, 0x39, 0x23, 0x6C, 0xAF, 0xCB, 0x23, - 0x28, 0x28, 0x29, 0x2A, 0x2A, 0x2A, 0x2A, 0x20, - 0x29, 0x39, 0x2B, 0x2B, 0x2B, 0x25, 0x78, 0xC4, - 0x63, 0x23, 0x29, 0x39, 0x27, 0x27, 0x3D, 0x27, - 0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x80, 0x4F, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49, - 0x49, 0x2D, 0x49, 0x2D, 0x49, 0x2D, 0x2D, 0x2D, - 0x49, 0x49, 0x35, 0x49, 0x2D, 0x2D, 0x39, 0x28, - 0x20, 0x20, 0x2A, 0x28, 0x33, 0x60, 0xC4, 0x22, - 0x2C, 0x2A, 0x2A, 0x22, 0x23, 0x22, 0x20, 0x21, - 0x2C, 0x29, 0x20, 0x2B, 0x2B, 0x54, 0x30, 0xC4, - 0x63, 0x22, 0x2C, 0x27, 0x27, 0x27, 0x3D, 0x27, - 0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49, - 0x61, 0x49, 0x2D, 0x49, 0x49, 0x2D, 0x2D, 0x49, - 0x49, 0x49, 0x2F, 0x49, 0x2D, 0x78, 0x29, 0x28, - 0x2C, 0x2A, 0x2B, 0x39, 0x2B, 0x25, 0x33, 0x20, - 0x2C, 0x20, 0x2A, 0x24, 0x54, 0x54, 0x23, 0x23, - 0x2C, 0x2A, 0x22, 0x2B, 0x20, 0x63, 0x30, 0x63, - 0xC4, 0x21, 0x39, 0x27, 0x27, 0x27, 0x35, 0x36, - 0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x2D, 0x49, 0x49, 0x49, - 0x49, 0x27, 0x27, 0x2D, 0x38, 0x27, 0x36, 0x36, - 0x49, 0x27, 0x49, 0x2D, 0x2D, 0x44, 0x24, 0x2B, - 0x20, 0x2C, 0x3F, 0x6B, 0x2A, 0x20, 0x21, 0x28, - 0x2C, 0x20, 0x2B, 0x24, 0x30, 0xCB, 0x63, 0x54, - 0x28, 0x20, 0x24, 0x2B, 0x23, 0x78, 0xC4, 0x63, - 0x63, 0x2B, 0x3F, 0x27, 0x27, 0x27, 0x38, 0x33, - 0x3D, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x63, 0x49, 0x49, 0x49, - 0x49, 0x49, 0x3D, 0x3D, 0x27, 0x27, 0x27, 0x2D, - 0x49, 0x49, 0x49, 0x2D, 0x62, 0x5F, 0xC4, 0x20, - 0x22, 0x2A, 0x6B, 0x8B, 0x2C, 0x2B, 0x2A, 0x3F, - 0x3F, 0x2A, 0x21, 0x21, 0xCB, 0x58, 0x6C, 0x60, - 0x20, 0x23, 0x24, 0x2A, 0x25, 0x78, 0x63, 0x63, - 0x54, 0x2A, 0x28, 0x27, 0x27, 0x27, 0x27, 0x62, - 0x3C, 0xB9, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x49, 0x2D, 0x2D, - 0x2D, 0x3D, 0x2F, 0x3C, 0x2D, 0x3C, 0x27, 0x38, - 0x2D, 0x49, 0x2D, 0x2D, 0xD1, 0x43, 0x30, 0x20, - 0x24, 0x21, 0x21, 0x21, 0x2B, 0x2A, 0x29, 0x8B, - 0x6B, 0x29, 0x2B, 0x2A, 0x30, 0x55, 0x55, 0x34, - 0x22, 0x23, 0x24, 0x29, 0x54, 0x30, 0x63, 0x63, - 0x25, 0x29, 0x22, 0x3C, 0xA5, 0xD4, 0xD5, 0x27, - 0x31, 0x56, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x2D, 0x2E, - 0x3E, 0x27, 0x27, 0x27, 0x27, 0x27, 0x36, 0x44, - 0x3C, 0x27, 0x2D, 0xC4, 0x78, 0xCC, 0x54, 0x2B, - 0x25, 0x24, 0x63, 0x60, 0x63, 0x24, 0x2A, 0x6B, - 0x3F, 0x39, 0x28, 0x21, 0x33, 0xB6, 0x44, 0x58, - 0x22, 0x23, 0x24, 0x2A, 0x30, 0x30, 0x63, 0x63, - 0x24, 0x39, 0x22, 0xBB, 0x9C, 0xB2, 0x9D, 0xA8, - 0x27, 0x8B, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9, - 0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0xD6, 0xD6, 0xD7, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x32, - 0x3D, 0x27, 0x39, 0x33, 0xC4, 0xC4, 0x22, 0x28, - 0x25, 0x54, 0x30, 0xD1, 0xD1, 0x60, 0x23, 0x6B, - 0x3F, 0x39, 0x2C, 0x2B, 0x20, 0x58, 0x8A, 0x58, - 0x22, 0x23, 0x23, 0x2B, 0x78, 0x30, 0xC4, 0xC4, - 0x23, 0x29, 0xBB, 0xBB, 0xD8, 0xB2, 0x9D, 0xA9, - 0xA9, 0x3C, 0x60, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, - 0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0xB9, 0x56, 0xD9, 0x85, 0x85, 0x85, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2D, - 0xA0, 0x83, 0x2C, 0x21, 0x30, 0x33, 0x29, 0x29, - 0x21, 0x33, 0x54, 0x42, 0x66, 0x55, 0xC4, 0x29, - 0x8B, 0x2C, 0x39, 0x28, 0x29, 0x31, 0x44, 0x58, - 0x23, 0x23, 0x21, 0x20, 0x30, 0xC4, 0xC4, 0x30, - 0x21, 0x20, 0xBB, 0xBC, 0xDA, 0xDB, 0xDC, 0xB2, - 0x83, 0xB4, 0x3C, 0x2F, 0xB9, 0x56, 0x56, 0xB9, - 0x56, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x56, 0xA7, 0xD4, 0x85, 0x82, - 0x3C, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x61, - 0x9E, 0x90, 0xDD, 0x21, 0x33, 0x25, 0x2C, 0x39, - 0x2A, 0x24, 0x24, 0x42, 0x62, 0x43, 0x34, 0x22, - 0x50, 0x39, 0x2C, 0x2C, 0x2A, 0x54, 0xD1, 0x58, - 0x22, 0x22, 0x2B, 0x22, 0x30, 0xC4, 0x30, 0x60, - 0x20, 0xDE, 0xBB, 0xD9, 0x84, 0x84, 0xDF, 0xA9, - 0xDB, 0xDB, 0x61, 0x27, 0x38, 0x4D, 0x56, 0x56, - 0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x56, 0x56, 0x8D, 0xD9, 0xD5, 0xA6, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0xBB, - 0x85, 0xDB, 0xDD, 0x21, 0x22, 0x22, 0x3F, 0x39, - 0x2C, 0x2B, 0x25, 0x34, 0x62, 0x66, 0xD1, 0xC4, - 0x6B, 0x39, 0x2C, 0x39, 0x29, 0x21, 0x58, 0xCC, - 0x22, 0x21, 0x29, 0x23, 0x30, 0x30, 0x30, 0x5E, - 0x82, 0xBB, 0xE0, 0xB1, 0xE1, 0x9C, 0xD4, 0xDC, - 0x9D, 0xA9, 0xE2, 0x27, 0x27, 0x27, 0x4D, 0x56, - 0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x4C, 0x48, 0xA8, 0xA8, 0xE3, 0x8C, - 0xC6, 0x3C, 0x27, 0x27, 0x27, 0xE4, 0xA6, 0xE5, - 0x83, 0xA9, 0xE6, 0xAF, 0x54, 0x2B, 0x8B, 0x39, - 0x39, 0x29, 0x20, 0x54, 0x42, 0x42, 0xB6, 0xCC, - 0x2A, 0x29, 0x39, 0x39, 0x2C, 0x2C, 0xCC, 0xCC, - 0x22, 0x20, 0x39, 0xE7, 0xC0, 0xD9, 0xA7, 0xBC, - 0x8D, 0xAA, 0x9C, 0xE8, 0x9C, 0x9D, 0xD4, 0xD4, - 0xD8, 0xA9, 0x84, 0xC7, 0x27, 0x27, 0x27, 0x2A, - 0x56, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0x56, 0x56, 0x48, 0x50, 0xAA, 0xE3, 0xE3, 0xC0, - 0xA6, 0x9A, 0xBA, 0xC8, 0x9A, 0xDE, 0x9B, 0xD5, - 0xE8, 0xD8, 0xD5, 0x2E, 0x58, 0x33, 0x6B, 0x39, - 0x2C, 0x39, 0x29, 0x28, 0xD1, 0x43, 0xB6, 0xAF, - 0x23, 0x28, 0x2C, 0x39, 0x39, 0x8B, 0x30, 0x31, - 0x21, 0x20, 0x3F, 0xBB, 0xDF, 0xDF, 0xD5, 0xA8, - 0xD5, 0x9C, 0x8E, 0xB2, 0x9D, 0xE9, 0xD4, 0xD8, - 0x90, 0xB2, 0xA9, 0x8F, 0x27, 0x27, 0x27, 0x27, - 0x2F, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0x56, 0xB9, 0x48, 0x48, 0x75, 0xE3, 0xAA, 0xAA, - 0xC0, 0xB4, 0xB4, 0xB4, 0x75, 0x9B, 0xD9, 0x83, - 0x9D, 0x90, 0xDF, 0xDD, 0x8A, 0x31, 0x4B, 0x2C, - 0x2C, 0x29, 0x2C, 0x3F, 0x6C, 0x55, 0xD1, 0x55, - 0x54, 0x29, 0x28, 0x39, 0x39, 0x6B, 0x24, 0x60, - 0x20, 0x2B, 0x3F, 0xA7, 0xB1, 0x9D, 0xA9, 0x8E, - 0xE5, 0xE5, 0xDF, 0xE0, 0xA9, 0x9D, 0xDF, 0xDF, - 0xEA, 0x9D, 0xB2, 0x84, 0xAA, 0x27, 0x27, 0x27, - 0x27, 0x35, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0xB9, 0x48, 0x48, 0xA6, 0x9B, 0xE3, 0xAA, - 0xAA, 0x9B, 0x9B, 0x9B, 0xAA, 0xE3, 0xD5, 0xD4, - 0x9D, 0xA9, 0xA9, 0x9D, 0xEB, 0xAF, 0x23, 0x28, - 0x2C, 0x29, 0x28, 0x39, 0x54, 0xCC, 0xAF, 0x55, - 0x30, 0x29, 0x2B, 0x2C, 0x39, 0x39, 0x2B, 0xC4, - 0x2B, 0x29, 0x39, 0xA7, 0x8E, 0x9D, 0x83, 0xE5, - 0xB1, 0xDB, 0xDC, 0xE0, 0xDC, 0x84, 0xE9, 0x84, - 0x83, 0xD4, 0xEC, 0x83, 0x8F, 0xE4, 0x27, 0x27, - 0x27, 0x27, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0xB9, 0x56, 0x40, 0x50, 0x9A, 0x75, 0xE3, 0xE3, - 0xE3, 0xD9, 0x8D, 0xAA, 0xD9, 0xA8, 0xB2, 0xDC, - 0xB2, 0x8D, 0x84, 0xEA, 0xB1, 0xEB, 0x54, 0x29, - 0x28, 0x2C, 0x2A, 0x28, 0x2B, 0x78, 0xCC, 0x58, - 0xCB, 0x20, 0x20, 0x29, 0x39, 0x39, 0x2C, 0x25, - 0x29, 0x2C, 0x39, 0xBB, 0xD9, 0xD9, 0x9D, 0x9D, - 0xB2, 0xB1, 0xD4, 0xDB, 0xB1, 0x9D, 0xD4, 0xEA, - 0xB1, 0x8D, 0xD8, 0x8E, 0x8F, 0xAA, 0x27, 0x27, - 0x27, 0x3D, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, - 0x56, 0x56, 0x47, 0xE4, 0xA6, 0x75, 0xAA, 0xA8, - 0x9C, 0x9C, 0xE1, 0x9C, 0x9C, 0x8E, 0xD8, 0x9D, - 0xA9, 0xDB, 0xA9, 0xDC, 0xD8, 0xDA, 0xD4, 0x2B, - 0x20, 0x2C, 0x28, 0x2A, 0x28, 0x63, 0x31, 0x58, - 0xCB, 0x24, 0x20, 0x2B, 0x2C, 0x39, 0x6B, 0x21, - 0x39, 0x6B, 0x2C, 0xC0, 0xE0, 0xB1, 0xB2, 0x9D, - 0x8E, 0xD8, 0xE0, 0xD9, 0x84, 0xDB, 0xD8, 0xB1, - 0x8E, 0xB2, 0xE2, 0x9C, 0x83, 0x9E, 0xBC, 0x3D, - 0xD3, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xB9, - 0x56, 0x4F, 0x27, 0x61, 0xA6, 0x9B, 0xE3, 0xA9, - 0xE9, 0xD4, 0xDA, 0xDB, 0x8E, 0xE1, 0xE9, 0x8E, - 0xD4, 0xA8, 0xE0, 0x84, 0xE8, 0xB1, 0xDC, 0x9D, - 0x20, 0x29, 0x29, 0x2B, 0x2C, 0x54, 0x78, 0xCC, - 0x78, 0x33, 0x2A, 0x20, 0x29, 0x39, 0x50, 0x2A, - 0x6B, 0x8B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xA9, - 0xB2, 0xDC, 0x8E, 0xDC, 0xE1, 0xDA, 0xA9, 0x8E, - 0xEA, 0xE2, 0x83, 0xE8, 0x8E, 0x83, 0xE2, 0xED, - 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, - 0xC9, 0x27, 0x27, 0xE4, 0xA6, 0x9B, 0xD5, 0xA8, - 0xD4, 0xB2, 0xD8, 0xDA, 0xD9, 0xE8, 0xE9, 0xE8, - 0xD8, 0xB1, 0xDA, 0xB2, 0xE9, 0x8E, 0xEC, 0xDA, - 0x22, 0x20, 0x39, 0x2B, 0x39, 0x24, 0xC4, 0x30, - 0x30, 0x54, 0x22, 0x29, 0x29, 0x39, 0x48, 0x2C, - 0x39, 0x6B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xB2, - 0xB2, 0x8E, 0xA9, 0xD8, 0xDA, 0xB1, 0xA9, 0xDA, - 0x9C, 0xDC, 0x8E, 0xD4, 0xE8, 0xE8, 0x8F, 0x9B, - 0x4F, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9, - 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x6B, - 0x27, 0x27, 0x27, 0xD7, 0xDE, 0xAA, 0xE3, 0xA8, - 0xB2, 0xD5, 0xE5, 0x90, 0xE2, 0xA9, 0xE9, 0xB2, - 0xDA, 0xB2, 0xE1, 0xB2, 0xE9, 0x8E, 0xDA, 0xDF, - 0x78, 0x2A, 0x2C, 0x2A, 0x6B, 0x28, 0x23, 0x54, - 0x63, 0xC4, 0x33, 0x28, 0x2C, 0x39, 0x47, 0x39, - 0x28, 0x2C, 0x29, 0xBB, 0x8D, 0x83, 0xE9, 0xD4, - 0xB2, 0xE9, 0xE9, 0xE8, 0xD4, 0xD8, 0xD4, 0xA9, - 0xDA, 0xB2, 0xE9, 0xA8, 0xB2, 0xA8, 0xD5, 0xAA, - 0xC6, 0x56, 0x56, 0x56, 0x56, 0x56, 0xB9, 0x56, - 0x56, 0x56, 0x56, 0x56, 0x56, 0xC9, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xB8, 0xB4, 0x9B, 0xE3, 0x8E, - 0x9D, 0x8E, 0xB2, 0xE8, 0xE8, 0x8E, 0xB2, 0xDA, - 0xB2, 0x8E, 0xEC, 0xB2, 0x8E, 0xB2, 0xBB, 0x58, - 0xAF, 0x33, 0x50, 0x39, 0x6B, 0x39, 0x29, 0x20, - 0x33, 0x30, 0x78, 0x23, 0x6B, 0x6B, 0x48, 0x6B, - 0x2B, 0x2A, 0x29, 0xBB, 0xE5, 0x9C, 0xB1, 0xB2, - 0xE5, 0x84, 0x8E, 0x9C, 0x84, 0xB2, 0xB2, 0x9D, - 0x84, 0xDF, 0xA9, 0x84, 0x8E, 0xA8, 0xE3, 0x9B, - 0xA6, 0xD7, 0x80, 0x4F, 0x56, 0x56, 0x56, 0x4F, - 0x4F, 0x4F, 0x4F, 0x2A, 0x2D, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xB8, 0xB4, 0xAA, 0xD5, 0xA9, - 0x9D, 0xB2, 0x90, 0xEA, 0xE9, 0xE2, 0xE1, 0x8E, - 0xB2, 0x9D, 0x8E, 0xB1, 0xA7, 0xEE, 0x63, 0xD1, - 0x2E, 0xCC, 0x28, 0x48, 0x8B, 0x47, 0x6B, 0x28, - 0x23, 0x78, 0x6C, 0x54, 0x29, 0x50, 0x50, 0x6B, - 0x23, 0x20, 0xBB, 0xBC, 0xBB, 0x8D, 0xE3, 0xDF, - 0x9C, 0xA9, 0x8D, 0xA8, 0xD9, 0x90, 0x9D, 0xA9, - 0xDC, 0xA9, 0x83, 0xB2, 0xA9, 0xD4, 0xE3, 0x9B, - 0x8C, 0xEF, 0x27, 0x27, 0x27, 0x3C, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0x84, - 0x9D, 0x84, 0x90, 0xB1, 0xA9, 0x9C, 0xD9, 0xB1, - 0xB2, 0xEA, 0xBB, 0x51, 0x24, 0x30, 0x30, 0x42, - 0x66, 0x58, 0x24, 0x48, 0x50, 0x3F, 0x20, 0x25, - 0x22, 0x60, 0x34, 0x30, 0x20, 0x8B, 0x8B, 0x39, - 0x54, 0x24, 0x2B, 0xC0, 0xC0, 0xC0, 0xBB, 0x9B, - 0xBC, 0xAA, 0xAA, 0xE3, 0xE3, 0x9C, 0xB2, 0xD4, - 0x83, 0xD8, 0xE8, 0x83, 0x84, 0xE8, 0xE5, 0x75, - 0x9A, 0xF0, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0xA8, - 0xA9, 0xD8, 0x8E, 0xEA, 0xA8, 0x9C, 0xD9, 0xE0, - 0xC0, 0x5E, 0x2C, 0x20, 0x54, 0x60, 0x30, 0x66, - 0xB6, 0xCC, 0x63, 0x3F, 0x8B, 0x28, 0x22, 0x33, - 0x23, 0x31, 0xAF, 0x31, 0x22, 0x6B, 0x6B, 0x29, - 0x30, 0x54, 0x22, 0x89, 0xBA, 0xED, 0xA6, 0x8C, - 0xB4, 0xC0, 0xB4, 0x75, 0x75, 0x9B, 0x9B, 0xE5, - 0xA9, 0xD5, 0x8E, 0x8E, 0x9C, 0xE3, 0x75, 0x8C, - 0xC8, 0xF1, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xF1, 0x9A, 0xB4, 0x9B, 0xE3, - 0xE3, 0xA8, 0xE3, 0xE5, 0xAA, 0xBC, 0xC0, 0x9A, - 0x26, 0x29, 0x20, 0x24, 0x63, 0x60, 0x54, 0x43, - 0x34, 0xCB, 0x30, 0x39, 0x2C, 0x20, 0x24, 0x54, - 0x22, 0x34, 0x34, 0x31, 0x24, 0x3F, 0x2C, 0x2B, - 0x31, 0x30, 0x25, 0x2A, 0x6B, 0x29, 0x20, 0xF2, - 0xBA, 0xBF, 0xC8, 0x9A, 0xA6, 0xA6, 0x8C, 0xB4, - 0x9B, 0xAA, 0xAA, 0xAA, 0x9B, 0x75, 0xDE, 0xBF, - 0x81, 0xEF, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, - 0x27, 0x27, 0x27, 0xEF, 0xBA, 0x9A, 0xB4, 0x75, - 0x9B, 0x9B, 0x9B, 0xC0, 0xB4, 0x9A, 0xA5, 0xC4, - 0x30, 0x28, 0x22, 0x33, 0x30, 0x30, 0x23, 0x34, - 0x31, 0x30, 0xC4, 0x2C, 0x2B, 0x22, 0x33, 0x63, - 0x21, 0x58, 0x6C, 0x60, 0x25, 0x39, 0x28, 0x2B, - 0xCC, 0x6C, 0x63, 0x20, 0x6B, 0x28, 0x2B, 0x20, - 0x63, 0x43, 0xF3, 0xEF, 0xF0, 0x81, 0xBA, 0xF4, - 0xF4, 0xA6, 0xDE, 0x8C, 0xA6, 0x9A, 0xBA, 0x81, - 0xB0, 0xE4, 0xA1, 0x20, 0x20, 0x23, 0x31, 0xC4, - 0x30, 0x24, 0x33, 0x31, 0x31, 0x60, 0x43, 0x35, - 0x35, 0x55, 0x6C, 0xEF, 0x81, 0xC8, 0x9A, 0xA6, - 0xB4, 0xB4, 0x8C, 0xA6, 0xBA, 0x68, 0x30, 0x30, - 0x30, 0x2B, 0x25, 0x54, 0xC4, 0x54, 0x24, 0x78, - 0x63, 0x63, 0x30, 0x29, 0x21, 0x24, 0x54, 0x63, - 0x23, 0x34, 0xCB, 0x30, 0x25, 0x39, 0x20, 0x20, - 0x58, 0x34, 0x60, 0x23, 0x6B, 0x29, 0x28, 0x20, - 0x22, 0xB6, 0x42, 0xB6, 0x58, 0x54, 0xF5, 0xD7, - 0xA5, 0xBA, 0xBA, 0xBA, 0xBA, 0x81, 0xA5, 0xF1, - 0xE4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x31, 0x60, - 0x54, 0x28, 0x2B, 0x22, 0x33, 0x30, 0x43, 0x35, - 0x66, 0xD1, 0x34, 0xE4, 0xEF, 0x81, 0xC8, 0x9A, - 0x9A, 0xC8, 0xC8, 0x81, 0xF6, 0x31, 0x63, 0x31, - 0x78, 0x2B, 0x54, 0x63, 0x54, 0x24, 0x23, 0x54, - 0x63, 0x54, 0x63, 0x2C, 0x23, 0x33, 0x63, 0x54, - 0x25, 0x31, 0x78, 0x30, 0x25, 0x3F, 0x20, 0x20, - 0xAF, 0x58, 0xCC, 0x33, 0x39, 0x29, 0x29, 0x2A, - 0x29, 0x58, 0x43, 0x42, 0xD1, 0xCB, 0x2C, 0x2C, - 0x37, 0xCD, 0xEF, 0xB0, 0xF0, 0xB0, 0xEF, 0xE4, - 0x63, 0x20, 0x20, 0x2C, 0x2C, 0x21, 0xCB, 0x78, - 0x54, 0x39, 0x39, 0x28, 0x2B, 0x28, 0x2B, 0xCB, - 0x55, 0xB6, 0xD1, 0x28, 0xE4, 0xD7, 0xB8, 0xF0, - 0xA5, 0xB0, 0xEF, 0x26, 0x23, 0x54, 0x31, 0x58, - 0xCB, 0x20, 0x63, 0x63, 0x25, 0x2B, 0x54, 0x78, - 0x30, 0x63, 0x54, 0x28, 0x33, 0x63, 0x63, 0x33, - 0x54, 0x78, 0xC4, 0x30, 0x24, 0x2C, 0x22, 0x22, - 0x55, 0x55, 0x34, 0x30, 0x28, 0x2C, 0x29, 0x29, - 0x28, 0x30, 0xB6, 0x42, 0x43, 0x55, 0x22, 0x29, - 0x2C, 0x2B, 0x2B, 0x3F, 0xE4, 0xE4, 0x43, 0x66, - 0x30, 0x23, 0x24, 0x2A, 0x28, 0x2B, 0x54, 0x63, - 0x33, 0x39, 0x28, 0x20, 0x20, 0x20, 0x2B, 0x31, - 0x30, 0xD1, 0x43, 0x30, 0x39, 0x28, 0xE4, 0xE4, - 0xD7, 0xF5, 0x2B, 0x6B, 0x20, 0x30, 0x34, 0xD1, - 0x60, 0x23, 0x63, 0x54, 0x22, 0x47, 0x60, 0xCB, - 0xC4, 0xC4, 0x25, 0x22, 0x54, 0xC4, 0x63, 0x23, - 0xC4, 0xC4, 0x63, 0xC4, 0x23, 0x2A, 0x24, 0x22, - 0x55, 0x55, 0xAF, 0x6C, 0x22, 0x39, 0x2C, 0x39, - 0x28, 0x23, 0xD1, 0x43, 0x42, 0x8A, 0x63, 0x39, - 0x39, 0x2A, 0x20, 0x6B, 0x33, 0xCC, 0xD1, 0xB6, - 0x30, 0x24, 0x54, 0x63, 0x31, 0xCC, 0xCC, 0xCB, - 0xC4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x39, 0x30, - 0x30, 0x6C, 0x43, 0x43, 0x6C, 0x63, 0x25, 0x24, - 0x63, 0x63, 0x63, 0x25, 0x63, 0xCC, 0xD1, 0x34, - 0x63, 0x25, 0x54, 0x25, 0x2A, 0x28, 0x31, 0xCB, - 0x63, 0x78, 0x24, 0x33, 0xC4, 0xC4, 0x33, 0x2C, - 0xC4, 0x54, 0x54, 0x30, 0x21, 0x22, 0x25, 0x23, - 0x55, 0x55, 0xD1, 0x58, 0x33, 0x6B, 0x2C, 0x39, - 0x39, 0x39, 0x34, 0x43, 0x42, 0x43, 0xCC, 0x2B, - 0x28, 0x29, 0x20, 0x28, 0x21, 0x30, 0xCC, 0xAF, - 0x54, 0x23, 0xC4, 0x54, 0x58, 0x2E, 0x35, 0x42, - 0x55, 0x54, 0x8B, 0x2A, 0x20, 0x20, 0x28, 0x22, - 0x78, 0x30, 0xD1, 0x43, 0x44, 0x6C, 0xC4, 0xC4, - 0x60, 0x31, 0x31, 0x63, 0x6C, 0xAF, 0xCC, 0xCB, - 0x24, 0x25, 0x33, 0x23, 0x2C, 0x24, 0x31, 0x30, - 0x63, 0xC4, 0x21, 0x54, 0x30, 0x63, 0x24, 0x2A, - 0x54, 0x63, 0x54, 0xC4, 0x2B, 0x24, 0x33, 0x24, - 0x34, 0x55, 0xD1, 0x55, 0x30, 0x28, 0x29, 0x39, - 0x39, 0x8B, 0x63, 0x55, 0x42, 0x66, 0xB6, 0x25, - 0x29, 0x29, 0x29, 0x28, 0x2A, 0x54, 0x78, 0x6C, - 0x23, 0x20, 0x25, 0x30, 0xCB, 0x62, 0x35, 0x35, - 0x35, 0x44, 0x24, 0x6B, 0x29, 0x20, 0x2A, 0x39, - 0x28, 0x63, 0x34, 0xB6, 0x34, 0xCB, 0x63, 0x30, - 0x31, 0x31, 0x30, 0x30, 0xCC, 0x60, 0x63, 0xC4, - 0x20, 0x33, 0x25, 0x20, 0x48, 0x33, 0x30, 0x54, - 0x78, 0x54, 0x2B, 0x63, 0x30, 0x63, 0x23, 0x22, - 0x63, 0x63, 0x63, 0x33, 0x28, 0x25, 0x54, 0x24, - 0x78, 0xAF, 0xD1, 0xD1, 0xCC, 0x22, 0x39, 0x39, - 0x2C, 0x3F, 0x2B, 0x34, 0xB6, 0x43, 0x43, 0xC4, - 0x2B, 0x28, 0x39, 0x50, 0x2C, 0x24, 0x63, 0x78, - 0x21, 0x2C, 0x2A, 0x23, 0x54, 0xD1, 0x35, 0x35, - 0x35, 0x35, 0x55, 0x22, 0x39, 0x2C, 0x2C, 0x2C, - 0x20, 0x30, 0xCC, 0x6C, 0xCB, 0x30, 0x54, 0x30, - 0x78, 0x63, 0x78, 0x30, 0x54, 0x78, 0x30, 0x23, - 0x2B, 0x33, 0x24, 0x28, 0x39, 0x24, 0x54, 0x30, - 0x78, 0x33, 0x25, 0xC4, 0xC4, 0x33, 0x39, 0x25, - 0xC4, 0x63, 0xC4, 0x24, 0x20, 0x54, 0x54, 0x25, - 0x63, 0xCC, 0xD1, 0xB6, 0x55, 0x54, 0x39, 0x29, - 0x39, 0x2C, 0x6B, 0x30, 0xAF, 0xB6, 0xB6, 0x60, - 0x22, 0x2A, 0x2C, 0x39, 0x2C, 0x21, 0x54, 0x63, - 0x21, 0x50, 0x2C, 0x2C, 0x2B, 0x25, 0x62, 0x35, - 0x35, 0x35, 0x35, 0xCC, 0x2B, 0x29, 0x2B, 0x20, - 0x23, 0x25, 0xC4, 0x30, 0xC4, 0x63, 0x63, 0x63, - 0x63, 0x33, 0x24, 0x31, 0x31, 0x31, 0x54, 0x28, - 0x24, 0x25, 0x22, 0x6B, 0x28, 0x24, 0xC4, 0x78, - 0x30, 0x24, 0x63, 0xC4, 0x54, 0x23, 0x29, 0x63, - 0xC4, 0x54, 0xC4, 0x21, 0x24, 0x54, 0x54, 0x25, - 0x30, 0xCB, 0xD1, 0xB6, 0x55, 0x63, 0x28, 0x29, - 0x39, 0x39, 0x48, 0x33, 0x58, 0x44, 0xB6, 0x60, - 0x24, 0x20, 0x2B, 0x28, 0x2A, 0x22, 0x54, 0x63, - 0x21, 0x48, 0x2A, 0x2B, 0x39, 0x21, 0xB6, 0x35, - 0x35, 0x35, 0x35, 0x42, 0x23, 0x29, 0x2A, 0x2B, - 0x23, 0x25, 0x54, 0x54, 0x54, 0x63, 0x63, 0x30, - 0x25, 0x2B, 0x31, 0x31, 0x31, 0x31, 0x21, 0x2C, - 0x33, 0x25, 0x21, 0x39, 0x20, 0x25, 0x30, 0x78, - 0xC4, 0x23, 0xC4, 0x30, 0x54, 0x20, 0x28, 0x63, - 0x63, 0x63, 0x63, 0x20, 0x25, 0x54, 0x54, 0x20, -}; - -unsigned char linux_logo_bw[] __initdata = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, - 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, - 0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, - 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9, - 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7, - 0x99, 0xF9, 0xC2, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF9, 0xF3, 0xBC, 0xF9, 0x90, 0x00, 0x1F, 0xFF, - 0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xA0, 0x00, - 0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9, - 0x83, 0xE0, 0x2F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, - 0x19, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x03, 0xF0, 0x3F, 0xF7, 0x8F, 0xFF, - 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0x7F, 0xF7, - 0xC7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, - 0x6F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, - 0x01, 0xF8, 0x7F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, - 0xF9, 0xC0, 0x21, 0xD8, 0x7F, 0xE7, 0xEF, 0xFF, - 0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0x7B, 0xFF, - 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4, - 0x7B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C, - 0xC0, 0x7C, 0x79, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, - 0xE3, 0x80, 0x00, 0x7C, 0x7C, 0xFF, 0xCF, 0xFF, - 0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0x77, 0xFF, - 0xDF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F, - 0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, - 0x00, 0x3F, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, - 0x1E, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x3F, 0xFF, - 0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1F, 0x9F, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1F, - 0x8F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, - 0x00, 0x0F, 0xC7, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, - 0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xF9, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x07, 0xFB, 0xF3, - 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x07, - 0xFD, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00, - 0x00, 0x03, 0xFE, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, - 0xF0, 0x00, 0x00, 0x03, 0xFE, 0x1F, 0xFF, 0xFF, - 0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xBF, - 0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00, - 0xFE, 0xBF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00, - 0x00, 0x00, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7, - 0xC0, 0x00, 0x00, 0x01, 0xFE, 0xBF, 0xFF, 0xFF, - 0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x9F, - 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01, - 0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, - 0x00, 0x01, 0xFE, 0x87, 0xFF, 0xFF, 0xFF, 0x9F, - 0x80, 0x00, 0x00, 0x01, 0xFD, 0x33, 0xFF, 0xFF, - 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0xF3, - 0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03, - 0x8B, 0xF9, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00, - 0x00, 0x02, 0x27, 0xF8, 0xFF, 0xFF, 0xFF, 0x99, - 0x80, 0x00, 0x00, 0x00, 0x07, 0xF8, 0xFF, 0xFF, - 0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0x8F, 0xF8, - 0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00, - 0xE3, 0xF8, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00, - 0x00, 0x00, 0xF8, 0x78, 0xFF, 0xFF, 0xC0, 0x40, - 0x38, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0xFF, - 0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x20, - 0x7F, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x78, 0x10, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, - 0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF, - 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04, - 0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10, - 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80, - 0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF, - 0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, - 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0, - 0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40, - 0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00, - 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF, - 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40, - 0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0, - 0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF, - 0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F, - 0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF, - 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F, - 0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F, - 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07, - 0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -}; - -/* Painted by Johnny Stenback */ - -unsigned char *linux_serial_image __initdata = "\n" -" .u$e.\n" -" .$$$$$:S\n" -" $\"*$/\"*$$\n" -" $.`$ . ^F\n" -" 4k+#+T.$F\n" -" 4P+++\"$\"$\n" -" :R\"+ t$$B\n" -" ___# $$$\n" -" | | R$$k\n" -" dd. | Linux $!$\n" -" ddd | Sparc $9$F\n" -" '!!!!!$ !!#!`\n" -" !!!!!* .!!!!!`\n" -"'!!!!!!!W..e$$!!!!!!` %s\n" -" \"~^^~ ^~~^\n" -"\n"; diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h --- v2.1.36/linux/include/asm-sparc64/processor.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-sparc64/processor.h Sun Apr 27 15:08:03 1997 @@ -1,4 +1,4 @@ -/* $Id: processor.h,v 1.21 1997/04/14 17:05:18 jj Exp $ +/* $Id: processor.h,v 1.23 1997/04/26 22:52:34 davem Exp $ * include/asm-sparc64/processor.h * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -71,7 +71,7 @@ #define SPARC_FLAG_32BIT 0x8 /* task is older 32-bit binary */ #define INIT_MMAP { &init_mm, 0xfffff80000000000, 0xfffff80001000000, \ - PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC } + PAGE_SHARED , VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } #define INIT_TSS { \ /* FPU regs */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ diff -u --recursive --new-file v2.1.36/linux/include/asm-sparc64/termbits.h linux/include/asm-sparc64/termbits.h --- v2.1.36/linux/include/asm-sparc64/termbits.h Mon Apr 14 16:28:24 1997 +++ linux/include/asm-sparc64/termbits.h Sun Apr 27 15:08:03 1997 @@ -148,7 +148,13 @@ #define HUPCL 0x00000400 #define CLOCAL 0x00000800 #define CBAUDEX 0x00001000 +/* We'll never see these speeds with the Zilogs, but for completeness... */ #define B57600 0x00001001 +#define B115200 0x00001002 +#define B230400 0x00001003 +#define B460800 0x00001004 +/* This is what we can do with the Zilogs. */ +#define B76800 0x00001005 #define CIBAUD 0x100f0000 /* input baud rate (not used) */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff -u --recursive --new-file v2.1.36/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h --- v2.1.36/linux/include/linux/affs_fs.h Thu Feb 6 02:58:49 1997 +++ linux/include/linux/affs_fs.h Thu May 1 12:05:02 1997 @@ -22,9 +22,9 @@ struct DateStamp { - __u32 ds_Days; - __u32 ds_Minute; - __u32 ds_Tick; + u32 ds_Days; + u32 ds_Minute; + u32 ds_Tick; }; @@ -32,66 +32,58 @@ /* amigaffs.c */ -extern int affs_get_key_entry(int bsize, void *data, int entry_pos); -extern int affs_find_next_hash_entry(int bsize, void *dir_data, int *hash_pos); -extern int affs_get_file_name(int bsize, void *fh_data, char **name); -extern unsigned int affs_checksum_block(int bsize, void *data, int *ptype, int *stype); -extern void affs_fix_checksum(int bsize, void *data, int cspos); -extern void secs_to_datestamp(int secs, struct DateStamp *ds); -extern int prot_to_mode(unsigned int prot); -extern unsigned int mode_to_prot(int mode); -extern int affs_fix_hash_pred(struct inode *startino, int startoffset, - int key, int newkey); -extern int affs_fix_link_pred(struct inode *startino, int key, int newkey); +extern int affs_get_key_entry(int bsize, void *data, int entry_pos); +extern int affs_get_file_name(int bsize, void *fh_data, char **name); +extern u32 affs_checksum_block(int bsize, void *data, s32 *ptype, s32 *stype); +extern void affs_fix_checksum(int bsize, void *data, int cspos); +extern void secs_to_datestamp(time_t secs, struct DateStamp *ds); +extern int prot_to_mode(unsigned int prot); +extern u32 mode_to_prot(int mode); +extern int affs_fix_hash_pred(struct inode *startino, int startoffset, + s32 key, s32 newkey); +extern int affs_fix_link_pred(struct inode *startino, s32 key, s32 newkey); +extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...); +extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...); /* bitmap. c */ -extern int affs_count_free_blocks(struct super_block *s); -extern int affs_count_free_bits(int blocksize, const char *data); -extern void affs_free_block(struct super_block *sb, int block); -extern int affs_new_header(struct inode *inode); -extern int affs_new_data(struct inode *inode); -extern void affs_make_zones(struct super_block *sb); +extern int affs_count_free_blocks(struct super_block *s); +extern int affs_count_free_bits(int blocksize, const char *data); +extern void affs_free_block(struct super_block *sb, s32 block); +extern s32 affs_new_header(struct inode *inode); +extern s32 affs_new_data(struct inode *inode); +extern void affs_make_zones(struct super_block *sb); /* namei.c */ -extern int affs_hash_name(const char *name, int len, int intl, int hashsize); -extern int affs_lookup(struct inode *dir,const char *name, int len, - struct inode **result); -extern int affs_unlink(struct inode *dir, const char *name, int len); -extern int affs_create(struct inode *dir, const char *name, int len, int mode, - struct inode **result); -extern int affs_mkdir(struct inode *dir, const char *name, int len, int mode); -extern int affs_rmdir(struct inode *dir, const char *name, int len); -extern int affs_link(struct inode *oldinode, struct inode *dir, - const char *name, int len); -extern int affs_symlink(struct inode *dir, const char *name, int len, - const char *symname); -extern int affs_fixup(struct buffer_head *bh, struct inode *inode); -extern int affs_rename(struct inode *old_dir, const char *old_name, int old_len, - struct inode *new_dir, const char *new_name, int new_len, - int must_be_dir); +extern int affs_hash_name(const char *name, int len, int intl, int hashsize); +extern int affs_lookup(struct inode *dir,const char *name, int len, + struct inode **result); +extern int affs_unlink(struct inode *dir, const char *name, int len); +extern int affs_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); +extern int affs_mkdir(struct inode *dir, const char *name, int len, int mode); +extern int affs_rmdir(struct inode *dir, const char *name, int len); +extern int affs_link(struct inode *oldinode, struct inode *dir, + const char *name, int len); +extern int affs_symlink(struct inode *dir, const char *name, int len, + const char *symname); +extern int affs_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len, + int must_be_dir); /* inode.c */ extern struct buffer_head *affs_bread(kdev_t dev, int block, int size); extern void affs_brelse(struct buffer_head *buf); -extern void affs_put_super(struct super_block *); -extern int affs_parent_ino(struct inode *dir); -extern struct super_block *affs_read_super(struct super_block *,void *, int); -extern void affs_statfs(struct super_block *, struct statfs *, int bufsiz); -extern void affs_read_inode(struct inode *); -extern void affs_write_inode(struct inode *); -extern int affs_notify_change(struct inode *inode, struct iattr *attr); -extern void affs_put_inode(struct inode *); +extern unsigned long affs_parent_ino(struct inode *dir); extern struct inode *affs_new_inode(const struct inode *dir); -extern int affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode, - const char *name, int len, int type); +extern int affs_add_entry(struct inode *dir, struct inode *link, + struct inode *inode, const char *name, + int len, s32 type); /* file.c */ -extern int affs_bmap(struct inode *inode, int block); -extern struct buffer_head *affs_getblock(struct inode *inode, int block); extern void affs_truncate(struct inode *); extern void affs_truncate_ofs(struct inode *); diff -u --recursive --new-file v2.1.36/linux/include/linux/affs_fs_i.h linux/include/linux/affs_fs_i.h --- v2.1.36/linux/include/linux/affs_fs_i.h Fri Dec 27 02:28:30 1996 +++ linux/include/linux/affs_fs_i.h Thu May 1 12:05:02 1997 @@ -9,19 +9,19 @@ struct key_cache { struct timeval kc_lru_time; /* Last time this cache was used */ - int kc_first; /* First cached key */ - int kc_last; /* Last cached key */ - int kc_this_key; /* Key of extension block this data block keys are from */ + s32 kc_first; /* First cached key */ + s32 kc_last; /* Last cached key */ + s32 kc_this_key; /* Key of extension block this data block keys are from */ int kc_this_seq; /* Sequence number of this extension block */ - int kc_next_key; /* Key of next extension block */ - int kc_keys[AFFS_KCSIZE]; /* Key cache */ + s32 kc_next_key; /* Key of next extension block */ + s32 kc_keys[AFFS_KCSIZE]; /* Key cache */ }; #define EC_SIZE (PAGE_SIZE - 4 * sizeof(struct key_cache) - 4) / 4 struct ext_cache { struct key_cache kc[4]; /* The 4 key caches */ - __s32 ec[EC_SIZE]; /* Keys of assorted extension blocks */ + s32 ec[EC_SIZE]; /* Keys of assorted extension blocks */ int max_ext; /* Index of last known extension block */ }; @@ -29,18 +29,18 @@ * affs fs inode data in memory */ struct affs_inode_info { - __u32 i_protect; /* unused attribute bits */ - __s32 i_parent; /* parent ino */ - __s32 i_original; /* if != 0, this is the key of the original */ - __s32 i_data[AFFS_MAX_PREALLOC]; /* preallocated blocks */ - struct ext_cache *i_ec; /* Cache gets allocated dynamically */ - int i_cache_users; /* Cache cannot be freed while > 0 */ - int i_lastblock; /* last allocated block */ - short i_pa_cnt; /* number of preallocated blocks */ - short i_pa_next; /* Index of next block in i_data[] */ - short i_pa_last; /* Index of next free slot in i_data[] */ - short i_zone; /* write zone */ - unsigned char i_hlink; /* This is a fake */ + u32 i_protect; /* unused attribute bits */ + s32 i_parent; /* parent ino */ + s32 i_original; /* if != 0, this is the key of the original */ + s32 i_data[AFFS_MAX_PREALLOC]; /* preallocated blocks */ + struct ext_cache *i_ec; /* Cache gets allocated dynamically */ + int i_cache_users; /* Cache cannot be freed while > 0 */ + int i_lastblock; /* last allocated block */ + short i_pa_cnt; /* number of preallocated blocks */ + short i_pa_next; /* Index of next block in i_data[] */ + short i_pa_last; /* Index of next free slot in i_data[] */ + short i_zone; /* write zone */ + unsigned char i_hlink; /* This is a fake */ unsigned char i_pad; }; diff -u --recursive --new-file v2.1.36/linux/include/linux/affs_fs_sb.h linux/include/linux/affs_fs_sb.h --- v2.1.36/linux/include/linux/affs_fs_sb.h Wed Jul 24 23:08:28 1996 +++ linux/include/linux/affs_fs_sb.h Thu May 1 12:05:02 1997 @@ -15,8 +15,8 @@ struct affs_bm_info { struct buffer_head *bm_bh; /* Buffer head if loaded (bm_count > 0) */ - int bm_firstblk; /* Block number of first bit in this map */ - int bm_key; /* Disk block number */ + s32 bm_firstblk; /* Block number of first bit in this map */ + s32 bm_key; /* Disk block number */ int bm_count; /* Usage counter */ }; @@ -37,11 +37,11 @@ struct affs_sb_info { int s_partition_size; /* Partition size in blocks. */ - int s_root_block; /* FFS root block number. */ + s32 s_root_block; /* FFS root block number. */ int s_hashsize; /* Size of hash table. */ unsigned long s_flags; /* See below. */ - short s_uid; /* uid to override */ - short s_gid; /* gid to override */ + s16 s_uid; /* uid to override */ + s16 s_gid; /* gid to override */ umode_t s_mode; /* mode to override */ int s_reserved; /* Number of reserved blocks. */ struct buffer_head *s_root_bh; /* Cached root block. */ diff -u --recursive --new-file v2.1.36/linux/include/linux/affs_hardblocks.h linux/include/linux/affs_hardblocks.h --- v2.1.36/linux/include/linux/affs_hardblocks.h Sun May 19 05:22:20 1996 +++ linux/include/linux/affs_hardblocks.h Thu May 1 12:05:02 1997 @@ -4,59 +4,59 @@ /* Just the needed definitions for the RDB of an Amiga HD. */ struct RigidDiskBlock { - __u32 rdb_ID; - __u32 rdb_SummedLongs; - __s32 rdb_ChkSum; - __u32 rdb_HostID; - __u32 rdb_BlockBytes; - __u32 rdb_Flags; - __u32 rdb_BadBlockList; - __u32 rdb_PartitionList; - __u32 rdb_FileSysHeaderList; - __u32 rdb_DriveInit; - __u32 rdb_Reserved1[6]; - __u32 rdb_Cylinders; - __u32 rdb_Sectors; - __u32 rdb_Heads; - __u32 rdb_Interleave; - __u32 rdb_Park; - __u32 rdb_Reserved2[3]; - __u32 rdb_WritePreComp; - __u32 rdb_ReducedWrite; - __u32 rdb_StepRate; - __u32 rdb_Reserved3[5]; - __u32 rdb_RDBBlocksLo; - __u32 rdb_RDBBlocksHi; - __u32 rdb_LoCylinder; - __u32 rdb_HiCylinder; - __u32 rdb_CylBlocks; - __u32 rdb_AutoParkSeconds; - __u32 rdb_HighRDSKBlock; - __u32 rdb_Reserved4; + u32 rdb_ID; + u32 rdb_SummedLongs; + s32 rdb_ChkSum; + u32 rdb_HostID; + u32 rdb_BlockBytes; + u32 rdb_Flags; + u32 rdb_BadBlockList; + u32 rdb_PartitionList; + u32 rdb_FileSysHeaderList; + u32 rdb_DriveInit; + u32 rdb_Reserved1[6]; + u32 rdb_Cylinders; + u32 rdb_Sectors; + u32 rdb_Heads; + u32 rdb_Interleave; + u32 rdb_Park; + u32 rdb_Reserved2[3]; + u32 rdb_WritePreComp; + u32 rdb_ReducedWrite; + u32 rdb_StepRate; + u32 rdb_Reserved3[5]; + u32 rdb_RDBBlocksLo; + u32 rdb_RDBBlocksHi; + u32 rdb_LoCylinder; + u32 rdb_HiCylinder; + u32 rdb_CylBlocks; + u32 rdb_AutoParkSeconds; + u32 rdb_HighRDSKBlock; + u32 rdb_Reserved4; char rdb_DiskVendor[8]; char rdb_DiskProduct[16]; char rdb_DiskRevision[4]; char rdb_ControllerVendor[8]; char rdb_ControllerProduct[16]; char rdb_ControllerRevision[4]; - __u32 rdb_Reserved5[10]; + u32 rdb_Reserved5[10]; }; #define IDNAME_RIGIDDISK 0x5244534B /* "RDSK" */ struct PartitionBlock { - __u32 pb_ID; - __u32 pb_SummedLongs; - __s32 pb_ChkSum; - __u32 pb_HostID; - __u32 pb_Next; - __u32 pb_Flags; - __u32 pb_Reserved1[2]; - __u32 pb_DevFlags; - __u8 pb_DriveName[32]; - __u32 pb_Reserved2[15]; - __u32 pb_Environment[17]; - __u32 pb_EReserved[15]; + u32 pb_ID; + u32 pb_SummedLongs; + s32 pb_ChkSum; + u32 pb_HostID; + u32 pb_Next; + u32 pb_Flags; + u32 pb_Reserved1[2]; + u32 pb_DevFlags; + u8 pb_DriveName[32]; + u32 pb_Reserved2[15]; + u32 pb_Environment[17]; + u32 pb_EReserved[15]; }; #define IDNAME_PARTITION 0x50415254 /* "PART" */ diff -u --recursive --new-file v2.1.36/linux/include/linux/amigaffs.h linux/include/linux/amigaffs.h --- v2.1.36/linux/include/linux/amigaffs.h Sun May 19 05:22:20 1996 +++ linux/include/linux/amigaffs.h Thu May 1 12:05:02 1997 @@ -56,131 +56,131 @@ struct root_front { - __s32 primary_type; - __s32 spare1[2]; - __s32 hash_size; - __s32 spare2; - __u32 checksum; - __s32 hashtable[0]; + s32 primary_type; + s32 spare1[2]; + s32 hash_size; + s32 spare2; + u32 checksum; + s32 hashtable[0]; }; struct root_end { - __s32 bm_flag; - __s32 bm_keys[25]; - __s32 bm_extend; + s32 bm_flag; + s32 bm_keys[25]; + s32 bm_extend; struct DateStamp dir_altered; - __u8 disk_name[40]; + u8 disk_name[40]; struct DateStamp disk_altered; struct DateStamp disk_made; - __s32 spare1[3]; - __s32 secondary_type; + s32 spare1[3]; + s32 secondary_type; }; struct dir_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __u32 checksum; - __s32 hashtable[0]; + s32 primary_type; + s32 own_key; + s32 spare1[3]; + u32 checksum; + s32 hashtable[0]; }; struct dir_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __s32 spare2; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + s32 spare2; + u8 comment[92]; struct DateStamp created; - __u8 dir_name[32]; - __s32 spare3[2]; - __s32 link_chain; - __s32 spare4[5]; - __s32 hash_chain; - __s32 parent; - __s32 spare5; - __s32 secondary_type; + u8 dir_name[32]; + s32 spare3[2]; + s32 link_chain; + s32 spare4[5]; + s32 hash_chain; + s32 parent; + s32 spare5; + s32 secondary_type; }; struct file_front { - __s32 primary_type; - __s32 own_key; - __s32 block_count; - __s32 unknown1; - __s32 first_data; - __u32 checksum; - __s32 blocks[0]; + s32 primary_type; + s32 own_key; + s32 block_count; + s32 unknown1; + s32 first_data; + u32 checksum; + s32 blocks[0]; }; struct file_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __s32 byte_size; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + s32 byte_size; + u8 comment[92]; struct DateStamp created; - __u8 file_name[32]; - __s32 spare2; - __s32 original; /* not really in file_end */ - __s32 link_chain; - __s32 spare3[5]; - __s32 hash_chain; - __s32 parent; - __s32 extension; - __s32 secondary_type; + u8 file_name[32]; + s32 spare2; + s32 original; /* not really in file_end */ + s32 link_chain; + s32 spare3[5]; + s32 hash_chain; + s32 parent; + s32 extension; + s32 secondary_type; }; struct hlink_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __u32 checksum; + s32 primary_type; + s32 own_key; + s32 spare1[3]; + u32 checksum; }; struct hlink_end { - __s32 spare1; - __s16 owner_uid; - __s16 owner_gid; - __u32 protect; - __u8 comment[92]; + s32 spare1; + s16 owner_uid; + s16 owner_gid; + u32 protect; + u8 comment[92]; struct DateStamp created; - __u8 link_name[32]; - __s32 spare2; - __s32 original; - __s32 link_chain; - __s32 spare3[5]; - __s32 hash_chain; - __s32 parent; - __s32 spare4; - __s32 secondary_type; + u8 link_name[32]; + s32 spare2; + s32 original; + s32 link_chain; + s32 spare3[5]; + s32 hash_chain; + s32 parent; + s32 spare4; + s32 secondary_type; }; struct slink_front { - __s32 primary_type; - __s32 own_key; - __s32 spare1[3]; - __s32 checksum; - __u8 symname[288]; /* depends on block size */ + s32 primary_type; + s32 own_key; + s32 spare1[3]; + s32 checksum; + u8 symname[288]; /* depends on block size */ }; struct data_front { - __s32 primary_type; - __s32 header_key; - __s32 sequence_number; - __s32 data_size; - __s32 next_data; - __s32 checksum; - __u8 data[488]; /* depends on block size */ + s32 primary_type; + s32 header_key; + s32 sequence_number; + s32 data_size; + s32 next_data; + s32 checksum; + u8 data[488]; /* depends on block size */ }; /* Permission bits */ diff -u --recursive --new-file v2.1.36/linux/include/linux/auto_fs.h linux/include/linux/auto_fs.h --- v2.1.36/linux/include/linux/auto_fs.h Fri Apr 4 08:52:25 1997 +++ linux/include/linux/auto_fs.h Thu May 8 13:55:40 1997 @@ -1,14 +1,14 @@ -/* -*- linux-c -*- --------------------------------------------------------- * - * +/* -*- linux-c -*- ------------------------------------------------------- * + * * linux/include/linux/auto_fs.h * - * Copyright 1997 Transmeta Corporation -- All Rights Reserved + * Copyright 1997 Transmeta Corporation - All Rights Reserved * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your * option, any later version, incorporated herein by reference. * - * ------------------------------------------------------------------------- */ + * ----------------------------------------------------------------------- */ #ifndef _LINUX_AUTO_FS_H @@ -20,11 +20,11 @@ #include #include -#define AUTOFS_PROTO_VERSION 2 +#define AUTOFS_PROTO_VERSION 3 enum autofs_packet_type { - autofs_ptype_missing, /* Missing entry (create wait queue) */ - /* ...need more in the future... */ + autofs_ptype_missing, /* Missing entry (mount request) */ + autofs_ptype_expire, /* Expire entry (umount request) */ }; struct autofs_packet_hdr { @@ -39,139 +39,24 @@ char name[NAME_MAX+1]; }; -#define AUTOFS_IOC_READY _IO(0x93,0x60) -#define AUTOFS_IOC_FAIL _IO(0x93,0x61) -#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62) - -#ifdef __KERNEL__ - -#include -#include - -#if LINUX_VERSION_CODE < 0x20100 - -#include -#define copy_to_user memcpy_tofs -#define copy_from_user memcpy_fromfs - -#else - -#include -#define register_symtab(x) do { } while (0) - -#endif - -#ifndef DPRINTK -#ifdef DEBUG -#define DPRINTK(D) printk D; -#else -#define DPRINTK(D) -#endif -#endif - -#define AUTOFS_SUPER_MAGIC 0x0187 - -/* Structures associated with the root directory hash */ - -#define AUTOFS_HASH_SIZE 67 - -typedef u32 autofs_hash_t; /* Type returned by autofs_hash() */ - -struct autofs_dir_ent { - autofs_hash_t hash; - struct autofs_dir_ent *next; - struct autofs_dir_ent **back; - char *name; - int len; - ino_t ino; - time_t expiry; /* Reserved for use in failed-lookup cache */ -}; - -struct autofs_dirhash { - struct autofs_dir_ent *h[AUTOFS_HASH_SIZE]; -}; - -struct autofs_wait_queue { - unsigned long wait_queue_token; - struct wait_queue *queue; - struct autofs_wait_queue *next; - /* We use the following to see what we are waiting for */ - autofs_hash_t hash; - int len; - char *name; - /* This is for status reporting upon return */ - int status; - int wait_ctr; -}; - -struct autofs_symlink { +struct autofs_packet_expire { + struct autofs_packet_hdr hdr; int len; - char *data; - time_t mtime; + char name[NAME_MAX+1]; }; -#define AUTOFS_MAX_SYMLINKS 256 - -#define AUTOFS_ROOT_INO 1 -#define AUTOFS_FIRST_SYMLINK 2 -#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS) - -#define AUTOFS_SYMLINK_BITMAP_LEN ((AUTOFS_MAX_SYMLINKS+31)/32) - -#ifndef END_OF_TIME -#define END_OF_TIME ((time_t)((unsigned long)((time_t)(~0UL)) >> 1)) -#endif - -struct autofs_sb_info { - struct file *pipe; - pid_t oz_pgrp; - int catatonic; - ino_t next_dir_ino; - struct autofs_wait_queue *queues; /* Wait queue pointer */ - struct autofs_dirhash dirhash; /* Root directory hash */ - struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS]; - u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; -}; +#define AUTOFS_IOC_READY _IO(0x93,0x60) +#define AUTOFS_IOC_FAIL _IO(0x93,0x61) +#define AUTOFS_IOC_CATATONIC _IO(0x93,0x62) +#define AUTOFS_IOC_PROTOVER _IOR(0x93,0x63,int) +#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long) +#define AUTOFS_IOC_EXPIRE _IOR(0x93,0x65,struct autofs_packet_expire) -/* autofs_oz_mode(): do we see the man behind the curtain? */ -static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; -} +#ifdef __KERNEL__ /* Init function */ int init_autofs_fs(void); -/* Hash operations */ - -autofs_hash_t autofs_hash(const char *,int); -void autofs_initialize_hash(struct autofs_dirhash *); -struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,autofs_hash_t,const char *,int); -void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *); -void autofs_hash_delete(struct autofs_dir_ent *); -struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *); -void autofs_hash_nuke(struct autofs_dirhash *); - -/* Operations structures */ - -extern struct inode_operations autofs_root_inode_operations; -extern struct inode_operations autofs_symlink_inode_operations; -extern struct inode_operations autofs_dir_inode_operations; - -/* Initializing function */ - -struct super_block *autofs_read_super(struct super_block *, void *,int); - -/* Queue management functions */ - -int autofs_wait(struct autofs_sb_info *,autofs_hash_t,const char *,int); -int autofs_wait_release(struct autofs_sb_info *,unsigned long,int); -void autofs_catatonic_mode(struct autofs_sb_info *); - -#ifdef DEBUG -void autofs_say(const char *name, int len); -#else -#define autofs_say(n,l) -#endif - #endif /* __KERNEL__ */ + #endif /* _LINUX_AUTO_FS_H */ diff -u --recursive --new-file v2.1.36/linux/include/linux/console.h linux/include/linux/console.h --- v2.1.36/linux/include/linux/console.h Fri Apr 4 08:52:25 1997 +++ linux/include/linux/console.h Thu May 1 12:05:02 1997 @@ -27,19 +27,20 @@ /* DPC: 1994-04-13 !!! con_putcs is new entry !!! */ struct consw { - unsigned long (*con_startup)(unsigned long, char **); - void (*con_init)(struct vc_data *); - int (*con_deinit)(struct vc_data *); - int (*con_clear)(struct vc_data *, int, int, int, int); - int (*con_putc)(struct vc_data *, int, int, int); - int (*con_putcs)(struct vc_data *, const char *, int, int, int); - int (*con_cursor)(struct vc_data *, int); - int (*con_scroll)(struct vc_data *, int, int, int, int); - int (*con_bmove)(struct vc_data *, int, int, int, int, int, int); - int (*con_switch)(struct vc_data *); - int (*con_blank)(int); - int (*con_get_font)(struct vc_data *, int *, int *, char *); - int (*con_set_font)(struct vc_data *, int, int, char *); + unsigned long (*con_startup)(unsigned long, const char **); + void (*con_init)(struct vc_data *); + int (*con_deinit)(struct vc_data *); + int (*con_clear)(struct vc_data *, int, int, int, int); + int (*con_putc)(struct vc_data *, int, int, int); + int (*con_putcs)(struct vc_data *, const char *, int, int, int); + int (*con_cursor)(struct vc_data *, int); + int (*con_scroll)(struct vc_data *, int, int, int, int); + int (*con_bmove)(struct vc_data *, int, int, int, int, int, int); + int (*con_switch)(struct vc_data *); + int (*con_blank)(int); + int (*con_get_font)(struct vc_data *, int *, int *, char *); + int (*con_set_font)(struct vc_data *, int, int, char *); + int (*con_set_palette)(struct vc_data *, unsigned char *); }; extern struct consw *conswitchp; diff -u --recursive --new-file v2.1.36/linux/include/linux/cyclades.h linux/include/linux/cyclades.h --- v2.1.36/linux/include/linux/cyclades.h Sat Apr 20 11:09:56 1996 +++ linux/include/linux/cyclades.h Mon May 5 08:35:07 1997 @@ -1,4 +1,4 @@ -/* +/* $Revision: 1.7 $$Date: 1997/03/26 10:30:00 $ * linux/include/linux/cyclades.h * * This file is maintained by Marcio Saito and @@ -6,9 +6,18 @@ * * This file contains the general definitions for the cyclades.c driver *$Log: cyclades.h,v $ - * Revision 1.5 1995/11/13 21:13:31 bentson - * changes suggested by Michael Chastain - * to support use of this file in non-kernel applications + *Revision 1.7 1997/03/26 10:30:00 daniel + *new entries at the end of cyclades_port struct to reallocate + *variables illegally allocated within card memory. + * + *Revision 1.6 1996/09/09 18:35:30 bentson + *fold in changes for Cyclom-Z -- including structures for + *communicating with board as well modest changes to original + *structures to support new features. + * + *Revision 1.5 1995/11/13 21:13:31 bentson + *changes suggested by Michael Chastain + *to support use of this file in non-kernel applications * * */ @@ -35,14 +44,359 @@ #define CYGETDEFTIMEOUT 0x435908 #define CYSETDEFTIMEOUT 0x435909 +/*************** CYCLOM-Z ADDITIONS ***************/ + +#define CZIOC ('M' << 8) +#define CZ_NBOARDS (CZIOC|0xfa) +#define CZ_BOOT_START (CZIOC|0xfb) +#define CZ_BOOT_DATA (CZIOC|0xfc) +#define CZ_BOOT_END (CZIOC|0xfd) +#define CZ_TEST (CZIOC|0xfe) + +#define MAX_BOARD 4 /* Max number of boards */ +#define MAX_PORT 128 /* Max number of ports per board */ +#define MAX_DEV 256 /* Max number of ports total */ + +#define CYZ_BOOT_NWORDS 0x100 +struct CYZ_BOOT_CTRL { + unsigned short nboard; + int status[MAX_BOARD]; + int nchannel[MAX_BOARD]; + int fw_rev[MAX_BOARD]; + unsigned long offset; + unsigned long data[CYZ_BOOT_NWORDS]; +}; + + +#ifndef DP_WINDOW_SIZE +/* #include "cyclomz.h" */ +/****************** ****************** *******************/ +/* + * The data types defined below are used in all ZFIRM interface + * data structures. They accomodate differences between HW + * architectures and compilers. + */ + +typedef unsigned long uclong; /* 32 bits, unsigned */ +typedef unsigned short ucshort; /* 16 bits, unsigned */ +typedef unsigned char ucchar; /* 8 bits, unsigned */ + +/* + * Memory Window Sizes + */ + +#define DP_WINDOW_SIZE (0x00080000) /* window size 512 Kb */ +#define CTRL_WINDOW_SIZE (0x00000100) /* runtime regs 256 bytes */ + +/* + * CUSTOM_REG - Cyclom-Z/PCI Custom Registers Set. The driver + * normally will access only interested on the fpga_id, fpga_version, + * start_cpu and stop_cpu. + */ + +struct CUSTOM_REG { + uclong fpga_id; /* FPGA Identification Register */ + uclong fpga_version; /* FPGA Version Number Register */ + uclong cpu_start; /* CPU start Register (write) */ + uclong cpu_stop; /* CPU stop Register (write) */ + uclong misc_reg; /* Miscelaneous Register */ + uclong idt_mode; /* IDT mode Register */ + uclong uart_irq_status; /* UART IRQ status Register */ + uclong clear_timer0_irq; /* Clear timer interrupt Register */ + uclong clear_timer1_irq; /* Clear timer interrupt Register */ + uclong clear_timer2_irq; /* Clear timer interrupt Register */ + uclong test_register; /* Test Register */ + uclong test_count; /* Test Count Register */ + uclong timer_select; /* Timer select register */ + uclong pr_uart_irq_status; /* Prioritized UART IRQ stat Reg */ + uclong ram_wait_state; /* RAM wait-state Register */ + uclong uart_wait_state; /* UART wait-state Register */ + uclong timer_wait_state; /* timer wait-state Register */ + uclong ack_wait_state; /* ACK wait State Register */ +}; + +/* + * RUNTIME_9060 - PLX PCI9060ES local configuration and shared runtime + * registers. This structure can be used to access the 9060 registers + * (memory mapped). + */ + +struct RUNTIME_9060 { + uclong loc_addr_range; /* 00h - Local Address Range */ + uclong loc_addr_base; /* 04h - Local Address Base */ + uclong loc_arbitr; /* 08h - Local Arbitration */ + uclong endian_descr; /* 0Ch - Big/Little Endian Descriptor */ + uclong loc_rom_range; /* 10h - Local ROM Range */ + uclong loc_rom_base; /* 14h - Local ROM Base */ + uclong loc_bus_descr; /* 18h - Local Bus descriptor */ + uclong loc_range_mst; /* 1Ch - Local Range for Master to PCI */ + uclong loc_base_mst; /* 20h - Local Base for Master PCI */ + uclong loc_range_io; /* 24h - Local Range for Master IO */ + uclong pci_base_mst; /* 28h - PCI Base for Master PCI */ + uclong pci_conf_io; /* 2Ch - PCI configuration for Master IO */ + uclong filler1; /* 30h */ + uclong filler2; /* 34h */ + uclong filler3; /* 38h */ + uclong filler4; /* 3Ch */ + uclong mail_box_0; /* 40h - Mail Box 0 */ + uclong mail_box_1; /* 44h - Mail Box 1 */ + uclong mail_box_2; /* 48h - Mail Box 2 */ + uclong mail_box_3; /* 4Ch - Mail Box 3 */ + uclong filler5; /* 50h */ + uclong filler6; /* 54h */ + uclong filler7; /* 58h */ + uclong filler8; /* 5Ch */ + uclong pci_doorbell; /* 60h - PCI to Local Doorbell */ + uclong loc_doorbell; /* 64h - Local to PCI Doorbell */ + uclong intr_ctrl_stat; /* 68h - Interrupt Control/Status */ + uclong init_ctrl; /* 6Ch - EEPROM control, Init Control, etc */ +}; + +/* Values for the Local Base Address re-map register */ + +#define WIN_RAM 0x00000001L /* set the sliding window to RAM */ +#define WIN_CREG 0x14000001L /* set the window to custom Registers */ + +/* Values timer select registers */ + +#define TIMER_BY_1M 0x00 /* clock divided by 1M */ +#define TIMER_BY_256K 0x01 /* clock divided by 256k */ +#define TIMER_BY_128K 0x02 /* clock divided by 128k */ +#define TIMER_BY_32K 0x03 /* clock divided by 32k */ + +/****************** ****************** *******************/ +#endif + +#ifndef ZFIRM_ID +/* #include "zfwint.h" */ +/****************** ****************** *******************/ +/* + * This file contains the definitions for interfacing with the + * Cyclom-Z ZFIRM Firmware. + */ + +/* General Constant definitions */ + +#define MAX_CHAN 64 /* max number of channels per board */ + +/* firmware id structure (set after boot) */ + +#define ID_ADDRESS 0x00000180L /* signature/pointer address */ +#define ZFIRM_ID 0x5557465AL /* ZFIRM/U signature */ +struct FIRM_ID { + uclong signature; /* ZFIRM/U signature */ + uclong zfwctrl_addr; /* pointer to ZFW_CTRL structure */ +}; + +/* Op. System id */ + +#define C_OS_LINUX 0x00000030 /* generic Linux system */ + +/* channel op_mode */ + +#define C_CH_DISABLE 0x00000000 /* channel is disabled */ +#define C_CH_TXENABLE 0x00000001 /* channel Tx enabled */ +#define C_CH_RXENABLE 0x00000002 /* channel Rx enabled */ +#define C_CH_ENABLE 0x00000003 /* channel Tx/Rx enabled */ +#define C_CH_LOOPBACK 0x00000004 /* Loopback mode */ + +/* comm_parity - parity */ + +#define C_PR_NONE 0x00000000 /* None */ +#define C_PR_ODD 0x00000001 /* Odd */ +#define C_PR_EVEN 0x00000002 /* Even */ +#define C_PR_MARK 0x00000004 /* Mark */ +#define C_PR_SPACE 0x00000008 /* Space */ +#define C_PR_PARITY 0x000000ff + +#define C_PR_DISCARD 0x00000100 /* discard char with frame/par error */ +#define C_PR_IGNORE 0x00000200 /* ignore frame/par error */ + +/* comm_data_l - data length and stop bits */ + +#define C_DL_CS5 0x00000001 +#define C_DL_CS6 0x00000002 +#define C_DL_CS7 0x00000004 +#define C_DL_CS8 0x00000008 +#define C_DL_CS 0x0000000f +#define C_DL_1STOP 0x00000010 +#define C_DL_15STOP 0x00000020 +#define C_DL_2STOP 0x00000040 +#define C_DL_STOP 0x000000f0 + +/* interrupt enabling/status */ + +#define C_IN_DISABLE 0x00000000 /* zero, disable interrupts */ +#define C_IN_TXBEMPTY 0x00000001 /* tx buffer empty */ +#define C_IN_TXLOWWM 0x00000002 /* tx buffer below LWM */ +#define C_IN_RXHIWM 0x00000010 /* rx buffer above HWM */ +#define C_IN_RXNNDT 0x00000020 /* rx no new data timeout */ +#define C_IN_MDCD 0x00000100 /* modem DCD change */ +#define C_IN_MDSR 0x00000200 /* modem DSR change */ +#define C_IN_MRI 0x00000400 /* modem RI change */ +#define C_IN_MCTS 0x00000800 /* modem CTS change */ +#define C_IN_RXBRK 0x00001000 /* Break received */ +#define C_IN_PR_ERROR 0x00002000 /* parity error */ +#define C_IN_FR_ERROR 0x00004000 /* frame error */ + +/* flow control */ + +#define C_FL_OXX 0x00000001 /* output Xon/Xoff flow control */ +#define C_FL_IXX 0x00000002 /* output Xon/Xoff flow control */ +#define C_FL_OIXANY 0x00000004 /* output Xon/Xoff (any xon) */ +#define C_FL_SWFLOW 0x0000000f + +/* flow status */ + +#define C_FS_TXIDLE 0x00000000 /* no Tx data in the buffer or UART */ +#define C_FS_SENDING 0x00000001 /* UART is sending data */ +#define C_FS_SWFLOW 0x00000002 /* Tx is stopped by received Xoff */ + +/* rs_control/rs_status RS-232 signals */ + +#define C_RS_DCD 0x00000100 /* CD */ +#define C_RS_DSR 0x00000200 /* DSR */ +#define C_RS_RI 0x00000400 /* RI */ +#define C_RS_CTS 0x00000800 /* CTS */ +#define C_RS_RTS 0x00000001 /* RTS */ +#define C_RS_DTR 0x00000004 /* DTR */ + +/* commands Host <-> Board */ + +#define C_CM_RESET 0x01 /* reset/flush buffers */ +#define C_CM_IOCTL 0x02 /* re-read CH_CTRL */ +#define C_CM_IOCTLW 0x03 /* re-read CH_CTRL, intr when done */ +#define C_CM_IOCTLM 0x04 /* RS-232 outputs change */ +#define C_CM_SENDXOFF 0x10 /* send Xoff */ +#define C_CM_SENDXON 0x11 /* send Xon */ +#define C_CM_CLFLOW 0x12 /* Clear flow control (resume) */ +#define C_CM_SENDBRK 0x41 /* send break */ +#define C_CM_INTBACK 0x42 /* Interrupt back */ +#define C_CM_SET_BREAK 0x43 /* Tx break on */ +#define C_CM_CLR_BREAK 0x44 /* Tx break off */ +#define C_CM_CMD_DONE 0x45 /* Previous command done */ +#define C_CM_TINACT 0x51 /* set inactivity detection */ +#define C_CM_IRQ_ENBL 0x52 /* enable generation of interrupts */ +#define C_CM_IRQ_DSBL 0x53 /* disable generation of interrupts */ +#define C_CM_ACK_ENBL 0x54 /* enable acknolowdged interrupt mode */ +#define C_CM_ACK_DSBL 0x55 /* disable acknolowdged intr mode */ +#define C_CM_FLUSH_RX 0x56 /* flushes Rx buffer */ +#define C_CM_FLUSH_TX 0x57 /* flushes Tx buffer */ + +#define C_CM_TXBEMPTY 0x60 /* Tx buffer is empty */ +#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_MDCD 0x70 /* modem DCD change */ +#define C_CM_MDSR 0x71 /* modem DSR change */ +#define C_CM_MRI 0x72 /* modem RI change */ +#define C_CM_MCTS 0x73 /* modem CTS change */ +#define C_CM_RXBRK 0x84 /* Break received */ +#define C_CM_PR_ERROR 0x85 /* Parity error */ +#define C_CM_FR_ERROR 0x86 /* Frame error */ +#define C_CM_CMDERROR 0x90 /* command error */ +#define C_CM_FATAL 0x91 /* fatal error */ +#define C_CM_HW_RESET 0x92 /* reset board */ + +/* + * CH_CTRL - This per port structure contains all parameters + * that control an specific port. It can be seen as the + * configuration registers of a "super-serial-controller". + */ + +struct CH_CTRL { + uclong op_mode; /* operation mode */ + uclong intr_enable; /* interrupt masking */ + uclong sw_flow; /* SW flow control */ + uclong flow_status; /* output flow status */ + uclong comm_baud; /* baud rate - numerically specified */ + uclong comm_parity; /* parity */ + uclong comm_data_l; /* data length/stop */ + uclong comm_flags; /* other flags */ + uclong hw_flow; /* HW flow control */ + uclong rs_control; /* RS-232 outputs */ + uclong rs_status; /* RS-232 inputs */ + uclong flow_xon; /* xon char */ + uclong flow_xoff; /* xoff char */ + uclong filler[3]; /* filler to align structures */ +}; + + +/* + * BUF_CTRL - This per channel structure contains + * all Tx and Rx buffer control for a given channel. + */ + +struct BUF_CTRL { + uclong flag_dma; /* buffers are in Host memory */ + uclong tx_bufaddr; /* address of the tx buffer */ + uclong tx_bufsize; /* tx buffer size */ + uclong tx_threshold; /* tx low water mark */ + uclong tx_get; /* tail index tx buf */ + uclong tx_put; /* head index tx buf */ + uclong rx_bufaddr; /* address of the rx buffer */ + uclong rx_bufsize; /* rx buffer size */ + uclong rx_threshold; /* rx high water mark */ + uclong rx_get; /* tail index rx buf */ + uclong rx_put; /* head index rx buf */ + uclong filler[5]; /* filler to align structures */ +}; + +/* + * BOARD_CTRL - This per board structure contains all global + * control fields related to the board. + */ + +struct BOARD_CTRL { + + /* static info provided by the on-board CPU */ + uclong n_channel; /* number of channels */ + uclong fw_version; /* firmware version */ + + /* static info provided by the driver */ + uclong op_system; /* op_system id */ + uclong dr_version; /* driver version */ + + /* board control area */ + uclong inactivity; /* inactivity control */ + + /* host to FW commands */ + uclong hcmd_channel; /* channel number */ + uclong *hcmd_param; /* pointer to parameters */ + + /* FW to Host commands */ + uclong fwcmd_channel; /* channel number */ + uclong *fwcmd_param; /* pointer to parameters */ + + /* filler so the structures are aligned */ + uclong filler[7]; +}; + +/* + * ZFW_CTRL - This is the data structure that includes all other + * data structures used by the Firmware. + */ + +struct ZFW_CTRL { + struct BOARD_CTRL board_ctrl; + struct CH_CTRL ch_ctrl[MAX_CHAN]; + struct BUF_CTRL buf_ctrl[MAX_CHAN]; +}; + +/****************** ****************** *******************/ +#endif + + + #ifdef __KERNEL__ /* Per card data structure */ struct cyclades_card { - int base_addr; + long base_addr; + long ctl_addr; int irq; - int num_chips; /* 0 if card is absent */ + int num_chips; /* 0 if card absent, 1 if Z/PCI, else Y */ int first_line; /* minor number of first channel on card */ int bus_index; /* address shift - 0 for ISA, 1 for PCI */ }; @@ -72,6 +426,7 @@ int xmit_fifo_size; int cor1,cor2,cor3,cor4,cor5; int tbpr,tco,rbpr,rco; + int baud; int ignore_status_mask; int close_delay; int IER; /* Interrupt Enable Register */ @@ -95,6 +450,8 @@ struct wait_queue *open_wait; struct wait_queue *close_wait; struct cyclades_monitor mon; + unsigned long jiffies[3]; + unsigned long rflush_count; }; /* @@ -111,6 +468,10 @@ #define CyMaxChipsPerCard 8 +#define CyPCI_Ywin 0x4000 +#define CyPCI_Zctl 0x100 +#define CyPCI_Zwin 0x80000 + /**** CD1400 registers ****/ #define CyRegSize 0x0400 @@ -282,3 +643,4 @@ #endif /* __KERNEL__ */ #endif /* _LINUX_CYCLADES_H */ + diff -u --recursive --new-file v2.1.36/linux/include/linux/digi1.h linux/include/linux/digi1.h --- v2.1.36/linux/include/linux/digi1.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/digi1.h Tue Apr 29 11:45:43 1997 @@ -0,0 +1,100 @@ +/* Definitions for DigiBoard ditty(1) command. */ + +#if !defined(TIOCMODG) +#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ +#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ +#endif + +#if !defined(TIOCMSET) +#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ +#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#endif + +#if !defined(TIOCMBIC) +#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ +#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#endif + +#if !defined(TIOCSDTR) +#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ +#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#endif + +/************************************************************************ + * Ioctl command arguments for DIGI parameters. + ************************************************************************/ +#define DIGI_GETA ('e'<<8) | 94 /* Read params */ + +#define DIGI_SETA ('e'<<8) | 95 /* Set params */ +#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ +#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ + +#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ + /* control characters */ +#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ + /* control characters */ +#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ + /* flow control chars */ +#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ + /* flow control chars */ + +#define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */ +#define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */ +#define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */ + +struct digiflow_struct +{ + unsigned char startc; /* flow cntl start char */ + unsigned char stopc; /* flow cntl stop char */ +}; + +typedef struct digiflow_struct digiflow_t; + + +/************************************************************************ + * Values for digi_flags + ************************************************************************/ +#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ +#define DIGI_FAST 0x0002 /* Fast baud rates */ +#define RTSPACE 0x0004 /* RTS input flow control */ +#define CTSPACE 0x0008 /* CTS output flow control */ +#define DSRPACE 0x0010 /* DSR output flow control */ +#define DCDPACE 0x0020 /* DCD output flow control */ +#define DTRPACE 0x0040 /* DTR input flow control */ +#define DIGI_FORCEDCD 0x0100 /* Force carrier */ +#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ +#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ + + +/************************************************************************ + * Values for digiDload + ************************************************************************/ +#define NORMAL 0 +#define PCI_CTL 1 + +#define SIZE8 0 +#define SIZE16 1 +#define SIZE32 2 + +/************************************************************************ + * Structure used with ioctl commands for DIGI parameters. + ************************************************************************/ +struct digi_struct +{ + unsigned short digi_flags; /* Flags (see above) */ +}; + +typedef struct digi_struct digi_t; + +struct digi_info +{ + unsigned long board; /* Which board is this ? */ + unsigned char status; /* Alive or dead */ + unsigned char type; /* see epca.h */ + unsigned char subtype; /* For future XEM, XR, etc ... */ + unsigned short numports; /* Number of ports configured */ + unsigned char *port; /* I/O Address */ + unsigned char *membase; /* DPR Address */ + unsigned char *version; /* For future ... */ + unsigned short windowData; /* For future ... */ +} ; diff -u --recursive --new-file v2.1.36/linux/include/linux/digiFep1.h linux/include/linux/digiFep1.h --- v2.1.36/linux/include/linux/digiFep1.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/digiFep1.h Tue Apr 29 11:45:43 1997 @@ -0,0 +1,136 @@ + +#define CSTART 0x400L +#define CMAX 0x800L +#define ISTART 0x800L +#define IMAX 0xC00L +#define CIN 0xD10L +#define GLOBAL 0xD10L +#define EIN 0xD18L +#define FEPSTAT 0xD20L +#define CHANSTRUCT 0x1000L +#define RXTXBUF 0x4000L + + +struct global_data +{ + volatile ushort cin; + volatile ushort cout; + volatile ushort cstart; + volatile ushort cmax; + volatile ushort ein; + volatile ushort eout; + volatile ushort istart; + volatile ushort imax; +}; + + +struct board_chan +{ + int filler1; + int filler2; + volatile ushort tseg; + volatile ushort tin; + volatile ushort tout; + volatile ushort tmax; + + volatile ushort rseg; + volatile ushort rin; + volatile ushort rout; + volatile ushort rmax; + + volatile ushort tlow; + volatile ushort rlow; + volatile ushort rhigh; + volatile ushort incr; + + volatile ushort etime; + volatile ushort edelay; + volatile unchar *dev; + + volatile ushort iflag; + volatile ushort oflag; + volatile ushort cflag; + volatile ushort gmask; + + volatile ushort col; + volatile ushort delay; + volatile ushort imask; + volatile ushort tflush; + + int filler3; + int filler4; + int filler5; + int filler6; + + volatile unchar num; + volatile unchar ract; + volatile unchar bstat; + volatile unchar tbusy; + volatile unchar iempty; + volatile unchar ilow; + volatile unchar idata; + volatile unchar eflag; + + volatile unchar tflag; + volatile unchar rflag; + volatile unchar xmask; + volatile unchar xval; + volatile unchar mstat; + volatile unchar mchange; + volatile unchar mint; + volatile unchar lstat; + + volatile unchar mtran; + volatile unchar orun; + volatile unchar startca; + volatile unchar stopca; + volatile unchar startc; + volatile unchar stopc; + volatile unchar vnext; + volatile unchar hflow; + + volatile unchar fillc; + volatile unchar ochar; + volatile unchar omask; + + unchar filler7; + unchar filler8[28]; +}; + + +#define SRXLWATER 0xE0 +#define SRXHWATER 0xE1 +#define STOUT 0xE2 +#define PAUSETX 0xE3 +#define RESUMETX 0xE4 +#define SAUXONOFFC 0xE6 +#define SENDBREAK 0xE8 +#define SETMODEM 0xE9 +#define SETIFLAGS 0xEA +#define SONOFFC 0xEB +#define STXLWATER 0xEC +#define PAUSERX 0xEE +#define RESUMERX 0xEF +#define SETBUFFER 0xF2 +#define SETCOOKED 0xF3 +#define SETHFLOW 0xF4 +#define SETCTRLFLAGS 0xF5 +#define SETVNEXT 0xF6 + + + +#define BREAK_IND 0x01 +#define LOWTX_IND 0x02 +#define EMPTYTX_IND 0x04 +#define DATA_IND 0x08 +#define MODEMCHG_IND 0x20 + +#define FEP_HUPCL 0002000 +#if 0 +#define RTS 0x02 +#define CD 0x08 +#define DSR 0x10 +#define CTS 0x20 +#define RI 0x40 +#define DTR 0x80 +#endif diff -u --recursive --new-file v2.1.36/linux/include/linux/digiPCI.h linux/include/linux/digiPCI.h --- v2.1.36/linux/include/linux/digiPCI.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/digiPCI.h Tue Apr 29 11:45:43 1997 @@ -0,0 +1,42 @@ +/************************************************************************* + * Defines and structure definitions for PCI BIOS Interface + *************************************************************************/ +#define PCIMAX 32 /* maximum number of PCI boards */ + + +#define PCI_VENDOR_DIGI 0x114F +#define PCI_DEVICE_EPC 0x0002 +#define PCI_DEVICE_RIGHTSWITCH 0x0003 /* For testing */ +#define PCI_DEVICE_XEM 0x0004 +#define PCI_DEVICE_XR 0x0005 +#define PCI_DEVICE_CX 0x0006 +#define PCI_DEVICE_XRJ 0x0009 /* Jupiter boards with */ +#define PCI_DEVICE_EPCJ 0x000a /* PLX 9060 chip for PCI */ + + +/* + * On the PCI boards, there is no IO space allocated + * The I/O registers will be in the first 3 bytes of the + * upper 2MB of the 4MB memory space. The board memory + * will be mapped into the low 2MB of the 4MB memory space + */ + +/* Potential location of PCI Bios from E0000 to FFFFF*/ +#define PCI_BIOS_SIZE 0x00020000 + +/* Size of Memory and I/O for PCI (4MB) */ +#define PCI_RAM_SIZE 0x00400000 + +/* Size of Memory (2MB) */ +#define PCI_MEM_SIZE 0x00200000 + +/* Offset of I/0 in Memory (2MB) */ +#define PCI_IO_OFFSET 0x00200000 + +#define MEMOUTB(basemem, pnum, setmemval) *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval) +#define MEMINB(basemem, pnum) *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum )) /* for PCI I/O */ + + + + + diff -u --recursive --new-file v2.1.36/linux/include/linux/epca.h linux/include/linux/epca.h --- v2.1.36/linux/include/linux/epca.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/epca.h Tue Apr 29 11:45:43 1997 @@ -0,0 +1,170 @@ +#define XEMPORTS 0xC02 +#define XEPORTS 0xC22 + +#define MAX_ALLOC 0x100 + +#define MAXBOARDS 12 +#define FEPCODESEG 0x0200L +#define FEPCODE 0x2000L +#define BIOSCODE 0xf800L + +#define MISCGLOBAL 0x0C00L +#define NPORT 0x0C22L +#define MBOX 0x0C40L +#define PORTBASE 0x0C90L + +/* Begin code defines used for epca_setup */ + +#define INVALID_BOARD_TYPE 0x1 +#define INVALID_NUM_PORTS 0x2 +#define INVALID_MEM_BASE 0x4 +#define INVALID_PORT_BASE 0x8 +#define INVALID_BOARD_STATUS 0x10 +#define INVALID_ALTPIN 0x20 + +/* End code defines used for epca_setup */ + + +#define FEPCLR 0x00 +#define FEPMEM 0x02 +#define FEPRST 0x04 +#define FEPINT 0x08 +#define FEPMASK 0x0e +#define FEPWIN 0x80 + +#define PCXE 0 +#define PCXEVE 1 +#define PCXEM 2 +#define EISAXEM 3 +#define PC64XE 4 +#define PCXI 5 +#define PCIXEM 7 +#define PCICX 8 +#define PCIXR 9 +#define PCIXRJ 10 +#define EPCA_NUM_TYPES 6 + + +static char *board_desc[] = +{ + "PC/Xe", + "PC/Xeve", + "PC/Xem", + "EISA/Xem", + "PC/64Xe", + "PC/Xi", + "unknown", + "PCI/Xem", + "PCI/CX", + "PCI/Xr", + "PCI/Xrj", +}; + +#define STARTC 021 +#define STOPC 023 +#define IAIXON 0x2000 + + +#define TXSTOPPED 0x1 +#define LOWWAIT 0x2 +#define EMPTYWAIT 0x4 +#define RXSTOPPED 0x8 +#define TXBUSY 0x10 + +#define DISABLED 0 +#define ENABLED 1 +#define OFF 0 +#define ON 1 + +#define FEPTIMEOUT 200000 +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 +#define SERIAL_TYPE_INFO 3 +#define EPCA_EVENT_HANGUP 1 +#define EPCA_MAGIC 0x5c6df104L + +struct channel +{ + long magic; + unchar boardnum; + unchar channelnum; + unchar omodem; /* FEP output modem status */ + unchar imodem; /* FEP input modem status */ + unchar modemfake; /* Modem values to be forced */ + unchar modem; /* Force values */ + unchar hflow; + unchar dsr; + unchar dcd; + unchar m_rts ; /* The bits used in whatever FEP */ + unchar m_dcd ; /* is indiginous to this board to */ + unchar m_dsr ; /* represent each of the physical */ + unchar m_cts ; /* handshake lines */ + unchar m_ri ; + unchar m_dtr ; + unchar stopc; + unchar startc; + unchar stopca; + unchar startca; + unchar fepstopc; + unchar fepstartc; + unchar fepstopca; + unchar fepstartca; + unchar txwin; + unchar rxwin; + ushort fepiflag; + ushort fepcflag; + ushort fepoflag; + ushort txbufhead; + ushort txbufsize; + ushort rxbufhead; + ushort rxbufsize; + int close_delay; + int count; + int blocked_open; + int event; + int asyncflags; + uint dev; + long session; + long pgrp; + ulong statusflags; + ulong c_iflag; + ulong c_cflag; + ulong c_lflag; + ulong c_oflag; + unchar *txptr; + unchar *rxptr; + unchar *tmp_buf; + struct board_info *board; + volatile struct board_chan *brdchan; + struct digi_struct digiext; + struct tty_struct *tty; + struct termios normal_termios; + struct termios callout_termios; + struct wait_queue *open_wait; + struct wait_queue *close_wait; + struct tq_struct tqueue; + volatile struct global_data *mailbox; +}; + +struct board_info +{ + unchar status; + unchar type; + unchar altpin; + ushort numports; + unchar *port; + unchar *membase; + unchar *re_map_port; + unchar *re_map_membase; + ulong memory_seg; + void ( * memwinon ) (struct board_info *, unsigned int) ; + void ( * memwinoff ) (struct board_info *, unsigned int) ; + void ( * globalwinon ) (struct channel *) ; + void ( * txwinon ) (struct channel *) ; + void ( * rxwinon ) (struct channel *) ; + void ( * memoff ) (struct channel *) ; + void ( * assertgwinon ) (struct channel *) ; + void ( * assertmemoff ) (struct channel *) ; + unchar poller_inhibited ; +}; + diff -u --recursive --new-file v2.1.36/linux/include/linux/epcaconfig.h linux/include/linux/epcaconfig.h --- v2.1.36/linux/include/linux/epcaconfig.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/epcaconfig.h Tue Apr 29 11:45:43 1997 @@ -0,0 +1,8 @@ +#define NUMCARDS 1 +#define NBDEVS 2 + +struct board_info static_boards[NUMCARDS]={ + { ENABLED, 0, OFF, 2, (unchar*) 0x320, (unchar*) 0xd0000 }, +}; + +/* DO NOT HAND EDIT THIS FILE! */ diff -u --recursive --new-file v2.1.36/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.1.36/linux/include/linux/ext2_fs.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/ext2_fs.h Sat Apr 26 12:35:58 1997 @@ -189,6 +189,7 @@ #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ /* @@ -363,7 +364,10 @@ __u32 s_feature_compat; /* compatible feature set */ __u32 s_feature_incompat; /* incompatible feature set */ __u32 s_feature_ro_compat; /* readonly-compatible feature set */ - __u32 s_reserved[230]; /* Padding to the end of the block */ + __u8 s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + __u32 s_reserved[206]; /* Padding to the end of the block */ }; /* @@ -387,6 +391,16 @@ #define EXT2_GOOD_OLD_INODE_SIZE 128 /* + * Feature set definitions + */ + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 + +#define EXT2_FEATURE_COMPAT_SUPP 0 +#define EXT2_FEATURE_INCOMPAT_SUPP 0 +#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + +/* * Default values for user and/or group using reserved blocks */ #define EXT2_DEF_RESUID 0 @@ -413,13 +427,6 @@ #define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ ~EXT2_DIR_ROUND) - -/* - * Feature set definitions --- none are defined as of now - */ -#define EXT2_FEATURE_COMPAT_SUPP 0 -#define EXT2_FEATURE_INCOMPAT_SUPP 0 -#define EXT2_FEATURE_RO_COMPAT_SUPP 0 #ifdef __KERNEL__ /* diff -u --recursive --new-file v2.1.36/linux/include/linux/ext2_fs_sb.h linux/include/linux/ext2_fs_sb.h --- v2.1.36/linux/include/linux/ext2_fs_sb.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/ext2_fs_sb.h Sat Apr 26 12:35:58 1997 @@ -60,6 +60,9 @@ int s_desc_per_block_bits; int s_inode_size; int s_first_ino; + int s_feature_compat; + int s_feature_incompat; + int s_feature_ro_compat; }; #endif /* _LINUX_EXT2_FS_SB */ diff -u --recursive --new-file v2.1.36/linux/include/linux/fb.h linux/include/linux/fb.h --- v2.1.36/linux/include/linux/fb.h Fri Apr 26 02:12:24 1996 +++ linux/include/linux/fb.h Thu May 1 12:05:02 1997 @@ -59,6 +59,7 @@ #define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ #define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ #define FB_ACCEL_CYBERVISION 3 /* Cybervision64 (S3 Trio64) */ +#define FB_ACCEL_RETINAZ3 4 /* RetinaZ3 (NCR77C32BLT) */ #define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ #define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ @@ -205,6 +206,7 @@ int (*switch_con)(int); /* tell fb to switch consoles */ int (*updatevar)(int); /* tell fb to update the vars */ void (*blank)(int); /* tell fb to (un)blank the screen */ + int (*setcmap)(struct fb_cmap *, int); /* tell fb to set the colormap */ }; #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.36/linux/include/linux/file.h linux/include/linux/file.h --- v2.1.36/linux/include/linux/file.h Fri Apr 4 08:52:25 1997 +++ linux/include/linux/file.h Sun Apr 27 15:08:03 1997 @@ -13,16 +13,37 @@ } extern int __fput(struct file *, struct inode *); +extern void insert_file_free(struct file *file); + +/* It does not matter which list it is on. */ +extern inline void remove_filp(struct file *file) +{ + if(file->f_next) + file->f_next->f_pprev = file->f_pprev; + *file->f_pprev = file->f_next; +} extern inline int fput(struct file *file, struct inode *inode) { int count = file->f_count-1; int error = 0; - if (!count) + if (!count) { error = __fput(file, inode); - file->f_count = count; + file->f_count = 0; + remove_filp(file); + insert_file_free(file); + } else + file->f_count = count; return error; +} + +extern inline void put_filp(struct file *file) +{ + if(--file->f_count == 0) { + remove_filp(file); + insert_file_free(file); + } } #endif diff -u --recursive --new-file v2.1.36/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.36/linux/include/linux/fs.h Wed Apr 23 19:01:28 1997 +++ linux/include/linux/fs.h Thu May 8 13:53:31 1997 @@ -95,7 +95,6 @@ * Exception: MS_RDONLY is always applied to the entire file system. */ #define IS_RDONLY(inode) (((inode)->i_sb) && ((inode)->i_sb->s_flags & MS_RDONLY)) -#define DO_UPDATE_ATIME(inode) (!((inode)->i_flags & MS_NOATIME) && !IS_RDONLY(inode)) #define IS_NOSUID(inode) ((inode)->i_flags & MS_NOSUID) #define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV) #define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC) @@ -105,6 +104,8 @@ #define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) +#define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME) +#define DO_UPDATE_ATIME(inode) (!IS_NOATIME(inode) && !IS_RDONLY(inode)) /* the read-only stuff doesn't really belong here, but any other place is probably as bad and I don't want to create yet another include file. */ @@ -129,7 +130,7 @@ extern void buffer_init(void); extern void inode_init(void); -extern unsigned long file_table_init(unsigned long start, unsigned long end); +extern void file_table_init(void); extern unsigned long name_cache_init(unsigned long start, unsigned long end); typedef char buffer_block[BLOCK_SIZE]; @@ -246,6 +247,7 @@ #define ATTR_ATIME_SET 128 #define ATTR_MTIME_SET 256 #define ATTR_FORCE 512 /* Not a change, but a change it */ +#define ATTR_ATTR_FLAG 1024 /* * This is the Inode Attributes structure, used for notify_change(). It @@ -265,8 +267,17 @@ time_t ia_atime; time_t ia_mtime; time_t ia_ctime; + unsigned int ia_attr_flags; }; +/* + * This is the inode attributes flag definitions + */ +#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */ +#define ATTR_FLAG_NOATIME 2 /* Don't update atime */ +#define ATTR_FLAG_APPEND 4 /* Append-only file */ +#define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */ + #include struct inode { @@ -305,9 +316,8 @@ unsigned char i_dirt; unsigned char i_pipe; unsigned char i_sock; - unsigned char i_seek; - unsigned char i_update; - unsigned short i_writecount; + int i_writecount; + unsigned int i_attr_flags; union { struct pipe_inode_info pipe_i; struct minix_inode_info minix_i; @@ -327,17 +337,21 @@ }; struct file { - mode_t f_mode; - loff_t f_pos; - unsigned short f_flags; - unsigned short f_count; - unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; - struct file *f_next, *f_prev; - int f_owner; /* pid or -pgrp where SIGIO should be sent */ - struct inode * f_inode; - struct file_operations * f_op; - unsigned long f_version; - void *private_data; /* needed for tty driver, and maybe others */ + struct file *f_next, **f_pprev; + struct inode *f_inode; + struct file_operations *f_op; + mode_t f_mode; + loff_t f_pos; + unsigned short f_count, f_flags; + unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; + + /* pid or -pgrp where SIGIO should be sent */ + int f_owner; + + unsigned long f_version; + + /* needed for tty driver, and maybe others */ + void *private_data; }; #define FL_POSIX 1 @@ -584,7 +598,7 @@ extern int fs_may_umount(kdev_t dev, struct inode * mount_root); extern int fs_may_remount_ro(kdev_t dev); -extern struct file *first_file; +extern struct file *inuse_filps; extern struct super_block super_blocks[NR_SUPER]; extern void refile_buffer(struct buffer_head * buf); diff -u --recursive --new-file v2.1.36/linux/include/linux/lp_m68k.h linux/include/linux/lp_m68k.h --- v2.1.36/linux/include/linux/lp_m68k.h Fri Dec 20 01:20:04 1996 +++ linux/include/linux/lp_m68k.h Thu May 1 12:05:02 1997 @@ -91,7 +91,8 @@ LP_UNKNOWN = 0, LP_AMIGA = 1, LP_ATARI = 2, -LP_MFC = 3 +LP_MFC = 3, +LP_IOEXT = 4 }; /* @@ -105,10 +106,10 @@ int (*lp_is_busy)(int); int (*lp_has_pout)(int); int (*lp_is_online)(int); - int (*lp_my_interrupt)(int); + int (*lp_dummy)(int); int (*lp_ioctl)(int, unsigned int, unsigned long); - void (*lp_open)(void); /* for module use counter */ - void (*lp_release)(void); /* for module use counter */ + int (*lp_open)(int); /* for module use counter */ + void (*lp_release)(int); /* for module use counter */ int flags; /*for BUSY... */ unsigned int chars; /*busy timeout */ unsigned int time; /*wait time */ @@ -124,7 +125,7 @@ extern struct lp_struct *lp_table[MAX_LP]; extern unsigned int lp_irq; -void lp_interrupt(int, void *, struct pt_regs *); +void lp_interrupt(int dev); int lp_init(void); int register_parallel(struct lp_struct *, int); void unregister_parallel(int); diff -u --recursive --new-file v2.1.36/linux/include/linux/major.h linux/include/linux/major.h --- v2.1.36/linux/include/linux/major.h Thu Dec 19 01:03:37 1996 +++ linux/include/linux/major.h Thu May 1 12:05:02 1997 @@ -70,6 +70,7 @@ #define RISCOM8_NORMAL_MAJOR 48 #define RISCOM8_CALLOUT_MAJOR 49 #define MKISS_MAJOR 55 +#define DSP56K_MAJOR 55 /* DSP56001 processor device */ /* * Tests for SCSI devices. diff -u --recursive --new-file v2.1.36/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.1.36/linux/include/linux/mm.h Wed Apr 23 19:01:29 1997 +++ linux/include/linux/mm.h Thu May 8 13:53:31 1997 @@ -37,18 +37,15 @@ unsigned long vm_end; pgprot_t vm_page_prot; unsigned short vm_flags; -/* AVL tree of VM areas per task, sorted by address */ - short vm_avl_height; - struct vm_area_struct * vm_avl_left; - struct vm_area_struct * vm_avl_right; -/* linked list of VM areas per task, sorted by address */ - struct vm_area_struct * vm_next; -/* for areas with inode, the circular list inode->i_mmap */ -/* for shm areas, the circular list of attaches */ -/* otherwise unused */ - struct vm_area_struct * vm_next_share; - struct vm_area_struct * vm_prev_share; -/* more */ + struct vm_area_struct *vm_next; + struct vm_area_struct **vm_pprev; + + /* For areas with inode, the list inode->i_mmap, for shm areas, + * the list of attaches, otherwise unused. + */ + struct vm_area_struct *vm_next_share; + struct vm_area_struct **vm_pprev_share; + struct vm_operations_struct * vm_ops; unsigned long vm_offset; struct inode * vm_inode; @@ -279,8 +276,6 @@ unsigned long prot, unsigned long flags, unsigned long off); extern void merge_segments(struct mm_struct *, unsigned long, unsigned long); extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *); -extern void remove_shared_vm_struct(struct vm_area_struct *); -extern void build_mmap_avl(struct mm_struct *); extern void exit_mmap(struct mm_struct *); extern int do_munmap(unsigned long, size_t); extern unsigned long get_unmapped_area(unsigned long, unsigned long); @@ -325,38 +320,30 @@ return 0; } -#define avl_empty (struct vm_area_struct *) NULL - /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ static inline struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr) { - struct vm_area_struct * result = NULL; + struct vm_area_struct *vma = NULL; if (mm) { - struct vm_area_struct ** next = &mm->mmap_avl; - for (;;) { - struct vm_area_struct *tree = *next; - if (tree == avl_empty) - break; - next = &tree->vm_avl_right; - if (tree->vm_end <= addr) - continue; - next = &tree->vm_avl_left; - result = tree; - if (tree->vm_start <= addr) - break; + /* Check the cache first. */ + vma = mm->mmap_cache; + if(!vma || (vma->vm_end <= addr) || (vma->vm_start > addr)) { + vma = mm->mmap; + while(vma && vma->vm_end <= addr) + vma = vma->vm_next; + mm->mmap_cache = vma; } } - return result; + return vma; } /* Look up the first VMA which intersects the interval start_addr..end_addr-1, NULL if none. Assume start_addr < end_addr. */ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr) { - struct vm_area_struct * vma; + struct vm_area_struct * vma = find_vma(mm,start_addr); - vma = find_vma(mm,start_addr); if (vma && end_addr <= vma->vm_start) vma = NULL; return vma; diff -u --recursive --new-file v2.1.36/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.36/linux/include/linux/proc_fs.h Sun Apr 13 10:18:22 1997 +++ linux/include/linux/proc_fs.h Thu May 8 13:53:31 1997 @@ -162,6 +162,7 @@ PROC_SCSI_7000FASST, PROC_SCSI_IBMMCA, PROC_SCSI_EATA2X, + PROC_SCSI_DC390T, PROC_SCSI_AM53C974, PROC_SCSI_SSC, PROC_SCSI_NCR53C406A, diff -u --recursive --new-file v2.1.36/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.36/linux/include/linux/sched.h Wed Apr 23 19:01:29 1997 +++ linux/include/linux/sched.h Thu May 8 13:53:31 1997 @@ -1,14 +1,6 @@ #ifndef _LINUX_SCHED_H #define _LINUX_SCHED_H -/* - * define DEBUG if you want the wait-queues to have some extra - * debugging code. It's not normally used, but might catch some - * wait-queue coding errors. - * - * #define DEBUG - */ - #include /* for HZ */ extern unsigned long event; @@ -149,29 +141,27 @@ } struct mm_struct { - int count; + struct vm_area_struct *mmap, *mmap_cache; pgd_t * pgd; + int count; + struct semaphore mmap_sem; unsigned long context; unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack, start_mmap; unsigned long arg_start, arg_end, env_start, env_end; unsigned long rss, total_vm, locked_vm; unsigned long def_flags; - struct vm_area_struct * mmap; - struct vm_area_struct * mmap_avl; - struct semaphore mmap_sem; }; -#define INIT_MM { \ - 1, \ - swapper_pg_dir, \ - 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, 0, \ - 0, 0, 0, \ - 0, \ - &init_mmap, &init_mmap, MUTEX } +#define INIT_MM { \ + &init_mmap, NULL, swapper_pg_dir, 1, \ + MUTEX, \ + 0, \ + 0, 0, 0, 0, \ + 0, 0, 0, 0, \ + 0, 0, 0, 0, \ + 0, 0, 0, \ + 0 } struct signal_struct { atomic_t count; @@ -200,8 +190,6 @@ struct linux_binfmt *binfmt; struct task_struct *next_task, *prev_task; struct task_struct *next_run, *prev_run; - unsigned long saved_kernel_stack; - unsigned long kernel_stack_page; int exit_code, exit_signal; /* ??? */ unsigned long personality; @@ -222,6 +210,14 @@ * p->p_pptr->pid) */ struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; + + /* PID hash table linkage. */ + struct task_struct *pidhash_next; + struct task_struct **pidhash_pprev; + + /* Pointer to task[] array linkage. */ + struct task_struct **tarray_ptr; + struct wait_queue *wait_chldexit; /* for wait4() */ unsigned short uid,euid,suid,fsuid; unsigned short gid,egid,sgid,fsgid; @@ -260,6 +256,7 @@ /* signal handlers */ struct signal_struct *sig; /* SMP state */ + int has_cpu; int processor; int last_processor; int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ @@ -294,6 +291,16 @@ #define DEF_PRIORITY (20*HZ/100) /* 200 ms time slices */ +/* Note: This is very ugly I admit. But some versions of gcc will + * dump core when an empty structure constant is parsed at + * the end of a large top level structure initialization. -DaveM + */ +#ifdef __SMP__ +#define INIT_LOCKS SPIN_LOCK_UNLOCKED +#else +#define INIT_LOCKS +#endif + /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -304,11 +311,13 @@ /* exec domain */&default_exec_domain, \ /* binfmt */ NULL, \ /* schedlink */ &init_task,&init_task, &init_task, &init_task, \ -/* stack */ 0,(unsigned long) &init_kernel_stack, \ /* ec,brk... */ 0,0,0,0,0, \ /* pid etc.. */ 0,0,0,0,0, \ /* suppl grps*/ 0, {0,}, \ -/* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \ +/* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \ +/* pidhash */ NULL, NULL, \ +/* tarray */ &task[0], \ +/* chld wait */ NULL, \ /* uid etc */ 0,0,0,0,0,0,0,0, \ /* timeout */ 0,SCHED_OTHER,0,0,0,0,0,0,0, \ /* timer */ { NULL, NULL, 0, 0, it_real_fn }, \ @@ -326,14 +335,88 @@ /* files */ &init_files, \ /* mm */ &init_mm, \ /* signals */ &init_signals, \ -/* SMP */ 0,0,0, \ +/* SMP */ 0,0,0,0, \ +/* locks */ INIT_LOCKS \ } +union task_union { + struct task_struct task; + unsigned long stack[2048]; +}; + +extern union task_union init_task_union; + extern struct mm_struct init_mm; -extern struct task_struct init_task; extern struct task_struct *task[NR_TASKS]; extern struct task_struct *last_task_used_math; +extern struct task_struct **tarray_freelist; +extern spinlock_t taskslot_lock; + +extern __inline__ void add_free_taskslot(struct task_struct **t) +{ + spin_lock(&taskslot_lock); + *t = (struct task_struct *) tarray_freelist; + tarray_freelist = t; + spin_unlock(&taskslot_lock); +} + +extern __inline__ struct task_struct **get_free_taskslot(void) +{ + struct task_struct **tslot; + + spin_lock(&taskslot_lock); + if((tslot = tarray_freelist) != NULL) + tarray_freelist = (struct task_struct **) *tslot; + spin_unlock(&taskslot_lock); + + return tslot; +} + +/* PID hashing. */ +#define PIDHASH_SZ (NR_TASKS >> 2) +extern struct task_struct *pidhash[PIDHASH_SZ]; +extern spinlock_t pidhash_lock; + +#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) + +extern __inline__ void hash_pid(struct task_struct *p) +{ + struct task_struct **htable = &pidhash[pid_hashfn(p->pid)]; + + spin_lock(&pidhash_lock); + if((p->pidhash_next = *htable) != NULL) + (*htable)->pidhash_pprev = &p->pidhash_next; + *htable = p; + p->pidhash_pprev = htable; + spin_unlock(&pidhash_lock); +} + +extern __inline__ void unhash_pid(struct task_struct *p) +{ + spin_lock(&pidhash_lock); + if(p->pidhash_next) + p->pidhash_next->pidhash_pprev = p->pidhash_pprev; + *p->pidhash_pprev = p->pidhash_next; + spin_unlock(&pidhash_lock); +} + +extern __inline__ struct task_struct *find_task_by_pid(int pid) +{ + struct task_struct **htable = &pidhash[pid_hashfn(pid)]; + struct task_struct *p; + + spin_lock(&pidhash_lock); + for(p = *htable; p && p->pid != pid; p = p->pidhash_next) + ; + spin_unlock(&pidhash_lock); + + return p; +} + +/* per-UID process charging. */ +extern int charge_uid(struct task_struct *p, int count); + #include extern unsigned long volatile jiffies; @@ -425,15 +508,15 @@ wait->next = next; } -extern spinlock_t waitqueue_lock; +extern rwlock_t waitqueue_lock; extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) { unsigned long flags; - spin_lock_irqsave(&waitqueue_lock, flags); + write_lock_irqsave(&waitqueue_lock, flags); __add_wait_queue(p, wait); - spin_unlock_irqrestore(&waitqueue_lock, flags); + write_unlock_irqrestore(&waitqueue_lock, flags); } extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) @@ -454,9 +537,9 @@ { unsigned long flags; - spin_lock_irqsave(&waitqueue_lock, flags); + write_lock_irqsave(&waitqueue_lock, flags); __remove_wait_queue(p, wait); - spin_unlock_irqrestore(&waitqueue_lock, flags); + write_unlock_irqrestore(&waitqueue_lock, flags); } extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p) diff -u --recursive --new-file v2.1.36/linux/include/linux/serial.h linux/include/linux/serial.h --- v2.1.36/linux/include/linux/serial.h Tue Mar 4 10:25:26 1997 +++ linux/include/linux/serial.h Thu May 8 13:53:31 1997 @@ -46,7 +46,8 @@ #define PORT_16650 6 #define PORT_16650V2 7 #define PORT_16750 8 -#define PORT_MAX 8 +#define PORT_STARTECH 9 +#define PORT_MAX 9 struct serial_uart_config { char *name; diff -u --recursive --new-file v2.1.36/linux/include/linux/skbuff.h linux/include/linux/skbuff.h --- v2.1.36/linux/include/linux/skbuff.h Wed Apr 23 19:01:29 1997 +++ linux/include/linux/skbuff.h Thu May 8 13:53:31 1997 @@ -123,6 +123,9 @@ #endif }; +/* These are just the default values. This is run time configurable. + * FIXME: Probably the config option should go away. -- erics + */ #ifdef CONFIG_SKB_LARGE #define SK_WMEM_MAX 65535 #define SK_RMEM_MAX 65535 diff -u --recursive --new-file v2.1.36/linux/include/linux/slab.h linux/include/linux/slab.h --- v2.1.36/linux/include/linux/slab.h Thu Feb 6 02:53:33 1997 +++ linux/include/linux/slab.h Thu May 8 13:53:31 1997 @@ -54,6 +54,7 @@ /* System wide slabs. */ extern kmem_cache_t *vm_area_cachep; +extern kmem_cache_t *mm_cachep; #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.36/linux/include/linux/smp.h linux/include/linux/smp.h --- v2.1.36/linux/include/linux/smp.h Sun Jan 26 05:36:05 1997 +++ linux/include/linux/smp.h Thu May 1 12:05:06 1997 @@ -47,6 +47,7 @@ #define smp_num_cpus 1 #define smp_processor_id() 0 +#define hard_smp_processor_id() 0 #define smp_message_pass(t,m,d,w) #define smp_threads_ready 1 #define kernel_lock() diff -u --recursive --new-file v2.1.36/linux/include/linux/socket.h linux/include/linux/socket.h --- v2.1.36/linux/include/linux/socket.h Thu Mar 27 14:40:11 1997 +++ linux/include/linux/socket.h Sun May 4 20:16:47 1997 @@ -3,8 +3,8 @@ #include /* arch-dependent defines */ #include /* the SIOCxxx I/O controls */ -#include /* iovec support */ #include /* pid_t */ +#include /* iovec support */ typedef unsigned short sa_family_t; diff -u --recursive --new-file v2.1.36/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.1.36/linux/include/linux/sysctl.h Wed Apr 23 19:01:29 1997 +++ linux/include/linux/sysctl.h Thu May 1 12:05:06 1997 @@ -104,6 +104,13 @@ /* /proc/sys/net/core */ +enum +{ + NET_CORE_WMEM_MAX=1, + NET_CORE_RMEM_MAX, + NET_CORE_WMEM_DEFAULT, + NET_CORE_RMEM_DEFAULT, +}; /* /proc/sys/net/ethernet */ diff -u --recursive --new-file v2.1.36/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.36/linux/include/linux/tty.h Fri Apr 4 08:52:26 1997 +++ linux/include/linux/tty.h Thu May 8 13:53:31 1997 @@ -288,6 +288,7 @@ extern int pty_init(void); extern int tty_init(void); extern int pcxe_init(void); +extern int pc_init(void); extern int vcs_init(void); extern int cy_init(void); extern int stl_init(void); @@ -330,10 +331,14 @@ /* serial.c */ extern long serial_console_init(long kmem_start, long kmem_end); - + /* pcxx.c */ extern int pcxe_open(struct tty_struct *tty, struct file *filp); + +/* epca.c */ + +extern int pc_open(struct tty_struct *tty, struct file *filp); /* console.c */ diff -u --recursive --new-file v2.1.36/linux/include/linux/zorro.h linux/include/linux/zorro.h --- v2.1.36/linux/include/linux/zorro.h Wed Apr 23 19:01:29 1997 +++ linux/include/linux/zorro.h Sun Apr 27 15:13:50 1997 @@ -637,642 +637,3 @@ #endif /* __KERNEL__ */ #endif /* __ZORRO_H */ -/* - * linux/zorro.h -- Amiga AutoConfig (Zorro) Expansion Device Definitions - * - * Copyright (C) 1995 Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef __ZORRO_H -#define __ZORRO_H - -#ifndef __ASSEMBLY__ - -/* - * Defined Board Manufacturers - * - * Please update arch/m68k/amiga/zorro.c if you make changes here - * Many IDs were obtained from ExpName/Identify ((C) Richard Körber) - * and by looking at the NetBSD-Amiga kernel sources - */ - -#define MANUF_PACIFIC (0x00D3) /* Pacific Peripherals */ -#define PROD_SE_2000_A500 (0x00) /* SE 2000 A500 */ -#define PROD_PACIFIC_HD (0x0A) /* HD Controller */ - -#define MANUF_KUPKE (0x00DD) /* Kupke */ -#define PROD_GOLEM_BOX_2 (0x00) /* Golem RAM Box 2MB */ - -#define MANUF_MEMPHIS (0x0100) /* Memphis */ -#define PROD_STORMBRINGER (0x00) /* Stormbringer */ - -#define MANUF_3_STATE (0x0200) /* 3-State */ -#define PROD_MEGAMIX_2000 (0x02) /* Megamix 2000 RAM */ - -#define MANUF_COMMODORE2 (0x0201) /* Commodore Braunschweig */ -#define PROD_A2088 (0x01) /* CBM A2088 XT Bridgeboard */ -#define PROD_A2286 (0x02) /* CBM A2286 AT Bridgeboard */ -#define PROD_A4091_2 (0x54) /* CBM A4091 SCSI Controller */ -#define PROD_A2386SX (0x67) /* CBM A2386-SX Bridgeboard */ - -#define MANUF_COMMODORE (0x0202) /* Commodore West Chester */ -#define PROD_A2090A (0x01) /* CBM A2090/A2090A HD Controller */ -#define PROD_A590 (0x02) /* CBM A590 SCSI Controller */ -#define PROD_A2091 (0x03) /* CBM A2091 SCSI Controller */ -#define PROD_A2090B (0x04) /* CBM A2090B 2090 Autoboot Card */ -#define PROD_ARCNET (0x09) /* CBM A2060 Arcnet Card */ -#define PROD_CBMRAM (0x0A) /* CBM A2052/58.RAM | 590/2091.RAM */ -#define PROD_A560RAM (0x20) /* CBM A560 Memory Module */ -#define PROD_A2232PROTO (0x45) /* CBM A2232 Serial Prototype */ -#define PROD_A2232 (0x46) /* CBM A2232 Serial Production */ -#define PROD_A2620 (0x50) /* CBM A2620 68020/RAM Card */ -#define PROD_A2630 (0x51) /* CBM A2630 68030/RAM Card */ -#define PROD_A4091 (0x54) /* CBM A4091 SCSI Controller */ -#define PROD_A2065_2 (0x5A) /* A2065 Ethernet Card */ -#define PROD_ROMULATOR (0x60) /* CBM Romulator Card */ -#define PROD_A3000TESTFIX (0x61) /* CBM A3000 Test Fixture */ -#define PROD_A2386SX_2 (0x67) /* A2386-SX Bridgeboard */ -#define PROD_A2065 (0x70) /* CBM A2065 Ethernet Card */ - -#define MANUF_COMMODORE3 (0x0203) /* Commodore West Chester */ -#define PROD_A2090A_CM (0x03) /* A2090A Combitec/MacroSystem */ - -#define MANUF_KCS (0x02FF) /* Kolff Computer Supplies */ -#define PROD_POWER_BOARD (0x00) /* KCS Power PC Board */ - -#define MANUF_CARDCO (0x03EC) /* Cardco */ -#define PROD_KRONOS_2000_SCSI (0x04) /* Kronos 2000 SCSI Controller */ -#define PROD_A1000_SCSI (0x0C) /* A1000 SCSI Controller */ -#define PROD_ESCORT_SCSI (0x0E) /* Escort SCSI Controller */ -#define PROD_CC_A2410 (0xF5) /* Cardco A2410 Hires Graphics Card */ - -#define MANUF_A_SQUARED (0x03ED) /* A-Squared */ -#define PROD_LIVE_2000 (0x01) /* Live! 2000 */ - -#define MANUF_COMSPEC (0x03EE) /* ComSpec Communications */ -#define PROD_AX2000 (0x01) /* AX2000 */ - -#define MANUF_ANAKIN (0x03F1) /* Anakin */ -#define PROD_EASYL (0x01) /* Easyl Tablet */ - -#define MANUF_MICROBOTICS (0x03F2) /* MicroBotics */ -#define PROD_STARBOARD_II (0x00) /* StarBoard II */ -#define PROD_STARDRIVE (0x02) /* StarDrive */ -#define PROD_8_UP_A (0x03) /* 8-Up (Rev A) */ -#define PROD_8_UP_Z (0x04) /* 8-Up (Rev Z) */ -#define PROD_DELTA_RAM (0x20) /* Delta Card RAM */ -#define PROD_8_STAR_RAM (0x40) /* 8-Star RAM */ -#define PROD_8_STAR (0x41) /* 8-Star */ -#define PROD_VXL_RAM (0x44) /* VXL RAM */ -#define PROD_VXL_30 (0x45) /* VXL-30 Turbo Board */ -#define PROD_DELTA (0x60) /* Delta Card */ -#define PROD_MBX_1200 (0x81) /* MBX 1200 */ -#define PROD_HARDFRAME_2000 (0x9E) /* Hardframe 2000 */ -#define PROD_MBX_1200_2 (0xC1) /* MBX 1200 */ - -#define MANUF_ACCESS (0x03F4) /* Access Associates */ - -#define MANUF_EXPANSION_TECH (0x03F6) /* Expansion Technologies */ - -#define MANUF_ASDG (0x03FF) /* ASDG */ -#define PROD_ASDG_MEMORY (0x01) /* Memory Expansion */ -#define PROD_ASDG_MEMORY_2 (0x02) /* Memory Expansion */ -#define PROD_LAN_ROVER (0xFE) /* Lan Rover Ethernet */ -#define PROD_TWIN_X (0xFF) /* Twin-X Serial Card */ - -#define MANUF_IMTRONICS (0x0404) /* Imtronics */ -#define PROD_HURRICANE_2800 (0x39) /* Hurricane 2800 68030 */ -#define PROD_HURRICANE_2800_2 (0x57) /* Hurricane 2800 68030 */ - -#define MANUF_UNIV_OF_LOWELL (0x0406) /* University of Lowell */ -#define PROD_A2410 (0x00) /* CBM A2410 Hires Graphics Card */ - -#define MANUF_AMERISTAR (0x041D) /* Ameristar */ -#define PROD_AMERISTAR2065 (0x01) /* A2065 Ethernet Card */ -#define PROD_A560 (0x09) /* Arcnet Card */ -#define PROD_A4066 (0x0A) /* A4066 Ethernet Card */ - -#define MANUF_SUPRA (0x0420) /* Supra */ -#define PROD_SUPRADRIVE_4x4 (0x01) /* SupraDrive 4x4 SCSI Controller */ -#define PROD_SUPRA_2000 (0x03) /* 2000 DMA HD */ -#define PROD_SUPRA_500 (0x05) /* 500 HD/RAM */ -#define PROD_SUPRA_500XP (0x09) /* 500XP/2000 RAM */ -#define PROD_SUPRA_500RX (0x0A) /* 500RX/2000 RAM */ -#define PROD_SUPRA_2400ZI (0x0B) /* 2400zi Modem */ -#define PROD_WORDSYNC (0x0C) /* Supra Wordsync SCSI Controller */ -#define PROD_WORDSYNC_II (0x0D) /* Supra Wordsync II SCSI Controller */ -#define PROD_SUPRA_2400ZIPLUS (0x10) /* 2400zi+ Modem */ - -#define MANUF_CSA (0x0422) /* Computer Systems Ass. */ -#define PROD_MAGNUM (0x11) /* Magnum 40 SCSI Controller */ -#define PROD_12GAUGE (0x15) /* 12 Gauge SCSI Controller */ - -#define MANUF_MTEC2 (0x0502) /* M-Tech */ -#define PROD_AT500_2 (0x03) /* AT500 RAM */ - -#define MANUF_GVP3 (0x06E1) /* Great Valley Products */ -#define PROD_IMPACT (0x08) /* Impact SCSI/Memory */ - -#define MANUF_BYTEBOX (0x07DA) /* ByteBox */ -#define PROD_BYTEBOX_A500 (0x00) /* A500 */ - -#define MANUF_HACKER (0x07DB) /* Test only: no product definitions */ - -#define MANUF_POWER_COMPUTING (0x07DC) /* Power Computing (DKB) */ -#define PROD_DKB_3128 (0x0E) /* DKB 3128 RAM */ -#define PROD_RAPID_FIRE (0x0F) /* Rapid Fire SCSI Controller */ -#define PROD_DKB_1202 (0x10) /* DKB 1202 RAM */ -#define PROD_VIPER_II_COBRA (0x12) /* Viper II Turbo Board (DKB Cobra) */ -#define PROD_WILDFIRE_060 (0x17) /* WildFire 060 Turbo Board */ -#define PROD_WILDFIRE_060_2 (0xFF) /* WildFire 060 Turbo Board */ - -#define MANUF_GVP (0x07E1) /* Great Valley Products */ -#define PROD_IMPACT_I_4K (0x01) /* Impact Series-I SCSI 4K */ -#define PROD_IMPACT_I_16K_2 (0x02) /* Impact Series-I SCSI 16K/2 */ -#define PROD_IMPACT_I_16K_3 (0x03) /* Impact Series-I SCSI 16K/3 */ -#define PROD_IMPACT_3001_IDE (0x08) /* Impact 3001 IDE */ -#define PROD_IMPACT_3001_RAM (0x09) /* Impact 3001 RAM */ -#define PROD_GVPIISCSI (0x0B) /* GVP Series II SCSI Controller */ -#define PROD_GVPIISCSI_2 (0x09) /* evidence that the driver works - for this product code also */ -#define PROD_GVPIIRAM (0x0A) /* GVP Series II RAM */ -#define PROD_GVP (0x0B) /* This code is used by a wide range of - GVP products - use the epc to - identify it correctly */ -#define PROD_GVP_A2000_030 (0x0D) /* GVP A2000 68030 Turbo Board */ -#define PROD_IMPACT_3001_IDE_2 (0x0D) /* Impact 3001 IDE */ -#define PROD_GFORCE_040_SCSI (0x16) /* GForce 040 with SCSI (new) */ -#define PROD_GVPIV_24 (0x20) /* GVP IV-24 Graphics Board */ -#define PROD_GFORCE_040 (0xFF) /* GForce 040 Turbo Board */ -/* #define PROD_GVPIO_EXT (0xFF)*/ /* GVP I/O Extender */ - -#define MANUF_SYNERGY (0x07E5) /* Synergy */ - -#define MANUF_XETEC (0x07E6) /* Xetec */ -#define PROD_FASTCARD_SCSI (0x01) /* FastCard SCSI Controller */ -#define PROD_FASTCARD_RAM (0x02) /* FastCard RAM */ - -#define MANUF_PPI (0x07EA) /* Progressive Peripherals Inc. */ -#define PROD_MERCURY (0x00) /* Mercury Turbo Board */ -#define PROD_PPS_A3000_040 (0x01) /* PP&S A3000 68040 Turbo Board */ -#define PROD_PPS_A2000_040 (0x69) /* PP&S A2000 68040 Turbo Board */ -#define PROD_ZEUS (0x96) /* Zeus SCSI Controller */ -#define PROD_PPS_A500_040 (0xBB) /* PP&S A500 68040 Turbo Board */ - -#define MANUF_XEBEC (0x07EC) /* Xebec */ - -#define MANUF_SPIRIT (0x07F2) /* Spirit */ -#define PROD_HDA_506 (0x04) /* HDA 506 Harddisk */ -#define PROD_OCTABYTE_RAM (0x06) /* OctaByte RAM */ - -#define MANUF_BSC (0x07FE) /* BSC */ -#define PROD_ALF_3_SCSI (0x03) /* BSC ALF 3 SCSI Controller */ - -#define MANUF_BSC3 (0x0801) /* BSC */ -#define PROD_ALF_2_SCSI (0x01) /* ALF 2 SCSI Controller */ -#define PROD_ALF_2_SCSI_2 (0x02) /* ALF 2 SCSI Controller */ -#define PROD_ALF_3_SCSI_2 (0x03) /* ALF 3 SCSI Controller */ - -#define MANUF_C_LTD (0x0802) /* C Ltd. */ -#define PROD_KRONOS_SCSI (0x04) /* Kronos SCSI Controller */ -#define PROD_A1000_SCSI_2 (0x0C) /* A1000 SCSI Controller */ - -#define MANUF_JOCHHEIM (0x0804) /* Jochheim */ -#define PROD_JOCHHEIM_RAM (0x01) /* Jochheim RAM */ - -#define MANUF_CHECKPOINT (0x0807) /* Checkpoint Technologies */ -#define PROD_SERIAL_SOLUTION (0x00) /* Serial Solution */ - -#define MANUF_ICD (0x0817) /* ICD */ -#define PROD_ADVANTAGE_2000 (0x01) /* Advantage 2000 SCSI Controller */ - -#define MANUF_KUPKE2 (0x0819) /* Kupke */ -#define PROD_KUPKE_SCSI_II (0x02) /* Golem SCSI-II Controller */ -#define PROD_GOLEM_BOX (0x03) /* Golem Box */ -#define PROD_KUPKE_TURBO (0x04) /* 030/882 Turbo Board */ -#define PROD_KUPKE_SCSI_AT (0x05) /* SCSI/AT Controller */ - -#define MANUF_GVP4 (0x081D) /* Great Valley Products */ -#define PROD_A2000_RAM8 (0x09) /* A2000-RAM8/2 */ - -#define MANUF_INTERWORKS_NET (0x081E) /* Interworks Network */ - -#define MANUF_HARDITAL (0x0820) /* Hardital Synthesis */ -#define PROD_TQM (0x14) /* TQM 68030+68882 Turbo Board */ - -#define MANUF_BSC2 (0x082C) /* BSC */ -#define PROD_OKTAGON_SCSI (0x05) /* BSC Oktagon 2008 SCSI Controller */ -#define PROD_TANDEM (0x06) /* BSC Tandem AT-2008/508 IDE */ -#define PROD_ALPHA_RAM_1200 (0x07) /* Alpha RAM 1200 */ -#define PROD_OKTAGON_RAM (0x08) /* BSC Oktagon 2008 RAM */ -#define PROD_MULTIFACE_I (0x10) /* Alfa Data MultiFace I */ -#define PROD_MULTIFACE_II (0x11) /* Alfa Data MultiFace II */ -#define PROD_MULTIFACE_III (0x12) /* Alfa Data MultiFace III */ -#define PROD_BSC_FRAEMBUFFER (0x20) /* Framebuffer */ -#define PROD_GRAFFITI_RAM (0x21) /* Graffiti Graphics Board */ -#define PROD_GRAFFITI_REG (0x22) -#define PROD_ISDN_MASTERCARD (0x40) /* BSC ISDN MasterCard */ -#define PROD_ISDN_MASTERCARD_2 (0x41) /* BSC ISDN MasterCard II */ - -#define MANUF_ADV_SYS_SOFT (0x0836) /* Advanced Systems & Software */ -#define PROD_NEXUS_SCSI (0x01) /* Nexus SCSI Controller */ -#define PROD_NEXUS_RAM (0x08) /* Nexus RAM */ - -#define MANUF_IMPULSE (0x0838) /* Impulse */ -#define PROD_FIRECRACKER_24 (0x00) /* FireCracker 24 */ - -#define MANUF_IVS (0x0840) /* IVS */ -#define PROD_GRANDSLAM_PIC_2 (0x02) /* GrandSlam PIC 2 RAM */ -#define PROD_GRANDSLAM_PIC_1 (0x04) /* GrandSlam PIC 1 RAM */ -#define PROD_IVS_OVERDRIVE (0x10) /* OverDrive HD */ -#define PROD_TRUMPCARD_CLASSIC (0x30) /* Trumpcard Classic SCSI Controller */ -#define PROD_TRUMPCARD_PRO (0x34) /* Trumpcard Pro SCSI Controller */ -#define PROD_META_4 (0x40) /* Meta-4 RAM */ -#define PROD_WAVETOOLS (0xBF) /* Wavetools Sound Board */ -#define PROD_VECTOR (0xF3) /* Vector SCSI Controller */ -#define PROD_VECTOR_2 (0xF4) /* Vector SCSI Controller */ - -#define MANUF_VECTOR (0x0841) /* Vector */ -#define PROD_CONNECTION (0xE3) /* Connection Serial IO */ - -#define MANUF_XPERT_PRODEV (0x0845) /* XPert/ProDev */ -#define PROD_VISIONA_RAM (0x01) /* Visiona Graphics Board */ -#define PROD_VISIONA_REG (0x02) -#define PROD_MERLIN_RAM (0x03) /* Merlin Graphics Board */ -#define PROD_MERLIN_REG (0x04) -#define PROD_MERLIN_REG_2 (0xC9) - -#define MANUF_HYDRA_SYSTEMS (0x0849) /* Hydra Systems */ -#define PROD_AMIGANET (0x01) /* Amiganet Board */ - -#define MANUF_SUNRIZE (0x084F) /* Sunrize Industries */ -#define PROD_AD1012 (0x01) /* AD1012 Sound Board */ -#define PROD_AD516 (0x02) /* AD516 Sound Board */ -#define PROD_DD512 (0x03) /* DD512 Sound Board */ - -#define MANUF_TRICERATOPS (0x0850) /* Triceratops */ -#define PROD_TRICERATOPS (0x01) /* Triceratops Multi I/O Board */ - -#define MANUF_APPLIED_MAGIC (0x0851) /* Applied Magic Inc */ -#define PROD_DMI_RESOLVER (0x01) /* DMI Resolver Graphics Board */ -#define PROD_DIGITAL_BCASTER (0x06) /* Digital Broadcaster */ - -#define MANUF_GFX_BASE (0x085E) /* GFX-Base */ -#define PROD_GDA_1_RAM (0x00) /* GDA-1 Graphics Board */ -#define PROD_GDA_1_REG (0x01) - -#define MANUF_ROCTEC (0x0860) /* RocTec */ -#define PROD_RH_800C (0x01) /* RH 800C Hard Disk Controller */ -#define PROD_RH_800C_RAM (0x01) /* RH 800C RAM */ - -#define MANUF_HELFRICH1 (0x0861) /* Helfrich */ -#define PROD_RAINBOW3 (0x21) /* Rainbow3 Graphics Board */ - -#define MANUF_SW_RESULT_ENTS (0x0866) /* Software Result Enterprises */ -#define PROD_GG2PLUS (0x01) /* GG2+ Bus Converter */ - -#define MANUF_MASOBOSHI (0x086D) /* Masoboshi */ -#define PROD_MASTER_CARD_RAM (0x03) /* Master Card RAM */ -#define PROD_MASTER_CARD_SCSI (0x04) /* Master Card SCSI Controller */ -#define PROD_MVD_819 (0x07) /* MVD 819 */ - -#define MANUF_DELACOMP (0x0873) /* DelaComp */ -#define PROD_DELACOMP_RAM_2000 (0x01) /* RAM Expansion 2000 */ - -#define MANUF_VILLAGE_TRONIC (0x0877) /* Village Tronic */ -#define PROD_DOMINO_RAM (0x01) /* Domino Graphics Board */ -#define PROD_DOMINO_REG (0x02) -#define PROD_PICASSO_II_RAM (0x0B) /* Picasso II/II+ Graphics Board */ -#define PROD_PICASSO_II_REG (0x0C) -#define PROD_PICASSO_II_SEGM (0x0D) /* Picasso II/II+ (Segmented Mode) */ -#define PROD_PICASSO_IV (0x15) /* Picassio IV Graphics Board */ -#define PROD_PICASSO_IV_2 (0x16) -#define PROD_PICASSO_IV_3 (0x17) -#define PROD_PICASSO_IV_4 (0x18) -#define PROD_ARIADNE (0xC9) /* Ariadne Ethernet */ - -#define MANUF_UTILITIES_ULTD (0x087B) /* Utilities Unlimited */ -#define PROD_EMPLANT_DELUXE (0x15) /* Emplant Deluxe SCSI Controller */ -#define PROD_EMPLANT_DELUXE2 (0x20) /* Emplant Deluxe SCSI Controller */ - -#define MANUF_AMITRIX (0x0880) /* Amitrix */ -#define PROD_AMITRIX_MULTI_IO (0x01) /* Multi-IO */ -#define PROD_AMITRIX_CD_RAM (0x02) /* CD-RAM Memory */ - -#define MANUF_ARMAX (0x0885) /* ArMax */ -#define PROD_OMNIBUS (0x00) /* OmniBus Graphics Board */ - -#define MANUF_NEWTEK (0x088F) /* NewTek */ -#define PROD_VIDEOTOASTER (0x00) /* VideoToaster */ - -#define MANUF_MTEC (0x0890) /* M-Tech Germany */ -#define PROD_AT500 (0x01) /* AT500 IDE Controller */ -#define PROD_MTEC_68030 (0x03) /* 68030 Turbo Board */ -#define PROD_MTEC_68020I (0x06) /* 68020i Turbo Board */ -#define PROD_MTEC_T1230 (0x20) /* A1200 T68030/42 RTC Turbo Board */ -#define PROD_MTEC_RAM (0x22) /* MTEC 8MB RAM */ - -#define MANUF_GVP2 (0x0891) /* Great Valley Products */ -#define PROD_SPECTRUM_RAM (0x01) /* EGS 28/24 Spectrum Graphics Board */ -#define PROD_SPECTRUM_REG (0x02) - -#define MANUF_HELFRICH2 (0x0893) /* Helfrich */ -#define PROD_PICCOLO_RAM (0x05) /* Piccolo Graphics Board */ -#define PROD_PICCOLO_REG (0x06) -#define PROD_PEGGY_PLUS (0x07) /* PeggyPlus MPEG Decoder Board */ -#define PROD_VIDEOCRUNCHER (0x08) /* VideoCruncher */ -#define PROD_SD64_RAM (0x0A) /* SD64 Graphics Board */ -#define PROD_SD64_REG (0x0B) - -#define MANUF_MACROSYSTEMS (0x089B) /* MacroSystems USA */ -#define PROD_WARP_ENGINE (0x13) /* Warp Engine 40xx SCSI Controller */ - -#define MANUF_ELBOX (0x089E) /* ElBox Computer */ -#define PROD_ELBOX_1200 (0x06) /* Elbox 1200/4 RAM */ - -#define MANUF_HARMS_PROF (0x0A00) /* Harms Professional */ -#define PROD_HARMS_030_PLUS (0x10) /* 030 plus */ -#define PROD_3500_TURBO (0xD0) /* 3500 Turbo board */ - -#define MANUF_MICRONIK (0x0A50) /* Micronik */ -#define PROD_RCA_120 (0x0A) /* RCA 120 RAM */ - -#define MANUF_MEGA_MICRO (0x1000) /* MegaMicro */ -#define PROD_SCRAM_500_SCSI (0x03) /* SCRAM 500 SCSI Controller */ -#define PROD_SCRAM_500_RAM (0x04) /* SCRAM 500 RAM */ - -#define MANUF_IMTRONICS2 (0x1028) /* Imtronics */ -#define PROD_HURRICANE_2800_3 (0x39) /* Hurricane 2800 68030 */ -#define PROD_HURRICANE_2800_4 (0x57) /* Hurricane 2800 68030 */ - -#define MANUF_KUPKE3 (0x1248) /* Kupke */ -#define PROD_GOLEM_3000 (0x01) /* Golem HD 3000 */ - -#define MANUF_ITH (0x1388) /* ITH */ -#define PROD_ISDN_MASTER_II (0x01) /* ISDN-Master II */ - -#define MANUF_VMC (0x1389) /* VMC */ -#define PROD_ISDN_BLASTER_Z2 (0x01) /* ISDN Blaster Z2 */ -#define PROD_HYPERCOM_4 (0x02) /* HyperCom 4 */ - -#define MANUF_INFORMATION (0x157C) /* Information */ -#define PROD_ISDN_ENGINE_I (0x64) /* ISDN Engine I */ - -#define MANUF_VORTEX (0x2017) /* Vortex */ -#define PROD_GOLDEN_GATE_386SX (0x07) /* Golden Gate 80386SX Board */ -#define PROD_GOLDEN_GATE_RAM (0x08) /* Golden Gate RAM */ -#define PROD_GOLDEN_GATE_486 (0x09) /* Golden Gate 80486 Board */ - -#define MANUF_DATAFLYER (0x2062) /* DataFlyer */ -#define PROD_DATAFLYER_4000SXS (0x01) /* DataFlyer 4000SX SCSI Controller */ -#define PROD_DATAFLYER_4000SXR (0x02) /* DataFlyer 4000SX RAM */ - -#define MANUF_READYSOFT (0x2100) /* ReadySoft */ -#define PROD_AMAX (0x01) /* AMax II/IV */ - -#define MANUF_PHASE5 (0x2140) /* Phase5 */ -#define PROD_BLIZZARD_RAM (0x01) /* Blizzard RAM */ -#define PROD_BLIZZARD (0x02) /* Blizzard */ -#define PROD_BLIZZARD_1220_IV (0x06) /* Blizzard 1220-IV Turbo Board */ -#define PROD_FASTLANE_RAM (0x0A) /* FastLane RAM */ -#define PROD_FASTLANE_SCSI (0x0B) /* FastLane/Blizzard 1230-II SCSI/CyberSCSI */ -#define PROD_CYBERSTORM_SCSI (0x0C) /* Blizzard 1220/CyberStorm */ -#define PROD_BLIZZARD_1230_III (0x0D) /* Blizzard 1230-III Turbo Board */ -#define PROD_BLIZZARD_1230_IV (0x11) /* Blizzard 1230-IV/1260 Turbo Board */ -#define PROD_BLIZZARD_2060SCSI (0x18) /* Blizzard 2060 SCSI Controller */ -#define PROD_CYBERSTORM_II (0x19) /* CyberStorm Mk II */ -#define PROD_CYBERVISION (0x22) /* CyberVision64 Graphics Board */ -#define PROD_CYBERVISION3D_PRT (0x32) /* CyberVision64-3D Prototype */ -#define PROD_CYBERVISION3D (0x43) /* CyberVision64-3D Graphics Board */ - -#define MANUF_DPS (0x2169) /* DPS */ -#define PROD_DPS_PAR (0x01) /* Personal Animation Recorder */ - -#define MANUF_APOLLO2 (0x2200) /* Apollo */ -#define PROD_A620 (0x00) /* A620 68020 Accelerator */ -#define PROD_A620_2 (0x01) /* A620 68020 Accelerator */ - -#define MANUF_APOLLO (0x2222) /* Apollo */ -#define PROD_AT_APOLLO (0x22) /* AT-Apollo */ -#define PROD_APOLLO_TURBO (0x23) /* Apollo Turbo Board */ - -#define MANUF_PETSOFF (0x38A5) /* Petsoff LP */ -#define PROD_DELFINA (0x00) /* Delfina DSP */ - -#define MANUF_UWE_GERLACH (0x3FF7) /* Uwe Gerlach */ -#define PROD_UG_RAM_ROM (0xd4) /* RAM/ROM */ - -#define MANUF_MACROSYSTEMS2 (0x4754) /* MacroSystems Germany */ -#define PROD_MAESTRO (0x03) /* Maestro */ -#define PROD_VLAB (0x04) /* VLab */ -#define PROD_MAESTRO_PRO (0x05) /* Maestro Pro */ -#define PROD_RETINA_Z2 (0x06) /* Retina Z2 Graphics Board */ -#define PROD_MULTI_EVOLUTION (0x08) /* MultiEvolution */ -#define PROD_TOCCATA (0x0C) /* Toccata Sound Board */ -#define PROD_RETINA_Z3 (0x10) /* Retina Z3 Graphics Board */ -#define PROD_VLAB_MOTION (0x12) /* VLab Motion */ -#define PROD_ALTAIS (0x13) /* Altais Graphics Board */ -#define PROD_FALCON_040 (0xFD) /* Falcon '040 Turbo Board */ - -#define MANUF_COMBITEC (0x6766) /* Combitec */ - -#define MANUF_SKI (0x8000) /* SKI Peripherals */ -#define PROD_MAST_FIREBALL (0x08) /* M.A.S.T. Fireball SCSI Controller */ -#define PROD_SKI_SCSI_SERIAL (0x80) /* SCSI / Dual Serial */ - -#define MANUF_CAMERON (0xAA01) /* Cameron */ -#define PROD_PERSONAL_A4 (0x10) /* Personal A4 */ - -#define MANUF_REIS_WARE (0xAA11) /* Reis-Ware */ -#define PROD_RW_HANDYSCANNER (0x11) /* Handyscanner */ - - -/* Illegal Manufacturer IDs. These do NOT appear in arch/m68k/amiga/zorro.c! */ - -#define MANUF_HACKER_INC (0x07DB) /* Hacker Inc. */ -#define PROD_HACKER_SCSI (0x01) /* Hacker Inc. SCSI Controller */ - -#define MANUF_RES_MNGT_FORCE (0x07DB) /* Resource Management Force */ -#define PROD_QUICKNET (0x02) /* QuickNet Ethernet */ - -#define MANUF_VECTOR2 (0x07DB) /* Vector */ -#define PROD_CONNECTION_2 (0xE0) /* Vector Connection */ -#define PROD_CONNECTION_3 (0xE1) /* Vector Connection */ -#define PROD_CONNECTION_4 (0xE2) /* Vector Connection */ -#define PROD_CONNECTION_5 (0xE3) /* Vector Connection */ - - -/* - * GVP's identifies most of their product through the 'extended - * product code' (epc). The epc has to be and'ed with the GVP_PRODMASK - * before the identification. - */ - -#define GVP_PRODMASK (0xf8) -#define GVP_SCSICLKMASK (0x01) - -enum GVP_ident { - GVP_GFORCE_040 = 0x20, - GVP_GFORCE_040_SCSI = 0x30, - GVP_A1291_SCSI = 0x40, - GVP_COMBO_R4 = 0x60, - GVP_COMBO_R4_SCSI = 0x70, - GVP_PHONEPAK = 0x78, - GVP_IOEXT = 0x98, - GVP_GFORCE_030 = 0xa0, - GVP_GFORCE_030_SCSI = 0xb0, - GVP_A530 = 0xc0, - GVP_A530_SCSI = 0xd0, - GVP_COMBO_R3 = 0xe0, - GVP_COMBO_R3_SCSI = 0xf0, - GVP_SERIESII = 0xf8, -}; - -enum GVP_flags { - GVP_IO = 0x01, - GVP_ACCEL = 0x02, - GVP_SCSI = 0x04, - GVP_24BITDMA = 0x08, - GVP_25BITDMA = 0x10, - GVP_NOBANK = 0x20, - GVP_14MHZ = 0x40, -}; - - -struct Node { - struct Node *ln_Succ; /* Pointer to next (successor) */ - struct Node *ln_Pred; /* Pointer to previous (predecessor) */ - u_char ln_Type; - char ln_Pri; /* Priority, for sorting */ - char *ln_Name; /* ID string, null terminated */ -}; - -struct ExpansionRom { - /* -First 16 bytes of the expansion ROM */ - u_char er_Type; /* Board type, size and flags */ - u_char er_Product; /* Product number, assigned by manufacturer */ - u_char er_Flags; /* Flags */ - u_char er_Reserved03; /* Must be zero ($ff inverted) */ - u_short er_Manufacturer; /* Unique ID,ASSIGNED BY COMMODORE-AMIGA! */ - u_long er_SerialNumber; /* Available for use by manufacturer */ - u_short er_InitDiagVec; /* Offset to optional "DiagArea" structure */ - u_char er_Reserved0c; - u_char er_Reserved0d; - u_char er_Reserved0e; - u_char er_Reserved0f; -}; - -/* er_Type board type bits */ -#define ERT_TYPEMASK 0xc0 -#define ERT_ZORROII 0xc0 -#define ERT_ZORROIII 0x80 - -/* other bits defined in er_Type */ -#define ERTB_MEMLIST 5 /* Link RAM into free memory list */ -#define ERTF_MEMLIST (1<<5) - -struct ConfigDev { - struct Node cd_Node; - u_char cd_Flags; /* (read/write) */ - u_char cd_Pad; /* reserved */ - struct ExpansionRom cd_Rom; /* copy of board's expansion ROM */ - void *cd_BoardAddr; /* where in memory the board was placed */ - u_long cd_BoardSize; /* size of board in bytes */ - u_short cd_SlotAddr; /* which slot number (PRIVATE) */ - u_short cd_SlotSize; /* number of slots (PRIVATE) */ - void *cd_Driver; /* pointer to node of driver */ - struct ConfigDev *cd_NextCD; /* linked list of drivers to config */ - u_long cd_Unused[4]; /* for whatever the driver wants */ -}; - -#else /* __ASSEMBLY__ */ - -LN_Succ = 0 -LN_Pred = LN_Succ+4 -LN_Type = LN_Pred+4 -LN_Pri = LN_Type+1 -LN_Name = LN_Pri+1 -LN_sizeof = LN_Name+4 - -ER_Type = 0 -ER_Product = ER_Type+1 -ER_Flags = ER_Product+1 -ER_Reserved03 = ER_Flags+1 -ER_Manufacturer = ER_Reserved03+1 -ER_SerialNumber = ER_Manufacturer+2 -ER_InitDiagVec = ER_SerialNumber+4 -ER_Reserved0c = ER_InitDiagVec+2 -ER_Reserved0d = ER_Reserved0c+1 -ER_Reserved0e = ER_Reserved0d+1 -ER_Reserved0f = ER_Reserved0e+1 -ER_sizeof = ER_Reserved0f+1 - -CD_Node = 0 -CD_Flags = CD_Node+LN_sizeof -CD_Pad = CD_Flags+1 -CD_Rom = CD_Pad+1 -CD_BoardAddr = CD_Rom+ER_sizeof -CD_BoardSize = CD_BoardAddr+4 -CD_SlotAddr = CD_BoardSize+4 -CD_SlotSize = CD_SlotAddr+2 -CD_Driver = CD_SlotSize+2 -CD_NextCD = CD_Driver+4 -CD_Unused = CD_NextCD+4 -CD_sizeof = CD_Unused+(4*4) - -#endif /* __ASSEMBLY__ */ - -#ifndef __ASSEMBLY__ - -#define ZORRO_NUM_AUTO 16 - -#ifdef __KERNEL__ - -extern int zorro_num_autocon; /* # of autoconfig devices found */ -extern struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO]; - - -/* - * Zorro Functions - */ - -extern int zorro_find(int manuf, int prod, int part, int index); -extern struct ConfigDev *zorro_get_board(int key); -extern void zorro_config_board(int key, int part); -extern void zorro_unconfig_board(int key, int part); - - -/* - * Bitmask indicating portions of available Zorro II RAM that are unused - * by the system. Every bit represents a 64K chunk, for a maximum of 8MB - * (128 chunks, physical 0x00200000-0x009fffff). - * - * If you want to use (= allocate) portions of this RAM, you should clear - * the corresponding bits. - */ - -extern u_long zorro_unused_z2ram[4]; - -#define Z2RAM_START (0x00200000) -#define Z2RAM_END (0x00a00000) -#define Z2RAM_SIZE (0x00800000) -#define Z2RAM_CHUNKSIZE (0x00010000) -#define Z2RAM_CHUNKMASK (0x0000ffff) -#define Z2RAM_CHUNKSHIFT (16) - - -/* - * Verbose Board Identification - */ - -extern void zorro_identify(void); -extern int zorro_get_list(char *buffer); - -#endif /* !__ASSEMBLY__ */ -#endif /* __KERNEL__ */ - -#endif /* __ZORRO_H */ diff -u --recursive --new-file v2.1.36/linux/include/net/sock.h linux/include/net/sock.h --- v2.1.36/linux/include/net/sock.h Wed Apr 23 19:01:29 1997 +++ linux/include/net/sock.h Thu May 8 13:54:18 1997 @@ -216,6 +216,7 @@ * Options received (usually on last packet, some only on SYN packets). */ char tstamp_ok, /* TIMESTAMP seen on SYN packet */ + wscale_ok, /* Wscale seen on SYN packet */ sack_ok; /* SACK_PERM seen on SYN packet */ char saw_tstamp; /* Saw TIMESTAMP on last packet */ __u16 in_mss; /* MSS option received from sender */ diff -u --recursive --new-file v2.1.36/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.36/linux/include/net/tcp.h Wed Apr 23 19:01:29 1997 +++ linux/include/net/tcp.h Thu May 8 13:56:01 1997 @@ -43,6 +43,17 @@ extern struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE]; extern struct sock *tcp_bound_hash[TCP_BHTABLE_SIZE]; +/* tcp_ipv4.c: These sysctl variables need to be shared between v4 and v6 + * because the v6 tcp code to intialize a connection needs to interoperate + * with the v4 code using the same variables. + * FIXME: It would be better to rewrite the connection code to be + * address family independent and just leave one copy in the ipv4 section. + * This would also clean up some code duplication. -- erics + */ +extern int sysctl_tcp_sack; +extern int sysctl_tcp_timestamps; +extern int sysctl_tcp_window_scaling; + /* These are AF independant. */ static __inline__ int tcp_bhashfn(__u16 lport) { @@ -224,8 +235,12 @@ __u16 rmt_port; __u16 mss; __u8 snd_wscale; + __u8 rcv_wscale; char sack_ok; char tstamp_ok; + char wscale_ok; + __u32 window_clamp; /* window clamp at creation time */ + __u32 rcv_wnd; /* rcv_wnd offered first time */ __u32 ts_recent; unsigned long expires; int retrans; @@ -452,6 +467,10 @@ extern struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX]; +/* + * FIXME: this method of choosing when to send a window update + * does not seem correct to me. -- erics + */ static __inline__ unsigned short tcp_raise_window(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -553,9 +572,9 @@ * It would be especially magical to compute the checksum for this * stuff on the fly here. */ -extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sack, int ts, int wscale) +extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sack, int ts, int offer_wscale, int wscale) { - int count = 4 + (wscale ? 4 : 0) + ((ts || sack) ? 4 : 0) + (ts ? 8 : 0); + int count = 4 + (offer_wscale ? 4 : 0) + ((ts || sack) ? 4 : 0) + (ts ? 8 : 0); unsigned char *optr = skb_put(skb,count); __u32 *ptr = (__u32 *)optr; @@ -579,10 +598,51 @@ *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) | (TCPOPT_NOP << 8) | TCPOPT_NOP); } - if (wscale) - *ptr++ = htonl((TCPOPT_WINDOW << 24) | (TCPOLEN_WINDOW << 16) | wscale); + if (offer_wscale) + *ptr++ = htonl((TCPOPT_WINDOW << 24) | (TCPOLEN_WINDOW << 16) | (wscale << 8)); skb->csum = csum_partial(optr, count, 0); return count; +} + +/* Determine a window scaling and initial window to offer. + * Based on the assumption that the given amount of space + * will be offered. Store the results in the tp structure. + * NOTE: for smooth operation initial space offering should + * be a multiple of mss if possible. We assume here that mss >= 1. + * This MUST be enforced by all callers. + */ +extern __inline__ void tcp_select_initial_window(__u32 space, __u16 mss, + __u32 *rcv_wnd, + __u32 *window_clamp, + int wscale_ok, + __u8 *rcv_wscale) +{ + /* If no clamp set the clamp to the max possible scaled window */ + if (*window_clamp == 0) + (*window_clamp) = (65535<<14); + space = min(*window_clamp,space); + + /* Quantize space offering to a multiple of mss if possible. */ + if (space > mss) + space = (space/mss)*mss; + + /* NOTE: offering an initial window larger than 32767 + * will break some buggy TCP stacks. We try to be nice. + * If we are not window scaling, then this truncates + * our initial window offering to 32k. There should also + * be a sysctl option to stop being nice. + */ + (*rcv_wnd) = min(space,32767); + (*rcv_wscale) = 0; + if (wscale_ok) { + /* See RFC1323 for an explanation of the limit to 14 */ + while (space > 65535 && (*rcv_wscale) < 14) { + space >>= 1; + (*rcv_wscale)++; + } + } + /* Set the clamp no higher than max representable value */ + (*window_clamp) = min(65535<<(*rcv_wscale),*window_clamp); } extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req) diff -u --recursive --new-file v2.1.36/linux/init/main.c linux/init/main.c --- v2.1.36/linux/init/main.c Wed Apr 23 19:01:29 1997 +++ linux/init/main.c Mon May 5 08:35:06 1997 @@ -68,6 +68,7 @@ extern long console_init(long, long); extern long kmalloc_init(long,long); extern void sock_init(void); +extern void uidcache_init(void); extern unsigned long pci_init(unsigned long, unsigned long); extern long mca_init(long, long); extern long sbus_init(long, long); @@ -175,6 +176,9 @@ #ifdef CONFIG_ISDN_DRV_HISAX extern void HiSax_setup(char *str, int *ints); #endif +#ifdef CONFIG_DIGIEPCA +extern void epca_setup(char *str, int *ints); +#endif #ifdef CONFIG_ISDN_DRV_PCBIT extern void pcbit_setup(char *str, int *ints); #endif @@ -191,6 +195,9 @@ extern void wd33c93_setup (char *str, int *ints); extern void gvp11_setup (char *str, int *ints); +#ifdef CONFIG_CYCLADES +extern void cy_setup(char *str, int *ints); +#endif #ifdef CONFIG_DIGI extern void pcxx_setup(char *str, int *ints); #endif @@ -257,7 +264,7 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; -__initfunc(char *get_options(char *str, int *ints)) +char *get_options(char *str, int *ints) { char *cur = str; int i=1; @@ -478,9 +485,15 @@ #if defined(CONFIG_GVP11_SCSI) { "gvp11=", gvp11_setup }, #endif +#ifdef CONFIG_CYCLADES + { "cyclades=", cy_setup }, +#endif #ifdef CONFIG_DIGI { "digi=", pcxx_setup }, #endif +#ifdef CONFIG_DIGIEPCA + { "digiepca=", epca_setup }, +#endif #ifdef CONFIG_RISCOM8 { "riscom8=", riscom8_setup }, #endif @@ -638,6 +651,7 @@ { "gscd", 0x1000 }, { "sbpcd", 0x1900 }, { "sonycd", 0x1800 }, + { "eda", 0x2400 }, { "eza", 0x2800 }, { "bpcd", 0x2900 }, #if CONFIG_APBLOCK @@ -779,43 +793,11 @@ extern int cpu_idle(void * unused); -/* - * Activate a secondary processor. - */ - -__initfunc(asmlinkage void start_secondary(void)) -{ - trap_init(); - init_IRQ(); - smp_callin(); - cpu_idle(NULL); -} - - - /* Called by boot processor to activate the rest. */ __initfunc(static void smp_init(void)) { - int i, j; - /* Get other processors into their bootup holding patterns. */ smp_boot_cpus(); - - /* Create the slave init tasks as sharing pid 0. This should only - * happen if we have virtual CPU numbers higher than 0. - */ - for (i=1; iprocessor=j; - } } /* @@ -832,6 +814,8 @@ #endif +extern void initialize_secondary(void); + /* * Activate the first processor. */ @@ -840,18 +824,14 @@ { char * command_line; -/* - * This little check will move. - */ - #ifdef __SMP__ - static int first_cpu=1; - - if(!first_cpu) - start_secondary(); - first_cpu=0; - -#endif + static int boot_cpu = 1; + /* "current" has been set up, we need to load it now */ + if (!boot_cpu) + initialize_secondary(); + boot_cpu = 0; +#endif + /* * Interrupts are still disabled. Do necessary setups, then * enable them @@ -896,7 +876,6 @@ memory_start = kmem_cache_init(memory_start, memory_end); sti(); calibrate_delay(); - memory_start = file_table_init(memory_start,memory_end); memory_start = name_cache_init(memory_start,memory_end); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && initrd_start < memory_start) { @@ -910,9 +889,11 @@ proc_root_init(); #endif kmem_cache_sizes_init(); + uidcache_init(); vma_init(); buffer_init(); inode_init(); + file_table_init(); sock_init(); #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) ipc_init(); diff -u --recursive --new-file v2.1.36/linux/ipc/msg.c linux/ipc/msg.c --- v2.1.36/linux/ipc/msg.c Mon Apr 14 16:28:26 1997 +++ linux/ipc/msg.c Thu May 1 12:05:06 1997 @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -39,7 +40,7 @@ static int kerneld_arr[MAX_KERNELDS]; static int n_kernelds = 0; -void msg_init (void) +__initfunc(void msg_init (void)) { int id; diff -u --recursive --new-file v2.1.36/linux/ipc/sem.c linux/ipc/sem.c --- v2.1.36/linux/ipc/sem.c Sun Jan 26 02:07:48 1997 +++ linux/ipc/sem.c Thu May 1 12:05:06 1997 @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -55,7 +56,7 @@ static unsigned short sem_seq = 0; -void sem_init (void) +__initfunc(void sem_init (void)) { int i; diff -u --recursive --new-file v2.1.36/linux/ipc/shm.c linux/ipc/shm.c --- v2.1.36/linux/ipc/shm.c Mon Apr 14 16:28:26 1997 +++ linux/ipc/shm.c Fri May 2 08:53:04 1997 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ static ulong swap_successes = 0; static ulong used_segs = 0; -void shm_init (void) +__initfunc(void shm_init (void)) { int id; @@ -402,42 +403,21 @@ shm_swap_in /* swapin */ }; -/* Insert shmd into the circular list shp->attaches */ +/* Insert shmd into the list shp->attaches */ static inline void insert_attach (struct shmid_ds * shp, struct vm_area_struct * shmd) { - struct vm_area_struct * attaches; - - if ((attaches = shp->attaches)) { - shmd->vm_next_share = attaches; - shmd->vm_prev_share = attaches->vm_prev_share; - shmd->vm_prev_share->vm_next_share = shmd; - attaches->vm_prev_share = shmd; - } else - shp->attaches = shmd->vm_next_share = shmd->vm_prev_share = shmd; + if((shmd->vm_next_share = shp->attaches) != NULL) + shp->attaches->vm_pprev_share = &shmd->vm_next_share; + shp->attaches = shmd; + shmd->vm_pprev_share = &shp->attaches; } -/* Remove shmd from circular list shp->attaches */ +/* Remove shmd from list shp->attaches */ static inline void remove_attach (struct shmid_ds * shp, struct vm_area_struct * shmd) { - if (shmd->vm_next_share == shmd) { - if (shp->attaches != shmd) { - printk("shm_close: shm segment (id=%ld) attach list inconsistent\n", - SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK); - printk("shm_close: %08lx-%08lx %c%c%c%c %08lx %08lx\n", - shmd->vm_start, shmd->vm_end, - shmd->vm_flags & VM_READ ? 'r' : '-', - shmd->vm_flags & VM_WRITE ? 'w' : '-', - shmd->vm_flags & VM_EXEC ? 'x' : '-', - shmd->vm_flags & VM_MAYSHARE ? 's' : 'p', - shmd->vm_offset, shmd->vm_pte); - } - shp->attaches = NULL; - } else { - if (shp->attaches == shmd) - shp->attaches = shmd->vm_next_share; - shmd->vm_prev_share->vm_next_share = shmd->vm_next_share; - shmd->vm_next_share->vm_prev_share = shmd->vm_prev_share; - } + if(shmd->vm_next_share) + shmd->vm_next_share->vm_pprev_share = shmd->vm_pprev_share; + *shmd->vm_pprev_share = shmd->vm_next_share; } /* @@ -575,7 +555,6 @@ shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE); - shmd->vm_next_share = shmd->vm_prev_share = NULL; shmd->vm_inode = NULL; shmd->vm_offset = 0; shmd->vm_ops = &shm_vm_ops; @@ -825,9 +804,10 @@ if (shmd->vm_mm->rss > 0) shmd->vm_mm->rss--; flush_tlb_page(shmd, tmp); - /* continue looping through circular list */ + /* continue looping through the linked list */ } while (0); - if ((shmd = shmd->vm_next_share) == shp->attaches) + shmd = shmd->vm_next_share; + if (!shmd) break; } diff -u --recursive --new-file v2.1.36/linux/ipc/util.c linux/ipc/util.c --- v2.1.36/linux/ipc/util.c Mon Oct 28 04:21:41 1996 +++ linux/ipc/util.c Thu May 1 12:05:06 1997 @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -18,7 +19,7 @@ extern void sem_init (void), msg_init (void), shm_init (void); -void ipc_init (void) +__initfunc(void ipc_init (void)) { sem_init(); msg_init(); diff -u --recursive --new-file v2.1.36/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.36/linux/kernel/exit.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/exit.c Thu May 1 12:05:06 1997 @@ -4,8 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#undef DEBUG_PROC_TREE - #include #include #include @@ -16,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -124,132 +123,29 @@ wake_up_interruptible(&tsk->p_pptr->wait_chldexit); } -void release(struct task_struct * p) +static void release(struct task_struct * p) { - int i; - - if (!p) - return; - if (p == current) { - printk("task releasing itself\n"); - return; - } - for (i=1 ; iprocessor != NO_PROC_ID) - barrier(); - spin_unlock_wait(&scheduler_lock); + /* FIXME! Cheesy, but kills the window... -DaveM */ + while (p->has_cpu) + barrier(); + spin_unlock_wait(&scheduler_lock); #endif - nr_tasks--; - task[i] = NULL; - REMOVE_LINKS(p); - release_thread(p); - if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page) - printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm); - free_kernel_stack(p->kernel_stack_page); - current->cmin_flt += p->min_flt + p->cmin_flt; - current->cmaj_flt += p->maj_flt + p->cmaj_flt; - current->cnswap += p->nswap + p->cnswap; - free_task_struct(p); - return; - } - panic("trying to release non-existent task"); -} - -#ifdef DEBUG_PROC_TREE -/* - * Check to see if a task_struct pointer is present in the task[] array - * Return 0 if found, and 1 if not found. - */ -int bad_task_ptr(struct task_struct *p) -{ - int i; - - if (!p) - return 0; - for (i=0 ; ip_pptr)) - printk("Warning, pid %d's parent link is bad\n", - task[i]->pid); - if (bad_task_ptr(task[i]->p_cptr)) - printk("Warning, pid %d's child link is bad\n", - task[i]->pid); - if (bad_task_ptr(task[i]->p_ysptr)) - printk("Warning, pid %d's ys link is bad\n", - task[i]->pid); - if (bad_task_ptr(task[i]->p_osptr)) - printk("Warning, pid %d's os link is bad\n", - task[i]->pid); - if (task[i]->p_pptr == task[i]) - printk("Warning, pid %d parent link points to self\n", - task[i]->pid); - if (task[i]->p_cptr == task[i]) - printk("Warning, pid %d child link points to self\n", - task[i]->pid); - if (task[i]->p_ysptr == task[i]) - printk("Warning, pid %d ys link points to self\n", - task[i]->pid); - if (task[i]->p_osptr == task[i]) - printk("Warning, pid %d os link points to self\n", - task[i]->pid); - if (task[i]->p_osptr) { - if (task[i]->p_pptr != task[i]->p_osptr->p_pptr) - printk( - "Warning, pid %d older sibling %d parent is %d\n", - task[i]->pid, task[i]->p_osptr->pid, - task[i]->p_osptr->p_pptr->pid); - if (task[i]->p_osptr->p_ysptr != task[i]) - printk( - "Warning, pid %d older sibling %d has mismatched ys link\n", - task[i]->pid, task[i]->p_osptr->pid); - } - if (task[i]->p_ysptr) { - if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr) - printk( - "Warning, pid %d younger sibling %d parent is %d\n", - task[i]->pid, task[i]->p_osptr->pid, - task[i]->p_osptr->p_pptr->pid); - if (task[i]->p_ysptr->p_osptr != task[i]) - printk( - "Warning, pid %d younger sibling %d has mismatched os link\n", - task[i]->pid, task[i]->p_ysptr->pid); - } - if (task[i]->p_cptr) { - if (task[i]->p_cptr->p_pptr != task[i]) - printk( - "Warning, pid %d youngest child %d has mismatched parent link\n", - task[i]->pid, task[i]->p_cptr->pid); - if (task[i]->p_cptr->p_ysptr) - printk( - "Warning, pid %d youngest child %d has non-NULL ys link\n", - task[i]->pid, task[i]->p_cptr->pid); - } + charge_uid(p, -1); + nr_tasks--; + add_free_taskslot(p->tarray_ptr); + unhash_pid(p); + REMOVE_LINKS(p); + release_thread(p); + current->cmin_flt += p->min_flt + p->cmin_flt; + current->cmaj_flt += p->maj_flt + p->cmaj_flt; + current->cnswap += p->nswap + p->cnswap; + free_task_struct(p); + } else { + printk("task releasing itself\n"); } } -#endif /* DEBUG_PROC_TREE */ /* * This checks not only the pgrp, but falls back on the pid if no @@ -347,17 +243,12 @@ retval = -EINVAL; if (sig >= 0 && sig <= 32) { - struct task_struct *p; + struct task_struct *p = find_task_by_pid(pid); - retval = -ESRCH; - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid != pid) - continue; - retval = send_sig(sig,p,priv); - break; - } - read_unlock(&tasklist_lock); + if(p) + retval = send_sig(sig, p, priv); + else + retval = -ESRCH; } return retval; } @@ -550,7 +441,7 @@ if (!--mm->count) { exit_mmap(mm); free_page_tables(mm); - kfree(mm); + kmem_cache_free(mm_cachep, mm); } } } diff -u --recursive --new-file v2.1.36/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.36/linux/kernel/fork.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/fork.c Thu May 1 12:05:06 1997 @@ -33,68 +33,177 @@ unsigned long int total_forks=0; /* Handle normal Linux uptimes. */ int last_pid=0; -static inline int find_empty_process(void) +/* SLAB cache for mm_struct's. */ +kmem_cache_t *mm_cachep; + +struct task_struct *pidhash[PIDHASH_SZ]; +spinlock_t pidhash_lock = SPIN_LOCK_UNLOCKED; + +struct task_struct **tarray_freelist = NULL; +spinlock_t taskslot_lock = SPIN_LOCK_UNLOCKED; + +/* UID task count cache, to prevent walking entire process list every + * single fork() operation. + */ +#define UIDHASH_SZ (PIDHASH_SZ >> 2) + +static struct uid_taskcount { + struct uid_taskcount *next, **pprev; + unsigned short uid; + int task_count; +} *uidhash[UIDHASH_SZ]; +static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; + +kmem_cache_t *uid_cachep; + +#define uidhashfn(uid) (((uid >> 8) ^ uid) & (UIDHASH_SZ - 1)) + +static inline void uid_hash_insert(struct uid_taskcount *up, unsigned int hashent) { - int i; + spin_lock(&uidhash_lock); + if((up->next = uidhash[hashent]) != NULL) + uidhash[hashent]->pprev = &up->next; + up->pprev = &uidhash[hashent]; + uidhash[hashent] = up; + spin_unlock(&uidhash_lock); +} - if (nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) { - if (current->uid) - return -EAGAIN; - } - if (current->uid) { - long max_tasks = current->rlim[RLIMIT_NPROC].rlim_cur; +static inline void uid_hash_remove(struct uid_taskcount *up) +{ + spin_lock(&uidhash_lock); + if(up->next) + up->next->pprev = up->pprev; + *up->pprev = up->next; + spin_unlock(&uidhash_lock); +} - max_tasks--; /* count the new process.. */ - if (max_tasks < nr_tasks) { - struct task_struct *p; - read_lock(&tasklist_lock); - for_each_task (p) { - if (p->uid == current->uid) - if (--max_tasks < 0) { - read_unlock(&tasklist_lock); - return -EAGAIN; - } - } - read_unlock(&tasklist_lock); +static inline struct uid_taskcount *uid_find(unsigned short uid, unsigned int hashent) +{ + struct uid_taskcount *up; + + spin_lock(&uidhash_lock); + for(up = uidhash[hashent]; (up && up->uid != uid); up = up->next) + ; + spin_unlock(&uidhash_lock); + return up; +} + +int charge_uid(struct task_struct *p, int count) +{ + unsigned int hashent = uidhashfn(p->uid); + struct uid_taskcount *up = uid_find(p->uid, hashent); + + if(up) { + int limit = p->rlim[RLIMIT_NPROC].rlim_cur; + int newcnt = up->task_count + count; + + if(newcnt > limit) + return -EAGAIN; + else if(newcnt == 0) { + uid_hash_remove(up); + kmem_cache_free(uid_cachep, up); + return 0; } + } else { + up = kmem_cache_alloc(uid_cachep, SLAB_KERNEL); + if(!up) + return -EAGAIN; + up->uid = p->uid; + up->task_count = 0; + uid_hash_insert(up, hashent); } - for (i = 0 ; i < NR_TASKS ; i++) { - if (!task[i]) - return i; + up->task_count += count; + return 0; +} + +void uidcache_init(void) +{ + int i; + + uid_cachep = kmem_cache_create("uid_cache", sizeof(struct uid_taskcount), + sizeof(unsigned long) * 2, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!uid_cachep) + panic("Cannot create uid taskcount SLAB cache\n"); + + for(i = 0; i < UIDHASH_SZ; i++) + uidhash[i] = 0; +} + +static inline int find_empty_process(void) +{ + struct task_struct **tslot; + + if(current->uid) { + int error; + + if(nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) + return -EAGAIN; + if((error = charge_uid(current, 1)) < 0) + return error; } + tslot = get_free_taskslot(); + if(tslot) + return tslot - &task[0]; return -EAGAIN; } +/* Protects next_safe and last_pid. */ +static spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED; + static int get_pid(unsigned long flags) { + static int next_safe = PID_MAX; struct task_struct *p; if (flags & CLONE_PID) return current->pid; - read_lock(&tasklist_lock); -repeat: - if ((++last_pid) & 0xffff8000) - last_pid=1; - for_each_task (p) { - if (p->pid == last_pid || - p->pgrp == last_pid || - p->session == last_pid) - goto repeat; + spin_lock(&lastpid_lock); + if((++last_pid) & 0xffff8000) { + last_pid = 300; /* Skip daemons etc. */ + goto inside; + } + if(last_pid >= next_safe) { +inside: + next_safe = PID_MAX; + read_lock(&tasklist_lock); + repeat: + for_each_task(p) { + if(p->pid == last_pid || + p->pgrp == last_pid || + p->session == last_pid) { + if(++last_pid >= next_safe) { + if(last_pid & 0xffff8000) + last_pid = 300; + next_safe = PID_MAX; + goto repeat; + } + } + if(p->pid > last_pid && next_safe > p->pid) + next_safe = p->pid; + if(p->pgrp > last_pid && next_safe > p->pgrp) + next_safe = p->pgrp; + if(p->session > last_pid && next_safe > p->session) + next_safe = p->session; + } + read_unlock(&tasklist_lock); } - read_unlock(&tasklist_lock); + spin_unlock(&lastpid_lock); return last_pid; } static inline int dup_mmap(struct mm_struct * mm) { - struct vm_area_struct * mpnt, **p, *tmp; + struct vm_area_struct * mpnt, *tmp, **pprev; - mm->mmap = NULL; - p = &mm->mmap; + mm->mmap = mm->mmap_cache = NULL; flush_cache_mm(current->mm); + pprev = &mm->mmap; for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) { + struct inode *inode; + tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (!tmp) { exit_mmap(mm); @@ -105,12 +214,18 @@ tmp->vm_flags &= ~VM_LOCKED; tmp->vm_mm = mm; tmp->vm_next = NULL; - if (tmp->vm_inode) { - tmp->vm_inode->i_count++; + inode = tmp->vm_inode; + if (inode) { + inode->i_count++; + if (tmp->vm_flags & VM_DENYWRITE) + inode->i_writecount--; + /* insert tmp into the share list, just after mpnt */ - tmp->vm_next_share->vm_prev_share = tmp; + if((tmp->vm_next_share = mpnt->vm_next_share) != NULL) + mpnt->vm_next_share->vm_pprev_share = + &tmp->vm_next_share; mpnt->vm_next_share = tmp; - tmp->vm_prev_share = mpnt; + tmp->vm_pprev_share = &mpnt->vm_next_share; } if (copy_page_range(mm, current->mm, tmp)) { exit_mmap(mm); @@ -119,18 +234,23 @@ } if (tmp->vm_ops && tmp->vm_ops->open) tmp->vm_ops->open(tmp); - *p = tmp; - p = &tmp->vm_next; + + /* Ok, finally safe to link it in. */ + if((tmp->vm_next = *pprev) != NULL) + (*pprev)->vm_pprev = &tmp->vm_next; + *pprev = tmp; + tmp->vm_pprev = pprev; + + pprev = &tmp->vm_next; } flush_tlb_mm(current->mm); - build_mmap_avl(mm); return 0; } static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk) { if (!(clone_flags & CLONE_VM)) { - struct mm_struct * mm = kmalloc(sizeof(*tsk->mm), GFP_KERNEL); + struct mm_struct * mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (!mm) return -1; *mm = *current->mm; @@ -146,7 +266,7 @@ if (dup_mmap(mm)) { free_page_tables(mm); free_mm: - kfree(mm); + kmem_cache_free(mm_cachep, mm); return -1; } return 0; @@ -232,20 +352,17 @@ { int nr; int error = -ENOMEM; - unsigned long new_stack; struct task_struct *p; lock_kernel(); p = alloc_task_struct(); if (!p) goto bad_fork; - new_stack = alloc_kernel_stack(p); - if (!new_stack) - goto bad_fork_free_p; + error = -EAGAIN; nr = find_empty_process(); if (nr < 0) - goto bad_fork_free_stack; + goto bad_fork_free; *p = *current; @@ -256,8 +373,6 @@ p->did_exec = 0; p->swappable = 0; - p->kernel_stack_page = new_stack; - *(unsigned long *) p->kernel_stack_page = STACK_MAGIC; p->state = TASK_UNINTERRUPTIBLE; p->flags &= ~(PF_PTRACED|PF_TRACESYS|PF_SUPERPRIV); p->flags |= PF_FORKNOEXEC; @@ -277,12 +392,15 @@ p->utime = p->stime = 0; p->cutime = p->cstime = 0; #ifdef __SMP__ + p->has_cpu = 0; p->processor = NO_PROC_ID; #endif p->lock_depth = 0; p->start_time = jiffies; - task[nr] = p; + p->tarray_ptr = &task[nr]; + *p->tarray_ptr = p; SET_LINKS(p); + hash_pid(p); nr_tasks++; error = -ENOMEM; @@ -330,16 +448,16 @@ bad_fork_cleanup_files: exit_files(p); bad_fork_cleanup: + charge_uid(current, -1); if (p->exec_domain && p->exec_domain->module) __MOD_DEC_USE_COUNT(p->exec_domain->module); if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); - task[nr] = NULL; + add_free_taskslot(p->tarray_ptr); + unhash_pid(p); REMOVE_LINKS(p); nr_tasks--; -bad_fork_free_stack: - free_kernel_stack(new_stack); -bad_fork_free_p: +bad_fork_free: free_task_struct(p); bad_fork: fork_out: diff -u --recursive --new-file v2.1.36/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.36/linux/kernel/ksyms.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/ksyms.c Wed Apr 30 15:36:50 1997 @@ -150,6 +150,7 @@ EXPORT_SYMBOL(open_namei); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(close_fp); +EXPORT_SYMBOL(insert_file_free); EXPORT_SYMBOL(check_disk_change); EXPORT_SYMBOL(invalidate_buffers); EXPORT_SYMBOL(invalidate_inodes); @@ -300,7 +301,6 @@ EXPORT_SYMBOL(sleep_on); EXPORT_SYMBOL(interruptible_sleep_on); EXPORT_SYMBOL(schedule); -EXPORT_SYMBOL(current_set); EXPORT_SYMBOL(jiffies); EXPORT_SYMBOL(xtime); EXPORT_SYMBOL(do_gettimeofday); diff -u --recursive --new-file v2.1.36/linux/kernel/panic.c linux/kernel/panic.c --- v2.1.36/linux/kernel/panic.c Fri Apr 4 08:52:26 1997 +++ linux/kernel/panic.c Thu May 1 12:05:06 1997 @@ -15,6 +15,7 @@ #include #include #include +#include asmlinkage void sys_sync(void); /* it's really int */ extern void unblank_console(void); @@ -22,7 +23,7 @@ int panic_timeout = 0; -void panic_setup(char *str, int *ints) +__initfunc(void panic_setup(char *str, int *ints)) { if (ints[0] == 1) panic_timeout = ints[1]; diff -u --recursive --new-file v2.1.36/linux/kernel/printk.c linux/kernel/printk.c --- v2.1.36/linux/kernel/printk.c Sun Apr 13 10:18:22 1997 +++ linux/kernel/printk.c Thu May 8 10:19:52 1997 @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -230,7 +231,9 @@ msg_level = -1; } __restore_flags(flags); +#if 0 /* debugging - avoid this if we're deadlocked */ wake_up_interruptible(&log_wait); +#endif return i; } @@ -261,7 +264,7 @@ * print any messages that were printed by the kernel before the * console driver was initialized. */ -void register_console(struct console * console) +__initfunc(void register_console(struct console * console)) { int i,j,len; int p = log_start; diff -u --recursive --new-file v2.1.36/linux/kernel/resource.c linux/kernel/resource.c --- v2.1.36/linux/kernel/resource.c Mon Apr 14 16:28:26 1997 +++ linux/kernel/resource.c Thu May 1 12:05:06 1997 @@ -12,6 +12,7 @@ #include #include #include +#include #define IOTABLE_SIZE 128 @@ -181,7 +182,7 @@ #endif /* Called from init/main.c to reserve IO ports. */ -void reserve_setup(char *str, int *ints) +__initfunc(void reserve_setup(char *str, int *ints)) { int i; diff -u --recursive --new-file v2.1.36/linux/kernel/sched.c linux/kernel/sched.c --- v2.1.36/linux/kernel/sched.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/sched.c Sun May 4 21:11:15 1997 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -88,16 +89,6 @@ extern void mem_use(void); -static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; -unsigned long init_user_stack[1024] = { STACK_MAGIC, }; -static struct vm_area_struct init_mmap = INIT_MMAP; -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; - -struct mm_struct init_mm = INIT_MM; -struct task_struct init_task = INIT_TASK; - unsigned long volatile jiffies=0; /* @@ -105,7 +96,6 @@ * via the SMP irq return path. */ -struct task_struct *current_set[NR_CPUS] = {&init_task, }; struct task_struct *last_task_used_math = NULL; struct task_struct * task[NR_TASKS] = {&init_task, }; @@ -250,7 +240,7 @@ #ifdef __SMP__ /* Give a largish advantage to the same processor... */ /* (this is equivalent to penalizing other processors) */ - if (p->last_processor == this_cpu) + if (p->processor == this_cpu) weight += PROC_CHANGE_PENALTY; #endif @@ -262,10 +252,139 @@ return weight; } +/* + * Event timer code + */ +#define TVN_BITS 6 +#define TVR_BITS 8 +#define TVN_SIZE (1 << TVN_BITS) +#define TVR_SIZE (1 << TVR_BITS) +#define TVN_MASK (TVN_SIZE - 1) +#define TVR_MASK (TVR_SIZE - 1) + +#define SLOW_BUT_DEBUGGING_TIMERS 0 + +struct timer_vec { + int index; + struct timer_list *vec[TVN_SIZE]; +}; + +struct timer_vec_root { + int index; + struct timer_list *vec[TVR_SIZE]; +}; + +static struct timer_vec tv5 = { 0 }; +static struct timer_vec tv4 = { 0 }; +static struct timer_vec tv3 = { 0 }; +static struct timer_vec tv2 = { 0 }; +static struct timer_vec_root tv1 = { 0 }; + +static struct timer_vec * const tvecs[] = { + (struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5 +}; + +#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0])) + +static unsigned long timer_jiffies = 0; + +static inline void insert_timer(struct timer_list *timer, + struct timer_list **vec, int idx) +{ + if ((timer->next = vec[idx])) + vec[idx]->prev = timer; + vec[idx] = timer; + timer->prev = (struct timer_list *)&vec[idx]; +} + +static inline void internal_add_timer(struct timer_list *timer) +{ + /* + * must be cli-ed when calling this + */ + unsigned long expires = timer->expires; + unsigned long idx = expires - timer_jiffies; + + if (idx < TVR_SIZE) { + int i = expires & TVR_MASK; + insert_timer(timer, tv1.vec, i); + } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { + int i = (expires >> TVR_BITS) & TVN_MASK; + insert_timer(timer, tv2.vec, i); + } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { + int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; + insert_timer(timer, tv3.vec, i); + } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { + int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; + insert_timer(timer, tv4.vec, i); + } else if (expires < timer_jiffies) { + /* can happen if you add a timer with expires == jiffies, + * or you set a timer to go off in the past + */ + insert_timer(timer, tv1.vec, tv1.index); + } else if (idx < 0xffffffffUL) { + int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; + insert_timer(timer, tv5.vec, i); + } else { + /* Can only get here on architectures with 64-bit jiffies */ + timer->next = timer->prev = timer; + } +} + +static spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED; + +void add_timer(struct timer_list *timer) +{ + unsigned long flags; + + spin_lock_irqsave(&timerlist_lock, flags); +#if SLOW_BUT_DEBUGGING_TIMERS + if (timer->next || timer->prev) { + printk("add_timer() called with non-zero list from %p\n", + __builtin_return_address(0)); + goto out; + } +#endif + internal_add_timer(timer); +#if SLOW_BUT_DEBUGGING_TIMERS +out: +#endif + spin_unlock_irqrestore(&timerlist_lock, flags); +} + +static inline int detach_timer(struct timer_list *timer) +{ + int ret = 0; + struct timer_list *next, *prev; + next = timer->next; + prev = timer->prev; + if (next) { + next->prev = prev; + } + if (prev) { + ret = 1; + prev->next = next; + } + return ret; +} + + +int del_timer(struct timer_list * timer) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&timerlist_lock, flags); + ret = detach_timer(timer); + timer->next = timer->prev = 0; + spin_unlock_irqrestore(&timerlist_lock, flags); + return ret; +} + #ifdef __SMP__ #define idle_task (task[cpu_number_map[this_cpu]]) -#define can_schedule(p) ((p)->processor == NO_PROC_ID) +#define can_schedule(p) (!(p)->has_cpu) #else @@ -292,12 +411,10 @@ int this_cpu; need_resched = 0; - this_cpu = smp_processor_id(); - if (local_irq_count[this_cpu]) { - printk("Scheduling in interrupt\n"); - *(char *)0 = 0; - } prev = current; + this_cpu = smp_processor_id(); + if (local_irq_count[this_cpu]) + goto scheduling_in_interrupt; release_kernel_lock(prev, this_cpu, lock_depth); if (bh_active & bh_mask) do_bottom_half(); @@ -307,16 +424,8 @@ /* move an exhausted RR process to be last.. */ if (!prev->counter && prev->policy == SCHED_RR) { - if (prev->pid) { - prev->counter = prev->priority; - move_last_runqueue(prev); - } else { - static int count = 5; - if (count) { - count--; - printk("Moving pid 0 last\n"); - } - } + prev->counter = prev->priority; + move_last_runqueue(prev); } timeout = 0; switch (prev->state) { @@ -349,7 +458,7 @@ */ spin_unlock_irq(&runqueue_lock); #ifdef __SMP__ - prev->processor = NO_PROC_ID; + prev->has_cpu = 0; #endif /* @@ -381,8 +490,10 @@ } } +#ifdef __SMP__ + next->has_cpu = 1; next->processor = this_cpu; - next->last_processor = this_cpu; +#endif if (prev != next) { struct timer_list timer; @@ -404,6 +515,11 @@ spin_unlock(&scheduler_lock); reacquire_kernel_lock(prev, smp_processor_id(), lock_depth); + return; + +scheduling_in_interrupt: + printk("Scheduling in interrupt\n"); + *(int *)0 = 0; } #ifndef __alpha__ @@ -421,19 +537,22 @@ #endif -spinlock_t waitqueue_lock; +rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED; /* * wake_up doesn't wake up stopped processes - they have to be awakened * with signals or similar. + * + * Note that we only need a read lock for the wait queue (and thus do not + * have to protect against interrupts), as the actual removal from the + * queue is handled by the process itself. */ void wake_up(struct wait_queue **q) { - unsigned long flags; struct wait_queue *next; struct wait_queue *head; - spin_lock_irqsave(&waitqueue_lock, flags); + read_lock(&waitqueue_lock); if (q && (next = *q)) { head = WAIT_QUEUE_HEAD(q); while (next != head) { @@ -453,16 +572,15 @@ break; } } - spin_unlock_irqrestore(&waitqueue_lock, flags); + read_unlock(&waitqueue_lock); } void wake_up_interruptible(struct wait_queue **q) { - unsigned long flags; struct wait_queue *next; struct wait_queue *head; - spin_lock_irqsave(&waitqueue_lock, flags); + read_lock(&waitqueue_lock); if (q && (next = *q)) { head = WAIT_QUEUE_HEAD(q); while (next != head) { @@ -481,7 +599,7 @@ break; } } - spin_unlock_irqrestore(&waitqueue_lock, flags); + read_unlock(&waitqueue_lock); } /* @@ -603,14 +721,14 @@ if (current == task[0]) panic("task[0] trying to sleep"); current->state = state; - spin_lock_irqsave(&waitqueue_lock, flags); + write_lock_irqsave(&waitqueue_lock, flags); __add_wait_queue(p, &wait); - spin_unlock(&waitqueue_lock); + write_unlock(&waitqueue_lock); sti(); schedule(); - spin_lock_irq(&waitqueue_lock); + write_lock_irq(&waitqueue_lock); __remove_wait_queue(p, &wait); - spin_unlock_irqrestore(&waitqueue_lock, flags); + write_unlock_irqrestore(&waitqueue_lock, flags); } void interruptible_sleep_on(struct wait_queue **p) @@ -623,133 +741,6 @@ __sleep_on(p,TASK_UNINTERRUPTIBLE); } - -#define TVN_BITS 6 -#define TVR_BITS 8 -#define TVN_SIZE (1 << TVN_BITS) -#define TVR_SIZE (1 << TVR_BITS) -#define TVN_MASK (TVN_SIZE - 1) -#define TVR_MASK (TVR_SIZE - 1) - -#define SLOW_BUT_DEBUGGING_TIMERS 0 - -struct timer_vec { - int index; - struct timer_list *vec[TVN_SIZE]; -}; - -struct timer_vec_root { - int index; - struct timer_list *vec[TVR_SIZE]; -}; - -static struct timer_vec tv5 = { 0 }; -static struct timer_vec tv4 = { 0 }; -static struct timer_vec tv3 = { 0 }; -static struct timer_vec tv2 = { 0 }; -static struct timer_vec_root tv1 = { 0 }; - -static struct timer_vec * const tvecs[] = { - (struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5 -}; - -#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0])) - -static unsigned long timer_jiffies = 0; - -static inline void insert_timer(struct timer_list *timer, - struct timer_list **vec, int idx) -{ - if ((timer->next = vec[idx])) - vec[idx]->prev = timer; - vec[idx] = timer; - timer->prev = (struct timer_list *)&vec[idx]; -} - -static inline void internal_add_timer(struct timer_list *timer) -{ - /* - * must be cli-ed when calling this - */ - unsigned long expires = timer->expires; - unsigned long idx = expires - timer_jiffies; - - if (idx < TVR_SIZE) { - int i = expires & TVR_MASK; - insert_timer(timer, tv1.vec, i); - } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { - int i = (expires >> TVR_BITS) & TVN_MASK; - insert_timer(timer, tv2.vec, i); - } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { - int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; - insert_timer(timer, tv3.vec, i); - } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { - int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; - insert_timer(timer, tv4.vec, i); - } else if (expires < timer_jiffies) { - /* can happen if you add a timer with expires == jiffies, - * or you set a timer to go off in the past - */ - insert_timer(timer, tv1.vec, tv1.index); - } else if (idx < 0xffffffffUL) { - int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; - insert_timer(timer, tv5.vec, i); - } else { - /* Can only get here on architectures with 64-bit jiffies */ - timer->next = timer->prev = timer; - } -} - -static spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED; - -void add_timer(struct timer_list *timer) -{ - unsigned long flags; - - spin_lock_irqsave(&timerlist_lock, flags); -#if SLOW_BUT_DEBUGGING_TIMERS - if (timer->next || timer->prev) { - printk("add_timer() called with non-zero list from %p\n", - __builtin_return_address(0)); - goto out; - } -#endif - internal_add_timer(timer); -#if SLOW_BUT_DEBUGGING_TIMERS -out: -#endif - spin_unlock_irqrestore(&timerlist_lock, flags); -} - -static inline int detach_timer(struct timer_list *timer) -{ - int ret = 0; - struct timer_list *next, *prev; - next = timer->next; - prev = timer->prev; - if (next) { - next->prev = prev; - } - if (prev) { - ret = 1; - prev->next = next; - } - return ret; -} - - -int del_timer(struct timer_list * timer) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&timerlist_lock, flags); - ret = detach_timer(timer); - timer->next = timer->prev = 0; - spin_unlock_irqrestore(&timerlist_lock, flags); - return ret; -} - static inline void cascade_timers(struct timer_vec *tv) { /* cascade all the timers from tv up one level */ @@ -841,17 +832,18 @@ */ static unsigned long count_active_tasks(void) { - struct task_struct **p; + struct task_struct *p; unsigned long nr = 0; - for(p = &LAST_TASK; p > &FIRST_TASK; --p) - if (*p && ((*p)->state == TASK_RUNNING || - (*p)->state == TASK_UNINTERRUPTIBLE || - (*p)->state == TASK_SWAPPING)) + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->pid && + (p->state == TASK_RUNNING || + p->state == TASK_UNINTERRUPTIBLE || + p->state == TASK_SWAPPING)) nr += FIXED_1; -#ifdef __SMP__ - nr-=(smp_num_cpus-1)*FIXED_1; -#endif + } + read_unlock(&tasklist_lock); return nr; } @@ -1338,22 +1330,12 @@ #endif -static struct task_struct *find_process_by_pid(pid_t pid) +static inline struct task_struct *find_process_by_pid(pid_t pid) { - struct task_struct *p; - - p = current; - if (pid) { - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid == pid) - goto found; - } - p = NULL; -found: - read_unlock(&tasklist_lock); - } - return p; + if (pid) + return find_task_by_pid(pid); + else + return current; } static int setscheduler(pid_t pid, int policy, @@ -1566,7 +1548,7 @@ static void show_task(int nr,struct task_struct * p) { - unsigned long free; + unsigned long free = 0; static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" }; printk("%-8s %3d ", p->comm, (p == current) ? -nr : nr); @@ -1585,10 +1567,12 @@ else printk(" %016lx ", thread_saved_pc(&p->tss)); #endif +#if 0 for (free = 1; free < PAGE_SIZE/sizeof(long) ; free++) { if (((unsigned long *)p->kernel_stack_page)[free]) break; } +#endif printk("%5lu %5d %6d ", free*sizeof(long), p->pid, p->p_pptr->pid); if (p->p_cptr) printk("%5d ", p->p_cptr->pid); @@ -1606,7 +1590,7 @@ void show_state(void) { - int i; + struct task_struct *p; #if ((~0UL) == 0xffffffff) printk("\n" @@ -1617,25 +1601,30 @@ " free sibling\n"); printk(" task PC stack pid father child younger older\n"); #endif - for (i=0 ; itarray_ptr - &task[0]),p); + read_unlock(&tasklist_lock); } -void sched_init(void) +__initfunc(void sched_init(void)) { /* * We have to do a little magic to get the first * process right in SMP mode. */ - int cpu=smp_processor_id(); -#ifndef __SMP__ - current_set[cpu]=&init_task; -#else + int cpu=hard_smp_processor_id(); + int nr = NR_TASKS; + init_task.processor=cpu; - for(cpu = 0; cpu < NR_CPUS; cpu++) - current_set[cpu] = &init_task; -#endif + + /* Init task array free list and pidhash table. */ + while(--nr > 0) + add_free_taskslot(&task[nr]); + + for(nr = 0; nr < PIDHASH_SZ; nr++) + pidhash[nr] = NULL; + init_bh(TIMER_BH, timer_bh); init_bh(TQUEUE_BH, tqueue_bh); init_bh(IMMEDIATE_BH, immediate_bh); diff -u --recursive --new-file v2.1.36/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.36/linux/kernel/sys.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/sys.c Thu May 1 12:05:06 1997 @@ -523,16 +523,15 @@ */ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid) { - int old_ruid; - int old_euid; + int old_ruid, old_euid, new_ruid; - old_ruid = current->uid; + new_ruid = old_ruid = current->uid; old_euid = current->euid; if (ruid != (uid_t) -1) { if ((old_ruid == ruid) || (current->euid==ruid) || suser()) - current->uid = ruid; + new_ruid = ruid; else return -EPERM; } @@ -542,10 +541,8 @@ (current->suid == euid) || suser()) current->fsuid = current->euid = euid; - else { - current->uid = old_ruid; + else return -EPERM; - } } if (ruid != (uid_t) -1 || (euid != (uid_t) -1 && euid != old_ruid)) @@ -553,6 +550,18 @@ current->fsuid = current->euid; if (current->euid != old_euid) current->dumpable = 0; + + if(new_ruid != old_ruid) { + /* What if a process setreuid()'s and this brings the + * new uid over his NPROC rlimit? We can check this now + * cheaply with the new uid cache, so if it matters + * we should be checking for it. -DaveM + */ + charge_uid(current, -1); + current->uid = new_ruid; + if(new_ruid) + charge_uid(current, 1); + } return 0; } @@ -570,9 +579,11 @@ asmlinkage int sys_setuid(uid_t uid) { int old_euid = current->euid; + int old_ruid, new_ruid; + old_ruid = new_ruid = current->uid; if (suser()) - current->uid = current->euid = current->suid = current->fsuid = uid; + new_ruid = current->euid = current->suid = current->fsuid = uid; else if ((uid == current->uid) || (uid == current->suid)) current->fsuid = current->euid = uid; else @@ -580,6 +591,14 @@ if (current->euid != old_euid) current->dumpable = 0; + + if(new_ruid != old_ruid) { + /* See comment above about NPROC rlimit issues... */ + charge_uid(current, -1); + current->uid = new_ruid; + if(new_ruid) + charge_uid(current, 1); + } return 0; } @@ -605,8 +624,13 @@ if ((suid != (uid_t) -1) && (suid != current->uid) && (suid != current->euid) && (suid != current->suid)) return -EPERM; - if (ruid != (uid_t) -1) + if (ruid != (uid_t) -1) { + /* See above commentary about NPROC rlimit issues here. */ + charge_uid(current, -1); current->uid = ruid; + if(ruid) + charge_uid(current, 1); + } if (euid != (uid_t) -1) current->euid = euid; if (suid != (uid_t) -1) @@ -709,22 +733,13 @@ if (pgid < 0) return -EINVAL; - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid == pid) { - /* NOTE: I haven't dropped tasklist_lock, this is - * on purpose. -DaveM - */ - goto found_task; - } - } - read_unlock(&tasklist_lock); - return -ESRCH; + if((p = find_task_by_pid(pid)) == NULL) + return -ESRCH; -found_task: /* From this point forward we keep holding onto the tasklist lock * so that our parent does not change from under us. -DaveM */ + read_lock(&tasklist_lock); err = -ESRCH; if (p->p_pptr == current || p->p_opptr == current) { err = -EPERM; @@ -762,18 +777,12 @@ if (!pid) { return current->pgrp; } else { - struct task_struct *p; - int ret = -ESRCH; + struct task_struct *p = find_task_by_pid(pid); - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid == pid) { - ret = p->pgrp; - break; - } - } - read_unlock(&tasklist_lock); - return ret; + if(p) + return p->pgrp; + else + return -ESRCH; } } @@ -785,25 +794,16 @@ asmlinkage int sys_getsid(pid_t pid) { - struct task_struct * p; - int ret; - - /* SMP: The 'self' case requires no lock */ if (!pid) { - ret = current->session; + return current->session; } else { - ret = -ESRCH; + struct task_struct *p = find_task_by_pid(pid); - read_lock(&tasklist_lock); - for_each_task(p) { - if (p->pid == pid) { - ret = p->session; - break; - } - } - read_unlock(&tasklist_lock); + if(p) + return p->session; + else + return -ESRCH; } - return ret; } asmlinkage int sys_setsid(void) diff -u --recursive --new-file v2.1.36/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.36/linux/kernel/sysctl.c Sun Apr 13 10:18:22 1997 +++ linux/kernel/sysctl.c Thu May 1 12:05:06 1997 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -210,7 +211,7 @@ }; -void sysctl_init(void) +__initfunc(void sysctl_init(void)) { #ifdef CONFIG_PROC_FS register_proc_table(root_table, &proc_sys_root); diff -u --recursive --new-file v2.1.36/linux/mm/kmalloc.c linux/mm/kmalloc.c --- v2.1.36/linux/mm/kmalloc.c Mon Apr 14 16:28:27 1997 +++ linux/mm/kmalloc.c Thu May 1 12:05:06 1997 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -201,7 +202,7 @@ free_pages((unsigned long) page, order); } -long kmalloc_init(long start_mem, long end_mem) +__initfunc(long kmalloc_init(long start_mem, long end_mem)) { int order; diff -u --recursive --new-file v2.1.36/linux/mm/mmap.c linux/mm/mmap.c --- v2.1.36/linux/mm/mmap.c Thu Feb 27 10:57:31 1997 +++ linux/mm/mmap.c Thu May 1 12:05:06 1997 @@ -16,13 +16,13 @@ #include #include #include +#include #include #include #include -/* - * description of effects of mapping type and prot in current implementation. +/* description of effects of mapping type and prot in current implementation. * this is due to the limited x86 page protection hardware. The expected * behavior is in parens: * @@ -37,7 +37,6 @@ * x: (no) no x: (no) yes x: (no) yes x: (yes) yes * */ - pgprot_t protection_map[16] = { __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 @@ -48,20 +47,18 @@ int sysctl_overcommit_memory; -/* - * Check that a process has enough memory to allocate a +/* Check that a process has enough memory to allocate a * new virtual mapping. */ static inline int vm_enough_memory(long pages) { - /* - * stupid algorithm to decide if we have enough memory: while + /* Stupid algorithm to decide if we have enough memory: while * simple, it hopefully works in most obvious cases.. Easy to * fool it, but this should catch most mistakes. */ long freepages; - /* sometimes we want to use more memory than we have. */ + /* Sometimes we want to use more memory than we have. */ if (sysctl_overcommit_memory) return 1; @@ -74,6 +71,20 @@ return freepages > pages; } +/* Remove one vm structure from the inode's i_mmap ring. */ +static inline void remove_shared_vm_struct(struct vm_area_struct *vma) +{ + struct inode * inode = vma->vm_inode; + + if (inode) { + if (vma->vm_flags & VM_DENYWRITE) + inode->i_writecount++; + if(vma->vm_next_share) + vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share; + *vma->vm_pprev_share = vma->vm_next_share; + } +} + asmlinkage unsigned long sys_brk(unsigned long brk) { unsigned long rlim, retval; @@ -91,17 +102,14 @@ goto out; } - /* - * Always allow shrinking brk - */ + /* Always allow shrinking brk. */ if (brk <= mm->brk) { retval = mm->brk = brk; do_munmap(newbrk, oldbrk-newbrk); goto out; } - /* - * Check against rlimit and stack.. - */ + + /* Check against rlimit and stack.. */ retval = mm->brk; rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) @@ -109,21 +117,15 @@ if (brk - mm->end_code > rlim) goto out; - /* - * Check against existing mmap mappings. - */ + /* Check against existing mmap mappings. */ if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) goto out; - /* - * Check if we have enough memory.. - */ + /* Check if we have enough memory.. */ if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) goto out; - /* - * Ok, looks good - let it rip. - */ + /* Ok, looks good - let it rip. */ if(do_mmap(NULL, oldbrk, newbrk-oldbrk, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0) == oldbrk) @@ -134,8 +136,7 @@ return retval; } -/* - * Combine the mmap "prot" and "flags" argument into one "vm_flags" used +/* Combine the mmap "prot" and "flags" argument into one "vm_flags" used * internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits * into "VM_xxx". */ @@ -162,6 +163,7 @@ { struct mm_struct * mm = current->mm; struct vm_area_struct * vma; + int correct_wcount = 0; if ((len = PAGE_ALIGN(len)) == 0) return addr; @@ -181,20 +183,17 @@ return -EAGAIN; } - /* - * do simple checking here so the lower-level routines won't have + /* Do simple checking here so the lower-level routines won't have * to. we assume access permissions have been handled by the open * of the memory object, so we don't do any here. */ - if (file != NULL) { switch (flags & MAP_TYPE) { case MAP_SHARED: if ((prot & PROT_WRITE) && !(file->f_mode & 2)) return -EACCES; - /* - * make sure there are no mandatory locks on the file. - */ + + /* make sure there are no mandatory locks on the file. */ if (locks_verify_locked(file->f_inode)) return -EAGAIN; /* fall through */ @@ -206,18 +205,12 @@ default: return -EINVAL; } - if (flags & MAP_DENYWRITE) { - if (file->f_inode->i_writecount > 0) - return -ETXTBSY; - } } else if ((flags & MAP_TYPE) != MAP_PRIVATE) return -EINVAL; - /* - * obtain the address to map to. we verify (or select) it and ensure + /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ - if (flags & MAP_FIXED) { if (addr & ~PAGE_MASK) return -EINVAL; @@ -227,8 +220,7 @@ return -ENOMEM; } - /* - * determine the object being mapped and call the appropriate + /* Determine the object being mapped and call the appropriate * specific mapper. the address has already been validated, but * not unmapped, but the maps are removed from the list. */ @@ -249,8 +241,8 @@ vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; if (flags & MAP_SHARED) { vma->vm_flags |= VM_SHARED | VM_MAYSHARE; - /* - * This looks strange, but when we don't have the file open + + /* This looks strange, but when we don't have the file open * for writing, we can demote the shared mapping to a simpler * private mapping. That also takes care of a security hole * with ptrace() writing to a shared mapping without write @@ -289,9 +281,26 @@ } if (file) { - int error = file->f_op->mmap(file->f_inode, file, vma); + int error = 0; + if (vma->vm_flags & VM_DENYWRITE) { + if (file->f_inode->i_writecount > 0) + error = -ETXTBSY; + else { + /* f_op->mmap might possibly sleep + * (generic_file_mmap doesn't, but other code + * might). In any case, this takes care of any + * race that this might cause. + */ + file->f_inode->i_writecount--; + correct_wcount = 1; + } + } + if (!error) + error = file->f_op->mmap(file->f_inode, file, vma); if (error) { + if (correct_wcount) + file->f_inode->i_writecount++; kmem_cache_free(vm_area_cachep, vma); return error; } @@ -299,6 +308,8 @@ flags = vma->vm_flags; insert_vm_struct(mm, vma); + if (correct_wcount) + file->f_inode->i_writecount++; merge_segments(mm, vma->vm_start, vma->vm_end); /* merge_segments might have merged our vma, so we can't use it any more */ @@ -317,8 +328,7 @@ return addr; } -/* - * Get an address range which is currently unmapped. +/* Get an address range which is currently unmapped. * For mmap() without MAP_FIXED and shmat() with addr=0. * Return value 0 means ENOMEM. */ @@ -342,376 +352,7 @@ } } -/* - * Searching a VMA in the linear list task->mm->mmap is horribly slow. - * Use an AVL (Adelson-Velskii and Landis) tree to speed up this search - * from O(n) to O(log n), where n is the number of VMAs of the task - * (typically around 6, but may reach 3000 in some cases). - * Written by Bruno Haible . - */ - -/* We keep the list and tree sorted by address. */ -#define vm_avl_key vm_end -#define vm_avl_key_t unsigned long /* typeof(vma->avl_key) */ - -/* - * task->mm->mmap_avl is the AVL tree corresponding to task->mm->mmap - * or, more exactly, its root. - * A vm_area_struct has the following fields: - * vm_avl_left left son of a tree node - * vm_avl_right right son of a tree node - * vm_avl_height 1+max(heightof(left),heightof(right)) - * The empty tree is represented as NULL. - */ - -/* Since the trees are balanced, their height will never be large. */ -#define avl_maxheight 41 /* why this? a small exercise */ -#define heightof(tree) ((tree) == avl_empty ? 0 : (tree)->vm_avl_height) -/* - * Consistency and balancing rules: - * 1. tree->vm_avl_height == 1+max(heightof(tree->vm_avl_left),heightof(tree->vm_avl_right)) - * 2. abs( heightof(tree->vm_avl_left) - heightof(tree->vm_avl_right) ) <= 1 - * 3. foreach node in tree->vm_avl_left: node->vm_avl_key <= tree->vm_avl_key, - * foreach node in tree->vm_avl_right: node->vm_avl_key >= tree->vm_avl_key. - */ - -/* Look up the nodes at the left and at the right of a given node. */ -static inline void avl_neighbours (struct vm_area_struct * node, struct vm_area_struct * tree, struct vm_area_struct ** to_the_left, struct vm_area_struct ** to_the_right) -{ - vm_avl_key_t key = node->vm_avl_key; - - *to_the_left = *to_the_right = NULL; - for (;;) { - if (tree == avl_empty) { - printk("avl_neighbours: node not found in the tree\n"); - return; - } - if (key == tree->vm_avl_key) - break; - if (key < tree->vm_avl_key) { - *to_the_right = tree; - tree = tree->vm_avl_left; - } else { - *to_the_left = tree; - tree = tree->vm_avl_right; - } - } - if (tree != node) { - printk("avl_neighbours: node not exactly found in the tree\n"); - return; - } - if (tree->vm_avl_left != avl_empty) { - struct vm_area_struct * node; - for (node = tree->vm_avl_left; node->vm_avl_right != avl_empty; node = node->vm_avl_right) - continue; - *to_the_left = node; - } - if (tree->vm_avl_right != avl_empty) { - struct vm_area_struct * node; - for (node = tree->vm_avl_right; node->vm_avl_left != avl_empty; node = node->vm_avl_left) - continue; - *to_the_right = node; - } - if ((*to_the_left && ((*to_the_left)->vm_next != node)) || (node->vm_next != *to_the_right)) - printk("avl_neighbours: tree inconsistent with list\n"); -} - -/* - * Rebalance a tree. - * After inserting or deleting a node of a tree we have a sequence of subtrees - * nodes[0]..nodes[k-1] such that - * nodes[0] is the root and nodes[i+1] = nodes[i]->{vm_avl_left|vm_avl_right}. - */ -static inline void avl_rebalance (struct vm_area_struct *** nodeplaces_ptr, int count) -{ - for ( ; count > 0 ; count--) { - struct vm_area_struct ** nodeplace = *--nodeplaces_ptr; - struct vm_area_struct * node = *nodeplace; - struct vm_area_struct * nodeleft = node->vm_avl_left; - struct vm_area_struct * noderight = node->vm_avl_right; - int heightleft = heightof(nodeleft); - int heightright = heightof(noderight); - if (heightright + 1 < heightleft) { - /* */ - /* * */ - /* / \ */ - /* n+2 n */ - /* */ - struct vm_area_struct * nodeleftleft = nodeleft->vm_avl_left; - struct vm_area_struct * nodeleftright = nodeleft->vm_avl_right; - int heightleftright = heightof(nodeleftright); - if (heightof(nodeleftleft) >= heightleftright) { - /* */ - /* * n+2|n+3 */ - /* / \ / \ */ - /* n+2 n --> / n+1|n+2 */ - /* / \ | / \ */ - /* n+1 n|n+1 n+1 n|n+1 n */ - /* */ - node->vm_avl_left = nodeleftright; nodeleft->vm_avl_right = node; - nodeleft->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightleftright); - *nodeplace = nodeleft; - } else { - /* */ - /* * n+2 */ - /* / \ / \ */ - /* n+2 n --> n+1 n+1 */ - /* / \ / \ / \ */ - /* n n+1 n L R n */ - /* / \ */ - /* L R */ - /* */ - nodeleft->vm_avl_right = nodeleftright->vm_avl_left; - node->vm_avl_left = nodeleftright->vm_avl_right; - nodeleftright->vm_avl_left = nodeleft; - nodeleftright->vm_avl_right = node; - nodeleft->vm_avl_height = node->vm_avl_height = heightleftright; - nodeleftright->vm_avl_height = heightleft; - *nodeplace = nodeleftright; - } - } - else if (heightleft + 1 < heightright) { - /* similar to the above, just interchange 'left' <--> 'right' */ - struct vm_area_struct * noderightright = noderight->vm_avl_right; - struct vm_area_struct * noderightleft = noderight->vm_avl_left; - int heightrightleft = heightof(noderightleft); - if (heightof(noderightright) >= heightrightleft) { - node->vm_avl_right = noderightleft; noderight->vm_avl_left = node; - noderight->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightrightleft); - *nodeplace = noderight; - } else { - noderight->vm_avl_left = noderightleft->vm_avl_right; - node->vm_avl_right = noderightleft->vm_avl_left; - noderightleft->vm_avl_right = noderight; - noderightleft->vm_avl_left = node; - noderight->vm_avl_height = node->vm_avl_height = heightrightleft; - noderightleft->vm_avl_height = heightright; - *nodeplace = noderightleft; - } - } - else { - int height = (heightleftvm_avl_height) - break; - node->vm_avl_height = height; - } - } -} - -/* Insert a node into a tree. */ -static inline void avl_insert (struct vm_area_struct * new_node, struct vm_area_struct ** ptree) -{ - vm_avl_key_t key = new_node->vm_avl_key; - struct vm_area_struct ** nodeplace = ptree; - struct vm_area_struct ** stack[avl_maxheight]; - int stack_count = 0; - struct vm_area_struct *** stack_ptr = &stack[0]; /* = &stack[stackcount] */ - for (;;) { - struct vm_area_struct * node = *nodeplace; - if (node == avl_empty) - break; - *stack_ptr++ = nodeplace; stack_count++; - if (key < node->vm_avl_key) - nodeplace = &node->vm_avl_left; - else - nodeplace = &node->vm_avl_right; - } - new_node->vm_avl_left = avl_empty; - new_node->vm_avl_right = avl_empty; - new_node->vm_avl_height = 1; - *nodeplace = new_node; - avl_rebalance(stack_ptr,stack_count); -} - -/* Insert a node into a tree, and - * return the node to the left of it and the node to the right of it. - */ -static inline void avl_insert_neighbours (struct vm_area_struct * new_node, struct vm_area_struct ** ptree, - struct vm_area_struct ** to_the_left, struct vm_area_struct ** to_the_right) -{ - vm_avl_key_t key = new_node->vm_avl_key; - struct vm_area_struct ** nodeplace = ptree; - struct vm_area_struct ** stack[avl_maxheight]; - int stack_count = 0; - struct vm_area_struct *** stack_ptr = &stack[0]; /* = &stack[stackcount] */ - *to_the_left = *to_the_right = NULL; - for (;;) { - struct vm_area_struct * node = *nodeplace; - if (node == avl_empty) - break; - *stack_ptr++ = nodeplace; stack_count++; - if (key < node->vm_avl_key) { - *to_the_right = node; - nodeplace = &node->vm_avl_left; - } else { - *to_the_left = node; - nodeplace = &node->vm_avl_right; - } - } - new_node->vm_avl_left = avl_empty; - new_node->vm_avl_right = avl_empty; - new_node->vm_avl_height = 1; - *nodeplace = new_node; - avl_rebalance(stack_ptr,stack_count); -} - -/* Removes a node out of a tree. */ -static inline void avl_remove (struct vm_area_struct * node_to_delete, struct vm_area_struct ** ptree) -{ - vm_avl_key_t key = node_to_delete->vm_avl_key; - struct vm_area_struct ** nodeplace = ptree; - struct vm_area_struct ** stack[avl_maxheight]; - int stack_count = 0; - struct vm_area_struct *** stack_ptr = &stack[0]; /* = &stack[stackcount] */ - struct vm_area_struct ** nodeplace_to_delete; - for (;;) { - struct vm_area_struct * node = *nodeplace; - if (node == avl_empty) { - /* what? node_to_delete not found in tree? */ - printk("avl_remove: node to delete not found in tree\n"); - return; - } - *stack_ptr++ = nodeplace; stack_count++; - if (key == node->vm_avl_key) - break; - if (key < node->vm_avl_key) - nodeplace = &node->vm_avl_left; - else - nodeplace = &node->vm_avl_right; - } - nodeplace_to_delete = nodeplace; - /* Have to remove node_to_delete = *nodeplace_to_delete. */ - if (node_to_delete->vm_avl_left == avl_empty) { - *nodeplace_to_delete = node_to_delete->vm_avl_right; - stack_ptr--; stack_count--; - } else { - struct vm_area_struct *** stack_ptr_to_delete = stack_ptr; - struct vm_area_struct ** nodeplace = &node_to_delete->vm_avl_left; - struct vm_area_struct * node; - for (;;) { - node = *nodeplace; - if (node->vm_avl_right == avl_empty) - break; - *stack_ptr++ = nodeplace; stack_count++; - nodeplace = &node->vm_avl_right; - } - *nodeplace = node->vm_avl_left; - /* node replaces node_to_delete */ - node->vm_avl_left = node_to_delete->vm_avl_left; - node->vm_avl_right = node_to_delete->vm_avl_right; - node->vm_avl_height = node_to_delete->vm_avl_height; - *nodeplace_to_delete = node; /* replace node_to_delete */ - *stack_ptr_to_delete = &node->vm_avl_left; /* replace &node_to_delete->vm_avl_left */ - } - avl_rebalance(stack_ptr,stack_count); -} - -#ifdef DEBUG_AVL - -/* print a list */ -static void printk_list (struct vm_area_struct * vma) -{ - printk("["); - while (vma) { - printk("%08lX-%08lX", vma->vm_start, vma->vm_end); - vma = vma->vm_next; - if (!vma) - break; - printk(" "); - } - printk("]"); -} - -/* print a tree */ -static void printk_avl (struct vm_area_struct * tree) -{ - if (tree != avl_empty) { - printk("("); - if (tree->vm_avl_left != avl_empty) { - printk_avl(tree->vm_avl_left); - printk("<"); - } - printk("%08lX-%08lX", tree->vm_start, tree->vm_end); - if (tree->vm_avl_right != avl_empty) { - printk(">"); - printk_avl(tree->vm_avl_right); - } - printk(")"); - } -} - -static char *avl_check_point = "somewhere"; - -/* check a tree's consistency and balancing */ -static void avl_checkheights (struct vm_area_struct * tree) -{ - int h, hl, hr; - - if (tree == avl_empty) - return; - avl_checkheights(tree->vm_avl_left); - avl_checkheights(tree->vm_avl_right); - h = tree->vm_avl_height; - hl = heightof(tree->vm_avl_left); - hr = heightof(tree->vm_avl_right); - if ((h == hl+1) && (hr <= hl) && (hl <= hr+1)) - return; - if ((h == hr+1) && (hl <= hr) && (hr <= hl+1)) - return; - printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point); -} - -/* check that all values stored in a tree are < key */ -static void avl_checkleft (struct vm_area_struct * tree, vm_avl_key_t key) -{ - if (tree == avl_empty) - return; - avl_checkleft(tree->vm_avl_left,key); - avl_checkleft(tree->vm_avl_right,key); - if (tree->vm_avl_key < key) - return; - printk("%s: avl_checkleft: left key %lu >= top key %lu\n",avl_check_point,tree->vm_avl_key,key); -} - -/* check that all values stored in a tree are > key */ -static void avl_checkright (struct vm_area_struct * tree, vm_avl_key_t key) -{ - if (tree == avl_empty) - return; - avl_checkright(tree->vm_avl_left,key); - avl_checkright(tree->vm_avl_right,key); - if (tree->vm_avl_key > key) - return; - printk("%s: avl_checkright: right key %lu <= top key %lu\n",avl_check_point,tree->vm_avl_key,key); -} - -/* check that all values are properly increasing */ -static void avl_checkorder (struct vm_area_struct * tree) -{ - if (tree == avl_empty) - return; - avl_checkorder(tree->vm_avl_left); - avl_checkorder(tree->vm_avl_right); - avl_checkleft(tree->vm_avl_left,tree->vm_avl_key); - avl_checkright(tree->vm_avl_right,tree->vm_avl_key); -} - -/* all checks */ -static void avl_check (struct task_struct * task, char *caller) -{ - avl_check_point = caller; -/* printk("task \"%s\", %s\n",task->comm,caller); */ -/* printk("task \"%s\" list: ",task->comm); printk_list(task->mm->mmap); printk("\n"); */ -/* printk("task \"%s\" tree: ",task->comm); printk_avl(task->mm->mmap_avl); printk("\n"); */ - avl_checkheights(task->mm->mmap_avl); - avl_checkorder(task->mm->mmap_avl); -} - -#endif - - -/* - * Normal function to fix up a mapping +/* Normal function to fix up a mapping * This function is the default for when an area has no specific * function. This may be used as part of a more specific routine. * This function works out what part of an area is affected and @@ -738,19 +379,11 @@ struct vm_area_struct *mpnt; unsigned long end = addr + len; - if (addr < area->vm_start || addr >= area->vm_end || - end <= area->vm_start || end > area->vm_end || - end < addr) - { - printk("unmap_fixup: area=%lx-%lx, unmap %lx-%lx!!\n", - area->vm_start, area->vm_end, addr, end); - return; - } area->vm_mm->total_vm -= len >> PAGE_SHIFT; if (area->vm_flags & VM_LOCKED) area->vm_mm->locked_vm -= len >> PAGE_SHIFT; - /* Unmapping the whole area */ + /* Unmapping the whole area. */ if (addr == area->vm_start && end == area->vm_end) { if (area->vm_ops && area->vm_ops->close) area->vm_ops->close(area); @@ -759,15 +392,13 @@ return; } - /* Work out to one of the ends */ + /* Work out to one of the ends. */ if (end == area->vm_end) area->vm_end = addr; - else - if (addr == area->vm_start) { + else if (addr == area->vm_start) { area->vm_offset += (end - area->vm_start); area->vm_start = end; - } - else { + } else { /* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */ /* Add end mapping -- leave beginning for below */ mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); @@ -785,7 +416,7 @@ insert_vm_struct(current->mm, mpnt); } - /* construct whatever mapping is needed */ + /* Construct whatever mapping is needed. */ mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (!mpnt) return; @@ -809,15 +440,14 @@ return ret; } -/* - * Munmap is split into 2 main parts -- this part which finds +/* Munmap is split into 2 main parts -- this part which finds * what needs doing, and the areas themselves, which do the * work. This now handles partial unmappings. * Jeremy Fitzhardine */ int do_munmap(unsigned long addr, size_t len) { - struct vm_area_struct *mpnt, *prev, *next, **npp, *free; + struct vm_area_struct *mpnt, *next, *free; if ((addr & ~PAGE_MASK) || addr > TASK_SIZE || len > TASK_SIZE-addr) return -EINVAL; @@ -825,33 +455,36 @@ if ((len = PAGE_ALIGN(len)) == 0) return 0; - /* - * Check if this memory area is ok - put it on the temporary + /* Check if this memory area is ok - put it on the temporary * list if so.. The checks here are pretty simple -- * every area affected in some way (by any overlap) is put * on the list. If nothing is put on, nothing is affected. */ - mpnt = find_vma(current->mm, addr); + mpnt = current->mm->mmap; + while(mpnt && mpnt->vm_end <= addr) + mpnt = mpnt->vm_next; if (!mpnt) return 0; - avl_neighbours(mpnt, current->mm->mmap_avl, &prev, &next); - /* we have prev->vm_next == mpnt && mpnt->vm_next = next */ - /* and addr < mpnt->vm_end */ - npp = (prev ? &prev->vm_next : ¤t->mm->mmap); + next = mpnt->vm_next; + + /* we have mpnt->vm_next = next and addr < mpnt->vm_end */ free = NULL; - for ( ; mpnt && mpnt->vm_start < addr+len; mpnt = *npp) { - *npp = mpnt->vm_next; + for ( ; mpnt && mpnt->vm_start < addr+len; ) { + struct vm_area_struct *next = mpnt->vm_next; + + if(mpnt->vm_next) + mpnt->vm_next->vm_pprev = mpnt->vm_pprev; + *mpnt->vm_pprev = mpnt->vm_next; + mpnt->vm_next = free; free = mpnt; - avl_remove(mpnt, ¤t->mm->mmap_avl); + mpnt = next; } - if (free == NULL) return 0; - /* - * Ok - we have the memory areas we should free on the 'free' list, + /* Ok - we have the memory areas we should free on the 'free' list, * so release them, and unmap the page range.. * If the one of the segments is only being partially unmapped, * it will put new vm_area_struct(s) into the address space. @@ -871,36 +504,27 @@ if (mpnt->vm_ops && mpnt->vm_ops->unmap) mpnt->vm_ops->unmap(mpnt, st, size); + flush_cache_range(current->mm, st, end); zap_page_range(current->mm, st, size); flush_tlb_range(current->mm, st, end); + unmap_fixup(mpnt, st, size); + kmem_cache_free(vm_area_cachep, mpnt); } while (free); - /* we could zap the page tables here too.. */ - + current->mm->mmap_cache = NULL; /* Kill the cache. */ return 0; } -/* Build the AVL tree corresponding to the VMA list. */ -void build_mmap_avl(struct mm_struct * mm) -{ - struct vm_area_struct * vma; - - mm->mmap_avl = NULL; - for (vma = mm->mmap; vma; vma = vma->vm_next) - avl_insert(vma, &mm->mmap_avl); -} - /* Release all mmaps. */ void exit_mmap(struct mm_struct * mm) { struct vm_area_struct * mpnt; mpnt = mm->mmap; - mm->mmap = NULL; - mm->mmap_avl = NULL; + mm->mmap = mm->mmap_cache = NULL; mm->rss = 0; mm->total_vm = 0; mm->locked_vm = 0; @@ -925,81 +549,38 @@ } } -/* - * Insert vm structure into process list sorted by address +/* Insert vm structure into process list sorted by address * and into the inode's i_mmap ring. */ void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp) { - struct vm_area_struct *share; + struct vm_area_struct **pprev = &mm->mmap; struct inode * inode; -#if 0 /* equivalent, but slow */ - struct vm_area_struct **p, *mpnt; - - p = &mm->mmap; - while ((mpnt = *p) != NULL) { - if (mpnt->vm_start > vmp->vm_start) - break; - if (mpnt->vm_end > vmp->vm_start) - printk("insert_vm_struct: overlapping memory areas\n"); - p = &mpnt->vm_next; - } - vmp->vm_next = mpnt; - *p = vmp; -#else - struct vm_area_struct * prev, * next; - - avl_insert_neighbours(vmp, &mm->mmap_avl, &prev, &next); - if ((prev ? prev->vm_next : mm->mmap) != next) - printk("insert_vm_struct: tree inconsistent with list\n"); - if (prev) - prev->vm_next = vmp; - else - mm->mmap = vmp; - vmp->vm_next = next; -#endif + /* Find where to link it in. */ + while(*pprev && (*pprev)->vm_start <= vmp->vm_start) + pprev = &(*pprev)->vm_next; + + /* Insert it. */ + if((vmp->vm_next = *pprev) != NULL) + (*pprev)->vm_pprev = &vmp->vm_next; + *pprev = vmp; + vmp->vm_pprev = pprev; inode = vmp->vm_inode; - if (!inode) - return; - - /* insert vmp into inode's circular share list */ - if ((share = inode->i_mmap)) { - vmp->vm_next_share = share->vm_next_share; - vmp->vm_next_share->vm_prev_share = vmp; - share->vm_next_share = vmp; - vmp->vm_prev_share = share; - } else - inode->i_mmap = vmp->vm_next_share = vmp->vm_prev_share = vmp; -} - -/* - * Remove one vm structure from the inode's i_mmap ring. - */ -void remove_shared_vm_struct(struct vm_area_struct *mpnt) -{ - struct inode * inode = mpnt->vm_inode; - - if (!inode) - return; - - if (mpnt->vm_next_share == mpnt) { - if (inode->i_mmap != mpnt) - printk("Inode i_mmap ring corrupted\n"); - inode->i_mmap = NULL; - return; + if (inode) { + if (vmp->vm_flags & VM_DENYWRITE) + inode->i_writecount--; + + /* insert vmp into inode's share list */ + if((vmp->vm_next_share = inode->i_mmap) != NULL) + inode->i_mmap->vm_pprev_share = &vmp->vm_next_share; + inode->i_mmap = vmp; + vmp->vm_pprev_share = &inode->i_mmap; } - - if (inode->i_mmap == mpnt) - inode->i_mmap = mpnt->vm_next_share; - - mpnt->vm_prev_share->vm_next_share = mpnt->vm_next_share; - mpnt->vm_next_share->vm_prev_share = mpnt->vm_prev_share; } -/* - * Merge the list of memory segments if possible. +/* Merge the list of memory segments if possible. * Redundant vm_area_structs are freed. * This assumes that the list is ordered by address. * We don't need to traverse the entire list, only those segments @@ -1010,13 +591,19 @@ struct vm_area_struct *prev, *mpnt, *next; down(&mm->mmap_sem); - mpnt = find_vma(mm, start_addr); + + prev = NULL; + mpnt = mm->mmap; + while(mpnt && mpnt->vm_end <= start_addr) { + prev = mpnt; + mpnt = mpnt->vm_next; + } if (!mpnt) goto no_vma; - avl_neighbours(mpnt, mm->mmap_avl, &prev, &next); - /* we have prev->vm_next == mpnt && mpnt->vm_next = next */ + next = mpnt->vm_next; + /* we have prev->vm_next == mpnt && mpnt->vm_next = next */ if (!prev) { prev = mpnt; mpnt = next; @@ -1026,41 +613,32 @@ * start_addr < mpnt->vm_end && prev->vm_start < end_addr */ for ( ; mpnt && prev->vm_start < end_addr ; prev = mpnt, mpnt = next) { -#if 0 - printk("looping in merge_segments, mpnt=0x%lX\n", (unsigned long) mpnt); -#endif - next = mpnt->vm_next; - /* - * To share, we must have the same inode, operations.. - */ - if (mpnt->vm_inode != prev->vm_inode) - continue; - if (mpnt->vm_pte != prev->vm_pte) - continue; - if (mpnt->vm_ops != prev->vm_ops) - continue; - if (mpnt->vm_flags != prev->vm_flags) + /* To share, we must have the same inode, operations.. */ + if ((mpnt->vm_inode != prev->vm_inode) || + (mpnt->vm_pte != prev->vm_pte) || + (mpnt->vm_ops != prev->vm_ops) || + (mpnt->vm_flags != prev->vm_flags) || + (prev->vm_end != mpnt->vm_start)) continue; - if (prev->vm_end != mpnt->vm_start) - continue; - /* - * and if we have an inode, the offsets must be contiguous.. - */ + + /* and if we have an inode, the offsets must be contiguous.. */ if ((mpnt->vm_inode != NULL) || (mpnt->vm_flags & VM_SHM)) { - if (prev->vm_offset + prev->vm_end - prev->vm_start != mpnt->vm_offset) + unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start; + if (off != mpnt->vm_offset) continue; } - /* - * merge prev with mpnt and set up pointers so the new + /* merge prev with mpnt and set up pointers so the new * big segment can possibly merge with the next one. * The old unused mpnt is freed. */ - avl_remove(mpnt, &mm->mmap_avl); + if(mpnt->vm_next) + mpnt->vm_next->vm_pprev = mpnt->vm_pprev; + *mpnt->vm_pprev = mpnt->vm_next; + prev->vm_end = mpnt->vm_end; - prev->vm_next = mpnt->vm_next; if (mpnt->vm_ops && mpnt->vm_ops->close) { mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start; mpnt->vm_start = mpnt->vm_end; @@ -1072,11 +650,12 @@ kmem_cache_free(vm_area_cachep, mpnt); mpnt = prev; } + mm->mmap_cache = NULL; /* Kill the cache. */ no_vma: up(&mm->mmap_sem); } -void vma_init(void) +__initfunc(void vma_init(void)) { vm_area_cachep = kmem_cache_create("vm_area_struct", sizeof(struct vm_area_struct), @@ -1084,4 +663,11 @@ NULL, NULL); if(!vm_area_cachep) panic("vma_init: Cannot alloc vm_area_struct cache."); + + mm_cachep = kmem_cache_create("mm_struct", + sizeof(struct mm_struct), + sizeof(long) * 4, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if(!mm_cachep) + panic("vma_init: Cannot alloc mm_struct cache."); } diff -u --recursive --new-file v2.1.36/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.36/linux/mm/page_alloc.c Wed Apr 23 19:01:29 1997 +++ linux/mm/page_alloc.c Thu May 1 12:05:06 1997 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -265,7 +266,7 @@ * - mark all memory queues empty * - clear the memory bitmaps */ -unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem) +__initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)) { mem_map_t * p; unsigned long mask = PAGE_MASK; @@ -273,7 +274,7 @@ /* * select nr of pages we try to keep free for important stuff - * with a minimum of 16 pages. This is totally arbitrary + * with a minimum of 48 pages. This is totally arbitrary */ i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7); if (i < 48) diff -u --recursive --new-file v2.1.36/linux/mm/slab.c linux/mm/slab.c --- v2.1.36/linux/mm/slab.c Mon Apr 14 16:28:27 1997 +++ linux/mm/slab.c Thu May 1 12:05:06 1997 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -269,8 +270,8 @@ static kmem_cache_t *clock_searchp = &cache_cache; /* Init an internal cache */ -static void -kmem_own_cache_init(kmem_cache_t *cachep) +__initfunc(static void +kmem_own_cache_init(kmem_cache_t *cachep)) { unsigned long size, i; @@ -293,8 +294,8 @@ } /* Initialisation - setup all internal caches */ -long -kmem_cache_init(long start, long end) +__initfunc(long +kmem_cache_init(long start, long end)) { /* sanity */ #define kmem_cache_offset(x) ((unsigned long)&((kmem_cache_t *)0)->x) @@ -319,8 +320,8 @@ } /* Initialisation - setup general caches */ -void -kmem_cache_sizes_init(void) +__initfunc(void +kmem_cache_sizes_init(void)) { unsigned long i; diff -u --recursive --new-file v2.1.36/linux/mm/swap.c linux/mm/swap.c --- v2.1.36/linux/mm/swap.c Wed Apr 23 19:01:29 1997 +++ linux/mm/swap.c Thu May 1 12:05:06 1997 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -67,7 +68,7 @@ /* General swap control */ /* Parse the kernel command line "swap=" option at load time: */ -void swap_setup(char *str, int *ints) +__initfunc(void swap_setup(char *str, int *ints)) { int * swap_vars[8] = { &MAX_PAGE_AGE, @@ -87,7 +88,7 @@ } /* Parse the kernel command line "buff=" option at load time: */ -void buff_setup(char *str, int *ints) +__initfunc(void buff_setup(char *str, int *ints)) { int * buff_vars[6] = { &MAX_BUFF_AGE, diff -u --recursive --new-file v2.1.36/linux/mm/swap_state.c linux/mm/swap_state.c --- v2.1.36/linux/mm/swap_state.c Mon Oct 28 04:21:41 1996 +++ linux/mm/swap_state.c Thu May 1 12:05:06 1997 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -69,8 +70,8 @@ return 0; } -unsigned long init_swap_cache(unsigned long mem_start, - unsigned long mem_end) +__initfunc(unsigned long init_swap_cache(unsigned long mem_start, + unsigned long mem_end)) { unsigned long swap_cache_size; diff -u --recursive --new-file v2.1.36/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.1.36/linux/mm/swapfile.c Tue Jan 28 00:02:45 1997 +++ linux/mm/swapfile.c Sun Apr 27 15:08:03 1997 @@ -298,24 +298,25 @@ */ static int try_to_unuse(unsigned int type) { - int nr; unsigned long page = get_free_page(GFP_KERNEL); + struct task_struct *p; if (!page) return -ENOMEM; - nr = 0; - while (nr < NR_TASKS) { - struct task_struct * p = task[nr]; - if (p) { - if (unuse_process(p->mm, type, page)) { - page = get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - continue; - } +again: + read_lock(&tasklist_lock); + for_each_task(p) { + read_unlock(&tasklist_lock); + if(unuse_process(p->mm, type, page)) { + page = get_free_page(GFP_KERNEL); + if(!page) + return -ENOMEM; + goto again; } - nr++; + read_lock(&tasklist_lock); } + read_unlock(&tasklist_lock); + free_page(page); return 0; } diff -u --recursive --new-file v2.1.36/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.36/linux/mm/vmscan.c Mon Apr 14 16:28:27 1997 +++ linux/mm/vmscan.c Sun Apr 27 15:08:03 1997 @@ -271,54 +271,72 @@ static int swap_out(unsigned int priority, int dma, int wait) { - static int swap_task; - int loop, counter; + static int skip_factor = 0; + int limit = nr_tasks - 1; + int loop, counter, i; struct task_struct *p; counter = ((PAGEOUT_WEIGHT * nr_tasks) >> 10) >> priority; + if(skip_factor > nr_tasks) + skip_factor = 0; + + read_lock(&tasklist_lock); + p = init_task.next_task; + i = skip_factor; + while(i--) + p = p->next_task; for(; counter >= 0; counter--) { - /* - * Check that swap_task is suitable for swapping. If not, look for - * the next suitable process. - */ + /* Check if task is suitable for swapping. */ loop = 0; while(1) { - if (swap_task >= NR_TASKS) { - swap_task = 1; + if(!--limit) { + limit = nr_tasks - 1; + /* See if all processes are unswappable or + * already swapped out. + */ if (loop) - /* all processes are unswappable or already swapped out */ - return 0; + goto out; loop = 1; } - - p = task[swap_task]; - if (p && p->swappable && p->mm->rss) + if (p->swappable && p->mm->rss) break; - - swap_task++; + if((p = p->next_task) == &init_task) + p = p->next_task; } + skip_factor++; - /* - * Determine the number of pages to swap from this process. - */ + /* Determine the number of pages to swap from this process. */ if (!p->swap_cnt) { - /* Normalise the number of pages swapped by + /* Normalise the number of pages swapped by multiplying by (RSS / 1MB) */ p->swap_cnt = AGE_CLUSTER_SIZE(p->mm->rss); } if (!--p->swap_cnt) - swap_task++; + skip_factor++; + read_unlock(&tasklist_lock); + switch (swap_out_process(p, dma, wait)) { - case 0: - if (p->swap_cnt) - swap_task++; - break; - case 1: - return 1; - default: - break; - } + case 0: + if (p->swap_cnt) + skip_factor++; + break; + case 1: + return 1; + default: + break; + }; + + /* Whoever we swapped may not even exist now, in fact we cannot + * assume anything about the list we were searching previously. + */ + read_lock(&tasklist_lock); + p = init_task.next_task; + i = skip_factor; + while(i--) + p = p->next_task; } +out: + read_unlock(&tasklist_lock); return 0; } diff -u --recursive --new-file v2.1.36/linux/net/802/llc_macinit.c linux/net/802/llc_macinit.c --- v2.1.36/linux/net/802/llc_macinit.c Thu Feb 27 10:57:32 1997 +++ linux/net/802/llc_macinit.c Thu May 1 12:05:06 1997 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -202,7 +203,7 @@ #define ALL_TYPES_8022 0 -void llc_init(struct net_proto *proto) +__initfunc(void llc_init(struct net_proto *proto)) { printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n"); return; diff -u --recursive --new-file v2.1.36/linux/net/802/p8022.c linux/net/802/p8022.c --- v2.1.36/linux/net/802/p8022.c Fri Feb 7 05:54:55 1997 +++ linux/net/802/p8022.c Thu May 1 12:05:07 1997 @@ -23,6 +23,7 @@ #include #include #include +#include #include static struct datalink_proto *p8022_list = NULL; @@ -90,7 +91,7 @@ EXPORT_SYMBOL(register_8022_client); EXPORT_SYMBOL(unregister_8022_client); -void p8022_proto_init(struct net_proto *pro) +__initfunc(void p8022_proto_init(struct net_proto *pro)) { p8022_packet_type.type=htons(ETH_P_802_2); dev_add_pack(&p8022_packet_type); diff -u --recursive --new-file v2.1.36/linux/net/802/p8022tr.c linux/net/802/p8022tr.c --- v2.1.36/linux/net/802/p8022tr.c Fri Jan 3 01:33:27 1997 +++ linux/net/802/p8022tr.c Thu May 1 12:05:07 1997 @@ -15,6 +15,7 @@ #include #include #include +#include #include #define SNAP_HEADER_LEN 8 @@ -91,7 +92,7 @@ EXPORT_SYMBOL(register_8022tr_client); EXPORT_SYMBOL(unregister_8022tr_client); -void p8022tr_proto_init(struct net_proto *pro) +__initfunc(void p8022tr_proto_init(struct net_proto *pro)) { p8022tr_packet_type.type=htons(ETH_P_TR_802_2); dev_add_pack(&p8022tr_packet_type); diff -u --recursive --new-file v2.1.36/linux/net/802/psnap.c linux/net/802/psnap.c --- v2.1.36/linux/net/802/psnap.c Fri Jan 3 01:33:27 1997 +++ linux/net/802/psnap.c Thu May 1 12:05:07 1997 @@ -19,6 +19,7 @@ #include #include #include +#include static struct datalink_proto *snap_list = NULL; static struct datalink_proto *snap_dl = NULL; /* 802.2 DL for SNAP */ @@ -87,7 +88,7 @@ EXPORT_SYMBOL(register_snap_client); EXPORT_SYMBOL(unregister_snap_client); -void snap_proto_init(struct net_proto *pro) +__initfunc(void snap_proto_init(struct net_proto *pro)) { snap_dl=register_8022_client(0xAA, snap_rcv); if(snap_dl==NULL) diff -u --recursive --new-file v2.1.36/linux/net/802/tr.c linux/net/802/tr.c --- v2.1.36/linux/net/802/tr.c Mon Apr 14 16:28:27 1997 +++ linux/net/802/tr.c Thu May 1 12:05:07 1997 @@ -31,6 +31,7 @@ #include #include #include +#include #include static void tr_source_route(struct trh_hdr *trh, struct device *dev); @@ -460,7 +461,7 @@ * too much for this. */ -void rif_init(struct net_proto *unused) +__initfunc(void rif_init(struct net_proto *unused)) { rif_timer.expires = RIF_TIMEOUT; diff -u --recursive --new-file v2.1.36/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c --- v2.1.36/linux/net/appletalk/aarp.c Sun Feb 2 05:18:48 1997 +++ linux/net/appletalk/aarp.c Thu May 1 12:05:07 1997 @@ -47,6 +47,7 @@ #include #include #include +#include /* * Lists of aarp entries @@ -796,7 +797,7 @@ static char aarp_snap_id[]={0x00,0x00,0x00,0x80,0xF3}; -void aarp_proto_init(void) +__initfunc(void aarp_proto_init(void)) { if((aarp_dl=register_snap_client(aarp_snap_id, aarp_rcv))==NULL) printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); diff -u --recursive --new-file v2.1.36/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c --- v2.1.36/linux/net/appletalk/ddp.c Mon Apr 14 16:28:27 1997 +++ linux/net/appletalk/ddp.c Thu May 1 12:05:07 1997 @@ -67,6 +67,7 @@ #include #include #include +#include #undef APPLETALK_DEBUG @@ -2034,7 +2035,7 @@ /* Called by proto.c on kernel start up */ -void atalk_proto_init(struct net_proto *pro) +__initfunc(void atalk_proto_init(struct net_proto *pro)) { (void) sock_register(&atalk_family_ops); if ((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL) diff -u --recursive --new-file v2.1.36/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c --- v2.1.36/linux/net/ax25/af_ax25.c Mon Apr 14 16:28:27 1997 +++ linux/net/ax25/af_ax25.c Thu May 1 12:05:07 1997 @@ -126,6 +126,7 @@ #include #include #include +#include #include #include @@ -1795,7 +1796,7 @@ }; #endif -void ax25_proto_init(struct net_proto *pro) +__initfunc(void ax25_proto_init(struct net_proto *pro)) { sock_register(&ax25_family_ops); ax25_packet_type.type = htons(ETH_P_AX25); diff -u --recursive --new-file v2.1.36/linux/net/core/firewall.c linux/net/core/firewall.c --- v2.1.36/linux/net/core/firewall.c Thu Mar 27 14:40:14 1997 +++ linux/net/core/firewall.c Thu May 1 12:05:07 1997 @@ -10,6 +10,7 @@ #include #include #include +#include #include struct semaphore firewall_sem = MUTEX; @@ -150,7 +151,7 @@ EXPORT_SYMBOL(call_out_firewall); EXPORT_SYMBOL(call_fw_firewall); -void fwchain_init(void) +__initfunc(void fwchain_init(void)) { int i; for(i=0;i SK_WMEM_MAX*2) + /* printk(KERN_DEBUG "setting SO_SNDBUF %d\n", val); */ + if (val > sysctl_wmem_max) return -EINVAL; - /* - * Once this is all 32bit values we can - * drop this check. + + /* FIXME: the tcp code should be made to work even + * with small sndbuf values. */ - if(val > 65535) - return -EINVAL; - sk->sndbuf = max(val,2048); + sk->sndbuf = max(val*2,2048); + /* * Wake up sending tasks if we * upped the value. @@ -206,12 +207,13 @@ break; case SO_RCVBUF: - if(val > SK_RMEM_MAX*2) - return -EINVAL; - /* Can go soon: FIXME */ - if(val > 65535) + /* printk(KERN_DEBUG "setting SO_RCVBUF %d\n", val); */ + + if (val > sysctl_rmem_max) return -EINVAL; - sk->rcvbuf = max(val,256); + + /* FIXME: is this lower bound the right one? */ + sk->rcvbuf = max(val*2,256); break; case SO_KEEPALIVE: @@ -533,15 +535,29 @@ } +/* FIXME: this is insane. We are trying suppose to be controlling how + * how much space we have for data bytes, not packet headers. + * This really points out that we need a better system for doing the + * receive buffer. -- erics + * WARNING: This is currently ONLY used in tcp. If you need it else where + * this will probably not be what you want. Possibly these two routines + * should move over to the ipv4 directory. + */ unsigned long sock_rspace(struct sock *sk) { int amt; - if (sk != NULL) - { - if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf-2*MIN_WINDOW) - return(0); - amt = min((sk->rcvbuf-atomic_read(&sk->rmem_alloc))/2-MIN_WINDOW, MAX_WINDOW); + if (sk != NULL) { + /* This used to have some bizzare complications that + * to attempt to reserve some amount of space. This doesn't + * make sense, since the number returned here does not + * actually reflect allocated space, but rather the amount + * of space we committed to. We gamble that we won't + * run out of memory, and returning a smaller number does + * not change the gamble. If we loose the gamble tcp still + * works, it may just slow down for retransmissions. + */ + amt = sk->rcvbuf - atomic_read(&sk->rmem_alloc); if (amt < 0) return(0); return(amt); @@ -550,10 +566,10 @@ } +/* FIXME: this is also insane. See above comment */ unsigned long sock_wspace(struct sock *sk) { - if (sk != NULL) - { + if (sk != NULL) { if (sk->shutdown & SEND_SHUTDOWN) return(0); if (atomic_read(&sk->wmem_alloc) >= sk->sndbuf) @@ -868,8 +884,8 @@ init_timer(&sk->timer); sk->allocation = GFP_KERNEL; - sk->rcvbuf = SK_RMEM_MAX; - sk->sndbuf = SK_WMEM_MAX; + sk->rcvbuf = sysctl_rmem_default*2; + sk->sndbuf = sysctl_wmem_default*2; sk->priority = SOPRI_NORMAL; sk->state = TCP_CLOSE; sk->zapped = 1; diff -u --recursive --new-file v2.1.36/linux/net/core/sysctl_net_core.c linux/net/core/sysctl_net_core.c --- v2.1.36/linux/net/core/sysctl_net_core.c Mon Apr 1 22:03:35 1996 +++ linux/net/core/sysctl_net_core.c Thu May 8 10:00:12 1997 @@ -8,6 +8,23 @@ #include #include +extern __u32 sysctl_wmem_max; +extern __u32 sysctl_rmem_max; +extern __u32 sysctl_wmem_default; +extern __u32 sysctl_rmem_default; + ctl_table core_table[] = { - {0} + {NET_CORE_WMEM_MAX, "wmem_max", + &sysctl_wmem_max, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_RMEM_MAX, "rmem_max", + &sysctl_rmem_max, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_WMEM_DEFAULT, "wmem_default", + &sysctl_wmem_default, sizeof(int), 0644, NULL, + &proc_dointvec}, + {NET_CORE_RMEM_DEFAULT, "rmem_default", + &sysctl_rmem_default, sizeof(int), 0644, NULL, + &proc_dointvec}, + { 0 } }; diff -u --recursive --new-file v2.1.36/linux/net/ethernet/eth.c linux/net/ethernet/eth.c --- v2.1.36/linux/net/ethernet/eth.c Wed Apr 23 19:01:29 1997 +++ linux/net/ethernet/eth.c Thu May 1 12:05:07 1997 @@ -36,8 +36,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include -#include #include #include #include @@ -52,16 +50,17 @@ #include #include #include +#include #include #include #include #include - - +#include +#include #include -void eth_setup(char *str, int *ints) +__initfunc(void eth_setup(char *str, int *ints)) { struct device *d = dev_base; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.1.36/linux/net/ipv4/af_inet.c Mon Apr 14 16:28:27 1997 +++ linux/net/ipv4/af_inet.c Thu May 1 12:05:07 1997 @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -1063,7 +1064,7 @@ * Called by socket.c on kernel startup. */ -void inet_proto_init(struct net_proto *pro) +__initfunc(void inet_proto_init(struct net_proto *pro)) { struct sk_buff *dummy_skb; struct inet_protocol *p; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/arp.c linux/net/ipv4/arp.c --- v2.1.36/linux/net/ipv4/arp.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/arp.c Thu May 1 12:05:07 1997 @@ -90,6 +90,7 @@ #include #include #include +#include #include #include @@ -1976,7 +1977,7 @@ }; #endif -void arp_init (void) +__initfunc(void arp_init (void)) { dev_add_pack(&arp_packet_type); /* Start with the regular checks for expired arp entries. */ diff -u --recursive --new-file v2.1.36/linux/net/ipv4/fib.c linux/net/ipv4/fib.c --- v2.1.36/linux/net/ipv4/fib.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/fib.c Thu May 1 12:05:07 1997 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -2020,7 +2021,7 @@ } -void ip_fib_init() +__initfunc(void ip_fib_init(void)) { struct in_rtrulemsg r; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.1.36/linux/net/ipv4/icmp.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/icmp.c Thu May 1 12:05:07 1997 @@ -256,6 +256,7 @@ #include #include #include +#include #include #include #include @@ -373,7 +374,7 @@ #ifndef CONFIG_NO_ICMP_LIMIT -static void xrlim_init(void) +__initfunc(static void xrlim_init(void)) { int type, entry; struct icmp_xrlim *xr; @@ -1167,7 +1168,7 @@ { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_address_reply, 0, NULL } }; -void icmp_init(struct net_proto_family *ops) +__initfunc(void icmp_init(struct net_proto_family *ops)) { int err; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_alias.c linux/net/ipv4/ip_alias.c --- v2.1.36/linux/net/ipv4/ip_alias.c Thu Dec 12 06:54:23 1996 +++ linux/net/ipv4/ip_alias.c Thu May 1 12:05:07 1997 @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef ALIAS_USER_LAND_DEBUG @@ -137,7 +138,7 @@ * ip_alias module initialization */ -int ip_alias_init(void) +__initfunc(int ip_alias_init(void)) { return register_net_alias_type(&ip_alias_type, AF_INET); } diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.1.36/linux/net/ipv4/ip_fragment.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/ip_fragment.c Thu May 1 12:05:07 1997 @@ -518,7 +518,7 @@ prev = NULL; for(next = qp->fragments; next != NULL; next = next->next) { - if (next->offset > offset) + if (next->offset >= offset) break; /* bingo! */ prev = next; } diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.1.36/linux/net/ipv4/ip_fw.c Thu Mar 27 14:40:15 1997 +++ linux/net/ipv4/ip_fw.c Thu May 1 12:05:07 1997 @@ -107,6 +107,7 @@ #include #include #include +#include #ifdef CONFIG_IP_MASQUERADE #include @@ -1298,7 +1299,7 @@ #endif -void ip_fw_init(void) +__initfunc(void ip_fw_init(void)) { #ifdef CONFIG_PROC_FS #ifdef CONFIG_IP_ACCT diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c --- v2.1.36/linux/net/ipv4/ip_masq.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/ip_masq.c Thu May 1 12:05:07 1997 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1010,7 +1011,7 @@ /* * Initialize ip masquerading */ -int ip_masq_init(void) +__initfunc(int ip_masq_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_net_ipmsqhst); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq_app.c linux/net/ipv4/ip_masq_app.c --- v2.1.36/linux/net/ipv4/ip_masq_app.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/ip_masq_app.c Thu May 1 12:05:07 1997 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -482,7 +483,7 @@ * Initialization routine */ -int ip_masq_app_init(void) +__initfunc(int ip_masq_app_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_net_ip_masq_app); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq_ftp.c linux/net/ipv4/ip_masq_ftp.c --- v2.1.36/linux/net/ipv4/ip_masq_ftp.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/ip_masq_ftp.c Thu May 1 12:05:07 1997 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -187,7 +188,7 @@ * ip_masq_ftp initialization */ -int ip_masq_ftp_init(void) +__initfunc(int ip_masq_ftp_init(void)) { return register_ip_masq_app(&ip_masq_ftp, IPPROTO_TCP, 21); } diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq_irc.c linux/net/ipv4/ip_masq_irc.c --- v2.1.36/linux/net/ipv4/ip_masq_irc.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/ip_masq_irc.c Thu May 1 12:05:07 1997 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -238,7 +239,7 @@ * ip_masq_irc initialization */ -int ip_masq_irc_init(void) +__initfunc(int ip_masq_irc_init(void)) { return register_ip_masq_app(&ip_masq_irc, IPPROTO_TCP, 6667); } diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq_quake.c linux/net/ipv4/ip_masq_quake.c --- v2.1.36/linux/net/ipv4/ip_masq_quake.c Thu Mar 27 14:40:15 1997 +++ linux/net/ipv4/ip_masq_quake.c Thu May 1 12:05:07 1997 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -279,7 +280,7 @@ * ip_masq_quake initialization */ -int ip_masq_quake_init(void) +__initfunc(int ip_masq_quake_init(void)) { return (register_ip_masq_app(&ip_masq_quake, IPPROTO_UDP, 26000) + register_ip_masq_app(&ip_masq_quakenew, IPPROTO_UDP, 27000)); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_masq_raudio.c linux/net/ipv4/ip_masq_raudio.c --- v2.1.36/linux/net/ipv4/ip_masq_raudio.c Mon Apr 14 16:28:27 1997 +++ linux/net/ipv4/ip_masq_raudio.c Thu May 1 12:05:07 1997 @@ -2,7 +2,7 @@ * IP_MASQ_RAUDIO - Real Audio masquerading module * * - * Version: @(#)$Id: ip_masq_raudio.c,v 1.5 1997/04/03 08:52:02 davem Exp $ + * Version: @(#)$Id: ip_masq_raudio.c,v 1.6 1997/04/29 09:38:26 mj Exp $ * * Author: Nigel Metheringham * [strongly based on ftp module by Juan Jose Ciarlante & Wouter Gadeyne] @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -200,7 +201,7 @@ * ip_masq_raudio initialization */ -int ip_masq_raudio_init(void) +__initfunc(int ip_masq_raudio_init(void)) { return register_ip_masq_app(&ip_masq_raudio, IPPROTO_TCP, 7070); } diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.1.36/linux/net/ipv4/ip_output.c Fri Apr 4 08:52:28 1997 +++ linux/net/ipv4/ip_output.c Thu May 1 12:05:07 1997 @@ -27,6 +27,8 @@ * (in case if packet not accepted by * output firewall rules) * Alexey Kuznetsov: use new route cache + * Andi Kleen: Fix broken PMTU recovery and remove + * some redundant tests. */ #include @@ -47,6 +49,7 @@ #include #include #include +#include #include #include @@ -126,9 +129,8 @@ iph->ihl = 5; iph->tos = sk->ip_tos; iph->frag_off = 0; - if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && + !(rt->rt_flags & RTF_NOPMTUDISC)) iph->frag_off |= htons(IP_DF); iph->ttl = sk->ip_ttl; iph->daddr = rt->rt_dst; @@ -207,9 +209,8 @@ iph->ihl = 5; iph->tos = sk->ip_tos; iph->frag_off = 0; - if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && + !(rt->rt_flags & RTF_NOPMTUDISC)) iph->frag_off |= htons(IP_DF); iph->ttl = sk->ip_ttl; iph->daddr = rt->rt_dst; @@ -480,8 +481,7 @@ #endif if (sk->ip_pmtudisc == IP_PMTUDISC_DONT || - (sk->ip_pmtudisc == IP_PMTUDISC_WANT && - rt->rt_flags&RTF_NOPMTUDISC)) + rt->rt_flags&RTF_NOPMTUDISC) df = 0; @@ -1036,7 +1036,7 @@ * IP registers the packet type and then calls the subprotocol initialisers */ -void ip_init(void) +__initfunc(void ip_init(void)) { dev_add_pack(&ip_packet_type); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v2.1.36/linux/net/ipv4/ipmr.c Mon Apr 14 16:28:27 1997 +++ linux/net/ipv4/ipmr.c Thu May 1 12:05:07 1997 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -1065,7 +1066,7 @@ * Setup for IP multicast routing */ -void ip_mr_init(void) +__initfunc(void ip_mr_init(void)) { printk(KERN_INFO "Linux IP multicast router 0.06.\n"); register_netdevice_notifier(&ip_mr_notifier); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c --- v2.1.36/linux/net/ipv4/rarp.c Thu Dec 12 06:54:24 1996 +++ linux/net/ipv4/rarp.c Thu May 1 12:05:07 1997 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -553,8 +554,8 @@ rarp_get_info }; -void -rarp_init(void) +__initfunc(void +rarp_init(void)) { proc_net_register(&proc_net_rarp); rarp_ioctl_hook = rarp_ioctl; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v2.1.36/linux/net/ipv4/route.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/route.c Thu May 1 12:05:07 1997 @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -1379,7 +1380,7 @@ rt_cache_flush(0); } -void ip_rt_init() +__initfunc(void ip_rt_init(void)) { ip_fib_init(); diff -u --recursive --new-file v2.1.36/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.36/linux/net/ipv4/tcp.c Wed Apr 23 19:01:29 1997 +++ linux/net/ipv4/tcp.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.61 1997/04/22 02:53:10 davem Exp $ + * Version: $Id: tcp.c,v 1.63 1997/04/29 09:38:33 mj Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -424,6 +424,7 @@ #include #include #include +#include #include #include @@ -849,7 +850,6 @@ tcp_size = skb->tail - ((unsigned char *)(skb->h.th) + tp->tcp_header_len); - /* printk("extending buffer\n"); */ /* This window_seq test is somewhat dangerous * If the remote does SWS avoidance we should * queue the best we can if not we should in @@ -1100,6 +1100,9 @@ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); __u32 rcv_wnd; + /* FIXME: double check this rule, then check against + * other use of similar rules. Abtract if possible. + */ rcv_wnd = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); if ((rcv_wnd < sk->mss) && (sock_rspace(sk) > rcv_wnd)) @@ -1655,7 +1658,7 @@ tcp_dec_slow_timer(TCP_SLT_KEEPALIVE); } -void tcp_init(void) +__initfunc(void tcp_init(void)) { tcp_openreq_cachep = kmem_cache_create("tcp_open_request", sizeof(struct open_request), diff -u --recursive --new-file v2.1.36/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.36/linux/net/ipv4/tcp_input.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv4/tcp_input.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.50 1997/04/22 02:53:12 davem Exp $ + * Version: $Id: tcp_input.c,v 1.51 1997/04/27 19:24:40 schenk Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -321,8 +321,10 @@ break; case TCPOPT_WINDOW: if(opsize==TCPOLEN_WINDOW && th->syn) - if (sysctl_tcp_window_scaling) + if (sysctl_tcp_window_scaling) { + tp->wscale_ok = 1; tp->snd_wscale = *(__u8 *)ptr; + } break; case TCPOPT_SACK_PERM: if(opsize==TCPOLEN_SACK_PERM && th->syn) @@ -816,7 +818,7 @@ */ if (before(tp->snd_wl1, ack_seq) || (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack))) { - unsigned long nwin = ntohs(th->window); + unsigned long nwin = ntohs(th->window) << tp->snd_wscale; if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd)) { flag |= FLAG_WIN_UPDATE; @@ -1464,17 +1466,21 @@ if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0) return 1; - /* Now we have several options: In theory there is - * nothing else in the frame. KA9Q has an option to - * send data with the syn, BSD accepts data with the - * syn up to the [to be] advertised window and - * Solaris 2.1 gives you a protocol error. For now - * we just ignore it, that fits the spec precisely - * and avoids incompatibilities. It would be nice in - * future to drop through and process the data. + /* Now we have several options: In theory there is + * nothing else in the frame. KA9Q has an option to + * send data with the syn, BSD accepts data with the + * syn up to the [to be] advertised window and + * Solaris 2.1 gives you a protocol error. For now + * we just ignore it, that fits the spec precisely + * and avoids incompatibilities. It would be nice in + * future to drop through and process the data. * - * Now that TTCP is starting to be used we ought to - * queue this data. + * Now that TTCP is starting to be used we ought to + * queue this data. + * But, this leaves one open to an easy denial of + * service attack, and SYN cookies can't defend + * against this problem. So, we drop the data + * in the interest of security over speed. */ return 0; } @@ -1514,10 +1520,9 @@ * move to established. */ tp->rcv_nxt = skb->seq+1; - tp->rcv_wnd = 0; tp->rcv_wup = skb->seq+1; - tp->snd_wnd = htons(th->window); + tp->snd_wnd = htons(th->window) << tp->snd_wscale; tp->snd_wl1 = skb->seq; tp->snd_wl2 = skb->ack_seq; @@ -1526,6 +1531,10 @@ tcp_set_state(sk, TCP_ESTABLISHED); tcp_parse_options(th,tp); /* FIXME: need to make room for SACK still */ + if (tp->wscale_ok == 0) { + tp->snd_wscale = tp->rcv_wscale = 0; + tp->window_clamp = min(tp->window_clamp,65535); + } if (tp->tstamp_ok) { tp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: Define constant! */ sk->dummy_th.doff += 3; /* reserve space of options */ @@ -1695,7 +1704,7 @@ sk->state_change(sk); tp->snd_una = skb->ack_seq; - tp->snd_wnd = htons(th->window); + tp->snd_wnd = htons(th->window) << tp->snd_wscale; tp->snd_wl1 = skb->seq; tp->snd_wl2 = skb->ack_seq; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.36/linux/net/ipv4/tcp_ipv4.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv4/tcp_ipv4.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.39 1997/04/22 02:53:14 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.42 1997/04/29 16:09:46 schenk Exp $ * * IPv4 specific functions * @@ -465,7 +465,7 @@ struct sk_buff *buff; struct sk_buff *skb1; int tmp; - struct tcphdr *t1; + struct tcphdr *th; struct rtable *rt; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; @@ -546,20 +546,17 @@ return(-ENETUNREACH); } - t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr)); - buff->h.th = t1; + th = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr)); + buff->h.th = th; - memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1)); + memcpy(th,(void *)&(sk->dummy_th), sizeof(*th)); buff->seq = sk->write_seq++; - t1->seq = htonl(buff->seq); + th->seq = htonl(buff->seq); tp->snd_nxt = sk->write_seq; buff->end_seq = sk->write_seq; - t1->ack = 0; - t1->window = htons(512); - t1->syn = 1; + th->ack = 0; + th->syn = 1; - /* Use 512 or whatever user asked for. */ - tp->window_clamp = rt->u.dst.window; sk->mtu = rt->u.dst.pmtu; if ((sk->ip_pmtudisc == IP_PMTUDISC_DONT || @@ -577,13 +574,26 @@ sk->mss = (sk->mtu - sizeof(struct iphdr) - sizeof(struct tcphdr)); + if (sk->mss < 1) { + printk(KERN_DEBUG "intial sk->mss below 1\n"); + sk->mss = 1; /* Sanity limit */ + } + + tp->window_clamp = rt->u.dst.window; + tcp_select_initial_window(sock_rspace(sk)/2,sk->mss, + &tp->rcv_wnd, + &tp->window_clamp, + sysctl_tcp_window_scaling, + &tp->rcv_wscale); + th->window = htons(tp->rcv_wnd); + tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack, sysctl_tcp_timestamps, - sysctl_tcp_window_scaling?tp->rcv_wscale:0); + sysctl_tcp_window_scaling,tp->rcv_wscale); buff->csum = 0; - t1->doff = (sizeof(*t1)+ tmp)>>2; + th->doff = (sizeof(*th)+ tmp)>>2; - tcp_v4_send_check(sk, t1, sizeof(struct tcphdr) + tmp, buff); + tcp_v4_send_check(sk, th, sizeof(struct tcphdr) + tmp, buff); tcp_set_state(sk,TCP_SYN_SENT); @@ -803,7 +813,6 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; struct sk_buff * skb; struct tcphdr *th; int tmp; @@ -829,6 +838,11 @@ */ req->mss = min(mss, req->mss); + if (req->mss < 1) { + printk(KERN_DEBUG "initial req->mss below 1\n"); + req->mss = 1; + } + /* Yuck, make this header setup more efficient... -DaveM */ memset(th, 0, sizeof(struct tcphdr)); th->syn = 1; @@ -839,7 +853,16 @@ skb->end_seq = skb->seq + 1; th->seq = ntohl(skb->seq); th->ack_seq = htonl(req->rcv_isn + 1); - th->window = ntohs(tp->rcv_wnd); + if (req->rcv_wnd == 0) { + /* Set this up on the first call only */ + req->window_clamp = skb->dst->window; + tcp_select_initial_window(sock_rspace(sk)/2,req->mss, + &req->rcv_wnd, + &req->window_clamp, + req->wscale_ok, + &req->rcv_wscale); + } + th->window = htons(req->rcv_wnd); /* XXX Partial csum of 4 byte quantity is itself! -DaveM * Yes, but it's a bit harder to special case now. It's @@ -850,7 +873,7 @@ */ tmp = tcp_syn_build_options(skb, req->mss, req->sack_ok, req->tstamp_ok, - (req->snd_wscale)?tp->rcv_wscale:0); + req->wscale_ok,req->rcv_wscale); skb->csum = 0; th->doff = (sizeof(*th) + tmp)>>2; th->check = tcp_v4_check(th, sizeof(*th) + tmp, @@ -881,7 +904,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) { struct ip_options *opt = (struct ip_options *) ptr; - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + struct tcp_opt tp; struct open_request *req; struct tcphdr *th = skb->h.th; __u32 saddr = skb->nh.iph->saddr; @@ -913,19 +936,20 @@ sk->ack_backlog++; + req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ + req->rcv_isn = skb->seq; req->snt_isn = isn; - tp->tstamp_ok = tp->sack_ok = tp->snd_wscale = 0; - tcp_parse_options(th,tp); - if (tp->saw_tstamp) { - tp->ts_recent = tp->rcv_tsval; - tp->ts_recent_stamp = jiffies; - } - req->mss = tp->in_mss; - req->tstamp_ok = tp->tstamp_ok; - req->sack_ok = tp->sack_ok; - req->snd_wscale = tp->snd_wscale; - req->ts_recent = tp->ts_recent; + tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; + tp.in_mss = 536; + tcp_parse_options(th,&tp); + if (tp.saw_tstamp) + req->ts_recent = tp.rcv_tsval; + req->mss = tp.in_mss; + req->tstamp_ok = tp.tstamp_ok; + req->sack_ok = tp.sack_ok; + req->snd_wscale = tp.snd_wscale; + req->wscale_ok = tp.wscale_ok; req->rmt_port = th->source; req->af.v4_req.loc_addr = daddr; req->af.v4_req.rmt_addr = saddr; @@ -1004,8 +1028,6 @@ atomic_set(&newsk->rmem_alloc, 0); newsk->localroute = sk->localroute; - newsk->max_unacked = MAX_WINDOW - TCP_WINDOW_DIFF; - newsk->err = 0; newsk->shutdown = 0; newsk->ack_backlog = 0; @@ -1060,7 +1082,6 @@ newsk->dst_cache = &rt->u.dst; - newtp->window_clamp = rt->u.dst.window; snd_mss = rt->u.dst.pmtu; /* FIXME: is mtu really the same as snd_mss? */ @@ -1072,10 +1093,19 @@ newtp->sack_ok = req->sack_ok; newtp->tstamp_ok = req->tstamp_ok; - newtp->snd_wscale = req->snd_wscale; - newtp->ts_recent = req->ts_recent; - newtp->ts_recent_stamp = jiffies; + newtp->window_clamp = req->window_clamp; + newtp->rcv_wnd = req->rcv_wnd; + newtp->wscale_ok = req->wscale_ok; + if (newtp->wscale_ok) { + newtp->snd_wscale = req->snd_wscale; + newtp->rcv_wscale = req->rcv_wscale; + } else { + newtp->snd_wscale = newtp->rcv_wscale = 0; + newtp->window_clamp = min(newtp->window_clamp,65535); + } if (newtp->tstamp_ok) { + newtp->ts_recent = req->ts_recent; + newtp->ts_recent_stamp = jiffies; newtp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: define constant! */ newsk->dummy_th.doff += 3; } else { @@ -1219,9 +1249,8 @@ case CHECKSUM_HW: if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) { struct iphdr * iph = skb->nh.iph; - printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, ack = %u, seq = %u, len=%d/%d/%d\n", + printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, len=%d/%d/%d\n", saddr, ntohs(th->source), daddr, - ntohl(th->ack_seq), ntohl(th->seq), ntohs(th->dest), len, skb->len, ntohs(iph->tot_len)); goto discard_it; } @@ -1346,10 +1375,12 @@ tp->ato = 0; tp->iat = (HZ/5) << 3; - tp->rcv_wnd = 8192; + /* FIXME: tie this to sk->rcvbuf? (May be unnecessary) */ + /* tp->rcv_wnd = 8192; */ tp->tstamp_ok = 0; tp->sack_ok = 0; - tp->in_mss = 0; + tp->wscale_ok = 0; + tp->in_mss = 536; tp->snd_wscale = 0; tp->sacks = 0; tp->saw_tstamp = 0; diff -u --recursive --new-file v2.1.36/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.1.36/linux/net/ipv4/tcp_output.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv4/tcp_output.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.42 1997/04/22 01:06:33 davem Exp $ + * Version: $Id: tcp_output.c,v 1.43 1997/04/27 19:24:43 schenk Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -404,14 +404,115 @@ -/* - * This function returns the amount that we can raise the - * usable window based on the following constraints +/* This function returns the amount that we can raise the + * usable window based on the following constraints * - * 1. The window can never be shrunk once it is offered (RFC 793) - * 2. We limit memory per socket + * 1. The window can never be shrunk once it is offered (RFC 793) + * 2. We limit memory per socket + * + * RFC 1122: + * "the suggested [SWS] avoidance algoritm for the receiver is to keep + * RECV.NEXT + RCV.WIN fixed until: + * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)" + * + * i.e. don't raise the right edge of the window until you can raise + * it at least MSS bytes. + * + * Unfortunately, the recomended algorithm breaks header prediction, + * since header prediction assumes th->window stays fixed. + * + * Strictly speaking, keeping th->window fixed violates the receiver + * side SWS prevention criteria. The problem is that under this rule + * a stream of single byte packets will cause the right side of the + * window to always advance by a single byte. + * + * Of course, if the sender implements sender side SWS prevention + * then this will not be a problem. + * + * BSD seems to make the following compromise: + * + * If the free space is less than the 1/4 of the maximum + * space available and the free space is less than 1/2 mss, + * then set the window to 0. + * Otherwise, just prevent the window from shrinking + * and from being larger than the largest representable value. + * + * This prevents incremental opening of the window in the regime + * where TCP is limited by the speed of the reader side taking + * data out of the TCP receive queue. It does nothing about + * those cases where the window is constrained on the sender side + * because the pipeline is full. + * + * BSD also seems to "accidentally" limit itself to windows that are a + * multiple of MSS, at least until the free space gets quite small. + * This would appear to be a side effect of the mbuf implementation. + * Combining these two algorithms results in the observed behavior + * of having a fixed window size at almost all times. + * + * Below we obtain similar behavior by forcing the offered window to + * a multiple of the mss when it is feasible to do so. + * + * FIXME: In our current implementation the value returned by sock_rpsace(sk) + * is the total space we have allocated to the socket to store skbuf's. + * The current design assumes that up to half of that space will be + * taken by headers, and the remaining space will be available for TCP data. + * This should be accounted for correctly instead. */ +unsigned short tcp_select_window(struct sock *sk) +{ + struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + int mss = sk->mss; + long free_space = sock_rspace(sk)/2; + long window, cur_win; + + if (tp->window_clamp) { + free_space = min(tp->window_clamp, free_space); + mss = min(tp->window_clamp, mss); + } else + printk(KERN_DEBUG "Clamp failure. Water leaking.\n"); + + if (mss < 1) { + mss = 1; + printk(KERN_DEBUG "tcp_select_window: mss fell to 0.\n"); + } + + /* compute the actual window i.e. + * old_window - received_bytes_on_that_win + */ + cur_win = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); + window = tp->rcv_wnd; + + if (cur_win < 0) { + cur_win = 0; + printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n", + tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup); + } + + if (free_space < sk->rcvbuf/4 && free_space < mss/2) + window = 0; + + /* Get the largest window that is a nice multiple of mss. + * Window clamp already applied above. + * If our current window offering is within 1 mss of the + * free space we just keep it. This prevents the divide + * and multiply from happening most of the time. + * We also don't do any window rounding when the free space + * is too small. + */ + if (window < free_space - mss && free_space > mss) + window = (free_space/mss)*mss; + /* Never shrink the offered window */ + if (window < cur_win) + window = cur_win; + + tp->rcv_wnd = window; + tp->rcv_wup = tp->rcv_nxt; + return window >> tp->rcv_wscale; /* RFC1323 scaling applied */ +} + +#if 0 +/* Old algorithm for window selection */ unsigned short tcp_select_window(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -427,37 +528,31 @@ /* compute the actual window i.e. * old_window - received_bytes_on_that_win */ - cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd); + cur_win = tp->rcv_wnd - (tp->rcv_nxt - tp->rcv_wup); window = tp->rcv_wnd; - + if (cur_win < 0) { cur_win = 0; printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n", tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup); } - /* - * RFC 1122: + /* RFC 1122: * "the suggested [SWS] avoidance algoritm for the receiver is to keep * RECV.NEXT + RCV.WIN fixed until: * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)" * - * i.e. don't raise the right edge of the window until you can't raise - * it MSS bytes + * i.e. don't raise the right edge of the window until you can raise + * it at least MSS bytes. */ - /* It would be a good idea if it didn't break header prediction. - * and BSD made the header predition standard... - * It expects the same value in the header i.e. th->window to be - * constant - */ usable = free_space - cur_win; if (usable < 0) usable = 0; if (window < usable) { /* Window is not blocking the sender - * and we have enought free space for it + * and we have enough free space for it */ if (cur_win > (sk->mss << 1)) goto out; @@ -469,7 +564,7 @@ */ window = max(usable, cur_win); } else { - if ((usable - window) >= mss) + while ((usable - window) >= mss) window += mss; } out: @@ -477,6 +572,7 @@ tp->rcv_wup = tp->rcv_nxt; return window; } +#endif static int tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb) { @@ -703,6 +799,11 @@ } } +/* WARNING: This routine must only be called when we have already sent + * a SYN packet that crossed the incoming SYN that caused this routine + * to get called. If this assumption fails then the initial rcv_wnd + * and rcv_wscale values will not be correct. + */ int tcp_send_synack(struct sock *sk) { struct tcp_opt * tp = &(sk->tp_pinfo.af_tcp); @@ -735,13 +836,16 @@ skb->end_seq = skb->seq + 1 /* th->syn */ ; th->seq = ntohl(skb->seq); - th->window = ntohs(tp->rcv_wnd); + /* This is a resend of a previous SYN, now with an ACK. + * we must reuse the previously offered window. + */ + th->window = htons(tp->rcv_wnd); tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt); tmp = tcp_syn_build_options(skb, sk->mss, tp->sack_ok, tp->tstamp_ok, - tp->snd_wscale?tp->rcv_wscale:0); + tp->wscale_ok,tp->rcv_wscale); skb->csum = 0; th->doff = (sizeof(*th) + tmp)>>2; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c --- v2.1.36/linux/net/ipv6/addrconf.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv6/addrconf.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: addrconf.c,v 1.18 1997/04/16 05:58:03 davem Exp $ + * $Id: addrconf.c,v 1.19 1997/04/29 09:38:41 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1215,7 +1216,7 @@ * Init / cleanup code */ -void addrconf_init() +__initfunc(void addrconf_init(void)) { struct device *dev; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c --- v2.1.36/linux/net/ipv6/af_inet6.c Thu Mar 27 14:40:16 1997 +++ linux/net/ipv6/af_inet6.c Thu May 1 12:05:07 1997 @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.16 1997/03/18 18:24:26 davem Exp $ + * $Id: af_inet6.c,v 1.17 1997/04/29 09:38:39 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -459,7 +460,7 @@ #ifdef MODULE int init_module(void) #else -void inet6_proto_init(struct net_proto *pro) +__initfunc(void inet6_proto_init(struct net_proto *pro)) #endif { struct sk_buff *dummy_skb; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/datagram.c linux/net/ipv6/datagram.c --- v2.1.36/linux/net/ipv6/datagram.c Mon Apr 14 16:28:28 1997 +++ linux/net/ipv6/datagram.c Fri May 2 18:58:35 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: datagram.c,v 1.10 1997/04/14 05:39:42 davem Exp $ + * $Id: datagram.c,v 1.11 1997/05/03 00:58:25 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,6 +15,9 @@ #include #include +#include +#include +#include #include #include #include diff -u --recursive --new-file v2.1.36/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.1.36/linux/net/ipv6/icmp.c Thu Mar 27 14:40:16 1997 +++ linux/net/ipv6/icmp.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.8 1997/03/18 18:24:30 davem Exp $ + * $Id: icmp.c,v 1.9 1997/04/29 09:38:42 mj Exp $ * * Based on net/ipv4/icmp.c * @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -486,7 +487,7 @@ return 0; } -void icmpv6_init(struct net_proto_family *ops) +__initfunc(void icmpv6_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/ip6_fw.c linux/net/ipv6/ip6_fw.c --- v2.1.36/linux/net/ipv6/ip6_fw.c Thu Mar 27 14:40:16 1997 +++ linux/net/ipv6/ip6_fw.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: ip6_fw.c,v 1.4 1997/03/18 18:24:34 davem Exp $ + * $Id: ip6_fw.c,v 1.5 1997/04/29 09:38:44 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -365,7 +366,7 @@ #define ip6_fw_init module_init #endif -void ip6_fw_init(void) +__initfunc(void ip6_fw_init(void)) { netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv); } diff -u --recursive --new-file v2.1.36/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c --- v2.1.36/linux/net/ipv6/ipv6_sockglue.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv6/ipv6_sockglue.c Thu May 1 12:05:07 1997 @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.11 1997/04/20 09:44:33 davem Exp $ + * $Id: ipv6_sockglue.c,v 1.12 1997/04/29 09:38:45 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -31,12 +31,11 @@ #include #include #include - +#include #include #include #include - #include #include #include @@ -239,7 +238,7 @@ extern void ipv6_sysctl_unregister(void); #endif -void ipv6_init(void) +__initfunc(void ipv6_init(void)) { dev_add_pack(&ipv6_packet_type); diff -u --recursive --new-file v2.1.36/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c --- v2.1.36/linux/net/ipv6/mcast.c Mon Apr 14 16:28:28 1997 +++ linux/net/ipv6/mcast.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: mcast.c,v 1.8 1997/04/12 04:32:48 davem Exp $ + * $Id: mcast.c,v 1.9 1997/04/29 09:38:46 mj Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -495,7 +496,7 @@ ma->mca_flags &= ~MAF_TIMER_RUNNING; } -void igmp6_init(struct net_proto_family *ops) +__initfunc(void igmp6_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c --- v2.1.36/linux/net/ipv6/ndisc.c Mon Apr 14 16:28:28 1997 +++ linux/net/ipv6/ndisc.c Thu May 1 12:05:07 1997 @@ -6,7 +6,7 @@ * Pedro Roque * Mike Shaver * - * $Id: ndisc.c,v 1.14 1997/04/12 04:32:51 davem Exp $ + * $Id: ndisc.c,v 1.15 1997/04/29 09:38:48 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1647,7 +1648,7 @@ }; #endif /* CONFIG_PROC_FS */ -void ndisc_init(struct net_proto_family *ops) +__initfunc(void ndisc_init(struct net_proto_family *ops)) { struct sock *sk; int err; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/route.c linux/net/ipv6/route.c --- v2.1.36/linux/net/ipv6/route.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv6/route.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: route.c,v 1.11 1997/04/16 05:58:05 davem Exp $ + * $Id: route.c,v 1.12 1997/04/29 09:38:50 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef CONFIG_PROC_FS #include @@ -1573,7 +1574,7 @@ }; #endif /* CONFIG_PROC_FS */ -void ip6_route_init(void) +__initfunc(void ip6_route_init(void)) { #ifdef CONFIG_PROC_FS proc_net_register(&proc_rt6_info); diff -u --recursive --new-file v2.1.36/linux/net/ipv6/sit.c linux/net/ipv6/sit.c --- v2.1.36/linux/net/ipv6/sit.c Thu Mar 27 14:40:17 1997 +++ linux/net/ipv6/sit.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: sit.c,v 1.13 1997/03/18 18:24:50 davem Exp $ + * $Id: sit.c,v 1.14 1997/04/29 09:38:52 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -243,7 +244,7 @@ return 0; } -int sit_init(void) +__initfunc(int sit_init(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.36/linux/net/ipv6/tcp_ipv6.c Wed Apr 23 19:01:30 1997 +++ linux/net/ipv6/tcp_ipv6.c Thu May 1 12:05:07 1997 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.27 1997/04/22 02:53:20 davem Exp $ + * $Id: tcp_ipv6.c,v 1.31 1997/04/29 21:51:23 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -432,21 +433,32 @@ tp->snd_nxt = sk->write_seq; buff->end_seq = sk->write_seq; th->ack = 0; - th->window = 2; th->syn = 1; - tp->window_clamp = 0; sk->mtu = dst->pmtu; sk->mss = sk->mtu - sizeof(struct ipv6hdr) - sizeof(struct tcphdr); + if (sk->mss < 1) { + printk(KERN_DEBUG "intial ipv6 sk->mss below 1\n"); + sk->mss = 1; /* Sanity limit */ + } + + tp->window_clamp = 0; /* FIXME: shouldn't ipv6 dst cache have this? */ + tcp_select_initial_window(sock_rspace(sk)/2,sk->mss, + &tp->rcv_wnd, + &tp->window_clamp, + sysctl_tcp_window_scaling, + &tp->rcv_wscale); + th->window = htons(tp->rcv_wnd); + /* * Put in the TCP options to say MTU. */ tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack, sysctl_tcp_timestamps, - sysctl_tcp_window_scaling?tp->rcv_wscale:0); + sysctl_tcp_window_scaling,tp->rcv_wscale); th->doff = sizeof(*th)/4 + (tmp>>2); buff->csum = 0; tcp_v6_send_check(sk, th, sizeof(struct tcphdr) + tmp, buff); @@ -586,9 +598,11 @@ } +/* FIXME: this is substantially similar to the ipv4 code. + * Can some kind of merge be done? -- erics + */ static void tcp_v6_send_synack(struct sock *sk, struct open_request *req) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; struct sk_buff * skb; struct tcphdr *th; struct dst_entry *dst; @@ -630,11 +644,32 @@ th->seq = ntohl(skb->seq); th->ack_seq = htonl(req->rcv_isn + 1); th->doff = sizeof(*th)/4 + 1; - - th->window = ntohs(tp->rcv_wnd); - tmp = tcp_syn_build_options(skb, sk->mss, req->sack_ok, req->tstamp_ok, - (req->snd_wscale)?tp->rcv_wscale:0); + /* Don't offer more than they did. + * This way we don't have to memorize who said what. + * FIXME: the selection of initial mss here doesn't quite + * match what happens under IPV4. Figure out the right thing to do. + */ + req->mss = min(sk->mss, req->mss); + + if (req->mss < 1) { + printk(KERN_DEBUG "initial req->mss below 1\n"); + req->mss = 1; + } + + if (req->rcv_wnd == 0) { + /* Set this up on the first call only */ + req->window_clamp = 0; /* FIXME: should be in dst cache */ + tcp_select_initial_window(sock_rspace(sk)/2,req->mss, + &req->rcv_wnd, + &req->window_clamp, + req->wscale_ok, + &req->rcv_wscale); + } + th->window = htons(req->rcv_wnd); + + tmp = tcp_syn_build_options(skb, req->mss, req->sack_ok, req->tstamp_ok, + req->snd_wscale,req->rcv_wscale); th->doff = sizeof(*th)/4 + (tmp>>2); th->check = tcp_v6_check(th, sizeof(*th) + tmp, &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr, @@ -656,10 +691,13 @@ tcp_v6_or_free }; +/* FIXME: this is substantially similar to the ipv4 code. + * Can some kind of merge be done? -- erics + */ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) { - struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct tcp_opt tp; struct open_request *req; __u16 req_mss; @@ -691,14 +729,20 @@ sk->ack_backlog++; + req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */ + req->rcv_isn = skb->seq; req->snt_isn = isn; - - tcp_parse_options(skb->h.th,tp); - req_mss = tp->in_mss; - if (!req_mss) - req_mss = 536; - req->mss = req_mss; + tp.tstamp_ok = tp.sack_ok = tp.wscale_ok = tp.snd_wscale = 0; + tp.in_mss = 536; + tcp_parse_options(skb->h.th,&tp); + if (tp.saw_tstamp) + req->ts_recent = tp.rcv_tsval; + req->mss = tp.in_mss; + req->tstamp_ok = tp.tstamp_ok; + req->sack_ok = tp.sack_ok; + req->snd_wscale = tp.snd_wscale; + req->wscale_ok = tp.wscale_ok; req->rmt_port = skb->h.th->source; ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr); @@ -876,6 +920,7 @@ newtp->sack_ok = req->sack_ok; newtp->tstamp_ok = req->tstamp_ok; newtp->snd_wscale = req->snd_wscale; + newtp->wscale_ok = req->wscale_ok; newtp->ts_recent = req->ts_recent; if (newtp->tstamp_ok) { newtp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: define the contant. */ @@ -1305,8 +1350,11 @@ tp->ato = 0; tp->iat = (HZ/5) << 3; - - tp->rcv_wnd = 8192; + + /* FIXME: right thing? */ + tp->rcv_wnd = 0; + tp->in_mss = 536; + /* tp->rcv_wnd = 8192; */ /* start with only sending one packet at a time. */ tp->snd_cwnd = 1; @@ -1320,7 +1368,7 @@ sk->max_ack_backlog = SOMAXCONN; sk->mtu = 576; - sk->mss = 516; + sk->mss = 536; sk->dummy_th.doff = sizeof(sk->dummy_th)/4; @@ -1416,7 +1464,7 @@ "TCPv6" /* name */ }; -void tcpv6_init(void) +__initfunc(void tcpv6_init(void)) { /* register inet6 protocol */ inet6_add_protocol(&tcpv6_protocol); diff -u --recursive --new-file v2.1.36/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.1.36/linux/net/ipv6/udp.c Mon Apr 14 16:28:28 1997 +++ linux/net/ipv6/udp.c Thu May 1 12:05:07 1997 @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.16 1997/04/11 22:22:57 davem Exp $ + * $Id: udp.c,v 1.17 1997/04/29 09:38:55 mj Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -770,7 +771,7 @@ 0 /* highestinuse */ }; -void udpv6_init(void) +__initfunc(void udpv6_init(void)) { inet6_add_protocol(&udpv6_protocol); } diff -u --recursive --new-file v2.1.36/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c --- v2.1.36/linux/net/ipx/af_ipx.c Mon Apr 14 16:28:28 1997 +++ linux/net/ipx/af_ipx.c Thu May 1 12:05:07 1997 @@ -91,6 +91,7 @@ #include #include #include +#include #ifdef MODULE static void ipx_proto_finito(void); @@ -2434,7 +2435,7 @@ * sockets be closed from user space. */ -static void ipx_proto_finito(void) +__initfunc(static void ipx_proto_finito(void)) { ipx_interface *ifc; while (ipx_interfaces) { diff -u --recursive --new-file v2.1.36/linux/net/lapb/lapb_iface.c linux/net/lapb/lapb_iface.c --- v2.1.36/linux/net/lapb/lapb_iface.c Thu Feb 27 10:57:32 1997 +++ linux/net/lapb/lapb_iface.c Thu May 1 12:05:07 1997 @@ -39,6 +39,7 @@ #include #include #include +#include #include static lapb_cb *volatile lapb_list = NULL; @@ -397,7 +398,7 @@ EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -void lapb_proto_init(struct net_proto *pro) +__initfunc(void lapb_proto_init(struct net_proto *pro)) { printk(KERN_INFO "LAPB for Linux. Version 0.01 for Linux NET3.038 (Linux 2.1)\n"); } diff -u --recursive --new-file v2.1.36/linux/net/netbeui/af_netbeui.c linux/net/netbeui/af_netbeui.c --- v2.1.36/linux/net/netbeui/af_netbeui.c Mon Apr 14 16:28:28 1997 +++ linux/net/netbeui/af_netbeui.c Thu May 1 12:05:07 1997 @@ -31,6 +31,7 @@ #include #include #include +#include #undef NETBEUI_DEBUG @@ -620,7 +621,7 @@ /* Called by proto.c on kernel start up */ -void netbeui_proto_init(struct net_proto *pro) +__initfunc(void netbeui_proto_init(struct net_proto *pro)) { (void) sock_register(netbeui_proto_ops.family, &netbeui_proto_ops); if ((nb_dl = register_8022_client(nb_8022_id, netbeui_rcv)) == NULL) diff -u --recursive --new-file v2.1.36/linux/net/netlink.c linux/net/netlink.c --- v2.1.36/linux/net/netlink.c Fri Apr 4 08:52:29 1997 +++ linux/net/netlink.c Thu May 1 12:05:07 1997 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -443,7 +444,7 @@ } -int init_netlink(void) +__initfunc(int init_netlink(void)) { int ct; diff -u --recursive --new-file v2.1.36/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c --- v2.1.36/linux/net/netrom/af_netrom.c Mon Apr 14 16:28:28 1997 +++ linux/net/netrom/af_netrom.c Thu May 1 12:05:07 1997 @@ -64,6 +64,7 @@ #include #include #include +#include int sysctl_netrom_default_path_quality = NR_DEFAULT_QUAL; int sysctl_netrom_obsolescence_count_initialiser = NR_DEFAULT_OBS; @@ -1361,7 +1362,7 @@ {"nr3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, nr_init} }; -void nr_proto_init(struct net_proto *pro) +__initfunc(void nr_proto_init(struct net_proto *pro)) { int i; diff -u --recursive --new-file v2.1.36/linux/net/netrom/sysctl_net_netrom.c linux/net/netrom/sysctl_net_netrom.c --- v2.1.36/linux/net/netrom/sysctl_net_netrom.c Sun Feb 2 05:18:52 1997 +++ linux/net/netrom/sysctl_net_netrom.c Thu May 1 12:05:07 1997 @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -78,7 +79,7 @@ {0} }; -void nr_register_sysctl(void) +__initfunc(void nr_register_sysctl(void)) { nr_table_header = register_sysctl_table(nr_root_table, 1); } diff -u --recursive --new-file v2.1.36/linux/net/netsyms.c linux/net/netsyms.c --- v2.1.36/linux/net/netsyms.c Mon Apr 14 16:28:28 1997 +++ linux/net/netsyms.c Thu May 1 12:05:07 1997 @@ -200,6 +200,10 @@ EXPORT_SYMBOL(__release_sock); EXPORT_SYMBOL(net_timer); /* UDP/TCP exported functions for TCPv6 */ +EXPORT_SYMBOL(sysctl_tcp_sack); +EXPORT_SYMBOL(sysctl_tcp_timestamps); +EXPORT_SYMBOL(sysctl_tcp_window_scaling); +EXPORT_SYMBOL(sock_rspace); EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_connect); EXPORT_SYMBOL(udp_sendmsg); diff -u --recursive --new-file v2.1.36/linux/net/rose/af_rose.c linux/net/rose/af_rose.c --- v2.1.36/linux/net/rose/af_rose.c Mon Apr 14 16:28:28 1997 +++ linux/net/rose/af_rose.c Thu May 1 12:05:07 1997 @@ -52,6 +52,7 @@ #include #include #include +#include int sysctl_rose_restart_request_timeout = ROSE_DEFAULT_T0; int sysctl_rose_call_request_timeout = ROSE_DEFAULT_T1; @@ -1381,7 +1382,7 @@ {"rose5", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init} }; -void rose_proto_init(struct net_proto *pro) +__initfunc(void rose_proto_init(struct net_proto *pro)) { int i; diff -u --recursive --new-file v2.1.36/linux/net/rose/sysctl_net_rose.c linux/net/rose/sysctl_net_rose.c --- v2.1.36/linux/net/rose/sysctl_net_rose.c Sun Feb 2 05:18:52 1997 +++ linux/net/rose/sysctl_net_rose.c Thu May 1 12:05:07 1997 @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -58,7 +59,7 @@ {0} }; -void rose_register_sysctl(void) +__initfunc(void rose_register_sysctl(void)) { rose_table_header = register_sysctl_table(rose_root_table, 1); } diff -u --recursive --new-file v2.1.36/linux/net/socket.c linux/net/socket.c --- v2.1.36/linux/net/socket.c Fri Apr 4 08:52:29 1997 +++ linux/net/socket.c Thu May 1 12:05:07 1997 @@ -71,6 +71,7 @@ #include #include #include +#include #if defined(CONFIG_KERNELD) && defined(CONFIG_NET) #include @@ -207,7 +208,6 @@ file->f_op = &socket_file_ops; file->f_mode = 3; file->f_flags = O_RDWR; - file->f_count = 1; file->f_inode = inode; if (inode) inode->i_count++; @@ -1400,7 +1400,7 @@ return 0; } -void proto_init(void) +__initfunc(void proto_init(void)) { extern struct net_proto protocols[]; /* Network protocols */ struct net_proto *pro; @@ -1417,7 +1417,7 @@ extern void sk_init(void); -void sock_init(void) +__initfunc(void sock_init(void)) { int i; diff -u --recursive --new-file v2.1.36/linux/net/unix/af_unix.c linux/net/unix/af_unix.c --- v2.1.36/linux/net/unix/af_unix.c Wed Apr 23 19:01:30 1997 +++ linux/net/unix/af_unix.c Thu May 1 12:05:07 1997 @@ -81,6 +81,7 @@ #include #include #include +#include #include @@ -1459,7 +1460,7 @@ unix_create }; -void unix_proto_init(struct net_proto *pro) +__initfunc(void unix_proto_init(struct net_proto *pro)) { struct sk_buff *dummy_skb; struct proc_dir_entry *ent; diff -u --recursive --new-file v2.1.36/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c --- v2.1.36/linux/net/wanrouter/wanmain.c Sun Feb 2 05:18:52 1997 +++ linux/net/wanrouter/wanmain.c Thu May 1 12:05:07 1997 @@ -34,6 +34,7 @@ #include /* htons(), etc. */ #include /* copy_to/from_user */ #include /* WAN router API definitions */ +#include /* __initfunc et al. */ /****** Defines and Macros **************************************************/ @@ -130,7 +131,7 @@ #else -void wanrouter_init(void) +__initfunc(void wanrouter_init(void)) { int err = wanrouter_proc_init(); if (err) printk(KERN_ERR diff -u --recursive --new-file v2.1.36/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c --- v2.1.36/linux/net/wanrouter/wanproc.c Mon Mar 17 14:54:36 1997 +++ linux/net/wanrouter/wanproc.c Thu May 1 12:05:07 1997 @@ -23,6 +23,7 @@ #include /* kmalloc(), kfree() */ #include /* verify_area(), etc. */ #include /* inline mem*, str* functions */ +#include /* __initfunc et al. */ #include /* kernel <-> user copy */ #include /* htons(), etc. */ #include /* copy_to_user */ @@ -271,7 +272,7 @@ * Initialize router proc interface. */ -int wanrouter_proc_init (void) +__initfunc(int wanrouter_proc_init (void)) { int err = proc_register(&proc_net, &proc_router); diff -u --recursive --new-file v2.1.36/linux/net/x25/af_x25.c linux/net/x25/af_x25.c --- v2.1.36/linux/net/x25/af_x25.c Mon Apr 14 16:28:29 1997 +++ linux/net/x25/af_x25.c Thu May 1 12:05:07 1997 @@ -45,6 +45,7 @@ #include #include #include +#include #include int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; @@ -1283,7 +1284,7 @@ }; #endif -void x25_proto_init(struct net_proto *pro) +__initfunc(void x25_proto_init(struct net_proto *pro)) { sock_register(&x25_family_ops); diff -u --recursive --new-file v2.1.36/linux/net/x25/sysctl_net_x25.c linux/net/x25/sysctl_net_x25.c --- v2.1.36/linux/net/x25/sysctl_net_x25.c Wed Dec 18 02:07:56 1996 +++ linux/net/x25/sysctl_net_x25.c Thu May 1 12:05:07 1997 @@ -10,6 +10,7 @@ #include #include #include +#include #include static int min_timer[] = {1 * X25_SLOWHZ}; @@ -46,7 +47,7 @@ {0} }; -void x25_register_sysctl(void) +__initfunc(void x25_register_sysctl(void)) { x25_table_header = register_sysctl_table(x25_root_table, 1); } Binary files v2.1.36/linux/scripts/a.out and linux/scripts/a.out differ diff -u --recursive --new-file v2.1.36/linux/scripts/mkdep.c linux/scripts/mkdep.c --- v2.1.36/linux/scripts/mkdep.c Fri Apr 4 08:52:29 1997 +++ linux/scripts/mkdep.c Sun May 4 20:17:01 1997 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include