diff -u --recursive --new-file v2.1.127/linux/CREDITS linux/CREDITS --- v2.1.127/linux/CREDITS Fri Oct 23 22:01:18 1998 +++ linux/CREDITS Tue Nov 10 16:00:36 1998 @@ -1677,11 +1677,12 @@ S: USA N: Henrik Storner -E: storner@osiris.ping.dk -E: storner@olicom.dk -W: http://eolicom.olicom.dk/~storner/ -D: Configure script: tristate, bugfixes +E: storner@image.dk +W: http://www.image.dk/~storner/ +W: http://www.sslug.dk/ +D: Configure script: Invented tristate for module-configuration D: vfat/msdos integration, kerneld docs, Linux promotion +D: Miscellaneous bug-fixes S: Chr. Winthersvej 1 B, st.th. S: DK-1860 Frederiksberg C S: Denmark @@ -1910,6 +1911,11 @@ N: Juergen Weigert E: jnweiger@immd4.informatik.uni-erlangen.de D: The Linux Support Team Erlangen + +N: David Weinehall +E: tao@acc.umu.se +D: NE/2-driver maintainer +D: Miscellaneous MCA-support N: Matt Welsh E: mdw@sunsite.unc.edu diff -u --recursive --new-file v2.1.127/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.127/linux/Documentation/Configure.help Sun Nov 8 14:02:40 1998 +++ linux/Documentation/Configure.help Sun Nov 8 10:45:13 1998 @@ -78,7 +78,7 @@ with the kernel internals are usually welcomed by the developers (before submitting bug reports, please read the documents README, MAINTAINERS, Documentation/BUG-HUNTING, and - Documentation/oops-tracing.txt in the kernel source). + Documentation/oops-tracing.txt in the kernel source). Unless you intend to help test and develop a feature or driver that falls into this category, or you have a situation that requires @@ -92,7 +92,7 @@ Linux can emulate a math coprocessor (used for floating point operations) if you don't have one. 486DX and Pentium processors have a math coprocessor built in, 486SX and 386 do not, unless you added - a 487DX or 387, respectively. (The messages during boot time can + a 487DX or 387, respectively. (The messages during boot time can give you some hints here ["man dmesg"].) Everyone needs either a coprocessor or this emulation. @@ -110,7 +110,7 @@ math coprocessor emulation can be found in arch/i386/math-emu/README. - If you are not sure, say Y; apart from resulting in a 45kB bigger + If you are not sure, say Y; apart from resulting in a 45 KB bigger kernel, it won't hurt. Normal PC floppy disk support @@ -127,16 +127,22 @@ The module will be called floppy.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Support for PowerMac floppy +CONFIG_MAC_FLOPPY + If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) + floppy controller, say Y here. Most commonly found in PowerMacs. + RAM disk support CONFIG_BLK_DEV_RAM Saying Y here will allow you to use a portion of your RAM memory as a block device, so that you can make filesystems on it, read and write to it and do all the other things that you can do with normal - block devices (such as hard drives). It is usually used to load and + block devices (such as hard drives). It is usually used to load and store a copy of a minimal root file system off of a floppy into RAM - during the initial install of Linux. Note that the kernel command - line option "ramdisk=XX" is now obsolete. For details, read - Documentation/ramdisk.txt. + during the initial install of Linux. + + Note that the kernel command line option "ramdisk=XX" is now + obsolete. For details, read Documentation/ramdisk.txt. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -158,8 +164,8 @@ CONFIG_BLK_DEV_LOOP Saying Y here will allow you to use a regular file as a block device; you can then create a file system on that block device and - mount it just as you would mount other block devices such as hard drive - partitions, CDROM drives or floppy drives. + mount it just as you would mount other block devices such as hard + drive partitions, CDROM drives or floppy drives. This is useful if you want to check an ISO 9660 file system before burning the CD, or if you want to use floppy images without first @@ -171,8 +177,9 @@ bits of, say, a sound file). This is also safe if the file resides on a remote file server. If you want to do this, you will first have to acquire and install a kernel patch from - ftp://ftp.replay.com/pub/crypto/linux/all, and then you need to say - Y to this option. + ftp://ftp.replay.com/pub/crypto/linux/all or + ftp://verden.pvv.org/pub/linux/kerneli/v2.1/, and then you need to + say Y to this option. Note that alternative ways to use encrypted filesystems are provided by the cfs package, which can be gotten via FTP (user: anonymous) @@ -200,18 +207,22 @@ Network Block Device support CONFIG_BLK_DEV_NBD Saying Y here will allow your computer to be a client for network - block devices -- it will be able to use block devices exported by + block devices, i.e. it will be able to use block devices exported by servers (mount filesystems on them etc.). Communication between client and server works over TCP/IP networking, but to the client program this is hidden: it looks like a regular local file access to - a special file such as /dev/nd0. It also allows you to run a - block-device in userland (making server and client physically the - same computer, communicating using the loopback network device). + a block device special file such as /dev/nd0. + + Network block devices also allows you to run a block-device in + userland (making server and client physically the same computer, + communicating using the loopback network device). + Read Documentation/nbd.txt for more information, especially about - where to find the server code. + where to find the server code, which runs in user space and does not + need special kernel support. - Note that this has nothing to do with the network file system NFS; - you can say N here even if you intend to use NFS. + Note that this has nothing to do with the network file systems NFS + or Coda; you can say N here even if you intend to use NFS or Coda. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -225,22 +236,25 @@ If you say Y here, you will use the full-featured IDE driver to control up to four IDE interfaces, each being able to serve a "master" and a "slave" device, for a total of up to eight IDE - disk/cdrom/tape/floppy drives. People with SCSI-only systems - should say 'N' here. + disk/cdrom/tape/floppy drives. People with SCSI-only systems + can say N here. - Useful information about large (>540MB) IDE disks, sound card IDE - ports, module support, and other topics, is contained in - Documentation/ide.txt. For detailed information about hard drives, - consult the Disk-HOWTO, available via FTP (user: anonymous) from - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. To fine-tune IDE - drive/interface parameters for improved performance, look for the - hdparm package at - sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/ + Useful information about large (>540 MB) IDE disks, multiple + interfaces, what to do if IDE devices are not automatically + detected, sound card IDE ports, module support, and other topics, is + contained in Documentation/ide.txt. For detailed information about + hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO, + available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + To fine-tune IDE drive/interface parameters for improved + performance, look for the hdparm package at + ftp://sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/ If you have one or more IDE drives, say Y here. If your system has no IDE drives, or if memory requirements are really tight, you could say N here, and select the "Old hard disk driver" instead to save - about 13kB of memory in the kernel. + about 13 KB of memory in the kernel. Old hard disk (MFM/RLL/IDE) driver CONFIG_BLK_DEV_HD_ONLY @@ -252,12 +266,14 @@ since it lacks the enhanced functionality of the new one. This makes it a good choice for systems with very tight memory restrictions, or for systems with only older MFM/RLL/ESDI drives. Choosing the old - driver can save 13kB or so of kernel memory. If you are unsure, then - just choose the Enhanced IDE/MFM/RLL driver instead of this one. For - more detailed information, read the Disk-HOWTO, available via FTP - (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + driver can save 13 KB or so of kernel memory. + + If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver + instead of this one. For more detailed information, read the + Disk-HOWTO, available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. - People with SCSI-only systems can say 'N' here. + People with SCSI-only systems can say N here. Use old disk-only driver on primary interface CONFIG_BLK_DEV_HD_IDE @@ -270,16 +286,20 @@ interface. Choosing this option may be useful for older systems which have MFM/RLL/ESDI controller+drives at the primary port address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. Normally, just say N here; you will then use the new - driver for all 4 interfaces. + addresses. + + Normally, just say N here; you will then use the new driver for all + 4 interfaces. - People with SCSI-only systems can say 'N' here. + People with SCSI-only systems don't need this and can say N here as + well. Include IDE/ATA-2 DISK support CONFIG_BLK_DEV_IDEDISK - This will include enhanced support for MFM/RLL/IDE hard disks. If you - have a MFM/RLL/IDE disk, and there is no special reason to use the - old hard disk driver instead, say Y. If all your disks are SCSI, say 'N'. + This will include enhanced support for MFM/RLL/IDE hard disks. If + you have a MFM/RLL/IDE disk, and there is no special reason to use + the old hard disk driver instead, say Y. If you have an SCSI-only + system, you can say N here. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -318,7 +338,8 @@ CONFIG_BLK_DEV_IDETAPE If you have an IDE tape drive using the ATAPI protocol, say Y. ATAPI is a newer protocol used by IDE tape and CDROM drives, similar - to the SCSI protocol (but say 'N' if your tape is a SCSI device). + to the SCSI protocol. If you have an SCSI tape drive however, you + can say N here. If you say Y here, the tape drive will be identified at boot time along with other IDE devices, as "hdb" or "hdc", or something @@ -334,12 +355,12 @@ Include IDE/ATAPI FLOPPY support CONFIG_BLK_DEV_IDEFLOPPY - If you have an IDE floppy drive which uses the ATAPI protocol, say - Y. ATAPI is a newer protocol used by IDE CDROM/tape/floppy drives, - similar to the SCSI protocol. IDE floppy drives include the LS-120 - and the ATAPI ZIP (ATAPI PD-CD/CDR drives are not supported by this - driver; support for PD-CD/CDR drives is available if you say Y to - "SCSI emulation support", below). + If you have an IDE floppy drive which uses the ATAPI protocol, + answer Y. ATAPI is a newer protocol used by IDE CDROM/tape/floppy + drives, similar to the SCSI protocol. IDE floppy drives include the + LS-120 and the ATAPI ZIP (ATAPI PD-CD/CDR drives are not supported + by this driver; support for PD-CD/CDR drives is available if you + answer Y to "SCSI emulation support", below). If you say Y here, the FLOPPY drive will be identified along with other IDE devices, as "hdb" or "hdc", or something similar (check @@ -368,18 +389,18 @@ If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. - People with SCSI-only systems should say 'N' here. If unsure, say N. + People with SCSI-only systems can say N here. If unsure, say N. CMD640 chipset bugfix/support CONFIG_BLK_DEV_CMD640 The CMD-Technologies CMD640 IDE chip is used on many common 486 and Pentium motherboards, usually in combination with a "Neptune" or - "SiS" chipset. Unfortunately, it has a number of rather nasty + "SiS" chipset. Unfortunately, it has a number of rather nasty design flaws that can cause severe data corruption under many common - conditions. Say Y here to include code which tries to automatically - detect and correct the problems under Linux. This option also + conditions. Say Y here to include code which tries to automatically + detect and correct the problems under Linux. This option also enables access to the secondary IDE ports in some CMD640 based - systems. + systems. This driver will work automatically in PCI based systems (most new systems have PCI slots). But if your system uses VESA local bus @@ -394,36 +415,35 @@ the "CSA-6400E PCI to IDE controller" that some people have. For details, read Documentation/ide.txt. - People with SCSI-only systems should say 'N' here. If unsure, say Y. + People with SCSI-only systems should say N here. If unsure, say Y. CMD640 enhanced support CONFIG_BLK_DEV_CMD640_ENHANCED This option includes support for setting/autotuning PIO modes and - prefetch on CMD640 IDE interfaces. For details, read + prefetch on CMD640 IDE interfaces. For details, read Documentation/ide.txt. If you have a CMD640 IDE interface and your - BIOS does not already do this for you, then say Y here. Otherwise + BIOS does not already do this for you, then say Y here. Otherwise say N. RZ1000 chipset bugfix/support CONFIG_BLK_DEV_RZ1000 - The PC-Technologies RZ1000 chip is used on many common 486 and + The PC-Technologies RZ1000 IDE chip is used on many common 486 and Pentium motherboards, usually along with the "Neptune" chipset. Unfortunately, it has a rather nasty design flaw that can cause - severe data corruption under many conditions. Say Y here to include + severe data corruption under many conditions. Say Y here to include code which automatically detects and corrects the problem under - Linux. This may slow disk throughput by a few percent, but at least + Linux. This may slow disk throughput by a few percent, but at least things will operate 100% reliably. - People with SCSI-only systems can say 'N' here. If unsure, say Y. + People with SCSI-only systems should say N here. If unsure, say Y. Generic PCI IDE chipset support CONFIG_BLK_DEV_IDEPCI Enable this for PCI systems which use IDE drive(s). This option helps the IDE driver to automatically detect and configure all PCI-based IDE interfaces in your system. - - People with SCSI-only systems should say 'N' here. It is safe to - say 'Y' to this question. + + People with SCSI-only systems should say N here; if unsure say Y. Generic PCI bus-master DMA support CONFIG_BLK_DEV_IDEDMA @@ -442,26 +462,33 @@ It is safe to say Y to this question. +Winbond SL82c105 support +CONFIG_BLK_DEV_SL82C105 + If you have a Winbond SL82c105 IDE controller, say Y here to enable + special configuration for this chip. This is common on various CHRP + motherboards, but could be used elsewhere. If in doubt, say Y. + Boot off-board chipsets first support CONFIG_BLK_DEV_OFFBOARD Normally, IDE controllers built into the motherboard (on-board - controllers) are assigned to ide0 and ide1 while those on add-in - PCI cards (off-board controllers) are relegated to ide2 and ide3. - Saying Y to here will reverse the situation, with off-board - controllers on ide0/1 and on-board controllers on ide2/3. This - can improve the usability of some boot managers such as LILO - when booting from a drive on an off-board controller. - Note that this will rearrange the order of the hd* devices and - may require modification of fstab and other files. + controllers) are assigned to ide0 and ide1 while those on add-in PCI + cards (off-board controllers) are relegated to ide2 and ide3. + Answering Y here will reverse the situation, with off-board + controllers on ide0/1 and on-board controllers on ide2/3. This can + improve the usability of some boot managers such as LILO when + booting from a drive on an off-board controller. + + Note that, if you say Y here, the order of the hd* devices will be + rearranged which may require modification of fstab and other files. If in doubt, say N. Use DMA by default when available CONFIG_IDEDMA_AUTO Prior to kernel version 2.1.112, Linux used to automatically use - DMA for IDE drives and chipsets which support it. Due to concerns + DMA for IDE drives and chipsets which support it. Due to concerns about a couple of cases where buggy hardware may have caused damage, - the default is now to NOT use DMA automatically. To revert to the + the default is now to NOT use DMA automatically. To revert to the previous behaviour, say Y to this question. If you suspect your hardware is at all flakey, say N here. @@ -472,46 +499,48 @@ Other IDE chipset support CONFIG_IDE_CHIPSETS Say Y here if you want to include enhanced support for various IDE - interface chipsets used on motherboards and add-on cards. This - enhanced support may be necessary for Linux to be able to access the - 3rd/4th drives in some systems. It may also enable setting of - higher speed I/O rates to improve system performance with these - chipsets. Most of these also require special kernel boot parameters - to actually turn on the support at runtime. - - People with SCSI-only systems should say 'N' here. + interface chipsets used on motherboards and add-on cards. You can + then pick your particular IDE chip from among the following options. + This enhanced support may be necessary for Linux to be able to + access the 3rd/4th drives in some systems. It may also enable + setting of higher speed I/O rates to improve system performance with + these chipsets. Most of these also require special kernel boot + parameters to actually turn on the support at runtime; you can find + a list of these in the file Documentation/ide.txt. + + People with SCSI-only systems can say N here. Generic 4 drives/port support CONFIG_BLK_DEV_4DRIVES - Certain older chipsets, including the Tekram 690CD, use a - single set of I/O ports at 0x1f0 to control up to four drives, - instead of the customary two drives per port. Support for this - can be enabled at runtime using the "ide0=four" kernel boot - parameter if you say Y here. + Certain older chipsets, including the Tekram 690CD, use a single set + of I/O ports at 0x1f0 to control up to four drives, instead of the + customary two drives per port. Support for this can be enabled at + runtime using the "ide0=four" kernel boot parameter if you say Y + here. DTC-2278 support CONFIG_BLK_DEV_DTC2278 This driver is enabled at runtime using the "ide0=dtc2278" kernel - boot parameter. It enables support for the secondary IDE interface + boot parameter. It enables support for the secondary IDE interface of the DTC-2278 card, and permits faster I/O speeds to be set as - well. See the Documentation/ide.txt and dtc2278.c files for more + well. See the Documentation/ide.txt and dtc2278.c files for more info. Holtek HT6560B support CONFIG_BLK_DEV_HT6560B This driver is enabled at runtime using the "ide0=ht6560b" kernel - boot parameter. It enables support for the secondary IDE interface + boot parameter. It enables support for the secondary IDE interface of the Holtek card, and permits faster I/O speeds to be set as well. See the Documentation/ide.txt and ht6560b.c files for more info. PROMISE DC4030 support (EXPERIMENTAL) CONFIG_BLK_DEV_PDC4030 This driver provides support for the secondary IDE interface and - cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver + cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver is known to incur timeouts/retries during heavy I/O to drives - attached to the secondary interface. CDROM and TAPE devices are not - supported yet. This driver is enabled at runtime using the - "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt + attached to the secondary interface. CDROM and TAPE devices are not + supported yet. This driver is enabled at runtime using the + "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt and drivers/block/pdc4030.c files for more info. PS/2 ESDI hard disk support @@ -522,7 +551,7 @@ Tekram TRM290 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_TRM290 This driver adds support for bus master DMA transfers - using the Tekram TRM290 PCI IDE chip. Volunteers are + using the Tekram TRM290 PCI IDE chip. Volunteers are needed for further tweaking and development. Please read the comments at the top of drivers/block/trm290.c. @@ -541,41 +570,47 @@ VIA82C586 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_VIA82C586 This adds initial timing settings for VIA (U)DMA onboard ide - controllers that are ATA3 compliant. May work with ATA4 systems, - but not tested to date. + controllers that are ATA3 compliant. May work with ATA4 systems, but + not tested to date. + + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. - This requires CONFIG_IDEDMA_AUTO to be enabled. Please read the comments at the top of drivers/block/via82C586.c If unsure, say N. +CMD646 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_CMD646 + Say Y here if you have an IDE controller like this. + HPT343 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_HPT343 - This driver adds up to 4 more eide devices sharing a single interrupt. - The HPT343 chipset in it's current form is a non-bootable PCI - UDMA controller. This driver requires dynamic tuning of the - chipset during the ide-probe at boot. It is reported to support - DVD II drives, by the manufacturer. + This driver adds up to 4 more EIDE devices sharing a single + interrupt. The HPT343 chipset in its current form is a non-bootable + PCI UDMA controller. This driver requires dynamic tuning of the + chipset during the ide-probe at boot. It is reported to support DVD + II drives, by the manufacturer. Please read the comments at the top of drivers/block/hpt343.c QDI QD6580 support CONFIG_BLK_DEV_QD6580 This driver is enabled at runtime using the "ide0=qd6580" kernel - boot parameter. It permits faster I/O speeds to be set. See the + boot parameter. It permits faster I/O speeds to be set. See the files Documentation/ide.txt and qd6580.c for more info. UMC 8672 support CONFIG_BLK_DEV_UMC8672 This driver is enabled at runtime using the "ide0=umc8672" kernel - boot parameter. It enables support for the secondary IDE interface + boot parameter. It enables support for the secondary IDE interface of the UMC-8672, and permits faster I/O speeds to be set as well. See the files Documentation/ide.txt and umc8672.c for more info. ALI M14xx support CONFIG_BLK_DEV_ALI14XX This driver is enabled at runtime using the "ide0=ali14xx" kernel - boot parameter. It enables support for the secondary IDE interface + boot parameter. It enables support for the secondary IDE interface of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster I/O speeds to be set as well. See the files Documentation/ide.txt and ali14xx.c for more info. @@ -620,12 +655,12 @@ Parallel port IDE disks CONFIG_PARIDE_PD This option enables the high-level driver for IDE-type disk devices - connected through a parallel port. If you chose to build PARIDE + connected through a parallel port. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the parallel port IDE driver, otherwise you should answer M to build - it as a loadable module. The module will be called pd.o. You + it as a loadable module. The module will be called pd.o. You must also have at least one parallel port protocol driver in your - system. Among the devices supported by this driver are the SyQuest + system. Among the devices supported by this driver are the SyQuest EZ-135, EZ-230 and SparQ drives, the Avatar Shark and the backpack hard drives from MicroSolutions. @@ -639,31 +674,31 @@ must also have at least one parallel port protocol driver in your system. Among the devices supported by this driver are the MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If - you have such a CD-ROM drive, you should also say Y or M to "ISO 9660 - CDROM filesystem support" below, because that's the filesystem used - on CDROMs. + you have such a CD-ROM drive, you should also say Y or M to "ISO + 9660 CDROM filesystem support" below, because that's the filesystem + used on CDROMs. Parallel port ATAPI disks CONFIG_PARIDE_PF This option enables the high-level driver for ATAPI disk devices - connected through a parallel port. If you chose to build PARIDE + connected through a parallel port. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pf.o. + to build it as a loadable module. The module will be called pf.o. You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver are the + your system. Among the devices supported by this driver are the MicroSolutions backpack PD/CD drive and the Imation Superdisk LS-120 drive. Parallel port ATAPI tapes CONFIG_PARIDE_PT This option enables the high-level driver for ATAPI tape devices - connected through a parallel port. If you chose to build PARIDE + connected through a parallel port. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pt.o. + to build it as a loadable module. The module will be called pt.o. You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver is the + your system. Among the devices supported by this driver is the parallel port version of the HP 5GB drive. Parallel port generic ATAPI devices @@ -671,54 +706,59 @@ This option enables a special high-level driver for generic ATAPI devices connected through a parallel port. The driver allows user programs, such as cdrecord, to send ATAPI commands directly to a - device. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the parallel port generic ATAPI driver, - otherwise you should answer M to build it as a loadable module. - The module will be called pg.o. You must also have at least one - parallel port protocol driver in your system. This driver - implements an API loosely related to the generic SCSI driver. - See /usr/include/linux/pg.h for details. + device. + + If you chose to build PARIDE support into your kernel, you may + answer Y here to build in the parallel port generic ATAPI driver, + otherwise you should answer M to build it as a loadable module. The + module will be called pg.o. + + You must also have at least one parallel port protocol driver in + your system. + + This driver implements an API loosely related to the generic SCSI + driver. See /usr/include/linux/pg.h for details. You can obtain the most recent version of cdrecord from - ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and - later fully support the pg driver. + ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and + later fully support this driver. ATEN EH-100 protocol CONFIG_PARIDE_ATEN This option enables support for the ATEN EH-100 parallel port IDE - protocol. This protocol is used in some inexpensive low performance - parallel port kits made in Hong Kong. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called aten.o. You must also - have a high-level driver for the type of device that you want to + protocol. This protocol is used in some inexpensive low performance + parallel port kits made in Hong Kong. If you chose to build PARIDE + support into your kernel, you may answer Y here to build in the + protocol driver, otherwise you should answer M to build it as a + loadable module. The module will be called aten.o. You must also + have a high-level driver for the type of device that you want to support. MicroSolutions backpack protocol CONFIG_PARIDE_BPCK - This option enables support for the MicroSolutions backpack - parallel port IDE protocol. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called bpck.o. You must also have - a high-level driver for the type of device that you want to support. + This option enables support for the MicroSolutions backpack parallel + port IDE protocol. If you chose to build PARIDE support into your + kernel, you may answer Y here to build in the protocol driver, + otherwise you should answer M to build it as a loadable module. The + module will be called bpck.o. You must also have a high-level driver + for the type of device that you want to support. DataStor Commuter protocol CONFIG_PARIDE_COMM This option enables support for the Commuter parallel port IDE - protocol from DataStor. If you chose to build PARIDE support + protocol from DataStor. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the protocol driver, otherwise you should answer M to build it as a loadable - module. The module will be called comm.o. You must also have + module. The module will be called comm.o. You must also have a high-level driver for the type of device that you want to support. DataStor EP-2000 protocol CONFIG_PARIDE_DSTR This option enables support for the EP-2000 parallel port IDE - protocol from DataStor. If you chose to build PARIDE support + protocol from DataStor. If you chose to build PARIDE support into your kernel, you may answer Y here to build in the protocol driver, otherwise you should answer M to build it as a loadable - module. The module will be called dstr.o. You must also have + module. The module will be called dstr.o. You must also have a high-level driver for the type of device that you want to support. Shuttle EPAT/EPEZ protocol @@ -767,11 +807,11 @@ FreeCom power protocol CONFIG_PARIDE_FRPW - This option enables support for the Freecom power parallel port IDE - protocol. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called frpw.o. You must also have a high-level driver for the type + This option enables support for the Freecom power parallel port IDE + protocol. If you chose to build PARIDE support into your kernel, you + may answer Y here to build in the protocol driver, otherwise you + should answer M to build it as a loadable module. The module will be + called frpw.o. You must also have a high-level driver for the type of device that you want to support. KingByte KBIC-951A/971A protocols @@ -788,11 +828,11 @@ KT PHd protocol CONFIG_PARIDE_KTTI This option enables support for the "PHd" parallel port IDE protocol - from KT Technology. This is a simple (low speed) adapter that is - used in some 2.5" portable hard drives. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called ktti.o. You must also + from KT Technology. This is a simple (low speed) adapter that is + used in some 2.5" portable hard drives. If you chose to build PARIDE + support into your kernel, you may answer Y here to build in the + protocol driver, otherwise you should answer M to build it as a + loadable module. The module will be called ktti.o. You must also have a high-level driver for the type of device that you want to support. @@ -800,43 +840,52 @@ CONFIG_PARIDE_ON20 This option enables support for the (obsolete) 90c20 parallel port IDE protocol from OnSpec (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you + name). If you chose to build PARIDE support into your kernel, you may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will - be called on20.o. You must also have a high-level driver for the + should answer M to build it as a loadable module. The module will + be called on20.o. You must also have a high-level driver for the type of device that you want to support. OnSpec 90c26 protocol CONFIG_PARIDE_ON26 - This option enables support for the 90c26 parallel port IDE protocol + This option enables support for the 90c26 parallel port IDE protocol from OnSpec Electronics (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will - be called on26.o. You must also have a high-level driver for the - type of device that you want to support. + name). If you chose to build PARIDE support into your kernel, you + may answer Y here to build in the protocol driver, otherwise you + should answer M to build it as a loadable module. The module will be + called on26.o. You must also have a high-level driver for the type + of device that you want to support. Multiple devices driver support CONFIG_BLK_DEV_MD This driver lets you combine several hard disk partitions into one - logical block device. This can be used to combine several redundant + logical block device. This can be used to simply append one + partition to another one or to combine several redundant hard disks to a RAID1/4/5 device so as to provide protection against - hard disk failures. More information and the necessary tools are - available over FTP (user: anonymous) from - ftp://sweet-smoke.ufr-info-p7.ibp.fr/pub/Linux in the md package and - the md-FAQ. Please read drivers/block/README.md and the relevant - section of the Disk-HOWTO, available via FTP (user: anonymous) from - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. If unsure, say N. + hard disk failures. This is called "Software RAID" since the + combining of the partitions is done by the kernel. "Hardware RAID" + means that the combining is done by a dedicated controller; if you + have such a controller, you do not need to say Y here. + + More information about Software RAID on Linux is contained in the + Software-RAID mini-HOWTO, available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also + learn where to get the supporting user space utilities raidtools. + + If unsure, say N. Linear (append) mode CONFIG_MD_LINEAR If you say Y here, then your multiple devices driver will be able to use the so-called linear mode, i.e. it will combine the hard disk - partitions by simply appending one to the other. If you want to - compile this as a module ( = code which can be inserted in and - removed from the running kernel whenever you want), say M here and - read Documentation/modules.txt. The module will be called - linear.o. If unsure, say Y. + partitions by simply appending one to the other. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called linear.o. + + If unsure, say Y. RAID-0 (striping) mode CONFIG_MD_STRIPED @@ -844,31 +893,19 @@ use the so-called raid0 mode, i.e. it will combine the hard disk partitions into one logical device in such a fashion as to fill them up evenly, one chunk here and one chunk there. This will increase - the throughput rate if the partitions reside on distinct disks. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - raid0.o. If unsure, say Y. + the throughput rate if the partitions reside on distinct disks. -Are you using a crosscompiler -CONFIG_CROSSCOMPILE - Set this if you are using another architecture to compile the - kernel for your MIPS machine. + Information about Software RAID on Linux is contained in the + Software-RAID mini-HOWTO, available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also + learn where to get the supporting user space utilities raidtools. -Support for Acer PICA 1 chipset -CONFIG_ACER_PICA_61 - This is a machine with a R4400 133/150 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://lena.fnet.fr/ (To browse the WWW, you need to have access to - a machine on the Internet that has a program like lynx or - netscape). + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called raid0.o. -Support for Algorithmics P4032 -CONFIG_ALGOR_P4032 - This is an evaluation board of the British company Algorithmics. The - board uses the R4300 and a R5230 CPUs. For more information about - this board see www.algor.co.uk. + If unsure, say Y. RAID-1 (mirroring) mode CONFIG_MD_MIRRORING @@ -878,23 +915,20 @@ an error free MD (multiple device) to the higher levels of the kernel. In a set with N drives, the available space is the capacity of a single drive, and the set protects against a failure of (N - 1) - drives. + drives. - Raidtools, a set of user-space tools which create and maintain - RAID1/4/5 sets, is available at: - ftp://ftp.kernel.org/pub/linux/daemons/raid - http://luthien.nuclecu.unam.mx/~miguel/raid + Information about Software RAID on Linux is contained in the + Software-RAID mini-HOWTO, available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also + learn where to get the supporting user space utilities raidtools. If you want to use such a RAID-1 set, say Y. This code is also available as a module called raid1.o ( = 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. If unsure, say Y. + Documentation/modules.txt. -Boot support (linear, striped) -CONFIG_MD_BOOT - To boot with an initial linear or striped md device you have to say - Y here. For lilo and loadlin options see Documentation/md.txt. + If unsure, say Y. RAID-4/RAID-5 mode CONFIG_MD_RAID5 @@ -906,16 +940,47 @@ while a RAID-5 set distributes the parity across the drives in one of the available parity distribution methods. - Raidtools, a set of user-space tools which create and maintain - RAID1/4/5 sets, is available at: - ftp://ftp.kernel.org/pub/linux/daemons/raid - http://luthien.nuclecu.unam.mx/~miguel/raid + Information about Software RAID on Linux is contained in the + Software-RAID mini-HOWTO, available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/mini. There you will also + learn where to get the supporting user space utilities raidtools. - If you want to use such a RAID-5 set, say Y. This code is also - available as a module called raid5.o ( = 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. If unsure, say Y. + If you want to use such a RAID-4/RAID-5 set, say Y. This code is + also available as a module called raid5.o ( = 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. + + If unsure, say Y. + +Boot support (linear, striped) +CONFIG_MD_BOOT + To boot with an initial linear or striped md device you have to + answer Y here. For lilo and loadlin options see the file + Documentation/md.txt. + +Support for Deskstation RPC44 +CONFIG_DESKSTATION_RPC44 + This is a machine with a R4400 100 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux + on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to + have access to a machine on the Internet that has a program like + lynx or netscape). + +Support for Acer PICA 1 chipset +CONFIG_ACER_PICA_61 + This is a machine with a R4400 133/150 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + http://lena.fnet.fr/ (To browse the WWW, you need to have access to + a machine on the Internet that has a program like lynx or netscape). + +Support for Algorithmics P4032 +CONFIG_ALGOR_P4032 + This is an evaluation board of the British company Algorithmics. The + board uses the R4300 and a R5230 CPUs. For more information about + this board see http://www.algor.co.uk. Support for Mips Magnum 4000 CONFIG_MIPS_MAGNUM_4000 @@ -935,27 +1000,27 @@ CPU type CONFIG_CPU_R3000 - Give the type of your machine's MIPS CPU. For this question, - it suffices to give a unique prefix of the option you want to - choose. In case of doubt select the R3000 CPU. This kernel will - run on other MIPS machines but with slightly reduced performance. + Give the type of your machine's MIPS CPU. For this question, it + suffices to give a unique prefix of the option you want to choose. + In case of doubt select the R3000 CPU. The kernel will then run on + other MIPS machines but with slightly reduced performance. Compile the kernel into the ECOFF object format CONFIG_ECOFF_KERNEL - Some machines require a kernel in the ECOFF format. You will have to - Choose this option for example if you want to a Mips Magnum 3000 or a - DECstation over network. + Some machines require a kernel in the ECOFF format. You will have to + say Y here for example if you want to use a Mips Magnum 3000 or a + DECstation. Generate little endian code CONFIG_CPU_LITTLE_ENDIAN Some MIPS machines can be configured for either little or big endian - byte order. Both modes require different kernels. Say yes if your - machine is little endian, no if it's a big endian machine. + byte order. These modes require different kernels. Say Y if your + machine is little endian, N if it's a big endian machine. Kernel support for IRIX binaries CONFIG_BINFMT_IRIX - This option enables the kernel support for IRIX binaries. Running - IRIX binaries additionally requires IRIX libraries. + If you say Y here, the kernel will support running of IRIX binaries. + You will need IRIX libraries for this to work. Networking support CONFIG_NET @@ -1036,10 +1101,11 @@ SYN flood protection CONFIG_SYN_COOKIES - Normal TCP/IP networking is open to an attack known as "SYN flooding". - This denial-of-service attack prevents legitimate remote users from - being able to connect to your computer and requires very little work - from the attacker, who can operate from anywhere on the Internet. + Normal TCP/IP networking is open to an attack known as "SYN + flooding". This denial-of-service attack prevents legitimate remote + users from being able to connect to your computer during an ongoing + attack and requires very little work from the attacker, who can + operate from anywhere on the Internet. SYN cookies provide protection against this type of attack. If you say Y here, the TCP/IP stack will use a cryptographic challenge @@ -1055,6 +1121,10 @@ an aid in tracing the packets to their actual source and should not be taken as absolute truth. + SYN cookies may prevent correct error reporting on clients when the + server is really overloaded. If this happens frequently better turn + them off. + If you say Y here, note that SYN cookies aren't enabled by default; you can enable them by saying Y to "/proc filesystem support" and "Sysctl support" below and executing the command @@ -1081,7 +1151,7 @@ question, it suffices to give a unique prefix of the option you want to choose. The choices: ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400) - AlphaStations. These usually come with a TGA graphics adapter, + AlphaStations. These usually come with a TGA graphics adapter, so you'll want to say Y to "TGA Console support", below, if you have one of these. ** Alpha-XL: A.k.a. "Windows NT Dream Machine" :-) These usually @@ -1134,20 +1204,24 @@ This includes intelligent serial boards such as Cyclades, Digiboards, etc. These are usually used for systems that need many serial ports because they serve many terminals or dial-in - connections. Note that the answer to this question won't directly - affect the kernel: saying N will just cause this configure script to - skip all the questions about non-standard serial boards. Most people - can say N here. + connections. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about non-standard serial boards. + + Most people can say N here. Extended dumb serial driver options CONFIG_SERIAL_EXTENDED If you wish to use any non-standard features of the standard "dumb" - driver, say Y here. This includes HUB6 support, shared serial + driver, say Y here. This includes HUB6 support, shared serial interrupts, special multiport support, support for more than the - four COM 1/2/3/4 boards, etc. Note that the answer to this question - won't directly affect the kernel: saying N will just cause this - configure script to skip all the questions about serial driver - options. If unsure, say N. + four COM 1/2/3/4 boards, etc. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about serial driver options. If unsure, say N. Support more than 4 serial ports CONFIG_SERIAL_MANY_PORTS @@ -1164,7 +1238,7 @@ Support for sharing serial interrupts CONFIG_SERIAL_SHARE_IRQ Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable + serial ports on the same board to share a single IRQ. To enable support for this in the serial driver, say Y here. Auto detect IRQ on standard ports (unsafe) @@ -1181,26 +1255,20 @@ CONFIG_SERIAL_MULTIPORT Some multiport serial ports have special ports which are used to signal when there are any serial ports on the board which need - servicing. Say Y here to enable the serial driver to take advantage + servicing. Say Y here to enable the serial driver to take advantage of those special I/O ports. SGI Zilog85C30 serial support CONFIG_SGI_SERIAL - If you want to use your SGI's built-in serial ports under Linux, say Y. + If you want to use your SGI's built-in serial ports under Linux, + answer Y. SGI graphics support CONFIG_SGI_GRAPHICS - If you have an SGI machine and you want to compile the graphic drivers - select this option. This will include the code for the /dev/graphics - and /dev/gfx drivers into the kernel for supporting the virtualized - access to your graphics hardware. - -Remote GDB kernel debugging -CONFIG_REMOTE_DEBUG - This enables remote debugging support for the MIPS kernel. Enabling - this option enlarges you kernel image disk size by several megabytes - and requires a machine with more than 16mb, better 32mb RAM to avoid - excessive linking time. + If you have an SGI machine and you want to compile the graphics + drivers, say Y here. This will include the code for the + /dev/graphics and /dev/gfx drivers into the kernel for supporting + virtualized access to your graphics hardware. Support the Bell Technologies HUB6 card CONFIG_HUB6 @@ -1238,10 +1306,10 @@ CONFIG_PCI_DIRECT If you don't want to use the PCI BIOS (e.g., because you run some embedded system with no BIOS at all) or Linux says it cannot use - your PCI BIOS, you can enable direct PCI hardware here. It might fail - if your machine is based on some unusual chipset, but it usually - works. If both PCI BIOS and direct PCI access are enabled, the use - of BIOS is preferred. If unsure, say Y. + your PCI BIOS, you can enable direct PCI hardware here. It might + fail if your machine is based on some unusual chipset, but it + usually works. If both PCI BIOS and direct PCI access are enabled, + the use of BIOS is preferred. If unsure, say Y. PCI quirks CONFIG_PCI_QUIRKS @@ -1253,9 +1321,9 @@ PCI bridge optimization (experimental) CONFIG_PCI_OPTIMIZE This can improve access times for some hardware devices if you have - a really broken BIOS and your computer uses a PCI bus system. Set to - Y if you think it might help, but try turning it off if you - experience any problems with the PCI bus. N is the safe answer. + a really broken BIOS and your computer uses a PCI bus system. Say Y + if you think it might help, but try turning it off if you experience + any problems with the PCI bus. N is the safe answer. Backward-compatible /proc/pci CONFIG_PCI_OLD_PROC @@ -1275,15 +1343,15 @@ MCA support CONFIG_MCA MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See + laptops. It is a bus system similar to PCI or ISA. See Documentation/mca.txt (and especially the web page given there) - before attempting to build an MCA bus kernel. Note that this is + before attempting to build an MCA bus kernel. Note that this is still experimental code. System V IPC CONFIG_SYSVIPC Inter Process Communication is a suite of library functions and - system calls which let processes (= running programs) synchronize + system calls which let processes (running programs) synchronize and exchange information. It is generally considered to be a good thing, and some programs won't run unless you say Y here. In particular, if you want to run the DOS emulator dosemu under Linux @@ -1296,7 +1364,7 @@ (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide. - Saying Y here enlarges your kernel by about 7kB. Just say Y. + Saying Y here enlarges your kernel by about 7 KB. Just say Y. BSD Process Accounting CONFIG_BSD_PROCESS_ACCT @@ -1319,31 +1387,33 @@ enabled, a tree of modifiable sysctl entries will be generated beneath the /proc/sys directory. They are explained in the files in Documentation/sysctl/. Note that enabling this option will enlarge - the kernel by at least 8kB. As it is generally a good thing, you - should say Y here unless building a kernel for install/rescue disks - or your system is very limited in memory. + the kernel by at least 8 KB. + + As it is generally a good thing, you should say Y here unless + building a kernel for install/rescue disks or your system is very + limited in memory. Kernel support for ELF binaries CONFIG_BINFMT_ELF ELF (Executable and Linkable Format) is a format for libraries and executables used across different architectures and operating - systems. Saying Y here will enable your kernel to run ELF binaries and - enlarge it by about 2kB. ELF support under Linux has now all but - replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) + systems. Saying Y here will enable your kernel to run ELF binaries + and enlarge it by about 2 KB. ELF support under Linux has now all + but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC) because it is portable (this does *not* mean that you will be able - to run executables from different architectures or operating - systems!) and makes building run-time libraries very easy. Many new + to run executables from different architectures or operating systems + however) and makes building run-time libraries very easy. Many new executables are distributed solely in ELF format. You definitely - want to say Y here. + want to say Y here. - Information about ELF is on the WWW at - http://www.sjc.ox.ac.uk/users/barlow/elf-howto.html (to browse the - WWW, you need to have access to a machine on the Internet that has a - program like lynx or netscape). If you find that after upgrading - from Linux kernel 1.2 and saying Y here, you still can't run any ELF - binaries (they just crash), then you'll have to install the newest - ELF runtime libraries, including ld.so (check the file - Documentation/Changes for location and latest version). + Information about ELF is contained in the ELF HOWTO available via + FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + If you find that after upgrading from Linux kernel 1.2 and saying Y + here, you still can't run any ELF binaries (they just crash), then + you'll have to install the newest ELF runtime libraries, including + ld.so (check the file Documentation/Changes for location and latest + version). If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -1389,14 +1459,14 @@ Saying Y here allows you to execute a JAVA bytecode binary just like any other Linux program: by simply typing in its name. (You also - need to have the JDK installed for this to work). As more and more + need to have the JDK installed for this to work). As more and more Java programs become available, the use for this will gradually - increase. You can even execute HTML files containing JAVA applets - (= JAVA binaries) if those files start with the string + increase. You can even execute HTML files containing JAVA applets + (little embedded JAVA binaries) if those files start with the string "". If you want to use this, say Y here and read - Documentation/java.txt. + Documentation/java.txt. - If you disable this option it will reduce your kernel by about 4kB. + If you disable this option it will reduce your kernel by about 4 KB. This is not much and by itself does not warrant removing support. However its removal is a good idea if you do not have the JDK installed. You may answer M for module support and later load the @@ -1417,7 +1487,7 @@ this to work, you need to have the emulator /usr/bin/em86 in place. You may answer M to compile the emulation support as a module and later load the module when you want to use a Linux/Intel binary. The - module will be called binfmt_em86.o. If unsure, say Y. + module will be called binfmt_em86.o. If unsure, say Y. Kernel support for MISC binaries CONFIG_BINFMT_MISC @@ -1450,7 +1520,7 @@ Solaris binary emulation CONFIG_SOLARIS_EMUL This is experimental code which will enable you to run (many) - Solaris binaries on your SPARC Linux machine. + Solaris binaries on your SPARC Linux machine. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -1462,11 +1532,23 @@ This is the processor type of your CPU. This information is used for optimizing purposes. In order to compile a kernel that can run on all x86 CPU types (albeit not optimally fast), you can specify - "386" here. If you specify one of "486" or "Pentium" or "PPro", - then the kernel will run on all of these CPUs: 486 and Pentium - (=586) and Pentium Pro (=686). In rare cases, it can make sense to - specify "Pentium" even if running on a 486: the kernel will be - smaller but slower. + "386" here. If you specify one of "486" or "Pentium" or "PPro", + then the kernel will run on all x86 architectures except on 386. + + Here are the settings recommended for greatest speed: + - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX and + Cyrix/TI 486DLC/DLC2. Only "386" kernels will run on a 386 class + machine. + - "486" for the AMD/Cyrix/IBM/Intel DX4 or 486DX/DX2/SL/SX/SX2, + AMD/Cyrix 5x86, NexGen Nx586 and UMC U5D or U5S + - "Pentium" for the AMD K5, K6 and K6-3D, Cyrix MediaGX, + Cyrix/IBM/National Semiconductor 6x86 and GXm, IDT Centaur + WinChip C6, and Intel Pentium/Pentium MMX + - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and + Intel Pentium II/Pentium Pro + + In rare cases, it can make sense to specify "Pentium" even if + running on a 486: the kernel will be smaller but slower. If you have a single processor machine, make sure that the line "SMP=1" at the top of the toplevel kernel Makefile is commented out; @@ -1479,12 +1561,12 @@ like lynx or netscape). People using multiprocessor machines should also say Y to "Enhanced Real Time Clock Support", below. - If you want to compile a kernel that should work on both single - processor and multi processor machines, it is possible to set SMP=1. - The "Advanced Power Management" code (see configuration option - below) will not work in that scenario, though. In addition, the - kernel will be slower on single processor machines, and other - problems may appear, so this is not recommended. + If you want to compile a kernel that works on both single processor + and multi processor machines, it is possible to set SMP=1. The + "Advanced Power Management" code (see configuration option below) + will not work in that scenario, though. In addition, the kernel will + be slower on single processor machines, and other problems may + appear, so this is not recommended. If you don't know what to do, choose "386". @@ -1492,7 +1574,13 @@ CONFIG_VGA_CONSOLE Saying Y here will allow you to use Linux in text mode through a display that complies with the generic VGA standard. Virtually - everyone wants that. Say Y. + everyone wants that. + + The program SVGATextMode can be used to utilize SVGA video cards to + their full potential in text mode. Download it via FTP (user: + anonymous) from ftp://sunsite.unc.edu/pub/Linux/utils/console. + + Say Y. Video mode selection support CONFIG_VIDEO_SELECT @@ -1528,13 +1616,15 @@ in the /dev directory, i.e. /dev/fb*. You need an utility program called fbset to make full use of frame - buffer devices. Please read the file - Documentation/fb/framebuffer.txt for more information. + buffer devices. Please read Documentation/fb/framebuffer.txt and the + Framebuffer-HOWTO at + http://www.tahallah.demon.co.uk/programming/prog.html for more + information. - If you want to play with it, say Y here and also to the driver for - your graphics board, below. If unsure, say N, unless you are - compiling a kernel for a non-X86 architecture, in which case you - should say Y. + Say Y here and to the driver for your graphics board below if you + are compiling a kernel for a non-x86 architecture. If you are + compiling for the x86 architecture, you can say Y if you want to + play with it, but it is not essential. Acorn VIDC support CONFIG_FB_ACORN @@ -1554,13 +1644,13 @@ Amiga OCS chipset support CONFIG_FB_AMIGA_OCS This enables support for the original Agnus and Denise video chips, - found in the Amiga 1000 and most A500's and A2000's. If you intend + found in the Amiga 1000 and most A500's and A2000's. If you intend to run Linux on any of these systems, say Y; otherwise say N. Amiga ECS chipset support CONFIG_FB_AMIGA_ECS This enables support for the Enhanced Chip Set, found in later - A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If + A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If you intend to run Linux on any of these systems, say Y; otherwise say N. @@ -1568,7 +1658,7 @@ CONFIG_FB_AMIGA_AGA This enables support for the Advanced Graphics Architecture (also known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T - and CD32. If you intend to run Linux on any of these systems, say Y; + and CD32. If you intend to run Linux on any of these systems, say Y; otherwise say N. Amiga CyberVision support @@ -1609,7 +1699,8 @@ Open Firmware frame buffer device support CONFIG_FB_OF - Say Y if you want support with Open Firmware for your graphics board. + Say Y if you want support with Open Firmware for your graphics + board. S3 Trio frame buffer device support CONFIG_FB_S3TRIO @@ -1626,13 +1717,13 @@ PowerMac "platinum" frame buffer device support CONFIG_FB_PLATINUM - This driver supports a frame buffer for the "platinum" graphics adapter - in some Power Macintoshes. + This driver supports a frame buffer for the "platinum" graphics + adapter in some Power Macintoshes. PowerMac "valkyrie" frame buffer device support CONFIG_FB_VALKYRIE - This driver supports a frame buffer for the "valkyrie" graphics adapter - in some Power Macintoshes. + This driver supports a frame buffer for the "valkyrie" graphics + adapter in some Power Macintoshes. Chips 65550 display support CONFIG_FB_CT65550 @@ -1651,29 +1742,39 @@ TGA frame buffer support CONFIG_FB_TGA - This is the frame buffer device driver for generic TGA graphic cards. - Say Y if you have one of those. + This is the frame buffer device driver for generic TGA graphic + cards. Say Y if you have one of those. VESA VGA graphics console CONFIG_FB_VESA - This is the frame buffer device driver for generic VESA graphic cards. - Please read Documentation/fb/vesafb.txt. + This is the frame buffer device driver for generic VESA 2.0 + compliant graphic cards. The older VESA 1.2 cards are not supported. + You will get a boot time penguin logo at no additional cost. Please + read Documentation/fb/vesafb.txt and the . If unsure, say Y. + +Backward compatibility mode for Xpmac +CONFIG_FB_COMPAT_XPMAC + If you use the Xpmac X server (common with mklinux), you'll need + to enable this to use X. You should consider changing to XFree86 + which includes a server that supports the frame buffer device + directly (XF68_FBDev). MDA text console (dual-headed) CONFIG_MDA_CONSOLE Say Y here if you have an old MDA or monochrome Hercules graphics - adapter in your system acting as a second head ( = video card). Do - not enable this driver if your MDA card is the primary card in your - system; the normal VGA driver will handle it. + adapter in your system acting as a second head ( = video card). You + will then be able to use two monitors with your Linux system. Do not + say Y here if your MDA card is the primary card in your system; the + normal VGA driver will handle it. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). - The module will be called mdacon.o. If you want to compile it as + The module will be called mdacon.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say N. -SBUS and UPA framebuffers +SBUS and UPA frame buffers CONFIG_FB_SBUS Say Y if you want support for SBUS or UPA based frame buffer device. @@ -1697,7 +1798,8 @@ TCX (SS4/SS5 only) support CONFIG_FB_TCX - This is the frame buffer device driver for the TCX 24/8bit frame buffer. + This is the frame buffer device driver for the TCX 24/8bit frame + buffer. Virtual Frame Buffer support (ONLY FOR TESTING!) CONFIG_FB_VIRTUAL @@ -1711,19 +1813,19 @@ kernel option `video=vfb:'. This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). - The module will be called vfb.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. + inserted and removed from the running kernel whenever you want). The + module will be called vfb.o. If you want to compile it as a module, + say M here and read Documentation/modules.txt. If unsure, say N. Advanced low level driver options CONFIG_FBCON_ADVANCED The frame buffer console uses character drawing routines that are - tailored to the specific organization of pixels in the memory of your - graphics hardware. These are called the low level frame buffer console - drivers. Note that they are used for text console output only; they are - NOT needed for graphical applications. + tailored to the specific organization of pixels in the memory of + your graphics hardware. These are called the low level frame buffer + console drivers. Note that they are used for text console output + only; they are NOT needed for graphical applications. If you say N here, the needed low level drivers are automatically enabled, depending on what frame buffer devices you selected above. @@ -1734,9 +1836,9 @@ for color depths you do not intend to use for text consoles. Low level frame buffer console drivers can be modules ( = code which - can be inserted and removed from the running kernel whenever you want). - The modules will be called fbcon-*.o. If you want to compile (some of) - them as modules, read Documentation/modules.txt. + can be inserted and removed from the running kernel whenever you + want). The modules will be called fbcon-*.o. If you want to compile + (some of) them as modules, read Documentation/modules.txt. If unsure, say N. @@ -1747,23 +1849,24 @@ 2 bpp packed pixels support CONFIG_FBCON_CFB2 - This is the low level frame buffer console driver for 2 bits per pixel - (4 colors) packed pixels. + This is the low level frame buffer console driver for 2 bits per + pixel (4 colors) packed pixels. 4 bpp packed pixels support CONFIG_FBCON_CFB4 - This is the low level frame buffer console driver for 4 bits per pixel - (16 colors) packed pixels. + This is the low level frame buffer console driver for 4 bits per + pixel (16 colors) packed pixels. 8 bpp packed pixels support CONFIG_FBCON_CFB8 - This is the low level frame buffer console driver for 8 bits per pixel - (256 colors) packed pixels. + This is the low level frame buffer console driver for 8 bits per + pixel (256 colors) packed pixels. 16 bpp packed pixels support CONFIG_FBCON_CFB16 This is the low level frame buffer console driver for 15 or 16 bits - per pixel (32K or 64K colors, also known as `hicolor') packed pixels. + per pixel (32K or 64K colors, also known as `hicolor') packed + pixels. 24 bpp packed pixels support CONFIG_FBCON_CFB24 @@ -1773,13 +1876,13 @@ 32 bpp packed pixels support CONFIG_FBCON_CFB32 - This is the low level frame buffer console driver for 32 bits per pixel - (16M colors, also known as `truecolor') sparse packed pixels. + This is the low level frame buffer console driver for 32 bits per + pixel (16M colors, also known as `truecolor') sparse packed pixels. Amiga bitplanes support CONFIG_FBCON_AFB - This is the low level frame buffer console driver for 1 to 8 bitplanes - (2 to 256 colors) on Amiga. + This is the low level frame buffer console driver for 1 to 8 + bitplanes (2 to 256 colors) on Amiga. Amiga interleaved bitplanes support CONFIG_FBCON_ILBM @@ -1804,8 +1907,8 @@ Mac variable bpp packed pixels support CONFIG_FBCON_MAC This is the low level frame buffer console driver for 1/2/4/8/16/32 - bits per pixel packed pixels on Mac. It supports variable font widths - for low resolution screens. + bits per pixel packed pixels on Mac. It supports variable font + widths for low resolution screens. VGA characters/attributes support CONFIG_FBCON_VGA @@ -1823,13 +1926,13 @@ For extensive information about drivers for many devices attaching to the parallel port see http://www.torque.net/linux-pp.html on the - WWW (To browse the WWW, you need to have access to a machine on the + WWW (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). It is possible to share a single parallel port among several devices and it is safe to compile all the corresponding drivers into the - kernel. If you want to compile parallel port support as a module - ( = code which can be inserted in and removed from the running kernel + kernel. If you want to compile parallel port support as a module ( = + code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called parport.o. If you have more than one parallel port and want to specify which port and IRQ to be used by @@ -1857,22 +1960,8 @@ Sun Ultra/AX-style hardware CONFIG_PARPORT_AX Say Y here if you need support for the parallel port hardware on Sun - Ultra/AX machines. This code is also available as a module (say M), - called parport_ax.o. If in doubt, saying N is the safe plan. - -Generate little endian code -CONFIG_CPU_LITTLE_ENDIAN - If your compiler is mipsel-linux-gcc or mipsel-linuxelf-gcc (as - opposed to mips-linux-gcc or mips-linuxelf-gcc), say Y here, - otherwise N. Most MIPS machines use little-endian code, but it might - be necessary to run older Mips systems, such as the Sony News and - MIPS RC3xxx, in big endian mode. - -Build fp execption handler module -CONFIG_MIPS_FPE_MODULE - Build the floating point exception handler module. This option is only - useful for people working on the floating point exception handler. If - you don't, say n. + Ultra/AX machines. This code is also available as a module (say M), + called parport_ax.o. If in doubt, saying N is the safe plan. Plug and Play support CONFIG_PNP @@ -1882,8 +1971,8 @@ Auto-probe for parallel devices CONFIG_PNP_PARPORT Some IEEE-1284 conforming parallel-port devices can identify - themselves when requested. Say Y to enable this feature, or M to - compile it as a module (parport_ieee1284.o). If in doubt, say N. + themselves when requested. Say Y to enable this feature, or M to + compile it as a module (parport_ieee1284.o). If in doubt, say N. Enable loadable module support CONFIG_MODULES @@ -1904,10 +1993,10 @@ same modules even after compiling a new kernel; this requires the program modprobe. All the software needed for module support is in the modutils package (check the file Documentation/Changes for - location and latest version). NOTE: if you say Y here but don't + location and latest version). NOTE: if you say Y here but don't have the program genksyms (which is also contained in the above mentioned modutils package), then the building of your kernel will - fail. If you are going to use modules that are generated from + fail. If you are going to use modules that are generated from non-kernel sources, you would benefit from this option. Otherwise it's not that important. So, N ought to be a safe bet. @@ -1919,20 +2008,21 @@ modprobe) before you can use them. If you say Y here however, the kernel will be able to load modules for itself: when a part of the kernel needs a module, it runs modprobe with the appropriate - arguments. (This is a replacement for kerneld.) Say Y here and read - about configuring it in Documentation/kmod.txt. + arguments, thereby loading the module if it is available. (This is a + replacement for kerneld.) Say Y here and read about configuring it + in Documentation/kmod.txt. ARP daemon support (EXPERIMENTAL) CONFIG_ARPD Normally, the kernel maintains an internal cache which maps IP addresses to hardware addresses on the local network, so that Ethernet/Token Ring/ etc. frames are sent to the proper address on - the physical networking layer. For small networks having a few + the physical networking layer. For small networks having a few hundred directly connected hosts or less, keeping this address - resolution (ARP) cache inside the kernel works well. However, + resolution (ARP) cache inside the kernel works well. However, maintaining an internal ARP cache does not work well for very large switched networks, and will use a lot of kernel memory if TCP/IP - connections are made to many machines on the network. + connections are made to many machines on the network. If you say Y here, the kernel's internal ARP cache will never grow to more than 256 entries (the oldest entries are expired in a LIFO @@ -1940,10 +2030,10 @@ daemon arpd. Arpd then answers the address resolution request either from its own cache or by asking the net. - This code is still experimental. If you do say Y here, you should - obtain a copy of arpd from - http://www.loran.com/~layes/arpd/index.html, and you should also say - Y to "Kernel/User network link driver", below. If unsure, say N. + This code is experimental. If you do say Y here, you should obtain a + copy of arpd from http://www.loran.com/~layes/arpd/index.html, and + you should also say Y to "Kernel/User network link driver", below. + If unsure, say N. TCP/IP networking CONFIG_INET @@ -1952,11 +2042,12 @@ kernel by about 35 kB), since some programs (e.g. the X window system) use TCP/IP even if your machine is not connected to any other computer. You will get the so-called loopback device which - allows you to ping yourself (great fun, that!). This option is also - necessary if you want to use the full power of term (term is a - program which gives you almost full Internet connectivity if you - have a regular dial up shell account on some Internet connected Unix - computer. Read http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). + allows you to ping yourself (great fun, that!). This option is + also necessary if you want to use the full power of term (term + is a program which gives you almost full Internet connectivity + if you have a regular dial up shell account on some Internet + connected Unix computer; for more information, read + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html). If you say Y here and also to "/proc filesystem support" and "Sysctl support" below, you can change various aspects of the behavior of @@ -1987,17 +2078,32 @@ will then be presented with several options that allow more precise control about the routing process. - The answer to this question won't directly affect the kernel: saying - N will just cause this configure script to skip all the questions - about advanced routing. + The answer to this question won't directly affect the kernel: + answering N will just cause this configure script to skip all the + questions about advanced routing. Note that your box can only act as a router if you enable IP forwarding in your kernel; you can do that by saying Y to "/proc - filesystem support" and "Sysctl support" below and executing the line + filesystem support" and "Sysctl support" below and executing the + line echo "1" > /proc/sys/net/ipv4/ip_forward - at boot time after the /proc filesystem has been mounted. + at boot time after the /proc filesystem has been mounted. + + If you turn on IP forwarding, you will also get the rp_filter, which + automatically rejects incoming packets if the routing table entry + for their source address doesn't match the network interface they're + arriving on. This has security advantages because it prevents the + so-called IP spoofing, however it can pose problems if you use + asymmetric routing (packets from you to a host take a different path + than packets from that host to you) or if you operate a non-routing + host which has several IP addresses on different interfaces. To turn + rp_filter off use: + + echo 0 > /proc/sys/net/ipv4/conf//rp_filter + or + echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter If unsure, say N here. @@ -2005,8 +2111,10 @@ CONFIG_IP_MULTIPLE_TABLES Normally, a router decides what to do with a received packet based solely on the packet's final destination address. If you say Y here, - routing can also take into account the originating address and the - network device from which the packet reached us. + the Linux router will also be able to take the packet's source + address into account. Furthermore, if you also say Y to "IP: use TOS + value as routing key" below, the TOS (Type-Of-Service) field of the + packet can be used for routing decisions as well. IP: equal cost multipath CONFIG_IP_ROUTE_MULTIPATH @@ -2022,10 +2130,9 @@ CONFIG_IP_ROUTE_TOS The header of every IP packet carries a TOS (Type of Service) value with which the packet requests a certain treatment, e.g. low latency - (for interactive traffic), high throughput, or high reliability. - Normally, these values are ignored, but if you say Y here, you will - be able to specify different routes for packets with different TOS - values. + (for interactive traffic), high throughput, or high reliability. If + you say Y here, you will be able to specify different routes for + packets with different TOS values. IP: verbose route monitoring CONFIG_IP_ROUTE_VERBOSE @@ -2044,7 +2151,8 @@ IP: fast network address translation CONFIG_IP_ROUTE_NAT If you say Y here, your router will be able to modify source and - destination addresses of packets that pass through it. + destination addresses of packets that pass through it, in a manner + you specify. IP: optimize as router not host CONFIG_IP_ROUTER @@ -2057,11 +2165,13 @@ Note that your box can only act as a router if you enable IP forwarding in your kernel; you can do that by saying Y to "/proc - filesystem support" and "Sysctl support" below and executing the line + filesystem support" and "Sysctl support" below and executing the + line echo "1" > /proc/sys/net/ipv4/ip_forward - at boot time after the /proc filesystem has been mounted. + at boot time after the /proc filesystem has been mounted. You can do + that even if you say N here. If unsure, say N here. @@ -2095,7 +2205,7 @@ echo "1" > /proc/sys/net/ipv4/ip_forward - at boot time after the /proc filesystem has been mounted. + at boot time after the /proc filesystem has been mounted. You need to say Y to "IP firewalling" in order to be able to use IP masquerading (masquerading means that local computers can chat with @@ -2131,10 +2241,10 @@ This enables automatic configuration of IP addresses of devices and of the routing table during kernel boot, based on either information supplied at the kernel command line or by BOOTP or RARP protocols. - You need to say Y only for diskless machines requiring network access - to boot (in which case you want to say Y to "Root file system on - NFS" as well), because all other machines configure the network in - their startup scripts. + You need to say Y only for diskless machines requiring network + access to boot (in which case you want to say Y to "Root file system + on NFS" as well), because all other machines configure the network + in their startup scripts. BOOTP support CONFIG_IP_PNP_BOOTP @@ -2144,7 +2254,7 @@ the BOOTP protocol (a special protocol designed for doing this job), say Y here. In case the boot ROM of your network card was designed for booting Linux and does BOOTP itself, providing all necessary - information on the kernel command line, you can say N here. If + information on the kernel command line, you can say N here. If unsure, say Y. Note that if you want to use BOOTP, a BOOTP server must be operating on your network. Read Documentation/nfsroot.txt for details. @@ -2201,7 +2311,7 @@ This enables your Linux firewall to transparently redirect any network traffic originating from the local network and destined for a remote host to a local server, called a "transparent proxy - server". This makes the local computers think they are talking to + server". This makes the local computers think they are talking to the remote end, while in fact they are connected to the local proxy. Redirection is activated by defining special input firewall rules (using the ipchains utility) and/or by doing an appropriate @@ -2233,7 +2343,7 @@ echo "1" > /proc/sys/net/ipv4/ip_forward - from a boot time script after the /proc filesystem has been mounted. + from a boot time script after the /proc filesystem has been mounted. Details on how to set things up are contained in the IP Masquerade mini-HOWTO, available via FTP (user: anonymous) from @@ -2244,33 +2354,55 @@ If you say Y here, you should also say Y to "IP: always defragment", below. - If you say Y here, then the modules ip_masq_ftp.o (for ftp transfers - through the firewall), ip_masq_irc.o (for irc chats through the - firewall), and ip_masq_raudio.o (for RealAudio downloads through the - firewall) will automatically be compiled. Modules are pieces of code - which can be inserted in and removed from the running kernel - whenever you want; read Documentation/modules.txt for details. + If you say Y here, then the modules ip_masq_ftp.o (for ftp file + transfers), ip_masq_irc.o (for irc chats), ip_masq_quake.o (you + guessed it), ip_masq_vdolive.o (for VDOLive video connections), + ip_masq_cuseeme.o (for CU-SeeMe broadcasts) and ip_masq_raudio.o + (for RealAudio downloads) will automatically be compiled. They are + needed to make masquerading for these protocols work. Modules are + pieces of code which can be inserted in and removed from the running + kernel whenever you want; read Documentation/modules.txt for + details. IP: ICMP masquerading CONFIG_IP_MASQUERADE_ICMP - The basic masquerade code described for "IP: masquerading" above only - handles TCP or UDP packets (and ICMP errors for existing - connections). This option adds additional support for masquerading + The basic masquerade code described for "IP: masquerading" above + only handles TCP or UDP packets (and ICMP errors for existing + connections). This option adds additional support for masquerading ICMP packets, such as ping or the probes used by the Windows 95 tracert program. If you want this, say Y. +IP: masquerading special modules support +CONFIG_IP_MASQUERADE_MOD + This provides support for special modules that can modify the + rewriting rules used when masquerading. Please not that this feature + adds a little overhead in the input packet processing chain. + + Examples of such modules are ipautofw (allowing the masquerading of + protocols which don't have their own protocol helpers) and port + forwarding (making an incoming port of a local computer visible + through the masquerading host). + + You will need the user space program "ipmasqadm" to use these + additional modules; you can download it from + http://juanjox.home.ml.org/ + + All this additional code is still under development and so is + currently marked EXPERIMENTAL. + + If you want to try, for example, PORT FORWARDING, say Y. + IP: ipautofw masquerade support (Experimental) CONFIG_IP_MASQUERADE_IPAUTOFW - ipautofw is a program by Richard Lynch allowing additional support - for masquerading protocols which do not (as yet) have their own - protocol helpers. Information and source for ipautofw is available - via FTP (user: anonymous) from + ipautofw is a program which allows the masquerading of protocols + which do not (as yet) have their own protocol helpers. Information + and source for ipautofw is available via FTP (user: anonymous) from ftp://ftp.netis.com/pub/members/rlynch/ - For 2.1 kernels, you will need "ipmasqadm" tool from - http://juanjox.home.ml.org + You will also need the ipmasqadm tool available from + http://juanjox.home.ml.org . The ipautofw code is still under development and so is currently marked EXPERIMENTAL. If you want to try it, say Y. @@ -2280,44 +2412,27 @@ The module will be called ip_masq_autofw.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -IP: masquerading special modules support -CONFIG_IP_MASQUERADE_MOD - This provides support for special modules that can modify rewriting - rules to achieve, for example, input port forwarding. - Beware that this feature adds a little overhead in the input packet - processing chain. - - You will need user space program "ipmasqadm" to use these - additional modules, you can download it from - http://juanjox.home.ml.org/ - - All this additional code is still under development and so is currently - marked EXPERIMENTAL. - - If you want to try, for example, PORT FORWARDING, say Y. - IP: ipportfw masquerade support CONFIG_IP_MASQUERADE_IPPORTFW - Port Forwarding is an addition to IP Masquerading written by Steven - Clarke to allow some forwarding of packets from outside to inside a - firewall on given ports. This could be useful if, for example, you - want to run a web server behind the firewall or masquerading host - and this web server should be visible to the outside world. An - external client connects to port 80 of the firewall, the firewall - forwards requests to this port to the web server, the web server - handles the request and the results are sent through the firewall to - the original client. The client thinks that the firewall machine - itself is running the web server. + Port Forwarding is an addition to IP Masquerading which allows some + forwarding of packets from outside to inside a firewall on given + ports. This could be useful if, for example, you want to run a web + server behind the firewall or masquerading host and this web server + should be visible to the outside world. An external client connects + to port 80 of the firewall, the firewall forwards requests to this + port to the web server, the web server handles the request and the + results are sent through the firewall to the original client. The + client thinks that the firewall machine itself is running the web + server. Information about it is available from http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to browse the WWW, you need to have access to a machine on the Internet - that has a program like lynx or netscape). You will need the user - space program "ipmasqadm" which can be downloaded from - http://juanjox.home.ml.org/ + that has a program like lynx or netscape). For general info, please + see ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/ - For general info, please see - ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/ + You will need the user space program "ipmasqadm" which can be + downloaded from http://juanjox.home.ml.org/ The portfw code is still under development and so is currently marked EXPERIMENTAL. If you want to try it, say Y. @@ -2329,9 +2444,9 @@ IP: ipmarkfw masquerade support CONFIG_IP_MASQUERADE_IPMARKFW - This provides functionally equivalent to port forwarding, the difference - is that Mark Forwarding uses "firewalling mark" to select which packets - must forward (see ipchains(8), "-m" argument). + This provides functionality equivalent to port forwarding, the + difference is that Mark Forwarding uses "firewalling mark" to select + which packets must forward (see ipchains(8), "-m" argument). The markfw code is still under development and so is currently marked EXPERIMENTAL. If you want to try it, say Y. @@ -2343,37 +2458,41 @@ IP: always defragment CONFIG_IP_ALWAYS_DEFRAG - This option means that all incoming fragments (= parts of IP packets + If you say Y here, then all incoming fragments (parts of IP packets that arose when some host between origin and destination decided - that the IP packets were too large and cut them into pieces) will be + that the packets were too large and cut them into pieces) will be reassembled (defragmented) before being processed, even if they are - about to be forwarded. + about to be forwarded. This option is highly recommended if you have said Y to "IP: masquerading" because that facility requires that second and further fragments can be related to TCP or UDP port numbers, which are only - stored in the first fragment. When using "IP: firewalling" support , - you might also want to say Y here, to have a more reliable firewall - (otherwise second and further fragments will always be accepted by - the firewall). When using "IP: transparent proxying", this option is - implicit, although it is safe to say Y here. Only say Y here if - running either a firewall that is the sole link to your network or a - transparent proxy; never ever say Y here for a normal router or - host. + stored in the first fragment. + + When using "IP: firewalling" support, you might also want to say Y + here, to have a more reliable firewall (otherwise second and further + fragments must be dealt with by the firewall, which can be tricky). + + When using "IP: transparent proxying", this option is implicit, + although it is safe to say Y here. + + Only say Y here if running either a firewall that is the sole link + to your network or a transparent proxy; never ever say Y here for a + normal router or host. IP: aliasing support CONFIG_IP_ALIAS Sometimes it is useful to give several IP addresses to a single - physical network interface (= serial port or Ethernet card). The - most common case is that you want to serve different WWW or ftp - documents to the outside according to which of your host names was - used to connect to you. This is called "multihosting" or "virtual - domains" or "virtual hosting services" and is explained in detail on - the WWW at http://www.thesphere.com/~dlp/TwoServers/ (to browse the - WWW, you need to have access to a machine on the Internet that has a - program like lynx or netscape) and also in the - Virtual-Hosting-HOWTO, available via FTP (user: anonymous) from - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + physical network interface (serial port or Ethernet card). The most + common case is that you want to serve different WWW or ftp documents + to the outside according to which of your host names was used to + connect to you. This is called "multihosting" or "virtual domains" + or "virtual hosting services" and is explained in detail on the WWW + at http://www.thesphere.com/~dlp/TwoServers/ (to browse the WWW, you + need to have access to a machine on the Internet that has a program + like lynx or netscape) and also in the Virtual-Hosting-HOWTO, + available via FTP (user: anonymous) from + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Another scenario would be that there are two logical networks living on your local Ethernet @@ -2400,27 +2519,31 @@ CONFIG_IP_PIMSM_V1 Kernel side support for Sparse Mode PIM (Protocol Independent Multicast) version 1. This multicast routing protocol is used widely - because Cisco supports it. You need special software to use it + because Cisco supports it. You need special software to use it (pimd-v1). Please see http://netweb.usc.edu/pim/ for more information about PIM (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or - netscape). Say Y if you want to use PIM-SM v1. Note that you can say - N here if you just want to use Dense Mode PIM. + netscape). + + Say Y if you want to use PIM-SM v1. Note that you can say N here if + you just want to use Dense Mode PIM. IP: PIM-SM version 2 support CONFIG_IP_PIMSM_V2 Kernel side support for Sparse Mode PIM version 2. In order to use this, you need an experimental routing daemon supporting it (pimd or - gated-5). This routing protocol is not used widely, so say N unless + gated-5). This routing protocol is not used widely, so say N unless you want to play with it. PC/TCP compatibility mode CONFIG_INET_PCTCP - If you have been having difficulties telnetting to your Linux machine - from a DOS system that uses (broken) PC/TCP networking software (all - versions up to OnNet 2.0) over your local Ethernet try saying Y - here. Everyone else says N. People having problems with NCSA telnet - should see the file linux/Documentation/networking/ncsa-telnet. + If you have been having difficulties telnetting to your Linux + machine from a DOS system that uses (broken) PC/TCP networking + software (all versions up to OnNet 2.0) over your local Ethernet try + saying Y here. Everyone else says N. + + People having problems with NCSA telnet should see the file + linux/Documentation/networking/ncsa-telnet. Reverse ARP server CONFIG_INET_RARP @@ -2431,9 +2554,9 @@ addresses. Diskless Sun 3 machines use this procedure at boot time, and diskless Linux boxes can be configured to do it as well. - If you want your Linux box to be able to *answer* such requests, say - Y here; you'll then have to run the program rarp ("man rarp") on - your box. + If you want your Linux box to be able to *answer* such requests, + answer Y here; you'll then have to run the program rarp ("man rarp") + on your box. If you actually want to use a diskless Sun 3 machine as an X terminal to Linux, say Y here and fetch Linux-Xkernel from @@ -2459,8 +2582,9 @@ Say Y if you are on a subnetted network with all machines connected by Ethernet segments only, as this option optimizes network access for this special case. If there are other connections, e.g. SLIP - links, between machines of your IP network, say N. If in doubt, say - N. The PATH mtu discovery facility will cover most cases anyway. + links, between machines of your IP network, say N. If in doubt, + answer N. The PATH mtu discovery facility will cover most cases + anyway. Path MTU Discovery (normally enabled) CONFIG_PATH_MTU_DISCOVERY @@ -2468,8 +2592,8 @@ over the net. "Path MTU Discovery" means that, instead of always sending very small chunks, we start out sending big ones and if we then discover that some host along the way likes its chunks smaller, - we adjust to a smaller size. This is good, so most people say - Y here. + we adjust to a smaller size. This is good, so most people say Y + here. However, some DOS software (versions of DOS NCSA telnet and Trumpet Winsock in PPP mode) is broken and won't be able to connect to your @@ -2481,37 +2605,39 @@ Disable NAGLE algorithm (normally enabled) CONFIG_TCP_NAGLE_OFF The NAGLE algorithm works by requiring an acknowledgment before - sending small IP frames (= packets). This keeps tiny telnet and - rlogin packets from congesting Wide Area Networks. Most people + sending small IP frames (packets). This keeps tiny telnet and + rlogin packets from congesting Wide Area Networks. Most people strongly recommend to say N here, thereby leaving NAGLE enabled. Those programs that would benefit from disabling this facility can do it on a per connection basis themselves. IP: Drop source routed frames CONFIG_IP_NOSR - Usually, the originator of an IP frame (= packet) specifies only the + Usually, the originator of an IP frame (packet) specifies only the destination, and the hosts along the way do the routing, i.e. they decide how to forward the frame. However, there is a feature of the IP protocol that allows to specify the full route for a given frame already at its origin. A frame with such a fully specified route is called "source routed". The question now is whether we should honour - these route requests when such frames arrive, or if we should - drop all those frames instead. Honouring them can introduce security - problems (and is rarely a useful feature), and hence it is recommended - that you say Y here unless you really know what you're doing. + these route requests when such frames arrive, or if we should drop + all those frames instead. Honouring them can introduce security + problems (and is rarely a useful feature), and hence it is + recommended that you say Y here unless you really know what you're + doing. -IP: Allow large windows (not recommended if <16Mb of memory) +IP: Allow large windows (not recommended if <16 MB of memory) CONFIG_SKB_LARGE On high speed, long distance networks the performance limit on - networking becomes the amount of data a machine can buffer until the - other end confirms its reception. (At 45Mbit/second there are a lot - of bits between New York and London ...). This option allows larger - amounts of data to be "in flight" at a given time. It also means a - user process can require a lot more memory for network buffers and - thus this option is best used only on machines with 16Mb of memory - or higher. Unless you are using long links with end to end speeds of - over 2Mbit a second or satellite links this option will make no - difference to performance. + networking becomes the amount of data the sending machine can buffer + until the other end confirms its reception. (At 45 Mbit/second there + are a lot of bits between New York and London ...). If you say Y + here, bigger buffers can be used which allows larger amounts of data + to be "in flight" at any given time. It also means a user process + can require a lot more memory for network buffers and thus this + option is best used only on machines with 16 MB of memory or higher. + Unless you are using long links with end to end speeds of over 2 + Mbit a second or satellite links this option will make no difference + to performance. Unix domain sockets CONFIG_UNIX @@ -2549,6 +2675,11 @@ given in Documentation/Changes. You will still be able to do regular IPv4 networking as well. + This protocol support is also available as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want). The module will be called ipv6.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + It is safe to say N here for now. IPv6: enable EUI-64 token format @@ -2612,12 +2743,12 @@ CONFIG_IPX_INTERN Every IPX network has an address that identifies it. Sometimes it is useful to give an IPX "network" address to your Linux box as well - (for example if your box is acting as a file server for different IPX - networks: it will then be accessible from everywhere using the same - address). The way this is done is to create a virtual internal + (for example if your box is acting as a file server for different + IPX networks: it will then be accessible from everywhere using the + same address). The way this is done is to create a virtual internal "network" inside your box and to assign an IPX address to this network. Say Y here if you want to do this; read the IPX-HOWTO at - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO for details. The full internal IPX network enables you to allocate sockets on different virtual nodes of the internal network. This is done by @@ -2625,13 +2756,14 @@ bind call. So applications should always initialize the node field to 0 when binding a socket on the primary network. In this case the socket is assigned the default node that has been given to the - kernel when the internal network was created. By enabling the full + kernel when the internal network was created. By enabling the full internal IPX network the cross-forwarding of packets targeted at 'special' sockets to sockets listening on the primary network is disabled. This might break existing applications, especially RIP/SAP daemons. A RIP/SAP daemon that works well with the full internal net - can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs. If you don't - know what you are doing, say N. + can be found on ftp://ftp.gwdg.de/pub/linux/misc/ncpfs. + + If you don't know what you are doing, say N. IPX: SPX networking (EXPERIMENTAL) CONFIG_SPX @@ -2683,7 +2815,7 @@ AppleTalk-IP driver support CONFIG_IPDDP This allows IP networking for users who only have AppleTalk - networking available. This feature is experimental. With this + networking available. This feature is experimental. With this driver, you can either encapsulate IP inside AppleTalk (e.g. if your Linux box is stuck on an AppleTalk only network) or decapsulate (e.g. if you want your Linux box to act as an Internet gateway for a @@ -2718,7 +2850,7 @@ Apple/Farallon LocalTalk PC card support CONFIG_LTPC This allows you to use the AppleTalk PC card to connect to LocalTalk - networks. The card is also known as the Farallon PhoneNet PC card. + networks. The card is also known as the Farallon PhoneNet PC card. If you are in doubt, this card is the one with the 65C02 chip on it. You also need version 1.3.3 or later of the netatalk package. This driver is experimental, which means that it may not work. @@ -2728,8 +2860,8 @@ CONFIG_COPS This allows you to use COPS AppleTalk cards to connect to LocalTalk networks. You also need version 1.3.3 or later of the netatalk - package. This driver is experimental, which means that it may not - work. This driver will only work if you choose "AppleTalk DDP" + package. This driver is experimental, which means that it may not + work. This driver will only work if you choose "AppleTalk DDP" networking support, above. Please read the file Documentation/networking/cops.txt. @@ -2746,15 +2878,16 @@ Amateur Radio support CONFIG_HAMRADIO - If you want to connect your Linux computer to an amateur radio, say - Y here. You want to read http://www.tapr.org/tapr/html/pkthome.html + If you want to connect your Linux box to an amateur radio, answer Y + here. You want to read http://www.tapr.org/tapr/html/pkthome.html (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape) and the HAM-HOWTO and the AX25-HOWTO, both available via FTP (user: anonymous) from - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that the answer to - this question won't directly affect the kernel: saying N will just - cause this configure script to skip all the questions about amateur - radio. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about amateur radio. Amateur Radio AX.25 Level 2 CONFIG_AX25 @@ -2815,7 +2948,7 @@ ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. You also might want to check out the file Documentation/networking/ax25.txt. More information about digital amateur radio in general is on the WWW at - http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you + http://www.tapr.org/tapr/html/pkthome.html (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). @@ -2836,7 +2969,7 @@ ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. You also might want to check out the file Documentation/networking/ax25.txt. More information about digital amateur radio in general is on the WWW at - http://www.tapr.org/tapr/html/pkthome.html (To browse the WWW, you + http://www.tapr.org/tapr/html/pkthome.html (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). @@ -2849,7 +2982,10 @@ CONFIG_MKISS KISS is a protocol used for the exchange of data between a computer and a Terminal Node Controller (a small embedded system commonly - used for networking over AX25 amateur radio connections). + used for networking over AX.25 amateur radio connections; it + connects the computer's serial port with the radio's microphone + input and speaker output). + Although KISS is less advanced than the 6pack protocol, it has the advantage that it is already supported by most modern TNCs without the need for a firmware upgrade. @@ -2900,15 +3036,15 @@ the AX25-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/. - This driver can operate multiple boards simultaneously. If you compile - it as a module (by saying M instead of Y), it will be called dmascc.o. - If you don't pass any parameter to the driver, all possible I/O - addresses are probed. This could irritate other devices that are - currently not in use. You may specify the list of addresses to be - probed by "dmascc=addr1,addr2,..." (when compiled into the kernel - image) or "io=addr1,addr2,..." (when loaded as a module). The network - interfaces will be called dmascc0 and dmascc1 for the board detected - first, dmascc2 and dmascc3 for the second one, and so on. + This driver can operate multiple boards simultaneously. If you + compile it as a module (by saying M instead of Y), it will be called + dmascc.o. If you don't pass any parameter to the driver, all + possible I/O addresses are probed. This could irritate other devices + that are currently not in use. You may specify the list of addresses + to be probed by "dmascc=addr1,addr2,..." (when compiled into the + kernel image) or "io=addr1,addr2,..." (when loaded as a module). The + network interfaces will be called dmascc0 and dmascc1 for the board + detected first, dmascc2 and dmascc3 for the second one, and so on. Before you configure each interface with ifconfig, you MUST set certain parameters, such as channel access timing, clock mode, and @@ -2984,7 +3120,7 @@ driver, "BAYCOM ser12 half duplex driver for AX.25" is the old driver and still provided in case this driver does not work with your serial interface chip. To configure the driver, use the sethdlc - utility available in the standard ax25 utilities package. For + utility available in the standard ax25 utilities package. For information on the modems, see http://www.baycom.de (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape) and @@ -2999,9 +3135,9 @@ CONFIG_BAYCOM_SER_HDX This is one of two drivers for Baycom style simple amateur radio modems that connect to a serial interface. The driver supports the - ser12 design in full duplex mode. This is the old driver. It is + ser12 design in full duplex mode. This is the old driver. It is still provided in case your serial interface chip does not work with - the full duplex driver. This driver is depreciated. To configure + the full duplex driver. This driver is depreciated. To configure the driver, use the sethdlc utility available in the standard ax25 utilities package. For information on the modems, see http://www.baycom.de (to browse the WWW, you need to have access to @@ -3016,9 +3152,9 @@ Sound card modem driver for AX.25 CONFIG_SOUNDMODEM This experimental driver allows a standard Sound Blaster or - WindowsSoundSystem compatible sound card to be used as a packet radio - modem (NOT as a telephone modem!), to send digital traffic over - amateur radio. + WindowsSoundSystem compatible sound card to be used as a packet + radio modem (NOT as a telephone modem!), to send digital traffic + over amateur radio. To configure the driver, use the sethdlc, smdiag and smmixer utilities available in the standard ax25 utilities package. For @@ -3039,8 +3175,8 @@ compatible cards. If you have a dual mode card (i.e. a WSS cards with a Sound Blaster emulation) you should say N here and Y to "Sound card modem support for WSS and Crystal cards", below, because - this usually results in better performance. This option also supports - SB16/32/64 in full duplex mode. + this usually results in better performance. This option also + supports SB16/32/64 in full duplex mode. Sound card modem support for WSS and Crystal cards CONFIG_SOUNDMODEM_WSS @@ -3054,15 +3190,16 @@ Sound card modem support for 1200 baud AFSK modulation CONFIG_SOUNDMODEM_AFSK1200 - This option enables the soundmodem driver 1200 baud AFSK modem, - compatible to popular modems using TCM3105 or AM7911. The demodulator - requires about 12% of the CPU power of a Pentium 75 CPU per channel. + This option enables the soundmodem driver 1200 baud AFSK modem, + compatible to popular modems using TCM3105 or AM7911. The + demodulator requires about 12% of the CPU power of a Pentium 75 CPU + per channel. Sound card modem support for 2400 baud AFSK modulation (7.3728MHz crystal) CONFIG_SOUNDMODEM_AFSK2400_7 This option enables the soundmodem driver 2400 baud AFSK modem, compatible to TCM3105 modems (over-)clocked with a 7.3728MHz - crystal. Note that the availability of this driver does _not_ imply + crystal. Note that the availability of this driver does _not_ imply that I recommend building such links. It is only here since users especially in eastern Europe have asked me to do so. In fact this modulation scheme has many disadvantages, mainly its incompatibility @@ -3097,7 +3234,7 @@ This option enables the soundmodem driver 4800 baud HAPN-1 compatible modem. This modulation seems to be widely used 'down under' and in the Netherlands. Here, nobody uses it, so I could not - test if it works. It is compatible to itself, however :-) + test if it works. It is compatible to itself, however :-) Sound card modem support for 9600 baud FSK G3RUH modulation CONFIG_SOUNDMODEM_FSK9600 @@ -3116,7 +3253,7 @@ (called "virtual circuits") to other computers connected to the X.25 network. Governments, banks, and other organizations tend to use it to connect to each other or to form Wide Area Networks (WANs). Many - countries have public X.25 networks. X.25 consists of two + countries have public X.25 networks. X.25 consists of two protocols: the higher level Packet Layer Protocol (PLP) (say Y here if you want that) and the lower level data link layer protocol LAPB (say Y to "LAPB Data Link Driver" below if you want that). @@ -3144,16 +3281,16 @@ LAPB Data Link Driver (EXPERIMENTAL) CONFIG_LAPB - Link Access Procedure, Balanced (LAPB) is the data link layer - (i.e. the lower) part of the X.25 protocol. It offers a reliable + Link Access Procedure, Balanced (LAPB) is the data link layer (i.e. + the lower) part of the X.25 protocol. It offers a reliable connection service to exchange data frames with one other host, and it is used to transport higher level protocols (mostly X.25 Packet - Layer, the higher part of X.25, but others are possible as - well). Usually, LAPB is used with specialized X.21 network cards, but - Linux currently supports LAPB only over Ethernet connections. If you - want to use LAPB connections over Ethernet, say Y here and to "LAPB - over Ethernet driver" below. Read - Documentation/networking/lapb-module.txt for technical details. + Layer, the higher part of X.25, but others are possible as well). + Usually, LAPB is used with specialized X.21 network cards, but Linux + currently supports LAPB only over Ethernet connections. If you want + to use LAPB connections over Ethernet, say Y here and to "LAPB over + Ethernet driver" below. Read + Documentation/networking/lapb-module.txt for technical details. If you want to compile this driver as a module though ( = code which can be inserted in and removed from the running kernel whenever you @@ -3225,16 +3362,6 @@ This is a backward compatibility option, choose Y for now. This option will be removed soon. -HIgh Performance Parallel Interface support (EXPERIMENTAL) -CONFIG_HIPPI - HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and - 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI - can run over copper (25m) or fiber (300m on multi-mode or 10km on - single-mode). If you are connected to a HIPPI network, and want - to enable HIPPI support in the kernel, say Y here (you must also - remember to enable the driver for your HIPPI card below). Most - people will say N here. - SCSI support? CONFIG_SCSI If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or @@ -3244,10 +3371,13 @@ because you will be asked for it. You also need to say Y here if you want support for the parallel - port version of the 100MB IOMEGA ZIP drive. + port version of the 100 MB IOMEGA ZIP drive. Please read the SCSI-HOWTO, available via FTP (user: anonymous) in - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. The + SCSI-Programming-HOWTO contains information about how to add or + remove an SCSI device from a running Linux machine without + rebooting. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -3261,9 +3391,9 @@ CONFIG_BLK_DEV_SD If you want to use a SCSI hard disk or the SCSI or parallel port version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO and the Disk-HOWTO, both available via FTP (user: - anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This is - NOT for SCSI CDROMs. + SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available via + FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + This is NOT for SCSI CDROMs. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -3292,8 +3422,8 @@ CONFIG_BLK_DEV_SR If you want to use a SCSI CDROM under Linux, say Y and read the SCSI-HOWTO and the CDROM-HOWTO from - sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also make sure to say Y or M - to "ISO 9660 CDROM filesystem support" later. + ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also make sure to say Y + or M to "ISO 9660 CDROM filesystem support" later. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -3316,11 +3446,11 @@ directly, so you need some additional software which knows how to talk to these devices using the SCSI protocol. For CD-writers, you would need the program cdwrite, available via FTP (user: anonymous) - from ftp://sunsite.unc.edu/pub/Linux/utils/disk-management; for other - devices, it's possible that you'll have to write the driver software - yourself, so have a look at the SCSI-HOWTO and at the + from ftp://sunsite.unc.edu/pub/Linux/utils/disk-management; for + other devices, it's possible that you'll have to write the driver + software yourself, so have a look at the SCSI-HOWTO and at the SCSI-Programming-HOWTO, both available via FTP (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -3334,7 +3464,7 @@ Unit Number), e.g. a CD jukebox, and only one LUN is detected, you can say Y here to force the SCSI driver to probe for multiple LUNs. A SCSI device with multiple LUNs acts logically like multiple SCSI - devices. The vast majority of SCSI devices have only one LUN, and + devices. The vast majority of SCSI devices have only one LUN, and so most people can say N here and should in fact do so, because it is safer. @@ -3342,24 +3472,30 @@ CONFIG_SCSI_CONSTANTS The error messages regarding your SCSI hardware will be easier to understand if you say Y here; it will enlarge your kernel by about - 12KB. If in doubt, say Y. + 12 KB. If in doubt, say Y. SCSI logging facility CONFIG_SCSI_LOGGING This turns on a logging facility that can be used to debug a number - of problems. Normally no logging output will appear, but you can - enable logging with a shell command like: + of SCSI related problems. + + If you say Y here, no logging output will appear by default, but you + can enable logging by saying Y to "/proc filesystem support" and + "Sysctl support" below and executing the command echo "scsi log token [level]" > /proc/scsi/scsi + at boot time after the /proc filesystem has been mounted. + There are a number of things that can be used for 'token' (you can find them in the source: drivers/scsi/scsi.c), and this allows you to select the types of information you want, and the level allows - you to select the level of verbosity. If you say N here, it may be - harder to track down some types of SCSI problems. If you say Y here - your kernel will be somewhat larger, but there should be no - noticeable performance impact as long as you have logging turned - off. + you to select the level of verbosity. + + If you say N here, it may be harder to track down some types of SCSI + problems. If you say Y here your kernel will be somewhat larger, but + there should be no noticeable performance impact as long as you have + logging turned off. AdvanSys SCSI support CONFIG_SCSI_ADVANSYS @@ -3389,7 +3525,7 @@ CONFIG_SCSI_AHA1542 This is support for a SCSI host adapter. It is explained in section 3.4 of the SCSI-HOWTO, available via FTP (user: anonymous) at - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that Trantor was + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that Trantor was recently purchased by Adaptec, and some former Trantor products are being sold under the Adaptec name. If it doesn't work out of the box, you may have to change some settings in drivers/scsi/aha1542.h. @@ -3422,10 +3558,10 @@ found by checking the help file for each of the available configuration options. You also want to read drivers/scsi/README.aic7xxx and the SCSI-HOWTO, available via FTP - (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note - that the AHA2920 SCSI host adapter is *not* supported by this + (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + Note that the AHA2920 SCSI host adapter is *not* supported by this driver; choose "Future Domain 16xx SCSI support" instead if you have - one of those. + one of those. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -3452,9 +3588,9 @@ Maximum number of commands per LUN CONFIG_AIC7XXX_CMDS_PER_LUN Specify the maximum number of commands you would like to allocate - per LUN (a LUN is a Logical Unit Number -- some physical SCSI devices, - e.g. CD jukeboxes, act logically as several separate units, each of - which gets its own number). + per LUN (a LUN is a Logical Unit Number -- some physical SCSI + devices, e.g. CD jukeboxes, act logically as several separate units, + each of which gets its own number). Reasonable figures are in the range of 14 to 32 commands per device, but depending on hardware could be increased or decreased from that @@ -3476,7 +3612,9 @@ small amount of overhead to each and every SCSI command the aic7xxx driver handles, so if you aren't really interested in this information, it is best to leave it disabled. This will only work if - you also say Y to "/proc filesystem support", below. If unsure, say N. + you also say Y to "/proc filesystem support", below. + + If unsure, say N. Delay in seconds after SCSI bus reset CONFIG_AIC7XXX_RESET_DELAY @@ -3496,12 +3634,12 @@ BusLogic SCSI support CONFIG_SCSI_BUSLOGIC This is support for BusLogic MultiMaster and FlashPoint SCSI Host - Adapters. Consult the SCSI-HOWTO, available via anonymous FTP from + Adapters. Consult the SCSI-HOWTO, available via anonymous FTP from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, and the files README.BusLogic and README.FlashPoint in drivers/scsi for more - information. If this driver does not work correctly without + information. If this driver does not work correctly without modification, please contact the author, Leonard N. Zubkoff, by - email to lnz@dandelion.com. + email to lnz@dandelion.com. You can also build this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -3512,18 +3650,18 @@ Omit BusLogic SCSI FlashPoint support CONFIG_SCSI_OMIT_FLASHPOINT This option allows you to omit the FlashPoint support from the - BusLogic SCSI driver. The FlashPoint SCCB Manager code is + BusLogic SCSI driver. The FlashPoint SCCB Manager code is substantial, so users of MultiMaster Host Adapters may wish to omit it. DTC3180/3280 SCSI support CONFIG_SCSI_DTC3280 - This is support for DTC 3180/3280 SCSI Host Adapters. Please read + This is support for DTC 3180/3280 SCSI Host Adapters. Please read the SCSI-HOWTO, available via FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO and the file - drivers/scsi/README.dtc3x80. + drivers/scsi/README.dtc3x80. - This driver is also available as a module (= code which can be + This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called dtc.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -3532,13 +3670,13 @@ CONFIG_SCSI_EATA_DMA This is support for the EATA-DMA protocol compliant SCSI Host Adapters like the SmartCache III/IV, SmartRAID controller families - and the DPT PM2011B and PM2012B controllers. Note that there is + and the DPT PM2011B and PM2012B controllers. Note that there is also another driver for the same hardware: "EATA ISA/EISA/PCI support". You should only say Y to one of them. Please read the SCSI-HOWTO, available via FTP (user: anonymous) at - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. - This driver is also available as a module (= code which can be + This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called eata_dma.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -3549,9 +3687,9 @@ Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant host adapters could also use this driver but are discouraged from doing so, since this driver only supports hard disks and lacks - numerous features. You might want to have a look at the SCSI-HOWTO, + numerous features. You might want to have a look at the SCSI-HOWTO, available via FTP (user: anonymous) at - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -3563,11 +3701,11 @@ This is support for the UltraStor 14F and 34F SCSI-2 host adapters. The source at drivers/scsi/u14-34f.c contains some information about this hardware. If the driver doesn't work out of the box, you may - have to change some settings in drivers/scsi/u14-34f.c. Read the + have to change some settings in drivers/scsi/u14-34f.c. Read the SCSI-HOWTO, available via FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that there is also another driver for the same hardware: "UltraStor SCSI support", - below. You should say Y to both only if you want 24F support as + below. You should say Y to both only if you want 24F support as well. This driver is also available as a module ( = code which can be @@ -3595,7 +3733,7 @@ other adapters based on the Future Domain chipsets (Quantum ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board). It is explained in section 3.7 of the SCSI-HOWTO, available via FTP - (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -3660,13 +3798,13 @@ allow DISCONNECT CONFIG_SCSI_NCR53C7xx_DISCONNECT This enables the disconnect/reconnect feature of the NCR SCSI - controller. When you say Y here, a slow SCSI device will not lock + controller. When you say Y here, a slow SCSI device will not lock the SCSI bus while processing a request, allowing simultaneous use of e.g. a SCSI hard disk and SCSI tape or CD-ROM drive, and providing much better performance when using slow and fast SCSI devices at the same time. Some devices, however, do not operate properly with this option enabled, and will cause your SCSI system - to hang, which might cause a system crash. The safe answer + to hang, which might cause a system crash. The safe answer therefore is to say N. NCR53C8XX SCSI support @@ -3676,7 +3814,7 @@ tagged command queuing and fast synchronous data transfers up to 80 MB/s with wide FAST-40 LVD devices and controllers. - The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 + The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 supports FAST-40 transfers with Ultra2 LVD devices. Please read drivers/scsi/README.ncr53c8xx for more information. @@ -3729,7 +3867,7 @@ device of yours to not support properly the target-disconnect feature. In that case, you would say Y here. In general however, to not allow targets to disconnect is not reasonable if there is more - than 1 device on a SCSI bus. The normal answer therefore is N. + than 1 device on a SCSI bus. The normal answer therefore is N. default tagged command queue depth CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS @@ -3740,12 +3878,12 @@ this feature, enter 0 or 1 here (it doesn't matter which). The default value is 8 and should be supported by most hard disks. - This option has no effect for adapters with NVRAM, since the driver - will get this information from the user set-up. It also can be + This option has no effect for adapters with NVRAM, since the driver + will get this information from the user set-up. It also can be overridden using a boot setup option, as follows (example): - 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to 4, - set queue depth to 16 for target 2 and target 3 on controller 0 and - set queue depth to 10 for target 0 / lun 2 on controller 1. + 'ncr53c8xx=tags:4/t2t3q16/t0u2q10' will set default queue depth to + 4, set queue depth to 16 for target 2 and target 3 on controller 0 + and set queue depth to 10 for target 0 / lun 2 on controller 1. The normal answer therefore is to go with the default 8 and to use a boot command line option for devices that need to use a different @@ -3757,14 +3895,15 @@ CONFIG_SCSI_NCR53C8XX_MAX_TAGS This option allows you to specify the maximum number of commands that can be queued to any device, when tagged command queuing is - possible. The default value is 32. Minimum is 2, maximum is 64. - For value less than 32, this option only saves a little memory - (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it. - For value greater than 32, latency on reselection will be increased - by 1 or 2 micro-seconds. So, the normal answer here is to go with the - default value 32 unless you are using very large hard disks with - large cache (>= 1MB) that are able to take advantage of more than - 32 tagged commands. + possible. The default value is 32. Minimum is 2, maximum is 64. For + value less than 32, this option only saves a little memory + (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it. For + value greater than 32, latency on reselection will be increased by 1 + or 2 micro-seconds. + + So, the normal answer here is to go with the default value 32 unless + you are using very large hard disks with large cache (>= 1 MB) that + are able to take advantage of more than 32 tagged commands. There is no safe option and the default answer is recommended. @@ -3798,8 +3937,8 @@ IBMMCA SCSI support CONFIG_SCSI_IBMMCA This is support for the IBM SCSI adapter found in many of the PS/2 - series computers. These machines have an MCA bus, so you need to say - Y to "MCA support" as well and read Documentation/mca.txt. + series computers. These machines have an MCA bus, so you need to + answer Y to "MCA support" as well and read Documentation/mca.txt. If the adapter isn't found during boot (a common problem for models 56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=' kernel @@ -3840,14 +3979,14 @@ assignment of hard disks as seen from e.g. DOS or OS/2 on your machine, which is in addition conformant to the SCSI-standard, you must say Y here. This is also necessary for MCA-Linux users who want - to keep downward- compatibility to older releases of the + to keep downward compatibility to older releases of the IBM-MCA-SCSI-driver (older than driver-release 2.00 and older than June 1997). If you like to have the lowest SCSI-id assigned as drive C:, as modern SCSI-BIOSes do, which does not conform to the standard, but is widespread and common in the PC-world of today, you must say N - here. If unsure, say Y. + here. If unsure, say Y. Reset SCSI-devices at boot time CONFIG_IBMMCA_SCSI_DEV_RESET @@ -3926,8 +4065,8 @@ Qlogic FastSCSI! cards as well as any other card based on the FASXX chip (including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards); it does NOT support the PCI version. The PCI versions are supported by - the Qlogic ISP driver though. Information about this driver is - contained in drivers/scsi/README.qlogicfas. You should also read + the Qlogic ISP driver though. Information about this driver is + contained in drivers/scsi/README.qlogicfas. You should also read the SCSI-HOWTO, available via FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. @@ -3940,12 +4079,13 @@ CONFIG_SCSI_QLOGIC_ISP This driver works for all QLogic PCI SCSI host adapters (IQ-PCI, IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter - card is supported by the "AM53/79C974 PCI SCSI" driver). If you say - Y here, make sure to say Y to "PCI BIOS support" as well. More - information is contained in the file - drivers/scsi/README.qlogicisp. You should also read the SCSI-HOWTO, - available via FTP (user: anonymous) at - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + card is supported by the "AM53/79C974 PCI SCSI" driver). + + If you say Y here, make sure to say Y to "PCI BIOS support" as well. + + Please read the file drivers/scsi/README.qlogicisp. You should also + read the SCSI-HOWTO, available via FTP (user: anonymous) at + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4000,7 +4140,7 @@ 7000FASST SCSI support CONFIG_SCSI_7000FASST This driver supports the Western Digital 7000 SCSI host adapter - family. Some information is in the source: drivers/scsi/wd7000.c. + family. Some information is in the source: drivers/scsi/wd7000.c. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -4010,12 +4150,12 @@ EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support CONFIG_SCSI_EATA This driver supports all the EATA/DMA-compliant SCSI host adapters - and does not need any BIOS32 service. DPT ISA and all EISA i/o + and does not need any BIOS32 service. DPT ISA and all EISA i/o addresses are probed looking for the "EATA" signature. If you said Y to "PCI BIOS support", the addresses of all the PCI SCSI controllers - reported by BIOS32 are probed as well. You want to read - the start of drivers/scsi/eata.c and the SCSI-HOWTO, available via - FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + reported by BIOS32 are probed as well. You want to read the start of + drivers/scsi/eata.c and the SCSI-HOWTO, available via FTP (user: + anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that there is also another driver for the same hardware available: "EATA-DMA support". You should say Y to only one of them. @@ -4051,7 +4191,7 @@ This is support for the NCR53c406a SCSI host adapter. For user configurable parameters, check out drivers/scsi/NCR53c406.c in the kernel source. Also read the SCSI-HOWTO, available via FTP (user: - anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -4060,31 +4200,32 @@ Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support CONFIG_SCSI_DC390T - This driver supports PCI SCSI host adapters based on the Am53C974A - chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard + This driver supports PCI SCSI host adapters based on the Am53C974A + chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard PCscsi/PCnet (Am53/79C974) solutions. + Documentation can be found in linux/drivers/scsi/README.tmscsim. - Note that this driver does NOT support Tekram DC390W/U/F, which are - based on NCR/Symbios chips. Use the NCR53C8XX driver for those. - Also note, that there is another generic Am53C974 driver. + Note that this driver does NOT support Tekram DC390W/U/F, which are + based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. + Also note that there is another generic Am53C974 driver. If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be called tmscsim.o. -Skip support for other Am53/79C974 based SCSI adapters +Omit support for other Am53/79C974 based SCSI adapters CONFIG_SCSI_DC390T_NOGENSUPP - Normally, the DC390(T) SCSI driver relies on the DC390 EEPROM to get - initial values for its settings, such as speed, termination, etc. - If it can't find this EEPROM, it will use defaults or the user - supplied boot/module parameters. For details on driver configuration - see linux/drivers/scsi/README.tmscsim. - - With this option set, if no EEPROM is found, the driver gives up and - thus only supports Tekram DC390(T) adapters. This can be useful if - you have a DC390(T) and another Am53C974 based adapter, which, for + If you say N here, the DC390(T) SCSI driver relies on the DC390 + EEPROM to get initial values for its settings, such as speed, + termination, etc. If it can't find this EEPROM, it will use defaults + or the user supplied boot/module parameters. For details on driver + configuration see linux/drivers/scsi/README.tmscsim. + + If you say Y here and if no EEPROM is found, the driver gives up and + thus only supports Tekram DC390(T) adapters. This can be useful if + you have a DC390(T) and another Am53C974 based adapter, which, for some reason, you want to drive with the other AM53C974 driver. If unsure, say N. @@ -4096,8 +4237,8 @@ available via FTP (user: anonymous) at ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO, is for you. - Note that there is another driver for AM53C974 based adapters: The - Tekram DC390(T) driver. + Note that there is another driver for AM53C974 based adapters: + "Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support", above. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -4118,7 +4259,7 @@ IOMEGA Parallel Port ZIP drive SCSI support CONFIG_SCSI_PPA This driver supports the parallel port version of IOMEGA's ZIP drive - (a 100Mb removable media device). For more information about this + (a 100 MB removable media device). For more information about this driver and how to use it you should read the file drivers/scsi/README.ppa. You should also read the SCSI-HOWTO, which is available via FTP (user: anonymous) from @@ -4141,17 +4282,13 @@ EPP (Enhanced Parallel Port) is a standard for parallel ports which allows them to act as expansion buses that can handle up to 64 peripheral devices. Some parallel port chipsets are slower than - their motherboard, and so we have to control the state of the FIFO - every now and then to avoid data loss. The permitted values for - this option are 0 (don't check FIFO), 1 (check FIFO every 4 bytes), - 2 (check FIFO every other byte) and 3 (check FIFO every time). If - your EPP chipset is from the SMC series, you are likely to have to - set this value greater than 0. - -SGI wd93 Scsi Driver -CONFIG_SCSI_SGIWD93 - This is the SCSI driver for WD33C93 / WD33C95 SCSI chips used in many - SGI machines. + their motherboard, and so we have to control the state of the + chipset's FIFO queue every now and then to avoid data loss. This + will be done if you say Y here. + + If your EPP chipset is from the SMC series, you are likely to have + to say Y here. Generally, saying Y is the safe option and slows + things down a bit. SCSI Debug host simulator. CONFIG_SCSI_DEBUG @@ -4175,18 +4312,18 @@ Sun SOC CONFIG_FC4_SOC - Serial Optical Channel is an interface card with one or two Fibre Optic - ports, each of which can be connected to a disk array. Only the SBus - incarnation of the adapter is supported at the moment. + Serial Optical Channel is an interface card with one or two Fibre + Optic ports, each of which can be connected to a disk array. Only + the SBus incarnation of the adapter is supported at the moment. SparcSTORAGE Array 100 and 200 series CONFIG_SCSI_PLUTO - If you never bought a disk array made by Sun, go with N. + If you never bought a disk array made by Sun, go with N. AcornSCSI support CONFIG_SCSI_ACORNSCSI_3 - This enables support for the Acorn SCSI card (aka30). If you have an - Acorn system with one of these, say Y. If unsure, say N. + This enables support for the Acorn SCSI card (aka30). If you have an + Acorn system with one of these, say Y. If unsure, say N. Acorn SCSI tagged queue support CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE @@ -4199,42 +4336,42 @@ Acorn SCSI Synchronous transfers support CONFIG_SCSI_ACORNSCSI_SYNC - Say Y here to enable synchronous transfer negotiation with all targets - on the Acorn SCSI card. + Say Y here to enable synchronous transfer negotiation with all + targets on the Acorn SCSI card. In general, this improves performance; however some SCSI devices don't implement it properly, so the safe answer is N. Oak SCSI support CONFIG_SCSI_OAK1 - This enables support for the Oak SCSI card. If you have an Acorn system - with one of these, say Y. If unsure, say N. + This enables support for the Oak SCSI card. If you have an Acorn + system with one of these, say Y. If unsure, say N. Cumana SCSI I support CONFIG_SCSI_CUMANA_1 - This enables support for the Cumana SCSI I card. If you have an Acorn - system with one of these, say Y. If unsure, say N. + This enables support for the Cumana SCSI I card. If you have an + Acorn system with one of these, say Y. If unsure, say N. Cumana SCSI II support CONFIG_SCSI_CUMANA_2 - This enables support for the Cumana SCSI II card. If you have an Acorn - system with one of these, say Y. If unsure, say N. + This enables support for the Cumana SCSI II card. If you have an + Acorn system with one of these, say Y. If unsure, say N. EcoSCSI support CONFIG_SCSI_ECOSCSI - This enables support for the EcoSCSI card -- a small card that sits in - the Econet socket. If you have an Acorn system with one of these, - say Y. If unsure, say N. + This enables support for the EcoSCSI card -- a small card that sits + in the Econet socket. If you have an Acorn system with one of these, + say Y. If unsure, say N. EESOX SCSI support CONFIG_SCSI_EESOXSCSI - This enables support for the EESOX SCSI card. If you have an Acorn + This enables support for the EESOX SCSI card. If you have an Acorn system with one of these, say Y, otherwise say N. Powertec SCSI support CONFIG_SCSI_POWERTECSCSI - This enables support for the Powertec SCSI card on Acorn systems. If - you have one of these, say Y. If unsure, say N. + This enables support for the Powertec SCSI card on Acorn systems. If + you have one of these, say Y. If unsure, say N. Network device support? CONFIG_NETDEVICES @@ -4255,8 +4392,8 @@ you want to use under Linux (make sure you know its name because you will be asked for it and read the Ethernet-HOWTO (especially if you plan to use more than one network card under Linux), available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you want to use - SLIP (Serial Line Internet Protocol is the protocol used to send + ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you want to + use SLIP (Serial Line Internet Protocol is the protocol used to send Internet traffic over telephone lines or null modem cables) or CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better and newer replacement for SLIP) or PLIP (Parallel Line Internet Protocol @@ -4266,7 +4403,7 @@ Make sure to read the NET-2-HOWTO. Eventually, you will have to read Olaf Kirch's excellent and free book "Network Administrator's - Guide", to be found in sunsite.unc.edu:/pub/Linux/docs/LDP. If + Guide", to be found in ftp://sunsite.unc.edu:/pub/Linux/docs/LDP. If unsure, say Y. Dummy net driver support @@ -4293,10 +4430,11 @@ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to connect to your Internet service provider or to connect to some other local Unix box or if you want to configure your Linux box as a - Slip/CSlip server for other people to dial in. SLIP (Serial Line - Internet Protocol) is a protocol used to send Internet traffic - over telephone lines or serial cables (also known as - null modems); nowadays, the PPP is a more common protocol than SLIP. + Slip/CSlip server for other people to dial in. SLIP (Serial Line + Internet Protocol) is a protocol used to send Internet traffic over + serial connections such as telephone lines or null modem cables; + nowadays, the protocol PPP is more commonly used for this same + purpose. Normally, your access provider has to support SLIP in order for you to be able to use it, but there is now a SLIP emulator called SLiRP @@ -4313,7 +4451,7 @@ http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape)). SLIP support will enlarge - your kernel by about 4kB. If unsure, say N. + your kernel by about 4 KB. If unsure, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -4325,9 +4463,9 @@ CONFIG_SLIP_COMPRESSED This protocol is faster than SLIP because it uses compression on the TCP/IP headers (not on the data itself), but it has to be supported - on both ends. Ask your access provider if you are not sure and say - Y, just in case. You will still be able to use plain SLIP. If you - plan to use SLiRP, the SLIP emulator (available via FTP (user: + on both ends. Ask your access provider if you are not sure and + answer Y, just in case. You will still be able to use plain SLIP. If + you plan to use SLiRP, the SLIP emulator (available via FTP (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/system/network/serial/) which allows you to use SLIP over a regular dial up shell connection, you @@ -4371,9 +4509,9 @@ To use PPP, you need an additional program called pppd as described in Documentation/networking/ppp.txt and in the PPP-HOWTO, available - from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you upgrade from an - older kernel, you might need to upgrade pppd as well. The PPP option - enlarges your kernel by about 16kB. + from ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you upgrade + from an older kernel, you might need to upgrade pppd as well. The + PPP option enlarges your kernel by about 16 KB. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4404,13 +4542,13 @@ STRIP (Metricom Starmode radio IP) CONFIG_STRIP Say Y if you have a Metricom radio and intend to use Starmode Radio - IP. STRIP is a radio protocol developed for the MosquitoNet project + IP. STRIP is a radio protocol developed for the MosquitoNet project (On the WWW at http://mosquitonet.stanford.edu/; to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape) to send Internet traffic using - Metricom radios. Metricom radios are small, battery powered, + Metricom radios. Metricom radios are small, battery powered, 100kbit/sec packet radio transceivers, about the size and weight of - a cellular telephone. (You may also have heard them called + a cellular telephone. (You may also have heard them called "Metricom modems" but we avoid the term "modem" because it misleads many people into thinking that you can plug a Metricom modem into a phone line and use it as a modem.) @@ -4458,7 +4596,7 @@ which allows you to open an LAPB point-to-point connection to some other computer on your Ethernet network. In order to do this, you need to say Y or M to the driver for your Ethernet card as well as - to "LAPB Data Link Driver". + to "LAPB Data Link Driver". If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -4495,8 +4633,8 @@ CONFIG_HFMODEM_WSS This option enables the hfmodem driver to use WindowsSoundSystem compatible cards. These cards feature a codec chip from either - Analog Devices (such as AD1848, AD1845) or Crystal - Semiconductors (such as CS4248, CS423x). + Analog Devices (such as AD1848, AD1845) or Crystal Semiconductors + (such as CS4248, CS423x). PLIP (parallel port) support CONFIG_PLIP @@ -4504,9 +4642,9 @@ reasonably fast mini network consisting of two (or, rarely, more) local machines. A PLIP link from a Linux box is a popular means to install a Linux distribution on a machine which doesn't have a CDROM - drive (a minimal system has to be transferred with floppies - first). The kernels on both machines need to have this PLIP option - enabled for this to work. + drive (a minimal system has to be transferred with floppies first). + The kernels on both machines need to have this PLIP option enabled + for this to work. The PLIP driver has two modes, mode 0 and mode 1. The parallel ports (the connectors at the computers with 25 holes) are connected with @@ -4527,9 +4665,9 @@ NET-2-HOWTO in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Note that the PLIP protocol was changed and this PLIP driver won't work together with the PLIP support in Linux versions 1.0.x. This option - enlarges your kernel by about 8kB. + enlarges your kernel by about 8 KB. - If you want to compile this as a module (= code which can be + If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called @@ -4539,8 +4677,8 @@ CONFIG_EQUALIZER If you have two serial connections to some other computer (this usually requires two modems and two telephone lines) and you use - SLIP (= the protocol for sending Internet traffic over telephone - lines) or PPP (= a better SLIP) on them, you can make them behave + SLIP (the protocol for sending Internet traffic over telephone + lines) or PPP (a better SLIP) on them, you can make them behave like one double speed connection using this driver. Naturally, this has to be supported at the other end as well, either with a similar EQL Linux driver or with a Livingston Portmaster 2e. Say Y if you @@ -4565,8 +4703,8 @@ to the device tap0; everything the kernel wants to send out over the device tap0 can instead be read by the user from /dev/tap0: the user mode program replaces the LAN that would be attached to an ordinary - Ethernet device. Please read the file - Documentation/networking/ethertap.txt for more information. + Ethernet device. Please read the file + Documentation/networking/ethertap.txt for more information. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4639,7 +4777,7 @@ AUN over UDP CONFIG_ECONET_AUNUDP - Say Y here if you want to send Econet/AUN traffic over a a UDP + Say Y here if you want to send Econet/AUN traffic over a UDP connection (UDP is a packet based protocol that runs on top of the Internet protocol IP) using an ordinary Ethernet network card. @@ -4669,7 +4807,7 @@ WAN routing support is always built as a module ( = code which can be inserted in and removed from the running kernel whenever you - want). The module is called wanrouter.o. For general information + want). The module is called wanrouter.o. For general information about modules read Documentation/modules.txt. Fast switching (read help!) @@ -4695,7 +4833,7 @@ 8390 can be found at ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). Really, this option is applicable to any machine attached to a fast enough - network, and even a 10Mb NIC is able to kill a not very slow box, + network, and even a 10 Mb NIC is able to kill a not very slow box, such as a 120MHz Pentium. However, do not say Y here if you did not experience any serious @@ -4712,20 +4850,20 @@ When the kernel has several packets to send out over the network devices, it has to make a decision which one to send first. This is especially important if some of the network devices are real time - devices that need a certain minimum data flow rate. There are + devices that need a certain minimum data flow rate. There are several different algorithms for how to do this "fairly"; they are - called packet schedulers. You can attach different schedulers to - different network devices. If you want to stick to the default + called packet schedulers. If you want to stick to the default scheduling algorithm, say N here. If you want to experiment with a - couple of different algorithms, say Y. Currently, this is only + couple of different algorithms, say Y. You can then attach different + schedulers to different network devices. Currently, this is only recommended for experts. To administer these schedulers, you'll need the user-level utilities from the package iproute2+tc at ftp://ftp.inr.ac.ru/ip-routing/ If you say Y here and to "/proc filesystem" below, you will be able - to read status information about priority schedulers from - the file /proc/net/psched. + to read status information about priority schedulers from the file + /proc/net/psched. The available schedulers are listed in the following questions; you can say Y to as many as you like. If unsure, say N now. @@ -4873,24 +5011,25 @@ performance will be written to /proc/net/profile. If you don't know what it is about, you don't need it: say N. -#Comtrol Hostess SV-11 support -#CONFIG_HOSTESS_SV11 -### -### I don't know what this is. -### +Comtrol Hostess SV-11 support +CONFIG_HOSTESS_SV11 + This is a network card for high speed synchronous serial links. It + is commonly used to connect to Cisco equipment over HSSI links. At + this point, the driver can only be compiled as a module. WAN Drivers CONFIG_WAN_DRIVERS Say Y to this option if your Linux box contains a WAN card and you - are planning to use the box as a WAN ( = Wide Area Network) router + are planning to use the box as a WAN ( = Wide Area Network) router ( = device used to interconnect local area networks over wide area - communication links, such as leased lines and public data networks, - e.g. X.25 and frame relay) and you will be offered a list of drivers + communication links, such as leased lines or public data networks, + e.g. X.25 or frame relay) and you will be offered a list of drivers for WAN cards currently available. For more information, read - Documentation/networking/wan-router.txt. Note that the answer to - this question won't directly affect the kernel: saying N will just - cause this configure script to skip all the questions about WAN - card drivers. If unsure, say N. + Documentation/networking/wan-router.txt. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about WAN card drivers. If unsure, say N. Sangoma WANPIPE(tm) multiprotocol cards CONFIG_VENDOR_SANGOMA @@ -4898,12 +5037,12 @@ browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape) is a family of intelligent multiprotocol WAN adapters with data transfer rates up to T1 (1.544 - Mbps). They are also known as Synchronous Data Link Adapters (SDLA) + Mbps). They are also known as Synchronous Data Link Adapters (SDLA) and designated S502E(A), S503 or S508. These cards support the X.25, Frame Relay, and PPP protocols. If you have one or more of these - cards, say Y to this option and read - Documentation/networking/wanpipe.txt. The next questions will ask - you about the protocols you want the driver to support. + cards, say Y to this option; you may then also want to read the file + Documentation/networking/wanpipe.txt. The next questions will ask + you about the protocols you want the driver to support. The driver will be compiled as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4912,8 +5051,8 @@ Maximum number of cards CONFIG_WANPIPE_CARDS - Enter number of WANPIPE adapters installed in your machine. The - driver can support up to 8 cards. You may enter more than you + Enter number of WANPIPE adapters installed in your machine. The + driver can support up to 8 cards. You may enter more than you actually have if you plan to add more cards in the future without re-compiling the driver, but remember that in this case you'll waste some kernel memory (about 1K per card). @@ -4923,15 +5062,15 @@ Say Y to this option if you are planning to connect a WANPIPE card to an X.25 network. You should then also have said Y to "CCITT X.25 Packet Layer" and "LAPB Data Link Driver", above. If you say N, the - X.25 support will not be included in the driver (saves about 16K of - kernel memory). + X.25 support will not be included in the driver (saves about 16 KB + of kernel memory). WANPIPE Frame Relay support CONFIG_WANPIPE_FR Say Y to this option if you are planning to connect a WANPIPE card to a frame relay network. You should then also have said Y to "Frame Relay (DLCI) support", above. If you say N, the frame relay - support will not be included in the driver (saves about 16K of + support will not be included in the driver (saves about 16 KB of kernel memory). WANPIPE PPP support @@ -4940,7 +5079,7 @@ to a leased line using Point-to-Point protocol (PPP). You should then also have said Y to "PPP (point-to-point) support", above. If you say N, the PPP support will not be included in the driver (saves - about 16K of kernel memory). + about 16 KB of kernel memory). Ethernet (10 or 100Mbit) CONFIG_NET_ETHERNET @@ -4980,8 +5119,8 @@ Sun Intel Ethernet support CONFIG_SUN_INTEL - This is support for the Intel Ethernet cards on some Sun workstations - (all those with a network interface 'ie0' under SunOS). + This is support for the Intel Ethernet cards on some Sun + workstations (all those with a network interface 'ie0' under SunOS). Western Digital/SMC cards CONFIG_NET_VENDOR_SMC @@ -5042,7 +5181,7 @@ CONFIG_ULTRA32 If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available via FTP (user: anonymous) in - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -5069,8 +5208,9 @@ PCI NE2000 support CONFIG_NE2K_PCI This driver is for NE2000 compatible PCI cards. It will not work - with ISA NE2000 cards. If you have a PCI NE2000 network (Ethernet) - card, say Y and read the Ethernet-HOWTO, available via FTP (user: + with ISA NE2000 cards (they have their own driver, "NE2000/NE1000 + support" below). If you have a PCI NE2000 network (Ethernet) card, + say Y and read the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This driver is also available as a module ( = code which can be @@ -5257,8 +5397,8 @@ CONFIG_VORTEX If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) or "Boomerang" series (EtherLink XL 3c900 or 3c905) network - (Ethernet) card, say Y and read the Ethernet-HOWTO, available via FTP - (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + (Ethernet) card, say Y and read the Ethernet-HOWTO, available via + FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. More specific information is in Documentation/networking/vortex.txt and in the comments at the beginning of drivers/net/3c59x.c. @@ -5287,9 +5427,9 @@ (arguably) beautiful poetry in Documentation/networking/arcnet.txt. You need both this driver, and the driver for the particular ARCnet - chipset of your card. If you don't know, then it's probably a - COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset support" - below. + chipset of your card. If you don't know, then it's probably a + COM90xx type card, so say Y (or M) to "ARCnet COM90xx chipset + support" below. You might also want to have a look at the Ethernet-HOWTO, available via FTP (user: anonymous) in @@ -5305,25 +5445,25 @@ Enable arc0e (ARCnet "ether-encap" packet format) CONFIG_ARCNET_ETH This allows you to use "Ethernet encapsulation" with your ARCnet - card via the virtual arc0e device. You only need arc0e if you want + card via the virtual arc0e device. You only need arc0e if you want to talk to nonstandard ARCnet software, specifically, - DOS/Windows-style "NDIS" drivers. You do not need to say Y here to + DOS/Windows-style "NDIS" drivers. You do not need to say Y here to communicate with industry-standard RFC1201 implementations, like the - arcether.com packet driver or most DOS/Windows ODI drivers. RFC1201 - is included automatically as the arc0 device. Please read the + arcether.com packet driver or most DOS/Windows ODI drivers. RFC1201 + is included automatically as the arc0 device. Please read the ARCnet documentation in Documentation/networking/arcnet.txt for more information about using arc0e and arc0s. Enable arc0s (ARCnet RFC1051 packet format) CONFIG_ARCNET_1051 This allows you to use RFC1051 with your ARCnet card via the virtual - arc0s device. You only need arc0s if you want to talk to ARCnet + arc0s device. You only need arc0s if you want to talk to ARCnet software complying with the "old" standard, specifically, the DOS arcnet.com packet driver, Amigas running AmiTCP, and some variants - of NetBSD. You do not need to say Y here to communicate with + of NetBSD. You do not need to say Y here to communicate with industry-standard RFC1201 implementations, like the arcether.com - packet driver or most DOS/Windows ODI drivers. RFC1201 is included - automatically as the arc0 device. Please read the ARCnet + packet driver or most DOS/Windows ODI drivers. RFC1201 is included + automatically as the arc0 device. Please read the ARCnet documentation in Documentation/networking/arcnet.txt for more information about using arc0e and arc0s. @@ -5343,7 +5483,7 @@ CONFIG_ARCNET_COM90xxIO This is the chipset driver for the COM90xx cards, using them in IO-mapped mode instead of memory-mapped mode. This is slower than - the normal driver. Only use it if your card doesn't support shared + the normal driver. Only use it if your card doesn't support shared memory. This driver is also available as a module ( = code which can be @@ -5533,7 +5673,13 @@ If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. Many Ethernet cards - without a specific driver are compatible with NE2000. + without a specific driver are compatible with NE2000. + + If you have a PCI NE2000 card however, say N here and Y to "PCI + NE2000 support", above. If you have a NE2000 card and are running on + an MCA system (a bus system used on some IBM PS/2 computers and + laptops), say N here and Y to "NE/2 (ne2000 MCA version) support", + below. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -5547,6 +5693,18 @@ the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. +NE/2 (ne2000 MCA version) support +CONFIG_NE2_MCA + If you have a network (Ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called ne2.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + EISA, VLB, PCI and on board controllers CONFIG_NET_EISA This is another class of network cards which attach directly to the @@ -5562,8 +5720,8 @@ AMD PCnet32 (VLB and PCI) support CONFIG_PCNET32 - If you have a PCnet32 or PCnetPCI based network (Ethernet) card, say - Y here and read the Ethernet-HOWTO, available via FTP (user: + If you have a PCnet32 or PCnetPCI based network (Ethernet) card, + answer Y here and read the Ethernet-HOWTO, available via FTP (user: anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. This driver is also available as a module ( = code which can be @@ -5584,18 +5742,6 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -Racal-Interlan EISA ES3210 support -CONFIG_ES3210 - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available via FTP (user: anonymous) in - ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called es3210.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. - Mylex EISA LNE390A/LNE390B support CONFIG_LNE390 If you have a network (Ethernet) card of this type, say Y and read @@ -5725,6 +5871,29 @@ Please email feedback to james.banks@caldera.com. +VIA Rhine support +CONFIG_VIA_RHINE + If you have a VIA "rhine" based network card (Rhine-I (3043) or + Rhine-2 (VT86c100A)), say Y here. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called via-rhine.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + +Racal-Interlan EISA ES3210 support +CONFIG_ES3210 + If you have a network (Ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called es3210.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + SMC EtherPower II (EXPERIMENTAL) CONFIG_EPIC100 If you have an SMC EtherPower II 9432 PCI Ethernet network card @@ -5738,11 +5907,10 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -VIA Rhine support -CONFIG_VIA_RHINE - If you have a VIA "rhine" based network card (Rhine-I (3043) or - Rhine-2 (VT86c100A)), say Y here. To build this driver as a module - say M. +SGI Seeq ethernet controller support +CONFIG_SGISEEQ + Say Y here if you have an Seeq based Ethernet network card. This is + used in many Silicon Graphics machines. Zenith Z-Note support CONFIG_ZNET @@ -5859,9 +6027,9 @@ The traffic shaper is a virtual network device that allows you to limit the rate of outgoing data flow over some other network device. See Documentation/networking/shaper.txt for more - information. To set up and configure shaper devices, you need the + information. To set up and configure shaper devices, you need the shapecfg program, available via FTP (user: anonymous) from - ftp://shadow.cabi.net/pub/Linux in the shaper package. + ftp://shadow.cabi.net/pub/Linux in the shaper package. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -5883,9 +6051,44 @@ This is support for the DIGITAL series of EISA (DEFEA) and PCI (DEFPA) controllers which can connect you to a local FDDI network. -SGI Seeq ethernet controller support - This is a driver for the Seeq based Ethernet adapters used in many - Silicon Graphics machines. +HIgh Performance Parallel Interface support (EXPERIMENTAL) +CONFIG_HIPPI + HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and + 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI + can run over copper (25m) or fiber (300m on multi-mode or 10km on + single-mode). HIPPI networks are commonly used for clusters and to + connect to super computers. If you are connected to a HIPPI network + and have a HIPPI network card in your computer that you want to use + under Linux, say Y here (you must also remember to enable the driver + for your HIPPI card below). Most people will say N here. + +CERN HIPPI PCI adapter support +CONFIG_CERN_HIPPI + Say Y here if this is your PCI HIPPI network card. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called cern_hippi.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, + say N. + +Essential RoadRunner HIPPI PCI adapter support +CONFIG_ROADRUNNER + Say Y here if this is your PCI HIPPI network card. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called rrunner.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, + say N. + +Use large TX/RX rings +CONFIG_ROADRUNNER_LARGE_RINGS + If you say Y here, the RoadRunner driver will preallocate up to 2 MB + of additional memory to allow for fastest operation, both for + transmitting and receiving. This memory cannot be used by any other + kernel code or by user space programs. Say Y here only if you have + the memory. Acorn Ether1 card CONFIG_ARM_ETHER1 @@ -5925,20 +6128,20 @@ file drivers/cdrom/.h where you can define your interface parameters and switch some internal goodies. - All these CDROM drivers are also usable as a module (= code which + All these CDROM drivers are also usable as a module ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile them as module, say M instead of Y and read Documentation/modules.txt. - If you want to use any of these CDROM drivers, you also have to say - Y or M to "ISO 9660 CDROM filesystem support" below (this answer will - get "defaulted" for you if you enable any of the Linux CDROM - drivers). + If you want to use any of these CDROM drivers, you also have to + answer Y or M to "ISO 9660 CDROM filesystem support" below (this + answer will get "defaulted" for you if you enable any of the Linux + CDROM drivers). Sony CDU31A/CDU33A CDROM support CONFIG_CDU31A These CDROM drives have a spring-pop-out caddyless drawer, and a - rectangular green LED centered beneath it. NOTE: these CDROM drives + rectangular green LED centered beneath it. NOTE: these CDROM drives will not be auto detected by the kernel at boot time; you have to provide the interface address as an option to the kernel at boot time as described in Documentation/cdrom/cdu31a or fill in your @@ -5964,13 +6167,13 @@ IDE/ATAPI models). Please also the file Documentation/cdrom/mcd. With the old LU-005 model, the whole drive chassis slides out for cd - insertion. The FX-xxx models use a motorized tray type mechanism. + insertion. The FX-xxx models use a motorized tray type mechanism. Note that this driver does not support XA or MultiSession CDs - (PhotoCDs). There is a new driver (next question) which can do + (PhotoCDs). There is a new driver (next question) which can do this. If you want that one, say N here. If the driver doesn't work out of the box, you might want to have a - look at drivers/cdrom/mcd.h. + look at drivers/cdrom/mcd.h. If you say Y here, you should also say Y or M to "ISO 9660 CDROM filesystem support" below, because that's the filesystem used on @@ -5985,10 +6188,11 @@ CONFIG_MCDX Use this driver if you want to be able to read XA or MultiSession CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005, - FX-001 or FX-001D CDROM drive. In addition, this driver uses much less - kernel memory than the old one, if that is a concern. This driver is - able to support more than one drive, but each drive needs a separate - interface card. Please read the file Documentation/cdrom/mcdx. + FX-001 or FX-001D CDROM drive. In addition, this driver uses much + less kernel memory than the old one, if that is a concern. This + driver is able to support more than one drive, but each drive needs + a separate interface card. Please read the file + Documentation/cdrom/mcdx. If you say Y here, you should also say Y or M to "ISO 9660 CDROM filesystem support" below, because that's the filesystem used on @@ -6049,7 +6253,7 @@ CONFIG_AZTCD This is your driver if you have an Aztech CDA268-01A, Orchid CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCDROM CR520 or - CR540 CDROM drive. This driver -- just like all these CDROM drivers + CR540 CDROM drive. This driver -- just like all these CDROM drivers -- is NOT for CDROM drives with IDE/ATAPI interfaces, such as Aztech CDA269-031SE. Please read the file Documentation/cdrom/aztcd. @@ -6078,7 +6282,7 @@ Goldstar R420 CDROM support CONFIG_GSCD - If this is your CDROM drive, say Y here. As described in + If this is your CDROM drive, say Y here. As described in the file linux/Documentation/cdrom/gscd, you might have to change a setting in the file linux/drivers/cdrom/gscd.h before compiling the kernel. Please read the file Documentation/cdrom/gscd. @@ -6095,7 +6299,7 @@ Philips/LMS CM206 CDROM support CONFIG_CM206 If you have a Philips/LMS CDROM drive cm206 in combination with a - cm260 host adapter card, say Y here. Please also read the file + cm260 host adapter card, say Y here. Please also read the file Documentation/cdrom/cm206. If you say Y here, you should also say Y or M to "ISO 9660 CDROM @@ -6139,9 +6343,9 @@ Soft configurable cdrom interface card support CONFIG_CDI_INIT If you want to include boot-time initialization of any cdrom - interface card that is software configurable, say Y here. Currently + interface card that is software configurable, say Y here. Currently only the ISP16/MAD16/Mozart sound cards with built-in cdrom - interfaces are supported. + interfaces are supported. Note that the answer to this question doesn't directly affect the kernel: saying N will just cause this configure script to skip all @@ -6149,11 +6353,11 @@ ISP16/MAD16/Mozart soft configurable cdrom interface support CONFIG_ISP16_CDI - These are sound cards with with built-in cdrom interfaces using the - OPTi 82C928 or 82C929 chips. Say Y here to have them detected and + These are sound cards with built-in cdrom interfaces using the OPTi + 82C928 or 82C929 chips. Say Y here to have them detected and possibly configured at boot time. In addition, You'll have to say Y to a driver for the particular cdrom drive you have attached to the - card. Read Documentation/cdrom/isp16 for details. + card. Read Documentation/cdrom/isp16 for details. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6172,15 +6376,15 @@ Minix fs support CONFIG_MINIX_FS - Minix is a simple operating system used in many classes about - OS's. The minix filesystem (= method to organize files on a hard disk + Minix is a simple operating system used in many classes about OS's. + The minix filesystem (method to organize files on a hard disk partition or a floppy disk) was the original filesystem for Linux, - has been superseded by the second extended filesystem ext2fs but is - still used for root/boot and other floppies or ram disks since it is - leaner. You don't want to use it on your hard disk because of certain - built-in restrictions. This option will enlarge your kernel by about - 25 kB. Everyone should say Y or M so that they are able to read this - common floppy format. + has since been superseded by the second extended filesystem ext2fs + but is still being used for root/boot and other floppies or ram + disks since it is leaner. You don't want to use it on your hard disk + because of certain built-in restrictions. This option will enlarge + your kernel by about 25 kB. Everyone should say Y or M so that they + are able to read this common floppy filesystem. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -6190,7 +6394,7 @@ Second extended fs support CONFIG_EXT2_FS - This is the de facto standard Linux filesystem (= method to organize + This is the de facto standard Linux filesystem (method to organize files on a storage device) for hard disks. You want to say Y here, unless you intend to use Linux exclusively @@ -6218,10 +6422,13 @@ directories on ext2 filesystems, use chattr ("man chattr"). Ext2fs partitions can be read from within DOS using the ext2tool - package (available via FTP (user: anonymous) from + command line tool package (available via FTP (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/system/filesystems/ext2) and from - within Windows 95 and Windows NT using the ex2fs explorer available - from http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm. + within Windows NT using the ext2nt command line tool package from + ftp://sunsite.unc.edu/pub/Linux/utils/dos. Explore2fs is a graphical + explorer for ext2fs partitions which runs on Windows 95 and Windows + NT and includes experimental write support; it is available from + http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm. If you want to compile this filesystem as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -6294,33 +6501,33 @@ Another way to read and write MSDOS floppies from within Linux (but not transparently) is with the mtools ("man mtools") program suite, - which doesn't require the msdos filesystem support. + which doesn't require the msdos filesystem support. If you want to use umsdos, the Unix-like filesystem on top of DOS, which allows you to run Linux from within a DOS partition without repartitioning, you'll have to say Y or M here. If you have Windows 95 or Windows NT installed on your MSDOS partitions, you should use the VFAT filesystem instead, or you will not be able to see the long - filenames generated by Windows 95 / Windows NT. + filenames generated by Windows 95 / Windows NT. - This option will enlarge your kernel by about 7 kB. If unsure, say - Y. This will only work if you said Y to "fat fs support" as well. If - you want to compile this as a module however ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called msdos.o. + This option will enlarge your kernel by about 7 kB. If unsure, + answer Y. This will only work if you said Y to "fat fs support" as + well. If you want to compile this as a module however ( = code which + can be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called msdos.o. vfat fs support CONFIG_VFAT_FS This allows you to mount MSDOS partitions of your hard drive. It - will let you use filenames in a way compatible with the long + will let you use filenames in a way compatible with the long filenames used by Windows 95 and Windows NT fat-based (not NTFS) partitions. It does not support Windows 95 compressed filesystems. You cannot use the VFAT filesystem for your root partition; use UMSDOS instead. This option enlarges your kernel by about 10 kB and - it only works if you said Y to the "fat fs support" above. Please read - the file Documentation/filesystems/vfat.txt for details. - If unsure, say N. + it only works if you said Y to the "fat fs support" above. Please + read the file Documentation/filesystems/vfat.txt for details. If + unsure, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -6335,7 +6542,7 @@ backing everything up and restoring afterwards) and hence you're able to quickly try out Linux or show it to your friends; the disadvantage is that Linux becomes susceptible to DOS viruses and - that UMSDOS is somewhat slower than ext2fs. Another use of umsdos + that UMSDOS is somewhat slower than ext2fs. Another use of umsdos is to write files with long unix filenames to MSDOS floppies; it also allows Unix-style softlinks and owner/permissions of files on MSDOS floppies. You will need a program called umssync in order to @@ -6385,7 +6592,7 @@ ftp://sunsite.unc.edu/pub/Linux/docs/LDP, on its man page: "man nfs", and in the NFS-HOWTO. - An superior but less widely used alternative to NFS is provided by + A superior but less widely used alternative to NFS is provided by the Coda filesystem; see "Coda filesystem support" below. If you say Y here, you should have said Y to TCP/IP networking also. @@ -6429,7 +6636,7 @@ You will need the support software from the linux-nfs package available at ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/. Please read the NFS-HOWTO, available via FTP (user: anonymous) from - sunsite.unc.edu:/pub/Linux/docs/HOWTO. + ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO. The NFS server is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6439,8 +6646,8 @@ Emulate Sun NFS daemon CONFIG_NFSD_SUN If you would like for the server to allow clients to access - directories that are mountpoints on the local filesystem (this is - how nfsd behaves on Sun systems), say yes here. If unsure, say N. + directories that are mount points on the local filesystem (this is + how nfsd behaves on Sun systems), say yes here. If unsure, say N. OS/2 HPFS filesystem support (read only) CONFIG_HPFS_FS @@ -6472,7 +6679,7 @@ NTFS read-write support (experimental) CONFIG_NTFS_RW If you say Y here, you will (hopefully) be able to write to NTFS - file systems as well as read from them. The read-write support + file systems as well as read from them. The read-write support in NTFS is far from being complete and is not well tested. If you enable this, back up your NTFS volume first since it may get damaged. @@ -6482,34 +6689,36 @@ System V and Coherent filesystem support CONFIG_SYSV_FS SCO, Xenix and Coherent are commercial Unix systems for Intel - machines. Saying Y here would allow you to read and write to and - from their floppies and hard disk partitions. + machines. Saying Y here would allow you to read to and write from + their floppies and hard disk partitions. - If you have a floppy or hard disk partition like that, it is likely + If you have floppies or hard disk partitions like that, it is likely that they contain binaries from those other Unix systems; in order - to run these binaries, you will want to install iBCS2 (iBCS2 [Intel - Binary Compatibility Standard] is a kernel module which lets you run - SCO, Xenix, Wyse, UnixWare, Dell Unix and System V programs under - Linux and is often needed to run commercial software that's only - available for those systems. It's available via FTP (user: - anonymous) from ftp://tsx-11.mit.edu/pub/linux/BETA). + to run these binaries, you will want to install iBCS2 (Intel Binary + Compatibility Standard is a kernel module which lets you run SCO, + Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux + and is often needed to run commercial software that's only available + for those systems. It's available via FTP (user: anonymous) from + ftp://tsx-11.mit.edu/pub/linux/BETA). If you only intend to mount files from some other Unix over the network using NFS, you don't need the System V filesystem support - (but you need NFS filesystem support obviously). Note that this - option is generally not needed for floppies, since a good portable - way to transport files and directories between unixes (and even - other operating systems) is given by the tar program ("man tar" or - preferably "info tar"). Note also that this option has nothing - whatsoever to do with the option "System V IPC". Read about the - System V filesystem in Documentation/filesystems/sysv-fs.txt. This - option will enlarge your kernel by about 34 kB. + (but you need NFS filesystem support obviously). + + Note that this option is generally not needed for floppies, since a + good portable way to transport files and directories between unixes + (and even other operating systems) is given by the tar program ("man + tar" or preferably "info tar"). Note also that this option has + nothing whatsoever to do with the option "System V IPC". Read about + the System V filesystem in Documentation/filesystems/sysv-fs.txt. + Saying Y here will enlarge your kernel by about 34 kB. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called sysv.o. If you haven't heard about all of this before, it's - safe to say N. + called sysv.o. + + If you haven't heard about all of this before, it's safe to say N. Amiga FFS filesystem support CONFIG_AFFS_FS @@ -6558,8 +6767,8 @@ want). The module is called romfs.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - If you don't know whether you need it, then you don't need it: say - N. + If you don't know whether you need it, then you don't need it: + answer N. QNX filesystem support (EXPERIMENTAL) CONFIG_QNX4FS_FS @@ -6576,13 +6785,13 @@ Kernel automounter support CONFIG_AUTOFS_FS The automounter is a tool to automatically mount remote filesystems - on demand. This implementation is partially kernel-based to reduce + on demand. This implementation is partially kernel-based to reduce overhead in the already-mounted case; this is unlike the BSD automounter (amd), which is a pure user space daemon. To use the automounter you need the user-space tools from - ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to say - Y to "NFS filesystem support", above. + ftp://ftp.kernel.org/pub/linux/daemons/autofs; you also want to + answer Y to "NFS filesystem support", above. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -6597,8 +6806,8 @@ BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, OpenBSD and NeXTstep) use a filesystem called UFS. Some System V Unixes can create and mount hard disk partitions and diskettes using - this filesystem as well. Saying Y here allows you to mount these - partitions and diskettes. + this filesystem as well. Saying Y here will allow you to read from + and write to these partitions and diskettes. If you only intend to mount files from some other Unix over the network using NFS, you don't need the UFS filesystem support (but @@ -6699,12 +6908,12 @@ SMB filesystem support (to mount WfW shares etc..) CONFIG_SMB_FS SMB (Server Message Block) is the protocol Windows for Workgroups - (WfW), Windows 95, Windows NT and Lan Manager use to share files and - printers over local networks. Saying Y here allows you to mount - their filesystems (often called "shares" in this context) and access - them just like any other Unix directory. Currently, this works only - if the Windows machines use TCP/IP as the underlying transport - protocol, and not NetBEUI. For details, read + (WfW), Windows 95, Windows NT and OS/2 Lan Manager use to share + files and printers over local networks. Saying Y here allows you to + mount their filesystems (often called "shares" in this context) and + access them just like any other Unix directory. Currently, this + works only if the Windows machines use TCP/IP as the underlying + transport protocol, and not NetBEUI. For details, read Documentation/filesystems/smbfs.txt and the SMB-HOWTO, available via FTP (user: anonymous) from ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. @@ -6738,18 +6947,17 @@ enables you to mount filesystems of a remote server and access them with regular Unix commands as if they were sitting on your hard disk. Coda has several advantages over NFS: support for disconnected - operation for laptops, read/write server replication, security model - for authentication and encryption, persistent client caches and - write back caching. + operation (e.g. for laptops), read/write server replication, + security model for authentication and encryption, persistent client + caches and write back caching. If you say Y here, your Linux box will be able to act as a Coda *client*. You will need user level code as well, both for the client and server. Servers are currently user level, i.e. need no kernel - support. For technical information, read - Documentation/filesystems/coda.txt. For further information see - http://www.coda.cs.cmu.edu (to browse the WWW, you need to have - access to a machine on the Internet that has a program like lynx or - netscape) or contact Peter Braam . + support. Please read Documentation/filesystems/coda.txt and check + out the Coda home page http://www.coda.cs.cmu.edu (to browse the + WWW, you need to have access to a machine on the Internet that has a + program like lynx or netscape). If you want to compile the coda client support as a module ( = code which can be inserted in and removed from the running kernel @@ -6764,7 +6972,7 @@ mount NetWare file server volumes and to access them just like any other Unix directory. For details, please read the file Documentation/filesystems/ncpfs.txt in the kernel source and the - IPX-HOWTO on sunsite.unc.edu:/pub/Linux/docs/howto. + IPX-HOWTO on ftp://sunsite.unc.edu:/pub/Linux/docs/howto. You do not have to say Y here if you want your Linux box to act as a file *server* for Novell NetWare clients. @@ -6887,16 +7095,17 @@ nls codepage 850 CONFIG_NLS_CODEPAGE_850 The Microsoft fat filesystem family can deal with filenames in - native language character sets. These character sets are stored - in so-called DOS codepages. You need to include the appropriate + native language character sets. These character sets are stored in + so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on DOS/Windows partitions correctly. This does apply to the filenames only, not to the file contents. You can include several codepages; say Y here if you want to include the DOS codepage that is used for - much of Europe -- United Kingdom, Germany, Spain, Italy, and [add more - countries here]. It has some characters useful to many European - languages that are not part of the US codepage 437. If unsure, say - Y. + much of Europe -- United Kingdom, Germany, Spain, Italy, and [add + more countries here]. It has some characters useful to many European + languages that are not part of the US codepage 437. + + If unsure, say Y. nls codepage 852 CONFIG_NLS_CODEPAGE_852 @@ -6907,7 +7116,7 @@ DOS/Windows partitions correctly. This does apply to the filenames only, not to the file contents. You can include several codepages; say Y here if you want to include the Latin 2 codepage used by DOS - for much of Central and Eastern Europe. It has all the required + for much of Central and Eastern Europe. It has all the required characters for these languages: Albanian, Croatian, Czech, English, Finnish, Hungarian, Irish, German, Polish, Romanian, Serbian (Latin transcription), Slovak, Slovenian, and Sorbian. @@ -7075,7 +7284,7 @@ correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-5, a Cyrillic character set with which you can type Bulgarian, Byelorussian, - Macedonian, Russian, Serbian, and Ukrainian. Note that the charset + Macedonian, Russian, Serbian, and Ukrainian. Note that the charset KOI8-R is preferred in Russia. nls iso8859-6 @@ -7131,30 +7340,67 @@ Virtual terminal CONFIG_VT - If you say Y here, you will get support for a terminal device with + If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you - can run several virtual terminals on one physical terminal; however, - you need at least one virtual terminal device in order to make use - of a physical terminal. Only people using embedded systems want to - say N here; most everybody else says Y. If unsure, say Y, or else - you won't be able to do much with your new shiny Linux system :-) + can run several virtual terminals (also called virtual consoles) on + one physical terminal. This is rather useful, for example one + virtual terminal can collect system messages and warnings, another + one can be used for a text-mode user session, and a third could run + an X session, all in parallel. Switching between virtual terminals + is done with certain key combinations, usually Alt-. + + The setterm command ("man setterm") can be used to change the + properties (such as colors) of a virtual terminal. + + You need at least one virtual terminal device in order to make use + of your keyboard and monitor. Therefore, only people configuring an + embedded system would want to say N here in order to save some + memory; the only way to log into such a system is then via a serial + or network connection. + + If unsure, say Y, or else you won't be able to do much with your new + shiny Linux system :-) Support for console on virtual terminal CONFIG_VT_CONSOLE - If you say Y here, by default all kernel messages will be sent to - the device /dev/tty0 which corresponds to the virtual terminal that - is visible on your display. You should say Y here unless you only - want to have the kernel messages output to a serial port (in which - case you probably want to say Y to "Console on serial port", below). + The system console is the device which receives all kernel messages + and warnings and which allows logins in single user mode. If you + answer Y here, a virtual terminal (the device used to interact with + a physical terminal) can be used as system console. This is the most + common mode of operations, so you should say Y here unless you want + the kernel messages be output only to a serial port (in which case + you should say Y to "Console on serial port", below). + + If you do say Y here, by default the currently visible virtual + terminal (/dev/tty0) will be used as system console. You can change + that with a kernel command line option such as "console=tty3" which + would use the third virtual terminal as system console. (Try "man + bootparam" or see the documentation of your boot loader (lilo or + loadlin) about how to pass options to the kernel at boot time. The + lilo procedure is also explained in the SCSI-HOWTO, available via + FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.) + + If unsure, say Y. Software generated cursor CONFIG_SOFTCURSOR If you say Y here, you'll be able to do lots of nice things with the cursors of your virtual consoles -- for example turn them into non-blinking block cursors which are more visible on laptop screens, - or change their color depending on the virtual console you're on. + or change their colors depending on the virtual console they're on. See Documentation/VGA-softcursor.txt for more information. +Support for PowerMac keyboard +CONFIG_MAC_KEYBOARD + This option allows you to use an ADB keyboard attached to your + machine. Note that this disables any other (ie. PS/2) keyboard + support, even if your machine is physically capable of using both at + the same time. + + If you use an ADB keyboard (4 pin connector), say Y here. + If you use a PS/2 keyboard (6 pin connector), say N here. + Standard/generic serial support CONFIG_SERIAL This selects whether you want to include the driver for the standard @@ -7169,38 +7415,54 @@ Documentation/modules.txt. The module will be called serial.o. [WARNING: Do not compile this driver as a module if you are using non-standard serial ports, since the configuration information will - be lost if you unload the driver. This limitation may be lifted in - the future.] + be lost when the driver is unloaded. This limitation may be lifted + in the future.] BTW1: If you have a mouseman serial mouse which is not recognized by the X window system, try running gpm first. BTW2: If you intend to connect a so-called Winmodem to your - machine's serial port, forget it. These modems require proprietary - drivers which are only available under Windows. + machine's serial port, forget it. These modems are crippled and + require proprietary drivers which are only available under Windows. Most people will say Y or M here, so that they can use serial mice, modems and similar devices connecting to the standard serial ports. Support for console on serial port CONFIG_SERIAL_CONSOLE - If you say Y here, it is possible to use a serial port as the - console. By default still the currently visible virtual console will - be used as the system console but you can alter that using a kernel - command line option such as "console=ttyS1". (Try "man bootparam" or - see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time. The lilo procedure - is also explained in the SCSI-HOWTO, available via FTP (user: - anonymous) in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.) If you - don't have a VGA card installed and you say Y here, the kernel will - automatically use /dev/ttyS0 as system console. + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). This could be useful if some terminal or printer is connected + to that serial port. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttyS1". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time. The lilo procedure is also explained in the + SCSI-HOWTO, available via FTP (user: anonymous) in + ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.) + + If you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + If unsure, say N. + +Support for PowerMac serial ports +CONFIG_MAC_SERIAL + If you have Macintosh style serial ports (8 pin mini-DIN), say Y + here. If you also have regular serial ports and enable the driver + for them, you can't currently use the serial console feature. Comtrol Rocketport support CONFIG_ROCKETPORT This is a driver for the Comtrol Rocketport cards which provide - multiple serial ports. You would need something like this to - connect more than two modems to your Linux box, for instance in - order to become a BBS. + multiple serial ports. You would need something like this to connect + more than two modems to your Linux box, for instance in order to + become a dial-in server. If you want to compile this driver as a module, say M here and read Documentation/modules.txt. The module will be called rocket.o. @@ -7208,12 +7470,12 @@ Digiboard Intelligent async support CONFIG_DIGIEPCA This is a driver for Digi International's Xx, Xeve, and Xem series - of cards which provide multiple serial ports. You would need + of cards which provide multiple serial ports. You would need something like this to connect more than two modems to your Linux - box, for instance in order to become a BBS. 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. + box, for instance in order to become a dial-in server. 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: There is another, separate driver for the Digiboard PC boards: "Digiboard PC/Xx Support" below. You should (and can) only select @@ -7227,8 +7489,8 @@ This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards that give you many serial ports. You would need something like this to connect more than two modems to your Linux box, for instance in - order to become a BBS. If you have a card like that, say Y here and - read the file Documentation/digiboard.txt. + order to become a dial-in server. If you have a card like that, say + Y here and read the file Documentation/digiboard.txt. If you want to compile this driver as a module, say M here and read Documentation/modules.txt. The module will be called pcxx.o. @@ -7238,8 +7500,8 @@ This is a driver for the SDL Communications RISCom/8 multiport card, which gives you many serial ports. You would need something like this to connect more than two modems to your Linux box, for instance - in order to become a BBS. If you have a card like that, say Y here - and read the file Documentation/riscom8.txt. + in order to become a dial-in server. If you have a card like that, + say Y here and read the file Documentation/riscom8.txt. Also it's possible to say M here and compile this driver as kernel loadable module; the module will be called riscom8.o. @@ -7249,7 +7511,7 @@ This is a driver for the Specialix IO8+ multiport card (both the ISA and the PCI version) which gives you many serial ports. You would need something like this to connect more than two modems to - your Linux box, for instance in order to become a BBS. + your Linux box, for instance in order to become a dial-in server. If you have a card like that, say Y here and read the file Documentation/specialix.txt. Also it's possible to say M here and @@ -7258,19 +7520,19 @@ Specialix DTR/RTS pin is RTS CONFIG_SPECIALIX_RTSCTS - The Specialix card can only support either RTS or DTR. If you say - N here, the driver will use the pin as "DTR" when the tty is in - software handshake mode. If you say Y here or hardware handshake - is on, it will always be RTS. Read the file - Documentation/specialix.txt for more information. + The Specialix card can only support either RTS or DTR. If you say N + here, the driver will use the pin as "DTR" when the tty is in + software handshake mode. If you say Y here or hardware handshake is + on, it will always be RTS. Read the file Documentation/specialix.txt + for more information. Cyclades async mux support CONFIG_CYCLADES This is a driver for a card that gives you many serial ports. You would need something like this to connect more than two modems to - your Linux box, for instance in order to become a BBS. For - information about the Cyclades-Z card, read - drivers/char/README.cycladesZ. + your Linux box, for instance in order to become a dial-in server. + For information about the Cyclades-Z card, read + drivers/char/README.cycladesZ. As of 1.3.9x kernels, this driver's minor numbers start at 0 instead of 32. @@ -7286,10 +7548,10 @@ CONFIG_STALDRV Stallion cards give you many serial ports. You would need something like this to connect more than two modems to your Linux box, for - instance in order to become a BBS. If you say Y here, you will be - asked for your specific card model in the next questions. Make sure - to read drivers/char/README.stallion in this case. If you have never - heard about all this, it's safe to say N. + instance in order to become a dial-in server. If you say Y here, you + will be asked for your specific card model in the next questions. + Make sure to read drivers/char/README.stallion in this case. If you + have never heard about all this, it's safe to say N. Stallion EasyIO or EC8/32 support CONFIG_STALLION @@ -7315,8 +7577,8 @@ Hayes ESP serial port support CONFIG_ESPSERIAL - This is a driver which supports Hayes ESP serial ports. Both single - port cards and multiport cards are supported. Make sure to read + This is a driver which supports Hayes ESP serial ports. Both single + port cards and multiport cards are supported. Make sure to read Documentation/hayes-esp.txt. To compile this driver as a module ( = code which can be inserted in @@ -7346,8 +7608,9 @@ filesystem; therefore, if you say Y here you should say Y to "/dev/pts filesystem for Unix98 PTYs" as well. - Say Y here if you are uncertain, unless you are very short on - memory. + You should say Y here only if your C library is glibc 2.1 or later + (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). Read the + instructions in Documentation/Changes. Maximum number of Unix98 PTYs in use (0-2048) CONFIG_UNIX98_PTY_COUNT @@ -7358,7 +7621,7 @@ connection and every xterm uses up one PTY. When not in use, each additional set of 256 PTYs occupy - approximately 8K of kernel memory on 32-bit architectures. + approximately 8 KB of kernel memory on 32-bit architectures. Parallel printer support CONFIG_PRINTER @@ -7392,7 +7655,7 @@ CONFIG_PRINTER_READBACK If your printer conforms to IEEE 1284, it may be able to provide a status indication when you read from it (for example, with `cat - /dev/lp1'). To use this feature, say Y here. + /dev/lp1'). To use this feature, say Y here. Mouse Support (not serial mice) CONFIG_MOUSE @@ -7436,20 +7699,16 @@ AST and IBM all use this as their mouse port on currently shipping machines. The trackballs of some laptops are PS/2 mice also. In particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse. + Although PS/2 mice are not technically bus mice, they are explained in detail in the Busmouse-HOWTO, available via FTP (user: anonymous) - in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. When using a PS/2 - mouse, you can get problems if you want to use the mouse both on the - Linux console and under X. Using the "-R" option of the Linux mouse - managing program gpm (available from - sunsite.unc.edu:/pub/Linux/system/Daemons) solves this problem, or - you can get the "mconv" utility also from sunsite. + in ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO. - If you want to compile this mouse driver as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read Documentation/modules.txt. The module - will be called psaux.o. If you are unsure, say N and read the HOWTO - nevertheless: it will tell you what you have. + When using a PS/2 mouse, you can get problems if you want to use the + mouse both on the Linux console and under X. Using the "-R" option + of the Linux mouse managing program gpm (available from + ftp://sunsite.unc.edu:/pub/Linux/system/Daemons) solves this + problem, or you can get the "mconv" utility also from sunsite. C&T 82C710 mouse port support (as on TI Travelmate) CONFIG_82C710_MOUSE @@ -7464,7 +7723,7 @@ http://toy.cabi.net; to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). It can turn the digitizer pad into a PS/2 mouse emulation - with tap gestures or into an absolute pad. + with tap gestures or into an absolute pad. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -7503,13 +7762,10 @@ If you are unsure, say N and read the HOWTO nevertheless: it will tell you what you have. -Support for user miscellaneous modules -CONFIG_UMISC - This option forces generic miscellaneous minor device support in the - kernel, and allows later loading of user miscellaneous character - device modules, such as drivers for optic pens and touchscreens. - Unless you need such specific modules, or are willing to write/test - one, just say N. +Support for PowerMac ADB mouse +CONFIG_ADBMOUSE + If you have an ADB mouse (4 pin connector) as is common on + Macintoshes, say Y here. QIC-02 tape support CONFIG_QIC02_TAPE @@ -7525,7 +7781,7 @@ header file (include/linux/tpqic02.h), in which case you should say N, or you can fetch a program via anonymous FTP which is able to configure this driver during runtime. The program to do this is - called 'qic02conf' and it is part of the 'tpqic02-support-X.Y.tar.gz' + called 'qic02conf' and it is part of the tpqic02-support-X.Y.tar.gz support package. If you want to use the qic02conf program, say Y. @@ -7607,7 +7863,7 @@ Default block size for zftape CONFIG_ZFT_DFLT_BLK_SZ - If unsure leave this at its default value, i.e. 10240. Note that + If unsure leave this at its default value, i.e. 10240. Note that you specify only the default block size here. The block size can be changed at run time using the MTSETBLK tape operation with the MTIOCTOP ioctl (i.e. with "mt -f /dev/qft0 setblk #BLKSZ" from the @@ -7618,7 +7874,7 @@ in multiples of a fixed block size. The block size defaults to 10240 which is what GNU tar uses. The values for the block size should be either 1 or multiples of 1024 up to a maximum value of - 63488 (i.e. 62k). If you specify `1' then zftape's builtin + 63488 (i.e. 62 K). If you specify `1' then zftape's builtin compression will be disabled. Reasonable values are `10240' (GNU tar's default block size), @@ -7628,12 +7884,12 @@ Number of DMA buffers CONFIG_FT_NR_BUFFERS - Please leave this at `3' unless you REALLY know what you are - doing. It is not necessary to change this value. Values below 3 make - the proper use of ftape impossible, values greater than 3 are a waste - of memory. You can change the amount of DMA memory used by ftape at + Please leave this at `3' unless you REALLY know what you are doing. + It is not necessary to change this value. Values below 3 make the + proper use of ftape impossible, values greater than 3 are a waste of + memory. You can change the amount of DMA memory used by ftape at runtime with "mt -f /dev/qft0 setdrvbuffer #NUMBUFFERS". Each buffer - wastes 32kb of memory. Please note that this memory cannot be + wastes 32 KB of memory. Please note that this memory cannot be swapped out. Procfs entry for ftape @@ -7646,9 +7902,9 @@ cartridge, the kernel driver, your tape drive, the floppy disk controller and the error history for the most recent use of the kernel driver. Saying Y will enlarge the size of the ftape driver - by approximately 2k. + by approximately 2 KB. - WARNING: When compiling ftape as a module (i.e. saying `M' to + WARNING: When compiling ftape as a module (i.e. saying M to "Floppy tape drive") it is dangerous to use ftape's proc file system interface. Accessing `/proc/ftape' while the module is unloaded will result in a kernel Oops. This cannot be fixed from inside ftape. @@ -7762,9 +8018,9 @@ Note that this menu lets you specify only the default setting for the IRQ channel. The hardware configuration can be changed at boot - time (when ftape is compiled into the kernel, i.e. if you specified - Y to "Floppy tape drive") or module load time (i.e. if you have said M - to "Floppy tape drive"). + time (when ftape is compiled into the kernel, i.e. if you said Y to + "Floppy tape drive") or module load time (i.e. if you said M to + "Floppy tape drive"). Please read also the file Documentation/ftape.txt which contains a short description of the parameters that can be set at boot or load @@ -7788,9 +8044,9 @@ Note that this menu lets you specify only the default setting for the DMA channel. The hardware configuration can be changed at boot - time (when ftape is compiled into the kernel, i.e. if you specified - Y to "Floppy tape drive") or module load time (i.e. if you have said M - to "Floppy tape drive"). + time (when ftape is compiled into the kernel, i.e. if you said Y to + "Floppy tape drive") or module load time (i.e. if you said M to + "Floppy tape drive"). Please read also the file Documentation/ftape.txt which contains a short description of the parameters that can be set at boot or load @@ -7828,11 +8084,11 @@ PCI or AGP bus. Enabling write-combining allows bus write transfers to be combined into a larger transfer before bursting over the PCI/AGP bus. This can increase performance of image write operations - 2.5 times or more. - This option creates a /proc/mtrr file which may be used to manipulate - your MTRRs. Typically the X server should use this. This should have - a reasonably generic interface so that similar control registers on - other processors can be easily supported. + 2.5 times or more. This option creates a /proc/mtrr file which may + be used to manipulate your MTRRs. Typically the X server should use + this. This should have a reasonably generic interface so that + similar control registers on other processors can be easily + supported. Saying Y here also fixes a problem with buggy SMP BIOSes which only set the MTRRs for the boot CPU and not the secondary CPUs. This can @@ -7841,7 +8097,8 @@ In general you should compile this into the kernel, rather than as a loadable module, because the BIOS fix needs to be done early in the boot sequence. If you compile this as a module, the BIOS fix will be - delayed until when you load the module. You do this at your own risk. + delayed until when you load the module. You do this at your own + risk. See Documentation/mtrr.txt for more information. @@ -7853,8 +8110,8 @@ Zilog serial support CONFIG_SUN_ZS - This driver does not exist at this point, so you might as well say - N. + This driver does not exist at this point, so you might as well + say N. Advanced Power Management CONFIG_APM @@ -7892,41 +8149,45 @@ anything, try disabling/enabling this option (or disabling/enabling APM in your BIOS). - Some other things to try when experiencing seemingly random, "weird" - problems: - 1) passing the "no-hlt" option to the kernel - 2) switching on floating point emulation in the kernel and passing + Some other things you should try when experiencing seemingly random, + "weird" problems: + + 1) make sure that you have enough swap space and that it is + enabled. + 2) pass the "no-hlt" option to the kernel + 3) switch on floating point emulation in the kernel and pass the "no387" option to the kernel - 3) passing the "floppy=nodma" option to the kernel - 4) passing the "mem=4M" option to the kernel (thereby disabling - all but the first 4M of RAM) - 5) making sure that the CPU is not over clocked. - 6) reading the sig11 FAQ at http://www.bitwizard.nl/sig11/ - 7) disabling the cache from your BIOS settings - 8) installing a better fan - 9) exchanging RAM chips - 10) exchanging the motherboard. + 4) pass the "floppy=nodma" option to the kernel + 5) pass the "mem=4M" option to the kernel (thereby disabling + all but the first 4 MB of RAM) + 6) make sure that the CPU is not over clocked. + 7) read the sig11 FAQ at http://www.bitwizard.nl/sig11/ + 8) disable the cache from your BIOS settings + 9) install a fan for the video card or exchange video RAM + 10) install a better fan for the CPU + 11) exchange RAM chips + 12) exchange the motherboard. Ignore USER SUSPEND CONFIG_APM_IGNORE_USER_SUSPEND - This option will ignore USER SUSPEND requests. On machines with a - compliant APM BIOS, you want to say N. However, on the NEC Versa M + This option will ignore USER SUSPEND requests. On machines with a + compliant APM BIOS, you want to say N. However, on the NEC Versa M series notebooks, it is necessary to say Y because of a BIOS bug. Enable APM at boot time CONFIG_APM_DO_ENABLE - Enable APM features at boot time. From page 36 of the APM BIOS + Enable APM features at boot time. From page 36 of the APM BIOS specification: "When disabled, the APM BIOS does not automatically power manage devices, enter the Standby State, enter the Suspend State, or take power saving steps in response to CPU Idle calls." This driver will make CPU Idle calls when Linux is idle (unless this - feature is turned off -- see "Do CPU IDLE calls", below). This + feature is turned off -- see "Do CPU IDLE calls", below). This should always save battery power, but more complicated APM features - will be dependent on your BIOS implementation. You may need to turn + will be dependent on your BIOS implementation. You may need to turn this option off if your computer hangs at boot time when using APM - support, or if it beeps continuously instead of suspending. Turn + support, or if it beeps continuously instead of suspending. Turn this off if you have a NEC UltraLite Versa 33/C or a Toshiba - T400CDT. This is off by default since most machines do fine without + T400CDT. This is off by default since most machines do fine without this feature. Do CPU IDLE calls @@ -7941,12 +8202,12 @@ Enable console blanking using APM CONFIG_APM_DISPLAY_BLANK - Enable console blanking using the APM. Some laptops can use this to + Enable console blanking using the APM. Some laptops can use this to turn off the LCD backlight when the screen blanker of the Linux - virtual console blanks the screen. Note that this is only used by + virtual console blanks the screen. Note that this is only used by the virtual console screen blanker, and won't turn off the backlight when using the X Window system. This also doesn't have anything to - do with your VESA-compliant power-saving monitor. Further, this + do with your VESA-compliant power-saving monitor. Further, this option doesn't work for all laptops -- it might not turn off your backlight at all, or it might print a lot of errors to the console, especially if you are using gpm. @@ -7954,13 +8215,14 @@ Power off on shutdown CONFIG_APM_POWER_OFF Enable the ability to power off the computer after the Linux kernel - is halted. You will need software (e.g., a suitable version of the + is halted. You will need software (e.g., a suitable version of the halt(8) command ("man 8 halt")) to cause the computer to power down. Recent versions of the sysvinit package available from ftp://sunsite.unc.edu/pub/Linux/system/daemons/init/ (user: anonymous) contain support for this ("halt -p" shuts down Linux and - powers off the computer). As with the other APM options, this - option may not work reliably with some APM BIOS implementations. + powers off the computer, if executed from runlevel 0). As with the + other APM options, this option may not work reliably with some APM + BIOS implementations. Ignore multiple suspend/standby events CONFIG_APM_IGNORE_MULTIPLE_SUSPEND @@ -7985,8 +8247,8 @@ your computer. For details, read Documentation/watchdog.txt in the kernel source. - The watchdog is usually used together with the watchdog daemon which - is available via FTP (user: anonymous) from + The watchdog is usually used together with the watchdog daemon + which is available via FTP (user: anonymous) from ftp://tsx-11.mit.edu/pub/linux/sources/sbin/. This daemon can also monitor NFS connections and can reboot the machine when the process table is full. @@ -8043,7 +8305,7 @@ This is the driver for the Berkshire Products PC Watchdog card. This card simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of - time. This driver is like the WDT501 driver but for different + time. This driver is like the WDT501 driver but for different hardware. Please read Documentation/pcwd-watchdog.txt. The PC watchdog cards can be ordered from http://www.berkprod.com. Some example rc.local files are available from ftp://ftp.bitgate.com. @@ -8051,8 +8313,9 @@ This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called pcwd.o. If you want to compile it as a module, - say M here and read Documentation/modules.txt. Most people will say - N. + say M here and read Documentation/modules.txt. + + Most people will say N. Acquire SBC Watchdog Timer CONFIG_ACQUIRE_WDT @@ -8062,54 +8325,55 @@ it does, it reboots your computer after a certain amount of time. This driver is like the WDT501 driver but for different hardware. - This driver is also available as a module ( = code which can be + This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module is called pscwdt.o. If you want to compile it as a module, - say M here and read Documentation/modules.txt. Most people will say N. + The module is called pscwdt.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Most people + will say N. Enhanced Real Time Clock Support CONFIG_RTC If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your - computer. Every PC has such a clock built in. It can be used to - generate signals from as low as 1Hz up to 8192Hz, and can also be - used as a 24 hour alarm. It reports status information via the file - /proc/rtc and its behaviour is set by various ioctls on - /dev/rtc. + will get access to the real time clock built into your computer. + Every PC has such a clock built in. It can be used to generate + signals from as low as 1Hz up to 8192Hz, and can also be used as a + 24 hour alarm. It reports status information via the file /proc/rtc + and its behaviour is set by various ioctls on /dev/rtc. - People running SMP (= multiprocessor) versions of Linux should say Y + People running SMP (multiprocessor) versions of Linux should say Y here to read and set the RTC clock in a SMP compatible fashion. (They should also read Documentation/smp and Documentation/IO-APIC.txt and the SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ (to browse the WWW, you need to have access to a machine on the Internet that has a program - like lynx or netscape)). + like lynx or netscape).) If you think you have a use for such a device (such as periodic data - sampling), then say Y here, and go read the file - Documentation/rtc.txt for details. + sampling), then say Y here, and read Documentation/rtc.txt for + details. Tadpole ANA H8 Support CONFIG_H8 The Hitachi H8/337 is a microcontroller used to deal with the power and thermal environment. If you say Y here, you will be able to - communicate with it via via a character special device. If unsure, - say N. + communicate with it via a character special device. + + If unsure, say N. /dev/nvram support CONFIG_NVRAM If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), - you get access to the 50 bytes of non-volatile memory in the real - time clock (RTC), which is contained in every PC and most - Ataris. This memory is conventionally called "CMOS RAM" on PCs and - "NVRAM" on Ataris. /dev/nvram may be used to view settings there, or - to change them (with some utility). It could also be used to - frequently save a few bits of very important data that may not be - lost over power-off and for which writing to disk is too - insecure. On Atari machines, /dev/nvram is always configured and - does not need to be selected. + you get read and write access to the 50 bytes of non-volatile memory + in the real time clock (RTC), which is contained in every PC and + most Ataris. This memory is conventionally called "CMOS RAM" on PCs + and "NVRAM" on Ataris. /dev/nvram may be used to view settings + there, or to change them (with some utility). It could also be used + to frequently save a few bits of very important data that may not be + lost over power-off and for which writing to disk is too insecure. + On Atari machines, /dev/nvram is always configured and does not need + to be selected. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -8121,7 +8385,7 @@ If you have a joystick, you can say Y here to enable generic joystick support. You will also need to say Y or M to at least one of the hardware specific joystick drivers. This will make the - joysticks available under /dev/jsX devices. Please read the file + joysticks available as /dev/jsX devices. Please read the file Documentation/joystick.txt which contains more information and the location of the joystick package that you'll need. @@ -8172,31 +8436,32 @@ ThrustMaster DirectConnect (BSP) joysticks CONFIG_JOY_THRUSTMASTER - Say Y here if you have a ThrustMaster Millenium 3D Inceptor, ThrustMaster - 3D Rage Pad, or ThrustMaster WCS III. For more information on how to use the - driver please read Documentation/joystick.txt + Say Y here if you have a ThrustMaster Millenium 3D Inceptor, + ThrustMaster 3D Rage Pad, or ThrustMaster WCS III. For more + information on how to use the driver please read + Documentation/joystick.txt NES, SNES, PSX, Multisystem gamepads CONFIG_JOY_CONSOLE Say Y here if you have a Nintendo Entertainment System gamepad, Super Nintendo Entertainment System gamepad, Sony PlayStation - gamepad or a Multisystem - Atari, Amiga, Commodore, Amstrad CPC + gamepad or a Multisystem -- Atari, Amiga, Commodore, Amstrad CPC joystick. For more information on how to use the driver please read Documentation/joystick.txt Sega, Multisystem gamepads CONFIG_JOY_DB9 Say Y here if you have a Sega Master System gamepad, Sega Genesis - gamepad, Sega Saturn gamepad, or a Multisystem - Atari, Amiga, + gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, Commodore, Amstrad CPC joystick. For more information on how to use the driver please read Documentation/joystick.txt TurboGraFX Multisystem joystick interface CONFIG_JOY_TURBOGRAFX - Say Y here if you have the TurboGraFX interface by Steffen Schwenke, and - want to use it with Multiststem - Atari, Amiga, Commodore, Amstrad CPC - joystick. For more information on how to use the driver please read - Documentation/joystick-parport.txt + Say Y here if you have the TurboGraFX interface by Steffen Schwenke, + and want to use it with Multiststem -- Atari, Amiga, Commodore, + Amstrad CPC joystick. For more information on how to use the driver + please read Documentation/joystick-parport.txt Amiga joysticks CONFIG_JOY_AMIGA @@ -8207,13 +8472,13 @@ Atomwide Serial Support CONFIG_ATOMWIDE_SERIAL If you have an Atomwide Serial card for an Acorn system, say Y to - this option. The driver can handle 1, 2, or 3 port cards. + this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N The Serial Port Dual Serial Port CONFIG_DUALSP_SERIAL If you have the Serial Port's dual serial card for an Acorn system, - say Y to this option. If unsure, say N + say Y to this option. If unsure, say N Sound card support CONFIG_SOUND @@ -8240,9 +8505,8 @@ I'm told that even without a sound card, you can make your computer say more than an occasional beep, by programming the PC speaker. - Kernel patches and programs to do that are in the pcsndrv package on - ftp://sunsite.unc.edu/pub/Linux/kernel/patches/console/ and in the - pcsp patch at http://www.imladris.demon.co.uk/pcsp/ + Kernel patches and supporting utilities to do that are in the pcsp + package, available at http://www.imladris.demon.co.uk/pcsp/. OSS sound modules CONFIG_SOUND_OSS @@ -8267,7 +8531,7 @@ ProAudioSpectrum 16 support CONFIG_SOUND_PAS Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio - 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have + 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have some other card made by Media Vision or Logitech since they are not PAS16 compatible. @@ -8277,7 +8541,7 @@ Creative Labs or a 100% hardware compatible clone (like the Thunderboard or SM Games). If your card was in the list of supported cards look at the card specific instructions in the - drivers/sound/Readme.cards file before answering this question. For + drivers/sound/Readme.cards file before answering this question. For an unknown card you may answer Y if the card claims to be Sound Blaster-compatible. @@ -8330,12 +8594,17 @@ instructions in the drivers/sound/Readme.cards file. It's safe to answer Y if you have a true MPU401 MIDI interface card. -6850 UART Midi support +6850 UART support CONFIG_SOUND_UART6850 This option enables support for MIDI interfaces based on the 6850 - UART chip. This interface is rarely found on sound cards. It's safe + UART chip. This interface is rarely found on sound cards. It's safe to answer N to this question. +VIDC Sound +CONFIG_VIDC_SOUND + Say Y here for ARM systems with the VIDC video controller and 16-bit + Linear sound DACs. If unsure, say N. + PSS (AD1848, ADSP-2115, ESC614) support CONFIG_SOUND_PSS Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven @@ -8357,8 +8626,8 @@ Have DSPxxx.LD firmware file CONFIG_PSS_HAVE_BOOT - If you have the DSPxxx.LD file or SYNTH.LD file for you card, answer - Y to include this file. Without this file the synth device (OPL) may + If you have the DSPxxx.LD file or SYNTH.LD file for you card, say Y + to include this file. Without this file the synth device (OPL) may not work. Full pathname of DSPxxx.LD firmware file @@ -8369,7 +8638,7 @@ 16 bit sampling option of GUS (_NOT_ GUS MAX) CONFIG_SOUND_GUS16 Answer Y if you have installed the 16 bit sampling daughtercard on - your GUS. Answer N if you have a GUS MAX, since saying Y here + your GUS. Answer N if you have a GUS MAX, since saying Y here disables GUS MAX support. GUS MAX support @@ -8378,10 +8647,10 @@ Microsoft Sound System support CONFIG_SOUND_MSS - Again think carefully before answering Y to this question. It's - safe to answer Y if you have the original Windows Sound System card - made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may - answer Y in case your card is NOT among these: + Again think carefully before answering Y to this question. It's safe + to answer Y if you have the original Windows Sound System card made + by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may say Y + in case your card is NOT among these: ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16, Ensoniq SoundScape (and compatibles made by Reveal and Spea), @@ -8448,27 +8717,33 @@ Support MIDI in older MAD16 based cards (requires SB) CONFIG_MAD16_OLDCARD - Answer Y (or M) if you have an older card based on the C928 - or Mozart chipset and you want to have MIDI support. If you - enable this option you also need to enable support for Sound Blaster. + Answer Y (or M) if you have an older card based on the C928 or + Mozart chipset and you want to have MIDI support. If you enable this + option you also need to enable support for Sound Blaster. Support for Crystal CS4232 based (PnP) cards CONFIG_SOUND_CS4232 Say Y here if you have a card based on the Crystal CS4232 chip set, - which uses its own Plug and Play protocol. See - Documentation/sound/CS4232 for more information on configuring this - card. + which uses its own Plug and Play protocol. + + See Documentation/sound/CS4232 for more information on configuring + this card. + +Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards +CONFIG_SOUND_OPL3SA2 + Say Y or M here if you have such a sound card. Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers CONFIG_SOUND_MAUI - Say Y here if you have a Turtle Beach Wave Front, Maui, or - Tropez sound card. + Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez + sound card. Have OSWF.MOT firmware file CONFIG_MAUI_HAVE_BOOT - Turtle Beach Maui and Tropez sound cards have a microcontroller which - needs to be initialized prior to use. OSWF.MOT is a file distributed - with the card's DOS/Windows drivers. Answer Y if you have this file. + Turtle Beach Maui and Tropez sound cards have a microcontroller + which needs to be initialized prior to use. OSWF.MOT is a file + distributed with the card's DOS/Windows drivers. Answer Y if you + have this file. Full pathname of OSWF.MOT firmware file CONFIG_MAUI_BOOT_FILE @@ -8477,22 +8752,23 @@ Support for Turtle Beach MultiSound Classic, Tahiti, Monterey CONFIG_SOUND_MSNDCLAS Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or - Monterey (not for the Pinnacle or Fiji). See - Documentation/sound/MultiSound for important information about this - driver. + Monterey (not for the Pinnacle or Fiji). + + See Documentation/sound/MultiSound for important information about + this driver. Full pathname of MSNDINIT.BIN firmware file CONFIG_MSNDCLAS_INIT_FILE The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See Documentation/sound/MultiSound for + operation, and are not currently included. These files can be + obtained from Turtle Beach. See Documentation/sound/MultiSound for information on how to obtain this. Full pathname of MSNDPERM.BIN firmware file CONFIG_MSNDCLAS_PERM_FILE The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See Documentation/sound/MultiSound for + operation, and are not currently included. These files can be + obtained from Turtle Beach. See Documentation/sound/MultiSound for information on how to obtain this. Support for Turtle Beach MultiSound Pinnacle, Fiji @@ -8504,61 +8780,61 @@ Full pathname of PNDSPINI.BIN firmware file CONFIG_MSNDPIN_INIT_FILE The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See Documentation/sound/MultiSound for + operation, and are not currently included. These files can be + obtained from Turtle Beach. See Documentation/sound/MultiSound for information on how to obtain this. Full pathname of PNDSPERM.BIN firmware file CONFIG_MSNDPIN_PERM_FILE The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See Documentation/sound/MultiSound for + operation, and are not currently included. These files can be + obtained from Turtle Beach. See Documentation/sound/MultiSound for information on how to obtain this. MSND Pinnacle have S/PDIF I/O CONFIG_MSNDPIN_DIGITAL - If you have the S/PDIF daughterboard for the Pinnacle or Fiji, say Y - here; otherwise, say N. If you have this, you will be able to play - and record from the S/PDIF port (digital signal). See + If you have the S/PDIF daughter board for the Pinnacle or Fiji, + answer Y here; otherwise, say N. If you have this, you will be able + to play and record from the S/PDIF port (digital signal). See Documentation/sound/MultiSound for information on how to make use of this capability. MSND Pinnacle non-PnP Mode CONFIG_MSNDPIN_NONPNP The Pinnacle and Fiji card resources can be configured either with - PnP, or through a configuration port. For the Pinnacle, - configuration in non-PnP mode allows use of the IDE and joystick - peripherals on the card as well, since they do not show up when the - card is in PnP mode. Specifying zero for any resource of a device - will disable the device. If you are running the card in PnP mode, - you must say N here and use isapnptools to configure the card's - resources. + PnP, or through a configuration port. Say Y here if your card is NOT + in PnP mode. For the Pinnacle, configuration in non-PnP mode allows + use of the IDE and joystick peripherals on the card as well; these + do not show up when the card is in PnP mode. Specifying zero for any + resource of a device will disable the device. If you are running the + card in PnP mode, you must say N here and use isapnptools to + configure the card's resources. MSND Pinnacle config port CONFIG_MSNDPIN_CFG - This is the port which the Pinnacle and Fiji uses to configure - the card's resources when not in PnP mode. If your card is in - PnP mode, then be sure to say N to the previous option, - CONFIG_MSNDPIN_NONPNP. + This is the port which the Pinnacle and Fiji uses to configure the + card's resources when not in PnP mode. If your card is in PnP mode, + then be sure to say N to the previous option, "MSND Pinnacle Non-PnP + Mode". MSND buffer size (kB) CONFIG_MSND_FIFOSIZE Configures the size of each audio buffer, in kilobytes, for recording and playing in the MultiSound drivers (both the Classic - and Pinnacle). Larger values reduce the chance of data overruns at + and Pinnacle). Larger values reduce the chance of data overruns at the expense of overall latency. If unsure, use the default. /dev/dsp and /dev/audio support CONFIG_SOUND_AUDIO - Answering N disables /dev/dsp and /dev/audio, the A/D and D/A - converter devices. Answer N only if you know you will not need - the option. They are usually required. Answer Y. + If you say Y here, you will get the /dev/dsp and /dev/audio devices; + these are the analog-digital and digital-analog converter devices + and are very useful, so say Y. MIDI interface support CONFIG_SOUND_MIDI Answering N disables /dev/midixx devices and access to any MIDI ports using /dev/sequencer and /dev/music. This option also affects - any MPU401 and/or General MIDI compatible devices. Answer Y. + any MPU401 and/or General MIDI compatible devices. Answer Y. FM synthesizer (YM3812/OPL-3) support CONFIG_SOUND_YM3812 @@ -8578,14 +8854,14 @@ ACI mixer (miroPCM12) CONFIG_ACI_MIXER - Audio Command Interface (ACI) driver. ACI is a protocol used to - communicate with the microcontroller on some sound cards produced - by miro, e.g. the miroSOUND PCM12 and PCM20. The main function - of the ACI is to control the mixer and to get a product - identification. This Voxware ACI driver currently only supports - the ACI functions on the miroSOUND PCM12 card. On the PCM20, ACI - also controls the radio tuner on this card, however this is not - yet supported in this software. + Audio Command Interface (ACI) driver. ACI is a protocol used to + communicate with the microcontroller on some sound cards produced by + miro, e.g. the miroSOUND PCM12 and PCM20. The main function of the + ACI is to control the mixer and to get a product identification. + This Voxware ACI driver currently only supports the ACI functions on + the miroSOUND PCM12 card. On the PCM20, ACI also controls the radio + tuner on this card, however this is not yet supported in this + software. SB32/AWE support CONFIG_AWE32_SYNTH @@ -8623,7 +8899,7 @@ Audio Excel DSP 16 (MSS emulation) CONFIG_AEDSP16_MSS Answer Y if you want your audio card to emulate Microsoft Sound - System. You should then say Y to "Microsoft Sound System support" + System. You should then say Y to "Microsoft Sound System support" and say N to "Audio Excel DSP 16 (SBPro emulation)". Audio Excel DSP 16 (SBPro emulation) @@ -8644,6 +8920,10 @@ This driver differs slightly from OSS/Free, so PLEASE READ Documentation/sound/es1370. +Joystick support at boot time +CONFIG_SOUND_ES1370_JOYPORT_BOOT + Say Y here to use the joystick port of your sound card. + Ensoniq ES1371 based PCI sound cards CONFIG_SOUND_ES1371 Say Y or M if you have a PCI sound card utilizing the Ensoniq @@ -8663,6 +8943,25 @@ differs slightly from OSS/Free, so PLEASE READ Documentation/sound/sonicvibes. +Are you using a crosscompiler +CONFIG_CROSSCOMPILE + Say Y here if you are compiling the kernel on a different + architecture than the one it is intended to run on. + +Build fp exception handler module +CONFIG_MIPS_FPE_MODULE + Build the floating point exception handler module. This option is + only useful for people working on the floating point exception + handler. If you don't, say N. + +Remote GDB kernel debugging +CONFIG_REMOTE_DEBUG + If you say Y here, it will be possible to remotely debug the MIPS + kernel using gdb. This enlarges your kernel image disk size by + several megabytes and requires a machine with more than 16 MB, + better 32 MB RAM to avoid excessive linking time. This is only + useful for kernel hackers. If unsure, say N. + Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even @@ -8682,10 +8981,10 @@ modem/telephone connections, and that you can have voice conversations while downloading stuff. It only works if your computer is equipped with an ISDN card and both you and your service - provider purchased an ISDN line from the phone company. For - details, read http://alumni.caltech.edu/~dank/isdn/ on the WWW. (To - browse the WWW, you need to have access to a machine on the Internet - that has a program like lynx or netscape.) + provider purchased an ISDN line from the phone company. For details, + read http://alumni.caltech.edu/~dank/isdn/ on the WWW. (To browse + the WWW, you need to have access to a machine on the Internet that + has a program like lynx or netscape.) This driver allows you to use an ISDN-card for networking connections and as dialin/out device. The isdn-tty's have a built in @@ -8748,7 +9047,7 @@ line with two B-channels, 4B supports two ISDN lines. For running this card, additional firmware is necessary, which has to be downloaded into the card using a utility which is distributed - separately. See Documentation/isdn/README and README.icn for more + separately. See Documentation/isdn/README and README.icn for more information. If you want to compile this as a module ( = code which can be @@ -8785,104 +9084,116 @@ HiSax Support for Teles 16.0/8.0 CONFIG_HISAX_16_0 - This enables HiSax support for the Teles ISDN-cards S0-16.0, - S0-8 and many compatibles. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port/shmem settings. + This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8 + and many compatibles. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port/shmem settings. HiSax Support for Teles 16.3 or PNP or PCMCIA CONFIG_HISAX_16_3 - This enables HiSax support for the Teles ISDN-cards S0-16.3 - the Teles/Creatix PnP and the Teles PCMCIA. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + This enables HiSax support for the Teles ISDN-cards S0-16.3 the + Teles/Creatix PnP and the Teles PCMCIA. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for Teles 16.3c CONFIG_HISAX_TELES3C This enables HiSax support for the Teles ISDN-cards 16.3c. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for AVM A1 (Fritz) CONFIG_HISAX_AVM_A1 This enables HiSax support for the AVM A1 (aka "Fritz"). - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for Elsa ISA cards CONFIG_HISAX_ELSA - This enables HiSax support for the Elsa Mircolink ISA cards, - for the Elsa Quickstep series cards and Elsa PCMCIA. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + This enables HiSax support for the Elsa Mircolink ISA cards, for the + Elsa Quickstep series cards and Elsa PCMCIA. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for ITK ix1-micro Revision 2 CONFIG_HISAX_IX1MICROR2 This enables HiSax support for the ITK ix1-micro Revision 2 card. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for Eicon.Diehl Diva cards CONFIG_HISAX_DIEHLDIVA - This enables HiSax support for the Eicon.Diehl Diva none PRO versions - passive ISDN cards. + This enables HiSax support for the Eicon.Diehl Diva none PRO + versions passive ISDN cards. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for ASUSCOM cards CONFIG_HISAX_ASUSCOM This enables HiSax support for the AsusCom and their OEM versions passive ISDN cards. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for TELEINT cards CONFIG_HISAX_TELEINT This enables HiSax support for the TELEINT SA1 semiactiv ISDN card. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for Sedlbauer speed card/win-star CONFIG_HISAX_SEDLBAUER This enables HiSax support for the Sedlbauer passive ISDN cards. - See Documentation/isdn/README.HiSax on how to configure it - using the different cards, a different D-channel protocol, or - non-standard IRQ/port settings. + + See Documentation/isdn/README.HiSax on how to configure it using the + different cards, a different D-channel protocol, or non-standard + IRQ/port settings. HiSax Support for USR Sportster internal TA CONFIG_HISAX_SPORTSTER This enables HiSax support for the USR Sportster internal TA card. + See Documentation/isdn/README.HiSax on how to configure it using a different D-channel protocol, or non-standard IRQ/port settings. HiSax Support for MIC card CONFIG_HISAX_MIC - This enables HiSax support for the ITH MIC card. See - Documentation/isdn/README.HiSax on how to configure it using a + This enables HiSax support for the ITH MIC card. + + See Documentation/isdn/README.HiSax on how to configure it using a different D-channel protocol, or non-standard IRQ/port settings. HiSax Support for NETjet card CONFIG_HISAX_NETJET This enables HiSax support for the NetJet from Traverse - Technologies. See Documentation/isdn/README.HiSax on how to - configure it using a different D-channel protocol, or non-standard - IRQ/port settings. + Technologies. + + See Documentation/isdn/README.HiSax on how to configure it using a + different D-channel protocol, or non-standard IRQ/port settings. HiSax Support for Niccy PnP/PCI card CONFIG_HISAX_NICCY - This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. See - Documentation/isdn/README.HiSax on how to configure it using a + This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI. + + See Documentation/isdn/README.HiSax on how to configure it using a different D-channel protocol, or non-standard IRQ/port settings. HiSax Support for Am7930 (EXPERIMENTAL) @@ -8903,10 +9214,10 @@ CONFIG_DE_AOC If you want that the HiSax hardware driver sends messages to the upper level of the isdn code on each AOCD (Advice Of Charge, During - the call -- transmission of the fee information during a call) and on - each AOCE (Advice Of Charge, at the End of the call -- transmission - of fee information at the end of the call), say Y here. This works - only in Germany. + the call -- transmission of the fee information during a call) and + on each AOCE (Advice Of Charge, at the End of the call -- + transmission of fee information at the end of the call), say Y here. + This works only in Germany. Support for Australian Microlink service (not for std. EURO) CONFIG_HISAX_ML @@ -8935,7 +9246,7 @@ This enables support for the PCBIT ISDN-card. This card is manufactured in Portugal by Octal. For running this card, additional firmware is necessary, which has to be downloaded into the card - using a utility which is distributed separately. See + using a utility which is distributed separately. See Documentation/isdn/README and Documentation/isdn/README.pcbit for more information. @@ -8950,7 +9261,7 @@ driver currently builds only in a modularized version ( = code which can be inserted in and removed from the running kernel whenever you want, details in Documentation/modules.txt); the module will be - called sc.o. See Documentation/isdn/README.sc and + called sc.o. See Documentation/isdn/README.sc and http://www.spellcast.com for more information (to browse the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape). @@ -8965,7 +9276,7 @@ interface for this card is provided. In order to use this card, additional firmware is necessary, which has to be downloaded into the card using a utility which is distributed separately. Please - read the file Documentation/isdn/README.avmb1. + read the file Documentation/isdn/README.avmb1. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -8975,7 +9286,7 @@ Verbose reason code reporting (kernel size +=7K) CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON If you say Y here, the AVM B1 driver will give verbose reasons for - disconnecting. This will increase the size of the kernel by 7K. If + disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. IBM Active 2000 support (EXPERIMENTAL) @@ -9030,21 +9341,21 @@ # Amiga support CONFIG_AMIGA - This option enables support for the Amiga series of computers. If + This option enables support for the Amiga series of computers. If you plan to use this kernel on an Amiga, say Y here and browse the material available in Documentation/m68k; otherwise say N. Atari support CONFIG_ATARI This option enables support for the 68000-based Atari series of - computers (including the TT, Falcon and Medusa). If you plan to use + computers (including the TT, Falcon and Medusa). If you plan to use this kernel on an Atari, say Y here and browse the material available in Documentation/m68k; otherwise say N. Hades support CONFIG_HADES - This option enables support for the Hades Atari clone. If you plan to - use this kernel on a Hades, say Y here; otherwise say N. + This option enables support for the Hades Atari clone. If you plan + to use this kernel on a Hades, say Y here; otherwise say N. Macintosh support CONFIG_MAC @@ -9060,49 +9371,49 @@ 68020 support CONFIG_M68020 If you anticipate running this kernel on a computer with a MC68020 - processor, say Y. Otherwise, say N. Note that the 68020 requires a - 68851 MMU (= memory management unit) to run Linux/m68k. + processor, say Y. Otherwise, say N. Note that the 68020 requires a + 68851 MMU (Memory Management Unit) to run Linux/m68k. 68030 support CONFIG_M68030 If you anticipate running this kernel on a computer with a MC68030 - processor, say Y. Otherwise, say N. Note that a MC68EC030 will not - work, as it does not include an MMU (= memory management unit). + processor, say Y. Otherwise, say N. Note that a MC68EC030 will not + work, as it does not include an MMU (Memory Management Unit). 68040 support CONFIG_M68040 If you anticipate running this kernel on a computer with a MC68LC040 - or MC68040 processor, say Y. Otherwise, say N. Note that an - MC68EC040 will not work, as it does not include an MMU (= memory - management unit). + or MC68040 processor, say Y. Otherwise, say N. Note that an + MC68EC040 will not work, as it does not include an MMU (Memory + Management Unit). Use -m68040 flag for 68040 specific optimizations CONFIG_OPTIMIZE_040 If you will only be running this kernel on a 68040-series processor, - this will make the kernel run somewhat faster. However, it will no + this will make the kernel run somewhat faster. However, it will no longer run on a 68020 or 68030, no matter whether you included 68020 - and 68030 support or not. Say N unless the only processor you are + and 68030 support or not. Say N unless the only processor you are compiling support for is the 68040 (or 68LC040). 68060 support CONFIG_M68060 If you anticipate running this kernel on a computer with a MC68060 - processor, say Y. Otherwise, say N. + processor, say Y. Otherwise, say N. Use -m68060 flag for 68060 specific optimizations CONFIG_OPTIMIZE_060 If you will only be running this kernel on a 68060-series processor, - this will make the kernel run somewhat faster. However, it will no + this will make the kernel run somewhat faster. However, it will no longer run on a 68020, 68030 or 68040, no matter whether you - included support for those processors or not. Say N unless the only + included support for those processors or not. Say N unless the only processor you are compiling support for is the 68060. Advanced processor options CONFIG_ADVANCED_CPU - This gives you access to some advanced options for the CPU. The + This gives you access to some advanced options for the CPU. The defaults should be fine for most users, but these options may make it possible for you to improve performance somewhat if you know what - you are doing. Most users should say N to this question. + you are doing. Most users should say N to this question. Use read-modify-write instructions CONFIG_RMW_INSNS @@ -9122,7 +9433,7 @@ This enables support for automatic identification of Amiga expansion 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 + it will enlarge your kernel by about 10 KB. The identification information is also available through /proc/zorro (say Y to "/proc filesystem support"!). @@ -9132,13 +9443,13 @@ Amiga OCS chipset support CONFIG_AMIFB_OCS This enables support for the original Agnus and Denise video chips, - found in the Amiga 1000 and most A500's and A2000's. If you intend + found in the Amiga 1000 and most A500's and A2000's. If you intend to run Linux on any of these systems, say Y; otherwise say N. Amiga ECS chipset support CONFIG_AMIFB_ECS This enables support for the Enhanced Chip Set, found in later - A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If + A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If you intend to run Linux on any of these systems, say Y; otherwise say N. @@ -9146,31 +9457,31 @@ CONFIG_AMIFB_AGA This enables support for the Advanced Graphics Architecture (also known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T - and CD32. If you intend to run Linux on any of these systems, say Y; + and CD32. If you intend to run Linux on any of these systems, say Y; otherwise say N. Amiga GSP (TMS340x0) support CONFIG_AMIGA_GSP Include support for Amiga graphics cards that use the Texas - Instruments TMS340x0 GSP (= graphics signal processor) chips. Say Y + Instruments TMS340x0 GSP (Graphics Signal Processor) chips. Say Y if you want to use a DMI Resolver or Commodore A2410 (Lowell) graphics card on an Amiga; otherwise, say N. DMI Resolver support CONFIG_GSP_RESOLVER - Include support in the kernel for the DMI Resolver graphics card. If + Include support in the kernel for the DMI Resolver graphics card. If you have one, say Y; otherwise, say N. A2410 support CONFIG_GSP_A2410 Include support in the kernel for the Commodore/University of Lowell - A2410 graphics card. If you have one, say Y; otherwise, say N. + A2410 graphics card. If you have one, say Y; otherwise, say N. Amiga Zorro II ramdisk support CONFIG_AMIGA_Z2RAM This enables support for using Chip RAM and Zorro II RAM as a - ramdisk or as a swap partition. Say Y if you want to include this - driver in the kernel. This driver is also available as a module + ramdisk or as a swap partition. Say Y if you want to include this + driver in the kernel. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called z2ram.o. If you want to compile it as a module, say M here and read @@ -9219,13 +9530,13 @@ it in the kernel. Otherwise, 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). The module will be called - acsi_slm.o. Be warned: the driver needs much ST-RAM and can cause + acsi_slm.o. Be warned: the driver needs much ST-RAM and can cause problems due to that fact! A3000 WD33C93A support CONFIG_A3000_SCSI If you have an Amiga 3000 and have SCSI devices connected to the - built-in SCSI controller, say Y. Otherwise, say N. This driver is + built-in SCSI controller, say Y. Otherwise, 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). The module is called wd33c93.o. If you want to compile it as a module, say M here @@ -9233,19 +9544,19 @@ A2091 WD33C93A support CONFIG_A2091_SCSI - If you have a Commodore A2091 SCSI controller, say Y. Otherwise, - say N. This driver is also available as a module ( = code which can + If you have a Commodore A2091 SCSI controller, say Y. Otherwise, + 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). The module is called wd33c93.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. GVP Series II WD33C93A support CONFIG_GVP11_SCSI - If you have a Great Valley Products Series II SCSI controller, say - Y. Also say Y if you have a later model of GVP SCSI controller - (such as the GVP A4008 or a Combo board). Otherwise, say N. - This driver does NOT work for the T-Rex series of accelerators from - TekMagic and GVP-M. + If you have a Great Valley Products Series II SCSI controller, + answer Y. Also say Y if you have a later model of GVP SCSI + controller (such as the GVP A4008 or a Combo board). Otherwise, + answer N. This driver does NOT work for the T-Rex series of + accelerators from TekMagic and GVP-M. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -9255,36 +9566,36 @@ Cyberstorm SCSI support CONFIG_CYBERSTORM_SCSI If you have an Amiga with an original (MkI) Phase5 Cyberstorm - accelerator board and the optional Cyberstorm SCSI controller, say - Y. Otherwise, say N. + accelerator board and the optional Cyberstorm SCSI controller, + answer Y. Otherwise, say N. Cyberstorm II SCSI support CONFIG_CYBERSTORMII_SCSI If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board - and the optional Cyberstorm SCSI controller, say Y. Otherwise, say - N. + and the optional Cyberstorm SCSI controller, say Y. Otherwise, + answer N. Blizzard 2060 SCSI support CONFIG_BLZ2060_SCSI If you have an Amiga with a Phase5 Blizzard 2060 accelerator board - and want to use the onboard SCSI controller, say Y. Otherwise, say - N. + and want to use the onboard SCSI controller, say Y. Otherwise, + answer N. Blizzard 1230IV/1260 SCSI support CONFIG_BLZ1230_SCSI If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard - 1260 accelerator, and the optional SCSI module, say Y. Otherwise, + 1260 accelerator, and the optional SCSI module, say Y. Otherwise, say N. Blizzard PowerUP 603e+ SCSI support CONFIG_BLZ603EPLUS_SCSI If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+ - accelerator, say Y. Otherwise, say N. + accelerator, say Y. Otherwise, say N. Fastlane SCSI support CONFIG_FASTLANE_SCSI If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use - one in the near future, say Y to this question. Otherwise, say N. + one in the near future, say Y to this question. Otherwise, say N. Atari native SCSI support CONFIG_ATARI_SCSI @@ -9294,7 +9605,7 @@ available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called atari_scsi.o. If you want to compile it as a module, say M here and - read Documentation/modules.txt. This driver supports both styles of + read Documentation/modules.txt. This driver supports both styles of NCR integration into the system: the TT style (separate DMA), and the Falcon style (via ST-DMA, replacing ACSI). It does NOT support other schemes, like in the Hades (without DMA). @@ -9316,7 +9627,7 @@ Ariadne support CONFIG_ARIADNE - If you have a Village Tronic Ariadne Ethernet adapter, say Y. + If you have a VillageTronics Ariadne Ethernet adapter, say Y. Otherwise, say N. This driver is also available as a module ( = code which can be @@ -9326,7 +9637,7 @@ Ariadne II support CONFIG_ARIADNE2 - If you have a Village Tronic Ariadne II Ethernet adapter, say Y. + If you have a VillageTronics Ariadne II Ethernet adapter, say Y. Otherwise, say N. This driver is also available as a module ( = code which can be @@ -9336,7 +9647,7 @@ A2065 support CONFIG_A2065 - If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, + If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise, say N. This driver is also available as a module ( = code which can be @@ -9346,7 +9657,7 @@ Hydra support CONFIG_HYDRA - If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. + If you have a Hydra Ethernet adapter, say Y. Otherwise, say N. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -9374,7 +9685,7 @@ Multiface Card III parallel support CONFIG_MULTIFACE_III_LP If you have a Multiface III card for your Amiga, and want to use its - parallel port in Linux, say Y. Otherwise, say N. + parallel port in Linux, say Y. Otherwise, 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). @@ -9383,7 +9694,7 @@ Amiga mouse support CONFIG_AMIGAMOUSE - If you want to be able to use an Amiga mouse in Linux, say Y. + If you want to be able to use an Amiga mouse in Linux, say Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9393,13 +9704,13 @@ Amiga Copper Console CONFIG_COPCON This configures the console to use the Amiga's graphics coprocessor - for scrolling, instead of using the CPU. This option markedly + for scrolling, instead of using the CPU. This option markedly improves response times in the high color modes (5 bitplanes and - up). If you would like to use this, say Y; otherwise, say N. + up). If you would like to use this, say Y; otherwise, say N. Atari mouse support CONFIG_ATARIMOUSE - If you want to be able to use an Atari mouse in Linux, say Y. + If you want to be able to use an Atari mouse in Linux, say Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9426,7 +9737,7 @@ LAN) and like to use them under Linux, say Y. All built-in SCC's are supported (TT, MegaSTE, Falcon), and also the ST-ESCC. If you have two connectors for channel A (Serial2 and LAN), they are visible as - two separate devices. + two separate devices. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9435,9 +9746,9 @@ Atari SCC serial DMA support CONFIG_ATARI_SCC_DMA - This enables DMA support for receiving data on channel A of the - SCC. If you have a TT you may say Y here and read - drivers/char/atari_SCC.README. All other users should say N here, + This enables DMA support for receiving data on channel A of the SCC. + If you have a TT you may say Y here and read + drivers/char/atari_SCC.README. All other users should say N here, because only the TT has SCC-DMA, even if your machine keeps claiming so at boot time. @@ -9452,19 +9763,19 @@ 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. + 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 + 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 - Y. + If you want to use your Amiga's built-in serial port in Linux, + answer Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you @@ -9478,8 +9789,8 @@ Multiface Card III serial support CONFIG_MULTIFACE_III_TTY - If you want to use a Multiface III card's serial port in Linux, say - Y. + If you want to use a Multiface III card's serial port in Linux, + answer Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9489,8 +9800,8 @@ Amiga or Atari DMA sound support CONFIG_DMASOUND If you want to use the internal audio of your Atari or Amiga in - Linux, answer Y to this question. This will provide a Sun-like - /dev/audio, compatible with the Linux/i386 sound system. Otherwise, + Linux, answer Y to this question. This will provide a Sun-like + /dev/audio, compatible with the Linux/i386 sound system. Otherwise, say N. This driver is also available as a module ( = code which can be @@ -9501,41 +9812,40 @@ MSDOS partition support CONFIG_MSDOS_PARTITION This option enables support for using hard disks that were - partitioned on an MS-DOS system. This may be useful if you are + partitioned on an MS-DOS system. This may be useful if you are sharing a hard disk between i386 and m68k Linux boxes, for example. Say Y if you need this feature; users who are only using their system-native partitioning scheme can say N here. Processor Type CONFIG_6xx - There are two types of PowerPC chips supported. The more common + There are two types of PowerPC chips supported. The more common types (601,603,604,740,750) and the embedded versions (821 and 860). - Unless you are building a kernel for one of the embedded boards using - the 821 or 860 choose 6xx. + Unless you are building a kernel for one of the embedded boards + using the 821 or 860 choose 6xx. Machine Type CONFIG_PMAC Linux currently supports several different kinds of PowerPC-based - machines: Apple Power Macintoshes and clones (such as the - Motorola Starmax series), PReP (PowerPC Reference Platform) machines - such as the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP - and the embedded MBX boards from Motorola. Currently, a single - kernel binary only supports one type or the other. However, there is - very early work on support for CHRP, PReP and PowerMac's from a - single binary. + machines: Apple Power Macintoshes and clones (such as the Motorola + Starmax series), PReP (PowerPC Reference Platform) machines such as + the Motorola PowerStack, Amiga Power-Up systems (APUS), CHRP and the + embedded MBX boards from Motorola. Currently, a single kernel binary + only supports one type or the other. However, there is very early + work on support for CHRP, PReP and PowerMac's from a single binary. Support for Open Firmware device tree in /proc CONFIG_PROC_DEVICETREE This option adds a device-tree directory under /proc which contains an image of the device tree that the kernel copies from Open - Firmware. If unsure, say Y here. + Firmware. If unsure, say Y here. MESH (Power Mac internal SCSI) support CONFIG_SCSI_MESH Many Power Macintoshes and clones have a MESH (Macintosh Enhanced SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the - other Power Macintoshes do). Say Y to include support for this SCSI - adaptor. This driver is also available as a module called mesh.o + other Power Macintoshes do). Say Y to include support for this SCSI + adaptor. This driver is also available as a module called mesh.o ( = 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. @@ -9545,18 +9855,18 @@ On Power Macintoshes (and clones) where the MESH SCSI bus adaptor drives a bus which is entirely internal to the machine (such as the 7500, 7600, 8500, etc.), the MESH is capable of synchronous - operation at up to 10MB/s. On machines where the SCSI bus + operation at up to 10 MB/s. On machines where the SCSI bus controlled by the MESH can have external devices connected, it is - usually rated at 5MB/s. 5 is a safe value here unless you know the - MESH SCSI bus is internal only; in that case you can say 10. Say 0 + usually rated at 5 MB/s. 5 is a safe value here unless you know the + MESH SCSI bus is internal only; in that case you can say 10. Say 0 to disable synchronous operation. 53C94 (Power Mac external SCSI) support CONFIG_SCSI_MAC53C94 On Power Macintoshes (and clones) with two SCSI buses, the external - SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older + SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older machines which only have one SCSI bus, such as the 7200, also use - the 53C94. Say Y to include support for the 53C94. + the 53C94. Say Y to include support for the 53C94. This driver is also available as a module called mac53c94.o ( = code which can be inserted in and removed from the running kernel @@ -9567,7 +9877,7 @@ CONFIG_MACE Power Macintoshes and clones with Ethernet built-in on the motherboard will usually use a MACE (Medium Access Control for - Ethernet) interface. Say Y to include support for the MACE chip. + Ethernet) interface. Say Y to include support for the MACE chip. BMAC (G3 ethernet) support CONFIG_BMAC @@ -9600,7 +9910,7 @@ RadioTrack II driver below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9614,7 +9924,7 @@ RadioTrack i/o port CONFIG_RADIO_RTRACK_PORT - Enter either 0x30f or 0x20f here. The card default is 0x30f, if you + Enter either 0x30f or 0x20f here. The card default is 0x30f, if you haven't changed the jumper setting on the card. AIMSlab RadioTrack II support @@ -9623,7 +9933,7 @@ port address below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9636,7 +9946,7 @@ RadioTrack II i/o port CONFIG_RADIO_RTRACK2_PORT - Enter either 0x30c or 0x20c here. The card default is 0x30c, if you + Enter either 0x30c or 0x20c here. The card default is 0x30c, if you haven't changed the jumper setting on the card. Aztech/Packard Bell Radio @@ -9645,7 +9955,7 @@ in the port address below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9658,8 +9968,8 @@ Aztech/Packard Bell radio card i/o port CONFIG_RADIO_AZTECH_PORT - Enter either 0x350 or 0x358 here. The card default is 0x350, if you - haven't changed the setting of jumper JP3 on the card. Removing the + Enter either 0x350 or 0x358 here. The card default is 0x350, if you + haven't changed the setting of jumper JP3 on the card. Removing the jumper sets the card to 0x358. SF16FMI Radio @@ -9668,7 +9978,7 @@ in the port address below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9689,7 +9999,7 @@ in the port address below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9710,7 +10020,7 @@ in the port address below. In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on + that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, you need to have access to a machine on the Internet that has a @@ -9769,17 +10079,17 @@ CPU Optimization CONFIG_CPU_ARM2 - This selects the processor type of your CPU. This is only used to + This selects the processor type of your CPU. This is only used to determine C compiler optimization options, and can affect the - compatibility of the kernel on other processors. If you specify - ARM6, the kernel should work on all 32-bit processors. If you + compatibility of the kernel on other processors. If you specify + ARM6, the kernel should work on all 32-bit processors. If you specify ARM2, ARM250 or ARM3, it should work on all 26-bit - processors. If you're not sure, set it to "None". + processors. If you're not sure, set it to "None". ARM System type CONFIG_ARCH_ARC - This selects what ARM system you wish to build the kernel for. It - also selects to some extent the CPU type. If you are unsure what + This selects what ARM system you wish to build the kernel for. It + also selects to some extent the CPU type. If you are unsure what to set this option to, please consult any information supplied with your system. @@ -9795,51 +10105,6 @@ it will give useful debugging/error results. If you don't debug the kernel, you can say N. -VIDC Sound -CONFIG_VIDC_SOUND - Say 'Y' here for ARM systems with the VIDC video controller and 16-bit - Linear sound DACs. If unsure, say N. - -Backward compatibility mode for Xpmac -CONFIG_FB_COMPAT_XPMAC - If you use the Xpmac X server (common with mklinux), you'll need - to enable this to use X. You should consider changing to XFree86 - which includes a server that supports the frame buffer device - directly (XF68_FBDev). - -Support for PowerMac keyboard -CONFIG_MAC_KEYBOARD - This option allows you to use an ADB keyboard attached to your - machine. Note that this disables any other (ie. PS/2) keyboard - support, even if your machine is physically capable of using both - at the same time. - - If you use an ADB keyboard (4 pin connector), say Y here. - If you use a PS/2 keyboard (6 pin connector), say N here. - -Support for PowerMac floppy -CONFIG_MAC_FLOPPY - If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) - floppy controller, say Y here. Most commonly found in PowerMacs. - -Support for PowerMac serial ports -CONFIG_MAC_SERIAL - If you have Macintosh style serial ports (8 pin mini-DIN), this - is the driver for them. If you also have regular serial ports - and enable the driver for them, you can't currently use the - serial console feature. - -Support for PowerMac ADB mouse -CONFIG_ADBMOUSE - If you have an ADB mouse (4 pin connector) as is common on - Macintoshes, say Y here. - -Winbond SL82c105 support -CONFIG_BLK_DEV_SL82C105 - If you have a Winbond SL82c105 IDE controller, say Y here to - enable special configuration for this chip. This is common - on various CHRP motherboards, but could be used elsewhere. - If in doubt, say Y. # # A couple of things I keep forgetting: # capitalize: AppleTalk, Ethernet, DMA, FTP, Internet, Intel, IRQ, @@ -9891,13 +10156,13 @@ # LocalWords: RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff # LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress # LocalWords: ICL EtherTeam ETH IDESCSI TXC SmartRAID SmartCache httpd sjc dlp -# LocalWords: thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ chipsets MG +# LocalWords: thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern # LocalWords: bsd comp SPARCstation le SunOS ie Gracilis PackeTwin PT pt LU FX # LocalWords: FX TEAC CR LCS mS ramdisk IDETAPE cmd fperllo encis tcfs unisa # LocalWords: Vertos Genoa Funai hsfs NCP NetWare tgz APM apm ioctls UltraLite # LocalWords: TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrecord pg # LocalWords: PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT -# LocalWords: KERNELD kerneld callouts AdvanSys advansys Admin WDT DataStor EP +# LocalWords: kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden # LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI # LocalWords: QD qd UMC umc ALI ali lena fnet fr azstarnet axplinux cdr fb MDA # LocalWords: Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC @@ -9948,7 +10213,7 @@ # LocalWords: INSNS Ataris AutoConfig ZORRO OCS AMIFB Agnus Denise ECS CDTV GB # LocalWords: AGA Cybervision CYBER GSP TMS DMI Zorro ACSI ROMs SLM BioNet GVP # LocalWords: PAMsNet TekMagic Cyberstorm MkI CYBERSTORMII MkII BLZ onboard cx -# LocalWords: Village Tronic ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB +# LocalWords: VillageTronics ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB # LocalWords: Rhotron BioData's Multiface AMIGAMOUSE COPCON Amiga's bitplanes # LocalWords: ATARIMOUSE MFPSER SCC's MegaSTE ESCC Atari's GVPIOEXT DMASOUND # LocalWords: fdutils cisco univercd rpcg htm iface lapb LAPBETHER tpqic qic @@ -9971,7 +10236,7 @@ # LocalWords: zorro CAPI AVMB capi avmb VP SYN syncookies EM em pc Ethertalk # LocalWords: Dayna DL Daynatalk LT PhoneNET ATB Daystar queueing CMDS SCBs ls # LocalWords: SCB STATS Thinnet ThunderLAN TLAN Netelligent NetFlex tlan james -# LocalWords: caldera Preload dcache Preloading slowdowns schoebel uni NBD nbd +# LocalWords: caldera Preload Preloading slowdowns schoebel uni NBD nbd prog # LocalWords: stuttgart rdist TRANS hostnames mango jukeboxes ESS userland PD # LocalWords: hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid # LocalWords: transname filespace adm Nodename hostname uname Kernelname bootp @@ -10033,6 +10298,19 @@ # LocalWords: CyberVision Cirrus PowerBooks Topcat SBUS CGsix TurboGX BWtwo SS # LocalWords: CGthree TCX unswapable vfb fbcon hicolor truecolor AFB ILBM SOC # LocalWords: IPLAN gracilis Fibre SBus SparcSTORAGE SV jnewbigin swin QNX qnx -# LocalWords: PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss -# LocalWords: synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX -# LocalWords: PowerMac's BMAC radiotrack rtrack miropcm +# LocalWords: PTY PTYS ptyxx ttyxx PTYs ssh sb Avance ALS pss pvv kerneli hd +# LocalWords: synth WaveFront MSND NONPNP AudioExcelDSP STRAM APUS CHRP MBX Nx +# LocalWords: PowerMac's BMAC radiotrack rtrack miropcm OFFBOARD HPT UDMA DVD +# LocalWords: hpt fokus gmd Cyrix DXL SLC DLC NexGen MediaGX GXm IDT WinChip +# LocalWords: MMX MII valkyrie mdacon vdolive VDOLive cuseeme CU hippi rrunner +# LocalWords: SeeMe ipmasqadm juanjox ipmarkfw markfw TNCs Microdyne rhine lib +# LocalWords: libc jsX gamepad gameport CHF FCS FPGaming MadCatz ASSASIN GrIP +# LocalWords: Assasin gamepads GamePad PDPI gamecards gamecard WingMan BSP WCS +# LocalWords: ThunderPad CyberMan SideWinder ThrustMaster DirectConnect NES XF +# LocalWords: Millenium SNES PSX Multisystem Nintendo PlayStation Amstrad CPC +# LocalWords: Sega TurboGraFX Steffen Schwenke Multiststem PDIF FIFOSIZE EPLUS +# LocalWords: PowerUP RoadRunner tahallah dos functionkey setterm imladris Woz +# LocalWords: PowerMacs Winbond Algorithmics ALGOR algor ECOFF IRIX SGI SGI's +# LocalWords: gfx virtualized Xpmac mklinux XFree FBDev Woodhouse mvhi Seeq fp +# LocalWords: SGISEEQ HIgh ADB ADBMOUSE crosscompiler CROSSCOMPILE FPE GDB gdb +# LocalWords: JOYPORT rp spoofing DawiControl NOGENSUPP EEPROM HSSI diff -u --recursive --new-file v2.1.127/linux/Documentation/mca.txt linux/Documentation/mca.txt --- v2.1.127/linux/Documentation/mca.txt Fri Oct 23 22:01:18 1998 +++ linux/Documentation/mca.txt Sun Nov 8 13:29:31 1998 @@ -279,8 +279,8 @@ Slot 6: ff ff ff ff ff ff ff ff Slot 7: 42 60 ff 08 ff ff ff ff 3Com 3c523 Etherlink/MC Slot 8: ff ff ff ff ff ff ff ff -Video: ff ff ff ff ff ff ff ff -SCSI: ff ff ff ff ff ff ff ff +Video : ff ff ff ff ff ff ff ff +SCSI : ff ff ff ff ff ff ff ff /proc/mca/slot1: Slot: 1 diff -u --recursive --new-file v2.1.127/linux/Documentation/sysctl/kernel.txt linux/Documentation/sysctl/kernel.txt --- v2.1.127/linux/Documentation/sysctl/kernel.txt Wed Jun 24 22:54:02 1998 +++ linux/Documentation/sysctl/kernel.txt Wed Nov 11 11:49:59 1998 @@ -15,6 +15,7 @@ before actually making adjustments. Currently, these files are in /proc/sys/kernel: +- acct - ctrl-alt-del - dentry-state - domainname @@ -33,6 +34,23 @@ - reboot-cmd ==> SPARC specific - securelevel - version + +============================================================== + +acct: + +highwater lowwater frequency + +If BSD-style process accounting is enabled these values control +its behaviour. If free space on filesystem where the log lives +goes below % accounting suspends. If free space gets +above % accounting resumes. determines +how often do we check the amount of free space (value is in +seconds). Default: +4 2 30 +That is, suspend accounting if there left <= 2% free; resume it +if we got >=4%; consider information about amount of free space +valid for 30 seconds. ============================================================== diff -u --recursive --new-file v2.1.127/linux/Documentation/video4linux/bttv/INSTALL linux/Documentation/video4linux/bttv/INSTALL --- v2.1.127/linux/Documentation/video4linux/bttv/INSTALL Wed Aug 26 11:37:33 1998 +++ linux/Documentation/video4linux/bttv/INSTALL Sun Nov 8 14:36:46 1998 @@ -20,6 +20,7 @@ 5: Philips PAL tuner 6: Temic NTSC tuner 7: Temic PAL tuner + 8: Temic 4036 FY5 NTSC tuner The number corresponds to the number (-1) given at the GPIO port of the Bt848 on Miro cards. @@ -34,7 +35,12 @@ 4: Intel 5: Diamond 6: AVerMedia - + 7: Matrix Vision MV-Delta + 8: Fly Video II + 9: TurboTV + 10: Newer Hauppage (Bt878) + 11: Miro PCTV Pro + 12: ADS Tech Channel Surfer TV (and maybe TV+FM) - You may have to adjust BTTV_MAJOR to a different number depending on your kernel version. The official number 81 does not work on some setups. diff -u --recursive --new-file v2.1.127/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.127/linux/MAINTAINERS Sun Nov 8 14:02:41 1998 +++ linux/MAINTAINERS Sun Nov 8 13:29:48 1998 @@ -204,7 +204,7 @@ L: linux-kernel@vger.rutgers.edu S: Maintained -DIGI INTL. EPCA DRIVER: +DIGI INTL. EPCA DRIVER P: Daniel Taylor M: support@dgii.com M: digilnux@dgii.com @@ -277,7 +277,7 @@ L: linux-net@vger.rutgers.edu S: Maintained -FTAPE/QIC-117: +FTAPE/QIC-117 P: Claus-Justus Heine M: claus@momo.math.rwth-aachen.de L: linux-tape@vger.rutgers.edu @@ -297,7 +297,7 @@ W: http://www.icp-vortex.com/ S: Supported -HAYES ESP SERIAL DRIVER: +HAYES ESP SERIAL DRIVER P: Andrew J. Robinson M: arobinso@nyx.net L: linux-kernel@vger.rutgers.edu @@ -396,14 +396,14 @@ L: linux-pmac@samba.anu.edu.au S: Maintained -M68K: +M68K P: Jes Sorensen M: Jes.Sorensen@cern.ch W: http://www.clark.net/pub/lawrencc/linux/index.html L: linux-m68k@lists.linux-m68k.org S: Maintained -M68K ON APPLE MACINTOSH: +M68K ON APPLE MACINTOSH P: Alan Cox M: Alan.Cox@linux.org W: http://www.mac.linux-m68k.org/home.html @@ -416,19 +416,26 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp S: Maintained -MENUCONFIG: +MENUCONFIG P: Michael Elizabeth Chastain M: mec@shout.net L: linux-kernel@vger.rutgers.edu S: Maintained -MIPS: +MIPS P: Ralf Baechle M: ralf@gnu.ai.mit.edu W: http://lena.fnet.fr/ L: linux-mips@fnet.fr S: Maintained +MISCELLANEOUS MCA-SUPPORT +P: David Weinehall +M: mcalinux@acc.umu.se (project MCA-team) +M: tao@acc.umu.se (personal) +L: linux-kernel@vger.rutgers.edu +S: Maintained + MODULE SUPPORT [GENERAL], KERNELD P: Richard Henderson M: richard@gnu.ai.mit.edu @@ -446,7 +453,7 @@ M: andrewtv@usa.net S: Maintained -NCP FILESYSTEM: +NCP FILESYSTEM P: Petr Vandrovec M: vandrove@vc.cvut.cz P: Volker Lendecke @@ -465,14 +472,14 @@ M: pavel@atrey.karlin.mff.cuni.cz S: Maintained -NETWORKING [GENERAL]: +NETWORKING [GENERAL] P: Networking Teak M: netdev@nuclecu.unam.mx L: linux-net@vger.rutgers.edu W: http://www.uk.linux.org/NetNews.html (2.0 only) S: Maintained -NETWORKING [IPv4/IPv6]: +NETWORKING [IPv4/IPv6] P: David S. Miller M: davem@caip.rutgers.edu P: Eric Schenk @@ -565,7 +572,7 @@ L: linux-hams@vger.rutgers.edu S: Maintained -RISCOM8 DRIVER: +RISCOM8 DRIVER P: Dmitry Gorodchanin M: pgmdsg@ibi.com L: linux-kernel@vger.rutgers.edu @@ -587,7 +594,7 @@ L: linux-scsi@vger.rutgers.edu S: Maintained -SMB FILESYSTEM: +SMB FILESYSTEM P: Volker Lendecke M: lendecke@Math.Uni-Goettingen.de L: samba@listproc.anu.edu.au @@ -642,7 +649,7 @@ W: http://mosquitonet.Stanford.EDU/strip.html S: Maintained -SVGA HANDLING: +SVGA HANDLING P: Martin Mares M: mj@atrey.karlin.mff.cuni.cz L: linux-video@atrey.karlin.mff.cuni.cz @@ -661,7 +668,7 @@ TOKEN-RING NETWORK DRIVER P: Paul Norton -M: p.norton@computer.org +M: pnorton@ieee.org L: linux-net@vger.rutgers.edu L: linux-tr@emissary.aus-etc.com S: Maintained @@ -737,6 +744,6 @@ L: linux-hams@vger.rutgers.edu S: Maintained -REST: +THE REST P: Linus Torvalds S: Buried alive in diapers diff -u --recursive --new-file v2.1.127/linux/Makefile linux/Makefile --- v2.1.127/linux/Makefile Sun Nov 8 14:02:41 1998 +++ linux/Makefile Sun Nov 8 13:52:59 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 127 +SUBLEVEL = 128 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --recursive --new-file v2.1.127/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.127/linux/arch/alpha/kernel/osf_sys.c Sun Nov 8 14:02:41 1998 +++ linux/arch/alpha/kernel/osf_sys.c Wed Nov 11 15:39:18 1998 @@ -1136,7 +1136,7 @@ unsigned long timeout; int ret; - timeout = ~0UL; + timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { time_t sec, usec; @@ -1147,8 +1147,6 @@ timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); timeout += sec * HZ; - if (timeout) - timeout += jiffies + 1; } ret = -ENOMEM; @@ -1168,7 +1166,7 @@ zero_fd_set(n, fds->res_out); zero_fd_set(n, fds->res_ex); - ret = do_select(n, fds, timeout); + ret = do_select(n, fds, &timeout); /* OSF does not copy back the remaining time. */ diff -u --recursive --new-file v2.1.127/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c --- v2.1.127/linux/arch/i386/kernel/time.c Fri Oct 23 22:01:19 1998 +++ linux/arch/i386/kernel/time.c Tue Nov 10 15:35:22 1998 @@ -589,7 +589,7 @@ * still perfectly ordered. * Note that the TSC counter will be reset if APM suspends * to disk; this won't break the kernel, though, 'cuz we're - * smart. See devices/char/apm_bios.c. + * smart. See arch/i386/kernel/apm.c. */ if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) { do_gettimeoffset = do_fast_gettimeoffset; diff -u --recursive --new-file v2.1.127/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.127/linux/arch/i386/kernel/traps.c Mon Oct 5 13:13:35 1998 +++ linux/arch/i386/kernel/traps.c Sun Nov 8 13:30:07 1998 @@ -21,6 +21,11 @@ #include #include +#ifdef CONFIG_MCA +#include +#include +#endif + #include #include #include @@ -295,6 +300,14 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) { +#ifdef CONFIG_MCA + /* Might actually be able to figure out what the guilty party + * is. */ + if( MCA_bus ) { + mca_handle_nmi(); + return; + } +#endif printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); diff -u --recursive --new-file v2.1.127/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.1.127/linux/arch/m68k/atari/stram.c Fri Oct 9 13:27:05 1998 +++ linux/arch/m68k/atari/stram.c Wed Nov 11 11:50:00 1998 @@ -19,6 +19,8 @@ #include #include #include +#include + #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_STRAM_SWAP @@ -116,6 +119,10 @@ * since the freeing algorithms are also blind to DMA capability of pages. */ +/* 1998-10-20: ++andreas + unswap_by_move disabled because it does not handle swapped shm pages. +*/ + #ifdef CONFIG_STRAM_SWAP #define ALIGN_IF_SWAP(x) PAGE_ALIGN(x) #else @@ -192,6 +199,9 @@ /* The ST-RAM's swap type */ static int stram_swap_type; +/* Semaphore for get_stram_region. */ +static struct semaphore stram_swap_sem = MUTEX; + /* major and minor device number of the ST-RAM device; for the major, we use * the same as Amiga z2ram, which is really similar and impossible on Atari, * and for the minor a relatively odd number to avoid the user creating and @@ -215,25 +225,6 @@ #ifdef CONFIG_STRAM_SWAP static int swap_init( unsigned long start_mem, unsigned long swap_data ); -static inline int unswap_pte( struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page, int isswap ); -static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page, int isswap ); -static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size, - unsigned long entry, unsigned long page, int - isswap ); -static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned - long entry, unsigned long page, int isswap ); -static int unswap_process( struct mm_struct * mm, unsigned long entry, - unsigned long page, int isswap ); -static int unswap_by_move(unsigned short *, unsigned long, unsigned long, - unsigned long); -static int unswap_by_read(unsigned short *, unsigned long, unsigned long, - unsigned long); static void *get_stram_region( unsigned long n_pages ); static void free_stram_region( unsigned long offset, unsigned long n_pages ); @@ -263,7 +254,7 @@ * This init function is called very early by atari/config.c * It initializes some internal variables needed for stram_alloc() */ -__initfunc(void atari_stram_init( void )) +void __init atari_stram_init(void) { int i; @@ -294,7 +285,7 @@ * This function is called from mem_init() to reserve the pages needed for * ST-RAM management. */ -__initfunc(void atari_stram_reserve_pages( unsigned long start_mem )) +void __init atari_stram_reserve_pages(unsigned long start_mem) { #ifdef CONFIG_STRAM_SWAP /* if max_swap_size is negative (i.e. no stram_swap= option given), @@ -573,8 +564,7 @@ * Initialize ST-RAM swap device * (lots copied and modified from sys_swapon() in mm/swapfile.c) */ -__initfunc(static int swap_init( unsigned long start_mem, - unsigned long swap_data )) +static int __init swap_init(unsigned long start_mem, unsigned long swap_data) { static struct dentry fake_dentry[3]; struct swap_info_struct *p; @@ -691,75 +681,64 @@ /* * The swap entry has been read in advance, and we return 1 to indicate * that the page has been used or is no longer needed. + * + * Always set the resulting pte to be nowrite (the same as COW pages + * after one process has exited). We don't know just how many PTEs will + * share this swap entry, so be cautious and let do_wp_page work out + * what to do if a write is requested later. */ -static inline int unswap_pte( struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page, int isswap ) +static inline void unswap_pte(struct vm_area_struct * vma, unsigned long + address, pte_t *dir, unsigned long entry, + unsigned long page /*, int isswap */) { pte_t pte = *dir; if (pte_none(pte)) - return 0; + return; if (pte_present(pte)) { - struct page *pg; - unsigned long page_nr = MAP_NR(pte_page(pte)); - unsigned long pg_swap_entry; - - if (page_nr >= max_mapnr) - return 0; - pg = mem_map + page_nr; - if (!(pg_swap_entry = in_swap_cache(pg))) - return 0; - if (pg_swap_entry != entry) - return 0; - if (isswap) { - DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; " - "exchanging to %08lx\n", - page_address(pg), entry, page ); - pg->offset = page; - swap_free(entry); - return 1; - } - else { - DPRINTK( "unswap_pte: page %08lx = entry %08lx was in swap cache; " - "deleted there\n", page_address(pg), entry ); - delete_from_swap_cache(pg); + /* If this entry is swap-cached, then page must already + hold the right address for any copies in physical + memory */ + if (pte_page(pte) != page) + return; + if (0 /* isswap */) + mem_map[MAP_NR(pte_page(pte))].offset = page; + else + /* We will be removing the swap cache in a moment, so... */ set_pte(dir, pte_mkdirty(pte)); - free_page(page); - return 1; - } + return; } if (pte_val(pte) != entry) - return 0; + return; - if (isswap) { + if (0 /* isswap */) { DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page ); set_pte(dir, __pte(page)); } else { DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx", entry, page ); - set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page,vma->vm_page_prot)))); + set_pte(dir, pte_mkdirty(mk_pte(page,vma->vm_page_prot))); + atomic_inc(&mem_map[MAP_NR(page)].count); ++vma->vm_mm->rss; } swap_free(entry); - return 1; } -static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir, - unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page, int isswap ) +static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir, + unsigned long address, unsigned long size, + unsigned long offset, unsigned long entry, + unsigned long page /* , int isswap */) { pte_t * pte; unsigned long end; if (pmd_none(*dir)) - return 0; + return; if (pmd_bad(*dir)) { printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir)); pmd_clear(dir); - return 0; + return; } pte = pte_offset(dir, address); offset += address & PMD_MASK; @@ -768,29 +747,27 @@ if (end > PMD_SIZE) end = PMD_SIZE; do { - if (unswap_pte( vma, offset+address-vma->vm_start, pte, entry, - page, isswap )) - return 1; + unswap_pte(vma, offset+address-vma->vm_start, pte, entry, + page /* , isswap */); address += PAGE_SIZE; pte++; } while (address < end); - return 0; } -static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir, - unsigned long address, unsigned long size, - unsigned long entry, unsigned long page, - int isswap ) +static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir, + unsigned long address, unsigned long size, + unsigned long entry, unsigned long page + /* , int isswap */) { pmd_t * pmd; unsigned long offset, end; if (pgd_none(*dir)) - return 0; + return; if (pgd_bad(*dir)) { printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir)); pgd_clear(dir); - return 0; + return; } pmd = pmd_offset(dir, address); offset = address & PGDIR_MASK; @@ -799,53 +776,45 @@ if (end > PGDIR_SIZE) end = PGDIR_SIZE; do { - if (unswap_pmd( vma, pmd, address, end - address, offset, entry, - page, isswap )) - return 1; + unswap_pmd(vma, pmd, address, end - address, offset, entry, + page /* , isswap */); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); - return 0; } -static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, - unsigned long entry, unsigned long page, int isswap ) +static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir, + unsigned long entry, unsigned long page + /* , int isswap */) { unsigned long start = vma->vm_start, end = vma->vm_end; - while( start < end ) { - if (unswap_pgd( vma, pgdir, start, end - start, entry, page, isswap )) - return 1; + while (start < end) { + unswap_pgd(vma, pgdir, start, end - start, entry, page + /* , isswap */); start = (start + PGDIR_SIZE) & PGDIR_MASK; pgdir++; } - return 0; } -static int unswap_process( struct mm_struct * mm, unsigned long entry, - unsigned long page, int isswap ) +static void unswap_process(struct mm_struct * mm, unsigned long entry, + unsigned long page /* , int isswap */) { struct vm_area_struct* vma; - int retval = 0; /* * Go through process' page directory. */ if (!mm || mm == &init_mm) - return 0; - down(&mm->mmap_sem); - for( vma = mm->mmap; vma; vma = vma->vm_next ) { + return; + for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); - if (unswap_vma( vma, pgd, entry, page, isswap )) { - retval = 1; - break; - } + unswap_vma(vma, pgd, entry, page /* , isswap */); } - up(&mm->mmap_sem); - return retval; } +#if 0 static int unswap_by_move(unsigned short *map, unsigned long max, unsigned long start, unsigned long n_pages) { @@ -899,14 +868,17 @@ #endif while( map[i] ) { + read_lock(&tasklist_lock); for_each_task(p) { if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ), entry, 1 )) { + read_unlock(&tasklist_lock); map[j]++; goto repeat; } } - if (map[i] && map[i] != 127) { + read_unlock(&tasklist_lock); + if (map[i] && map[i] != SWAP_MAP_MAX) { printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu " "not used by any process\n", i ); /* quit while loop and overwrite bad map entry */ @@ -932,13 +904,15 @@ } return( 0 ); } +#endif static int unswap_by_read(unsigned short *map, unsigned long max, unsigned long start, unsigned long n_pages) { struct task_struct *p; - unsigned long entry, page = 0; + unsigned long entry, page; unsigned long i; + struct page *page_map; DPRINTK( "unswapping %lu..%lu by reading in\n", start, start+n_pages-1 ); @@ -949,43 +923,35 @@ "reserved??\n", i ); continue; } - entry = SWP_ENTRY( stram_swap_type, i ); - DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", - i, map[i], nr_swap_pages ); - while( map[i] ) { - if (!page && !(page = __get_free_page(GFP_KERNEL))) { - printk( KERN_NOTICE "get_stram_region: out of memory\n" ); - return( -ENOMEM ); - } - DPRINTK( "unswap: reading swap page %lu to %08lx\n", i, page ); - rw_swap_page( READ, entry, (char *)page, 1 ); - - for_each_task(p) { - if (unswap_process( p->mm, entry, page, 0 )) { - page = 0; -#ifdef DO_PROC - stat_swap_force++; -#endif - break; - } - } - if (page) { - /* - * If we couldn't find an entry, there are several - * possible reasons: someone else freed it first, - * we freed the last reference to an overflowed entry, - * or the system has lost track of the use counts. - */ - if (map[i] && map[i] != SWAP_MAP_MAX) - printk( KERN_ERR "get_stram_region: swap entry %08lx " - "not used by any process\n", entry ); - /* quit while loop and overwrite bad map entry */ - if (!map[i]) { - DPRINTK( "unswap: map[i] became 0\n" ); - } - break; + if (map[i]) { + entry = SWP_ENTRY(stram_swap_type, i); + DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n", + i, map[i], nr_swap_pages); + + /* Get a page for the entry, using the existing + swap cache page if there is one. Otherwise, + get a clean page and read the swap into it. */ + page_map = read_swap_cache(entry); + if (page_map) { + page = page_address(page_map); + read_lock(&tasklist_lock); + for_each_task(p) + unswap_process(p->mm, entry, page + /* , 0 */); + read_unlock(&tasklist_lock); + shm_unuse(entry, page); + /* Now get rid of the extra reference to + the temporary page we've been using. */ + if (PageSwapCache(page_map)) + delete_from_swap_cache(page_map); + __free_page(page_map); + #ifdef DO_PROC + stat_swap_force++; + #endif } + else if (map[i]) + return -ENOMEM; } DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", @@ -998,9 +964,7 @@ --nr_swap_pages; } - if (page) - free_page(page); - return( 0 ); + return 0; } /* @@ -1015,7 +979,9 @@ void *ret = NULL; DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages ); - + + down(&stram_swap_sem); + /* disallow writing to the swap device now */ stram_swap_info->flags = SWP_USED; @@ -1026,9 +992,14 @@ DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n", start, region_free ); +#if 0 err = ((total_free-region_free >= n_pages-region_free) ? unswap_by_move( map, max, start, n_pages ) : unswap_by_read( map, max, start, n_pages )); +#else + err = unswap_by_read(map, max, start, n_pages); +#endif + if (err) goto end; @@ -1036,6 +1007,7 @@ end: /* allow using swap device again */ stram_swap_info->flags = SWP_WRITEOK; + up(&stram_swap_sem); DPRINTK( "get_stram_region: returning %p\n", ret ); return( ret ); } @@ -1110,7 +1082,7 @@ start_over: /* increment tail until final window size reached, and count free pages */ nfree = 0; - for( tail = head; tail-head < n_pages && tail < max-n_pages; ++tail ) { + for( tail = head; tail-head < n_pages && tail < max; ++tail ) { if (map[tail] == SWAP_MAP_BAD) { head = tail+1; goto start_over; @@ -1165,7 +1137,7 @@ /* setup parameters from command line */ -__initfunc(void stram_swap_setup(char *str, int *ints)) +void __init stram_swap_setup(char *str, int *ints) { if (ints[0] >= 1) max_swap_size = ((ints[1] < 0 ? 0 : ints[1]) * 1024) & PAGE_MASK; @@ -1262,7 +1234,7 @@ block_fsync /* fsync */ }; -__initfunc(int stram_device_init(void)) +int __init stram_device_init(void) { if (!MACH_IS_ATARI) diff -u --recursive --new-file v2.1.127/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.1.127/linux/arch/m68k/config.in Fri Oct 9 13:27:05 1998 +++ linux/arch/m68k/config.in Wed Nov 11 11:50:00 1998 @@ -266,7 +266,7 @@ tristate 'Parallel printer support' CONFIG_M68K_PRINTER if [ "$CONFIG_ZORRO" = "y" ]; then - dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER + dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE @@ -333,11 +333,6 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT bool ' Software Watchdog' CONFIG_SOFT_WATCHDOG -fi -if [ "$CONFIG_VME" = "y" ]; then - define_bool CONFIG_UMISC y -else - bool 'Support for user misc device modules' CONFIG_UMISC fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Enhanced Real Time Clock Support' CONFIG_RTC diff -u --recursive --new-file v2.1.127/linux/arch/m68k/kernel/m68k_defs.h linux/arch/m68k/kernel/m68k_defs.h --- v2.1.127/linux/arch/m68k/kernel/m68k_defs.h Sat Sep 5 16:46:40 1998 +++ linux/arch/m68k/kernel/m68k_defs.h Wed Nov 11 11:50:00 1998 @@ -3,6 +3,6 @@ */ #define TS_MAGICKEY 0x5a5a5a5a -#define TS_TSS 482 -#define TS_ESP0 502 -#define TS_FPU 506 +#define TS_TSS 478 +#define TS_ESP0 498 +#define TS_FPU 502 diff -u --recursive --new-file v2.1.127/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.1.127/linux/arch/m68k/kernel/process.c Fri Oct 9 13:27:05 1998 +++ linux/arch/m68k/kernel/process.c Wed Nov 11 11:50:00 1998 @@ -95,6 +95,9 @@ void machine_power_off(void) { +#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF) + apm_set_power_state(APM_STATE_OFF); +#endif } void show_regs(struct pt_regs * regs) diff -u --recursive --new-file v2.1.127/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.1.127/linux/arch/m68k/kernel/ptrace.c Tue Jun 23 10:01:21 1998 +++ linux/arch/m68k/kernel/ptrace.c Wed Nov 11 11:50:00 1998 @@ -450,10 +450,10 @@ else child->flags &= ~PF_TRACESYS; child->exit_code = data; - wake_up_process(child); /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + wake_up_process(child); ret = 0; goto out; } @@ -469,11 +469,11 @@ ret = 0; if (child->state == TASK_ZOMBIE) /* already dead */ goto out; - wake_up_process(child); child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + wake_up_process(child); goto out; } @@ -487,9 +487,9 @@ tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); put_reg(child, PT_SR, tmp); - wake_up_process(child); child->exit_code = data; /* give it a chance to run. */ + wake_up_process(child); ret = 0; goto out; } @@ -502,7 +502,6 @@ if ((unsigned long) data > _NSIG) goto out; child->flags &= ~(PF_PTRACED|PF_TRACESYS); - wake_up_process(child); child->exit_code = data; write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); @@ -512,6 +511,7 @@ /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + wake_up_process(child); ret = 0; goto out; } diff -u --recursive --new-file v2.1.127/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.1.127/linux/arch/mips/kernel/irixelf.c Fri Oct 23 22:01:19 1998 +++ linux/arch/mips/kernel/irixelf.c Wed Nov 11 11:49:59 1998 @@ -1197,7 +1197,7 @@ #else corefile[4] = '\0'; #endif - dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC, 0600); + dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); if (IS_ERR(dentry)) { inode = NULL; goto end_coredump; diff -u --recursive --new-file v2.1.127/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c --- v2.1.127/linux/arch/sparc64/kernel/binfmt_aout32.c Mon Oct 5 13:13:37 1998 +++ linux/arch/sparc64/kernel/binfmt_aout32.c Wed Nov 11 11:50:00 1998 @@ -106,7 +106,7 @@ #else corefile[4] = '\0'; #endif - dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC, 0600); + dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); if (IS_ERR(dentry)) { dentry = NULL; goto end_coredump; diff -u --recursive --new-file v2.1.127/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.1.127/linux/drivers/block/acsi.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/acsi.c Wed Nov 11 11:50:00 1998 @@ -1343,7 +1343,7 @@ if (acsi_wait_for_noIRQ( 20 ) && acsicmd_nodma( modesense_cmd, 0 ) && acsi_wait_for_IRQ( 3*HZ ) && - acsi_getstatus() == 0); + acsi_getstatus() == 0) break; } if (page == 4) { diff -u --recursive --new-file v2.1.127/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.127/linux/drivers/block/floppy.c Sun Nov 8 14:02:50 1998 +++ linux/drivers/block/floppy.c Sun Nov 8 23:08:02 1998 @@ -4183,6 +4183,9 @@ continue; FDCS->rawcmd = 2; if (user_reset_fdc(-1,FD_RESET_ALWAYS,0)){ + /* free ioports reserved by floppy_grab_irq_and_dma() */ + release_region(FDCS->address, 6); + release_region(FDCS->address+7, 1); FDCS->address = -1; FDCS->version = FDC_NONE; continue; @@ -4190,6 +4193,9 @@ /* Try to determine the floppy controller type */ FDCS->version = get_fdc_version(); if (FDCS->version == FDC_NONE){ + /* free ioports reserved by floppy_grab_irq_and_dma() */ + release_region(FDCS->address, 6); + release_region(FDCS->address+7, 1); FDCS->address = -1; continue; } @@ -4211,6 +4217,12 @@ if (have_no_fdc) { DPRINT("no floppy controllers found\n"); + floppy_tq.routine = (void *)(void *) empty; + mark_bh(IMMEDIATE_BH); + schedule(); + if (usage_count) + floppy_release_irq_and_dma(); + blk_dev[MAJOR_NR].request_fn = NULL; unregister_blkdev(MAJOR_NR,"fd"); } return have_no_fdc; diff -u --recursive --new-file v2.1.127/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.127/linux/drivers/block/ll_rw_blk.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/ll_rw_blk.c Wed Nov 11 22:30:16 1998 @@ -331,10 +331,16 @@ goto out; } for ( ; tmp->next ; tmp = tmp->next) { - if ((IN_ORDER(tmp,req) || - !IN_ORDER(tmp,tmp->next)) && - IN_ORDER(req,tmp->next)) - break; + const int after_current = IN_ORDER(tmp,req); + const int before_next = IN_ORDER(req,tmp->next); + + if (!IN_ORDER(tmp,tmp->next)) { + if (after_current || before_next) + break; + } else { + if (after_current && before_next) + break; + } } req->next = tmp->next; tmp->next = req; diff -u --recursive --new-file v2.1.127/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.1.127/linux/drivers/block/ps2esdi.c Wed Aug 26 11:37:35 1998 +++ linux/drivers/block/ps2esdi.c Sun Nov 8 13:43:07 1998 @@ -109,20 +109,16 @@ static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL; int no_int_yet; -static int access_count[MAX_HD] = -{0,}; -static char ps2esdi_valid[MAX_HD] = -{0,}; -static int ps2esdi_sizes[MAX_HD << 6] = -{0,}; -static int ps2esdi_blocksizes[MAX_HD << 6] = -{0,}; +static int access_count[MAX_HD] = {0,}; +static char ps2esdi_valid[MAX_HD] = {0,}; +static int ps2esdi_sizes[MAX_HD << 6] = {0,}; +static int ps2esdi_blocksizes[MAX_HD << 6] = {0,}; static int ps2esdi_drives = 0; static struct hd_struct ps2esdi[MAX_HD << 6]; static u_short io_base; -static struct timer_list esdi_timer = -{NULL, NULL, 0, 0L, ps2esdi_reset_timer}; +static struct timer_list esdi_timer = {NULL, NULL, 0, 0L, ps2esdi_reset_timer}; static int reset_status; +static int ps2esdi_slot = -1; int tp720esdi = 0; /* Is it Integrated ESDI of ThinkPad-720? */ struct ps2esdi_i_struct { @@ -198,6 +194,51 @@ } /* ps2esdi_init */ +#ifdef MODULE + +int cyl[2] = {-1,-1}; +int head[2] = {-1, -1}; +int sect[2] = {-1, -1}; + +MODULE_PARM(tp720esdi, "i"); +MODULE_PARM(cyl, "i"); +MODULE_PARM(head, "i"); +MODULE_PARM(track, "i"); + +int init_module(void) { + int drive; + + for(drive = 0; drive <= 1; drive++) { + struct ps2_esdi_i_struct *info = &ps2esdi_info[drive]; + + if (cyl[drive] != -1) { + info->cyl = info->lzone = cyl[drive]; + info->wpcom = 0; + } + if (head[drive] != -1) { + info->head = head[drive]; + info->ctl = (head[drive] > 8 ? 8 : 0); + } + if (sect[drive] != -1) info->sect = sect[drive]; + } + return ps2esdi_init(); +} + +void +cleanup_module(void) +{ + if(ps2esdi_slot) + { + mca_mark_as_unused(ps2esdi_slot); + mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); + } + release_region(io_base, 4); + free_dma(dma_arb_level); + free_irq(PS2ESDI_IRQ, NULL) + unregister_blkdev(MAJOR_NR, "ed"); +} +#endif /* MODULE */ + /* handles boot time command line parameters */ __initfunc(void tp720_setup(char *str, int *ints)) { @@ -289,6 +330,8 @@ return; } + ps2esdi_slot = slot; + mca_mark_as_used(slot); mca_set_adapter_procfn(slot, (MCA_ProcFn) ps2esdi_getinfo, NULL); /* Found the slot - read the POS register 2 to get the necessary @@ -383,6 +426,9 @@ } for (i = 0; i < (MAX_HD << 6); i++) ps2esdi_blocksizes[i] = 1024; + + request_dma(dma_arb_level, "ed"); + request_region(io_base, 4, "ed"); blksize_size[MAJOR_NR] = ps2esdi_blocksizes; } /* ps2esdi_geninit */ @@ -511,7 +557,7 @@ printk("%s: hard reset...\n", DEVICE_NAME); outb_p(CTRL_HARD_RESET, ESDI_CONTROL); expire = jiffies + 200; - while (jiffies < expire); + while (time_before(jiffies, expire)); outb_p(1, ESDI_CONTROL); } /* hard reset */ @@ -588,7 +634,7 @@ outb(CTRL_ENABLE_INTR, ESDI_CONTROL); /* do not write to the controller, if it is busy */ - for (i = jiffies + ESDI_STAT_TIMEOUT; (i > jiffies) && (inb(ESDI_STATUS) & + for (i = jiffies + ESDI_STAT_TIMEOUT; time_after(i, jiffies) && (inb(ESDI_STATUS) & STATUS_BUSY);); #if 0 @@ -611,7 +657,7 @@ for (i = (((*cmd_blk) >> 14) + 1) << 1; i; i--) { status = inb(ESDI_STATUS); for (j = jiffies + ESDI_STAT_TIMEOUT; - (j > jiffies) && (status & STATUS_BUSY) && + time_after(j, jiffies) && (status & STATUS_BUSY) && (status & STATUS_CMD_INF); status = inb(ESDI_STATUS)); if ((status & (STATUS_BUSY | STATUS_CMD_INF)) == STATUS_BUSY) { #if 0 diff -u --recursive --new-file v2.1.127/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.1.127/linux/drivers/block/xd.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/block/xd.c Sun Nov 8 13:43:07 1998 @@ -108,9 +108,7 @@ { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */ { 0x000B,"CRD18A Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */ { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */ - { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */ { 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */ - { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */ { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */ { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */ { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */ @@ -589,7 +587,7 @@ int success; xdc_busy = 1; - while ((success = ((inb(port) & mask) != flags)) && (jiffies < expiry)) { + while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) { xd_timer.expires = jiffies; cli(); add_timer(&xd_timer); @@ -1169,7 +1167,7 @@ for (i = 4; i > 0; i--) if(((xd[i] = xd[i-1]) >= 0) && !count) count = i; - if((xd[0] = count)); + if((xd[0] = count)) xd_setup(NULL, xd); xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 }); if (!xd_drives) { diff -u --recursive --new-file v2.1.127/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c --- v2.1.127/linux/drivers/cdrom/mcdx.c Sun Nov 8 14:02:52 1998 +++ linux/drivers/cdrom/mcdx.c Sun Nov 8 10:43:19 1998 @@ -787,23 +787,13 @@ * May be we could use a simple count loop w/ jumps to itself, but * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */ { - unsigned long tout = jiffies + jifs; - if (jifs < 0) return; + if (jifs < 0) return; - /* If loaded during kernel boot no *_sleep_on is - * allowed! */ - if (current->pid == 0) { - while (jiffies < tout) { - schedule_timeout(0); - } - } else { - current->timeout = tout; - xtrace(SLEEP, "*** delay: sleepq\n"); - interruptible_sleep_on(&stuff->sleepq); - xtrace(SLEEP, "delay awoken\n"); - if (signal_pending(current)) { - xtrace(SLEEP, "got signal\n"); - } + xtrace(SLEEP, "*** delay: sleepq\n"); + interruptible_sleep_on_timeout(&stuff->sleepq, jifs); + xtrace(SLEEP, "delay awoken\n"); + if (signal_pending(current)) { + xtrace(SLEEP, "got signal\n"); } } diff -u --recursive --new-file v2.1.127/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.1.127/linux/drivers/char/bttv.c Fri Oct 23 22:01:20 1998 +++ linux/drivers/char/bttv.c Sun Nov 8 14:36:46 1998 @@ -403,7 +403,8 @@ struct tvcard { - int inputs; + int video_inputs; + int audio_inputs; int tuner; int svhs; u32 gpiomask; @@ -415,30 +416,37 @@ static struct tvcard tvcards[] = { /* default */ - { 3, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, + { 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, /* MIRO */ - { 4, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}}, + { 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}}, /* Hauppauge */ - { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, + { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, /* STB */ - { 3, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}}, + { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}}, /* Intel??? */ - { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, + { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, /* Diamond DTV2000 */ - { 3, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}}, + { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}}, /* AVerMedia TVPhone */ - { 3, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}}, + { 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}}, /* Matrix Vision MV-Delta */ - { 5,-1, 3, 0, { 2, 3, 1, 0, 0}}, + { 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0}}, /* Fly Video II */ - { 3, 0, 2, 0xc00, { 2, 3, 1, 1}, + { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, {0, 0xc00, 0x800, 0x400, 0xc00, 0}}, /* TurboTV */ - { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}}, + { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}}, /* Newer Hauppauge (bt878) */ - { 3, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}}, + { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}}, /* MIRO PCTV pro */ - { 3, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}}, + { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}}, + /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */ + { + 3, 4, 0, 2, 0x0F, + { 0x02, 0x03, 0x01, 0x01}, + { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00}, + 0x00 + }, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -612,7 +620,7 @@ btand(~(3<<5), BT848_IFORM); mdelay(10); - input %= tvcards[btv->type].inputs; + input %= tvcards[btv->type].video_inputs; if (input==tvcards[btv->type].svhs) { btor(BT848_CONTROL_COMP, BT848_E_CONTROL); @@ -1304,7 +1312,7 @@ struct bttv *btv=(struct bttv *)dev; btv->user--; - audio(btv, AUDIO_MUTE); + audio(btv, AUDIO_INTERN); btv->cap&=~3; bt848_set_risc_jmps(btv); @@ -1383,8 +1391,8 @@ VID_TYPE_CLIPPING| VID_TYPE_FRAMERAM| VID_TYPE_SCALES; - b.channels = tvcards[btv->type].inputs; - b.audios = tvcards[btv->type].inputs; + b.channels = tvcards[btv->type].video_inputs; + b.audios = tvcards[btv->type].audio_inputs; b.maxwidth = 768; b.maxheight = 576; b.minwidth = 32; @@ -1402,7 +1410,7 @@ v.tuners=0; v.type=VIDEO_TYPE_CAMERA; v.norm = btv->win.norm; - if (v.channel>=tvcards[btv->type].inputs) + if (v.channel>=tvcards[btv->type].video_inputs) return -EINVAL; if(v.channel==tvcards[btv->type].tuner) { @@ -1429,7 +1437,7 @@ if(copy_from_user(&v, arg,sizeof(v))) return -EFAULT; - if (v.channel>tvcards[btv->type].inputs) + if (v.channel>=tvcards[btv->type].video_inputs) return -EINVAL; bt848_muxsel(btv, v.channel); if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC @@ -1710,7 +1718,10 @@ if(v.flags&VIDEO_AUDIO_MUTE) audio(btv, AUDIO_MUTE); /* One audio source per tuner */ - if(v.audio!=0) + /* if(v.audio!=0) */ + /* Nope... I have three on my ADSTech TV card. The*/ + /* ADSTech TV+FM prolly has 4 */ + if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs) return -EINVAL; bt848_muxsel(btv,v.audio); if(!(v.flags&VIDEO_AUDIO_MUTE)) @@ -2456,8 +2467,13 @@ printk("MATRIX-Vision\n"); strcat(btv->video_dev.name,"(MATRIX-Vision)"); break; + case BTTV_ADSTECH_TV: + printk("ADSTech Channel Surfer TV\n"); + strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)"); + btv->tuner_type=8; + break; } - audio(btv, AUDIO_MUTE); + audio(btv, AUDIO_INTERN); } diff -u --recursive --new-file v2.1.127/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.1.127/linux/drivers/char/bttv.h Fri Oct 23 22:01:20 1998 +++ linux/drivers/char/bttv.h Sun Nov 8 14:36:46 1998 @@ -186,6 +186,7 @@ #define BTTV_TURBOTV 0x09 #define BTTV_HAUPPAUGE878 0x0a #define BTTV_MIROPRO 0x0b +#define BTTV_ADSTECH_TV 0x0c #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 diff -u --recursive --new-file v2.1.127/linux/drivers/char/ftape/lowlevel/fdc-io.c linux/drivers/char/ftape/lowlevel/fdc-io.c --- v2.1.127/linux/drivers/char/ftape/lowlevel/fdc-io.c Sun Nov 8 14:02:54 1998 +++ linux/drivers/char/ftape/lowlevel/fdc-io.c Sun Nov 8 11:13:03 1998 @@ -388,8 +388,9 @@ struct wait_queue wait = {current, NULL}; sigset_t old_sigmask; static int resetting = 0; - TRACE_FUN(ft_t_fdc_dma); long timeout; + + TRACE_FUN(ft_t_fdc_dma); #if LINUX_VERSION_CODE >= KERNEL_VER(2,0,16) if (waitqueue_active(&ftape_wait_intr)) { diff -u --recursive --new-file v2.1.127/linux/drivers/char/ftape/zftape/zftape-buffers.c linux/drivers/char/ftape/zftape/zftape-buffers.c --- v2.1.127/linux/drivers/char/ftape/zftape/zftape-buffers.c Tue Nov 25 14:45:28 1997 +++ linux/drivers/char/ftape/zftape/zftape-buffers.c Sun Nov 8 11:13:46 1998 @@ -122,9 +122,8 @@ void *new; while ((new = kmalloc(size, GFP_KERNEL)) == NULL) { - current->timeout = HZ/10; current->state = TASK_INTERRUPTIBLE; - schedule(); + schedule_timeout(HZ/10); } memset(new, 0, size); used_memory += size; diff -u --recursive --new-file v2.1.127/linux/drivers/char/pms.c linux/drivers/char/pms.c --- v2.1.127/linux/drivers/char/pms.c Sat Sep 5 16:46:40 1998 +++ linux/drivers/char/pms.c Tue Nov 10 15:57:03 1998 @@ -77,7 +77,7 @@ return inb(data_port); } -extern int i2c_stat(u8 slave) +static int pms_i2c_stat(u8 slave) { int counter; int i; @@ -116,7 +116,7 @@ return inb(data_port); } -int i2c_write(u16 slave, u16 sub, u16 data) +static int pms_i2c_write(u16 slave, u16 sub, u16 data) { int skip=0; int count; @@ -166,7 +166,7 @@ return count; } -int i2c_read(int slave, int sub) +static int pms_i2c_read(int slave, int sub) { int i=0; for(i=0;i 1512 effectively disables this feature. */ +static const int rx_copybreak = 200; +/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ +static const int mtu = 1500; +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 20; + +/* Enable the automatic media selection code -- usually set. */ +#define AUTOMEDIA 1 + +/* Allow the use of fragment bus master transfers instead of only + programmed-I/O for Vortex cards. Full-bus-master transfers are always + enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined, + the feature may be turned on using 'options'. */ +#define VORTEX_BUS_MASTER + +/* A few values that may be tweaked. */ +/* Keep the ring sizes a power of two for efficiency. */ +#define TX_RING_SIZE 16 +#define RX_RING_SIZE 16 +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ + +#ifdef MODULE +#ifdef MODVERSIONS +#include +#endif +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#if (LINUX_VERSION_CODE >= 0x10344) +#define NEW_MULTICAST +#include +#else +#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) +#endif + +/* Kernel version compatibility functions. */ +#define RUN_AT(x) (jiffies + (x)) +#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) + +#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev) +#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance) +#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) + +#if (LINUX_VERSION_CODE < 0x20123) +#define test_and_set_bit(val, addr) set_bit(val, addr) +#elif defined(MODULE) +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(max_interrupt_work, "i"); +#endif + +/* "Knobs" for adjusting internal parameters. */ +/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ +#define DRIVER_DEBUG 1 +/* Some values here only for performance evaluation and path-coverage + debugging. */ +static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0; + +/* Number of times to check to see if the Tx FIFO has space, used in some + limited cases. */ +#define WAIT_TX_AVAIL 200 + +/* Operational parameter that usually are not changed. */ +#define TX_TIMEOUT 40 /* Time in jiffies before concluding Tx hung */ + +/* The size here is somewhat misleading: the Corkscrew also uses the ISA + aliased registers at +0x400. + */ +#define CORKSCREW_TOTAL_SIZE 0x20 + +#ifdef HAVE_DEVLIST +struct netdev_entry tc515_drv = +{"3c515", tc515_probe, CORKSCREW_TOTAL_SIZE, NULL}; +#endif + +#ifdef DRIVER_DEBUG +int vortex_debug = DRIVER_DEBUG; +#else +int vortex_debug = 1; +#endif + +#define CORKSCREW_ID 10 + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL, +3Com's ISA bus adapter for Fast Ethernet. Due to the unique I/O port layout, +it's not practical to integrate this driver with the other EtherLink drivers. + +II. Board-specific settings + +The Corkscrew has an EEPROM for configuration, but no special settings are +needed for Linux. + +III. Driver operation + +The 3c515 series use an interface that's very similar to the 3c900 "Boomerang" +PCI cards, with the bus master interface extensively modified to work with +the ISA bus. + +The card is capable of full-bus-master transfers with separate +lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet, +DEC Tulip and Intel Speedo3. + +This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate +receive buffer. This scheme allocates full-sized skbuffs as receive +buffers. The value RX_COPYBREAK is used as the copying breakpoint: it is +chosen to trade-off the memory wasted by passing the full-sized skbuff to +the queue layer for all frames vs. the copying cost of copying a frame to a +correctly-sized skbuff. + + +IIIC. Synchronization +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and other software. + +IV. Notes + +Thanks to Terry Murphy of 3Com for providing documentation and a development +board. + +The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com +project names. I use these names to eliminate confusion -- 3Com product +numbers and names are very similar and often confused. + +The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes! +This driver only supports ethernet frames because of the recent MTU limit +of 1.5K, but the changes to support 4.5K are minimal. +*/ + +/* Operational definitions. + These are not used by other compilation units and thus are not + exported in a ".h" file. + + First the windows. There are eight register windows, with the command + and status registers available in each. + */ +#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) +#define EL3_CMD 0x0e +#define EL3_STATUS 0x0e + +/* The top five bits written to EL3_CMD are a command, the lower + 11 bits are the parameter, if applicable. + Note that 11 parameters bits was fine for ethernet, but the new chips + can handle FDDI length frames (~4500 octets) and now parameters count + 32-bit 'Dwords' rather than octets. */ + +enum vortex_cmd { + TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, + RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, + UpStall = 6<<11, UpUnstall = (6<<11)+1, + DownStall = (6<<11)+2, DownUnstall = (6<<11)+3, + RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, + FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, + SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, + SetTxThreshold = 18<<11, SetTxStart = 19<<11, + StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, + StatsDisable = 22<<11, StopCoax = 23<<11,}; + +/* The SetRxFilter command accepts the following classes: */ +enum RxFilter { + RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; + +/* Bits in the general status register. */ +enum vortex_status { + IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, + TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, + IntReq = 0x0040, StatsFull = 0x0080, + DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10, + DMAInProgress = 1<<11, /* DMA controller is still busy.*/ + CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ +}; + +/* Register window 1 offsets, the window used in normal operation. + On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */ +enum Window1 { + TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, + RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, + TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ +}; +enum Window0 { + Wn0IRQ = 0x08, +#if defined(CORKSCREW) + Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */ + Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */ +#else + Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ + Wn0EepromData = 12, /* Window 0: EEPROM results register. */ +#endif +}; +enum Win0_EEPROM_bits { + EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, + EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ + EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ +}; +/* EEPROM locations. */ +enum eeprom_offset { + PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, + EtherLink3ID=7, }; + +enum Window3 { /* Window 3: MAC/config bits. */ + Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, +}; +union wn3_config { + int i; + struct w3_config_fields { + unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; + int pad8:8; + unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1; + int pad24:7; + } u; +}; + +enum Window4 { + Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */ +}; +enum Win4_Media_bits { + Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */ + Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ + Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */ + Media_LnkBeat = 0x0800, +}; +enum Window7 { /* Window 7: Bus Master control. */ + Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, +}; +/* Boomerang-style bus master control registers. Note ISA aliases! */ +enum MasterCtrl { + PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = 0x40c, + TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418, +}; + +/* The Rx and Tx descriptor lists. + Caution Alpha hackers: these types are 32 bits! Note also the 8 byte + alignment contraint on tx_ring[] and rx_ring[]. */ +struct boom_rx_desc { + u32 next; + s32 status; + u32 addr; + s32 length; +}; +/* Values for the Rx status entry. */ +enum rx_desc_status { + RxDComplete=0x00008000, RxDError=0x4000, + /* See boomerang_rx() for actual error bits */ +}; + +struct boom_tx_desc { + u32 next; + s32 status; + u32 addr; + s32 length; +}; + +struct vortex_private { + char devname[8]; /* "ethN" string, also for kernel debug. */ + const char *product_name; + struct device *next_module; + /* The Rx and Tx rings are here to keep them quad-word-aligned. */ + struct boom_rx_desc rx_ring[RX_RING_SIZE]; + struct boom_tx_desc tx_ring[TX_RING_SIZE]; + /* The addresses of transmit- and receive-in-place skbuffs. */ + struct sk_buff* rx_skbuff[RX_RING_SIZE]; + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct enet_statistics stats; + struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ + struct timer_list timer; /* Media selection timer. */ + int capabilities; /* Adapter capabilities word. */ + int options; /* User-settable misc. driver options. */ + int last_rx_packets; /* For media autoselection. */ + unsigned int available_media:8, /* From Wn3_Options */ + media_override:3, /* Passed-in media type. */ + default_media:3, /* Read from the EEPROM. */ + full_duplex:1, autoselect:1, + bus_master:1, /* Vortex can only do a fragment bus-m. */ + full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */ + tx_full:1; +}; + +/* The action to take with a media selection timer tick. + Note that we deviate from the 3Com order by checking 10base2 before AUI. + */ +enum xcvr_types { + XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, + XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8, +}; + +static struct media_table { + char *name; + unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ + mask:8, /* The transceiver-present bit in Wn3_Config.*/ + next:8; /* The media type to try next. */ + short wait; /* Time before we check media status. */ +} media_tbl[] = { + { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10}, + { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10}, + { "undefined", 0, 0x80, XCVR_10baseT, 10000}, + { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10}, + { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10}, + { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10}, + { "MII", 0, 0x40, XCVR_10baseT, 3*HZ }, + { "undefined", 0, 0x01, XCVR_10baseT, 10000}, + { "Default", 0, 0xFF, XCVR_10baseT, 10000}, +}; + +static int vortex_scan(struct device *dev); +static struct device *vortex_found_device(struct device *dev, int ioaddr, + int irq, int product_index, + int options); +static int vortex_probe1(struct device *dev); +static int vortex_open(struct device *dev); +static void vortex_timer(unsigned long arg); +static int vortex_start_xmit(struct sk_buff *skb, struct device *dev); +static int vortex_rx(struct device *dev); +static int boomerang_rx(struct device *dev); +static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs); +static int vortex_close(struct device *dev); +static void update_stats(int addr, struct device *dev); +static struct enet_statistics *vortex_get_stats(struct device *dev); +static void set_rx_mode(struct device *dev); + + +/* Unlike the other PCI cards the 59x cards don't need a large contiguous + memory region, so making the driver a loadable module is feasible. + + Unfortunately maximizing the shared code between the integrated and + module version of the driver results in a complicated set of initialization + procedures. + init_module() -- modules / tc59x_init() -- built-in + The wrappers for vortex_scan() + vortex_scan() The common routine that scans for PCI and EISA cards + vortex_found_device() Allocate a device structure when we find a card. + Different versions exist for modules and built-in. + vortex_probe1() Fill in the device structure -- this is separated + so that the modules code can put it in dev->init. +*/ +/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ +/* Note: this is the only limit on the number of cards supported!! */ +static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,}; + +#ifdef MODULE +static int debug = -1; +/* A list of all installed Vortex devices, for removing the driver module. */ +static struct device *root_vortex_dev = NULL; + +int +init_module(void) +{ + int cards_found; + + if (debug >= 0) + vortex_debug = debug; + if (vortex_debug) + printk(version); + + root_vortex_dev = NULL; + cards_found = vortex_scan(0); + return cards_found ? 0 : -ENODEV; +} + +#else +int tc515_probe(struct device *dev) +{ + int cards_found = 0; + + cards_found = vortex_scan(dev); + + if (vortex_debug > 0 && cards_found) + printk(version); + + return cards_found ? 0 : -ENODEV; +} +#endif /* not MODULE */ + +static int vortex_scan(struct device *dev) +{ + int cards_found = 0; + static int ioaddr = 0x100; + + /* Check all locations on the ISA bus -- evil! */ + for (; ioaddr < 0x400; ioaddr += 0x20) { + int irq; + if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE)) + continue; + /* Check the resource configuration for a matching ioaddr. */ + if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) + continue; + /* Verify by reading the device ID from the EEPROM. */ + { + int timer; + outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); + /* Pause for at least 162 us. for the read to take place. */ + for (timer = 4; timer >= 0; timer--) { + udelay(162); + if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0) + break; + } + if (inw(ioaddr + Wn0EepromData) != 0x6d50) + continue; + } + printk("3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n", + inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); + irq = inw(ioaddr + 0x2002) & 15; + vortex_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev && dev->mem_start + ? dev->mem_start : options[cards_found]); + dev = 0; + cards_found++; + } + + if (vortex_debug) + printk("%d 3c515 cards found.\n", cards_found); + return cards_found; +} + +static struct device *vortex_found_device(struct device *dev, int ioaddr, + int irq, int product_index, + int options) +{ + struct vortex_private *vp; + +#ifdef MODULE + /* Allocate and fill new device structure. */ + int dev_size = sizeof(struct device) + + sizeof(struct vortex_private) + 15; /* Pad for alignment */ + + dev = (struct device *) kmalloc(dev_size, GFP_KERNEL); + memset(dev, 0, dev_size); + /* Align the Rx and Tx ring entries. */ + dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15); + vp = (struct vortex_private *)dev->priv; + dev->name = vp->devname; /* An empty string. */ + dev->base_addr = ioaddr; + dev->irq = irq; + dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); + dev->init = vortex_probe1; + vp->product_name = "3c515"; + vp->options = options; + if (options >= 0) { + vp->media_override = ((options & 7) == 2) ? 0 : options & 7; + vp->full_duplex = (options & 8) ? 1 : 0; + vp->bus_master = (options & 16) ? 1 : 0; + } else { + vp->media_override = 7; + vp->full_duplex = 0; + vp->bus_master = 0; + } + ether_setup(dev); + vp->next_module = root_vortex_dev; + root_vortex_dev = dev; + if (register_netdev(dev) != 0) + return 0; +#else /* not a MODULE */ + if (dev) { + /* Caution: quad-word alignment required for rings! */ + dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL); + memset(dev->priv, 0, sizeof (struct vortex_private)); + } + dev = init_etherdev(dev, sizeof(struct vortex_private)); + dev->base_addr = ioaddr; + dev->irq = irq; + dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); + vp = (struct vortex_private *)dev->priv; + vp->product_name = "3c515"; + vp->options = options; + if (options >= 0) { + vp->media_override = ((options & 7) == 2) ? 0 : options & 7; + vp->full_duplex = (options & 8) ? 1 : 0; + vp->bus_master = (options & 16) ? 1 : 0; + } else { + vp->media_override = 7; + vp->full_duplex = 0; + vp->bus_master = 0; + } + + vortex_probe1(dev); +#endif /* MODULE */ + return dev; +} + +static int vortex_probe1(struct device *dev) +{ + int ioaddr = dev->base_addr; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ + int i; + + printk("%s: 3Com %s at %#3x,", dev->name, + vp->product_name, ioaddr); + + /* Read the station address from the EEPROM. */ + EL3WINDOW(0); + for (i = 0; i < 0x18; i++) { + short *phys_addr = (short *)dev->dev_addr; + int timer; + outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd); + /* Pause for at least 162 us. for the read to take place. */ + for (timer = 4; timer >= 0; timer--) { + udelay(162); + if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0) + break; + } + eeprom[i] = inw(ioaddr + Wn0EepromData); + checksum ^= eeprom[i]; + if (i < 3) + phys_addr[i] = htons(eeprom[i]); + } + checksum = (checksum ^ (checksum >> 8)) & 0xff; + if (checksum != 0x00) + printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); + for (i = 0; i < 6; i++) + printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); + if (eeprom[16] == 0x11c7) { /* Corkscrew */ + if (request_dma(dev->dma, "3c515")) { + printk(", DMA %d allocation failed", dev->dma); + dev->dma = 0; + } else + printk(", DMA %d", dev->dma); + } + printk(", IRQ %d\n", dev->irq); + /* Tell them about an invalid IRQ. */ + if (vortex_debug && (dev->irq <= 0 || dev->irq > 15)) + printk(" *** Warning: this IRQ is unlikely to work! ***\n"); + + { + char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + union wn3_config config; + EL3WINDOW(3); + vp->available_media = inw(ioaddr + Wn3_Options); + config.i = inl(ioaddr + Wn3_Config); + if (vortex_debug > 1) + printk(" Internal config register is %4.4x, transceivers %#x.\n", + config.i, inw(ioaddr + Wn3_Options)); + printk(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", + 8 << config.u.ram_size, + config.u.ram_width ? "word" : "byte", + ram_split[config.u.ram_split], + config.u.autoselect ? "autoselect/" : "", + media_tbl[config.u.xcvr].name); + dev->if_port = config.u.xcvr; + vp->default_media = config.u.xcvr; + vp->autoselect = config.u.autoselect; + } + if (vp->media_override != 7) { + printk(" Media override to transceiver type %d (%s).\n", + vp->media_override, media_tbl[vp->media_override].name); + dev->if_port = vp->media_override; + } + + vp->capabilities = eeprom[16]; + vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0; + /* Rx is broken at 10mbps, so we always disable it. */ + /* vp->full_bus_master_rx = 0;*/ + vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0; + + /* We do a request_region() to register /proc/ioports info. */ + request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name); + + /* The 3c59x-specific entries in the device structure. */ + dev->open = &vortex_open; + dev->hard_start_xmit = &vortex_start_xmit; + dev->stop = &vortex_close; + dev->get_stats = &vortex_get_stats; + dev->set_multicast_list = &set_rx_mode; + + return 0; +} + + +static int +vortex_open(struct device *dev) +{ + int ioaddr = dev->base_addr; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + union wn3_config config; + int i; + + /* Before initializing select the active media port. */ + EL3WINDOW(3); + if (vp->full_duplex) + outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ + config.i = inl(ioaddr + Wn3_Config); + + if (vp->media_override != 7) { + if (vortex_debug > 1) + printk("%s: Media override to transceiver %d (%s).\n", + dev->name, vp->media_override, + media_tbl[vp->media_override].name); + dev->if_port = vp->media_override; + } else if (vp->autoselect) { + /* Find first available media type, starting with 100baseTx. */ + dev->if_port = 4; + while (! (vp->available_media & media_tbl[dev->if_port].mask)) + dev->if_port = media_tbl[dev->if_port].next; + + if (vortex_debug > 1) + printk("%s: Initial media type %s.\n", + dev->name, media_tbl[dev->if_port].name); + + init_timer(&vp->timer); + vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); + vp->timer.data = (unsigned long)dev; + vp->timer.function = &vortex_timer; /* timer handler */ + add_timer(&vp->timer); + } else + dev->if_port = vp->default_media; + + config.u.xcvr = dev->if_port; + outl(config.i, ioaddr + Wn3_Config); + + if (vortex_debug > 1) { + printk("%s: vortex_open() InternalConfig %8.8x.\n", + dev->name, config.i); + } + + outw(TxReset, ioaddr + EL3_CMD); + for (i = 20; i >= 0 ; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + + outw(RxReset, ioaddr + EL3_CMD); + /* Wait a few ticks for the RxReset command to complete. */ + for (i = 20; i >= 0 ; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + + outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); + + /* Use the now-standard shared IRQ implementation. */ + if (vp->capabilities == 0x11c7) { + /* Corkscrew: Cannot share ISA resources. */ + if (dev->irq == 0 + || dev->dma == 0 + || request_irq(dev->irq, &vortex_interrupt, 0, + vp->product_name, dev)) + return -EAGAIN; + enable_dma(dev->dma); + set_dma_mode(dev->dma, DMA_MODE_CASCADE); + } else if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, + vp->product_name, dev)) { + return -EAGAIN; + } + + if (vortex_debug > 1) { + EL3WINDOW(4); + printk("%s: vortex_open() irq %d media status %4.4x.\n", + dev->name, dev->irq, inw(ioaddr + Wn4_Media)); + } + + /* Set the station address and mask in window 2 each time opened. */ + EL3WINDOW(2); + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + i); + for (; i < 12; i+=2) + outw(0, ioaddr + i); + + if (dev->if_port == 3) + /* Start the thinnet transceiver. We should really wait 50ms...*/ + outw(StartCoax, ioaddr + EL3_CMD); + EL3WINDOW(4); + outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | + media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + + /* Switch to the stats window, and clear all stats by reading. */ + outw(StatsDisable, ioaddr + EL3_CMD); + EL3WINDOW(6); + for (i = 0; i < 10; i++) + inb(ioaddr + i); + inw(ioaddr + 10); + inw(ioaddr + 12); + /* New: On the Vortex we must also clear the BadSSD counter. */ + EL3WINDOW(4); + inb(ioaddr + 12); + /* ..and on the Boomerang we enable the extra statistics bits. */ + outw(0x0040, ioaddr + Wn4_NetDiag); + + /* Switch to register set 7 for normal use. */ + EL3WINDOW(7); + + if (vp->full_bus_master_rx) { /* Boomerang bus master. */ + vp->cur_rx = vp->dirty_rx = 0; + if (vortex_debug > 2) + printk("%s: Filling in the Rx ring.\n", dev->name); + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb; + if (i < (RX_RING_SIZE - 1)) + vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]); + else + vp->rx_ring[i].next = 0; + vp->rx_ring[i].status = 0; /* Clear complete bit. */ + vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000; + skb = dev_alloc_skb(PKT_BUF_SZ); + vp->rx_skbuff[i] = skb; + if (skb == NULL) + break; /* Bad news! */ + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + vp->rx_ring[i].addr = virt_to_bus(skb->tail); + } + vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ + outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr); + } + if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ + vp->cur_tx = vp->dirty_tx = 0; + outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ + /* Clear the Tx ring. */ + for (i = 0; i < TX_RING_SIZE; i++) + vp->tx_skbuff[i] = 0; + outl(0, ioaddr + DownListPtr); + } + /* Set reciever mode: presumably accept b-case and phys addr only. */ + set_rx_mode(dev); + outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ + outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ + /* Allow status bits to be seen. */ + outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull | + (vp->full_bus_master_tx ? DownComplete : TxAvailable) | + (vp->full_bus_master_rx ? UpComplete : RxComplete) | + (vp->bus_master ? DMADone : 0), + ioaddr + EL3_CMD); + /* Ack all pending events, and set active indicator mask. */ + outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, + ioaddr + EL3_CMD); + outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull + | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete, + ioaddr + EL3_CMD); + + MOD_INC_USE_COUNT; + + return 0; +} + +static void vortex_timer(unsigned long data) +{ +#ifdef AUTOMEDIA + struct device *dev = (struct device *)data; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int ioaddr = dev->base_addr; + unsigned long flags; + int ok = 0; + + if (vortex_debug > 1) + printk("%s: Media selection timer tick happened, %s.\n", + dev->name, media_tbl[dev->if_port].name); + + save_flags(flags); cli(); { + int old_window = inw(ioaddr + EL3_CMD) >> 13; + int media_status; + EL3WINDOW(4); + media_status = inw(ioaddr + Wn4_Media); + switch (dev->if_port) { + case 0: case 4: case 5: /* 10baseT, 100baseTX, 100baseFX */ + if (media_status & Media_LnkBeat) { + ok = 1; + if (vortex_debug > 1) + printk("%s: Media %s has link beat, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + } else if (vortex_debug > 1) + printk("%s: Media %s is has no link beat, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + + break; + default: /* Other media types handled by Tx timeouts. */ + if (vortex_debug > 1) + printk("%s: Media %s is has no indication, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + ok = 1; + } + if ( ! ok) { + union wn3_config config; + + do { + dev->if_port = media_tbl[dev->if_port].next; + } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); + if (dev->if_port == 8) { /* Go back to default. */ + dev->if_port = vp->default_media; + if (vortex_debug > 1) + printk("%s: Media selection failing, using default %s port.\n", + dev->name, media_tbl[dev->if_port].name); + } else { + if (vortex_debug > 1) + printk("%s: Media selection failed, now trying %s port.\n", + dev->name, media_tbl[dev->if_port].name); + vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); + add_timer(&vp->timer); + } + outw((media_status & ~(Media_10TP|Media_SQE)) | + media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + + EL3WINDOW(3); + config.i = inl(ioaddr + Wn3_Config); + config.u.xcvr = dev->if_port; + outl(config.i, ioaddr + Wn3_Config); + + outw(dev->if_port == 3 ? StartCoax : StopCoax, ioaddr + EL3_CMD); + } + EL3WINDOW(old_window); + } restore_flags(flags); + if (vortex_debug > 1) + printk("%s: Media selection timer finished, %s.\n", + dev->name, media_tbl[dev->if_port].name); + +#endif /* AUTOMEDIA*/ + return; +} + +static int +vortex_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int ioaddr = dev->base_addr; + + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + int i; + + /* Min. wait before assuming a Tx failed == 400ms. */ + + if (tickssofar < 400*HZ/1000) /* We probably aren't empty. */ + return 1; + printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n", + dev->name, inb(ioaddr + TxStatus), + inw(ioaddr + EL3_STATUS)); + /* Slight code bloat to be user friendly. */ + if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) + printk("%s: Transmitter encountered 16 collisions -- network" + " network cable problem?\n", dev->name); +#ifndef final_version + printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n", + vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx); + printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), + &vp->tx_ring[0]); + for (i = 0; i < TX_RING_SIZE; i++) { + printk(" %d: %p length %8.8x status %8.8x\n", i, + &vp->tx_ring[i], + vp->tx_ring[i].length, + vp->tx_ring[i].status); + } +#endif + /* Issue TX_RESET and TX_START commands. */ + outw(TxReset, ioaddr + EL3_CMD); + for (i = 20; i >= 0 ; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + outw(TxEnable, ioaddr + EL3_CMD); + dev->trans_start = jiffies; + /* dev->tbusy = 0;*/ + vp->stats.tx_errors++; + vp->stats.tx_dropped++; + return 0; /* Yes, silently *drop* the packet! */ + } + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + If this ever occurs the queue layer is doing something evil! */ + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + return 1; + } + + if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */ + /* Calculate the next Tx descriptor entry. */ + int entry = vp->cur_tx % TX_RING_SIZE; + struct boom_tx_desc *prev_entry; + unsigned long flags, i; + + if (vp->tx_full) /* No room to transmit with */ + return 1; + if (vp->cur_tx != 0) + prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; + else + prev_entry = NULL; + if (vortex_debug > 3) + printk("%s: Trying to send a packet, Tx index %d.\n", + dev->name, vp->cur_tx); + /* vp->tx_full = 1; */ + vp->tx_skbuff[entry] = skb; + vp->tx_ring[entry].next = 0; + vp->tx_ring[entry].addr = virt_to_bus(skb->data); + vp->tx_ring[entry].length = skb->len | 0x80000000; + vp->tx_ring[entry].status = skb->len | 0x80000000; + + save_flags(flags); + cli(); + outw(DownStall, ioaddr + EL3_CMD); + /* Wait for the stall to complete. */ + for (i = 20; i >= 0 ; i--) + if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0) + break; + if (prev_entry) + prev_entry->next = virt_to_bus(&vp->tx_ring[entry]); + if (inl(ioaddr + DownListPtr) == 0) { + outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr); + queued_packet++; + } + outw(DownUnstall, ioaddr + EL3_CMD); + restore_flags(flags); + + vp->cur_tx++; + if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) + vp->tx_full = 1; + else { /* Clear previous interrupt enable. */ + if (prev_entry) + prev_entry->status &= ~0x80000000; + dev->tbusy = 0; + } + dev->trans_start = jiffies; + return 0; + } + /* Put out the doubleword header... */ + outl(skb->len, ioaddr + TX_FIFO); +#ifdef VORTEX_BUS_MASTER + if (vp->bus_master) { + /* Set the bus-master controller to transfer the packet. */ + outl((int)(skb->data), ioaddr + Wn7_MasterAddr); + outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); + vp->tx_skb = skb; + outw(StartDMADown, ioaddr + EL3_CMD); + /* dev->tbusy will be cleared at the DMADone interrupt. */ + } else { + /* ... and the packet rounded to a doubleword. */ + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + dev_kfree_skb (skb); + if (inw(ioaddr + TxFree) > 1536) { + dev->tbusy = 0; + } else + /* Interrupt us when the FIFO has room for max-sized packet. */ + outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + } +#else + /* ... and the packet rounded to a doubleword. */ + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + dev_kfree_skb (skb); + if (inw(ioaddr + TxFree) > 1536) { + dev->tbusy = 0; + } else + /* Interrupt us when the FIFO has room for max-sized packet. */ + outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); +#endif /* bus master */ + + dev->trans_start = jiffies; + + /* Clear the Tx status stack. */ + { + short tx_status; + int i = 4; + + while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { + if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ + if (vortex_debug > 2) + printk("%s: Tx error, status %2.2x.\n", + dev->name, tx_status); + if (tx_status & 0x04) vp->stats.tx_fifo_errors++; + if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + if (tx_status & 0x30) { + int j; + outw(TxReset, ioaddr + EL3_CMD); + for (j = 20; j >= 0 ; j--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + } + outw(TxEnable, ioaddr + EL3_CMD); + } + outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ + } + } + return 0; +} + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Use the now-standard shared IRQ implementation. */ + struct device *dev = dev_id; + struct vortex_private *lp; + int ioaddr, status; + int latency; + int i = max_interrupt_work; + + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk("%s: Re-entering the interrupt handler.\n", dev->name); + return; + } + + ioaddr = dev->base_addr; + latency = inb(ioaddr + Timer); + lp = (struct vortex_private *)dev->priv; + + status = inw(ioaddr + EL3_STATUS); + + if (vortex_debug > 4) + printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name, + status, latency); + if ((status & 0xE000) != 0xE000) { + static int donedidthis=0; + /* Some interrupt controllers store a bogus interrupt from boot-time. + Ignore a single early interrupt, but don't hang the machine for + other interrupt problems. */ + if (donedidthis++ > 100) { + printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", + dev->name, status, dev->start); + FREE_IRQ(dev->irq, dev); + } + } + + do { + if (vortex_debug > 5) + printk("%s: In interrupt loop, status %4.4x.\n", + dev->name, status); + if (status & RxComplete) + vortex_rx(dev); + + if (status & TxAvailable) { + if (vortex_debug > 5) + printk(" TX room bit was handled.\n"); + /* There's room in the FIFO for a full-sized packet. */ + outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); + dev->tbusy = 0; + mark_bh(NET_BH); + } + if (status & DownComplete) { + unsigned int dirty_tx = lp->dirty_tx; + + while (lp->cur_tx - dirty_tx > 0) { + int entry = dirty_tx % TX_RING_SIZE; + if (inl(ioaddr + DownListPtr) == + virt_to_bus(&lp->tx_ring[entry])) + break; /* It still hasn't been processed. */ + if (lp->tx_skbuff[entry]) { + dev_kfree_skb(lp->tx_skbuff[entry]); + lp->tx_skbuff[entry] = 0; + } + dirty_tx++; + } + lp->dirty_tx = dirty_tx; + outw(AckIntr | DownComplete, ioaddr + EL3_CMD); + if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) { + lp->tx_full= 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + } +#ifdef VORTEX_BUS_MASTER + if (status & DMADone) { + outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ + dev->tbusy = 0; + dev_kfree_skb (lp->tx_skb); /* Release the transfered buffer */ + mark_bh(NET_BH); + } +#endif + if (status & UpComplete) { + boomerang_rx(dev); + outw(AckIntr | UpComplete, ioaddr + EL3_CMD); + } + if (status & (AdapterFailure | RxEarly | StatsFull)) { + /* Handle all uncommon interrupts at once. */ + if (status & RxEarly) { /* Rx early is unused. */ + vortex_rx(dev); + outw(AckIntr | RxEarly, ioaddr + EL3_CMD); + } + if (status & StatsFull) { /* Empty statistics. */ + static int DoneDidThat = 0; + if (vortex_debug > 4) + printk("%s: Updating stats.\n", dev->name); + update_stats(ioaddr, dev); + /* DEBUG HACK: Disable statistics as an interrupt source. */ + /* This occurs when we have the wrong media type! */ + if (DoneDidThat == 0 && + inw(ioaddr + EL3_STATUS) & StatsFull) { + int win, reg; + printk("%s: Updating stats failed, disabling stats as an" + " interrupt source.\n", dev->name); + for (win = 0; win < 8; win++) { + EL3WINDOW(win); + printk("\n Vortex window %d:", win); + for (reg = 0; reg < 16; reg++) + printk(" %2.2x", inb(ioaddr+reg)); + } + EL3WINDOW(7); + outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure + | UpComplete | DownComplete | TxComplete, + ioaddr + EL3_CMD); + DoneDidThat++; + } + } + if (status & AdapterFailure) { + /* Adapter failure requires Rx reset and reinit. */ + outw(RxReset, ioaddr + EL3_CMD); + /* Set the Rx filter to the current state. */ + set_rx_mode(dev); + outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ + outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); + } + } + + if (--i < 0) { + printk("%s: Too much work in interrupt, status %4.4x. " + "Disabling functions (%4.4x).\n", + dev->name, status, SetStatusEnb | ((~status) & 0x7FE)); + /* Disable all pending interrupts. */ + outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD); + outw(AckIntr | 0x7FF, ioaddr + EL3_CMD); + break; + } + /* Acknowledge the IRQ. */ + outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); + + } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); + + if (vortex_debug > 4) + printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status); + + dev->interrupt = 0; + return; +} + +static int +vortex_rx(struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + short rx_status; + + if (vortex_debug > 5) + printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", + inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + while ((rx_status = inw(ioaddr + RxStatus)) > 0) { + if (rx_status & 0x4000) { /* Error, update stats. */ + unsigned char rx_error = inb(ioaddr + RxErrors); + if (vortex_debug > 2) + printk(" Rx error: status %2.2x.\n", rx_error); + vp->stats.rx_errors++; + if (rx_error & 0x01) vp->stats.rx_over_errors++; + if (rx_error & 0x02) vp->stats.rx_length_errors++; + if (rx_error & 0x04) vp->stats.rx_frame_errors++; + if (rx_error & 0x08) vp->stats.rx_crc_errors++; + if (rx_error & 0x10) vp->stats.rx_length_errors++; + } else { + /* The packet length: up to 4.5K!. */ + short pkt_len = rx_status & 0x1fff; + struct sk_buff *skb; + + skb = DEV_ALLOC_SKB(pkt_len + 5); + if (vortex_debug > 4) + printk("Receiving packet size %d status %4.4x.\n", + pkt_len, rx_status); + if (skb != NULL) { + skb->dev = dev; +#if LINUX_VERSION_CODE >= 0x10300 + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + /* 'skb_put()' points to the start of sk_buff data area. */ + insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), + (pkt_len + 3) >> 2); + outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ + skb->protocol = eth_type_trans(skb, dev); +#else + skb->len = pkt_len; + /* 'skb->data' points to the start of sk_buff data area. */ + insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2); + outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ +#endif /* KERNEL_1_3_0 */ + netif_rx(skb); + dev->last_rx = jiffies; + vp->stats.rx_packets++; + /* Wait a limited time to go to next packet. */ + for (i = 200; i >= 0; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + continue; + } else if (vortex_debug) + printk("%s: Couldn't allocate a sk_buff of size %d.\n", + dev->name, pkt_len); + } + outw(RxDiscard, ioaddr + EL3_CMD); + vp->stats.rx_dropped++; + /* Wait a limited time to skip this packet. */ + for (i = 200; i >= 0; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + } + + return 0; +} + +static int +boomerang_rx(struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int entry = vp->cur_rx % RX_RING_SIZE; + int ioaddr = dev->base_addr; + int rx_status; + + if (vortex_debug > 5) + printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n", + inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) { + if (rx_status & RxDError) { /* Error, update stats. */ + unsigned char rx_error = rx_status >> 16; + if (vortex_debug > 2) + printk(" Rx error: status %2.2x.\n", rx_error); + vp->stats.rx_errors++; + if (rx_error & 0x01) vp->stats.rx_over_errors++; + if (rx_error & 0x02) vp->stats.rx_length_errors++; + if (rx_error & 0x04) vp->stats.rx_frame_errors++; + if (rx_error & 0x08) vp->stats.rx_crc_errors++; + if (rx_error & 0x10) vp->stats.rx_length_errors++; + } else { + /* The packet length: up to 4.5K!. */ + short pkt_len = rx_status & 0x1fff; + struct sk_buff *skb; + + if (vortex_debug > 4) + printk("Receiving packet size %d status %4.4x.\n", + pkt_len, rx_status); + + /* Check if the packet is long enough to just accept without + copying to a properly sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) { + skb->dev = dev; + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + /* 'skb_put()' points to the start of sk_buff data area. */ + memcpy(skb_put(skb, pkt_len), + bus_to_virt(vp->rx_ring[entry].addr), + pkt_len); + rx_copy++; + } else{ + void *temp; + /* Pass up the skbuff already on the Rx ring. */ + skb = vp->rx_skbuff[entry]; + vp->rx_skbuff[entry] = NULL; + temp = skb_put(skb, pkt_len); + /* Remove this checking code for final release. */ + if (bus_to_virt(vp->rx_ring[entry].addr) != temp) + printk("%s: Warning -- the skbuff addresses do not match" + " in boomerang_rx: %p vs. %p / %p.\n", dev->name, + bus_to_virt(vp->rx_ring[entry].addr), + skb->head, temp); + rx_nocopy++; + } +#if LINUX_VERSION_CODE > 0x10300 + skb->protocol = eth_type_trans(skb, dev); +#else + skb->len = pkt_len; +#endif + netif_rx(skb); + dev->last_rx = jiffies; + vp->stats.rx_packets++; + } + entry = (++vp->cur_rx) % RX_RING_SIZE; + } + /* Refill the Rx ring buffers. */ + for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) { + struct sk_buff *skb; + entry = vp->dirty_rx % RX_RING_SIZE; + if (vp->rx_skbuff[entry] == NULL) { + skb = dev_alloc_skb(PKT_BUF_SZ); + if (skb == NULL) + break; /* Bad news! */ + skb->dev = dev; /* Mark as being used by this device. */ +#if LINUX_VERSION_CODE > 0x10300 + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + vp->rx_ring[entry].addr = virt_to_bus(skb->tail); +#else + vp->rx_ring[entry].addr = virt_to_bus(skb->data); +#endif + vp->rx_skbuff[entry] = skb; + } + vp->rx_ring[entry].status = 0; /* Clear complete bit. */ + } + return 0; +} + +static int +vortex_close(struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int ioaddr = dev->base_addr; + int i; + + dev->start = 0; + dev->tbusy = 1; + + if (vortex_debug > 1) { + printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n", + dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); + printk("%s: vortex close stats: rx_nocopy %d rx_copy %d" + " tx_queued %d.\n", + dev->name, rx_nocopy, rx_copy, queued_packet); + } + + del_timer(&vp->timer); + + /* Turn off statistics ASAP. We update lp->stats below. */ + outw(StatsDisable, ioaddr + EL3_CMD); + + /* Disable the receiver and transmitter. */ + outw(RxDisable, ioaddr + EL3_CMD); + outw(TxDisable, ioaddr + EL3_CMD); + + if (dev->if_port == XCVR_10base2) + /* Turn off thinnet power. Green! */ + outw(StopCoax, ioaddr + EL3_CMD); + +#ifdef SA_SHIRQ + free_irq(dev->irq, dev); +#else + free_irq(dev->irq); + irq2dev_map[dev->irq] = 0; +#endif + + outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); + + update_stats(ioaddr, dev); + if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ + outl(0, ioaddr + UpListPtr); + for (i = 0; i < RX_RING_SIZE; i++) + if (vp->rx_skbuff[i]) { +#if LINUX_VERSION_CODE < 0x20100 + vp->rx_skbuff[i]->free = 1; +#endif + dev_kfree_skb (vp->rx_skbuff[i]); + vp->rx_skbuff[i] = 0; + } + } + if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ + outl(0, ioaddr + DownListPtr); + for (i = 0; i < TX_RING_SIZE; i++) + if (vp->tx_skbuff[i]) { + dev_kfree_skb(vp->tx_skbuff[i]); + vp->tx_skbuff[i] = 0; + } + } + + MOD_DEC_USE_COUNT; + + return 0; +} + +static struct enet_statistics * +vortex_get_stats(struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + unsigned long flags; + + if (dev->start) { + save_flags(flags); + cli(); + update_stats(dev->base_addr, dev); + restore_flags(flags); + } + return &vp->stats; +} + +/* Update statistics. + Unlike with the EL3 we need not worry about interrupts changing + the window setting from underneath us, but we must still guard + against a race condition with a StatsUpdate interrupt updating the + table. This is done by checking that the ASM (!) code generated uses + atomic updates with '+='. + */ +static void update_stats(int ioaddr, struct device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + + /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ + /* Switch to the stats window, and read everything. */ + EL3WINDOW(6); + vp->stats.tx_carrier_errors += inb(ioaddr + 0); + vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); + /* Multiple collisions. */ inb(ioaddr + 2); + vp->stats.collisions += inb(ioaddr + 3); + vp->stats.tx_window_errors += inb(ioaddr + 4); + vp->stats.rx_fifo_errors += inb(ioaddr + 5); + vp->stats.tx_packets += inb(ioaddr + 6); + vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; + /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ + /* Tx deferrals */ inb(ioaddr + 8); + /* Don't bother with register 9, an extension of registers 6&7. + If we do use the 6&7 values the atomic update assumption above + is invalid. */ + inw(ioaddr + 10); /* Total Rx and Tx octets. */ + inw(ioaddr + 12); + /* New: On the Vortex we must also clear the BadSSD counter. */ + EL3WINDOW(4); + inb(ioaddr + 12); + + /* We change back to window 7 (not 1) with the Vortex. */ + EL3WINDOW(7); + return; +} + +/* This new version of set_rx_mode() supports v1.4 kernels. + The Vortex chip has no documented multicast filter, so the only + multicast setting is to receive all multicast frames. At least + the chip has a very clean way to set the mode, unlike many others. */ +static void +set_rx_mode(struct device *dev) +{ + int ioaddr = dev->base_addr; + short new_mode; + + if (dev->flags & IFF_PROMISC) { + if (vortex_debug > 3) + printk("%s: Setting promiscuous mode.\n", dev->name); + new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; + } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; + } else + new_mode = SetRxFilter | RxStation | RxBroadcast; + + outw(new_mode, ioaddr + EL3_CMD); +} + +#ifdef MODULE +void +cleanup_module(void) +{ + struct device *next_dev; + + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_vortex_dev) { + next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module; + if (root_vortex_dev->dma) + free_dma(root_vortex_dev->dma); + unregister_netdev(root_vortex_dev); + outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD); + release_region(root_vortex_dev->base_addr, CORKSCREW_TOTAL_SIZE); + kfree(root_vortex_dev); + root_vortex_dev = next_dev; + } +} +#endif /* MODULE */ + +/* + * Local variables: + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c515.c" + * c-indent-level: 4 + * tab-width: 4 + * End: + */ diff -u --recursive --new-file v2.1.127/linux/drivers/net/3c523.c linux/drivers/net/3c523.c --- v2.1.127/linux/drivers/net/3c523.c Fri Oct 9 13:27:08 1998 +++ linux/drivers/net/3c523.c Sun Nov 8 13:44:52 1998 @@ -1,84 +1,84 @@ /* -net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip) + net-3-driver for the 3c523 Etherlink/MC card (i82586 Ethernet chip) -This is an extension to the Linux operating system, and is covered by the -same Gnu Public License that covers that work. + This is an extension to the Linux operating system, and is covered by the + same Gnu Public License that covers that work. -Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca) + Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca) -This is basically Michael Hipp's ni52 driver, with a new probing -algorithm and some minor changes to the 82586 CA and reset routines. -Thanks a lot Michael for a really clean i82586 implementation! Unless -otherwise documented in ni52.c, any bugs are mine. - -Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in -any way. The ni52 is a lot easier to modify. - -sources: - ni52.c - - Crynwr packet driver collection was a great reference for my first - attempt at this sucker. The 3c507 driver also helped, until I noticed - that ni52.c was a lot nicer. - - EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference - Manual, courtesy of 3Com CardFacts, documents the 3c523-specific - stuff. Information on CardFacts is found in the Ethernet HOWTO. - Also see - - Microprocessor Communications Support Chips, T.J. Byers, ISBN - 0-444-01224-9, has a section on the i82586. It tells you just enough - to know that you really don't want to learn how to program the chip. - - The original device probe code was stolen from ps2esdi.c - -Known Problems: - Since most of the code was stolen from ni52.c, you'll run across the - same bugs in the 0.62 version of ni52.c, plus maybe a few because of - the 3c523 idiosynchacies. The 3c523 has 16K of RAM though, so there - shouldn't be the overrun problem that the 8K ni52 has. - - This driver is for a 16K adapter. It should work fine on the 64K - adapters, but it will only use one of the 4 banks of RAM. Modifying - this for the 64K version would require a lot of heinous bank - switching, which I'm sure not interested in doing. If you try to - implement a bank switching version, you'll basically have to remember - what bank is enabled and do a switch everytime you access a memory - location that's not current. You'll also have to remap pointers on - the driver side, because it only knows about 16K of the memory. - Anyone desperate or masochistic enough to try? - - It seems to be stable now when multiple transmit buffers are used. I - can't see any performance difference, but then I'm working on a 386SX. - - Multicast doesn't work. It doesn't even pretend to work. Don't use - it. Don't compile your kernel with multicast support. I don't know - why. - -Features: - This driver is useable as a loadable module. If you try to specify an - IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will - search the MCA slots until it finds a 3c523 with the specified - parameters. - - This driver should support multiple ethernet cards, but I can't test - that. If someone would I'd greatly appreciate it. - - This has been tested with both BNC and TP versions, internal and - external transceivers. Haven't tested with the 64K version (that I - know of). - -History: - Jan 1st, 1996 - first public release - Feb 4th, 1996 - update to 1.3.59, incorporated multicast diffs from ni52.c - Feb 15th, 1996 - added shared irq support + This is basically Michael Hipp's ni52 driver, with a new probing + algorithm and some minor changes to the 82586 CA and reset routines. + Thanks a lot Michael for a really clean i82586 implementation! Unless + otherwise documented in ni52.c, any bugs are mine. + + Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in + any way. The ni52 is a lot easier to modify. + + sources: + ni52.c + + Crynwr packet driver collection was a great reference for my first + attempt at this sucker. The 3c507 driver also helped, until I noticed + that ni52.c was a lot nicer. + + EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference + Manual, courtesy of 3Com CardFacts, documents the 3c523-specific + stuff. Information on CardFacts is found in the Ethernet HOWTO. + Also see + + Microprocessor Communications Support Chips, T.J. Byers, ISBN + 0-444-01224-9, has a section on the i82586. It tells you just enough + to know that you really don't want to learn how to program the chip. + + The original device probe code was stolen from ps2esdi.c + + Known Problems: + Since most of the code was stolen from ni52.c, you'll run across the + same bugs in the 0.62 version of ni52.c, plus maybe a few because of + the 3c523 idiosynchacies. The 3c523 has 16K of RAM though, so there + shouldn't be the overrun problem that the 8K ni52 has. + + This driver is for a 16K adapter. It should work fine on the 64K + adapters, but it will only use one of the 4 banks of RAM. Modifying + this for the 64K version would require a lot of heinous bank + switching, which I'm sure not interested in doing. If you try to + implement a bank switching version, you'll basically have to remember + what bank is enabled and do a switch everytime you access a memory + location that's not current. You'll also have to remap pointers on + the driver side, because it only knows about 16K of the memory. + Anyone desperate or masochistic enough to try? + + It seems to be stable now when multiple transmit buffers are used. I + can't see any performance difference, but then I'm working on a 386SX. + + Multicast doesn't work. It doesn't even pretend to work. Don't use + it. Don't compile your kernel with multicast support. I don't know + why. + + Features: + This driver is useable as a loadable module. If you try to specify an + IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will + search the MCA slots until it finds a 3c523 with the specified + parameters. + + This driver should support multiple ethernet cards, but I can't test + that. If someone would I'd greatly appreciate it. + + This has been tested with both BNC and TP versions, internal and + external transceivers. Haven't tested with the 64K version (that I + know of). + + History: + Jan 1st, 1996 + first public release + Feb 4th, 1996 + update to 1.3.59, incorporated multicast diffs from ni52.c + Feb 15th, 1996 + added shared irq support - $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ -*/ + $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ + */ #ifdef MODULE #include @@ -105,8 +105,8 @@ #include "3c523.h" /*************************************************************************/ -#define DEBUG /* debug on */ -#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit*/ +#define DEBUG /* debug on */ +#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */ #define make32(ptr16) (p->memtop + (short) (ptr16) ) #define make24(ptr32) ((char *) (ptr32) - p->base) @@ -114,11 +114,19 @@ /*************************************************************************/ /* - Tables to which we can map values in the configuration registers. -*/ -static int irq_table[] __initdata = {12, 7, 3, 9}; -static int csr_table[] __initdata = {0x300, 0x1300, 0x2300, 0x3300}; -static int shm_table[] __initdata = {0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000}; + Tables to which we can map values in the configuration registers. + */ +static int irq_table[] __initdata = { + 12, 7, 3, 9 +}; + +static int csr_table[] __initdata = { + 0x300, 0x1300, 0x2300, 0x3300 +}; + +static int shm_table[] __initdata = { + 0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000 +}; /******************* how to calculate the buffers ***************************** @@ -135,21 +143,21 @@ * if you don't know the driver, better do not change this values: */ -#define RECV_BUFF_SIZE 1524 /* slightly oversized */ -#define XMIT_BUFF_SIZE 1524 /* slightly oversized */ -#define NUM_XMIT_BUFFS 4 /* config for both, 8K and 16K shmem */ -#define NUM_RECV_BUFFS_8 1 /* config for 8K shared mem */ -#define NUM_RECV_BUFFS_16 6 /* config for 16K shared mem */ +#define RECV_BUFF_SIZE 1524 /* slightly oversized */ +#define XMIT_BUFF_SIZE 1524 /* slightly oversized */ +#define NUM_XMIT_BUFFS 4 /* config for both, 8K and 16K shmem */ +#define NUM_RECV_BUFFS_8 1 /* config for 8K shared mem */ +#define NUM_RECV_BUFFS_16 6 /* config for 16K shared mem */ #if (NUM_XMIT_BUFFS == 1) -#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ +#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ #endif /**************************************************************************/ #define DELAY(x) {int i=jiffies; \ if(loops_per_sec == 1) \ - while(i+(x)>jiffies); \ + while(time_after(i+(x), jiffies)); \ else \ __delay((loops_per_sec>>5)*x); \ } @@ -167,42 +175,41 @@ dev->name,__LINE__); \ elmc_id_reset586(); } } } -static void elmc_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr); -static int elmc_open(struct device *dev); -static int elmc_close(struct device *dev); -static int elmc_send_packet(struct sk_buff *,struct device *); -static struct net_device_stats *elmc_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); +static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr); +static int elmc_open(struct device *dev); +static int elmc_close(struct device *dev); +static int elmc_send_packet(struct sk_buff *, struct device *); +static struct net_device_stats *elmc_get_stats(struct device *dev); +static void set_multicast_list(struct device *dev); /* helper-functions */ -static int init586(struct device *dev); -static int check586(struct device *dev,char *where,unsigned size); -static void alloc586(struct device *dev); -static void startrecv586(struct device *dev); -static void *alloc_rfa(struct device *dev,void *ptr); -static void elmc_rcv_int(struct device *dev); -static void elmc_xmt_int(struct device *dev); -static void elmc_rnr_int(struct device *dev); +static int init586(struct device *dev); +static int check586(struct device *dev, char *where, unsigned size); +static void alloc586(struct device *dev); +static void startrecv586(struct device *dev); +static void *alloc_rfa(struct device *dev, void *ptr); +static void elmc_rcv_int(struct device *dev); +static void elmc_xmt_int(struct device *dev); +static void elmc_rnr_int(struct device *dev); -struct priv -{ +struct priv { struct net_device_stats stats; unsigned long base; char *memtop; - volatile struct rfd_struct *rfd_last,*rfd_top,*rfd_first; - volatile struct scp_struct *scp; /* volatile is important */ - volatile struct iscp_struct *iscp; /* volatile is important */ - volatile struct scb_struct *scb; /* volatile is important */ - volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; + volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first; + volatile struct scp_struct *scp; /* volatile is important */ + volatile struct iscp_struct *iscp; /* volatile is important */ + volatile struct scb_struct *scb; /* volatile is important */ + volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; #if (NUM_XMIT_BUFFS == 1) volatile struct nop_cmd_struct *nop_cmds[2]; #else volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; #endif - volatile int nop_point,num_recv_buffs; - volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; - volatile int xmit_count,xmit_last; + volatile int nop_point, num_recv_buffs; + volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; + volatile int xmit_count, xmit_last; volatile int slot; }; @@ -210,379 +217,368 @@ #define elmc_reset586() {elmc_do_reset586(dev->base_addr,ELMC_CTRL_INTE);} /* with interrupts disabled - this will clear the interrupt bit in the -3c523 control register, and won't put it back. This effectively -disables interrupts on the card. */ + 3c523 control register, and won't put it back. This effectively + disables interrupts on the card. */ #define elmc_id_attn586() {elmc_do_attn586(dev->base_addr,0);} #define elmc_id_reset586() {elmc_do_reset586(dev->base_addr,0);} /*************************************************************************/ /* - Do a Channel Attention on the 3c523. This is extremely board dependent. -*/ -static -void -elmc_do_attn586( int ioaddr, int ints ) { - /* the 3c523 requires a minimum of 500 ns. The delays here might be - a little too large, and hence they may cut the performance of the - card slightly. If someone who knows a little more about Linux - timing would care to play with these, I'd appreciate it. */ - - /* this bit masking stuff is crap. I'd rather have separate - registers with strobe triggers for each of these functions. - Ya take what ya got. */ - - outb( ELMC_CTRL_RST|0x3|ELMC_CTRL_CA|ints, ioaddr + ELMC_CTRL); - DELAY_16(); /* > 500 ns */ - outb( ELMC_CTRL_RST|0x3|ints, ioaddr + ELMC_CTRL); + Do a Channel Attention on the 3c523. This is extremely board dependent. + */ +static void elmc_do_attn586(int ioaddr, int ints) +{ + /* the 3c523 requires a minimum of 500 ns. The delays here might be + a little too large, and hence they may cut the performance of the + card slightly. If someone who knows a little more about Linux + timing would care to play with these, I'd appreciate it. */ + + /* this bit masking stuff is crap. I'd rather have separate + registers with strobe triggers for each of these functions. + Ya take what ya got. */ + + outb(ELMC_CTRL_RST | 0x3 | ELMC_CTRL_CA | ints, ioaddr + ELMC_CTRL); + DELAY_16(); /* > 500 ns */ + outb(ELMC_CTRL_RST | 0x3 | ints, ioaddr + ELMC_CTRL); } /*************************************************************************/ /* - Reset the 82586 on the 3c523. Also very board dependent. -*/ -static -void -elmc_do_reset586( int ioaddr, int ints ) { - /* toggle the RST bit low then high */ - outb( 0x3|ELMC_CTRL_LBK, ioaddr + ELMC_CTRL ); - DELAY_16(); /* > 500 ns */ - outb( ELMC_CTRL_RST|ELMC_CTRL_LBK|0x3, ioaddr + ELMC_CTRL ); + Reset the 82586 on the 3c523. Also very board dependent. + */ +static void elmc_do_reset586(int ioaddr, int ints) +{ + /* toggle the RST bit low then high */ + outb(0x3 | ELMC_CTRL_LBK, ioaddr + ELMC_CTRL); + DELAY_16(); /* > 500 ns */ + outb(ELMC_CTRL_RST | ELMC_CTRL_LBK | 0x3, ioaddr + ELMC_CTRL); - elmc_do_attn586( ioaddr, ints ); + elmc_do_attn586(ioaddr, ints); } /********************************************** * close device */ -static -int -elmc_close(struct device *dev) { - elmc_id_reset586(); /* the hard way to stop the receiver */ +static int elmc_close(struct device *dev) +{ + elmc_id_reset586(); /* the hard way to stop the receiver */ - free_irq(dev->irq, dev); + free_irq(dev->irq, dev); - dev->start = 0; - dev->tbusy = 0; + dev->start = 0; + dev->tbusy = 0; #ifdef MODULE MOD_DEC_USE_COUNT; #endif - return 0; + return 0; } /********************************************** * open device */ -static -int -elmc_open(struct device *dev) { - - elmc_id_attn586(); /* disable interrupts */ - - if(request_irq( dev->irq, &elmc_interrupt, SA_SHIRQ|SA_SAMPLE_RANDOM, - "3c523", dev ) - ) { - printk( "%s: couldn't get irq %d\n", dev->name, dev->irq ); - elmc_id_reset586(); - return -EAGAIN; - } - - alloc586(dev); - init586(dev); - startrecv586(dev); - - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; +static int elmc_open(struct device *dev) +{ + + elmc_id_attn586(); /* disable interrupts */ + + if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, + "3c523", dev) + ) { + printk("%s: couldn't get irq %d\n", dev->name, dev->irq); + elmc_id_reset586(); + return -EAGAIN; + } + alloc586(dev); + init586(dev); + startrecv586(dev); + + dev->interrupt = 0; + dev->tbusy = 0; + dev->start = 1; #ifdef MODULE MOD_INC_USE_COUNT; #endif - return 0; /* most done by init */ + return 0; /* most done by init */ } /********************************************** * Check to see if there's an 82586 out there. */ -__initfunc(static -int -check586( struct device *dev, char *where, unsigned size)) { - struct priv *p = (struct priv *) dev->priv; - char *iscp_addrs[2]; - int i = 0; - - p->base = (unsigned long) where + size - 0x01000000; - p->memtop = where + size; - p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS); - memset((char *)p->scp,0, sizeof(struct scp_struct)); - p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ - - iscp_addrs[0] = where; - iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct); - - for( i = 0; i < 2; i ++ ) { - p->iscp = (struct iscp_struct *) iscp_addrs[i]; - memset((char *)p->iscp,0, sizeof(struct iscp_struct)); - - p->scp->iscp = make24(p->iscp); - p->iscp->busy = 1; - - elmc_id_reset586(); - - /* reset586 does an implicit CA */ - - /* apparently, you sometimes have to kick the 82586 twice... */ - elmc_id_attn586(); - - if(p->iscp->busy) { /* i82586 clears 'busy' after successful init */ - return 0; - } - } +__initfunc(static int check586(struct device *dev, char *where, unsigned size)) +{ + struct priv *p = (struct priv *) dev->priv; + char *iscp_addrs[2]; + int i = 0; + + p->base = (unsigned long) where + size - 0x01000000; + p->memtop = where + size; + p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); + memset((char *) p->scp, 0, sizeof(struct scp_struct)); + p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ + + iscp_addrs[0] = where; + iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct); + + for (i = 0; i < 2; i++) { + p->iscp = (struct iscp_struct *) iscp_addrs[i]; + memset((char *) p->iscp, 0, sizeof(struct iscp_struct)); + + p->scp->iscp = make24(p->iscp); + p->iscp->busy = 1; + + elmc_id_reset586(); + + /* reset586 does an implicit CA */ + + /* apparently, you sometimes have to kick the 82586 twice... */ + elmc_id_attn586(); - return 1; + if (p->iscp->busy) { /* i82586 clears 'busy' after successful init */ + return 0; + } + } + return 1; } /****************************************************************** * set iscp at the right place, called by elmc_probe and open586. */ -void -alloc586( struct device *dev ) { - struct priv *p = (struct priv *) dev->priv; - - elmc_id_reset586(); - DELAY(2); +void alloc586(struct device *dev) +{ + struct priv *p = (struct priv *) dev->priv; - p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); - p->scb = (struct scb_struct *) (dev->mem_start); - p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct)); + elmc_id_reset586(); + DELAY(2); - memset((char *) p->iscp,0,sizeof(struct iscp_struct)); - memset((char *) p->scp ,0,sizeof(struct scp_struct)); + p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); + p->scb = (struct scb_struct *) (dev->mem_start); + p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct)); - p->scp->iscp = make24(p->iscp); - p->scp->sysbus = SYSBUSVAL; - p->iscp->scb_offset = make16(p->scb); + memset((char *) p->iscp, 0, sizeof(struct iscp_struct)); + memset((char *) p->scp, 0, sizeof(struct scp_struct)); - p->iscp->busy = 1; - elmc_id_reset586(); - elmc_id_attn586(); + p->scp->iscp = make24(p->iscp); + p->scp->sysbus = SYSBUSVAL; + p->iscp->scb_offset = make16(p->scb); - DELAY(2); + p->iscp->busy = 1; + elmc_id_reset586(); + elmc_id_attn586(); - if(p->iscp->busy) { - printk("%s: Init-Problems (alloc).\n",dev->name); - } + DELAY(2); - memset((char *)p->scb,0,sizeof(struct scb_struct)); + if (p->iscp->busy) { + printk("%s: Init-Problems (alloc).\n", dev->name); + } + memset((char *) p->scb, 0, sizeof(struct scb_struct)); } /*****************************************************************/ -static int -elmc_getinfo( char* buf, int slot, void* d ) { + +static int elmc_getinfo(char *buf, int slot, void *d) +{ int len = 0; - struct device* dev = (struct device*) d; + struct device *dev = (struct device *) d; int i; - if( dev == NULL ) return len; + if (dev == NULL) + return len; - len += sprintf( buf+len, "Revision: 0x%x\n", - inb( dev->base_addr + ELMC_REVISION ) & 0xf ); - len += sprintf( buf+len, "IRQ: %d\n", dev->irq ); - len += sprintf( buf+len, "IO Address: %#lx-%#lx\n", dev->base_addr, - dev->base_addr+ELMC_IO_EXTENT ); - len += sprintf( buf+len, "Memory: %#lx-%#lx\n", dev->mem_start, - dev->mem_end-1 ); - len += sprintf( buf+len, "Transceiver: %s\n", dev->if_port ? - "External" : "Internal" ); - len += sprintf( buf+len, "Device: %s\n", dev->name ); - len += sprintf( buf+len, "Hardware Address:" ); - for (i = 0; i < 6; i ++ ) { - len += sprintf( buf+len, " %02x", dev->dev_addr[i] ); + len += sprintf(buf + len, "Revision: 0x%x\n", + inb(dev->base_addr + ELMC_REVISION) & 0xf); + len += sprintf(buf + len, "IRQ: %d\n", dev->irq); + len += sprintf(buf + len, "IO Address: %#lx-%#lx\n", dev->base_addr, + dev->base_addr + ELMC_IO_EXTENT); + len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, + dev->mem_end - 1); + len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ? + "External" : "Internal"); + len += sprintf(buf + len, "Device: %s\n", dev->name); + len += sprintf(buf + len, "Hardware Address:"); + for (i = 0; i < 6; i++) { + len += sprintf(buf + len, " %02x", dev->dev_addr[i]); } buf[len++] = '\n'; buf[len] = 0; return len; -} /* elmc_getinfo() */ +} /* elmc_getinfo() */ /*****************************************************************/ -__initfunc(int -elmc_probe(struct device *dev)) { - static int slot = 0; - int base_addr = dev ? dev->base_addr : 0; - int irq = dev ? dev->irq : 0; - u_char status = 0; - u_char revision = 0; - int i = 0; - unsigned int size = 0; - - if( MCA_bus == 0 ) { - return ENODEV; - } +__initfunc(int elmc_probe(struct device *dev)) +{ + static int slot = 0; + int base_addr = dev ? dev->base_addr : 0; + int irq = dev ? dev->irq : 0; + u_char status = 0; + u_char revision = 0; + int i = 0; + unsigned int size = 0; + + if (MCA_bus == 0) { + return ENODEV; + } /* search through the slots for the 3c523. */ - slot = mca_find_adapter( ELMC_MCA_ID, 0 ); - while( slot != -1 ) { - status = mca_read_stored_pos( slot, 2 ); + slot = mca_find_adapter(ELMC_MCA_ID, 0); + while (slot != -1) { + status = mca_read_stored_pos(slot, 2); /* - If we're trying to match a specified irq or IO address, - we'll reject a match unless it's what we're looking for. - */ - if( base_addr || irq ) { + If we're trying to match a specified irq or IO address, + we'll reject a match unless it's what we're looking for. + */ + if (base_addr || irq) { /* we're looking for a card at a particular place */ - if( irq && - irq != irq_table[ (status & ELMC_STATUS_IRQ_SELECT) >> 6] - ) { - slot = mca_find_adapter( ELMC_MCA_ID, slot + 1 ); + if (irq && irq != irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]) { + slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } - - if( base_addr && base_addr != - csr_table[ (status & ELMC_STATUS_CSR_SELECT) >> 1] - ) { - slot = mca_find_adapter( ELMC_MCA_ID, slot + 1 ); + if (base_addr && base_addr != csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]) { + slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); continue; } } - /* found what we're looking for... */ break; } /* we didn't find any 3c523 in the slots we checked for */ - if( slot == MCA_NOTFOUND ) { + if (slot == MCA_NOTFOUND) { return ((base_addr || irq) ? ENXIO : ENODEV); } + mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC"); + mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev); - mca_set_adapter_name( slot, "3Com 3c523 Etherlink/MC" ); - mca_set_adapter_procfn( slot, (MCA_ProcFn) elmc_getinfo, dev ); + /* if we get this far, adapter has been found - carry on */ + printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); - /* if we get this far, adapter has been found - carry on */ - printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); + /* Now we extract configuration info from the card. + The 3c523 provides information in two of the POS registers, but + the second one is only needed if we want to tell the card what IRQ + to use. I suspect that whoever sets the thing up initially would + prefer we don't screw with those things. + + Note that we read the status info when we found the card... + + See 3c523.h for more details. + */ + + /* revision is stored in the first 4 bits of the revision register */ + revision = inb(dev->base_addr + ELMC_REVISION) & 0xf; + + /* figure out our irq */ + dev->irq = irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]; + + /* according to docs, we read the interrupt and write it back to + the IRQ select register, since the POST might not configure the IRQ + properly. */ + switch (dev->irq) { + case 3: + mca_write_pos(slot, 3, 0x04); + break; + case 7: + mca_write_pos(slot, 3, 0x02); + break; + case 9: + mca_write_pos(slot, 3, 0x08); + break; + case 12: + mca_write_pos(slot, 3, 0x01); + break; + } + + /* Our IO address? */ + dev->base_addr = csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]; + + request_region(dev->base_addr, ELMC_IO_EXTENT, "3c523"); + + dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL); + if (dev->priv == NULL) { + return -ENOMEM; + } + memset((char *) dev->priv, 0, sizeof(struct priv)); + + ((struct priv *) (dev->priv))->slot = slot; + + printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, + dev->base_addr); + + /* Determine if we're using the on-board transceiver (i.e. coax) or + an external one. The information is pretty much useless, but I + guess it's worth brownie points. */ + dev->if_port = (status & ELMC_STATUS_DISABLE_THIN); + + /* The 3c523 has a 24K chunk of memory. The first 16K is the + shared memory, while the last 8K is for the EtherStart BIOS ROM. + Which we don't care much about here. We'll just tell Linux that + we're using 16K. MCA won't permit adress space conflicts caused + by not mapping the other 8K. */ + dev->mem_start = phys_to_virt(shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]); + + /* We're using MCA, so it's a given that the information about memory + size is correct. The Crynwr drivers do something like this. */ + + elmc_id_reset586(); /* seems like a good idea before checking it... */ + + size = 0x4000; /* check for 16K mem */ + if (!check586(dev, (char *) dev->mem_start, size)) { + printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, + dev->mem_start); + release_region(dev->base_addr, ELMC_IO_EXTENT); + return ENODEV; + } + dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ - /* Now we extract configuration info from the card. - The 3c523 provides information in two of the POS registers, but - the second one is only needed if we want to tell the card what IRQ - to use. I suspect that whoever sets the thing up initially would - prefer we don't screw with those things. - - Note that we read the status info when we found the card... - - See 3c523.h for more details. - */ - - /* revision is stored in the first 4 bits of the revision register */ - revision = inb( dev->base_addr + ELMC_REVISION ) & 0xf; - - /* figure out our irq */ - dev->irq = irq_table[ (status & ELMC_STATUS_IRQ_SELECT) >> 6]; - - /* according to docs, we read the interrupt and write it back to - the IRQ select register, since the POST might not configure the IRQ - properly. */ - switch( dev->irq ) { - case 3: - mca_write_pos( slot, 3, 0x04 ); - break; - case 7: - mca_write_pos( slot, 3, 0x02 ); - break; - case 9: - mca_write_pos( slot, 3, 0x08 ); - break; - case 12: - mca_write_pos( slot, 3, 0x01 ); - break; - } - - /* Our IO address? */ - dev->base_addr = csr_table[ (status & ELMC_STATUS_CSR_SELECT) >> 1]; - - request_region( dev->base_addr, ELMC_IO_EXTENT,"3c523"); - - dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL); - if (dev->priv == NULL) { - return -ENOMEM; - } - memset((char *) dev->priv,0,sizeof(struct priv)); - - ((struct priv *) (dev->priv))->slot = slot; - - printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, - dev->base_addr); - - /* Determine if we're using the on-board transceiver (i.e. coax) or - an external one. The information is pretty much useless, but I - guess it's worth brownie points. */ - dev->if_port = (status & ELMC_STATUS_DISABLE_THIN); - - /* The 3c523 has a 24K chunk of memory. The first 16K is the - shared memory, while the last 8K is for the EtherStart BIOS ROM. - Which we don't care much about here. We'll just tell Linux that - we're using 16K. MCA won't permit adress space conflicts caused - by not mapping the other 8K. */ - dev->mem_start = shm_table[ (status & ELMC_STATUS_MEMORY_SELECT) >> 3]; - - /* We're using MCA, so it's a given that the information about memory - size is correct. The Crynwr drivers do something like this. */ - - elmc_id_reset586(); /* seems like a good idea before checking it... */ - - size = 0x4000; /* check for 16K mem */ - if(!check586(dev,(char *) dev->mem_start,size)) { - printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, - dev->mem_start ); - release_region( dev->base_addr, ELMC_IO_EXTENT ); - return ENODEV; - } - dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ - - ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000; - alloc586(dev); - - elmc_id_reset586(); /* make sure it doesn't generate spurious ints */ - - /* set number of receive-buffs according to memsize */ - ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; - - /* dump all the assorted information */ - printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, - dev->irq, dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1); - - /* The hardware address for the 3c523 is stored in the first six - bytes of the IO address. */ - printk( "%s: hardware address ", dev->name ); - for (i = 0; i < 6; i ++ ) { - dev->dev_addr[i] = inb(dev->base_addr + i); - printk(" %02x", dev->dev_addr[i]); - } - printk( "\n" ); - - dev->open = &elmc_open; - dev->stop = &elmc_close; - dev->get_stats = &elmc_get_stats; - dev->hard_start_xmit = &elmc_send_packet; - dev->set_multicast_list = &set_multicast_list; - - ether_setup(dev); - - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - - /* note that we haven't actually requested the IRQ from the kernel. - That gets done in elmc_open(). I'm not sure that's such a good idea, - but it works, so I'll go with it. */ + ((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000; + alloc586(dev); - return 0; + elmc_id_reset586(); /* make sure it doesn't generate spurious ints */ + + /* set number of receive-buffs according to memsize */ + ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; + + /* dump all the assorted information */ + printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, + dev->irq, dev->if_port ? "ex" : "in", + virt_to_phys(dev->mem_start), + virt_to_phys(dev->mem_end - 1)); + + /* The hardware address for the 3c523 is stored in the first six + bytes of the IO address. */ + printk("%s: hardware address ", dev->name); + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = inb(dev->base_addr + i); + printk(" %02x", dev->dev_addr[i]); + } + printk("\n"); + + dev->open = &elmc_open; + dev->stop = &elmc_close; + dev->get_stats = &elmc_get_stats; + dev->hard_start_xmit = &elmc_send_packet; + dev->set_multicast_list = &set_multicast_list; + + ether_setup(dev); + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 0; + + /* note that we haven't actually requested the IRQ from the kernel. + That gets done in elmc_open(). I'm not sure that's such a good idea, + but it works, so I'll go with it. */ + + return 0; } /********************************************** @@ -590,241 +586,237 @@ * needs a correct 'allocated' memory */ -static -int -init586(struct device *dev) { - void *ptr; - unsigned long s; - int i,result=0; - struct priv *p = (struct priv *) dev->priv; - volatile struct configure_cmd_struct *cfg_cmd; - volatile struct iasetup_cmd_struct *ias_cmd; - volatile struct tdr_cmd_struct *tdr_cmd; - volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi=dev->mc_list; - int num_addrs=dev->mc_count; - - ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); - - cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */ - cfg_cmd->cmd_status = 0; - cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; - cfg_cmd->cmd_link = 0xffff; - - cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ - cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */ - cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ - cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ - cfg_cmd->priority = 0x00; - cfg_cmd->ifs = 0x60; - cfg_cmd->time_low = 0x00; - cfg_cmd->time_high = 0xf2; - cfg_cmd->promisc = 0; - if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) - { - cfg_cmd->promisc=1; - dev->flags|=IFF_PROMISC; - } - cfg_cmd->carr_coll = 0x00; - - p->scb->cbl_offset = make16(cfg_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_id_attn586(); - - s = jiffies; /* warning: only active with interrupts on !! */ - while(!(cfg_cmd->cmd_status & STAT_COMPL)) { - if(jiffies-s > 30) break; - } - - if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) { - printk("%s (elmc): configure command failed: %x\n",dev->name,cfg_cmd->cmd_status); - return 1; - } - - /* - * individual address setup - */ - ias_cmd = (struct iasetup_cmd_struct *)ptr; - - ias_cmd->cmd_status = 0; - ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; - ias_cmd->cmd_link = 0xffff; - - memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); - - p->scb->cbl_offset = make16(ias_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_id_attn586(); - - s = jiffies; - while(!(ias_cmd->cmd_status & STAT_COMPL)) { - if(jiffies-s > 30) break; - } - - if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { - printk("%s (elmc): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status); - return 1; - } - - /* - * TDR, wire check .. e.g. no resistor e.t.c - */ - tdr_cmd = (struct tdr_cmd_struct *)ptr; - - tdr_cmd->cmd_status = 0; - tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; - tdr_cmd->cmd_link = 0xffff; - tdr_cmd->status = 0; - - p->scb->cbl_offset = make16(tdr_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_attn586(); - - s = jiffies; - while(!(tdr_cmd->cmd_status & STAT_COMPL)) { - if(jiffies - s > 30) { - printk("%s: %d Problems while running the TDR.\n",dev->name,__LINE__); - result = 1; - break; - } - } - - if(!result) { - DELAY(2); /* wait for result */ - result = tdr_cmd->status; - - p->scb->cmd = p->scb->status & STAT_MASK; - elmc_id_attn586(); /* ack the interrupts */ - - if(result & TDR_LNK_OK) { - /* empty */ - } else if(result & TDR_XCVR_PRB) { - printk("%s: TDR: Transceiver problem!\n",dev->name); - } else if(result & TDR_ET_OPN) { - printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - } else if(result & TDR_ET_SRT) { - if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - } else { - printk("%s: TDR: Unknown status %04x\n",dev->name,result); - } - } - - /* - * ack interrupts - */ - p->scb->cmd = p->scb->status & STAT_MASK; - elmc_id_attn586(); - - /* - * alloc nop/xmit-cmds - */ +static int init586(struct device *dev) +{ + void *ptr; + unsigned long s; + int i, result = 0; + struct priv *p = (struct priv *) dev->priv; + volatile struct configure_cmd_struct *cfg_cmd; + volatile struct iasetup_cmd_struct *ias_cmd; + volatile struct tdr_cmd_struct *tdr_cmd; + volatile struct mcsetup_cmd_struct *mc_cmd; + struct dev_mc_list *dmi = dev->mc_list; + int num_addrs = dev->mc_count; + + ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); + + cfg_cmd = (struct configure_cmd_struct *) ptr; /* configure-command */ + cfg_cmd->cmd_status = 0; + cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; + cfg_cmd->cmd_link = 0xffff; + + cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ + cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */ + cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ + cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ + cfg_cmd->priority = 0x00; + cfg_cmd->ifs = 0x60; + cfg_cmd->time_low = 0x00; + cfg_cmd->time_high = 0xf2; + cfg_cmd->promisc = 0; + if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC)) { + cfg_cmd->promisc = 1; + dev->flags |= IFF_PROMISC; + } + cfg_cmd->carr_coll = 0x00; + + p->scb->cbl_offset = make16(cfg_cmd); + + p->scb->cmd = CUC_START; /* cmd.-unit start */ + elmc_id_attn586(); + + s = jiffies; /* warning: only active with interrupts on !! */ + while (!(cfg_cmd->cmd_status & STAT_COMPL)) { + if (jiffies - s > 30) + break; + } + + if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) { + printk("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); + return 1; + } + /* + * individual address setup + */ + ias_cmd = (struct iasetup_cmd_struct *) ptr; + + ias_cmd->cmd_status = 0; + ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; + ias_cmd->cmd_link = 0xffff; + + memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN); + + p->scb->cbl_offset = make16(ias_cmd); + + p->scb->cmd = CUC_START; /* cmd.-unit start */ + elmc_id_attn586(); + + s = jiffies; + while (!(ias_cmd->cmd_status & STAT_COMPL)) { + if (jiffies - s > 30) + break; + } + + if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) { + printk("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status); + return 1; + } + /* + * TDR, wire check .. e.g. no resistor e.t.c + */ + tdr_cmd = (struct tdr_cmd_struct *) ptr; + + tdr_cmd->cmd_status = 0; + tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; + tdr_cmd->cmd_link = 0xffff; + tdr_cmd->status = 0; + + p->scb->cbl_offset = make16(tdr_cmd); + + p->scb->cmd = CUC_START; /* cmd.-unit start */ + elmc_attn586(); + + s = jiffies; + while (!(tdr_cmd->cmd_status & STAT_COMPL)) { + if (jiffies - s > 30) { + printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); + result = 1; + break; + } + } + + if (!result) { + DELAY(2); /* wait for result */ + result = tdr_cmd->status; + + p->scb->cmd = p->scb->status & STAT_MASK; + elmc_id_attn586(); /* ack the interrupts */ + + if (result & TDR_LNK_OK) { + /* empty */ + } else if (result & TDR_XCVR_PRB) { + printk("%s: TDR: Transceiver problem!\n", dev->name); + } else if (result & TDR_ET_OPN) { + printk("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + } else if (result & TDR_ET_SRT) { + if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ + printk("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); + } else { + printk("%s: TDR: Unknown status %04x\n", dev->name, result); + } + } + /* + * ack interrupts + */ + p->scb->cmd = p->scb->status & STAT_MASK; + elmc_id_attn586(); + + /* + * alloc nop/xmit-cmds + */ #if (NUM_XMIT_BUFFS == 1) - for(i=0;i<2;i++) { - p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - } - p->xmit_cmds[0] = (struct transmit_cmd_struct *)ptr; /* transmit cmd/buff 0 */ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); + for (i = 0; i < 2; i++) { + p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; + p->nop_cmds[i]->cmd_cmd = CMD_NOP; + p->nop_cmds[i]->cmd_status = 0; + p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); + ptr = (char *) ptr + sizeof(struct nop_cmd_struct); + } + p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr; /* transmit cmd/buff 0 */ + ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); #else - for(i=0;inop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); - } + for (i = 0; i < NUM_XMIT_BUFFS; i++) { + p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; + p->nop_cmds[i]->cmd_cmd = CMD_NOP; + p->nop_cmds[i]->cmd_status = 0; + p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); + ptr = (char *) ptr + sizeof(struct nop_cmd_struct); + p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr; /*transmit cmd/buff 0 */ + ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); + } #endif - ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ + ptr = alloc_rfa(dev, (void *) ptr); /* init receive-frame-area */ - /* - * Multicast setup - */ - - if(dev->mc_count) { - /* I don't understand this: do we really need memory after the init? */ - int len = ((char *) p->iscp - (char *) ptr - 8) / 6; - if(len <= 0) { - printk("%s: Ooooops, no memory for MC-Setup!\n",dev->name); - } else { - if(len < num_addrs) { - num_addrs = len; - printk("%s: Sorry, can only apply %d MC-Address(es).\n", - dev->name, num_addrs); - } - mc_cmd = (struct mcsetup_cmd_struct *) ptr; - mc_cmd->cmd_status = 0; - mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; - mc_cmd->cmd_link = 0xffff; - mc_cmd->mc_cnt = num_addrs * 6; - for(i=0;imc_list[i], dmi->dmi_addr,6); - dmi=dmi->next; - } - p->scb->cbl_offset = make16(mc_cmd); - p->scb->cmd = CUC_START; - elmc_id_attn586(); - s = jiffies; - while(!(mc_cmd->cmd_status & STAT_COMPL)) { - if(jiffies - s > 30) - break; - } - if(!(mc_cmd->cmd_status & STAT_COMPL)) { - printk("%s: Can't apply multicast-address-list.\n",dev->name); - } - } - } - - /* - * alloc xmit-buffs / init xmit_cmds - */ - for(i=0;ixmit_cbuffs[i] = (char *)ptr; /* char-buffs */ - ptr = (char *) ptr + XMIT_BUFF_SIZE; - p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */ - ptr = (char *) ptr + sizeof(struct tbd_struct); - if((void *)ptr > (void *)p->iscp) { - printk("%s: not enough shared-mem for your configuration!\n",dev->name); - return 1; - } - memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct)); - memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct)); - p->xmit_cmds[i]->cmd_status = STAT_COMPL; - p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; - p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); - p->xmit_buffs[i]->next = 0xffff; - p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); - } + /* + * Multicast setup + */ + + if (dev->mc_count) { + /* I don't understand this: do we really need memory after the init? */ + int len = ((char *) p->iscp - (char *) ptr - 8) / 6; + if (len <= 0) { + printk("%s: Ooooops, no memory for MC-Setup!\n", dev->name); + } else { + if (len < num_addrs) { + num_addrs = len; + printk("%s: Sorry, can only apply %d MC-Address(es).\n", + dev->name, num_addrs); + } + mc_cmd = (struct mcsetup_cmd_struct *) ptr; + mc_cmd->cmd_status = 0; + mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; + mc_cmd->cmd_link = 0xffff; + mc_cmd->mc_cnt = num_addrs * 6; + for (i = 0; i < num_addrs; i++) { + memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr, 6); + dmi = dmi->next; + } + p->scb->cbl_offset = make16(mc_cmd); + p->scb->cmd = CUC_START; + elmc_id_attn586(); + s = jiffies; + while (!(mc_cmd->cmd_status & STAT_COMPL)) { + if (jiffies - s > 30) + break; + } + if (!(mc_cmd->cmd_status & STAT_COMPL)) { + printk("%s: Can't apply multicast-address-list.\n", dev->name); + } + } + } + /* + * alloc xmit-buffs / init xmit_cmds + */ + for (i = 0; i < NUM_XMIT_BUFFS; i++) { + p->xmit_cbuffs[i] = (char *) ptr; /* char-buffs */ + ptr = (char *) ptr + XMIT_BUFF_SIZE; + p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */ + ptr = (char *) ptr + sizeof(struct tbd_struct); + if ((void *) ptr > (void *) p->iscp) { + printk("%s: not enough shared-mem for your configuration!\n", dev->name); + return 1; + } + memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct)); + memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct)); + p->xmit_cmds[i]->cmd_status = STAT_COMPL; + p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; + p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); + p->xmit_buffs[i]->next = 0xffff; + p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); + } - p->xmit_count = 0; - p->xmit_last = 0; + p->xmit_count = 0; + p->xmit_last = 0; #ifndef NO_NOPCOMMANDS - p->nop_point = 0; + p->nop_point = 0; #endif - /* - * 'start transmitter' (nop-loop) - */ + /* + * 'start transmitter' (nop-loop) + */ #ifndef NO_NOPCOMMANDS - p->scb->cbl_offset = make16(p->nop_cmds[0]); - p->scb->cmd = CUC_START; - elmc_id_attn586(); - WAIT_4_SCB_CMD(); + p->scb->cbl_offset = make16(p->nop_cmds[0]); + p->scb->cmd = CUC_START; + elmc_id_attn586(); + WAIT_4_SCB_CMD(); #else - p->xmit_cmds[0]->cmd_link = 0xffff; - p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT; + p->xmit_cmds[0]->cmd_link = 0xffff; + p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT; #endif - return 0; + return 0; } /****************************************************** @@ -832,44 +824,43 @@ * It sets up the Receive Frame Area (RFA). */ -static -void* -alloc_rfa(struct device *dev,void *ptr) { - volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr; - volatile struct rbd_struct *rbd; - int i; - struct priv *p = (struct priv *) dev->priv; - - memset((char *) rfd,0,sizeof(struct rfd_struct)*p->num_recv_buffs); - p->rfd_first = rfd; - - for(i = 0; i < p->num_recv_buffs; i++) { - rfd[i].next = make16(rfd + (i+1) % p->num_recv_buffs); - } - rfd[p->num_recv_buffs-1].last = RFD_SUSP; /* RU suspend */ - - ptr = (void *) (rfd + p->num_recv_buffs); - - rbd = (struct rbd_struct *) ptr; - ptr = (void *) (rbd + p->num_recv_buffs); - - /* clr descriptors */ - memset((char *) rbd,0,sizeof(struct rbd_struct)*p->num_recv_buffs); - - for(i=0;inum_recv_buffs;i++) { - rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs)); - rbd[i].size = RECV_BUFF_SIZE; - rbd[i].buffer = make24(ptr); - ptr = (char *) ptr + RECV_BUFF_SIZE; - } +static void *alloc_rfa(struct device *dev, void *ptr) +{ + volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr; + volatile struct rbd_struct *rbd; + int i; + struct priv *p = (struct priv *) dev->priv; + + memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs); + p->rfd_first = rfd; + + for (i = 0; i < p->num_recv_buffs; i++) { + rfd[i].next = make16(rfd + (i + 1) % p->num_recv_buffs); + } + rfd[p->num_recv_buffs - 1].last = RFD_SUSP; /* RU suspend */ + + ptr = (void *) (rfd + p->num_recv_buffs); + + rbd = (struct rbd_struct *) ptr; + ptr = (void *) (rbd + p->num_recv_buffs); - p->rfd_top = p->rfd_first; - p->rfd_last = p->rfd_first + p->num_recv_buffs - 1; + /* clr descriptors */ + memset((char *) rbd, 0, sizeof(struct rbd_struct) * p->num_recv_buffs); - p->scb->rfa_offset = make16(p->rfd_first); - p->rfd_first->rbd_offset = make16(rbd); + for (i = 0; i < p->num_recv_buffs; i++) { + rbd[i].next = make16((rbd + (i + 1) % p->num_recv_buffs)); + rbd[i].size = RECV_BUFF_SIZE; + rbd[i].buffer = make24(ptr); + ptr = (char *) ptr + RECV_BUFF_SIZE; + } + + p->rfd_top = p->rfd_first; + p->rfd_last = p->rfd_first + p->num_recv_buffs - 1; + + p->scb->rfa_offset = make16(p->rfd_first); + p->rfd_first->rbd_offset = make16(rbd); - return ptr; + return ptr; } @@ -877,152 +868,145 @@ * Interrupt Handler ... */ -static -void -elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) { - struct device *dev = (struct device *) dev_id; - unsigned short stat; - struct priv *p; - - if (dev == NULL) { - printk ("elmc-interrupt: irq %d for unknown device.\n",(int) -(((struct pt_regs *)reg_ptr)->orig_eax+2)); - return; - } else if( !dev->start ) { - /* The 3c523 has this habit of generating interrupts during the - reset. I'm not sure if the ni52 has this same problem, but it's - really annoying if we haven't finished initializing it. I was - hoping all the elmc_id_* commands would disable this, but I - might have missed a few. */ - - elmc_id_attn586(); /* ack inter. and disable any more */ - return; - } else if( !(ELMC_CTRL_INT & inb( dev->base_addr+ELMC_CTRL )) ) { - /* wasn't this device */ - return; - } - - /* reading ELMC_CTRL also clears the INT bit. */ - - p = (struct priv *) dev->priv; - - dev->interrupt = 1; - - while((stat=p->scb->status & STAT_MASK)) { - p->scb->cmd = stat; - elmc_attn586(); /* ack inter. */ - - if(stat & STAT_CX) { - /* command with I-bit set complete */ - elmc_xmt_int(dev); - } - - if(stat & STAT_FR) { - /* received a frame */ - elmc_rcv_int(dev); - } +static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr) +{ + struct device *dev = (struct device *) dev_id; + unsigned short stat; + struct priv *p; + + if (dev == NULL) { + printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2)); + return; + } else if (!dev->start) { + /* The 3c523 has this habit of generating interrupts during the + reset. I'm not sure if the ni52 has this same problem, but it's + really annoying if we haven't finished initializing it. I was + hoping all the elmc_id_* commands would disable this, but I + might have missed a few. */ + + elmc_id_attn586(); /* ack inter. and disable any more */ + return; + } else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) { + /* wasn't this device */ + return; + } + /* reading ELMC_CTRL also clears the INT bit. */ + + p = (struct priv *) dev->priv; + + dev->interrupt = 1; + + while ((stat = p->scb->status & STAT_MASK)) + { + p->scb->cmd = stat; + elmc_attn586(); /* ack inter. */ + if (stat & STAT_CX) { + /* command with I-bit set complete */ + elmc_xmt_int(dev); + } + if (stat & STAT_FR) { + /* received a frame */ + elmc_rcv_int(dev); + } #ifndef NO_NOPCOMMANDS - if(stat & STAT_CNA) { - /* CU went 'not ready' */ - if(dev->start) { - printk("%s: oops! CU has left active state. stat: %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status); - } - } + if (stat & STAT_CNA) { + /* CU went 'not ready' */ + if (dev->start) { + printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + } + } #endif - if(stat & STAT_RNR) { - /* RU went 'not ready' */ + if (stat & STAT_RNR) { + /* RU went 'not ready' */ - if(p->scb->status & RU_SUSPEND) { - /* special case: RU_SUSPEND */ + if (p->scb->status & RU_SUSPEND) { + /* special case: RU_SUSPEND */ - WAIT_4_SCB_CMD(); - p->scb->cmd = RUC_RESUME; - elmc_attn586(); - } else { - printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n",dev->name,(int) stat,(int) p->scb->status); - elmc_rnr_int(dev); - } - } - WAIT_4_SCB_CMD(); /* wait for ack. (elmc_xmt_int can be faster than ack!!) */ - if(p->scb->cmd) { /* timed out? */ - break; - } - } + WAIT_4_SCB_CMD(); + p->scb->cmd = RUC_RESUME; + elmc_attn586(); + } else { + printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status); + elmc_rnr_int(dev); + } + } + WAIT_4_SCB_CMD(); /* wait for ack. (elmc_xmt_int can be faster than ack!!) */ + if (p->scb->cmd) { /* timed out? */ + break; + } + } - dev->interrupt = 0; + dev->interrupt = 0; } /******************************************************* * receive-interrupt */ -static -void -elmc_rcv_int(struct device *dev) { - int status; - unsigned short totlen; - struct sk_buff *skb; - struct rbd_struct *rbd; - struct priv *p = (struct priv *) dev->priv; - - for(;(status = p->rfd_top->status) & STAT_COMPL;) { - rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); - - if(status & STAT_OK) /* frame received without error? */ - { - if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */ - { - totlen &= RBD_MASK; /* length of this frame */ - rbd->status = 0; - skb = (struct sk_buff *) dev_alloc_skb(totlen+2); - if(skb != NULL) { - skb->dev = dev; - skb_reserve(skb,2); /* 16 byte alignment */ - memcpy(skb_put(skb,totlen),(char *) p->base+(unsigned long) rbd->buffer, totlen); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - p->stats.rx_packets++; - p->stats.rx_bytes+=totlen; - } else { - p->stats.rx_dropped++; - } - } else { - printk("%s: received oversized frame.\n",dev->name); - p->stats.rx_dropped++; - } - } else /* frame !(ok), only with 'save-bad-frames' */ { - printk("%s: oops! rfd-error-status: %04x\n",dev->name,status); - p->stats.rx_errors++; - } - p->rfd_top->status = 0; - p->rfd_top->last = RFD_SUSP; - p->rfd_last->last = 0; /* delete RU_SUSP */ - p->rfd_last = p->rfd_top; - p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ - } +static void elmc_rcv_int(struct device *dev) +{ + int status; + unsigned short totlen; + struct sk_buff *skb; + struct rbd_struct *rbd; + struct priv *p = (struct priv *) dev->priv; + + for (; (status = p->rfd_top->status) & STAT_COMPL;) { + rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); + + if (status & STAT_OK) { /* frame received without error? */ + if ((totlen = rbd->status) & RBD_LAST) { /* the first and the last buffer? */ + totlen &= RBD_MASK; /* length of this frame */ + rbd->status = 0; + skb = (struct sk_buff *) dev_alloc_skb(totlen + 2); + if (skb != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte alignment */ + memcpy(skb_put(skb, totlen), (char *) p->base + (unsigned long) rbd->buffer, totlen); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + p->stats.rx_packets++; + p->stats.rx_bytes += totlen; + } else { + p->stats.rx_dropped++; + } + } else { + printk("%s: received oversized frame.\n", dev->name); + p->stats.rx_dropped++; + } + } else { /* frame !(ok), only with 'save-bad-frames' */ + printk("%s: oops! rfd-error-status: %04x\n", dev->name, status); + p->stats.rx_errors++; + } + p->rfd_top->status = 0; + p->rfd_top->last = RFD_SUSP; + p->rfd_last->last = 0; /* delete RU_SUSP */ + p->rfd_last = p->rfd_top; + p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ + } } /********************************************************** * handle 'Receiver went not ready'. */ -static -void -elmc_rnr_int(struct device *dev) { - struct priv *p = (struct priv *) dev->priv; - - p->stats.rx_errors++; - - WAIT_4_SCB_CMD(); /* wait for the last cmd */ - p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ - elmc_attn586(); - WAIT_4_SCB_CMD(); /* wait for accept cmd. */ +static void elmc_rnr_int(struct device *dev) +{ + struct priv *p = (struct priv *) dev->priv; + + p->stats.rx_errors++; + + WAIT_4_SCB_CMD(); /* wait for the last cmd */ + p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ + elmc_attn586(); + WAIT_4_SCB_CMD(); /* wait for accept cmd. */ - alloc_rfa(dev,(char *)p->rfd_first); - startrecv586(dev); /* restart RU */ + alloc_rfa(dev, (char *) p->rfd_first); + startrecv586(dev); /* restart RU */ - printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->status); + printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); } @@ -1030,286 +1014,269 @@ * handle xmit - interrupt */ -static -void -elmc_xmt_int(struct device *dev) { - int status; - struct priv *p = (struct priv *) dev->priv; - - status = p->xmit_cmds[p->xmit_last]->cmd_status; - if(!(status & STAT_COMPL)) { - printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name); - } - - if(status & STAT_OK) { - p->stats.tx_packets++; - p->stats.collisions += (status & TCMD_MAXCOLLMASK); - } else { - p->stats.tx_errors++; - if(status & TCMD_LATECOLL) { - printk("%s: late collision detected.\n",dev->name); - p->stats.collisions++; - } else if(status & TCMD_NOCARRIER) { - p->stats.tx_carrier_errors++; - printk("%s: no carrier detected.\n",dev->name); - } else if(status & TCMD_LOSTCTS) { - printk("%s: loss of CTS detected.\n",dev->name); - } else if(status & TCMD_UNDERRUN) { - p->stats.tx_fifo_errors++; - printk("%s: DMA underrun detected.\n",dev->name); - } else if(status & TCMD_MAXCOLL) { - printk("%s: Max. collisions exceeded.\n",dev->name); - p->stats.collisions += 16; - } - } +static void elmc_xmt_int(struct device *dev) +{ + int status; + struct priv *p = (struct priv *) dev->priv; + + status = p->xmit_cmds[p->xmit_last]->cmd_status; + if (!(status & STAT_COMPL)) { + printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); + } + if (status & STAT_OK) { + p->stats.tx_packets++; + p->stats.collisions += (status & TCMD_MAXCOLLMASK); + } else { + p->stats.tx_errors++; + if (status & TCMD_LATECOLL) { + printk("%s: late collision detected.\n", dev->name); + p->stats.collisions++; + } else if (status & TCMD_NOCARRIER) { + p->stats.tx_carrier_errors++; + printk("%s: no carrier detected.\n", dev->name); + } else if (status & TCMD_LOSTCTS) { + printk("%s: loss of CTS detected.\n", dev->name); + } else if (status & TCMD_UNDERRUN) { + p->stats.tx_fifo_errors++; + printk("%s: DMA underrun detected.\n", dev->name); + } else if (status & TCMD_MAXCOLL) { + printk("%s: Max. collisions exceeded.\n", dev->name); + p->stats.collisions += 16; + } + } #if (NUM_XMIT_BUFFS != 1) - if( (++p->xmit_last) == NUM_XMIT_BUFFS) { - p->xmit_last = 0; - } + if ((++p->xmit_last) == NUM_XMIT_BUFFS) { + p->xmit_last = 0; + } #endif - dev->tbusy = 0; - mark_bh(NET_BH); + dev->tbusy = 0; + mark_bh(NET_BH); } /*********************************************************** * (re)start the receiver */ -static -void -startrecv586(struct device *dev) -{ - struct priv *p = (struct priv *) dev->priv; - - p->scb->rfa_offset = make16(p->rfd_first); - p->scb->cmd = RUC_START; - elmc_attn586(); /* start cmd. */ - WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */ +static void startrecv586(struct device *dev) +{ + struct priv *p = (struct priv *) dev->priv; + + p->scb->rfa_offset = make16(p->rfd_first); + p->scb->cmd = RUC_START; + elmc_attn586(); /* start cmd. */ + WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */ } /****************************************************** * send frame */ -static -int -elmc_send_packet(struct sk_buff *skb, struct device *dev) +static int elmc_send_packet(struct sk_buff *skb, struct device *dev) { - int len; + int len; #ifndef NO_NOPCOMMANDS - int next_nop; + int next_nop; #endif - struct priv *p = (struct priv *) dev->priv; + struct priv *p = (struct priv *) dev->priv; - if(dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) { - return 1; - } - - /* COMMAND-UNIT active? */ - if(p->scb->status & CU_ACTIVE) { - dev->tbusy = 0; + if (dev->tbusy) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5) { + return 1; + } + /* COMMAND-UNIT active? */ + if (p->scb->status & CU_ACTIVE) { + dev->tbusy = 0; #ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n",dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); + printk("%s: strange ... timeout with CU active?!?\n", dev->name); + printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point); #endif - p->scb->cmd = CUC_ABORT; - elmc_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd = CUC_START; - elmc_attn586(); - WAIT_4_SCB_CMD(); - dev->trans_start = jiffies; - return 0; - } else { + p->scb->cmd = CUC_ABORT; + elmc_attn586(); + WAIT_4_SCB_CMD(); + p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); + p->scb->cmd = CUC_START; + elmc_attn586(); + WAIT_4_SCB_CMD(); + dev->trans_start = jiffies; + return 0; + } else { #ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status); - printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); + printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status); + printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); #endif - elmc_close(dev); - elmc_open(dev); - } - dev->trans_start = jiffies; - return 0; - } - - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - } else { - memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + elmc_close(dev); + elmc_open(dev); + } + dev->trans_start = jiffies; + return 0; + } + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + printk("%s: Transmitter access conflict.\n", dev->name); + } else { + memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len); + len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #if (NUM_XMIT_BUFFS == 1) -# ifdef NO_NOPCOMMANDS - p->xmit_buffs[0]->size = TBD_LAST | len; - for(i=0;i<16;i++) { - p->scb->cbl_offset = make16(p->xmit_cmds[0]); - p->scb->cmd = CUC_START; - p->xmit_cmds[0]->cmd_status = 0; - - elmc_attn586(); - dev->trans_start = jiffies; - if(!i) { - dev_kfree_skb(skb); - } - WAIT_4_SCB_CMD(); - if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ - { - break; - } - if(p->xmit_cmds[0]->cmd_status) { - break; - } - if(i==15) { - printk("%s: Can't start transmit-command.\n",dev->name); - } - } -# else - next_nop = (p->nop_point + 1) & 0x1; - p->xmit_buffs[0]->size = TBD_LAST | len; - - p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - dev->trans_start = jiffies; - p->nop_point = next_nop; - dev_kfree_skb(skb); -# endif +#ifdef NO_NOPCOMMANDS + p->xmit_buffs[0]->size = TBD_LAST | len; + for (i = 0; i < 16; i++) { + p->scb->cbl_offset = make16(p->xmit_cmds[0]); + p->scb->cmd = CUC_START; + p->xmit_cmds[0]->cmd_status = 0; + + elmc_attn586(); + dev->trans_start = jiffies; + if (!i) { + dev_kfree_skb(skb); + } + WAIT_4_SCB_CMD(); + if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */ + break; + } + if (p->xmit_cmds[0]->cmd_status) { + break; + } + if (i == 15) { + printk("%s: Can't start transmit-command.\n", dev->name); + } + } #else - p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; - if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) { - next_nop = 0; - } - - p->xmit_cmds[p->xmit_count]->cmd_status = 0; - p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; - p->xmit_count = next_nop; - - cli(); - if(p->xmit_count != p->xmit_last) { - dev->tbusy = 0; - } - sti(); - dev_kfree_skb(skb); + next_nop = (p->nop_point + 1) & 0x1; + p->xmit_buffs[0]->size = TBD_LAST | len; + + p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link + = make16((p->nop_cmds[next_nop])); + p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; + + p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); + dev->trans_start = jiffies; + p->nop_point = next_nop; + dev_kfree_skb(skb); +#endif +#else + p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; + if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) { + next_nop = 0; + } + p->xmit_cmds[p->xmit_count]->cmd_status = 0; + p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link + = make16((p->nop_cmds[next_nop])); + p->nop_cmds[next_nop]->cmd_status = 0; + + p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); + dev->trans_start = jiffies; + p->xmit_count = next_nop; + + cli(); + if (p->xmit_count != p->xmit_last) { + dev->tbusy = 0; + } + sti(); + dev_kfree_skb(skb); #endif - } - return 0; + } + return 0; } /******************************************* * Someone wanna have the statistics */ -static struct net_device_stats *elmc_get_stats( struct device *dev ) +static struct net_device_stats *elmc_get_stats(struct device *dev) { - struct priv *p = (struct priv *) dev->priv; - unsigned short crc,aln,rsc,ovrn; + struct priv *p = (struct priv *) dev->priv; + unsigned short crc, aln, rsc, ovrn; - crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ - p->scb->crc_errs -= crc; - aln = p->scb->aln_errs; - p->scb->aln_errs -= aln; - rsc = p->scb->rsc_errs; - p->scb->rsc_errs -= rsc; - ovrn = p->scb->ovrn_errs; - p->scb->ovrn_errs -= ovrn; - - p->stats.rx_crc_errors += crc; - p->stats.rx_fifo_errors += ovrn; - p->stats.rx_frame_errors += aln; - p->stats.rx_dropped += rsc; + crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ + p->scb->crc_errs -= crc; + aln = p->scb->aln_errs; + p->scb->aln_errs -= aln; + rsc = p->scb->rsc_errs; + p->scb->rsc_errs -= rsc; + ovrn = p->scb->ovrn_errs; + p->scb->ovrn_errs -= ovrn; + + p->stats.rx_crc_errors += crc; + p->stats.rx_fifo_errors += ovrn; + p->stats.rx_frame_errors += aln; + p->stats.rx_dropped += rsc; - return &p->stats; + return &p->stats; } /******************************************************** * Set MC list .. */ -static -void -set_multicast_list(struct device *dev) { - if(!dev->start) { - /* without a running interface, promiscuous doesn't work */ - return; - } - - dev->start = 0; - alloc586(dev); - init586(dev); - startrecv586(dev); - dev->start = 1; +static void set_multicast_list(struct device *dev) +{ + if (!dev->start) { + /* without a running interface, promiscuous doesn't work */ + return; + } + dev->start = 0; + alloc586(dev); + init586(dev); + startrecv586(dev); + dev->start = 1; } /*************************************************************************/ #ifdef MODULE -static char devicename[9] = { 0, }; -static struct device dev_elmc = { - devicename /*"3c523"*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe }; -static int irq=0; -static int io=0; +static char devicename[9] = {0,}; + +static struct device dev_elmc = +{ + devicename /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, elmc_probe +}; + +static int irq = 0; +static int io = 0; MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); -int -init_module(void) { +int init_module(void) +{ struct device *dev = &dev_elmc; - dev->base_addr=io; - dev->irq=irq; + dev->base_addr = io; + dev->irq = irq; if (register_netdev(dev) != 0) { return -EIO; } - return 0; } -void -cleanup_module(void) { +void cleanup_module(void) +{ struct device *dev = &dev_elmc; - if (MOD_IN_USE) { - printk("3c523: device busy, remove delayed\n"); - } else { - /* shutdown interrupts on the card */ - elmc_id_reset586(); - - if( dev->irq != 0 ) { - /* this should be done by close, but if we failed to - initialize properly something may have gotten hosed. */ - free_irq( dev->irq, dev ); - dev->irq = 0; - } - - - - if( dev->base_addr != 0 ) { - release_region( dev->base_addr, ELMC_IO_EXTENT ); - dev->base_addr = 0; - } - irq = 0; - io = 0; - - unregister_netdev(dev); + /* shutdown interrupts on the card */ + elmc_id_reset586(); + if (dev->irq != 0) { + /* this should be done by close, but if we failed to + initialize properly something may have gotten hosed. */ + free_irq(dev->irq, dev); + dev->irq = 0; + } + if (dev->base_addr != 0) { + release_region(dev->base_addr, ELMC_IO_EXTENT); + dev->base_addr = 0; + } + irq = 0; + io = 0; + unregister_netdev(dev); - mca_set_adapter_procfn( ((struct priv *) (dev->priv))->slot, - NULL, NULL ); + mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, + NULL, NULL); - kfree_s(dev->priv,sizeof(struct priv)); - dev->priv=NULL; - } + kfree_s(dev->priv, sizeof(struct priv)); + dev->priv = NULL; } -#endif /* MODULE */ + +#endif /* MODULE */ diff -u --recursive --new-file v2.1.127/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.1.127/linux/drivers/net/3c59x.c Wed Sep 9 14:51:08 1998 +++ linux/drivers/net/3c59x.c Sun Nov 8 11:00:06 1998 @@ -79,6 +79,8 @@ #include #include #include + +#include #include /* For NR_IRQS only. */ #include #include @@ -332,10 +334,20 @@ union wn3_config { int i; struct w3_config_fields { +#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; int pad8:8; unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1; int pad24:7; +#elif defined(__BIG_ENDIAN_BITFIELD) + unsigned int rom_size:2, ram_speed:2, ram_width:1, ram_size:3; + int pad8:8; + unsigned int xcvr:4, pad18:2, ram_split:2; + int pad24:7; + unsigned int autoselect:1; +#else +#error "Bitfield endianness not defined! Check your byteorder.h" +#endif } u; }; diff -u --recursive --new-file v2.1.127/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.127/linux/drivers/net/Config.in Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/Config.in Sun Nov 8 13:43:07 1998 @@ -56,6 +56,7 @@ fi fi tristate '3c509/3c579 support' CONFIG_EL3 + tristate '3c515 ISA Fast EtherLink' CONFIG_3C515 tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX fi bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE @@ -84,7 +85,7 @@ bool 'Other ISA cards' CONFIG_NET_ISA if [ "$CONFIG_NET_ISA" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'AT1700 support (EXPERIMENTAL)' CONFIG_AT1700 + tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 fi tristate 'Cabletron E21xx support' CONFIG_E2100 tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA diff -u --recursive --new-file v2.1.127/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.127/linux/drivers/net/Makefile Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/Makefile Sun Nov 8 13:43:08 1998 @@ -482,6 +482,14 @@ endif endif +ifeq ($(CONFIG_3C515),y) +L_OBJS += 3c515.o +else + ifeq ($(CONFIG_3C515),m) + M_OBJS += 3c515.o + endif +endif + ifeq ($(CONFIG_VORTEX),y) L_OBJS += 3c59x.o else diff -u --recursive --new-file v2.1.127/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.127/linux/drivers/net/Space.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/Space.c Sun Nov 8 13:43:08 1998 @@ -110,6 +110,7 @@ extern int rtl8139_probe(struct device *dev); extern int hplance_probe(struct device *dev); extern int via_rhine_probe(struct device *dev); +extern int tc515_probe(struct device *dev); /* Gigabit Ethernet adapters */ extern int yellowfin_probe(struct device *dev); @@ -268,6 +269,9 @@ #ifdef CONFIG_HP100 /* ISA, EISA & PCI */ {hp100_probe, 0}, #endif +#ifdef CONFIG_3C515 + {tc515_probe, 0}, +#endif #ifdef CONFIG_ULTRA {ultra_probe, 0}, #endif diff -u --recursive --new-file v2.1.127/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c --- v2.1.127/linux/drivers/net/ariadne2.c Mon Oct 5 13:13:39 1998 +++ linux/drivers/net/ariadne2.c Wed Nov 11 11:50:00 1998 @@ -97,7 +97,7 @@ return 0; } } - return ENODEV; + return -ENODEV; } __initfunc(static int ariadne2_init(struct device *dev, unsigned int key, @@ -131,7 +131,7 @@ while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2*HZ/100) { printk(" not found (no reset ack).\n"); - return ENODEV; + return -ENODEV; } writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */ diff -u --recursive --new-file v2.1.127/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.1.127/linux/drivers/net/at1700.c Thu Feb 12 20:56:07 1998 +++ linux/drivers/net/at1700.c Sun Nov 8 13:43:31 1998 @@ -1,6 +1,6 @@ /* at1700.c: A network device driver for the Allied Telesis AT1700. - Written 1993-94 by Donald Becker. + Written 1993-98 by Donald Becker. Copyright 1993 United States Government as represented by the Director, National Security Agency. @@ -22,6 +22,8 @@ ATI provided their EEPROM configuration code header file. Thanks to NIIBE Yutaka for bug fixes. + MCA bus (AT1720) support by Rene Schmit + Bugs: The MB86965 has a design flaw that makes all probes unreliable. Not only is it difficult to detect, it also moves around in I/O space in @@ -29,7 +31,7 @@ */ static const char *version = - "at1700.c:v1.12 1/18/95 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + "at1700.c:v1.15 4/7/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; #include @@ -48,15 +50,48 @@ #include #include #include -#include #include #include #include -/* This unusual address order is used to verify the CONFIG register. */ -static int at1700_probe_list[] __initdata = -{0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0}; +#include + +/* Tunable parameters. */ + +/* When to switch from the 64-entry multicast filter to Rx-all-multicast. */ +#define MC_FILTERBREAK 64 + +/* These unusual address orders are used to verify the CONFIG register. */ + +static int fmv18x_probe_list[] = { + 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0 +}; + +/* + * ISA + */ + +static int at1700_probe_list[] = { + 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 +}; + +/* + * MCA + */ + +static int at1700_ioaddr_pattern[] = { + 0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07 +}; + +static int at1700_mca_probe_list[] = { + 0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0 +}; + +static int at1700_irq_pattern[] = { + 0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00, + 0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00 +}; /* use 0 for production, 1 for verification, >2 for debug */ #ifndef NET_DEBUG @@ -68,10 +103,14 @@ /* Information that need to be kept for each board. */ struct net_local { - struct net_device_stats stats; - uint tx_started:1; /* Number of packet on the Tx queue. */ + struct enet_statistics stats; + unsigned char mc_filter[8]; + uint jumpered:1; /* Set iff the board has jumper config. */ + uint tx_started:1; /* Packets are on the Tx queue. */ + uint invalid_irq:1; uchar tx_queue; /* Number of packet on the Tx queue. */ - ushort tx_queue_len; /* Current length of the Tx queue. */ + char mca_slot; /* -1 means ISA */ + ushort tx_queue_len; /* Current length of the Tx queue. */ }; @@ -89,56 +128,59 @@ #define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */ #define TX_START 10 #define MODE13 13 +/* Configuration registers only on the '865A/B chips. */ #define EEPROM_Ctrl 16 #define EEPROM_Data 17 -#define IOCONFIG 19 +#define IOCONFIG 18 /* Either read the jumper, or move the I/O. */ +#define IOCONFIG1 19 +#define SAPROM 20 /* The station address PROM, if no EEPROM. */ #define RESET 31 /* Write to reset some parts of the chip. */ #define AT1700_IO_EXTENT 32 - -/* EEPROM_Ctrl bits. */ -#define EE_SHIFT_CLK 0x40 /* EEPROM shift clock, in reg. 16. */ -#define EE_CS 0x20 /* EEPROM chip select, in reg. 16. */ -#define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ -#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ - -/* Delay between EEPROM clock transitions. */ -#define eeprom_delay() do { int _i = 40; while (--_i > 0) { inb(0x80); }} while (0) - -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << 6) -#define EE_READ_CMD (6 << 6) -#define EE_ERASE_CMD (7 << 6) - - /* Index to functions, as function prototypes. */ extern int at1700_probe(struct device *dev); -static int at1700_probe1(struct device *dev, short ioaddr); +static int at1700_probe1(struct device *dev, int ioaddr); static int read_eeprom(int ioaddr, int location); static int net_open(struct device *dev); static int net_send_packet(struct sk_buff *skb, struct device *dev); static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void net_rx(struct device *dev); static int net_close(struct device *dev); -static struct net_device_stats *net_get_stats(struct device *dev); -static void set_multicast_list(struct device *dev); +static struct enet_statistics *net_get_stats(struct device *dev); +static void set_rx_mode(struct device *dev); +#ifdef CONFIG_MCA +struct at1720_mca_adapters_struct { + char* name; + int id; +}; +/* rEnE : maybe there are others I don't know off... */ + +struct at1720_mca_adapters_struct at1720_mca_adapters[] = { + { "Allied Telesys AT1720AT", 0x6410 }, + { "Allied Telesys AT1720BT", 0x6413 }, + { "Allied Telesys AT1720T", 0x6416 }, + { NULL, 0 }, +}; +#endif + /* Check for a network adaptor of this type, and return '0' iff one exists. If dev->base_addr == 0, probe all likely locations. If dev->base_addr == 1, always return failure. If dev->base_addr == 2, allocate space for the device and return success (detachable devices only). */ + #ifdef HAVE_DEVLIST -/* Support for an alternate probe manager, which will eliminate the +/* Support for a alternate probe manager, which will eliminate the boilerplate below. */ struct netdev_entry at1700_drv = {"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list}; #else -__initfunc(int -at1700_probe(struct device *dev)) + +int at1700_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -155,7 +197,6 @@ if (at1700_probe1(dev, ioaddr) == 0) return 0; } - return ENODEV; } #endif @@ -168,12 +209,15 @@ that can be done is checking a few bits and then diving right into an EEPROM read. */ -__initfunc(int at1700_probe1(struct device *dev, short ioaddr)) +int at1700_probe1(struct device *dev, int ioaddr) { - char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; - unsigned int i, irq; - - /* Resetting the chip doesn't reset the ISA interface, so don't bother. + char fmv_irqmap[4] = {3, 7, 10, 15}; + char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; + unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0; + int l_i; + int slot; + + /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ #ifdef notdef @@ -181,31 +225,98 @@ ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5), read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl)); #endif - if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr - || read_eeprom(ioaddr, 4) != 0x0000 - || (read_eeprom(ioaddr, 5) & 0xff00) != 0xF400) - return -ENODEV; - /* Reset the internal state machines. */ - outb(0, ioaddr + RESET); +#ifdef CONFIG_MCA + /* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */ - irq = irqmap[(read_eeprom(ioaddr, 12)&0x04) - | (read_eeprom(ioaddr, 0)>>14)]; + /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily + modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca) + to support standard MCA probing. */ + + /* redone for multi-card detection by ZP Gu (zpg@castle.net) */ + /* now works as a module */ + + if( MCA_bus ) { + int j; + u_char pos3, pos4; + + for( j = 0; at1720_mca_adapters[j].name != NULL; j ++ ) { + slot = 0; + while( slot != MCA_NOTFOUND ) { + + slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot ); + if( slot == MCA_NOTFOUND ) break; + + /* if we get this far, an adapter has been detected and is + enabled */ + + pos3 = mca_read_stored_pos( slot, 3 ); + pos4 = mca_read_stored_pos( slot, 4 ); + + for (l_i = 0; l_i < 0x09; l_i++) + if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i]) + break; + ioaddr = at1700_mca_probe_list[l_i]; + + for (irq = 0; irq < 0x10; irq++) + if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq]) + break; + + /* probing for a card at a particular IO/IRQ */ + if (dev && + ((dev->irq && dev->irq != irq) || + (dev->base_addr && dev->base_addr != ioaddr))) { + slot++; /* probing next slot */ + continue; + } + + if (dev) + dev->irq = irq; + + /* claim the slot */ + mca_set_adapter_name( slot, at1720_mca_adapters[j].name ); + mca_mark_as_used(slot); - /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, "at1700", dev)) { - printk ("AT1700 found at %#3x, but it's unusable due to a conflict on" - "IRQ %d.\n", ioaddr, irq); - return EAGAIN; + goto found; + } + } + /* if we get here, we didn't find an MCA adapter - try ISA */ } +#endif + slot = -1; + /* We must check for the EEPROM-config boards first, else accessing + IOCONFIG0 will move the board! */ + if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr + && read_eeprom(ioaddr, 4) == 0x0000 + && (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400) + is_at1700 = 1; + else if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] == ioaddr + && inb(ioaddr + SAPROM ) == 0x00 + && inb(ioaddr + SAPROM + 1) == 0x00 + && inb(ioaddr + SAPROM + 2) == 0x0e) + is_fmv18x = 1; + else + return -ENODEV; + +found: + + /* Reset the internal state machines. */ + outb(0, ioaddr + RESET); /* Allocate a new 'dev' if needed. */ if (dev == NULL) dev = init_etherdev(0, sizeof(struct net_local)); + if (is_at1700) + irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) + | (read_eeprom(ioaddr, 0)>>14)]; + else + if (is_fmv18x) + irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03]; + /* Grab the region so that we can find another board if the IRQ request fails. */ - request_region(ioaddr, AT1700_IO_EXTENT, "at1700"); + request_region(ioaddr, AT1700_IO_EXTENT, dev->name); printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name, ioaddr, irq); @@ -234,12 +345,12 @@ } /* Set the station address in bank zero. */ - outb(0xe0, ioaddr + 7); + outb(0xe0, ioaddr + CONFIG_1); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + 8 + i); /* Switch to bank 1 and set the multicast table to accept none. */ - outb(0xe4, ioaddr + 7); + outb(0xe4, ioaddr + CONFIG_1); for (i = 0; i < 8; i++) outb(0x00, ioaddr + 8 + i); @@ -248,7 +359,7 @@ outb(0xda, ioaddr + CONFIG_0); /* Switch to bank 2 and lock our I/O address. */ - outb(0xe8, ioaddr + 7); + outb(0xe8, ioaddr + CONFIG_1); outb(dev->if_port, MODE13); /* Power-down the chip. Aren't we green! */ @@ -265,52 +376,75 @@ dev->open = net_open; dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - dev->set_multicast_list = &set_multicast_list; + dev->hard_start_xmit = net_send_packet; + dev->get_stats = net_get_stats; + dev->set_multicast_list = &set_rx_mode; /* Fill in the fields of 'dev' with ethernet-generic values. */ - ether_setup(dev); + + { + struct net_local *lp = (struct net_local *)dev->priv; + lp->jumpered = is_fmv18x; + lp->mca_slot = slot; + /* Snarf the interrupt vector now. */ + if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) { + printk (" AT1700 at %#3x is unusable due to a conflict on" + "IRQ %d.\n", ioaddr, irq); + lp->invalid_irq = 1; + return 0; + } + } + return 0; } -__initfunc(static int read_eeprom(int ioaddr, int location)) + +/* EEPROM_Ctrl bits. */ +#define EE_SHIFT_CLK 0x40 /* EEPROM shift clock, in reg. 16. */ +#define EE_CS 0x20 /* EEPROM chip select, in reg. 16. */ +#define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ +#define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ + +/* Delay between EEPROM clock transitions. */ +#define eeprom_delay() do {} while (0); + +/* The EEPROM commands include the alway-set leading bit. */ +#define EE_WRITE_CMD (5 << 6) +#define EE_READ_CMD (6 << 6) +#define EE_ERASE_CMD (7 << 6) + +static int read_eeprom(int ioaddr, int location) { int i; unsigned short retval = 0; - short ee_addr = ioaddr + EEPROM_Ctrl; - short ee_daddr = ioaddr + EEPROM_Data; + int ee_addr = ioaddr + EEPROM_Ctrl; + int ee_daddr = ioaddr + EEPROM_Data; int read_cmd = location | EE_READ_CMD; - short ctrl_val = EE_CS; - - outb(ctrl_val, ee_addr); /* Shift the read command bits out. */ for (i = 9; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + outb(EE_CS, ee_addr); outb(dataval, ee_daddr); - outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ eeprom_delay(); - outb(EE_CS, ee_addr); /* Finish EEPROM a clock tick. */ + outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ eeprom_delay(); } - outb(EE_CS, ee_addr); - + outb(EE_DATA_WRITE, ee_daddr); for (i = 16; i > 0; i--) { + outb(EE_CS, ee_addr); + eeprom_delay(); outb(EE_CS | EE_SHIFT_CLK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0); - outb(EE_CS, ee_addr); - eeprom_delay(); } /* Terminate the EEPROM access. */ - ctrl_val &= ~EE_CS; - outb(ctrl_val | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); - outb(ctrl_val, ee_addr); + outb(EE_CS, ee_addr); eeprom_delay(); + outb(EE_SHIFT_CLK, ee_addr); + outb(0, ee_addr); return retval; } @@ -330,7 +464,7 @@ outb(dev->dev_addr[i], ioaddr + 8 + i); /* Switch to bank 1 and set the multicast table to accept none. */ - outb(0xe4, ioaddr + 7); + outb(0xe4, ioaddr + CONFIG_1); for (i = 0; i < 8; i++) outb(0x00, ioaddr + 8 + i); @@ -338,10 +472,8 @@ bus access, and two 4K Tx queues. */ outb(0xda, ioaddr + CONFIG_0); - /* Same config 0, except enable the Rx and Tx. */ - outb(0x5a, ioaddr + CONFIG_0); - /* Switch to register bank 2 for the run-time registers. */ - outb(0xe8, ioaddr + CONFIG_1); + /* Switch to register bank 2, enable the Rx and Tx. */ + outw(0xe85a, ioaddr + CONFIG_0); lp->tx_started = 0; lp->tx_queue = 0; @@ -564,6 +696,7 @@ /* The inverse routine to net_open(). */ static int net_close(struct device *dev) { +/* struct net_local *lp = (struct net_local *)dev->priv;*/ int ioaddr = dev->base_addr; dev->tbusy = 1; @@ -572,7 +705,15 @@ /* Set configuration register 0 to disable Tx and Rx. */ outb(0xda, ioaddr + CONFIG_0); - /* Update the statistics -- ToDo. */ + /* No statistic counters on the chip to update. */ + +#if 0 + /* Disable the IRQ on boards where it is feasible. */ + if (lp->jumpered) { + outb(0x00, ioaddr + IOCONFIG1); + free_irq(dev->irq, dev); + } +#endif /* Power-down the chip. Green, green, green! */ outb(0x00, ioaddr + CONFIG_1); @@ -582,44 +723,90 @@ return 0; } -/* Get the current statistics. This may be called with the card open or - closed. */ - -static struct net_device_stats *net_get_stats(struct device *dev) +/* Get the current statistics. + This may be called with the card open or closed. + There are no on-chip counters, so this function is trivial. +*/ +static struct enet_statistics * +net_get_stats(struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; + return &lp->stats; +} - cli(); - /* ToDo: Update the statistics from the device registers. */ - sti(); +/* + Set the multicast/promiscuous mode for this adaptor. +*/ - return &lp->stats; +/* The little-endian AUTODIN II ethernet CRC calculation. + N.B. Do not use for bulk data, use a table-based routine instead. + This is common code and should be moved to net/core/crc.c */ +static unsigned const ethernet_polynomial_le = 0xedb88320U; +static inline unsigned ether_crc_le(int length, unsigned char *data) +{ + unsigned int crc = 0xffffffff; /* Initial value. */ + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 8; --bit >= 0; current_octet >>= 1) { + if ((crc ^ current_octet) & 1) { + crc >>= 1; + crc ^= ethernet_polynomial_le; + } else + crc >>= 1; + } + } + return crc; } -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. - */ static void -set_multicast_list(struct device *dev) +set_rx_mode(struct device *dev) { - short ioaddr = dev->base_addr; - if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) - { - /* - * We must make the kernel realise we had to move - * into promisc mode or we start all out war on - * the cable. - AC - */ - dev->flags|=IFF_PROMISC; + int ioaddr = dev->base_addr; + struct net_local *lp = (struct net_local *)dev->priv; + unsigned char mc_filter[8]; /* Multicast hash filter */ + long flags; + int i; + if (dev->flags & IFF_PROMISC) { + /* Unconditionally log net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + memset(mc_filter, 0xff, sizeof(mc_filter)); outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ + } else if (dev->mc_count > MC_FILTERBREAK + || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter perfectly -- accept all multicasts. */ + memset(mc_filter, 0xff, sizeof(mc_filter)); + outb(2, ioaddr + RX_MODE); /* Use normal mode. */ + } else if (dev->mc_count == 0) { + memset(mc_filter, 0x00, sizeof(mc_filter)); + outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ + } else { + struct dev_mc_list *mclist; + int i; + + memset(mc_filter, 0, sizeof(mc_filter)); + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) + set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26, + mc_filter); } - else - outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */ + + save_flags(flags); + cli(); + if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { + int saved_bank = inw(ioaddr + CONFIG_0); + /* Switch to bank 1 and set the multicast table. */ + outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0); + for (i = 0; i < 8; i++) + outb(mc_filter[i], ioaddr + 8 + i); + memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); + outw(saved_bank, ioaddr + CONFIG_0); + } + restore_flags(flags); + return; } + #ifdef MODULE static char devicename[9] = { 0, }; static struct device dev_at1700 = { @@ -630,8 +817,6 @@ static int io = 0x260; static int irq = 0; -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); int init_module(void) { @@ -649,22 +834,28 @@ void cleanup_module(void) { + struct net_local *lp = dev_at1700.priv; unregister_netdev(&dev_at1700); + if(lp->mca_slot) + { + mca_mark_as_unused(lp->mca_slot); + } kfree(dev_at1700.priv); dev_at1700.priv = NULL; /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_at1700.irq, &dev_at1700); + free_irq(dev_at1700.irq, NULL); release_region(dev_at1700.base_addr, AT1700_IO_EXTENT); } #endif /* MODULE */ /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c at1700.c" - * version-control: t - * kept-new-versions: 5 + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c" + * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c" * tab-width: 4 + * c-basic-offset: 4 * c-indent-level: 4 * End: */ + diff -u --recursive --new-file v2.1.127/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c --- v2.1.127/linux/drivers/net/ibmtr.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/ibmtr.c Sun Nov 8 13:44:53 1998 @@ -59,12 +59,13 @@ * Changes by Christopher Turcksin * + Now compiles ok as a module again. * - * Changes by Paul Norton (p.norton@computer.org) : + * Changes by Paul Norton (pnorton@ieee.org) : * + moved the header manipulation code in tr_tx and tr_rx to * net/802/tr.c. (July 12 1997) * + add retry and timeout on open if cable disconnected. (May 5 1998) * + lifted 2000 byte mtu limit. now depends on shared-RAM size. * May 25 1998) + * + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998) */ #ifdef PCMCIA @@ -93,8 +94,8 @@ /* version and credits */ static char *version = -"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" -" v2.1.106 6/22/98 Paul Norton \n"; +"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" +" v2.1.125 10/20/98 Paul Norton \n"; static char pcchannelid[] = { 0x05, 0x00, 0x04, 0x09, @@ -416,7 +417,7 @@ timeout = jiffies + TR_SPIN_INTERVAL; while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)) - if (jiffies > timeout) { + if (time_after(jiffies, timeout)) { DPRINTK("Hardware timeout during initialization.\n"); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; @@ -634,56 +635,56 @@ switch (ti->mapped_ram_size) { case 16 : /* 8KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); - ti->rbuf_len4 = 2048; - ti->rbuf_cnt4 = 1; + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4 = 2; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 1; + ti->rbuf_len16 = 1032; + ti->rbuf_cnt16 = 2; break; case 32 : /* 16KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); - ti->rbuf_len4 = 512; + ti->rbuf_len4 = 520; ti->rbuf_cnt4 = 9; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 4096); - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 2; + ti->rbuf_len16 = 1032; /* 1024 usable */ + ti->rbuf_cnt16 = 4; break; case 64 : /* 32KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); - ti->rbuf_len4 = 2048; - ti->rbuf_cnt4 = 3; + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 10240); - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 5; + ti->rbuf_len16 = 1032; + ti->rbuf_cnt16 = 10; break; case 127 : /* 63KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); - ti->rbuf_len4 = 2048; - ti->rbuf_cnt4 = 3; + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 16384); - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 8; + ti->rbuf_len16 = 1032; + ti->rbuf_cnt16 = 16; break; case 128 : /* 64KB shared RAM */ ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); - ti->rbuf_len4 = 2048; - ti->rbuf_cnt4 = 3; + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4 = 6; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 17960); - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 9; + ti->rbuf_len16 = 1032; + ti->rbuf_cnt16 = 18; break; default : ti->dhb_size4mb = 2048; - ti->rbuf_len4 = 2048; - ti->rbuf_cnt4 = 1; + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4 = 2; ti->dhb_size16mb = 2048; - ti->rbuf_len16 = 2048; - ti->rbuf_cnt16 = 1; + ti->rbuf_len16 = 1032; + ti->rbuf_cnt16 = 2; break; } - ti->maxmtu16 = ti->dhb_size16mb-((ti->rbuf_cnt16)<<3)-TR_HLEN; - ti->maxmtu4 = ti->dhb_size4mb-((ti->rbuf_cnt4)<<3)-TR_HLEN; + ti->maxmtu16 = (ti->rbuf_len16*ti->rbuf_cnt16)-((ti->rbuf_cnt16)<<3)-TR_HLEN; + ti->maxmtu4 = (ti->rbuf_len4*ti->rbuf_cnt4)-((ti->rbuf_cnt4)<<3)-TR_HLEN; DPRINTK("Maximum MTU 16Mbps: %d, 4Mbps: %d\n", ti->maxmtu16, ti->maxmtu4); diff -u --recursive --new-file v2.1.127/linux/drivers/net/ipddp.c linux/drivers/net/ipddp.c --- v2.1.127/linux/drivers/net/ipddp.c Thu May 7 22:51:50 1998 +++ linux/drivers/net/ipddp.c Sun Nov 8 13:45:07 1998 @@ -62,12 +62,6 @@ static struct ipddp_route *ipddp_route_list = NULL; -/* - * The name of the card. Is used for messages and in the requests for - * io regions, irqs and dma channels - */ -static const char *cardname = "ipddp"; - #ifdef CONFIG_IPDDP_ENCAP static int ipddp_mode = IPDDP_ENCAP; #else diff -u --recursive --new-file v2.1.127/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c --- v2.1.127/linux/drivers/net/rtl8139.c Fri May 8 23:14:48 1998 +++ linux/drivers/net/rtl8139.c Sun Nov 8 13:48:06 1998 @@ -1,6 +1,6 @@ /* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */ /* - Written 1997 by Donald Becker. + Written 1997-1998 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -15,14 +15,27 @@ Support and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html + + Twister-tuning code contributed by Kinston . */ static const char *version = -"rtl8139.c:v0.14 12/9/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; +"rtl8139.c:v1.04 9/22/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n"; /* A few user-configurable values. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 10; +static int max_interrupt_work = 20; +#define rtl8129_debug debug +static int rtl8129_debug = 1; + +/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + The RTL chips use a 64 element hash table based on the Ethernet CRC. */ +static int multicast_filter_limit = 32; + +/* Used to pass the full-duplex flag, etc. */ +#define MAX_UNITS 8 /* More are supported, limit only on options */ +static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* Size of the in-memory receive ring. */ #define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K */ @@ -37,11 +50,11 @@ /* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */ #define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */ -#define TX_DMA_BURST 4 +#define TX_DMA_BURST 4 /* Calculate as 16< #ifdef MODULE @@ -59,79 +72,49 @@ #include #include #include -#include #include #include #include #include #include -#include /* Processor type for cache alignment. */ -#include -#include -#include - #include #include #include +#include /* Processor type for cache alignment. */ +#include +#include -/* Kernel compatibility defines, common to David Hind's PCMCIA package. +/* Kernel compatibility defines, some common to David Hind's PCMCIA package. This is only in the support-all-kernels source code. */ -#include /* Evil, but neccessary */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300 -#define RUN_AT(x) (x) /* What to put in timer->expires. */ -#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC) -#define virt_to_bus(addr) ((unsigned long)addr) -#define bus_to_virt(addr) ((void*)addr) - -#else /* 1.3.0 and later */ #define RUN_AT(x) (jiffies + (x)) -#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) -#endif -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338 -#ifdef MODULE -#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) -char kernel_version[] = UTS_RELEASE; -#endif -#else -#undef MOD_INC_USE_COUNT -#define MOD_INC_USE_COUNT -#undef MOD_DEC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif -#endif /* 1.3.38 */ - -#if (LINUX_VERSION_CODE >= 0x10344) -#define NEW_MULTICAST #include -#endif -#ifdef SA_SHIRQ -#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev) -#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance) -#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) +#if LINUX_VERSION_CODE < 0x20123 +#define test_and_set_bit(val, addr) set_bit(val, addr) +#endif +#if LINUX_VERSION_CODE <= 0x20139 +#define net_device_stats enet_statistics #else -#define FREE_IRQ(irqnum, dev) free_irq(irqnum) -#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n) -#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) +#define NETSTATS_VER2 #endif - -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) +#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS) +/* Grrrr, the PCI code changed, but did not consider CardBus... */ #include +#define PCI_SUPPORT_VER1 +#else +#define PCI_SUPPORT_VER2 +#endif +#if LINUX_VERSION_CODE < 0x20159 +#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); +#else +#define dev_free_skb(skb) dev_kfree_skb(skb); #endif /* The I/O extent. */ #define RTL8129_TOTAL_SIZE 0x80 -#ifdef HAVE_DEVLIST -struct netdev_entry rtl8139_drv = -{"RTL8139", rtl8139_probe, RTL8129_TOTAL_SIZE, NULL}; -#endif - -static int rtl8129_debug = 1; - /* Theory of Operation @@ -177,16 +160,45 @@ IVc. Errata */ + + +/* This table drives the PCI probe routines. It's mostly boilerplate in all + of the drivers, and will likely be provided by some future kernel. + Note the matching code -- the first table entry matchs all 56** cards but + second only the 1234 card. +*/ +enum pci_flags_bit { + PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, + PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +}; +struct pci_id_info { + const char *name; + u16 vendor_id, device_id, device_id_mask, flags; + int io_size; + struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); +}; + +static struct device * rtl8129_probe1(int pci_bus, int pci_devfn, + struct device *dev, long ioaddr, + int irq, int chp_idx, int fnd_cnt); + +static struct pci_id_info pci_tbl[] = +{{ "RealTek RTL8129 Fast Ethernet", + 0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, + { "RealTek RTL8139 Fast Ethernet", + 0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, + { "RealTek RTL8139 Fast Ethernet (mislabeled)", + 0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1}, + {0,}, /* 0 terminated list. */ +}; + +/* The capability table matches the chip table above. */ +enum {HAS_MII_XCVR=0x01, HAS_CHIP_XCVR=0x02, HAS_LNK_CHNG=0x04}; +static int rtl_cap_tbl[] = { + HAS_MII_XCVR, HAS_CHIP_XCVR|HAS_LNK_CHNG, HAS_CHIP_XCVR|HAS_LNK_CHNG, +}; -#ifndef PCI_VENDOR_ID_REALTEK -#define PCI_VENDOR_ID_REALTEK 0x10ec -#endif -#ifndef PCI_DEVICE_ID_REALTEK_8129 -#define PCI_DEVICE_ID_REALTEK_8129 0x8129 -#endif -#ifndef PCI_DEVICE_ID_REALTEK_8139 -#define PCI_DEVICE_ID_REALTEK_8139 0x8139 -#endif /* The rest of these values should never change. */ #define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */ @@ -195,7 +207,7 @@ enum RTL8129_registers { MAC0=0, /* Ethernet hardware address. */ MAR0=8, /* Multicast filter. */ - TxStat0=0x10, /* Transmit status (Four 32bit registers). */ + TxStatus0=0x10, /* Transmit status (Four 32bit registers). */ TxAddr0=0x20, /* Tx descriptors (also four 32bit). */ RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36, ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A, @@ -206,7 +218,12 @@ Cfg9346=0x50, Config0=0x51, Config1=0x52, FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B, MultiIntr=0x5C, TxSummary=0x60, - BMCR=0x62, BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, NWayExpansion=0x6A, + MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, + NWayExpansion=0x6A, + /* Undocumented registers, but required for proper operation. */ + FIFOTMS=0x70, /* FIFO Test Mode Select */ + CSCR=0x74, /* Chip Status and Configuration Register. */ + PARA78=0x78, PARA7c=0x7c, /* Magic transceiver parameter register. */ }; enum ChipCmdBits { @@ -228,25 +245,44 @@ RxBadAlign=0x0002, RxStatusOK=0x0001, }; +enum CSCRBits { + CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800, + CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0, + CSCR_LinkDownCmd=0x0f3c0, +}; + +/* Twister tuning parameters from RealTek. Completely undocumented. */ +unsigned long param[4][4]={ + {0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43}, + {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83}, + {0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83}, + {0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83} +}; + struct rtl8129_private { char devname[8]; /* Used only for kernel debugging. */ const char *product_name; struct device *next_module; int chip_id; int chip_revision; + unsigned char pci_bus, pci_devfn; +#if LINUX_VERSION_CODE > 0x20139 + struct net_device_stats stats; +#else struct enet_statistics stats; +#endif struct timer_list timer; /* Media selection timer. */ - unsigned int cur_rx, cur_tx; /* The next free and used entries */ - unsigned int dirty_rx, dirty_tx; + unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ + unsigned int cur_tx, dirty_tx, tx_flag; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff* tx_skbuff[NUM_TX_DESC]; unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ unsigned char *rx_ring; unsigned char *tx_bufs; /* Tx bounce buffer region. */ - unsigned char mc_filter[8]; /* Current multicast filter. */ char phys[4]; /* MII device addresses. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int duplex_lock:1; /* Full-duplex operation requested. */ unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int media2:4; /* Secondary monitored media port. */ unsigned int medialock:1; /* Don't sense media type. */ @@ -254,24 +290,21 @@ }; #ifdef MODULE -/* Used to pass the full-duplex flag, etc. */ -static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#if LINUX_VERSION_CODE > 0x20118 +#if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver"); -MODULE_PARM(debug, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(multicast_filter_limit, "i"); MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(debug, "i"); #endif #endif -static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options, int card_idx); static int rtl8129_open(struct device *dev); -static int read_eeprom(int ioaddr, int location); -static int mdio_read(int ioaddr, int phy_id, int location); +static int read_eeprom(long ioaddr, int location); +static int mdio_read(struct device *dev, int phy_id, int location); +static void mdio_write(struct device *dev, int phy_id, int location, int val); static void rtl8129_timer(unsigned long data); static void rtl8129_tx_timeout(struct device *dev); static void rtl8129_init_ring(struct device *dev); @@ -279,161 +312,138 @@ static int rtl8129_rx(struct device *dev); static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int rtl8129_close(struct device *dev); +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd); static struct enet_statistics *rtl8129_get_stats(struct device *dev); -#ifdef NEW_MULTICAST +static inline u32 ether_crc(int length, unsigned char *data); static void set_rx_mode(struct device *dev); -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif - -#ifdef MODULE /* A list of all installed RTL8129 devices, for removing the driver module. */ static struct device *root_rtl8129_dev = NULL; -#endif + +/* Ideally we would detect all network cards in slot order. That would + be best done a central PCI probe dispatch, which wouldn't work + well when dynamically adding drivers. So instead we detect just the + Rtl81*9 cards in slot order. */ int rtl8139_probe(struct device *dev) { int cards_found = 0; - static int pci_index = 0; /* Static, for multiple probe calls. */ + int pci_index = 0; + unsigned char pci_bus, pci_device_fn; - /* Ideally we would detect all network cards in slot order. That would - be best done a central PCI probe dispatch, which wouldn't work - well with the current structure. So instead we detect just the - Rtl81*9 cards in slot order. */ - - if (pci_present()) { - unsigned char pci_bus, pci_device_fn; - - for (;pci_index < 0xff; pci_index++) { - unsigned char pci_latency; -#if LINUX_VERSION_CODE >= 0x20155 - unsigned int pci_irq_line; - struct pci_dev *pdev; -#else - unsigned char pci_irq_line; -#endif - unsigned short pci_command, new_command, vendor, device; - unsigned int pci_ioaddr; + if ( ! pcibios_present()) + return -ENODEV; - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, -#ifdef REVERSE_PROBE_ORDER - 0xff - pci_index, -#else - pci_index, -#endif - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) + for (;pci_index < 0xff; pci_index++) { + u16 vendor, device, pci_command, new_command; + int chip_idx, irq; + long ioaddr; + + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, + &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_DEVICE_ID, &device); + + for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor == pci_tbl[chip_idx].vendor_id + && (device & pci_tbl[chip_idx].device_id_mask) == + pci_tbl[chip_idx].device_id) break; - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - if (vendor != PCI_VENDOR_ID_REALTEK) - continue; - - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); -#if LINUX_VERSION_CODE >= 0x20155 - pdev = pci_find_slot(pci_bus, pci_device_fn); - pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0]; + if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ + continue; + + { +#if defined(PCI_SUPPORT_VER2) + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->base_address[0] & ~3; + irq = pdev->irq; #else + u32 pci_ioaddr; + u8 pci_irq_line; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_ioaddr); + ioaddr = pci_ioaddr & ~3; + irq = pci_irq_line; #endif - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - - if (device != PCI_DEVICE_ID_REALTEK_8129 - && device != PCI_DEVICE_ID_REALTEK_8139) { - printk(KERN_NOTICE"Unknown RealTek PCI ethernet chip type " - "%4.4x detected: not configured.\n", device); - continue; - } - if (check_region(pci_ioaddr, RTL8129_TOTAL_SIZE)) - continue; + } - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled this" - " device! Updating PCI config %4.4x->%4.4x.\n", - pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); - } + if ((pci_tbl[chip_idx].flags & PCI_USES_IO) && + check_region(ioaddr, pci_tbl[chip_idx].io_size)) + continue; + + /* Activate the card: fix for brain-damaged Win98 BIOSes. */ + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | (pci_tbl[chip_idx].flags & 7); + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled the" + " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", + pci_bus, pci_device_fn, pci_command, new_command); + pcibios_write_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, new_command); + } -#ifdef MODULE - dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device, - options[cards_found], cards_found); -#else - dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device, - dev ? dev->mem_start : 0, -1); -#endif + dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr, + irq, chip_idx, cards_found); - if (dev) { - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 32) { - printk(KERN_NOTICE" PCI latency timer (CFLT) is " - "unreasonably low at %d. Setting to 64 clocks.\n", - pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 64); - } else if (rtl8129_debug > 1) - printk(KERN_INFO" PCI latency timer (CFLT) is %#x.\n", - pci_latency); - dev = 0; - cards_found++; + if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) { + u8 pci_latency; + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < 32) { + printk(KERN_NOTICE " PCI latency timer (CFLT) is " + "unreasonably low at %d. Setting to 64 clocks.\n", + pci_latency); + pcibios_write_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, 64); } } + dev = 0; + cards_found++; } -#if defined (MODULE) - return cards_found; -#else return cards_found ? 0 : -ENODEV; -#endif } -static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options, int card_idx) +static struct device * rtl8129_probe1(int pci_bus, int pci_devfn, + struct device *dev, long ioaddr, + int irq, int chip_idx, int found_cnt) { static int did_version = 0; /* Already printed version info. */ struct rtl8129_private *tp; - int i; + int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0; if (rtl8129_debug > 0 && did_version++ == 0) printk(KERN_INFO "%s", version); dev = init_etherdev(dev, 0); - printk(KERN_INFO "%s: RealTek RTL%x at %#3x, IRQ %d, ", - dev->name, chip_id, ioaddr, irq); + printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", + dev->name, pci_tbl[chip_idx].name, ioaddr, irq); /* Bring the chip out of low-power mode. */ outb(0x00, ioaddr + Config1); - /* Perhaps this should be read from the EEPROM? */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(ioaddr + MAC0 + i); + if (read_eeprom(ioaddr, 0) != 0xffff) + for (i = 0; i < 3; i++) + ((u16 *)(dev->dev_addr))[i] = read_eeprom(ioaddr, i + 7); + else + for (i = 0; i < 6; i++) + dev->dev_addr[i] = inb(ioaddr + MAC0 + i); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - if (rtl8129_debug > 1) { - printk(KERN_INFO "%s: EEPROM contents\n", dev->name); - for (i = 0; i < 64; i++) - printk(" %4.4x%s", read_eeprom(ioaddr, i), - i%16 == 15 ? "\n"KERN_INFO : ""); - } - /* We do a request_region() to register /proc/ioports info. */ - request_region(ioaddr, RTL8129_TOTAL_SIZE, "RealTek RTL8129/39 Fast Ethernet"); + request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name); dev->base_addr = ioaddr; dev->irq = irq; @@ -443,22 +453,21 @@ memset(tp, 0, sizeof(*tp)); dev->priv = tp; -#ifdef MODULE tp->next_module = root_rtl8129_dev; root_rtl8129_dev = dev; -#endif - tp->chip_id = chip_id; + tp->chip_id = chip_idx; + tp->pci_bus = pci_bus; + tp->pci_devfn = pci_devfn; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but takes too much time. */ - if (chip_id == 0x8129) { + if (rtl_cap_tbl[chip_idx] & HAS_MII_XCVR) { int phy, phy_idx; for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) { - int mii_status = mdio_read(ioaddr, phy, 1); - + int mii_status = mdio_read(dev, phy, 1); if (mii_status != 0xffff && mii_status != 0x0000) { tp->phys[phy_idx++] = phy; printk(KERN_INFO "%s: MII transceiver found at address %d.\n", @@ -472,7 +481,7 @@ tp->phys[0] = -1; } } else { - tp->phys[0] = -1; + tp->phys[0] = 32; } /* Put the chip into low-power mode. */ @@ -481,18 +490,21 @@ outb('H', ioaddr + HltClk); /* 'R' would leave the clock running. */ /* The lower four bits are the media type. */ - if (options > 0) { - tp->full_duplex = (options & 16) ? 1 : 0; - tp->default_port = options & 15; + if (option > 0) { + tp->full_duplex = (option & 0x200) ? 1 : 0; + tp->default_port = option & 15; if (tp->default_port) tp->medialock = 1; } -#ifdef MODULE - if (card_idx >= 0) { - if (full_duplex[card_idx] >= 0) - tp->full_duplex = full_duplex[card_idx]; + + if (found_cnt < MAX_UNITS && full_duplex[found_cnt] > 0) + tp->full_duplex = full_duplex[found_cnt]; + + if (tp->full_duplex) { + printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); + mdio_write(dev, tp->phys[0], 4, 0x141); + tp->duplex_lock = 1; } -#endif /* The Rtl8129-specific entries in the device structure. */ dev->open = &rtl8129_open; @@ -500,6 +512,7 @@ dev->stop = &rtl8129_close; dev->get_stats = &rtl8129_get_stats; dev->set_multicast_list = &set_rx_mode; + dev->do_ioctl = &mii_ioctl; return dev; } @@ -516,24 +529,21 @@ #define EE_ENB (0x80 | EE_CS) /* Delay between EEPROM clock transitions. - The 1.2 code is a "nasty" timing loop, but PC compatible machines are - *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */ -#ifdef _LINUX_DELAY_H -#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000) -#else -#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0) -#endif + No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. + */ + +#define eeprom_delay() inl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5 << 6) #define EE_READ_CMD (6 << 6) #define EE_ERASE_CMD (7 << 6) -static int read_eeprom(int ioaddr, int location) +static int read_eeprom(long ioaddr, int location) { int i; - unsigned short retval = 0; - short ee_addr = ioaddr + Cfg9346; + unsigned retval = 0; + long ee_addr = ioaddr + Cfg9346; int read_cmd = location | EE_READ_CMD; outb(EE_ENB & ~EE_CS, ee_addr); @@ -541,22 +551,21 @@ /* Shift the read command bits out. */ for (i = 10; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - eeprom_delay(100); + eeprom_delay(); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(150); - outb(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(250); + eeprom_delay(); } outb(EE_ENB, ee_addr); + eeprom_delay(); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(100); + eeprom_delay(); retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0); outb(EE_ENB, ee_addr); - eeprom_delay(100); + eeprom_delay(); } /* Terminate the EEPROM access. */ @@ -566,43 +575,50 @@ /* MII serial management: mostly bogus for now. */ /* Read and write the MII management registers using software-generated - serial MDIO protocol. The maxium data clock rate is 2.5 Mhz. */ + serial MDIO protocol. + The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues. */ #define MDIO_DIR 0x80 #define MDIO_DATA_OUT 0x04 #define MDIO_DATA_IN 0x02 #define MDIO_CLK 0x01 -#ifdef _LINUX_DELAY_H -#define mdio_delay() udelay(1) /* Really 400ns. */ -#else -#define mdio_delay() __SLOW_DOWN_IO; -#endif +#define MDIO_WRITE0 (MDIO_DIR) +#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) + +#define mdio_delay() inb(mdio_addr) + +static char mii_2_8139_map[8] = {MII_BMCR, MII_BMSR, 0, 0, NWayAdvert, + NWayLPAR, NWayExpansion, 0 }; /* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync(int ioaddr) +static void mdio_sync(long mdio_addr) { int i; - int mdio_addr = ioaddr + MII_SMI; for (i = 32; i >= 0; i--) { - outb(MDIO_DIR | MDIO_DATA_OUT, mdio_addr); + outb(MDIO_WRITE1, mdio_addr); mdio_delay(); - outb(MDIO_DIR | MDIO_DATA_OUT | MDIO_CLK, mdio_addr); + outb(MDIO_WRITE1 | MDIO_CLK, mdio_addr); mdio_delay(); } return; } -static int mdio_read(int ioaddr, int phy_id, int location) +static int mdio_read(struct device *dev, int phy_id, int location) { - int i; - int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; + long mdio_addr = dev->base_addr + MII_SMI; + int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int retval = 0; - int mdio_addr = ioaddr + MII_SMI; + int i; - mdio_sync(ioaddr); + if ((phy_id & 0x1f) == 0) { /* Really a 8139. Use internal registers. */ + return location < 8 && mii_2_8139_map[location] ? + inw(dev->base_addr + mii_2_8139_map[location]) : 0; + } + mdio_sync(mdio_addr); /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { - int dataval = - (read_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; + int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; outb(MDIO_DIR | dataval, mdio_addr); mdio_delay(); @@ -620,31 +636,52 @@ } return (retval>>1) & 0xffff; } + +static void mdio_write(struct device *dev, int phy_id, int location, int value) +{ + long mdio_addr = dev->base_addr + MII_SMI; + int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; + int i; + + if (phy_id == 32) { /* Really a 8139. Use internal registers. */ + if (location < 8 && mii_2_8139_map[location]) + outw(value, dev->base_addr + mii_2_8139_map[location]); + return; + } + mdio_sync(mdio_addr); + + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; + outb(dataval, mdio_addr); + mdio_delay(); + outb(dataval | MDIO_CLK, mdio_addr); + mdio_delay(); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + outb(0, mdio_addr); + mdio_delay(); + outb(MDIO_CLK, mdio_addr); + mdio_delay(); + } + return; +} + static int rtl8129_open(struct device *dev) { struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; int i; - int full_duplex = 0; /* Soft reset the chip. */ outb(CmdReset, ioaddr + ChipCmd); -#ifdef SA_SHIRQ - if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, - "RealTek RTL8129/39 Fast Ethernet", dev)) { + if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ, dev->name, dev)) { return -EAGAIN; } -#else - if (irq2dev_map[dev->irq] != NULL - || (irq2dev_map[dev->irq] = dev) == NULL - || dev->irq == 0 - || request_irq(dev->irq, &rtl8129_interrupt, 0, "RTL8129")) { - return -EAGAIN; - } -#endif MOD_INC_USE_COUNT; @@ -660,20 +697,10 @@ } rtl8129_init_ring(dev); -#ifndef final_version - /* Used to monitor rx ring overflow. */ - memset(tp->rx_ring + RX_BUF_LEN, 0xcc, 16); -#endif - /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) break; -#ifndef final_version - if (rtl8129_debug > 2) - printk(KERN_DEBUG"%s: reset finished with status %2.2x after %d loops.\n", - dev->name, inb(ioaddr + ChipCmd), 1000-i); -#endif for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + MAC0 + i); @@ -683,29 +710,26 @@ outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8), ioaddr + RxConfig); outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig); + tp->tx_flag = (TX_FIFO_THRESH<<11) & 0x003f0000; - full_duplex = tp->full_duplex; - if (tp->phys[0] >= 0 || tp->chip_id == 0x8139) { - u16 mii_reg5; - if (tp->chip_id == 0x8139) - mii_reg5 = inw(ioaddr + NWayLPAR); - else - mii_reg5 = mdio_read(ioaddr, tp->phys[0], 5); + tp->full_duplex = tp->duplex_lock; + if (tp->phys[0] >= 0 || (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) { + u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5); if (mii_reg5 == 0xffff) ; /* Not there */ else if ((mii_reg5 & 0x0100) == 0x0100 || (mii_reg5 & 0x00C0) == 0x0040) - full_duplex = 1; + tp->full_duplex = 1; if (rtl8129_debug > 1) printk(KERN_INFO"%s: Setting %s%s-duplex based on" " auto-negotiated partner ability %4.4x.\n", dev->name, mii_reg5 == 0 ? "" : (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", - full_duplex ? "full" : "half", mii_reg5); + tp->full_duplex ? "full" : "half", mii_reg5); } outb(0xC0, ioaddr + Cfg9346); - outb(full_duplex ? 0x60 : 0x20, ioaddr + Config1); + outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); outb(0x00, ioaddr + Cfg9346); outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf); @@ -715,13 +739,6 @@ set_rx_mode(dev); outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); -#ifndef final_version - if (rtl8129_debug > 1) - printk(KERN_DEBUG"%s: In rtl8129_open() Tx/Rx Config %8.8x/%8.8x" - " Chip Config %2.2x/%2.2x.\n", - dev->name, inl(ioaddr + TxConfig), inl(ioaddr + RxConfig), - inb(ioaddr + Config0), inb(ioaddr + Config1)); -#endif dev->tbusy = 0; dev->interrupt = 0; @@ -732,10 +749,10 @@ | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); if (rtl8129_debug > 1) - printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %4.4x IRQ %d" + printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d" " GP Pins %2.2x %s-duplex.\n", dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData), - full_duplex ? "full" : "half"); + tp->full_duplex ? "full" : "half"); /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ @@ -752,26 +769,26 @@ { struct device *dev = (struct device *)data; struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; int next_tick = 0; + int mii_reg5 = mdio_read(dev, tp->phys[0], 5); - if (tp->chip_id == 0x8139) { - u16 mii_reg5 = inw(ioaddr + NWayLPAR); - if ((mii_reg5 & 0x0100) == 0x0100 - || (mii_reg5 & 0x00C0) == 0x0040) - if ( ! tp->full_duplex) { - tp->full_duplex = 1; - if (rtl8129_debug > 0) - printk(KERN_INFO "%s: Switching to full-duplex based on " - "link partner ability of %4.4x.\n", - dev->name, mii_reg5); - outb(0xC0, ioaddr + Cfg9346); - outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); - outb(0x00, ioaddr + Cfg9346); - } + if (! tp->duplex_lock && mii_reg5 != 0xffff) { + int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040; + if (tp->full_duplex != duplex) { + tp->full_duplex = duplex; + printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link" + " partner ability of %4.4x.\n", dev->name, + tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5); + outb(0xC0, ioaddr + Cfg9346); + outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); + outb(0x00, ioaddr + Cfg9346); + } + next_tick = 60*HZ; } + if (rtl8129_debug > 2) { - if (tp->chip_id == 0x8129) + if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR) printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n", dev->name, inb(ioaddr + GPPinData)); else @@ -794,33 +811,80 @@ static void rtl8129_tx_timeout(struct device *dev) { struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; - int i; + long ioaddr = dev->base_addr; + int mii_reg, i; if (rtl8129_debug > 0) - printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x.\n", - dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus)); + printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x " + "media %2.2x.\n", + dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus), + inb(ioaddr + GPPinData)); + + /* Disable interrupts by clearing the interrupt mask. */ + outw(0x0000, ioaddr + IntrMask); + /* Emit info to figure out what went wrong. */ + printk("%s: Tx queue start entry %d dirty entry %d.\n", + dev->name, tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++) printk(KERN_DEBUG"%s: Tx descriptor %d is %8.8x.%s\n", - dev->name, i, inl(ioaddr + TxStat0 + i*4), + dev->name, i, inl(ioaddr + TxStatus0 + i*4), i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); - if (tp->chip_id == 0x8129) { - int mii_reg; - printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]); - for (mii_reg = 0; mii_reg < 8; mii_reg++) - printk(" %4.4x", mdio_read(ioaddr, tp->phys[0], mii_reg)); - printk(".\n"); - } else { - printk(KERN_DEBUG"%s: MII status register is %4.4x.\n", - dev->name, inw(ioaddr + BMSR)); - } - /* Restart the chip Tx process. */ + printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]); + for (mii_reg = 0; mii_reg < 8; mii_reg++) + printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg)); + printk(".\n"); + + /* Soft reset the chip. */ + outb(CmdReset, ioaddr + ChipCmd); + /* Check that the chip has finished the reset. */ + for (i = 1000; i > 0; i--) + if ((inb(ioaddr + ChipCmd) & CmdReset) == 0) + break; + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + MAC0 + i); + + outb(0x00, ioaddr + Cfg9346); + tp->cur_rx = 0; + /* Must enable Tx/Rx before setting transfer thresholds! */ outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); - /* Continue from any transmit abort. */ - outl((TX_DMA_BURST<<8) || 0x03000001, ioaddr + TxConfig); + outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8), + ioaddr + RxConfig); + outl((TX_DMA_BURST<<8), ioaddr + TxConfig); + set_rx_mode(dev); + { /* Save the unsent Tx packets. */ + struct sk_buff *saved_skb[NUM_TX_DESC], *skb; + int j; + for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++) + saved_skb[j] = tp->tx_skbuff[tp->dirty_tx % NUM_TX_DESC]; + tp->dirty_tx = tp->cur_tx = 0; + + for (i = 0; i < j; i++) { + skb = tp->tx_skbuff[i] = saved_skb[i]; + if ((long)skb->data & 3) { /* Must use alignment buffer. */ + memcpy(tp->tx_buf[i], skb->data, skb->len); + outl(virt_to_bus(tp->tx_buf[i]), ioaddr + TxAddr0 + i*4); + } else + outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + i*4); + /* Note: the chip doesn't have auto-pad! */ + outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), + ioaddr + TxStatus0 + i*4); + } + tp->cur_tx = i; + while (i < NUM_TX_DESC) + tp->tx_skbuff[i] = 0; + if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ + dev->tbusy = 0; + tp->tx_full = 0; + } else { + tp->tx_full = 1; + } + } dev->trans_start = jiffies; tp->stats.tx_errors++; + /* Enable all known interrupts by setting the interrupt mask. */ + outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver + | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask); return; } @@ -833,8 +897,8 @@ int i; tp->tx_full = 0; - tp->cur_rx = tp->cur_tx = 0; - tp->dirty_rx = tp->dirty_tx = 0; + tp->cur_rx = 0; + tp->dirty_tx = tp->cur_tx = 0; for (i = 0; i < NUM_TX_DESC; i++) { tp->tx_skbuff[i] = 0; @@ -846,20 +910,9 @@ rtl8129_start_xmit(struct sk_buff *skb, struct device *dev) { struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; int entry; -#ifndef final_version - if (skb == NULL || skb->len <= 0) { - printk(KERN_ERR"%s: Obsolete driver Tx request made: skbuff==NULL.\n", - dev->name); -#if 0 - dev_tint(dev); -#endif - return 0; - } -#endif - /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { @@ -879,12 +932,11 @@ } else outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4); /* Note: the chip doesn't have auto-pad! */ - outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | - (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), - ioaddr + TxStat0 + entry*4); + outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN), + ioaddr + TxStatus0 + entry*4); if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */ - dev->tbusy = 0; + clear_bit(0, (void*)&dev->tbusy); } else { tp->tx_full = 1; } @@ -892,36 +944,36 @@ dev->trans_start = jiffies; if (rtl8129_debug > 4) printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n", - dev->name, skb->data, skb->len, entry); + dev->name, skb->data, (int)skb->len, entry); return 0; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs) +static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { -#ifdef SA_SHIRQ struct device *dev = (struct device *)dev_instance; -#else - struct device *dev = (struct device *)(irq2dev_map[irq]); -#endif - struct rtl8129_private *tp; - int ioaddr, boguscnt = max_interrupt_work; + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + int boguscnt = max_interrupt_work; int status; + long ioaddr = dev->base_addr; - if (dev == NULL) { - printk (KERN_ERR"rtl8139_interrupt(): IRQ %d for unknown device.\n", - irq); +#if defined(__i386__) + /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + dev->interrupt = 0; /* Avoid halting machine. */ return; } - - ioaddr = dev->base_addr; - tp = (struct rtl8129_private *)dev->priv; - if (test_and_set_bit(0, (void*)&dev->interrupt)) { +#else + if (dev->interrupt) { printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); return; } + dev->interrupt = 1; +#endif do { status = inw(ioaddr + IntrStatus); @@ -944,9 +996,9 @@ for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) { int entry = dirty_tx % NUM_TX_DESC; - int txstatus = inl(ioaddr + TxStat0 + entry*4); + int txstatus = inl(ioaddr + TxStatus0 + entry*4); - if ( ! (txstatus & TxHostOwns)) + if ( ! (txstatus & (TxStatOK | TxUnderrun | TxAborted))) break; /* It still hasn't been Txed */ /* Note: TxCarrierLost is always asserted at 100mbps. */ @@ -973,15 +1025,20 @@ /* No count for tp->stats.tx_deferred */ #endif if (txstatus & TxUnderrun) { - /* Todo: increase the Tx FIFO threshold. */ + /* Add 64 to the Tx FIFO threshold. */ + if (tp->tx_flag < 0x00300000) + tp->tx_flag += 0x00020000; tp->stats.tx_fifo_errors++; } tp->stats.collisions += (txstatus >> 24) & 15; +#if LINUX_VERSION_CODE > 0x20119 + tp->stats.tx_bytes += txstatus & 0x7ff; +#endif tp->stats.tx_packets++; } /* Free the original skb. */ - dev_kfree_skb(tp->tx_skbuff[entry]); + dev_free_skb(tp->tx_skbuff[entry]); tp->tx_skbuff[entry] = 0; } @@ -993,8 +1050,7 @@ } #endif - if (tp->tx_full && dev->tbusy - && dirty_tx > tp->cur_tx - NUM_TX_DESC) { + if (tp->tx_full && dirty_tx > tp->cur_tx - NUM_TX_DESC) { /* The ring is no longer full, clear tbusy. */ tp->tx_full = 0; dev->tbusy = 0; @@ -1007,17 +1063,29 @@ /* Check uncommon events with one test. */ if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver |TxErr|RxErr)) { + if (rtl8129_debug > 2) + printk(KERN_NOTICE"%s: Abnormal interrupt, status %8.8x.\n", + dev->name, status); -#ifndef final_version - if (rtl8129_debug > 0) - printk(KERN_DEBUG"%s: Unusual error, status %4.4x.\n", - dev->name, status); -#endif - + if (status == 0xffffffff) + break; /* Update the error count. */ tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); outl(0, ioaddr + RxMissed); + if ((status & RxUnderrun) && + (rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) { + /* Really link-change on new chips. */ + int lpar = inw(ioaddr + NWayLPAR); + int duplex = (lpar&0x0100)||(lpar & 0x01C0) == 0x0040; + if (tp->full_duplex != duplex) { + tp->full_duplex = duplex; + outb(0xC0, ioaddr + Cfg9346); + outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); + outb(0x00, ioaddr + Cfg9346); + } + status &= ~RxUnderrun; + } if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) tp->stats.rx_errors++; @@ -1028,7 +1096,14 @@ tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN; outw(tp->cur_rx - 16, ioaddr + RxBufPtr); } - /* Error sources cleared above. */ + if (status & PCIErr) { + u32 pci_cmd_status; + pcibios_read_config_dword(tp->pci_bus, tp->pci_devfn, + PCI_COMMAND, &pci_cmd_status); + + printk(KERN_ERR "%s: PCI Bus error %4.4x.\n", + dev->name, pci_cmd_status); + } } if (--boguscnt < 0) { printk(KERN_WARNING"%s: Too much work at interrupt, " @@ -1044,29 +1119,20 @@ printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n", dev->name, inl(ioaddr + IntrStatus)); -#ifndef final_version - /* Code that should never be run! Perhaps remove after testing.. */ - { - static int stopit = 10; - if (dev->start == 0 && --stopit < 0) { - printk(KERN_ERR"%s: Emergency stop, looping startup interrupt.\n", - dev->name); - FREE_IRQ(irq, dev); - } - } -#endif - +#if defined(__i386__) + clear_bit(0, (void*)&dev->interrupt); +#else dev->interrupt = 0; +#endif return; } -/* Todo: The data sheet doesn't describe the Rx ring at all, so I'm winging - it here until I have a chip to play with. 8/30/97 */ -static int -rtl8129_rx(struct device *dev) +/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the + field alignments and semantics. */ +static int rtl8129_rx(struct device *dev) { struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; unsigned char *rx_ring = tp->rx_ring; u16 cur_rx = tp->cur_rx; @@ -1077,9 +1143,9 @@ inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd)); while ((inb(ioaddr + ChipCmd) & 1) == 0) { - u16 ring_offset = cur_rx % RX_BUF_LEN; + int ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status = *(u32*)(rx_ring + ring_offset); - u16 rx_size = rx_status >> 16; + int rx_size = rx_status >> 16; if (rtl8129_debug > 4) { int i; @@ -1105,12 +1171,18 @@ tp->stats.rx_frame_errors++; if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++; if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++; + /* Reset the receiver, based on RealTek recommendation. (Bug?) */ + tp->cur_rx = 0; + outb(CmdTxEnb, ioaddr + ChipCmd); + outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd); + outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | + (RX_DMA_BURST<<8), ioaddr + RxConfig); } else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ struct sk_buff *skb; - skb = DEV_ALLOC_SKB(rx_size + 2); + skb = dev_alloc_skb(rx_size + 2); if (skb == NULL) { printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n", dev->name); @@ -1129,26 +1201,32 @@ rx_size-semi_count); if (rtl8129_debug > 4) { int i; - printk(KERN_DEBUG"%s: Frame wrap @%d", dev->name, semi_count); + printk(KERN_DEBUG"%s: Frame wrap @%d", + dev->name, semi_count); for (i = 0; i < 16; i++) printk(" %2.2x", rx_ring[i]); printk(".\n"); memset(rx_ring, 0xcc, 16); } - } else + } else { +#if 1 /* USE_IP_COPYSUM */ + eth_copy_and_sum(skb, &rx_ring[ring_offset + 4], + rx_size, 0); + skb_put(skb, rx_size); +#else memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4], rx_size); -#if LINUX_VERSION_CODE >= 0x10300 - skb->protocol = eth_type_trans(skb, dev); -#else - skb->len = rx_size; #endif + } + skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); +#if LINUX_VERSION_CODE > 0x20119 + tp->stats.rx_bytes += rx_size; +#endif tp->stats.rx_packets++; } - cur_rx += rx_size + 4; - cur_rx = (cur_rx + 3) & ~3; + cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; outw(cur_rx - 16, ioaddr + RxBufPtr); } if (rtl8129_debug > 4) @@ -1163,7 +1241,7 @@ static int rtl8129_close(struct device *dev) { - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; int i; @@ -1186,29 +1264,11 @@ del_timer(&tp->timer); -#ifdef SA_SHIRQ free_irq(dev->irq, dev); -#else - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; -#endif - -#ifndef final_version - /* Used to monitor rx ring overflow. */ - for (i = 0; i < 16; i++) - if (tp->rx_ring[RX_BUF_LEN+i] != 0xcc) { - printk(KERN_WARNING"%s: Rx ring overflowed! Values are ", - dev->name); - for (i = 0; i < 16; i++) - printk(" %2.2x", tp->rx_ring[RX_BUF_LEN + i]); - printk(".\n"); - break; - } -#endif for (i = 0; i < NUM_TX_DESC; i++) { if (tp->tx_skbuff[i]) - dev_kfree_skb(tp->tx_skbuff[i]); + dev_free_skb(tp->tx_skbuff[i]); tp->tx_skbuff[i] = 0; } kfree(tp->rx_ring); @@ -1224,11 +1284,33 @@ return 0; } +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) +{ + struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; + u16 *data = (u16 *)&rq->ifr_data; + + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = tp->phys[0] & 0x3f; + /* Fall Through */ + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + if (!suser()) + return -EPERM; + mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + return 0; + default: + return -EOPNOTSUPP; + } +} + static struct enet_statistics * rtl8129_get_stats(struct device *dev) { struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; if (dev->start) { tp->stats.rx_missed_errors += inl(ioaddr + RxMissed); @@ -1239,94 +1321,69 @@ } /* Set or clear the multicast filter for this adaptor. - Note that we only use exclusion around actually queueing the - new frame, not around filling tp->setup_frame. This is non-deterministic - when re-entered but still correct. */ - -/* The little-endian AUTODIN II ethernet CRC calculation. - N.B. Do not use for bulk data, use a table-based routine instead. - This is common code and should be moved to net/core/crc.c */ -static unsigned const ethernet_polynomial_le = 0xedb88320U; -static inline unsigned ether_crc_le(int length, unsigned char *data) + This routine is not state sensitive and need not be SMP locked. */ + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) { - unsigned int crc = 0xffffffff; /* Initial value. */ - while(--length >= 0) { + int crc = -1; + + while(--length >= 0) { unsigned char current_octet = *data++; int bit; - for (bit = 8; --bit >= 0; current_octet >>= 1) { - if ((crc ^ current_octet) & 1) { - crc >>= 1; - crc ^= ethernet_polynomial_le; - } else - crc >>= 1; - } - } - return crc; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + return crc; } +/* Bits in RxConfig. */ +enum rx_mode_bits { + AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08, + AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01, +}; -static void -#ifdef NEW_MULTICAST -set_rx_mode(struct device *dev) -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif +static void set_rx_mode(struct device *dev) { - int ioaddr = dev->base_addr; - struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; - unsigned char mc_filter[8]; /* Multicast hash filter */ - int i; + long ioaddr = dev->base_addr; + u32 mc_filter[2]; /* Multicast hash filter */ + int i, rx_mode; + + if (rtl8129_debug > 3) + printk(KERN_DEBUG"%s: set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", + dev->name, dev->flags, inl(ioaddr + RxConfig)); - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + /* Note: do not reorder, GCC is clever about common statements. */ + if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name); - memset(mc_filter, 0xff, sizeof(mc_filter)); - outb(0x0F, ioaddr + RxConfig); - } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + rx_mode = AcceptBroadcast|AcceptMulticast|AcceptMyPhys|AcceptAllPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; + } else if ((dev->mc_count > multicast_filter_limit) + || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ - memset(mc_filter, 0xff, sizeof(mc_filter)); - outb(0x0E, ioaddr + RxConfig); - } else if (dev->mc_count == 0) { - outb(0x0A, ioaddr + RxConfig); - return; + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; - - memset(mc_filter, 0, sizeof(mc_filter)); + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; + mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) - set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f, - mc_filter); - } - /* ToDo: perhaps we need to stop the Tx and Rx process here? */ - if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) { - for (i = 0; i < 2; i++) - outl(((u32 *)mc_filter)[i], ioaddr + MAR0 + i*4); - memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter)); + set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26, mc_filter); } - if (rtl8129_debug > 3) - printk(KERN_DEBUG"%s: set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", - dev->name, dev->flags, inl(ioaddr + RxConfig)); + /* We can safely update without stopping the chip. */ + outb(rx_mode, ioaddr + RxConfig); + outl(mc_filter[0], ioaddr + MAR0 + 0); + outl(mc_filter[1], ioaddr + MAR0 + 4); return; } #ifdef MODULE - -/* An additional parameter that may be passed in... */ -static int debug = -1; - -int -init_module(void) +int init_module(void) { - int cards_found; - - if (debug >= 0) - rtl8129_debug = debug; - - root_rtl8129_dev = NULL; - cards_found = rtl8139_probe(0); - - return cards_found ? 0 : -ENODEV; + return rtl8139_probe(0); } void @@ -1336,9 +1393,13 @@ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_rtl8129_dev) { - next_dev = ((struct rtl8129_private *)root_rtl8129_dev->priv)->next_module; + struct rtl8129_private *tp = + (struct rtl8129_private *)root_rtl8129_dev->priv; + next_dev = tp->next_module; unregister_netdev(root_rtl8129_dev); - release_region(root_rtl8129_dev->base_addr, RTL8129_TOTAL_SIZE); + release_region(root_rtl8129_dev->base_addr, + pci_tbl[tp->chip_id].io_size); + kfree(tp); kfree(root_rtl8129_dev); root_rtl8129_dev = next_dev; } @@ -1348,7 +1409,8 @@ /* * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c" + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 diff -u --recursive --new-file v2.1.127/linux/drivers/net/strip.c linux/drivers/net/strip.c --- v2.1.127/linux/drivers/net/strip.c Fri Oct 9 13:27:09 1998 +++ linux/drivers/net/strip.c Sun Nov 8 13:48:06 1998 @@ -1270,6 +1270,8 @@ } static const char proc_strip_status_name[] = "strip"; + +#ifdef CONFIG_PROC_FS static struct proc_dir_entry proc_strip_get_status_info = { PROC_NET_STRIP_STATUS, /* unsigned short low_ino */ @@ -1284,7 +1286,7 @@ NULL, NULL, NULL, /* struct proc_dir_entry *next, *parent, *subdir; */ NULL /* void *data; */ }; - +#endif /* CONFIG_PROC_FS */ /************************************************************************/ /* Sending routines */ @@ -2847,10 +2849,12 @@ /* * Register the status file with /proc */ +#ifdef CONFIG_PROC_FS if (proc_net_register(&proc_strip_get_status_info) != 0) { printk(KERN_ERR "strip: status proc_net_register() failed.\n"); } +#endif #ifdef MODULE return status; @@ -2881,7 +2885,9 @@ strip_free(struct_strip_list); /* Unregister with the /proc/net file here. */ +#ifdef CONFIG_PROC_FS proc_net_unregister(PROC_NET_STRIP_STATUS); +#endif if ((i = tty_register_ldisc(N_STRIP, NULL))) printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); diff -u --recursive --new-file v2.1.127/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.1.127/linux/drivers/net/yellowfin.c Sun Jun 7 11:16:33 1998 +++ linux/drivers/net/yellowfin.c Sun Nov 8 13:48:06 1998 @@ -1,11 +1,12 @@ /* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */ /* - Written 1997 by Donald Becker. + Written 1997-1998 by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. This driver is for the Packet Engines G-NIC PCI Gigabit Ethernet adapter. + It also supports the Symbios Logic version of the same chip core. The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of Excellence in Space Data and Information Sciences @@ -15,7 +16,9 @@ http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html */ -static const char *version = "yellowfin.c:v0.10 12/5/97 becker@cesdis.gsfc.nasa.gov\n"; +static const char *version = +"yellowfin.c:v1.02 7/26/98 Written by Donald Becker, becker@cesdis.edu\n" +" http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html\n"; /* A few user-configurable values. */ @@ -27,7 +30,7 @@ static int bogus_rx = 0; static int dma_ctrl = 0x004A0263; /* Constrained by errata */ static int fifo_cfg = 0x0020; /* Bypass external Tx FIFO. */ -#elif YF_NEW +#elif YF_NEW /* A future perfect board :->. */ static int dma_ctrl = 0x00CAC277; /* Override when loading module! */ static int fifo_cfg = 0x0028; #else @@ -36,8 +39,18 @@ #endif /* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1518 effectively disables this feature. */ -static const int rx_copybreak = 100; + Setting to > 1514 effectively disables this feature. */ +static int rx_copybreak = 0; + +/* Used to pass the media type, etc. + No media types are currently defined. These exist for driver + interoperability. +*/ +#define MAX_UNITS 8 /* More are supported, limit only on options */ +static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; + +/* Operational parameters that are set at compile time. */ /* Keep the ring sizes a power of two for efficiency. Making the Tx ring too large decreases the effectiveness of channel @@ -80,68 +93,35 @@ #include #include -/* Kernel compatibility defines, common to David Hind's PCMCIA package. - This is only in the support-all-kernels source code. */ +/* Kernel compatibility defines, most common to the PCCard package. */ #include /* Evil, but neccessary */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300 -#define RUN_AT(x) (x) /* What to put in timer->expires. */ -#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC) -#define virt_to_bus(addr) ((unsigned long)addr) -#define bus_to_virt(addr) ((void*)addr) - -#else /* 1.3.0 and later */ #define RUN_AT(x) (jiffies + (x)) -#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) -#endif - -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338 -#ifdef MODULE -#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__) -char kernel_version[] = UTS_RELEASE; -#endif -#else -#undef MOD_INC_USE_COUNT -#define MOD_INC_USE_COUNT -#undef MOD_DEC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif -#endif /* 1.3.38 */ -#if (LINUX_VERSION_CODE >= 0x10344) -#define NEW_MULTICAST -#include -#endif #if (LINUX_VERSION_CODE >= 0x20100) -#ifdef MODULE char kernel_version[] = UTS_RELEASE; #endif -#endif -#ifdef SA_SHIRQ -#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) -#else -#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs) -#endif #if (LINUX_VERSION_CODE < 0x20123) #define test_and_set_bit(val, addr) set_bit(val, addr) -#include #endif - -static const char *card_name = "Yellowfin G-NIC Gbit Ethernet"; +#if LINUX_VERSION_CODE <= 0x20139 +#define net_device_stats enet_statistics +#define NETSTATS_VER2 +#endif +#if LINUX_VERSION_CODE < 0x20155 +#define PCI_SUPPORT_VER1 +#define pci_present pcibios_present +#endif +#if LINUX_VERSION_CODE < 0x20159 +#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE); +#else +#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); +#endif /* The PCI I/O space extent. */ #define YELLOWFIN_TOTAL_SIZE 0x100 -#ifdef HAVE_DEVLIST -struct netdev_entry yellowfin_drv = -{card_name, yellowfin_pci_probe, YELLOWFIN_TOTAL_SIZE, NULL}; -#endif - -#ifdef YELLOWFIN_DEBUG -int yellowfin_debug = YELLOWFIN_DEBUG; -#else int yellowfin_debug = 1; -#endif /* Theory of Operation @@ -204,15 +184,20 @@ IV. Notes Thanks to Kim Stearns of Packet Engines for providing a pair of G-NIC boards. +Thanks to Bruce Faust of Digitalscape for providing both their SYM53C885 board +and an AlphaStation to verifty the Alpha port! IVb. References Yellowfin Engineering Design Specification, 4/23/97 Preliminary/Confidential +Symbios SYM53C885 PCI-SCSI/Fast Ethernet Multifunction Controller Preliminary + Data Manual v3.0 +http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html IVc. Errata -See Packet Engines confidential appendix. +See Packet Engines confidential appendix (prototype chips only). */ @@ -221,6 +206,7 @@ #ifndef PCI_VENDOR_ID_PKT_ENG /* To be defined in linux/pci.h */ #define PCI_VENDOR_ID_PKT_ENG 0x1000 /* Hmm, likely number.. */ +#define PCI_DEVICE_ID_SYM58C885 0x0701 #define PCI_DEVICE_ID_YELLOWFIN 0x0702 #endif @@ -228,6 +214,21 @@ static void yellowfin_timer(unsigned long data); +enum capability_flags {HasMII=1, FullTxStatus=2}; +struct chip_info { + u16 vendor_id, device_id, device_id_mask, pci_flags; + const char *name; + void (*media_timer)(unsigned long data); + u32 chip_rev; /* As read from ChipRev, not PCI dev ID. */ + int flags; +} chip_tbl[] = { + {0x1000, 0x0702, 0xffff, 0, "Yellowfin G-NIC Gbit Ethernet", + yellowfin_timer, 0x0702, FullTxStatus}, + {0x1000, 0x0701, 0xffff, 0, "Symbios SYM83C885", + yellowfin_timer, 0x0701, HasMII}, + {0,}, +}; + /* Offsets to the Yellowfin registers. Various sizes and alignments. */ enum yellowfin_offsets { TxCtrl=0x00, TxStatus=0x04, TxPtr=0x0C, @@ -235,8 +236,13 @@ RxCtrl=0x40, RxStatus=0x44, RxPtr=0x4C, RxIntrSel=0x50, RxBranchSel=0x54, RxWaitSel=0x58, EventStatus=0x80, IntrEnb=0x82, IntrClear=0x84, IntrStatus=0x86, - ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, RxDepth=0xB8, FlowCtrl=0xBC, + ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, FrameGap0=0xA2, FrameGap1=0xA4, + MII_Cmd=0xA6, MII_Addr=0xA8, MII_Wr_Data=0xAA, MII_Rd_Data=0xAC, + MII_Status=0xAE, + RxDepth=0xB8, FlowCtrl=0xBC, AddrMode=0xD0, StnAddr=0xD2, HashTbl=0xD8, FIFOcfg=0xF8, + EEStatus=0xF0, EECtrl=0xF1, EEAddr=0xF2, EERead=0xF3, EEWrite=0xF4, + EEFeature=0xF5, }; /* The Yellowfin Rx and Tx buffer descriptors. */ @@ -280,27 +286,34 @@ struct yellowfin_desc tx_ring[TX_RING_SIZE*2]; const char *product_name; struct device *next_module; + /* The addresses of receive-in-place skbuffs. */ + struct sk_buff* rx_skbuff[RX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct tx_status_words tx_status[TX_RING_SIZE]; - /* The addresses of receive-in-place skbuffs. */ - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - int chip_id; - struct enet_statistics stats; struct timer_list timer; /* Media selection timer. */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct enet_statistics stats; + /* Frequently used and paired value: keep adjacent for cache effect. */ + int chip_id; + int in_interrupt; + struct yellowfin_desc *rx_head_desc; + struct tx_status_words *tx_tail_desc; + unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ + unsigned int cur_tx, dirty_tx; + unsigned int rx_buf_sz; /* Based on MTU+slack. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int duplex_lock:1; unsigned int medialock:1; /* Do not sense media. */ unsigned int default_port:4; /* Last dev->if_port value. */ + /* MII transceiver section. */ + int mii_cnt; /* MII device addresses. */ + u16 advertising; /* NWay media advertisement */ + unsigned char phys[2]; /* MII device addresses. */ u32 pad[4]; /* Used for 32-byte alignment */ }; #ifdef MODULE -/* Used to pass the media type, etc. */ -#define MAX_UNITS 8 /* More are supported, limit only on options */ -static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Donald Becker "); @@ -311,169 +324,163 @@ MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); #endif #endif -static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options); +static struct device *yellowfin_probe1(struct device *dev, long ioaddr, + int irq, int chip_id, int options); +static int read_eeprom(long ioaddr, int location); +static int mdio_read(long ioaddr, int phy_id, int location); +static void mdio_write(long ioaddr, int phy_id, int location, int value); +#ifdef HAVE_PRIVATE_IOCTL +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd); +#endif static int yellowfin_open(struct device *dev); static void yellowfin_timer(unsigned long data); static void yellowfin_tx_timeout(struct device *dev); static void yellowfin_init_ring(struct device *dev); static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev); +static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int yellowfin_rx(struct device *dev); -static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs); +static void yellowfin_error(struct device *dev, int intr_status); static int yellowfin_close(struct device *dev); static struct enet_statistics *yellowfin_get_stats(struct device *dev); -#ifdef NEW_MULTICAST static void set_rx_mode(struct device *dev); -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif -#ifdef MODULE /* A list of all installed Yellowfin devices, for removing the driver module. */ static struct device *root_yellowfin_dev = NULL; -#endif int yellowfin_probe(struct device *dev) { int cards_found = 0; - static int pci_index = 0; /* Static, for multiple probe calls. */ + int pci_index = 0; + unsigned char pci_bus, pci_device_fn; - /* Ideally we would detect all network cards in slot order. That would - be best done a central PCI probe dispatch, which wouldn't work - well with the current structure. So instead we detect just the - Yellowfin cards in slot order. */ - - if (pci_present()) { - unsigned char pci_bus, pci_device_fn; - - for (;pci_index < 0xff; pci_index++) { -#if LINUX_VERSION_CODE >= 0x20155 - unsigned int pci_irq_line; - struct pci_dev *pdev; -#else - unsigned char pci_irq_line; -#endif - unsigned char pci_latency; - unsigned short pci_command, vendor, device; - unsigned int pci_ioaddr, chip_idx = 0; - -#ifdef REVERSE_PROBE_ORDER - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, - 0xfe - pci_index, - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - continue; -#else - if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, - pci_index, - &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) + if ( ! pci_present()) + return -ENODEV; + + for (;pci_index < 0xff; pci_index++) { + u8 pci_latency; + u16 pci_command, new_command, vendor, device; + int chip_idx; + int irq; + long ioaddr; + + if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, + pci_index, + &pci_bus, &pci_device_fn) + != PCIBIOS_SUCCESSFUL) + break; + + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_DEVICE_ID, &device); + + for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor == chip_tbl[chip_idx].vendor_id + && (device & chip_tbl[chip_idx].device_id_mask) == + chip_tbl[chip_idx].device_id) break; -#endif - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); -#if LINUX_VERSION_CODE >= 0x20155 - pdev = pci_find_slot(pci_bus, pci_device_fn); - pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0]; + if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */ + continue; + + { +#if LINUX_VERSION_CODE >= 0x20155 || PCI_SUPPORT_1 + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->base_address[0]; + irq = pdev->irq; #else + u32 pci_ioaddr; + u8 pci_irq_line; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_ioaddr); + ioaddr = pci_ioaddr; + irq = pci_irq_line; #endif - /* Remove I/O space marker in bit 0. */ - pci_ioaddr &= ~3; - - if (vendor != PCI_VENDOR_ID_PKT_ENG) - continue; - - if (device != PCI_DEVICE_ID_YELLOWFIN) - continue; + } + /* Remove I/O space marker in bit 0. */ + ioaddr &= ~3; - if (yellowfin_debug > 2) - printk("Found Packet Engines Yellowfin G-NIC at I/O %#x, IRQ %d.\n", - pci_ioaddr, pci_irq_line); + if (yellowfin_debug > 2) + printk(KERN_INFO "Found %s at I/O %#lx, IRQ %d.\n", + chip_tbl[chip_idx].name, ioaddr, irq); + + if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE)) + continue; + + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled the" + " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", + pci_bus, pci_device_fn, pci_command, new_command); + pcibios_write_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, new_command); + } - if (check_region(pci_ioaddr, YELLOWFIN_TOTAL_SIZE)) - continue; + dev = yellowfin_probe1(dev, ioaddr, irq, chip_idx, cards_found); -#ifdef MODULE - dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, - cards_found < MAX_UNITS ? options[cards_found] : 0); -#else - dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, - dev ? dev->mem_start : 0); -#endif - - if (dev) { - /* Get and check the bus-master and latency values. */ - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk(" PCI Master Bit has not been set! Setting...\n"); - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, pci_command); - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < min_pci_latency) { - printk(" PCI latency timer (CFLT) is unreasonably low at %d." - " Setting to %d clocks.\n", + if (dev) { + /* Get and check the bus-master and latency values. */ + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency < min_pci_latency) { + printk(KERN_INFO " PCI latency timer (CFLT) is " + "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); pcibios_write_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, min_pci_latency); - } else if (yellowfin_debug > 1) - printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - dev = 0; - cards_found++; - } + } else if (yellowfin_debug > 1) + printk(KERN_INFO " PCI latency timer (CFLT) is %#x.\n", + pci_latency); + dev = 0; + cards_found++; } } -#if defined (MODULE) - return cards_found; -#else - return 0; -#endif + return cards_found ? 0 : -ENODEV; } -static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq, - int chip_id, int options) +static struct device *yellowfin_probe1(struct device *dev, long ioaddr, + int irq, int chip_id, int card_idx) { static int did_version = 0; /* Already printed version info. */ struct yellowfin_private *yp; - int i; + int option, i; if (yellowfin_debug > 0 && did_version++ == 0) printk(version); dev = init_etherdev(dev, sizeof(struct yellowfin_private)); - printk("%s: P-E Yellowfin type %8x at %#3x, ", - dev->name, inl(ioaddr + ChipRev), ioaddr); + printk(KERN_INFO "%s: %s type %8x at 0x%lx, ", + dev->name, chip_tbl[chip_id].name, inl(ioaddr + ChipRev), ioaddr); + if (inw(ioaddr + ChipRev) == 0x0702) + for (i = 0; i < 6; i++) + dev->dev_addr[i] = inb(ioaddr + StnAddr + i); + else { + int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0); + for (i = 0; i < 6; i++) + dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i); + } for (i = 0; i < 5; i++) - printk("%2.2x:", inb(ioaddr + StnAddr + i)); - printk("%2.2x, IRQ %d.\n", inb(ioaddr + StnAddr + i), irq); - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(ioaddr + StnAddr + i); + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); /* Reset the chip. */ outl(0x80000000, ioaddr + DMACtrl); - /* We do a request_region() only to register /proc/ioports info. */ - request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, card_name); + request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, dev->name); dev->base_addr = ioaddr; dev->irq = irq; @@ -483,28 +490,28 @@ memset(yp, 0, sizeof(*yp)); dev->priv = yp; -#ifdef MODULE yp->next_module = root_yellowfin_dev; root_yellowfin_dev = dev; -#endif yp->chip_id = chip_id; - yp->full_duplex = 1; -#ifdef YELLOWFIN_DEFAULT_MEDIA - yp->default_port = YELLOWFIN_DEFAULT_MEDIA; -#endif -#ifdef YELLOWFIN_NO_MEDIA_SWITCH - yp->medialock = 1; -#endif + option = card_idx < MAX_UNITS ? options[card_idx] : 0; + if (dev->mem_start) + option = dev->mem_start; /* The lower four bits are the media type. */ - if (options > 0) { - yp->full_duplex = (options & 16) ? 1 : 0; - yp->default_port = options & 15; + if (option > 0) { + if (option & 0x200) + yp->full_duplex = 1; + yp->default_port = option & 15; if (yp->default_port) yp->medialock = 1; } + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + yp->full_duplex = 1; + + if (yp->full_duplex) + yp->duplex_lock = 1; /* The Yellowfin-specific entries in the device structure. */ dev->open = &yellowfin_open; @@ -512,40 +519,88 @@ dev->stop = &yellowfin_close; dev->get_stats = &yellowfin_get_stats; dev->set_multicast_list = &set_rx_mode; +#ifdef HAVE_PRIVATE_IOCTL + dev->do_ioctl = &mii_ioctl; +#endif if (mtu) dev->mtu = mtu; - /* todo: Reset the xcvr interface and turn on heartbeat. */ + if (chip_tbl[yp->chip_id].flags & HasMII) { + int phy, phy_idx = 0; + for (phy = 0; phy < 32 && phy_idx < 4; phy++) { + int mii_status = mdio_read(ioaddr, phy, 1); + if (mii_status != 0xffff && + mii_status != 0x0000) { + yp->phys[phy_idx++] = phy; + yp->advertising = mdio_read(ioaddr, phy, 4); + printk(KERN_INFO "%s: MII PHY found at address %d, status " + "0x%4.4x advertising %4.4x.\n", + dev->name, phy, mii_status, yp->advertising); + } + } + yp->mii_cnt = phy_idx; + } return dev; } +static int read_eeprom(long ioaddr, int location) +{ + int bogus_cnt = 1000; + + outb(location, ioaddr + EEAddr); + outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl); + while ((inb(ioaddr + EEStatus) & 0x80) && --bogus_cnt > 0) + ; + return inb(ioaddr + EERead); +} + +/* MII Managemen Data I/O accesses. + These routines assume the MDIO controller is idle, and do not exit until + the command is finished. */ + +static int mdio_read(long ioaddr, int phy_id, int location) +{ + int i; + + outw((phy_id<<8) + location, ioaddr + MII_Addr); + outw(1, ioaddr + MII_Cmd); + for (i = 10000; i >= 0; i--) + if ((inw(ioaddr + MII_Status) & 1) == 0) + break; + return inw(ioaddr + MII_Rd_Data); +} + +static void mdio_write(long ioaddr, int phy_id, int location, int value) +{ + int i; + + outw((phy_id<<8) + location, ioaddr + MII_Addr); + outw(value, ioaddr + MII_Wr_Data); + + /* Wait for the command to finish. */ + for (i = 10000; i >= 0; i--) + if ((inw(ioaddr + MII_Status) & 1) == 0) + break; + return; +} + -static int -yellowfin_open(struct device *dev) +static int yellowfin_open(struct device *dev) { struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; + int i; /* Reset the chip. */ outl(0x80000000, ioaddr + DMACtrl); -#ifdef SA_SHIRQ - if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, - card_name, dev)) { - return -EAGAIN; - } -#else - if (irq2dev_map[dev->irq] != NULL - || (irq2dev_map[dev->irq] = dev) == NULL - || dev->irq == 0 - || request_irq(dev->irq, &yellowfin_interrupt, 0, card_name)) { + if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; - } -#endif if (yellowfin_debug > 1) - printk("%s: yellowfin_open() irq %d.\n", dev->name, dev->irq); + printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n", + dev->name, dev->irq); MOD_INC_USE_COUNT; @@ -554,6 +609,9 @@ outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr); outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr); + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + StnAddr + i); + /* Set up various condition 'select' registers. There are no options here. */ outl(0x00800080, ioaddr + TxIntrSel); /* Interrupt on Tx abort */ @@ -575,17 +633,19 @@ dev->tbusy = 0; dev->interrupt = 0; - - /* We are always in full-duplex mode with the current chip! */ - yp->full_duplex = 1; + yp->in_interrupt = 0; /* Setting the Rx mode will start the Rx process. */ - outw(0x01CD | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); -#ifdef NEW_MULTICAST + if (yp->chip_id == 0) { + /* We are always in full-duplex mode with gigabit! */ + yp->full_duplex = 1; + outw(0x01CF, ioaddr + Cnfg); + } else { + outw(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */ + outw(0x1018, ioaddr + FrameGap1); + outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); + } set_rx_mode(dev); -#else - set_rx_mode(dev, 0, 0); -#endif dev->start = 1; @@ -596,7 +656,7 @@ outl(0x80008000, ioaddr + TxCtrl); if (yellowfin_debug > 2) { - printk("%s: Done yellowfin_open().\n", + printk(KERN_DEBUG "%s: Done yellowfin_open().\n", dev->name); } /* Set the timer to check for link beat. */ @@ -613,13 +673,36 @@ { struct device *dev = (struct device *)data; struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; int next_tick = 0; if (yellowfin_debug > 3) { - printk("%s: Yellowfin timer tick, status %8.8x.\n", - dev->name, inl(ioaddr + IntrStatus)); + printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n", + dev->name, inw(ioaddr + IntrStatus)); + } + + if (yp->mii_cnt) { + int mii_reg1 = mdio_read(ioaddr, yp->phys[0], 1); + int mii_reg5 = mdio_read(ioaddr, yp->phys[0], 5); + int negotiated = mii_reg5 & yp->advertising; + if (yellowfin_debug > 1) + printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, " + "link partner capability %4.4x.\n", + dev->name, yp->phys[0], mii_reg1, mii_reg5); + + if ( ! yp->duplex_lock && + ((negotiated & 0x0300) == 0x0100 + || (negotiated & 0x00C0) == 0x0040)) { + yp->full_duplex = 1; + } + outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg); + + if (mii_reg1 & 0x0004) + next_tick = 60*HZ; + else + next_tick = 3*HZ; } + if (next_tick) { yp->timer.expires = RUN_AT(next_tick); add_timer(&yp->timer); @@ -629,20 +712,22 @@ static void yellowfin_tx_timeout(struct device *dev) { struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; - int ioaddr = dev->base_addr; - int i; + long ioaddr = dev->base_addr; - printk("%s: Yellowfin transmit timed out, status %8.8x, resetting...\n", + printk(KERN_WARNING "%s: Yellowfin transmit timed out, status %8.8x, resetting...\n", dev->name, inl(ioaddr)); #ifndef __alpha__ - printk(" Rx ring %8.8x: ", (int)yp->rx_ring); - for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)yp->rx_ring[i].status); - printk("\n Tx ring %8.8x: ", (int)yp->tx_ring); - for (i = 0; i < TX_RING_SIZE; i++) - printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status); - printk("\n"); + { + int i; + printk(KERN_DEBUG " Rx ring %8.8x: ", (int)yp->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + printk(" %8.8x", (unsigned int)yp->rx_ring[i].status); + printk("\n"KERN_DEBUG" Tx ring %8.8x: ", (int)yp->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status); + printk("\n"); + } #endif /* Perhaps we should reinitialize the hardware here. */ @@ -658,8 +743,7 @@ /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void -yellowfin_init_ring(struct device *dev) +static void yellowfin_init_ring(struct device *dev) { struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; int i; @@ -668,24 +752,23 @@ yp->cur_rx = yp->cur_tx = 0; yp->dirty_rx = yp->dirty_tx = 0; + yp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); + yp->rx_head_desc = &yp->rx_ring[0]; + for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; - int pkt_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); - yp->rx_ring[i].request_cnt = pkt_buf_sz; + yp->rx_ring[i].request_cnt = yp->rx_buf_sz; yp->rx_ring[i].cmd = CMD_RX_BUF | INTR_ALWAYS; - skb = DEV_ALLOC_SKB(pkt_buf_sz); - skb_reserve(skb, 2); /* 16 byte align the IP header. */ + skb = dev_alloc_skb(yp->rx_buf_sz); yp->rx_skbuff[i] = skb; - if (skb == NULL) - break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ -#if LINUX_VERSION_CODE > 0x10300 - yp->rx_ring[i].addr = virt_to_bus(skb->tail); -#else - yp->rx_ring[i].addr = virt_to_bus(skb->data); -#endif + if (skb) { + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* 16 byte align the IP header. */ + yp->rx_ring[i].addr = virt_to_bus(skb->tail); + } else if (yp->dirty_rx == 0) + yp->dirty_rx = (unsigned int)(0 - RX_RING_SIZE); yp->rx_ring[i].branch_addr = virt_to_bus(&yp->rx_ring[i+1]); } /* Mark the last entry as wrapping the ring. */ @@ -709,19 +792,26 @@ yp->tx_ring[i].cmd = CMD_STOP; /* Branch on Tx error. */ yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]); i++; - yp->tx_ring[i].cmd = CMD_TXSTATUS; /* Interrupt, no wait. */ - yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]); - yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]); + if (chip_tbl[yp->chip_id].flags & FullTxStatus) { + yp->tx_ring[i].cmd = CMD_TXSTATUS; + yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]); + yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]); + } else { /* Symbios chips write only tx_errs word. */ + yp->tx_ring[i].cmd = CMD_TXSTATUS | INTR_ALWAYS; + yp->tx_ring[i].request_cnt = 2; + yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2].tx_errs); + } yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]); } /* Wrap ring */ yp->tx_ring[--i].cmd = CMD_TXSTATUS | BRANCH_ALWAYS | INTR_ALWAYS; yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]); #endif + yp->tx_tail_desc = &yp->tx_status[0]; + return; } -static int -yellowfin_start_xmit(struct sk_buff *skb, struct device *dev) +static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev) { struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; unsigned entry; @@ -773,19 +863,19 @@ CMD_TX_PKT | BRANCH_IFTRUE; #endif - /* Todo: explicitly flush cache lines here. */ + /* Non-x86 Todo: explicitly flush cache lines here. */ /* Wake the potentially-idle transmit channel. */ outl(0x10001000, dev->base_addr + TxCtrl); if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1) - dev->tbusy = 0; /* Typical path */ + clear_bit(0, (void*)&dev->tbusy); /* Typical path */ else yp->tx_full = 1; dev->trans_start = jiffies; if (yellowfin_debug > 4) { - printk("%s: Yellowfin transmit frame #%d queued in slot %d.\n", + printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n", dev->name, yp->cur_tx, entry); } return 0; @@ -793,302 +883,320 @@ /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs) +static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { -#ifdef SA_SHIRQ /* Use the now-standard shared IRQ implementation. */ struct device *dev = (struct device *)dev_instance; -#else - struct device *dev = (struct device *)(irq2dev_map[irq]); -#endif - - struct yellowfin_private *lp; - int ioaddr, boguscnt = max_interrupt_work; + struct yellowfin_private *yp; + long ioaddr, boguscnt = max_interrupt_work; +#ifndef final_version /* Can never occur. */ if (dev == NULL) { - printk ("yellowfin_interrupt(): irq %d for unknown device.\n", irq); + printk (KERN_ERR "yellowfin_interrupt(): irq %d for unknown device.\n", irq); return; } +#endif ioaddr = dev->base_addr; - lp = (struct yellowfin_private *)dev->priv; - if (test_and_set_bit(0, (void*)&dev->interrupt)) { + yp = (struct yellowfin_private *)dev->priv; + if (test_and_set_bit(0, (void*)&yp->in_interrupt)) { + dev->interrupt = 1; printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); return; } do { u16 intr_status = inw(ioaddr + IntrClear); - unsigned dirty_tx = lp->dirty_tx; if (yellowfin_debug > 4) - printk("%s: Yellowfin interrupt, status %4.4x.\n", + printk(KERN_DEBUG "%s: Yellowfin interrupt, status %4.4x.\n", dev->name, intr_status); if (intr_status == 0) break; - if (intr_status & (IntrRxDone | IntrEarlyRx)) + if (intr_status & (IntrRxDone | IntrEarlyRx)) { yellowfin_rx(dev); + outl(0x10001000, ioaddr + RxCtrl); /* Wake Rx engine. */ + } #ifdef NO_TXSTATS - for (; dirty_tx < lp->cur_tx; dirty_tx++) { - int entry = dirty_tx % TX_RING_SIZE; - if (lp->tx_ring[entry].status == 0) + for (; yp->cur_tx - yp->dirty_tx > 0; yp->dirty_tx++) { + int entry = yp->dirty_tx % TX_RING_SIZE; + if (yp->tx_ring[entry].status == 0) break; /* Free the original skb. */ - dev_kfree_skb(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; - lp->stats.tx_packets++; + DEV_FREE_SKB(yp->tx_skbuff[entry]); + yp->tx_skbuff[entry] = 0; + yp->stats.tx_packets++; } - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 4) { + if (yp->tx_full && dev->tbusy + && yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) { /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - dev->tbusy = 0; + yp->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); mark_bh(NET_BH); } - lp->dirty_tx = dirty_tx; #else if (intr_status & IntrTxDone - || lp->tx_status[dirty_tx % TX_RING_SIZE].tx_errs) { + || yp->tx_tail_desc->tx_errs) { + unsigned dirty_tx = yp->dirty_tx; - for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) { + for (dirty_tx = yp->dirty_tx; yp->cur_tx - dirty_tx > 0; + dirty_tx++) { /* Todo: optimize this. */ int entry = dirty_tx % TX_RING_SIZE; - u16 tx_errs = lp->tx_status[entry].tx_errs; + u16 tx_errs = yp->tx_status[entry].tx_errs; +#ifndef final_version + if (yellowfin_debug > 5) + printk(KERN_DEBUG "%s: Tx queue %d check, Tx status " + "%4.4x %4.4x %4.4x %4.4x.\n", + dev->name, entry, + yp->tx_status[entry].tx_cnt, + yp->tx_status[entry].tx_errs, + yp->tx_status[entry].total_tx_cnt, + yp->tx_status[entry].paused); +#endif if (tx_errs == 0) break; /* It still hasn't been Txed */ if (tx_errs & 0xF8100000) { /* There was an major error, log it. */ #ifndef final_version if (yellowfin_debug > 1) - printk("%s: Transmit error, Tx status %4.4x.\n", + printk(KERN_DEBUG "%s: Transmit error, Tx status %4.4x.\n", dev->name, tx_errs); #endif - lp->stats.tx_errors++; - if (tx_errs & 0xF800) lp->stats.tx_aborted_errors++; - if (tx_errs & 0x0800) lp->stats.tx_carrier_errors++; - if (tx_errs & 0x2000) lp->stats.tx_window_errors++; - if (tx_errs & 0x8000) lp->stats.tx_fifo_errors++; + yp->stats.tx_errors++; + if (tx_errs & 0xF800) yp->stats.tx_aborted_errors++; + if (tx_errs & 0x0800) yp->stats.tx_carrier_errors++; + if (tx_errs & 0x2000) yp->stats.tx_window_errors++; + if (tx_errs & 0x8000) yp->stats.tx_fifo_errors++; #ifdef ETHER_STATS - if (tx_errs & 0x1000) lp->stats.collisions16++; + if (tx_errs & 0x1000) yp->stats.collisions16++; #endif } else { +#ifndef final_version + if (yellowfin_debug > 4) + printk(KERN_DEBUG "%s: Normal transmit, Tx status %4.4x.\n", + dev->name, tx_errs); +#endif #ifdef ETHER_STATS - if (status & 0x0400) lp->stats.tx_deferred++; + if (tx_errs & 0x0400) yp->stats.tx_deferred++; #endif - lp->stats.collisions += tx_errs & 15; - lp->stats.tx_packets++; + yp->stats.collisions += tx_errs & 15; + yp->stats.tx_packets++; } /* Free the original skb. */ - dev_kfree_skb(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; + DEV_FREE_SKB(yp->tx_skbuff[entry]); + yp->tx_skbuff[entry] = 0; /* Mark status as empty. */ - lp->tx_status[entry].tx_errs = 0; + yp->tx_status[entry].tx_errs = 0; } #ifndef final_version - if (lp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, lp->tx_full); + if (yp->cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, yp->cur_tx, yp->tx_full); dirty_tx += TX_RING_SIZE; } #endif - if (lp->tx_full && dev->tbusy - && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + if (yp->tx_full && dev->tbusy + && yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; - dev->tbusy = 0; + yp->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); mark_bh(NET_BH); } - lp->dirty_tx = dirty_tx; + yp->dirty_tx = dirty_tx; + yp->tx_tail_desc = &yp->tx_status[dirty_tx % TX_RING_SIZE]; } #endif - /* Log errors and other events. */ - if (intr_status & 0x2ee) { /* Abnormal error summary. */ - printk("%s: Something Wicked happened! %4.4x.\n", - dev->name, intr_status); - /* Hmmmmm, it's not clear what to do here. */ - if (intr_status & (IntrTxPCIErr | IntrTxPCIFault)) - lp->stats.tx_errors++; - if (intr_status & (IntrRxPCIErr | IntrRxPCIFault)) - lp->stats.rx_errors++; - } + /* Log errors and other uncommon events. */ + if (intr_status & 0x2ee) /* Abnormal error summary. */ + yellowfin_error(dev, intr_status); + if (--boguscnt < 0) { - printk("%s: Too much work at interrupt, status=0x%4.4x.\n", + printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n", dev->name, intr_status); break; } } while (1); if (yellowfin_debug > 3) - printk("%s: exiting interrupt, status=%#4.4x.\n", + printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, inw(ioaddr + IntrStatus)); /* Code that should never be run! Perhaps remove after testing.. */ { static int stopit = 10; if (dev->start == 0 && --stopit < 0) { - printk("%s: Emergency stop, looping startup interrupt.\n", + printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n", dev->name); -#ifdef SA_SHIRQ free_irq(irq, dev); -#else - free_irq(irq); -#endif } } dev->interrupt = 0; + clear_bit(0, (void*)&yp->in_interrupt); return; } /* This routine is logically part of the interrupt handler, but separated for clarity and better register allocation. */ -static int -yellowfin_rx(struct device *dev) +static int yellowfin_rx(struct device *dev) { - struct yellowfin_private *lp = (struct yellowfin_private *)dev->priv; struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; - int entry = lp->cur_rx % RX_RING_SIZE; + int entry = yp->cur_rx % RX_RING_SIZE; int boguscnt = 20; if (yellowfin_debug > 4) { - printk(" In yellowfin_rx(), entry %d status %4.4x.\n", entry, - yp->rx_ring[entry].status); - printk(" #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n", + printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %4.4x.\n", + entry, yp->rx_ring[entry].status); + printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n", entry, yp->rx_ring[entry].cmd, yp->rx_ring[entry].request_cnt, yp->rx_ring[entry].addr, yp->rx_ring[entry].result_cnt, yp->rx_ring[entry].status); } - /* If EOP is set on the next entry, it's a new packet. Send it up. */ - while (yp->rx_ring[entry].status) { - /* Todo: optimize this mess. */ - u16 desc_status = yp->rx_ring[entry].status; - struct yellowfin_desc *desc = &lp->rx_ring[entry]; - int frm_size = desc->request_cnt - desc->result_cnt; - u8 *buf_addr = bus_to_virt(lp->rx_ring[entry].addr); - s16 frame_status = *(s16*)&(buf_addr[frm_size - 2]); + while (yp->rx_head_desc->status) { + struct yellowfin_desc *desc = yp->rx_head_desc; + u16 desc_status = desc->status; + int data_size = desc->request_cnt - desc->result_cnt; + u8 *buf_addr = bus_to_virt(desc->addr); + s16 frame_status = *(s16*)&(buf_addr[data_size - 2]); /* ?Alpha safe on 885? */ if (yellowfin_debug > 4) - printk(" yellowfin_rx() status was %4.4x.\n", frame_status); + printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n", + frame_status); if (--boguscnt < 0) break; if ( ! (desc_status & RX_EOP)) { - printk("%s: Oversized Ethernet frame spanned multiple buffers," + printk(KERN_WARNING "%s: Oversized Ethernet frame spanned multiple buffers," " status %4.4x!\n", dev->name, desc_status); - lp->stats.rx_length_errors++; - } else if (frame_status & 0x0038) { + yp->stats.rx_length_errors++; + } else if (yp->chip_id == 0 && (frame_status & 0x0038)) { /* There was a error. */ if (yellowfin_debug > 3) - printk(" yellowfin_rx() Rx error was %4.4x.\n", frame_status); - lp->stats.rx_errors++; - if (frame_status & 0x0060) lp->stats.rx_length_errors++; - if (frame_status & 0x0008) lp->stats.rx_frame_errors++; - if (frame_status & 0x0010) lp->stats.rx_crc_errors++; - if (frame_status < 0) lp->stats.rx_dropped++; + printk(KERN_DEBUG " yellowfin_rx() Rx error was %4.4x.\n", + frame_status); + yp->stats.rx_errors++; + if (frame_status & 0x0060) yp->stats.rx_length_errors++; + if (frame_status & 0x0008) yp->stats.rx_frame_errors++; + if (frame_status & 0x0010) yp->stats.rx_crc_errors++; + if (frame_status < 0) yp->stats.rx_dropped++; + } else if (yp->chip_id != 0 && + ((buf_addr[data_size-1] & 0x85) || buf_addr[data_size-2] & 0xC0)) { + u8 status1 = buf_addr[data_size-2]; + u8 status2 = buf_addr[data_size-1]; + yp->stats.rx_errors++; + if (status1 & 0xC0) yp->stats.rx_length_errors++; + if (status2 & 0x03) yp->stats.rx_frame_errors++; + if (status2 & 0x04) yp->stats.rx_crc_errors++; + if (status2 & 0x80) yp->stats.rx_dropped++; #ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ - } else if (memcmp(bus_to_virt(lp->rx_ring[entry].addr), + } else if (memcmp(bus_to_virt(yp->rx_ring[entry].addr), dev->dev_addr, 6) != 0 - && memcmp(bus_to_virt(lp->rx_ring[entry].addr), - "\0377\0377\0377\0377\0377\0377", 6) != 0) { - printk("%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", - dev->name, - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[0], - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[1], - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[2], - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[3], - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[4], - ((char *)bus_to_virt(lp->rx_ring[entry].addr))[5]); + && memcmp(bus_to_virt(yp->rx_ring[entry].addr), + "\377\377\377\377\377\377", 6) != 0) { + printk(KERN_WARNING "%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + dev->name, buf_addr[0], buf_addr[1], buf_addr[2], + buf_addr[3], buf_addr[4], buf_addr[5]); bogus_rx++; #endif } else { - u8 bogus_cnt = buf_addr[frm_size - 8]; - short pkt_len = frm_size - 8 - bogus_cnt; struct sk_buff *skb; - int rx_in_place = 0; + int pkt_len = data_size - + (yp->chip_id ? 7 : 8 + buf_addr[data_size - 8]); + /* To verify: Yellowfin Length should omit the CRC! */ - /* Check if the packet is long enough to just accept without - copying to a properly sized skbuff. */ +#ifndef final_version + if (yellowfin_debug > 4) + printk(KERN_DEBUG " yellowfin_rx() normal Rx pkt length %d" + " of %d, bogus_cnt %d.\n", + pkt_len, data_size, boguscnt); +#endif + /* Check if the packet is long enough to just pass up the skbuff + without copying to a properly sized skbuff. */ if (pkt_len > rx_copybreak) { - struct sk_buff *newskb; - char *temp; - - /* Get a fresh skbuff to replace the filled one. */ - newskb = DEV_ALLOC_SKB(dev->mtu <= 1500 ? PKT_BUF_SZ - : dev->mtu + 32); - if (newskb == NULL) { - skb = 0; /* No memory, drop the packet. */ - goto memory_squeeze; - } - /* Pass up the skb already on the Rx ring. */ - skb = lp->rx_skbuff[entry]; - temp = skb_put(skb, pkt_len); - if (bus_to_virt(lp->rx_ring[entry].addr) != temp) - printk("%s: Warning -- the skbuff addresses do not match" - " in yellowfin_rx: %p vs. %p / %p.\n", dev->name, - bus_to_virt(lp->rx_ring[entry].addr), + char *temp = skb_put(skb = yp->rx_skbuff[entry], pkt_len); +#ifndef final_verison /* Remove after testing. */ + if (bus_to_virt(yp->rx_ring[entry].addr) != temp) + printk(KERN_WARNING "%s: Warning -- the skbuff addresses " + "do not match in yellowfin_rx: %p vs. %p / %p.\n", + dev->name, bus_to_virt(yp->rx_ring[entry].addr), skb->head, temp); - rx_in_place = 1; - lp->rx_skbuff[entry] = newskb; - newskb->dev = dev; - skb_reserve(newskb, 2); /* 16 byte align IP header */ - lp->rx_ring[entry].addr = virt_to_bus(newskb->tail); - } else - skb = DEV_ALLOC_SKB(pkt_len + 2); - memory_squeeze: - if (skb == NULL) { - printk("%s: Memory squeeze, deferring packet.\n", dev->name); - /* todo: Check that at least two ring entries are free. - If not, free one and mark stats->rx_dropped++. */ - break; - } - skb->dev = dev; - if (! rx_in_place) { +#endif + yp->rx_skbuff[entry] = NULL; + } else { + skb = dev_alloc_skb(pkt_len + 2); + if (skb == NULL) + break; + skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the data fields */ +#if 1 + eth_copy_and_sum(skb, bus_to_virt(yp->rx_ring[entry].addr), + pkt_len, 0); + skb_put(skb, pkt_len); +#else memcpy(skb_put(skb, pkt_len), - bus_to_virt(lp->rx_ring[entry].addr), pkt_len); + bus_to_virt(yp->rx_ring[entry].addr), pkt_len); +#endif } -#if LINUX_VERSION_CODE > 0x10300 skb->protocol = eth_type_trans(skb, dev); -#else - skb->len = pkt_len; -#endif netif_rx(skb); - lp->stats.rx_packets++; + dev->last_rx = jiffies; + yp->stats.rx_packets++; } + entry = (++yp->cur_rx) % RX_RING_SIZE; + yp->rx_head_desc = &yp->rx_ring[entry]; + } - /* Mark this entry as being the end-of-list, and the prior entry - as now valid. */ - lp->rx_ring[entry].cmd = CMD_STOP; - yp->rx_ring[entry].status = 0; - { - int prev_entry = entry - 1; - if (prev_entry < 0) - lp->rx_ring[RX_RING_SIZE - 1].cmd = - CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS; - else - lp->rx_ring[prev_entry].cmd = CMD_RX_BUF | INTR_ALWAYS; + /* Refill the Rx ring buffers. */ + for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) { + struct sk_buff *skb; + entry = yp->dirty_rx % RX_RING_SIZE; + if (yp->rx_skbuff[entry] == NULL) { + skb = dev_alloc_skb(yp->rx_buf_sz); + if (skb == NULL) + break; /* Better luck next round. */ + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + yp->rx_ring[entry].addr = virt_to_bus(skb->tail); + yp->rx_skbuff[entry] = skb; } - entry = (++lp->cur_rx) % RX_RING_SIZE; + yp->rx_ring[entry].cmd = CMD_STOP; + yp->rx_ring[entry].status = 0; /* Clear complete bit. */ + if (entry != 0) + yp->rx_ring[entry - 1].cmd = CMD_RX_BUF | INTR_ALWAYS; + else + yp->rx_ring[RX_RING_SIZE - 1].cmd = + CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS; } - /* todo: restart Rx engine if stopped. For now we just make the Rx ring - large enough to avoid this. */ return 0; } -static int -yellowfin_close(struct device *dev) +static void yellowfin_error(struct device *dev, int intr_status) +{ + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + + printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", + dev->name, intr_status); + /* Hmmmmm, it's not clear what to do here. */ + if (intr_status & (IntrTxPCIErr | IntrTxPCIFault)) + yp->stats.tx_errors++; + if (intr_status & (IntrRxPCIErr | IntrRxPCIFault)) + yp->stats.rx_errors++; +} + +static int yellowfin_close(struct device *dev) { - int ioaddr = dev->base_addr; + long ioaddr = dev->base_addr; struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; int i; @@ -1096,10 +1204,10 @@ dev->tbusy = 1; if (yellowfin_debug > 1) { - printk("%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n", + printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n", dev->name, inw(ioaddr + TxStatus), - inw(ioaddr + RxStatus), inl(ioaddr + IntrStatus)); - printk("%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", + inw(ioaddr + RxStatus), inw(ioaddr + IntrStatus)); + printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx); } @@ -1112,8 +1220,9 @@ del_timer(&yp->timer); +#ifdef __i386__ if (yellowfin_debug > 2) { - printk("\n Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring)); + printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring)); for (i = 0; i < TX_RING_SIZE*2; i++) printk(" %c #%d desc. %4.4x %4.4x %8.8x %8.8x %4.4x %4.4x.\n", inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', @@ -1121,20 +1230,20 @@ yp->tx_ring[i].request_cnt, yp->tx_ring[i].addr, yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_cnt, yp->tx_ring[i].status); - printk(" Tx status %p:\n", yp->tx_status); + printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); for (i = 0; i < TX_RING_SIZE; i++) printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n", i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); - printk("\n Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring)); + printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring)); for (i = 0; i < RX_RING_SIZE; i++) { - printk(" %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n", + printk(KERN_DEBUG " %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n", inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ', i, yp->rx_ring[i].cmd, yp->rx_ring[i].request_cnt, yp->rx_ring[i].addr, yp->rx_ring[i].result_cnt, yp->rx_ring[i].status); - if (yellowfin_debug > 5) { + if (yellowfin_debug > 6) { if (*(u8*)yp->rx_ring[i].addr != 0x69) { int j; for (j = 0; j < 0x50; j++) @@ -1144,13 +1253,9 @@ } } } +#endif /* __i386__ debugging only */ -#ifdef SA_SHIRQ free_irq(dev->irq, dev); -#else - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; -#endif /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { @@ -1160,19 +1265,19 @@ #if LINUX_VERSION_CODE < 0x20100 yp->rx_skbuff[i]->free = 1; #endif - dev_kfree_skb(yp->rx_skbuff[i]); + DEV_FREE_SKB(yp->rx_skbuff[i]); } yp->rx_skbuff[i] = 0; } for (i = 0; i < TX_RING_SIZE; i++) { if (yp->tx_skbuff[i]) - dev_kfree_skb(yp->tx_skbuff[i]); + DEV_FREE_SKB(yp->tx_skbuff[i]); yp->tx_skbuff[i] = 0; } #ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ if (yellowfin_debug > 0) { - printk("%s: Received %d frames that we should not have.\n", + printk(KERN_DEBUG "%s: Received %d frames that we should not have.\n", dev->name, bogus_rx); } #endif @@ -1181,8 +1286,7 @@ return 0; } -static struct enet_statistics * -yellowfin_get_stats(struct device *dev) +static struct enet_statistics *yellowfin_get_stats(struct device *dev) { struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; return &yp->stats; @@ -1194,6 +1298,7 @@ N.B. Do not use for bulk data, use a table-based routine instead. This is common code and should be moved to net/core/crc.c */ static unsigned const ethernet_polynomial_le = 0xedb88320U; + static inline unsigned ether_crc_le(int length, unsigned char *data) { unsigned int crc = 0xffffffff; /* Initial value. */ @@ -1212,25 +1317,20 @@ } -static void -#ifdef NEW_MULTICAST -set_rx_mode(struct device *dev) -#else -static void set_rx_mode(struct device *dev, int num_addrs, void *addrs); -#endif +static void set_rx_mode(struct device *dev) { - int ioaddr = dev->base_addr; + struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv; + long ioaddr = dev->base_addr; u16 cfg_value = inw(ioaddr + Cnfg); /* Stop the Rx process to change any value. */ outw(cfg_value & ~0x1000, ioaddr + Cnfg); if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ /* Unconditionally log net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); outw(0x000F, ioaddr + AddrMode); } else if ((dev->mc_count > 64) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well, or accept all multicasts. */ - printk("%s: Set all-multicast mode.\n", dev->name); outw(0x000B, ioaddr + AddrMode); } else if (dev->mc_count > 0) { /* Must use the multicast hash table. */ struct dev_mc_list *mclist; @@ -1241,49 +1341,67 @@ i++, mclist = mclist->next) { /* Due to a bug in the early chip versions, multiple filter slots must be set for each address. */ - set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f, - hash_table); - set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f, - hash_table); - set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f, - hash_table); + if (yp->chip_id == 0) { + set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f, + hash_table); + } set_bit((ether_crc_le(6, mclist->dmi_addr) >> 3) & 0x3f, hash_table); } /* Copy the hash table to the chip. */ for (i = 0; i < 4; i++) outw(hash_table[i], ioaddr + HashTbl + i*2); - printk("%s: Set multicast mode.\n", dev->name); outw(0x0003, ioaddr + AddrMode); } else { /* Normal, unicast/broadcast-only mode. */ - printk("%s: Set unicast mode.\n", dev->name); outw(0x0001, ioaddr + AddrMode); } /* Restart the Rx process. */ outw(cfg_value | 0x1000, ioaddr + Cnfg); } + +#ifdef HAVE_PRIVATE_IOCTL +static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) +{ + long ioaddr = dev->base_addr; + u16 *data = (u16 *)&rq->ifr_data; + + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = ((struct yellowfin_private *)dev->priv)->phys[0] & 0x1f; + /* Fall Through */ + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + if (!suser()) + return -EPERM; + mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); + return 0; + default: + return -EOPNOTSUPP; + } +} +#endif /* HAVE_PRIVATE_IOCTL */ + #ifdef MODULE /* An additional parameter that may be passed in... */ static int debug = -1; -int -init_module(void) +int init_module(void) { - int cards_found; - if (debug >= 0) yellowfin_debug = debug; - root_yellowfin_dev = NULL; - cards_found = yellowfin_probe(0); - - return cards_found ? 0 : -ENODEV; + return yellowfin_probe(0); } -void -cleanup_module(void) +void cleanup_module(void) { struct device *next_dev; @@ -1301,7 +1419,9 @@ /* * Local variables: - * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c" + * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * compile-command-alphaLX: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED" + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 diff -u --recursive --new-file v2.1.127/linux/drivers/net/z85230.c linux/drivers/net/z85230.c --- v2.1.127/linux/drivers/net/z85230.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/net/z85230.c Sun Nov 8 13:48:07 1998 @@ -391,9 +391,12 @@ if(chan->rxdma_on) { /* Special condition check only */ - u8 r7=read_zsreg(chan, R7); - u8 r6=read_zsreg(chan, R6); - u8 status=read_zsreg(chan, R1); + u8 status; + + read_zsreg(chan, R7); + read_zsreg(chan, R6); + + status=read_zsreg(chan, R1); if(status&END_FR) { z8530_rx_done(chan); /* Fire up the next one */ diff -u --recursive --new-file v2.1.127/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c --- v2.1.127/linux/drivers/pci/pcisyms.c Wed May 20 19:10:39 1998 +++ linux/drivers/pci/pcisyms.c Sun Nov 8 13:48:07 1998 @@ -28,8 +28,10 @@ EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_set_master); +#ifdef CONFIG_PROC_FS EXPORT_SYMBOL(pci_proc_attach_device); EXPORT_SYMBOL(pci_proc_detach_device); +#endif /* Backward compatibility */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.127/linux/drivers/scsi/Config.in Sun Nov 8 14:03:02 1998 +++ linux/drivers/scsi/Config.in Sun Nov 8 13:50:46 1998 @@ -48,6 +48,11 @@ int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16 fi dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI +if [ "$CONFIG_MCA" = "y" ]; then + if [ "$CONFIG_SCSI" = "y" ]; then + bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS + fi +fi dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI if [ "$CONFIG_PARPORT" != "n" ]; then diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.1.127/linux/drivers/scsi/Makefile Fri Oct 9 13:27:10 1998 +++ linux/drivers/scsi/Makefile Sun Nov 8 13:50:46 1998 @@ -486,6 +486,11 @@ endif endif +ifeq ($(CONFIG_SCSI_FD_MCS),y) +L_OBJS += fd_mcs.o +endif + + ifeq ($(CONFIG_SCSI_T128),y) L_OBJS += t128.o else diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/aic7xxx/sequencer.h linux/drivers/scsi/aic7xxx/sequencer.h --- v2.1.127/linux/drivers/scsi/aic7xxx/sequencer.h Fri Oct 23 22:01:21 1998 +++ linux/drivers/scsi/aic7xxx/sequencer.h Sun Nov 8 13:20:14 1998 @@ -36,8 +36,10 @@ * $Id: sequencer.h,v 1.3 1997/09/27 19:37:31 gibbs Exp $ */ +#ifdef __LITTLE_ENDIAN_BITFIELD struct ins_format1 { - unsigned int immediate : 8, + unsigned int + immediate : 8, source : 9, destination : 9, ret : 1, @@ -46,7 +48,8 @@ }; struct ins_format2 { - unsigned int shift_control : 8, + unsigned int + shift_control : 8, source : 9, destination : 9, ret : 1, @@ -55,12 +58,43 @@ }; struct ins_format3 { - unsigned int immediate : 8, + unsigned int + immediate : 8, source : 9, address : 10, opcode : 4, parity : 1; }; +#elif defined(__BIG_ENDIAN_BITFIELD) +struct ins_format1 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + immediate : 8; +}; + +struct ins_format2 { + unsigned int + parity : 1, + opcode : 4, + ret : 1, + destination : 9, + source : 9, + shift_control : 8; +}; + +struct ins_format3 { + unsigned int + parity : 1, + opcode : 4, + address : 10, + source : 9, + immediate : 8; +}; +#endif union ins_formats { struct ins_format1 format1; diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.1.127/linux/drivers/scsi/aic7xxx.c Sun Nov 8 14:03:02 1998 +++ linux/drivers/scsi/aic7xxx.c Tue Nov 10 15:38:38 1998 @@ -304,13 +304,18 @@ * #define AIC7XXX_VERBOSE_DEBUGGING */ -#ifdef MODULE +#if defined(MODULE) || defined(PCMCIA) #include #endif +#if defined(PCMCIA) +# undef MODULE +#endif + #include #include #include +#include #include #include #include @@ -349,7 +354,7 @@ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -#define AIC7XXX_C_VERSION "5.1.3" +#define AIC7XXX_C_VERSION "5.1.4" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -683,12 +688,14 @@ #define CFDISC 0x0010 /* enable disconnection */ #define CFWIDEB 0x0020 /* wide bus device (wide card) */ #define CFSYNCHISULTRA 0x0040 /* CFSYNC is an ultra offset */ -/* UNUSED 0x0080 */ +#define CFNEWULTRAFORMAT 0x0080 /* Use the Ultra2 SEEPROM format */ #define CFSTART 0x0100 /* send start unit SCSI command */ #define CFINCBIOS 0x0200 /* include in BIOS scan */ #define CFRNFOUND 0x0400 /* report even if not found */ #define CFMULTILUN 0x0800 /* probe mult luns in BIOS scan */ -/* UNUSED 0xF000 */ +#define CFWBCACHEYES 0x4000 /* Enable W-Behind Cache on drive */ +#define CFWBCACHENC 0xc000 /* Don't change W-Behind Cache */ +/* UNUSED 0x3000 */ unsigned short device_flags[16]; /* words 0-15 */ /* @@ -1481,8 +1488,8 @@ static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd); static void aic7xxx_print_card(struct aic7xxx_host *p); static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p); -#ifdef AIC7XXX_VERBOSE_DEBUGGING static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded); +#ifdef AIC7XXX_VERBOSE_DEBUGGING static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer); #endif @@ -1544,26 +1551,6 @@ #endif } -static void -aic_outsb(struct aic7xxx_host *p, long port, unsigned char *valp, size_t size) -{ -#ifdef MMAPIO - if(p->maddr) - { - int i; - for (i=0; i < size; i++) - { - p->maddr[port] = valp[i]; - } - mb(); - } - else - outsb(p->base + port, valp, size); -#else - outsb(p->base + port, valp, size); -#endif -} - /*+F************************************************************************* * Function: * aic7xxx_setup @@ -1752,7 +1739,9 @@ static inline void restart_sequencer(struct aic7xxx_host *p) { - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE, SEQCTL); } /* @@ -1831,6 +1820,8 @@ instr = *(union ins_formats*) &seqprog[instrptr * 4]; + instr.integer = le32_to_cpu(instr.integer); + fmt1_ins = &instr.format1; fmt3_ins = NULL; @@ -1926,7 +1917,10 @@ (fmt1_ins->opcode << 25); } } - aic_outsb(p, SEQRAM, instr.bytes, 4); + aic_outb(p, (instr.integer & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 8) & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 16) & 0xff), SEQRAM); + aic_outb(p, ((instr.integer >> 24) & 0xff), SEQRAM); break; default: @@ -1976,18 +1970,21 @@ downloaded++; } - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE | FAILDIS, SEQCTL); + unpause_sequencer(p, TRUE); + mdelay(1); + pause_sequencer(p); + aic_outb(p, FASTMODE, SEQCTL); if (aic7xxx_verbose & VERBOSE_PROBE) { printk(" %d instructions downloaded\n", downloaded); } -#ifdef AIC7XXX_VERBOSE_DEBUGGING if (aic7xxx_dump_sequencer) aic7xxx_print_sequencer(p, downloaded); -#endif } -#ifdef AIC7XXX_VERBOSE_DEBUGGING /*+F************************************************************************* * Function: * aic7xxx_print_sequencer @@ -2022,10 +2019,15 @@ else printk(" "); } - aic_outb(p, FASTMODE|SEQRESET, SEQCTL); + aic_outb(p, 0, SEQADDR0); + aic_outb(p, 0, SEQADDR1); + aic_outb(p, FASTMODE | FAILDIS, SEQCTL); + unpause_sequencer(p, TRUE); + mdelay(1); + pause_sequencer(p); + aic_outb(p, FASTMODE, SEQCTL); printk("\n"); } -#endif /*+F************************************************************************* * Function: @@ -4147,8 +4149,10 @@ #endif for(i=0; idev_timer[i]) ) + if ( timer_pending(&p->dev_timer[i]) && + time_before_eq(p->dev_timer[i].expires, jiffies) ) { + del_timer(&p->dev_timer[i]); p->dev_temp_queue_depth[i] = p->dev_max_queue_depth[i]; j = 0; while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) && @@ -5498,7 +5502,7 @@ { unsigned char lastbyte; unsigned char phasemis; - int done; + int done = FALSE; switch(p->msg_type) { @@ -7548,6 +7552,7 @@ p->host_no, p->mbase, (unsigned long)p->maddr); } +#ifdef CONFIG_PCI /* * Now that we know our instance number, we can set the flags we need to * force termination if need be. @@ -7587,6 +7592,7 @@ #endif } } +#endif /* * That took care of devconfig and stpwlev, now for the actual termination @@ -7638,19 +7644,6 @@ } /* - * Load the sequencer program, then re-enable the board - - * resetting the AIC-7770 disables it, leaving the lights - * on with nobody home. - */ - aic7xxx_loadseq(p); - - if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 ) - { - aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */ - } - aic_outb(p, aic_inb(p, SBLKCTL) & ~AUTOFLUSHDIS, SBLKCTL); - - /* * Clear out any possible pending interrupts. */ aic7xxx_clear_intstat(p); @@ -7852,6 +7845,18 @@ */ aic7xxx_allocate_scb(p); + /* + * Load the sequencer program, then re-enable the board - + * resetting the AIC-7770 disables it, leaving the lights + * on with nobody home. + */ + aic7xxx_loadseq(p); + + if ( (p->chip & AHC_CHIPID_MASK) == AHC_AIC7770 ) + { + aic_outb(p, ENABLE, BCTL); /* Enable the boards BUS drivers. */ + } + if ( !(aic7xxx_no_reset) ) { if (p->features & AHC_TWIN) @@ -8254,9 +8259,10 @@ { for (i = 0; i < max_targets; i++) { - if( (p->features & AHC_ULTRA) && - !(sc->adapter_control & CFULTRAEN) && - (sc->device_flags[i] & CFSYNCHISULTRA) ) + if( ((p->features & AHC_ULTRA) && + !(sc->adapter_control & CFULTRAEN) && + (sc->device_flags[i] & CFSYNCHISULTRA)) || + (sc->device_flags[i] & CFNEWULTRAFORMAT) ) { p->flags |= AHC_NEWEEPROM_FMT; break; @@ -8333,6 +8339,15 @@ { p->ultraenb |= mask; } + else if (sc->device_flags[i] & CFNEWULTRAFORMAT) + { + if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 ) + { + sc->device_flags[i] &= ~CFXFER; + sc->device_flags[i] |= CFSYNCHISULTRA; + p->ultraenb |= mask; + } + } } else if (sc->adapter_control & CFULTRAEN) { @@ -8480,8 +8495,10 @@ struct aic7xxx_host *current_p = NULL; struct aic7xxx_host *list_p = NULL; int found = 0; +#if defined(__i386__) || defined(__alpha__) ahc_flag_type flags = 0; int type; +#endif unsigned char sxfrctl1; #if defined(__i386__) || defined(__alpha__) unsigned char hcntrl, hostconf; diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c --- v2.1.127/linux/drivers/scsi/blz1230.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/blz1230.c Wed Nov 11 11:50:00 1998 @@ -50,7 +50,7 @@ volatile unsigned char cmd_buffer[16]; /* This is where all commands are put - * before they are trasfered to the ESP chip + * before they are transfered to the ESP chip * via PIO. */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c --- v2.1.127/linux/drivers/scsi/blz2060.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/blz2060.c Wed Nov 11 11:50:00 1998 @@ -50,7 +50,7 @@ volatile unsigned char cmd_buffer[16]; /* This is where all commands are put - * before they are trasfered to the ESP chip + * before they are transfered to the ESP chip * via PIO. */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c --- v2.1.127/linux/drivers/scsi/cyberstorm.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/cyberstorm.c Wed Nov 11 11:50:00 1998 @@ -59,7 +59,7 @@ volatile unsigned char cmd_buffer[16]; /* This is where all commands are put - * before they are trasfered to the ESP chip + * before they are transfered to the ESP chip * via PIO. */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c --- v2.1.127/linux/drivers/scsi/fastlane.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/fastlane.c Wed Nov 11 11:50:00 1998 @@ -72,7 +72,7 @@ volatile unsigned char cmd_buffer[16]; /* This is where all commands are put - * before they are trasfered to the ESP chip + * before they are transfered to the ESP chip * via PIO. */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/fd_mcs.c linux/drivers/scsi/fd_mcs.c --- v2.1.127/linux/drivers/scsi/fd_mcs.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/fd_mcs.c Sun Nov 8 13:50:47 1998 @@ -0,0 +1,1481 @@ +/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver + * + * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net) + * + * This driver is cloned from fdomain.* to specifically support + * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s + * also equipped with IBM Fast SCSI Adapter/A which is an OEM + * of MCS 700. + * + * This driver also supports Reply SB16/SCSI card (the SCSI part). + * + * What makes this driver different is that this driver is MCA only + * and it supports multiple adapters in the same system, IRQ + * sharing, some driver statistics, and maps highest SCSI id to sda. + * All cards are auto-detected. + * + * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4 + * + * LILO command-line options: + * fd_mcs=[,] + * + * ******************************************************** + * Please see Copyrights/Comments in fdomain.* for credits. + * Following is from fdomain.c for acknowledgement: + * + * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu + * Revised: Wed Oct 2 11:10:55 1996 by r.faith@ieee.org + * Author: Rickard E. Faith, faith@cs.unc.edu + * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith + * + * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $ + + * 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, 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. + + ************************************************************************** + + NOTES ON USER DEFINABLE OPTIONS: + + DEBUG: This turns on the printing of various debug information. + + ENABLE_PARITY: This turns on SCSI parity checking. With the current + driver, all attached devices must support SCSI parity. If none of your + devices support parity, then you can probably get the driver to work by + turning this option off. I have no way of testing this, however, and it + would appear that no one ever uses this option. + + FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the + 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by + the SCSI device, an interrupt will be raised. Therefore, this could be as + low as 0, or as high as 16. Note, however, that values which are too high + or too low seem to prevent any interrupts from occurring, and thereby lock + up the machine. I have found that 2 is a good number, but throughput may + be increased by changing this value to values which are close to 2. + Please let me know if you try any different values. + [*****Now a runtime option*****] + + RESELECTION: This is no longer an option, since I gave up trying to + implement it in version 4.x of this driver. It did not improve + performance at all and made the driver unstable (because I never found one + of the two race conditions which were introduced by the multiple + outstanding command code). The instability seems a very high price to pay + just so that you don't have to wait for the tape to rewind. If you want + this feature implemented, send me patches. I'll be happy to send a copy + of my (broken) driver to anyone who would like to see a copy. + + **************************************************************************/ + +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "fd_mcs.h" + +#define DRIVER_VERSION "v0.2 by ZP Gu" + +struct proc_dir_entry proc_scsi_fd_mcs = { + PROC_SCSI_FD_MCS, 6, "fd_mcs", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +}; + +/* START OF USER DEFINABLE OPTIONS */ + +#define DEBUG 0 /* Enable debugging output */ +#define ENABLE_PARITY 1 /* Enable SCSI Parity */ +#define DO_DETECT 0 /* Do device detection here (see scsi.c) */ + +/* END OF USER DEFINABLE OPTIONS */ + +#if DEBUG +#define EVERY_ACCESS 0 /* Write a line on every scsi access */ +#define ERRORS_ONLY 1 /* Only write a line if there is an error */ +#define DEBUG_DETECT 1 /* Debug fd_mcs_detect() */ +#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ +#define DEBUG_ABORT 1 /* Debug abort() routine */ +#define DEBUG_RESET 1 /* Debug reset() routine */ +#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ +#else +#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ +#define ERRORS_ONLY 0 +#define DEBUG_DETECT 0 +#define DEBUG_MESSAGES 0 +#define DEBUG_ABORT 0 +#define DEBUG_RESET 0 +#define DEBUG_RACE 0 +#endif + +/* Errors are reported on the line, so we don't need to report them again */ +#if EVERY_ACCESS +#undef ERRORS_ONLY +#define ERRORS_ONLY 0 +#endif + +#if ENABLE_PARITY +#define PARITY_MASK 0x08 +#else +#define PARITY_MASK 0x00 +#endif + +enum chip_type { + unknown = 0x00, + tmc1800 = 0x01, + tmc18c50 = 0x02, + tmc18c30 = 0x03, +}; + +enum { + in_arbitration = 0x02, + in_selection = 0x04, + in_other = 0x08, + disconnect = 0x10, + aborted = 0x20, + sent_ident = 0x40, +}; + +enum in_port_type { + Read_SCSI_Data = 0, + SCSI_Status = 1, + TMC_Status = 2, + FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ + Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ + LSB_ID_Code = 5, + MSB_ID_Code = 6, + Read_Loopback = 7, + SCSI_Data_NoACK = 8, + Interrupt_Status = 9, + Configuration1 = 10, + Configuration2 = 11, /* tmc18c50/tmc18c30 only */ + Read_FIFO = 12, + FIFO_Data_Count = 14 +}; + +enum out_port_type { + Write_SCSI_Data = 0, + SCSI_Cntl = 1, + Interrupt_Cntl = 2, + SCSI_Mode_Cntl = 3, + TMC_Cntl = 4, + Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ + Write_Loopback = 7, + IO_Control = 11, /* tmc18c30 only */ + Write_FIFO = 12 +}; + +struct fd_hostdata { + unsigned long _bios_base; + int _bios_major; + int _bios_minor; + volatile int _in_command; + Scsi_Cmnd *_current_SC; + enum chip_type _chip; + int _adapter_mask; + int _fifo_count; /* Number of 512 byte blocks before INTR */ + + char _adapter_name[64]; +#if DEBUG_RACE + volatile int _in_interrupt_flag; +#endif + + int _SCSI_Mode_Cntl_port; + int _FIFO_Data_Count_port; + int _Interrupt_Cntl_port; + int _Interrupt_Status_port; + int _Interrupt_Cond_port; + int _Read_FIFO_port; + int _Read_SCSI_Data_port; + int _SCSI_Cntl_port; + int _SCSI_Data_NoACK_port; + int _SCSI_Status_port; + int _TMC_Cntl_port; + int _TMC_Status_port; + int _Write_FIFO_port; + int _Write_SCSI_Data_port; + + int _FIFO_Size; /* = 0x2000; 8k FIFO for + pre-tmc18c30 chips */ + /* simple stats */ + int _Bytes_Read; + int _Bytes_Written; + int _INTR_Processed; +}; + +#define FD_MAX_HOSTS 3 /* enough? */ + +#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata) +#define bios_base (HOSTDATA(shpnt)->_bios_base) +#define bios_major (HOSTDATA(shpnt)->_bios_major) +#define bios_minor (HOSTDATA(shpnt)->_bios_minor) +#define in_command (HOSTDATA(shpnt)->_in_command) +#define current_SC (HOSTDATA(shpnt)->_current_SC) +#define chip (HOSTDATA(shpnt)->_chip) +#define adapter_mask (HOSTDATA(shpnt)->_adapter_mask) +#define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count) +#define adapter_name (HOSTDATA(shpnt)->_adapter_name) +#if DEBUG_RACE +#define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag) +#endif +#define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port) +#define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port) +#define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port) +#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port) +#define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port) +#define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port) +#define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port) +#define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port) +#define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port) +#define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port) +#define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port) +#define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port) +#define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port) +#define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port) +#define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size) +#define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read) +#define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written) +#define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed) + +struct fd_mcs_adapters_struct { + char* name; + int id; + enum chip_type fd_chip; + int fifo_size; + int fifo_count; +}; + +#define REPLY_ID 0x5137 + +static struct fd_mcs_adapters_struct fd_mcs_adapters[] = { + { "Future Domain SCSI Adapter MCS-700(18C50)", + 0x60e9, + tmc18c50, + 0x2000, + 4 }, + { "Future Domain SCSI Adapter MCS-600/700(TMC-1800)", + 0x6127, + tmc1800, + 0x2000, + 4 }, + { "Reply Sound Blaster/SCSI Adapter", + REPLY_ID, + tmc18c30, + 0x800, + 2 }, +}; + +#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct) + +static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs ); + +static unsigned long addresses[] = {0xc8000, 0xca000, 0xce000, 0xde000}; +static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; +static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; + +/* host information */ +static int found = 0; +static struct Scsi_Host *hosts[FD_MAX_HOSTS+1] = { NULL }; + +static int user_fifo_count = 0; +static int user_fifo_size = 0; + +void fd_mcs_setup( char *str, int *ints ) +{ + static int done_setup = 0; + + if (done_setup++ || ints[0] < 1 || ints[0] > 2 || + ints[1] < 1 || ints[1] > 16) { + printk( "fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n" ); + } + + user_fifo_count = ints[0] >= 1 ? ints[1] : 0; + user_fifo_size = ints[0] >= 2 ? ints[2] : 0; +} + +static void print_banner( struct Scsi_Host *shpnt ) +{ + printk( "scsi%d : ", shpnt->host_no); + + if (bios_base) { + printk( "BIOS at 0x%lX", bios_base); + } else { + printk( "No BIOS"); + } + + printk( ", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n", + shpnt->this_id, + chip == tmc18c50 ? "TMC-18C50" + : (chip == tmc18c30 ? "TMC-18C30" : + (chip == tmc1800 ? "TMC-1800" : "Unknown")), + shpnt->irq, + shpnt->io_port ); +} + + +static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */ +{ + do { + udelay(10*1000); + } while (--amount); +} + +inline static void fd_mcs_make_bus_idle( struct Scsi_Host *shpnt ) +{ + outb( 0, SCSI_Cntl_port ); + outb( 0, SCSI_Mode_Cntl_port ); + if (chip == tmc18c50 || chip == tmc18c30) + outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ + else + outb( 0x01 | PARITY_MASK, TMC_Cntl_port ); +} + +int fd_mcs_detect( Scsi_Host_Template *tpnt ) +{ + int loop; + struct Scsi_Host *shpnt; + + /* get id, port, bios, irq */ + int slot; + u_char pos2, pos3, pos4; + int id, port, irq; + unsigned long bios; + + /* if not MCA machine, return */ + if (!MCA_bus) + return 0; + + /* changeable? */ + id = 7; + + for( loop = 0; loop < FD_BRDS; loop++ ) { + slot = 0; + while ( MCA_NOTFOUND != + (slot = mca_find_adapter(fd_mcs_adapters[loop].id, + slot)) ) { + + /* if we get this far, an adapter has been detected and is + enabled */ + + printk("scsi : %s at slot %d\n", + fd_mcs_adapters[loop].name, slot + 1 ); + + pos2 = mca_read_stored_pos( slot, 2 ); + pos3 = mca_read_stored_pos( slot, 3 ); + pos4 = mca_read_stored_pos( slot, 4); + + /* ready for next probe */ + slot++; + + if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */ + static int reply_irq[] = {10, 11, 14, 15}; + + bios = 0; /* no bios */ + + if (pos2 & 0x2) + port = ports[pos4 & 0x3]; + else + continue; + + /* can't really disable it, same as irq=10 */ + irq = reply_irq[((pos4 >> 2) & 0x1) + 2*((pos4 >> 4) & 0x1)]; + } else { + bios = addresses[pos2 >> 6]; + port = ports[(pos2 >> 4) & 0x03]; + irq = ints[(pos2 >> 1) & 0x07]; + } + + if (irq) { + /* claim the slot */ + mca_set_adapter_name( slot-1, fd_mcs_adapters[loop].name ); + + /* check irq/region */ + if (check_region(port, 0x10) || + request_irq(irq, fd_mcs_intr, + SA_SHIRQ, "fd_mcs", hosts)) { + printk( "fd_mcs: check_region() || request_irq() failed, Skip it\n"); + + continue; + } + + /* register */ + if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) { + printk( "fd_mcs: scsi_register() failed\n"); + continue; + } + + /* request I/O region */ + request_region( port, 0x10, "fd_mcs" ); + + /* save name */ + strcpy(adapter_name, fd_mcs_adapters[loop].name); + + /* chip/fifo */ + chip = fd_mcs_adapters[loop].fd_chip; + /* use boot time value if available */ + FIFO_COUNT = + user_fifo_count?user_fifo_count:fd_mcs_adapters[loop].fifo_count; + FIFO_Size = + user_fifo_size?user_fifo_size:fd_mcs_adapters[loop].fifo_size; + +#ifdef NOT_USED + /* *************************************************** */ + /* Try to toggle 32-bit mode. This only + works on an 18c30 chip. (User reports + say this works, so we should switch to + it in the near future.) */ + outb( 0x80, port + IO_Control ); + if ((inb( port + Configuration2 ) & 0x80) == 0x80) { + outb( 0x00, port + IO_Control ); + if ((inb( port + Configuration2 ) & 0x80) == 0x00) { + chip = tmc18c30; + FIFO_Size = 0x800; /* 2k FIFO */ + + printk("FIRST: chip=%s, fifo_size=0x%x\n", + (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size); + } + } + + /* That should have worked, but appears to + have problems. Let's assume it is an + 18c30 if the RAM is disabled. */ + + if (inb( port + Configuration2 ) & 0x02) { + chip = tmc18c30; + FIFO_Size = 0x800; /* 2k FIFO */ + + printk("SECOND: chip=%s, fifo_size=0x%x\n", + (chip == tmc18c30)?"tmc18c30":"tmc18c50", FIFO_Size); + } + /* *************************************************** */ +#endif + +#if 0 + /* IBM/ANSI scsi scan ordering */ + /* Stick this back in when the scsi.c changes are there */ + shpnt->reverse_scan = 1; +#endif + + + /* saving info */ + hosts[found++] = shpnt; + + shpnt->this_id = id; + shpnt->irq = irq; + shpnt->io_port = port; + shpnt->n_io_port = 0x10; + + /* save */ + bios_base = bios; + adapter_mask = (1 << id); + + /* save more */ + SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl; + FIFO_Data_Count_port = port + FIFO_Data_Count; + Interrupt_Cntl_port = port + Interrupt_Cntl; + Interrupt_Status_port = port + Interrupt_Status; + Interrupt_Cond_port = port + Interrupt_Cond; + Read_FIFO_port = port + Read_FIFO; + Read_SCSI_Data_port = port + Read_SCSI_Data; + SCSI_Cntl_port = port + SCSI_Cntl; + SCSI_Data_NoACK_port = port + SCSI_Data_NoACK; + SCSI_Status_port = port + SCSI_Status; + TMC_Cntl_port = port + TMC_Cntl; + TMC_Status_port = port + TMC_Status; + Write_FIFO_port = port + Write_FIFO; + Write_SCSI_Data_port = port + Write_SCSI_Data; + + Bytes_Read = 0; + Bytes_Written = 0; + INTR_Processed = 0; + + /* say something */ + print_banner( shpnt ); + + /* reset */ + outb( 1, SCSI_Cntl_port ); + do_pause( 2 ); + outb( 0, SCSI_Cntl_port ); + do_pause( 115 ); + outb( 0, SCSI_Mode_Cntl_port ); + outb( PARITY_MASK, TMC_Cntl_port ); + /* done reset */ + +#if DO_DETECT + /* scan devices attached */ + { + const int buflen = 255; + int i, j, retcode; + Scsi_Cmnd SCinit; + unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; + unsigned char do_request_sense[] = { REQUEST_SENSE, + 0, 0, 0, buflen, 0 }; + unsigned char do_read_capacity[] = { READ_CAPACITY, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned char buf[buflen]; + + SCinit.request_buffer = SCinit.buffer = buf; + SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; + SCinit.use_sg = 0; + SCinit.lun = 0; + SCinit.host = shpnt; + + printk( "fd_mcs: detection routine scanning for devices:\n" ); + for (i = 0; i < 8; i++) { + if (i == shpnt->this_id) /* Skip host adapter */ + continue; + SCinit.target = i; + memcpy(SCinit.cmnd, do_request_sense, + sizeof(do_request_sense)); + retcode = fd_mcs_command(&SCinit); + if (!retcode) { + memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); + retcode = fd_mcs_command(&SCinit); + if (!retcode) { + printk( " SCSI ID %d: ", i ); + for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) + printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); + memcpy(SCinit.cmnd, do_read_capacity, + sizeof(do_read_capacity)); + retcode = fd_mcs_command(&SCinit); + if (!retcode) { + unsigned long blocks, size, capacity; + + blocks = (buf[0] << 24) | (buf[1] << 16) + | (buf[2] << 8) | buf[3]; + size = (buf[4] << 24) | (buf[5] << 16) | + (buf[6] << 8) | buf[7]; + capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; + + printk( "%lu MB (%lu byte blocks)\n", + ((capacity + 5L) / 10L), size ); + } + } + } + } + } +#endif + } + } + + if (found == FD_MAX_HOSTS) { + printk( "fd_mcs: detecting reached max=%d host adapters.\n", + FD_MAX_HOSTS); + break; + } + } + + return found; +} + +const char *fd_mcs_info(struct Scsi_Host *shpnt) +{ + return adapter_name; +} + +static int TOTAL_INTR = 0; + +/* + * inout : decides on the direction of the dataflow and the meaning of the + * variables + * buffer: If inout==FALSE data is being written to it else read from it + * *start: If inout==FALSE start of the valid data in the buffer + * offset: If inout==FALSE offset from the beginning of the imaginary file + * from which we start writing into the buffer + * length: If inout==FALSE max number of bytes to be written into the buffer + * else number of bytes in the buffer + */ +int fd_mcs_proc_info( char *buffer, char **start, off_t offset, + int length, int hostno, int inout ) +{ + struct Scsi_Host *shpnt; + int len = 0; + int i; + + if (inout) + return(-ENOSYS); + + *start = buffer + offset; + + for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++); + shpnt = hosts[i]; + + if (!shpnt) { + return(-ENOENT); + } else { + len += sprintf(buffer+len, "Future Domain MCS-600/700 Driver %s\n", + DRIVER_VERSION); + + len += sprintf(buffer+len, "HOST #%d: %s\n", + hostno, adapter_name); + + len += sprintf(buffer+len, "FIFO Size=0x%x, FIFO Count=%d\n", + FIFO_Size, FIFO_COUNT); + + len += sprintf(buffer+len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", + TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written); + } + + if ((len -= offset) <= 0) + return 0; + if (len > length) + len = length; + return len; +} + +static int fd_mcs_select(struct Scsi_Host *shpnt, int target ) +{ + int status; + unsigned long timeout; + + outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ + outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); + + /* Stop arbitration and enable parity */ + outb( PARITY_MASK, TMC_Cntl_port ); + + timeout = 350; /* 350mS -- because of timeouts + (was 250mS) */ + + do { + status = inb( SCSI_Status_port ); /* Read adapter status */ + if (status & 1) { /* Busy asserted */ + /* Enable SCSI Bus (on error, should make bus idle with 0) */ + outb( 0x80, SCSI_Cntl_port ); + return 0; + } + udelay(1000); /* wait one msec */ + } while (--timeout); + + /* Make bus idle */ + fd_mcs_make_bus_idle(shpnt); +#if EVERY_ACCESS + if (!target) printk( "Selection failed\n" ); +#endif +#if ERRORS_ONLY + if (!target) { + static int flag = 0; + + if (!flag) /* Skip first failure for all chips. */ + ++flag; + else + printk( "fd_mcs: Selection failed\n" ); + } +#endif + return 1; +} + +static void my_done( struct Scsi_Host *shpnt, int error ) +{ + if (in_command) { + in_command = 0; + outb( 0x00, Interrupt_Cntl_port ); + fd_mcs_make_bus_idle(shpnt); + current_SC->result = error; + current_SC->scsi_done( current_SC ); + } else { + panic( "fd_mcs: my_done() called outside of command\n" ); + } +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif +} + +/* only my_done needs to be protected */ +static void fd_mcs_intr( int irq, void *dev_id, struct pt_regs * regs ) +{ + unsigned long flags; + int status; + int done = 0; + unsigned data_count, tmp_count; + + int i = 0; + struct Scsi_Host *shpnt; + + TOTAL_INTR++; + + /* search for one adapter-response on shared interrupt */ + while ((shpnt = hosts[i++])) { + if ((inb(TMC_Status_port)) & 1) + break; + } + + /* return if some other device on this IRQ caused the interrupt */ + if (!shpnt) { + return; + } + + INTR_Processed++; + + outb( 0x00, Interrupt_Cntl_port ); + + /* Abort calls my_done, so we do nothing here. */ + if (current_SC->SCp.phase & aborted) { +#if DEBUG_ABORT + printk( "Interrupt after abort, ignoring\n" ); +#endif + /* return; */ + } + +#if DEBUG_RACE + ++in_interrupt_flag; +#endif + + if (current_SC->SCp.phase & in_arbitration) { + status = inb( TMC_Status_port ); /* Read adapter status */ + if (!(status & 0x02)) { +#if EVERY_ACCESS + printk( " AFAIL " ); +#endif + spin_lock_irqsave(&io_request_lock, flags); + my_done( shpnt, DID_BUS_BUSY << 16 ); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } + current_SC->SCp.phase = in_selection; + + outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); + + outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ + outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port ); + + /* Stop arbitration and enable parity */ + outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; + } else if (current_SC->SCp.phase & in_selection) { + status = inb( SCSI_Status_port ); + if (!(status & 0x01)) { + /* Try again, for slow devices */ + if (fd_mcs_select(shpnt, current_SC->target )) { +#if EVERY_ACCESS + printk( " SFAIL " ); +#endif + spin_lock_irqsave(&io_request_lock, flags); + my_done( shpnt, DID_NO_CONNECT << 16 ); + spin_unlock_irqrestore(&io_request_lock, flags); + return; + } else { +#if EVERY_ACCESS + printk( " AltSel " ); +#endif + /* Stop arbitration and enable parity */ + outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); + } + } + current_SC->SCp.phase = in_other; + outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); + outb( 0x80, SCSI_Cntl_port ); +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; + } + + /* current_SC->SCp.phase == in_other: this is the body of the routine */ + + status = inb( SCSI_Status_port ); + + if (status & 0x10) { /* REQ */ + + switch (status & 0x0e) { + + case 0x08: /* COMMAND OUT */ + outb( current_SC->cmnd[current_SC->SCp.sent_command++], + Write_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "CMD = %x,", + current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); +#endif + break; + case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ + if (chip != tmc1800 && !current_SC->SCp.have_data_in) { + current_SC->SCp.have_data_in = -1; + outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + } + break; + case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ + if (chip != tmc1800 && !current_SC->SCp.have_data_in) { + current_SC->SCp.have_data_in = 1; + outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + } + break; + case 0x0c: /* STATUS IN */ + current_SC->SCp.Status = inb( Read_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "Status = %x, ", current_SC->SCp.Status ); +#endif +#if ERRORS_ONLY + if (current_SC->SCp.Status + && current_SC->SCp.Status != 2 + && current_SC->SCp.Status != 8) { + printk( "ERROR fd_mcs: target = %d, command = %x, status = %x\n", + current_SC->target, + current_SC->cmnd[0], + current_SC->SCp.Status ); + } +#endif + break; + case 0x0a: /* MESSAGE OUT */ + outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ + break; + case 0x0e: /* MESSAGE IN */ + current_SC->SCp.Message = inb( Read_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "Message = %x, ", current_SC->SCp.Message ); +#endif + if (!current_SC->SCp.Message) ++done; +#if DEBUG_MESSAGES || EVERY_ACCESS + if (current_SC->SCp.Message) { + printk( "fd_mcs: message = %x\n", current_SC->SCp.Message ); + } +#endif + break; + } + } + + if (chip == tmc1800 + && !current_SC->SCp.have_data_in + && (current_SC->SCp.sent_command + >= current_SC->cmd_len)) { + /* We have to get the FIFO direction + correct, so I've made a table based + on the SCSI Standard of which commands + appear to require a DATA OUT phase. + */ + /* + p. 94: Command for all device types + CHANGE DEFINITION 40 DATA OUT + COMPARE 39 DATA OUT + COPY 18 DATA OUT + COPY AND VERIFY 3a DATA OUT + INQUIRY 12 + LOG SELECT 4c DATA OUT + LOG SENSE 4d + MODE SELECT (6) 15 DATA OUT + MODE SELECT (10) 55 DATA OUT + MODE SENSE (6) 1a + MODE SENSE (10) 5a + READ BUFFER 3c + RECEIVE DIAGNOSTIC RESULTS 1c + REQUEST SENSE 03 + SEND DIAGNOSTIC 1d DATA OUT + TEST UNIT READY 00 + WRITE BUFFER 3b DATA OUT + + p.178: Commands for direct-access devices (not listed on p. 94) + FORMAT UNIT 04 DATA OUT + LOCK-UNLOCK CACHE 36 + PRE-FETCH 34 + PREVENT-ALLOW MEDIUM REMOVAL 1e + READ (6)/RECEIVE 08 + READ (10) 3c + READ CAPACITY 25 + READ DEFECT DATA (10) 37 + READ LONG 3e + REASSIGN BLOCKS 07 DATA OUT + RELEASE 17 + RESERVE 16 DATA OUT + REZERO UNIT/REWIND 01 + SEARCH DATA EQUAL (10) 31 DATA OUT + SEARCH DATA HIGH (10) 30 DATA OUT + SEARCH DATA LOW (10) 32 DATA OUT + SEEK (6) 0b + SEEK (10) 2b + SET LIMITS (10) 33 + START STOP UNIT 1b + SYNCHRONIZE CACHE 35 + VERIFY (10) 2f + WRITE (6)/PRINT/SEND 0a DATA OUT + WRITE (10)/SEND 2a DATA OUT + WRITE AND VERIFY (10) 2e DATA OUT + WRITE LONG 3f DATA OUT + WRITE SAME 41 DATA OUT ? + + p. 261: Commands for sequential-access devices (not previously listed) + ERASE 19 + LOAD UNLOAD 1b + LOCATE 2b + READ BLOCK LIMITS 05 + READ POSITION 34 + READ REVERSE 0f + RECOVER BUFFERED DATA 14 + SPACE 11 + WRITE FILEMARKS 10 ? + + p. 298: Commands for printer devices (not previously listed) + ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) ***** + SLEW AND PRINT 0b DATA OUT -- same as seek + STOP PRINT 1b + SYNCHRONIZE BUFFER 10 + + p. 315: Commands for processor devices (not previously listed) + + p. 321: Commands for write-once devices (not previously listed) + MEDIUM SCAN 38 + READ (12) a8 + SEARCH DATA EQUAL (12) b1 DATA OUT + SEARCH DATA HIGH (12) b0 DATA OUT + SEARCH DATA LOW (12) b2 DATA OUT + SET LIMITS (12) b3 + VERIFY (12) af + WRITE (12) aa DATA OUT + WRITE AND VERIFY (12) ae DATA OUT + + p. 332: Commands for CD-ROM devices (not previously listed) + PAUSE/RESUME 4b + PLAY AUDIO (10) 45 + PLAY AUDIO (12) a5 + PLAY AUDIO MSF 47 + PLAY TRACK RELATIVE (10) 49 + PLAY TRACK RELATIVE (12) a9 + READ HEADER 44 + READ SUB-CHANNEL 42 + READ TOC 43 + + p. 370: Commands for scanner devices (not previously listed) + GET DATA BUFFER STATUS 34 + GET WINDOW 25 + OBJECT POSITION 31 + SCAN 1b + SET WINDOW 24 DATA OUT + + p. 391: Commands for optical memory devices (not listed) + ERASE (10) 2c + ERASE (12) ac + MEDIUM SCAN 38 DATA OUT + READ DEFECT DATA (12) b7 + READ GENERATION 29 + READ UPDATED BLOCK 2d + UPDATE BLOCK 3d DATA OUT + + p. 419: Commands for medium changer devices (not listed) + EXCHANGE MEDIUM 46 + INITIALIZE ELEMENT STATUS 07 + MOVE MEDIUM a5 + POSITION TO ELEMENT 2b + READ ELEMENT STATUS b8 + REQUEST VOL. ELEMENT ADDRESS b5 + SEND VOLUME TAG b6 DATA OUT + + p. 454: Commands for communications devices (not listed previously) + GET MESSAGE (6) 08 + GET MESSAGE (10) 28 + GET MESSAGE (12) a8 + */ + + switch (current_SC->cmnd[0]) { + case CHANGE_DEFINITION: case COMPARE: case COPY: + case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: + case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: + + case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: + case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: + case WRITE_6: case WRITE_10: case WRITE_VERIFY: + case 0x3f: case 0x41: + + case 0xb1: case 0xb0: case 0xb2: + case 0xaa: case 0xae: + + case 0x24: + + case 0x38: case 0x3d: + + case 0xb6: + + case 0xea: /* alternate number for WRITE LONG */ + + current_SC->SCp.have_data_in = -1; + outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + break; + + case 0x00: + default: + + current_SC->SCp.have_data_in = 1; + outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + break; + } + } + + if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ + while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) { +#if EVERY_ACCESS + printk( "DC=%d, ", data_count ) ; +#endif + if (data_count > current_SC->SCp.this_residual) + data_count = current_SC->SCp.this_residual; + if (data_count > 0) { +#if EVERY_ACCESS + printk( "%d OUT, ", data_count ); +#endif + if (data_count == 1) { + Bytes_Written++; + + outb( *current_SC->SCp.ptr++, Write_FIFO_port ); + --current_SC->SCp.this_residual; + } else { + data_count >>= 1; + tmp_count = data_count << 1; + outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count ); + current_SC->SCp.ptr += tmp_count; + Bytes_Written += tmp_count; + current_SC->SCp.this_residual -= tmp_count; + } + } + if (!current_SC->SCp.this_residual) { + if (current_SC->SCp.buffers_residual) { + --current_SC->SCp.buffers_residual; + ++current_SC->SCp.buffer; + current_SC->SCp.ptr = current_SC->SCp.buffer->address; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + } else + break; + } + } + } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ + while ((data_count = inw( FIFO_Data_Count_port )) > 0) { +#if EVERY_ACCESS + printk( "DC=%d, ", data_count ); +#endif + if (data_count > current_SC->SCp.this_residual) + data_count = current_SC->SCp.this_residual; + if (data_count) { +#if EVERY_ACCESS + printk( "%d IN, ", data_count ); +#endif + if (data_count == 1) { + Bytes_Read++; + *current_SC->SCp.ptr++ = inb( Read_FIFO_port ); + --current_SC->SCp.this_residual; + } else { + data_count >>= 1; /* Number of words */ + tmp_count = data_count << 1; + insw( Read_FIFO_port, current_SC->SCp.ptr, data_count ); + current_SC->SCp.ptr += tmp_count; + Bytes_Read += tmp_count; + current_SC->SCp.this_residual -= tmp_count; + } + } + if (!current_SC->SCp.this_residual + && current_SC->SCp.buffers_residual) { + --current_SC->SCp.buffers_residual; + ++current_SC->SCp.buffer; + current_SC->SCp.ptr = current_SC->SCp.buffer->address; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + } + } + } + + if (done) { +#if EVERY_ACCESS + printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in ); +#endif + +#if ERRORS_ONLY + if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { + if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) { + unsigned char key; + unsigned char code; + unsigned char qualifier; + + key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) + & 0x0f; + code = (unsigned char)(*((char *)current_SC->request_buffer + 12)); + qualifier = (unsigned char)(*((char *)current_SC->request_buffer + + 13)); + + if (key != UNIT_ATTENTION + && !(key == NOT_READY + && code == 0x04 + && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) + && !(key == ILLEGAL_REQUEST && (code == 0x25 + || code == 0x24 + || !code))) + + printk( "fd_mcs: REQUEST SENSE " + "Key = %x, Code = %x, Qualifier = %x\n", + key, code, qualifier ); + } + } +#endif +#if EVERY_ACCESS + printk( "BEFORE MY_DONE. . ." ); +#endif + spin_lock_irqsave(&io_request_lock, flags); + my_done( shpnt, + (current_SC->SCp.Status & 0xff) + | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) ); + spin_unlock_irqrestore(&io_request_lock, flags); +#if EVERY_ACCESS + printk( "RETURNING.\n" ); +#endif + + } else { + if (current_SC->SCp.phase & disconnect) { + outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port ); + outb( 0x00, SCSI_Cntl_port ); + } else { + outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); + } + } +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; +} + +int fd_mcs_release(struct Scsi_Host *shpnt) +{ + int i, this_host, irq_usage; + + release_region(shpnt->io_port, shpnt->n_io_port); + + this_host = -1; + irq_usage = 0; + for (i = 0; i < found; i++) { + if (shpnt == hosts[i]) + this_host = i; + if (shpnt->irq == hosts[i]->irq) + irq_usage++; + } + + /* only for the last one */ + if (1 == irq_usage) + free_irq(shpnt->irq, hosts); + + found--; + + for (i = this_host; i < found; i++) + hosts[i] = hosts[i+1]; + + hosts[found] = NULL; + + return 0; +} + +int fd_mcs_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +{ + struct Scsi_Host *shpnt = SCpnt->host; + + if (in_command) { + panic( "fd_mcs: fd_mcs_queue() NOT REENTRANT!\n" ); + } +#if EVERY_ACCESS + printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->target, + *(unsigned char *)SCpnt->cmnd, + SCpnt->use_sg, + SCpnt->request_bufflen ); +#endif + + fd_mcs_make_bus_idle(shpnt); + + SCpnt->scsi_done = done; /* Save this for the done function */ + current_SC = SCpnt; + + /* Initialize static data */ + + if (current_SC->use_sg) { + current_SC->SCp.buffer = + (struct scatterlist *)current_SC->request_buffer; + current_SC->SCp.ptr = current_SC->SCp.buffer->address; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + current_SC->SCp.buffers_residual = current_SC->use_sg - 1; + } else { + current_SC->SCp.ptr = (char *)current_SC->request_buffer; + current_SC->SCp.this_residual = current_SC->request_bufflen; + current_SC->SCp.buffer = NULL; + current_SC->SCp.buffers_residual = 0; + } + + + current_SC->SCp.Status = 0; + current_SC->SCp.Message = 0; + current_SC->SCp.have_data_in = 0; + current_SC->SCp.sent_command = 0; + current_SC->SCp.phase = in_arbitration; + + /* Start arbitration */ + outb( 0x00, Interrupt_Cntl_port ); + outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ + outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */ + in_command = 1; + outb( 0x20, Interrupt_Cntl_port ); + outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ + + return 0; +} + +static void internal_done( Scsi_Cmnd *SCpnt ) +{ + /* flag it done */ + SCpnt->host_scribble = (unsigned char *)1; +} + +int fd_mcs_command( Scsi_Cmnd *SCpnt ) +{ + fd_mcs_queue( SCpnt, internal_done ); + /* host_scribble is used for status here */ + SCpnt->host_scribble = NULL; + while (!SCpnt->host_scribble) + barrier(); + return SCpnt->result; +} + +#if DEBUG_ABORT || DEBUG_RESET +static void fd_mcs_print_info( Scsi_Cmnd *SCpnt ) +{ + unsigned int imr; + unsigned int irr; + unsigned int isr; + struct Scsi_Host *shpnt = SCpnt->host; + + if (!SCpnt || !SCpnt->host) { + printk( "fd_mcs: cannot provide detailed information\n" ); + } + + printk( "%s\n", fd_mcs_info( SCpnt->host ) ); + print_banner( SCpnt->host ); + switch (SCpnt->SCp.phase) { + case in_arbitration: printk( "arbitration " ); break; + case in_selection: printk( "selection " ); break; + case in_other: printk( "other " ); break; + default: printk( "unknown " ); break; + } + + printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->SCp.phase, + SCpnt->target, + *(unsigned char *)SCpnt->cmnd, + SCpnt->use_sg, + SCpnt->request_bufflen ); + printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", + SCpnt->SCp.sent_command, + SCpnt->SCp.have_data_in, + SCpnt->timeout ); +#if DEBUG_RACE + printk( "in_interrupt_flag = %d\n", in_interrupt_flag ); +#endif + + imr = (inb( 0x0a1 ) << 8) + inb( 0x21 ); + outb( 0x0a, 0xa0 ); + irr = inb( 0xa0 ) << 8; + outb( 0x0a, 0x20 ); + irr += inb( 0x20 ); + outb( 0x0b, 0xa0 ); + isr = inb( 0xa0 ) << 8; + outb( 0x0b, 0x20 ); + isr += inb( 0x20 ); + + /* Print out interesting information */ + printk( "IMR = 0x%04x", imr ); + if (imr & (1 << shpnt->irq)) + printk( " (masked)" ); + printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); + + printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) ); + printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) ); + if (inb( TMC_Status_port ) & 1) + printk( " (interrupt)" ); + printk( "\n" ); + printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) ); + if (inb( Interrupt_Status_port ) & 0x08) + printk( " (enabled)" ); + printk( "\n" ); + if (chip == tmc18c50 || chip == tmc18c30) { + printk( "FIFO Status = 0x%02x\n", inb( shpnt->io_port + FIFO_Status ) ); + printk( "Int. Condition = 0x%02x\n", + inb( shpnt->io_port + Interrupt_Cond ) ); + } + printk( "Configuration 1 = 0x%02x\n", inb( shpnt->io_port + Configuration1 ) ); + if (chip == tmc18c50 || chip == tmc18c30) + printk( "Configuration 2 = 0x%02x\n", + inb( shpnt->io_port + Configuration2 ) ); +} +#endif + +int fd_mcs_abort( Scsi_Cmnd *SCpnt) +{ + struct Scsi_Host *shpnt = SCpnt->host; + + unsigned long flags; +#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT + printk( "fd_mcs: abort " ); +#endif + + save_flags( flags ); + cli(); + if (!in_command) { +#if EVERY_ACCESS || ERRORS_ONLY + printk( " (not in command)\n" ); +#endif + restore_flags( flags ); + return SCSI_ABORT_NOT_RUNNING; + } else printk( "\n" ); + +#if DEBUG_ABORT + fd_mcs_print_info( SCpnt ); +#endif + + fd_mcs_make_bus_idle(shpnt); + + current_SC->SCp.phase |= aborted; + + current_SC->result = DID_ABORT << 16; + + restore_flags( flags ); + + /* Aborts are not done well. . . */ + spin_lock_irqsave(&io_request_lock, flags); + my_done( shpnt, DID_ABORT << 16 ); + spin_unlock_irqrestore(&io_request_lock, flags); + + return SCSI_ABORT_SUCCESS; +} + +int fd_mcs_reset( Scsi_Cmnd *SCpnt, unsigned int reset_flags ) +{ + struct Scsi_Host *shpnt = SCpnt->host; + +#if DEBUG_RESET + static int called_once = 0; +#endif + +#if ERRORS_ONLY + if (SCpnt) printk( "fd_mcs: SCSI Bus Reset\n" ); +#endif + +#if DEBUG_RESET + if (called_once) fd_mcs_print_info( current_SC ); + called_once = 1; +#endif + + outb( 1, SCSI_Cntl_port ); + do_pause( 2 ); + outb( 0, SCSI_Cntl_port ); + do_pause( 115 ); + outb( 0, SCSI_Mode_Cntl_port ); + outb( PARITY_MASK, TMC_Cntl_port ); + + /* Unless this is the very first call (i.e., SCPnt == NULL), everything + is probably hosed at this point. We will, however, try to keep + things going by informing the high-level code that we need help. */ + + return SCSI_RESET_WAKEUP; +} + +#include "sd.h" +#include + +int fd_mcs_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ) +{ + int drive; + unsigned char buf[512 + sizeof( int ) * 2]; + int size = disk->capacity; + int *sizes = (int *)buf; + unsigned char *data = (unsigned char *)(sizes + 2); + unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; + int retcode; + + /* BIOS >= 3.4 for MCA cards */ + drive = MINOR(dev) / 16; + + /* This algorithm was provided by Future Domain (much thanks!). */ + + sizes[0] = 0; /* zero bytes out */ + sizes[1] = 512; /* one sector in */ + memcpy( data, do_read, sizeof( do_read ) ); + retcode = kernel_scsi_ioctl( disk->device, + SCSI_IOCTL_SEND_COMMAND, + (void *)buf ); + if (!retcode /* SCSI command ok */ + && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ + && data[0x1c2]) { /* Partition type */ + + /* The partition table layout is as follows: + + Start: 0x1b3h + Offset: 0 = partition status + 1 = starting head + 2 = starting sector and cylinder (word, encoded) + 4 = partition type + 5 = ending head + 6 = ending sector and cylinder (word, encoded) + 8 = starting absolute sector (double word) + c = number of sectors (double word) + Signature: 0x1fe = 0x55aa + + So, this algorithm assumes: + 1) the first partition table is in use, + 2) the data in the first entry is correct, and + 3) partitions never divide cylinders + + Note that (1) may be FALSE for NetBSD (and other BSD flavors), + as well as for Linux. Note also, that Linux doesn't pay any + attention to the fields that are used by this algorithm -- it + only uses the absolute sector data. Recent versions of Linux's + fdisk(1) will fill this data in correctly, and forthcoming + versions will check for consistency. + + Checking for a non-zero partition type is not part of the + Future Domain algorithm, but it seemed to be a reasonable thing + to do, especially in the Linux and BSD worlds. */ + + info_array[0] = data[0x1c3] + 1; /* heads */ + info_array[1] = data[0x1c4] & 0x3f; /* sectors */ + } else { + + /* Note that this new method guarantees that there will always be + less than 1024 cylinders on a platter. This is good for drives + up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ + + if ((unsigned int)size >= 0x7e0000U) { + info_array[0] = 0xff; /* heads = 255 */ + info_array[1] = 0x3f; /* sectors = 63 */ + } else if ((unsigned int)size >= 0x200000U) { + info_array[0] = 0x80; /* heads = 128 */ + info_array[1] = 0x3f; /* sectors = 63 */ + } else { + info_array[0] = 0x40; /* heads = 64 */ + info_array[1] = 0x20; /* sectors = 32 */ + } + } + /* For both methods, compute the cylinders */ + info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); + + + return 0; +} + +#ifdef MODULE +/* Eventually this will go into an include file, but this will be later */ +Scsi_Host_Template driver_template = FD_MCS; + +#include "scsi_module.c" +#endif diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/fd_mcs.h linux/drivers/scsi/fd_mcs.h --- v2.1.127/linux/drivers/scsi/fd_mcs.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/fd_mcs.h Sun Nov 8 13:50:47 1998 @@ -0,0 +1,54 @@ +/* fd_mcs.h -- Header for Future Domain MCS 600/700 (or IBM OEM) driver + * + * fd_mcs.h v0.2 03/11/1998 ZP Gu (zpg@castle.net) + * + + * 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, 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. + + */ + +#ifndef _FD_MCS_H +#define _FD_MCS_H + +extern int fd_mcs_detect( Scsi_Host_Template * ); +extern int fd_mcs_release( struct Scsi_Host * ); +extern int fd_mcs_command( Scsi_Cmnd * ); +extern int fd_mcs_abort( Scsi_Cmnd * ); +extern int fd_mcs_reset( Scsi_Cmnd *, unsigned int ); +extern int fd_mcs_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); +extern int fd_mcs_biosparam( Disk *, kdev_t, int * ); +extern int fd_mcs_proc_info( char *, char **, off_t, int, int, int ); +extern const char *fd_mcs_info(struct Scsi_Host *); + +extern struct proc_dir_entry proc_scsi_fd_mcs; + +#define FD_MCS {\ + proc_dir: &proc_scsi_fd_mcs, \ + proc_info: fd_mcs_proc_info, \ + detect: fd_mcs_detect, \ + release: fd_mcs_release, \ + info: fd_mcs_info, \ + command: fd_mcs_command, \ + queuecommand: fd_mcs_queue, \ + abort: fd_mcs_abort, \ + reset: fd_mcs_reset, \ + bios_param: fd_mcs_biosparam, \ + can_queue: 1, \ + this_id: 7, \ + sg_tablesize: 64, \ + cmd_per_lun: 1, \ + use_clustering: DISABLE_CLUSTERING } + +#endif /* _FD_MCS_H */ diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.1.127/linux/drivers/scsi/hosts.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/hosts.c Sun Nov 8 13:50:47 1998 @@ -133,6 +133,10 @@ #include "u14-34f.h" #endif +#ifdef CONFIG_SCSI_FD_MCS +#include "fd_mcs.h" +#endif + #ifdef CONFIG_SCSI_FUTURE_DOMAIN #include "fdomain.h" #endif diff -u --recursive --new-file v2.1.127/linux/drivers/scsi/scsicam.c linux/drivers/scsi/scsicam.c --- v2.1.127/linux/drivers/scsi/scsicam.c Fri Oct 9 13:27:11 1998 +++ linux/drivers/scsi/scsicam.c Sun Nov 8 13:51:34 1998 @@ -45,6 +45,7 @@ struct buffer_head *bh; int ret_code; int size = disk->capacity; + unsigned long temp_cyl; if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024))) return -1; @@ -67,6 +68,11 @@ if (ret_code || ip[0] > 255 || ip[1] > 63) { ip[0] = 64; ip[1] = 32; + temp_cyl = size / (ip[0] * ip[1]); + if (temp_cyl > 65534) { + ip[0] = 255; + ip[1] = 63; + } ip[2] = size / (ip[0] * ip[1]); } diff -u --recursive --new-file v2.1.127/linux/drivers/sound/Readme.modules linux/drivers/sound/Readme.modules --- v2.1.127/linux/drivers/sound/Readme.modules Sun Jul 26 11:57:16 1998 +++ linux/drivers/sound/Readme.modules Sun Nov 8 13:56:10 1998 @@ -66,6 +66,34 @@ recommend using /etc/modules.conf. +Persistent DMA Buffers: + +The sound modules normally allocate DMA buffers during open() and +deallocate them during close(). Linux can often have problems allocating +DMA buffers for ISA cards on machines with more than 16MB RAM. This is +because ISA DMA buffers must exist below the 16MB boundry and it is quite +possible that we can't find a large enough free block in this region after +the machine has been running for any amount of time. The way to avoid this +problem is to allocate the DMA buffers during module load and deallocate +them when the module is unloaded. For this to be effective we need to load +the sound modules right after the kernel boots, either manually or by an +init script, and keep them around until we shut down. This is a little +wasteful of RAM, but it guarantees that sound always works. + +To make the sound driver use persistent DMA buffers we need to pass the +sound.o module a "dmabuf=1" command-line argument. This is normally done +in /etc/conf.modules (or the more proper /etc/modules.conf) like so: + +options sound dmabuf=1 + +If you have 16MB or less RAM or a PCI sound card, this is wasteful and +unnecessary. It is possible that machine with 16MB or less RAM will find +this option useful, but if your machine is so memory-starved that it +cannot find a 64K block free, you will be wasting even more RAM by keeping +the sound modules loaded and the DMA buffers allocated when they are not +needed. The proper solution is to upgrade your RAM. But you do also have +this improper solution as well. Use it wisely. + I'm afraid I know nothing about anything but my setup, being more of a text-mode guy anyway. If you have options for other cards or other helpful hints, send them to me, Jim Bray, jb@as220.org, http://as220.org/jb. diff -u --recursive --new-file v2.1.127/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c --- v2.1.127/linux/drivers/sound/ad1848.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/sound/ad1848.c Sun Nov 8 13:56:10 1998 @@ -1814,7 +1814,7 @@ ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ if (devc->timer_ticks == 0) - printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", devc->irq); + printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq); else { DDB(printk("Interrupt test OK\n")); @@ -1935,7 +1935,7 @@ if (!share_dma) { if (irq > 0) - free_irq(devc->irq, NULL); + free_irq(devc->irq, (void *)devc->dev_no); sound_free_dma(audio_devs[dev]->dmap_out->dma); @@ -1945,6 +1945,10 @@ mixer = audio_devs[devc->dev_no]->mixer_dev; if(mixer>=0) sound_unload_mixerdev(mixer); + + nr_ad1848_devs--; + for ( ; i < nr_ad1848_devs ; i++) + adev_info[i] = adev_info[i+1]; } else printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base); diff -u --recursive --new-file v2.1.127/linux/drivers/sound/audio.c linux/drivers/sound/audio.c --- v2.1.127/linux/drivers/sound/audio.c Fri Oct 23 22:01:21 1998 +++ linux/drivers/sound/audio.c Sun Nov 8 13:56:10 1998 @@ -228,8 +228,8 @@ if (l > buf_size) l = buf_size; - returned = l; - used = l; + returned = l; + used = l; if (!audio_devs[dev]->d->copy_user) { if ((dma_buf + l) > @@ -246,13 +246,13 @@ if(copy_from_user(dma_buf, &(buf)[p], l)) return -EFAULT; } - else audio_devs[dev]->d->copy_user ( dev, - dma_buf, 0, - buf, p, - c, buf_size, - &used, &returned, - l); - l = returned; + else audio_devs[dev]->d->copy_user (dev, + dma_buf, 0, + buf, p, + c, buf_size, + &used, &returned, + l); + l = returned; if (audio_devs[dev]->local_conversion & CNV_MU_LAW) { diff -u --recursive --new-file v2.1.127/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- v2.1.127/linux/drivers/sound/dev_table.c Thu Sep 17 17:53:37 1998 +++ linux/drivers/sound/dev_table.c Sun Nov 8 13:56:10 1998 @@ -516,6 +516,7 @@ { if (dev != -1) { + DMAbuf_deinit(dev); audio_devs[dev] = NULL; unregister_sound_dsp((dev<<4)+3); } diff -u --recursive --new-file v2.1.127/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h --- v2.1.127/linux/drivers/sound/dev_table.h Fri Oct 23 22:01:21 1998 +++ linux/drivers/sound/dev_table.h Sun Nov 8 13:56:10 1998 @@ -188,12 +188,12 @@ int (*prepare_for_output) (int dev, int bufsize, int nbufs); void (*halt_io) (int dev); int (*local_qlen)(int dev); - void (*copy_user)(int dev, - char *localbuf, int localoffs, - const char *userbuf, int useroffs, - int max_in, int max_out, - int *used, int *returned, - int len); + void (*copy_user) (int dev, + char *localbuf, int localoffs, + const char *userbuf, int useroffs, + int max_in, int max_out, + int *used, int *returned, + int len); void (*halt_input) (int dev); void (*halt_output) (int dev); void (*trigger) (int dev, int bits); diff -u --recursive --new-file v2.1.127/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v2.1.127/linux/drivers/sound/dmabuf.c Sun Nov 8 14:03:03 1998 +++ linux/drivers/sound/dmabuf.c Sun Nov 8 13:56:10 1998 @@ -18,7 +18,10 @@ * determine if it was woken up by the expiring timeout or by * an explicit wake_up. The return value from schedule_timeout * can be used instead; if 0, the wakeup was due to the timeout. + * + * Rob Riggs Added persistent DMA buffers (1998/10/17) */ + #include #define BE_CONSERVATIVE @@ -28,6 +31,9 @@ #if defined(CONFIG_AUDIO) || defined(CONFIG_GUS) +#define DMAP_FREE_ON_CLOSE 0 +#define DMAP_KEEP_ON_CLOSE 1 +extern int sound_dmap_flag; static void dma_reset_output(int dev); static void dma_reset_input(int dev); @@ -212,7 +218,8 @@ disable_dma(dmap->dma); release_dma_lock(flags); - sound_free_dmap(dmap); + if (sound_dmap_flag == DMAP_FREE_ON_CLOSE) + sound_free_dmap(dmap); } @@ -732,7 +739,7 @@ * Wait for free space */ if (signal_pending(current)) - return -EIO; + return -EINTR; timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT)); if (timeout) timeout_value = dmabuf_timeout(dmap); @@ -1009,8 +1016,8 @@ unsigned long f; f=claim_dma_lock(); - clear_dma_ff(chan); disable_dma(dmap->dma); + clear_dma_ff(chan); pos = dmap->bytes_in_use - get_dma_residue(chan); enable_dma(dmap->dma); release_dma_lock(f); @@ -1104,8 +1111,8 @@ unsigned long f; f=claim_dma_lock(); - clear_dma_ff(chan); disable_dma(dmap->dma); + clear_dma_ff(chan); pos = dmap->bytes_in_use - get_dma_residue(chan); enable_dma(dmap->dma); release_dma_lock(f); @@ -1181,6 +1188,13 @@ adev->dmap_in->dma = dma2; } } + /* Persistent DMA buffers allocated here */ + if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { + if (adev->dmap_in->raw_buf == NULL) + sound_alloc_dmap(adev->dmap_in); + if (adev->dmap_out->raw_buf == NULL) + sound_alloc_dmap(adev->dmap_out); + } } } @@ -1251,12 +1265,13 @@ /* This routine is called when driver is being unloaded */ if (!adev) return; -#ifdef RUNTIME_DMA_ALLOC - sound_free_dmap(adev->dmap_out); - if (adev->flags & DMA_DUPLEX) - sound_free_dmap(adev->dmap_in); -#endif + /* Persistent DMA buffers deallocated here */ + if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { + sound_free_dmap(adev->dmap_out); + if (adev->flags & DMA_DUPLEX) + sound_free_dmap(adev->dmap_in); + } } #endif diff -u --recursive --new-file v2.1.127/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c --- v2.1.127/linux/drivers/sound/dmasound.c Sun Nov 8 14:03:03 1998 +++ linux/drivers/sound/dmasound.c Sun Nov 8 13:56:10 1998 @@ -816,7 +816,7 @@ #define ONE_SECOND HZ /* in jiffies (100ths of a second) */ #define NO_TIME_LIMIT 0xffffffff #define SLEEP(queue, time_limit) \ - interruptible_sleep_on(&queue, (time_limit)); + interruptible_sleep_on_timeout(&queue, (time_limit)); #define WAKE_UP(queue) (wake_up_interruptible(&queue)) /* diff -u --recursive --new-file v2.1.127/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c --- v2.1.127/linux/drivers/sound/mad16.c Thu Sep 17 17:53:37 1998 +++ linux/drivers/sound/mad16.c Sun Nov 8 13:56:10 1998 @@ -834,7 +834,6 @@ void unload_mad16(struct address_info *hw_config) { - int mixer = audio_devs[hw_config->slots[0]]->mixer_dev; ad1848_unload(hw_config->io_base + 4, hw_config->irq, hw_config->dma, diff -u --recursive --new-file v2.1.127/linux/drivers/sound/os.h linux/drivers/sound/os.h --- v2.1.127/linux/drivers/sound/os.h Tue Jun 9 11:57:30 1998 +++ linux/drivers/sound/os.h Sun Nov 8 13:56:10 1998 @@ -48,7 +48,6 @@ extern void reprogram_timer(void); -#define RUNTIME_DMA_ALLOC #define USE_AUTOINIT_DMA extern caddr_t sound_mem_blocks[1024]; diff -u --recursive --new-file v2.1.127/linux/drivers/sound/sb.h linux/drivers/sound/sb.h --- v2.1.127/linux/drivers/sound/sb.h Fri Oct 23 22:01:22 1998 +++ linux/drivers/sound/sb.h Sun Nov 8 13:56:10 1998 @@ -87,14 +87,14 @@ /* State variables */ int opened; - /* new audio fields for full duplex support */ - int fullduplex; - int duplex; + /* new audio fields for full duplex support */ + int fullduplex; + int duplex; int speed, bits, channels; volatile int irq_ok; volatile int intr_active, irq_mode; - /* duplicate audio fields for full duplex support */ - volatile int intr_active_2, irq_mode_2; + /* duplicate audio fields for full duplex support */ + volatile int intr_active_16, irq_mode_16; /* Mixer fields */ int *levels; @@ -110,12 +110,12 @@ int trg_bytes; int trg_intrflag; int trg_restart; - /* duplicate audio fields for full duplex support */ - unsigned long trg_buf_2; - int trigger_bits_2; - int trg_bytes_2; - int trg_intrflag_2; - int trg_restart_2; + /* duplicate audio fields for full duplex support */ + unsigned long trg_buf_16; + int trigger_bits_16; + int trg_bytes_16; + int trg_intrflag_16; + int trg_restart_16; unsigned char tconst; int my_dev; diff -u --recursive --new-file v2.1.127/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c --- v2.1.127/linux/drivers/sound/sb_audio.c Fri Oct 23 22:01:22 1998 +++ linux/drivers/sound/sb_audio.c Sun Nov 8 13:56:10 1998 @@ -51,7 +51,7 @@ restore_flags(flags); return -EBUSY; } - if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) + if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) { if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit")) { @@ -63,10 +63,9 @@ restore_flags(flags); devc->irq_mode = IMODE_NONE; - devc->irq_mode_2 = IMODE_NONE; - devc->intr_active_2 = 0; - devc->fullduplex = devc->duplex && - ((mode & OPEN_READ) && (mode & OPEN_WRITE)); + devc->irq_mode_16 = IMODE_NONE; + devc->fullduplex = devc->duplex && + ((mode & OPEN_READ) && (mode & OPEN_WRITE)); sb_dsp_reset(devc); /* The ALS007 seems to require that the DSP be removed from the output */ @@ -92,11 +91,11 @@ { sb_devc *devc = audio_devs[dev]->devc; - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ? - devc->dma16 : devc->dma8; + audio_devs[dev]->dmap_out->dma = devc->dma8; + audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ? + devc->dma16 : devc->dma8; - if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) + if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) sound_close_dma(devc->dma16); /* For ALS007, turn DSP output back on if closing the device for read */ @@ -114,34 +113,40 @@ { sb_devc *devc = audio_devs[dev]->devc; - if( !devc->fullduplex || devc->bits == AFMT_S16_LE) { - devc->trg_buf = buf; - devc->trg_bytes = nr_bytes; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_OUTPUT; - } else { - devc->trg_buf_2 = buf; - devc->trg_bytes_2 = nr_bytes; - devc->trg_intrflag_2 = intrflag; - devc->irq_mode_2 = IMODE_OUTPUT; - } + if (!devc->fullduplex || devc->bits == AFMT_S16_LE) + { + devc->trg_buf = buf; + devc->trg_bytes = nr_bytes; + devc->trg_intrflag = intrflag; + devc->irq_mode = IMODE_OUTPUT; + } + else + { + devc->trg_buf_16 = buf; + devc->trg_bytes_16 = nr_bytes; + devc->trg_intrflag_16 = intrflag; + devc->irq_mode_16 = IMODE_OUTPUT; + } } static void sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag) { sb_devc *devc = audio_devs[dev]->devc; - if( !devc->fullduplex || devc->bits != AFMT_S16_LE) { - devc->trg_buf = buf; - devc->trg_bytes = count; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_INPUT; - } else { - devc->trg_buf_2 = buf; - devc->trg_bytes_2 = count; - devc->trg_intrflag_2 = intrflag; - devc->irq_mode_2 = IMODE_INPUT; - } + if (!devc->fullduplex || devc->bits != AFMT_S16_LE) + { + devc->trg_buf = buf; + devc->trg_bytes = count; + devc->trg_intrflag = intrflag; + devc->irq_mode = IMODE_INPUT; + } + else + { + devc->trg_buf_16 = buf; + devc->trg_bytes_16 = count; + devc->trg_intrflag_16 = intrflag; + devc->irq_mode_16 = IMODE_INPUT; + } } /* @@ -854,17 +859,23 @@ { sb_devc *devc = audio_devs[dev]->devc; - if( !devc->fullduplex) { - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8; - } else if( devc->bits == AFMT_S16_LE) { - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = devc->dma16; - } else { - audio_devs[dev]->dmap_out->dma = devc->dma16; - audio_devs[dev]->dmap_in->dma = devc->dma8; - } + if (!devc->fullduplex) + { + audio_devs[dev]->dmap_out->dma = + audio_devs[dev]->dmap_in->dma = + devc->bits == AFMT_S16_LE ? + devc->dma16 : devc->dma8; + } + else if (devc->bits == AFMT_S16_LE) + { + audio_devs[dev]->dmap_out->dma = devc->dma8; + audio_devs[dev]->dmap_in->dma = devc->dma16; + } + else + { + audio_devs[dev]->dmap_out->dma = devc->dma16; + audio_devs[dev]->dmap_in->dma = devc->dma8; + } devc->trigger_bits = 0; return 0; @@ -874,17 +885,23 @@ { sb_devc *devc = audio_devs[dev]->devc; - if( !devc->fullduplex) { - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8; - } else if( devc->bits == AFMT_S16_LE) { - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = devc->dma16; - } else { - audio_devs[dev]->dmap_out->dma = devc->dma16; - audio_devs[dev]->dmap_in->dma = devc->dma8; - } + if (!devc->fullduplex) + { + audio_devs[dev]->dmap_out->dma = + audio_devs[dev]->dmap_in->dma = + devc->bits == AFMT_S16_LE ? + devc->dma16 : devc->dma8; + } + else if (devc->bits == AFMT_S16_LE) + { + audio_devs[dev]->dmap_out->dma = devc->dma8; + audio_devs[dev]->dmap_in->dma = devc->dma16; + } + else + { + audio_devs[dev]->dmap_out->dma = devc->dma16; + audio_devs[dev]->dmap_in->dma = devc->dma8; + } devc->trigger_bits = 0; return 0; @@ -895,23 +912,27 @@ { unsigned long flags, cnt; sb_devc *devc = audio_devs[dev]->devc; - unsigned long bits; + unsigned long bits; - if( !devc->fullduplex || devc->bits == AFMT_S16_LE) { - devc->irq_mode = IMODE_OUTPUT; - devc->intr_active = 1; - } else { - devc->irq_mode_2 = IMODE_OUTPUT; - devc->intr_active_2 = 1; - } - - /* save value */ - save_flags (flags); - cli (); - bits = devc->bits; - if( devc->fullduplex) - devc->bits = (devc->bits == AFMT_S16_LE) ? AFMT_U8 : AFMT_S16_LE; - restore_flags (flags); + if (!devc->fullduplex || devc->bits == AFMT_S16_LE) + { + devc->irq_mode = IMODE_OUTPUT; + devc->intr_active = 1; + } + else + { + devc->irq_mode_16 = IMODE_OUTPUT; + devc->intr_active_16 = 1; + } + + /* save value */ + save_flags (flags); + cli (); + bits = devc->bits; + if (devc->fullduplex) + devc->bits = (devc->bits == AFMT_S16_LE) ? + AFMT_U8 : AFMT_S16_LE; + restore_flags (flags); cnt = count; if (devc->bits == AFMT_S16_LE) @@ -933,8 +954,8 @@ sb_dsp_command(devc, (unsigned char) (cnt & 0xff)); sb_dsp_command(devc, (unsigned char) (cnt >> 8)); - /* restore real value after all programming */ - devc->bits = bits; + /* restore real value after all programming */ + devc->bits = bits; restore_flags(flags); } @@ -943,13 +964,16 @@ unsigned long flags, cnt; sb_devc *devc = audio_devs[dev]->devc; - if( !devc->fullduplex || devc->bits != AFMT_S16_LE) { - devc->irq_mode = IMODE_INPUT; - devc->intr_active = 1; - } else { - devc->irq_mode_2 = IMODE_INPUT; - devc->intr_active_2 = 1; - } + if (!devc->fullduplex || devc->bits != AFMT_S16_LE) + { + devc->irq_mode = IMODE_INPUT; + devc->intr_active = 1; + } + else + { + devc->irq_mode_16 = IMODE_INPUT; + devc->intr_active_16 = 1; + } cnt = count; if (devc->bits == AFMT_S16_LE) @@ -978,122 +1002,138 @@ { sb_devc *devc = audio_devs[dev]->devc; - int bits_2 = bits & devc->irq_mode_2; + int bits_16 = bits & devc->irq_mode_16; bits &= devc->irq_mode; - if (!bits) + if (!bits && !bits_16) sb_dsp_command(devc, 0xd0); /* Halt DMA */ else { - if( bits) { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb16_audio_start_input(dev, devc->trg_buf, - devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - sb16_audio_output_block(dev, devc->trg_buf, - devc->trg_bytes, - devc->trg_intrflag); - break; - } - } - if( bits_2) { - switch (devc->irq_mode_2) - { - case IMODE_INPUT: - sb16_audio_start_input (dev, devc->trg_buf_2, - devc->trg_bytes_2, - devc->trg_intrflag_2); - break; - case IMODE_OUTPUT: - sb16_audio_output_block (dev, devc->trg_buf_2, - devc->trg_bytes_2, - devc->trg_intrflag_2); - break; - } - } + if (bits) + { + switch (devc->irq_mode) + { + case IMODE_INPUT: + sb16_audio_start_input(dev, + devc->trg_buf, + devc->trg_bytes, + devc->trg_intrflag); + break; + + case IMODE_OUTPUT: + sb16_audio_output_block(dev, + devc->trg_buf, + devc->trg_bytes, + devc->trg_intrflag); + break; + } + } + if (bits_16) + { + switch (devc->irq_mode_16) + { + case IMODE_INPUT: + sb16_audio_start_input(dev, + devc->trg_buf_16, + devc->trg_bytes_16, + devc->trg_intrflag_16); + break; + + case IMODE_OUTPUT: + sb16_audio_output_block(dev, + devc->trg_buf_16, + devc->trg_bytes_16, + devc->trg_intrflag_16); + break; + } + } } - devc->trigger_bits = bits | bits_2; + devc->trigger_bits = bits | bits_16; } static unsigned char lbuf8[2048]; static signed short *lbuf16 = (signed short *)lbuf8; #define LBUFCOPYSIZE 1024 static void -sb16_copy_from_user( int dev, - char *localbuf, int localoffs, - const char *userbuf, int useroffs, - int max_in, int max_out, - int *used, int *returned, - int len) -{ - sb_devc *devc = audio_devs[dev]->devc; - int i, c, p, locallen; - unsigned char *buf8; - signed short *buf16; - - /* if not duplex no conversion */ - if( !devc->fullduplex) { - copy_from_user( localbuf + localoffs, userbuf + useroffs, len); - *used = len; - *returned = len; - } else if( devc->bits == AFMT_S16_LE) { - /* 16 -> 8 */ - /* max_in >> 1, max number of samples in ( 16 bits ) */ - /* max_out, max number of samples out ( 8 bits ) */ - /* len, number of samples that will be taken ( 16 bits )*/ - /* c, count of samples remaining in buffer ( 16 bits )*/ - /* p, count of samples already processed ( 16 bits )*/ - len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1); - c = len; - p = 0; - buf8 = (unsigned char *)(localbuf + localoffs); - while( c) { - locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); - /* << 1 in order to get 16 bit samples */ - copy_from_user( lbuf16, - userbuf+useroffs + (p << 1), - locallen << 1); - for( i = 0; i < locallen; i++) { - buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80; - } - c -= locallen; p += locallen; - } - /* used = ( samples * 16 bits size ) */ - *used = len << 1; - /* returned = ( samples * 8 bits size ) */ - *returned = len; - } else { - /* 8 -> 16 */ - /* max_in, max number of samples in ( 8 bits ) */ - /* max_out >> 1, max number of samples out ( 16 bits ) */ - /* len, number of samples that will be taken ( 8 bits )*/ - /* c, count of samples remaining in buffer ( 8 bits )*/ - /* p, count of samples already processed ( 8 bits )*/ - len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in; - c = len; - p = 0; - buf16 = (signed short *)(localbuf + localoffs); - while( c) { - locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); - copy_from_user( lbuf8, - userbuf+useroffs + p, - locallen); - for( i = 0; i < locallen; i++) { - buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8; - } - c -= locallen; p += locallen; - } - /* used = ( samples * 8 bits size ) */ - *used = len; - /* returned = ( samples * 16 bits size ) */ - *returned = len << 1; - } +sb16_copy_from_user(int dev, + char *localbuf, int localoffs, + const char *userbuf, int useroffs, + int max_in, int max_out, + int *used, int *returned, + int len) +{ + sb_devc *devc = audio_devs[dev]->devc; + int i, c, p, locallen; + unsigned char *buf8; + signed short *buf16; + + /* if not duplex no conversion */ + if (!devc->fullduplex) + { + copy_from_user (localbuf + localoffs, userbuf + useroffs, len); + *used = len; + *returned = len; + } + else if (devc->bits == AFMT_S16_LE) + { + /* 16 -> 8 */ + /* max_in >> 1, max number of samples in ( 16 bits ) */ + /* max_out, max number of samples out ( 8 bits ) */ + /* len, number of samples that will be taken ( 16 bits )*/ + /* c, count of samples remaining in buffer ( 16 bits )*/ + /* p, count of samples already processed ( 16 bits )*/ + len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1); + c = len; + p = 0; + buf8 = (unsigned char *)(localbuf + localoffs); + while (c) + { + locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); + /* << 1 in order to get 16 bit samples */ + copy_from_user (lbuf16, + userbuf+useroffs + (p << 1), + locallen << 1); + for (i = 0; i < locallen; i++) + { + buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80; + } + c -= locallen; p += locallen; + } + /* used = ( samples * 16 bits size ) */ + *used = len << 1; + /* returned = ( samples * 8 bits size ) */ + *returned = len; + } + else + { + /* 8 -> 16 */ + /* max_in, max number of samples in ( 8 bits ) */ + /* max_out >> 1, max number of samples out ( 16 bits ) */ + /* len, number of samples that will be taken ( 8 bits )*/ + /* c, count of samples remaining in buffer ( 8 bits )*/ + /* p, count of samples already processed ( 8 bits )*/ + len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in; + c = len; + p = 0; + buf16 = (signed short *)(localbuf + localoffs); + while (c) + { + locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); + copy_from_user (lbuf8, + userbuf+useroffs + p, + locallen); + for (i = 0; i < locallen; i++) + { + buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8; + } + c -= locallen; p += locallen; + } + /* used = ( samples * 8 bits size ) */ + *used = len; + /* returned = ( samples * 16 bits size ) */ + *returned = len << 1; + } } @@ -1208,7 +1248,7 @@ sb16_audio_prepare_for_output, sb1_audio_halt_xfer, NULL, /* local_qlen */ - sb16_copy_from_user, /* copy_from_user */ + sb16_copy_from_user, /* copy_from_user */ NULL, NULL, sb16_audio_trigger, @@ -1244,7 +1284,6 @@ struct audio_driver *driver = &sb1_audio_driver; - devc->duplex = 0; switch (devc->model) { case MDL_SB1: /* SB1.0 or SB 1.5 */ @@ -1283,10 +1322,11 @@ DDB(printk("Will use SB16 driver\n")); audio_flags = DMA_AUTOMODE; format_mask |= AFMT_S16_LE; - if( devc->dma8 != devc->dma16 && devc->dma16 != -1) { - audio_flags |= DMA_DUPLEX; - devc->duplex = 1; - } + if (devc->dma8 != devc->dma16 && devc->dma16 != -1) + { + audio_flags |= DMA_DUPLEX; + devc->duplex = 1; + } driver = &sb16_audio_driver; break; @@ -1300,8 +1340,7 @@ name,driver, sizeof(struct audio_driver), audio_flags, format_mask, devc, devc->dma8, - (devc->dma8 != devc->dma16 && devc->dma16 != -1) - ? devc->dma16 : devc->dma8)) < 0) + devc->duplex ? devc->dma16 : devc->dma8) < 0)) { printk(KERN_ERR "Sound Blaster: unable to install audio.\n"); return; diff -u --recursive --new-file v2.1.127/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.1.127/linux/drivers/sound/sb_common.c Fri Oct 23 22:01:22 1998 +++ linux/drivers/sound/sb_common.c Sun Nov 8 13:56:10 1998 @@ -168,17 +168,27 @@ /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */ ; } - } else if (devc->intr_active_2 && (src & 0x02)) { - switch (devc->irq_mode_2) - { - case IMODE_OUTPUT: - DMAbuf_outputintr (devc->dev, 1); - break; - case IMODE_INPUT: - DMAbuf_inputintr (devc->dev); - break; - } - } + } + else if (devc->intr_active_16 && (src & 0x02)) + { + switch (devc->irq_mode_16) + { + case IMODE_OUTPUT: + DMAbuf_outputintr(devc->dev, 1); + break; + + case IMODE_INPUT: + DMAbuf_inputintr(devc->dev); + break; + + case IMODE_INIT: + break; + + default: + /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */ + ; + } + } /* * Acknowledge interrupts */ @@ -605,6 +615,7 @@ sb_devc sb_info; sb_devc *devc = &sb_info; + memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */ sb_info.my_mididev = -1; sb_info.my_mixerdev = -1; sb_info.my_dev = -1; @@ -621,7 +632,6 @@ #endif return 0; } - memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */ devc->type = hw_config->card_subtype; @@ -971,7 +981,7 @@ /* We don't have to do this bit any more the UART401 is its own master -- Krzysztof Halasa */ /* But we have to do it, if UART401 is not detected */ - if (!sbmpu && devc->my_mididev) + if (!sbmpu) sound_unload_mididev(devc->my_mididev); sound_unload_audiodev(devc->my_dev); } diff -u --recursive --new-file v2.1.127/linux/drivers/sound/sb_mixer.h linux/drivers/sound/sb_mixer.h --- v2.1.127/linux/drivers/sound/sb_mixer.h Fri Oct 23 22:01:22 1998 +++ linux/drivers/sound/sb_mixer.h Sun Nov 8 22:47:48 1998 @@ -201,7 +201,7 @@ MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4), MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x6a, 6, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_MIC, 0x6a, 2, 3, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4), MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), diff -u --recursive --new-file v2.1.127/linux/drivers/sound/sgalaxy.c linux/drivers/sound/sgalaxy.c --- v2.1.127/linux/drivers/sound/sgalaxy.c Sun Nov 8 14:03:04 1998 +++ linux/drivers/sound/sgalaxy.c Sun Nov 8 13:56:11 1998 @@ -29,7 +29,7 @@ static void sleep( unsigned howlong ) { current->state = TASK_INTERRUPTIBLE; - schedule(howlong); + schedule_timeout(howlong); } #define DPORT 0x80 @@ -108,9 +108,7 @@ sleep( HZ/10 ); - if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) ) - return 1; - return 0; + return probe_ms_sound(ai); } void attach_sgalaxy( struct address_info *ai ) diff -u --recursive --new-file v2.1.127/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.1.127/linux/drivers/sound/soundcard.c Wed Aug 26 11:37:39 1998 +++ linux/drivers/sound/soundcard.c Sun Nov 8 13:56:11 1998 @@ -15,6 +15,8 @@ * integrated sound_switch.c * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, * which should disappear in the near future) + * + * Rob Riggs Added persistent DMA buffers support (1998/10/17) */ #include @@ -64,6 +66,9 @@ caddr_t sound_mem_blocks[1024]; int sound_nblocks = 0; +/* Persistent DMA buffers */ +int sound_dmap_flag = 0; /* Off by default */ + static int soundcard_configured = 0; static char dma_alloc_map[MAX_DMA_CHANNELS] = @@ -848,7 +853,9 @@ #ifdef MODULE int traceinit = 0; +static int dmabuf = 0; MODULE_PARM(traceinit, "i"); +MODULE_PARM(dmabuf, "i"); int init_module(void) { @@ -874,6 +881,10 @@ printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); return err; } + + /* Protecting the innocent */ + sound_dmap_flag = (dmabuf > 0 ? 1 : 0); + chrdev_registered = 1; soundcard_init(); diff -u --recursive --new-file v2.1.127/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c --- v2.1.127/linux/drivers/sound/wavfront.c Sun Nov 8 14:03:04 1998 +++ linux/drivers/sound/wavfront.c Sun Nov 8 13:56:11 1998 @@ -2055,14 +2055,12 @@ return (0); } -static void -wavefront_close (int dev) - +static void wavefront_close (int dev) { struct wf_config *hw = &wavefront_configuration; - int i; #ifdef WF_STATS + int i; printk ("Status during loop: %ld\n", hw->status_found_during_loop); for (i = 0; i < 4; i++) { printk ("Status during sleep[%d]: %ld\n", @@ -2075,42 +2073,36 @@ return; } -static void -wavefront_aftertouch (int dev, int channel, int pressure) +static void wavefront_aftertouch (int dev, int channel, int pressure) { midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure); }; -static void -wavefront_bender (int dev, int chn, int value) +static void wavefront_bender (int dev, int chn, int value) { midi_synth_bender (wavefront_configuration.mididev, chn, value); }; -static void -wavefront_controller (int dev, int channel, int ctrl_num, int value) +static void wavefront_controller (int dev, int channel, int ctrl_num, int value) { if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value); midi_synth_controller (wavefront_configuration.mididev, channel,ctrl_num,value); }; -static void -wavefront_panning(int dev, int channel, int pressure) +static void wavefront_panning(int dev, int channel, int pressure) { midi_synth_controller (wavefront_configuration.mididev, channel,CTL_PAN,pressure); }; -static int -wavefront_set_instr (int dev, int channel, int instr_no) +static int wavefront_set_instr (int dev, int channel, int instr_no) { return(midi_synth_set_instr (wavefront_configuration.mididev, channel,instr_no)); }; -static int -wavefront_kill_note (int dev, int channel, int note, int volume) +static int wavefront_kill_note (int dev, int channel, int note, int volume) { if (note==255) return (midi_synth_start_note (wavefront_configuration.mididev, @@ -2119,8 +2111,7 @@ channel, note, volume)); }; -static int -wavefront_start_note (int dev, int channel, int note, int volume) +static int wavefront_start_note (int dev, int channel, int note, int volume) { if (note==255) { midi_synth_aftertouch (wavefront_configuration.mididev, @@ -2140,13 +2131,11 @@ return(0); }; -static void -wavefront_setup_voice (int dev, int voice, int chn) +static void wavefront_setup_voice (int dev, int voice, int chn) { }; static void wavefront_reset (int dev) - { int i; diff -u --recursive --new-file v2.1.127/linux/drivers/sound/wf_midi.c linux/drivers/sound/wf_midi.c --- v2.1.127/linux/drivers/sound/wf_midi.c Thu Aug 20 17:05:16 1998 +++ linux/drivers/sound/wf_midi.c Sun Nov 8 13:56:11 1998 @@ -375,24 +375,25 @@ return 1; } -void -wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy) +void wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy) { struct wf_mpu_config *devc; - int dev; + int dev; static struct wf_mpu_config *isrc = 0; - int n; + int n; struct midi_input_info *mi; - static int cnt = 0; - if (irq < 0 || irq > 15) { + if (irq < 0 || irq > 15) + { printk (KERN_ERR "WF-MPU: bogus interrupt #%d", irq); return; } dev = irq2dev[irq]; mi = &midi_devs[dev]->in_info; - if (mi->m_busy) return; + if (mi->m_busy) + return; mi->m_busy = 1; + sti (); n = 50; @@ -445,8 +446,7 @@ mi->m_busy = 0; } -static int -wf_mpu_open (int dev, int mode, +static int wf_mpu_open (int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) diff -u --recursive --new-file v2.1.127/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.1.127/linux/fs/binfmt_aout.c Sat Sep 5 16:46:41 1998 +++ linux/fs/binfmt_aout.c Wed Nov 11 11:49:59 1998 @@ -116,7 +116,7 @@ #else corefile[4] = '\0'; #endif - dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC, 0600); + dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); if (IS_ERR(dentry)) { dentry = NULL; goto end_coredump; diff -u --recursive --new-file v2.1.127/linux/fs/exec.c linux/fs/exec.c --- v2.1.127/linux/fs/exec.c Sun Nov 8 14:03:05 1998 +++ linux/fs/exec.c Wed Nov 11 22:38:58 1998 @@ -445,9 +445,9 @@ /* * This function makes sure the current process has its own signal table, - * so that flush_old_signals can later reset the signals without disturbing - * other processes. (Other processes might share the signal table via - * the CLONE_SIGHAND option to clone().) + * so that flush_signal_handlers can later reset the handlers without + * disturbing other processes. (Other processes might share the signal + * table via the CLONE_SIGHAND option to clone().) */ static inline int make_private_signals(void) @@ -486,12 +486,6 @@ * so that a new one can be started */ -static inline void flush_old_signals(struct task_struct *t) -{ - flush_signals(t); - flush_signal_handlers(t); -} - static inline void flush_old_files(struct files_struct * files) { unsigned long j; @@ -553,7 +547,7 @@ permission(bprm->dentry->d_inode,MAY_READ)) current->dumpable = 0; - flush_old_signals(current); + flush_signal_handlers(current); flush_old_files(current->files); return 0; diff -u --recursive --new-file v2.1.127/linux/fs/ext2/dir.c linux/fs/ext2/dir.c --- v2.1.127/linux/fs/ext2/dir.c Wed Aug 26 11:37:40 1998 +++ linux/fs/ext2/dir.c Wed Nov 11 11:49:59 1998 @@ -70,7 +70,7 @@ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ - ext2_truncate, /* truncate */ + NULL, /* truncate */ ext2_permission, /* permission */ NULL /* smap */ }; diff -u --recursive --new-file v2.1.127/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v2.1.127/linux/fs/isofs/dir.c Wed Aug 26 11:37:41 1998 +++ linux/fs/isofs/dir.c Thu Nov 12 11:44:09 1998 @@ -59,7 +59,7 @@ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ - isofs_bmap, /* bmap */ + NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ }; diff -u --recursive --new-file v2.1.127/linux/fs/lockd/svc.c linux/fs/lockd/svc.c --- v2.1.127/linux/fs/lockd/svc.c Sun Nov 8 14:03:06 1998 +++ linux/fs/lockd/svc.c Sun Nov 8 13:58:53 1998 @@ -135,7 +135,7 @@ * during grace period). */ if (!nlmsvc_grace_period) { - timeout = nlmsvc_retry_blocked() - jiffies; + timeout = nlmsvc_retry_blocked(); } else if (nlmsvc_grace_period < jiffies) nlmsvc_grace_period = 0; diff -u --recursive --new-file v2.1.127/linux/fs/lockd/svclock.c linux/fs/lockd/svclock.c --- v2.1.127/linux/fs/lockd/svclock.c Wed Aug 26 11:37:41 1998 +++ linux/fs/lockd/svclock.c Sun Nov 8 14:02:19 1998 @@ -615,6 +615,7 @@ } if ((block = nlm_blocked) && block->b_when != NLM_NEVER) - return block->b_when; - return 0; + return (block->b_when - jiffies); + + return MAX_SCHEDULE_TIMEOUT; } diff -u --recursive --new-file v2.1.127/linux/fs/minix/dir.c linux/fs/minix/dir.c --- v2.1.127/linux/fs/minix/dir.c Wed Aug 26 11:37:41 1998 +++ linux/fs/minix/dir.c Wed Nov 11 11:49:59 1998 @@ -55,7 +55,7 @@ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ - minix_truncate, /* truncate */ + NULL, /* truncate */ NULL /* permission */ }; diff -u --recursive --new-file v2.1.127/linux/fs/minix/fsync.c linux/fs/minix/fsync.c --- v2.1.127/linux/fs/minix/fsync.c Sat Sep 13 11:07:28 1997 +++ linux/fs/minix/fsync.c Thu Nov 12 11:44:09 1998 @@ -144,7 +144,7 @@ return err; } -int V1_minix_sync_file(struct inode * inode, struct file * file) +static int V1_minix_sync_file(struct inode * inode, struct file * file) { int wait, err = 0; @@ -305,7 +305,7 @@ return err; } -int V2_minix_sync_file(struct inode * inode, struct file * file) +static int V2_minix_sync_file(struct inode * inode, struct file * file) { int wait, err = 0; diff -u --recursive --new-file v2.1.127/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.1.127/linux/fs/minix/inode.c Wed Jun 24 22:54:09 1998 +++ linux/fs/minix/inode.c Thu Nov 12 11:44:09 1998 @@ -40,7 +40,7 @@ sb->s_dirt = 0; } -void minix_write_super (struct super_block * sb) +static void minix_write_super (struct super_block * sb) { struct minix_super_block * ms; @@ -55,7 +55,7 @@ } -void minix_put_super(struct super_block *sb) +static void minix_put_super(struct super_block *sb) { int i; @@ -86,7 +86,7 @@ minix_remount }; -int minix_remount (struct super_block * sb, int * flags, char * data) +static int minix_remount (struct super_block * sb, int * flags, char * data) { struct minix_super_block * ms; @@ -162,7 +162,7 @@ return errmsg; } -struct super_block *minix_read_super(struct super_block *s, void *data, +static struct super_block *minix_read_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; @@ -326,7 +326,7 @@ return NULL; } -int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) +static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) { struct statfs tmp; @@ -830,7 +830,7 @@ /* * The global function to read an inode. */ -void minix_read_inode(struct inode * inode) +static void minix_read_inode(struct inode * inode) { if (INODE_VERSION(inode) == MINIX_V1) V1_minix_read_inode(inode); @@ -916,7 +916,7 @@ return bh; } -struct buffer_head *minix_update_inode(struct inode *inode) +static struct buffer_head *minix_update_inode(struct inode *inode) { if (INODE_VERSION(inode) == MINIX_V1) return V1_minix_update_inode(inode); @@ -924,7 +924,7 @@ return V2_minix_update_inode(inode); } -void minix_write_inode(struct inode * inode) +static void minix_write_inode(struct inode * inode) { struct buffer_head *bh; diff -u --recursive --new-file v2.1.127/linux/fs/minix/truncate.c linux/fs/minix/truncate.c --- v2.1.127/linux/fs/minix/truncate.c Wed Jun 24 22:54:09 1998 +++ linux/fs/minix/truncate.c Thu Nov 12 11:44:09 1998 @@ -176,7 +176,7 @@ return retry; } -void V1_minix_truncate(struct inode * inode) +static void V1_minix_truncate(struct inode * inode) { int retry; diff -u --recursive --new-file v2.1.127/linux/fs/msdos/namei.c linux/fs/msdos/namei.c --- v2.1.127/linux/fs/msdos/namei.c Mon Sep 28 10:51:35 1998 +++ linux/fs/msdos/namei.c Thu Nov 12 11:44:09 1998 @@ -993,7 +993,7 @@ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ - fat_bmap, /* bmap */ + NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ diff -u --recursive --new-file v2.1.127/linux/fs/nfs/read.c linux/fs/nfs/read.c --- v2.1.127/linux/fs/nfs/read.c Tue Mar 10 10:03:34 1998 +++ linux/fs/nfs/read.c Thu Nov 12 01:02:07 1998 @@ -230,6 +230,17 @@ dprintk("NFS: nfs_readpage (%p %ld@%ld)\n", page, PAGE_SIZE, page->offset); set_bit(PG_locked, &page->flags); + + /* + * Try to flush any pending writes to the file.. + * + * NOTE! Because we own the page lock, there cannot + * be any new pending writes generated at this point. + */ + error = nfs_flush_pages(inode, 0, 0, 0); + if (error) + return error; + atomic_inc(&page->count); if (!IS_SWAPFILE(inode) && !PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_SIZE) diff -u --recursive --new-file v2.1.127/linux/fs/nfs/write.c linux/fs/nfs/write.c --- v2.1.127/linux/fs/nfs/write.c Wed Sep 9 14:51:09 1998 +++ linux/fs/nfs/write.c Thu Nov 12 12:02:03 1998 @@ -59,7 +59,7 @@ #define NFS_PARANOIA 1 #define NFSDBG_FACILITY NFSDBG_PAGECACHE -static void nfs_wback_lock(struct rpc_task *task); +static void nfs_wback_begin(struct rpc_task *task); static void nfs_wback_result(struct rpc_task *task); static void nfs_cancel_request(struct nfs_wreq *req); @@ -73,9 +73,7 @@ * Limit number of delayed writes */ static int nr_write_requests = 0; -static int nr_failed_requests = 0; static struct rpc_wait_queue write_queue = RPC_INIT_WAITQ("write_chain"); -struct nfs_wreq * nfs_failed_requests = NULL; /* Hack for future NFS swap support */ #ifndef IS_SWAPFILE @@ -83,46 +81,6 @@ #endif /* - * Unlock a page after writing it - */ -static inline void -nfs_unlock_page(struct page *page) -{ - dprintk("NFS: unlock %ld\n", page->offset); - clear_bit(PG_locked, &page->flags); - wake_up(&page->wait); - -#ifdef CONFIG_NFS_SWAP - /* async swap-out support */ - if (test_and_clear_bit(PG_decr_after, &page->flags)) - atomic_dec(&page->count); - if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) { - /* - * We're doing a swap, so check that this page is - * swap-cached and do the necessary cleanup. - */ - swap_after_unlock_page(page->offset); - } -#endif -} - -/* - * Transfer a page lock to a write request waiting for it. - */ -static inline void -transfer_page_lock(struct nfs_wreq *req) -{ - dprintk("NFS: transfer_page_lock\n"); - - req->wb_flags &= ~NFS_WRITE_WANTLOCK; - req->wb_flags |= NFS_WRITE_LOCKED; - rpc_wake_up_task(&req->wb_task); - - dprintk("NFS: wake up task %d (flags %x)\n", - req->wb_task.tk_pid, req->wb_flags); -} - -/* * Write a page synchronously. * Offset is the data offset within the page. */ @@ -195,7 +153,6 @@ inode->i_ino, fattr.fileid); } - nfs_unlock_page(page); return written? written : result; } @@ -220,11 +177,13 @@ } /* - * Find a write request for a given page + * Find a non-busy write request for a given page to + * try to combine with. */ static inline struct nfs_wreq * find_write_request(struct inode *inode, struct page *page) { + pid_t pid = current->pid; struct nfs_wreq *head, *req; dprintk("NFS: find_write_request(%x/%ld, %p)\n", @@ -232,8 +191,21 @@ if (!(req = head = NFS_WRITEBACK(inode))) return NULL; do { - if (req->wb_page == page) + /* + * We can't combine with canceled requests or + * requests that have already been started.. + */ + if (req->wb_flags & (NFS_WRITE_CANCELLED | NFS_WRITE_INPROGRESS)) + continue; + + if (req->wb_page == page && req->wb_pid == pid) return req; + + /* + * Ehh, don't keep too many tasks queued.. + */ + rpc_wake_up_task(&req->wb_task); + } while ((req = WB_NEXT(req)) != head); return NULL; } @@ -260,64 +232,13 @@ } /* - * Find a failed write request by pid - */ -static struct nfs_wreq * -find_failed_request(struct inode *inode, pid_t pid) -{ - struct nfs_wreq *head, *req; - - req = head = nfs_failed_requests; - while (req != NULL) { - if (req->wb_inode == inode && (pid == 0 || req->wb_pid == pid)) - return req; - if ((req = WB_NEXT(req)) == head) - break; - } - return NULL; -} - -/* - * Add a request to the failed list. - */ -static void -append_failed_request(struct nfs_wreq * req) -{ - static int old_max = 16; - - append_write_request(&nfs_failed_requests, req); - nr_failed_requests++; - if (nr_failed_requests >= old_max) { - printk("NFS: %d failed requests\n", nr_failed_requests); - old_max = old_max << 1; - } -} - -/* - * Remove a request from the failed list and free it. - */ -static void -remove_failed_request(struct nfs_wreq * req) -{ - remove_write_request(&nfs_failed_requests, req); - kfree(req); - nr_failed_requests--; -} - -/* * Find and release all failed requests for this inode. */ int nfs_check_failed_request(struct inode * inode) { - struct nfs_wreq * req; - int found = 0; - - while ((req = find_failed_request(inode, 0)) != NULL) { - remove_failed_request(req); - found++; - } - return found; + /* FIXME! */ + return 0; } /* @@ -334,6 +255,10 @@ dprintk("nfs: trying to update write request %p\n", req); + /* not contiguous? */ + if (rqlast < first || last < rqfirst) + return 0; + /* Check the credentials associated with this write request. * If the buffer is owned by the same user, we can happily * add our data without risking server permission problems. @@ -349,12 +274,25 @@ rqfirst = first; if (rqlast < last) rqlast = last; + req->wb_offset = rqfirst; req->wb_bytes = rqlast - rqfirst; + req->wb_count++; return 1; } +static inline void +free_write_request(struct nfs_wreq * req) +{ + if (!--req->wb_count) { + struct inode *inode = req->wb_inode; + remove_write_request(&NFS_WRITEBACK(inode), req); + kfree(req); + nr_write_requests--; + } +} + /* * Create and initialize a writeback request */ @@ -371,8 +309,7 @@ page->offset + offset, bytes); /* FIXME: Enforce hard limit on number of concurrent writes? */ - - wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_USER); + wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_KERNEL); if (!wreq) goto out_fail; memset(wreq, 0, sizeof(*wreq)); @@ -380,7 +317,7 @@ task = &wreq->wb_task; rpc_init_task(task, clnt, nfs_wback_result, RPC_TASK_NFSWRITE); task->tk_calldata = wreq; - task->tk_action = nfs_wback_lock; + task->tk_action = nfs_wback_begin; rpcauth_lookupcred(task); /* Obtain user creds */ if (task->tk_status < 0) @@ -393,6 +330,7 @@ wreq->wb_page = page; wreq->wb_offset = offset; wreq->wb_bytes = bytes; + wreq->wb_count = 2; /* One for the IO, one for us */ atomic_inc(&page->count); @@ -414,8 +352,7 @@ * Schedule a writeback RPC call. * If the server is congested, don't add to our backlog of queued * requests but call it synchronously. - * The function returns false if the page has been unlocked as the - * consequence of a synchronous write call. + * The function returns whether we should wait for the thing or not. * * FIXME: Here we could walk the inode's lock list to see whether the * page we're currently writing to has been write-locked by the caller. @@ -438,7 +375,6 @@ dprintk("NFS: %4d schedule_write_request (sync)\n", task->tk_pid); /* Page is already locked */ - req->wb_flags |= NFS_WRITE_LOCKED; rpc_clnt_sigmask(clnt, &oldmask); rpc_execute(task); rpc_clnt_sigunmask(clnt, &oldmask); @@ -450,39 +386,38 @@ rpc_sleep_on(&write_queue, task, NULL, NULL); } - return sync == 0; + return sync; } /* - * Wait for request to complete - * This is almost a copy of __wait_on_page + * Wait for request to complete. */ -static inline int +static int wait_on_write_request(struct nfs_wreq *req) { + struct rpc_clnt *clnt = NFS_CLIENT(req->wb_inode); struct wait_queue wait = { current, NULL }; - struct page *page = req->wb_page; - int retval; sigset_t oldmask; - struct rpc_clnt *clnt = NFS_CLIENT(req->wb_inode); + int retval; + + /* Make sure it's started.. */ + if (!WB_INPROGRESS(req)) + rpc_wake_up_task(&req->wb_task); rpc_clnt_sigmask(clnt, &oldmask); - add_wait_queue(&page->wait, &wait); - atomic_inc(&page->count); + add_wait_queue(&req->wb_wait, &wait); for (;;) { current->state = TASK_INTERRUPTIBLE; retval = 0; - if (!PageLocked(page)) + if (req->wb_flags & NFS_WRITE_COMPLETE) break; retval = -ERESTARTSYS; if (signalled()) break; schedule(); } - remove_wait_queue(&page->wait, &wait); + remove_wait_queue(&req->wb_wait, &wait); current->state = TASK_RUNNING; - /* N.B. page may have been unused, so we must use free_page() */ - free_page(page_address(page)); rpc_clnt_sigunmask(clnt, &oldmask); return retval; } @@ -505,21 +440,18 @@ * things with a page scheduled for an RPC call (e.g. invalidate it). */ int -nfs_updatepage(struct file *file, struct page *page, const char *buffer, - unsigned long offset, unsigned int count, int sync) +nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count, int sync) { struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; - u8 *page_addr = (u8 *) page_address(page); struct nfs_wreq *req; - int status = 0, page_locked = 1; + int synchronous = sync; + int retval; dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, count, page->offset+offset, sync); - set_bit(PG_locked, &page->flags); - /* * Try to find a corresponding request on the writeback queue. * If there is one, we can be sure that this request is not @@ -530,151 +462,54 @@ * After returning, generic_file_write will wait on the * page and retry the update. */ - if ((req = find_write_request(inode, page)) != NULL) { - if (update_write_request(req, offset, count)) { - /* N.B. check for a fault here and cancel the req */ - /* - * SECURITY - copy_from_user must zero the - * rest of the data after a fault! - */ - copy_from_user(page_addr + offset, buffer, count); - goto updated; - } - dprintk("NFS: wake up conflicting write request.\n"); - transfer_page_lock(req); - return 0; - } - - /* Copy data to page buffer. */ - status = -EFAULT; - if (copy_from_user(page_addr + offset, buffer, count)) - goto done; + req = find_write_request(inode, page); + if (req && update_write_request(req, offset, count)) + goto updated; - /* If wsize is smaller than page size, update and write + /* + * If wsize is smaller than page size, update and write * page synchronously. */ if (NFS_SERVER(inode)->wsize < PAGE_SIZE) return nfs_writepage_sync(dentry, inode, page, offset, count); /* Create the write request. */ - status = -ENOBUFS; req = create_write_request(dentry, inode, page, offset, count); if (!req) - goto done; + return -ENOBUFS; + + /* + * Ok, there's another user of this page with the new request.. + * Increment the usage count, and schedule the request (the + * end of the request will drop the usage count..) + */ + atomic_inc(&page->count); /* Schedule request */ - page_locked = schedule_write_request(req, sync); + synchronous = schedule_write_request(req, sync); updated: - /* - * If we wrote up to the end of the chunk, transmit request now. - * We should be a bit more intelligent about detecting whether a - * process accesses the file sequentially or not. - */ - if (page_locked && (offset + count >= PAGE_SIZE || sync)) - req->wb_flags |= NFS_WRITE_WANTLOCK; + if (req->wb_bytes == PAGE_SIZE) + set_bit(PG_uptodate, &page->flags); - /* If the page was written synchronously, return any error that - * may have happened; otherwise return the write count. */ - if (page_locked || (status = nfs_write_error(inode)) >= 0) - status = count; - -done: - /* Unlock page and wake up anyone sleeping on it */ - if (page_locked) { - if (req && WB_WANTLOCK(req)) { - transfer_page_lock(req); - /* rpc_execute(&req->wb_task); */ - if (sync) { - /* if signalled, ensure request is cancelled */ - if ((count = wait_on_write_request(req)) != 0) { - nfs_cancel_request(req); - status = count; - } - if ((count = nfs_write_error(inode)) < 0) - status = count; - } + retval = count; + if (synchronous) { + int status = wait_on_write_request(req); + if (status) { + nfs_cancel_request(req); + retval = status; } else { - if (status < 0) { -printk("NFS: %s/%s write failed, clearing bit\n", -dentry->d_parent->d_name.name, dentry->d_name.name); - clear_bit(PG_uptodate, &page->flags); - } - nfs_unlock_page(page); + status = req->wb_status; + if (status < 0) + retval = status; } - } - - dprintk("NFS: nfs_updatepage returns %d (isize %ld)\n", - status, inode->i_size); - return status; -} - -/* - * Flush out a dirty page. - */ -static void -nfs_flush_request(struct nfs_wreq *req) -{ - struct page *page = req->wb_page; - -#ifdef NFS_DEBUG_VERBOSE -if (req->wb_inode != page->inode) -printk("NFS: inode %ld no longer has page %p\n", req->wb_inode->i_ino, page); -#endif - dprintk("NFS: nfs_flush_request(%s/%s, @%ld)\n", - req->wb_dentry->d_parent->d_name.name, - req->wb_dentry->d_name.name, page->offset); - - req->wb_flags |= NFS_WRITE_WANTLOCK; - if (!test_and_set_bit(PG_locked, &page->flags)) { - transfer_page_lock(req); - } else { - printk(KERN_WARNING "NFS oops in %s: can't lock page!\n", - __FUNCTION__); - rpc_wake_up_task(&req->wb_task); - } -} - -/* - * Flush writeback requests. See nfs_flush_dirty_pages for details. - */ -static struct nfs_wreq * -nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len, - int invalidate) -{ - struct nfs_wreq *head, *req, *last = NULL; - off_t rqoffset, rqend, end; - - end = len? offset + len : 0x7fffffffUL; - - req = head = NFS_WRITEBACK(inode); - while (req != NULL) { - dprintk("NFS: %4d nfs_flush inspect %s/%s @%ld fl %x\n", - req->wb_task.tk_pid, - req->wb_dentry->d_parent->d_name.name, - req->wb_dentry->d_name.name, - req->wb_page->offset, req->wb_flags); - rqoffset = req->wb_page->offset + req->wb_offset; - rqend = rqoffset + req->wb_bytes; - if (rqoffset < end && offset < rqend && - (pid == 0 || req->wb_pid == pid)) { - if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) { -#ifdef NFS_DEBUG_VERBOSE -printk("nfs_flush: flushing inode=%ld, %d @ %lu\n", -req->wb_inode->i_ino, req->wb_bytes, rqoffset); -#endif - nfs_flush_request(req); - } - last = req; - } - if (invalidate) - req->wb_flags |= NFS_WRITE_INVALIDATE; - if ((req = WB_NEXT(req)) == head) - break; + if (retval < 0) + clear_bit(PG_uptodate, &page->flags); } - return last; + free_write_request(req); + return retval; } /* @@ -711,53 +546,67 @@ } /* - * Flush out all dirty pages belonging to a certain user process and - * maybe wait for the RPC calls to complete. + * Try to flush any dirty pages, returning a success marker.. * - * Another purpose of this function is sync()ing a file range before a - * write lock is released. This is what offset and length are for, even if - * this isn't used by the nlm module yet. + * Unlike "nfs_flush_dirty_pages()" this does not invalidate + * the writes if it is interrupted. The caller will instead + * look at the error code and gracefully fail to do what it + * wanted to do. */ int -nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len) +nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len) { - struct nfs_wreq *last = NULL; - int result = 0; + int retval; + + do { + struct nfs_wreq *req = NFS_WRITEBACK(inode); + struct nfs_wreq *head = req; - dprintk("NFS: flush_dirty_pages(%x/%ld for pid %d %ld/%ld)\n", - inode->i_dev, inode->i_ino, current->pid, offset, len); + if (!req) + return 0; - for (;;) { - /* Flush all pending writes for the pid and file region */ - last = nfs_flush_pages(inode, pid, offset, len, 0); - if (last == NULL) - break; - result = wait_on_write_request(last); - if (result) { - nfs_cancel_dirty(inode,pid); - break; + /* + * Iterate over all outstanding write requests, + * looking for any that are ours.. + */ + for (;;) { + if (!(req->wb_flags & NFS_WRITE_COMPLETE)) { + if (!pid || req->wb_pid == pid) + break; + } + req = WB_NEXT(req); + if (req == head) + return 0; } - } - return result; -} + req->wb_count++; + retval = wait_on_write_request(req); + free_write_request(req); + } while (!retval); + return retval; +} /* - * Flush out any pending write requests and flag that they be discarded - * after the write is complete. + * Flush out all dirty pages belonging to a certain user process and + * maybe wait for the RPC calls to complete. * - * This function is called from nfs_refresh_inode just before it calls - * invalidate_inode_pages. After nfs_flush_pages returns, we can be sure - * that all dirty pages are locked, so that invalidate_inode_pages does - * not throw away any dirty pages. + * Another purpose of this function is sync()ing a file range before a + * write lock is released. This is what offset and length are for, even if + * this isn't used by the nlm module yet. */ +int +nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len) +{ + int retval = nfs_flush_pages(inode, pid, offset, len); + if (retval) + nfs_cancel_dirty(inode,pid); + return retval; +} + void nfs_invalidate_pages(struct inode *inode) { - dprintk("NFS: nfs_invalidate_pages(%x/%ld)\n", - inode->i_dev, inode->i_ino); - - nfs_flush_pages(inode, 0, 0, 0, 1); + nfs_cancel_dirty(inode,0); } /* @@ -795,21 +644,8 @@ int nfs_check_error(struct inode *inode) { - struct nfs_wreq *req; - int status = 0; - - dprintk("nfs: checking for write error inode %04x/%ld\n", - inode->i_dev, inode->i_ino); - - req = find_failed_request(inode, current->pid); - if (req) { - dprintk("nfs: write error %d inode %04x/%ld\n", - req->wb_task.tk_status, inode->i_dev, inode->i_ino); - - status = req->wb_task.tk_status; - remove_failed_request(req); - } - return status; + /* FIXME! */ + return 0; } /* @@ -819,23 +655,16 @@ * set up the RPC call info, and pass to the call FSM. */ static void -nfs_wback_lock(struct rpc_task *task) +nfs_wback_begin(struct rpc_task *task) { struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata; struct page *page = req->wb_page; struct dentry *dentry = req->wb_dentry; - dprintk("NFS: %4d nfs_wback_lock (%s/%s, status=%d flags=%x)\n", + dprintk("NFS: %4d nfs_wback_begin (%s/%s, status=%d flags=%x)\n", task->tk_pid, dentry->d_parent->d_name.name, dentry->d_name.name, task->tk_status, req->wb_flags); - if (!WB_HAVELOCK(req)) - req->wb_flags |= NFS_WRITE_WANTLOCK; - - if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags)) - goto out_locked; - req->wb_flags &= ~NFS_WRITE_WANTLOCK; - req->wb_flags |= NFS_WRITE_LOCKED; task->tk_status = 0; /* Setup the task struct for a writeback call */ @@ -848,12 +677,6 @@ req->wb_flags |= NFS_WRITE_INPROGRESS; return; - -out_locked: - printk("NFS: page already locked in writeback_lock!\n"); - task->tk_timeout = 2 * HZ; - rpc_sleep_on(&write_queue, task, NULL, NULL); - return; } /* @@ -873,15 +696,10 @@ /* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */ req->wb_flags |= NFS_WRITE_COMPLETE; + req->wb_status = status; + if (status < 0) { - /* - * An error occurred. Report the error back to the - * application by adding the request to the failed - * requests list. - */ - if (find_failed_request(inode, req->wb_pid)) - status = 0; - clear_bit(PG_uptodate, &page->flags); + req->wb_flags |= NFS_WRITE_INVALIDATE; } else if (!WB_CANCELLED(req)) { struct nfs_fattr *fattr = &req->wb_fattr; /* Update attributes as result of writeback. @@ -911,31 +729,27 @@ } } - /* - * This call might block, so we defer removing the request - * from the inode's writeback list. - */ rpc_release_task(task); if (WB_INVALIDATE(req)) clear_bit(PG_uptodate, &page->flags); - if (WB_HAVELOCK(req)) - nfs_unlock_page(page); + __free_page(page); + + wake_up(&req->wb_wait); + /* - * Now it's safe to remove the request from the inode's - * writeback list and wake up any tasks sleeping on it. - * If the request failed, add it to the failed list. + * FIXME! + * + * We should not free the request here if it has pending + * error status on it. We should just leave it around, to + * let the error be collected later. However, the error + * collecting routines are too stupid for that right now, + * so we just drop the error on the floor at this point + * for any async writes. + * + * This should not be a major headache to fix, but I want + * to validate basic operations first. */ - remove_write_request(&NFS_WRITEBACK(inode), req); - - if (status >= 0) - kfree(req); - else { - dprintk("NFS: %4d saving write failure code\n", task->tk_pid); - append_failed_request(req); - } - - free_page(page_address(page)); - nr_write_requests--; + free_write_request(req); } diff -u --recursive --new-file v2.1.127/linux/fs/open.c linux/fs/open.c --- v2.1.127/linux/fs/open.c Wed Aug 26 11:37:43 1998 +++ linux/fs/open.c Wed Nov 11 11:49:59 1998 @@ -626,7 +626,7 @@ * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ -static int do_open(const char * filename, int flags, int mode, int fd) +struct file *filp_open(const char * filename, int flags, int mode) { struct inode * inode; struct dentry * dentry; @@ -667,8 +667,7 @@ } f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - fd_install(fd, f); - return 0; + return f; cleanup_all: if (f->f_mode & FMODE_WRITE) @@ -679,7 +678,19 @@ cleanup_file: put_filp(f); out: - return error; + return ERR_PTR(error); +} + +/* should probably go into sys_open() */ +static int do_open(const char * filename, int flags, int mode, int fd) +{ + struct file * f; + + f = filp_open(filename, flags, mode); + if (IS_ERR(f)) + return PTR_ERR(f); + fd_install(fd, f); + return 0; } /* diff -u --recursive --new-file v2.1.127/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.127/linux/fs/proc/array.c Sun Nov 8 14:03:07 1998 +++ linux/fs/proc/array.c Sun Nov 8 14:06:17 1998 @@ -24,11 +24,11 @@ * * * Bruno Haible : remove 4K limit for the maps file - * + * * * Yves Arrouye : remove removal of trailing spaces in get_array. * - + * * Jerome Forissier : added per-CPU time information to /proc/stat * and /proc//cpu extension * @@ -37,6 +37,11 @@ * Hans Marcus * * aeb@cwi.nl : /proc/partitions + * + * + * Alan Cox : security fixes. + * + * */ #include @@ -1326,6 +1331,46 @@ return -EBADF; } +static int process_unauthorized(int type, int pid) +{ + struct task_struct *p; + uid_t euid; /* Save the euid keep the lock short */ + + read_lock(&tasklist_lock); + + /* + * Grab the lock, find the task, save the uid and + * check it has an mm still (ie its not dead) + */ + + p = find_task_by_pid(pid); + if(p) + { + euid=p->euid; + if(!p->mm) /* Scooby scooby doo where are you ? */ + p=NULL; + } + + read_unlock(&tasklist_lock); + + if (!p) + return 1; + + switch(type) + { + case PROC_PID_STATUS: + case PROC_PID_STATM: + case PROC_PID_STAT: + case PROC_PID_MAPS: + case PROC_PID_CMDLINE: + return 0; + } + if(capable(CAP_DAC_OVERRIDE) || current->fsuid == euid) + return 0; + return 1; +} + + static int get_process_array(char * page, int pid, int type) { switch (type) { @@ -1377,6 +1422,13 @@ type &= 0x0000ffff; start = NULL; dp = (struct proc_dir_entry *) inode->u.generic_ip; + + if (pid && process_unauthorized(type, pid)) + { + free_page(page); + return -EIO; + } + if (dp->get_info) length = dp->get_info((char *)page, &start, *ppos, count, 0); diff -u --recursive --new-file v2.1.127/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.127/linux/fs/proc/root.c Mon Sep 28 10:51:35 1998 +++ linux/fs/proc/root.c Sun Nov 8 14:06:17 1998 @@ -827,6 +827,7 @@ inode = proc_get_inode(dir->i_sb, ino, &proc_pid); if (!inode) return -EINVAL; + inode->i_flags|=S_IMMUTABLE; } dentry->d_op = &proc_dentry_operations; @@ -943,6 +944,7 @@ for (i = 0; i < nr_pids; i++) { int pid = pid_array[i]; + ino_t ino = (pid << 16) + PROC_PID_INO; unsigned long j = PROC_NUMBUF; do { @@ -951,7 +953,7 @@ pid /= 10; } while (pid); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0) break; filp->f_pos++; } diff -u --recursive --new-file v2.1.127/linux/fs/qnx4/file.c linux/fs/qnx4/file.c --- v2.1.127/linux/fs/qnx4/file.c Sat Sep 5 16:46:41 1998 +++ linux/fs/qnx4/file.c Thu Nov 12 11:44:09 1998 @@ -180,11 +180,7 @@ struct inode_operations qnx4_file_inode_operations = { &qnx4_file_operations, /* default file operations */ -#ifdef CONFIG_QNX4FS_RW - qnx4_create, /* create */ -#else - NULL, -#endif + NULL, /* create? It's not a directory */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ diff -u --recursive --new-file v2.1.127/linux/fs/qnx4/symlinks.c linux/fs/qnx4/symlinks.c --- v2.1.127/linux/fs/qnx4/symlinks.c Sat Sep 5 16:46:41 1998 +++ linux/fs/qnx4/symlinks.c Thu Nov 12 11:44:09 1998 @@ -32,11 +32,7 @@ struct inode_operations qnx4_symlink_inode_operations = { NULL, /* no file-operations */ -#ifdef CONFIG_QNX4FS_RW - qnx4_create, /* create */ -#else - NULL, -#endif + NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ diff -u --recursive --new-file v2.1.127/linux/fs/readdir.c linux/fs/readdir.c --- v2.1.127/linux/fs/readdir.c Tue Mar 10 10:03:34 1998 +++ linux/fs/readdir.c Thu Nov 12 09:58:32 1998 @@ -6,12 +6,9 @@ #include #include -#include #include #include #include -#include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/fs/smbfs/file.c linux/fs/smbfs/file.c --- v2.1.127/linux/fs/smbfs/file.c Wed Aug 26 11:37:43 1998 +++ linux/fs/smbfs/file.c Thu Nov 12 11:49:25 1998 @@ -195,40 +195,15 @@ } static int -smb_updatepage(struct file *file, struct page *page, const char *buffer, - unsigned long offset, unsigned int count, int sync) +smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count, int sync) { struct dentry *dentry = file->f_dentry; - unsigned long page_addr = page_address(page); - int result; pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, count, page->offset+offset, sync); -#ifdef SMBFS_PARANOIA - if (test_bit(PG_locked, &page->flags)) - printk("smb_updatepage: page already locked!\n"); -#endif - set_bit(PG_locked, &page->flags); - atomic_inc(&page->count); - - if (copy_from_user((char *) page_addr + offset, buffer, count)) - goto bad_fault; - result = smb_writepage_sync(dentry, page, offset, count); -out: - free_page(page_addr); - return result; - -bad_fault: -#ifdef SMBFS_PARANOIA -printk("smb_updatepage: fault at addr=%lu, offset=%lu, buffer=%p\n", -page_addr, offset, buffer); -#endif - result = -EFAULT; - clear_bit(PG_uptodate, &page->flags); - smb_unlock_page(page); - goto out; + return smb_writepage_sync(dentry, page, offset, count); } static ssize_t diff -u --recursive --new-file v2.1.127/linux/fs/super.c linux/fs/super.c --- v2.1.127/linux/fs/super.c Fri Oct 9 13:27:15 1998 +++ linux/fs/super.c Wed Nov 11 11:49:59 1998 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -663,10 +664,7 @@ * are no quotas running any more. Just turn them on again. */ DQUOT_OFF(dev); - -#ifdef CONFIG_BSD_PROCESS_ACCT - (void) acct_auto_close(dev); -#endif + acct_auto_close(dev); /* * If we may have to abort operations to get out of this @@ -971,6 +969,8 @@ */ shrink_dcache_sb(sb); fsync_dev(sb->s_dev); + if (flags & MS_RDONLY) + acct_auto_close(sb->s_dev); retval = do_remount_sb(sb, flags, data); } dput(dentry); diff -u --recursive --new-file v2.1.127/linux/fs/sysv/dir.c linux/fs/sysv/dir.c --- v2.1.127/linux/fs/sysv/dir.c Wed Aug 26 11:37:43 1998 +++ linux/fs/sysv/dir.c Wed Nov 11 11:49:59 1998 @@ -62,7 +62,7 @@ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ - sysv_truncate, /* truncate */ + NULL, /* truncate */ NULL /* permission */ }; diff -u --recursive --new-file v2.1.127/linux/fs/ufs/dir.c linux/fs/ufs/dir.c --- v2.1.127/linux/fs/ufs/dir.c Fri Oct 23 22:01:22 1998 +++ linux/fs/ufs/dir.c Thu Nov 12 11:44:37 1998 @@ -220,8 +220,8 @@ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ - ufs_bmap, /* bmap */ - ufs_truncate, /* truncate */ + NULL, /* bmap */ + NULL, /* truncate */ ufs_permission, /* permission */ NULL, /* smap */ }; diff -u --recursive --new-file v2.1.127/linux/fs/vfat/namei.c linux/fs/vfat/namei.c --- v2.1.127/linux/fs/vfat/namei.c Wed Sep 9 14:51:09 1998 +++ linux/fs/vfat/namei.c Thu Nov 12 11:44:09 1998 @@ -1846,7 +1846,7 @@ NULL, /* followlink */ NULL, /* readpage */ NULL, /* writepage */ - fat_bmap, /* bmap */ + NULL, /* bmap */ NULL, /* truncate */ NULL /* permission */ }; diff -u --recursive --new-file v2.1.127/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h --- v2.1.127/linux/include/asm-alpha/spinlock.h Fri Oct 23 22:01:22 1998 +++ linux/include/asm-alpha/spinlock.h Wed Nov 11 13:15:07 1998 @@ -5,9 +5,18 @@ #ifndef __SMP__ -/* gcc 2.7.2 can crash initializing an empty structure. */ -typedef struct { int dummy; } spinlock_t; -#define SPIN_LOCK_UNLOCKED { 0 } +/* + * Your basic spinlocks, allowing only a single CPU anywhere + * + * Gcc-2.7.x has a nasty bug with empty initializers. + */ +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) + typedef struct { } spinlock_t; + #define SPIN_LOCK_UNLOCKED (spinlock_t) { } +#else + typedef struct { int gcc_is_buggy; } spinlock_t; + #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +#endif #define spin_lock_init(lock) ((void) 0) #define spin_lock(lock) ((void) 0) @@ -29,9 +38,16 @@ * can "mix" irq-safe locks - any writer needs to get a * irq-safe write-lock, but readers can get non-irqsafe * read-locks. + * + * Gcc-2.7.x has a nasty bug with empty initializers. */ -typedef struct { int dummy; } rwlock_t; -#define RW_LOCK_UNLOCKED { 0 } +#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) + typedef struct { } rwlock_t; + #define RW_LOCK_UNLOCKED (rwlock_t) { } +#else + typedef struct { int gcc_is_buggy; } rwlock_t; + #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } +#endif #define read_lock(lock) ((void) 0) #define read_unlock(lock) ((void) 0) diff -u --recursive --new-file v2.1.127/linux/include/asm-i386/dma.h linux/include/asm-i386/dma.h --- v2.1.127/linux/include/asm-i386/dma.h Fri Oct 9 13:27:15 1998 +++ linux/include/asm-i386/dma.h Thu Nov 12 00:41:55 1998 @@ -161,8 +161,6 @@ dma_outb(dmanr | 4, DMA1_MASK_REG); else dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); - /* I hate voodoo programming but .. */ - udelay(20); } /* Clear the 'DMA Pointer Flip Flop'. diff -u --recursive --new-file v2.1.127/linux/include/asm-i386/shmparam.h linux/include/asm-i386/shmparam.h --- v2.1.127/linux/include/asm-i386/shmparam.h Mon Sep 11 23:49:24 1995 +++ linux/include/asm-i386/shmparam.h Sun Nov 8 14:06:18 1998 @@ -33,7 +33,9 @@ * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). */ -#define SHMMAX 0x1000000 /* max shared seg size (bytes) */ +#define SHMMAX 0x2000000 /* max shared seg size (bytes) */ +/* Try not to change the default shipped SHMMAX - people rely on it */ + #define SHMMIN 1 /* really PAGE_SIZE */ /* min shared seg size (bytes) */ #define SHMMNI (1<<_SHM_ID_BITS) /* max num of segs system wide */ #define SHMALL /* max shm system wide (pages) */ \ diff -u --recursive --new-file v2.1.127/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h --- v2.1.127/linux/include/asm-m68k/ide.h Tue Jun 23 10:01:28 1998 +++ linux/include/asm-m68k/ide.h Wed Nov 11 11:50:00 1998 @@ -146,34 +146,36 @@ if (_nr & 15) { \ _tmp = (_nr & 15) - 1; \ asm volatile ( \ - "1: movew %2@,%3@+; dbra %4,1b" \ + "1: movew %2@,%0@+; dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + if (_nr >> 4) { \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "movew %2@,%0@+; " \ + "dbra %1,1b" \ : "=a" (_buf), "=d" (_tmp) \ : "a" (_port), "0" (_buf), \ "1" (_tmp)); \ } \ - _tmp = (_nr >> 4) - 1; \ - asm volatile ( \ - "1: " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "movew %2@,%3@+; " \ - "dbra %4,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ }) #define outsw(port, buf, nr) ({ \ @@ -185,34 +187,36 @@ if (_nr & 15) { \ _tmp = (_nr & 15) - 1; \ asm volatile ( \ - "1: movew %3@,%2@+; dbra %4,1b" \ + "1: movew %0@+,%2@; dbra %1,1b" \ + : "=a" (_buf), "=d" (_tmp) \ + : "a" (_port), "0" (_buf), \ + "1" (_tmp)); \ + } \ + if (_nr >> 4) { \ + _tmp = (_nr >> 4) - 1; \ + asm volatile ( \ + "1: " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "movew %0@+,%2@; " \ + "dbra %1,1b" \ : "=a" (_buf), "=d" (_tmp) \ : "a" (_port), "0" (_buf), \ "1" (_tmp)); \ } \ - _tmp = (_nr >> 4) - 1; \ - asm volatile ( \ - "1: " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "movew %3@+,%2@; " \ - "dbra %4,1b" \ - : "=a" (_buf), "=d" (_tmp) \ - : "a" (_port), "0" (_buf), \ - "1" (_tmp)); \ }) #ifdef CONFIG_ATARI diff -u --recursive --new-file v2.1.127/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h --- v2.1.127/linux/include/asm-m68k/serial.h Tue Jun 23 10:01:28 1998 +++ linux/include/asm-m68k/serial.h Wed Nov 11 11:50:00 1998 @@ -336,9 +336,21 @@ if (tty->flip.count >= TTY_FLIPBUF_SIZE) return; tty->flip.count++; - if (err == TTY_BREAK) { + switch(err) { + case TTY_BREAK: + info->icount.brk++; if (info->flags & ASYNC_SAK) do_SAK(tty); + break; + case TTY_PARITY: + info->icount.parity++; + break; + case TTY_OVERRUN: + info->icount.overrun++; + break; + case TTY_FRAME: + info->icount.frame++; + break; } *tty->flip.flag_buf_ptr++ = err; *tty->flip.char_buf_ptr++ = ch; diff -u --recursive --new-file v2.1.127/linux/include/linux/acct.h linux/include/linux/acct.h --- v2.1.127/linux/include/linux/acct.h Fri Jul 31 17:05:53 1998 +++ linux/include/linux/acct.h Thu Nov 12 00:30:56 1998 @@ -76,8 +76,10 @@ #include #ifdef CONFIG_BSD_PROCESS_ACCT +extern void acct_auto_close(kdev_t dev); extern int acct_process(long exitcode); #else +#define acct_auto_close(x) do { } while (0) #define acct_process(x) do { } while (0) #endif diff -u --recursive --new-file v2.1.127/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.127/linux/include/linux/fs.h Fri Oct 23 22:01:26 1998 +++ linux/include/linux/fs.h Thu Nov 12 00:32:45 1998 @@ -605,8 +605,7 @@ void (*truncate) (struct inode *); int (*permission) (struct inode *, int); int (*smap) (struct inode *,int); - int (*updatepage) (struct file *, struct page *, const char *, - unsigned long, unsigned int, int); + int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int); int (*revalidate) (struct dentry *); }; @@ -687,6 +686,7 @@ extern int get_unused_fd(void); extern void put_unused_fd(unsigned int); extern int close_fp(struct file *, fl_owner_t id); +extern struct file *filp_open(const char *, int, int); extern char * getname(const char * filename); extern void putname(char * name); diff -u --recursive --new-file v2.1.127/linux/include/linux/kernel.h linux/include/linux/kernel.h --- v2.1.127/linux/include/linux/kernel.h Sun Nov 8 14:03:11 1998 +++ linux/include/linux/kernel.h Sun Nov 8 14:12:59 1998 @@ -46,6 +46,7 @@ NORET_TYPE void do_exit(long error_code) ATTRIB_NORET; extern unsigned long simple_strtoul(const char *,char **,unsigned int); +extern long simple_strtol(const char *,char **,unsigned int); extern int sprintf(char * buf, const char * fmt, ...); extern int vsprintf(char *buf, const char *, va_list); diff -u --recursive --new-file v2.1.127/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h --- v2.1.127/linux/include/linux/nfs_fs.h Fri Jul 31 17:06:29 1998 +++ linux/include/linux/nfs_fs.h Thu Nov 12 01:02:48 1998 @@ -101,31 +101,29 @@ struct dentry * wb_dentry; /* dentry referenced */ struct inode * wb_inode; /* inode referenced */ struct page * wb_page; /* page to be written */ + struct wait_queue * wb_wait; /* wait for completion */ unsigned int wb_offset; /* offset within page */ unsigned int wb_bytes; /* dirty range */ + unsigned int wb_count; /* user count */ + int wb_status; pid_t wb_pid; /* owner process */ unsigned short wb_flags; /* status flags */ struct nfs_writeargs wb_args; /* NFS RPC stuff */ struct nfs_fattr wb_fattr; /* file attributes */ }; -#define wb_status wb_task.tk_status #define WB_NEXT(req) ((struct nfs_wreq *) ((req)->wb_list.next)) /* * Various flags for wb_flags */ -#define NFS_WRITE_WANTLOCK 0x0001 /* needs to lock page */ -#define NFS_WRITE_LOCKED 0x0002 /* holds lock on page */ #define NFS_WRITE_CANCELLED 0x0004 /* has been cancelled */ #define NFS_WRITE_UNCOMMITTED 0x0008 /* written but uncommitted (NFSv3) */ #define NFS_WRITE_INVALIDATE 0x0010 /* invalidate after write */ #define NFS_WRITE_INPROGRESS 0x0100 /* RPC call in progress */ #define NFS_WRITE_COMPLETE 0x0200 /* RPC call completed */ -#define WB_WANTLOCK(req) ((req)->wb_flags & NFS_WRITE_WANTLOCK) -#define WB_HAVELOCK(req) ((req)->wb_flags & NFS_WRITE_LOCKED) #define WB_CANCELLED(req) ((req)->wb_flags & NFS_WRITE_CANCELLED) #define WB_UNCOMMITTED(req) ((req)->wb_flags & NFS_WRITE_UNCOMMITTED) #define WB_INVALIDATE(req) ((req)->wb_flags & NFS_WRITE_INVALIDATE) @@ -217,11 +215,11 @@ extern int nfs_find_dentry_request(struct inode *, struct dentry *); extern int nfs_check_failed_request(struct inode *); extern int nfs_check_error(struct inode *); +extern int nfs_flush_pages(struct inode *, pid_t, off_t, off_t); extern int nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t); extern int nfs_truncate_dirty_pages(struct inode *, unsigned long); extern void nfs_invalidate_pages(struct inode *); -extern int nfs_updatepage(struct file *, struct page *, const char *, - unsigned long, unsigned int, int); +extern int nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int); /* * linux/fs/nfs/read.c @@ -246,13 +244,10 @@ return _nfs_revalidate_inode(server, dentry); } -extern struct nfs_wreq * nfs_failed_requests; static inline int nfs_write_error(struct inode *inode) { - if (nfs_failed_requests == NULL) - return 0; - return nfs_check_error(inode); + return NFS_WRITEBACK(inode) && nfs_check_error(inode); } /* NFS root */ diff -u --recursive --new-file v2.1.127/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.127/linux/include/linux/sched.h Sun Nov 8 14:03:11 1998 +++ linux/include/linux/sched.h Thu Nov 12 09:58:32 1998 @@ -20,7 +20,6 @@ #include #include #include -#include #include /* @@ -65,11 +64,9 @@ extern int last_pid; #include -#include #include #include #include -#include #include #include @@ -457,7 +454,6 @@ #define CURRENT_TIME (xtime.tv_sec) extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode)); -extern void FASTCALL(sleep_on(struct wait_queue ** p)); extern void FASTCALL(sleep_on(struct wait_queue ** p)); extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p)); extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p, diff -u --recursive --new-file v2.1.127/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.1.127/linux/include/linux/sysctl.h Sun Nov 8 14:03:12 1998 +++ linux/include/linux/sysctl.h Wed Nov 11 11:50:50 1998 @@ -44,99 +44,103 @@ /* For internal pattern-matching use only: */ #ifdef __KERNEL__ -#define CTL_ANY -1 /* Matches any name */ +#define CTL_ANY -1 /* Matches any name */ #define CTL_NONE 0 #endif enum { -/*1*/ CTL_KERN=1, /* General kernel info and control */ - CTL_VM, /* VM management */ - CTL_NET, /* Networking */ - CTL_PROC, /* Process info */ - CTL_FS, /* Filesystems */ - CTL_DEBUG, /* Debugging */ -/*7*/ CTL_DEV, /* Devices */ + CTL_KERN=1, /* General kernel info and control */ + CTL_VM=2, /* VM management */ + CTL_NET=3, /* Networking */ + CTL_PROC=4, /* Process info */ + CTL_FS=5, /* Filesystems */ + CTL_DEBUG=6, /* Debugging */ + CTL_DEV=7, /* Devices */ }; /* CTL_KERN names: */ enum { -/*1*/ KERN_OSTYPE=1, /* string: system version */ - KERN_OSRELEASE, /* string: system release */ - KERN_OSREV, /* int: system revision */ - KERN_VERSION, /* string: compile time info */ - KERN_SECUREMASK, /* struct: maximum rights mask */ - KERN_PROF, /* table: profiling information */ - KERN_NODENAME, -/*8*/ KERN_DOMAINNAME, -/*14*/ KERN_SECURELVL=14, /* int: system security level */ - KERN_PANIC, /* int: panic timeout */ -/*16*/ KERN_REALROOTDEV, /* real root device to mount after initrd */ -/*19*/ KERN_JAVA_INTERPRETER=19,/* path to Java(tm) interpreter */ -/*20*/ KERN_JAVA_APPLETVIEWER, /* path to Java(tm) appletviewer */ - KERN_SPARC_REBOOT, /* reboot command on Sparc */ - KERN_CTLALTDEL, /* int: allow ctl-alt-del to reboot */ - KERN_PRINTK, /* sturct: control printk logging parameters */ - KERN_NAMETRANS, /* Name translation */ - KERN_PPC_HTABRECLAIM, /* turn htab reclaimation on/off on PPC */ - KERN_PPC_ZEROPAGED, /* turn idle page zeroing on/off on PPC */ - KERN_PPC_POWERSAVE_NAP, /* use nap mode for power saving */ - KERN_PPC_L2CR, /* l2cr register on PPC */ - KERN_MODPROBE, -/*29*/ KERN_SG_BIG_BUFF + KERN_OSTYPE=1, /* string: system version */ + KERN_OSRELEASE=2, /* string: system release */ + KERN_OSREV=3, /* int: system revision */ + KERN_VERSION=4, /* string: compile time info */ + KERN_SECUREMASK=5, /* struct: maximum rights mask */ + KERN_PROF=6, /* table: profiling information */ + KERN_NODENAME=7, + KERN_DOMAINNAME=8, + + KERN_SECURELVL=14, /* int: system security level */ + KERN_PANIC=15, /* int: panic timeout */ + KERN_REALROOTDEV=16, /* real root device to mount after initrd */ + + KERN_JAVA_INTERPRETER=19, /* path to Java(tm) interpreter */ + KERN_JAVA_APPLETVIEWER=20, /* path to Java(tm) appletviewer */ + KERN_SPARC_REBOOT=21, /* reboot command on Sparc */ + KERN_CTLALTDEL=22, /* int: allow ctl-alt-del to reboot */ + KERN_PRINTK=23, /* struct: control printk logging parameters */ + KERN_NAMETRANS=24, /* Name translation */ + KERN_PPC_HTABRECLAIM=25, /* turn htab reclaimation on/off on PPC */ + KERN_PPC_ZEROPAGED=26, /* turn idle page zeroing on/off on PPC */ + KERN_PPC_POWERSAVE_NAP=27, /* use nap mode for power saving */ + KERN_MODPROBE=28, + KERN_SG_BIG_BUFF=29, + KERN_ACCT=30, /* BSD process accounting parameters */ + KERN_PPC_L2CR=31, /* l2cr register on PPC */ }; /* CTL_VM names: */ enum { -/*1*/ VM_SWAPCTL=1, /* struct: Set vm swapping control */ - VM_SWAPOUT, /* int: Background pageout interval */ - VM_FREEPG, /* struct: Set free page thresholds */ - VM_BDFLUSH, /* struct: Control buffer cache flushing */ - VM_OVERCOMMIT_MEMORY, /* Turn off the virtual memory safety limit */ - VM_BUFFERMEM, /* struct: Set buffer memory thresholds */ - VM_PAGECACHE, /* struct: Set cache memory thresholds */ - VM_PAGERDAEMON, /* struct: Control kswapd behaviour */ -/*9*/ VM_PGT_CACHE /* struct: Set page table cache parameters */ + VM_SWAPCTL=1, /* struct: Set vm swapping control */ + VM_SWAPOUT=2, /* int: Background pageout interval */ + VM_FREEPG=3, /* struct: Set free page thresholds */ + VM_BDFLUSH=4, /* struct: Control buffer cache flushing */ + VM_OVERCOMMIT_MEMORY=5, /* Turn off the virtual memory safety limit */ + VM_BUFFERMEM=6, /* struct: Set buffer memory thresholds */ + VM_PAGECACHE=7, /* struct: Set cache memory thresholds */ + VM_PAGERDAEMON=8, /* struct: Control kswapd behaviour */ + VM_PGT_CACHE=9 /* struct: Set page table cache parameters */ }; /* CTL_NET names: */ enum { -/*1*/ NET_CORE=1, - NET_ETHER, - NET_802, - NET_UNIX, - NET_IPV4, - NET_IPX, - NET_ATALK, - NET_NETROM, - NET_AX25, -/*10*/ NET_BRIDGE, - NET_ROSE, - NET_IPV6, - NET_X25, - NET_TR, -/*15*/ NET_DECNET + NET_CORE=1, + NET_ETHER=2, + NET_802=3, + NET_UNIX=4, + NET_IPV4=5, + NET_IPX=6, + NET_ATALK=7, + NET_NETROM=8, + NET_AX25=9, + NET_BRIDGE=10, + NET_ROSE=11, + NET_IPV6=12, + NET_X25=13, + NET_TR=14, + NET_DECNET=15 }; /* /proc/sys/net/core */ enum { -/*1*/ NET_CORE_WMEM_MAX=1, - NET_CORE_RMEM_MAX, - NET_CORE_WMEM_DEFAULT, - NET_CORE_RMEM_DEFAULT, - NET_CORE_MAX_BACKLOG, - NET_CORE_FASTROUTE, - NET_CORE_MSG_COST, - NET_CORE_MSG_BURST, -/*10*/ NET_CORE_OPTMEM_MAX, + NET_CORE_WMEM_MAX=1, + NET_CORE_RMEM_MAX=2, + NET_CORE_WMEM_DEFAULT=3, + NET_CORE_RMEM_DEFAULT=4, +/* was NET_CORE_DESTROY_DELAY */ + NET_CORE_MAX_BACKLOG=6, + NET_CORE_FASTROUTE=7, + NET_CORE_MSG_COST=8, + NET_CORE_MSG_BURST=9, + NET_CORE_OPTMEM_MAX=10, }; /* /proc/sys/net/ethernet */ @@ -147,143 +151,143 @@ enum { -/*1*/ NET_UNIX_DESTROY_DELAY=1, -/*2*/ NET_UNIX_DELETE_DELAY, + NET_UNIX_DESTROY_DELAY=1, + NET_UNIX_DELETE_DELAY=2, }; /* /proc/sys/net/ipv4 */ enum { /* v2.0 compatibile variables */ -/*8*/ NET_IPV4_FORWARD = 8, - NET_IPV4_DYNADDR = 9, + NET_IPV4_FORWARD=8, + NET_IPV4_DYNADDR=9, -/*16*/ NET_IPV4_CONF = 16, - NET_IPV4_NEIGH = 17, - NET_IPV4_ROUTE = 18, - NET_IPV4_FIB_HASH = 19, - -/*33*/ NET_IPV4_TCP_TIMESTAMPS=33, - NET_IPV4_TCP_WINDOW_SCALING, - NET_IPV4_TCP_SACK, - NET_IPV4_TCP_RETRANS_COLLAPSE, - NET_IPV4_DEFAULT_TTL, - NET_IPV4_AUTOCONFIG, - NET_IPV4_NO_PMTU_DISC, -/*40*/ NET_IPV4_TCP_SYN_RETRIES, - NET_IPV4_IPFRAG_HIGH_THRESH, - NET_IPV4_IPFRAG_LOW_THRESH, - NET_IPV4_IPFRAG_TIME, - NET_IPV4_TCP_MAX_KA_PROBES, - NET_IPV4_TCP_KEEPALIVE_TIME, - NET_IPV4_TCP_KEEPALIVE_PROBES, - NET_IPV4_TCP_RETRIES1, - NET_IPV4_TCP_RETRIES2, - NET_IPV4_TCP_FIN_TIMEOUT, -/*50*/ NET_IPV4_IP_MASQ_DEBUG, - NET_TCP_SYNCOOKIES, - NET_TCP_STDURG, - NET_TCP_RFC1337, - NET_TCP_SYN_TAILDROP, - NET_TCP_MAX_SYN_BACKLOG, - NET_IPV4_LOCAL_PORT_RANGE, - NET_IPV4_ICMP_ECHO_IGNORE_ALL, - NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, - NET_IPV4_ICMP_SOURCEQUENCH_RATE, -/*60*/ NET_IPV4_ICMP_DESTUNREACH_RATE, - NET_IPV4_ICMP_TIMEEXCEED_RATE, - NET_IPV4_ICMP_PARAMPROB_RATE, -/*63*/ NET_IPV4_ICMP_ECHOREPLY_RATE, + NET_IPV4_CONF=16, + NET_IPV4_NEIGH=17, + NET_IPV4_ROUTE=18, + NET_IPV4_FIB_HASH=19, + + NET_IPV4_TCP_TIMESTAMPS=33, + NET_IPV4_TCP_WINDOW_SCALING=34, + NET_IPV4_TCP_SACK=35, + NET_IPV4_TCP_RETRANS_COLLAPSE=36, + NET_IPV4_DEFAULT_TTL=37, + NET_IPV4_AUTOCONFIG=38, + NET_IPV4_NO_PMTU_DISC=39, + NET_IPV4_TCP_SYN_RETRIES=40, + NET_IPV4_IPFRAG_HIGH_THRESH=41, + NET_IPV4_IPFRAG_LOW_THRESH=42, + NET_IPV4_IPFRAG_TIME=43, + NET_IPV4_TCP_MAX_KA_PROBES=44, + NET_IPV4_TCP_KEEPALIVE_TIME=45, + NET_IPV4_TCP_KEEPALIVE_PROBES=46, + NET_IPV4_TCP_RETRIES1=47, + NET_IPV4_TCP_RETRIES2=48, + NET_IPV4_TCP_FIN_TIMEOUT=49, + NET_IPV4_IP_MASQ_DEBUG=50, + NET_TCP_SYNCOOKIES=51, + NET_TCP_STDURG=52, + NET_TCP_RFC1337=53, + NET_TCP_SYN_TAILDROP=54, + NET_TCP_MAX_SYN_BACKLOG=55, + NET_IPV4_LOCAL_PORT_RANGE=56, + NET_IPV4_ICMP_ECHO_IGNORE_ALL=57, + NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS=58, + NET_IPV4_ICMP_SOURCEQUENCH_RATE=59, + NET_IPV4_ICMP_DESTUNREACH_RATE=60, + NET_IPV4_ICMP_TIMEEXCEED_RATE=61, + NET_IPV4_ICMP_PARAMPROB_RATE=62, + NET_IPV4_ICMP_ECHOREPLY_RATE=63, }; enum { -/*1*/ NET_IPV4_ROUTE_FLUSH = 1, - NET_IPV4_ROUTE_MIN_DELAY, - NET_IPV4_ROUTE_MAX_DELAY, - NET_IPV4_ROUTE_GC_THRESH, - NET_IPV4_ROUTE_MAX_SIZE, - NET_IPV4_ROUTE_GC_MIN_INTERVAL, - NET_IPV4_ROUTE_GC_TIMEOUT, - NET_IPV4_ROUTE_GC_INTERVAL, - NET_IPV4_ROUTE_REDIRECT_LOAD, -/*10*/ NET_IPV4_ROUTE_REDIRECT_NUMBER, - NET_IPV4_ROUTE_REDIRECT_SILENCE, - NET_IPV4_ROUTE_ERROR_COST, - NET_IPV4_ROUTE_ERROR_BURST, -/*14*/ NET_IPV4_ROUTE_GC_ELASTICITY, + NET_IPV4_ROUTE_FLUSH=1, + NET_IPV4_ROUTE_MIN_DELAY=2, + NET_IPV4_ROUTE_MAX_DELAY=3, + NET_IPV4_ROUTE_GC_THRESH=4, + NET_IPV4_ROUTE_MAX_SIZE=5, + NET_IPV4_ROUTE_GC_MIN_INTERVAL=6, + NET_IPV4_ROUTE_GC_TIMEOUT=7, + NET_IPV4_ROUTE_GC_INTERVAL=8, + NET_IPV4_ROUTE_REDIRECT_LOAD=9, + NET_IPV4_ROUTE_REDIRECT_NUMBER=10, + NET_IPV4_ROUTE_REDIRECT_SILENCE=11, + NET_IPV4_ROUTE_ERROR_COST=12, + NET_IPV4_ROUTE_ERROR_BURST=13, + NET_IPV4_ROUTE_GC_ELASTICITY=14, }; enum { -/*-2*/ NET_PROTO_CONF_ALL = -2, -/*-3*/ NET_PROTO_CONF_DEFAULT = -3, + NET_PROTO_CONF_ALL=-2, + NET_PROTO_CONF_DEFAULT=-3, /* And device ifindices ... */ }; enum { -/*1*/ NET_IPV4_CONF_FORWARDING = 1, - NET_IPV4_CONF_MC_FORWARDING, - NET_IPV4_CONF_PROXY_ARP, - NET_IPV4_CONF_ACCEPT_REDIRECTS, - NET_IPV4_CONF_SECURE_REDIRECTS, - NET_IPV4_CONF_SEND_REDIRECTS, - NET_IPV4_CONF_SHARED_MEDIA, - NET_IPV4_CONF_RP_FILTER, - NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, -/*10*/ NET_IPV4_CONF_BOOTP_RELAY, -/*11*/ NET_IPV4_CONF_LOG_MARTIANS, + NET_IPV4_CONF_FORWARDING=1, + NET_IPV4_CONF_MC_FORWARDING=2, + NET_IPV4_CONF_PROXY_ARP=3, + NET_IPV4_CONF_ACCEPT_REDIRECTS=4, + NET_IPV4_CONF_SECURE_REDIRECTS=5, + NET_IPV4_CONF_SEND_REDIRECTS=6, + NET_IPV4_CONF_SHARED_MEDIA=7, + NET_IPV4_CONF_RP_FILTER=8, + NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9, + NET_IPV4_CONF_BOOTP_RELAY=10, + NET_IPV4_CONF_LOG_MARTIANS=11, }; /* /proc/sys/net/ipv6 */ enum { -/*16*/ NET_IPV6_CONF = 16, - NET_IPV6_NEIGH = 17, -/*18*/ NET_IPV6_ROUTE = 18, + NET_IPV6_CONF=16, + NET_IPV6_NEIGH=17, + NET_IPV6_ROUTE=18, }; enum { -/*1*/ NET_IPV6_ROUTE_FLUSH = 1, - NET_IPV6_ROUTE_GC_THRESH, - NET_IPV6_ROUTE_MAX_SIZE, - NET_IPV6_ROUTE_GC_MIN_INTERVAL, - NET_IPV6_ROUTE_GC_TIMEOUT, - NET_IPV6_ROUTE_GC_INTERVAL, -/*7*/ NET_IPV6_ROUTE_GC_ELASTICITY, + NET_IPV6_ROUTE_FLUSH=1, + NET_IPV6_ROUTE_GC_THRESH=2, + NET_IPV6_ROUTE_MAX_SIZE=3, + NET_IPV6_ROUTE_GC_MIN_INTERVAL=4, + NET_IPV6_ROUTE_GC_TIMEOUT=5, + NET_IPV6_ROUTE_GC_INTERVAL=6, + NET_IPV6_ROUTE_GC_ELASTICITY=7, }; enum { -/*1*/ NET_IPV6_FORWARDING = 1, - NET_IPV6_HOP_LIMIT, - NET_IPV6_MTU, - NET_IPV6_ACCEPT_RA, - NET_IPV6_ACCEPT_REDIRECTS, - NET_IPV6_AUTOCONF, - NET_IPV6_DAD_TRANSMITS, - NET_IPV6_RTR_SOLICITS, - NET_IPV6_RTR_SOLICIT_INTERVAL, -/*10*/ NET_IPV6_RTR_SOLICIT_DELAY, + NET_IPV6_FORWARDING=1, + NET_IPV6_HOP_LIMIT=2, + NET_IPV6_MTU=3, + NET_IPV6_ACCEPT_RA=4, + NET_IPV6_ACCEPT_REDIRECTS=5, + NET_IPV6_AUTOCONF=6, + NET_IPV6_DAD_TRANSMITS=7, + NET_IPV6_RTR_SOLICITS=8, + NET_IPV6_RTR_SOLICIT_INTERVAL=9, + NET_IPV6_RTR_SOLICIT_DELAY=10, }; /* /proc/sys/net//neigh/ */ enum { -/*1*/ NET_NEIGH_MCAST_SOLICIT=1, - NET_NEIGH_UCAST_SOLICIT, - NET_NEIGH_APP_SOLICIT, - NET_NEIGH_RETRANS_TIME, - NET_NEIGH_REACHABLE_TIME, - NET_NEIGH_DELAY_PROBE_TIME, - NET_NEIGH_GC_STALE_TIME, - NET_NEIGH_UNRES_QLEN, - NET_NEIGH_PROXY_QLEN, -/*10*/ NET_NEIGH_ANYCAST_DELAY, - NET_NEIGH_PROXY_DELAY, - NET_NEIGH_LOCKTIME, - NET_NEIGH_GC_INTERVAL, - NET_NEIGH_GC_THRESH1, - NET_NEIGH_GC_THRESH2, -/*16*/ NET_NEIGH_GC_THRESH3 + NET_NEIGH_MCAST_SOLICIT=1, + NET_NEIGH_UCAST_SOLICIT=2, + NET_NEIGH_APP_SOLICIT=3, + NET_NEIGH_RETRANS_TIME=4, + NET_NEIGH_REACHABLE_TIME=5, + NET_NEIGH_DELAY_PROBE_TIME=6, + NET_NEIGH_GC_STALE_TIME=7, + NET_NEIGH_UNRES_QLEN=8, + NET_NEIGH_PROXY_QLEN=9, + NET_NEIGH_ANYCAST_DELAY=10, + NET_NEIGH_PROXY_DELAY=11, + NET_NEIGH_LOCKTIME=12, + NET_NEIGH_GC_INTERVAL=13, + NET_NEIGH_GC_THRESH1=14, + NET_NEIGH_GC_THRESH2=15, + NET_NEIGH_GC_THRESH3=16 }; /* /proc/sys/net/ipx */ @@ -291,83 +295,83 @@ /* /proc/sys/net/appletalk */ enum { -/*1*/ NET_ATALK_AARP_EXPIRY_TIME = 1, - NET_ATALK_AARP_TICK_TIME, - NET_ATALK_AARP_RETRANSMIT_LIMIT, -/*4*/ NET_ATALK_AARP_RESOLVE_TIME, + NET_ATALK_AARP_EXPIRY_TIME=1, + NET_ATALK_AARP_TICK_TIME=2, + NET_ATALK_AARP_RETRANSMIT_LIMIT=3, + NET_ATALK_AARP_RESOLVE_TIME=4, }; /* /proc/sys/net/netrom */ enum { -/*1*/ NET_NETROM_DEFAULT_PATH_QUALITY = 1, - NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER, - NET_NETROM_NETWORK_TTL_INITIALISER, - NET_NETROM_TRANSPORT_TIMEOUT, - NET_NETROM_TRANSPORT_MAXIMUM_TRIES, - NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY, - NET_NETROM_TRANSPORT_BUSY_DELAY, - NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE, - NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT, -/*10*/ NET_NETROM_ROUTING_CONTROL, -/*11*/ NET_NETROM_LINK_FAILS_COUNT + NET_NETROM_DEFAULT_PATH_QUALITY=1, + NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER=2, + NET_NETROM_NETWORK_TTL_INITIALISER=3, + NET_NETROM_TRANSPORT_TIMEOUT=4, + NET_NETROM_TRANSPORT_MAXIMUM_TRIES=5, + NET_NETROM_TRANSPORT_ACKNOWLEDGE_DELAY=6, + NET_NETROM_TRANSPORT_BUSY_DELAY=7, + NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE=8, + NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT=9, + NET_NETROM_ROUTING_CONTROL=10, + NET_NETROM_LINK_FAILS_COUNT=11 }; /* /proc/sys/net/ax25 */ enum { -/*1*/ NET_AX25_IP_DEFAULT_MODE = 1, - NET_AX25_DEFAULT_MODE, - NET_AX25_BACKOFF_TYPE, - NET_AX25_CONNECT_MODE, - NET_AX25_STANDARD_WINDOW, - NET_AX25_EXTENDED_WINDOW, - NET_AX25_T1_TIMEOUT, - NET_AX25_T2_TIMEOUT, - NET_AX25_T3_TIMEOUT, -/*10*/ NET_AX25_IDLE_TIMEOUT, - NET_AX25_N2, - NET_AX25_PACLEN, - NET_AX25_PROTOCOL, -/*14*/ NET_AX25_DAMA_SLAVE_TIMEOUT + NET_AX25_IP_DEFAULT_MODE=1, + NET_AX25_DEFAULT_MODE=2, + NET_AX25_BACKOFF_TYPE=3, + NET_AX25_CONNECT_MODE=4, + NET_AX25_STANDARD_WINDOW=5, + NET_AX25_EXTENDED_WINDOW=6, + NET_AX25_T1_TIMEOUT=7, + NET_AX25_T2_TIMEOUT=8, + NET_AX25_T3_TIMEOUT=9, + NET_AX25_IDLE_TIMEOUT=10, + NET_AX25_N2=11, + NET_AX25_PACLEN=12, + NET_AX25_PROTOCOL=13, + NET_AX25_DAMA_SLAVE_TIMEOUT=14 }; /* /proc/sys/net/rose */ enum { -/*1*/ NET_ROSE_RESTART_REQUEST_TIMEOUT = 1, - NET_ROSE_CALL_REQUEST_TIMEOUT, - NET_ROSE_RESET_REQUEST_TIMEOUT, - NET_ROSE_CLEAR_REQUEST_TIMEOUT, - NET_ROSE_ACK_HOLD_BACK_TIMEOUT, - NET_ROSE_ROUTING_CONTROL, - NET_ROSE_LINK_FAIL_TIMEOUT, - NET_ROSE_MAX_VCS, - NET_ROSE_WINDOW_SIZE, -/*10*/ NET_ROSE_NO_ACTIVITY_TIMEOUT, + NET_ROSE_RESTART_REQUEST_TIMEOUT=1, + NET_ROSE_CALL_REQUEST_TIMEOUT=2, + NET_ROSE_RESET_REQUEST_TIMEOUT=3, + NET_ROSE_CLEAR_REQUEST_TIMEOUT=4, + NET_ROSE_ACK_HOLD_BACK_TIMEOUT=5, + NET_ROSE_ROUTING_CONTROL=6, + NET_ROSE_LINK_FAIL_TIMEOUT=7, + NET_ROSE_MAX_VCS=8, + NET_ROSE_WINDOW_SIZE=9, + NET_ROSE_NO_ACTIVITY_TIMEOUT=10, }; /* /proc/sys/net/x25 */ enum { -/*1*/ NET_X25_RESTART_REQUEST_TIMEOUT = 1, - NET_X25_CALL_REQUEST_TIMEOUT, - NET_X25_RESET_REQUEST_TIMEOUT, - NET_X25_CLEAR_REQUEST_TIMEOUT, -/*5*/ NET_X25_ACK_HOLD_BACK_TIMEOUT + NET_X25_RESTART_REQUEST_TIMEOUT=1, + NET_X25_CALL_REQUEST_TIMEOUT=2, + NET_X25_RESET_REQUEST_TIMEOUT=3, + NET_X25_CLEAR_REQUEST_TIMEOUT=4, + NET_X25_ACK_HOLD_BACK_TIMEOUT=5 }; /* /proc/sys/net/token-ring */ enum { -/*1*/ NET_TR_RIF_TIMEOUT=1 + NET_TR_RIF_TIMEOUT=1 }; /* /proc/sys/net/decnet */ enum { -/*1*/ NET_DECNET_DEF_T3_BROADCAST = 1, - NET_DECNET_DEF_T3_POINTTOPOINT, - NET_DECNET_DEF_T1, - NET_DECNET_DEF_BCT1, - NET_DECNET_CACHETIMEOUT, -/*6*/ NET_DECNET_DEBUG_LEVEL + NET_DECNET_DEF_T3_BROADCAST=1, + NET_DECNET_DEF_T3_POINTTOPOINT=2, + NET_DECNET_DEF_T1=3, + NET_DECNET_DEF_BCT1=4, + NET_DECNET_CACHETIMEOUT=5, + NET_DECNET_DEBUG_LEVEL=6 }; /* CTL_PROC names: */ @@ -375,29 +379,29 @@ /* CTL_FS names: */ enum { -/*1*/ FS_NRINODE=1, /* int: current number of allocated inodes */ - FS_STATINODE, - FS_MAXINODE, /* int: maximum number of inodes that can be allocated */ - FS_NRDQUOT, /* int: current number of allocated dquots */ - FS_MAXDQUOT, /* int: maximum number of dquots that can be allocated */ - FS_NRFILE, /* int: current number of allocated filedescriptors */ - FS_MAXFILE, /* int: maximum number of filedescriptors that can be allocated */ - FS_DENTRY, - FS_NRSUPER, /* int: current number of allocated super_blocks */ -/*10*/ FS_MAXSUPER, /* int: maximum number of super_blocks that can be allocated */ + FS_NRINODE=1, /* int:current number of allocated inodes */ + FS_STATINODE=2, + FS_MAXINODE=3, /* int:maximum number of inodes that can be allocated */ + FS_NRDQUOT=4, /* int:current number of allocated dquots */ + FS_MAXDQUOT=5, /* int:maximum number of dquots that can be allocated */ + FS_NRFILE=6, /* int:current number of allocated filedescriptors */ + FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */ + FS_DENTRY=8, + FS_NRSUPER=9, /* int:current number of allocated super_blocks */ + FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */ }; /* CTL_DEBUG names: */ /* CTL_DEV names: */ enum { -/*1*/ DEV_CDROM = 1, -/*2*/ DEV_HWMON, + DEV_CDROM=1, + DEV_HWMON=2, }; /* /proc/sys/dev/cdrom */ enum { -/*1*/ DEV_CDROM_INFO = 1, + DEV_CDROM_INFO=1, }; #ifdef __KERNEL__ diff -u --recursive --new-file v2.1.127/linux/include/linux/zorro.h linux/include/linux/zorro.h --- v2.1.127/linux/include/linux/zorro.h Fri Oct 9 13:27:16 1998 +++ linux/include/linux/zorro.h Wed Nov 11 11:50:00 1998 @@ -428,8 +428,8 @@ #define ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE ZORRO_ID(M_TECH_GERMANY, 0x24, 0) #define ZORRO_MANUF_GREAT_VALLEY_PRODUCTS_4 0x0891 -#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x01, 0) -#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x02, 0) +#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x01, 0) +#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG ZORRO_ID(GREAT_VALLEY_PRODUCTS_4, 0x02, 0) #define ZORRO_MANUF_APOLLO_1 0x0892 #define ZORRO_PROD_APOLLO_A1200 ZORRO_ID(APOLLO_1, 0x01, 0) diff -u --recursive --new-file v2.1.127/linux/init/main.c linux/init/main.c --- v2.1.127/linux/init/main.c Sun Nov 8 14:03:12 1998 +++ linux/init/main.c Thu Nov 12 09:58:32 1998 @@ -11,16 +11,11 @@ #define __KERNEL_SYSCALLS__ -#include +#include #include #include -#include -#include -#include #include #include -#include -#include #include #include #include @@ -34,7 +29,6 @@ #include #include -#include #include #include @@ -377,7 +371,7 @@ int i=1; while (cur && isdigit(*cur) && i <= 10) { - ints[i++] = simple_strtoul(cur,NULL,0); + ints[i++] = simple_strtol(cur,NULL,0); if ((cur = strchr(cur,',')) != NULL) cur++; } diff -u --recursive --new-file v2.1.127/linux/kernel/acct.c linux/kernel/acct.c --- v2.1.127/linux/kernel/acct.c Sun Nov 8 14:03:12 1998 +++ linux/kernel/acct.c Thu Nov 12 09:58:32 1998 @@ -23,6 +23,21 @@ * * Now we silently close acct_file on attempt to reopen. Cleaned sys_acct(). * XTerms and EMACS are manifestations of pure evil. 21/10/98, AV. + * + * Fixed a nasty interaction with with sys_umount(). If the accointing + * was suspeneded we failed to stop it on umount(). Messy. + * Another one: remount to readonly didn't stop accounting. + * Question: what should we do if we have CAP_SYS_ADMIN but not + * CAP_SYS_PACCT? Current code does the following: umount returns -EBUSY + * unless we are messing with the root. In that case we are getting a + * real mess with do_remount_sb(). 9/11/98, AV. + * + * Fixed a bunch of races (and pair of leaks). Probably not the best way, + * but this one obviously doesn't introduce deadlocks. Later. BTW, found + * one race (and leak) in BSD implementation. + * OK, that's better. ANOTHER race and leak in BSD variant. There always + * is one more bug... TODO: move filp_open into open.c and make + * parameters sysctl-controllable. 10/11/98, AV. */ #include @@ -30,18 +45,13 @@ #include #ifdef CONFIG_BSD_PROCESS_ACCT -#include +#include #include -#include #include #include -#include #include -#include -#include #include #include -#include #include #include @@ -51,11 +61,13 @@ * These constants control the amount of freespace that suspend and * resume the process accounting system, and the time delay between * each check. + * Turned into sysctl-controllable parameters. AV, 12/11/98 */ -#define RESUME (4) /* More than 4% free space will resume */ -#define SUSPEND (2) /* Less than 2% free space will suspend */ -#define ACCT_TIMEOUT (30 * HZ) /* 30 second timeout between checks */ +int acct_parm[3] = {4, 2, 30}; +#define RESUME (acct_parm[0]) /* >foo% free space - resume */ +#define SUSPEND (acct_parm[1]) /* f_dentry->d_inode->i_sb; + sb = file->f_dentry->d_inode->i_sb; if (!sb->s_op || !sb->s_op->statfs) - return; + return res; fs = get_fs(); set_fs(KERNEL_DS); + /* May block */ sb->s_op->statfs(sb, &sbuf, sizeof(struct statfs)); set_fs(fs); + if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100) + act = -1; + else if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100) + act = 1; + else + act = 0; + + /* + * If some joker switched acct_file under us we'ld better be + * silent and _not_ touch anything. + */ + if (file != acct_file) + return act ? (act>0) : res; + if (acct_active) { - if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100) { + if (act < 0) { acct_active = 0; printk(KERN_INFO "Process accounting paused\r\n"); } } else { - if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100) { + if (act > 0) { acct_active = 1; printk(KERN_INFO "Process accounting resumed\r\n"); } } + del_timer(&acct_timer); acct_needcheck = 0; - acct_timer.expires = jiffies + ACCT_TIMEOUT; + acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_timer); + return acct_active; } /* @@ -121,9 +153,7 @@ */ asmlinkage int sys_acct(const char *name) { - struct dentry *dentry; - struct inode *inode; - struct file_operations *ops; + struct file *file = NULL, *old_acct = NULL; char *tmp; int error = -EPERM; @@ -131,82 +161,57 @@ if (!capable(CAP_SYS_PACCT)) goto out; + if (name) { + tmp = getname(name); + error = PTR_ERR(tmp); + if (IS_ERR(tmp)) + goto out; + /* Difference from BSD - they don't do O_APPEND */ + file = filp_open(tmp, O_WRONLY|O_APPEND, 0); + putname(tmp); + if (IS_ERR(file)) { + error = PTR_ERR(file); + goto out; + } + error = -EACCES; + if (!S_ISREG(file->f_dentry->d_inode->i_mode)) + goto out_err; + + error = -EIO; + if (!file->f_op->write) + goto out_err; + } + + error = 0; if (acct_file) { - /* fput() may block, so just in case... */ - struct file *tmp = acct_file; - if (acct_active) - acct_process(0); + old_acct = acct_file; del_timer(&acct_timer); acct_active = 0; acct_needcheck = 0; acct_file = NULL; - fput(tmp); } - error = 0; - if (!name) /* We are done */ - goto out; - - tmp = getname(name); - error = PTR_ERR(tmp); - if (IS_ERR(tmp)) - goto out; - - dentry = open_namei(tmp, O_RDWR, 0600); - putname(tmp); - - error = PTR_ERR(dentry); - if (IS_ERR(dentry)) - goto out; - - inode = dentry->d_inode; - - error = -EACCES; - if (!S_ISREG(inode->i_mode)) - goto out_d; - - error = -EIO; - if (!inode->i_op || !(ops = inode->i_op->default_file_ops) || - !ops->write) - goto out_d; - - error = -EUSERS; - if (!(acct_file = get_empty_filp())) - goto out_d; - - acct_file->f_mode = (O_WRONLY + 1) & O_ACCMODE; - acct_file->f_flags = O_WRONLY; - acct_file->f_dentry = dentry; - acct_file->f_pos = inode->i_size; - acct_file->f_reada = 0; - acct_file->f_op = ops; - error = get_write_access(inode); - if (error) - goto out_f; - if (ops->open) - error = ops->open(inode, acct_file); - if (error) { - put_write_access(inode); - goto out_f; + if (name) { + acct_file = file; + acct_needcheck = 0; + acct_active = 1; + acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; + add_timer(&acct_timer); + } + if (old_acct) { + do_acct_process(0,old_acct); + fput(old_acct); } - acct_needcheck = 0; - acct_active = 1; - acct_timer.expires = jiffies + ACCT_TIMEOUT; - add_timer(&acct_timer); - goto out; -out_f: - /* decrementing f_count is _not_ enough */ - put_filp(acct_file); - acct_file = NULL; -out_d: - dput(dentry); out: unlock_kernel(); return error; +out_err: + fput(file); + goto out; } void acct_auto_close(kdev_t dev) { - if (acct_active && acct_file && acct_file->f_dentry->d_inode->i_dev == dev) + if (acct_file && acct_file->f_dentry->d_inode->i_dev == dev) sys_acct((char *)NULL); } @@ -260,7 +265,10 @@ #define KSTK_EIP(stack) (((unsigned long *)(stack))[1019]) #define KSTK_ESP(stack) (((unsigned long *)(stack))[1022]) -int acct_process(long exitcode) +/* + * do_acct_process does all actual work. + */ +static int do_acct_process(long exitcode, struct file *file) { struct acct ac; mm_segment_t fs; @@ -268,14 +276,15 @@ /* * First check to see if there is enough free_space to continue - * the process accounting system. Check_free_space toggles the - * acct_active flag so we need to check that after check_free_space. + * the process accounting system. */ - check_free_space(); - - if (!acct_active) + if (!file) return 0; - + file->f_count++; + if (!check_free_space(file)) { + fput(file); + return 0; + } /* * Fill the accounting struct with the needed info as recorded @@ -327,10 +336,19 @@ */ fs = get_fs(); set_fs(KERNEL_DS); - acct_file->f_op->write(acct_file, (char *)&ac, - sizeof(struct acct), &acct_file->f_pos); + file->f_op->write(file, (char *)&ac, + sizeof(struct acct), &file->f_pos); set_fs(fs); + fput(file); return 0; +} + +/* + * acct_process - now just a wrapper around do_acct_process + */ +int acct_process(long exitcode) +{ + return do_acct_process(exitcode, acct_file); } #else diff -u --recursive --new-file v2.1.127/linux/kernel/capability.c linux/kernel/capability.c --- v2.1.127/linux/kernel/capability.c Fri Oct 23 22:01:27 1998 +++ linux/kernel/capability.c Thu Nov 12 09:58:32 1998 @@ -6,10 +6,8 @@ */ #include -#include -#include -#include #include +#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/exec_domain.c linux/kernel/exec_domain.c --- v2.1.127/linux/kernel/exec_domain.c Sun Jan 26 02:07:48 1997 +++ linux/kernel/exec_domain.c Thu Nov 12 09:58:32 1998 @@ -1,8 +1,5 @@ -#include -#include #include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.127/linux/kernel/exit.c Fri Oct 23 22:01:27 1998 +++ linux/kernel/exit.c Thu Nov 12 09:58:32 1998 @@ -7,16 +7,12 @@ #include #include #include -#include #include -#include #include #include -#include #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.127/linux/kernel/fork.c Mon Oct 5 13:13:47 1998 +++ linux/kernel/fork.c Thu Nov 12 09:58:32 1998 @@ -14,17 +14,13 @@ #include #include #include -#include #include #include #include -#include #include -#include #include #include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/info.c linux/kernel/info.c --- v2.1.127/linux/kernel/info.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/info.c Thu Nov 12 09:58:32 1998 @@ -9,10 +9,8 @@ #include #include #include -#include #include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/itimer.c linux/kernel/itimer.c --- v2.1.127/linux/kernel/itimer.c Sun Nov 8 14:03:12 1998 +++ linux/kernel/itimer.c Thu Nov 12 09:58:32 1998 @@ -6,13 +6,10 @@ /* These are all the functions necessary to implement itimers */ -#include #include #include #include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/kmod.c linux/kernel/kmod.c --- v2.1.127/linux/kernel/kmod.c Fri Oct 23 22:01:27 1998 +++ linux/kernel/kmod.c Thu Nov 12 09:58:32 1998 @@ -12,10 +12,8 @@ #define __KERNEL_SYSCALLS__ #include -#include #include #include -#include #include diff -u --recursive --new-file v2.1.127/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.127/linux/kernel/ksyms.c Sun Nov 8 14:03:12 1998 +++ linux/kernel/ksyms.c Thu Nov 12 09:58:32 1998 @@ -11,32 +11,24 @@ #include #include -#include -#include +#include #include #include -#include #include #include #include #include #include -#include #include #include #include #include -#include -#include -#include #include #include -#include #include #include #include #include -#include #include #include #include @@ -51,9 +43,6 @@ #include #include #include -#include - -#include #if defined(CONFIG_PROC_FS) #include @@ -62,9 +51,6 @@ #include #endif #include -#ifdef __SMP__ -#include -#endif extern char *get_options(char *str, int *ints); extern void set_device_ro(kdev_t dev,int flag); diff -u --recursive --new-file v2.1.127/linux/kernel/module.c linux/kernel/module.c --- v2.1.127/linux/kernel/module.c Tue Jun 9 11:57:31 1998 +++ linux/kernel/module.c Thu Nov 12 09:58:32 1998 @@ -1,13 +1,11 @@ #include -#include +#include #include /* defines GFP_KERNEL */ #include #include -#include #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/panic.c linux/kernel/panic.c --- v2.1.127/linux/kernel/panic.c Wed Sep 9 14:51:13 1998 +++ linux/kernel/panic.c Thu Nov 12 09:58:32 1998 @@ -10,10 +10,8 @@ */ #include -#include #include #include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/printk.c linux/kernel/printk.c --- v2.1.127/linux/kernel/printk.c Wed Aug 26 11:37:45 1998 +++ linux/kernel/printk.c Thu Nov 12 09:58:32 1998 @@ -16,16 +16,12 @@ #include #include -#include #include -#include #include -#include #include #include #include -#include #include #define LOG_BUF_LEN (16384) diff -u --recursive --new-file v2.1.127/linux/kernel/resource.c linux/kernel/resource.c --- v2.1.127/linux/kernel/resource.c Wed Aug 26 11:37:45 1998 +++ linux/kernel/resource.c Thu Nov 12 09:58:32 1998 @@ -8,9 +8,7 @@ */ #include -#include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/sched.c linux/kernel/sched.c --- v2.1.127/linux/kernel/sched.c Sun Nov 8 14:03:12 1998 +++ linux/kernel/sched.c Thu Nov 12 09:58:32 1998 @@ -16,25 +16,18 @@ * current-task */ -#include #include -#include -#include #include #include #include -#include -#include #include #include #include #include #include -#include #include #include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/signal.c linux/kernel/signal.c --- v2.1.127/linux/kernel/signal.c Sun Nov 8 14:03:12 1998 +++ linux/kernel/signal.c Thu Nov 12 09:58:32 1998 @@ -8,14 +8,10 @@ #include #include -#include -#include #include #include -#include #include #include -#include #include #include #include @@ -333,10 +329,10 @@ if (nr_queued_signals < max_queued_signals) { q = (struct signal_queue *) kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL); - nr_queued_signals++; } if (q) { + nr_queued_signals++; q->next = NULL; *t->sigqueue_tail = q; t->sigqueue_tail = &q->next; diff -u --recursive --new-file v2.1.127/linux/kernel/softirq.c linux/kernel/softirq.c --- v2.1.127/linux/kernel/softirq.c Fri Jan 23 18:10:32 1998 +++ linux/kernel/softirq.c Thu Nov 12 09:58:32 1998 @@ -8,17 +8,13 @@ * bottom_half handler need not be re-entrant. */ -#include #include -#include -#include #include +#include #include #include -#include #include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.127/linux/kernel/sys.c Fri Oct 23 22:01:27 1998 +++ linux/kernel/sys.c Thu Nov 12 09:58:32 1998 @@ -6,20 +6,13 @@ #include #include -#include -#include #include -#include #include -#include #include -#include #include #include #include #include -#include -#include #include #include #include diff -u --recursive --new-file v2.1.127/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.127/linux/kernel/sysctl.c Sun Nov 8 14:03:13 1998 +++ linux/kernel/sysctl.c Thu Nov 12 09:58:32 1998 @@ -22,10 +22,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -58,6 +56,10 @@ void *buffer, size_t *lenp); #endif +#ifdef CONFIG_BSD_PROCESS_ACCT +extern int acct_parm[]; +#endif + extern int pgt_cache_water[]; static int parse_table(int *, int, void *, size_t *, void *, size_t, @@ -192,6 +194,10 @@ #ifdef CONFIG_CHR_DEV_SG {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int), 0444, NULL, &proc_dointvec}, +#endif +#ifdef CONFIG_BSD_PROCESS_ACCT + {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int), + 0644, NULL, &proc_dointvec}, #endif {0} }; diff -u --recursive --new-file v2.1.127/linux/kernel/time.c linux/kernel/time.c --- v2.1.127/linux/kernel/time.c Wed May 20 19:10:42 1998 +++ linux/kernel/time.c Thu Nov 12 09:58:32 1998 @@ -20,12 +20,9 @@ #include #include -#include -#include #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.127/linux/lib/vsprintf.c linux/lib/vsprintf.c --- v2.1.127/linux/lib/vsprintf.c Thu Mar 26 15:57:06 1998 +++ linux/lib/vsprintf.c Sun Nov 8 14:06:18 1998 @@ -39,6 +39,13 @@ return result; } +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') diff -u --recursive --new-file v2.1.127/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.127/linux/mm/filemap.c Sun Nov 8 14:03:13 1998 +++ linux/mm/filemap.c Wed Nov 11 22:48:13 1998 @@ -1523,9 +1523,8 @@ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur; struct page *page, **hash; unsigned long page_cache = 0; - unsigned long pgpos, offset; - unsigned long bytes, written; - long status, sync, didread; + unsigned long written; + long status, sync; if (!inode->i_op || !inode->i_op->updatepage) return -EIO; @@ -1556,18 +1555,20 @@ } while (count) { + unsigned long bytes, pgpos, offset; /* * Try to find the page in the cache. If it isn't there, * allocate a free page. */ offset = (pos & ~PAGE_MASK); pgpos = pos & PAGE_MASK; - - if ((bytes = PAGE_SIZE - offset) > count) + bytes = PAGE_SIZE - offset; + if (bytes > count) bytes = count; hash = page_hash(inode, pgpos); - if (!(page = __find_page(inode, pgpos, *hash))) { + page = __find_page(inode, pgpos, *hash); + if (!page) { if (!page_cache) { page_cache = __get_free_page(GFP_USER); if (page_cache) @@ -1580,51 +1581,25 @@ page_cache = 0; } - /* - * Note: setting of the PG_locked bit is handled - * below the i_op->xxx interface. - */ - didread = 0; -page_wait: + /* Get exclusive IO access to the page.. */ wait_on_page(page); - if (PageUptodate(page)) - goto do_update_page; + set_bit(PG_locked, &page->flags); /* - * The page is not up-to-date ... if we're writing less - * than a full page of data, we may have to read it first. - * But if the page is past the current end of file, we must - * clear it before updating. + * Do the real work.. If the writer ends up delaying the write, + * the writer needs to increment the page use counts until he + * is done with the page. */ - if (bytes < PAGE_SIZE) { - if (pgpos < inode->i_size) { - status = -EIO; - if (didread >= 2) - goto done_with_page; - status = inode->i_op->readpage(file, page); - if (status < 0) - goto done_with_page; - didread++; - goto page_wait; - } else { - /* Must clear for partial writes */ - memset((void *) page_address(page), 0, - PAGE_SIZE); - } - } - /* - * N.B. We should defer setting PG_uptodate at least until - * the data is copied. A failure in i_op->updatepage() could - * leave the page with garbage data. - */ - set_bit(PG_uptodate, &page->flags); - -do_update_page: - /* All right, the page is there. Now update it. */ - status = inode->i_op->updatepage(file, page, buf, - offset, bytes, sync); -done_with_page: + bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes); + status = -EFAULT; + if (bytes) + status = inode->i_op->updatepage(file, page, offset, bytes, sync); + + /* Mark it unlocked again and drop the page.. */ + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); __free_page(page); + if (status < 0) break; diff -u --recursive --new-file v2.1.127/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.127/linux/mm/vmscan.c Sun Nov 8 14:03:13 1998 +++ linux/mm/vmscan.c Sun Nov 8 14:12:21 1998 @@ -538,6 +538,8 @@ do { if (!do_try_to_free_page(0)) break; + if (nr_free_pages > 2*freepages.high) + break; } while (time_before_eq(jiffies,end_time)); } /* As if we could ever get here - maybe we want to make this killable */ diff -u --recursive --new-file v2.1.127/linux/net/802/fddi.c linux/net/802/fddi.c --- v2.1.127/linux/net/802/fddi.c Mon Jan 12 15:28:19 1998 +++ linux/net/802/fddi.c Sun Nov 8 14:06:18 1998 @@ -98,17 +98,19 @@ { struct fddihdr *fddi = (struct fddihdr *)skb->data; - if (fddi->hdr.llc_snap.ethertype != __constant_htons(ETH_P_IP)) +#ifdef CONFIG_INET + if (fddi->hdr.llc_snap.ethertype == __constant_htons(ETH_P_IP)) + /* Try to get ARP to resolve the header and fill destination address */ + return arp_find(fddi->daddr, skb); + else +#endif { printk("%s: Don't know how to resolve type %02X addresses.\n", skb->dev->name, htons(fddi->hdr.llc_snap.ethertype)); return(0); } - - /* Try to get ARP to resolve the header and fill destination address */ - - return arp_find(fddi->daddr, skb); } + /* * Determine the packet's protocol ID and fill in skb fields. diff -u --recursive --new-file v2.1.127/linux/net/econet/econet.c linux/net/econet/econet.c --- v2.1.127/linux/net/econet/econet.c Tue Aug 18 22:02:08 1998 +++ linux/net/econet/econet.c Sun Nov 8 14:36:46 1998 @@ -330,8 +330,6 @@ { /* Real hardware Econet. We're not worthy etc. */ #ifdef CONFIG_ECONET_NATIVE - unsigned char *p; - dev_lock_list(); skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, diff -u --recursive --new-file v2.1.127/linux/net/socket.c linux/net/socket.c --- v2.1.127/linux/net/socket.c Sat Sep 5 16:46:42 1998 +++ linux/net/socket.c Sun Nov 8 14:36:46 1998 @@ -93,7 +93,7 @@ #include #include - +static int sock_no_open(struct inode *irrelevant, struct file *dontcare); static long long sock_lseek(struct file *file, long long offset, int whence); static ssize_t sock_read(struct file *file, char *buf, size_t size, loff_t *ppos); @@ -121,7 +121,7 @@ sock_poll, sock_ioctl, NULL, /* mmap */ - NULL, /* no special open code... */ + sock_no_open, /* special open code to disallow open via /proc */ NULL, /* flush */ sock_close, NULL, /* no fsync */ @@ -303,6 +303,17 @@ sockets_in_use++; return sock; +} + +/* + * In theory you can't get an open on this inode, but /proc provides + * a back door. Remember to keep it shut otherwise you'll let the + * creepy crawlies in. + */ + +static int sock_no_open(struct inode *irrelevant, struct file *dontcare) +{ + return -ENXIO; } void sock_release(struct socket *sock) diff -u --recursive --new-file v2.1.127/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c --- v2.1.127/linux/net/wanrouter/wanproc.c Sat Sep 5 16:46:42 1998 +++ linux/net/wanrouter/wanproc.c Sun Nov 8 14:36:46 1998 @@ -56,6 +56,8 @@ /****** Function Prototypes *************************************************/ +#ifdef CONFIG_PROC_FS + /* Proc filesystem interface */ static int router_proc_perms(struct inode *, int); static ssize_t router_proc_read(struct file* file, char* buf, size_t count, loff_t *ppos); @@ -176,7 +178,7 @@ /* * /proc/net/router */ - + static struct proc_dir_entry proc_router = { 0, /* .low_ino */ @@ -528,3 +530,30 @@ * End */ +#else + +/* + * No /proc - output stubs + */ + +__initfunc(int wanrouter_proc_init(void)) +{ + return 0; +} + +void wanrouter_proc_cleanup(void) +{ + return; +} + +int wanrouter_proc_add(wan_device_t *wandev) +{ + return 0; +} + +int wanrouter_proc_delete(wan_device_t *wandev) +{ + return 0; +} + +#endif diff -u --recursive --new-file v2.1.127/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c --- v2.1.127/linux/scripts/lxdialog/menubox.c Fri Oct 23 22:01:27 1998 +++ linux/scripts/lxdialog/menubox.c Sun Nov 8 14:36:46 1998 @@ -62,9 +62,6 @@ { int j; char menu_item[menu_width+1]; -#if OLD_NCURSES - int i; -#endif strncpy(menu_item, item, menu_width); menu_item[menu_width] = 0; @@ -74,8 +71,11 @@ wattrset (win, menubox_attr); wmove (win, choice, 0); #if OLD_NCURSES - for (i = 0; i < menu_width; i++) - waddch (win, ' '); + { + int i; + for (i = 0; i < menu_width; i++) + waddch (win, ' '); + } #else wclrtoeol(win); #endif diff -u --recursive --new-file v2.1.127/linux/scripts/lxdialog/textbox.c linux/scripts/lxdialog/textbox.c --- v2.1.127/linux/scripts/lxdialog/textbox.c Fri Oct 23 22:01:27 1998 +++ linux/scripts/lxdialog/textbox.c Sun Nov 8 14:36:46 1998 @@ -453,9 +453,6 @@ { int y, x; char *line; -#if OLD_NCURSES - int i; -#endif line = get_line (); line += MIN (strlen (line), hscroll); /* Scroll horizontally */ @@ -466,8 +463,11 @@ getyx (win, y, x); /* Clear 'residue' of previous line */ #if OLD_NCURSES - for (i = 0; i < width - x; i++) - waddch (win, ' '); + { + int i; + for (i = 0; i < width - x; i++) + waddch (win, ' '); + } #else wclrtoeol(win); #endif