diff -u --recursive --new-file v2.3.12/linux/CREDITS linux/CREDITS --- v2.3.12/linux/CREDITS Wed Jul 21 15:46:48 1999 +++ linux/CREDITS Fri Aug 6 13:22:22 1999 @@ -814,12 +814,15 @@ N: Andre Hedrick E: hedrick@astro.dyer.vanderbilt.edu +D: Random SMP kernel hacker... D: Uniform Multi-Platform E-IDE driver -D: Aladdin 1533/1543(C) chipset IDE -D: HighPoint HPT343/5 chipset IDE -D: PIIX chipset IDE -D: Promise Ultra/33 chipset IDE -D: Promise Ultra/66 chipset IDE +D: Aladdin 1533/1543(C) chipset +D: Active-Chipset maddness.......... +D: HighPoint HPT343/5 Ultra/33 & HPT366 Ultra/66 chipsets +D: Intel PIIX chipset +D: Promise PDC20246/20247 & PDC20262 chipsets +D: SiS5513 Ultra/66/33 chipsets +D: VIA 82C586/596/686 chipsets S: Nashville, TN S: USA @@ -2091,7 +2094,7 @@ S: Australia N: Jeffrey A. Uphoff -E: juphoff@nrao.edu +E: juphoff@transmeta.com E: jeff.uphoff@linux.org P: 1024/9ED505C5 D7 BB CA AA 10 45 40 1B 16 19 0A C0 38 A0 3E CB D: Linux Security/Alert mailing lists' moderator/maintainer. @@ -2099,9 +2102,9 @@ D: PAM S/Key module developer. D: 'dip' contributor. D: AIPS port, astronomical community support. -S: National Radio Astronomy Observatory -S: 520 Edgemont Road -S: Charlottesville, Virginia 22903 +S: Transmeta Corporation +S: 2540 Mission College Blvd. +S: Santa Clara, CA 95054 S: USA N: Matthias Urlichs @@ -2187,16 +2190,19 @@ D: Miscellaneous MCA-support N: Matt Welsh -E: mdw@sunsite.unc.edu -D: Linux Documentation Project coordinator -D: Author, _Running_Linux_ and I&GS guide -D: Linuxdoc-SGML formatting system +E: mdw@metalab.unc.edu +W: http://www.cs.berkeley.edu/~mdw +D: Original Linux Documentation Project coordinator +D: Author, "Running Linux" (O'Reilly) +D: Author, "Linux Installation and Getting Started" (LDP) and several HOWTOs +D: Linuxdoc-SGML formatting system (now SGML-Tools) +D: Device drivers for various high-speed network interfaces (Myrinet, ATM) D: Keithley DAS1200 device driver -D: Maintainer of sunsite WWW and FTP, moderator c.o.l.answers -S: Cornell University Computer Science Department -S: Robotics and Vision Laboratory -S: 4130 Upson Hall -S: Ithaca, New York 14850 +D: Original maintainer of sunsite WWW and FTP sites +D: Original moderator of c.o.l.announce and c.o.l.answers +S: Computer Science Division +S: UC Berkeley +S: Berkeley, CA 94720-1776 S: USA N: Greg Wettstein @@ -2284,6 +2290,7 @@ E: R.E.Wolff@BitWizard.nl D: Written kmalloc/kfree D: Written Specialix IO8+ driver +D: Written Specialix SX driver S: van Bronckhorststraat 12 S: 2612 XV Delft S: The Netherlands diff -u --recursive --new-file v2.3.12/linux/Documentation/Changes linux/Documentation/Changes --- v2.3.12/linux/Documentation/Changes Thu Jul 8 15:42:19 1999 +++ linux/Documentation/Changes Fri Aug 6 10:44:11 1999 @@ -61,7 +61,7 @@ - Bash 1.14.7 ; bash -version - Ncpfs 2.2.0 ; ncpmount -v - Pcmcia-cs 3.0.7 ; cardmgr -V -- PPP 2.3.5 ; pppd --version +- PPP 2.3.9 ; pppd --version - Util-linux 2.9i ; chsh -v Upgrade notes @@ -390,8 +390,8 @@ PPP === - Due to changes in the routing code, those of you using PPP -networking will need to upgrade your pppd. + Due to changes in the PPP driver and routing code, those of you +using PPP networking will need to upgrade your pppd. iBCS ==== @@ -689,8 +689,8 @@ PPP === -The 2.3.5 release: -ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.5.tar.gz +The 2.3.9 release: +ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.9.tar.gz IP Chains ========= diff -u --recursive --new-file v2.3.12/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.12/linux/Documentation/Configure.help Wed Jul 28 14:47:42 1999 +++ linux/Documentation/Configure.help Mon Aug 9 12:28:00 1999 @@ -546,6 +546,20 @@ It is safe to say Y to this question. +Use DMA by default when available +CONFIG_IDEDMA_PCI_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 + 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 + previous behaviour, say Y to this question. + + If you suspect your hardware is at all flakey, say N here. + Do NOT email the IDE kernel people regarding this issue! + + It is normally safe to answer Y to this question unless your + motherboard uses a VIA VP2 chipset, in which case you should say N. + Good-Bad DMA Model-Firmware (EXPERIMENTAL) IDEDMA_NEW_DRIVE_LISTINGS This test compares both the model and firmware revision for buggy drives @@ -555,23 +569,6 @@ If in doubt, say N. -Generic ATA-66 support (DANGEROUS) -CONFIG_IDEDMA_ULTRA_66 - This allows for your Generic IDE control to attempt support for - using ATA-66 or UDMA-66 transfer modes 3/4. If you are not sure what you - are attempting, "DO NOT" even think about this option, unless your - mainboard's chipset is verified. Do not complain to anyone if you - do not know what you are doing and are just playing around. - This option has no known success cases to date. - - Say N, or beware......... - -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 @@ -590,96 +587,31 @@ If in doubt, say N. -Use DMA by default when available -CONFIG_IDEDMA_PCI_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 - 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 - previous behaviour, say Y to this question. - - If you suspect your hardware is at all flakey, say N here. - Do NOT email the IDE kernel people regarding this issue! - - It is normally safe to answer Y to this question unless your - motherboard uses a VIA VP2 chipset, in which case you should say N. - -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. 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. - -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 - of the DTC-2278 card, and permits faster I/O speeds to be set as - well. See the Documentation/ide.txt and drivers/block/dtc2278.c - files for more info. +AEC6210 chipset support +CONFIG_BLK_DEV_AEC6210 + This driver adds up to 4 more eide devices sharing a single interrupt. + This add-on card is a bootable PCI UDMA controller. In order to get this + card to initialize correctly in some cases, you should include this driver. -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 - of the Holtek card, and permits faster I/O speeds to be set as well. - See the Documentation/ide.txt and drivers/block/ht6560b.c files for - more info. + This prefers CONFIG_IDEDMA_PCI_AUTO to be enabled, regardless. -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 - 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 - and drivers/block/pdc4030.c files for more info. + Please read the comments at the top of drivers/block/aec6210.c -PS/2 ESDI hard disk support -CONFIG_BLK_DEV_PS2 - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - If you want to compile the 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 ps2esdi.o. +ALI M15x3 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_ALI15X3 + This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C + onboard chipsets. It also tests for Simplex mode and enables + normal dual channel support. -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 - needed for further tweaking and development. - Please read the comments at the top of drivers/block/trm290.c. + This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. -OPTi 82C621 enhanced support (EXPERIMENTAL) -CONFIG_BLK_DEV_OPTI621 - This is a driver for the OPTi 82C621 EIDE controller. - Please read the comments at the top of drivers/block/opti621.c. + Please read the comments at the top of drivers/block/alim15x3.c -NS87415 support (EXPERIMENTAL) -CONFIG_BLK_DEV_NS87415 - This driver adds detection and support for the NS87415 chip - (used in SPARC64, among others). + If unsure, say N. - Please read the comments at the top of drivers/block/ns87415.c. +CMD646 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_CMD646 + Say Y here if you have an IDE controller like this. CY82C693 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_CY82C693 @@ -691,37 +623,67 @@ Please read the comments at the top of drivers/block/cy82c693.c -VIA82C586 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_VIA82C586 - This allows you to to configure your chipset for a better use while - running (U)DMA: it will allow you to enable efficiently the second - channel dma usage, as it is may not be set by BIOS. It allows you to - run a kernel command line at boot time in order to set fifo config. - If no command line is provided, it will try to set fifo configuration - at its best. It will allow you to get a proc/ide/via display - (while running a "cat") provided you enabled "proc" support and - set DISPLAY_APOLLO_TIMINGS in via82c586.c +HPT34X chipset support +CONFIG_BLK_DEV_HPT34X + This driver adds up to 4 more EIDE devices sharing a single + interrupt. The HPT343 chipset in its current form is a non-bootable or + HPT345/HPT363 chipset is bootable (needs BIOS FIX) PCI UDMA controllers. + 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/hpt34x.c + +HPT34X DMA support (DANGEROUS) +CONFIG_BLK_DEV_HPT34X_DMA This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. - If unsure, say N. + Please read the comments at the top of drivers/block/hpt34x.c -CMD646 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_CMD646 - Say Y here if you have an IDE controller like this. +HPT366 chipset support +CONFIG_BLK_DEV_HPT366 + This is an Ultra DMA chipset for ATA-66. + This driver adds up to 4 more EIDE devices sharing a single + interrupt. The HPT366 chipset in its current form is a non-bootable. + 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. -ALI M15x3 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_ALI15X3 - This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C - onboard chipsets. It also tests for Simplex mode and enables - normal dual channel support. + Please read the comments at the top of drivers/block/hpt366.c - This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. +Intel PIIXn chipsets support +CONFIG_BLK_DEV_PIIX + This driver adds PIO mode setting and tuning for all PIIX IDE + controllers by Intel. Since the BIOS can sometimes improperly tune + PIO 0-4 mode settings, this allows dynamic tuning of the chipset + via the standard end-user tool 'hdparm'. - Please read the comments at the top of drivers/block/alim15x3.c + Please read the comments at the top of drivers/block/piix.c + + If unsure, say N. + +PIIXn Tuning support (EXPERIMENTAL) +CONFIG_BLK_DEV_PIIX_TUNING + This driver extension adds DMA mode setting and tuning for all PIIX IDE + controllers by Intel. Since the BIOS can sometimes improperly setup + the device/adapter combination and speed limits, It has become a necessity + to back/forward speed devices as needed. + + Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode 2 + if the BIOS can to perform this task at INIT. If unsure, say N. +NS87415 support (EXPERIMENTAL) +CONFIG_BLK_DEV_NS87415 + This driver adds detection and support for the NS87415 chip + (used in SPARC64, among others). + + Please read the comments at the top of drivers/block/ns87415.c. + +OPTi 82C621 enhanced support (EXPERIMENTAL) +CONFIG_BLK_DEV_OPTI621 + This is a driver for the OPTi 82C621 EIDE controller. + Please read the comments at the top of drivers/block/opti621.c. + PROMISE PDC20246/PDC20262 support CONFIG_BLK_DEV_PDC202XX Promise Ultra33 or PDC20246. @@ -764,54 +726,127 @@ Say N. -AEC6210 chipset support -CONFIG_BLK_DEV_AEC6210 - This driver adds up to 4 more eide devices sharing a single interrupt. - This add-on card is a bootable PCI UDMA controller. In order to get this - card to initialize correctly in some cases, you should include this driver. +SiS5513 chipset support +CONFIG_BLK_DEV_SIS5513 + This driver ensures (U)DMA support for SIS5513 chipset based mainboards. + SiS620/530 UDMA mode 4, SiS5600/5597 UDMA mode 2, all other DMA mode 2 + limited chipsets are unsupported to date. - This prefers CONFIG_IDEDMA_PCI_AUTO to be enabled, regardless. + This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. - Please read the comments at the top of drivers/block/aec6210.c + Please read the comments at the top of drivers/block/sis5513.c -Intel PIIXn chipsets support -CONFIG_BLK_DEV_PIIX - This driver adds PIO mode setting and tuning for all PIIX IDE - controllers by Intel. Since the BIOS can sometimes improperly tune - PIO 0-4 mode settings, this allows dynamic tuning of the chipset - via the standard end-user tool 'hdparm'. +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. - Please read the comments at the top of drivers/block/piix.c +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 + needed for further tweaking and development. + Please read the comments at the top of drivers/block/trm290.c. + +VIA82C586 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_VIA82C586 + This allows you to to configure your chipset for a better use while + running (U)DMA: it will allow you to enable efficiently the second + channel dma usage, as it is may not be set by BIOS. It allows you to + run a kernel command line at boot time in order to set fifo config. + If no command line is provided, it will try to set fifo configuration + at its best. It will allow you to get a proc/ide/via display + (while running a "cat") provided you enabled "proc" support and + set DISPLAY_APOLLO_TIMINGS in via82c586.c + + This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. If unsure, say N. -PIIXn Tuning support (EXPERIMENTAL) -CONFIG_BLK_DEV_PIIX_TUNING - This driver extension adds DMA mode setting and tuning for all PIIX IDE - controllers by Intel. Since the BIOS can sometimes improperly setup - the device/adapter combination and speed limits, It has become a necessity - to back/forward speed devices as needed. +Support for PowerMac IDE devices (must also enable IDE) +CONFIG_BLK_DEV_IDE_PMAC + No help for CONFIG_BLK_DEV_IDE_PMAC - Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode 2 - if the BIOS can to perform this task at INIT. +PowerMac IDE DMA support +CONFIG_BLK_DEV_IDEDMA_PMAC + No help for CONFIG_BLK_DEV_IDEDMA_PMAC - If unsure, say N. +Use DMA by default +CONFIG_IDEDMA_PMAC_AUTO + No help for CONFIG_IDEDMA_PMAC_AUTO -HPT34X chipset support -CONFIG_BLK_DEV_HPT34X - This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT343 chipset in its current form is a non-bootable or - HPT345/HPT363 chipset is bootable (needs BIOS FIX) PCI UDMA controllers. - 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. +ICS IDE interface support +CONFIG_BLK_DEV_IDE_ICSIDE + No help for CONFIG_BLK_DEV_IDE_ICSIDE - Please read the comments at the top of drivers/block/hpt343.c +ICS DMA support +CONFIG_BLK_DEV_IDEDMA_ICS + No help for CONFIG_BLK_DEV_IDEDMA_ICS -HPT34X DMA support (DANGEROUS) -CONFIG_BLK_DEV_HPT34X_DMA - This requires CONFIG_IDEDMA_PCI_AUTO to be enabled. +Use ICS DMA by default +CONFIG_IDEDMA_ICS_AUTO + No help for CONFIG_IDEDMA_ICS_AUTO + +RapIDE interface support +CONFIG_BLK_DEV_IDE_RAPIDE + No help for CONFIG_BLK_DEV_IDE_RAPIDE + +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. 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. + +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 + 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 drivers/block/ali14xx.c for more info. + +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 + of the DTC-2278 card, and permits faster I/O speeds to be set as + well. See the Documentation/ide.txt and drivers/block/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 + of the Holtek card, and permits faster I/O speeds to be set as well. + See the Documentation/ide.txt and drivers/block/ht6560b.c files for + more info. - Please read the comments at the top of drivers/block/hpt343.c +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 + 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 + and drivers/block/pdc4030.c files for more info. QDI QD6580 support CONFIG_BLK_DEV_QD6580 @@ -828,14 +863,6 @@ See the files Documentation/ide.txt and drivers/block/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 - 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 drivers/block/ali14xx.c for more info. - Amiga builtin Gayle IDE interface support CONFIG_BLK_DEV_GAYLE This is the IDE driver for the builtin IDE interface on some Amiga @@ -845,21 +872,6 @@ (hard disks, CD-ROM drives, etc.) that are connected to the builtin IDE interface. -Falcon IDE interface support -CONFIG_BLK_DEV_FALCON_IDE - This is the IDE driver for the builtin IDE interface on the Atari Falcon. - Say Y if you have a Falcon and want to use IDE devices (hard disks, - CD-ROM drives, etc.) that are connected to the builtin IDE interface. - -Amiga Buddha/Catweasel IDE interface support (EXPERIMENTAL) -CONFIG_BLK_DEV_BUDDHA - This is the IDE driver for the IDE interfaces on the Buddha and - Catweasel expansion boards. It supports up to two interfaces on the - Buddha and three on the Catweasel. - Say Y if you have a Buddha or Catweasel expansion board and want to - use IDE devices (hard disks, CD-ROM drives, etc.) that are connected - to one of its IDE interfaces. - Amiga IDE Doubler support (EXPERIMENTAL) CONFIG_BLK_DEV_IDEDOUBLER This driver provides support for the so called `IDE doublers' (made by @@ -872,17 +884,20 @@ Say Y if you have an IDE doubler. The driver is enabled at kernel runtime using the "ide=doubler" kernel boot parameter. -Support for PowerMac IDE devices (must also enable IDE) -CONFIG_BLK_DEV_IDE_PMAC - No help for CONFIG_BLK_DEV_IDE_PMAC - -PowerMac IDE DMA support -CONFIG_BLK_DEV_IDEDMA_PMAC - No help for CONFIG_BLK_DEV_IDEDMA_PMAC +Amiga Buddha/Catweasel IDE interface support (EXPERIMENTAL) +CONFIG_BLK_DEV_BUDDHA + This is the IDE driver for the IDE interfaces on the Buddha and + Catweasel expansion boards. It supports up to two interfaces on the + Buddha and three on the Catweasel. + Say Y if you have a Buddha or Catweasel expansion board and want to + use IDE devices (hard disks, CD-ROM drives, etc.) that are connected + to one of its IDE interfaces. -Use DMA by default -CONFIG_IDEDMA_PMAC_AUTO - No help for CONFIG_IDEDMA_PMAC_AUTO +Falcon IDE interface support +CONFIG_BLK_DEV_FALCON_IDE + This is the IDE driver for the builtin IDE interface on the Atari Falcon. + Say Y if you have a Falcon and want to use IDE devices (hard disks, + CD-ROM drives, etc.) that are connected to the builtin IDE interface. Macintosh Quadra/Powerbook IDE interface support CONFIG_BLK_DEV_MAC_IDE @@ -894,21 +909,15 @@ (hard disks, CD-ROM drives, etc.) that are connected to the builtin IDE interface. -ICS IDE interface support -CONFIG_BLK_DEV_IDE_ICSIDE - No help for CONFIG_BLK_DEV_IDE_ICSIDE - -ICS DMA support -CONFIG_BLK_DEV_IDEDMA_ICS - No help for CONFIG_BLK_DEV_IDEDMA_ICS - -Use ICS DMA by default -CONFIG_IDEDMA_ICS_AUTO - No help for CONFIG_IDEDMA_ICS_AUTO - -RapIDE interface support -CONFIG_BLK_DEV_IDE_RAPIDE - No help for CONFIG_BLK_DEV_IDE_RAPIDE +PS/2 ESDI hard disk support +CONFIG_BLK_DEV_PS2 + Say Y here if you have a PS/2 machine with a MCA bus and an ESDI + hard disk. + + If you want to compile the 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 ps2esdi.o. XT hard disk support CONFIG_BLK_DEV_XD @@ -3529,6 +3538,13 @@ ### Don't know what's going on here. ### # +YAM driver for AX.25 +CONFIG_YAM + Support for the YAM modem on serial port. 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. + BAYCOM picpar and par96 driver for AX.25 CONFIG_BAYCOM_PAR This is a driver for Baycom style simple amateur radio modems that @@ -5173,23 +5189,11 @@ end of the link as well. It's good enough, for example, to run IP over the async ports of a Camtec JNT Pad. If unsure, say N. -PPP (point-to-point) support +PPP (point-to-point protocol) support CONFIG_PPP PPP (Point to Point Protocol) is a newer and better SLIP. It serves the same purpose: sending Internet traffic over telephone (and other - serial) lines. Ask your access provider if they support it, because - otherwise you can't use it (not quite true any more: the free - program SLiRP can emulate a PPP line if you just have a regular dial - up shell account on some UNIX computer; get it via FTP (user: - anonymous) from - ftp://metalab.unc.edu/pub/Linux/system/network/serial/). Note that - you don't need "PPP support" if you just want to run 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 (to browse - the WWW, you need to have access to a machine on the Internet that - has a program like lynx or netscape)). + serial) lines. Most ISPs these days support PPP rather than SLIP. To use PPP, you need an additional program called pppd as described in Documentation/networking/ppp.txt and in the PPP-HOWTO, available @@ -5197,19 +5201,55 @@ from an older kernel, you might need to upgrade pppd as well. The PPP option enlarges your kernel by about 16 KB. + Almost always, if you answer Y or M to this question, you should + give the same answer to the next question, about PPP support for + async serial ports. + 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 said Y to "Version information on all symbols" above, then you cannot compile the PPP driver into the kernel; you can then only - compile it as a module. The module will be called ppp.o. If you want - to compile it as a module, say M here and read + compile it as a module. The module will be called ppp_generic.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. Note that, no matter what - you do, the BSD compression code (used to compress the IP packets - sent over the serial line; has to be supported at the other end as - well) will always be compiled as a module; it is called bsd_comp.o - and will show up in the directory modules once you have said "make - modules". If unsure, say N. + Documentation/networking/net-modules.txt. + +PPP support for async serial ports +CONFIG_PPP_ASYNC + Say Y (or M) here if you want to be able to use PPP over standard + asynchronous serial ports, such as COM1 or COM2 on a PC. If you use + a modem (not a synchronous or ISDN modem) to contact your ISP, you + need this option. + + This code is also available as a module (code which can be inserted + into and removed from the running kernel). If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +PPP Deflate compression +CONFIG_PPP_DEFLATE + Support for the Deflate compression method for PPP, which uses the + Deflate algorithm (the same algorithm that gzip uses) to compress + each PPP packet before it is sent over the wire. The peer (the + machine at the other end of the PPP link, usually your ISP) has to + support the Deflate compression method as well for this to be + useful. + + This code is also available as a module (code which can be inserted + into and removed from the running kernel). If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +PPP BSD-Compress compression +CONFIG_PPP_BSDCOMP + Support for the BSD-Compress compression method for PPP, which uses + the LZW compression method to compress each PPP packet before it is + sent over the wire. The peer (the other end of the PPP link) has to + support the BSD-Compress compression method as well for this to be + useful. The PPP Deflate compression method is preferable to + BSD-Compress, because it compresses better and is patent-free. + + Note that the BSD compression code will always be compiled as a + module; it is called bsd_comp.o and will show up in the directory + modules once you have said "make modules". If unsure, say N. Wireless LAN (non-hamradio) CONFIG_NET_RADIO @@ -5312,26 +5352,6 @@ say M here and read Documentation/modules.txt. The module will be called x25_asy.o. If unsure, say N. -Shortwave radio modem driver -CONFIG_HFMODEM - This experimental driver is used by a package (to be released) - that implements the shortwave radio protocols RTTY, Sitor (Amtor), - Pactor 1 and GTOR using a standard PC sound card. If unsure, - say N. - -Shortwave radio modem driver support for Sound Blaster and compatible cards -CONFIG_HFMODEM_SBC - This option enables the hfmodem driver to use Sound Blaster and - compatible cards. It requires a 16bit capable card, i.e. - SB16 or better, or ESS1688 or newer. - -Shortwave radio modem driver support for WSS and Crystal cards -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). - PLIP (parallel port) support CONFIG_PLIP PLIP (Parallel Line Internet Protocol) is used to create a @@ -5534,7 +5554,7 @@ section (except for CONFIG_IP_ROUTE_TOS and CONFIG_IP_ROUTE_FWMARK). At the moment, few devices support fast switching (tulip is one of them, modified 8390 can be found at - ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). + ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz). If unsure, say N. @@ -5544,8 +5564,8 @@ during periods of extremal congestion. At the moment only a couple of device drivers support it (really only one -- tulip, modified 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 + ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz). + Really, this option is applicable to any machine attached to a fast enough network, and even a 10 Mb NIC is able to kill a not very slow box, such as a 120MHz Pentium. @@ -9397,7 +9417,7 @@ If you run Linux on a multiprocessor machine and said Y to "Symmetric Multi Processing" above, you should say Y here to read - and set the RTC clock in an SMP compatible fashion. + and set the RTC in an SMP compatible fashion. If you think you have a use for such a device (such as periodic data sampling), then say Y here, and read Documentation/rtc.txt for @@ -11938,10 +11958,20 @@ This driver will eventually handle audio devices, such as USB speakers. -USB Abstract Control Model support (Preliminary) +USB Communications Device Class (ACM) support (Preliminary) CONFIG_USB_ACM - This driver allows for devices which support the Abstract Control Model, - including many USB-based modems, ISDN adapters, and network adapters. + This driver handles devices which support the Abstract Control Model, + a subtype of the USB Communications Device Class. This includes many + USB-based modems and ISDN adapters. Add special files with: + mknod /dev/ttyACM0 c 166 0 + mknod /dev/ttyACM1 c 166 1 + mknod /dev/ttyACM2 c 166 2 + mknod /dev/ttyACM3 c 166 3 + +USS720 parport driver +CONFIG_USB_USS720 + This driver is for USB parallel port adapters that use the USS-720 + chip. USB /proc filesystem entry support (Preliminary) CONFIG_USB_PROC @@ -12102,7 +12132,7 @@ # LocalWords: KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt RX mdafb # LocalWords: dataless kerneltype SYSNAME Comtrol Rocketport palmtop fbset EGS # LocalWords: nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY -# LocalWords: HFMODEM shortwave Sitor Amtor Pactor GTOR hfmodem hayes TX TMOUT +# LocalWords: hayes TX TMOUT # LocalWords: IDEPCI IDEDMA idedma PDC pdc TRM trm raidtools luthien nuclecu # LocalWords: unam mx miguel koobera uic EMUL solaris pp ieee lpsg co DMAs TOS # LocalWords: BLDCONFIG preloading jumperless BOOTINIT modutils multipath GRE diff -u --recursive --new-file v2.3.12/linux/Documentation/devices.tex linux/Documentation/devices.tex --- v2.3.12/linux/Documentation/devices.tex Thu May 13 11:00:08 1999 +++ linux/Documentation/devices.tex Thu Aug 5 18:48:45 1999 @@ -1784,11 +1784,31 @@ \end{devicelist} \begin{devicelist} +\major{ }{}{block}{Eighth IDE hard disk/CD-ROM interface} + \minor{0}{/dev/hdq}{Master: whole disk (or CD-ROM)} + \minor{64}{/dev/hdr}{Slave: whole disk (or CD-ROM)} +\end{devicelist} + +\noindent +Partitions are handled the same way as for the first interface (see +major number 3). + +\begin{devicelist} \major{91}{}{char }{CAN-Bus controller} \minor{0}{/dev/can0}{First CAN-Bus controller} \minor{1}{/dev/can1}{Second CAN-Bus controller} \minordots \end{devicelist} + +\begin{devicelist} +\major{ }{}{block}{Ninth IDE hard disk/CD-ROM interface} + \minor{0}{/dev/hds}{Master: whole disk (or CD-ROM)} + \minor{64}{/dev/hdt}{Slave: whole disk (or CD-ROM)} +\end{devicelist} + +\noindent +Partitions are handled the same way as for the first interface (see +major number 3). \begin{devicelist} \major{92}{}{char }{Reserved for ith Kommunikationstechnik MIC ISDN card} diff -u --recursive --new-file v2.3.12/linux/Documentation/devices.txt linux/Documentation/devices.txt --- v2.3.12/linux/Documentation/devices.txt Thu May 13 11:00:08 1999 +++ linux/Documentation/devices.txt Thu Aug 5 18:48:45 1999 @@ -1241,10 +1241,24 @@ 30 = /dev/mtd15 16th MTD (rw) 31 = /dev/mtdr15 16th MTD (ro) + block Eighth IDE hard disk/CD-ROM interface + 0 = /dev/hdq Master: whole disk (or CD-ROM) + 64 = /dev/hdr Slave: whole disk (or CD-ROM) + + Partitions are handled the same way as for the first + interface (see major number 3). + 91 char CAN-Bus devices 0 = /dev/can0 First CAN-Bus controller 1 = /dev/can1 Second CAN-Bus controller ... + + block Ninth IDE hard disk/CD-ROM interface + 0 = /dev/hds Master: whole disk (or CD-ROM) + 64 = /dev/hdt Slave: whole disk (or CD-ROM) + + Partitions are handled the same way as for the first + interface (see major number 3). 92 char Reserved for ith Kommunikationstechnik MIC ISDN card diff -u --recursive --new-file v2.3.12/linux/Documentation/joystick-api.txt linux/Documentation/joystick-api.txt --- v2.3.12/linux/Documentation/joystick-api.txt Wed Oct 21 08:43:33 1998 +++ linux/Documentation/joystick-api.txt Wed Aug 4 21:08:36 1999 @@ -1,7 +1,7 @@ Joystick API Documentation -*-Text-*- Ragnar Hojland Espinosa - + 7 Aug 1998 @@ -74,9 +74,10 @@ 2nd Axis Y 3 ...and so on -Hats vary from one joystick type to another. Some can be moved in 8 -directions, some only in 4, however, the driver always reports a hat as two -independent axis, even if the hardware doesn't allow independent movement. +Hats vary from one joystick type to another. Some can be moved in 8 +directions, some only in 4. The driver, however, always reports a hat +as two independent axis, even if the hardware doesn't allow independent +movement. 2.3 js_event.value @@ -85,7 +86,7 @@ For an axis, ``value'' is a signed integer between -32767 and +32767 representing the position of the joystick along that axis. If you don't read a 0 when the joystick is `dead', or if it doesn't span the -full range, you should recalibrate (with, for example, jscal). +full range, you should recalibrate it (with, for example, jscal). For a button, ``value'' for a press button event is 1 and for a release button event is 0. @@ -93,16 +94,16 @@ Though this if (js_event.type == JS_EVENT_BUTTON) { - buttons_state ^= (1 << js_event.number); + buttons_state ^= (1 << js_event.number); } may work well if you handle JS_EVENT_INIT events separately, if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) { - if (js_event.value) - buttons_state |= (1 << js_event.number); - else - buttons_state &= ~(1 << js_event.number); + if (js_event.value) + buttons_state |= (1 << js_event.number); + else + buttons_state &= ~(1 << js_event.number); } is much safer since it can't lose sync with the driver. As you would @@ -112,6 +113,7 @@ 2.4 js_event.time ~~~~~~~~~~~~~~~~~ + The time an event was generated is stored in ``js_event.time''. It's a time in miliseconds since ... well, since sometime in the past. This eases the task of detecting double clicks, figuring out if movement of axis and button @@ -144,14 +146,14 @@ For example, while (1) { - while (read (fd, &e, sizeof(struct js_event)) > 0) { - process_event (e); - } - /* EAGAIN is returned when the queue is empty */ - if (errno != EAGAIN) { - /* error */ - } - /* do something interesting with processed events */ + while (read (fd, &e, sizeof(struct js_event)) > 0) { + process_event (e); + } + /* EAGAIN is returned when the queue is empty */ + if (errno != EAGAIN) { + /* error */ + } + /* do something interesting with processed events */ } One reason for emptying the queue is that if it gets full you'll start @@ -219,6 +221,7 @@ #ifdef JS_VERSION #if JS_VERSION > 0xsomething + 4.2 JSIOCGNAME ~~~~~~~~~~~~~~ @@ -232,6 +235,7 @@ strncpy(name, "Unknown", sizeof(name)); printf("Name: %s\n", name); + 4.3 JSIOC[SG]CORR ~~~~~~~~~~~~~~~~~ @@ -266,10 +270,10 @@ struct JS_DATA_TYPE js; while (1) { - if (read (fd, &js, JS_RETURN) != JS_RETURN) { - /* error */ - } - usleep (1000); + if (read (fd, &js, JS_RETURN) != JS_RETURN) { + /* error */ + } + usleep (1000); } As you can figure out from the example, the read returns immediately, @@ -298,6 +302,7 @@ The v0.8.0.2 driver also had an interface for 'digital joysticks', (now called Multisystem joystick in this driver), under /dev/djsX. This driver doesn't try to be compatible with that interface. + 6. Final Notes ~~~~~~~~~~~~~~ diff -u --recursive --new-file v2.3.12/linux/Documentation/modules.txt linux/Documentation/modules.txt --- v2.3.12/linux/Documentation/modules.txt Tue Mar 10 14:43:13 1998 +++ linux/Documentation/modules.txt Thu Aug 5 14:34:01 1999 @@ -59,7 +59,7 @@ Most low-level SCSI drivers: (i.e. aha1542, in2000) All SCSI high-level drivers: disk, tape, cdrom, generic. - Most ethernet drivers: (too many to list, please see the file + Most Ethernet drivers: (too many to list, please see the file ./Documentation/networking/net-modules.txt) Most CDROM drivers: diff -u --recursive --new-file v2.3.12/linux/Documentation/mtrr.txt linux/Documentation/mtrr.txt --- v2.3.12/linux/Documentation/mtrr.txt Thu Jun 3 08:17:28 1999 +++ linux/Documentation/mtrr.txt Thu Aug 5 14:34:01 1999 @@ -52,7 +52,7 @@ reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1 reg02: base=0xf8000000 (3968MB), size= 4MB: write-combining, count=1 -This is for videoram at base address 0xf8000000 and size 4 MBytes. To +This is for video RAM at base address 0xf8000000 and size 4 megabytes. To find out your base address, you need to look at the output of your X server, which tells you where the linear framebuffer address is. A typical line that you may get is: @@ -68,7 +68,7 @@ (--) S3: videoram: 4096k -That's 4 MBytes, which is 0x400000 bytes (in hexadecimal). +That's 4 megabytes, which is 0x400000 bytes (in hexadecimal). A patch is being written for XFree86 which will make this automatic: in other words the X server will manipulate /proc/mtrr using the ioctl() interface, so users won't have to do anything. If you use a diff -u --recursive --new-file v2.3.12/linux/Documentation/nbd.txt linux/Documentation/nbd.txt --- v2.3.12/linux/Documentation/nbd.txt Thu Feb 26 11:01:24 1998 +++ linux/Documentation/nbd.txt Thu Aug 5 14:34:01 1999 @@ -4,11 +4,11 @@ means, that it works on my computer, and it worked on one of school computers. - What is it: With this compiled in the kernel, linux can use a remote + What is it: With this compiled in the kernel, Linux can use a remote server as one of its block devices. So every time the client computer wants to read /dev/nd0, it sends a request over TCP to the server, which will reply with the data read. This can be used for stations with - low-disk space (or even diskless - if you boot from floppy) to + low disk space (or even diskless - if you boot from floppy) to borrow disk space from another computer. Unlike NFS, it is possible to put any filesystem on it etc. It is impossible to use NBD as a root filesystem, since it requires a user-level program to start. It also diff -u --recursive --new-file v2.3.12/linux/Documentation/networking/00-INDEX linux/Documentation/networking/00-INDEX --- v2.3.12/linux/Documentation/networking/00-INDEX Wed May 20 18:54:34 1998 +++ linux/Documentation/networking/00-INDEX Thu Aug 5 14:34:01 1999 @@ -13,9 +13,9 @@ alias.txt - info on using alias network devices arcnet-hardware.txt - - tons of info on arcnet, hubs, arcnet card jumper settings, etc. + - tons of info on ARCnet, hubs, jumper settings for ARCnet cards, etc. arcnet.txt - - info on the using the arcnet driver itself. + - info on the using the ARCnet driver itself. ax25.txt - info on using AX.25 and NET/ROM code for Linux baycom.txt @@ -69,13 +69,13 @@ smc9.txt - the driver for SMC's 9000 series of Ethernet cards soundmodem.txt - - Linux driver for soundcards as AX.25 modems + - Linux driver for sound cards as AX.25 modems tcp.txt - short blurb on how TCP output takes place. tulip.txt - info on using DEC 21040/21041/21140 based PCI Ethernet cards. vortex.txt - - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) e'net cards. + - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards. wan-router.txt - Wan router documentation wanpipe.txt diff -u --recursive --new-file v2.3.12/linux/Documentation/networking/Configurable linux/Documentation/networking/Configurable --- v2.3.12/linux/Documentation/networking/Configurable Thu Sep 4 13:25:28 1997 +++ linux/Documentation/networking/Configurable Thu Aug 5 14:34:01 1999 @@ -20,11 +20,11 @@ 7000 Others are already accessible via the related user space programs. -For example, MAX_WINDOW has a default of 32k which is a good choice for -modern hardware, but if you have a slow (8 bit) ethercard and/or a slow +For example, MAX_WINDOW has a default of 32 k which is a good choice for +modern hardware, but if you have a slow (8 bit) Ethernet card and/or a slow machine, then this will be far too big for the card to keep up with fast -Tx'ing machines on the same net, resulting in overruns and receive errors. -A value of about 4k would be more appropriate, which can be set via: +machines transmitting on the same net, resulting in overruns and receive errors. +A value of about 4 k would be more appropriate, which can be set via: # route add -net 192.168.3.0 window 4096 diff -u --recursive --new-file v2.3.12/linux/Documentation/networking/DLINK.txt linux/Documentation/networking/DLINK.txt --- v2.3.12/linux/Documentation/networking/DLINK.txt Wed May 20 18:54:34 1998 +++ linux/Documentation/networking/DLINK.txt Thu Aug 5 14:34:01 1999 @@ -18,8 +18,8 @@ pocket adapters, for the parallel port on a Linux based machine. Some adapter "clones" will also work. Xircom is _not_ a clone... These drivers _can_ be used as loadable modules, - and were developed for use on Linux v1.1.13 and above. - For use on Linux v1.0.X, or earlier releases, see below. + and were developed for use on Linux 1.1.13 and above. + For use on Linux 1.0.X, or earlier releases, see below. I have used these drivers for NFS, ftp, telnet and X-clients on remote machines. Transmissions with ftp seems to work as @@ -57,7 +57,7 @@ de620.h Macros for de620.c If you are upgrading from the d-link tar release, there will - also be a "dlink-patches" file that will patch Linux v1.1.18: + also be a "dlink-patches" file that will patch Linux 1.1.18: linux/drivers/net/Makefile linux/drivers/net/CONFIG linux/drivers/net/MODULES @@ -162,10 +162,10 @@ 6. USING THE DRIVERS WITH EARLIER RELEASES. - The later v1.1.X releases of the Linux kernel include some + The later 1.1.X releases of the Linux kernel include some changes in the networking layer (a.k.a. NET3). This affects these drivers in a few places. The hints that follow are - _not_ tested by me, since I don't have the diskspace to keep + _not_ tested by me, since I don't have the disk space to keep all releases on-line. Known needed changes to date: - release patchfile: some patches will fail, but they should diff -u --recursive --new-file v2.3.12/linux/Documentation/networking/dgrs.txt linux/Documentation/networking/dgrs.txt --- v2.3.12/linux/Documentation/networking/dgrs.txt Wed May 20 18:54:34 1998 +++ linux/Documentation/networking/dgrs.txt Thu Aug 5 14:34:01 1999 @@ -1,4 +1,4 @@ - The Digi Intl. RightSwitch SE-X (dgrs) Device Driver + The Digi International RightSwitch SE-X (dgrs) Device Driver This is a Linux driver for the Digi International RightSwitch SE-X EISA and PCI boards. These are 4 (EISA) or 6 (PCI) port Ethernet diff -u --recursive --new-file v2.3.12/linux/Documentation/networking/multicast.txt linux/Documentation/networking/multicast.txt --- v2.3.12/linux/Documentation/networking/multicast.txt Thu Jun 4 22:53:50 1998 +++ linux/Documentation/networking/multicast.txt Mon Aug 9 10:23:09 1999 @@ -1,11 +1,13 @@ -Behaviour of cards under Multicast. This is how they currently -behave not what the hardware can do - i.e. the lance driver doesn't -use its filter, even though the code for loading it is in the DEC -lance based driver. +Behaviour of Cards Under Multicast +================================== -The following multicast requirements are needed +This is how they currently behave, not what the hardware can do--for example, +the Lance driver doesn't use its filter, even though the code for loading +it is in the DEC Lance-based driver. + +The following are requirements for multicasting ----------------------------------------------- -Appletalk Multicast hardware filtering not important but +AppleTalk Multicast hardware filtering not important but avoid cards only doing promisc IP-Multicast Multicast hardware filters really help IP-MRoute AllMulti hardware filters are of no help diff -u --recursive --new-file v2.3.12/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt --- v2.3.12/linux/Documentation/scsi-generic.txt Sat Apr 24 17:49:37 1999 +++ linux/Documentation/scsi-generic.txt Thu Aug 5 14:34:01 1999 @@ -1,34 +1,38 @@ - Notes on Linux's SG driver version 2.1.30 + Notes on Linux's SG driver version 2.1.34 ----------------------------------------- - 990328 + 990606 Introduction ============ +Sg is one of the four "high level" SCSI device drivers along with +sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized +(but lower level) than its siblings and tends to be used on SCSI devices +that don't fit into the already serviced categories. Thus sg is used for +scanners, cd writers and reading audio cds digitally amongst other things. + These are notes on the Linux SCSI generic packet device driver (sg) -describing version 2.1.30 . The original driver was written by Lawrence -Foard and has remained in place with minimal changes since circa 1992. +describing version 2.1.34 . The original driver was written by Lawrence +Foard and remained in place with minimal changes since circa 1992. Version 2 of this driver remains backward compatible (binary and source **) with the original. It adds scatter gather, command queuing, per file descriptor sequencing, asynchronous notification and better error reporting. -Sg is one of the four "high level" SCSI device drivers along with -sd, st and sr (disk, tape and CDROM respectively). Sg is more generalized -(but lower level) than its sibling and tends to be used on SCSI devices -that don't fit into the already serviced categories. Thus sg is used for -scanners, cd writers and reading audio cds amongst other things. +This is an abridged version of the sg documentation that is targeted +at the linux/Documentation directory. The full document can be found +at http://www.torque.net/sg/p/scsi-generic_long.txt . -The interface and usage of the original sg driver has been documented +The interface and usage of the original sg driver have been documented by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy of the document is version 1.5 dated 7th May 1996. It can found at -ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/SCSI-Programming-HOWTO . -Amongst other things it has a lot of tables from the SCSI-2 standard -that are very useful for programming this interface. +ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO-SCSI-Programming-HOWTO . +A copy of this document can be found at: +http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO . ** It is possible to write applications that perform differently depending on whether they are using the original or this version of -the sg device driver. The author is not aware of any useful applications -that have problems with version 2 (yet). +the sg device driver. The author is not aware of any useful +pre-existing applications that have problems with version 2 (yet). Architecture @@ -38,9 +42,11 @@ the others are sd (for direct-access devices - disks), st (for tapes) and sr (for data cdroms). The other three devices are block devices. -The unifying layer of the SCSI sub-system in the so-called mid-level. -Below that are all the drivers for the various adapters supported by -Linux. +The unifying layer of the SCSI sub-system is the so-called mid-level. +Below that are the "low level" drivers which are the drivers for the +various adapters supported by Linux. Also at this level are pseudo +adapter drivers such as ide-scsi which converts the SCSI protocol to +ATAPI (which are similar to one another) for use by IDE devices. Since sg is a character device it supports the traditional Unix system calls of open(), close(), read(), write() and ioctl(). Two other @@ -85,8 +91,9 @@ unsigned char sense_buffer[16]; }; /* this structure is 36 bytes long */ -The 'pack_len' is bizzare and ends up having the 'reply_len' put in it -(perhaps it had a use at some stage). +The 'pack_len' is bizarre and ends up having the 'reply_len' put in it +(perhaps it had a use at some stage). Even though it looks like an +input variable, it is not read by sg internally (only written). The 'reply_len' is the length of the data the corresponding read() will/should request (including the sg_header). @@ -95,14 +102,14 @@ back to the corresponding read() so it can be used for sequencing by an application. -The 'result' is also bizzare, turning certain types of host codes it 0 (no +The 'result' is also bizarre, turning certain types of host codes to 0 (no error), EBUSY or EIO. With better error reporting now available, the 'result' is best ignored. -The 'twelve_byte' field overrides the internal SCSI command length "guessing" +The 'twelve_byte' field overrides the internal SCSI command length detection algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces -a command lenth of 12 bytes. -The command length "guessing" algorithm is as follows: +a command length of 12 bytes. +The command length detection algorithm is as follows: Group: 0 1 2 3 4 5 6 7 Length: 6 10 10 12 12 12 10 10 @@ -115,6 +122,7 @@ buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately this is unlikely to happen in the 2.2.x series of kernels. + The new sg_header offered in this driver is: #define SG_MAX_SENSE 16 struct sg_header @@ -122,15 +130,17 @@ int pack_len; /* [o] reply_len (ie useless) ignored as input */ int reply_len; /* [i] max length of expected reply (inc. sg_header) */ int pack_id; /* [io] id number of packet (use ints >= 0) */ - int result; /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */ + int result; /* [o] 0==ok, else (+ve) Unix errno (best ignored) */ unsigned int twelve_byte:1; /* [i] Force 12 byte command length for group 6 & 7 commands */ unsigned int target_status:5; /* [o] scsi status from target */ unsigned int host_status:8; /* [o] host status (see "DID" codes) */ unsigned int driver_status:8; /* [o] driver status+suggestion */ unsigned int other_flags:10; /* unused */ - unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] when target_status is - CHECK_CONDITION or COMMAND_TERMINATED this is output. */ + unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases: + when target_status is CHECK_CONDITION or + when target_status is COMMAND_TERMINATED or + when (driver_status & DRIVER_SENSE) is true. */ }; /* This structure is 36 bytes long on i386 */ Firstly the new header is binary compatible with the original. This is @@ -146,6 +156,9 @@ the value of 'pack_id' available after a read() is the value given to that variable in the prior, corresponding write(). +The SCSI command length can now be given directly using the SG_NEXT_CMD_LEN +ioctl(). + The 'target_status' field is always output and is the (masked and shifted 1 bit right) SCSI status code from the target device. The allowable values are (found in ): @@ -162,28 +175,28 @@ When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the 'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE) is true then the 'sense_buffer' is also output (this seems to occur when -the scsi ide emulation is used). When the 'sense_buffer' is output the +the ide-scsi emulation is used). When the 'sense_buffer' is output the SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) . The 'host_status' field is always output and has the following values -whose "defines" are not visible outside the kernel (unfortunately): +whose "defines" are not visible outside the kernel. A copy of these +defines can be found in sg_err.h (see the utilities section): #define DID_OK 0x00 /* NO error */ #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ #define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ #define DID_TIME_OUT 0x03 /* TIMED OUT for other reason */ -#define DID_BAD_TARGET 0x04 /* BAD target. */ +#define DID_BAD_TARGET 0x04 /* BAD target, device not responding? */ #define DID_ABORT 0x05 /* Told to abort for some other reason */ #define DID_PARITY 0x06 /* Parity error */ -#define DID_ERROR 0x07 /* Internal error */ +#define DID_ERROR 0x07 /* Internal error [DMA underrun on aic7xxx]*/ #define DID_RESET 0x08 /* Reset by somebody. */ #define DID_BAD_INTR 0x09 /* Got an interrupt we weren't expecting. */ #define DID_PASSTHROUGH 0x0a /* Force command past mid-layer */ -#define DID_SOFT_ERROR 0x0b /* The low level driver just wish a retry */ +#define DID_SOFT_ERROR 0x0b /* The low level driver wants a retry */ The 'driver_status' field is always output. When ('driver_status' & -DRIVER_SENSE) is true the 'sense_buffer' is also output. The following -values whose "defines" are not visible outside the kernel (unfortunately) -can occur: +DRIVER_SENSE) is true the 'sense_buffer' is also output. A copy of these +defines can be found in sg_err.h (see the utilities section): #define DRIVER_OK 0x00 /* Typically no suggestion */ #define DRIVER_BUSY 0x01 #define DRIVER_SOFT 0x02 @@ -192,7 +205,7 @@ #define DRIVER_INVALID 0x05 #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 -#define DRIVER_SENSE 0x08 +#define DRIVER_SENSE 0x08 /* Implies sense_buffer output */ /* above status 'or'ed with one of the following suggestions */ #define SUGGEST_RETRY 0x10 #define SUGGEST_ABORT 0x20 @@ -200,55 +213,8 @@ #define SUGGEST_DIE 0x40 #define SUGGEST_SENSE 0x80 -'other_flags' still remains as a 10 bit field, so code that places 0 in it -will still be happy. It is not used. - - -memory -====== -Memory is a scarce resource in any computer. Sg needs to reserve memory -suitable for DMA roughly equal in size to the maximum of the write and -read data buffers for each packet. This DMA memory is obtained at the time -of a write() and released when the corresponding read() is called (although -if memory is tight it may be using the buffer reserved by the open() ). - -Linux obtaining memory a challenge for several reasons. The memory pool -that sg uses is in common with all other device drivers and all user -processes. In this environment the only way to 99.9% guarantee a driver -will have memory in Linux is to build it into the kernel (ie not as a -module) and then reserve it on initialization before user processes get -a chance. [Of course, another driver initialized before sg could take -all available memory ...] Another problem is the biggest contiguous -chunk of memory that can be obtained from the kernel is 32 * PAGE_SIZE -(which is 128KBytes on i386). As memory gets "splintered" there is a good -chance that buffers won't be available (my machine has 64 MBytes of RAM -and has 3 available at the moment). - -The original sg driver used the following technique: grab a SG_BIG_BUFF -sized buffer at driver initialization and use it for all requests greater -than PAGE_SIZE (4096 bytes on i386). By default SG_BIG_BUFF is set to -32 KBytes in the origianl driver but many applications suggest that the -user increases this number. Linux limits the biggest single buffer of -this type to 32 * PAGE_SIZE (128KBytes on i386). Unfortunately if the -sg driver is a module then there is a high chance a contiguous block of -that large size will not be available at module initialization. - -The author has found no "silver bullet" solution but uses multiple -techniques hoping that at least one is able provide memory at the critical -time. Listed below are some of these techniques: - - use scatter gather: then instead of one large buffer needing to - be found, multiple smaller buffer can be used - - use memory above the 16MByte level: the original driver limited - itself to obtaining memory below the 16MByte level (on the i386) - due to the shortcomings of DMA on ISA adapters. Yet more and more - people use PCI adapters that don't have this problem. So make - the decision based on the capabilities of the host adpater - associated with the current SCSI device - - reserve some memory at open() for emergencies but otherwise - fetch and release it on a per packet basis - - if the kernel is short of memory then dip into the SCSI DMA - pool (maintained by the mid-level driver) to a limited amount - +'other_flags' still remains as a 10 bit field (reduced from 31 bits), so +code that places 0 in it will still be happy. It is not used. System Calls @@ -257,16 +223,16 @@ Unix operating system calls when applied to a SCSI generic device using this version of the device driver. -open ----- +open(const char * filename, int flags) +-------------------------------------- The filename should be an 'sg' device such as /dev/sg[a-z] /dev/sg[0,1,2,...] or a symbolic link to one of these. [Devfs has its own sub-directory for -sg devices.] It seems as though SCSI devices are allocated to sg minor -numbers in the same order as they appear in 'cat /proc/scsi/scsi'. -Sg is a "character" based Linux device driver. This means it has an -open/close/read/write/ioctl type interface. +sg devices with entries like: /dev/sg/c1b2t3u4 .] It seems as though SCSI +devices are allocated to sg minor numbers in the same order as they appear +in 'cat /proc/scsi/scsi'. Sg is a "character" based Linux device driver. +This means it has an open/close/read/write/ioctl type interface. Flags can be either O_RDONLY or O_RDWR or-ed with either O_EXCL waits for other opens on sg device to be closed before @@ -279,7 +245,7 @@ The original version of sg did not allow the O_RDONLY (yielding a EACCES error). This version allows it for accessing ioctls (e.g. doing an sg device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be -allowed. +allowed. These flags are found in . By default, sequencing is per file descriptor in this version of sg. This means, for example that 2 processes can independently manipulate the same @@ -290,32 +256,38 @@ previous version of sg supported only per device sequencing and this can still be selected with the SG_SET_MERGE_FD,1 ioctl(). -The driver will attempt to reserve SG_SCATTER_SZ bytes (32KBytes in the -current sg.h) on open() for "emergency" situations. If this is unavailable -it will halve its request and try again. It gives up if PAGE_SIZE bytes -(4096 bytes on i386) cannot be obtained so no memory is reserved. In this -case open() will still return successfully. The actual amount of memory -reserved can be found with the SG_GET_RESERVED_SIZE ioctl(). +The driver will attempt to reserve SG_DEF_RESERVED_SIZE bytes (32KBytes in +the current sg.h) on open(). The size of this reserved buffer can +subsequently be modified with the SG_SET_RESERVED_SIZE ioctl(). In both +cases these are requests subject to various dynamic constraints. The actual +amount of memory obtained can be found by the SG_GET_RESERVED_SIZE ioctl(). +The reserved buffer will be used if: + - it is not already in use (eg when command queuing is in use) + - a write() does not call for a buffer size larger than the + reserved size. Returns a file descriptor if >= 0 , otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): -ENODEV sg not compiled into kernel or the kernel cannot find the - sg module (or it can't initialize itself (low memory??)) -ENXIO either scsi sub-system is currently processing some error - (eg doing a device reset) or the sg driver/module removed - or corrupted +EACCES Either the user doesn't have appropriate permissions on + 'filename' or attempted to use both O_RDONLY and O_EXCL EBUSY O_NONBLOCK set and some user of this sg device has O_EXCL set while someone is already using this device EINTR while waiting for an "exclusive" lock to clear, a signal is received, just try again ... +ENODEV sg not compiled into kernel or the kernel cannot find the + sg module (or it can't initialize itself (low memory??)) +ENOENT given filename not found ENOMEM An attempt to get memory to store this open's context failed (this was _not_ a request to reserve DMA memory) -EACCES An attempt to use both O_RDONLY and O_EXCL +ENXIO either there is no attached device corresponding to given + filename or scsi sub-system is currently processing some + error (eg doing a device reset) or the sg driver/module + removed or corrupted -write ------ +write(int sg_fd, const void * buffer, size_t count) +--------------------------------------------------- Even though sg is a character-based device driver it sends and receives packets to/from the associated scsi device. Write() is used to send a packet containing 2 mandatory parts and 1 optional part. The mandatory @@ -343,32 +315,33 @@ Returns number of bytes written if > 0 , otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): -ENXIO either scsi sub-system is currently processing some error - (eg doing a device reset) or the sg driver/module removed - or corrupted EACCES opened with RD_ONLY flag -EIO incoming buffer too short. It should be at least (6 + - sizeof(struct sg_header))==42 bytes long -EDOM a) command queuing off: a packet is already queued - b) command queuing on: too many packets queued - (SG_MAX_QUEUE exceeded) EAGAIN SCSI mid-level out of command blocks (rare), try again. This is more likely to happen when queuing commands, so wait a bit (eg usleep(10000) ) before trying again +EDOM a) command queuing off: a packet is already queued + b) command queuing on: too many packets queued + (SG_MAX_QUEUE exceeded) + c) SCSI command length given in SG_NEXT_CMD_LEN too long +EFAULT 'buffer' for 'count' bytes is an invalid memory range +EIO incoming buffer too short. It should be at least (6 + + sizeof(struct sg_header))==42 bytes long ENOMEM can't get memory for DMA. Take evasive action ... - (see section on memory) +ENXIO either scsi sub-system is currently processing some error + (eg doing a device reset) or the sg driver/module removed + or corrupted -read ----- +read(int sg_fd, void * buffer, size_t count) +-------------------------------------------- Read() is used to receive a packet containing 1 mandatory part and 1 optional part. The mandatory part is: - a control block (an instance of struct sg_header) The optional part is: - incoming data (eg if a SCSI read command was sent by earlier write() ) The buffer given to a read() and its corresponding count should be -sufficient to accommodate this packet to avoid truncation. Truncation has -occurred if count < sg_header::replylen . +sufficient to accommodate this packet to avoid truncation. Truncation occurs +if count < sg_header::replylen . By default, read() will return the oldest packet queued up. If the SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to @@ -377,7 +350,6 @@ wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given to read() will match the oldest packet. - Returns number of bytes read if > 0 , otherwise -1 implies an error. Unfortunately the return value in the non-error case is simply the same as the count argument. It is not the actual number of bytes @@ -385,25 +357,26 @@ such an underrun indication. Error codes (value in 'errno' after -1 returned): -ENXIO either scsi sub-system is currently processing some error - (eg doing a device reset) or the sg driver/module removed - or corrupted EAGAIN either no waiting packet or requested packet is not available while O_NONBLOCK flag was set +EFAULT 'buffer' for 'count' bytes is an invalid memory range EINTR while waiting for a packet, a signal is received, just try again ... EIO if the 'count' given to read() is < sizeof(struct sg_header) and the 'result' element in sg_header is non-zero. Not a recommended error reporting technique +ENXIO either scsi sub-system is currently processing some error + (eg doing a device reset) or the sg driver/module removed + or corrupted -close ------ +close(int sg_fd) +---------------- Preferably a close() should be done after all issued write()s have had their corresponding read() calls completed. Unfortunately this is not always possible. The semantics of close() in Unix are to return more or less immediately (ie not wait on any event) so the driver needs to -arrange to an orderly cleanup of those packets that are still "in +arrange for an orderly cleanup of those packets that are still "in flight". A process that has an open file descriptor to an sg device may be aborted @@ -411,22 +384,22 @@ (which is called 'sg_release()' in the version 2 driver) to facilitate the cleanup mentioned above. -A problem persists in version 2.1.8 if the sg driver is a module and is -removed while packets are still "in flight". Hopefully this will be soon -fixed. +A problem persists in version 2.1.34 if the sg driver is a module and is +removed while packets are still "in flight". Returns 0 if successful, otherwise -1 implies an error. Error codes (value in 'errno' after -1 returned): ENXIO sg driver/module removed or corrupted -ioctl (sg specific) -------------------- +ioctl(int sg_fd, int command, ...) [sg specific] +------------------------------------------------- Ken Thompson (or perhaps some other Unix luminary) described ioctl() as the "garbage bin of Unix". This driver compounds the situation by adding -around 18 more commands. These commands either yield state information (10 -of them), change the driver's characteristics (8 of them) or allow direct -communication with the common SCSI mid-level driver. +more ... +If a ioctl command is not recognized by sg (and the various lower levels +that it may pass the command on to) then the error EINVAL occurs. If an +invalid address is given (in the 3rd argument) then the error EFAULT occurs. Those commands with an appended "+" are new in version 2. @@ -442,15 +415,38 @@ SG_SET_TIMEOUT: Assumes 3rd argument points to an int containing the new timeout value for this file descriptor. The unit is a "jiffy". Packets that are -already "in flight" will not be effected. The default value is set -on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). +already "in flight" will not be affected. The default value is set +on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). This default is +currently 1 minute and may not be long enough for formats. SG_EMULATED_HOST: Assumes 3rd argument points to an int and outputs a flag indicating -whether the host (adapter) is connected to a real SCSI bus or is +whether the host (adapter) is connected to a real SCSI bus or is an emulated one (eg ide-scsi device driver). A value of 1 means emulated while 0 is not. +SG_SET_TRANSFORM W: +Third argument is ignored. Only is meaningful when SG_EMULATED host has +yielded 1 (ie the low-level is the ide-scsi device driver); otherwise +an EINVAL error occurs. The default state is to _not_ transform SCSI +commands to the corresponding ATAPI commands but pass them straight +through as is. [Only certain classes of SCSI commands need to be +transformed to their ATAPI equivalents.] Making this ioctl command causes +transforms to occur thereafter. Subsequent calls to this ioctl command +have no additional effect. Beware, this state will affect all devices +(and hence all related sg file descriptors) associated with this ide-scsi +"bus". +The author of ide-scsi has pointed out that this is not the intended +behaviour which is a 3rd argument of 0 to disable transforms and 1 to +enable transforms. Note the 3rd argument is an 'int' not a 'int *'. +Perhaps the intended behaviour will be implemented soon. + +SG_GET_TRANSFORM: +Third argument is ignored. Only is meaningful when SG_EMULATED host has +yielded 1 (ie the low-level is the ide-scsi device driver); otherwise +an EINVAL error occurs. Returns 0 to indicate _not_ transforming SCSI +to ATAPI commands (default). Returns 1 when it is transforming. + SG_SET_FORCE_LOW_DMA +: Assumes 3rd argument points to an int containing 0 or 1. 0 (default) means sg decides whether to use memory above 16 Mbyte level (on i386) @@ -459,10 +455,10 @@ space. If 1 is given then the host adapter is overridden and only memory below the 16MB level is used for DMA. A requirement for this should be -extremely rare. If the "reserve" buffer allocated on open() is not in +extremely rare. If the "reserved" buffer allocated on open() is not in use then it will be de-allocated and re-allocated under the 16MB level (and the latter operation could fail yielding ENOMEM). -Only the current file descriptor is effected. +Only the current file descriptor is affected. SG_GET_LOW_DMA +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 @@ -472,11 +468,11 @@ adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 . SG_GET_SCSI_ID +: -Assumes 3rd argument is pointing to an object of type Sg_scsi_id and -populates it. That structure contains ints for host_no, channel, -scsi_id, lun and scsi_type. Most of this information is available from -other sources (eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) -but tends to be awkward to collect. +Assumes 3rd argument is pointing to an object of type Sg_scsi_id (see +sg.h) and populates it. That structure contains ints for host_no, +channel, scsi_id, lun and scsi_type. Most of this information is +available from other sources (eg SCSI_IOCTL_GET_IDLUN and +SCSI_IOCTL_GET_BUS_NUMBER) but tends to be awkward to collect. SG_SET_FORCE_PACK_ID +: Assumes 3rd argument is pointing to an int. 0 (default) instructs read() @@ -486,9 +482,9 @@ oldest packet matching that pack_id or wait until it arrives (or yield EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1 given to read() in the mode will match the oldest packet. -Only the current file descriptor is effected by this command. +Only the current file descriptor is affected by this command. -SG_GET_LOW_DMA +: +SG_GET_PACK_ID +: Assumes 3rd argument points to an int and places the pack_id of the oldest (written) packet in it. If no packet is waiting to be read then yields -1. @@ -503,30 +499,33 @@ the adapter does support scatter gather. SG_SET_RESERVED_SIZE +W: -This is not currently implemented. It is intended for reserving either a -large buffer or scatter gather list that will be available until the -current file descriptor is closed. The requested amount of memory may -not be available so SG_GET_RESERVED_SIZE should be used after this call -to see how much was reserved. (EBUSY error possible) +Assumes 3rd argument is pointing to an int. That value will be used to +request a new reserved buffer of that size. The previous reserved buffer +is freed (if it is not in use; if it was in use -EBUSY is returned). +A new reserved buffer is then allocated and its actual size can be found by +calling the SG_GET_RESERVED_SIZE ioctl(). The reserved buffer is then used +for DMA purposes by subsequent write() commands if it is not already in +use and if the write() is not calling for a buffer size larger than that +reserved. The reserved buffer may well be a series of kernel buffers if the +adapter supports scatter-gather. Large buffers can be requested (eg 1 MB). SG_GET_RESERVED_SIZE +: Assumes 3rd argument points to an int and places the size in bytes of -the DMA buffer reserved on open() for emergencies. If this is 0 then it -is probably not wise to attempt on operation like burning a CD on this -file descriptor. +the reserved buffer from open() or the most recent SG_SET_RESERVED_SIZE +ioctl() call on this fd. The result can be 0 if memory is very tight. In +this case it may not be wise to attempt something like burning a CD on +this file descriptor. SG_SET_MERGE_FD +W: Assumes 3rd argument is pointing to an int. 0 (the default) causes all subsequent sequencing to be per file descriptor. 1 causes all subsequent sequencing to be per device. If this command tries to change the current -state and the is one or more _other_ file descriptors using this sg -device then an EBUSY error occurs. Also if this file descriptor was not -open()ed with the O_RDWR flag then an EACCES error occurs. -Per device sequencing was the original semantics and allowed, for example -different processes to "share" the device, one perhaps write()ing with -the other one read()ing. This command is supplied if anyone needs those -semantics. Per file descriptor sequencing, perhaps with the usage of -the O_EXCL flag, seems more sensible. +state and there is one or more _other_ file descriptors using this sg +device then an EBUSY error occurs. Per device sequencing was the original +semantics and allowed, for example different processes to "share" the +device, one perhaps write()ing with the other one read()ing. This command +is supplied if anyone needs those semantics. Per file descriptor +sequencing, perhaps with the use of the O_EXCL flag, seems more sensible. SG_GET_MERGE_FD +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies @@ -538,14 +537,42 @@ SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write() a packet while one is already queued will result in a EDOM error. 1 turns command queuing on. -Changing the queuing state only effects write()s done after the change. -Only the current file descriptor is effected by this command. +Changing the queuing state only affects write()s done after the change. +Only the current file descriptor is affected by this command. SG_GET_COMMAND_Q +: Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies that command queuing is off on this file descriptor. 1 implies command queuing is on. +SG_SET_UNDERRUN_FLAG +: +Assumes 3rd argument is pointing to an int. 0 (current default, set by +SG_DEF_UNDERRUN_FLAG in sg.h) requests underruns be ignored. 1 requests +that underruns be flagged. [The only low level driver that acts on this +at the moment is the aic7xxx which yields a DID_ERROR error on underrun.] +Only the current file descriptor is affected by this command (unless +"per device" sequencing has been selected). + +SG_GET_UNDERRUN_FLAG +: +Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies +that underruns are not being reported. 1 implies that underruns are being +reported (see SG_SET_UNDERRUN_FLAG for more details). + +SG_NEXT_CMD_LEN +: +Assumes 3rd argument is pointing to an int. The value of the int (if > 0) +will be used as the SCSI command length of the next SCSI command sent to +a write() on this fd. After that write() the SCSI command length logic is +reset to use automatic length detection (ie depending on SCSI command group +and the 'twelve_byte' field). If the current SCSI command length maximum of +12 is exceeded then the affected write() will yield an EDOM error. +Giving this ioctl() a value of 0 will set automatic length detection for +the next write(). N.B. Only the following write() on this fd is affected by +this ioctl(). + +SG_GET_VERSION_NUM +: +Assumes 3rd argument points to an int. The version number is then placed +in that int. A sg version such as 2.1.34 will yield "20134" from this ioctl. + SG_SET_DEBUG +: Assumes 3rd argument is pointing to an int. 0 (default) turns debugging off. Values > 0 cause the SCSI sense buffer to be decoded and output @@ -556,73 +583,53 @@ the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of debug will appear in your console/log. -ioctl (in common with sd, st + sr) ----------------------------------- -The following ioctl()s can be called from any high-level scsi device -driver (ie sd, st, sr + sg). Access permissions may differ a bit from -one device to another, the access information given below is specific to -the sg device driver. - -SCSI_IOCTL_GET_IDLUN: -SCSI_IOCTL_GET_BUS_NUMBER: - -SCSI_IOCTL_SEND_COMMAND: W -If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto -the SCSI mid-level driver for processing. -Don't know much about this one but it looks pretty powerful and -dangerous. Some comments says it is also deprecated. - -: W -If open()ed O_RDONLY yields an EACCESS error. Otherwise is forwarded onto -the SCSI mid-level driver for processing. - -poll ----- +poll(struct pollfd * udfds, unsigned int nfds, int timeout_ms) +-------------------------------------------------------------- This is a native call in Linux 2.2 but most of its capabilities are available through the older select() call. Given a choice poll() should probably be used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK -for polling; or alternatively with asynchronous notification using the -fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal. +for polling; and optionally with asynchronous notification as well using +the fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal. Only if something drastically is wrong (eg file handle gone stale) will POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set. POLLIN is set when there is one or more packets waiting to be read. -When POLLIN is set it implies that a read() will not block (or yield +When POLLIN is set it implies that a read() will not block (nor yield EAGAIN in non-blocking mode) but return a packet immediately. POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet -(ie will _not_ yield an EDOM error). The setting of POLLOUT is effected +(ie will _not_ yield an EDOM error). The setting of POLLOUT is affected by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain set until the number of queued packets reaches SG_MAX_QUEUE, if the state is off then POLLOUT is only set when no packets are queued. Note that a packet can be queued after write()ing but not available to be read(); this typically happens when a SCSI read command is issued while -the data is being retreaved. +the data is being retrieved. Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case it is per device. -fcntl ------ +fcntl(int sg_fd, int cmd) or fcntl(int sg_fd, int cmd, long arg) +---------------------------------------------------------------- There are several uses for this system call in association with a sg -file descriptor. The first pseudo code shows code that is useful for +file descriptor. The following pseudo code shows code that is useful for scanning the sg devices, taking care not to be caught in a wait for an O_EXCL lock by another process, and when the appropriate device is -found switching to normal blocked io. A working example of this logic -is in the sg_scan.c utility program. +found, switching to normal blocked io. A working example of this logic +is in the sg_scan utility program. open("/dev/sga", O_RDONLY | O_NONBLOCK) /* check device, EBUSY means some other process has O_EXCL lock on it */ -/* one the device you want is found then ... */ +/* when the device you want is found then ... */ flags = fcntl(sg_fd, F_GETFL) fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK)) -/* for simple apps is is easier to use normal blocked io */ +/* since, for simple apps, it is easier to use normal blocked io */ Some work has to be done in Linux to set up for asynchronous notification. -This is a non-blocking mode of operation in which when the driver receives +This is a non-blocking mode of operation in which, when the driver receives data back from a device so that a read() can be done, it sends a SIGPOLL (aka SIGIO) signal to the owning process. A working example of this logic -is in the sg_poll.c test program. +is in the sg_poll test program. sigemptyset(&sig_set) sigaddset(&sig_set, SIGPOLL) @@ -634,3 +641,91 @@ Utility and Test Programs ========================= +See the README file in the sg_utils.tgz tarball. At the time of +writing this was sg_utils990527.tgz . + +Briefly, that tarball contains the following utilities: +sg_dd512 'dd' like program that assumes 512 byte blocks size +sg_dd2048 'dd' like program that assumes 2048 byte blocks size +sgq_dd512 like 'sg_dd512' but does command queuing on "if" +sg_scan outputs information (optionally Inquiry) on SCSI devices +sg_rbuf tests SCSI bus transfer speed (without physical IO) +sg_whoami outputs info (optionally capacity) of given SCSI device +sginfo outputs "mode" information about SCSI devices (it is a + re-port of the scsiinfo program onto the sg interface) + +It also contains the following test programs: +sg_debug outputs sg driver state to console/log file +sg_poll tests asynchronous notification +sg_inquiry does a SCSI Inquiry command (from original HOWTO) +sg_tst_med checks presence of media (from original HOWTO) + +There are also 2 source files (sg_err.[hc]) for outputting and categorizing +SCSI 2 errors and warnings. This code is used by most of the above +utility and test programs. + +The following programs: sg_dd512, sg_dd2048, sg_scan, sg_rbuf, sg_tst_med, +sg_inquiry and sginfo, can be compiled either for this new sg driver _or_ +the original sg driver. + + +Header files +============ +User applications need to find the correct "sg.h" header file matching +their kernel in order to write code using the sg device driver. This is +sometimes more difficult than it should be. The correct "sg.h" will usually +be found at /usr/src/linux/include/scsi/sg.h . Another important header +file is "scsi.h" which will be in the same directory. + +Several distributions have taken their own copies of these files and placed +them in /usr/include/scsi which is where "#include " would go +looking. The directory /usr/include/scsi _should_ be a symbolic link to +/usr/src/linux/include/scsi/ . It was is Redhat 5.1 and 5.2 but it is +not is Redhat 6.0 . Some other distributions have the same problem. To +solve this (as root) do the following: + +# cd /usr/include +# mv scsi scsi_orig +# ln -s ../src/linux/include/scsi scsi + +This doesn't seem to be a problem with /usr/include/linux (at least in +Redhat where it is a symbolic link) so it is hard to understand why +/usr/include/scsi is defined the way it is. The fact the +/usr/include/linux is a symbolic link opens up the following solution +proposed by the author of cdparanoia (Monty): +#include + + +Extra information in scsi-generic_long.txt +========================================== +This document is an abridged form of a more comprehensive document called +scsi-generic_long.txt (see www.torque.net/sg/p/scsi-generic_long.txt). + +The longer document contains additional sections on: + - memory issues + - ioctl()s in common with sd, st + sr + - distinguishing the original from the new driver + - SG_BIG_BUFF and friends + - shortcomings + - future directions + - an appendix with some SCSI 2 information in it + + +Conclusion +========== +The SCSI generic packet device driver attempts to make as few assumptions +as possible about the device it is connected to while giving applications +using it as much flexibility as possible on the SCSI command level. Sg +needs to hide the "messy" kernel related details while protecting +the integrity of the kernel against sg "abuse". Some of these aims are +contradictory and some compromises need to be made. For example: should +a sg based application be able to reset a SCSI bus when that could cause +collateral damage to a disk holding the root file system? There is no +easy answer to this and many other related questions. + +If you have any suggestion about sg (or improving (the accuracy of) this +document) please contact me. + + +Douglas Gilbert +dgilbert@interlog.com diff -u --recursive --new-file v2.3.12/linux/Documentation/sx.txt linux/Documentation/sx.txt --- v2.3.12/linux/Documentation/sx.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sx.txt Thu Aug 5 14:47:44 1999 @@ -0,0 +1,289 @@ + + sx.txt -- specialix SX/SI multiport serial driver readme. + + + + Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) + + Specialix pays for the development and support of this driver. + Please DO contact support@specialix.co.uk if you require + support. + + This driver was developed in the BitWizard linux device + driver service. If you require a linux device driver for your + product, please contact devices@BitWizard.nl for a quote. + + (History) + There used to be an SI driver by Simon Allan. This is a complete + rewrite from scratch. Just a few lines-of-code have been snatched. + + (Sources) + Specialix document number 6210028: SX Host Card and Download Code + Software Functional Specification. + + (Copying) + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + USA. + + (Addendum) + I'd appreciate it that if you have fixes, that you send them + to me first. + + +Introduction +============ + +This file contains some random information, that I like to have online +instead of in a manual that can get lost. Ever misplace your Linux +kernel sources? And the manual of one of the boards in your computer? + + +Theory of operation +=================== + +An important thing to know is that the driver itself doesn't have the +firmware for the card. This means that you need the separate package +"sx_firmware". For now you can get the source at + + ftp://ftp.bitwizard.nl/specialix/sx_firmware_.tgz + +The firmware load needs a "misc" device, so you'll need to enable the +"Support for user misc device modules" in your kernel configuration. +The misc device needs to be called "/dev/specialix_sxctl". It needs +misc major 10, and minor number 167 (assigned by HPA). The section +on creating device files below also creates this device. + +After loading the sx.o module into your kernel, the driver will report +the number of cards detected, but because it doesn't have any +firmware, it will not be able to determine the number of ports. Only +when you then run "sx_firmware" will the firmware be downloaded and +the rest of the driver initialized. At that time the sx_firmware +program will report the number of ports installed. + +In contrast with many other multi port serial cards, some of the data +structures are only allocated when the card knows the number of ports +that are connected. This means we won't waste memory for 120 port +descriptor structures when you only have 8 ports. If you experience +problems due to this, please report them: I haven't seen any. + + +Interrupts +========== + +A multi port serial card, would generate a horrendous amount of +interrupts if it would interrupt the CPU for every received +character. Even more than 10 years ago, the trick not to use +interrupts but to poll the serial cards was invented. + +The SX card allow us to do this two ways. First the card limits its +own interrupt rate to a rate that won't overwhelm the CPU. Secondly, +we could forget about the cards interrupt completely and use the +internal timer for this purpose. + +Polling the card can take up to a few percent of your CPU. Using the +interrupts would be better if you have most of the ports idle. Using +timer-based polling is better if your card almost always has work to +do. You save the separate interrupt in that case. + +In any case, it doesn't really matter all that much. + +The most common problem with interrupts is that for ISA cards in a PCI +system the BIOS has to be told to configure that interrupt as "legacy +ISA". Otherwise the card can pull on the interrupt line all it wants +but the CPU won't see this. + +If you can't get the interrupt to work, remember that polling mode is +more efficient (provided you actually use the card intensively). + + +Allowed Configurations +====================== + +Some configurations are disallowed. Even though at a glance they might +seem to work, they are known to lockup the bus between the host card +and the device concentrators. You should respect the drivers decision +not to support certain configurations. It's there for a reason. + +Warning: Seriously technical stuff ahead. Executive summary: Don't use +SX cards except configured at a 64k boundary. Skip the next paragraph. + +The SX cards can theoretically be placed at a 32k boundary. So for +instance you can put an SX card at 0xc8000-0xd7fff. This is not a +"recommended configuration". ISA cards have to tell the bus controller +how they like their timing. Due to timing issues they have to do this +based on which 64k window the address falls into. This means that the +32k window below and above the SX card have to use exactly the same +timing as the SX card. That reportedly works for other SX cards. But +you're still left with two useless 32k windows that should not be used +by anybody else. + + +Configuring the driver +====================== + +PCI cards are always detected. The driver auto-probes for ISA cards at +some sensible addresses. Please report if the auto-probe causes trouble +in your system, or when a card isn't detected. + +I'm afraid I haven't implemented "kernel command line parameters" yet. +This means that if the default doesn't work for you, you shouldn't use +the compiled-into-the-kernel version of the driver. Use a module +instead. If you convince me that you need this, I'll make it for +you. Deal? + +I'm afraid that the module parameters are a bit clumsy. If you have a +better idea, please tell me. + +You can specify several parameters: + + sx_poll: number of jiffies between timer-based polls. + + Set this to "0" to disable timer based polls. + Initialization of cards without a working interrupt + will fail. + + Set this to "1" if you want a polling driver. + (on Intel: 100 polls per second). If you don't use + fast baud rates, you might consider a value like "5". + (If you don't know how to do the math, use 1). + + sx_slowpoll: Number of jiffies between timer-based polls. + Set this to "100" to poll once a second. + This should get the card out of a stall if the driver + ever misses an interrupt. I've never seen this happen, + and if it does, that's a bug. Tell me. + + sx_maxints: Number of interrupts to request from the card. + The card normally limits interrupts to about 100 per + second to offload the host CPU. You can increase this + number to reduce latency on the card a little. + Note that if you give a very high number you can overload + your CPU as well as the CPU on the host card. This setting + is inaccurate and not recommended for SI cards (But it + works). + + sx_irqmask: The mask of allowable IRQs to use. I suggest you set + this to 0 (disable IRQs all together) and use polling if + the assignment of IRQs becomes problematic. + + sx_debug: You can enable different sorts of debug traces with this. + At "-1" all debugging traces are active. You'll get several + times more debugging output than you'll get characters + transmitted. + + +Baud rates +========== + +Theoretically new SXDCs should be capable of more than 460k +baud. However the line drivers usually give up before that. Also the +CPU on the card may not be able to handle 8 channels going at full +blast at that speed. Moreover, the buffers are not large enough to +allow operation with 100 interrupts per second. You'll have to realize +that the card has a 256 byte buffer, so you'll have to increase the +number of interrupts per second if you have more than 256*100 bytes +per second to transmit. If you do any performance testing in this +area, I'd be glad to hear from you... + +(Psst Linux users..... I think the Linux driver is more efficient than +the driver for other OSes. If you can and want to benchmark them +against each other, be my guest, and report your findings...... :-) + + +Ports and devices +================= + +Port 0 is the top connector on the module closest to the host +card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8 +instead of from 0 to 7, as they are numbered by linux. I'm stubborn in +this: I know for sure that I wouldn't be able to calculate which port +is which anymore if I would change that.... + + +Devices: + +You should make the device files as follows: + +#!/bin/sh +# (I recommend that you cut-and-paste this into a file and run that) +cd /dev +t=0 +mknod specialix_sxctl c 10 167 +while [ $t -lt 64 ] + do + echo -n "$t " + mknod ttyX$t c 32 $t + mknod cux$t c 33 $t + t=`expr $t + 1` +done +echo "" +rm /etc/psdevtab +ps > /dev/null + + +This creates 64 devices. If you have more, increase the constant on +the line with "while". The devices start at 0, as is customary on +Linux. Specialix seems to like starting the numbering at 1. + +If your system doesn't come with these devices pre-installed, bug your +linux-vendor about this. They should have these devices +"pre-installed" before the new millennium. The "ps" stuff at the end +is to "tell" ps that the new devices exist. + +Officially the maximum number of cards per computer is 4. This driver +however supports as many cards in one machine as you want. You'll run +out of interrupts after a few, but you can switch to polled operation +then. At about 256 ports (More than 8 cards), we run out of minor +device numbers. Sorry. I suggest you buy a second computer.... (Or +switch to RIO). + +------------------------------------------------------------------------ + + + Fixed bugs and restrictions: + - Hangup processing. + -- Done. + + - the write path in generic_serial (lockup / oops). + -- Done (Ugly: not the way I want it. Copied from serial.c). + + - write buffer isn't flushed at close. + -- Done. I still seem to loose a few chars at close. + Sorry. I think that this is a firmware issue. (-> Specialix) + + - drain hardware before changing termios + - Change debug on the fly. + - ISA free irq -1. (no firmware loaded). + - adding c8000 as a probe address. Added warning. + - Add a RAMtest for the RAM on the card.c + - Crash when opening a port "way" of the number of allowed ports. + (for example opening port 60 when there are only 24 ports attached) + - Sometimes the use-count strays a bit. After a few hours of + testing the use count is sometimes "3". If you are not like + me and can remember what you did to get it that way, I'd + appreciate an Email. Possibly fixed. Tell me if anyone still + sees this. + - TAs don't work right if you don't connect all the modem control + signals. SXDCs do. T225 firmware problem -> Specialix. + (Mostly fixed now, I think. Tell me if you encounter this!) + + Bugs & restrictions: + + - Arbitrary baud rates. Requires firmware update. (-> Specialix) + + - Low latency (mostly firmware, -> Specialix) + + + diff -u --recursive --new-file v2.3.12/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- v2.3.12/linux/Documentation/sysrq.txt Wed Jun 24 14:30:07 1998 +++ linux/Documentation/sysrq.txt Mon Aug 9 10:23:09 1999 @@ -9,8 +9,8 @@ * How do I enable the magic SysRQ key? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when -configuring the kernel. This option is only available it 2.1.x or later +You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when +configuring the kernel. This option is only available in 2.1.x or later kernels. * How do I use the magic SysRQ key? diff -u --recursive --new-file v2.3.12/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.12/linux/MAINTAINERS Thu Jul 8 15:42:19 1999 +++ linux/MAINTAINERS Mon Aug 9 10:23:09 1999 @@ -706,11 +706,6 @@ W: http://www.torque.net/sg S: Maintained -SCSI GENERIC -L: linux-scsi@vger.rutgers.edu -M: douglas.gilbert@rbcds.com -S: Maintained - SCSI SUBSYSTEM L: linux-scsi@vger.rutgers.edu S: Unmaintained diff -u --recursive --new-file v2.3.12/linux/Makefile linux/Makefile --- v2.3.12/linux/Makefile Wed Jul 28 14:47:42 1999 +++ linux/Makefile Tue Aug 3 10:10:23 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 12 +SUBLEVEL = 13 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -110,7 +110,7 @@ FILESYSTEMS =fs/filesystems.a NETWORKS =net/network.a DRIVERS =drivers/block/block.a \ - drivers/char/char.a \ + drivers/char/char.o \ drivers/parport/parport.a LIBS =$(TOPDIR)/lib/lib.a SUBDIRS =kernel drivers mm fs net ipc lib diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.3.12/linux/arch/alpha/kernel/alpha_ksyms.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/alpha_ksyms.c Wed Aug 4 15:48:00 1999 @@ -105,7 +105,7 @@ EXPORT_SYMBOL(alpha_write_fp_reg); /* In-kernel system calls. */ -EXPORT_SYMBOL(__kernel_thread); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_dup); EXPORT_SYMBOL(sys_exit); diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.3.12/linux/arch/alpha/kernel/bios32.c Tue Dec 1 09:33:59 1998 +++ linux/arch/alpha/kernel/bios32.c Fri Aug 6 10:41:47 1999 @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -456,27 +456,23 @@ * HACK: the PCI-to-EISA bridge does not seem to identify * itself as a bridge... :-( */ - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82375) { + if (dev->vendor == PCI_VENDOR_ID_INTEL + && dev->device == PCI_DEVICE_ID_INTEL_82375) { dev->class = PCI_CLASS_BRIDGE_EISA; DBG_DEVS(("layout_dev: ignoring PCEB...\n")); return; } - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82378) { + if (dev->vendor == PCI_VENDOR_ID_INTEL + && dev->device == PCI_DEVICE_ID_INTEL_82378) { dev->class = PCI_CLASS_BRIDGE_ISA; DBG_DEVS(("layout_dev: ignoring SIO...\n")); return; } - /* - * We don't have code that will init the CYPRESS bridge correctly - * so we do the next best thing, and depend on the previous - * console code to do the right thing, and ignore it here... :-\ - */ - if (dev->vendor == PCI_VENDOR_ID_CONTAQ && - dev->device == PCI_DEVICE_ID_CONTAQ_82C693) { + if (dev->vendor == PCI_VENDOR_ID_CONTAQ + && dev->device == PCI_DEVICE_ID_CONTAQ_82C693 + && dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) { DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n")); return; } @@ -496,8 +492,10 @@ 0xffffffff); pcibios_read_config_dword(bus->number, dev->devfn, off, &base); if (!base) { - /* this base-address register is unused */ - dev->base_address[idx] = 0; + /* This base-address register is unused. */ + dev->resource[idx].start = 0; + dev->resource[idx].end = 0; + dev->resource[idx].flags = 0; continue; } @@ -518,6 +516,17 @@ base &= PCI_BASE_ADDRESS_IO_MASK; mask = (~base << 1) | 0x1; size = (mask & base) & 0xffffffff; + + /* We don't want to disturb normal IDE functions, so + we don't touch the first two I/O ports on the + Cypress. */ + if (dev->vendor == PCI_VENDOR_ID_CONTAQ + && dev->device == PCI_DEVICE_ID_CONTAQ_82C693 + && dev->class >> 8 == PCI_CLASS_BRIDGE_ISA + && idx < 2) { + continue; + } + /* * Aligning to 0x800 rather than the minimum base of * 0x400 is an attempt to avoid having devices in @@ -535,7 +544,12 @@ new_io_reset(dev, off, orig_base); handle = PCI_HANDLE(bus->number) | base | 1; - dev->base_address[idx] = handle; + dev->resource[idx].start + = handle & PCI_BASE_ADDRESS_IO_MASK; + dev->resource[idx].end + = dev->resource[idx].start + size - 1; + dev->resource[idx].flags + = handle & ~PCI_BASE_ADDRESS_IO_MASK; DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n", dev->device, handle, size)); @@ -615,7 +629,12 @@ new_io_reset(dev, off, orig_base); handle = PCI_HANDLE(bus->number) | base; - dev->base_address[idx] = handle; + dev->resource[idx].start + = handle & PCI_BASE_ADDRESS_MEM_MASK; + dev->resource[idx].end + = dev->resource[idx].start + size - 1; + dev->resource[idx].flags + = handle & ~PCI_BASE_ADDRESS_MEM_MASK; /* * Currently for 64-bit cards, we simply do the usual @@ -637,7 +656,9 @@ new_io_reset (dev, off+4, orig_base2); } /* Bypass hi reg in the loop. */ - dev->base_address[++idx] = 0; + dev->resource[++idx].start = 0; + dev->resource[idx].end = 0; + dev->resource[idx].flags = 0; printk("bios32 WARNING: " "handling 64-bit device in " @@ -655,8 +676,7 @@ if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED || dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA || dev->class >> 8 == PCI_CLASS_STORAGE_IDE || - dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) - { + dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) { /* * All of these (may) have I/O scattered all around * and may not use i/o-base address registers at all. diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.3.12/linux/arch/alpha/kernel/entry.S Mon May 10 09:55:21 1999 +++ linux/arch/alpha/kernel/entry.S Wed Aug 4 15:48:00 1999 @@ -38,6 +38,8 @@ */ #define PF_PTRACED 0x00000010 +#define CLONE_VM 0x00000100 + /* * This defines the normal kernel pt-regs layout. * @@ -225,21 +227,23 @@ .end kernel_clone /* - * __kernel_thread(clone_flags, fn, arg) + * kernel_thread(fn, arg, clone_flags) */ .align 3 -.globl __kernel_thread -.ent __kernel_thread -__kernel_thread: +.globl kernel_thread +.ent kernel_thread +kernel_thread: ldgp $29,0($27) /* we can be called from a module */ .frame $30, 4*8, $26 subq $30,4*8,$30 stq $10,16($30) stq $9,8($30) + lda $0,CLONE_VM stq $26,0($30) .prologue 1 - mov $17,$9 /* save fn */ - mov $18,$10 /* save arg */ + mov $16,$9 /* save fn */ + mov $17,$10 /* save arg */ + or $18,$0,$16 /* shuffle flags to front; add CLONE_VM. */ bsr $26,kernel_clone bne $20,1f /* $20 is non-zero in child */ ldq $26,0($30) @@ -257,7 +261,7 @@ mov $0,$16 mov $31,$26 jsr $31,sys_exit -.end __kernel_thread +.end kernel_thread /* * __kernel_execve(path, argv, envp, regs) @@ -1092,7 +1096,7 @@ .quad sys_munlockall .quad sys_sysinfo .quad sys_sysctl - .quad sys_idle /* 320 */ + .quad sys_ni_syscall /* 320 */ .quad sys_oldumount .quad sys_swapon .quad sys_times diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h --- v2.3.12/linux/arch/alpha/kernel/machvec.h Tue Jun 22 10:46:52 1999 +++ linux/arch/alpha/kernel/machvec.h Thu Jul 29 13:37:22 1999 @@ -8,14 +8,10 @@ #include -/* Whee. TSUNAMI doesn't have an HAE. Fix things up for the GENERIC - kernel by defining the HAE address to be that of the cache. Now - we can read and write it as we like. ;-) */ +/* Whee. Both TSUNAMI and POLARIS don't have an HAE. Fix things up for + the GENERIC kernel by defining the HAE address to be that of the cache. + Now we can read and write it as we like. ;-) */ #define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache) - -/* Whee. POLARIS doesn't have an HAE. Fix things up for the GENERIC - kernel by defining the HAE address to be that of the cache. Now - we can read and write it as we like. ;-) */ #define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache) /* Only a few systems don't define IACK_SC, handling all interrupts through @@ -36,21 +32,24 @@ #define DO_EV4_MMU \ max_asn: EV4_MAX_ASN, \ - mv_get_mmu_context: ev4_get_mmu_context, \ + mv_switch_mm: ev4_switch_mm, \ + mv_activate_mm: ev4_activate_mm, \ mv_flush_tlb_current: ev4_flush_tlb_current, \ mv_flush_tlb_other: ev4_flush_tlb_other, \ mv_flush_tlb_current_page: ev4_flush_tlb_current_page #define DO_EV5_MMU \ max_asn: EV5_MAX_ASN, \ - mv_get_mmu_context: ev5_get_mmu_context, \ + mv_switch_mm: ev5_switch_mm, \ + mv_activate_mm: ev5_activate_mm, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ mv_flush_tlb_current_page: ev5_flush_tlb_current_page #define DO_EV6_MMU \ max_asn: EV6_MAX_ASN, \ - mv_get_mmu_context: ev5_get_mmu_context, \ + mv_switch_mm: ev5_switch_mm, \ + mv_activate_mm: ev5_activate_mm, \ mv_flush_tlb_current: ev5_flush_tlb_current, \ mv_flush_tlb_other: ev5_flush_tlb_other, \ mv_flush_tlb_current_page: ev5_flush_tlb_current_page diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.12/linux/arch/alpha/kernel/osf_sys.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/osf_sys.c Thu Jul 29 13:37:22 1999 @@ -895,11 +895,12 @@ w = ieee_fpcr_to_swcr(fpcr); if (!(fpcr & FPCR_UNDZ)) { w &= ~IEEE_TRAP_ENABLE_UNF; - w |= current->tss.flags & IEEE_TRAP_ENABLE_UNF; + w |= (current->thread.flags + & IEEE_TRAP_ENABLE_UNF); } } else { /* Otherwise we are forced to do everything in sw. */ - w = current->tss.flags & IEEE_SW_MASK; + w = current->thread.flags & IEEE_SW_MASK; } if (put_user(w, (unsigned long *) buffer)) @@ -917,7 +918,7 @@ case GSI_UACPROC: if (nbytes < sizeof(unsigned int)) return -EINVAL; - w = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK; + w = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (put_user(w, (unsigned int *)buffer)) return -EFAULT; return 1; @@ -964,8 +965,8 @@ /* Update softare trap enable bits. */ if (get_user(swcr, (unsigned long *)buffer)) return -EFAULT; - current->tss.flags &= ~IEEE_SW_MASK; - current->tss.flags |= swcr & IEEE_SW_MASK; + current->thread.flags &= ~IEEE_SW_MASK; + current->thread.flags |= swcr & IEEE_SW_MASK; /* Update the real fpcr. Keep UNFD off if not UNDZ. */ fpcr = rdfpcr(); @@ -997,9 +998,9 @@ return -EFAULT; switch (v) { case SSIN_UACPROC: - current->tss.flags &= + current->thread.flags &= ~(UAC_BITMASK << UAC_SHIFT); - current->tss.flags |= + current->thread.flags |= (w & UAC_BITMASK) << UAC_SHIFT; break; diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.3.12/linux/arch/alpha/kernel/process.c Wed Jul 28 14:47:42 1999 +++ linux/arch/alpha/kernel/process.c Tue Aug 3 08:20:45 1999 @@ -74,9 +74,8 @@ return 0; } -#ifdef __SMP__ -int -cpu_idle(void *unused) +void +cpu_idle(void) { /* An endless idle loop with no priority at all. */ current->priority = 0; @@ -94,27 +93,6 @@ } } } -#endif - -asmlinkage int -sys_idle(void) -{ - if (current->pid != 0) - return -EPERM; - - /* An endless idle loop with no priority at all. */ - current->priority = 0; - current->counter = -100; - init_idle(); - - while (1) { - /* FIXME -- EV6 and LCA45 know how to power down - the CPU. */ - - schedule(); - check_pgt_cache(); - } -} void generic_kill_arch (int mode, char *restart_cmd) @@ -254,7 +232,7 @@ that EV6 defines UNFD valid only with UNDZ, which we don't want for IEEE conformance -- so that disabled bit remains in software. */ - current->tss.flags &= ~IEEE_SW_MASK; + current->thread.flags &= ~IEEE_SW_MASK; wrfpcr(FPCR_DYN_NORMAL | FPCR_INVD | FPCR_DZED | FPCR_OVFD | FPCR_INED); } @@ -324,10 +302,10 @@ #else childstack->r26 = (unsigned long) ret_from_sys_call; #endif - p->tss.usp = usp; - p->tss.ksp = (unsigned long) childstack; - p->tss.pal_flags = 1; /* set FEN, clear everything else */ - p->tss.flags = current->tss.flags; + p->thread.usp = usp; + p->thread.ksp = (unsigned long) childstack; + p->thread.pal_flags = 1; /* set FEN, clear everything else */ + p->thread.flags = current->thread.flags; return 0; } diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h --- v2.3.12/linux/arch/alpha/kernel/proto.h Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/proto.h Tue Aug 3 08:20:45 1999 @@ -162,6 +162,7 @@ extern void rtc_init_pit(void); extern void generic_init_pit(void); extern unsigned long est_cycle_freq; +extern struct resource timer_resource; /* smc37c93x.c */ extern void SMC93x_Init(void); @@ -193,7 +194,7 @@ /* process.c */ extern void generic_kill_arch (int mode, char *reboot_cmd); -extern int cpu_idle(void *) __attribute__((noreturn)); +extern void cpu_idle(void) __attribute__((noreturn)); /* ptrace.c */ extern int ptrace_set_bpt (struct task_struct *child); diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.3.12/linux/arch/alpha/kernel/ptrace.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/ptrace.c Thu Jul 29 13:37:22 1999 @@ -106,7 +106,7 @@ long *addr; if (regno == 30) { - addr = &task->tss.usp; + addr = &task->thread.usp; } else if (regno == 31 || regno > 64) { zero = 0; addr = &zero; @@ -175,31 +175,31 @@ * branch (emulation can be tricky for fp branches). */ displ = ((s32)(insn << 11)) >> 9; - child->tss.bpt_addr[nsaved++] = pc + 4; + child->thread.bpt_addr[nsaved++] = pc + 4; if (displ) /* guard against unoptimized code */ - child->tss.bpt_addr[nsaved++] = pc + 4 + displ; + child->thread.bpt_addr[nsaved++] = pc + 4 + displ; DBG(DBG_BPT, ("execing branch\n")); } else if (op_code == 0x1a) { reg_b = (insn >> 16) & 0x1f; - child->tss.bpt_addr[nsaved++] = get_reg(child, reg_b); + child->thread.bpt_addr[nsaved++] = get_reg(child, reg_b); DBG(DBG_BPT, ("execing jump\n")); } else { - child->tss.bpt_addr[nsaved++] = pc + 4; + child->thread.bpt_addr[nsaved++] = pc + 4; DBG(DBG_BPT, ("execing normal insn\n")); } /* install breakpoints: */ for (i = 0; i < nsaved; ++i) { - res = read_int(child, child->tss.bpt_addr[i], &insn); + res = read_int(child, child->thread.bpt_addr[i], &insn); if (res < 0) return res; - child->tss.bpt_insn[i] = insn; - DBG(DBG_BPT, (" -> next_pc=%lx\n", child->tss.bpt_addr[i])); - res = write_int(child, child->tss.bpt_addr[i], BREAKINST); + child->thread.bpt_insn[i] = insn; + DBG(DBG_BPT, (" -> next_pc=%lx\n", child->thread.bpt_addr[i])); + res = write_int(child, child->thread.bpt_addr[i], BREAKINST); if (res < 0) return res; } - child->tss.bpt_nsaved = nsaved; + child->thread.bpt_nsaved = nsaved; return 0; } @@ -210,9 +210,9 @@ int ptrace_cancel_bpt(struct task_struct * child) { - int i, nsaved = child->tss.bpt_nsaved; + int i, nsaved = child->thread.bpt_nsaved; - child->tss.bpt_nsaved = 0; + child->thread.bpt_nsaved = 0; if (nsaved > 2) { printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); @@ -220,8 +220,8 @@ } for (i = 0; i < nsaved; ++i) { - write_int(child, child->tss.bpt_addr[i], - child->tss.bpt_insn[i]); + write_int(child, child->thread.bpt_addr[i], + child->thread.bpt_insn[i]); } return (nsaved != 0); } @@ -365,7 +365,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->tss.bpt_nsaved = -1; /* mark single-stepping */ + child->thread.bpt_nsaved = -1; /* mark single-stepping */ child->flags &= ~PF_TRACESYS; wake_up_process(child); child->exit_code = data; diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.3.12/linux/arch/alpha/kernel/smp.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/smp.c Fri Aug 6 10:41:47 1999 @@ -75,18 +75,23 @@ extern asmlinkage void entInt(void); -/* - * Process bootcommand SMP options, like "nosmp" and "maxcpus=". - */ -void __init -smp_setup(char *str, int *ints) +static int __init nosmp(char *str) +{ + max_cpus = 0; + return 1; +} + +__setup("nosmp", nosmp); + +static int __init maxcpus(char *str) { - if (ints && ints[0] > 0) - max_cpus = ints[1]; - else - max_cpus = 0; + get_option(&str, &max_cpus); + return 1; } +__setup("maxcpus", maxcpus); + + /* * Called by both boot and secondaries to move global data into * per-processor storage. @@ -133,6 +138,10 @@ /* Setup the scheduler for this processor. */ init_idle(); + /* ??? This should be in init_idle. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + /* Get our local ticker going. */ smp_setup_percpu_timer(cpuid); @@ -153,7 +162,7 @@ cpuid, current)); /* Do nothing. */ - cpu_idle(NULL); + cpu_idle(); } @@ -335,21 +344,21 @@ /* Initialize the CPU's HWPCB to something just good enough for us to get started. Immediately after starting, we'll swpctx - to the target idle task's tss. Reuse the stack in the mean + to the target idle task's ptb. Reuse the stack in the mean time. Precalculate the target PCBB. */ hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16; hwpcb->usp = 0; - hwpcb->ptbr = idle->tss.ptbr; + hwpcb->ptbr = idle->thread.ptbr; hwpcb->pcc = 0; hwpcb->asn = 0; - hwpcb->unique = virt_to_phys(&idle->tss); - hwpcb->flags = idle->tss.pal_flags; + hwpcb->unique = virt_to_phys(&idle->thread); + hwpcb->flags = idle->thread.pal_flags; hwpcb->res1 = hwpcb->res2 = 0; DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n", hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique)); DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", - cpuid, idle->state, idle->tss.pal_flags)); + cpuid, idle->state, idle->thread.pal_flags)); /* Setup HWRPB fields that SRM uses to activate secondary CPU */ hwrpb->CPU_restart = __smp_callin; @@ -399,10 +408,13 @@ HWRPB.CPU_restart says to start. But this gets all the other task-y sort of data structures set up like we wish. */ kernel_thread((void *)__smp_callin, NULL, CLONE_PID|CLONE_VM); - idle = task[cpunum]; - if (!idle) - panic("No idle process for CPU %d", cpuid); - idle->processor = cpuid; + + idle = init_task.prev_task; + if (!idle) + panic("No idle process for CPU %d", cpunum); + del_from_runqueue(idle); + init_tasks[cpunum] = idle; + idle->processor = cpuid; /* Schedule the first task manually. */ /* ??? Ingo, what is this? */ @@ -512,6 +524,10 @@ init_idle(); + /* ??? This should be in init_idle. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + /* Nothing to do on a UP box, or when told not to. */ if (smp_num_probed == 1 || max_cpus == 0) { printk(KERN_INFO "SMP mode deactivated.\n"); @@ -859,16 +875,16 @@ ipi_flush_tlb_mm(void *x) { struct mm_struct *mm = (struct mm_struct *) x; - if (mm == current->mm) + if (mm == current->active_mm) flush_tlb_current(mm); } void flush_tlb_mm(struct mm_struct *mm) { - if (mm == current->mm) { + if (mm == current->active_mm) { flush_tlb_current(mm); - if (atomic_read(&mm->count) == 1) + if (atomic_read(&mm->mm_users) <= 1) return; } else flush_tlb_other(mm); @@ -888,7 +904,7 @@ ipi_flush_tlb_page(void *x) { struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x; - if (data->mm == current->mm) + if (data->mm == current->active_mm) flush_tlb_current_page(data->mm, data->vma, data->addr); } @@ -898,9 +914,9 @@ struct flush_tlb_page_struct data; struct mm_struct *mm = vma->vm_mm; - if (mm == current->mm) { + if (mm == current->active_mm) { flush_tlb_current_page(mm, vma, addr); - if (atomic_read(&mm->count) == 1) + if (atomic_read(&mm->mm_users) <= 1) return; } else flush_tlb_other(mm); diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c --- v2.3.12/linux/arch/alpha/kernel/sys_ruffian.c Sat Jan 9 19:08:27 1999 +++ linux/arch/alpha/kernel/sys_ruffian.c Tue Aug 3 08:20:45 1999 @@ -220,19 +220,25 @@ { /* FIXME: What do we do with ruffian_get_bank_size above? */ +#if 1 + pyxis_init_arch(mem_start, mem_end); +#else pyxis_enable_errors(); if (!pyxis_srm_window_setup()) { printk("ruffian_init_arch: Skipping window register rewrites." "\n... Trust DeskStation firmware!\n"); } pyxis_finish_init_arch(); +#endif } static void ruffian_init_pit (void) { /* Ruffian depends on the system timer established in MILO! */ - request_region(0x70, 0x10, "timer"); + timer_resource.start = 0x70; + timer_resource.end = 0x70 + 0x10; + request_resource(&ioport_resource, &timer_resource); outb(0xb6, 0x43); /* pit counter 2: speaker */ outb(0x31, 0x42); diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.3.12/linux/arch/alpha/kernel/time.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/kernel/time.c Thu Jul 29 13:37:22 1999 @@ -47,6 +47,12 @@ static int set_rtc_mmss(unsigned long); +#ifdef CONFIG_RTC +struct resource timer_resource = { "pit", 0x40, 0x40+0x20 }; +#else +struct resource timer_resource = { "rtc", 0, 0 }; +#endif + /* * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting @@ -184,7 +190,7 @@ CMOS_WRITE(control, RTC_CONTROL); (void) CMOS_READ(RTC_INTR_FLAGS); - request_region(0x40, 0x20, "timer"); /* reserve pit */ + request_resource(&ioport_resource, &timer_resource); /* Setup interval timer. */ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ @@ -219,7 +225,9 @@ } (void) CMOS_READ(RTC_INTR_FLAGS); - request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */ + timer_resource.start = RTC_PORT(0); + timer_resource.end = RTC_PORT(0) + 0x10; + request_resource(&ioport_resource, &timer_resource); outb(0x36, 0x43); /* pit counter 0: system timer */ outb(0x00, 0x40); @@ -323,7 +331,7 @@ /* setup timer */ irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL)) + if (request_irq(TIMER_IRQ, irq_handler, 0, timer_resource.name, NULL)) panic("Could not allocate timer IRQ!"); } diff -u --recursive --new-file v2.3.12/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c --- v2.3.12/linux/arch/alpha/kernel/traps.c Fri May 14 12:41:23 1999 +++ linux/arch/alpha/kernel/traps.c Thu Jul 29 13:37:22 1999 @@ -103,12 +103,12 @@ dik_show_code((unsigned int *)regs->pc); dik_show_trace((unsigned long *)(regs+1)); - if (current->tss.flags & (1UL << 63)) { + if (current->thread.flags & (1UL << 63)) { printk("die_if_kernel recursion detected.\n"); sti(); while (1); } - current->tss.flags |= (1UL << 63); + current->thread.flags |= (1UL << 63); do_exit(SIGSEGV); } @@ -154,7 +154,9 @@ unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - die_if_kernel("Instruction fault", ®s, type, 0); + die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"), + ®s, type, 0); + switch (type) { case 0: /* breakpoint */ if (ptrace_cancel_bpt(current)) { @@ -494,12 +496,12 @@ dik_show_code((unsigned int *)pc); dik_show_trace((unsigned long *)(®s+1)); - if (current->tss.flags & (1UL << 63)) { + if (current->thread.flags & (1UL << 63)) { printk("die_if_kernel recursion detected.\n"); sti(); while (1); } - current->tss.flags |= (1UL << 63); + current->thread.flags |= (1UL << 63); do_exit(SIGSEGV); } @@ -601,7 +603,7 @@ /* Check the UAC bits to decide what the user wants us to do with the unaliged access. */ - uac_bits = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK; + uac_bits = (current->thread.flags >> UAC_SHIFT) & UAC_BITMASK; if (!(uac_bits & UAC_NOPRINT)) { if (cnt >= 5 && jiffies - last_time > 5*HZ) { cnt = 0; diff -u --recursive --new-file v2.3.12/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v2.3.12/linux/arch/alpha/lib/Makefile Sat Jan 16 17:02:51 1999 +++ linux/arch/alpha/lib/Makefile Fri Aug 6 10:41:47 1999 @@ -5,7 +5,7 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \ checksum.o csum_partial_copy.o strlen.o \ strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \ - strchr.o strrchr.o \ + strchr.o strrchr.o memchr.o \ copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \ csum_ipv6_magic.o strcasecmp.o semaphore.o \ srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o diff -u --recursive --new-file v2.3.12/linux/arch/alpha/lib/memchr.S linux/arch/alpha/lib/memchr.S --- v2.3.12/linux/arch/alpha/lib/memchr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/memchr.S Fri Aug 6 10:41:47 1999 @@ -0,0 +1,164 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@cs.arizona.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Finds characters in a memory area. Optimized for the Alpha: + + - memory accessed as aligned quadwords only + - uses cmpbge to compare 8 bytes in parallel + - does binary search to find 0 byte in last + quadword (HAKMEM needed 12 instructions to + do this instead of the 9 instructions that + binary search needs). + +For correctness consider that: + + - only minimum number of quadwords may be accessed + - the third argument is an unsigned long +*/ + + .set noreorder + .set noat + + .globl memchr + .ent memchr +memchr: + .frame $30,0,$26,0 + .prologue 0 + + # Hack -- if someone passes in (size_t)-1, hoping to just + # search til the end of the address space, we will overflow + # below when we find the address of the last byte. Given + # that we will never have a 56-bit address space, cropping + # the length is the easiest way to avoid trouble. + zap $18, 0x80, $5 #-e0 : + + beq $18, $not_found # .. e1 : + ldq_u $1, 0($16) # e1 : load first quadword + insbl $17, 1, $2 # .. e0 : $2 = 000000000000ch00 + and $17, 0xff, $17 #-e0 : $17 = 00000000000000ch + cmpult $18, 9, $4 # .. e1 : + or $2, $17, $17 # e0 : $17 = 000000000000chch + lda $3, -1($31) # .. e1 : + sll $17, 16, $2 #-e0 : $2 = 00000000chch0000 + addq $16, $5, $5 # .. e1 : + or $2, $17, $17 # e1 : $17 = 00000000chchchch + unop # : + sll $17, 32, $2 #-e0 : $2 = chchchch00000000 + or $2, $17, $17 # e1 : $17 = chchchchchchchch + extql $1, $16, $7 # e0 : + beq $4, $first_quad # .. e1 : + + ldq_u $6, -1($5) #-e1 : eight or less bytes to search + extqh $6, $16, $6 # .. e0 : + mov $16, $0 # e0 : + or $7, $6, $1 # .. e1 : $1 = quadword starting at $16 + + # Deal with the case where at most 8 bytes remain to be searched + # in $1. E.g.: + # $18 = 6 + # $1 = ????c6c5c4c3c2c1 +$last_quad: + negq $18, $6 #-e0 : + xor $17, $1, $1 # .. e1 : + srl $3, $6, $6 # e0 : $6 = mask of $18 bits set + cmpbge $31, $1, $2 # .. e1 : + and $2, $6, $2 #-e0 : + beq $2, $not_found # .. e1 : + +$found_it: + # Now, determine which byte matched: + negq $2, $3 # e0 : + and $2, $3, $2 # e1 : + + and $2, 0x0f, $1 #-e0 : + addq $0, 4, $3 # .. e1 : + cmoveq $1, $3, $0 # e0 : + + addq $0, 2, $3 # .. e1 : + and $2, 0x33, $1 #-e0 : + cmoveq $1, $3, $0 # .. e1 : + + and $2, 0x55, $1 # e0 : + addq $0, 1, $3 # .. e1 : + cmoveq $1, $3, $0 #-e0 : + +$done: ret # .. e1 : + + # Deal with the case where $18 > 8 bytes remain to be + # searched. $16 may not be aligned. + .align 4 +$first_quad: + andnot $16, 0x7, $0 #-e1 : + insqh $3, $16, $2 # .. e0 : $2 = 0000ffffffffffff ($16<0:2> ff) + xor $1, $17, $1 # e0 : + or $1, $2, $1 # e1 : $1 = ====ffffffffffff + cmpbge $31, $1, $2 #-e0 : + bne $2, $found_it # .. e1 : + + # At least one byte left to process. + + ldq $1, 8($0) # e0 : + subq $5, 1, $18 # .. e1 : + addq $0, 8, $0 #-e0 : + + # Make $18 point to last quad to be accessed (the + # last quad may or may not be partial). + + andnot $18, 0x7, $18 # .. e1 : + cmpult $0, $18, $2 # e0 : + beq $2, $final # .. e1 : + + # At least two quads remain to be accessed. + + subq $18, $0, $4 #-e0 : $4 <- nr quads to be processed + and $4, 8, $4 # e1 : odd number of quads? + bne $4, $odd_quad_count # e1 : + + # At least three quads remain to be accessed + + mov $1, $4 # e0 : move prefetched value to correct reg + + .align 4 +$unrolled_loop: + ldq $1, 8($0) #-e0 : prefetch $1 + xor $17, $4, $2 # .. e1 : + cmpbge $31, $2, $2 # e0 : + bne $2, $found_it # .. e1 : + + addq $0, 8, $0 #-e0 : +$odd_quad_count: + xor $17, $1, $2 # .. e1 : + ldq $4, 8($0) # e0 : prefetch $4 + cmpbge $31, $2, $2 # .. e1 : + addq $0, 8, $6 #-e0 : + bne $2, $found_it # .. e1 : + + cmpult $6, $18, $6 # e0 : + addq $0, 8, $0 # .. e1 : + bne $6, $unrolled_loop #-e1 : + + mov $4, $1 # e0 : move prefetched value into $1 +$final: subq $5, $0, $18 # .. e1 : $18 <- number of bytes left to do + bne $18, $last_quad # e1 : + +$not_found: + mov $31, $0 #-e0 : + ret # .. e1 : + + .end memchr diff -u --recursive --new-file v2.3.12/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c --- v2.3.12/linux/arch/alpha/math-emu/fp-emul.c Mon May 10 09:55:21 1999 +++ linux/arch/alpha/math-emu/fp-emul.c Thu Jul 29 13:37:22 1999 @@ -107,7 +107,7 @@ alpha_fp_emul (unsigned long pc) { unsigned long op_fun, fa, fb, fc, func, mode; - unsigned long fpcw = current->tss.flags; + unsigned long fpcw = current->thread.flags; unsigned long va, vb, vc, res, fpcr; __u32 insn; @@ -255,7 +255,7 @@ */ if (res) { /* Record exceptions in software control word. */ - current->tss.flags = fpcw |= res >> 35; + current->thread.flags = fpcw |= res >> 35; /* Update hardware control register */ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); diff -u --recursive --new-file v2.3.12/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v2.3.12/linux/arch/alpha/mm/fault.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/mm/fault.c Fri Aug 6 10:41:47 1999 @@ -37,12 +37,9 @@ unsigned long last_asn = ASN_FIRST_VERSION; #endif -void -get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) +void ev5_flush_tlb_current(struct mm_struct *mm) { - unsigned long new = __get_new_mmu_context(p, mm); - mm->context = new; - p->tss.asn = new & HARDWARE_ASN_MASK; + ev5_activate_mm(NULL, mm, smp_processor_id()); } @@ -78,7 +75,8 @@ { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - unsigned fixup; + unsigned int fixup; + int fault; /* As of EV6, a load into $31/$f31 is a prefetch, and never faults (or is suppressed by the PALcode). Support that for older CPUs @@ -94,8 +92,12 @@ } } + /* If we're in an interrupt context, or have no user context, + we must not take the fault. */ + if (!mm || in_interrupt()) + goto no_context; + down(&mm->mmap_sem); - lock_kernel(); vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -121,9 +123,21 @@ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } - handle_mm_fault(current, vma, address, cause > 0); + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + fault = handle_mm_fault(current, vma, address, cause > 0); up(&mm->mmap_sem); - goto out; + + if (fault < 0) + goto out_of_memory; + if (fault == 0) + goto do_sigbus; + + return; /* * Something tried to access memory that isn't in our memory map.. @@ -134,9 +148,10 @@ if (user_mode(regs)) { force_sig(SIGSEGV, current); - goto out; + return; } +no_context: /* Are we prepared to handle this fault as an exception? */ if ((fixup = search_exception_table(regs->pc)) != 0) { unsigned long newpc; @@ -144,7 +159,7 @@ printk("%s: Exception at [<%lx>] (%lx)\n", current->comm, regs->pc, newpc); regs->pc = newpc; - goto out; + return; } /* @@ -155,7 +170,25 @@ "virtual address %016lx\n", address); die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16); do_exit(SIGKILL); - out: - unlock_kernel(); -} +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + printk(KERN_ALERT "VM: killing process %s(%d)\n", + current->comm, current->pid); + if (!user_mode(regs)) + goto no_context; + do_exit(SIGKILL); + +do_sigbus: + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + force_sig(SIGBUS, current); + if (!user_mode(regs)) + goto no_context; + return; +} diff -u --recursive --new-file v2.3.12/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.3.12/linux/arch/alpha/mm/init.c Wed Jul 21 15:46:48 1999 +++ linux/arch/alpha/mm/init.c Thu Jul 29 13:37:22 1999 @@ -178,7 +178,7 @@ { register unsigned long sp __asm__("$30"); pcb->ksp = sp; - return __reload_tss(pcb); + return __reload_thread(pcb); } /* @@ -233,10 +233,10 @@ } /* Also set up the real kernel PCB while we're at it. */ - init_task.tss.ptbr = newptbr; - init_task.tss.pal_flags = 1; /* set FEN, clear everything else */ - init_task.tss.flags = 0; - original_pcb_ptr = load_PCB(&init_task.tss); + init_task.thread.ptbr = newptbr; + init_task.thread.pal_flags = 1; /* set FEN, clear everything else */ + init_task.thread.flags = 0; + original_pcb_ptr = load_PCB(&init_task.thread); tbia(); /* Save off the contents of the original PCB so that we can diff -u --recursive --new-file v2.3.12/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds --- v2.3.12/linux/arch/alpha/vmlinux.lds Tue May 13 22:41:00 1997 +++ linux/arch/alpha/vmlinux.lds Wed Aug 4 15:48:00 1999 @@ -2,11 +2,11 @@ ENTRY(__start) SECTIONS { - . = 0xfffffc0000310000; - _text = .; - .text : { *(.text) } - .text2 : { *(.text2) } - _etext = .; + . = 0xfffffc0000310000; + _text = .; + .text : { *(.text) } + .text2 : { *(.text2) } + _etext = .; /* Exception table */ . = ALIGN(16); @@ -26,6 +26,17 @@ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } + + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + + . = ALIGN(8); + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(2*8192); /* Align double page for init_task_union */ __init_end = .; @@ -34,6 +45,7 @@ /* Global data */ _data = .; + .data.cacheline_aligned : { *(.data.cacheline_aligned) } .rodata : { *(.rodata) } .data : { *(.data) CONSTRUCTORS } .got : { *(.got) } diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S --- v2.3.12/linux/arch/arm/kernel/entry-armo.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/entry-armo.S Mon Aug 2 10:19:52 1999 @@ -650,6 +650,15 @@ b SYMBOL_NAME(do_DataAbort) /* + * Register switch for older 26-bit only ARMs + */ +ENTRY(__switch_to) + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously + +/* *============================================================================= * Low-level interface code *----------------------------------------------------------------------------- diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.3.12/linux/arch/arm/kernel/entry-armv.S Wed Jul 21 15:46:48 1999 +++ linux/arch/arm/kernel/entry-armv.S Mon Aug 2 10:19:52 1999 @@ -455,7 +455,7 @@ mov r0, r2 ldr r2, .LCprocfns mov lr, pc - ldr pc, [r2, #8] @ call processor specific code + ldr pc, [r2, #4] @ call processor specific code mov r3, sp bl SYMBOL_NAME(do_DataAbort) ldr r0, [sp, #S_PSR] @@ -542,7 +542,7 @@ msr cpsr, r2 ldr r2, .LCprocfns mov lr, pc - ldr pc, [r2, #8] @ call processor specific code + ldr pc, [r2, #4] @ call processor specific code mov r3, sp adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_DataAbort) @@ -654,6 +654,23 @@ add sp, sp, #S_FRAME_SIZE movs pc, lr #endif + +/* + * Register switch for ARMv3 and ARMv4 processors + * r0 = previous, r1 = next, return previous. + * previous and next are guaranteed not to be the same. + */ +ENTRY(__switch_to) + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + mrs ip, cpsr + stmfd sp!, {ip} @ Save cpsr_SVC + ldr r2, [r1, #TSS_DOMAIN] + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + mcr p15, 0, r2, c3, c0 @ Set domain register + ldmfd sp!, {ip} + msr spsr, ip @ Save tasks CPSR into SPSR for this return + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously .section ".text.init",#alloc,#execinstr /* diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c --- v2.3.12/linux/arch/arm/kernel/fiq.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/fiq.c Mon Aug 2 10:19:52 1999 @@ -53,15 +53,12 @@ #ifdef CONFIG_CPU_32 static inline void unprotect_page_0(void) { - __asm__ __volatile__("mcr p15, 0, %0, c3, c0" : - : "r" (DOMAIN_USER_MANAGER | - DOMAIN_KERNEL_CLIENT | - DOMAIN_IO_CLIENT)); + modify_domain(DOMAIN_USER, DOMAIN_MANAGER); } static inline void protect_page_0(void) { - set_fs(get_fs()); + modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } #else diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.3.12/linux/arch/arm/kernel/process.c Wed Jul 21 15:46:48 1999 +++ linux/arch/arm/kernel/process.c Mon Aug 2 10:19:52 1999 @@ -207,9 +207,7 @@ void flush_thread(void) { - int i; - - memset(¤t->tss.debug, 0, sizeof(current->tss.debug)); + memset(¤t->thread.debug, 0, sizeof(current->thread.debug)); current->used_math = 0; current->flags &= ~PF_USEDFPU; } @@ -231,7 +229,7 @@ save = ((struct context_save_struct *)(childregs)) - 1; init_thread_css(save); - p->tss.save = save; + p->thread.save = save; return 0; } @@ -244,7 +242,7 @@ int fpvalid = 0; if (current->used_math) - memcpy (fp, ¤t->tss.fpstate.soft, sizeof (fp)); + memcpy (fp, ¤t->thread.fpstate.soft, sizeof (fp)); return fpvalid; } @@ -262,11 +260,11 @@ dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; dump->u_ssize = 0; - dump->u_debugreg[0] = current->tss.debug.bp[0].address; - dump->u_debugreg[1] = current->tss.debug.bp[1].address; - dump->u_debugreg[2] = current->tss.debug.bp[0].insn; - dump->u_debugreg[3] = current->tss.debug.bp[1].insn; - dump->u_debugreg[4] = current->tss.debug.nsaved; + dump->u_debugreg[0] = current->thread.debug.bp[0].address; + dump->u_debugreg[1] = current->thread.debug.bp[1].address; + dump->u_debugreg[2] = current->thread.debug.bp[0].insn; + dump->u_debugreg[3] = current->thread.debug.bp[1].insn; + dump->u_debugreg[4] = current->thread.debug.nsaved; if (dump->start_stack < 0x04000000) dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- v2.3.12/linux/arch/arm/kernel/ptrace.c Wed Jul 21 15:46:48 1999 +++ linux/arch/arm/kernel/ptrace.c Mon Aug 2 10:19:52 1999 @@ -28,7 +28,7 @@ /* * this routine will get a word off of the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. + * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our * data space. */ @@ -43,7 +43,7 @@ /* * this routine will put a word on the processes privileged stack. - * the offset is how far from the base addr as stored in the TSS. + * the offset is how far from the base addr as stored in the THREAD. * this routine assumes that all the privileged stacks are in our * data space. */ @@ -334,7 +334,7 @@ int ptrace_set_bpt (struct task_struct *child) { - struct debug_info *dbg = &child->tss.debug; + struct debug_info *dbg = &child->thread.debug; unsigned long insn, pc, alt; int res; @@ -363,7 +363,7 @@ */ int ptrace_cancel_bpt (struct task_struct *child) { - struct debug_info *dbg = &child->tss.debug; + struct debug_info *dbg = &child->thread.debug; unsigned long tmp; int i, nsaved = dbg->nsaved; @@ -514,7 +514,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->tss.debug.nsaved = -1; + child->thread.debug.nsaved = -1; child->flags &= ~PF_TRACESYS; wake_up_process(child); child->exit_code = data; diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- v2.3.12/linux/arch/arm/kernel/signal.c Wed Jul 28 14:47:42 1999 +++ linux/arch/arm/kernel/signal.c Mon Aug 2 10:19:52 1999 @@ -273,8 +273,8 @@ err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr); #endif - err |= __put_user (current->tss.trap_no, &sc->trap_no); - err |= __put_user (current->tss.error_code, &sc->error_code); + err |= __put_user (current->thread.trap_no, &sc->trap_no); + err |= __put_user (current->thread.error_code, &sc->error_code); err |= __put_user (mask, &sc->oldmask); return err; diff -u --recursive --new-file v2.3.12/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.3.12/linux/arch/arm/kernel/traps.c Wed Jul 21 15:46:48 1999 +++ linux/arch/arm/kernel/traps.c Mon Aug 2 10:19:52 1999 @@ -198,8 +198,8 @@ { printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr, __builtin_return_address(0)); - current->tss.error_code = 0; - current->tss.trap_no = 11; + current->thread.error_code = 0; + current->thread.trap_no = 11; force_sig(SIGBUS, current); /* die_if_kernel("Oops - bad user access alignment", regs, mode);*/ } @@ -210,8 +210,8 @@ printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); #endif - current->tss.error_code = 0; - current->tss.trap_no = 6; + current->thread.error_code = 0; + current->thread.trap_no = 6; force_sig(SIGILL, current); die_if_kernel("Oops - undefined instruction", regs, mode); } @@ -222,8 +222,8 @@ printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); #endif - current->tss.error_code = 0; - current->tss.trap_no = 11; + current->thread.error_code = 0; + current->thread.trap_no = 11; force_sig(SIGBUS, current); die_if_kernel("Oops - address exception", regs, mode); } @@ -367,7 +367,7 @@ { pgd_t *pgd; - printk ("current->tss.memmap = %08lX\n", current->tss.memmap); + printk ("current->thread.memmap = %08lX\n", current->thread.memmap); pgd = pgd_offset(current->mm, addr); printk ("*pgd = %08lx", pgd_val (*pgd)); if (!pgd_none (*pgd)) { diff -u --recursive --new-file v2.3.12/linux/arch/arm/lib/getconsdata.c linux/arch/arm/lib/getconsdata.c --- v2.3.12/linux/arch/arm/lib/getconsdata.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/lib/getconsdata.c Mon Aug 2 10:19:52 1999 @@ -32,11 +32,13 @@ unsigned long MM = OFF_TSK(mm); unsigned long PGD = OFF_MM(pgd); -unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap); -unsigned long TSS_SAVE = OFF_TSK(tss.save); -unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save); +unsigned long TSS_SAVE = OFF_TSK(thread.save); +unsigned long TSS_FPESAVE = OFF_TSK(thread.fpstate.soft.save); #ifdef CONFIG_CPU_26 -unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap); +unsigned long TSS_MEMMAP = OFF_TSK(thread.memmap); +unsigned long TSS_MEMCMAP = OFF_TSK(thread.memcmap); +#elif defined(CONFIG_CPU_32) +unsigned long TSS_DOMAIN = OFF_TSK(thread.domain); #endif #ifdef _PAGE_PRESENT diff -u --recursive --new-file v2.3.12/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- v2.3.12/linux/arch/arm/mm/fault-armv.c Sat May 8 11:06:56 1999 +++ linux/arch/arm/mm/fault-armv.c Mon Aug 2 10:19:52 1999 @@ -32,13 +32,14 @@ #include "fault-common.c" +/* + * need to get a 16k page for level 1 + */ pgd_t *get_pgd_slow(void) { - /* - * need to get a 16k page for level 1 - */ pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2); pgd_t *init; + pmd_t *new_pmd; if (pgd) { init = pgd_offset(&init_mm, 0); @@ -46,8 +47,32 @@ memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR); + + /* + * On ARM, first page must always be allocated + */ + if (!pmd_alloc(pgd, 0)) + goto nomem; + else { + pmd_t *old_pmd = pmd_offset(init, 0); + new_pmd = pmd_offset(pgd, 0); + + if (!pte_alloc(new_pmd, 0)) + goto nomem_pmd; + else { + pte_t *new_pte = pte_offset(new_pmd, 0); + pte_t *old_pte = pte_offset(old_pmd, 0); + + set_pte (new_pte, *old_pte); + } + } } return pgd; + +nomem_pmd: + pmd_free(new_pmd); +nomem: + return NULL; } pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) diff -u --recursive --new-file v2.3.12/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c --- v2.3.12/linux/arch/arm/mm/fault-common.c Wed Jul 28 14:47:42 1999 +++ linux/arch/arm/mm/fault-common.c Mon Aug 2 10:19:52 1999 @@ -85,7 +85,10 @@ printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", reason, addr); - printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd); + if (!mm) + mm = &init_mm; + + printk(KERN_ALERT "pgd = %p\n", mm->pgd); show_pte(mm, addr); die("Oops", regs, mode); @@ -151,8 +154,8 @@ /* User mode accesses just cause a SIGSEGV */ if (mode & FAULT_CODE_USER) { - tsk->tss.error_code = mode; - tsk->tss.trap_no = 14; + tsk->thread.error_code = mode; + tsk->thread.trap_no = 14; #ifdef CONFIG_DEBUG_USER printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); @@ -186,8 +189,8 @@ * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->tss.error_code = mode; - tsk->tss.trap_no = 14; + tsk->thread.error_code = mode; + tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); /* Kernel mode? Handle exceptions or die */ diff -u --recursive --new-file v2.3.12/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c --- v2.3.12/linux/arch/arm/mm/mm-rpc.c Thu Dec 17 09:05:42 1998 +++ linux/arch/arm/mm/mm-rpc.c Mon Aug 2 10:19:52 1999 @@ -85,8 +85,6 @@ rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000; rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000; - - current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir); } #define MAPPING \ diff -u --recursive --new-file v2.3.12/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S --- v2.3.12/linux/arch/arm/mm/proc-arm6,7.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/mm/proc-arm6,7.S Mon Aug 2 10:19:52 1999 @@ -53,41 +53,6 @@ mov pc, lr /* - * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next) - * - * Params : prev Old task structure - * : next New task structure for process to run - * - * Returns : prev - * - * Purpose : Perform a task switch, saving the old processes state, and restoring - * the new. - * - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. - */ -_arm6_7_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - mrs ip, cpsr - stmfd sp!, {ip} @ Save cpsr_SVC - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldr r2, [r1, #TSK_ADDR_LIMIT] - ldr r3, [r1, #TSS_MEMMAP] @ Page table pointer - teq r2, #0 - moveq r2, #DOM_KERNELDOMAIN - movne r2, #DOM_USERDOMAIN - mcr p15, 0, r2, c3, c0 @ Set domain reg - mov r1, #0 - mcr p15, 0, r1, c7, c0, 0 @ flush cache - mcr p15, 0, r3, c2, c0, 0 @ update page table ptr - mcr p15, 0, r1, c5, c0, 0 @ flush TLBs - ldmfd sp!, {ip} - msr spsr, ip @ Save tasks CPSR into SPSR for this return - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously - -/* * Function: arm6_7_data_abort () * * Params : r0 = address of aborted instruction @@ -341,6 +306,19 @@ mov pc, lr /* + * Function: arm6_7_set_pgd(unsigned long pgd_phys) + * Params : pgd_phys Physical address of page table + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + */ +_arm6_7_set_pgd: + mov r1, #0 + mcr p15, 0, r1, c7, c0, 0 @ flush cache + mcr p15, 0, r0, c2, c0, 0 @ update page table ptr + mcr p15, 0, r1, c5, c0, 0 @ flush TLBs + mov pc, lr + +/* * Function: arm6_set_pmd () * * Params : r0 = Address to set @@ -421,19 +399,19 @@ ENTRY(arm6_processor_functions) .word _arm6_name @ 0 - .word _arm6_7_switch_to @ 4 - .word _arm6_data_abort @ 8 - .word _arm6_7_check_bugs @ 12 - .word _arm6_7_proc_init @ 16 - .word _arm6_7_proc_fin @ 20 + .word _arm6_data_abort @ 4 + .word _arm6_7_check_bugs @ 8 + .word _arm6_7_proc_init @ 12 + .word _arm6_7_proc_fin @ 16 + .word _arm6_7_flush_cache @ 20 .word _arm6_7_flush_cache @ 24 .word _arm6_7_flush_cache @ 28 - .word _arm6_7_flush_cache @ 32 - .word _arm6_7_null @ 36 - .word _arm6_7_flush_cache @ 40 - .word _arm6_7_flush_tlb_all @ 44 - .word _arm6_7_flush_tlb_area @ 48 + .word _arm6_7_null @ 32 + .word _arm6_7_flush_cache @ 36 + .word _arm6_7_flush_tlb_all @ 40 + .word _arm6_7_flush_tlb_area @ 44 + .word _arm6_7_set_pgd @ 48 .word _arm6_set_pmd @ 52 .word _arm6_7_set_pte @ 56 .word _arm6_7_reset @ 60 @@ -451,19 +429,19 @@ ENTRY(arm7_processor_functions) .word _arm7_name @ 0 - .word _arm6_7_switch_to @ 4 - .word _arm7_data_abort @ 8 - .word _arm6_7_check_bugs @ 12 - .word _arm6_7_proc_init @ 16 - .word _arm6_7_proc_fin @ 20 + .word _arm7_data_abort @ 4 + .word _arm6_7_check_bugs @ 8 + .word _arm6_7_proc_init @ 12 + .word _arm6_7_proc_fin @ 16 + .word _arm6_7_flush_cache @ 20 .word _arm6_7_flush_cache @ 24 .word _arm6_7_flush_cache @ 28 - .word _arm6_7_flush_cache @ 32 - .word _arm6_7_null @ 36 - .word _arm6_7_flush_cache @ 40 - .word _arm6_7_flush_tlb_all @ 44 - .word _arm6_7_flush_tlb_area @ 48 + .word _arm6_7_null @ 32 + .word _arm6_7_flush_cache @ 36 + .word _arm6_7_flush_tlb_all @ 40 + .word _arm6_7_flush_tlb_area @ 44 + .word _arm6_7_set_pgd @ 48 .word _arm7_set_pmd @ 52 .word _arm6_7_set_pte @ 56 .word _arm6_7_reset @ 60 diff -u --recursive --new-file v2.3.12/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S --- v2.3.12/linux/arch/arm/mm/proc-sa110.S Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/mm/proc-sa110.S Mon Aug 2 10:19:52 1999 @@ -207,40 +207,35 @@ mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c7, c5, 0 @ flush I cache mov pc, lr + +/* + * Function: sa110_data_abort () + * Params : r0 = address of aborted instruction + * Purpose : obtain information about current aborted instruction + * Returns : r0 = address of abort + * : r1 = FSR + * : r2 != 0 if writing + */ + .align 5 +_sa110_data_abort: + ldr r2, [r0] @ read instruction causing problem + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov r2, r2, lsr #19 @ b1 = L + and r3, r2, #0x69 << 2 + and r2, r2, #2 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #255 + mov pc, lr + + .align 5 /* - * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next) - * Params : prev Old task structure - * : next New task structure for process to run - * Returns : prev + * Function: sa110_set_pgd(unsigned long pgd_phys) + * Params : pgd_phys Physical address of page table * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. */ .align 5 -_sa110_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - mrs ip, cpsr - stmfd sp!, {ip} @ Save cpsr_SVC - ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldr r5, [r1, #TSK_ADDR_LIMIT] - ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer - teq r5, #0 - moveq r5, #DOM_KERNELDOMAIN - movne r5, #DOM_USERDOMAIN - mcr p15, 0, r5, c3, c0 @ Set segment -/* - * Flushing the cache is nightmarishly slow, so we take any excuse - * to get out of it. If the old page table is the same as the new, - * this is a CLONE_VM relative of the old task and there is no need - * to flush. The overhead of the tests isn't even on the radar - * compared to the cost of the flush itself. - */ - teq r4, r2 - beq 2f +_sa110_set_pgd: ldr r3, =Lclean_switch ldr r2, [r3] ands r2, r2, #1 @@ -255,29 +250,8 @@ mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ flush I cache mcr p15, 0, r1, c7, c10, 4 @ drain WB - mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c8, c7, 0 @ flush TLBs -2: ldmfd sp!, {ip} - msr spsr, ip @ Save tasks CPSR into SPSR for this return - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously - -/* - * Function: sa110_data_abort () - * Params : r0 = address of aborted instruction - * Purpose : obtain information about current aborted instruction - * Returns : r0 = address of abort - * : r1 = FSR - * : r2 != 0 if writing - */ - .align 5 -_sa110_data_abort: - ldr r2, [r0] @ read instruction causing problem - mrc p15, 0, r0, c6, c0, 0 @ get FAR - mov r2, r2, lsr #19 @ b1 = L - and r3, r2, #0x69 << 2 - and r2, r2, #2 - mrc p15, 0, r1, c5, c0, 0 @ get FSR - and r1, r1, #255 mov pc, lr /* @@ -362,20 +336,20 @@ ENTRY(sa110_processor_functions) .word _sa110_name @ 0 - .word _sa110_switch_to @ 4 - .word _sa110_data_abort @ 8 - .word _sa110_check_bugs @ 12 - .word _sa110_proc_init @ 16 - .word _sa110_proc_fin @ 20 - - .word _sa110_flush_cache_all @ 24 - .word _sa110_flush_cache_area @ 28 - .word _sa110_flush_cache_entry @ 32 - .word _sa110_clean_cache_area @ 36 - .word _sa110_flush_ram_page @ 40 - .word _sa110_flush_tlb_all @ 44 - .word _sa110_flush_tlb_area @ 48 + .word _sa110_data_abort @ 4 + .word _sa110_check_bugs @ 8 + .word _sa110_proc_init @ 12 + .word _sa110_proc_fin @ 16 + + .word _sa110_flush_cache_all @ 20 + .word _sa110_flush_cache_area @ 24 + .word _sa110_flush_cache_entry @ 28 + .word _sa110_clean_cache_area @ 32 + .word _sa110_flush_ram_page @ 36 + .word _sa110_flush_tlb_all @ 40 + .word _sa110_flush_tlb_area @ 44 + .word _sa110_set_pgd @ 48 .word _sa110_set_pmd @ 52 .word _sa110_set_pte @ 56 .word _sa110_reset @ 60 diff -u --recursive --new-file v2.3.12/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.12/linux/arch/i386/config.in Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/config.in Thu Aug 5 18:44:28 1999 @@ -94,8 +94,8 @@ source drivers/parport/Config.in -bool 'Advanced Power Management BIOS support' CONFIG_APM -if [ "$CONFIG_APM" = "y" ]; then +tristate 'Advanced Power Management BIOS support' CONFIG_APM +if [ "$CONFIG_APM" != "n" ]; then bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE diff -u --recursive --new-file v2.3.12/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.12/linux/arch/i386/defconfig Thu Jul 8 15:42:19 1999 +++ linux/arch/i386/defconfig Thu Aug 5 18:53:36 1999 @@ -94,7 +94,9 @@ # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_AEC6210 is not set # CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_CPQ_DA is not set @@ -293,14 +295,12 @@ # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_MOUSE=y # # Mice # -# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y CONFIG_PSMOUSE=y CONFIG_82C710_MOUSE=y # CONFIG_PC110_PAD is not set diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.3.12/linux/arch/i386/kernel/Makefile Wed Jul 21 15:46:48 1999 +++ linux/arch/i386/kernel/Makefile Tue Aug 3 09:56:37 1999 @@ -34,8 +34,12 @@ endif endif -ifdef CONFIG_APM +ifeq ($(CONFIG_APM),y) OX_OBJS += apm.o +else + ifeq ($(CONFIG_APM),m) + MX_OBJS += apm.o + endif endif ifdef CONFIG_SMP diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.3.12/linux/arch/i386/kernel/apm.c Thu May 13 23:22:05 1999 +++ linux/arch/i386/kernel/apm.c Fri Aug 6 11:17:13 1999 @@ -273,7 +273,6 @@ static void set_time(void); static void check_events(void); -static void do_apm_timer(unsigned long); static int do_open(struct inode *, struct file *); static int do_release(struct inode *, struct file *); @@ -314,11 +313,9 @@ static int debug = 0; static int apm_disabled = 0; -static DECLARE_WAIT_QUEUE_HEAD(process_list); +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static struct apm_bios_struct * user_list = NULL; -static struct timer_list apm_timer; - static char driver_version[] = "1.9"; /* no spaces */ #ifdef APM_DEBUG @@ -543,6 +540,50 @@ return set_power_state(0x0001, state); } +/* + * If no process has been interested in this + * CPU for some time, we want to wake up the + * power management thread - we probably want + * to conserve power. + */ +#define HARD_IDLE_TIMEOUT (HZ/3) + +/* This should wake up kapmd and ask it to slow the CPU */ +#define powermanagement_idle() do { } while (0) + +extern int hlt_counter; + +/* + * This is the idle thing. + */ +void apm_cpu_idle(void) +{ + unsigned int start_idle; + + start_idle = jiffies; + while (1) { + if (!current->need_resched) { + if (jiffies - start_idle < HARD_IDLE_TIMEOUT) { + if (!current_cpu_data.hlt_works_ok) + continue; + if (hlt_counter) + continue; + asm volatile("sti ; hlt" : : : "memory"); + continue; + } + + /* + * Ok, do some power management - we've been idle for too long + */ + powermanagement_idle(); + } + + schedule(); + check_pgt_cache(); + start_idle = jiffies; + } +} + void apm_power_off(void) { /* @@ -756,7 +797,7 @@ break; } } - wake_up_interruptible(&process_list); + wake_up_interruptible(&apm_waitqueue); return 1; } @@ -942,32 +983,39 @@ } } -static void do_apm_timer(unsigned long unused) +/* + * This is the APM thread main loop. + */ +static void apm_mainloop(void) { - int err; - - static int pending_count = 0; + DECLARE_WAITQUEUE(wait, current); + apm_enabled = 1; - if (((standbys_pending > 0) || (suspends_pending > 0)) - && (apm_bios_info.version > 0x100) - && (pending_count-- <= 0)) { - pending_count = 4; + add_wait_queue(&apm_waitqueue, &wait); + for (;;) { + static int pending_count = 0; + int err; - err = apm_set_power_state(APM_STATE_BUSY); - if (err) - apm_error("busy", err); - } + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(APM_CHECK_TIMEOUT); - if (!(((standbys_pending > 0) || (suspends_pending > 0)) - && (apm_bios_info.version == 0x100))) - check_events(); + if (((standbys_pending > 0) || (suspends_pending > 0)) + && (apm_bios_info.version > 0x100) + && (pending_count-- <= 0)) { + pending_count = 4; + + err = apm_set_power_state(APM_STATE_BUSY); + if (err) + apm_error("busy", err); + } - init_timer(&apm_timer); - apm_timer.expires = APM_CHECK_TIMEOUT + jiffies; - add_timer(&apm_timer); + if (!(((standbys_pending > 0) || (suspends_pending > 0)) + && (apm_bios_info.version == 0x100))) + check_events(); + } } -/* Called from sys_idle, must make sure apm_enabled. */ +/* Called from cpu_idle, must make sure apm_enabled. */ int apm_do_idle(void) { #ifdef CONFIG_APM_CPU_IDLE @@ -986,7 +1034,7 @@ #endif } -/* Called from sys_idle, must make sure apm_enabled. */ +/* Called from cpu_idle, must make sure apm_enabled. */ void apm_do_busy(void) { #ifdef CONFIG_APM_CPU_IDLE @@ -1027,7 +1075,7 @@ if (queue_empty(as)) { if (fp->f_flags & O_NONBLOCK) return -EAGAIN; - add_wait_queue(&process_list, &wait); + add_wait_queue(&apm_waitqueue, &wait); repeat: current->state = TASK_INTERRUPTIBLE; if (queue_empty(as) && !signal_pending(current)) { @@ -1035,7 +1083,7 @@ goto repeat; } current->state = TASK_RUNNING; - remove_wait_queue(&process_list, &wait); + remove_wait_queue(&apm_waitqueue, &wait); } i = count; while ((i >= sizeof(event)) && !queue_empty(as)) { @@ -1069,7 +1117,7 @@ as = fp->private_data; if (check_apm_bios_struct(as, "select")) return 0; - poll_wait(fp, &process_list, wait); + poll_wait(fp, &apm_waitqueue, wait); if (!queue_empty(as)) return POLLIN | POLLRDNORM; return 0; @@ -1263,7 +1311,97 @@ return p - buf; } -void __init apm_setup(char *str, int *dummy) +static int apm(void *unused) +{ + unsigned short bx; + unsigned short cx; + unsigned short dx; + unsigned short error; + char * power_stat; + char * bat_stat; + + strcpy(current->comm, "kapmd"); + sigfillset(¤t->blocked); + + if (apm_bios_info.version > 0x100) { + /* + * We only support BIOSs up to version 1.2 + */ + if (apm_bios_info.version > 0x0102) + apm_bios_info.version = 0x0102; + if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) { + /* Fall back to an APM 1.0 connection. */ + apm_bios_info.version = 0x100; + } + } + if (debug) { + printk(KERN_INFO "apm: Connection version %d.%d\n", + (apm_bios_info.version >> 8) & 0xff, + apm_bios_info.version & 0xff ); + + error = apm_get_power_status(&bx, &cx, &dx); + if (error) + printk(KERN_INFO "apm: power status not available\n"); + else { + switch ((bx >> 8) & 0xff) { + case 0: power_stat = "off line"; break; + case 1: power_stat = "on line"; break; + case 2: power_stat = "on backup power"; break; + default: power_stat = "unknown"; break; + } + switch (bx & 0xff) { + case 0: bat_stat = "high"; break; + case 1: bat_stat = "low"; break; + case 2: bat_stat = "critical"; break; + case 3: bat_stat = "charging"; break; + default: bat_stat = "unknown"; break; + } + printk(KERN_INFO + "apm: AC %s, battery status %s, battery life ", + power_stat, bat_stat); + if ((cx & 0xff) == 0xff) + printk("unknown\n"); + else + printk("%d%%\n", cx & 0xff); + if (apm_bios_info.version > 0x100) { + printk(KERN_INFO + "apm: battery flag 0x%02x, battery life ", + (cx >> 8) & 0xff); + if (dx == 0xffff) + printk("unknown\n"); + else + printk("%d %s\n", dx & 0x7fff, + (dx & 0x8000) ? + "minutes" : "seconds"); + } + } + } + +#ifdef CONFIG_APM_DO_ENABLE + if (apm_bios_info.flags & APM_BIOS_DISABLED) { + /* + * This call causes my NEC UltraLite Versa 33/C to hang if it + * is booted with PM disabled but not in the docking station. + * Unfortunate ... + */ + error = apm_enable_power_management(); + if (error) { + apm_error("enable power management", error); + return -1; + } + } +#endif + if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0) + && (apm_bios_info.version > 0x0100)) { + if (apm_engage_power_management(0x0001) == APM_SUCCESS) + apm_bios_info.flags &= ~APM_BIOS_DISENGAGED; + } + + apm_mainloop(); + return 0; +} + +static int __init apm_setup(char *str) { int invert; @@ -1283,16 +1421,23 @@ if (str != NULL) str += strspn(str, ", \t"); } + return 1; } -void __init apm_bios_init(void) +__setup("apm=", apm_setup); + +/* + * Just start the APM thread. We do NOT want to do APM BIOS + * calls from anything but the APM thread, if for no other reason + * than the fact that we don't trust the APM BIOS. This way, + * most common APM BIOS problems that lead to protection errors + * etc will have at least some level of being contained... + * + * In short, if something bad happens, at least we have a choice + * of just killing the apm thread.. + */ +static int __init apm_init(void) { - unsigned short bx; - unsigned short cx; - unsigned short dx; - unsigned short error; - char * power_stat; - char * bat_stat; static struct proc_dir_entry *ent; if (apm_bios_info.version == 0) { @@ -1339,6 +1484,15 @@ return; } +#ifdef CONFIG_SMP + if (smp_num_cpus > 1) { + printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + if (smp_hack) + smp_hack = 2; + return -1; + } +#endif + /* * Set up a segment that references the real mode segment 0x40 * that extends up to the end of page zero (that we have reserved). @@ -1378,92 +1532,6 @@ (apm_bios_info.dseg_len - 1) & 0xffff); } #endif -#ifdef CONFIG_SMP - if (smp_num_cpus > 1) { - printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); - if (smp_hack) - smp_hack = 2; - return; - } -#endif - if (apm_bios_info.version > 0x100) { - /* - * We only support BIOSs up to version 1.2 - */ - if (apm_bios_info.version > 0x0102) - apm_bios_info.version = 0x0102; - if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) { - /* Fall back to an APM 1.0 connection. */ - apm_bios_info.version = 0x100; - } - } - if (debug) { - printk(KERN_INFO "apm: Connection version %d.%d\n", - (apm_bios_info.version >> 8) & 0xff, - apm_bios_info.version & 0xff ); - - error = apm_get_power_status(&bx, &cx, &dx); - if (error) - printk(KERN_INFO "apm: power status not available\n"); - else { - switch ((bx >> 8) & 0xff) { - case 0: power_stat = "off line"; break; - case 1: power_stat = "on line"; break; - case 2: power_stat = "on backup power"; break; - default: power_stat = "unknown"; break; - } - switch (bx & 0xff) { - case 0: bat_stat = "high"; break; - case 1: bat_stat = "low"; break; - case 2: bat_stat = "critical"; break; - case 3: bat_stat = "charging"; break; - default: bat_stat = "unknown"; break; - } - printk(KERN_INFO - "apm: AC %s, battery status %s, battery life ", - power_stat, bat_stat); - if ((cx & 0xff) == 0xff) - printk("unknown\n"); - else - printk("%d%%\n", cx & 0xff); - if (apm_bios_info.version > 0x100) { - printk(KERN_INFO - "apm: battery flag 0x%02x, battery life ", - (cx >> 8) & 0xff); - if (dx == 0xffff) - printk("unknown\n"); - else - printk("%d %s\n", dx & 0x7fff, - (dx & 0x8000) ? - "minutes" : "seconds"); - } - } - } - -#ifdef CONFIG_APM_DO_ENABLE - if (apm_bios_info.flags & APM_BIOS_DISABLED) { - /* - * This call causes my NEC UltraLite Versa 33/C to hang if it - * is booted with PM disabled but not in the docking station. - * Unfortunate ... - */ - error = apm_enable_power_management(); - if (error) { - apm_error("enable power management", error); - return; - } - } -#endif - if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0) - && (apm_bios_info.version > 0x0100)) { - if (apm_engage_power_management(0x0001) == APM_SUCCESS) - apm_bios_info.flags &= ~APM_BIOS_DISENGAGED; - } - - init_timer(&apm_timer); - apm_timer.function = do_apm_timer; - apm_timer.expires = APM_CHECK_TIMEOUT + jiffies; - add_timer(&apm_timer); ent = create_proc_entry("apm", 0, 0); if (ent != NULL) @@ -1471,5 +1539,7 @@ misc_register(&apm_device); - apm_enabled = 1; + kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); } + +module_init(apm_init) diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.3.12/linux/arch/i386/kernel/bios32.c Sat Apr 24 17:49:37 1999 +++ linux/arch/i386/kernel/bios32.c Thu Aug 5 18:44:28 1999 @@ -907,12 +907,17 @@ if ((try & PCI_BASE_ADDRESS_IO_MASK) != addr) { addr = 0; printk("PCI: Address setup failed, got %04x\n", try); - } else - dev->base_address[idx] = try; + } else { + struct resource *res = dev->resource + idx; + res->start = addr; + res->end = addr + size - 1; + res->flags |= PCI_BASE_ADDRESS_IO_MASK; + } } if (!addr) { pcibios_write_config_dword(bus, devfn, reg, 0); - dev->base_address[idx] = 0; + dev->resource[idx].start = 0; + dev->resource[idx].flags = 0; } pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); } @@ -939,7 +944,7 @@ e->vendor == d->vendor && e->device == d->device && e->class == d->class && - !memcmp(e->base_address, d->base_address, sizeof(e->base_address))) + !memcmp(e->resource, d->resource, sizeof(e->resource))) break; if (!e) return; @@ -1060,7 +1065,7 @@ int i; for(i=0; i<4; i++) - d->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO; + d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } struct dev_ex { @@ -1112,11 +1117,12 @@ */ has_io = has_mem = 0; for(i=0; i<6; i++) { - unsigned long a = dev->base_address[i]; + struct resource *res = dev->resource + i; + unsigned long a = res->flags; if (a & PCI_BASE_ADDRESS_SPACE_IO) { + unsigned long addr = res->start; has_io = 1; - a &= PCI_BASE_ADDRESS_IO_MASK; - if (!a || a == PCI_BASE_ADDRESS_IO_MASK) + if (!addr || addr == PCI_BASE_ADDRESS_IO_MASK) pcibios_fixup_io_addr(dev, i); } else if (a & PCI_BASE_ADDRESS_MEM_MASK) has_mem = 1; @@ -1234,7 +1240,7 @@ access_pci = bios; } -__initfunc(char *pcibios_setup(char *str)) +char * __init pcibios_setup(char *str) { if (!strcmp(str, "off")) { pci_probe = 0; diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.3.12/linux/arch/i386/kernel/entry.S Wed Jul 21 15:46:48 1999 +++ linux/arch/i386/kernel/entry.S Thu Jul 29 15:18:50 1999 @@ -481,7 +481,7 @@ .long SYMBOL_NAME(sys_uname) .long SYMBOL_NAME(sys_iopl) /* 110 */ .long SYMBOL_NAME(sys_vhangup) - .long SYMBOL_NAME(sys_idle) + .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */ .long SYMBOL_NAME(sys_vm86old) .long SYMBOL_NAME(sys_wait4) .long SYMBOL_NAME(sys_swapoff) /* 115 */ diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c --- v2.3.12/linux/arch/i386/kernel/init_task.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/kernel/init_task.c Tue Aug 3 10:32:57 1999 @@ -1,10 +1,10 @@ #include #include +#include #include #include #include -#include static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.3.12/linux/arch/i386/kernel/io_apic.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/kernel/io_apic.c Fri Aug 6 11:43:09 1999 @@ -242,40 +242,43 @@ int pirq_entries [MAX_PIRQS]; int pirqs_enabled; -void __init ioapic_setup(char *str, int *ints) +static int __init ioapic_setup(char *str) { extern int skip_ioapic_setup; /* defined in arch/i386/kernel/smp.c */ skip_ioapic_setup = 1; + return 1; } -void __init ioapic_pirq_setup(char *str, int *ints) +__setup("noapic", ioapic_setup); + +static int __init ioapic_pirq_setup(char *str) { int i, max; + int ints[MAX_PIRQS+1]; + + get_options(str, ARRAY_SIZE(ints), ints); for (i = 0; i < MAX_PIRQS; i++) pirq_entries[i] = -1; - if (!ints) { - pirqs_enabled = 0; - printk("PIRQ redirection, trusting MP-BIOS.\n"); - - } else { - pirqs_enabled = 1; - printk("PIRQ redirection, working around broken MP-BIOS.\n"); - max = MAX_PIRQS; - if (ints[0] < MAX_PIRQS) - max = ints[0]; - - for (i = 0; i < max; i++) { - printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]); - /* - * PIRQs are mapped upside down, usually. - */ - pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; - } + pirqs_enabled = 1; + printk("PIRQ redirection, working around broken MP-BIOS.\n"); + max = MAX_PIRQS; + if (ints[0] < MAX_PIRQS) + max = ints[0]; + + for (i = 0; i < max; i++) { + printk("... PIRQ%d -> IRQ %d\n", i, ints[i+1]); + /* + * PIRQs are mapped upside down, usually. + */ + pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; } + return 1; } + +__setup("pirq=", ioapic_pirq_setup); /* * Find the IRQ entry number of a certain pin. diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.12/linux/arch/i386/kernel/irq.c Wed Jul 21 15:46:48 1999 +++ linux/arch/i386/kernel/irq.c Fri Aug 6 11:43:09 1999 @@ -470,7 +470,6 @@ int i; unsigned long *stack; int cpu = smp_processor_id(); - extern char *get_options(char *str, int *ints); printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d %d]\n", @@ -480,7 +479,7 @@ stack = (unsigned long *) &stack; for (i = 40; i ; i--) { unsigned long x = *++stack; - if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) { + if (x > (unsigned long) &get_option && x < (unsigned long) &vsprintf) { printk("<[%08lx]> ", x); } } diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c --- v2.3.12/linux/arch/i386/kernel/ldt.c Wed Jul 21 15:46:48 1999 +++ linux/arch/i386/kernel/ldt.c Tue Aug 3 12:10:35 1999 @@ -98,8 +98,9 @@ printk(KERN_WARNING "LDT allocated for cloned task!\n"); /* * Possibly do an SMP cross-call to other CPUs to reload - * their LDTs + * their LDTs? */ + load_LDT(mm); } lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->segments); diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.3.12/linux/arch/i386/kernel/process.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/kernel/process.c Fri Aug 6 11:09:10 1999 @@ -51,14 +51,7 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -#ifdef CONFIG_APM -extern int apm_do_idle(void); -extern void apm_do_busy(void); -#endif - -static int hlt_counter=0; - -#define HARD_IDLE_TIMEOUT (HZ / 3) +int hlt_counter=0; void disable_hlt(void) { @@ -70,101 +63,67 @@ hlt_counter--; } -#ifndef __SMP__ - -static void hard_idle(void) -{ - while (!current->need_resched) { - if (boot_cpu_data.hlt_works_ok && !hlt_counter) { -#ifdef CONFIG_APM - /* If the APM BIOS is not enabled, or there - is an error calling the idle routine, we - should hlt if possible. We need to check - need_resched again because an interrupt - may have occurred in apm_do_idle(). */ - start_bh_atomic(); - if (!apm_do_idle() && !current->need_resched) - __asm__("hlt"); - end_bh_atomic(); -#else - __asm__("hlt"); -#endif - } - if (current->need_resched) - break; - schedule(); - } -#ifdef CONFIG_APM - apm_do_busy(); -#endif -} - -/* - * The idle loop on a uniprocessor i386.. - */ -static int cpu_idle(void *unused) +static void default_idle(void) { - int work = 1; - unsigned long start_idle = 0; - - /* endless idle loop with no priority at all */ - current->priority = 0; - current->counter = -100; - init_idle(); - - for (;;) { - if (work) - start_idle = jiffies; - - if (jiffies - start_idle > HARD_IDLE_TIMEOUT) - hard_idle(); - else { - if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched) - __asm__("hlt"); + while (1) { + while (!current->need_resched) { + if (!current_cpu_data.hlt_works_ok) + continue; + if (hlt_counter) + continue; + asm volatile("sti ; hlt" : : : "memory"); } - - work = current->need_resched; schedule(); check_pgt_cache(); } -} +} -#else +void (*idle)(void) = default_idle; -/* - * This is being executed in task 0 'user space'. - */ +#if 1 + +#include -int cpu_idle(void *unused) +static int __init piix4_idle_init(void) { - /* endless idle loop with no priority at all */ - current->priority = 0; - current->counter = -100; - init_idle(); + /* This is the PIIX4 ACPI device */ + struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - while(1) { - if (current_cpu_data.hlt_works_ok && !hlt_counter && - !current->need_resched) - __asm__("hlt"); + if (dev) { + u32 base; + + printk("Found PIIX4 ACPI device\n"); + pci_read_config_dword(dev, 0x40, &base); + printk(" Base address %04x\n", base); +#ifdef __SMP__ /* - * although we are an idle CPU, we do not want to - * get into the scheduler unnecessarily. + * We can't really do idle things with multiple CPU's, I'm + * afraid. We'd need a per-CPU ACPI device. */ - if (current->need_resched) { - schedule(); - check_pgt_cache(); - } + if (smp_num_cpus > 1) + return 0; +#endif } + return 0; } +__initcall(piix4_idle_init); + #endif -asmlinkage int sys_idle(void) +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) { - if (current->pid != 0) - return -EPERM; - cpu_idle(NULL); - return 0; + /* endless idle loop with no priority at all */ + init_idle(); + current->priority = 0; + current->counter = -100; + idle(); } /* @@ -177,7 +136,7 @@ static int reboot_mode = 0; static int reboot_thru_bios = 0; -__initfunc(void reboot_setup(char *str, int *ints)) +static int __init reboot_setup(char *str) { while(1) { switch (*str) { @@ -199,8 +158,10 @@ else break; } + return 1; } +__setup("reboot=", reboot_setup); /* The following code and data reboots the machine by switching to real mode and jumping to the BIOS reset entry point, as if the CPU has diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.12/linux/arch/i386/kernel/setup.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/kernel/setup.c Thu Jul 29 16:02:09 1999 @@ -35,9 +35,7 @@ #include #include #include -#ifdef CONFIG_APM #include -#endif #ifdef CONFIG_BLK_DEV_RAM #include #endif @@ -77,9 +75,7 @@ */ struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info; -#ifdef CONFIG_APM struct apm_bios_info apm_bios_info; -#endif struct sys_desc_table_struct { unsigned short length; unsigned char table[0]; @@ -284,9 +280,7 @@ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; -#ifdef CONFIG_APM apm_bios_info = APM_BIOS_INFO; -#endif if( SYS_DESC_TABLE.length != 0 ) { MCA_bus = SYS_DESC_TABLE.table[3] &0x2; machine_id = SYS_DESC_TABLE.table[0]; diff -u --recursive --new-file v2.3.12/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.3.12/linux/arch/i386/kernel/smp.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/kernel/smp.c Sat Aug 7 12:59:40 1999 @@ -172,6 +172,22 @@ max_cpus = 0; } +static int __init nosmp(char *str) +{ + max_cpus = 0; + return 1; +} + +__setup("nosmp", nosmp); + +static int __init maxcpus(char *str) +{ + get_option(&str, &max_cpus); + return 1; +} + +__setup("maxcpus", maxcpus); + void ack_APIC_irq(void) { /* Clear the IPI */ @@ -875,7 +891,7 @@ int cpucount = 0; -extern int cpu_idle(void * unused); +extern int cpu_idle(void); /* * Activate a secondary processor. @@ -891,7 +907,7 @@ smp_callin(); while (!atomic_read(&smp_commenced)) /* nothing */ ; - return cpu_idle(NULL); + return cpu_idle(); } /* @@ -939,8 +955,6 @@ * once we got the process: */ idle = init_task.prev_task; - - init_tasks[cpucount] = idle; if (!idle) panic("No idle process for CPU %d", i); @@ -952,6 +966,7 @@ del_from_runqueue(idle); unhash_process(idle); + init_tasks[cpucount] = idle; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); @@ -1229,6 +1244,7 @@ io_apic_irqs = 0; #endif cpu_online_map = cpu_present_map; + smp_num_cpus = 1; goto smp_done; } @@ -1615,7 +1631,10 @@ * Take care of "crossing" invalidates */ if (test_bit(cpu, &smp_invalidate_needed)) { + struct mm_struct *mm = current->mm; clear_bit(cpu, &smp_invalidate_needed); + if (mm) + atomic_set_mask(1 << cpu, &mm->cpu_vm_mask); local_flush_tlb(); } --stuck; @@ -1639,11 +1658,10 @@ { unsigned long vm_mask = 1 << current->processor; struct mm_struct *mm = current->mm; + unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; - if (mm->cpu_vm_mask != vm_mask) { - flush_tlb_others(mm->cpu_vm_mask & ~vm_mask); - mm->cpu_vm_mask = vm_mask; - } + mm->cpu_vm_mask = vm_mask; + flush_tlb_others(cpu_mask); local_flush_tlb(); } diff -u --recursive --new-file v2.3.12/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.3.12/linux/arch/i386/mm/fault.c Wed Jul 28 14:47:42 1999 +++ linux/arch/i386/mm/fault.c Mon Aug 2 15:56:47 1999 @@ -245,6 +245,7 @@ printk(" at virtual address %08lx\n",address); printk(" printing eip:\n"); printk("%08lx\n", regs->eip); + asm("movl %%cr3,%0":"=r" (page)); page = ((unsigned long *) __va(page))[address >> 22]; printk(KERN_ALERT "*pde = %08lx\n", page); if (page & 1) { diff -u --recursive --new-file v2.3.12/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.3.12/linux/arch/i386/mm/init.c Wed Jul 21 15:46:48 1999 +++ linux/arch/i386/mm/init.c Wed Aug 4 22:53:14 1999 @@ -28,6 +28,8 @@ #include #include +static unsigned long totalram = 0; + extern void show_net_buffers(void); extern unsigned long init_smp_mappings(unsigned long); @@ -419,6 +421,7 @@ continue; } set_page_count(mem_map+MAP_NR(tmp), 1); + totalram += PAGE_SIZE; #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end)) @@ -446,28 +449,16 @@ mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); set_page_count(mem_map+MAP_NR(addr), 1); free_page(addr); + totalram += PAGE_SIZE; } printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); } void si_meminfo(struct sysinfo *val) { - int i; - - i = max_mapnr; - val->totalram = 0; + val->totalram = totalram; val->sharedram = 0; val->freeram = nr_free_pages << PAGE_SHIFT; val->bufferram = atomic_read(&buffermem); - while (i-- > 0) { - if (PageReserved(mem_map+i)) - continue; - val->totalram++; - if (!page_count(mem_map+i)) - continue; - val->sharedram += page_count(mem_map+i) - 1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; return; } diff -u --recursive --new-file v2.3.12/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds --- v2.3.12/linux/arch/i386/vmlinux.lds Tue Jun 22 14:41:36 1999 +++ linux/arch/i386/vmlinux.lds Mon Aug 9 12:41:57 1999 @@ -42,15 +42,21 @@ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; . = ALIGN(4096); __init_end = .; - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - . = ALIGN(4096); .data.page_aligned : { *(.data.idt) } + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } __bss_start = .; /* BSS */ .bss : { diff -u --recursive --new-file v2.3.12/linux/arch/i386/vmlinux.lds.S linux/arch/i386/vmlinux.lds.S --- v2.3.12/linux/arch/i386/vmlinux.lds.S Mon Jun 7 17:02:23 1999 +++ linux/arch/i386/vmlinux.lds.S Mon Aug 2 13:57:59 1999 @@ -42,15 +42,21 @@ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; . = ALIGN(4096); __init_end = .; - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - . = ALIGN(4096); .data.page_aligned : { *(.data.idt) } + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } __bss_start = .; /* BSS */ .bss : { diff -u --recursive --new-file v2.3.12/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c --- v2.3.12/linux/arch/m68k/apollo/config.c Fri Jul 10 15:18:30 1998 +++ linux/arch/m68k/apollo/config.c Mon Aug 9 12:27:30 1999 @@ -1,4 +1,3 @@ -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/apollo/dn_debug.c linux/arch/m68k/apollo/dn_debug.c --- v2.3.12/linux/arch/m68k/apollo/dn_debug.c Thu Feb 12 16:30:12 1998 +++ linux/arch/m68k/apollo/dn_debug.c Mon Aug 9 12:27:30 1999 @@ -1,4 +1,3 @@ -#include #define DN_DEBUG_BUFFER_BASE 0x82800000 #define DN_DEBUG_BUFFER_SIZE 8*1024*1024 diff -u --recursive --new-file v2.3.12/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c --- v2.3.12/linux/arch/m68k/atari/joystick.c Wed Sep 2 09:39:18 1998 +++ linux/arch/m68k/atari/joystick.c Mon Aug 9 12:27:30 1999 @@ -134,7 +134,8 @@ { joystick[0].active = joystick[1].active = 0; joystick[0].ready = joystick[1].ready = 0; - joystick[0].wait = joystick[1].wait = NULL; + init_waitqueue_head(&joystick[0].wait); + init_waitqueue_head(&joystick[1].wait); if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops)) printk("unable to get major %d for joystick devices\n", MAJOR_NR); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.3.12/linux/arch/m68k/atari/stram.c Wed Jul 28 14:47:42 1999 +++ linux/arch/m68k/atari/stram.c Mon Aug 9 12:27:30 1999 @@ -200,7 +200,7 @@ static int stram_swap_type; /* Semaphore for get_stram_region. */ -static struct semaphore stram_swap_sem = MUTEX; +static DECLARE_MUTEX(stram_swap_sem); /* 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, @@ -346,12 +346,11 @@ "swap=%08lx-%08lx\n", swap_start, swap_end ); /* reserve some amount of memory for maintainance of - * swapping itself: 1 page for the lockmap, and one page - * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for - * each page) */ + * swapping itself: one page for each 2048 (PAGE_SIZE/2) + * swap pages. (2 bytes for each page) */ swap_data = start_mem; - start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1) - >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT; + start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1) + >> (PAGE_SHIFT-1)) << PAGE_SHIFT; /* correct swap_start if necessary */ if (swap_start == swap_data) swap_start = start_mem; @@ -610,8 +609,7 @@ p->flags = SWP_USED; p->swap_file = &fake_dentry[0]; p->swap_device = 0; - p->swap_lockmap = (unsigned char *)(swap_data); - p->swap_map = (unsigned short *)(swap_data + PAGE_SIZE); + p->swap_map = (unsigned short *)swap_data; p->cluster_nr = 0; p->next = -1; p->prio = 0x7ff0; /* a rather high priority, but not the higest @@ -623,9 +621,6 @@ swap_inode.i_rdev = p->swap_device; stram_open( &swap_inode, MAGIC_FILE_P ); p->max = SWAP_NR(swap_end); - - /* initialize lockmap */ - memset( p->swap_lockmap, 0, PAGE_SIZE ); /* initialize swap_map: set regions that are already allocated or belong * to kernel data space to SWAP_MAP_BAD, otherwise to free */ diff -u --recursive --new-file v2.3.12/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c --- v2.3.12/linux/arch/m68k/bvme6000/config.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/bvme6000/config.c Mon Aug 9 12:27:30 1999 @@ -14,7 +14,6 @@ * for more details. */ -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.3.12/linux/arch/m68k/config.in Tue May 11 09:57:14 1999 +++ linux/arch/m68k/config.in Mon Aug 9 12:27:30 1999 @@ -100,7 +100,7 @@ bool '/proc/hardware support' CONFIG_PROC_HARDWARE if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT + tristate 'Parallel port support (EXPERIMENTAL)' CONFIG_PARPORT if [ "$CONFIG_PARPORT" != "n" ]; then if [ "$CONFIG_AMIGA" != "n" ]; then dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT @@ -118,6 +118,10 @@ if [ "$CONFIG_ATARI" == "y" ]; then dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT fi + dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT + if [ "$CONFIG_PRINTER" != "n" ]; then + bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK + fi fi @@ -318,25 +322,23 @@ define_bool CONFIG_NVRAM y fi -if [ "$CONFIG_PARPORT" = "n" ]; then - tristate 'Parallel printer support' CONFIG_M68K_PRINTER - if [ "$CONFIG_ZORRO" = "y" ]; then - dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER - fi -else - dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT - if [ "$CONFIG_PRINTER" != "n" ]; then - bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK - fi -fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE + if [ "$CONFIG_AMIGAMOUSE" != "n" ]; then + define_bool CONFIG_MOUSE y + fi fi if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari mouse support' CONFIG_ATARIMOUSE + if [ "$CONFIG_ATARIMOUSE" != "n" ]; then + define_bool CONFIG_MOUSE y + fi fi if [ "$CONFIG_MAC" = "y" ]; then bool 'Mac ADB mouse support' CONFIG_ADBMOUSE + if [ "$CONFIG_ADBMOUSE" != "n" ]; then + define_bool CONFIG_MOUSE y + fi fi if [ "$CONFIG_ATARI" = "y" ]; then tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER @@ -374,6 +376,9 @@ if [ "$CONFIG_SUN3X_ZS" = "y" ]; then bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD bool 'Sun mouse support' CONFIG_SUN_MOUSE + if [ "$CONFIG_SUN_MOUSE" != "n" ]; then + define_bool CONFIG_MOUSE y + fi define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y define_bool CONFIG_SUN_SERIAL y diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.3.12/linux/arch/m68k/kernel/entry.S Tue May 11 09:57:14 1999 +++ linux/arch/m68k/kernel/entry.S Mon Aug 9 12:27:30 1999 @@ -67,7 +67,7 @@ ENTRY(reschedule) | save top of frame - movel %sp,%curptr@(TASK_TSS+TSS_ESP0) + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) pea SYMBOL_NAME(ret_from_exception) jmp SYMBOL_NAME(schedule) @@ -89,6 +89,16 @@ SAVE_SWITCH_STACK jbsr SYMBOL_NAME(syscall_trace) + | After a fork we jump here directly from resume, + | so that %d1 contains the previous task + | Theoretically only needed on SMP, but let's watch + | what happens in schedule_tail() in future... +ENTRY(ret_from_fork) + movel %d1,%sp@- + jsr SYMBOL_NAME(schedule_tail) + addql #4,%sp + jra SYMBOL_NAME(ret_from_exception) + SYMBOL_NAME_LABEL(ret_from_signal) RESTORE_SWITCH_STACK addql #4,%sp @@ -100,7 +110,7 @@ GET_CURRENT(%d0) | save top of frame - movel %sp,%curptr@(TASK_TSS+TSS_ESP0) + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) cmpl #NR_syscalls,%d2 jcc badsys @@ -118,8 +128,10 @@ andw #ALLOWINT,%sr tstl %curptr@(TASK_NEEDRESCHED) jne SYMBOL_NAME(reschedule) +#if 0 cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals jeq 2f +#endif | check for delayed trace bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF) jne do_delayed_trace @@ -265,25 +277,25 @@ */ /* save sr */ - movew %sr,%a0@(TASK_TSS+TSS_SR) + movew %sr,%a0@(TASK_THREAD+THREAD_SR) /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ movec %sfc,%d0 - movew %d0,%a0@(TASK_TSS+TSS_FS) + movew %d0,%a0@(TASK_THREAD+THREAD_FS) /* save usp */ /* it is better to use a movel here instead of a movew 8*) */ movec %usp,%d0 - movel %d0,%a0@(TASK_TSS+TSS_USP) + movel %d0,%a0@(TASK_THREAD+THREAD_USP) /* save non-scratch registers on stack */ SAVE_SWITCH_STACK /* save current kernel stack pointer */ - movel %sp,%a0@(TASK_TSS+TSS_KSP) + movel %sp,%a0@(TASK_THREAD+THREAD_KSP) /* save floating point context */ - fsave %a0@(TASK_TSS+TSS_FPSTATE) + fsave %a0@(TASK_THREAD+THREAD_FPSTATE) #if defined(CONFIG_M68060) #if !defined(CPU_M68060_ONLY) @@ -291,18 +303,18 @@ beqs 1f #endif /* The 060 FPU keeps status in bits 15-8 of the first longword */ - tstb %a0@(TASK_TSS+TSS_FPSTATE+2) + tstb %a0@(TASK_THREAD+THREAD_FPSTATE+2) jeq 3f #if !defined(CPU_M68060_ONLY) jra 2f #endif #endif /* CONFIG_M68060 */ #if !defined(CPU_M68060_ONLY) -1: tstb %a0@(TASK_TSS+TSS_FPSTATE) +1: tstb %a0@(TASK_THREAD+THREAD_FPSTATE) jeq 3f #endif -2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG) - fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL) +2: fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG) + fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL) 3: /* Return previous task in %d1 */ movel %curptr,%d1 @@ -310,69 +322,6 @@ /* switch to new task (a1 contains new task) */ movel %a1,%curptr - /* Skip address space switching if they are the same. */ - movel %a0@(TASK_MM),%d0 - cmpl %a1@(TASK_MM),%d0 - jeq 4f - -#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) - /* 68040 or 68060 ? */ - tstl SYMBOL_NAME(m68k_is040or060) - bnes 1f -#endif -#if defined(CPU_M68020_OR_M68030) - /* - * switch address space - */ - - /* flush MC68030/MC68020 caches (they are virtually addressed) */ - movec %cacr,%d0 - oriw #LFLUSH_I_AND_D,%d0 - movec %d0,%cacr - - /* switch the root pointer */ -#ifdef CPU_M68030_ONLY - .chip 68030 - pmovefd %a1@(TASK_TSS+TSS_CRP),%crp - .chip 68k - pflush #0,#4 -#else - pmove %a1@(TASK_TSS+TSS_CRP),%crp -#endif -#endif - -#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060) - jra 2f /* skip m68040 stuff */ -1: -#endif -#if defined(CPU_M68040_OR_M68060) - /* - * switch address space - */ - .chip 68040 - - /* flush address translation cache (user entries) */ - pflushan - - /* switch the root pointer */ - movel %a1@(TASK_TSS+TSS_CRP+4),%d0 - movec %d0,%urp - -#if defined (CONFIG_M68060) - /* is it a '060 ? */ -#if !defined(CPU_M68060_ONLY) - btst #3,SYMBOL_NAME(m68k_cputype)+3 - beqs 2f -#endif - /* clear user entries in the branch cache */ - movec %cacr,%d0 - orl #0x00200000,%d0 - movec %d0,%cacr -#endif /* CONFIG_M68060 */ - .chip 68k -#endif /* CPU_M68040_OR_M68060 */ -2: -4: /* restore floating point context */ #if defined(CONFIG_M68060) @@ -381,37 +330,37 @@ beqs 1f #endif /* The 060 FPU keeps status in bits 15-8 of the first longword */ - tstb %a1@(TASK_TSS+TSS_FPSTATE+2) + tstb %a1@(TASK_THREAD+THREAD_FPSTATE+2) jeq 3f #if !defined(CPU_M68060_ONLY) jra 2f #endif #endif /* CONFIG_M68060 */ #if !defined(CPU_M68060_ONLY) -1: tstb %a1@(TASK_TSS+TSS_FPSTATE) +1: tstb %a1@(TASK_THREAD+THREAD_FPSTATE) jeq 3f #endif -2: fmovemx %a1@(TASK_TSS+TSS_FPREG),%fp0-%fp7 - fmoveml %a1@(TASK_TSS+TSS_FPCNTL),%fpcr/%fpsr/%fpiar -3: frestore %a1@(TASK_TSS+TSS_FPSTATE) +2: fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7 + fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar +3: frestore %a1@(TASK_THREAD+THREAD_FPSTATE) /* restore the kernel stack pointer */ - movel %a1@(TASK_TSS+TSS_KSP),%sp + movel %a1@(TASK_THREAD+THREAD_KSP),%sp /* restore non-scratch registers */ RESTORE_SWITCH_STACK /* restore user stack pointer */ - movel %a1@(TASK_TSS+TSS_USP),%a0 + movel %a1@(TASK_THREAD+THREAD_USP),%a0 movel %a0,%usp /* restore fs (sfc,%dfc) */ - movew %a1@(TASK_TSS+TSS_FS),%a0 + movew %a1@(TASK_THREAD+THREAD_FS),%a0 movec %a0,%sfc movec %a0,%dfc /* restore status register */ - movew %a1@(TASK_TSS+TSS_SR),%sr + movew %a1@(TASK_THREAD+THREAD_SR),%sr rts @@ -530,7 +479,7 @@ .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */ .long SYMBOL_NAME(sys_vhangup) - .long SYMBOL_NAME(sys_idle) + .long SYMBOL_NAME(sys_ni_syscall) /* obsolete idle() syscall */ .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */ .long SYMBOL_NAME(sys_wait4) .long SYMBOL_NAME(sys_swapoff) /* 115 */ diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/m68k_defs.c linux/arch/m68k/kernel/m68k_defs.c --- v2.3.12/linux/arch/m68k/kernel/m68k_defs.c Tue Jan 19 10:58:26 1999 +++ linux/arch/m68k/kernel/m68k_defs.c Mon Aug 9 12:27:30 1999 @@ -26,25 +26,34 @@ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending)); DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched)); - DEFINE(TASK_TSS, offsetof(struct task_struct, tss)); + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); /* offsets into the thread struct */ - DEFINE(TSS_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(TSS_USP, offsetof(struct thread_struct, usp)); - DEFINE(TSS_SR, offsetof(struct thread_struct, sr)); - DEFINE(TSS_FS, offsetof(struct thread_struct, fs)); - DEFINE(TSS_CRP, offsetof(struct thread_struct, crp)); - DEFINE(TSS_ESP0, offsetof(struct thread_struct, esp0)); - DEFINE(TSS_FPREG, offsetof(struct thread_struct, fp)); - DEFINE(TSS_FPCNTL, offsetof(struct thread_struct, fpcntl)); - DEFINE(TSS_FPSTATE, offsetof(struct thread_struct, fpstate)); + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); + DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); + DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); /* offsets into the pt_regs */ DEFINE(PT_D0, offsetof(struct pt_regs, d0)); DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_PC, offsetof(struct pt_regs, pc)); DEFINE(PT_SR, offsetof(struct pt_regs, sr)); - /* bitfields are a bit difficult */ DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); @@ -68,6 +77,12 @@ DEFINE(FBCON_FONT_DESC_HEIGHT, offsetof(struct fbcon_font_desc, height)); DEFINE(FBCON_FONT_DESC_DATA, offsetof(struct fbcon_font_desc, data)); DEFINE(FBCON_FONT_DESC_PREF, offsetof(struct fbcon_font_desc, pref)); + + /* signal defines */ + DEFINE(SIGSEGV, SIGSEGV); + DEFINE(SEGV_MAPERR, SEGV_MAPERR); + DEFINE(SIGTRAP, SIGTRAP); + DEFINE(TRAP_TRACE, TRAP_TRACE); /* offsets into the custom struct */ DEFINE(CUSTOMBASE, &custom); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.3.12/linux/arch/m68k/kernel/m68k_ksyms.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/kernel/m68k_ksyms.c Mon Aug 9 12:27:30 1999 @@ -55,8 +55,6 @@ EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_set_cachemode); EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(register_serial); -EXPORT_SYMBOL(unregister_serial); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c --- v2.3.12/linux/arch/m68k/kernel/process.c Wed Jul 28 14:47:42 1999 +++ linux/arch/m68k/kernel/process.c Mon Aug 9 12:27:30 1999 @@ -45,35 +45,47 @@ struct mm_struct init_mm = INIT_MM(init_mm); union task_union init_task_union - __attribute__((section("init_task"), aligned(2*PAGE_SIZE))) - = { task: INIT_TASK }; +__attribute__((section("init_task"), aligned(THREAD_SIZE))) + = { task: INIT_TASK(init_task_union.task) }; + +asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_exception(void); /* * The idle loop on an m68k.. */ -asmlinkage int sys_idle(void) +static void default_idle(void) { - if (current->pid != 0) - return -EPERM; - - /* endless idle loop with no priority at all */ - current->priority = 0; - current->counter = -100; - for (;;) { + while(1) { if (!current->need_resched) -#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) +#ifdef MACH_ATARI_ONLY /* block out HSYNC on the atari (falcon) */ __asm__("stop #0x2200" : : : "cc"); -#else /* portable version */ +#else __asm__("stop #0x2000" : : : "cc"); -#endif /* machine compilation types */ +#endif schedule(); check_pgt_cache(); } } +void (*idle)(void) = default_idle; + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) +{ + /* endless idle loop with no priority at all */ + init_idle(); + current->priority = 0; + current->counter = -100; + idle(); +} + void machine_restart(char * __unused) { if (mach_reset) @@ -148,7 +160,7 @@ { unsigned long zero = 0; set_fs(USER_DS); - current->tss.fs = __USER_DS; + current->thread.fs = __USER_DS; asm volatile (".chip 68k/68881\n\t" "frestore %0@\n\t" ".chip 68k" : : "a" (&zero)); @@ -191,7 +203,7 @@ struct switch_stack * childstack, *stack; unsigned long stack_offset, *retp; - stack_offset = 2*PAGE_SIZE - sizeof(struct pt_regs); + stack_offset = THREAD_SIZE - sizeof(struct pt_regs); childregs = (struct pt_regs *) ((unsigned long) p + stack_offset); *childregs = *regs; @@ -202,26 +214,26 @@ childstack = ((struct switch_stack *) childregs) - 1; *childstack = *stack; - childstack->retpc = (unsigned long) ret_from_exception; + childstack->retpc = (unsigned long)ret_from_fork; - p->tss.usp = usp; - p->tss.ksp = (unsigned long)childstack; + p->thread.usp = usp; + p->thread.ksp = (unsigned long)childstack; /* * Must save the current SFC/DFC value, NOT the value when * the parent was last descheduled - RGH 10-08-96 */ - p->tss.fs = get_fs().seg; + p->thread.fs = get_fs().seg; /* Copy the current fpu state */ - asm volatile ("fsave %0" : : "m" (p->tss.fpstate[0]) : "memory"); + asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); - if (!CPU_IS_060 ? p->tss.fpstate[0] : p->tss.fpstate[2]) + if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" - : : "m" (p->tss.fp[0]), "m" (p->tss.fpcntl[0]) + : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) : "memory"); /* Restore the state in case the fpu was busy */ - asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0])); + asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); return 0; } @@ -230,7 +242,7 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) { - char fpustate[216]; + char fpustate[216]; /* First dump the fpu context to avoid protocol violation. */ asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.3.12/linux/arch/m68k/kernel/ptrace.c Mon Jun 7 11:15:33 1999 +++ linux/arch/m68k/kernel/ptrace.c Mon Aug 9 12:27:30 1999 @@ -37,7 +37,7 @@ /* sets the trace bits. */ #define TRACE_BITS 0x8000 -/* Find the stack offset for a register, relative to tss.esp0. */ +/* Find the stack offset for a register, relative to thread.esp0. */ #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) #define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ - sizeof(struct switch_stack)) @@ -60,9 +60,9 @@ unsigned long *addr; if (regno == PT_USP) - addr = &task->tss.usp; + addr = &task->thread.usp; else if (regno < sizeof(regoff)/sizeof(regoff[0])) - addr = (unsigned long *)(task->tss.esp0 + regoff[regno]); + addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); else return 0; return *addr; @@ -77,9 +77,9 @@ unsigned long *addr; if (regno == PT_USP) - addr = &task->tss.usp; + addr = &task->thread.usp; else if (regno < sizeof(regoff)/sizeof(regoff[0])) - addr = (unsigned long *) (task->tss.esp0 + regoff[regno]); + addr = (unsigned long *) (task->thread.esp0 + regoff[regno]); else return -1; *addr = data; @@ -386,7 +386,7 @@ tmp >>= 16; } else if (addr >= 21 && addr < 49) - tmp = child->tss.fp[addr - 21]; + tmp = child->thread.fp[addr - 21]; else goto out; ret = put_user(tmp,(unsigned long *) data); @@ -423,7 +423,7 @@ } if (addr >= 21 && addr < 48) { - child->tss.fp[addr - 21] = data; + child->thread.fp[addr - 21] = data; ret = 0; } goto out; @@ -544,7 +544,7 @@ case PTRACE_GETFPREGS: { /* Get the child FPU state. */ ret = 0; - if (copy_to_user((void *)data, &child->tss.fp, + if (copy_to_user((void *)data, &child->thread.fp, sizeof(struct user_m68kfp_struct))) ret = -EFAULT; goto out; @@ -552,7 +552,7 @@ case PTRACE_SETFPREGS: { /* Set the child FPU state. */ ret = 0; - if (copy_from_user(&child->tss.fp, (void *)data, + if (copy_from_user(&child->thread.fp, (void *)data, sizeof(struct user_m68kfp_struct))) ret = -EFAULT; goto out; diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.3.12/linux/arch/m68k/kernel/signal.c Wed Jul 28 14:47:42 1999 +++ linux/arch/m68k/kernel/signal.c Mon Aug 9 12:27:30 1999 @@ -156,6 +156,9 @@ /* * Do a signal return; undo the signal stack. + * + * Keep the return code on the stack quadword aligned! + * That makes the cache flush below easier. */ struct sigframe @@ -175,9 +178,9 @@ int sig; struct siginfo *pinfo; void *puc; + char retcode[8]; struct siginfo info; struct ucontext uc; - char retcode[8]; }; @@ -478,7 +481,7 @@ struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); - struct sigframe *frame = (struct sigframe *)(usp - 24); + struct sigframe *frame = (struct sigframe *)(usp - 4); sigset_t set; int d0; @@ -677,25 +680,6 @@ "cpushl %%bc,(%0)\n\t" ".chip 68k" : : "a" (temp)); - if (((vaddr + 8) ^ vaddr) & ~15) { - if (((vaddr + 8) ^ vaddr) & PAGE_MASK) - __asm__ __volatile__ (".chip 68040\n\t" - "nop\n\t" - "ptestr (%1)\n\t" - "movec %%mmusr,%0\n\t" - ".chip 68k" - : "=r" (temp) - : "a" (vaddr + 8)); - - temp &= PAGE_MASK; - temp |= (vaddr + 8) & ~PAGE_MASK; - - __asm__ __volatile__ (".chip 68040\n\t" - "nop\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (temp)); - } } else if (CPU_IS_060) { unsigned long temp; @@ -708,18 +692,6 @@ "cpushl %%bc,(%0)\n\t" ".chip 68k" : : "a" (temp)); - if (((vaddr + 8) ^ vaddr) & ~15) { - if (((vaddr + 8) ^ vaddr) & PAGE_MASK) - __asm__ __volatile__ (".chip 68060\n\t" - "plpar (%0)\n\t" - ".chip 68k" - : "=a" (temp) - : "0" (vaddr + 8)); - __asm__ __volatile__ (".chip 68060\n\t" - "cpushl %%bc,(%0)\n\t" - ".chip 68k" - : : "a" (temp)); - } } else { /* @@ -797,11 +769,9 @@ /* Set up to return from userspace. */ err |= __put_user(frame->retcode, &frame->pretcode); - /* addaw #20,sp */ - err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0)); /* moveq #,d0; trap #0 */ err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), - (long *)(frame->retcode + 4)); + (long *)(frame->retcode)); if (err) goto give_sigsegv; @@ -881,10 +851,10 @@ /* Set up to return from userspace. */ err |= __put_user(frame->retcode, &frame->pretcode); - /* movel #,d0; trap #0 */ - err |= __put_user(0x203c, (short *)(frame->retcode + 0)); - err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2)); - err |= __put_user(0x4e40, (short *)(frame->retcode + 6)); + /* moveq #,d0; notb d0; trap #0 */ + err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), + (long *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); if (err) goto give_sigsegv; @@ -964,11 +934,10 @@ if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked,sig); - recalc_sigpending(current); - } + recalc_sigpending(current); } /* @@ -985,7 +954,7 @@ siginfo_t info; struct k_sigaction *ka; - current->tss.esp0 = (unsigned long) regs; + current->thread.esp0 = (unsigned long) regs; if (!oldset) oldset = ¤t->blocked; @@ -1090,6 +1059,7 @@ default: sigaddset(¤t->signal, signr); + recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ diff -u --recursive --new-file v2.3.12/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c --- v2.3.12/linux/arch/m68k/kernel/traps.c Mon Oct 5 13:54:39 1998 +++ linux/arch/m68k/kernel/traps.c Mon Aug 9 12:27:30 1999 @@ -648,7 +648,7 @@ { /* Only set esp0 if coming from user mode */ if (user_mode(&fp->ptregs)) - current->tss.esp0 = (unsigned long) fp; + current->thread.esp0 = (unsigned long) fp; #if DEBUG printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c --- v2.3.12/linux/arch/m68k/mac/adb-bus.c Sat May 15 15:05:35 1999 +++ linux/arch/m68k/mac/adb-bus.c Mon Aug 9 12:27:30 1999 @@ -13,7 +13,6 @@ * MSch (1/98) Integrated start of IIsi driver by Robert Thompson */ -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mm/fault.c linux/arch/m68k/mm/fault.c --- v2.3.12/linux/arch/m68k/mm/fault.c Wed Jul 28 14:47:42 1999 +++ linux/arch/m68k/mm/fault.c Mon Aug 9 12:27:30 1999 @@ -36,7 +36,7 @@ struct mm_struct *mm = current->mm; struct vm_area_struct * vma; unsigned long fixup; - int write; + int write, fault; #ifdef DEBUG printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", @@ -44,7 +44,6 @@ current->mm->pgd); #endif - /* * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -100,7 +99,10 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ - if (!handle_mm_fault(current, vma, address, write)) + fault = handle_mm_fault(current, vma, address, write); + if (fault < 0) + goto out_of_memory; + if (!fault) goto do_sigbus; /* There seems to be a missing invalidate somewhere in do_no_page. @@ -160,6 +162,13 @@ * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ +out_of_memory: + up(&mm->mmap_sem); + printk("VM: killing process %s\n", current->comm); + if (error_code & 4) + do_exit(SIGKILL); + goto no_context; + do_sigbus: up(&mm->mmap_sem); diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.3.12/linux/arch/m68k/mm/init.c Wed Jun 30 13:38:18 1999 +++ linux/arch/m68k/mm/init.c Mon Aug 9 12:27:30 1999 @@ -28,8 +28,6 @@ #include #endif -#undef DEBUG - extern void die_if_kernel(char *,struct pt_regs *,long); extern void show_net_buffers(void); @@ -94,12 +92,12 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!atomic_read(&mem_map[i].count)) + else if (!page_count(mem_map+i)) free++; - else if (atomic_read(&mem_map[i].count) == 1) + else if (page_count(mem_map+i) == 1) nonshared++; else - shared += atomic_read(&mem_map[i].count) - 1; + shared += page_count(mem_map+i) - 1; } printk("%d pages of RAM\n",total); printk("%d free pages\n",free); @@ -138,6 +136,7 @@ } static pmd_t *last_pgtable __initdata = NULL; +static pmd_t *zero_pgtable __initdata = NULL; __initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp)) { @@ -183,7 +182,7 @@ { #define PTRTREESIZE (256*1024) #define ROOTTREESIZE (32*1024*1024) - static unsigned long virtaddr = 0; + static unsigned long virtaddr = PAGE_OFFSET; unsigned long physaddr; pgd_t *pgd_dir; pmd_t *pmd_dir; @@ -235,7 +234,8 @@ #ifdef DEBUG printk ("[zero map]"); #endif - pte_dir = (pte_t *)kernel_ptr_table(memavailp); + zero_pgtable = kernel_ptr_table(memavailp); + pte_dir = (pte_t *)zero_pgtable; pmd_dir->pmd[0] = virt_to_phys(pte_dir) | _PAGE_TABLE | _PAGE_ACCESSED; pte_val(*pte_dir++) = 0; @@ -352,38 +352,6 @@ start_mem += PAGE_SIZE; memset((void *)empty_zero_page, 0, PAGE_SIZE); - /* - * allocate the "swapper" page directory and - * record in task 0 (swapper) tss - */ - init_mm.pgd = (pgd_t *)kernel_ptr_table(&start_mem); - memset (init_mm.pgd, 0, sizeof(pgd_t)*PTRS_PER_PGD); - - /* setup CPU root pointer for swapper task */ - task[0]->tss.crp[0] = 0x80000000 | _PAGE_TABLE; - task[0]->tss.crp[1] = virt_to_phys(init_mm.pgd); - -#ifdef DEBUG - printk ("task 0 pagedir at %p virt, %#lx phys\n", - swapper_pg_dir, task[0]->tss.crp[1]); -#endif - - if (CPU_IS_040_OR_060) - asm __volatile__ (".chip 68040\n\t" - "movec %0,%%urp\n\t" - ".chip 68k" - : /* no outputs */ - : "r" (task[0]->tss.crp[1])); - else - asm __volatile__ (".chip 68030\n\t" - "pmove %0,%%crp\n\t" - ".chip 68k" - : /* no outputs */ - : "m" (task[0]->tss.crp[0])); -#ifdef DEBUG - printk ("set crp\n"); -#endif - /* * Set up SFC/DFC registers (user data space) */ @@ -418,7 +386,7 @@ atari_stram_reserve_pages( start_mem ); #endif - for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) { + for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) { if (virt_to_phys ((void *)tmp) >= mach_max_dma_address) clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); if (PageReserved(mem_map+MAP_NR(tmp))) { @@ -435,7 +403,7 @@ datapages++; continue; } - atomic_set(&mem_map[MAP_NR(tmp)].count, 1); + set_page_count(mem_map+MAP_NR(tmp), 1); #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start || (tmp < (initrd_start & PAGE_MASK) || tmp >= initrd_end)) @@ -450,6 +418,10 @@ init_pointer_table(pgd_page(kernel_pg_dir[i])); } + /* insert also pointer table that we used to unmap the zero page */ + if (zero_pgtable) + init_pointer_table((unsigned long)zero_pgtable); + printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n", (unsigned long) nr_free_pages << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), @@ -465,7 +437,7 @@ addr = (unsigned long)&__init_begin; for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - atomic_set(&mem_map[MAP_NR(addr)].count, 1); + set_page_count(mem_map+MAP_NR(addr), 1); free_page(addr); } } @@ -483,9 +455,9 @@ if (PageReserved(mem_map+i)) continue; val->totalram++; - if (!atomic_read(&mem_map[i].count)) + if (!page_count(mem_map+i)) continue; - val->sharedram += atomic_read(&mem_map[i].count) - 1; + val->sharedram += page_count(mem_map+i) - 1; } val->totalram <<= PAGE_SHIFT; val->sharedram <<= PAGE_SHIFT; diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c --- v2.3.12/linux/arch/m68k/mm/memory.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/mm/memory.c Mon Aug 9 12:27:30 1999 @@ -227,31 +227,33 @@ /* address match? */ base = regval & 0xff000000; mask = ~(regval << 8) & 0xff000000; - return ((vaddr ^ base) & mask) == 0; + return (((unsigned long)vaddr ^ base) & mask) == 0; } +#if DEBUG_INVALID_PTOV +int mm_inv_cnt = 5; +#endif + #ifndef CONFIG_SINGLE_MEMORY_CHUNK /* * The following two routines map from a physical address to a kernel * virtual address and vice versa. */ -unsigned long mm_vtop (unsigned long vaddr) +unsigned long mm_vtop(unsigned long vaddr) { int i=0; - unsigned long voff = vaddr; - unsigned long offset = 0; + unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET; - do{ - if (voff < offset + m68k_memory[i].size) { + do { + if (voff < m68k_memory[i].size) { #ifdef DEBUGPV - printk ("VTOP(%lx)=%lx\n", vaddr, - m68k_memory[i].addr + voff - offset); + printk ("VTOP(%p)=%lx\n", vaddr, + m68k_memory[i].addr + voff); #endif - return m68k_memory[i].addr + voff - offset; - } else - offset += m68k_memory[i].size; - i++; - }while (i < m68k_num_memory); + return m68k_memory[i].addr + voff; + } + voff -= m68k_memory[i].size; + } while (++i < m68k_num_memory); return mm_vtop_fallback(vaddr); } @@ -259,7 +261,7 @@ /* Separate function to make the common case faster (needs to save less registers) */ -unsigned long mm_vtop_fallback (unsigned long vaddr) +unsigned long mm_vtop_fallback(unsigned long vaddr) { /* not in one of the memory chunks; test for applying transparent * translation */ @@ -272,13 +274,13 @@ ".chip 68k" : : "a" (&ttreg) ); if (transp_transl_matches( ttreg, vaddr )) - return vaddr; + return (unsigned long)vaddr; asm volatile( ".chip 68030\n\t" "pmove %/tt1,%0@\n\t" ".chip 68k" : : "a" (&ttreg) ); if (transp_transl_matches( ttreg, vaddr )) - return vaddr; + return (unsigned long)vaddr; } else if (CPU_IS_040_OR_060) { unsigned long ttreg; @@ -288,13 +290,13 @@ ".chip 68k" : "=d" (ttreg) ); if (transp_transl_matches( ttreg, vaddr )) - return vaddr; + return (unsigned long)vaddr; asm volatile( ".chip 68040\n\t" "movec %%dtt1,%0\n\t" ".chip 68k" : "=d" (ttreg) ); if (transp_transl_matches( ttreg, vaddr )) - return vaddr; + return (unsigned long)vaddr; } /* no match, too, so get the actual physical address from the MMU. */ @@ -306,11 +308,21 @@ set_fs (MAKE_MM_SEG(SUPER_DATA)); /* The PLPAR instruction causes an access error if the translation - * is not possible. We don't catch that here, so a bad kernel trap - * will be reported in this case. */ - asm volatile (".chip 68060\n\t" - "plpar (%0)\n\t" - ".chip 68k" + * is not possible. To catch this we use the same exception mechanism + * as for user space accesses in . */ + asm volatile (".chip 68060\n" + "1: plpar (%0)\n" + ".chip 68k\n" + "2:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "3: lea -1,%0\n" + " jra 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,3b\n" + ".previous" : "=a" (paddr) : "0" (vaddr)); set_fs (fs); @@ -332,12 +344,13 @@ set_fs (fs); if (mmusr & MMU_T_040) { - return (vaddr); /* Transparent translation */ + return (unsigned long)vaddr; /* Transparent translation */ } if (mmusr & MMU_R_040) - return (mmusr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1)); + return (mmusr & PAGE_MASK) | ((unsigned long)vaddr & (PAGE_SIZE-1)); - panic ("VTOP040: bad virtual address %08lx (%lx)", vaddr, mmusr); + printk("VTOP040: bad virtual address %lx (%lx)", vaddr, mmusr); + return -1; } else { volatile unsigned short temp; unsigned short mmusr; @@ -350,46 +363,51 @@ mmusr = temp; if (mmusr & (MMU_I|MMU_B|MMU_L)) - panic ("VTOP030: bad virtual address %08lx (%x)", vaddr, mmusr); + printk("VTOP030: bad virtual address %lx (%x)\n", vaddr, mmusr); descaddr = phys_to_virt((unsigned long)descaddr); switch (mmusr & MMU_NUM) { case 1: - return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff); + return (*descaddr & 0xfe000000) | ((unsigned long)vaddr & 0x01ffffff); case 2: - return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff); + return (*descaddr & 0xfffc0000) | ((unsigned long)vaddr & 0x0003ffff); case 3: - return (*descaddr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1)); + return (*descaddr & PAGE_MASK) | ((unsigned long)vaddr & (PAGE_SIZE-1)); default: - panic ("VTOP: bad levels (%u) for virtual address %08lx", + printk("VTOP: bad levels (%u) for virtual address %lx\n", mmusr & MMU_NUM, vaddr); } } - panic ("VTOP: bad virtual address %08lx", vaddr); + printk("VTOP: bad virtual address %lx\n", vaddr); + return -1; } #ifndef CONFIG_SINGLE_MEMORY_CHUNK -unsigned long mm_ptov (unsigned long paddr) +void *mm_ptov (unsigned long paddr) { int i = 0; - unsigned long offset = 0; + unsigned long poff, voff = PAGE_OFFSET; - do{ - if (paddr >= m68k_memory[i].addr && - paddr < (m68k_memory[i].addr - + m68k_memory[i].size)) { + do { + poff = paddr - m68k_memory[i].addr; + if (poff < m68k_memory[i].size) { #ifdef DEBUGPV - printk ("PTOV(%lx)=%lx\n", paddr, - (paddr - m68k_memory[i].addr) + offset); + printk ("PTOV(%lx)=%lx\n", paddr, poff + voff); +#endif + return (void *)(poff + voff); + } + voff += m68k_memory[i].size; + } while (++i < m68k_num_memory); + +#if DEBUG_INVALID_PTOV + if (mm_inv_cnt > 0) { + mm_inv_cnt--; + printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n", + paddr, __builtin_return_address(0)); + } #endif - return (paddr - m68k_memory[i].addr) + offset; - } else - offset += m68k_memory[i].size; - i++; - }while (i < m68k_num_memory); - /* * assume that the kernel virtual address is the same as the * physical address. @@ -411,9 +429,9 @@ * to the ZTWO_VADDR range */ if (MACH_IS_AMIGA && paddr < 16*1024*1024) - return ZTWO_VADDR(paddr); + return (void *)ZTWO_VADDR(paddr); #endif - return paddr; + return (void *)-1; } #endif diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c --- v2.3.12/linux/arch/m68k/mvme147/config.c Wed May 12 08:50:00 1999 +++ linux/arch/m68k/mvme147/config.c Mon Aug 9 12:27:30 1999 @@ -13,7 +13,6 @@ * for more details. */ -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c --- v2.3.12/linux/arch/m68k/mvme16x/config.c Tue May 11 09:57:14 1999 +++ linux/arch/m68k/mvme16x/config.c Mon Aug 9 12:27:30 1999 @@ -15,7 +15,6 @@ */ #include -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c --- v2.3.12/linux/arch/m68k/q40/config.c Wed May 12 08:50:00 1999 +++ linux/arch/m68k/q40/config.c Mon Aug 9 12:27:30 1999 @@ -12,7 +12,6 @@ * for more details. */ -#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds --- v2.3.12/linux/arch/m68k/vmlinux.lds Tue Jan 5 11:20:43 1999 +++ linux/arch/m68k/vmlinux.lds Mon Aug 9 12:27:30 1999 @@ -31,22 +31,32 @@ CONSTRUCTORS } - .bss : { *(.bss) } /* BSS */ - _edata = .; /* End of data section */ - . = ALIGN(16); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } + . = ALIGN(8192); + init_task : { *(init_task) } . = ALIGN(4096); /* Init code and data */ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; . = ALIGN(8192); __init_end = .; - init_task : { *(init_task) } /* The initial task and kernel stack */ + . = ALIGN(16); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } _end = . ; /* Stabs debugging sections. */ diff -u --recursive --new-file v2.3.12/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c --- v2.3.12/linux/arch/mips/dec/serial.c Wed Jun 30 13:38:18 1999 +++ linux/arch/mips/dec/serial.c Wed Aug 4 16:36:41 1999 @@ -17,7 +17,7 @@ */ #include -#include +#include #include #ifdef CONFIG_ZS diff -u --recursive --new-file v2.3.12/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.3.12/linux/arch/mips/dec/setup.c Wed Jun 30 13:38:18 1999 +++ linux/arch/mips/dec/setup.c Wed Aug 4 16:36:41 1999 @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/mips/dec/wbflush.c linux/arch/mips/dec/wbflush.c --- v2.3.12/linux/arch/mips/dec/wbflush.c Wed Jun 30 13:38:18 1999 +++ linux/arch/mips/dec/wbflush.c Wed Aug 4 16:36:41 1999 @@ -14,7 +14,7 @@ */ #include -#include +#include static void wbflush_kn01(void); static void wbflush_kn210(void); diff -u --recursive --new-file v2.3.12/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c --- v2.3.12/linux/arch/ppc/kernel/apus_setup.c Wed Jul 28 14:47:42 1999 +++ linux/arch/ppc/kernel/apus_setup.c Mon Aug 9 12:32:28 1999 @@ -325,11 +325,11 @@ switch (cmode) { - case KERNELMAP_FULL_CACHING: + case IOMAP_FULL_CACHING: mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED); flags = 0; break; - case KERNELMAP_NOCACHE_SER: + case IOMAP_NOCACHE_SER: mask = ~0; flags = (_PAGE_NO_CACHE | _PAGE_GUARDED); break; diff -u --recursive --new-file v2.3.12/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c --- v2.3.12/linux/arch/ppc/kernel/pmac_support.c Sun Nov 15 10:51:43 1998 +++ linux/arch/ppc/kernel/pmac_support.c Wed Aug 4 16:36:41 1999 @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.3.12/linux/arch/ppc/kernel/ppc_ksyms.c Wed Jun 30 13:38:19 1999 +++ linux/arch/ppc/kernel/ppc_ksyms.c Mon Aug 9 11:39:37 1999 @@ -219,3 +219,7 @@ EXPORT_SYMBOL(abs); EXPORT_SYMBOL(device_is_compatible); + +#ifdef CONFIG_VT +EXPORT_SYMBOL(screen_info); +#endif diff -u --recursive --new-file v2.3.12/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c --- v2.3.12/linux/arch/ppc/kernel/smp.c Wed Jul 28 14:47:42 1999 +++ linux/arch/ppc/kernel/smp.c Wed Aug 4 16:36:41 1999 @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c --- v2.3.12/linux/arch/sparc/kernel/pcic.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/pcic.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.6 1999/06/03 15:02:18 davem Exp $ +/* $Id: pcic.c,v 1.7 1999/07/23 01:56:07 davem Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.3.12/linux/arch/sparc/kernel/process.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/process.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.137 1999/05/08 03:00:10 davem Exp $ +/* $Id: process.c,v 1.138 1999/07/23 01:56:10 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.3.12/linux/arch/sparc/kernel/setup.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc/kernel/setup.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.107 1999/06/03 15:02:20 davem Exp $ +/* $Id: setup.c,v 1.108 1999/07/30 09:35:03 davem Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.3.12/linux/arch/sparc/kernel/signal.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc/kernel/signal.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.92 1999/06/14 05:23:53 davem Exp $ +/* $Id: signal.c,v 1.94 1999/07/30 09:35:04 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -659,6 +659,9 @@ err |= __copy_to_user(sf, (char *) regs->u_regs [UREG_FP], sizeof (struct reg_window)); + + err |= __copy_to_user(&sf->info, info, sizeof(siginfo_t)); + if (err) goto sigsegv; diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/sparc-stub.c linux/arch/sparc/kernel/sparc-stub.c --- v2.3.12/linux/arch/sparc/kernel/sparc-stub.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/sparc-stub.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc-stub.c,v 1.24 1998/02/08 07:58:44 ecd Exp $ +/* $Id: sparc-stub.c,v 1.25 1999/07/23 01:56:13 davem Exp $ * sparc-stub.c: KGDB support for the Linux kernel. * * Modifications to run under Linux diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.3.12/linux/arch/sparc/kernel/sparc_ksyms.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/sparc_ksyms.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.77 1999/03/21 06:37:43 davem Exp $ +/* $Id: sparc_ksyms.c,v 1.78 1999/07/23 01:56:15 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/sunos_ioctl.c linux/arch/sparc/kernel/sunos_ioctl.c --- v2.3.12/linux/arch/sparc/kernel/sunos_ioctl.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/sunos_ioctl.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sunos_ioctl.c,v 1.31 1998/10/25 19:31:04 davem Exp $ +/* $Id: sunos_ioctl.c,v 1.33 1999/07/28 12:59:03 anton Exp $ * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -21,6 +21,7 @@ #include #include #include +#include #include #if 0 diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.12/linux/arch/sparc/kernel/sys_sunos.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/kernel/sys_sunos.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.101 1999/06/29 12:33:54 davem Exp $ +/* $Id: sys_sunos.c,v 1.102 1999/07/23 01:56:19 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/arch/sparc/kernel/trampoline.S linux/arch/sparc/kernel/trampoline.S --- v2.3.12/linux/arch/sparc/kernel/trampoline.S Tue Apr 14 17:44:19 1998 +++ linux/arch/sparc/kernel/trampoline.S Wed Aug 4 16:36:41 1999 @@ -1,10 +1,11 @@ -/* $Id: trampoline.S,v 1.12 1998/03/19 15:36:38 jj Exp $ +/* $Id: trampoline.S,v 1.13 1999/08/04 03:19:15 davem Exp $ * trampoline.S: SMP cpu boot-up trampoline code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include .globl C_LABEL(sun4m_cpu_startup), C_LABEL(__smp4m_processor_id) .globl C_LABEL(sun4d_cpu_startup), C_LABEL(__smp4d_processor_id) diff -u --recursive --new-file v2.3.12/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c --- v2.3.12/linux/arch/sparc/lib/debuglocks.c Thu Apr 22 19:24:51 1999 +++ linux/arch/sparc/lib/debuglocks.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: debuglocks.c,v 1.7 1999/04/21 02:26:58 anton Exp $ +/* $Id: debuglocks.c,v 1.8 1999/08/05 09:49:59 anton Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -53,7 +53,7 @@ lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); for(i = 0; i < NR_CPUS; i++) - printk(" reader[i]=%08lx", lock->reader_pc[i]); + printk(" reader[%d]=%08lx", i, lock->reader_pc[i]); printk("\n"); } diff -u --recursive --new-file v2.3.12/linux/arch/sparc/math-emu/sfp-machine.h linux/arch/sparc/math-emu/sfp-machine.h --- v2.3.12/linux/arch/sparc/math-emu/sfp-machine.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc/math-emu/sfp-machine.h Mon Aug 2 22:07:16 1999 @@ -30,9 +30,12 @@ #define _FP_WS_TYPE signed long #define _FP_I_TYPE long -#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm) -#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm) -#define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_4_wide(Q,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) @@ -54,7 +57,7 @@ * CPU instruction emulation this should prefer Y. * (see SPAMv9 B.2.2 section). */ -#define _FP_CHOOSENAN(fs, wc, R, X, Y) \ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ do { \ if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ diff -u --recursive --new-file v2.3.12/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c --- v2.3.12/linux/arch/sparc/mm/asyncd.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc/mm/asyncd.c Wed Aug 4 15:39:46 1999 @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.15 1999/07/04 04:35:50 davem Exp $ +/* $Id: asyncd.c,v 1.16 1999/08/04 03:19:16 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. @@ -271,3 +271,14 @@ } } +#if CONFIG_AP1000 + +static int __init init_ap1000(void) +{ + kernel_thread(asyncd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + return 0; +} + +module_init(init_ap1000) + +#endif diff -u --recursive --new-file v2.3.12/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- v2.3.12/linux/arch/sparc/mm/fault.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc/mm/fault.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.103 1999/07/04 04:35:51 davem Exp $ +/* $Id: fault.c,v 1.106 1999/07/30 09:35:07 davem Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -382,12 +382,13 @@ if(expand_stack(vma, address)) goto bad_area; good_area: - if(write) + if(write) { if(!(vma->vm_flags & VM_WRITE)) goto bad_area; - else + } else { if(!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; + } if (!handle_mm_fault(current, vma, address, write)) goto do_sigbus; up(&mm->mmap_sem); diff -u --recursive --new-file v2.3.12/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.3.12/linux/arch/sparc/mm/srmmu.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc/mm/srmmu.c Mon Aug 9 11:29:37 1999 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.187 1999/04/28 17:00:45 davem Exp $ +/* $Id: srmmu.c,v 1.190 1999/08/07 17:47:01 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -114,6 +114,7 @@ #define srmmu_ahashfn(addr) ((addr) >> 24) int viking_mxcc_present = 0; +static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; /* Physical memory can be _very_ non-contiguous on the sun4m, especially * the SS10/20 class machines and with the latest openprom revisions. @@ -819,7 +820,9 @@ static void srmmu_switch_to_context(struct task_struct *tsk) { if(tsk->mm->context == NO_CONTEXT) { + spin_lock(&srmmu_context_spinlock); alloc_context(tsk->mm); + spin_unlock(&srmmu_context_spinlock); ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd); } srmmu_set_context(tsk->mm->context); @@ -827,7 +830,9 @@ static void srmmu_init_new_context(struct mm_struct *mm) { + spin_lock(&srmmu_context_spinlock); alloc_context(mm); + spin_unlock(&srmmu_context_spinlock); flush_cache_mm(mm); ctxd_set(&srmmu_context_table[mm->context], mm->pgd); @@ -1398,7 +1403,9 @@ if(tsk->mm->context == NO_CONTEXT) { ctxd_t *ctxp; + spin_lock(&srmmu_context_spinlock); alloc_context(tsk->mm); + spin_unlock(&srmmu_context_spinlock); ctxp = &srmmu_context_table[tsk->mm->context]; srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4)))); hypersparc_flush_page_to_ram((unsigned long)ctxp); @@ -1411,7 +1418,9 @@ { ctxd_t *ctxp; + spin_lock(&srmmu_context_spinlock); alloc_context(mm); + spin_unlock(&srmmu_context_spinlock); ctxp = &srmmu_context_table[mm->context]; srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); diff -u --recursive --new-file v2.3.12/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.3.12/linux/arch/sparc/mm/sun4c.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc/mm/sun4c.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.173 1999/01/17 02:20:37 davem Exp $ +/* $Id: sun4c.c,v 1.175 1999/07/30 09:35:10 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile --- v2.3.12/linux/arch/sparc64/Makefile Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/Makefile Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.37 1999/06/04 13:29:10 jj Exp $ +# $Id: Makefile,v 1.38 1999/08/02 12:06:06 jj Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the @@ -15,7 +15,7 @@ CC := sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include CC_HAS_ARGS := $(shell if echo "$(CC)" | grep '\(__KERNEL__\| \)' > /dev/null; then echo y; else echo n; fi) -IS_EGCS := $(shell if $(CC) -c -m64 -mcmodel=medlow -o _tmp.o arch/sparc64/math-emu/fnegq.c >/dev/null 2>&1; then echo y; else echo n; fi; rm -f _tmp.o) +IS_EGCS := $(shell if $(CC) -c -m64 -mcmodel=medlow -o /dev/null /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) ifneq ($(CC_HAS_ARGS),y) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.12/linux/arch/sparc64/config.in Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/config.in Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.67 1999/05/01 09:17:37 davem Exp $ +# $Id: config.in,v 1.73 1999/08/06 12:11:47 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -36,6 +36,7 @@ # Global things across all Sun machines. define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y +define_bool CONFIG_MOUSE y define_bool CONFIG_SUN_MOUSE y define_bool CONFIG_SERIAL y define_bool CONFIG_SUN_SERIAL y @@ -105,7 +106,8 @@ dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE define_bool CONFIG_BLK_DEV_IDEPCI y define_bool CONFIG_BLK_DEV_IDEDMA y - define_bool CONFIG_IDEDMA_PCI_AUTO y + define_bool CONFIG_IDEDMA_AUTO y + define_bool IDEDMA_NEW_DRIVE_LISTINGS y define_bool CONFIG_BLK_DEV_NS87415 y define_bool CONFIG_BLK_DEV_CMD646 y fi diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.3.12/linux/arch/sparc64/defconfig Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/defconfig Fri Aug 6 11:58:00 1999 @@ -49,6 +49,7 @@ # CONFIG_FBCON_FONTS is not set CONFIG_SBUS=y CONFIG_SBUSCHAR=y +CONFIG_MOUSE=y CONFIG_SUN_MOUSE=y CONFIG_SERIAL=y CONFIG_SUN_SERIAL=y @@ -93,12 +94,13 @@ CONFIG_BINFMT_MISC=m CONFIG_SOLARIS_EMUL=m CONFIG_PARPORT=m -# CONFIG_PARPORT_PC is not set +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set # CONFIG_PARPORT_ATARI is not set # CONFIG_PARPORT_OTHER is not set -# CONFIG_PARPORT_1284 is not set +CONFIG_PARPORT_1284=y CONFIG_PRINTER=m CONFIG_ENVCTRL=m @@ -123,7 +125,8 @@ # CONFIG_BLK_DEV_IDESCSI is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_IDEDMA_AUTO=y +IDEDMA_NEW_DRIVE_LISTINGS=y CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_CMD646=y diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.3.12/linux/arch/sparc64/kernel/Makefile Wed Mar 10 16:53:37 1999 +++ linux/arch/sparc64/kernel/Makefile Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.43 1999/01/02 16:45:53 davem Exp $ +# $Id: Makefile,v 1.44 1999/08/02 12:05:53 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -61,12 +61,16 @@ check_asm: dummy @echo "/* Automatically generated. Do not edit. */" > asm_offsets.h @echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h - @echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h - @echo "" >> asm_offsets.h - @echo "#include " >> asm_offsets.h - @echo "" >> asm_offsets.h - @echo "#ifndef CONFIG_SMP" >> asm_offsets.h - @echo "" >> asm_offsets.h + @echo -e "#define __ASM_OFFSETS_H__\n" >> asm_offsets.h + @echo -e "#include \n" >> asm_offsets.h + @echo '#if defined(__KERNEL__) && !defined(__ASSEMBLY__)' >> asm_offsets.h + @if $(CC) -c -m64 -mcmodel=medlow -o /dev/null /dev/null >/dev/null 2>&1; then \ + echo '# if !((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))' >> asm_offsets.h; \ + else \ + echo '# if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)' >> asm_offsets.h; \ + fi + @echo -e "# error Please issue 'make check_asm' in linux top-level directory first\n# endif\n#endif\n" >> asm_offsets.h + @echo -e "#ifndef CONFIG_SMP\n" >> asm_offsets.h @echo "#include " > tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c @@ -92,11 +96,8 @@ # ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c - @echo "" >> asm_offsets.h - @echo "#else /* CONFIG_SMP */" >> asm_offsets.h - @echo "" >> asm_offsets.h - @echo "#ifndef SPIN_LOCK_DEBUG" >>asm_offsets.h - @echo "" >> asm_offsets.h + @echo -e "\n#else /* CONFIG_SMP */\n" >> asm_offsets.h + @echo -e "#ifndef SPIN_LOCK_DEBUG\n" >>asm_offsets.h @echo "#include " > tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @@ -124,9 +125,7 @@ # ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c - @echo "" >> asm_offsets.h - @echo "#else /* SPIN_LOCK_DEBUG */" >> asm_offsets.h - @echo "" >> asm_offsets.h + @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h @echo "#include " > tmp.c $(CC) -D__SMP__ -DSPIN_LOCK_DEBUG -E tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @@ -151,10 +150,8 @@ # ./check_asm >> asm_offsets.h @rm -f check_asm check_asm.c - @echo "#endif /* SPIN_LOCK_DEBUG */" >> asm_offsets.h - @echo "" >> asm_offsets.h - @echo "#endif /* CONFIG_SMP */" >> asm_offsets.h - @echo "" >> asm_offsets.h + @echo -e "#endif /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h + @echo -e "#endif /* CONFIG_SMP */\n" >> asm_offsets.h @echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h @if test -r $(HPATH)/asm/asm_offsets.h; then \ if cmp -s asm_offsets.h $(HPATH)/asm/asm_offsets.h; then \ diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c --- v2.3.12/linux/arch/sparc64/kernel/binfmt_aout32.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/kernel/binfmt_aout32.c Mon Aug 2 22:07:16 1999 @@ -339,6 +339,16 @@ current->mm->start_stack = (unsigned long) create_aout32_tables((char *)bprm->p, bprm); + if (!(current->thread.flags & SPARC_FLAG_32BIT)) { + unsigned long pgd_cache; + + pgd_cache = ((unsigned long)current->mm->pgd[0])<<11UL; + __asm__ __volatile__("stxa\t%0, [%1] %2" + : /* no outputs */ + : "r" (pgd_cache), + "r" (TSB_REG), "i" (ASI_DMMU)); + current->thread.flags |= SPARC_FLAG_32BIT; + } start_thread32(regs, ex.a_entry, current->mm->start_stack); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c --- v2.3.12/linux/arch/sparc64/kernel/binfmt_elf32.c Sun Oct 4 10:22:43 1998 +++ linux/arch/sparc64/kernel/binfmt_elf32.c Mon Aug 2 22:07:16 1999 @@ -142,7 +142,7 @@ #ifdef CONFIG_BINFMT_ELF32_MODULE #define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE #endif -#define ELF_FLAGS_INIT current->tss.flags |= SPARC_FLAG_32BIT +#define ELF_FLAGS_INIT current->thread.flags |= SPARC_FLAG_32BIT MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra"); MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek"); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c --- v2.3.12/linux/arch/sparc64/kernel/devices.c Tue May 11 08:24:31 1999 +++ linux/arch/sparc64/kernel/devices.c Mon Aug 2 22:07:16 1999 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,10 @@ int nd, prom_node_cpu, thismid; int cpu_nds[64]; /* One node for each cpu */ int cpu_ctr = 0; + + /* FIX ME FAST... -DaveM */ + ioport_resource.end = 0xffffffffffffffffUL; + iomem_resource.end = 0xffffffffffffffffUL; prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str)); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.3.12/linux/arch/sparc64/kernel/ebus.c Tue May 11 08:24:31 1999 +++ linux/arch/sparc64/kernel/ebus.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.36 1999/05/04 03:21:42 davem Exp $ +/* $Id: ebus.c,v 1.38 1999/08/06 10:37:32 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -17,6 +17,7 @@ #include #include #include +#include #undef PROM_DEBUG #undef DEBUG_FILL_EBUS_DEV @@ -56,9 +57,9 @@ return mem; } -__initfunc(void ebus_intmap_match(struct linux_ebus *ebus, - struct linux_prom_registers *reg, - int *interrupt)) +void __init ebus_intmap_match(struct linux_ebus *ebus, + struct linux_prom_registers *reg, + int *interrupt) { unsigned int hi, lo, irq; int i; @@ -83,8 +84,8 @@ prom_halt(); } -__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg, - struct linux_ebus_child *dev)) +void __init fill_ebus_child(int node, struct linux_prom_registers *preg, + struct linux_ebus_child *dev) { int regs[PROMREG_MAX]; int irqs[PROMREG_MAX]; @@ -135,10 +136,11 @@ } #ifdef DEBUG_FILL_EBUS_DEV - dprintf("child '%s': address%s\n", dev->prom_name, + dprintf("child '%s': address%s ", dev->prom_name, dev->num_addrs > 1 ? "es" : ""); for (i = 0; i < dev->num_addrs; i++) - dprintf(" %016lx\n", dev->base_address[i]); + dprintf("%016lx ", dev->base_address[i]); + dprintf("\n"); if (dev->num_irqs) { dprintf(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); for (i = 0; i < dev->num_irqs; i++) @@ -148,7 +150,7 @@ #endif } -__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) +void __init fill_ebus_device(int node, struct linux_ebus_device *dev) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; @@ -172,7 +174,7 @@ for (i = 0; i < dev->num_addrs; i++) { n = (regs[i].which_io - 0x10) >> 2; - dev->base_address[i] = dev->bus->self->base_address[n]; + dev->base_address[i] = dev->bus->self->resource[n].start; dev->base_address[i] += (unsigned long)regs[i].phys_addr; } @@ -189,10 +191,11 @@ } #ifdef DEBUG_FILL_EBUS_DEV - dprintf("'%s': address%s\n", dev->prom_name, + dprintf("'%s': address%s ", dev->prom_name, dev->num_addrs > 1 ? "es" : ""); for (i = 0; i < dev->num_addrs; i++) - dprintf(" %016lx\n", dev->base_address[i]); + dprintf("%016lx ", dev->base_address[i]); + dprintf("\n"); if (dev->num_irqs) { dprintf(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); for (i = 0; i < dev->num_irqs; i++) @@ -225,7 +228,7 @@ extern void clock_probe(void); -__initfunc(void ebus_init(void)) +void __init ebus_init(void) { struct linux_prom_pci_registers regs[PROMREG_MAX]; struct linux_pbm_info *pbm; @@ -234,7 +237,8 @@ struct pci_dev *pdev; struct pcidev_cookie *cookie; char lbuf[128]; - unsigned long addr, *base; + struct resource *base; + unsigned long addr; unsigned short pci_command; int nd, len, ebusnd; int reg, rng, nreg; @@ -317,7 +321,7 @@ } nreg = len / sizeof(struct linux_prom_pci_registers); - base = &ebus->self->base_address[0]; + base = &ebus->self->resource[0]; for (reg = 0; reg < nreg; reg++) { if (!(regs[reg].phys_hi & 0x03000000)) continue; @@ -334,7 +338,14 @@ addr += (u64)regs[reg].phys_mid << 32UL; addr += (u64)rp->parent_phys_lo; addr += (u64)rp->parent_phys_hi << 32UL; - *base++ = (unsigned long)__va(addr); + + base->name = "EBUS"; + base->start = (unsigned long)__va(addr); + base->end = base->start + regs[reg].size_lo - 1; + base->flags = 0; + request_resource(&ioport_resource, base); + + base += 1; printk(" %lx[%x]", (unsigned long)__va(addr), regs[reg].size_lo); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.3.12/linux/arch/sparc64/kernel/entry.S Tue May 11 08:24:31 1999 +++ linux/arch/sparc64/kernel/entry.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.103 1999/05/08 03:00:21 davem Exp $ +/* $Id: entry.S,v 1.106 1999/08/02 08:39:34 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -42,13 +42,13 @@ /* This is trivial with the new code... */ .globl do_fpdis do_fpdis: - ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g5 ! Load Group + ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g5 ! Load Group sethi %hi(TSTATE_PEF), %g4 ! IEU0 wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles andcc %g5, FPRS_FEF, %g0 ! IEU1 Group be,a,pt %icc, 1f ! CTI clr %g7 ! IEU0 - ldub [%g6 + AOFF_task_tss + AOFF_thread_gsr], %g7 ! Load Group + ldub [%g6 + AOFF_task_thread + AOFF_thread_gsr], %g7 ! Load Group 1: andcc %g5, FPRS_DL, %g0 ! IEU1 bne,pn %icc, 2f ! CTI fzero %f0 ! FPA @@ -157,7 +157,7 @@ flush %g6 fpdis_exit2: wr %g7, 0, %gsr - ldx [%g6 + AOFF_task_tss + AOFF_thread_xfsr], %fsr + ldx [%g6 + AOFF_task_thread + AOFF_thread_xfsr], %fsr rdpr %tstate, %g3 or %g3, %g4, %g3 ! anal... wrpr %g3, %tstate @@ -167,13 +167,13 @@ .globl do_fptrap .align 32 do_fptrap: - ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3 - stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr] + ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3 + stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr] rd %fprs, %g1 or %g3, %g1, %g3 - stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved] + stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved] rd %gsr, %g3 - stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_gsr] + stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr] mov SECONDARY_CONTEXT, %g3 add %g6, AOFF_task_fpregs, %g2 ldxa [%g3] ASI_DMMU, %g5 @@ -633,41 +633,28 @@ jmpl %g1, %g0 add %sp, STACK_BIAS + REGWIN_SZ, %o0 - .globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall + .globl sys_pipe, sys_sigpause, sys_nis_syscall .globl sys_sigsuspend, sys_rt_sigsuspend, sys32_rt_sigsuspend - .globl sys_sigreturn, sys_rt_sigreturn + .globl sys_rt_sigreturn .globl sys32_sigreturn, sys32_rt_sigreturn .globl sys32_execve, sys_ptrace .globl sys_sigaltstack, sys32_sigaltstack .globl sys32_sigstack .align 32 -sys_pipe: sethi %hi(sparc_pipe), %g1 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - jmpl %g1 + %lo(sparc_pipe), %g0 - nop -sys_nis_syscall:sethi %hi(c_sys_nis_syscall), %g1 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - jmpl %g1 + %lo(c_sys_nis_syscall), %g0 - nop - +sys_pipe: ba,pt %xcc, sparc_pipe + add %sp, STACK_BIAS + REGWIN_SZ, %o0 +sys_nis_syscall:ba,pt %xcc, c_sys_nis_syscall + add %sp, STACK_BIAS + REGWIN_SZ, %o0 sys_memory_ordering: - sethi %hi(sparc_memory_ordering), %g1 - add %sp, STACK_BIAS + REGWIN_SZ, %o1 - jmpl %g1 + %lo(sparc_memory_ordering), %g0 - nop -sys_sigaltstack:sethi %hi(do_sigaltstack), %g1 - add %i6, STACK_BIAS, %o2 - jmpl %g1 + %lo(do_sigaltstack), %g1 - nop -sys32_sigstack: sethi %hi(do_sys32_sigstack), %g1 - mov %i6, %o2 - jmpl %g1 + %lo(do_sys32_sigstack), %g1 - nop + ba,pt %xcc, sparc_memory_ordering + add %sp, STACK_BIAS + REGWIN_SZ, %o1 +sys_sigaltstack:ba,pt %xcc, do_sigaltstack + add %i6, STACK_BIAS, %o2 +sys32_sigstack: ba,pt %xcc, do_sys32_sigstack + mov %i6, %o2 sys32_sigaltstack: - sethi %hi(do_sys32_sigaltstack), %g1 - mov %i6, %o2 - jmpl %g1 + %lo(do_sys32_sigaltstack), %g1 - nop + ba,pt %xcc, do_sys32_sigaltstack + mov %i6, %o2 .align 32 sys_sigsuspend: add %sp, STACK_BIAS + REGWIN_SZ, %o0 @@ -689,10 +676,6 @@ call do_sigpause add %o7, 1f-.-4, %o7 nop -sys_sigreturn: add %sp, STACK_BIAS + REGWIN_SZ, %o0 - call do_sigreturn - add %o7, 1f-.-4, %o7 - nop sys32_sigreturn: add %sp, STACK_BIAS + REGWIN_SZ, %o0 call do_sigreturn32 @@ -761,38 +744,30 @@ ba,pt %xcc, do_fork add %sp, STACK_BIAS + REGWIN_SZ, %o2 ret_from_syscall: - /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves tss.flags in + /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in * %o7 for us. Check performance counter stuff too. */ -#ifdef __SMP__ - andn %o7, 0x100, %l0 + andn %o7, SPARC_FLAG_NEWCHILD, %l0 mov %g5, %o0 /* 'prev' */ call schedule_tail - sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags] -#else - andn %o7, 0x100, %l0 - sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags] -#endif - andcc %l0, 0x200, %g0 + stb %l0, [%g6 + AOFF_task_thread + AOFF_thread_flags] + andcc %l0, SPARC_FLAG_PERFCTR, %g0 be,pt %icc, 1f nop - ldx [%g6 + AOFF_task_tss + AOFF_thread_pcr_reg], %o7 + ldx [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7 wr %g0, %o7, %pcr wr %g0, %g0, %pic 1: b,pt %xcc, ret_sys_call ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0 sparc_exit: rdpr %otherwin, %g1 - rdpr %pstate, %g2 - wrpr %g2, PSTATE_IE, %pstate + wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate rdpr %cansave, %g3 add %g3, %g1, %g3 wrpr %g3, 0x0, %cansave wrpr %g0, 0x0, %otherwin - wrpr %g2, 0x0, %pstate - mov %o7, %l5 - sth %g0, [%g6 + AOFF_task_tss + AOFF_thread_w_saved] - call sys_exit - mov %l5, %o7 + wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate + ba,pt %xcc, sys_exit + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved] linux_sparc_ni_syscall: sethi %hi(sys_ni_syscall), %l7 diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S --- v2.3.12/linux/arch/sparc64/kernel/etrap.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/kernel/etrap.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.41 1999/05/25 16:53:09 jj Exp $ +/* $Id: etrap.S,v 1.42 1999/07/30 09:35:18 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -56,7 +56,7 @@ wrpr %g0, 0, %canrestore ! Single Group+4bubbles sll %g2, 3, %g2 ! IEU0 Group mov 1, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth] ! Store + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store wrpr %g3, 0, %otherwin ! Single Group+4bubbles wrpr %g2, 0, %wstate ! Single Group+4bubbles stxa %g0, [%l4] ASI_DMMU ! Store Group @@ -89,11 +89,11 @@ jmpl %l2 + 0x4, %g0 ! CTI Group mov %l6, %g6 ! IEU0 -3: ldub [%l6 + AOFF_task_tss + AOFF_thread_fpdepth], %l5 ! Load Group - add %l6, AOFF_task_tss + AOFF_thread_fpsaved + 1, %l4 ! IEU0 +3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group + add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0 srl %l5, 1, %l3 ! IEU0 Group add %l5, 2, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth] ! Store + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store ba,pt %xcc, 2b ! CTI stb %g0, [%l4 + %l3] ! Store Group diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.3.12/linux/arch/sparc64/kernel/ioctl32.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/ioctl32.c Mon Aug 9 11:29:37 1999 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.63 1999/06/09 04:56:14 davem Exp $ +/* $Id: ioctl32.c,v 1.66 1999/08/08 01:37:06 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -38,6 +38,7 @@ #include #include #include +#include #include /* Ugly hack. */ @@ -570,7 +571,7 @@ if(cmd == SIOCETHTOOL) len = sizeof(struct ethtool_cmd); if(cmd == SIOCGPPPVER) - len = strlen(PPP_VERSION) + 1; + len = strlen((char *)ifr.ifr_data) + 1; else if(cmd == SIOCGPPPCSTATS) len = sizeof(struct ppp_comp_stats); else @@ -2366,6 +2367,10 @@ case AUTOFS_IOC_PROTOVER: case AUTOFS_IOC_EXPIRE: + /* Raw devices */ + case RAW_SETBIND: + case RAW_GETBIND: + error = sys_ioctl (fd, cmd, arg); goto out; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.3.12/linux/arch/sparc64/kernel/process.c Wed Jun 30 13:38:19 1999 +++ linux/arch/sparc64/kernel/process.c Wed Aug 4 15:39:46 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.95 1999/06/28 08:48:51 davem Exp $ +/* $Id: process.c,v 1.99 1999/08/04 03:19:20 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -46,7 +46,7 @@ /* * the idle loop on a Sparc... ;) */ -asmlinkage int sys_idle(void) +int cpu_idle(void) { if (current->pid != 0) return -EPERM; @@ -77,7 +77,7 @@ */ #define idle_me_harder() (cpu_data[current->processor].idle_volume += 1) #define unidle_me() (cpu_data[current->processor].idle_volume = 0) -asmlinkage int cpu_idle(void) +int cpu_idle(void) { current->priority = 0; current->counter = -100; @@ -99,15 +99,6 @@ } } -asmlinkage int sys_idle(void) -{ - if(current->pid != 0) - return -EPERM; - - cpu_idle(); - return 0; -} - #endif extern char reboot_command []; @@ -189,7 +180,7 @@ struct reg_window r_w; mm_segment_t old_fs; - if ((regs->tstate & TSTATE_PRIV) || !(current->tss.flags & SPARC_FLAG_32BIT)) { + if ((regs->tstate & TSTATE_PRIV) || !(current->thread.flags & SPARC_FLAG_32BIT)) { __asm__ __volatile__ ("flushw"); rw = (struct reg_window *)(regs->u_regs[14] + STACK_BIAS); if (!(regs->tstate & TSTATE_PRIV)) { @@ -369,90 +360,96 @@ regs->u_regs[15]); } -void show_thread(struct thread_struct *tss) +void show_thread(struct thread_struct *thread) { int i; #if 0 - printk("kregs: 0x%016lx\n", (unsigned long)tss->kregs); - show_regs(tss->kregs); + printk("kregs: 0x%016lx\n", (unsigned long)thread->kregs); + show_regs(thread->kregs); #endif - printk("sig_address: 0x%016lx\n", tss->sig_address); - printk("sig_desc: 0x%016lx\n", tss->sig_desc); - printk("ksp: 0x%016lx\n", tss->ksp); + printk("sig_address: 0x%016lx\n", thread->sig_address); + printk("sig_desc: 0x%016lx\n", thread->sig_desc); + printk("ksp: 0x%016lx\n", thread->ksp); - if (tss->w_saved) { + if (thread->w_saved) { for (i = 0; i < NSWINS; i++) { - if (!tss->rwbuf_stkptrs[i]) + if (!thread->rwbuf_stkptrs[i]) continue; printk("reg_window[%d]:\n", i); - printk("stack ptr: 0x%016lx\n", tss->rwbuf_stkptrs[i]); + printk("stack ptr: 0x%016lx\n", thread->rwbuf_stkptrs[i]); } - printk("w_saved: 0x%04x\n", tss->w_saved); + printk("w_saved: 0x%04x\n", thread->w_saved); } - printk("flags: 0x%08x\n", tss->flags); - printk("current_ds: 0x%x\n", tss->current_ds.seg); + printk("flags: 0x%08x\n", thread->flags); + printk("current_ds: 0x%x\n", thread->current_ds.seg); } /* Free current thread data structures etc.. */ void exit_thread(void) { - if (current->tss.utraps) { - if (current->tss.utraps[0] < 2) - kfree (current->tss.utraps); + struct thread_struct *t = ¤t->thread; + + if (t->utraps) { + if (t->utraps[0] < 2) + kfree (t->utraps); else - current->tss.utraps[0]--; + t->utraps[0]--; } /* Turn off performance counters if on. */ - if (current->tss.flags & SPARC_FLAG_PERFCTR) { - current->tss.user_cntd0 = - current->tss.user_cntd1 = NULL; - current->tss.pcr_reg = 0; - current->tss.flags &= ~(SPARC_FLAG_PERFCTR); + if (t->flags & SPARC_FLAG_PERFCTR) { + t->user_cntd0 = t->user_cntd1 = NULL; + t->pcr_reg = 0; + t->flags &= ~(SPARC_FLAG_PERFCTR); write_pcr(0); } } void flush_thread(void) { - if (!(current->tss.flags & SPARC_FLAG_KTHREAD)) - flush_user_windows(); - current->tss.w_saved = 0; + struct thread_struct *t = ¤t->thread; + + if (current->mm) { + if (t->flags & SPARC_FLAG_32BIT) { + struct mm_struct *mm = current->mm; + pgd_t *pgd0 = &mm->pgd[0]; + unsigned long pgd_cache; + + if (pgd_none(*pgd0)) { + pmd_t *page = get_pmd_fast(); + if (!page) + (void) get_pmd_slow(pgd0, 0); + else + pgd_set(pgd0, page); + } + pgd_cache = pgd_val(*pgd0) << 11UL; + __asm__ __volatile__("stxa %0, [%1] %2" + : /* no outputs */ + : "r" (pgd_cache), + "r" (TSB_REG), + "i" (ASI_DMMU)); + } + } + t->w_saved = 0; /* Turn off performance counters if on. */ - if (current->tss.flags & SPARC_FLAG_PERFCTR) { - current->tss.user_cntd0 = - current->tss.user_cntd1 = NULL; - current->tss.pcr_reg = 0; - current->tss.flags &= ~(SPARC_FLAG_PERFCTR); + if (t->flags & SPARC_FLAG_PERFCTR) { + t->user_cntd0 = t->user_cntd1 = NULL; + t->pcr_reg = 0; + t->flags &= ~(SPARC_FLAG_PERFCTR); write_pcr(0); } - /* No new signal delivery by default. */ - current->tss.new_signal = 0; - current->tss.fpsaved[0] = 0; + /* Clear FPU register state. */ + t->fpsaved[0] = 0; - /* Now, this task is no longer a kernel thread. */ - current->tss.current_ds = USER_DS; - if(current->tss.flags & SPARC_FLAG_KTHREAD) { - current->tss.flags &= ~SPARC_FLAG_KTHREAD; + if (t->current_ds.seg != ASI_AIUS) + set_fs(USER_DS); - /* exec_mmap() set context to NO_CONTEXT, here is - * where we grab a new one. - */ - activate_context(current); - } - if (current->tss.flags & SPARC_FLAG_32BIT) - __asm__ __volatile__("stxa %%g0, [%0] %1" - : /* no outputs */ - : "r"(TSB_REG), "i"(ASI_DMMU)); - __cli(); - current->tss.ctx = current->mm->context & 0x3ff; - spitfire_set_secondary_context (current->tss.ctx); - __asm__ __volatile__("flush %g6"); - __sti(); + /* Init new signal delivery disposition. */ + t->flags &= ~SPARC_FLAG_NEWSIGNALS; } /* It's a bit more tricky when 64-bit tasks are involved... */ @@ -460,12 +457,7 @@ { unsigned long fp, distance, rval; - /* do_fork() grabs the parent semaphore, we must release it - * temporarily so we can build the child clone stack frame - * without deadlocking. - */ - up(¤t->mm->mmap_sem); - if(!(current->tss.flags & SPARC_FLAG_32BIT)) { + if(!(current->thread.flags & SPARC_FLAG_32BIT)) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window *)psp)->ins[6])); @@ -482,7 +474,7 @@ rval = (csp - distance); if(copy_in_user(rval, psp, distance)) rval = 0; - else if(current->tss.flags & SPARC_FLAG_32BIT) { + else if(current->thread.flags & SPARC_FLAG_32BIT) { if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) rval = 0; } else { @@ -492,47 +484,46 @@ else rval = rval - STACK_BIAS; } - down(¤t->mm->mmap_sem); return rval; } /* Standard stuff. */ static inline void shift_window_buffer(int first_win, int last_win, - struct thread_struct *tp) + struct thread_struct *t) { int i; for(i = first_win; i < last_win; i++) { - tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1]; - memcpy(&tp->reg_window[i], &tp->reg_window[i+1], + t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1]; + memcpy(&t->reg_window[i], &t->reg_window[i+1], sizeof(struct reg_window)); } } void synchronize_user_stack(void) { - struct thread_struct *tp = ¤t->tss; + struct thread_struct *t = ¤t->thread; unsigned long window; flush_user_windows(); - if((window = tp->w_saved) != 0) { + if((window = t->w_saved) != 0) { int winsize = REGWIN_SZ; int bias = 0; - if(tp->flags & SPARC_FLAG_32BIT) + if(t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; window -= 1; do { - unsigned long sp = (tp->rwbuf_stkptrs[window] + bias); - struct reg_window *rwin = &tp->reg_window[window]; + unsigned long sp = (t->rwbuf_stkptrs[window] + bias); + struct reg_window *rwin = &t->reg_window[window]; if(!copy_to_user((char *)sp, rwin, winsize)) { - shift_window_buffer(window, tp->w_saved - 1, tp); - tp->w_saved--; + shift_window_buffer(window, t->w_saved - 1, t); + t->w_saved--; } } while(window--); } @@ -540,28 +531,28 @@ void fault_in_user_windows(struct pt_regs *regs) { - struct thread_struct *tp = ¤t->tss; + struct thread_struct *t = ¤t->thread; unsigned long window; int winsize = REGWIN_SZ; int bias = 0; - if(tp->flags & SPARC_FLAG_32BIT) + if(t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; flush_user_windows(); - window = tp->w_saved; + window = t->w_saved; if(window != 0) { window -= 1; do { - unsigned long sp = (tp->rwbuf_stkptrs[window] + bias); - struct reg_window *rwin = &tp->reg_window[window]; + unsigned long sp = (t->rwbuf_stkptrs[window] + bias); + struct reg_window *rwin = &t->reg_window[window]; if(copy_to_user((char *)sp, rwin, winsize)) goto barf; } while(window--); } - current->tss.w_saved = 0; + t->w_saved = 0; return; barf: do_exit(SIGILL); @@ -582,65 +573,73 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, struct task_struct *p, struct pt_regs *regs) { + struct thread_struct *t = &p->thread; char *child_trap_frame; /* Calculate offset to stack_frame & pt_regs */ child_trap_frame = ((char *)p) + ((PAGE_SIZE << 1) - (TRACEREG_SZ+REGWIN_SZ)); memcpy(child_trap_frame, (((struct reg_window *)regs)-1), (TRACEREG_SZ+REGWIN_SZ)); - p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; - p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); - p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP; - p->tss.fpsaved[0] = 0; - p->mm->segments = (void *) 0; + t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; + t->flags |= SPARC_FLAG_NEWCHILD; + t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); + t->cwp = (regs->tstate + 1) & TSTATE_CWP; + t->fpsaved[0] = 0; if(regs->tstate & TSTATE_PRIV) { /* Special case, if we are spawning a kernel thread from * a userspace task (via KMOD, NFS, or similar) we must * disable performance counters in the child because the * address space and protection realm are changing. */ - if (current->tss.flags & SPARC_FLAG_PERFCTR) { - p->tss.user_cntd0 = - p->tss.user_cntd1 = NULL; - p->tss.pcr_reg = 0; - p->tss.flags &= ~(SPARC_FLAG_PERFCTR); + if (t->flags & SPARC_FLAG_PERFCTR) { + t->user_cntd0 = t->user_cntd1 = NULL; + t->pcr_reg = 0; + t->flags &= ~(SPARC_FLAG_PERFCTR); } - p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp; - p->tss.flags |= (SPARC_FLAG_KTHREAD | SPARC_FLAG_NEWCHILD); - p->tss.current_ds = KERNEL_DS; - p->tss.ctx = 0; - __asm__ __volatile__("flushw"); - memcpy((void *)(p->tss.ksp + STACK_BIAS), + t->kregs->u_regs[UREG_FP] = p->thread.ksp; + t->current_ds = KERNEL_DS; + flush_register_windows(); + memcpy((void *)(t->ksp + STACK_BIAS), (void *)(regs->u_regs[UREG_FP] + STACK_BIAS), sizeof(struct reg_window)); - p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p; + t->kregs->u_regs[UREG_G6] = (unsigned long) p; } else { - if(current->tss.flags & SPARC_FLAG_32BIT) { + if(t->flags & SPARC_FLAG_32BIT) { sp &= 0x00000000ffffffffUL; regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; } - p->tss.kregs->u_regs[UREG_FP] = sp; - p->tss.flags = (p->tss.flags & ~SPARC_FLAG_KTHREAD) | - SPARC_FLAG_NEWCHILD; - p->tss.current_ds = USER_DS; - p->tss.ctx = (p->mm->context & 0x3ff); + t->kregs->u_regs[UREG_FP] = sp; + t->current_ds = USER_DS; if (sp != regs->u_regs[UREG_FP]) { unsigned long csp; csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); if(!csp) return -EFAULT; - p->tss.kregs->u_regs[UREG_FP] = csp; + t->kregs->u_regs[UREG_FP] = csp; } - if (p->tss.utraps) - p->tss.utraps[0]++; + if (t->utraps) + t->utraps[0]++; } /* Set the return value for the child. */ - p->tss.kregs->u_regs[UREG_I0] = current->pid; - p->tss.kregs->u_regs[UREG_I1] = 1; + t->kregs->u_regs[UREG_I0] = current->pid; + t->kregs->u_regs[UREG_I1] = 1; /* Set the second return value for the parent. */ regs->u_regs[UREG_I1] = 0; +#if 0 + printk("\ncopy_thread: c(%p[mm(%p:%p)]) p(%p[mm(%p:%p)])\n", + current, current->mm, current->active_mm, + p, p->mm, p->active_mm); + printk("copy_thread: c MM_ctx(%016lx) MM_pgd(%016lx)\n", + (current->mm ? current->mm->context : 0), + (current->mm ? pgd_val(current->mm->pgd[0]) : 0)); + printk("copy_thread: p MM_ctx(%016lx) MM_pgd(%08x)\n", + (p->mm ? p->mm->context : 0), + (p->mm ? pgd_val(p->mm->pgd[0]) : 0)); + printk("copy_thread: c->flags(%x) p->flags(%x) ", + current->thread.flags, p->thread.flags); +#endif return 0; } @@ -703,10 +702,10 @@ dump->u_dsize &= ~(PAGE_SIZE - 1); first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1)); dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1); - memcpy(&dump->fpu.fpstatus.fregs.regs[0], ¤t->tss.float_regs[0], (sizeof(unsigned long) * 32)); - dump->fpu.fpstatus.fsr = current->tss.fsr; + memcpy(&dump->fpu.fpstatus.fregs.regs[0], ¤t->thread.float_regs[0], (sizeof(unsigned long) * 32)); + dump->fpu.fpstatus.fsr = current->thread.fsr; dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0; - dump->sigcode = current->tss.sig_desc; + dump->sigcode = current->thread.sig_desc; #endif } @@ -729,9 +728,9 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) { unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); - unsigned long fprs = current->tss.fpsaved[0]; + unsigned long fprs = current->thread.fpsaved[0]; - if ((current->tss.flags & SPARC_FLAG_32BIT) != 0) { + if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) { elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs; if (fprs & FPRS_DL) @@ -745,7 +744,7 @@ memset(&fpregs32->pr_q[0], 0, (sizeof(unsigned int) * 64)); if (fprs & FPRS_FEF) { - fpregs32->pr_fsr = (unsigned int) current->tss.xfsr[0]; + fpregs32->pr_fsr = (unsigned int) current->thread.xfsr[0]; fpregs32->pr_en = 1; } else { fpregs32->pr_fsr = 0; @@ -765,8 +764,8 @@ memset(&fpregs->pr_regs[16], 0, sizeof(unsigned int) * 32); if(fprs & FPRS_FEF) { - fpregs->pr_fsr = current->tss.xfsr[0]; - fpregs->pr_gsr = current->tss.gsr[0]; + fpregs->pr_fsr = current->thread.xfsr[0]; + fpregs->pr_gsr = current->thread.gsr[0]; } else { fpregs->pr_fsr = fpregs->pr_gsr = 0; } @@ -784,6 +783,8 @@ int error, base = 0; char *filename; + /* User register window flush is done by entry.S */ + /* Check for indirect call. */ if(regs->u_regs[UREG_G1] == 0) base = 1; @@ -798,8 +799,8 @@ putname(filename); if(!error) { fprs_write(0); - current->tss.xfsr[0] = 0; - current->tss.fpsaved[0] = 0; + current->thread.xfsr[0] = 0; + current->thread.fpsaved[0] = 0; regs->tstate &= ~TSTATE_PEF; } out: diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c --- v2.3.12/linux/arch/sparc64/kernel/psycho.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/psycho.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: psycho.c,v 1.86 1999/07/01 10:39:43 davem Exp $ +/* $Id: psycho.c,v 1.89 1999/08/06 10:37:35 davem Exp $ * psycho.c: Ultra/AX U2P PCI controller support. * * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu) @@ -808,6 +808,264 @@ } } +extern struct pci_bus pci_root; +extern struct pci_dev *pci_devices; +static struct pci_dev **pci_last_dev_p = &pci_devices; +extern int pci_reverse; + +extern void pci_namedevice(struct pci_dev *); + +static void __init sparc64_pci_read_bases(struct pci_dev *dev, unsigned int howmany) +{ + unsigned int reg; + u32 l; + + for(reg=0; reg < howmany; reg++) { + struct resource *res = dev->resource + reg; + unsigned long mask; + unsigned int newval, size; + + res->name = dev->name; + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l); + if (l == 0xffffffff) + continue; + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), 0xffffffff); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &newval); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), l); + + mask = PCI_BASE_ADDRESS_MEM_MASK; + if (l & PCI_BASE_ADDRESS_SPACE_IO) + mask = PCI_BASE_ADDRESS_IO_MASK; + + newval &= mask; + if (!newval) + continue; + + res->start = l & mask; + res->flags = l & ~mask; + + size = 1; + do { + size <<= 1; + } while (!(size & newval)); + + /* 64-bit memory? */ + if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) + == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { + unsigned int high; + reg++; + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &high); + if (high) + res->start |= ((unsigned long) high) << 32; + } + res->end = res->start + size - 1; + } +} + +static unsigned int __init sparc64_pci_scan_bus(struct pci_bus *bus) +{ + unsigned int devfn, l, max, class; + unsigned char cmd, irq, tmp, hdr_type, is_multi = 0; + struct pci_dev *dev, **bus_last; + struct pci_bus *child; + + bus_last = &bus->devices; + max = bus->secondary; + for (devfn = 0; devfn < 0xff; ++devfn) { + if (PCI_FUNC(devfn) && !is_multi) { + /* not a multi-function device */ + continue; + } + if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) + continue; + if (!PCI_FUNC(devfn)) + is_multi = hdr_type & 0x80; + + if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || + /* some broken boards return 0 if a slot is empty: */ + l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) + continue; + + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if(dev==NULL) + { + printk(KERN_ERR "pci: out of memory.\n"); + continue; + } + memset(dev, 0, sizeof(*dev)); + dev->bus = bus; + dev->devfn = devfn; + dev->vendor = l & 0xffff; + dev->device = (l >> 16) & 0xffff; + pci_namedevice(dev); + + /* non-destructively determine if device can be a master: */ + pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd); + pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); + pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &tmp); + dev->master = ((tmp & PCI_COMMAND_MASTER) != 0); + pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd); + + pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class); + class >>= 8; /* upper 3 bytes */ + dev->class = class; + class >>= 8; + dev->hdr_type = hdr_type; + + switch (hdr_type & 0x7f) { /* header type */ + case PCI_HEADER_TYPE_NORMAL: /* standard header */ + if (class == PCI_CLASS_BRIDGE_PCI) + goto bad; + /* + * If the card generates interrupts, read IRQ number + * (some architectures change it during pcibios_fixup()) + */ + pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); + if (irq) + pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); + dev->irq = irq; + sparc64_pci_read_bases(dev, 6); + pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); + dev->rom_address = (l == 0xffffffff) ? 0 : l; + break; + case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ + if (class != PCI_CLASS_BRIDGE_PCI) + goto bad; + sparc64_pci_read_bases(dev, 2); + pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); + dev->rom_address = (l == 0xffffffff) ? 0 : l; + break; + case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ + if (class != PCI_CLASS_BRIDGE_CARDBUS) + goto bad; + sparc64_pci_read_bases(dev, 1); + break; + default: /* unknown header */ + bad: + printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", + bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type); + continue; + } + + /* + * Put it into the global PCI device chain. It's used to + * find devices once everything is set up. + */ + if (!pci_reverse) { + *pci_last_dev_p = dev; + pci_last_dev_p = &dev->next; + } else { + dev->next = pci_devices; + pci_devices = dev; + } + + /* + * Now insert it into the list of devices held + * by the parent bus. + */ + *bus_last = dev; + bus_last = &dev->sibling; + } + + /* + * After performing arch-dependent fixup of the bus, look behind + * all PCI-to-PCI bridges on this bus. + */ + pcibios_fixup_bus(bus); + for(dev=bus->devices; dev; dev=dev->sibling) + /* + * If it's a bridge, scan the bus behind it. + */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + unsigned int buses; + unsigned int devfn = dev->devfn; + unsigned short cr; + + /* + * Insert it into the tree of buses. + */ + child = kmalloc(sizeof(*child), GFP_ATOMIC); + if(child==NULL) + { + printk(KERN_ERR "pci: out of memory for bridge.\n"); + continue; + } + memset(child, 0, sizeof(*child)); + child->next = bus->children; + bus->children = child; + child->self = dev; + child->parent = bus; + + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = ++max; + child->primary = bus->secondary; + child->subordinate = 0xff; + /* + * Clear all status bits and turn off memory, + * I/O and master enables. + */ + pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); + pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); + pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); + /* + * Read the existing primary/secondary/subordinate bus + * number configuration to determine if the PCI bridge + * has already been configured by the system. If so, + * do not modify the configuration, merely note it. + */ + pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); + if ((buses & 0xFFFFFF) != 0) + { + unsigned int cmax; + + child->primary = buses & 0xFF; + child->secondary = (buses >> 8) & 0xFF; + child->subordinate = (buses >> 16) & 0xFF; + child->number = child->secondary; + cmax = sparc64_pci_scan_bus(child); + if (cmax > max) max = cmax; + } + else + { + /* + * Configure the bus numbers for this bridge: + */ + buses &= 0xff000000; + buses |= + (((unsigned int)(child->primary) << 0) | + ((unsigned int)(child->secondary) << 8) | + ((unsigned int)(child->subordinate) << 16)); + pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); + /* + * Now we can scan all subordinate buses: + */ + max = sparc64_pci_scan_bus(child); + /* + * Set the subordinate bus number to its real + * value: + */ + child->subordinate = max; + buses = (buses & 0xff00ffff) + | ((unsigned int)(child->subordinate) << 16); + pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); + } + pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); + } + + /* + * We've scanned the bus and so we know all about what's on + * the other side of any bridges that may be on this bus plus + * any devices. + * + * Return how far we've got finding sub-buses. + */ + return max; +} + static void __init sabre_probe(struct linux_psycho *sabre) { struct pci_bus *pbus = sabre->pci_bus; @@ -816,7 +1074,7 @@ pbus->number = pbus->secondary = busno; pbus->sysdata = sabre; - pbus->subordinate = pci_scan_bus(pbus); + pbus->subordinate = sparc64_pci_scan_bus(pbus); busno = pbus->subordinate + 1; for(pbus = pbus->children; pbus; pbus = pbus->next) { @@ -847,7 +1105,7 @@ pbm_fixup_busno(pbm, busno); - pbus->subordinate = pci_scan_bus(pbus); + pbus->subordinate = sparc64_pci_scan_bus(pbus); /* * Set the maximum subordinate bus of this pbm. @@ -1159,7 +1417,7 @@ int bustype = (pregs[preg].phys_hi >> 24) & 0x3; int bsreg, brindex; unsigned int rtmp; - u64 pci_addr; + u64 pci_addr, pci_size; if(bustype == 0) { /* Config space cookie, nothing to do. */ @@ -1216,6 +1474,8 @@ /* Now construct UPA physical address. */ pci_addr = (((u64)pregs[preg].phys_mid) << 32UL); pci_addr |= (((u64)pregs[preg].phys_lo)); + pci_size = (((u64)pregs[preg].size_hi) << 32UL); + pci_size |= (((u64)pregs[preg].size_lo)); if(ap) { pci_addr += ((u64)ap->phys_lo); @@ -1224,12 +1484,12 @@ /* Final step, apply PBM range. */ for(rng = 0; rng < pbm->num_pbm_ranges; rng++) { - struct linux_prom_pci_ranges *rp = &pbm->pbm_ranges[rng]; - int space = (rp->child_phys_hi >> 24) & 3; + struct linux_prom_pci_ranges *rngp = &pbm->pbm_ranges[rng]; + int space = (rngp->child_phys_hi >> 24) & 3; if(space == bustype) { - pci_addr += ((u64)rp->parent_phys_lo); - pci_addr += (((u64)rp->parent_phys_hi) << 32UL); + pci_addr += ((u64)rngp->parent_phys_lo); + pci_addr += (((u64)rngp->parent_phys_hi) << 32UL); break; } } @@ -1246,15 +1506,31 @@ */ pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &rtmp); pci_write_config_dword(pdev, PCI_ROM_ADDRESS, rtmp & ~1); - } else - pdev->base_address[brindex] = (unsigned long)__va(pci_addr); - - /* Preserve I/O space bit. */ - if(bustype == 0x1) { - pdev->base_address[brindex] |= 1; - IO_seen = 1; } else { - MEM_seen = 1; + struct resource *root, *rp; + + rp = &pdev->resource[brindex]; + + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + (brindex * 4), &rtmp); + if (rtmp & 0x1) + rtmp &= 0x1; + else + rtmp &= 0xf; + + rp->name = pdev->name; + rp->start = (unsigned long)__va(pci_addr); + rp->end = rp->start + pci_size - 1; + + /* Keep track of what we've seen so far. */ + if(rtmp & 0x1) { + IO_seen = 1; + root = &ioport_resource; + } else { + MEM_seen = 1; + root = &iomem_resource; + } + rp->flags = rtmp; + request_resource(root, rp); } } @@ -1267,28 +1543,32 @@ int breg; for(breg = PCI_BASE_ADDRESS_0; breg <= PCI_BASE_ADDRESS_5; breg += 4) { + struct resource *rp; int io; ridx = ((breg - PCI_BASE_ADDRESS_0) >> 2); - base = (unsigned int)pdev->base_address[ridx]; + rp = &pdev->resource[ridx]; + base = (unsigned int)rp->start; - if(pdev->base_address[ridx] > PAGE_OFFSET) + /* Already handled? */ + if(rp->start > PAGE_OFFSET) continue; - io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; - base &= ~((io ? - PCI_BASE_ADDRESS_IO_MASK : - PCI_BASE_ADDRESS_MEM_MASK)); + pci_read_config_dword(pdev, breg, &rtmp); + io = (rtmp & 0x1); offset = (pdev->bus->number << 16) | (pdev->devfn << 8) | breg; vp = pci_find_vma(pbm, base, offset, io); if(!vp || vp->start > base) { unsigned int size, new_base; - pci_read_config_dword(pdev, breg, &rtmp); pci_write_config_dword(pdev, breg, 0xffffffff); pci_read_config_dword(pdev, breg, &size); + if(io) - size &= ~1; + size &= ~0x1; + else + size &= ~0xf; + size = (~(size) + 1); if(!size) continue; @@ -1332,17 +1612,17 @@ /* Apply PBM ranges and update pci_dev. */ pci_addr = new_base; for(rng = 0; rng < pbm->num_pbm_ranges; rng++) { - struct linux_prom_pci_ranges *rp; + struct linux_prom_pci_ranges *rngp; int rspace; - rp = &pbm->pbm_ranges[rng]; - rspace = (rp->child_phys_hi >> 24) & 3; + rngp = &pbm->pbm_ranges[rng]; + rspace = (rngp->child_phys_hi >> 24) & 3; if(io && rspace != 1) continue; else if(!io && rspace != 2) continue; - pci_addr += ((u64)rp->parent_phys_lo); - pci_addr += (((u64)rp->parent_phys_hi)<<32UL); + pci_addr += ((u64)rngp->parent_phys_lo); + pci_addr += (((u64)rngp->parent_phys_hi)<<32UL); break; } if(rng == pbm->num_pbm_ranges) { @@ -1350,14 +1630,19 @@ prom_printf("fixup_doit: YIEEE, cannot find " "PBM ranges\n"); } - pdev->base_address[ridx] = (unsigned long)__va(pci_addr); + rp->name = pdev->name; + rp->start = (unsigned long) __va(pci_addr); + rp->end = rp->start + size - 1; - /* Preserve I/O space bit. */ + /* Keep track of what we've seen so far. */ if(io) { - pdev->base_address[ridx] |= 1; IO_seen = 1; + rp->flags = rtmp & 0x1; + request_resource(&ioport_resource, rp); } else { MEM_seen = 1; + rp->flags = rtmp & 0xf; + request_resource(&iomem_resource, rp); } } } @@ -1420,15 +1705,15 @@ /* Apply PBM ranges and update pci_dev. */ pci_addr = new_base; for(rng = 0; rng < pbm->num_pbm_ranges; rng++) { - struct linux_prom_pci_ranges *rp; + struct linux_prom_pci_ranges *rngp; int rspace; - rp = &pbm->pbm_ranges[rng]; - rspace = (rp->child_phys_hi >> 24) & 3; + rngp = &pbm->pbm_ranges[rng]; + rspace = (rngp->child_phys_hi >> 24) & 3; if(rspace != 2) continue; - pci_addr += ((u64)rp->parent_phys_lo); - pci_addr += (((u64)rp->parent_phys_hi)<<32UL); + pci_addr += ((u64)rngp->parent_phys_lo); + pci_addr += (((u64)rngp->parent_phys_hi)<<32UL); break; } if(rng == pbm->num_pbm_ranges) { @@ -1471,8 +1756,8 @@ #ifdef FIXUP_REGS_DEBUG dprintf("REG_FIXUP[%04x,%04x]: ", pdev->vendor, pdev->device); for(preg = 0; preg < 6; preg++) { - if(pdev->base_address[preg] != 0) - dprintf("%d[%016lx] ", preg, pdev->base_address[preg]); + if(pdev->resource[preg].start != 0) + dprintf("%d[%016lx] ", preg, pdev->resource[preg].start); } dprintf("\n"); #endif @@ -2119,9 +2404,10 @@ static inline int sabre_out_of_range(unsigned char devfn) { - return ((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || - ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || - (PCI_SLOT(devfn) > 1); + return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || + ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || + (PCI_SLOT(devfn) > 1) || + (pci_probe_enable == 0)); } static int diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c --- v2.3.12/linux/arch/sparc64/kernel/ptrace.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/ptrace.c Mon Aug 2 22:07:16 1999 @@ -52,7 +52,7 @@ static inline void pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr) { - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { if(put_user(value, (unsigned int *)addr)) return pt_error_return(regs, EFAULT); } else { @@ -114,7 +114,7 @@ unsigned long addr2 = regs->u_regs[UREG_I4]; struct task_struct *child; - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { addr &= 0xffffffffUL; data &= 0xffffffffUL; addr2 &= 0xffffffffUL; @@ -220,7 +220,7 @@ goto out; } - if(!(child->tss.flags & SPARC_FLAG_32BIT) && + if(!(child->thread.flags & SPARC_FLAG_32BIT) && ((request == PTRACE_READDATA64) || (request == PTRACE_WRITEDATA64) || (request == PTRACE_READTEXT64) || @@ -242,7 +242,7 @@ int res, copied; res = -EIO; - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { copied = access_process_vm(child, addr, &tmp32, sizeof(tmp32), 0); tmp64 = (unsigned long) tmp32; @@ -267,7 +267,7 @@ unsigned int tmp32; int copied, res = -EIO; - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { tmp32 = data; copied = access_process_vm(child, addr, &tmp32, sizeof(tmp32), 1); @@ -289,7 +289,7 @@ case PTRACE_GETREGS: { struct pt_regs32 *pregs = (struct pt_regs32 *) addr; - struct pt_regs *cregs = child->tss.kregs; + struct pt_regs *cregs = child->thread.kregs; int rval; if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || @@ -313,7 +313,7 @@ case PTRACE_GETREGS64: { struct pt_regs *pregs = (struct pt_regs *) addr; - struct pt_regs *cregs = child->tss.kregs; + struct pt_regs *cregs = child->thread.kregs; int rval; if (__put_user(cregs->tstate, (&pregs->tstate)) || @@ -337,7 +337,7 @@ case PTRACE_SETREGS: { struct pt_regs32 *pregs = (struct pt_regs32 *) addr; - struct pt_regs *cregs = child->tss.kregs; + struct pt_regs *cregs = child->thread.kregs; unsigned int psr, pc, npc, y; int i; @@ -370,7 +370,7 @@ case PTRACE_SETREGS64: { struct pt_regs *pregs = (struct pt_regs *) addr; - struct pt_regs *cregs = child->tss.kregs; + struct pt_regs *cregs = child->thread.kregs; unsigned long tstate, tpc, tnpc, y; int i; @@ -418,7 +418,7 @@ if (copy_to_user(&fps->regs[0], fpregs, (32 * sizeof(unsigned int))) || - __put_user(child->tss.xfsr[0], (&fps->fsr)) || + __put_user(child->thread.xfsr[0], (&fps->fsr)) || __put_user(0, (&fps->fpqd)) || __put_user(0, (&fps->flags)) || __put_user(0, (&fps->extra)) || @@ -439,7 +439,7 @@ if (copy_to_user(&fps->regs[0], fpregs, (64 * sizeof(unsigned int))) || - __put_user(child->tss.xfsr[0], (&fps->fsr))) { + __put_user(child->thread.xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out; } @@ -468,11 +468,11 @@ pt_error_return(regs, EFAULT); goto out; } - child->tss.xfsr[0] &= 0xffffffff00000000UL; - child->tss.xfsr[0] |= fsr; - if (!(child->tss.fpsaved[0] & FPRS_FEF)) - child->tss.gsr[0] = 0; - child->tss.fpsaved[0] |= (FPRS_FEF | FPRS_DL); + child->thread.xfsr[0] &= 0xffffffff00000000UL; + child->thread.xfsr[0] |= fsr; + if (!(child->thread.fpsaved[0] & FPRS_FEF)) + child->thread.gsr[0] = 0; + child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL); pt_succ_return(regs, 0); goto out; } @@ -486,13 +486,13 @@ if (copy_from_user(fpregs, &fps->regs[0], (64 * sizeof(unsigned int))) || - __get_user(child->tss.xfsr[0], (&fps->fsr))) { + __get_user(child->thread.xfsr[0], (&fps->fsr))) { pt_error_return(regs, EFAULT); goto out; } - if (!(child->tss.fpsaved[0] & FPRS_FEF)) - child->tss.gsr[0] = 0; - child->tss.fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); + if (!(child->thread.fpsaved[0] & FPRS_FEF)) + child->thread.gsr[0] = 0; + child->thread.fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); pt_succ_return(regs, 0); goto out; } @@ -538,11 +538,11 @@ goto out; } #ifdef DEBUG_PTRACE - printk ("Original: %016lx %016lx\n", child->tss.kregs->tpc, child->tss.kregs->tnpc); + printk ("Original: %016lx %016lx\n", child->thread.kregs->tpc, child->thread.kregs->tnpc); printk ("Continuing with %016lx %016lx\n", addr, addr+4); #endif - child->tss.kregs->tpc = addr; - child->tss.kregs->tnpc = addr + 4; + child->thread.kregs->tpc = addr; + child->thread.kregs->tnpc = addr + 4; } if (request == PTRACE_SYSCALL) @@ -554,8 +554,8 @@ #ifdef DEBUG_PTRACE printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm, child->pid, child->exit_code, - child->tss.kregs->tpc, - child->tss.kregs->tnpc); + child->thread.kregs->tpc, + child->thread.kregs->tnpc); #endif wake_up_process(child); @@ -634,7 +634,7 @@ return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; - current->tss.flags ^= MAGIC_CONSTANT; + current->thread.flags ^= MAGIC_CONSTANT; notify_parent(current, SIGCHLD); schedule(); /* diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.3.12/linux/arch/sparc64/kernel/rtrap.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/kernel/rtrap.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.46 1999/05/25 16:53:20 jj Exp $ +/* $Id: rtrap.S,v 1.47 1999/07/30 09:35:23 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -11,6 +11,7 @@ #include #include #include +#include #define PTREGS_OFF (STACK_BIAS + REGWIN_SZ) @@ -39,13 +40,13 @@ be,pt %icc, to_user andn %l7, PSTATE_IE, %l7 - ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %l5 + ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 brz,pt %l5, rt_continue srl %l5, 1, %o0 - add %g6, AOFF_task_tss + AOFF_thread_fpsaved, %l6 + add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6 ldub [%l6 + %o0], %l2 sub %l5, 2, %l5 - add %g6, AOFF_task_tss + AOFF_thread_gsr, %o1 + add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1 andcc %l2, (FPRS_FEF|FPRS_DU), %g0 be,pt %icc, 2f and %l2, FPRS_DL, %l6 @@ -55,7 +56,7 @@ rd %fprs, %g5 wr %g5, FPRS_FEF, %fprs ldub [%o1 + %o0], %g5 - add %g6, AOFF_task_tss + AOFF_thread_xfsr, %o1 + add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1 membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 add %g6, AOFF_task_fpregs, %o3 @@ -71,9 +72,8 @@ ldda [%o4 + %o2] ASI_BLK_P, %f48 1: membar #Sync ldx [%o1 + %o5], %fsr -2: stb %l5, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] -rt_continue: lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 - ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 +2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] +rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 mov %g6, %o5 @@ -105,10 +105,11 @@ wrpr %o2, %g0, %tnpc brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 + ldxa [%l7 + %l7] ASI_DMMU, %l0 stxa %l0, [%l7] ASI_DMMU flush %o5 - rdpr %wstate, %l1 + rdpr %wstate, %l1 rdpr %otherwin, %l2 srl %l1, 3, %l1 wrpr %l2, %g0, %canrestore @@ -116,8 +117,8 @@ wrpr %g0, %g0, %otherwin restore rdpr %canrestore, %g1 - wrpr %g1, 0x0, %cleanwin + wrpr %g1, 0x0, %cleanwin retry kern_rtt: restore retry @@ -125,8 +126,8 @@ wrpr %l7, PSTATE_IE, %pstate orcc %g0, %l0, %g0 be,a,pt %xcc, check_signal - lduw [%g6 + AOFF_task_sigpending], %l0 + lduw [%g6 + AOFF_task_sigpending], %l0 call schedule nop lduw [%g6 + AOFF_task_sigpending], %l0 @@ -146,7 +147,7 @@ */ check_user_wins: wrpr %l7, 0x0, %pstate - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 brz,pt %o2, 1f sethi %hi(TSTATE_PEF), %l6 @@ -162,8 +163,8 @@ call rtrap_check add %sp, STACK_BIAS + REGWIN_SZ, %o0 #endif - lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %l5 - andcc %l5, 0x200, %g0 + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 + andcc %l5, SPARC_FLAG_PERFCTR, %g0 be,pt %xcc, 1f nop @@ -172,7 +173,7 @@ call update_perfctrs nop wrpr %l7, 0x0, %pstate - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 brz,pt %o2, 1f sethi %hi(TSTATE_PEF), %l6 wrpr %l7, PSTATE_IE, %pstate @@ -182,14 +183,14 @@ 1: andcc %l1, %l6, %g0 be,pt %xcc, rt_continue - stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only rd %fprs, %l5 andcc %l5, FPRS_FEF, %g0 be,a,pn %icc, rt_continue andn %l1, %l6, %l1 - ba,pt %xcc, rt_continue+4 - lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 + ba,pt %xcc, rt_continue + nop 5: wr %g0, FPRS_FEF, %fprs membar #StoreLoad | #LoadLoad @@ -201,6 +202,6 @@ 1: membar #Sync wr %g0, FPRS_DU, %fprs ba,pt %xcc, rt_continue - stb %l5, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] + stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] #undef PTREGS_OFF diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.3.12/linux/arch/sparc64/kernel/setup.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/kernel/setup.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.44 1999/05/28 02:17:29 davem Exp $ +/* $Id: setup.c,v 1.46 1999/08/02 08:39:36 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -135,17 +135,21 @@ * Find process owning ctx, lookup mapping. */ struct task_struct *p; + struct mm_struct *mm = NULL; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - for_each_task(p) - if (p->tss.ctx == ctx) + for_each_task(p) { + mm = p->mm; + if (CTX_HWBITS(mm->context) == ctx) break; - if (p->tss.ctx != ctx) + } + if (!mm || + CTX_HWBITS(mm->context) != ctx) goto done; - pgdp = pgd_offset(p->mm, va); + pgdp = pgd_offset(mm, va); if (pgd_none(*pgdp)) goto done; pmdp = pmd_offset(pgdp, va); @@ -534,8 +538,7 @@ init_mm.mmap->vm_page_prot = PAGE_SHARED; init_mm.mmap->vm_start = PAGE_OFFSET; init_mm.mmap->vm_end = *memory_end_p; - init_mm.context = (unsigned long) NO_CONTEXT; - init_task.tss.kregs = &fake_swapper_regs; + init_task.thread.kregs = &fake_swapper_regs; #ifdef CONFIG_IP_PNP if (!ic_set_manually) { diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.3.12/linux/arch/sparc64/kernel/signal.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/kernel/signal.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.41 1999/06/14 05:23:58 davem Exp $ +/* $Id: signal.c,v 1.44 1999/08/04 07:04:13 jj Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -46,7 +46,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) { struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0]; - struct thread_struct *tp = ¤t->tss; + struct thread_struct *tp = ¤t->thread; mc_gregset_t *grp; unsigned long pc, npc, tstate; unsigned long fp, i7; @@ -123,9 +123,9 @@ err |= copy_from_user(fpregs+16, ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16, (sizeof(unsigned int) * 32)); - err |= __get_user(current->tss.xfsr[0], + err |= __get_user(current->thread.xfsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); - err |= __get_user(current->tss.gsr[0], + err |= __get_user(current->thread.gsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); regs->tstate &= ~TSTATE_PEF; } @@ -141,7 +141,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs) { struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0]; - struct thread_struct *tp = ¤t->tss; + struct thread_struct *tp = ¤t->thread; mc_gregset_t *grp; mcontext_t *mcp; unsigned long fp, i7; @@ -155,7 +155,7 @@ #if 1 fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */ #else - fenab = (current->tss.fpsaved[0] & FPRS_FEF); + fenab = (current->thread.fpsaved[0] & FPRS_FEF); #endif mcp = &ucp->uc_mcontext; @@ -205,7 +205,7 @@ unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; - fprs = current->tss.fpsaved[0]; + fprs = current->thread.fpsaved[0]; if (fprs & FPRS_DL) err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs, (sizeof(unsigned int) * 32)); @@ -213,8 +213,8 @@ err |= copy_to_user( ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, (sizeof(unsigned int) * 32)); - err |= __put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); - err |= __put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); + err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); + err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); } if (err) @@ -226,34 +226,17 @@ do_exit(SIGSEGV); } -/* - * The new signal frame, intended to be used for Linux applications only - * (we have enough in there to work with clone). - * All the interesting bits are in the info field. - */ - -struct new_signal_frame { - struct sparc_stackf ss; - __siginfo_t info; - __siginfo_fpu_t * fpu_save; - unsigned int insns [2]; - unsigned long extramask[_NSIG_WORDS-1]; - __siginfo_fpu_t fpu_state; -}; - struct rt_signal_frame { struct sparc_stackf ss; - siginfo_t info; + siginfo_t info; struct pt_regs regs; - sigset_t mask; __siginfo_fpu_t * fpu_save; - unsigned int insns [2]; stack_t stack; + sigset_t mask; __siginfo_fpu_t fpu_state; }; /* Align macros */ -#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) /* @@ -265,7 +248,7 @@ sigset_t saveset; #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { extern asmlinkage void _sigpause32_common(old_sigset_t32, struct pt_regs *); _sigpause32_common(set, regs); @@ -372,65 +355,12 @@ if (fprs & FPRS_DU) err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32)); - err |= __get_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __get_user(current->tss.gsr[0], &fpu->si_gsr); - current->tss.fpsaved[0] |= fprs; + err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __get_user(current->thread.gsr[0], &fpu->si_gsr); + current->thread.fpsaved[0] |= fprs; return err; } -void do_sigreturn(struct pt_regs *regs) -{ - struct new_signal_frame *sf; - unsigned long tpc, tnpc, tstate; - __siginfo_fpu_t *fpu_save; - sigset_t set; - int err; - - synchronize_user_stack (); - sf = (struct new_signal_frame *) - (regs->u_regs [UREG_FP] + STACK_BIAS); - - /* 1. Make sure we are not getting garbage from the user */ - if (((unsigned long) sf) & 3) - goto segv; - - err = get_user(tpc, &sf->info.si_regs.tpc); - err |= __get_user(tnpc, &sf->info.si_regs.tnpc); - err |= ((tpc | tnpc) & 3); - - /* 2. Restore the state */ - err |= __get_user(regs->y, &sf->info.si_regs.y); - err |= __get_user(tstate, &sf->info.si_regs.tstate); - err |= copy_from_user(regs->u_regs, sf->info.si_regs.u_regs, sizeof(regs->u_regs)); - - /* User can only change condition codes in %tstate. */ - regs->tstate &= ~(TSTATE_ICC); - regs->tstate |= (tstate & TSTATE_ICC); - - err |= __get_user(fpu_save, &sf->fpu_save); - if (fpu_save) - err |= restore_fpu_state(regs, &sf->fpu_state); - - err |= __get_user(set.sig[0], &sf->info.si_mask); - if (_NSIG_WORDS > 1) - err |= __copy_from_user(&set.sig[1], &sf->extramask, sizeof(sf->extramask)); - - if (err) - goto segv; - - regs->tpc = tpc; - regs->tnpc = tnpc; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); - current->blocked = set; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - return; -segv: - send_sig(SIGSEGV, current, 1); -} - void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame *sf; @@ -503,15 +433,15 @@ unsigned long fprs; int err = 0; - fprs = current->tss.fpsaved[0]; + fprs = current->thread.fpsaved[0]; if (fprs & FPRS_DL) err |= copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, (sizeof(unsigned int) * 32)); - err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __put_user(current->tss.gsr[0], &fpu->si_gsr); + err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __put_user(current->thread.gsr[0], &fpu->si_gsr); err |= __put_user(fprs, &fpu->si_fprs); return err; @@ -533,77 +463,6 @@ } static inline void -new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) -{ - struct new_signal_frame *sf; - int sigframe_size, err; - - /* 1. Make sure everything is clean */ - synchronize_user_stack(); - save_and_clear_fpu(); - - sigframe_size = NF_ALIGNEDSZ; - - if (!(current->tss.fpsaved[0] & FPRS_FEF)) - sigframe_size -= sizeof(__siginfo_fpu_t); - - sf = (struct new_signal_frame *)get_sigframe(ka, regs, sigframe_size); - - if (invalid_frame_pointer (sf, sigframe_size)) - goto sigill; - - if (current->tss.w_saved != 0) { -#ifdef DEBUG_SIGNALS - printk ("%s[%d]: Invalid user stack frame for " - "signal delivery.\n", current->comm, current->pid); -#endif - goto sigill; - } - - /* 2. Save the current process state */ - err = copy_to_user(&sf->info.si_regs, regs, sizeof (*regs)); - - if (current->tss.fpsaved[0] & FPRS_FEF) { - err |= save_fpu_state(regs, &sf->fpu_state); - err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); - } else { - err |= __put_user(0, &sf->fpu_save); - } - - err |= __put_user(oldset->sig[0], &sf->info.si_mask); - if (_NSIG_WORDS > 1) - err |= __copy_to_user(sf->extramask, &oldset->sig[1], - sizeof(sf->extramask)); - - err |= copy_in_user((u64 *)sf, - (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), - sizeof(struct reg_window)); - if (err) - goto sigsegv; - - /* 3. signal handler back-trampoline and parameters */ - regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; - regs->u_regs[UREG_I0] = signo; - regs->u_regs[UREG_I1] = (unsigned long) &sf->info; - - /* 5. signal handler */ - regs->tpc = (unsigned long) ka->sa.sa_handler; - regs->tnpc = (regs->tpc + 4); - - /* 4. return to kernel instructions */ - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - return; - -sigill: - lock_kernel(); - do_exit(SIGILL); -sigsegv: - lock_kernel(); - do_exit(SIGSEGV); -} - -static inline void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { @@ -615,7 +474,7 @@ save_and_clear_fpu(); sigframe_size = RT_ALIGNEDSZ; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) + if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct rt_signal_frame *)get_sigframe(ka, regs, sigframe_size); @@ -623,7 +482,7 @@ if (invalid_frame_pointer (sf, sigframe_size)) goto sigill; - if (current->tss.w_saved != 0) { + if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); @@ -634,7 +493,7 @@ /* 2. Save the current process state */ err = copy_to_user(&sf->regs, regs, sizeof (*regs)); - if (current->tss.fpsaved[0] & FPRS_FEF) { + if (current->thread.fpsaved[0] & FPRS_FEF) { err |= save_fpu_state(regs, &sf->fpu_state); err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { @@ -652,7 +511,12 @@ (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), sizeof(struct reg_window)); - err |= copy_to_user(&sf->info, info, sizeof(siginfo_t)); + if (info) + err |= copy_to_user(&sf->info, info, sizeof(siginfo_t)); + else { + err |= __put_user(signo, &sf->info.si_signo); + err |= __put_user(SI_NOINFO, &sf->info.si_code); + } if (err) goto sigsegv; @@ -681,10 +545,7 @@ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - if(ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, signr, oldset, info); - else - new_setup_frame(ka, regs, signr, oldset); + setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); if(ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; if(!(ka->sa.sa_flags & SA_NOMASK)) { @@ -785,7 +646,7 @@ oldset = ¤t->blocked; #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *, unsigned long, int); return do_signal32(oldset, regs, orig_i0, restart_syscall); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.3.12/linux/arch/sparc64/kernel/signal32.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/kernel/signal32.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.48 1999/06/14 05:24:01 davem Exp $ +/* $Id: signal32.c,v 1.50 1999/07/30 09:35:25 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -202,9 +202,9 @@ err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32)); - err |= __get_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __get_user(current->tss.gsr[0], &fpu->si_gsr); - current->tss.fpsaved[0] |= fprs; + err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __get_user(current->thread.gsr[0], &fpu->si_gsr); + current->thread.fpsaved[0] |= fprs; return err; } @@ -285,7 +285,7 @@ int err; synchronize_user_stack(); - if (current->tss.new_signal) + if (current->thread.flags & SPARC_FLAG_NEWSIGNALS) return do_new_sigreturn32(regs); scptr = (struct sigcontext32 *) @@ -489,20 +489,20 @@ err |= __put_user(pc, &sc->sigc_pc); err |= __put_user(npc, &sc->sigc_npc); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sc->sigc_psr); err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - err |= __put_user(current->tss.w_saved, &sc->sigc_oswins); + err |= __put_user(current->thread.w_saved, &sc->sigc_oswins); #if 0 /* w_saved is not currently used... */ - if(current->tss.w_saved) - for(window = 0; window < current->tss.w_saved; window++) { + if(current->thread.w_saved) + for(window = 0; window < current->thread.w_saved; window++) { sc->sigc_spbuf[window] = - (char *)current->tss.rwbuf_stkptrs[window]; + (char *)current->thread.rwbuf_stkptrs[window]; err |= copy_to_user(&sc->sigc_wbuf[window], - ¤t->tss.reg_window[window], + ¤t->thread.reg_window[window], sizeof(struct reg_window)); } else @@ -511,15 +511,15 @@ (u32 *)(regs->u_regs[UREG_FP]), sizeof(struct reg_window32)); - current->tss.w_saved = 0; /* So process is allowed to execute. */ + current->thread.w_saved = 0; /* So process is allowed to execute. */ err |= __put_user(signr, &sframep->sig_num); if(signr == SIGSEGV || signr == SIGILL || signr == SIGFPE || signr == SIGBUS || signr == SIGEMT) { - err |= __put_user(current->tss.sig_desc, &sframep->sig_code); - err |= __put_user(current->tss.sig_address, &sframep->sig_address); + err |= __put_user(current->thread.sig_desc, &sframep->sig_code); + err |= __put_user(current->thread.sig_address, &sframep->sig_address); } else { err |= __put_user(0, &sframep->sig_code); err |= __put_user(0, &sframep->sig_address); @@ -544,15 +544,15 @@ unsigned long fprs; int err = 0; - fprs = current->tss.fpsaved[0]; + fprs = current->thread.fpsaved[0]; if (fprs & FPRS_DL) err |= copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16, (sizeof(unsigned int) * 32)); - err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr); - err |= __put_user(current->tss.gsr[0], &fpu->si_gsr); + err |= __put_user(current->thread.xfsr[0], &fpu->si_fsr); + err |= __put_user(current->thread.gsr[0], &fpu->si_gsr); err |= __put_user(fprs, &fpu->si_fprs); return err; @@ -572,7 +572,7 @@ save_and_clear_fpu(); sigframe_size = NF_ALIGNEDSZ; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) + if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct new_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size); @@ -585,7 +585,7 @@ goto sigill; } - if (current->tss.w_saved != 0) { + if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); @@ -598,7 +598,7 @@ err |= __put_user(regs->tnpc, &sf->info.si_regs.npc); err |= __put_user(regs->y, &sf->info.si_regs.y); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sf->info.si_regs.psr); for (i = 0; i < 16; i++) @@ -738,7 +738,7 @@ err |= __put_user(regs->tpc, &((*gr) [SVR4_PC])); err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC])); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &((*gr) [SVR4_PSR])); err |= __put_user(regs->y, &((*gr) [SVR4_Y])); @@ -760,7 +760,7 @@ err |= __put_user((u32)(long)gw, &mc->gwin); /* 2. Number of windows to restore at setcontext (): */ - err |= __put_user(current->tss.w_saved, &gw->count); + err |= __put_user(current->thread.w_saved, &gw->count); /* 3. Save each valid window * Currently, it makes a copy of the windows from the kernel copy. @@ -774,23 +774,23 @@ * to flush the user windows. */ #if 0 - for(window = 0; window < current->tss.w_saved; window++) { + for(window = 0; window < current->thread.w_saved; window++) { err |= __put_user((int *) &(gw->win [window]), (int **)gw->winptr +window ); err |= copy_to_user(&gw->win [window], - ¤t->tss.reg_window [window], + ¤t->thread.reg_window [window], sizeof (svr4_rwindow_t)); err |= __put_user(0, (int *)gw->winptr + window); } #endif /* 4. We just pay attention to the gw->count field on setcontext */ - current->tss.w_saved = 0; /* So process is allowed to execute. */ + current->thread.w_saved = 0; /* So process is allowed to execute. */ /* Setup the signal information. Solaris expects a bunch of * information to be passed to the signal handler, we don't provide * that much currently, should use those that David already - * is providing with tss.sig_desc + * is providing with thread.sig_desc */ err |= __put_user(signr, &si->siginfo.signo); err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); @@ -837,8 +837,8 @@ synchronize_user_stack(); save_and_clear_fpu(); - if (current->tss.w_saved){ - printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->tss.w_saved); + if (current->thread.w_saved){ + printk ("Uh oh, w_saved is not zero (%d)\n", (int) current->thread.w_saved); do_exit (SIGSEGV); } err = clear_user(uc, sizeof (*uc)); @@ -863,7 +863,7 @@ err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]); #else i = tstate_to_psr(regs->tstate) & ~PSR_EF; - if (current->tss.fpsaved[0] & FPRS_FEF) + if (current->thread.fpsaved[0] & FPRS_FEF) i |= PSR_EF; err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]); #endif @@ -890,7 +890,7 @@ /* Set the context for a svr4 application, this is Solaris way to sigreturn */ asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs) { - struct thread_struct *tp = ¤t->tss; + struct thread_struct *tp = ¤t->thread; svr4_gregset_t *gr; u32 pc, npc, psr; sigset_t set; @@ -990,7 +990,7 @@ save_and_clear_fpu(); sigframe_size = RT_ALIGNEDSZ; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) + if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct rt_signal_frame32 *)get_sigframe(&ka->sa, regs, sigframe_size); @@ -1003,7 +1003,7 @@ goto sigill; } - if (current->tss.w_saved != 0) { + if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); @@ -1016,7 +1016,7 @@ err |= __put_user(regs->tnpc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); psr = tstate_to_psr (regs->tstate); - if(current->tss.fpsaved[0] & FPRS_FEF) + if(current->thread.fpsaved[0] & FPRS_FEF) psr |= PSR_EF; err |= __put_user(psr, &sf->regs.psr); for (i = 0; i < 16; i++) @@ -1032,6 +1032,42 @@ } else { err |= __put_user(0, &sf->fpu_save); } + + err = __put_user (info->si_signo, &sf->info.si_signo); + err |= __put_user (info->si_errno, &sf->info.si_errno); + err |= __put_user (info->si_code, &sf->info.si_code); + if (info->si_code < 0) + err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE); + else { + i = info->si_signo; + if (info->si_code == SI_USER) + i = SIGRTMIN; + switch (i) { + case SIGPOLL: + err |= __put_user (info->si_band, &sf->info.si_band); + err |= __put_user (info->si_fd, &sf->info.si_fd); + break; + case SIGCHLD: + err |= __put_user (info->si_pid, &sf->info.si_pid); + err |= __put_user (info->si_uid, &sf->info.si_uid); + err |= __put_user (info->si_status, &sf->info.si_status); + err |= __put_user (info->si_utime, &sf->info.si_utime); + err |= __put_user (info->si_stime, &sf->info.si_stime); + break; + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: + case SIGEMT: + err |= __put_user ((long)info->si_addr, &sf->info.si_addr); + err |= __put_user (info->si_trapno, &sf->info.si_trapno); + break; + default: + err |= __put_user (info->si_pid, &sf->info.si_pid); + err |= __put_user (info->si_uid, &sf->info.si_uid); + break; + } + } /* Setup sigaltstack */ err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); @@ -1040,13 +1076,13 @@ switch (_NSIG_WORDS) { case 4: seta.sig[7] = (oldset->sig[3] >> 32); - seta.sig[6] = oldset->sig[3]; + seta.sig[6] = oldset->sig[3]; case 3: seta.sig[5] = (oldset->sig[2] >> 32); - seta.sig[4] = oldset->sig[2]; + seta.sig[4] = oldset->sig[2]; case 2: seta.sig[3] = (oldset->sig[1] >> 32); - seta.sig[2] = oldset->sig[1]; + seta.sig[2] = oldset->sig[1]; case 1: seta.sig[1] = (oldset->sig[0] >> 32); - seta.sig[0] = oldset->sig[0]; + seta.sig[0] = oldset->sig[0]; } err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t)); @@ -1113,7 +1149,7 @@ else { if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(ka, regs, signr, oldset, info); - else if (current->tss.new_signal) + else if (current->thread.flags & SPARC_FLAG_NEWSIGNALS) new_setup_frame32(ka, regs, signr, oldset); else setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset); @@ -1256,13 +1292,13 @@ if(signr != SIGCHLD) continue; - /* sys_wait4() grabs the master kernel lock, so - * we need not do so, that sucker should be - * threaded and would not be that difficult to - * do anyways. - */ - while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - ; + /* sys_wait4() grabs the master kernel lock, so + * we need not do so, that sucker should be + * threaded and would not be that difficult to + * do anyways. + */ + while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + ; continue; } if(ka->sa.sa_handler == SIG_DFL) { @@ -1312,10 +1348,10 @@ { struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff); unsigned int ins[8]; - + while(rw && !(((unsigned long) rw) & 0x3)) { - copy_from_user(ins, &rw->ins[0], sizeof(ins)); + copy_from_user(ins, &rw->ins[0], sizeof(ins)); printk("Caller[%08x](%08x,%08x,%08x,%08x,%08x,%08x)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]); rw = (struct reg_window32 *)(unsigned long)ins[6]; } @@ -1374,7 +1410,7 @@ /* Now see if we want to update the new state. */ if (ssptr) { void *ss_sp; - + if (get_user((long)ss_sp, &ssptr->the_stack)) goto out; /* If the current stack was set with sigaltstack, don't diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.3.12/linux/arch/sparc64/kernel/smp.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/smp.c Mon Aug 2 22:07:16 1999 @@ -53,7 +53,7 @@ int smp_num_cpus = 1; int smp_threads_ready = 0; -__initfunc(void smp_setup(char *str, int *ints)) +void __init smp_setup(char *str, int *ints) { /* XXX implement me XXX */ } @@ -151,13 +151,17 @@ /* Clear this or we will die instantly when we * schedule back to this idler... */ - current->tss.flags &= ~(SPARC_FLAG_NEWCHILD); + current->thread.flags &= ~(SPARC_FLAG_NEWCHILD); + + /* Attach to the address space of init_task. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; while(!smp_processors_ready) membar("#LoadLoad"); } -extern int cpu_idle(void *unused); +extern int cpu_idle(void); extern void init_IRQ(void); void initialize_secondary(void) @@ -169,7 +173,7 @@ trap_init(); init_IRQ(); smp_callin(); - return cpu_idle(NULL); + return cpu_idle(); } void cpu_panic(void) @@ -216,9 +220,17 @@ entry += phys_base - KERNBASE; cookie += phys_base - KERNBASE; kernel_thread(start_secondary, NULL, CLONE_PID); - p = task[++cpucount]; + cpucount++; + + p = init_task.prev_task; + init_tasks[cpucount] = p; + p->processor = i; p->has_cpu = 1; /* we schedule the first task manually */ + + del_from_runqueue(p); + unhash_process(p); + callin_flag = 0; for (no = 0; no < linux_num_cpus; no++) if (linux_cpus[no].mid == i) @@ -384,6 +396,9 @@ * are flush_tlb_*() routines, and these run after flush_cache_*() * which performs the flushw. * + * XXX I diked out the fancy flush avoidance code for the + * XXX swapping cases for now until the new MM code stabilizes. -DaveM + * * The SMP TLB coherency scheme we use works as follows: * * 1) mm->cpu_vm_mask is a bit mask of which cpus an address @@ -395,16 +410,16 @@ * cross calls. * * One invariant is that when a cpu switches to a process, and - * that processes tsk->mm->cpu_vm_mask does not have the current - * cpu's bit set, that tlb context is flushed locally. + * that processes tsk->active_mm->cpu_vm_mask does not have the + * current cpu's bit set, that tlb context is flushed locally. * * If the address space is non-shared (ie. mm->count == 1) we avoid * cross calls when we want to flush the currently running process's * tlb state. This is done by clearing all cpu bits except the current - * processor's in current->mm->cpu_vm_mask and performing the flush - * locally only. This will force any subsequent cpus which run this - * task to flush the context from the local tlb if the process migrates - * to another cpu (again). + * processor's in current->active_mm->cpu_vm_mask and performing the + * flush locally only. This will force any subsequent cpus which run + * this task to flush the context from the local tlb if the process + * migrates to another cpu (again). * * 3) For shared address spaces (threads) and swapping we bite the * bullet for most cases and perform the cross call. @@ -422,13 +437,13 @@ */ void smp_flush_tlb_mm(struct mm_struct *mm) { - u32 ctx = mm->context & 0x3ff; + u32 ctx = CTX_HWBITS(mm->context); - if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - mm->cpu_vm_mask = (1UL << smp_processor_id()); + if (mm == current->active_mm && + atomic_read(&mm->mm_users) == 1 && + (mm->cpu_vm_mask == (1UL << smp_processor_id()))) goto local_flush_and_out; - } + smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); local_flush_and_out: @@ -438,15 +453,15 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - u32 ctx = mm->context & 0x3ff; + u32 ctx = CTX_HWBITS(mm->context); start &= PAGE_MASK; end &= PAGE_MASK; - if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - mm->cpu_vm_mask = (1UL << smp_processor_id()); + if(mm == current->active_mm && + atomic_read(&mm->mm_users) == 1 && + (mm->cpu_vm_mask == (1UL << smp_processor_id()))) goto local_flush_and_out; - } + smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); local_flush_and_out: @@ -455,30 +470,15 @@ void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - u32 ctx = mm->context & 0x3ff; + u32 ctx = CTX_HWBITS(mm->context); page &= PAGE_MASK; - if(mm == current->mm && atomic_read(&mm->count) == 1) { - if(mm->cpu_vm_mask != (1UL << smp_processor_id())) - mm->cpu_vm_mask = (1UL << smp_processor_id()); + if(mm == current->active_mm && + atomic_read(&mm->mm_users) == 1 && + (mm->cpu_vm_mask == (1UL << smp_processor_id()))) { goto local_flush_and_out; - } else { - /* Try to handle two special cases to avoid cross calls - * in common scenerios where we are swapping process - * pages out. - */ - if(((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK) || - (mm->cpu_vm_mask == 0)) { - /* A dead context cannot ever become "alive" until - * a task switch is done to it. - */ - return; /* It's dead, nothing to do. */ - } - if(mm->cpu_vm_mask == (1UL << smp_processor_id())) { - __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); - return; /* Only local flush is necessary. */ - } } + smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); local_flush_and_out: diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.3.12/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.60 1999/07/03 22:11:12 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.62 1999/08/06 01:42:48 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -215,7 +215,6 @@ /* Kernel thread creation. */ EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(init_mm); /* prom symbols */ EXPORT_SYMBOL(idprom); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.3.12/linux/arch/sparc64/kernel/sys_sparc.c Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/kernel/sys_sparc.c Fri Aug 6 11:58:00 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.27 1999/06/02 12:06:34 jj Exp $ +/* $Id: sys_sparc.c,v 1.29 1999/08/04 07:04:10 jj Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -41,7 +41,9 @@ asmlinkage unsigned long sparc_brk(unsigned long brk) { - if(brk >= 0x80000000000UL) /* VM hole */ + if((brk >= 0x80000000000UL && brk < PAGE_OFFSET) || + (brk - current->mm->brk > 0x80000000000UL && + brk - current->mm->brk < PAGE_OFFSET)) /* VM hole */ return current->mm->brk; return sys_brk(brk); } @@ -170,7 +172,7 @@ } retval = -EINVAL; - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { if (len > 0xf0000000UL || addr > 0xf0000000UL - len) goto out_putf; } else { @@ -178,7 +180,7 @@ (addr < 0x80000000000UL && addr > 0x80000000000UL-len)) goto out_putf; - if (addr >= 0x80000000000ULL && addr < 0xfffff80000000000UL) { + if (addr >= 0x80000000000UL && addr < PAGE_OFFSET) { /* VM hole */ retval = current->mm->brk; goto out_putf; @@ -281,40 +283,40 @@ return -EINVAL; if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) { if (old_p) { - if (!current->tss.utraps) + if (!current->thread.utraps) put_user_ret(NULL, old_p, -EFAULT); else - put_user_ret((utrap_handler_t)(current->tss.utraps[type]), old_p, -EFAULT); + put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT); } if (old_d) put_user_ret(NULL, old_d, -EFAULT); return 0; } lock_kernel(); - if (!current->tss.utraps) { - current->tss.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); - if (!current->tss.utraps) return -ENOMEM; - current->tss.utraps[0] = 1; - memset(current->tss.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long)); + if (!current->thread.utraps) { + current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + if (!current->thread.utraps) return -ENOMEM; + current->thread.utraps[0] = 1; + memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long)); } else { - if ((utrap_handler_t)current->tss.utraps[type] != new_p && current->tss.utraps[0] > 1) { - long *p = current->tss.utraps; + if ((utrap_handler_t)current->thread.utraps[type] != new_p && current->thread.utraps[0] > 1) { + long *p = current->thread.utraps; - current->tss.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); - if (!current->tss.utraps) { - current->tss.utraps = p; + current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + if (!current->thread.utraps) { + current->thread.utraps = p; return -ENOMEM; } p[0]--; - current->tss.utraps[0] = 1; - memcpy(current->tss.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long)); + current->thread.utraps[0] = 1; + memcpy(current->thread.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long)); } } if (old_p) - put_user_ret((utrap_handler_t)(current->tss.utraps[type]), old_p, -EFAULT); + put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT); if (old_d) put_user_ret(NULL, old_d, -EFAULT); - current->tss.utraps[type] = (long)new_p; + current->thread.utraps[type] = (long)new_p; unlock_kernel(); return 0; } @@ -363,10 +365,10 @@ unsigned long pic, tmp; read_pic(pic); - tmp = (current->tss.kernel_cntd0 += (unsigned int)pic); - __put_user(tmp, current->tss.user_cntd0); - tmp = (current->tss.kernel_cntd1 += (pic >> 32)); - __put_user(tmp, current->tss.user_cntd1); + tmp = (current->thread.kernel_cntd0 += (unsigned int)pic); + __put_user(tmp, current->thread.user_cntd0); + tmp = (current->thread.kernel_cntd1 += (pic >> 32)); + __put_user(tmp, current->thread.user_cntd1); reset_pic(); } @@ -377,24 +379,24 @@ switch(opcode) { case PERFCTR_ON: - current->tss.pcr_reg = arg2; - current->tss.user_cntd0 = (u64 *) arg0; - current->tss.user_cntd1 = (u64 *) arg1; - current->tss.kernel_cntd0 = - current->tss.kernel_cntd1 = 0; + current->thread.pcr_reg = arg2; + current->thread.user_cntd0 = (u64 *) arg0; + current->thread.user_cntd1 = (u64 *) arg1; + current->thread.kernel_cntd0 = + current->thread.kernel_cntd1 = 0; write_pcr(arg2); reset_pic(); - current->tss.flags |= SPARC_FLAG_PERFCTR; + current->thread.flags |= SPARC_FLAG_PERFCTR; break; case PERFCTR_OFF: err = -EINVAL; - if ((current->tss.flags & SPARC_FLAG_PERFCTR) != 0) { - current->tss.user_cntd0 = - current->tss.user_cntd1 = NULL; - current->tss.pcr_reg = 0; + if ((current->thread.flags & SPARC_FLAG_PERFCTR) != 0) { + current->thread.user_cntd0 = + current->thread.user_cntd1 = NULL; + current->thread.pcr_reg = 0; write_pcr(0); - current->tss.flags &= ~(SPARC_FLAG_PERFCTR); + current->thread.flags &= ~(SPARC_FLAG_PERFCTR); err = 0; } break; @@ -402,50 +404,50 @@ case PERFCTR_READ: { unsigned long pic, tmp; - if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) { + if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) { err = -EINVAL; break; } read_pic(pic); - tmp = (current->tss.kernel_cntd0 += (unsigned int)pic); - err |= __put_user(tmp, current->tss.user_cntd0); - tmp = (current->tss.kernel_cntd1 += (pic >> 32)); - err |= __put_user(tmp, current->tss.user_cntd1); + tmp = (current->thread.kernel_cntd0 += (unsigned int)pic); + err |= __put_user(tmp, current->thread.user_cntd0); + tmp = (current->thread.kernel_cntd1 += (pic >> 32)); + err |= __put_user(tmp, current->thread.user_cntd1); reset_pic(); break; } case PERFCTR_CLRPIC: - if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) { + if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) { err = -EINVAL; break; } - current->tss.kernel_cntd0 = - current->tss.kernel_cntd1 = 0; + current->thread.kernel_cntd0 = + current->thread.kernel_cntd1 = 0; reset_pic(); break; case PERFCTR_SETPCR: { u64 *user_pcr = (u64 *)arg0; - if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) { + if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) { err = -EINVAL; break; } - err |= __get_user(current->tss.pcr_reg, user_pcr); - write_pcr(current->tss.pcr_reg); - current->tss.kernel_cntd0 = - current->tss.kernel_cntd1 = 0; + err |= __get_user(current->thread.pcr_reg, user_pcr); + write_pcr(current->thread.pcr_reg); + current->thread.kernel_cntd0 = + current->thread.kernel_cntd1 = 0; reset_pic(); break; } case PERFCTR_GETPCR: { u64 *user_pcr = (u64 *)arg0; - if (!(current->tss.flags & SPARC_FLAG_PERFCTR)) { + if (!(current->thread.flags & SPARC_FLAG_PERFCTR)) { err = -EINVAL; break; } - err |= __put_user(current->tss.pcr_reg, user_pcr); + err |= __put_user(current->thread.pcr_reg, user_pcr); break; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.3.12/linux/arch/sparc64/kernel/sys_sparc32.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/sys_sparc32.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.112 1999/06/29 12:34:02 davem Exp $ +/* $Id: sys_sparc32.c,v 1.117 1999/08/02 08:39:40 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1663,85 +1663,6 @@ return ret; } -siginfo_t32 * -siginfo64to32(siginfo_t32 *d, siginfo_t *s) -{ - memset (&d, 0, sizeof(siginfo_t32)); - d->si_signo = s->si_signo; - d->si_errno = s->si_errno; - d->si_code = s->si_code; - if (s->si_signo >= SIGRTMIN) { - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (long)(s->si_addr); - /* XXX: Do we need to translate this from sparc64 to sparc32 traps? */ - d->si_trapno = s->si_trapno; - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; - } - return d; -} - -siginfo_t * -siginfo32to64(siginfo_t *d, siginfo_t32 *s) -{ - d->si_signo = s->si_signo; - d->si_errno = s->si_errno; - d->si_code = s->si_code; - if (s->si_signo >= SIGRTMIN) { - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; - } else switch (s->si_signo) { - /* XXX: What about POSIX1.b timers */ - case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; - break; - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - d->si_addr = (void *)A(s->si_addr); - /* XXX: Do we need to translate this from sparc32 to sparc64 traps? */ - d->si_trapno = s->si_trapno; - break; - case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; - break; - default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - break; - } - return d; -} - extern asmlinkage int sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize); @@ -1753,10 +1674,9 @@ sigset_t s; sigset_t32 s32; struct timespec t; - int ret; + int ret, err, i; mm_segment_t old_fs = get_fs(); siginfo_t info; - siginfo_t32 info32; if (copy_from_user (&s32, uthese, sizeof(sigset_t32))) return -EFAULT; @@ -1776,8 +1696,43 @@ ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); set_fs (old_fs); if (ret >= 0 && uinfo) { - if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32))) - return -EFAULT; + err = put_user (info.si_signo, &uinfo->si_signo); + err |= __put_user (info.si_errno, &uinfo->si_errno); + err |= __put_user (info.si_code, &uinfo->si_code); + if (info.si_code < 0) + err |= __copy_to_user (uinfo->_sifields._pad, info._sifields._pad, SI_PAD_SIZE); + else { + i = info.si_signo; + if (info.si_code == SI_USER) + i = SIGRTMIN; + switch (i) { + case SIGPOLL: + err |= __put_user (info.si_band, &uinfo->si_band); + err |= __put_user (info.si_fd, &uinfo->si_fd); + break; + case SIGCHLD: + err |= __put_user (info.si_pid, &uinfo->si_pid); + err |= __put_user (info.si_uid, &uinfo->si_uid); + err |= __put_user (info.si_status, &uinfo->si_status); + err |= __put_user (info.si_utime, &uinfo->si_utime); + err |= __put_user (info.si_stime, &uinfo->si_stime); + break; + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: + case SIGEMT: + err |= __put_user ((long)info.si_addr, &uinfo->si_addr); + err |= __put_user (info.si_trapno, &uinfo->si_trapno); + break; + default: + err |= __put_user (info.si_pid, &uinfo->si_pid); + err |= __put_user (info.si_uid, &uinfo->si_uid); + break; + } + } + if (err) + ret = -EFAULT; } return ret; } @@ -1789,14 +1744,12 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { siginfo_t info; - siginfo_t32 info32; int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32))) + if (copy_from_user (&info, uinfo, 3*sizeof(int)) || + copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) return -EFAULT; - /* XXX: Is this correct? */ - siginfo32to64(&info, &info32); set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); set_fs (old_fs); @@ -2659,7 +2612,7 @@ int ret; if(sig < 0) { - current->tss.new_signal = 1; + current->thread.flags |= SPARC_FLAG_NEWSIGNALS; sig = -sig; } @@ -2703,7 +2656,7 @@ /* All tasks which use RT signals (effectively) use * new style signals. */ - current->tss.new_signal = 1; + current->thread.flags |= SPARC_FLAG_NEWSIGNALS; if (act) { new_ka.ka_restorer = restorer; @@ -2883,6 +2836,8 @@ int error, base = 0; char *filename; + /* User register window flush is done by entry.S */ + /* Check for indirect call. */ if((u32)regs->u_regs[UREG_G1] == 0) base = 1; @@ -2899,8 +2854,8 @@ if(!error) { fprs_write(0); - current->tss.xfsr[0] = 0; - current->tss.fpsaved[0] = 0; + current->thread.xfsr[0] = 0; + current->thread.fpsaved[0] = 0; regs->tstate &= ~TSTATE_PEF; } out: diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.3.12/linux/arch/sparc64/kernel/sys_sunos32.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/kernel/sys_sunos32.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.28 1999/06/29 12:34:04 davem Exp $ +/* $Id: sys_sunos32.c,v 1.30 1999/07/30 09:35:31 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -557,9 +557,9 @@ struct pt_regs *regs; lock_kernel(); - regs = current->tss.kregs; - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = regs->u_regs[UREG_G1]; + regs = current->thread.kregs; + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = regs->u_regs[UREG_G1]; send_sig(SIGSYS, current, 1); printk("Process makes ni_syscall number %d, register dump:\n", (int) regs->u_regs[UREG_G1]); @@ -1159,7 +1159,7 @@ if(!kmbuf) break; sp = (struct sparc_stackf32 *) - (current->tss.kregs->u_regs[UREG_FP] & 0xffffffffUL); + (current->thread.kregs->u_regs[UREG_FP] & 0xffffffffUL); if(get_user(arg5, &sp->xxargs[0])) { rval = -EFAULT; break; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.3.12/linux/arch/sparc64/kernel/systbls.S Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/kernel/systbls.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.54 1999/06/02 12:06:31 jj Exp $ +/* $Id: systbls.S,v 1.56 1999/07/31 00:06:17 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -59,7 +59,7 @@ .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask /*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir .word sys_nis_syscall, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall -/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo +/*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex /*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid @@ -112,15 +112,15 @@ .word sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall /*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents .word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module +/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname /*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask -/*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall +/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall .word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall -/*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo - .word sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex -/*220*/ .word sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid +/*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo + .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex +/*220*/ .word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid /*230*/ .word sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.3.12/linux/arch/sparc64/kernel/traps.c Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/kernel/traps.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.60 1999/06/02 19:19:55 jj Exp $ +/* $Id: traps.c,v 1.61 1999/07/30 09:35:32 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -147,12 +147,12 @@ if(i) printk(","); if(!sdp->arg_is_string[i]) { - if (current->tss.flags & SPARC_FLAG_32BIT) + if (current->thread.flags & SPARC_FLAG_32BIT) printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]); else printk("%016lx", regs->u_regs[UREG_I0 + i]); } else { - if (current->tss.flags & SPARC_FLAG_32BIT) + if (current->thread.flags & SPARC_FLAG_32BIT) strncpy_from_user(scall_strbuf, (char *)(regs->u_regs[UREG_I0 + i] & 0xffffffff), 512); @@ -178,7 +178,7 @@ } #endif /* SYSCALL_TRACING */ -#if 0 +#if 1 void rtrap_check(struct pt_regs *regs) { register unsigned long pgd_phys asm("o1"); @@ -219,7 +219,7 @@ if((pgd_phys != __pa(current->mm->pgd)) || ((pgd_cache != 0) && - (pgd_cache != pgd_val(current->mm->pgd[0]))) || + (pgd_cache != pgd_val(current->mm->pgd[0])<<11UL)) || (g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) || #define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000) #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) @@ -228,18 +228,17 @@ #undef KERN_LOWBITS ((ctx != (current->mm->context & 0x3ff)) || (ctx == 0) || - (current->tss.ctx != ctx))) { + (CTX_HWBITS(current->mm->context) != ctx))) { printk("SHIT[%s:%d]: " - "(PP[%016lx] CACH[%016lx] CTX[%x] g1g3[%016lx] g2[%016lx]) ", + "(PP[%016lx] CACH[%016lx] CTX[%lx] g1g3[%016lx] g2[%016lx]) ", current->comm, current->pid, pgd_phys, pgd_cache, ctx, g1_or_g3, g2); printk("SHIT[%s:%d]: " - "[PP[%016lx] CACH[%016lx] CTX[%x:%x]] PC[%016lx:%016lx]\n", + "[PP[%016lx] CACH[%016lx] CTX[%lx]] PC[%016lx:%016lx]\n", current->comm, current->pid, __pa(current->mm->pgd), pgd_val(current->mm->pgd[0]), current->mm->context & 0x3ff, - current->tss.ctx, regs->tpc, regs->tnpc); show_regs(regs); #if 1 @@ -262,8 +261,8 @@ } if (regs->tstate & TSTATE_PRIV) die_if_kernel ("Kernel bad trap", regs); - current->tss.sig_desc = SUBSIG_BADTRAP(lvl - 0x100); - current->tss.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_BADTRAP(lvl - 0x100); + current->thread.sig_address = regs->tpc; force_sig(SIGILL, current); unlock_kernel (); } @@ -289,8 +288,8 @@ #endif die_if_kernel("Iax", regs); } - current->tss.sig_desc = SUBSIG_ILLINST; - current->tss.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_ILLINST; + current->thread.sig_address = regs->tpc; force_sig(SIGILL, current); unlock_kernel(); } @@ -402,8 +401,8 @@ regs->tpc = regs->tnpc; regs->tnpc += 4; } else { - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = SUBSIG_FPERROR; + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_FPERROR; send_sig(SIGFPE, current, 1); } } @@ -411,7 +410,7 @@ void do_fpieee(struct pt_regs *regs) { #ifdef DEBUG_FPU - printk("fpieee %016lx\n", current->tss.xfsr[0]); + printk("fpieee %016lx\n", current->thread.xfsr[0]); #endif do_fpe_common(regs); } @@ -423,7 +422,7 @@ struct fpustate *f = FPUSTATE; int ret = 0; - switch ((current->tss.xfsr[0] & 0x1c000)) { + switch ((current->thread.xfsr[0] & 0x1c000)) { case (2 << 14): /* unfinished_FPop */ case (3 << 14): /* unimplemented_FPop */ ret = do_mathemu(regs, f); @@ -431,7 +430,7 @@ } if (ret) return; #ifdef DEBUG_FPU - printk("fpother %016lx\n", current->tss.xfsr[0]); + printk("fpother %016lx\n", current->thread.xfsr[0]); #endif do_fpe_common(regs); } @@ -440,8 +439,8 @@ { if(regs->tstate & TSTATE_PRIV) die_if_kernel("Penguin overflow trap from kernel mode", regs); - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = SUBSIG_TAG; /* as good as any */ + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_TAG; /* as good as any */ send_sig(SIGEMT, current, 1); } @@ -540,7 +539,7 @@ if(tstate & TSTATE_PRIV) die_if_kernel("Kernel illegal instruction", regs); - if(current->tss.flags & SPARC_FLAG_32BIT) + if(current->thread.flags & SPARC_FLAG_32BIT) pc = (u32)pc; if (get_user(insn, (u32 *)pc) != -EFAULT) { if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ { @@ -551,8 +550,8 @@ return; } } - current->tss.sig_address = pc; - current->tss.sig_desc = SUBSIG_ILLINST; + current->thread.sig_address = pc; + current->thread.sig_desc = SUBSIG_ILLINST; send_sig(SIGILL, current, 1); } @@ -565,23 +564,23 @@ return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr); } else { - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = SUBSIG_PRIVINST; + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_PRIVINST; send_sig(SIGBUS, current, 1); } } void do_privop(struct pt_regs *regs) { - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = SUBSIG_PRIVINST; + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); } void do_privact(struct pt_regs *regs) { - current->tss.sig_address = regs->tpc; - current->tss.sig_desc = SUBSIG_PRIVINST; + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); } @@ -590,8 +589,8 @@ { if(tstate & TSTATE_PRIV) die_if_kernel("Penguin instruction from Penguin mode??!?!", regs); - current->tss.sig_address = pc; - current->tss.sig_desc = SUBSIG_PRIVINST; + current->thread.sig_address = pc; + current->thread.sig_desc = SUBSIG_PRIVINST; send_sig(SIGILL, current, 1); } @@ -727,4 +726,11 @@ void trap_init(void) { + /* Attach to the address space of init_task. */ + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + + /* NOTE: Other cpus have this done as they are started + * up on SMP. + */ } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c --- v2.3.12/linux/arch/sparc64/kernel/unaligned.c Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/kernel/unaligned.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.16 1999/05/25 16:53:15 jj Exp $ +/* $Id: unaligned.c,v 1.18 1999/08/02 08:39:44 davem Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -70,7 +70,7 @@ return 2; else { printk("Impossible unaligned trap. insn=%08x\n", insn); - die_if_kernel("Byte sized unaligned access?!?!", current->tss.kregs); + die_if_kernel("Byte sized unaligned access?!?!", current->thread.kregs); } } @@ -117,7 +117,7 @@ struct reg_window *win; win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); value = win->locals[reg - 16]; - } else if (current->tss.flags & SPARC_FLAG_32BIT) { + } else if (current->thread.flags & SPARC_FLAG_32BIT) { struct reg_window32 *win32; win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); get_user(value, &win32->locals[reg - 16]); @@ -137,7 +137,7 @@ struct reg_window *win; win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); return &win->locals[reg - 16]; - } else if (current->tss.flags & SPARC_FLAG_32BIT) { + } else if (current->thread.flags & SPARC_FLAG_32BIT) { struct reg_window32 *win32; win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); return (unsigned long *)&win32->locals[reg - 16]; @@ -164,10 +164,10 @@ } } -/* This is just to make gcc think panic does return... */ -static void unaligned_panic(char *str) +/* This is just to make gcc think die_if_kernel does return... */ +static void unaligned_panic(char *str, struct pt_regs *regs) { - panic(str); + die_if_kernel(str, regs); } #define do_integer_load(dest_reg, size, saddr, is_signed, asi, errh) ({ \ @@ -380,7 +380,7 @@ if(!ok_for_kernel(insn) || dir == both) { printk("Unsupported unaligned load/store trap for kernel at <%016lx>.\n", regs->tpc); - unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store."); + unaligned_panic("Kernel does fpu/atomic unaligned load/store.", regs); __asm__ __volatile__ ("\n" "kernel_unaligned_trap_fault:\n\t" @@ -453,7 +453,7 @@ if (rd) regs->u_regs[rd] = ret; } else { - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { struct reg_window32 *win32; win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); put_user(ret, &win32->locals[rd - 16]); @@ -480,9 +480,9 @@ int flag = (freg < 32) ? FPRS_DL : FPRS_DU; save_and_clear_fpu(); - current->tss.xfsr[0] &= ~0x1c000; + current->thread.xfsr[0] &= ~0x1c000; if (freg & 3) { - current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */; + current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */; do_fpother(regs); return 0; } @@ -490,7 +490,7 @@ /* STQ */ u64 first = 0, second = 0; - if (current->tss.fpsaved[0] & flag) { + if (current->thread.fpsaved[0] & flag) { first = *(u64 *)&f->regs[freg]; second = *(u64 *)&f->regs[freg+2]; } @@ -565,18 +565,18 @@ break; } } - if (!(current->tss.fpsaved[0] & FPRS_FEF)) { - current->tss.fpsaved[0] = FPRS_FEF; - current->tss.gsr[0] = 0; + if (!(current->thread.fpsaved[0] & FPRS_FEF)) { + current->thread.fpsaved[0] = FPRS_FEF; + current->thread.gsr[0] = 0; } - if (!(current->tss.fpsaved[0] & flag)) { + if (!(current->thread.fpsaved[0] & flag)) { if (freg < 32) memset(f->regs, 0, 32*sizeof(u32)); else memset(f->regs+32, 0, 32*sizeof(u32)); } memcpy(f->regs + freg, data, size * 4); - current->tss.fpsaved[0] |= flag; + current->thread.fpsaved[0] |= flag; } advance(regs); return 1; @@ -609,7 +609,7 @@ if(tstate & TSTATE_PRIV) die_if_kernel("lddfmna from kernel", regs); - if(current->tss.flags & SPARC_FLAG_32BIT) + if(current->thread.flags & SPARC_FLAG_32BIT) pc = (u32)pc; if (get_user(insn, (u32 *)pc) != -EFAULT) { asi = sfsr >> 16; @@ -629,18 +629,18 @@ if (asi & 0x8) /* Little */ value = __swab64p(&value); flag = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) { - current->tss.fpsaved[0] = FPRS_FEF; - current->tss.gsr[0] = 0; + if (!(current->thread.fpsaved[0] & FPRS_FEF)) { + current->thread.fpsaved[0] = FPRS_FEF; + current->thread.gsr[0] = 0; } - if (!(current->tss.fpsaved[0] & flag)) { + if (!(current->thread.fpsaved[0] & flag)) { if (freg < 32) memset(f->regs, 0, 32*sizeof(u32)); else memset(f->regs+32, 0, 32*sizeof(u32)); } *(u64 *)(f->regs + freg) = value; - current->tss.fpsaved[0] |= flag; + current->thread.fpsaved[0] |= flag; } else { daex: data_access_exception(regs); return; @@ -661,7 +661,7 @@ if(tstate & TSTATE_PRIV) die_if_kernel("stdfmna from kernel", regs); - if(current->tss.flags & SPARC_FLAG_32BIT) + if(current->thread.flags & SPARC_FLAG_32BIT) pc = (u32)pc; if (get_user(insn, (u32 *)pc) != -EFAULT) { freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20); @@ -672,7 +672,7 @@ (asi < ASI_P)) goto daex; save_and_clear_fpu(); - if (current->tss.fpsaved[0] & flag) + if (current->thread.fpsaved[0] & flag) value = *(u64 *)&f->regs[freg]; switch (asi) { case ASI_P: diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S --- v2.3.12/linux/arch/sparc64/kernel/winfixup.S Sun Oct 4 10:22:43 1998 +++ linux/arch/sparc64/kernel/winfixup.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.27 1998/09/25 01:09:14 davem Exp $ +/* $Id: winfixup.S,v 1.28 1999/07/30 09:35:34 davem Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -95,56 +95,56 @@ * do not touch %g7 or %g2 so we handle the two cases fine. */ spill_fixup: - lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1 andcc %g1, SPARC_FLAG_32BIT, %g0 - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1 sll %g1, 3, %g3 add %g6, %g3, %g3 - stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs] sll %g1, 7, %g3 bne,pt %xcc, 1f add %g6, %g3, %g3 - stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] - stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] - stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] - - stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] - stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] - stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] - stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] - stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] + stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48] + + stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60] + stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68] + stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70] b,pt %xcc, 2f - stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] -1: stw %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78] +1: stw %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] - stw %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x04] - stw %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - stw %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x0c] - stw %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - stw %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x14] - stw %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - stw %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x1c] - stw %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - - stw %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x24] - stw %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - stw %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x2c] - stw %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - stw %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x34] - stw %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - stw %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x3c] + stw %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x04] + stw %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] + stw %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x0c] + stw %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + stw %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x14] + stw %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + stw %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x1c] + stw %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + + stw %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x24] + stw %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + stw %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x2c] + stw %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + stw %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x34] + stw %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] + stw %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x3c] 2: add %g1, 1, %g1 - sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved] + stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved] rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 saved @@ -208,47 +208,47 @@ b,pt %xcc, rtrap nop ! yes, the nop is correct spill_fixup_mna: - lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1 andcc %g1, SPARC_FLAG_32BIT, %g0 - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1 sll %g1, 3, %g3 add %g6, %g3, %g3 - stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs] sll %g1, 7, %g3 bne,pt %xcc, 1f add %g6, %g3, %g3 - stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - - stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] - stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] - stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] - stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] - stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] - - stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] - stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] - stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] + stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] + stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + + stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48] + stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60] + + stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68] + stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70] + stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78] b,pt %xcc, 2f add %g1, 1, %g1 -1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - - std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] +1: std %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] + std %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] + std %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + + std %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + std %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + std %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + std %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + std %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] add %g1, 1, %g1 -2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved] +2: stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved] rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 @@ -315,47 +315,47 @@ b,pt %xcc, rtrap nop ! yes, the nop is correct spill_fixup_dax: - lduh [%g6 + AOFF_task_tss + AOFF_thread_flags], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %g1 andcc %g1, SPARC_FLAG_32BIT, %g0 - lduh [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %g1 sll %g1, 3, %g3 add %g6, %g3, %g3 - stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + stx %sp, [%g3 + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs] sll %g1, 7, %g3 bne,pt %xcc, 1f add %g6, %g3, %g3 - stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - - stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] - stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] - stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] - stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] - stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] - - stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] - stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] - stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] + stx %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] + stx %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + + stx %l5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + stx %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x48] + stx %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x60] + + stx %i5, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x68] + stx %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x70] + stx %i7, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x78] b,pt %xcc, 2f add %g1, 1, %g1 -1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - - std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] +1: std %l0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x00] + std %l2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x08] + std %l4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x10] + + std %l6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x18] + std %i0, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x20] + std %i2, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x28] + std %i4, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x30] + std %i6, [%g3 + AOFF_task_thread + AOFF_thread_reg_window + 0x38] add %g1, 1, %g1 -2: sth %g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved] +2: stb %g1, [%g6 + AOFF_task_thread + AOFF_thread_w_saved] rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.3.12/linux/arch/sparc64/lib/VIScopy.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/lib/VIScopy.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.20 1999/05/25 16:52:57 jj Exp $ +/* $Id: VIScopy.S,v 1.21 1999/07/30 09:35:35 davem Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -29,19 +29,19 @@ #include #define FPU_CLEAN_RETL \ - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \ + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ VISExit \ clr %o0; \ retl; \ wr %o1, %g0, %asi; #define FPU_RETL \ - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \ + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ VISExit \ clr %o0; \ retl; \ wr %o1, %g0, %asi; #define NORMAL_RETL \ - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o1; \ + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1; \ clr %o0; \ retl; \ wr %o1, %g0, %asi; @@ -1009,7 +1009,7 @@ /* If this is copy_from_user(), zero out the rest of the * kernel buffer. */ - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %o4 + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o4 andcc asi_src, 0x1, %g0 be,pt %icc, 1f VISExit diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/lib/VIScsum.S linux/arch/sparc64/lib/VIScsum.S --- v2.3.12/linux/arch/sparc64/lib/VIScsum.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/lib/VIScsum.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: VIScsum.S,v 1.4 1999/05/25 16:53:00 jj Exp $ +/* $Id: VIScsum.S,v 1.5 1999/07/30 09:35:36 davem Exp $ * VIScsum.S: High bandwidth IP checksumming utilizing the UltraSparc * Visual Instruction Set. * @@ -341,7 +341,7 @@ DO_THE_TRICK(f44,f46,f48,f50,f52,f54,f56,f58,f60,f62,f0,f2,f4,f6,f8,f10,f12,f14) END_THE_TRICK(f60,f62,f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30) #ifdef __KERNEL__ - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g7 + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g7 #endif and %o1, 0x3f, %o1 /* IEU0 Group */ #ifdef __KERNEL__ diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/lib/VISsave.S linux/arch/sparc64/lib/VISsave.S --- v2.3.12/linux/arch/sparc64/lib/VISsave.S Tue Oct 27 09:52:20 1998 +++ linux/arch/sparc64/lib/VISsave.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: VISsave.S,v 1.3 1998/10/21 10:36:39 jj Exp $ +/* $Id: VISsave.S,v 1.4 1999/07/30 09:35:37 davem Exp $ * VISsave.S: Code for saving FPU register state for * VIS routines. One should not call this directly, * but use macros provided in . @@ -19,35 +19,35 @@ .align 32 VISenter: - ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1 brnz,a,pn %g1, 1f cmp %g1, 1 - stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved] - stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr] + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved] + stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr] 9: jmpl %g7 + %g0, %g0 nop 1: bne,pn %icc, 2f srl %g1, 1, %g1 -vis1: ldub [%g6 + AOFF_task_tss + AOFF_thread_fpsaved], %g3 - stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr] +vis1: ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3 + stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr] or %g3, %o5, %g3 - stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved] + stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved] rd %gsr, %g3 clr %g1 ba,pt %xcc, 3f - stb %g3, [%g6 + AOFF_task_tss + AOFF_thread_gsr] + stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr] 2: add %g6, %g1, %g3 cmp %o5, FPRS_DU be,pn %icc, 6f sll %g1, 3, %g1 - stb %o5, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved] + stb %o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved] rd %gsr, %g2 - stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_gsr] + stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr] add %g6, %g1, %g2 - stx %fsr, [%g2 + AOFF_task_tss + AOFF_thread_xfsr] + stx %fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr] sll %g1, 5, %g1 3: andcc %o5, FPRS_DL|FPRS_DU, %g0 be,pn %icc, 9b @@ -69,10 +69,10 @@ jmpl %g7 + %g0, %g0 nop -6: ldub [%g3 + AOFF_task_tss + AOFF_thread_fpsaved], %o5 +6: ldub [%g3 + AOFF_task_thread + AOFF_thread_fpsaved], %o5 or %o5, FPRS_DU, %o5 add %g6, AOFF_task_fpregs+0x80, %g2 - stb %o5, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved] + stb %o5, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved] sll %g1, 5, %g1 add %g6, AOFF_task_fpregs+0xc0, %g3 @@ -87,11 +87,11 @@ .align 32 VISenterhalf: - ldub [%g6 + AOFF_task_tss + AOFF_thread_fpdepth], %g1 + ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %g1 brnz,a,pn %g1, 1f cmp %g1, 1 - stb %g0, [%g6 + AOFF_task_tss + AOFF_thread_fpsaved] - stx %fsr, [%g6 + AOFF_task_tss + AOFF_thread_xfsr] + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved] + stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr] clr %o5 jmpl %g7 + %g0, %g0 wr %g0, FPRS_FEF, %fprs @@ -103,12 +103,12 @@ 2: addcc %g6, %g1, %g3 sll %g1, 3, %g1 andn %o5, FPRS_DU, %g2 - stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_fpsaved] + stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_fpsaved] rd %gsr, %g2 - stb %g2, [%g3 + AOFF_task_tss + AOFF_thread_gsr] + stb %g2, [%g3 + AOFF_task_thread + AOFF_thread_gsr] add %g6, %g1, %g2 - stx %fsr, [%g2 + AOFF_task_tss + AOFF_thread_xfsr] + stx %fsr, [%g2 + AOFF_task_thread + AOFF_thread_xfsr] sll %g1, 5, %g1 3: andcc %o5, FPRS_DL, %g0 be,pn %icc, 4f diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.3.12/linux/arch/sparc64/lib/blockops.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/lib/blockops.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.17 1999/05/25 16:52:52 jj Exp $ +/* $Id: blockops.S,v 1.18 1999/07/30 09:35:37 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) @@ -29,7 +29,7 @@ .type copy_page,@function copy_page: /* %o0=dest, %o1=src */ VISEntry - ldx [%g6 + AOFF_task_mm], %o2 + ldx [%g6 + AOFF_task_active_mm], %o2 sub %o0, %g4, %g1 sethi %uhi(_PAGE_VALID), %g3 sub %o1, %g4, %g2 @@ -107,7 +107,7 @@ .type clear_page,@function clear_page: /* %o0=dest */ VISEntryHalf - ldx [%g6 + AOFF_task_mm], %o2 + ldx [%g6 + AOFF_task_active_mm], %o2 sub %o0, %g4, %g1 sethi %uhi(_PAGE_VALID), %g3 sllx %g3, 32, %g3 diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S --- v2.3.12/linux/arch/sparc64/lib/checksum.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/lib/checksum.S Mon Aug 2 22:07:16 1999 @@ -266,7 +266,7 @@ .globl cpc_handler cpc_handler: ldx [%sp + 0x7ff + 128], %g1 - ldub [%g6 + AOFF_task_tss + AOFF_thread_current_ds], %g3 + ldub [%g6 + AOFF_task_thread + AOFF_thread_current_ds], %g3 sub %g0, EFAULT, %g2 brnz,a,pt %g1, 1f st %g2, [%g1] diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/fcmpeq.c linux/arch/sparc64/math-emu/fcmpeq.c --- v2.3.12/linux/arch/sparc64/math-emu/fcmpeq.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/fcmpeq.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fcmpeq.c,v 1.5 1999/05/28 13:43:29 jj Exp $ +/* $Id: fcmpeq.c,v 1.6 1999/07/30 09:35:40 davem Exp $ * arch/sparc64/math-emu/fcmpeq.c * * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -26,14 +26,14 @@ if (!FP_INHIBIT_RESULTS) { rd = (void *)(((long)rd)&~3); if (ret == -1) ret = 2; - fsr = current->tss.xfsr[0]; + fsr = current->thread.xfsr[0]; switch (fccno) { case 0: fsr &= ~0xc00; fsr |= (ret << 10); break; case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break; case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break; case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break; } - current->tss.xfsr[0] = fsr; + current->thread.xfsr[0] = fsr; } FP_HANDLE_EXCEPTIONS; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/fcmpq.c linux/arch/sparc64/math-emu/fcmpq.c --- v2.3.12/linux/arch/sparc64/math-emu/fcmpq.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/fcmpq.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fcmpq.c,v 1.5 1999/05/28 13:43:33 jj Exp $ +/* $Id: fcmpq.c,v 1.6 1999/07/30 09:35:40 davem Exp $ * arch/sparc64/math-emu/fcmpq.c * * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -26,14 +26,14 @@ if (!FP_INHIBIT_RESULTS) { rd = (void *)(((long)rd)&~3); if (ret == -1) ret = 2; - fsr = current->tss.xfsr[0]; + fsr = current->thread.xfsr[0]; switch (fccno) { case 0: fsr &= ~0xc00; fsr |= (ret << 10); break; case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break; case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break; case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break; } - current->tss.xfsr[0] = fsr; + current->thread.xfsr[0] = fsr; } FP_HANDLE_EXCEPTIONS; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/fsubd.c linux/arch/sparc64/math-emu/fsubd.c --- v2.3.12/linux/arch/sparc64/math-emu/fsubd.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/fsubd.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fsubd.c,v 1.4 1999/05/28 13:45:04 jj Exp $ +/* $Id: fsubd.c,v 1.5 1999/08/02 14:08:04 jj Exp $ * arch/sparc64/math-emu/fsubd.c * * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -17,9 +17,7 @@ FP_UNPACK_DP(A, rs1); FP_UNPACK_DP(B, rs2); - if (B_c != FP_CLS_NAN) - B_s ^= 1; - FP_ADD_D(R, A, B); + FP_SUB_D(R, A, B); FP_PACK_DP(rd, R); FP_HANDLE_EXCEPTIONS; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/fsubq.c linux/arch/sparc64/math-emu/fsubq.c --- v2.3.12/linux/arch/sparc64/math-emu/fsubq.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/fsubq.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fsubq.c,v 1.4 1999/05/28 13:45:09 jj Exp $ +/* $Id: fsubq.c,v 1.5 1999/08/02 14:08:06 jj Exp $ * arch/sparc64/math-emu/fsubq.c * * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -17,9 +17,7 @@ FP_UNPACK_QP(A, rs1); FP_UNPACK_QP(B, rs2); - if (B_c != FP_CLS_NAN) - B_s ^= 1; - FP_ADD_Q(R, A, B); + FP_SUB_Q(R, A, B); FP_PACK_QP(rd, R); FP_HANDLE_EXCEPTIONS; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/fsubs.c linux/arch/sparc64/math-emu/fsubs.c --- v2.3.12/linux/arch/sparc64/math-emu/fsubs.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/fsubs.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fsubs.c,v 1.4 1999/05/28 13:45:12 jj Exp $ +/* $Id: fsubs.c,v 1.5 1999/08/02 14:08:07 jj Exp $ * arch/sparc64/math-emu/fsubs.c * * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -17,9 +17,7 @@ FP_UNPACK_SP(A, rs1); FP_UNPACK_SP(B, rs2); - if (B_c != FP_CLS_NAN) - B_s ^= 1; - FP_ADD_S(R, A, B); + FP_SUB_S(R, A, B); FP_PACK_SP(rd, R); FP_HANDLE_EXCEPTIONS; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c --- v2.3.12/linux/arch/sparc64/math-emu/math.c Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/math.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: math.c,v 1.8 1999/05/28 13:43:11 jj Exp $ +/* $Id: math.c,v 1.9 1999/07/30 09:35:41 davem Exp $ * arch/sparc64/math-emu/math.c * * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -75,7 +75,7 @@ */ static int record_exception(struct pt_regs *regs, int eflag) { - u64 fsr = current->tss.xfsr[0]; + u64 fsr = current->thread.xfsr[0]; int would_trap; /* Determine if this exception would have generated a trap. */ @@ -120,7 +120,7 @@ if(would_trap != 0) fsr |= (1UL << 14); - current->tss.xfsr[0] = fsr; + current->thread.xfsr[0] = fsr; /* If we will not trap, advance the program counter over * the instruction being handled. @@ -148,7 +148,7 @@ if(tstate & TSTATE_PRIV) die_if_kernel("FPQuad from kernel", regs); - if(current->tss.flags & SPARC_FLAG_32BIT) + if(current->thread.flags & SPARC_FLAG_32BIT) pc = (u32)pc; if (get_user(insn, (u32 *)pc) != -EFAULT) { if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ { @@ -201,33 +201,33 @@ if (type) { void *rs1 = NULL, *rs2 = NULL, *rd = NULL; - freg = (current->tss.xfsr[0] >> 14) & 0xf; + freg = (current->thread.xfsr[0] >> 14) & 0xf; if (freg != (type >> 8)) goto err; - current->tss.xfsr[0] &= ~0x1c000; + current->thread.xfsr[0] &= ~0x1c000; freg = ((insn >> 14) & 0x1f); switch (type & 0x3) { case 3: if (freg & 2) { - current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */; + current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */; goto err; } case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); case 1: rs1 = (void *)&f->regs[freg]; flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current->tss.fpsaved[0] & flags)) + if (!(current->thread.fpsaved[0] & flags)) rs1 = (void *)&zero; break; } freg = (insn & 0x1f); switch ((type >> 2) & 0x3) { case 3: if (freg & 2) { - current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */; + current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */; goto err; } case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); case 1: rs2 = (void *)&f->regs[freg]; flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current->tss.fpsaved[0] & flags)) + if (!(current->thread.fpsaved[0] & flags)) rs2 = (void *)&zero; break; } @@ -235,23 +235,23 @@ switch ((type >> 4) & 0x3) { case 0: rd = (void *)(long)(freg & 3); break; case 3: if (freg & 2) { - current->tss.xfsr[0] |= (6 << 14) /* invalid_fp_register */; + current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */; goto err; } case 2: freg = ((freg & 1) << 5) | (freg & 0x1e); case 1: rd = (void *)&f->regs[freg]; flags = (freg < 32) ? FPRS_DL : FPRS_DU; - if (!(current->tss.fpsaved[0] & FPRS_FEF)) { - current->tss.fpsaved[0] = FPRS_FEF; - current->tss.gsr[0] = 0; + if (!(current->thread.fpsaved[0] & FPRS_FEF)) { + current->thread.fpsaved[0] = FPRS_FEF; + current->thread.gsr[0] = 0; } - if (!(current->tss.fpsaved[0] & flags)) { + if (!(current->thread.fpsaved[0] & flags)) { if (freg < 32) memset(f->regs, 0, 32*sizeof(u32)); else memset(f->regs+32, 0, 32*sizeof(u32)); } - current->tss.fpsaved[0] |= flags; + current->thread.fpsaved[0] |= flags; break; } flags = func(rd, rs2, rs1); @@ -259,7 +259,7 @@ return record_exception(regs, flags); /* Success and no exceptions detected. */ - current->tss.xfsr[0] &= ~(FSR_CEXC_MASK); + current->thread.xfsr[0] &= ~(FSR_CEXC_MASK); regs->tpc = regs->tnpc; regs->tnpc += 4; return 1; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/op-1.h linux/arch/sparc64/math-emu/op-1.h --- v2.3.12/linux/arch/sparc64/math-emu/op-1.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/op-1.h Mon Aug 2 22:07:16 1999 @@ -120,31 +120,31 @@ /* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the multiplication immediately. */ -#define _FP_MUL_MEAT_1_imm(fs, R, X, Y) \ +#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \ do { \ R##_f = X##_f * Y##_f; \ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \ } while (0) /* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ -#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit) \ +#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \ do { \ _FP_W_TYPE _Z_f0, _Z_f1; \ doit(_Z_f1, _Z_f0, X##_f, Y##_f); \ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \ R##_f = _Z_f0; \ } while (0) /* Finally, a simple widening multiply algorithm. What fun! */ -#define _FP_MUL_MEAT_1_hard(fs, R, X, Y) \ +#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \ do { \ _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \ \ @@ -168,7 +168,7 @@ _FP_FRAC_ADD_2(_z, _z, _a); \ \ /* normalize */ \ - _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \ R##_f = _z_f0; \ } while (0) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/op-2.h linux/arch/sparc64/math-emu/op-2.h --- v2.3.12/linux/arch/sparc64/math-emu/op-2.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/op-2.h Mon Aug 2 22:07:16 1999 @@ -234,7 +234,7 @@ /* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ -#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit) \ +#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \ do { \ _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ \ @@ -255,7 +255,7 @@ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ R##_f0 = _FP_FRAC_WORD_4(_z,0); \ R##_f1 = _FP_FRAC_WORD_4(_z,1); \ } while (0) @@ -264,7 +264,7 @@ Do only 3 multiplications instead of four. This one is for machines where multiplication is much more expensive than subtraction. */ -#define _FP_MUL_MEAT_2_wide_3mul(fs, R, X, Y, doit) \ +#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \ do { \ _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ _FP_W_TYPE _d; \ @@ -299,12 +299,12 @@ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ R##_f0 = _FP_FRAC_WORD_4(_z,0); \ R##_f1 = _FP_FRAC_WORD_4(_z,1); \ } while (0) -#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y) \ +#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \ do { \ _FP_FRAC_DECL_4(_z); \ _FP_W_TYPE _x[2], _y[2]; \ @@ -316,11 +316,106 @@ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ R##_f0 = _z_f[0]; \ R##_f1 = _z_f[1]; \ } while (0) +/* Do at most 120x120=240 bits multiplication using double floating + point multiplication. This is useful if floating point + multiplication has much bigger throughput than integer multiply. + It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits + between 106 and 120 only. + Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set. + SETFETZ is a macro which will disable all FPU exceptions and set rounding + towards zero, RESETFE should optionally reset it back. */ + +#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \ + do { \ + static const double _const[] = { \ + /* 2^-24 */ 5.9604644775390625e-08, \ + /* 2^-48 */ 3.5527136788005009e-15, \ + /* 2^-72 */ 2.1175823681357508e-22, \ + /* 2^-96 */ 1.2621774483536189e-29, \ + /* 2^28 */ 2.68435456e+08, \ + /* 2^4 */ 1.600000e+01, \ + /* 2^-20 */ 9.5367431640625e-07, \ + /* 2^-44 */ 5.6843418860808015e-14, \ + /* 2^-68 */ 3.3881317890172014e-21, \ + /* 2^-92 */ 2.0194839173657902e-28, \ + /* 2^-116 */ 1.2037062152420224e-35}; \ + double _a240, _b240, _c240, _d240, _e240, _f240, \ + _g240, _h240, _i240, _j240, _k240; \ + union { double d; UDItype i; } _l240, _m240, _n240, _o240, \ + _p240, _q240, _r240, _s240; \ + UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \ + \ + if (wfracbits < 106 || wfracbits > 120) \ + abort(); \ + \ + setfetz; \ + \ + _e240 = (double)(long)(X##_f0 & 0xffffff); \ + _j240 = (double)(long)(Y##_f0 & 0xffffff); \ + _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \ + _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \ + _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \ + _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \ + _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \ + _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \ + _a240 = (double)(long)(X##_f1 >> 32); \ + _f240 = (double)(long)(Y##_f1 >> 32); \ + _e240 *= _const[3]; \ + _j240 *= _const[3]; \ + _d240 *= _const[2]; \ + _i240 *= _const[2]; \ + _c240 *= _const[1]; \ + _h240 *= _const[1]; \ + _b240 *= _const[0]; \ + _g240 *= _const[0]; \ + _s240.d = _e240*_j240;\ + _r240.d = _d240*_j240 + _e240*_i240;\ + _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\ + _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\ + _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\ + _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \ + _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \ + _l240.d = _a240*_g240 + _b240*_f240; \ + _k240 = _a240*_f240; \ + _r240.d += _s240.d; \ + _q240.d += _r240.d; \ + _p240.d += _q240.d; \ + _o240.d += _p240.d; \ + _n240.d += _o240.d; \ + _m240.d += _n240.d; \ + _l240.d += _m240.d; \ + _k240 += _l240.d; \ + _s240.d -= ((_const[10]+_s240.d)-_const[10]); \ + _r240.d -= ((_const[9]+_r240.d)-_const[9]); \ + _q240.d -= ((_const[8]+_q240.d)-_const[8]); \ + _p240.d -= ((_const[7]+_p240.d)-_const[7]); \ + _o240.d += _const[7]; \ + _n240.d += _const[6]; \ + _m240.d += _const[5]; \ + _l240.d += _const[4]; \ + if (_s240.d != 0.0) _y240 = 1; \ + if (_r240.d != 0.0) _y240 = 1; \ + if (_q240.d != 0.0) _y240 = 1; \ + if (_p240.d != 0.0) _y240 = 1; \ + _t240 = (DItype)_k240; \ + _u240 = _l240.i; \ + _v240 = _m240.i; \ + _w240 = _n240.i; \ + _x240 = _o240.i; \ + R##_f1 = (_t240 << (128 - (wfracbits - 1))) \ + | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \ + R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \ + | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \ + | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \ + | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \ + | _y240; \ + resetfe; \ + } while (0) /* * Division algorithms: diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/op-4.h linux/arch/sparc64/math-emu/op-4.h --- v2.3.12/linux/arch/sparc64/math-emu/op-4.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/op-4.h Mon Aug 2 22:07:16 1999 @@ -232,7 +232,7 @@ /* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ -#define _FP_MUL_MEAT_4_wide(fs, R, X, Y, doit) \ +#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \ do { \ _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \ @@ -311,12 +311,12 @@ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ } while (0) -#define _FP_MUL_MEAT_4_gmp(fs, R, X, Y) \ +#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \ do { \ _FP_FRAC_DECL_8(_z); \ \ @@ -325,7 +325,7 @@ /* Normalize since we know where the msb of the multiplicands \ were (bit B), we know that the msb of the of the product is \ at either 2B or 2B-1. */ \ - _FP_FRAC_SRS_8(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ + _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ } while (0) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/op-common.h linux/arch/sparc64/math-emu/op-common.h --- v2.3.12/linux/arch/sparc64/math-emu/op-common.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/op-common.h Mon Aug 2 22:07:16 1999 @@ -207,7 +207,7 @@ * Main addition routine. The input values should be cooked. */ -#define _FP_ADD(fs, wc, R, X, Y) \ +#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ do { \ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ { \ @@ -284,7 +284,7 @@ } \ \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ - _FP_CHOOSENAN(fs, wc, R, X, Y); \ + _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \ break; \ \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ @@ -345,6 +345,13 @@ } \ } while (0) +#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+') +#define _FP_SUB(fs, wc, R, X, Y) \ + do { \ + if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \ + _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \ + } while (0) + /* * Main negation routine. FIXME -- when we care about setting exception @@ -382,7 +389,7 @@ break; \ \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ - _FP_CHOOSENAN(fs, wc, R, X, Y); \ + _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \ break; \ \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ @@ -440,7 +447,7 @@ break; \ \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ - _FP_CHOOSENAN(fs, wc, R, X, Y); \ + _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \ break; \ \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/quad.h linux/arch/sparc64/math-emu/quad.h --- v2.3.12/linux/arch/sparc64/math-emu/quad.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/quad.h Mon Aug 2 22:07:16 1999 @@ -108,13 +108,9 @@ _FP_PACK_RAW_4_P(Q,val,X); \ } while (0) -#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X) -#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X) -#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y) -/* single.h and double.h define FP_SUB_t this way too. However, _FP_SUB is - * never defined in op-common.h! Fortunately nobody seems to use the FP_SUB_t - * macros: I suggest a combination of FP_NEG and FP_ADD :-> -- PMM 02/1998 - */ +#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X) +#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X) +#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y) #define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y) #define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y) #define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/math-emu/sfp-machine.h linux/arch/sparc64/math-emu/sfp-machine.h --- v2.3.12/linux/arch/sparc64/math-emu/sfp-machine.h Sat May 29 11:09:04 1999 +++ linux/arch/sparc64/math-emu/sfp-machine.h Mon Aug 2 22:07:16 1999 @@ -29,9 +29,12 @@ #define _FP_WS_TYPE signed long #define _FP_I_TYPE long -#define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y) -#define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm) -#define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide_3mul(Q,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y) @@ -53,7 +56,7 @@ * CPU instruction emulation this should prefer Y. * (see SPAMv9 B.2.2 section). */ -#define _FP_CHOOSENAN(fs, wc, R, X, Y) \ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ do { \ if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ @@ -71,7 +74,7 @@ /* Obtain the current rounding mode. */ #ifndef FP_ROUNDMODE -#define FP_ROUNDMODE ((current->tss.xfsr[0] >> 30) & 0x3) +#define FP_ROUNDMODE ((current->thread.xfsr[0] >> 30) & 0x3) #endif /* Exception flags. */ @@ -83,6 +86,6 @@ #define FP_HANDLE_EXCEPTIONS return _fex -#define FP_INHIBIT_RESULTS ((current->tss.xfsr[0] >> 23) & _fex) +#define FP_INHIBIT_RESULTS ((current->thread.xfsr[0] >> 23) & _fex) #endif diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c --- v2.3.12/linux/arch/sparc64/mm/asyncd.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/mm/asyncd.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.8 1999/07/04 04:35:55 davem Exp $ +/* $Id: asyncd.c,v 1.9 1999/07/30 09:35:43 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. @@ -91,7 +91,8 @@ void async_fault(unsigned long address, int write, int taskid, void (*callback)(int,unsigned long,int,int)) { - struct task_struct *tsk = task[taskid]; +#warning Need some fixing here... -DaveM + struct task_struct *tsk = current /* XXX task[taskid] */; struct mm_struct *mm = tsk->mm; stats.faults++; @@ -111,7 +112,8 @@ { static unsigned last_address; static int last_task, loop_counter; - struct task_struct *tsk = task[taskid]; +#warning Need some fixing here... -DaveM + struct task_struct *tsk = current /* XXX task[taskid] */; pgd_t *pgd; pmd_t *pmd; pte_t *pte; @@ -178,8 +180,8 @@ bad_area: stats.failure++; - tsk->tss.sig_address = address; - tsk->tss.sig_desc = SUBSIG_NOMAPPING; + tsk->thread.sig_address = address; + tsk->thread.sig_desc = SUBSIG_NOMAPPING; send_sig(SIGSEGV, tsk, 1); return 1; } diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.3.12/linux/arch/sparc64/mm/fault.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/mm/fault.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.36 1999/07/04 04:35:56 davem Exp $ +/* $Id: fault.c,v 1.38 1999/08/02 08:39:50 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -84,10 +84,11 @@ printk(KERN_ALERT "Unable to handle kernel paging request " "at virtual address %016lx\n", (unsigned long)address); } - printk(KERN_ALERT "tsk->mm->context = %016lx\n", - (unsigned long) tsk->mm->context); - printk(KERN_ALERT "tsk->mm->pgd = %016lx\n", - (unsigned long) tsk->mm->pgd); + printk(KERN_ALERT "tsk->{mm,active_mm}->context = %016lx\n", + (tsk->mm ? tsk->mm->context : tsk->active_mm->context)); + printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", + (tsk->mm ? (unsigned long) tsk->mm->pgd : + (unsigned long) tsk->active_mm->pgd)); die_if_kernel("Oops", regs); } @@ -159,11 +160,40 @@ down(&mm->mmap_sem); #ifdef DEBUG_LOCKUPS - if (regs->tpc == lastpc && address == lastaddr && write == lastwrite) { + if (regs->tpc == lastpc && + address == lastaddr && + write == lastwrite) { lockcnt++; if (lockcnt == 100000) { - printk("do_sparc64_fault: possible fault loop for %016lx %s\n", address, write ? "write" : "read"); + unsigned char tmp; + register unsigned long tmp1 asm("o5"); + register unsigned long tmp2 asm("o4"); + + printk("do_sparc64_fault[%s:%d]: possible fault loop for %016lx %s\n", + current->comm, current->pid, + address, write ? "write" : "read"); + printk("do_sparc64_fault: CHECK[papgd[%016lx],pcac[%016lx]]\n", + __pa(mm->pgd), pgd_val(mm->pgd[0])<<11UL); + __asm__ __volatile__( + "wrpr %%g0, 0x494, %%pstate\n\t" + "mov %3, %%g4\n\t" + "mov %%g7, %0\n\t" + "ldxa [%%g4] %2, %1\n\t" + "wrpr %%g0, 0x096, %%pstate" + : "=r" (tmp1), "=r" (tmp2) + : "i" (ASI_DMMU), "i" (TSB_REG)); + printk("do_sparc64_fault: IS[papgd[%016lx],pcac[%016lx]]\n", + tmp1, tmp2); + printk("do_sparc64_fault: CHECK[ctx(%016lx)] IS[ctx(%016lx)]\n", + mm->context, spitfire_get_secondary_context()); + __asm__ __volatile__("rd %%asi, %0" + : "=r" (tmp)); + printk("do_sparc64_fault: CHECK[seg(%02x)] IS[seg(%02x)]\n", + current->thread.current_ds.seg, tmp); show_regs(regs); + __sti(); + while(1) + barrier(); } } else { lastpc = regs->tpc; @@ -282,8 +312,8 @@ return; } } else { - current->tss.sig_address = address; - current->tss.sig_desc = SUBSIG_NOMAPPING; + current->thread.sig_address = address; + current->thread.sig_desc = SUBSIG_NOMAPPING; force_sig(SIGSEGV, current); return; } @@ -293,8 +323,8 @@ do_sigbus: up(&mm->mmap_sem); - current->tss.sig_address = address; - current->tss.sig_desc = SUBSIG_MISCERROR; + current->thread.sig_address = address; + current->thread.sig_desc = SUBSIG_MISCERROR; force_sig(SIGBUS, current); if (regs->tstate & TSTATE_PRIV) goto do_kernel_fault; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c --- v2.3.12/linux/arch/sparc64/mm/generic.c Mon Mar 15 16:10:43 1999 +++ linux/arch/sparc64/mm/generic.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: generic.c,v 1.8 1999/03/12 06:51:50 davem Exp $ +/* $Id: generic.c,v 1.9 1999/07/23 22:32:01 davem Exp $ * generic.c: Generic Sparc mm routines that are not dependent upon * MMU type but are Sparc specific. * @@ -95,7 +95,8 @@ space); curend = address + 0x10000; offset += 0x10000; - } + } else + offset += PAGE_SIZE; } else offset += PAGE_SIZE; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.3.12/linux/arch/sparc64/mm/init.c Wed Jun 30 13:38:19 1999 +++ linux/arch/sparc64/mm/init.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.130 1999/06/29 12:34:06 davem Exp $ +/* $Id: init.c,v 1.131 1999/07/30 09:35:45 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -42,7 +42,10 @@ unsigned long phys_base; /* get_new_mmu_context() uses "cache + 1". */ +spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED; unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; +#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6)) +unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; /* References to section boundaries */ extern char __init_begin, __init_end, etext, __bss_start; @@ -386,7 +389,7 @@ dvma_pages_current_offset; /* Map the CPU's view. */ - pgdp = pgd_offset(init_task.mm, addr); + pgdp = pgd_offset(&init_mm, addr); pmdp = pmd_alloc_kernel(pgdp, addr); ptep = pte_alloc_kernel(pmdp, addr); pte = mk_pte(the_page, PAGE_KERNEL); @@ -677,7 +680,7 @@ for (vaddr = trans[i].virt; vaddr < trans[i].virt + trans[i].size; vaddr += PAGE_SIZE) { - pgdp = pgd_offset(init_task.mm, vaddr); + pgdp = pgd_offset(&init_mm, vaddr); if (pgd_none(*pgdp)) { pmdp = sparc_init_alloc(&mempool, PMD_TABLE_SIZE); @@ -739,7 +742,7 @@ int i; if (!enter) - set_fs(current->tss.current_ds); + set_fs(current->thread.current_ds); if (!prom_ditlb_set) return; @@ -957,9 +960,6 @@ : : "r" (pstate)); } -#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6)) -unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; - /* Caller does TLB context flushing on local CPU if necessary. * * We must be careful about boundary cases so that we never @@ -969,14 +969,16 @@ */ void get_new_mmu_context(struct mm_struct *mm) { - unsigned long ctx = (tlb_context_cache + 1) & ~(CTX_VERSION_MASK); - unsigned long new_ctx; + unsigned long ctx, new_ctx; + spin_lock(&ctx_alloc_lock); + ctx = CTX_HWBITS(tlb_context_cache + 1); if (ctx == 0) ctx = 1; - if ((mm->context != NO_CONTEXT) && - !((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK)) - clear_bit(mm->context & ~(CTX_VERSION_MASK), mmu_context_bmap); + if (CTX_VALID(mm->context)) { + unsigned long nr = CTX_HWBITS(mm->context); + mmu_context_bmap[nr>>6] &= ~(1UL << (nr & 63)); + } new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx); if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) { new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); @@ -1003,12 +1005,13 @@ goto out; } } - set_bit(new_ctx, mmu_context_bmap); + mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63)); new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); out: tlb_context_cache = new_ctx; + spin_unlock(&ctx_alloc_lock); + mm->context = new_ctx; - mm->cpu_vm_mask = 0; } #ifndef __SMP__ @@ -1049,7 +1052,7 @@ pte_t *ptep; while (start < end) { - pgdp = pgd_offset(init_task.mm, start); + pgdp = pgd_offset(&init_mm, start); if (pgd_none(*pgdp)) { pmdp = sparc_init_alloc(&mempool, PAGE_SIZE); memset(pmdp, 0, PAGE_SIZE); @@ -1073,7 +1076,7 @@ void sparc_ultra_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus, int rdonly) { - pgd_t *pgdp = pgd_offset(init_task.mm, virt_addr); + pgd_t *pgdp = pgd_offset(&init_mm, virt_addr); pmd_t *pmdp = pmd_offset(pgdp, virt_addr); pte_t *ptep = pte_offset(pmdp, virt_addr); pte_t pte; @@ -1095,7 +1098,7 @@ pmd_t *pmdp; pte_t *ptep; - pgdp = pgd_offset(init_task.mm, virt_addr); + pgdp = pgd_offset(&init_mm, virt_addr); pmdp = pmd_offset(pgdp, virt_addr); ptep = pte_offset(pmdp, virt_addr); diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.3.12/linux/arch/sparc64/mm/ultra.S Sun Mar 28 09:07:47 1999 +++ linux/arch/sparc64/mm/ultra.S Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.32 1999/03/28 08:39:34 davem Exp $ +/* $Id: ultra.S,v 1.33 1999/08/02 08:39:49 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -136,36 +136,37 @@ flush_icache_page: /* %o0 = phys_page */ sethi %hi(1 << 13), %o2 ! IC_set bit mov 1, %g1 - srlx %o0, 5, %o0 ! phys-addr comparitor + srlx %o0, 5, %o0 clr %o1 ! IC_addr sllx %g1, 36, %g1 sub %g1, 1, %g2 - andn %g2, 0xff, %g2 ! IC_tag mask - nop + or %o0, %g1, %o0 ! VALID+phys-addr comparitor + sllx %g2, 1, %g2 + andn %g2, 0xfe, %g2 ! IC_tag mask 1: ldda [%o1] ASI_IC_TAG, %o4 and %o5, %g2, %o5 cmp %o5, %o0 be,pn %xcc, iflush1 - nop + add %o1, 0x20, %g3 2: ldda [%o1 + %o2] ASI_IC_TAG, %o4 and %o5, %g2, %o5 - cmp %o5, %o0 + cmp %o5, %o0 be,pn %xcc, iflush2 nop -3: add %o1, 0x20, %o1 - cmp %o1, %o2 +3: cmp %g3, %o2 bne,pt %xcc, 1b - nop + mov %g3, %o1 retl nop + iflush1:stxa %g0, [%o1] ASI_IC_TAG - ba,pt %xcc, 2b - flush %g6 + flush %g6 + ba,a,pt %xcc, 2b iflush2:stxa %g0, [%o1 + %o2] ASI_IC_TAG - ba,pt %xcc, 3b - flush %g6 + flush %g6 + ba,a,pt %xcc, 3b #ifdef __SMP__ /* These are all called by the slaves of a cross call, at diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c --- v2.3.12/linux/arch/sparc64/prom/p1275.c Tue Oct 27 09:52:21 1998 +++ linux/arch/sparc64/prom/p1275.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: p1275.c,v 1.15 1998/10/13 14:03:47 davem Exp $ +/* $Id: p1275.c,v 1.16 1999/08/02 12:05:57 jj Exp $ * p1275.c: Sun IEEE 1275 PROM low level interface routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -252,8 +252,8 @@ * the counter is needed. -DaveM */ static int prom_entry_depth = 0; -#ifdef __SMP__ static spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED; +#ifdef __SMP__ extern void smp_capture(void); extern void smp_release(void); #endif diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c --- v2.3.12/linux/arch/sparc64/solaris/ioctl.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/solaris/ioctl.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: ioctl.c,v 1.11 1999/05/27 00:36:25 davem Exp $ +/* $Id: ioctl.c,v 1.12 1999/07/23 01:57:03 davem Exp $ * ioctl.c: Solaris ioctl emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -367,7 +367,6 @@ static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg, int len, int *len_p) { - struct inode *ino; int ret; switch (cmd & 0xff) { @@ -459,7 +458,6 @@ mm_segment_t old_fs; struct strioctl si; struct inode *ino; - struct file *filp; struct sol_socket_struct *sock; struct module_info *mi; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c --- v2.3.12/linux/arch/sparc64/solaris/socksys.c Thu Jul 8 15:42:19 1999 +++ linux/arch/sparc64/solaris/socksys.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: socksys.c,v 1.8 1998/08/26 10:28:28 davem Exp $ +/* $Id: socksys.c,v 1.9 1999/07/23 01:57:07 davem Exp $ * socksys.c: /dev/inet/ stuff for Solaris emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- v2.3.12/linux/arch/sparc64/solaris/timod.c Wed Jul 28 14:47:42 1999 +++ linux/arch/sparc64/solaris/timod.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.2 1999/05/12 11:11:55 davem Exp $ +/* $Id: timod.c,v 1.3 1999/08/02 12:06:01 jj Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -33,9 +33,7 @@ u32 arg); asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); -#ifdef __SMP__ spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED; -#endif static char * page = NULL ; #ifndef DEBUG_SOLARIS_KMALLOC @@ -866,7 +864,7 @@ SOLD("entry"); lock_kernel(); - if(fd >= current->files->max_fds) goto out; + if(fd >= NR_OPEN) goto out; filp = current->files->fd[fd]; if(!filp) goto out; @@ -933,7 +931,7 @@ SOLD("entry"); lock_kernel(); - if(fd >= current->files->max_fds) goto out; + if(fd >= NR_OPEN) goto out; filp = current->files->fd[fd]; if(!filp) goto out; diff -u --recursive --new-file v2.3.12/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.3.12/linux/arch/sparc64/vmlinux.lds Tue Aug 4 16:03:35 1998 +++ linux/arch/sparc64/vmlinux.lds Fri Aug 6 11:58:00 1999 @@ -39,8 +39,17 @@ __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup_init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; . = ALIGN(8192); __init_end = .; + . = ALIGN(64); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } __bss_start = .; .sbss : { *(.sbss) *(.scommon) } .bss : diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- v2.3.12/linux/drivers/acorn/block/fd1772.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/block/fd1772.c Mon Aug 2 10:19:52 1999 @@ -116,6 +116,8 @@ * 16/11/96 - Fiddled and frigged for 2.0.18 * * DAG 30/01/99 - Started frobbing for 2.2.1 + * DAG 20/06/99 - A little more frobbing: + * Included include/asm/uaccess.h for get_user/put_user */ #include @@ -142,6 +144,8 @@ #include #include #include +#include + #define MAJOR_NR FLOPPY_MAJOR #define FLOPPY_DMA 0 @@ -1600,7 +1604,7 @@ }; -int floppy_init(void) +int fd1772_init(void) { int i; diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/char/mouse_rpc.c linux/drivers/acorn/char/mouse_rpc.c --- v2.3.12/linux/drivers/acorn/char/mouse_rpc.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/char/mouse_rpc.c Mon Aug 2 10:19:52 1999 @@ -18,7 +18,7 @@ #include #include -#include "../../char/mouse.h" +#include "../../char/busmouse.h" static short old_x, old_y, old_b; static int mousedev; diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- v2.3.12/linux/drivers/acorn/net/ether3.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/net/ether3.c Mon Aug 2 10:19:52 1999 @@ -100,9 +100,17 @@ * The SEEQ8005 doesn't like us writing to it's registers * too quickly. */ -#define ether3_outb(v,r) { outb((v),(r)); udelay(1); } -#define ether3_outw(v,r) { outw((v),(r)); udelay(1); } +static inline void ether3_outb(int v, const int r) +{ + outb(v, r); + udelay(1); +} +static inline void ether3_outw(int v, const int r) +{ + outw(v, r); + udelay(1); +} #define ether3_inb(r) ({ unsigned int __v = inb((r)); udelay(1); __v; }) #define ether3_inw(r) ({ unsigned int __v = inw((r)); udelay(1); __v; }) diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c --- v2.3.12/linux/drivers/acorn/scsi/acornscsi.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/scsi/acornscsi.c Mon Aug 2 10:19:52 1999 @@ -2982,7 +2982,7 @@ p = string; - p += sprintf(string, "%s at port %X irq %d v%d.%d.%d" + p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d" #ifdef CONFIG_SCSI_ACORNSCSI_SYNC " SYNC" #endif diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- v2.3.12/linux/drivers/acorn/scsi/fas216.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/scsi/fas216.c Mon Aug 2 10:19:52 1999 @@ -100,11 +100,16 @@ static void fas216_dumpstate(FAS216_Info *info) { + unsigned char is, stat, inst; + + is = inb(REG_IS(info)); + stat = inb(REG_STAT(info)); + inst = inb(REG_INST(info)); + printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X" " INST=%02X IS=%02X CFIS=%02X", inb(REG_CTCL(info)), inb(REG_CTCM(info)), - inb(REG_CMD(info)), inb(REG_STAT(info)), - inb(REG_INST(info)), inb(REG_IS(info)), + inb(REG_CMD(info)), stat, inst, is, inb(REG_CFIS(info))); printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n", inb(REG_CNTL1(info)), inb(REG_CNTL2(info)), @@ -623,36 +628,18 @@ { unsigned int residual; char *ptr; - int correction = 0; fas216_checkmagic(info, "fas216_pio"); residual = info->scsi.SCp.this_residual; ptr = info->scsi.SCp.ptr; - if (direction == DMA_OUT) { -// while (residual > 0) { -// if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) { - outb(*ptr++, REG_FF(info)); - residual -= 1; -// } -// if (inb(REG_STAT(info)) & STAT_INT) -// break; -// } -// correction = inb(REG_CFIS(info)) & CFIS_CF; - } else { -// while (residual > 0) { -// if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) { - *ptr++ = inb(REG_FF(info)); - residual -= 1; -// } -// if (inb(REG_STAT(info)) & STAT_INT) -// break; -// } - } + if (direction == DMA_OUT) + outb(*ptr++, REG_FF(info)); + else + *ptr++ = inb(REG_FF(info)); - ptr -= correction; - residual += correction; + residual -= 1; if (residual == 0) { if (info->scsi.SCp.buffers_residual) { @@ -1035,26 +1022,59 @@ #endif } -static unsigned char fas216_get_msg_byte(FAS216_Info *info) +static int fas216_wait_cmd(FAS216_Info *info, int cmd) { int tout; + int stat; - outb(CMD_MSGACCEPTED, REG_CMD(info)); - for (tout = 1000000; tout; tout --) - if (inb(REG_STAT(info)) & STAT_INT) + outb(cmd, REG_CMD(info)); + + for (tout = 1000; tout; tout -= 1) { + stat = inb(REG_STAT(info)); + if (stat & STAT_INT) break; + udelay(1); + } + + return stat; +} + +static int fas216_get_msg_byte(FAS216_Info *info) +{ + int stat; + + stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); + + if ((stat & STAT_INT) == 0) + goto timedout; + + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; inb(REG_INST(info)); - outb(CMD_TRANSFERINFO, REG_CMD(info)); + stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); - for (tout = 1000000; tout; tout --) - if (inb(REG_STAT(info)) & STAT_INT) - break; + if ((stat & STAT_INT) == 0) + goto timedout; + + if ((stat & STAT_BUSMASK) != STAT_MESGIN) + goto unexpected_phase_change; inb(REG_INST(info)); return inb(REG_FF(info)); + +timedout: + printk("scsi%d.%c: timed out waiting for message byte\n", + info->host->host_no, fas216_target(info)); + return -1; + +unexpected_phase_change: + printk("scsi%d.%c: unexpected phase change: status = %02X\n", + info->host->host_no, fas216_target(info), stat); + + return -2; } /* Function: void fas216_message(FAS216_Info *info) @@ -1063,20 +1083,33 @@ */ static void fas216_message(FAS216_Info *info) { - unsigned char message[16]; - unsigned int msglen = 1; + unsigned char *message = info->scsi.message; + unsigned int msglen = 1, i; + int msgbyte = 0; fas216_checkmagic(info, "fas216_message"); message[0] = inb(REG_FF(info)); if (message[0] == EXTENDED_MESSAGE) { - message[1] = fas216_get_msg_byte(info); + msgbyte = fas216_get_msg_byte(info); - for (msglen = 2; msglen < message[1] + 2; msglen++) - message[msglen] = fas216_get_msg_byte(info); + if (msgbyte >= 0) { + message[1] = msgbyte; + + for (msglen = 2; msglen < message[1] + 2; msglen++) { + msgbyte = fas216_get_msg_byte(info); + + if (msgbyte >= 0) + message[msglen] = msgbyte; + else + break; + } + } } + info->scsi.msglen = msglen; + #ifdef DEBUG_MESSAGES { int i; @@ -1098,12 +1131,18 @@ switch (message[0]) { case COMMAND_COMPLETE: + if (msglen != 1) + goto unrecognised; + printk(KERN_ERR "scsi%d.%c: command complete with no " "status in MESSAGE_IN?\n", info->host->host_no, fas216_target(info)); break; case SAVE_POINTERS: + if (msglen != 1) + goto unrecognised; + /* * Save current data pointer to SAVED data pointer * SCSI II standard says that we must not acknowledge @@ -1122,6 +1161,9 @@ break; case RESTORE_POINTERS: + if (msglen != 1) + goto unrecognised; + /* * Restore current data pointer from SAVED data pointer */ @@ -1134,10 +1176,16 @@ break; case DISCONNECT: + if (msglen != 1) + goto unrecognised; + info->scsi.phase = PHASE_MSGIN_DISCONNECT; break; case MESSAGE_REJECT: + if (msglen != 1) + goto unrecognised; + switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) { case EXTENDED_MESSAGE | EXTENDED_SDTR << 8: fas216_handlesync(info, message); @@ -1158,13 +1206,19 @@ break; case SIMPLE_QUEUE_TAG: - /* handled above */ + if (msglen < 2) + goto unrecognised; + + /* handled above - print a warning since this is untested */ printk("scsi%d.%c: reconnect queue tag %02X\n", info->host->host_no, fas216_target(info), message[1]); break; case EXTENDED_MESSAGE: + if (msglen < 3) + goto unrecognised; + switch (message[2]) { case EXTENDED_SDTR: /* Sync transfer negociation request/reply */ fas216_handlesync(info, message); @@ -1175,28 +1229,38 @@ break; default: - printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n", - info->host->host_no, fas216_target(info), - message[2]); - goto reject_message; + goto unrecognised; } break; default: - printk("scsi%d.%c: unrecognised message %02X, rejecting\n", - info->host->host_no, fas216_target(info), - message[0]); - goto reject_message; + goto unrecognised; } outb(CMD_MSGACCEPTED, REG_CMD(info)); return; +unrecognised: + printk("scsi%d.%c: unrecognised message, rejecting\n", + info->host->host_no, fas216_target(info)); + printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info)); + for (i = 0; i < msglen; i++) + printk("%s%02X", i & 31 ? " " : "\n ", message[i]); + printk("\n"); + reject_message: + /* + * Something strange seems to be happening here - + * I can't use SETATN since the chip gives me an + * invalid command interrupt when I do. Weird. + */ +outb(CMD_NOP, REG_CMD(info)); +fas216_dumpstate(info); outb(CMD_SETATN, REG_CMD(info)); - outb(CMD_MSGACCEPTED, REG_CMD(info)); msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; +fas216_dumpstate(info); + outb(CMD_MSGACCEPTED, REG_CMD(info)); } /* Function: void fas216_send_command(FAS216_Info *info) @@ -1269,156 +1333,182 @@ printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase); #endif - switch (ssr & IS_BITS) { - case IS_MSGBYTESENT: /* select with ATN and stop steps completed */ - case IS_COMPLETE: /* last action completed */ - outb(CMD_NOP, REG_CMD(info)); + + switch (info->scsi.phase) { + case PHASE_SELECTION: + if ((ssr & IS_BITS) != 1) + goto bad_is; + break; + + case PHASE_SELSTEPS: + switch (ssr & IS_BITS) { + case IS_SELARB: + case IS_MSGBYTESENT: + goto bad_is; + + case IS_NOTCOMMAND: + case IS_EARLYPHASE: + if ((stat & STAT_BUSMASK) == STAT_MESGIN) + break; + goto bad_is; + + case IS_COMPLETE: + break; + } + + default: + break; + } + + outb(CMD_NOP, REG_CMD(info)); #define STATE(st,ph) ((ph) << 3 | (st)) - /* This table describes the legal SCSI state transitions, - * as described by the SCSI II spec. - */ - switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { - /* Reselmsgin -> Data In */ - case STATE(STAT_DATAIN, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ - case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ - case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ - case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ - case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ - fas216_starttransfer(info, DMA_IN, 0); - return; - - case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 0); - return; - - /* Reselmsgin -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ - case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ - fas216_starttransfer(info, DMA_OUT, 1); - return; - - /* Reselmsgin -> Status */ - case STATE(STAT_STATUS, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - goto status; - case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ - case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ - fas216_stoptransfer(info); - case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ - case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ - case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ - case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ - status: - outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); - info->scsi.phase = PHASE_STATUS; - return; - - case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ - case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ - fas216_stoptransfer(info); - case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ - case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - info->scsi.phase = PHASE_MSGIN; - return; - - /* Reselmsgin -> Message In */ - case STATE(STAT_MESGIN, PHASE_RECONNECTED): - case STATE(STAT_MESGIN, PHASE_MSGIN): - info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return; + /* This table describes the legal SCSI state transitions, + * as described by the SCSI II spec. + */ + switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { + /* Reselmsgin -> Data In */ + case STATE(STAT_DATAIN, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ + case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ + case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ + case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ + case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ + fas216_starttransfer(info, DMA_IN, 0); + return; - /* Reselmsgin -> Command */ - case STATE(STAT_COMMAND, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ - case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ - fas216_send_command(info); - info->scsi.phase = PHASE_COMMAND; - return; - /* Selection -> Message Out */ - case STATE(STAT_MESGOUT, PHASE_SELECTION): - fas216_send_messageout(info, 1); - return; - /* Any -> Message Out */ - case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): - fas216_send_messageout(info, 0); - return; - - /* Error recovery rules. - * These either attempt to abort or retry the operation. - * TODO: we need more of these - */ - case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */ - /* error - we've sent out all the command bytes - * we have. - * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS - * to include the command bytes sent for this to work - * correctly. - */ - printk(KERN_ERR "scsi%d.%c: " - "target trying to receive more command bytes\n", - info->host->host_no, fas216_target(info)); - outb(CMD_SETATN, REG_CMD(info)); - outb(15, REG_STCL(info)); - outb(0, REG_STCM(info)); - outb(0, REG_STCH(info)); - outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info)); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - return; + case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ + fas216_starttransfer(info, DMA_OUT, 0); + return; - /* Selection -> Message Out */ - case STATE(STAT_MESGOUT, PHASE_SELSTEPS): - case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */ - /* If we get another message out phase, this - * usually means some parity error occurred. - * Resend complete set of messages. If we have - * more than 1 byte to send, we need to assert - * ATN again. - */ - if (msgqueue_msglength(&info->scsi.msgs) > 1) - outb(CMD_SETATN, REG_CMD(info)); + /* Reselmsgin -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ + case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ + case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ + fas216_starttransfer(info, DMA_OUT, 1); + return; - fas216_send_messageout(info, 0); - return; - } + /* Reselmsgin -> Status */ + case STATE(STAT_STATUS, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + goto status; + case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ + case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ + fas216_stoptransfer(info); + case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ + case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ + case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ + case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ + status: + outb(CMD_INITCMDCOMPLETE, REG_CMD(info)); + info->scsi.phase = PHASE_STATUS; + return; - if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) { - printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - msgqueue_flush(&info->scsi.msgs); + case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ + case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ + fas216_stoptransfer(info); + case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ + case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ + info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + outb(CMD_FLUSHFIFO, REG_CMD(info)); + outb(CMD_TRANSFERINFO, REG_CMD(info)); + info->scsi.phase = PHASE_MSGIN; + return; + + /* Reselmsgin -> Message In */ + case STATE(STAT_MESGIN, PHASE_RECONNECTED): + case STATE(STAT_MESGIN, PHASE_MSGIN): + info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + return; + + /* Reselmsgin -> Command */ + case STATE(STAT_COMMAND, PHASE_RECONNECTED): + fas216_finish_reconnect(info); + case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ + case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ + fas216_send_command(info); + info->scsi.phase = PHASE_COMMAND; + return; + /* Selection -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_SELECTION): + fas216_send_messageout(info, 1); + return; + /* Any -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): + fas216_send_messageout(info, 0); + return; + + /* Error recovery rules. + * These either attempt to abort or retry the operation. + * TODO: we need more of these + */ + case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */ + /* error - we've sent out all the command bytes + * we have. + * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS + * to include the command bytes sent for this to work + * correctly. + */ + printk(KERN_ERR "scsi%d.%c: " + "target trying to receive more command bytes\n", + info->host->host_no, fas216_target(info)); + outb(CMD_SETATN, REG_CMD(info)); + outb(15, REG_STCL(info)); + outb(0, REG_STCM(info)); + outb(0, REG_STCH(info)); + outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info)); + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + return; + + /* Selection -> Message Out */ + case STATE(STAT_MESGOUT, PHASE_SELSTEPS): + case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */ + /* If we get another message out phase, this + * usually means some parity error occurred. + * Resend complete set of messages. If we have + * more than 1 byte to send, we need to assert + * ATN again. + */ + if (msgqueue_msglength(&info->scsi.msgs) > 1) outb(CMD_SETATN, REG_CMD(info)); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - info->scsi.aborting = 1; - outb(CMD_TRANSFERINFO, REG_CMD(info)); - return; - } - printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat), - fas216_drv_phase(info)); - print_debug_list(); + + fas216_send_messageout(info, 0); return; + } - default: - printk("scsi%d.%c: bus service at step %d?\n", + if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) { + printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n", info->host->host_no, fas216_target(info), - ssr & IS_BITS); - print_debug_list(); + fas216_bus_phase(stat)); + msgqueue_flush(&info->scsi.msgs); + outb(CMD_SETATN, REG_CMD(info)); + msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); + info->scsi.phase = PHASE_MSGOUT_EXPECT; + info->scsi.aborting = 1; + outb(CMD_TRANSFERINFO, REG_CMD(info)); + return; } + printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", + info->host->host_no, fas216_target(info), + fas216_bus_phase(stat), + fas216_drv_phase(info)); + print_debug_list(); + return; + +bad_is: + printk("scsi%d.%c: bus service at step %d?\n", + info->host->host_no, fas216_target(info), + ssr & IS_BITS); + print_debug_list(); + + fas216_done(info, DID_ERROR); } /* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) @@ -1895,7 +1985,7 @@ } /* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1, - * Scsi_Cmnd **SCpntp2, int result) + * Scsi_Cmnd **SCpntp2, int result, int no_report) * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 * Params : SCpntp1 - pointer to command to return * SCpntp2 - pointer to command to check @@ -1904,7 +1994,7 @@ * structure as *SCpntp2. */ static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, - int result) + int result, int no_report) { Scsi_Cmnd *SCpnt = *SCpntp1; @@ -1912,7 +2002,8 @@ *SCpntp1 = NULL; SCpnt->result = result; - SCpnt->scsi_done(SCpnt); + if (!no_report || SCpnt != *SCpntp2) + SCpnt->scsi_done(SCpnt); } if (SCpnt == *SCpntp2) @@ -2199,6 +2290,7 @@ FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; Scsi_Cmnd *SCptr; int result = 0; + int synchronous = reset_flags & SCSI_RESET_SYNCHRONOUS; fas216_checkmagic(info, "fas216_reset"); @@ -2258,10 +2350,10 @@ /* * Signal all commands in progress have been reset */ - fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16); + fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16, synchronous); while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL) - fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16); + fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16, synchronous); if (SCpnt) { /* @@ -2274,7 +2366,8 @@ queue_removecmd(&info->queues.issue, SCpnt); SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); + if (!synchronous) + SCpnt->scsi_done(SCpnt); } return result | SCSI_RESET_SUCCESS; diff -u --recursive --new-file v2.3.12/linux/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h --- v2.3.12/linux/drivers/acorn/scsi/fas216.h Thu Jun 17 01:11:35 1999 +++ linux/drivers/acorn/scsi/fas216.h Mon Aug 2 10:19:52 1999 @@ -237,6 +237,8 @@ unsigned int async_stp; /* Async transfer STP value */ unsigned char msgin_fifo; /* bytes in fifo at time of message in */ + unsigned char message[256]; /* last message received from device */ + unsigned int msglen; /* length of last message received */ unsigned char disconnectable:1; /* this command can be disconnected */ unsigned char aborting:1; /* aborting command */ diff -u --recursive --new-file v2.3.12/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.12/linux/drivers/block/Config.in Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/Config.in Thu Aug 5 18:48:45 1999 @@ -43,7 +43,6 @@ bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' Good-Bad DMA Model-Firmware (EXPERIMENTAL)' IDEDMA_NEW_DRIVE_LISTINGS - bool ' Generic ATA-66 support (DANGEROUS)' CONFIG_IDEDMA_ULTRA_66 define_bool IDEDMA_PCI_EXPERIMENTAL y else define_bool IDEDMA_PCI_EXPERIMENTAL n @@ -61,6 +60,7 @@ "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then bool ' HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA fi + bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then @@ -80,6 +80,7 @@ bool ' Special Mode Feature (DANGEROUS)' PDC202XX_FORCE_MASTER_MODE fi fi + bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586 @@ -206,9 +207,11 @@ "$CONFIG_BLK_DEV_CMD640" = "y" -o \ "$CONFIG_BLK_DEV_CY82C693" = "y" -o \ "$CONFIG_BLK_DEV_HPT34X" = "y" -o \ + "$CONFIG_BLK_DEV_HPT366" = "y" -o \ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_OPTI621" = "y" -o \ "$CONFIG_BLK_DEV_PIIX" = "y" -o \ + "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then define_bool CONFIG_BLK_DEV_IDE_MODES y else diff -u --recursive --new-file v2.3.12/linux/drivers/block/MAKEDEV-IDE45 linux/drivers/block/MAKEDEV-IDE45 --- v2.3.12/linux/drivers/block/MAKEDEV-IDE45 Thu May 13 11:00:08 1999 +++ linux/drivers/block/MAKEDEV-IDE45 Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -#!/bin/sh -# -# Andre Hedrick -# -# The song goes, "I did it the hard way..........." -# - -if [ ! -f /dev/hdi ]; then \ - echo "Making IDE4 Primary Devices hdi's"; \ - mknod /dev/hdi b 56 0; \ - mknod /dev/hdi1 b 56 1; \ - mknod /dev/hdi2 b 56 2; \ - mknod /dev/hdi3 b 56 3; \ - mknod /dev/hdi4 b 56 4; \ - mknod /dev/hdi5 b 56 5; \ - mknod /dev/hdi6 b 56 6; \ - mknod /dev/hdi7 b 56 7; \ - mknod /dev/hdi8 b 56 8; \ - mknod /dev/hdi9 b 56 9; \ - mknod /dev/hdi10 b 56 10; \ - mknod /dev/hdi11 b 56 11; \ - mknod /dev/hdi12 b 56 12; \ - mknod /dev/hdi13 b 56 13; \ - mknod /dev/hdi14 b 56 14; \ - mknod /dev/hdi15 b 56 15; \ - mknod /dev/hdi16 b 56 16; \ - chown root.disk /dev/hdi*; \ - chmod 660 /dev/hdi*; \ -fi - -if [ ! -f /dev/hdj ]; then \ - echo "Making IDE4 Secondary Devices hdj's"; \ - mknod /dev/hdj b 56 64; \ - mknod /dev/hdj1 b 56 65; \ - mknod /dev/hdj2 b 56 66; \ - mknod /dev/hdj3 b 56 67; \ - mknod /dev/hdj4 b 56 68; \ - mknod /dev/hdj5 b 56 69; \ - mknod /dev/hdj6 b 56 70; \ - mknod /dev/hdj7 b 56 71; \ - mknod /dev/hdj8 b 56 72; \ - mknod /dev/hdj9 b 56 73; \ - mknod /dev/hdj10 b 56 74; \ - mknod /dev/hdj11 b 56 75; \ - mknod /dev/hdj12 b 56 76; \ - mknod /dev/hdj13 b 56 77; \ - mknod /dev/hdj14 b 56 78; \ - mknod /dev/hdj15 b 56 79; \ - mknod /dev/hdj16 b 56 80; \ - chown root.disk /dev/hdj*; \ - chmod 660 /dev/hdj*; \ -fi - -if [ ! -f /dev/hdk ]; then \ - echo "Making IDE5 Primary Devices hdk's"; \ - mknod /dev/hdk b 57 0; \ - mknod /dev/hdk1 b 57 1; \ - mknod /dev/hdk2 b 57 2; \ - mknod /dev/hdk3 b 57 3; \ - mknod /dev/hdk4 b 57 4; \ - mknod /dev/hdk5 b 57 5; \ - mknod /dev/hdk6 b 57 6; \ - mknod /dev/hdk7 b 57 7; \ - mknod /dev/hdk8 b 57 8; \ - mknod /dev/hdk9 b 57 9; \ - mknod /dev/hdk10 b 57 10; \ - mknod /dev/hdk11 b 57 11; \ - mknod /dev/hdk12 b 57 12; \ - mknod /dev/hdk13 b 57 13; \ - mknod /dev/hdk14 b 57 14; \ - mknod /dev/hdk15 b 57 15; \ - mknod /dev/hdk16 b 57 16; \ - chown root.disk /dev/hdk*; \ - chmod 660 /dev/hdk*; \ -fi - -if [ ! -f /dev/hdl ]; then \ - echo "Making IDE5 Secondary Devices hdl's"; \ - mknod /dev/hdl b 57 64; \ - mknod /dev/hdl1 b 57 65; \ - mknod /dev/hdl2 b 57 66; \ - mknod /dev/hdl3 b 57 67; \ - mknod /dev/hdl4 b 57 68; \ - mknod /dev/hdl5 b 57 69; \ - mknod /dev/hdl6 b 57 70; \ - mknod /dev/hdl7 b 57 71; \ - mknod /dev/hdl8 b 57 72; \ - mknod /dev/hdl9 b 57 73; \ - mknod /dev/hdl10 b 57 74; \ - mknod /dev/hdl11 b 57 75; \ - mknod /dev/hdl12 b 57 76; \ - mknod /dev/hdl13 b 57 77; \ - mknod /dev/hdl14 b 57 78; \ - mknod /dev/hdl15 b 57 79; \ - mknod /dev/hdl16 b 57 80; \ - chown root.disk /dev/hdl*; \ - chmod 660 /dev/hdl*; \ -fi - diff -u --recursive --new-file v2.3.12/linux/drivers/block/MAKEDEV-IDE67 linux/drivers/block/MAKEDEV-IDE67 --- v2.3.12/linux/drivers/block/MAKEDEV-IDE67 Thu May 13 11:00:08 1999 +++ linux/drivers/block/MAKEDEV-IDE67 Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -#!/bin/sh -# -# Andre Hedrick -# -# The song goes, "I did it the hard way..........." -# - -if [ ! -f /dev/hdm ]; then \ - echo "Making IDE6 Primary Devices hdm's"; \ - mknod /dev/hdm b 88 0; \ - mknod /dev/hdm1 b 88 1; \ - mknod /dev/hdm2 b 88 2; \ - mknod /dev/hdm3 b 88 3; \ - mknod /dev/hdm4 b 88 4; \ - mknod /dev/hdm5 b 88 5; \ - mknod /dev/hdm6 b 88 6; \ - mknod /dev/hdm7 b 88 7; \ - mknod /dev/hdm8 b 88 8; \ - mknod /dev/hdm9 b 88 9; \ - mknod /dev/hdm10 b 88 10; \ - mknod /dev/hdm11 b 88 11; \ - mknod /dev/hdm12 b 88 12; \ - mknod /dev/hdm13 b 88 13; \ - mknod /dev/hdm14 b 88 14; \ - mknod /dev/hdm15 b 88 15; \ - mknod /dev/hdm16 b 88 16; \ - chown root.disk /dev/hdm*; \ - chmod 660 /dev/hdm*; \ -fi - -if [ ! -f /dev/hdn ]; then \ - echo "Making IDE6 Secondary Devices hdn's"; \ - mknod /dev/hdn b 88 64; \ - mknod /dev/hdn1 b 88 65; \ - mknod /dev/hdn2 b 88 66; \ - mknod /dev/hdn3 b 88 67; \ - mknod /dev/hdn4 b 88 68; \ - mknod /dev/hdn5 b 88 69; \ - mknod /dev/hdn6 b 88 70; \ - mknod /dev/hdn7 b 88 71; \ - mknod /dev/hdn8 b 88 72; \ - mknod /dev/hdn9 b 88 73; \ - mknod /dev/hdn10 b 88 74; \ - mknod /dev/hdn11 b 88 75; \ - mknod /dev/hdn12 b 88 76; \ - mknod /dev/hdn13 b 88 77; \ - mknod /dev/hdn14 b 88 78; \ - mknod /dev/hdn15 b 88 79; \ - mknod /dev/hdn16 b 88 80; \ - chown root.disk /dev/hdn*; \ - chmod 660 /dev/hdn*; \ -fi - -if [ ! -f /dev/hdo ]; then \ - echo "Making IDE7 Primary Devices hdo's"; \ - mknod /dev/hdo b 89 0; \ - mknod /dev/hdo1 b 89 1; \ - mknod /dev/hdo2 b 89 2; \ - mknod /dev/hdo3 b 89 3; \ - mknod /dev/hdo4 b 89 4; \ - mknod /dev/hdo5 b 89 5; \ - mknod /dev/hdo6 b 89 6; \ - mknod /dev/hdo7 b 89 7; \ - mknod /dev/hdo8 b 89 8; \ - mknod /dev/hdo9 b 89 9; \ - mknod /dev/hdo10 b 89 10; \ - mknod /dev/hdo11 b 89 11; \ - mknod /dev/hdo12 b 89 12; \ - mknod /dev/hdo13 b 89 13; \ - mknod /dev/hdo14 b 89 14; \ - mknod /dev/hdo15 b 89 15; \ - mknod /dev/hdo16 b 89 16; \ - chown root.disk /dev/hdo*; \ - chmod 660 /dev/hdo*; \ -fi - -if [ ! -f /dev/hdp ]; then \ - echo "Making IDE7 Secondary Devices hdp's"; \ - mknod /dev/hdp b 89 64; \ - mknod /dev/hdp1 b 89 65; \ - mknod /dev/hdp2 b 89 66; \ - mknod /dev/hdp3 b 89 67; \ - mknod /dev/hdp4 b 89 68; \ - mknod /dev/hdp5 b 89 69; \ - mknod /dev/hdp6 b 89 70; \ - mknod /dev/hdp7 b 89 71; \ - mknod /dev/hdp8 b 89 72; \ - mknod /dev/hdp9 b 89 73; \ - mknod /dev/hdp10 b 89 74; \ - mknod /dev/hdp11 b 89 75; \ - mknod /dev/hdp12 b 89 76; \ - mknod /dev/hdp13 b 89 77; \ - mknod /dev/hdp14 b 89 78; \ - mknod /dev/hdp15 b 89 79; \ - mknod /dev/hdp16 b 89 80; \ - chown root.disk /dev/hdp*; \ - chmod 660 /dev/hdp*; \ -fi - diff -u --recursive --new-file v2.3.12/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.3.12/linux/drivers/block/Makefile Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/Makefile Thu Aug 5 18:48:45 1999 @@ -94,116 +94,136 @@ endif endif -ifeq ($(CONFIG_BLK_DEV_HD),y) -L_OBJS += hd.o +# +# IDE-STUFF +# + +ifeq ($(CONFIG_BLK_DEV_AEC6210),y) +IDE_OBJS += aec6210.o endif -ifeq ($(CONFIG_BLK_DEV_RZ1000),y) -IDE_OBJS += rz1000.o +ifeq ($(CONFIG_BLK_DEV_ALI14XX),y) +IDE_OBJS += ali14xx.o endif -ifeq ($(CONFIG_BLK_DEV_CMD640),y) -IDE_OBJS += cmd640.o +ifeq ($(CONFIG_BLK_DEV_ALI15X3),y) +IDE_OBJS += alim15x3.o endif -ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y) -IDE_OBJS += ide-pmac.o +ifeq ($(CONFIG_BLK_DEV_BUDDHA),y) +IDE_OBJS += buddha.o endif -ifeq ($(CONFIG_BLK_DEV_IDEPCI),y) -IDE_OBJS += ide-pci.o +ifeq ($(CONFIG_BLK_DEV_CMD640),y) +IDE_OBJS += cmd640.o endif -ifeq ($(CONFIG_BLK_DEV_IDEDMA),y) -IDE_OBJS += ide-dma.o +ifeq ($(CONFIG_BLK_DEV_CMD646),y) +IDE_OBJS += cmd646.o +endif + +ifeq ($(CONFIG_BLK_DEV_CY82C693),y) +IDE_OBJS += cy82c693.o endif ifeq ($(CONFIG_BLK_DEV_DTC2278),y) IDE_OBJS += dtc2278.o endif -ifeq ($(CONFIG_BLK_DEV_HT6560B),y) -IDE_OBJS += ht6560b.o +ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y) +IDE_OBJS += falconide.o endif -ifeq ($(CONFIG_BLK_DEV_QD6580),y) -IDE_OBJS += qd6580.o +ifeq ($(CONFIG_BLK_DEV_GAYLE),y) +IDE_OBJS += gayle.o endif -ifeq ($(CONFIG_BLK_DEV_UMC8672),y) -IDE_OBJS += umc8672.o +ifeq ($(CONFIG_BLK_DEV_HD),y) +L_OBJS += hd.o endif -ifeq ($(CONFIG_BLK_DEV_ALI14XX),y) -IDE_OBJS += ali14xx.o +ifeq ($(CONFIG_BLK_DEV_HPT34X),y) +IDE_OBJS += hpt34x.o endif -ifeq ($(CONFIG_BLK_DEV_PDC4030),y) -IDE_OBJS += pdc4030.o +ifeq ($(CONFIG_BLK_DEV_HPT366),y) +IDE_OBJS += hpt366.o endif -ifeq ($(CONFIG_BLK_DEV_TRM290),y) -IDE_OBJS += trm290.o +ifeq ($(CONFIG_BLK_DEV_HT6560B),y) +IDE_OBJS += ht6560b.o endif -ifeq ($(CONFIG_BLK_DEV_OPTI621),y) -IDE_OBJS += opti621.o +ifeq ($(CONFIG_BLK_DEV_IDEDMA),y) +IDE_OBJS += ide-dma.o +endif + +ifeq ($(CONFIG_BLK_DEV_IDEPCI),y) +IDE_OBJS += ide-pci.o +endif + +ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y) +IDE_OBJS += ide-pmac.o +endif + +ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y) +IDE_OBJS += macide.o endif ifeq ($(CONFIG_BLK_DEV_NS87415),y) IDE_OBJS += ns87415.o endif -ifeq ($(CONFIG_BLK_DEV_VIA82C586),y) -IDE_OBJS += via82c586.o +ifeq ($(CONFIG_BLK_DEV_OPTI621),y) +IDE_OBJS += opti621.o endif -ifeq ($(CONFIG_BLK_DEV_GAYLE),y) -IDE_OBJS += gayle.o +ifeq ($(CONFIG_BLK_DEV_PDC202XX),y) +IDE_OBJS += pdc202xx.o endif -ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y) -IDE_OBJS += falconide.o +ifeq ($(CONFIG_BLK_DEV_PDC4030),y) +IDE_OBJS += pdc4030.o endif -ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y) -IDE_OBJS += macide.o +ifeq ($(CONFIG_BLK_DEV_PIIX),y) +IDE_OBJS += piix.o endif -ifeq ($(CONFIG_BLK_DEV_BUDDHA),y) -IDE_OBJS += buddha.o +ifeq ($(CONFIG_BLK_DEV_QD6580),y) +IDE_OBJS += qd6580.o endif -ifeq ($(CONFIG_BLK_DEV_CMD646),y) -IDE_OBJS += cmd646.o +ifeq ($(CONFIG_BLK_DEV_RZ1000),y) +IDE_OBJS += rz1000.o endif -ifeq ($(CONFIG_BLK_DEV_SL82C105),y) -IDE_OBJS += sl82c105.o +ifeq ($(CONFIG_BLK_DEV_SIS5513),y) +IDE_OBJS += sis5513.o endif -ifeq ($(CONFIG_BLK_DEV_ALI15X3),y) -IDE_OBJS += alim15x3.o +ifeq ($(CONFIG_BLK_DEV_SL82C105),y) +IDE_OBJS += sl82c105.o endif -ifeq ($(CONFIG_BLK_DEV_CY82C693),y) -IDE_OBJS += cy82c693.o +ifeq ($(CONFIG_BLK_DEV_TRM290),y) +IDE_OBJS += trm290.o endif -ifeq ($(CONFIG_BLK_DEV_PIIX),y) -IDE_OBJS += piix.o +ifeq ($(CONFIG_BLK_DEV_UMC8672),y) +IDE_OBJS += umc8672.o endif -ifeq ($(CONFIG_BLK_DEV_PDC202XX),y) -IDE_OBJS += pdc202xx.o +ifeq ($(CONFIG_BLK_DEV_VIA82C586),y) +IDE_OBJS += via82c586.o endif -ifeq ($(CONFIG_BLK_DEV_AEC6210),y) -IDE_OBJS += aec6210.o +ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y) +IDE_OBJS += icside.o endif -ifeq ($(CONFIG_BLK_DEV_HPT34X),y) -IDE_OBJS += hpt34x.o +ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y) +IDE_OBJS += rapide.o endif ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored diff -u --recursive --new-file v2.3.12/linux/drivers/block/README.buddha linux/drivers/block/README.buddha --- v2.3.12/linux/drivers/block/README.buddha Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/README.buddha Mon Aug 9 12:32:28 1999 @@ -0,0 +1,210 @@ + +The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by +Geert Uytterhoeven based on the following specifications: + +------------------------------------------------------------------------ + +Register map of the Buddha IDE controller and the +Buddha-part of the Catweasel Zorro-II version + +The Autoconfiguration has been implemented just as Commodore +described in their manuals, no tricks have been used (for +example leaving some address lines out of the equations...). +If you want to configure the board yourself (for example let +a Linux kernel configure the card), look at the Commodore +Docs. Reading the nibbles should give this information: + +Vendor number: 4626 ($1212) +product number: 0 (42 for Catweasel Z-II) +Serial number: 0 +Rom-vector: $1000 + +The card should be a Z-II board, size 64K, not for freemem +list, Rom-Vektor is valid, no second Autoconfig-board on the +same card, no space preferrence, supports "Shutup_forever". + +Setting the base address should be done in two steps, just +as the Amiga Kickstart does: The lower nibble of the 8-Bit +address is written to $4a, then the whole Byte is written to +$48, while it doesn't matter how often you're writing to $4a +as long as $48 is not touched. After $48 has been written, +the whole card disappears from $e8 and is mapped to the new +addrress just written. Make shure $4a is written befor $48, +otherwise your chance is only 1:16 to find the board :-). + +The local memory-map is even active when mapped to $e8: + +$0-$7e Autokonfig-space, see Z-II docs. + +$80-$7fd reserved + +$7fe Speed-select Register: Read & Write + (description see further down) + +$800-$8ff IDE-Select 0 (Port 0, Register set 0) + +$900-$9ff IDE-Select 1 (Port 0, Register set 1) + +$a00-$aff IDE-Select 2 (Port 1, Register set 0) + +$b00-$bff IDE-Select 3 (Port 1, Register set 1) + +$c00-$cff IDE-Select 4 (Port 2, Register set 0, + Catweasel only!) + +$d00-$dff IDE-Select 5 (Port 3, Register set 1, + Catweasel only!) + +$e00-$eff local expansion port, on Catweasel Z-II the + Catweasel registers are also mapped here. + Never touch, use multidisk.device! + +$f00 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 0. + +$f01-$f3f mirror of $f00 + +$f40 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 1. + +$f41-$f7f mirror of $f40 + +$f80 read only, Byte-access: Bit 7 shows the + level of the IRQ-line of IDE port 2. + (Catweasel only!) + +$f81-$fbf mirror of $f80 + +$fc0 write-only: Writing any value to this + register enables IRQs to be passed from the + IDE ports to the Zorro bus. This mechanism + has been implemented to be compatible with + harddisks that are either defective or have + a buggy firmware and pull the IRQ line up + while starting up. If interrupts would + always be passed to the bus, the computer + might not start up. Once enabled, this flag + can not be disabled again. The level of the + flag can not be determined by software + (what for? Write to me if it's necessary!). + +$fc1-$fff mirror of $fc0 + +$1000-$ffff Buddha-Rom with offset $1000 in the rom + chip. The addresses $0 to $fff of the rom + chip cannot be read. Rom is Byte-wide and + mapped to even addresses. + +The IDE ports issue an INT2. You can read the level of the +IRQ-lines of the IDE-ports by reading from the three (two +for Buddha-only) registers $f00, $f40 and $f80. This way +more than one I/O request can be handled and you can easily +determine what driver has to serve the INT2. Buddha and +Catweasel expansion boards can issue an INT6. A seperate +memory map is available for the I/O module and the sysop's +I/O module. + +The IDE ports are fed by the address lines A2 to A4, just as +the Amiga 1200 and Amiga 4000 IDE ports are. This way +existing drivers can be easily ported to Buddha. A move.l +polls two words out of the same address of IDE port since +every word is mirrored once. movem is not possible, but +it's not necessary either, because you can only speedup +68000 systems with this technique. A 68020 system with +fastmem is faster with move.l. + +If you're using the mirrored registers of the IDE-ports with +A6=1, the Buddha doesn't care about the speed that you have +selected in the speed register (see further down). With +A6=1 (for example $840 for port 0, register set 0), a 780ns +access is being made. These registers should be used for a +command access to the harddisk/CD-Rom, since command +accesses are Byte-wide and have to be made slower according +to the ATA-X3T9 manual. + +Now for the speed-register: The register is byte-wide, and +only the upper three bits are used (Bits 7 to 5). Bit 4 +must always be set to 1 to be compatible with later Buddha +versions (if I'll ever update this one). I presume that +I'll never use the lower four bits, but they have to be set +to 1 by definition. + The values in this table have to be shifted 5 bits to the +left and or'd with $1f (this sets the lower 5 bits). + +All the timings have in common: Select and IOR/IOW rise at +the same time. IOR and IOW have a propagation delay of +about 30ns to the clocks on the Zorro bus, that's why the +values are no multiple of 71. One clock-cycle is 71ns long +(exactly 70,5 at 14,18 Mhz on PAL systems). + +value 0 (Default after reset) + +497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles) +(same timing as the Amiga 1200 does on it's IDE port without +accelerator card) + +value 1 + +639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles) + +value 2 + +781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles) + +value 3 + +355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) + +value 4 + +355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles) + +value 5 + +355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles) + +value 6 + +1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles) + +value 7 + +355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle) + +When accessing IDE registers with A6=1 (for example $84x), +the timing will always be mode 0 8-bit compatible, no matter +what you have selected in the speed register: + +781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive. + +All the timings with a very short select-signal (the 355ns +fast accesses) depend on the accelerator card used in the +system: Sometimes two more clock cycles are inserted by the +bus interface, making the whole access 497ns long. This +doesn't affect the reliability of the controller nor the +performance of the card, since this doesn't happen very +often. + +All the timings are calculated and only confirmed by +measurements that allowed me to count the clock cycles. If +the system is clocked by an oscillator other than 28,37516 +Mhz (for example the NTSC-frequency 28,63636 Mhz), each +clock cycle is shortened to a bit less than 70ns (not worth +mentioning). You could think of a small performance boost +by overclocking the system, but you would either need a +multisync monitor, or a graphics card, and your internal +diskdrive would go crazy, that's why you shouldn't tune your +Amiga this way. + +Giving you the possibility to write software that is +compatible with both the Buddha and the Catweasel Z-II, The +Buddha acts just like a Catweasel Z-II with no device +connected to the third IDE-port. The IRQ-register $f80 +always shows a "no IRQ here" on the Buddha, and accesses to +the third IDE port are going into data's Nirwana on the +Buddha. + + Jens Schönfeld february 19th, 1997 + updated may 27th, 1997 + eMail: sysop@nostlgic.tng.oche.de + diff -u --recursive --new-file v2.3.12/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.3.12/linux/drivers/block/acsi.c Sat May 15 23:43:04 1999 +++ linux/drivers/block/acsi.c Mon Aug 9 12:32:28 1999 @@ -253,17 +253,8 @@ static char *CurrentBuffer; -#define SET_TIMER() \ - do { \ - del_timer( &acsi_timer ); \ - acsi_timer.expires = jiffies + ACSI_TIMEOUT; \ - add_timer( &acsi_timer ); \ - } while(0) - -#define CLEAR_TIMER() \ - do { \ - del_timer( &acsi_timer ); \ - } while(0) +#define SET_TIMER() mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT) +#define CLEAR_TIMER() del_timer(&acsi_timer) static unsigned long STramMask; #define STRAM_ADDR(a) (((a) & STramMask) == 0) @@ -425,8 +416,8 @@ { if (INT_LEVEL < 6) { - unsigned long maxjif; - for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); ) + unsigned long maxjif = jiffies + timeout; + while (time_before(jiffies, maxjif)) if (!(mfp.par_dt_reg & 0x20)) return( 1 ); } else { @@ -442,8 +433,8 @@ { if (INT_LEVEL < 6) { - unsigned long maxjif; - for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); ) + unsigned long maxjif = jiffies + timeout; + while (time_before(jiffies, maxjif)) if (mfp.par_dt_reg & 0x20) return( 1 ); } else { @@ -502,7 +493,7 @@ #endif rwflag = rwflag ? 0x100 : 0; - paddr = VTOP( buffer ); + paddr = virt_to_phys( buffer ); acsi_delay_end(COMMAND_DELAY); DISABLE_IRQ(); @@ -610,7 +601,7 @@ if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 ); if (!acsi_wait_for_IRQ( 10 )) return( 0 ); acsi_getstatus(); - dma_cache_maintenance( VTOP(buffer), 16, 0 ); + dma_cache_maintenance( virt_to_phys(buffer), 16, 0 ); return( 1 ); } @@ -809,7 +800,7 @@ return; } - dma_cache_maintenance( VTOP(CurrentBuffer), CurrentNSect*512, 0 ); + dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 ); if (CurrentBuffer == acsi_buffer) copy_from_acsibuffer(); @@ -1030,7 +1021,7 @@ * consecutive buffers and thus can be done with a single command. */ buffer = CURRENT->buffer; - pbuffer = VTOP(buffer); + pbuffer = virt_to_phys(buffer); nsect = CURRENT->current_nr_sectors; CurrentNReq = 1; @@ -1052,7 +1043,7 @@ unsigned long pendadr, pnewadr; pendadr = pbuffer + nsect*512; while( (bh = bh->b_reqnext) ) { - pnewadr = VTOP(bh->b_data); + pnewadr = virt_to_phys(bh->b_data); if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break; nsect += bh->b_size >> 9; pendadr = pnewadr + bh->b_size; @@ -1814,7 +1805,7 @@ unregister_blkdev( MAJOR_NR, "ad" ); return -ENOMEM; } - phys_acsi_buffer = VTOP( acsi_buffer ); + phys_acsi_buffer = virt_to_phys( acsi_buffer ); STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; diff -u --recursive --new-file v2.3.12/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c --- v2.3.12/linux/drivers/block/acsi_slm.c Tue May 11 23:33:00 1999 +++ linux/drivers/block/acsi_slm.c Mon Aug 9 12:32:28 1999 @@ -413,8 +413,8 @@ CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun ); cmd = slmprint_cmd; - paddr = VTOP( SLMBuffer ); - dma_cache_maintenance( paddr, VTOP(BufferP)-paddr, 1 ); + paddr = virt_to_phys( SLMBuffer ); + dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 ); DISABLE_IRQ(); /* Low on A1 */ @@ -466,7 +466,7 @@ addr = get_dma_addr(); stat = acsi_getstatus(); SLMError = (stat < 0) ? SLMSTAT_ACSITO : - (addr < VTOP(BufferP)) ? SLMSTAT_NOTALL : + (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL : stat; dma_wd.dma_mode_status = 0x80; diff -u --recursive --new-file v2.3.12/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c --- v2.3.12/linux/drivers/block/aec6210.c Wed May 26 16:55:40 1999 +++ linux/drivers/block/aec6210.c Thu Aug 5 18:48:45 1999 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998 + * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998 * - * Copyright (C) 1998 Andre Hedrick (hedrick@astro.dyer.vanderbilt.edu) + * Copyright (C) 1998-99 Andre Hedrick * * pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02 * pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02 @@ -31,7 +31,6 @@ * NO-Devices * 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02 * 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00 - */ #include @@ -54,10 +53,8 @@ __initfunc(unsigned int pci_init_aec6210 (struct pci_dev *dev, const char *name)) { if (dev->rom_address) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - dev->rom_address | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", - name, dev->rom_address); + pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE); + printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address); } return dev->irq; } diff -u --recursive --new-file v2.3.12/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.3.12/linux/drivers/block/ataflop.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/ataflop.c Mon Aug 9 12:32:28 1999 @@ -215,11 +215,10 @@ * restored upon disk change by floppy_revalidate() if valid (as seen by * default_params[].blocks > 0 - a bit in unit[].flags might be used for this?) */ -static struct atari_disk_type default_params[FD_MAX_UNITS] = { - { NULL, 0, 0, 0, 0}, }; +static struct atari_disk_type default_params[FD_MAX_UNITS]; static int floppy_sizes[256]; -static int floppy_blocksizes[256] = { 0, }; +static int floppy_blocksizes[256]; /* current info on each unit */ static struct atari_floppy_struct { @@ -331,26 +330,6 @@ * will give up. */ -#define START_MOTOR_OFF_TIMER(delay) \ - do { \ - motor_off_timer.expires = jiffies + (delay); \ - add_timer( &motor_off_timer ); \ - MotorOffTrys = 0; \ - } while(0) - -#define START_CHECK_CHANGE_TIMER(delay) \ - do { \ - timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \ - timer_active |= (1 << FLOPPY_TIMER); \ - } while(0) - -#define START_TIMEOUT() \ - mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT) - -#define STOP_TIMEOUT() \ - del_timer(&timeout_timer) - - /* * The driver is trying to determine the correct media format * while Probing is set. fd_rwsec_done() clears it after a @@ -420,6 +399,31 @@ { NULL, NULL, 0, 0, fd_times_out }; +static inline void +start_motor_off_timer(void) +{ + mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY); + MotorOffTrys = 0; +} + +static inline void +start_check_change_timer(void) +{ + timer_table[FLOPPY_TIMER].expires = jiffies + CHECK_CHANGE_DELAY; + timer_active |= (1 << FLOPPY_TIMER); +} + +static inline void +start_timeout(void) +{ + mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT); +} + +static inline void +stop_timeout(void) +{ + del_timer(&timeout_timer); +} /* Select the side to use. */ @@ -497,19 +501,12 @@ static void fd_motor_off_timer( unsigned long dummy ) { -/* unsigned long flags; */ unsigned char status; - int delay; - del_timer( &motor_off_timer ); - if (SelectedDrive < 0) /* no drive selected, needn't deselect anyone */ return; -/* save_flags(flags); - cli(); */ - if (stdma_islocked()) goto retry; @@ -519,21 +516,18 @@ /* motor already turned off by FDC -> deselect drives */ MotorOn = 0; fd_deselect(); -/* restore_flags(flags); */ return; } /* not yet off, try again */ retry: -/* restore_flags(flags); */ /* Test again later; if tested too often, it seems there is no disk * in the drive and the FDC will leave the motor on forever (or, * at least until a disk is inserted). So we'll test only twice * per second from then on... */ - delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ? - (++MotorOffTrys, HZ/20) : HZ/2; - START_MOTOR_OFF_TIMER( delay ); + mod_timer(&motor_off_timer, + jiffies + (MotorOffTrys++ < FD_MOTOR_OFF_MAXTRY ? HZ/20 : HZ/2)); } @@ -571,7 +565,7 @@ } restore_flags(flags); - START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); + start_check_change_timer(); } @@ -603,8 +597,7 @@ unsigned char status; void (*handler)( int ); - handler = FloppyIRQHandler; - FloppyIRQHandler = NULL; + handler = xchg(&FloppyIRQHandler, NULL); if (handler) { nop(); @@ -805,7 +798,7 @@ NeedSeek = 1; MotorOn = 1; - START_TIMEOUT(); + start_timeout(); /* wait for IRQ */ } @@ -813,7 +806,7 @@ static void fd_calibrate_done( int status ) { DPRINT(("fd_calibrate_done()\n")); - STOP_TIMEOUT(); + stop_timeout(); /* set the correct speed now */ if (ATARIHW_PRESENT(FDCSPEED)) @@ -853,7 +846,7 @@ MotorOn = 1; set_head_settle_flag(); - START_TIMEOUT(); + start_timeout(); /* wait for IRQ */ } @@ -861,7 +854,7 @@ static void fd_seek_done( int status ) { DPRINT(("fd_seek_done()\n")); - STOP_TIMEOUT(); + stop_timeout(); /* set the correct speed */ if (ATARIHW_PRESENT(FDCSPEED)) @@ -900,7 +893,7 @@ DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' )); if (ReqCmd == WRITE) { if (ATARIHW_PRESENT(EXTD_DMA)) { - paddr = (unsigned long)VTOP(ReqData); + paddr = virt_to_phys(ReqData); } else { copy_buffer( ReqData, DMABuffer ); @@ -913,7 +906,8 @@ if (read_track) paddr = PhysTrackBuffer; else - paddr = ATARIHW_PRESENT(EXTD_DMA) ? VTOP(ReqData) : PhysDMABuffer; + paddr = ATARIHW_PRESENT(EXTD_DMA) ? + virt_to_phys(ReqData) : PhysDMABuffer; rwflag = 0; } @@ -978,14 +972,12 @@ * search for the first non-existent sector and need 1 sec to * recognise that it isn't present :-( */ - del_timer (&readtrack_timer); - readtrack_timer.expires = - jiffies + HZ/5 + (old_motoron ? 0 : HZ); - /* 1 rot. + 5 rot.s if motor was off */ MultReadInProgress = 1; - add_timer( &readtrack_timer ); + mod_timer(&readtrack_timer, + /* 1 rot. + 5 rot.s if motor was off */ + jiffies + HZ/5 + (old_motoron ? 0 : HZ)); } - START_TIMEOUT(); + start_timeout(); } @@ -996,8 +988,6 @@ save_flags(flags); cli(); - del_timer( &readtrack_timer ); - if (!MultReadInProgress) { /* This prevents a race condition that could arise if the * interrupt is triggered while the calling of this timer @@ -1045,8 +1035,7 @@ /* not yet finished, wait another tenth rotation */ restore_flags(flags); DPRINT(("fd_readtrack_check(): not yet finished\n")); - readtrack_timer.expires = jiffies + HZ/5/10; - add_timer( &readtrack_timer ); + mod_timer(&readtrack_timer, jiffies + HZ/5/10); } } @@ -1068,7 +1057,7 @@ { unsigned int track; - STOP_TIMEOUT(); + stop_timeout(); /* Correct the track if stretch != 0 */ if (SUDT->stretch) { @@ -1150,7 +1139,7 @@ if (!read_track) { void *addr; addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer; - dma_cache_maintenance( VTOP(addr), 512, 0 ); + dma_cache_maintenance( virt_to_phys(addr), 512, 0 ); if (!ATARIHW_PRESENT( EXTD_DMA )) copy_buffer (addr, ReqData); } else { @@ -1237,7 +1226,7 @@ dma_wd.fdc_acces_seccount = FDCCMD_WRTRA | get_head_settle_flag(); MotorOn = 1; - START_TIMEOUT(); + start_timeout(); /* wait for interrupt */ } @@ -1246,7 +1235,7 @@ { DPRINT(("fd_writetrack_done()\n")); - STOP_TIMEOUT(); + stop_timeout(); if (status & FDCSTAT_WPROT) { printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive ); @@ -1304,7 +1293,7 @@ SET_IRQ_HANDLER( finish_fdc_done ); FDC_WRITE (FDCREG_CMD, FDCCMD_SEEK); MotorOn = 1; - START_TIMEOUT(); + start_timeout(); /* we must wait for the IRQ here, because the ST-DMA is released immediately afterwards and the interrupt may be delivered to the wrong driver. */ @@ -1317,19 +1306,18 @@ unsigned long flags; DPRINT(("finish_fdc_done entered\n")); - STOP_TIMEOUT(); + stop_timeout(); NeedSeek = 0; if ((timer_active & (1 << FLOPPY_TIMER)) && - timer_table[FLOPPY_TIMER].expires < jiffies + 5) + time_before(timer_table[FLOPPY_TIMER].expires, jiffies + 5)) /* If the check for a disk change is done too early after this * last seek command, the WP bit still reads wrong :-(( */ timer_table[FLOPPY_TIMER].expires = jiffies + 5; else - START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); - del_timer( &motor_off_timer ); - START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY ); + start_check_change_timer(); + start_motor_off_timer(); save_flags(flags); cli(); @@ -1828,10 +1816,10 @@ FDC_WRITE (FDCREG_TRACK, 0xff00); FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 ); - for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; time_before(jiffies, timeout); ) { + timeout = jiffies + 2*HZ+HZ/2; + while (time_before(jiffies, timeout)) if (!(mfp.par_dt_reg & 0x20)) break; - } status = FDC_READ( FDCREG_STATUS ); ok = (status & FDCSTAT_TR00) != 0; @@ -1892,9 +1880,9 @@ } if (cnt > 0) { - START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY ); + start_motor_off_timer(); if (cnt == 1) fd_select_drive( 0 ); - START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); + start_check_change_timer(); } } @@ -2045,8 +2033,8 @@ return -ENOMEM; } TrackBuffer = DMABuffer + 512; - PhysDMABuffer = (unsigned long) VTOP(DMABuffer); - PhysTrackBuffer = (unsigned long) VTOP(TrackBuffer); + PhysDMABuffer = virt_to_phys(DMABuffer); + PhysTrackBuffer = virt_to_phys(TrackBuffer); BufferDrive = BufferSide = BufferTrack = -1; for (i = 0; i < FD_MAX_UNITS; i++) { diff -u --recursive --new-file v2.3.12/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c --- v2.3.12/linux/drivers/block/cmd646.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/cmd646.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: cmd646.c,v 1.14 1999/07/03 08:56:09 davem Exp $ +/* $Id: cmd646.c,v 1.15 1999/07/23 01:48:37 davem Exp $ * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because * there the "BIOS" has done all of the following already. diff -u --recursive --new-file v2.3.12/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.3.12/linux/drivers/block/cpqarray.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/cpqarray.c Thu Aug 5 15:04:42 1999 @@ -631,7 +631,7 @@ irq = pdev->irq; for(i=0; i<6; i++) - addr[i] = pdev->base_address[i]; + addr[i] = pdev->resource[i].flags; (void) pcibios_read_config_word(bus, device_fn, PCI_COMMAND,&command); @@ -665,7 +665,7 @@ */ for(i=0; i<6; i++) if (!(addr[i] & 0x1)) { - c->paddr = addr[i]; + c->paddr = pdev->resource[i].start; break; } c->vaddr = remap_pci_mem(c->paddr, 128); diff -u --recursive --new-file v2.3.12/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.3.12/linux/drivers/block/floppy.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/floppy.c Fri Aug 6 11:43:09 1999 @@ -330,7 +330,6 @@ #define SEL_DLY (2*HZ/100) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* * this struct defines the different floppy drive types. */ @@ -4063,10 +4062,13 @@ { "L40SX", 0, &print_unex, 0, 0 } }; #define FLOPPY_SETUP -void __init floppy_setup(char *str, int *ints) +void __init floppy_setup(char *str) { int i; int param; + int ints[11]; + + str = get_options(str,ARRAY_SIZE(ints),ints); if (str) { for (i=0; i< ARRAY_SIZE(config_params); i++){ if (strcmp(str,config_params[i].name) == 0){ @@ -4358,8 +4360,6 @@ #ifdef MODULE -extern char *get_options(char *str, int *ints); - char *floppy=NULL; static void __init parse_floppy_cfg_string(char *cfg) @@ -4374,18 +4374,17 @@ cfg++; } if(*ptr) - floppy_setup(get_options(ptr,ints),ints); + floppy_setup(ptr); } } -static void __init mod_setup(char *pattern, void (*setup)(char *, int *)) +static void __init mod_setup(char *pattern, void (*setup)(char *)) { unsigned long i; char c; int j; int match; char buffer[100]; - int ints[11]; int length = strlen(pattern)+1; match=0; @@ -4400,7 +4399,7 @@ if (!c || c == ' ' || c == '\t'){ if (j){ buffer[j] = '\0'; - setup(get_options(buffer,ints),ints); + setup(buffer); } j=0; } else diff -u --recursive --new-file v2.3.12/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.3.12/linux/drivers/block/genhd.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/genhd.c Fri Aug 6 10:49:54 1999 @@ -85,6 +85,10 @@ * This requires special handling here. */ switch (hd->major) { + case IDE9_MAJOR: + unit += 2; + case IDE8_MAJOR: + unit += 2; case IDE7_MAJOR: unit += 2; case IDE6_MAJOR: @@ -1383,7 +1387,7 @@ resetup_one_dev(dev, drive); } -void __init device_setup(void) +static int __init device_setup(void) { extern void console_map_init(void); extern void cpqarray_init(void); @@ -1441,7 +1445,10 @@ #ifdef CONFIG_MD_BOOT md_setup_drive(); #endif + return 0; } + +__initcall(device_setup); #ifdef CONFIG_PROC_FS int get_partition_list(char * page) diff -u --recursive --new-file v2.3.12/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v2.3.12/linux/drivers/block/hd.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/hd.c Mon Aug 2 11:12:00 1999 @@ -21,6 +21,7 @@ * Removed 99% of above. Use Mark's ide driver for those options. * This is now a lightweight ST-506 driver. (Paul Gortmaker) * + * Modified 1995 Russell King for ARM processor. */ /* Uncomment the following if you want verbose error reports. */ @@ -49,6 +50,12 @@ #define MAJOR_NR HD_MAJOR #include +#ifdef __arm__ +#undef HD_IRQ +#include +#define HD_IRQ IRQ_HARDDISK +#endif + static int revalidate_hddisk(kdev_t, int); #define HD_DELAY 0 @@ -64,14 +71,14 @@ static void recal_intr(void); static void bad_rw_intr(void); -static char recalibrate[MAX_HD] = { 0, }; -static char special_op[MAX_HD] = { 0, }; -static int access_count[MAX_HD] = {0, }; -static char busy[MAX_HD] = {0, }; +static char recalibrate[MAX_HD]; +static char special_op[MAX_HD]; +static int access_count[MAX_HD]; +static char busy[MAX_HD]; static DECLARE_WAIT_QUEUE_HEAD(busy_wait); -static int reset = 0; -static int hd_error = 0; +static int reset; +static int hd_error; #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) @@ -86,13 +93,14 @@ static struct hd_i_struct hd_info[] = { HD_TYPE }; static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); #else -static struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; -static int NR_HD = 0; +static struct hd_i_struct hd_info[MAX_HD]; +static int NR_HD; #endif -static struct hd_struct hd[MAX_HD<<6]={{0,0},}; -static int hd_sizes[MAX_HD<<6] = {0, }; -static int hd_blocksizes[MAX_HD<<6] = {0, }; +static struct hd_struct hd[MAX_HD<<6]; +static int hd_sizes[MAX_HD<<6]; +static int hd_blocksizes[MAX_HD<<6]; +static int hd_hardsectsizes[MAX_HD<<6]; #if (HD_DELAY > 0) unsigned long last_req; @@ -611,7 +619,7 @@ (long *) arg); case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; return revalidate_hddisk(inode->i_rdev, 1); @@ -746,6 +754,17 @@ } } #endif /* __i386__ */ +#ifdef __arm__ + if (!NR_HD) { + /* We don't know anything about the drive. This means + * that you *MUST* specify the drive parameters to the + * kernel yourself. + */ + printk("hd: no drives specified - use hd=cyl,head,sectors" + " on kernel command line\n"); + } +#endif + for (drive=0 ; drive < NR_HD ; drive++) { hd[drive<<6].nr_sects = hd_info[drive].head * hd_info[drive].sect * hd_info[drive].cyl; @@ -764,9 +783,12 @@ } hd_gendisk.nr_real = NR_HD; - for(drive=0; drive < (MAX_HD << 6); drive++) + for(drive=0; drive < (MAX_HD << 6); drive++) { hd_blocksizes[drive] = 1024; + hd_hardsectsizes[drive] = 512; + } blksize_size[MAJOR_NR] = hd_blocksizes; + hardsect_size[MAJOR_NR] = hd_hardsectsizes; } static struct file_operations hd_fops = { diff -u --recursive --new-file v2.3.12/linux/drivers/block/hpt34x.c linux/drivers/block/hpt34x.c --- v2.3.12/linux/drivers/block/hpt34x.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/hpt34x.c Thu Aug 5 18:48:45 1999 @@ -1,8 +1,7 @@ /* - * linux/drivers/block/hpt34x.c Version 0.24 July 3, 1999 + * linux/drivers/block/hpt34x.c Version 0.25 July 11, 1999 * * Copyright (C) 1998-99 Andre Hedrick - * (hedrick@astro.dyer.vanderbilt.edu) * * 00:12.0 Unknown mass storage controller: * Triones Technologies, Inc. @@ -118,9 +117,14 @@ return ((int) ide_dma_off_quietly); #endif /* HPT343_DISABLE_ALL_DMAING */ - if (id->dma_ultra & 0x0004) { + if (id->dma_ultra & 0x0010) { + goto backspeed; + } else if (id->dma_ultra & 0x0008) { + goto backspeed; + } else if (id->dma_ultra & 0x0004) { +backspeed: if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0404; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -128,7 +132,7 @@ speed = XFER_UDMA_2; } else if (id->dma_ultra & 0x0002) { if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0202; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -136,7 +140,7 @@ speed = XFER_UDMA_1; } else if (id->dma_ultra & 0x0001) { if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0101; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -190,7 +194,8 @@ (void) hpt34x_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); @@ -337,47 +342,10 @@ __initfunc(unsigned int pci_init_hpt34x (struct pci_dev *dev, const char *name)) { - int i; unsigned short cmd; - unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; -#if 0 - unsigned char misc10 = inb(hpt34xIoBase + 0x0010); - unsigned char misc11 = inb(hpt34xIoBase + 0x0011); -#endif pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); pci_read_config_word(dev, PCI_COMMAND, &cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - - dev->base_address[0] = (hpt34xIoBase + 0x20); - dev->base_address[1] = (hpt34xIoBase + 0x34); - dev->base_address[2] = (hpt34xIoBase + 0x28); - dev->base_address[3] = (hpt34xIoBase + 0x3c); - - for(i=0; i<4; i++) - dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO; - - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->base_address[0]); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->base_address[1]); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->base_address[2]); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->base_address[3]); - pci_write_config_word(dev, PCI_COMMAND, cmd); - -#if 0 - outb(misc10|0x78, (hpt34xIoBase + 0x0010)); - outb(misc11, (hpt34xIoBase + 0x0011)); -#endif - -#ifdef DEBUG - printk("%s: 0x%02x 0x%02x\n", - (pcicmd & PCI_COMMAND_MEMORY) ? "HPT345" : name, - inb(hpt34xIoBase + 0x0010), - inb(hpt34xIoBase + 0x0011)); -#endif - if (cmd & PCI_COMMAND_MEMORY) { if (dev->rom_address) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE); @@ -385,6 +353,25 @@ } pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } else { + int i = 0; + unsigned long hpt34xIoBase = dev->resource[4].start; + + pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; + /* + * Since 20-23 can be assigned and are R/W, we correct them. + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); + + pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } return dev->irq; diff -u --recursive --new-file v2.3.12/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c --- v2.3.12/linux/drivers/block/hpt366.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/hpt366.c Fri Aug 6 11:16:54 1999 @@ -0,0 +1,492 @@ +/* + * linux/drivers/block/hpt366.c Version 0.11 August 04, 1999 + * + * Copyright (C) 1999 Andre Hedrick + * + * drive_number + * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +const char *bad_ata66_4[] = { + "WDC AC310200R", + "QUANTUM FIREBALLP KA13.6", + NULL +}; + +const char *bad_ata66_3[] = { + "WDC AC310200R", + NULL +}; + +const char *bad_ata33[] = { + "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", + "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", + "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", + "Maxtor 90510D4", + "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", + "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", + "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", + NULL +}; + +struct chipset_bus_clock_list_entry { + byte xfer_speed; + unsigned int chipset_settings; +}; + +struct chipset_bus_clock_list_entry forty_base [] = { + + { XFER_UDMA_4 , 0x900fd943 }, + { XFER_UDMA_3 , 0x900ad943 }, + { XFER_UDMA_2 , 0x900bd943 }, + { XFER_UDMA_1 , 0x9008d943 }, + { XFER_UDMA_0 , 0x9008d943 }, + + { XFER_MW_DMA_2 , 0xa008d943 }, + { XFER_MW_DMA_1 , 0xa010d955 }, + { XFER_MW_DMA_0 , 0xa010d9fc }, + + { XFER_PIO_4 , 0xc008d963 }, + { XFER_PIO_3 , 0xc010d974 }, + { XFER_PIO_2 , 0xc010d997 }, + { XFER_PIO_1 , 0xc010d9c7 }, + { XFER_PIO_0 , 0xc018d9d9 }, + { 0 , 0x0120d9d9 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base [] = { + + { XFER_UDMA_4 , 0x90c9a731 }, + { XFER_UDMA_3 , 0x90cfa731 }, + { XFER_UDMA_2 , 0x90caa731 }, + { XFER_UDMA_1 , 0x90cba731 }, + { XFER_UDMA_0 , 0x90c8a731 }, + + { XFER_MW_DMA_2 , 0xa0c8a731 }, + { XFER_MW_DMA_1 , 0xa0c8a732 }, /* 0xa0c8a733 */ + { XFER_MW_DMA_0 , 0xa0c8a797 }, + + { XFER_PIO_4 , 0xc0c8a731 }, + { XFER_PIO_3 , 0xc0c8a742 }, + { XFER_PIO_2 , 0xc0d0a753 }, + { XFER_PIO_1 , 0xc0d0a7a3 }, /* 0xc0d0a793 */ + { XFER_PIO_0 , 0xc0d0a7aa }, /* 0xc0d0a7a7 */ + { 0 , 0x0120a7a7 } +}; + +struct chipset_bus_clock_list_entry twenty_five_base [] = { + + { XFER_UDMA_4 , 0x90c98521 }, + { XFER_UDMA_3 , 0x90cf8521 }, + { XFER_UDMA_2 , 0x90cf8521 }, + { XFER_UDMA_1 , 0x90cb8521 }, + { XFER_UDMA_0 , 0x90cb8521 }, + + { XFER_MW_DMA_2 , 0xa0ca8521 }, + { XFER_MW_DMA_1 , 0xa0ca8532 }, + { XFER_MW_DMA_0 , 0xa0ca8575 }, + + { XFER_PIO_4 , 0xc0ca8521 }, + { XFER_PIO_3 , 0xc0ca8532 }, + { XFER_PIO_2 , 0xc0ca8542 }, + { XFER_PIO_1 , 0xc0d08572 }, + { XFER_PIO_0 , 0xc0d08585 }, + { 0 , 0x01208585 } +}; + +#define HPT366_DEBUG_DRIVE_INFO 0 +#define HPT366_ALLOW_ATA66_4 1 +#define HPT366_ALLOW_ATA66_3 1 +#define HPT366_ALLOW_ATA33_2 1 +#define HPT366_ALLOW_ATA33_1 1 +#define HPT366_ALLOW_ATA33_0 1 + +extern char *ide_xfer_verbose (byte xfer_rate); + +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + while (*list) { + if (!strcmp(*list++,id->model)) { +#ifdef DEBUG + printk("%s: Broken ASIC, BackSpeeding (U)DMA for %s\n", drive->name, id->model); +#endif /* DEBUG */ + return 1; + } + } + return 0; +} + +static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) +{ + for ( ; chipset_table->xfer_speed ; chipset_table++) + if (chipset_table->xfer_speed == speed) + return chipset_table->chipset_settings; + return 0x01208585; +} + +static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) +{ + int err; + byte busclock; + +#if HPT366_DEBUG_DRIVE_INFO + int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + byte regtime = (drive->select.b.unit & 0x01) ? 0x43 : 0x40; + unsigned int reg1 = 0; + unsigned int reg2 = 0; + + pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); + pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock); + switch(busclock) { + case 0xd9: + reg2 = pci_bus_clock_list(speed, forty_base); + break; + case 0x85: + reg2 = pci_bus_clock_list(speed, twenty_five_base); + break; + case 0xa7: + default: + reg2 = pci_bus_clock_list(speed, thirty_three_base); + break; + } + + if (drive->id->dword_io & 1) + reg2 |= 0x80000000; + else + reg2 &= ~0x80000000; + + pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); + err = ide_config_drive_speed(drive, speed); + +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: %s drive%d (0x%08x 0x%08x) 0x%04x\n", + drive->name, ide_xfer_verbose(speed), + drive_number, reg1, reg2, err); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + return(err); +} + +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initally for designed for + * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. + * + * check_in_drive_lists(drive, bad_ata66_4) + * check_in_drive_lists(drive, bad_ata66_3) + * check_in_drive_lists(drive, bad_ata33) + * + */ +static int config_chipset_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + byte speed = 0x00; + + if ((id->dma_ultra & 0x0010) && + (!check_in_drive_lists(drive, bad_ata66_4)) && + (HPT366_ALLOW_ATA66_4) && + (HWIF(drive)->udma_four)) { + if (!((id->dma_ultra >> 8) & 16)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x1010; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_UDMA_4; + } else if ((id->dma_ultra & 0x0008) && + (!check_in_drive_lists(drive, bad_ata66_3)) && + (HPT366_ALLOW_ATA66_3) && + (HWIF(drive)->udma_four)) { + if (!((id->dma_ultra >> 8) & 8)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0808; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_UDMA_3; + } else if ((id->dma_ultra & 0x0004) && + (HPT366_ALLOW_ATA33_2) && + (!check_in_drive_lists(drive, bad_ata33))) { + if (!((id->dma_ultra >> 8) & 4)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0404; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0002) && + (HPT366_ALLOW_ATA33_1) && + (!check_in_drive_lists(drive, bad_ata33))) { + if (!((id->dma_ultra >> 8) & 2)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0202; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_UDMA_1; + } else if ((id->dma_ultra & 0x0001) && + (HPT366_ALLOW_ATA33_0) && + (!check_in_drive_lists(drive, bad_ata33))) { + if (!((id->dma_ultra >> 8) & 1)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0101; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_UDMA_0; + } else if (id->dma_mword & 0x0004) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 4)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0404; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_2; + } else if (id->dma_mword & 0x0002) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 2)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0202; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_1; + } else if (id->dma_mword & 0x0001) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 1)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0101; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_0; + } else if (id->dma_1word & 0x0004) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_1word >> 8) & 4)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0404; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_2; + } else if (id->dma_1word & 0x0002) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_1word >> 8) & 2)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0202; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_1; + } else if (id->dma_1word & 0x0001) { + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_1word >> 8) & 1)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0101; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_0; + } else { + return ((int) ide_dma_off_quietly); + } + + (void) hpt366_tune_chipset(drive, speed); + + return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + ((id->dma_1word >> 8) & 7) ? ide_dma_on : + ide_dma_off_quietly); +} + +static void config_chipset_for_pio (ide_drive_t *drive) +{ + unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; + unsigned short xfer_pio = drive->id->eide_pio_modes; + + byte timing, speed, pio; + + pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + + if (xfer_pio> 4) + xfer_pio = 0; + + if (drive->id->eide_pio_iordy > 0) { + for (xfer_pio = 5; + xfer_pio>0 && + drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; + xfer_pio--); + } else { + xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : + (drive->id->eide_pio_modes & 2) ? 0x04 : + (drive->id->eide_pio_modes & 1) ? 0x03 : + (drive->id->tPIO & 2) ? 0x02 : + (drive->id->tPIO & 1) ? 0x01 : xfer_pio; + } + + timing = (xfer_pio >= pio) ? xfer_pio : pio; + + switch(timing) { + case 4: speed = XFER_PIO_4;break; + case 3: speed = XFER_PIO_3;break; + case 2: speed = XFER_PIO_2;break; + case 1: speed = XFER_PIO_1;break; + default: + speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; + break; + } + (void) hpt366_tune_chipset(drive, speed); +} + +static void hpt366_tune_drive (ide_drive_t *drive, byte pio) +{ + byte speed; + switch(pio) { + case 4: speed = XFER_PIO_4;break; + case 3: speed = XFER_PIO_3;break; + case 2: speed = XFER_PIO_2;break; + case 1: speed = XFER_PIO_1;break; + default: speed = XFER_PIO_0;break; + } + (void) hpt366_tune_chipset(drive, speed); +} + +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x001F) { + /* Force if Capable UltraDMA */ + dma_func = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x0007)) { + /* Force if Capable regular DMA modes */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + + config_chipset_for_pio(drive); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + +/* + * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. + * + * This is specific to the HPT343 UDMA bios-less chipset + * and HPT345 UDMA bios chipset (stamped HPT363) + * by HighPoint|Triones Technologies, Inc. + */ + +int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + byte reg50h = 0, reg52h = 0; + + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); +#if 0 + case ide_dma_lostirq: + pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); + printk("%s: (ide_dma_lostirq) reg52h=0x%02x\n", drive->name, reg52h); + break; + case ide_dma_timeout: + (void) ide_dmaproc(ide_dma_off_quietly, drive); + pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); + printk("%s: (ide_dma_timeout) reg52h=0x%02x\n", drive->name, reg52h); + if (reg52h & 0x04) { + pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0xff); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h); + } + pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); + pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); + printk("%s: (ide_dma_timeout) reg50h=0x%02x reg52h=0x%02x :: again\n", drive->name, reg50h, reg52h); + (void) ide_dmaproc(ide_dma_on, drive); + if (reg52h & 0x04) + (void) ide_dmaproc(ide_dma_off, drive); + return 1; +#endif + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} + +__initfunc(unsigned int pci_init_hpt366 (struct pci_dev *dev, const char *name)) +{ + byte ata66 = 0; + + pci_read_config_byte(dev, 0x5a, &ata66); + if (dev->rom_address) + pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE); + printk("%s: reg5ah=0x%02x ATA-%s Cable Port%d\n", name, ata66, (ata66 & 0x02) ? "33" : "66", PCI_FUNC(dev->devfn)); + return dev->irq; +} + +__initfunc(void ide_init_hpt366 (ide_hwif_t *hwif)) +{ + hwif->tuneproc = &hpt366_tune_drive; + if (hwif->dma_base) { + byte ata66 = 0; + + hwif->dmaproc = &hpt366_dmaproc; + pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); + hwif->udma_four = (ata66 & 0x02) ? 0 : 1; + } else { + hwif->udma_four = 0; + hwif->autodma = 0; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } +} diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- v2.3.12/linux/drivers/block/ide-cd.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/block/ide-cd.c Mon Aug 9 12:34:22 1999 @@ -2,7 +2,7 @@ * linux/drivers/block/ide-cd.c * Copyright (C) 1994, 1995, 1996 scott snyder * Copyright (C) 1996-1998 Erik Andersen - * Copyright (C) 1998, 1999 Jens Axboe + * Copyright (C) 1998, 1999 Jens Axboe * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. @@ -243,11 +243,23 @@ * Useful when using ide-cd in conjunction with * ide-scsi. TODO: non-modular way of doing the * same. + * + * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic + * packet interface to cdrom.c. + * - Unified audio ioctl support, most of it. + * - cleaned up various deprecated verify_area(). + * - Added ide_cdrom_packet() as the interface for + * the Uniform generic_packet(). + * - bunch of other stuff, will fill in logs later. + * - report 1 slot for non-changers, like the other + * cd-rom drivers. don't report select disc for + * non-changers as well. + * - mask out audio playing, if the device can't do it. * * *************************************************************************/ - -#define IDECD_VERSION "4.53" + +#define IDECD_VERSION "4.54" #include #include @@ -517,8 +529,8 @@ int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; - int stat, err, sense_key, cmd; - + int stat, cmd, err, sense_key; + /* Check for errors. */ stat = GET_STAT(); *stat_ret = stat; @@ -526,8 +538,8 @@ if (OK_STAT (stat, good_stat, BAD_R_STAT)) return 0; - /* Got an error. */ - err = IN_BYTE (IDE_ERROR_REG); + /* Get the IDE error register. */ + err = GET_ERR(); sense_key = err >> 4; if (rq == NULL) @@ -1170,8 +1182,6 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag, struct atapi_request_sense *reqbuf); - - /* Interrupt routine for packet command completion. */ static void cdrom_pc_intr (ide_drive_t *drive) { @@ -1385,14 +1395,15 @@ if (CDROM_STATE_FLAGS (drive)->door_locked == 0 && drive->usage && (pc->c[0] != REQUEST_SENSE && pc->c[0] != ALLOW_MEDIUM_REMOVAL && - pc->c[0] != START_STOP)) { + pc->c[0] != START_STOP && + pc->c[0] != MODE_SENSE_10 && + pc->c[0] != MODE_SELECT_10)) { (void) cdrom_lockdoor (drive, 1, NULL); } return 0; } } - /**************************************************************************** * cdrom driver request routine. */ @@ -1518,7 +1529,7 @@ struct atapi_request_sense my_reqbuf; int stat; struct packet_command pc; - + if (reqbuf == NULL) reqbuf = &my_reqbuf; @@ -1564,45 +1575,18 @@ { struct packet_command pc; - if (CDROM_CONFIG_FLAGS (drive)->no_eject==1 && ejectflag==0) + if (CDROM_CONFIG_FLAGS (drive)->no_eject && !ejectflag) return -EDRIVE_CANT_DO_THIS; + + /* reload fails on some drives, if the tray is locked */ + if (CDROM_STATE_FLAGS (drive)->door_locked && ejectflag) + return 0; memset (&pc, 0, sizeof (pc)); pc.sense_data = reqbuf; pc.c[0] = START_STOP; - pc.c[4] = 2 + (ejectflag != 0); - return cdrom_queue_packet_command (drive, &pc); -} - - -static int -cdrom_pause (ide_drive_t *drive, int pauseflag, - struct atapi_request_sense *reqbuf) -{ - struct packet_command pc; - - memset (&pc, 0, sizeof (pc)); - pc.sense_data = reqbuf; - - pc.c[0] = SCMD_PAUSE_RESUME; - pc.c[8] = !pauseflag; - return cdrom_queue_packet_command (drive, &pc); -} - - -static int -cdrom_startstop (ide_drive_t *drive, int startflag, - struct atapi_request_sense *reqbuf) -{ - struct packet_command pc; - - memset (&pc, 0, sizeof (pc)); - pc.sense_data = reqbuf; - - pc.c[0] = START_STOP; - pc.c[1] = 1; - pc.c[4] = startflag; + pc.c[4] = 0x02 + (ejectflag != 0); return cdrom_queue_packet_command (drive, &pc); } @@ -1611,8 +1595,8 @@ struct atapi_request_sense *reqbuf) { struct { - unsigned lba; - unsigned blocklen; + __u32 lba; + __u32 blocklen; } capbuf; int stat; @@ -1892,7 +1876,7 @@ cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end, struct atapi_request_sense *reqbuf) { - int i, stat; + int i, stat = 0; struct atapi_request_sense my_reqbuf; if (reqbuf == NULL) @@ -2048,7 +2032,6 @@ return cdrom_queue_packet_command (drive, &pc); } - /* Read the drive mechanism status and slot table into our internal buffer. If the buffer does not yet exist, allocate it. */ static int @@ -2090,6 +2073,24 @@ NULL); } +/* the generic packet interface to cdrom.c */ +static int ide_cdrom_packet(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc) +{ + struct packet_command pc; + ide_drive_t *drive = (ide_drive_t*) cdi->handle; + + /* here we queue the commands from the uniform CD-ROM + layer. the packet must be complete, as we do not + touch it at all. */ + memset(&pc, 0, sizeof(pc)); + memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); + pc.buffer = cgc->buffer; + pc.buflen = cgc->buflen; + cgc->stat = cdrom_queue_packet_command(drive, &pc); + return cgc->stat; +} + static int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi, @@ -2168,19 +2169,16 @@ toc = info->toc; - stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra)); - if (stat) return stat; - - copy_from_user (&ra, (void *)arg, sizeof (ra)); + if (copy_from_user(&ra, (void *)arg, sizeof (ra))) + return -EFAULT; if (ra.nframes < 0 || ra.nframes > toc->capacity) return -EINVAL; else if (ra.nframes == 0) return 0; - stat = verify_area (VERIFY_WRITE, (char *)ra.buf, - ra.nframes * CD_FRAMESIZE_RAW); - if (stat) return stat; + if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes * CD_FRAMESIZE_RAW)) + return -EFAULT; if (ra.addr_format == CDROM_MSF) lba = msf_to_lba (ra.addr.msf.minute, @@ -2208,8 +2206,7 @@ buf, this_nblocks * CD_FRAMESIZE_RAW, NULL); if (stat) break; - copy_to_user (ra.buf, buf, - this_nblocks * CD_FRAMESIZE_RAW); + __copy_to_user(ra.buf, buf,this_nblocks * CD_FRAMESIZE_RAW); ra.buf += this_nblocks * CD_FRAMESIZE_RAW; ra.nframes -= this_nblocks; lba += this_nblocks; @@ -2224,11 +2221,8 @@ char buffer[16]; int stat; - stat = verify_area (VERIFY_READ, (void *) arg, - sizeof (char)); - if (stat) return stat; - - copy_from_user (&spindown, (void *) arg, sizeof(char)); + if (copy_from_user(&spindown, (void *) arg, sizeof(char))) + return -EFAULT; stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer, sizeof (buffer), NULL); @@ -2245,17 +2239,14 @@ char buffer[16]; int stat; - stat = verify_area (VERIFY_WRITE, (void *) arg, - sizeof (char)); - if (stat) return stat; - stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer, sizeof (buffer), NULL); if (stat) return stat; spindown = buffer[11] & 0x0f; - copy_to_user ((void *) arg, &spindown, sizeof (char)); + if (copy_to_user((void *) arg, &spindown, sizeof (char))) + return -EFAULT; return 0; } @@ -2268,14 +2259,14 @@ memset (&pc, 0, sizeof (pc)); - stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c)); - if (stat) return stat; - copy_from_user (&pc.c, (void *) arg, sizeof (pc.c)); + if (copy_from_user(&pc.c, (void *) arg, sizeof (pc.c))) + return -EFAULT; + arg += sizeof (pc.c); - stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len)); - if (stat) return stat; - copy_from_user (&len, (void *) arg , sizeof (len)); + if (copy_from_user (&len, (void *) arg , sizeof (len))) + return -EFAULT; + arg += sizeof (len); lena = len; @@ -2438,70 +2429,6 @@ return cdrom_play_lba_range (drive, lba_start, lba_end, NULL); } - case CDROMVOLCTRL: { - struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg; - char buffer[24], mask[24]; - int stat; - - stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer, - sizeof (buffer), NULL); - if (stat) return stat; - stat = cdrom_mode_sense (drive, PAGE_AUDIO, 1, mask, - sizeof (buffer), NULL); - if (stat) return stat; - - buffer[1] = buffer[2] = 0; - - buffer[17] = volctrl->channel0 & mask[17]; - buffer[19] = volctrl->channel1 & mask[19]; - buffer[21] = volctrl->channel2 & mask[21]; - buffer[23] = volctrl->channel3 & mask[23]; - - return cdrom_mode_select (drive, PAGE_AUDIO, buffer, - sizeof (buffer), NULL); - } - - case CDROMVOLREAD: { - struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg; - char buffer[24]; - int stat; - - stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer, - sizeof (buffer), NULL); - if (stat) return stat; - - volctrl->channel0 = buffer[17]; - volctrl->channel1 = buffer[19]; - volctrl->channel2 = buffer[21]; - volctrl->channel3 = buffer[23]; - - return 0; - } - - case CDROMSTART: - return cdrom_startstop (drive, 1, NULL); - - case CDROMSTOP: { -#ifdef IHAVEADOLPHIN - /* Certain Drives require this. Most don't - and will produce errors upon CDROMSTOP - pit says the Dolphin needs this. If you - own a dolphin, just define IHAVEADOLPHIN somewhere */ - int stat; - stat = cdrom_startstop (drive, 0, NULL); - if (stat) return stat; - return cdrom_eject (drive, 1, NULL); -#endif /* end of IHAVEADOLPHIN */ - return cdrom_startstop (drive, 0, NULL); - } - - case CDROMPAUSE: - return cdrom_pause (drive, 1, NULL); - - case CDROMRESUME: - return cdrom_pause (drive, 0, NULL); - - default: return -EINVAL; } @@ -2534,7 +2461,6 @@ return cdrom_eject (drive, !position, NULL); } - static int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) { @@ -2835,9 +2761,11 @@ ide_cdrom_dev_ioctl, /* dev_ioctl */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN - | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET - | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */ - 0 /* n_minors */ + | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS + | CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD + | CDC_DVD_R| CDC_DVD_RAM | CDC_GENERIC_PACKET, /* capability */ + 0, /* n_minors */ + ide_cdrom_packet }; static int ide_cdrom_register (ide_drive_t *drive, int nslots) @@ -2853,6 +2781,25 @@ *(int *)&devinfo->capacity = nslots; devinfo->handle = (void *) drive; strcpy(devinfo->name, drive->name); + + /* set capability mask to match the probe. */ + if (!CDROM_CONFIG_FLAGS (drive)->cd_r) + devinfo->mask |= CDC_CD_R; + if (!CDROM_CONFIG_FLAGS (drive)->cd_rw) + devinfo->mask |= CDC_CD_RW; + if (!CDROM_CONFIG_FLAGS (drive)->dvd) + devinfo->mask |= CDC_DVD; + if (!CDROM_CONFIG_FLAGS (drive)->dvd_r) + devinfo->mask |= CDC_DVD_R; + if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram) + devinfo->mask |= CDC_DVD_RAM; + if (!CDROM_CONFIG_FLAGS (drive)->is_changer) + devinfo->mask |= CDC_SELECT_DISC; + if (!CDROM_CONFIG_FLAGS (drive)->audio_play) + devinfo->mask |= CDC_PLAY_AUDIO; + if (!CDROM_CONFIG_FLAGS (drive)->close_tray) + devinfo->mask |= CDC_CLOSE_TRAY; + return register_cdrom (devinfo); } @@ -2860,7 +2807,7 @@ static int ide_cdrom_probe_capabilities (ide_drive_t *drive) { - int stat, nslots = 0, attempts = 3; + int stat, nslots = 1, attempts = 3; struct { char pad[8]; struct atapi_capabilities_page cap; @@ -2891,7 +2838,11 @@ if (buf.cap.dvd_ram_write) CDROM_CONFIG_FLAGS (drive)->dvd_r = 1; if (buf.cap.dvd_r_write) - CDROM_CONFIG_FLAGS (drive)->dvd_rw = 1; + CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1; + if (buf.cap.audio_play) + CDROM_CONFIG_FLAGS (drive)->audio_play = 1; + if (buf.cap.mechtype == 0) + CDROM_CONFIG_FLAGS (drive)->close_tray = 0; #if ! STANDARD_ATAPI if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) { @@ -2931,10 +2882,10 @@ drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed, (CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM"); - if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_rw) + if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram) printk (" DVD%s%s", - (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-RAM" : "", - (CDROM_CONFIG_FLAGS (drive)->dvd_rw)? "/RW" : ""); + (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "", + (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : ""); if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) printk (" CD%s%s", @@ -3060,9 +3011,11 @@ CDROM_CONFIG_FLAGS (drive)->test_write = 0; CDROM_CONFIG_FLAGS (drive)->dvd = 0; CDROM_CONFIG_FLAGS (drive)->dvd_r = 0; - CDROM_CONFIG_FLAGS (drive)->dvd_rw = 0; + CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0; CDROM_CONFIG_FLAGS (drive)->no_eject = 1; CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; + CDROM_CONFIG_FLAGS (drive)->audio_play = 0; + CDROM_CONFIG_FLAGS (drive)->close_tray = 1; /* limit transfer size per interrupt. */ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0; @@ -3195,7 +3148,6 @@ (MKDEV (HWIF (drive)->major, (drive->select.b.unit)<driver_data))->config_flags)) @@ -518,9 +520,11 @@ #if defined(__BIG_ENDIAN_BITFIELD) __u8 mech_state : 3; - __u8 reserved1 : 5; + __u8 door_open : 1; + __u8 reserved1 : 4; #elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved1 : 5; + __u8 reserved1 : 4; + __u8 door_open : 1; __u8 mech_state : 3; #else #error "Please fix " @@ -653,13 +657,13 @@ { MODE_SENSE_10, "Mode Sense" }, { LOAD_UNLOAD, "Load/Unload CD" }, { READ_12, "Read(12)" }, + { GET_PERFORMANCE, "Get Performance" }, { READ_CD_MSF, "Read CD MSF" }, { SCAN, "Scan" }, { SET_CD_SPEED, "Set CD Speed" }, { PLAY_CD, "Play CD" }, { MECHANISM_STATUS, "Mechanism Status" }, { READ_CD, "Read CD" }, - { DVD_GET_PERFORMANCE, "Get Performance" }, }; diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c --- v2.3.12/linux/drivers/block/ide-dma.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/ide-dma.c Fri Aug 6 10:41:47 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-dma.c Version 4.09 April 23, 1999 + * linux/drivers/block/ide-dma.c Version 4.09 April 23, 1999 * * Copyright (c) 1999 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License @@ -357,12 +357,11 @@ /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) return hwif->dmaproc(ide_dma_off, drive); -#ifdef CONFIG_IDEDMA_ULTRA_66 + /* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */ - if ((id->field_valid & 4) && (id->word93 & 0x2000)) + if ((id->field_valid & 4) && (hwif->udma_four) && (id->word93 & 0x2000)) if ((id->dma_ultra & (id->dma_ultra >> 11) & 3)) return hwif->dmaproc(ide_dma_on, drive); -#endif /* CONFIG_IDEDMA_ULTRA_66 */ /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ if (id->field_valid & 4) /* UltraDMA */ if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) @@ -443,6 +442,12 @@ case ide_dma_bad_drive: case ide_dma_good_drive: return check_drive_lists(drive, (func == ide_dma_good_drive)); + case ide_dma_lostirq: + case ide_dma_timeout: + /* + * printk("ide_dmaproc: chipset supported func only: %d\n", func); + */ + return 1; default: printk("ide_dmaproc: unsupported func: %d\n", func); return 1; @@ -510,7 +515,7 @@ /* * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: */ -__initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name)) +unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) { unsigned long dma_base = 0; struct pci_dev *dev = hwif->pci_dev; @@ -518,7 +523,7 @@ if (hwif->mate && hwif->mate->dma_base) { dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); } else { - dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; + dma_base = dev->resource[4].start; if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) { printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base); dma_base = 0; @@ -532,10 +537,6 @@ switch(dev->device) { case PCI_DEVICE_ID_CMD_643: - /* - * Lets attempt to use the same Ali tricks - * to fix CMD643..... - */ #ifdef CONFIG_BLK_DEV_ALI15X3 case PCI_DEVICE_ID_AL_M5219: case PCI_DEVICE_ID_AL_M5229: @@ -550,9 +551,19 @@ } break; default: - if (inb(dma_base+2) & 0x80) { - printk("%s: simplex device: DMA disabled\n", name); - dma_base = 0; + /* + * If the device claims "simplex" DMA, + * this means only one of the two interfaces + * can be trusted with DMA at any point in time. + * So we should enable DMA only on one of the + * two interfaces. + */ + if ((inb(dma_base+2) & 0x80)) { /* simplex device? */ + if ((!hwif->drives[0].present && !hwif->drives[1].present) || + (hwif->mate && hwif->mate->dma_base)) { + printk("%s: simplex device: DMA disabled\n", name); + dma_base = 0; + } } } } diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c --- v2.3.12/linux/drivers/block/ide-floppy.c Wed Jun 30 13:38:19 1999 +++ linux/drivers/block/ide-floppy.c Thu Aug 5 14:34:01 1999 @@ -1,7 +1,7 @@ /* - * linux/drivers/block/ide-floppy.c Version 0.8 Dec 7, 1997 + * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999 * - * Copyright (C) 1996, 1997 Gadi Oxman + * Copyright (C) 1996 - 1999 Gadi Oxman */ /* @@ -26,9 +26,12 @@ * Issue START command only if TEST UNIT READY fails. * Add work-around for IOMEGA ZIP revision 21.D. * Remove idefloppy_get_capabilities(). + * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of + * bytes requested on each interrupt to be zero. + * Thanks to for pointing this out. */ -#define IDEFLOPPY_VERSION "0.8" +#define IDEFLOPPY_VERSION "0.9" #include #include @@ -997,7 +1000,7 @@ pc->retries++; pc->actually_transferred=0; /* We haven't transferred any data yet */ pc->current_position=pc->buffer; - bcount.all=pc->request_transfer; /* Request to transfer the entire buffer at once */ + bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024); #ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { @@ -1521,9 +1524,19 @@ floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); - if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 && - ((strcmp(drive->id->fw_rev, "21.D") == 0) || - (strcmp(drive->id->fw_rev, "23.D") == 0))) { + /* + * We used to check revisions here. At this point however + * I'm giving up. Just assume they are all broken, its easier. + * + * The actual reason for the workarounds was likely + * a driver bug after all rather than a firmware bug, + * and the workaround below used to hide it. It should + * be fixed as of version 1.9, but to be on the safe side + * we'll leave the limitation below for the 2.2.x tree. + */ + + if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) + { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c --- v2.3.12/linux/drivers/block/ide-pci.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/ide-pci.c Mon Aug 9 10:23:09 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide-pci.c Version 1.03 May 1, 1999 + * linux/drivers/block/ide-pci.c Version 1.04 July 27, 1999 * * Copyright (c) 1998-1999 Andre Hedrick * @@ -52,6 +52,7 @@ #define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) #define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) +#define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) #define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) #define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) @@ -106,11 +107,14 @@ #endif #ifdef CONFIG_BLK_DEV_VIA82C586 +extern unsigned int pci_init_via82c568(struct pci_dev *, const char *); extern void ide_init_via82c586(ide_hwif_t *); extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase); +#define PCI_VIA82C586 &pci_init_via82c568 #define INIT_VIA82C586 &ide_init_via82c586 #define DMA_VIA82C586 &ide_dmacapable_via82c586 #else +#define PCI_VIA82C586 NULL #define INIT_VIA82C586 NULL #define DMA_VIA82C586 NULL #endif @@ -166,6 +170,26 @@ #define INIT_HPT34X NULL #endif +#ifdef CONFIG_BLK_DEV_HPT366 +extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); +extern void ide_init_hpt366(ide_hwif_t *); +#define PCI_HPT366 &pci_init_hpt366 +#define INIT_HPT366 &ide_init_hpt366 +#else +#define PCI_HPT366 NULL +#define INIT_HPT366 IDE_IGNORE +#endif + +#ifdef CONFIG_BLK_DEV_SIS5513 +extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); +extern void ide_init_sis5513(ide_hwif_t *); +#define PCI_SIS5513 &pci_init_sis5513 +#define INIT_SIS5513 &ide_init_sis5513 +#else +#define PCI_SIS5513 NULL +#define INIT_SIS5513 NULL +#endif + #define INIT_SAMURAI NULL #define INIT_CX5530 NULL @@ -183,71 +207,85 @@ void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); ide_pci_enablebit_t enablebits[2]; byte bootable; + byte sixtysix; unsigned int extra; } ide_pci_device_t; static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", NULL, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", NULL, NULL, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_VP_IDE, "VP_IDE", PCI_VIA82C586, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, 0 }, + {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 0, 16 }, + {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 1, 48 }, + {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 }, + {DEVID_SIS5513, "SIS5513", PCI_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 1, 0 }, + {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0, 0 }, + {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, 0 }, + {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0, 0 }, + {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0, 16 }, + {DEVID_HPT366, "HPT366", PCI_HPT366, INIT_HPT366, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 1, 256 }, + {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0, 0 }, + {DEVID_CY82C693,"CY82C693", NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }}; + +static byte hpt363_shared_irq = 0; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt * settings of split-mirror pci-config space, place chipset into init-mode, * and/or preserve an interrupt if the card is not native ide support. */ -__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name)) +static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name) { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT343: { - int i; unsigned short pcicmd = 0; - unsigned long hpt34xIoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; pci_write_config_byte(dev, 0x80, 0x00); - dev->base_address[0] = (hpt34xIoBase + 0x20); - dev->base_address[1] = (hpt34xIoBase + 0x34); - dev->base_address[2] = (hpt34xIoBase + 0x28); - dev->base_address[3] = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO; - pci_read_config_word(dev, PCI_COMMAND, &pcicmd); if (!(pcicmd & PCI_COMMAND_MEMORY)) { + /* + * FIXME - this is too ugly, and looks senseless. + * Why not just use resource[4]? + * + * This was a cleaner/quicker way to get the ioports + * that the are not decode do to a flaw in the chipset + * design. + */ + + int i; + unsigned long hpt34xIoBase = dev->resource[4].start; + + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } else { pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } } + case PCI_DEVICE_ID_TTI_HPT366: case PCI_DEVICE_ID_PROMISE_20246: case PCI_DEVICE_ID_PROMISE_20262: case PCI_DEVICE_ID_ARTOP_ATP850UF: @@ -262,7 +300,7 @@ * Match a PCI IDE port against an entry in ide_hwifs[], * based on io_base port if possible. */ -__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)) +static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name) { int h; ide_hwif_t *hwif; @@ -324,7 +362,7 @@ return NULL; } -__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)) +static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name) { byte reg, progif = 0; @@ -346,11 +384,15 @@ /* * Setup base registers for IDE command/control spaces for each interface: */ - for (reg = 0; reg < 4; reg++) - if (!dev->base_address[reg]) { + for (reg = 0; reg < 4; reg++) { + struct resource *res = dev->resource + reg; + if (!(res->flags & PCI_BASE_ADDRESS_SPACE_IO)) + continue; + if (!res->start) { printk("%s: Missing I/O address #%d\n", name, reg); return 1; } + } return 0; } @@ -364,7 +406,7 @@ * we "know" about, this information is in the ide_pci_device_t struct; * for all other chipsets, we just assume both interfaces are enabled. */ -__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)) +static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) { unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; unsigned short pcicmd = 0, tried_config = 0; @@ -446,9 +488,12 @@ ide_pci_enablebit_t *e = &(d->enablebits[port]); if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port)) + return; if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { - ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK; - base = dev->base_address[2*port] & ~7; + /* FIXME! This really should check that it really gets the IO/MEM part right! */ + ctl = dev->resource[(2*port)+1].start; + base = dev->resource[2*port].start; } if ((ctl && !base) || (base && !ctl)) { printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); @@ -484,13 +529,12 @@ hwif->irq = hwif->channel ? 15 : 14; goto bypass_umc_dma; } - + if ((!d->sixtysix) && (hwif->udma_four)) + hwif->udma_four = 0; #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) autodma = 0; - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) - hwif->udma_four = 1; if (autodma) hwif->autodma = 1; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || @@ -499,6 +543,7 @@ #ifdef CONFIG_BLK_DEV_HPT34X IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || #endif /* CONFIG_BLK_DEV_HPT34X */ + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) { unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name); @@ -534,11 +579,49 @@ printk("%s: neither IDE port enabled (BIOS)\n", d->name); } +__initfunc(static void hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)) +{ + struct pci_dev *dev2; + ide_pci_device_t *d2; + unsigned char pin1 = 0, pin2 = 0; + + d2 = d; + if (PCI_FUNC(dev->devfn) & 1) + return; + + for (dev2=pci_devices; dev2; dev2=dev2->next) { + if ((dev2->vendor == dev->vendor) && + (dev2->device == dev->device) && + (PCI_FUNC(dev2->devfn) & 1)) + break; + } + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + if (dev2) { + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + hpt363_shared_irq = (pin1 != pin2) ? 1 : 0; + } + + if (hpt363_shared_irq) { + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", + d->name, pin1, pin2); + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + + if (dev2) { + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); + } +} + /* * ide_scan_pcibus() gets invoked at boot time from ide.c. * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. */ -__initfunc(void ide_scan_pcibus (void)) +void __init ide_scan_pcibus (void) { struct pci_dev *dev; ide_pci_devid_t devid; @@ -558,6 +641,8 @@ continue; /* CY82C693 is more than only a IDE controller */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) continue; /* UM8886A/BF pair */ + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) + hpt366_device_order_fixup(dev, d); else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c --- v2.3.12/linux/drivers/block/ide-pmac.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/block/ide-pmac.c Mon Aug 9 10:23:09 1999 @@ -230,8 +230,8 @@ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC -__initfunc(static void -pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif)) +static void __init +pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif) { hwif->dma_base = (unsigned long) ioremap(np->addrs[1].address, 0x200); diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.3.12/linux/drivers/block/ide-probe.c Thu Jul 8 15:42:19 1999 +++ linux/drivers/block/ide-probe.c Thu Aug 5 18:48:45 1999 @@ -20,7 +20,7 @@ * Version 1.04 fixed buggy treatments of known flash memory cards * * Version 1.05 fix for (hwif->chipset == ide_pdc4030) - * added ide6/7 + * added ide6/7/8/9 * allowed for secondary flash card to be detectable * with new flag : drive->ata_flash : 1; */ @@ -762,6 +762,12 @@ #endif #if MAX_HWIFS > 7 case IDE7_MAJOR: rfn = &do_ide7_request; break; +#endif +#if MAX_HWIFS > 8 + case IDE8_MAJOR: rfn = &do_ide8_request; break; +#endif +#if MAX_HWIFS > 9 + case IDE9_MAJOR: rfn = &do_ide9_request; break; #endif default: printk("%s: request_fn NOT DEFINED\n", hwif->name); diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c --- v2.3.12/linux/drivers/block/ide-tape.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/block/ide-tape.c Thu Aug 5 18:48:45 1999 @@ -3583,8 +3583,8 @@ /* * These two ide-pci host adapters appear to need this disabled. */ - if ((hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || - (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { + if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) || + (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) { drive->dsc_overlap = 0; } else #endif /* CONFIG_BLK_DEV_IDEPCI */ diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.3.12/linux/drivers/block/ide.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/block/ide.c Mon Aug 9 12:32:28 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 6.19 January 29, 1999 + * linux/drivers/block/ide.c Version 6.20 July 10, 1999 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -93,19 +93,28 @@ * Version 6.17 fix for newest EZ-Drive problem * Version 6.18 default unpartitioned-disk translation now "BIOS LBA" * Version 6.19 Re-design for a UNIFORM driver for all platforms, - * model based on suggestions from Russell King and - * Geert Uytterhoeven + * model based on suggestions from Russell King and + * Geert Uytterhoeven * Promise DC4030VL now supported. + * add support for ide6/ide7 * delay_50ms() changed to ide_delay_50ms() and exported. + * Version 6.20 Added/Fixed Generic ATA-66 support and hwif detection. + * Added hdx=flash to allow for second flash disk + * detection w/o the hang loop. + * Added support for ide8/ide9 + * Added idex=ata66 for the quirky chipsets that are + * ATA-66 compliant, but have yet to determine a method + * of verification of the 80c cable presence. + * Specifically Promise's PDC20262 chipset. * - * Some additional driver compile-time options are in ide.h + * Some additional driver compile-time options are in ./include/linux/ide.h * * To do, in likely order of completion: * - modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f */ -#define REVISION "Revision: 6.19" -#define VERSION "Id: ide.c 6.19 1999/01/29" +#define REVISION "Revision: 6.20" +#define VERSION "Id: ide.c 6.20 1999/07/10" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -144,7 +153,11 @@ extern byte fifoconfig; /* defined in via82c586.c used by ide_setup()*/ #endif -static const byte ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR }; +static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, + IDE2_MAJOR, IDE3_MAJOR, + IDE4_MAJOR, IDE5_MAJOR, + IDE6_MAJOR, IDE7_MAJOR, + IDE8_MAJOR, IDE9_MAJOR }; static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ @@ -1308,6 +1321,20 @@ } #endif /* MAX_HWIFS > 7 */ +#if MAX_HWIFS > 8 +void do_ide8_request (void) +{ + unlock_do_hwgroup_request (ide_hwifs[8].hwgroup); +} +#endif /* MAX_HWIFS > 8 */ + +#if MAX_HWIFS > 9 +void do_ide9_request (void) +{ + unlock_do_hwgroup_request (ide_hwifs[9].hwgroup); +} +#endif /* MAX_HWIFS > 9 */ + static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq) { unsigned long flags; @@ -1347,6 +1374,7 @@ handler(drive); } else if (drive_is_ready(drive)) { printk("%s: lost interrupt\n", drive->name); + (void) hwgroup->hwif->dmaproc(ide_dma_lostirq, drive); spin_unlock_irqrestore(&hwgroup->spinlock, flags); handler(drive); } else { @@ -1357,6 +1385,7 @@ * need something here for HPT34X.......AMH * irq timeout: status=0x58 { DriveReady SeekComplete DataRequest } */ + (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); } spin_unlock_irqrestore(&hwgroup->spinlock, flags); ide_error(drive, "irq timeout", GET_STAT()); @@ -1957,7 +1986,7 @@ } for (index = 0; index < MAX_HWIFS; ++index) { hwif = &ide_hwifs[index]; - if ((!hwif->present && !initializing) || + if ((!hwif->present && !hwif->mate && !initializing) || (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing)) goto found; } @@ -2524,7 +2553,7 @@ * stridx() returns the offset of c within s, * or -1 if c is '\0' or not found within s. */ -__initfunc(static int stridx (const char *s, char c)) +static int __init stridx (const char *s, char c) { char *i = strchr(s, c); return (i && c) ? i - s : -1; @@ -2542,7 +2571,7 @@ * and base16 is allowed when prefixed with "0x". * 4. otherwise, zero is returned. */ -__initfunc(static int match_parm (char *s, const char *keywords[], int vals[], int max_vals)) +static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals) { static const char *decimal = "0123456789"; static const char *hex = "0123456789abcdef"; @@ -2641,6 +2670,10 @@ * "idex=four" : four drives on idex and ide(x^1) share same ports * "idex=reset" : reset interface before first use * "idex=dma" : enable DMA by default on both drives if possible + * "idex=ata66" : informs the interface that it has an 80c cable + * for chipsets that are ATA-66 capable, but + * the ablity to bit test for detection is + * currently unknown. * * "splitfifo=betweenChan" * : FIFO Configuration of VIA 82c586(,"A"or"B"). @@ -2668,8 +2701,9 @@ * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) * "ide0=umc8672" : probe/support umc8672 chipsets * "idex=dc4030" : probe/support Promise DC4030VL interface + * "ide=doubler" : probe/support IDE doublers on Amiga */ -__initfunc(void ide_setup (char *s)) +void __init ide_setup (char *s) { int i, vals[3]; ide_hwif_t *hwif; @@ -2828,9 +2862,12 @@ if (s[3] >= '0' && s[3] <= max_hwif) { /* * Be VERY CAREFUL changing this: note hardcoded indexes below + * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding. */ - const char *ide_words[] = {"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "four", - "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL}; + const char *ide_words[] = { + "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", + "minus8", "minus9", "minus10", + "four", "qd6580", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -2838,19 +2875,19 @@ /* * Cryptic check to ensure chipset not already set for hwif: */ - if (i > 0 || i <= -7) { /* is parameter a chipset name? */ + if (i > 0 || i <= -11) { /* is parameter a chipset name? */ if (hwif->chipset != ide_unknown) goto bad_option; /* chipset already specified */ - if (i <= -7 && i != -14 && hw != 0) + if (i <= -11 && i != -18 && hw != 0) goto bad_hwif; /* chipset drivers are for "ide0=" only */ - if (i <= -7 && i != -14 && ide_hwifs[hw+1].chipset != ide_unknown) + if (i <= -11 && i != -18 && ide_hwifs[hw+1].chipset != ide_unknown) goto bad_option; /* chipset for 2nd port already specified */ printk("\n"); } switch (i) { #ifdef CONFIG_BLK_DEV_PDC4030 - case -14: /* "dc4030" */ + case -18: /* "dc4030" */ { extern void init_pdc4030(void); init_pdc4030(); @@ -2858,7 +2895,7 @@ } #endif /* CONFIG_BLK_DEV_PDC4030 */ #ifdef CONFIG_BLK_DEV_ALI14XX - case -13: /* "ali14xx" */ + case -17: /* "ali14xx" */ { extern void init_ali14xx (void); init_ali14xx(); @@ -2866,7 +2903,7 @@ } #endif /* CONFIG_BLK_DEV_ALI14XX */ #ifdef CONFIG_BLK_DEV_UMC8672 - case -12: /* "umc8672" */ + case -16: /* "umc8672" */ { extern void init_umc8672 (void); init_umc8672(); @@ -2874,7 +2911,7 @@ } #endif /* CONFIG_BLK_DEV_UMC8672 */ #ifdef CONFIG_BLK_DEV_DTC2278 - case -11: /* "dtc2278" */ + case -15: /* "dtc2278" */ { extern void init_dtc2278 (void); init_dtc2278(); @@ -2882,7 +2919,7 @@ } #endif /* CONFIG_BLK_DEV_DTC2278 */ #ifdef CONFIG_BLK_DEV_CMD640 - case -10: /* "cmd640_vlb" */ + case -14: /* "cmd640_vlb" */ { extern int cmd640_vlb; /* flag for cmd640.c */ cmd640_vlb = 1; @@ -2890,7 +2927,7 @@ } #endif /* CONFIG_BLK_DEV_CMD640 */ #ifdef CONFIG_BLK_DEV_HT6560B - case -9: /* "ht6560b" */ + case -13: /* "ht6560b" */ { extern void init_ht6560b (void); init_ht6560b(); @@ -2898,7 +2935,7 @@ } #endif /* CONFIG_BLK_DEV_HT6560B */ #if CONFIG_BLK_DEV_QD6580 - case -8: /* "qd6580" */ + case -12: /* "qd6580" */ { extern void init_qd6580 (void); init_qd6580(); @@ -2906,7 +2943,7 @@ } #endif /* CONFIG_BLK_DEV_QD6580 */ #ifdef CONFIG_BLK_DEV_4DRIVES - case -7: /* "four" drives on one set of ports */ + case -11: /* "four" drives on one set of ports */ { ide_hwif_t *mate = &ide_hwifs[hw^1]; mate->drives[0].select.all ^= 0x20; @@ -2917,6 +2954,18 @@ goto do_serialize; } #endif /* CONFIG_BLK_DEV_4DRIVES */ + case -10: /* minus10 */ + case -9: /* minus9 */ + case -8: /* minus8 */ + goto bad_option; + case -7: /* ata66 */ +#ifdef CONFIG_BLK_DEV_IDEPCI + hwif->udma_four = 1; + goto done; +#else /* !CONFIG_BLK_DEV_IDEPCI */ + hwif->udma_four = 0; + goto bad_hwif; +#endif /* CONFIG_BLK_DEV_IDEPCI */ case -6: /* dma */ hwif->autodma = 1; goto done; @@ -3080,7 +3129,7 @@ /* * probe_for_hwifs() finds/initializes "known" IDE interfaces */ -__initfunc(static void probe_for_hwifs (void)) +static void __init probe_for_hwifs (void) { #ifdef CONFIG_PCI if (pci_present()) @@ -3154,7 +3203,7 @@ #endif /* CONFIG_BLK_DEV_BUDDHA */ } -__initfunc(void ide_init_builtin_drivers (void)) +void __init ide_init_builtin_drivers (void) { /* * Probe for special PCI and other "known" interface chipsets @@ -3425,6 +3474,12 @@ #if MAX_HWIFS > 7 EXPORT_SYMBOL(do_ide7_request); #endif /* MAX_HWIFS > 7 */ +#if MAX_HWIFS > 8 +EXPORT_SYMBOL(do_ide8_request); +#endif /* MAX_HWIFS > 8 */ +#if MAX_HWIFS > 9 +EXPORT_SYMBOL(do_ide9_request); +#endif /* MAX_HWIFS > 9 */ /* * Driver module @@ -3469,7 +3524,7 @@ /* * This is gets invoked once during initialization, to set *everything* up */ -__initfunc(int ide_init (void)) +int __init ide_init (void) { static char banner_printed = 0; @@ -3491,7 +3546,7 @@ char *options = NULL; MODULE_PARM(options,"s"); -__initfunc(static void parse_options (char *line)) +static void __init parse_options (char *line) { char *next = line; diff -u --recursive --new-file v2.3.12/linux/drivers/block/linear.c linux/drivers/block/linear.c --- v2.3.12/linux/drivers/block/linear.c Sat Nov 8 11:39:12 1997 +++ linux/drivers/block/linear.c Mon Aug 9 10:23:09 1999 @@ -184,7 +184,7 @@ #ifndef MODULE -__initfunc(void linear_init (void)) +void __init linear_init (void) { register_md_personality (LINEAR, &linear_personality); } diff -u --recursive --new-file v2.3.12/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.3.12/linux/drivers/block/ll_rw_blk.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/block/ll_rw_blk.c Mon Aug 9 11:49:24 1999 @@ -286,7 +286,7 @@ * with the request-lists in peace. Thus it should be called with no spinlocks * held. * - * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA, + * By this point, req->cmd is always either READ/WRITE, never READA, * which is important for drive_stat_acct() above. */ @@ -417,7 +417,7 @@ } } - rw_ahead = 0; /* normal case; gets changed below for READA/WRITEA */ + rw_ahead = 0; /* normal case; gets changed below for READA */ switch (rw) { case READA: rw_ahead = 1; @@ -431,9 +431,6 @@ case WRITERAW: rw = WRITE; goto do_write; /* Skip the buffer refile */ - case WRITEA: - rw_ahead = 1; - rw = WRITE; /* drop into WRITE */ case WRITE: if (!test_and_clear_bit(BH_Dirty, &bh->b_state)) goto end_io; /* Hmmph! Nothing to write */ @@ -486,6 +483,8 @@ case IDE5_MAJOR: case IDE6_MAJOR: case IDE7_MAJOR: + case IDE8_MAJOR: + case IDE9_MAJOR: case ACSI_MAJOR: case MFM_ACORN_MAJOR: /* @@ -596,13 +595,6 @@ struct blk_dev_struct * dev; int i; - /* Make sure that the first block contains something reasonable */ - while (!*bh) { - bh++; - if (--nr <= 0) - return; - } - dev = NULL; if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV) dev = blk_dev + major; @@ -652,26 +644,22 @@ } for (i = 0; i < nr; i++) { - if (bh[i]) { - set_bit(BH_Req, &bh[i]->b_state); + set_bit(BH_Req, &bh[i]->b_state); #ifdef CONFIG_BLK_DEV_MD - if (MAJOR(bh[i]->b_dev) == MD_MAJOR) { - md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]); - continue; - } -#endif - make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]); + if (MAJOR(bh[i]->b_dev) == MD_MAJOR) { + md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]); + continue; } +#endif + make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]); } return; sorry: for (i = 0; i < nr; i++) { - if (bh[i]) { - clear_bit(BH_Dirty, &bh[i]->b_state); - clear_bit(BH_Uptodate, &bh[i]->b_state); - bh[i]->b_end_io(bh[i], 0); - } + clear_bit(BH_Dirty, &bh[i]->b_state); + clear_bit(BH_Uptodate, &bh[i]->b_state); + bh[i]->b_end_io(bh[i], 0); } return; } diff -u --recursive --new-file v2.3.12/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.3.12/linux/drivers/block/md.c Sat May 15 23:43:04 1999 +++ linux/drivers/block/md.c Mon Aug 9 10:23:09 1999 @@ -1174,7 +1174,7 @@ }; /* called from init/main.c */ -__initfunc(void md_setup(char *str,int *ints)) +void __init md_setup(char *str,int *ints) { int i; for(i=0;i<=ints[0];i++) { @@ -1186,7 +1186,7 @@ return; } -__initfunc(void do_md_setup(char *str,int *ints)) +void __init do_md_setup(char *str,int *ints) { int minor, pers, factor, fault; kdev_t dev; @@ -1265,7 +1265,7 @@ void raid1_init (void); void raid5_init (void); -__initfunc(int md_init (void)) +int __init md_init (void) { printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, @@ -1306,7 +1306,7 @@ } #ifdef CONFIG_MD_BOOT -__initfunc(void md_setup_drive(void)) +void __init md_setup_drive(void) { if(md_setup_args.set) do_md_setup(md_setup_args.str, md_setup_args.ints); diff -u --recursive --new-file v2.3.12/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c --- v2.3.12/linux/drivers/block/ns87415.c Wed Jun 2 22:21:51 1999 +++ linux/drivers/block/ns87415.c Mon Aug 9 10:23:09 1999 @@ -102,7 +102,7 @@ } } -__initfunc(void ide_init_ns87415 (ide_hwif_t *hwif)) +void __init ide_init_ns87415 (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; unsigned int ctrl, using_inta; diff -u --recursive --new-file v2.3.12/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c --- v2.3.12/linux/drivers/block/pdc202xx.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/block/pdc202xx.c Thu Aug 5 18:48:45 1999 @@ -215,8 +215,8 @@ byte test1, test2, speed; byte AP, BP, CP, DP, EP; int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - byte udma_66 = ((id->word93 & 0x2000) && (dev->device == PCI_DEVICE_ID_PROMISE_20262)) ? 1 : 0; - byte udma_33 = ultra ? (inb((dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0; + byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0; + byte udma_33 = ultra ? (inb((dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0; pci_read_config_byte(dev, 0x50, &EP); @@ -308,7 +308,7 @@ speed = XFER_UDMA_3; } else if ((id->dma_ultra & 0x0004) && (udma_33)) { if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0404; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -319,7 +319,7 @@ speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (udma_33)) { if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0202; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -330,7 +330,7 @@ speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (udma_33)) { if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0x0F00; + drive->id->dma_ultra &= ~0xFF00; drive->id->dma_ultra |= 0x0101; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; @@ -493,7 +493,7 @@ __initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name)) { - unsigned long high_16 = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; + unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; byte udma_speed_flag = inb(high_16 + 0x001f); byte primary_mode = inb(high_16 + 0x001a); byte secondary_mode = inb(high_16 + 0x001b); @@ -551,5 +551,20 @@ { if (hwif->dma_base) { hwif->dmaproc = &pdc202xx_dmaproc; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20262: +#if 0 + { + unsigned long high_16 = hwif->pci_dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; + hwif->udma_four = 1; + } +#endif + break; + case PCI_DEVICE_ID_PROMISE_20246: + default: + hwif->udma_four = 0; + break; + } } } diff -u --recursive --new-file v2.3.12/linux/drivers/block/piix.c linux/drivers/block/piix.c --- v2.3.12/linux/drivers/block/piix.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/block/piix.c Thu Aug 5 18:48:45 1999 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/piix.c Version 0.24 June 28, 1999 + * linux/drivers/block/piix.c Version 0.25 July 11, 1999 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer @@ -149,18 +149,19 @@ #ifdef CONFIG_BLK_DEV_PIIX_TUNING -static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra) +static int piix_config_drive_for_dma(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - unsigned long flags; int sitre; short reg4042, reg44, reg48, reg4a; byte speed; int u_speed; - byte maslave = hwif->channel ? 0x42 : 0x40; + + byte maslave = hwif->channel ? 0x42 : 0x40; + int ultra = (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0; int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); int a_speed = 2 << (drive_number * 4); int u_flag = 1 << drive_number; @@ -171,9 +172,6 @@ pci_read_config_word(dev, 0x48, ®48); pci_read_config_word(dev, 0x4a, ®4a); - save_flags(flags); - cli(); - if (id->dma_ultra && (ultra)) { if (!(reg48 & u_flag)) { pci_write_config_word(dev, 0x48, reg48|u_flag); @@ -184,7 +182,12 @@ } } - if ((id->dma_ultra & 0x0004) && (ultra)) { + if ((id->dma_ultra & 0x0010) && (ultra)) { + goto backspeed; + } else if ((id->dma_ultra & 0x0008) && (ultra)) { + goto backspeed; + } else if ((id->dma_ultra & 0x0004) && (ultra)) { +backspeed: drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; if (!((id->dma_ultra >> 8) & 4)) { @@ -256,7 +259,6 @@ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); } - restore_flags(flags); piix_tune_drive(drive, piix_dma_2_pio(speed)); (void) ide_config_drive_speed(drive, speed); @@ -269,7 +271,8 @@ printk("\n"); #endif /* PIIX_DEBUG_DRIVE_INFO */ - return ((int) ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); @@ -277,10 +280,9 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { - int ultra = (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0; switch (func) { case ide_dma_check: - return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive, ultra), drive); + return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive), drive); default : break; } @@ -292,12 +294,14 @@ void ide_init_piix (ide_hwif_t *hwif) { hwif->tuneproc = &piix_tune_drive; -#ifdef CONFIG_BLK_DEV_PIIX_TUNING + if (hwif->dma_base) { +#ifdef CONFIG_BLK_DEV_PIIX_TUNING hwif->dmaproc = &piix_dmaproc; - } else #endif /* CONFIG_BLK_DEV_PIIX_TUNING */ - { + hwif->drives[0].autotune = 0; + hwif->drives[1].autotune = 0; + } else { hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; } diff -u --recursive --new-file v2.3.12/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.3.12/linux/drivers/block/ps2esdi.c Sat May 15 23:43:04 1999 +++ linux/drivers/block/ps2esdi.c Mon Aug 9 10:23:09 1999 @@ -178,7 +178,7 @@ }; /* initialization routine called by ll_rw_blk.c */ -__initfunc(int ps2esdi_init(void)) +int __init ps2esdi_init(void) { /* register the device - pass the name, major number and operations @@ -244,7 +244,7 @@ #endif /* MODULE */ /* handles boot time command line parameters */ -__initfunc(void tp720_setup(char *str, int *ints)) +void __init tp720_setup(char *str, int *ints) { /* no params, just sets the tp720esdi flag if it exists */ @@ -252,7 +252,7 @@ tp720esdi = 1; } -__initfunc(void ed_setup(char *str, int *ints)) +void __init ed_setup(char *str, int *ints) { int hdind = 0; @@ -299,7 +299,7 @@ } /* ps2 esdi specific initialization - called thru the gendisk chain */ -__initfunc(static void ps2esdi_geninit(struct gendisk *ignored)) +static void __init ps2esdi_geninit(struct gendisk *ignored) { /* The first part contains the initialization code @@ -437,7 +437,7 @@ } /* ps2esdi_geninit */ -__initfunc(static void ps2esdi_get_device_cfg(void)) +static void __init ps2esdi_get_device_cfg(void) { u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH]; diff -u --recursive --new-file v2.3.12/linux/drivers/block/q40ide.c linux/drivers/block/q40ide.c --- v2.3.12/linux/drivers/block/q40ide.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/q40ide.c Mon Aug 9 12:32:28 1999 @@ -0,0 +1,109 @@ +/* + * linux/drivers/block/q40ide.c -- Q40 I/O port IDE Driver + * + * original file created 12 Jul 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * RZ: + * almost identical with pcide.c, maybe we can merge it later. + * Differences: + * max 2 HWIFS for now + * translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw] + * address translation + * + */ + +#include +#include +#include +#include +#include + +#include "ide.h" + + /* + * Bases of the IDE interfaces + */ + +#define PCIDE_NUM_HWIFS 2 + +#define PCIDE_BASE1 0x1f0 +#define PCIDE_BASE2 0x170 +#define PCIDE_BASE3 0x1e8 +#define PCIDE_BASE4 0x168 +#define PCIDE_BASE5 0x1e0 +#define PCIDE_BASE6 0x160 + +static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = { + PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, + PCIDE_BASE6 */ +}; + + + /* + * Offsets from one of the above bases + */ + +#undef HD_DATA +#define HD_DATA 0x1f0 + +#define PCIDE_REG(x) ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1)) + +static const int pcide_offsets[IDE_NR_PORTS] = { + PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR), + PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS), + PCIDE_REG(CMD) +}; + +int q40ide_default_irq(q40ide_ioreg_t base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + default: + return 0; + } +} + +void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq) +{ + q40ide_ioreg_t port = base; + int i = 8; + + while (i--) + *p++ = port++; + *p++ = base + 0x206; + if (irq != NULL) + *irq = 0; +} + + + /* + * Probe for PC IDE interfaces + */ + +int q40ide_probe_hwif(int index, ide_hwif_t *hwif) +{ + static int pcide_index[PCIDE_NUM_HWIFS] = { 0, }; + int i; + + if (!MACH_IS_Q40) + return 0; + + for (i = 0; i < PCIDE_NUM_HWIFS; i++) { + if (!pcide_index[i]) { + /*printk("ide%d: Q40 IDE interface\n", index);*/ + pcide_index[i] = index+1; + } + if (pcide_index[i] == index+1) { + ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL); + hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i]; */ /* 14 */ + return 1; + } + } + return 0; +} diff -u --recursive --new-file v2.3.12/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.3.12/linux/drivers/block/rd.c Wed Jun 30 13:38:19 1999 +++ linux/drivers/block/rd.c Mon Aug 9 10:23:09 1999 @@ -116,6 +116,7 @@ int rd_size = 4096; /* Size of the RAM disks */ #ifndef MODULE + int rd_doload = 0; /* 1 = load RAM disk, 0 = don't load */ int rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ int rd_image_start = 0; /* starting block # of image */ @@ -123,7 +124,52 @@ unsigned long initrd_start,initrd_end; int mount_initrd = 1; /* zero if initrd should not be mounted */ int initrd_below_start_ok = 0; + +static int __init no_initrd(char *str) +{ + mount_initrd = 0; + return 1; +} + +__setup("noinitrd", no_initrd); + #endif + +static int __init ramdisk_start_setup(char *str) +{ + rd_image_start = simple_strtol(str,NULL,0); + return 1; +} + +static int __init load_ramdisk(char *str) +{ + rd_doload = simple_strtol(str,NULL,0) & 3; + return 1; +} + +static int __init prompt_ramdisk(char *str) +{ + rd_prompt = simple_strtol(str,NULL,0) & 1; + return 1; +} + +static int __init ramdisk_size(char *str) +{ + rd_size = simple_strtol(str,NULL,0); + return 1; +} + +static int __init ramdisk_size2(char *str) +{ + return ramdisk_size(str); +} + +__setup("ramdisk_start=", ramdisk_start_setup); +__setup("load_ramdisk=", load_ramdisk); +__setup("prompt_ramdisk=", prompt_ramdisk); +__setup("ramdisk=", ramdisk_size); +__setup("ramdisk_size=", ramdisk_size2); + #endif /* @@ -297,7 +343,7 @@ }; /* This is the registration and initialization section of the RAM disk driver */ -__initfunc(int rd_init(void)) +int __init rd_init(void) { int i; @@ -370,8 +416,8 @@ * romfs * gzip */ -__initfunc(int -identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)) +int __init +identify_ramdisk_image(kdev_t device, struct file *fp, int start_block) { const int size = 512; struct minix_super_block *minixsb; @@ -463,7 +509,7 @@ /* * This routine loads in the RAM disk image. */ -__initfunc(static void rd_load_image(kdev_t device, int offset, int unit)) +static void __init rd_load_image(kdev_t device, int offset, int unit) { struct inode inode, out_inode; struct file infile, outfile; @@ -585,7 +631,7 @@ } -__initfunc(static void rd_load_disk(int n)) +static void __init rd_load_disk(int n) { #ifdef CONFIG_BLK_DEV_INITRD extern kdev_t real_root_dev; @@ -614,18 +660,18 @@ } -__initfunc(void rd_load(void)) +void __init rd_load(void) { rd_load_disk(0); } -__initfunc(void rd_load_secondary(void)) +void __init rd_load_secondary(void) { rd_load_disk(1); } #ifdef CONFIG_BLK_DEV_INITRD -__initfunc(void initrd_load(void)) +void __init initrd_load(void) { rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),rd_image_start,0); } @@ -684,21 +730,21 @@ #include "../../lib/inflate.c" -__initfunc(static void *malloc(int size)) +static void __init *malloc(int size) { return kmalloc(size, GFP_KERNEL); } -__initfunc(static void free(void *where)) +static void __init free(void *where) { kfree(where); } -__initfunc(static void gzip_mark(void **ptr)) +static void __init gzip_mark(void **ptr) { } -__initfunc(static void gzip_release(void **ptr)) +static void __init gzip_release(void **ptr) { } @@ -707,7 +753,7 @@ * Fill the input buffer. This is called only when the buffer is empty * and at least one byte is really needed. */ -__initfunc(static int fill_inbuf(void)) +static int __init fill_inbuf(void) { if (exit_code) return -1; @@ -724,7 +770,7 @@ * Write the output window window[0..outcnt-1] and update crc and bytes_out. * (Used for the decompressed data only.) */ -__initfunc(static void flush_window(void)) +static void __init flush_window(void) { ulg c = crc; /* temporary variable */ unsigned n; @@ -741,14 +787,14 @@ outcnt = 0; } -__initfunc(static void error(char *x)) +static void __init error(char *x) { printk(KERN_ERR "%s", x); exit_code = 1; } -__initfunc(static int -crd_load(struct file * fp, struct file *outfp)) +static int __init +crd_load(struct file * fp, struct file *outfp) { int result; diff -u --recursive --new-file v2.3.12/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c --- v2.3.12/linux/drivers/block/rz1000.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/rz1000.c Mon Aug 9 10:23:09 1999 @@ -33,7 +33,7 @@ #ifdef CONFIG_BLK_DEV_IDEPCI -__initfunc(void ide_init_rz1000 (ide_hwif_t *hwif)) /* called from ide-pci.c */ +void __init ide_init_rz1000 (ide_hwif_t *hwif) /* called from ide-pci.c */ { unsigned short reg; struct pci_dev *dev = hwif->pci_dev; @@ -53,7 +53,7 @@ #else -__initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name)) +static void __init init_rz1000 (struct pci_dev *dev, const char *name) { unsigned short reg, h; @@ -83,7 +83,7 @@ } } -__initfunc(void ide_probe_for_rz100x (void)) /* called from ide.c */ +void __init ide_probe_for_rz100x (void) /* called from ide.c */ { struct pci_dev *dev = NULL; diff -u --recursive --new-file v2.3.12/linux/drivers/block/sis5513.c linux/drivers/block/sis5513.c --- v2.3.12/linux/drivers/block/sis5513.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/block/sis5513.c Fri Aug 6 11:16:54 1999 @@ -0,0 +1,417 @@ +/* + * linux/drivers/block/sis5513.c Version 0.06 July 11, 1999 + * + * Copyright (C) 1999 Andre Hedrick + * + * drive_number + * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +static struct pci_dev *host_dev; + +#define SIS5513_DEBUG_DRIVE_INFO 0 + +extern char *ide_xfer_verbose (byte xfer_rate); + +/* + * ((id->word93 & 0x2000) && (HWIF(drive)->udma_four)) + */ +static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + byte drive_pci, test1, test2, mask; + int err; + + byte speed = 0x00; + byte unmask = 0xE0; + byte four_two = 0x00; + int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0; + + if (host_dev) { + switch(host_dev->device) { + case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_620: + unmask = 0xF0; + four_two = 0x01; + default: + break; + } + } + + switch(drive_number) { + case 0: drive_pci = 0x40;break; + case 1: drive_pci = 0x42;break; + case 2: drive_pci = 0x44;break; + case 3: drive_pci = 0x46;break; + default: return ide_dma_off; + } + + pci_read_config_byte(dev, drive_pci, &test1); + pci_read_config_byte(dev, drive_pci|0x01, &test2); + + if ((!ultra) && (test2 & 0x80)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~0x80); + pci_read_config_byte(dev, drive_pci|0x01, &test2); + } + + if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { + if (!((id->dma_ultra >> 8) & 16)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x1010; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + if (!(test2 & 0x90)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); + } + speed = XFER_UDMA_4; + } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { + if (!((id->dma_ultra >> 8) & 8)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0808; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + if (!(test2 & 0xA0)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); + } + speed = XFER_UDMA_3; + } else if ((id->dma_ultra & 0x0004) && (ultra)) { + if (!((id->dma_ultra >> 8) & 4)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0404; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + mask = (four_two) ? 0xB0 : 0xA0; + if (!(test2 & mask)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + pci_write_config_byte(dev, drive_pci|0x01, test2|mask); + } + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0002) && (ultra)) { + if (!((id->dma_ultra >> 8) & 2)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0202; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + mask = (four_two) ? 0xD0 : 0xC0; + if (!(test2 & mask)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + pci_write_config_byte(dev, drive_pci|0x01, test2|mask); + } + speed = XFER_UDMA_1; + } else if ((id->dma_ultra & 0x0001) && (ultra)) { + if (!((id->dma_ultra >> 8) & 1)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0101; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + } + if (!(test2 & unmask)) { + pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); + pci_write_config_byte(dev, drive_pci|0x01, test2|unmask); + } + speed = XFER_UDMA_0; + } else if (id->dma_mword & 0x0004) { + if (!((id->dma_mword >> 8) & 4)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0404; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_2; + } else if (id->dma_mword & 0x0002) { + if (!((id->dma_mword >> 8) & 2)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0202; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_1; + } else if (id->dma_mword & 0x0001) { + if (!((id->dma_mword >> 8) & 1)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0101; + drive->id->dma_1word &= ~0x0F00; + } + speed = XFER_MW_DMA_0; + } else if (id->dma_1word & 0x0004) { + if (!((id->dma_1word >> 8) & 4)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0404; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_2; + } else if (id->dma_1word & 0x0002) { + if (!((id->dma_1word >> 8) & 2)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0202; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_1; + } else if (id->dma_1word & 0x0001) { + if (!((id->dma_1word >> 8) & 1)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0101; + drive->id->dma_mword &= ~0x0F00; + } + speed = XFER_SW_DMA_0; + } else { + return ((int) ide_dma_off_quietly); + } + + err = ide_config_drive_speed(drive, speed); + +#if SIS5513_DEBUG_DRIVE_INFO + printk("%s: %s drive%d\n", + drive->name, + ide_xfer_verbose(speed), + drive_number); +#endif /* SIS5513_DEBUG_DRIVE_INFO */ + + return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + ((id->dma_ultra >> 8) & 7) ? ide_dma_on : + ((id->dma_mword >> 8) & 7) ? ide_dma_on : + ((id->dma_1word >> 8) & 7) ? ide_dma_on : + ide_dma_off_quietly); +} + +static void config_drive_art_rwp (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + + byte timing, pio, drive_pci, test1, test2; + + unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; + unsigned short xfer_pio = drive->id->eide_pio_modes; + int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + + if (drive->media == ide_disk) { + struct pci_dev *dev = hwif->pci_dev; + byte reg4bh = 0; + byte rw_prefetch = (0x11 << drive_number); + + pci_read_config_byte(dev, 0x4b, ®4bh); + if ((reg4bh & rw_prefetch) != rw_prefetch) + pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); + } + + pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + + if (xfer_pio> 4) + xfer_pio = 0; + + if (drive->id->eide_pio_iordy > 0) { + for (xfer_pio = 5; + xfer_pio>0 && + drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; + xfer_pio--); + } else { + xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : + (drive->id->eide_pio_modes & 2) ? 0x04 : + (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; + } + + timing = (xfer_pio >= pio) ? xfer_pio : pio; + +/* + * Mode 0 Mode 1 Mode 2 Mode 3 Mode 4 + * Active time 8T (240ns) 6T (180ns) 4T (120ns) 3T (90ns) 3T (90ns) + * 0x41 2:0 bits 000 110 100 011 011 + * Recovery time 12T (360ns) 7T (210ns) 4T (120ns) 3T (90ns) 1T (30ns) + * 0x40 3:0 bits 0000 0111 0100 0011 0001 + * Cycle time 20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns) + */ + + switch(drive_number) { + case 0: drive_pci = 0x40;break; + case 1: drive_pci = 0x42;break; + case 2: drive_pci = 0x44;break; + case 3: drive_pci = 0x46;break; + default: return; + } + + pci_read_config_byte(dev, drive_pci, &test1); + pci_read_config_byte(dev, drive_pci|0x01, &test2); + + /* + * Do a blanket clear of active and recovery timings. + */ + + test1 &= ~0x07; + test2 &= ~0x0F; + + switch(timing) { + case 4: test1 |= 0x01;test2 |= 0x03;break; + case 3: test1 |= 0x03;test2 |= 0x03;break; + case 2: test1 |= 0x04;test2 |= 0x04;break; + case 1: test1 |= 0x07;test2 |= 0x06;break; + default: break; + } + + pci_write_config_byte(dev, drive_pci, test1); + pci_write_config_byte(dev, drive_pci|0x01, test2); +} + +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_off_quietly; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + return HWIF(drive)->dmaproc(ide_dma_off, drive); + } + + if (id->field_valid & 4) { + if (id->dma_ultra & 0x001F) { + /* Force if Capable UltraDMA */ + dma_func = config_chipset_for_dma(drive, 1); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x0007)) { + /* Force if Capable regular DMA modes */ + dma_func = config_chipset_for_dma(drive, 0); + } + } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && + (id->eide_dma_time > 150)) { + /* Consult the list of known "good" drives */ + dma_func = config_chipset_for_dma(drive, 0); + } + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + +/* + * sis5513_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. + */ +int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + config_drive_art_rwp(drive); + return config_drive_xfer_rate(drive); + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} + +__initfunc(unsigned int pci_init_sis5513 (struct pci_dev *dev, const char *name)) +{ + struct pci_dev *host; + byte latency = 0, reg48h = 0; + + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); + pci_read_config_byte(dev, 0x48, ®48h); + + for (host = pci_devices; host; host=host->next) { + if (host->vendor == PCI_VENDOR_ID_SI && + host->device == PCI_DEVICE_ID_SI_620) { + if (latency != 0x10) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); + host_dev = host; + printk("%s: Chipset Core ATA-66, SiS620\n", name); + printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", + name, + (reg48h & 0x10) ? "33" : "66", + (reg48h & 0x20) ? "33" : "66"); + break; + } else if (host->vendor == PCI_VENDOR_ID_SI && + host->device == PCI_DEVICE_ID_SI_530) { + host_dev = host; + printk("%s: Chipset Core ATA-66, SiS530\n", name); + printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", + name, + (reg48h & 0x10) ? "33" : "66", + (reg48h & 0x20) ? "33" : "66"); + break; + } else if (host->vendor == PCI_VENDOR_ID_SI && + host->device == PCI_DEVICE_ID_SI_5600) { + host_dev = host; + printk("SIS5600:%s Chipset Core ATA-33\n", name); + break; + } else if (host->vendor == PCI_VENDOR_ID_SI && + host->device == PCI_DEVICE_ID_SI_5597) { + host_dev = host; + printk("SIS5597:%s Chipset Core ATA-33\n", name); + break; + } + } + + if (host_dev) { + byte reg52h = 0; + + pci_read_config_byte(dev, 0x52, ®52h); + if (!(reg52h & 0x04)) + pci_write_config_byte(dev, 0x52, reg52h|0x04); + } + + return 0; +} + +__initfunc(void ide_init_sis5513 (ide_hwif_t *hwif)) +{ + byte reg48h = 0; + byte mask = hwif->channel ? 0x20 : 0x10; + + pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + hwif->irq = hwif->channel ? 15 : 14; + + if (!(hwif->dma_base)) + return; + + if (host_dev) { + switch(host_dev->device) { + case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_620: + hwif->autodma = 1; + hwif->udma_four = (reg48h & mask) ? 0 : 1; + hwif->dmaproc = &sis5513_dmaproc; + return; + case PCI_DEVICE_ID_SI_5600: + case PCI_DEVICE_ID_SI_5597: + hwif->autodma = 1; + hwif->udma_four = 0; + hwif->dmaproc = &sis5513_dmaproc; + return; + default: + hwif->autodma = 0; + hwif->udma_four = 0; + return; + } + } +} diff -u --recursive --new-file v2.3.12/linux/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c --- v2.3.12/linux/drivers/block/sl82c105.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/sl82c105.c Thu Aug 5 18:48:45 1999 @@ -1,3 +1,14 @@ +/* + * drivers/block/sl82c105.c + * + * SL82C105/Winbond 553 IDE driver + * + * Maintainer unknown. + * + * Drive tuning added from Corel Computer's kernel sources + * -- Russell King (15/11/98) linux@arm.linux.org.uk + */ + #include #include #include @@ -15,9 +26,108 @@ #include "ide_modes.h" +#ifdef CONFIG_ARCH_NETWINDER +/* + * Convert a PIO mode and cycle time to the required on/off + * times for the interface. This has protection against run-away + * timings. + */ +static unsigned int get_timing_sl82c105(ide_pio_data_t *p) +{ + unsigned int cmd_on; + unsigned int cmd_off; + + cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30; + cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30; + + if (cmd_on > 32) + cmd_on = 32; + if (cmd_on == 0) + cmd_on = 1; + + if (cmd_off > 32) + cmd_off = 32; + if (cmd_off == 0) + cmd_off = 1; + + return (cmd_on - 1) << 8 | (cmd_off - 1); +} + +/* + * Tell the drive to enable the specified PIO mode. + * This should be in ide.c, maybe as a special command + * (see do_special). + */ +static int ide_set_drive_pio_mode(ide_drive_t *drive, byte pio) +{ + ide_hwif_t *hwif = HWIF(drive); + + if (pio > 2) { + /* FIXME: I don't believe that this SELECT_DRIVE is required, + * since ide.c only calls tuneproc from do_special, after + * the correct drive has been selected. + */ + SELECT_DRIVE(hwif, drive); + OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + OUT_BYTE(0x08 | pio, IDE_NSECTOR_REG); + OUT_BYTE(0x03, IDE_FEATURE_REG); + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + + if (ide_wait_stat(drive, DRIVE_READY, + BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD)) { + printk("%s: drive not ready for command\n", + drive->name); + return 1; + } + + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + } + + return 0; +} + +/* + * We only deal with PIO mode here - DMA mode 'using_dma' is not + * initialised at the point that this function is called. + */ +static void tune_sl82c105(ide_drive_t *drive, byte pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + ide_pio_data_t p; + unsigned int drv_ctrl = 0x909; + + pio = ide_get_best_pio_mode(drive, pio, 5, &p); + + if (!ide_set_drive_pio_mode(drive, pio)) { + drv_ctrl = get_timing_sl82c105(&p); + + if (p.use_iordy) + drv_ctrl |= 0x40; + } + + pci_write_config_word(dev, + (hwif->channel ? 0x4c : 0x44) + + (drive->select.b.unit ? 4 : 0), + drv_ctrl); + + printk("%s: selected PIO mode %d (%dns)\n", + drive->name, p.pio_mode, p.cycle_time); +} +#endif + void ide_init_sl82c105(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; + +#ifdef CONFIG_ARCH_NETWINDER + unsigned char ctrl_stat; + + pci_read_config_byte(dev, 0x40, &ctrl_stat); + pci_write_config_byte(dev, 0x40, ctrl_stat | 0x33); + + hwif->tuneproc = tune_sl82c105; +#else unsigned short t16; unsigned int t32; pci_read_config_word(dev, PCI_COMMAND, &t16); @@ -33,4 +143,5 @@ printk("IDE control/status register: %08x\n",t32); pci_write_config_dword(dev, 0x40, 0x10ff08a1); #endif /* CONFIG_MBX */ +#endif } diff -u --recursive --new-file v2.3.12/linux/drivers/block/trm290.c linux/drivers/block/trm290.c --- v2.3.12/linux/drivers/block/trm290.c Thu May 13 11:04:54 1999 +++ linux/drivers/block/trm290.c Mon Aug 9 10:23:09 1999 @@ -212,7 +212,7 @@ /* * Invoked from ide-dma.c at boot time. */ -__initfunc(void ide_init_trm290 (ide_hwif_t *hwif)) +void __init ide_init_trm290 (ide_hwif_t *hwif) { unsigned int cfgbase = 0; unsigned long flags; @@ -220,7 +220,7 @@ struct pci_dev *dev = hwif->pci_dev; hwif->chipset = ide_trm290; - cfgbase = dev->base_address[4]; + cfgbase = dev->resource[4].start; if ((dev->class & 5) && cfgbase) { hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK; diff -u --recursive --new-file v2.3.12/linux/drivers/block/via82c586.c linux/drivers/block/via82c586.c --- v2.3.12/linux/drivers/block/via82c586.c Wed May 26 16:55:40 1999 +++ linux/drivers/block/via82c586.c Thu Aug 5 18:48:45 1999 @@ -1,8 +1,8 @@ /* - * linux/drivers/block/via82c586.c Version 0.03 Nov. 19, 1998 + * linux/drivers/block/via82c586.c Version 0.04 July 11, 1999 * * Copyright (C) 1998 Michel Aubry, Maintainer - * Copyright (C) 1998 Andre Hedrick, Integrater + * Copyright (C) 1998 Andre Hedrick, Maintainer * * The VIA MVP-3 is reported OK with UDMA. * The TX Pro III is also reported OK with UDMA. @@ -57,6 +57,9 @@ #include +static struct pci_dev *host_dev; +static struct pci_dev *isa_dev; + #define DISPLAY_VIA_TIMINGS #if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) @@ -438,6 +441,137 @@ return 0; } +__initfunc(unsigned int pci_init_via82c568 (struct pci_dev *dev, const char *name)) +{ + struct pci_dev *host; + struct pci_dev *isa; + + byte revision = 0; + + for (host = pci_devices; host; host=host->next) { + if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C585) { + host_dev = host; + printk("VT 82C585 Apollo VP1/VPX"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C586_1) { + isa_dev = isa; + pci_read_config_byte(isa_dev, 0x0d, &revision); + if (revision >= 0x20) + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C595) { + host_dev = host; + printk("VT 82C595 Apollo VP2"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C586_1) { + isa_dev = isa; + pci_read_config_byte(isa_dev, 0x0d, &revision); + if (revision >= 0x20) + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C597_0) { + host_dev = host; + printk("VT 82C597 Apollo VP3"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C586_1) { + isa_dev = isa; + pci_read_config_byte(isa_dev, 0x0d, &revision); + if (revision >= 0x20) + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C598_0) { + host_dev = host; + printk("VT 82C598 Apollo MVP3"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C586_1) { + isa_dev = isa; + pci_read_config_byte(isa_dev, 0x0d, &revision); + if (revision >= 0x20) + printk(" Chipset Core ATA-33"); + break; + } else if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C596) { + isa_dev = isa; + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C680) { + host_dev = host; + printk("VT 82C680 Apollo P6"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C586_1) { + isa_dev = isa; + pci_read_config_byte(isa_dev, 0x0d, &revision); + if (revision >= 0x20) + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C691) { + host_dev = host; + printk("VT 82C691 Apollo Pro"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C596) { + isa_dev = isa; + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } else if (host->vendor == PCI_VENDOR_ID_VIA && + host->device == PCI_DEVICE_ID_VIA_82C693) { + host_dev = host; + printk("VT 82C693 Apollo Pro Plus"); + for (isa = pci_devices; isa; isa=isa->next) { + if (isa->vendor == PCI_VENDOR_ID_VIA && + isa->device == PCI_DEVICE_ID_VIA_82C596) { + isa_dev = isa; + printk(" Chipset Core ATA-33"); + break; + } + } + printk("\n"); + break; + } + } + return 0; +} + +__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif)) +{ + set_via_timings(hwif); +} + /* * ide_dmacapable_via82c568(ide_hwif_t *, unsigned long) * checks if channel "channel" of if hwif is dma @@ -464,9 +598,3 @@ ide_setup_dma(hwif, dmabase, 8); } } - -__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif)) -{ - set_via_timings(hwif); -} - diff -u --recursive --new-file v2.3.12/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.3.12/linux/drivers/block/xd.c Sat May 15 23:43:04 1999 +++ linux/drivers/block/xd.c Mon Aug 9 10:23:09 1999 @@ -179,7 +179,7 @@ static int nodma = XD_DONT_USE_DMA; /* xd_init: register the block device number and set up pointer tables */ -__initfunc(int xd_init (void)) +int __init xd_init (void) { if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd: Unable to get major number %d\n",MAJOR_NR); @@ -194,7 +194,7 @@ } /* xd_detect: scan the possible BIOS ROM locations for the signature strings */ -__initfunc(static u_char xd_detect (u_char *controller, unsigned int *address)) +static __init u_char xd_detect (u_char *controller, unsigned int *address) { u_char i,j,found = 0; @@ -218,7 +218,7 @@ /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */ /* and set up the "raw" device entries in the table */ -__initfunc(static void xd_geninit (struct gendisk *ignored)) +static void __init xd_geninit (struct gendisk *ignored) { u_char i,controller; unsigned int address; @@ -686,7 +686,7 @@ return (csb & CSB_ERROR); } -__initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive))) +static u_char __init xd_initdrives (void (*init_drive)(u_char drive)) { u_char cmdblk[6],i,count = 0; @@ -708,14 +708,14 @@ return (count); } -__initfunc(static void xd_manual_geo_set (u_char drive)) +static void __init xd_manual_geo_set (u_char drive) { xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]); xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]); xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]); } -__initfunc(static void xd_dtc_init_controller (unsigned int address)) +static void __init xd_dtc_init_controller (unsigned int address) { switch (address) { case 0x00000: @@ -732,7 +732,7 @@ } -__initfunc(static void xd_dtc5150cx_init_drive (u_char drive)) +static void __init xd_dtc5150cx_init_drive (u_char drive) { /* values from controller's BIOS - BIOS chip may be removed */ static u_short geometry_table[][4] = { @@ -779,7 +779,7 @@ xd_recalibrate(drive); } -__initfunc(static void xd_dtc_init_drive (u_char drive)) +static void __init xd_dtc_init_drive (u_char drive) { u_char cmdblk[6],buf[64]; @@ -806,7 +806,7 @@ printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive); } -__initfunc(static void xd_wd_init_controller (unsigned int address)) +static void __init xd_wd_init_controller (unsigned int address) { switch (address) { case 0x00000: @@ -828,7 +828,7 @@ sleep_on(&xdc_wait); } -__initfunc(static void xd_wd_init_drive (u_char drive)) +static void __init xd_wd_init_drive (u_char drive) { /* values from controller's BIOS - BIOS may be disabled */ static u_short geometry_table[][4] = { @@ -912,7 +912,7 @@ } -__initfunc(static void xd_seagate_init_controller (unsigned int address)) +static void __init xd_seagate_init_controller (unsigned int address) { switch (address) { case 0x00000: @@ -928,7 +928,7 @@ outb(0,XD_RESET); /* reset the controller */ } -__initfunc(static void xd_seagate_init_drive (u_char drive)) +static void __init xd_seagate_init_drive (u_char drive) { u_char cmdblk[6],buf[0x200]; @@ -944,7 +944,7 @@ } /* Omti support courtesy Dirk Melchers */ -__initfunc(static void xd_omti_init_controller (unsigned int address)) +static void __init xd_omti_init_controller (unsigned int address) { switch (address) { case 0x00000: @@ -961,7 +961,7 @@ outb(0,XD_RESET); /* reset the controller */ } -__initfunc(static void xd_omti_init_drive (u_char drive)) +static void __init xd_omti_init_drive (u_char drive) { /* gets infos from drive */ xd_override_init_drive(drive); @@ -971,7 +971,7 @@ } /* Xebec support (AK) */ -__initfunc(static void xd_xebec_init_controller (unsigned int address)) +static void __init xd_xebec_init_controller (unsigned int address) { /* iobase may be set manually in range 0x300 - 0x33C irq may be set manually to 2(9),3,4,5,6,7 @@ -1004,7 +1004,7 @@ sleep_on(&xdc_wait); } -__initfunc(static void xd_xebec_init_drive (u_char drive)) +static void __init xd_xebec_init_drive (u_char drive) { /* values from controller's BIOS - BIOS chip may be removed */ static u_short geometry_table[][5] = { @@ -1047,7 +1047,7 @@ /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */ -__initfunc(static void xd_override_init_drive (u_char drive)) +static void __init xd_override_init_drive (u_char drive) { u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 }; u_char cmdblk[6],i; @@ -1074,7 +1074,7 @@ } /* xd_setup: initialise controler from command line parameters */ -__initfunc(void xd_setup (char *command,int *integers)) +void __init xd_setup (char *command,int *integers) { switch (integers[0]) { case 4: if (integers[4] < 0) @@ -1097,7 +1097,7 @@ #ifndef MODULE /* xd_manual_geo_init: initialise drive geometry from command line parameters (used only for WD drives) */ -__initfunc(void xd_manual_geo_init (char *command,int *integers)) +void __init xd_manual_geo_init (char *command,int *integers) { int i; if (integers[0]%3 != 0) { @@ -1110,7 +1110,7 @@ #endif /* MODULE */ /* xd_setparam: set the drive characteristics */ -__initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)) +static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc) { u_char cmdblk[14]; diff -u --recursive --new-file v2.3.12/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c --- v2.3.12/linux/drivers/block/z2ram.c Fri Dec 18 09:36:05 1998 +++ linux/drivers/block/z2ram.c Mon Aug 9 12:32:28 1999 @@ -32,23 +32,18 @@ #include #include #include - -#if defined(MODULE) #include -#endif #include #include #include -#ifdef CONFIG_APUS #include #include -#endif #include -extern int num_memory; -extern struct mem_info memory[NUM_MEMINFO]; +extern int m68k_realnum_memory; +extern struct mem_info m68k_memory[NUM_MEMINFO]; #define TRUE (1) #define FALSE (0) @@ -191,14 +186,14 @@ int index = device - Z2MINOR_MEMLIST1 + 1; unsigned long size, paddr, vaddr; - if (index >= num_memory) { + if (index >= m68k_realnum_memory) { printk( KERN_ERR DEVICE_NAME ": no such entry in z2ram_map\n" ); return -ENOMEM; } - paddr = memory[index].addr; - size = memory[index].size & ~(Z2RAM_CHUNKSIZE-1); + paddr = m68k_memory[index].addr; + size = m68k_memory[index].size & ~(Z2RAM_CHUNKSIZE-1); #ifdef __powerpc__ /* FIXME: ioremap doesn't build correct memory tables. */ @@ -212,8 +207,7 @@ _PAGE_WRITETHRU); #else - vaddr = kernel_map (paddr, size, KERNELMAP_FULL_CACHING, - NULL); + vaddr = (unsigned long)ioremap(paddr, size); #endif z2ram_map = kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]), @@ -316,9 +310,7 @@ blk_size[ MAJOR_NR ] = z2_sizes; } -#if defined(MODULE) MOD_INC_USE_COUNT; -#endif return 0; } @@ -331,9 +323,11 @@ sync_dev( inode->i_rdev ); -#if defined(MODULE) + /* + * FIXME: unmap memory + */ + MOD_DEC_USE_COUNT; -#endif return 0; } @@ -356,8 +350,8 @@ NULL, /* revalidate */ }; -__initfunc(int -z2_init( void )) +int __init +z2_init( void ) { if ( !MACH_IS_AMIGA ) diff -u --recursive --new-file v2.3.12/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- v2.3.12/linux/drivers/cdrom/cdrom.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/cdrom/cdrom.c Mon Aug 9 12:34:22 1999 @@ -1,7 +1,7 @@ /* linux/drivers/cdrom/cdrom.c. Copyright (c) 1996, 1997 David A. van Leeuwen. Copyright (c) 1997, 1998 Erik Andersen - Copyright (c) 1998, 1999 Jens Axboe + Copyright (c) 1998, 1999 Jens Axboe May be copied or modified under the terms of the GNU General Public License. See linux/COPYING for more information. @@ -125,11 +125,44 @@ -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of CDC_CLOSE_TRAY. -- proc info didn't mask against capabilities mask. + + 3.00 Aug 5, 1999 - Jens Axboe + -- Unified audio ioctl handling across CD-ROM drivers. A lot of the + code was duplicated before. Drives that support the generic packet + interface are now being fed packets from here instead. + -- First attempt at adding support for MMC2 commands - for DVD and + CD-R(W) drives. Only the DVD parts are in now - the interface used is + the same as for the audio ioctls. + -- ioctl cleanups. if a drive couldn't play audio, it didn't get + a change to perform device specific ioctls as well. + -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities. + -- Put in sysctl files for autoclose, autoeject, check_media, debug, + and lock. + -- /proc/sys/dev/cdrom/info has been updated to also contain info about + CD-Rx and DVD capabilities. + -- Now default to checking media type. + -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for + doing this anyway, with the generic_packet addition. + + 3.01 Aug 6, 1999 - Jens Axboe + -- Fix up the sysctl handling so that the option flags get set + correctly. + -- Fix up ioctl handling so the device specific ones actually get + called :). + + 3.02 Aug 8, 1999 - Jens Axboe + -- Fixed volume control on SCSI drives (or others with longer audio + page). + -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath + for telling me and for having defined the various + DVD structures and ioctls in the first place! He designed the original + DVD patches for ide-cd and while I rearranged and unified them, the + interface is still the same. -------------------------------------------------------------------------*/ -#define REVISION "Revision: 2.55" -#define VERSION "Id: cdrom.c 2.55 1999/04/25" +#define REVISION "Revision: 3.02" +#define VERSION "Id: cdrom.c 3.02 1999/08/08" /* I use an error-log mask to give fine grain control over the type of messages dumped to the system logs. The available masks include: */ @@ -172,7 +205,7 @@ static int autoclose=1; static int autoeject=0; static int lockdoor = 1; -static int check_media_type = 0; +static int check_media_type = 1; MODULE_PARM(debug, "i"); MODULE_PARM(autoclose, "i"); MODULE_PARM(autoeject, "i"); @@ -194,8 +227,12 @@ #define IOCTL_OUT(arg, type, out) \ copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT) +/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in + a lot of places. This macro makes the code more clear. */ +#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & type) -#define FM_WRITE 0x2 /* file mode write bit */ +/* used in the audio ioctls */ +#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret /* Not-exported routines. */ static int cdrom_open(struct inode *ip, struct file *fp); @@ -208,6 +245,8 @@ struct cdrom_device_ops * cdo); static void sanitize_format(union cdrom_addr *addr, u_char * curr, u_char requested); +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + unsigned long arg); #ifdef CONFIG_SYSCTL static void cdrom_sysctl_register(void); #endif /* CONFIG_SYSCTL */ @@ -269,13 +308,14 @@ ENSURE(reset, CDC_RESET); ENSURE(audio_ioctl, CDC_PLAY_AUDIO); ENSURE(dev_ioctl, CDC_IOCTLS); + ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; cdo->n_minors = 0; cdi->options = CDO_USE_FFLAGS; - if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY) + if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY)) cdi->options |= (int) CDO_AUTO_CLOSE; - if (autoeject==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY) + if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY)) cdi->options |= (int) CDO_AUTO_EJECT; if (lockdoor==1) cdi->options |= (int) CDO_LOCK; @@ -347,7 +387,7 @@ cdinfo(CD_OPEN, "entering cdrom_open\n"); if (cdi == NULL) return -ENODEV; - if (fp->f_mode & FM_WRITE) + if (fp->f_mode & FMODE_WRITE) return -EROFS; purpose = purpose || !(cdi->options & CDO_USE_FFLAGS); if (purpose) @@ -377,7 +417,7 @@ if (ret == CDS_TRAY_OPEN) { cdinfo(CD_OPEN, "the tray is open...\n"); /* can/may i close it? */ - if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY && + if (CDROM_CAN(CDC_CLOSE_TRAY) && cdi->options & CDO_AUTO_CLOSE) { cdinfo(CD_OPEN, "trying to close the tray.\n"); ret=cdo->tray_move(cdi,0); @@ -421,6 +461,9 @@ * for example, need bit CDO_CHECK_TYPE cleared! */ if (tracks.data==0) { if (cdi->options & CDO_CHECK_TYPE) { + /* give people a warning shot, now that CDO_CHECK_TYPE + is the default case! */ + printk("cdrom: pid %d is buggy!\n", (unsigned int)current->pid); cdinfo(CD_OPEN, "bummer. wrong media type.\n"); ret=-EMEDIUMTYPE; goto clean_up_and_return; @@ -442,8 +485,7 @@ cdinfo(CD_OPEN, "open device failed.\n"); goto clean_up_and_return; } - if (cdo->capability & ~cdi->mask & CDC_LOCK && - cdi->options & CDO_LOCK) { + if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { cdo->lock_door(cdi, 1); cdinfo(CD_OPEN, "door locked.\n"); } @@ -457,8 +499,7 @@ is a goto to avoid bloating the driver with redundant code. */ clean_up_and_return: cdinfo(CD_WARNING, "open failed.\n"); - if (cdo->capability & ~cdi->mask & CDC_LOCK && - cdi->options & CDO_LOCK) { + if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { cdo->lock_door(cdi, 0); cdinfo(CD_OPEN, "door unlocked.\n"); } @@ -482,7 +523,7 @@ if (ret == CDS_TRAY_OPEN) { cdinfo(CD_OPEN, "the tray is open...\n"); /* can/may i close it? */ - if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY && + if (CDROM_CAN(CDC_CLOSE_TRAY) && cdi->options & CDO_AUTO_CLOSE) { cdinfo(CD_OPEN, "trying to close the tray.\n"); ret=cdo->tray_move(cdi,0); @@ -553,8 +594,7 @@ if (sb) invalidate_inodes(sb); invalidate_buffers(dev); if (opened_for_data && - cdi->options & CDO_AUTO_EJECT && - cdo->capability & ~cdi->mask & CDC_OPEN_TRAY) + cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) cdo->tray_move(cdi, 1); } return 0; @@ -572,7 +612,7 @@ unsigned int mask = (1 << (queue & 1)); int ret = !!(cdi->mc_flags & mask); - if (!(cdi->ops->capability & ~cdi->mask & CDC_MEDIA_CHANGED)) + if (!CDROM_CAN(CDC_MEDIA_CHANGED)) return ret; /* changed since last call? */ if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) { @@ -594,7 +634,7 @@ return 0; if (cdi->ops->media_changed == NULL) return 0; - if (!(cdi->ops->capability & ~cdi->mask & CDC_MEDIA_CHANGED)) + if (!CDROM_CAN(CDC_MEDIA_CHANGED)) return 0; return (media_changed(cdi, 0)); } @@ -610,7 +650,7 @@ tracks->xa=0; tracks->error=0; cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); - if (!(cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)) { + if (!CDROM_CAN(CDC_PLAY_AUDIO)) { tracks->error=CDS_NO_INFO; return; } @@ -684,6 +724,374 @@ *curr = requested; } +/* DVD handling */ + +#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key)) +#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge)) + +static void setup_report_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type) +{ + cgc->cmd[0] = DVD_REPORT_KEY; + cgc->cmd[10] = type | (agid << 6); +} + +static void setup_send_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type) +{ + cgc->cmd[0] = DVD_SEND_KEY; + cgc->cmd[10] = type | (agid << 6); +} + +static int dvd_do_auth (struct cdrom_device_info *cdi, dvd_authinfo *ai) +{ + int rv; + u_char buf[20]; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(&cgc, 0, sizeof(cgc)); + memset(buf, 0x93, sizeof(buf)); + cgc.buffer = buf; + + switch (ai->type) { + /* LU data send */ + case DVD_LU_SEND_AGID: + cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_AGID\n"); + setup_report_key (&cgc, 0, 0); + cgc.buflen = cgc.cmd[9] = 8; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + ai->lsa.agid = buf[7] >> 6; + /* Returning data, let host change state */ + break; + + case DVD_LU_SEND_KEY1: + cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_KEY1\n"); + setup_report_key (&cgc, ai->lsk.agid, 2); + cgc.buflen = cgc.cmd[9] = 12; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + copy_key(ai->lsk.key, &buf[4]); + /* Returning data, let host change state */ + break; + + case DVD_LU_SEND_CHALLENGE: + cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_CHALLENGE\n"); + setup_report_key (&cgc, ai->lsc.agid, 1); + cgc.buflen = cgc.cmd[9] = 16; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + copy_chal(ai->lsc.chal, &buf[4]); + /* Returning data, let host change state */ + break; + + /* Post-auth key */ + case DVD_LU_SEND_TITLE_KEY: + cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_TITLE_KEY\n"); + setup_report_key (&cgc, ai->lstk.agid, 4); + cgc.cmd[5] = ai->lstk.lba; + cgc.cmd[4] = ai->lstk.lba >> 8; + cgc.cmd[3] = ai->lstk.lba >> 16; + cgc.cmd[2] = ai->lstk.lba >> 24; + cgc.buflen = cgc.cmd[9] = 12; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + ai->lstk.cpm = (buf[4] >> 7) & 1; + ai->lstk.cp_sec = (buf[4] >> 6) & 1; + ai->lstk.cgms = (buf[4] >> 4) & 3; + copy_key (ai->lstk.title_key, &buf[5]); + /* Returning data, let host change state */ + break; + + case DVD_LU_SEND_ASF: + cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_ASF\n"); + setup_report_key (&cgc, ai->lsasf.asf, 5); + cgc.buflen = cgc.cmd[9] = 8; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + ai->lsasf.asf = buf[7] & 1; + break; + + /* LU data receive (LU changes state) */ + case DVD_HOST_SEND_CHALLENGE: + cdinfo(CD_DO_IOCTL, "entering DVD_HOST_SEND_CHALLENGE\n"); + setup_send_key (&cgc, ai->hsc.agid, 1); + cgc.buflen = -(cgc.cmd[9] = 16); + buf[1] = 14; + copy_chal (&buf[4], ai->hsc.chal); + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + ai->type = DVD_LU_SEND_KEY1; + break; + + case DVD_HOST_SEND_KEY2: + cdinfo(CD_DO_IOCTL, "entering DVD_HOST_SEND_KEY2\n"); + setup_send_key (&cgc, ai->hsk.agid, 3); + cgc.buflen = -(cgc.cmd[9] = 12); + buf[1] = 10; + copy_key (&buf[4], ai->hsk.key); + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) { + ai->type = DVD_AUTH_FAILURE; + return rv; + } + ai->type = DVD_AUTH_ESTABLISHED; + break; + + /* Misc */ + case DVD_INVALIDATE_AGID: + cdinfo(CD_DO_IOCTL, "entering DVD_INVALIDATE_AGID\n"); + setup_report_key (&cgc, ai->lsa.agid, 0x3f); + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + break; + + default: + cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type); + return -ENOTTY; + } + + return 0; +} + +static int dvd_read_physical (struct cdrom_device_info *cdi, dvd_struct *s) +{ + int rv, i; + u_char buf[4 + 4 * 20], *base; + struct dvd_layer *layer; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(buf, 0, sizeof(buf)); + memset(&cgc, 0, sizeof(cgc)); + cgc.buffer = buf; + cgc.buflen = sizeof(buf); + cgc.cmd[0] = DVD_READ_STRUCTURE; + cgc.cmd[6] = s->physical.layer_num; + cgc.cmd[7] = s->type; + cgc.cmd[9] = cgc.buflen & 0xff; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + base = &buf[4]; + layer = &s->physical.layer[0]; + + /* place the data... really ugly, but at least we won't have to + worry about endianess in userspace or here. */ + for (i = 0; i < 4; ++i, base += 20, ++layer) { + memset (layer, 0, sizeof (*layer)); + layer->book_version = base[0] & 0xf; + layer->book_type = base[0] >> 4; + layer->min_rate = base[1] & 0xf; + layer->disc_size = base[1] >> 4; + layer->layer_type = base[2] & 0xf; + layer->track_path = (base[2] >> 4) & 1; + layer->nlayers = (base[2] >> 5) & 3; + layer->track_density = base[3] & 0xf; + layer->linear_density = base[3] >> 4; + layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; + layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; + layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; + layer->bca = base[16] >> 7; + } + + return 0; +} + +static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s) +{ + int rv; + u_char buf[8]; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(buf, 0, sizeof(buf)); + memset(&cgc, 0, sizeof(cgc)); + cgc.buffer = buf; + cgc.buflen = sizeof(buf); + cgc.cmd[0] = DVD_READ_STRUCTURE; + cgc.cmd[6] = s->copyright.layer_num; + cgc.cmd[7] = s->type; + cgc.cmd[8] = cgc.buflen >> 8; + cgc.cmd[9] = cgc.buflen & 0xff; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + s->copyright.cpst = buf[4]; + s->copyright.rmi = buf[5]; + + return 0; +} + +static int dvd_read_disckey (struct cdrom_device_info *cdi, dvd_struct *s) +{ + int rv; + u_char buf[4 + 2048]; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(buf, 0, sizeof (buf)); + memset(&cgc, 0, sizeof (cgc)); + + cgc.buffer = buf; + cgc.buflen = sizeof(buf); + cgc.cmd[0] = DVD_READ_STRUCTURE; + cgc.cmd[7] = s->type; + cgc.cmd[8] = sizeof(buf) >> 8; + cgc.cmd[9] = cgc.buflen & 0xff; + cgc.cmd[10] = s->disckey.agid << 6; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + memcpy (s->disckey.value, &buf[4], 2048); + + return 0; +} + +static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s) +{ + int rv; + u_char buf[4 + 188]; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(buf, 0, sizeof (buf)); + memset(&cgc, 0, sizeof (cgc)); + cgc.buffer = buf; + cgc.buflen = sizeof(buf); + cgc.cmd[0] = DVD_READ_STRUCTURE; + cgc.cmd[7] = s->type; + cgc.cmd[9] = cgc.buflen = 0xff; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + s->bca.len = buf[0] << 8 | buf[1]; + if (s->bca.len < 12 || s->bca.len > 188) { + cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len); + return -EIO; + } + memcpy(s->bca.value, &buf[4], s->bca.len); + + return 0; +} + +static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s) +{ + int rv; + u_char buf[4 + 2048]; + struct cdrom_generic_command cgc; + struct cdrom_device_ops *cdo = cdi->ops; + + memset(buf, 0, sizeof(buf)); + memset(&cgc, 0, sizeof(cgc)); + cgc.buffer = buf; + cgc.cmd[0] = DVD_READ_STRUCTURE; + cgc.cmd[7] = s->type; + cgc.buflen = sizeof(buf); + cgc.cmd[8] = sizeof(buf) >> 8; + cgc.cmd[9] = cgc.buflen & 0xff; + + rv = cdo->generic_packet(cdi, &cgc); + if (rv) + return rv; + + s->manufact.len = buf[0] << 8 | buf[1]; + if (s->manufact.len < 0 || s->manufact.len > 2048) { + cdinfo(CD_WARNING, "Recieved invalid manufacture info length (%d)\n", s->bca.len); + return -EIO; + } + memcpy(s->manufact.value, &buf[4], s->manufact.len); + + return 0; +} + +static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s) +{ + switch (s->type) { + case DVD_STRUCT_PHYSICAL: + return dvd_read_physical(cdi, s); + + case DVD_STRUCT_COPYRIGHT: + return dvd_read_copyright(cdi, s); + + case DVD_STRUCT_DISCKEY: + return dvd_read_disckey(cdi, s); + + case DVD_STRUCT_BCA: + return dvd_read_bca(cdi, s); + + case DVD_STRUCT_MANUFACT: + return dvd_read_manufact(cdi, s); + + default: + cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n", + s->type); + return -EINVAL; + } +} + +static int cdrom_mode_sense(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc, + int page_code, int page_control) +{ + struct cdrom_device_ops *cdo = cdi->ops; + + memset(cgc->cmd, 0, sizeof(cgc->cmd)); + + cgc->cmd[0] = 0x5a; /* MODE_SENSE_10 */ + cgc->cmd[2] = page_code | (page_control << 6); + cgc->cmd[7] = cgc->buflen >> 8; + cgc->cmd[8] = cgc->buflen & 0xff; + return cdo->generic_packet(cdi, cgc); +} + +static int cdrom_mode_select(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc) +{ + struct cdrom_device_ops *cdo = cdi->ops; + + memset(cgc->cmd, 0, sizeof(cgc->cmd)); + + cgc->cmd[0] = 0x55; /* MODE_SELECT_10 */ + cgc->cmd[1] = 0x10; /* PF */ + + /* generic_packet() wants the length as seen from the drive, i.e. + it will transfer data _to_ us. The CD-ROM wants the absolute + value, however. */ + cgc->cmd[7] = (-cgc->buflen) >> 8; + cgc->cmd[8] = (-cgc->buflen) & 0xff; + + return cdo->generic_packet(cdi, cgc); +} + /* Some of the cdrom ioctls are not implemented here, because these * appear to be either too device-specific, or it is not clear to me * what use they are. These are (number of drivers that support them @@ -704,6 +1112,7 @@ kdev_t dev = ip->i_rdev; struct cdrom_device_info *cdi = cdrom_find_device (dev); struct cdrom_device_ops *cdo; + int ret; if (cdi == NULL) return -ENODEV; @@ -715,7 +1124,6 @@ /* maybe we should order cases after statistics of use? */ case CDROMMULTISESSION: { - int ret; struct cdrom_multisession ms_info; u_char requested_format; cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); @@ -737,28 +1145,28 @@ } case CDROMEJECT: { - int ret; cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); - if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)) + if (!CDROM_CAN(CDC_OPEN_TRAY)) return -ENOSYS; if (cdi->use_count != 1 || keeplocked) return -EBUSY; - if (cdo->capability & ~cdi->mask & CDC_LOCK) + if (CDROM_CAN(CDC_LOCK)) if ((ret=cdo->lock_door(cdi, 0))) return ret; return cdo->tray_move(cdi, 1); } - case CDROMCLOSETRAY: + case CDROMCLOSETRAY: { cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); - if (!(cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY)) + if (!CDROM_CAN(CDC_CLOSE_TRAY)) return -ENOSYS; return cdo->tray_move(cdi, 0); + } - case CDROMEJECT_SW: + case CDROMEJECT_SW: { cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); - if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)) + if (!CDROM_CAN(CDC_OPEN_TRAY)) return -ENOSYS; if (keeplocked) return -EBUSY; @@ -766,13 +1174,13 @@ if (arg) cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT; return 0; + } case CDROM_MEDIA_CHANGED: { cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); - if (!(cdo->capability & ~cdi->mask & CDC_MEDIA_CHANGED)) + if (!CDROM_CAN(CDC_MEDIA_CHANGED)) return -ENOSYS; - if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC) - || arg == CDSL_CURRENT) + if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) /* cannot select disc or select current disc */ return media_changed(cdi, 1); if ((unsigned int)arg >= cdi->capacity) @@ -780,7 +1188,7 @@ return cdo->media_changed (cdi, arg); } - case CDROM_SET_OPTIONS: + case CDROM_SET_OPTIONS: { cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); /* options need to be in sync with capability. too late for that, so we have to check each one separately... */ @@ -789,34 +1197,36 @@ case CDO_CHECK_TYPE: break; case CDO_LOCK: - if (!(cdo->capability & ~cdi->mask & CDC_LOCK)) + if (!CDROM_CAN(CDC_LOCK)) return -ENOSYS; break; case 0: return cdi->options; /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */ default: - if (!(cdo->capability & ~cdi->mask & arg)) + if (!CDROM_CAN(arg)) return -ENOSYS; } cdi->options |= (int) arg; return cdi->options; + } - case CDROM_CLEAR_OPTIONS: + case CDROM_CLEAR_OPTIONS: { cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); cdi->options &= ~(int) arg; return cdi->options; + } case CDROM_SELECT_SPEED: { cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); - if (!(cdo->capability & ~cdi->mask & CDC_SELECT_SPEED)) + if (!CDROM_CAN(CDC_SELECT_SPEED)) return -ENOSYS; return cdo->select_speed(cdi, arg); } case CDROM_SELECT_DISC: { cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); - if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC)) + if (!CDROM_CAN(CDC_SELECT_DISC)) return -ENOSYS; if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) return cdo->select_disc(cdi, arg); @@ -826,15 +1236,17 @@ } case CDROMRESET: { + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n"); - if (!(cdo->capability & ~cdi->mask & CDC_RESET)) + if (!CDROM_CAN(CDC_RESET)) return -ENOSYS; return cdo->reset(cdi); } case CDROM_LOCKDOOR: { - cdinfo(CD_DO_IOCTL, "%socking door.\n",arg?"L":"Unl"); - if (!(cdo->capability & ~cdi->mask & CDC_LOCK)) { + cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); + if (!CDROM_CAN(CDC_LOCK)) { return -EDRIVE_CANT_DO_THIS; } else { keeplocked = arg ? 1 : 0; @@ -845,7 +1257,7 @@ case CDROM_DEBUG: { if (!capable(CAP_SYS_ADMIN)) return -EACCES; - cdinfo(CD_DO_IOCTL, "%sabling debug.\n",arg?"En":"Dis"); + cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); debug = arg ? 1 : 0; return debug; } @@ -861,7 +1273,6 @@ * is written on the CD is /not/ uniform across all discs! */ case CDROM_GET_MCN: { - int ret; struct cdrom_mcn mcn; cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); if (!(cdo->capability & CDC_MCN)) @@ -923,144 +1334,263 @@ return CDS_NO_INFO; } - case CDROM_CHANGER_NSLOTS: + case CDROM_CHANGER_NSLOTS: { cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); - return cdi->capacity; + return cdi->capacity; + } + } -/* The following is not implemented, because there are too many - * different data types. We could support /1/ raw mode, that is large - * enough to hold everything. - */ + /* use the ioctls that are implemented through the generic_packet() + interface. this may look at bit funny, but if -ENOTTY is + returned that particular ioctl is not implemented and we + let it go through the device specific ones. */ + if (CDROM_CAN(CDC_GENERIC_PACKET)) { + ret = mmc_ioctl(cdi, cmd, arg); + if (ret != -ENOTTY) { + return ret; + } + } -#if 0 - case CDROMREADMODE1: { - int ret; + /* note: most of the cdinfo() calls are commented out here, + because they fill up the sys log when CD players poll + the drive. */ + switch (cmd) { + case CDROMSUBCHNL: { + struct cdrom_subchnl q; + u_char requested, back; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ + IOCTL_IN(arg, struct cdrom_subchnl, q); + requested = q.cdsc_format; + if (!((requested == CDROM_MSF) || + (requested == CDROM_LBA))) + return -EINVAL; + q.cdsc_format = CDROM_MSF; + if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) + return ret; + back = q.cdsc_format; /* local copy */ + sanitize_format(&q.cdsc_absaddr, &back, requested); + sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); + IOCTL_OUT(arg, struct cdrom_subchnl, q); + /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ + return 0; + } + case CDROMREADTOCHDR: { + struct cdrom_tochdr header; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ + IOCTL_IN(arg, struct cdrom_tochdr, header); + if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) + return ret; + IOCTL_OUT(arg, struct cdrom_tochdr, header); + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ + return 0; + } + case CDROMREADTOCENTRY: { + struct cdrom_tocentry entry; + u_char requested_format; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ + IOCTL_IN(arg, struct cdrom_tocentry, entry); + requested_format = entry.cdte_format; + if (!((requested_format == CDROM_MSF) || + (requested_format == CDROM_LBA))) + return -EINVAL; + /* make interface to low-level uniform */ + entry.cdte_format = CDROM_MSF; + if ((ret=cdo->audio_ioctl(cdi, cmd, &entry))) + return ret; + sanitize_format(&entry.cdte_addr, + &entry.cdte_format, requested_format); + IOCTL_OUT(arg, struct cdrom_tocentry, entry); + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ + return 0; + } + case CDROMPLAYMSF: { struct cdrom_msf msf; - char buf[CD_FRAMESIZE]; - cdinfo(CD_DO_IOCTL, "entering CDROMREADMODE1\n"); + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); IOCTL_IN(arg, struct cdrom_msf, msf); - if (ret=cdo->read_audio(dev, cmd, &msf, &buf, cdi)) + CHECKAUDIO; + return cdo->audio_ioctl(cdi, cmd, &msf); + } + case CDROMPLAYTRKIND: { + struct cdrom_ti ti; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); + IOCTL_IN(arg, struct cdrom_ti, ti); + CHECKAUDIO; + return cdo->audio_ioctl(cdi, cmd, &ti); + } + case CDROMVOLCTRL: { + struct cdrom_volctrl volume; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); + IOCTL_IN(arg, struct cdrom_volctrl, volume); + return cdo->audio_ioctl(cdi, cmd, &volume); + } + case CDROMVOLREAD: { + struct cdrom_volctrl volume; + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); + if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) return ret; - IOCTL_OUT(arg, __typeof__(buf), buf); + IOCTL_OUT(arg, struct cdrom_volctrl, volume); return 0; } -#endif + case CDROMSTART: + case CDROMSTOP: + case CDROMPAUSE: + case CDROMRESUME: { + if (!CDROM_CAN(CDC_PLAY_AUDIO)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); + CHECKAUDIO; + return cdo->audio_ioctl(cdi, cmd, NULL); + } } /* switch */ -/* Now all the audio-ioctls follow, they are all routed through the - same call audio_ioctl(). */ + /* do the device specific ioctls */ + if (CDROM_CAN(CDC_IOCTLS)) + return cdo->dev_ioctl(cdi, cmd, arg); + + return -ENOSYS; +} -#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + unsigned long arg) +{ + struct cdrom_device_ops *cdo = cdi->ops; + struct cdrom_generic_command cgc; + int rv; - if (!(cdo->capability & CDC_PLAY_AUDIO)) - return -ENOSYS; - else { - switch (cmd) { - case CDROMSUBCHNL: { - int ret; - struct cdrom_subchnl q; - u_char requested, back; - /* comment out the cdinfo calls here because they - fill up the sys logs when CD players poll the drive*/ - /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - IOCTL_IN(arg, struct cdrom_subchnl, q); - requested = q.cdsc_format; - if (!((requested == CDROM_MSF) || - (requested == CDROM_LBA))) - return -EINVAL; - q.cdsc_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) - return ret; - back = q.cdsc_format; /* local copy */ - sanitize_format(&q.cdsc_absaddr, &back, requested); - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); - IOCTL_OUT(arg, struct cdrom_subchnl, q); - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ - return 0; - } - case CDROMREADTOCHDR: { - int ret; - struct cdrom_tochdr header; - /* comment out the cdinfo calls here because they - fill up the sys logs when CD players poll the drive*/ - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - IOCTL_IN(arg, struct cdrom_tochdr, header); - if ((ret=cdo->audio_ioctl(cdi, cmd, &header))) - return ret; - IOCTL_OUT(arg, struct cdrom_tochdr, header); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */ - return 0; - } - case CDROMREADTOCENTRY: { - int ret; - struct cdrom_tocentry entry; - u_char requested_format; - /* comment out the cdinfo calls here because they - fill up the sys logs when CD players poll the drive*/ - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - IOCTL_IN(arg, struct cdrom_tocentry, entry); - requested_format = entry.cdte_format; - if (!((requested_format == CDROM_MSF) || - (requested_format == CDROM_LBA))) - return -EINVAL; - /* make interface to low-level uniform */ - entry.cdte_format = CDROM_MSF; - if ((ret=cdo->audio_ioctl(cdi, cmd, &entry))) - return ret; - sanitize_format(&entry.cdte_addr, - &entry.cdte_format, requested_format); - IOCTL_OUT(arg, struct cdrom_tocentry, entry); - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ + memset(&cgc, 0, sizeof(cgc)); + + /* build a unified command and queue it through + cdo->generic_packet() */ + switch (cmd) { + case CDROMVOLCTRL: + case CDROMVOLREAD: { + struct cdrom_volctrl volctrl; + char buffer[32], mask[32]; + unsigned short offset; + cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); + + IOCTL_IN(arg, struct cdrom_volctrl, volctrl); + + cgc.buffer = buffer; + cgc.buflen = 24; + rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0); + if (rv) return rv; + + /* some drives have longer pages, adjust and reread. */ + if (buffer[1] > cgc.buflen) { + cgc.buflen = buffer[1] + 2; + rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0); + if (rv) return rv; + } + + /* get the offset from the length of the page. length + is measure from byte 2 an on, thus the 14. */ + offset = buffer[1] - 14; + + /* now we have the current volume settings. if it was only + a CDROMVOLREAD, return these values */ + if (cmd == CDROMVOLREAD) { + volctrl.channel0 = buffer[offset+9]; + volctrl.channel1 = buffer[offset+11]; + volctrl.channel2 = buffer[offset+13]; + volctrl.channel3 = buffer[offset+15]; + IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); return 0; - } - case CDROMPLAYMSF: { - int ret; - struct cdrom_msf msf; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); - IOCTL_IN(arg, struct cdrom_msf, msf); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &msf); - } - case CDROMPLAYTRKIND: { - int ret; - struct cdrom_ti ti; - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, &ti); - } - case CDROMVOLCTRL: { - struct cdrom_volctrl volume; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n"); - IOCTL_IN(arg, struct cdrom_volctrl, volume); - return cdo->audio_ioctl(cdi, cmd, &volume); - } - case CDROMVOLREAD: { - int ret; - struct cdrom_volctrl volume; - cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n"); - if ((ret=cdo->audio_ioctl(cdi, cmd, &volume))) - return ret; - IOCTL_OUT(arg, struct cdrom_volctrl, volume); + } + + /* get the volume mask */ + cgc.buffer = mask; + rv = cdrom_mode_sense(cdi, &cgc, 0xe, 1); + if (rv) return rv; + + buffer[offset+9] = volctrl.channel0 & mask[offset+9]; + buffer[offset+11] = volctrl.channel1 & mask[offset+11]; + buffer[offset+13] = volctrl.channel2 & mask[offset+13]; + buffer[offset+15] = volctrl.channel3 & mask[offset+15]; + + /* clear the first three */ + memset(buffer, 0, 3); + + /* set volume */ + cgc.buflen = -cgc.buflen; + cgc.buffer = buffer; + return cdrom_mode_select(cdi, &cgc); + } + + case CDROMSTART: + case CDROMSTOP: { + cdinfo(CD_DO_IOCTL, "entering audio ioctl (start/stop)\n"); + cgc.cmd[0] = 0x1b; + cgc.cmd[1] = 1; + cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0; + return cdo->generic_packet(cdi, &cgc); + } + + case CDROMPAUSE: + case CDROMRESUME: { + cdinfo(CD_DO_IOCTL, "entering audio ioctl (pause/resume)\n"); + cgc.cmd[0] = 0x4b; + cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; + return cdo->generic_packet(cdi, &cgc); + } + + case DVD_READ_STRUCT: { + dvd_struct s; + if (!CDROM_CAN(CDC_DVD)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering dvd_read_struct\n"); + IOCTL_IN(arg, dvd_struct, s); + if ((rv = dvd_read_struct(cdi, &s)) == 0) { + IOCTL_OUT(arg, dvd_struct, s); return 0; - } - case CDROMSTART: - case CDROMSTOP: - case CDROMPAUSE: - case CDROMRESUME: { - int ret; - cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n"); - CHECKAUDIO; - return cdo->audio_ioctl(cdi, cmd, NULL); - } - } /* switch */ - } + } + return rv; + } - /* device specific ioctls? */ - if (!(cdo->capability & CDC_IOCTLS)) - return -ENOSYS; - else - return cdo->dev_ioctl(cdi, cmd, arg); + case DVD_AUTH: { + dvd_authinfo ai; + if (!CDROM_CAN(CDC_DVD)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering dvd_auth\n"); + IOCTL_IN(arg, dvd_authinfo, ai); + if ((rv = dvd_do_auth (cdi, &ai))) + return rv; + IOCTL_OUT(arg, dvd_authinfo, ai); + return 0; + } + + case CDROM_SEND_PACKET: { + if (!CDROM_CAN(CDC_GENERIC_PACKET)) + return -ENOSYS; + cdinfo(CD_DO_IOCTL, "entering send_packet\n"); + IOCTL_IN(arg, struct cdrom_generic_command, cgc); + cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL); + rv = cdo->generic_packet(cdi, &cgc); + if (copy_to_user((void*)arg, cgc.buffer, cgc.buflen)) { + kfree(cgc.buffer); + return -EFAULT; + } + kfree(cgc.buffer); + return rv; + } + + } /* switch */ + + return -ENOTTY; } EXPORT_SYMBOL(cdrom_count_tracks); @@ -1072,90 +1602,197 @@ #define CDROM_STR_SIZE 1000 -static char cdrom_drive_info[CDROM_STR_SIZE]="info\n"; +struct cdrom_sysctl_settings { + char info[CDROM_STR_SIZE]; /* general info */ + int autoclose; /* close tray upon mount, etc */ + int autoeject; /* eject on umount */ + int debug; /* turn on debugging messages */ + int lock; /* lock the door on device open */ + int check; /* check media type */ +} cdrom_sysctl_settings; int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp) { int pos; struct cdrom_device_info *cdi; + char *info = cdrom_sysctl_settings.info; if (!*lenp || (filp->f_pos && !write)) { *lenp = 0; return 0; } - pos = sprintf(cdrom_drive_info, "CD-ROM information, " VERSION "\n"); + pos = sprintf(info, "CD-ROM information, " VERSION "\n"); - pos += sprintf(cdrom_drive_info+pos, "\ndrive name:\t"); + pos += sprintf(info+pos, "\ndrive name:\t"); + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) + pos += sprintf(info+pos, "\t%s", cdi->name); + + pos += sprintf(info+pos, "\ndrive speed:\t"); + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) + pos += sprintf(info+pos, "\t%d", cdi->speed); + + pos += sprintf(info+pos, "\ndrive # of slots:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%s", cdi->name); + pos += sprintf(info+pos, "\t%d", cdi->capacity); - pos += sprintf(cdrom_drive_info+pos, "\ndrive speed:\t"); + pos += sprintf(info+pos, "\nCan close tray:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->speed); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0); - pos += sprintf(cdrom_drive_info+pos, "\ndrive # of slots:"); + pos += sprintf(info+pos, "\nCan open tray:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->capacity); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan close tray:\t"); + pos += sprintf(info+pos, "\nCan lock tray:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_CLOSE_TRAY)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan open tray:\t"); + pos += sprintf(info+pos, "\nCan change speed:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_OPEN_TRAY)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan lock tray:\t"); + pos += sprintf(info+pos, "\nCan select disk:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_LOCK)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan change speed:"); + pos += sprintf(info+pos, "\nCan read multisession:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_SPEED)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan select disk:"); + pos += sprintf(info+pos, "\nCan read MCN:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_DISC)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan read multisession:"); + pos += sprintf(info+pos, "\nReports media changed:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & CDC_MULTI_SESSION)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan read MCN:\t"); + pos += sprintf(info+pos, "\nCan play audio:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & CDC_MCN)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nReports media changed:"); + pos += sprintf(info+pos, "\nCan write CD-R:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & CDC_MEDIA_CHANGED)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0); - pos += sprintf(cdrom_drive_info+pos, "\nCan play audio:\t"); + pos += sprintf(info+pos, "\nCan write CD-RW:"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(cdrom_drive_info+pos, "\t%d", - ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0)); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0); - strcpy(cdrom_drive_info+pos,"\n\n"); - pos += 3; - if (*lenp > pos) - *lenp = pos; + pos += sprintf(info+pos, "\nCan read DVD:\t"); + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0); + pos += sprintf(info+pos, "\nCan write DVD-R:"); + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0); + + pos += sprintf(info+pos, "\nCan write DVD-RAM:"); + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0); + + strcpy(info+pos,"\n\n"); + return proc_dostring(ctl, write, filp, buffer, lenp); } +/* Unfortunately, per device settings are not implemented through + procfs/sysctl yet. When they are, this will naturally disappear. For now + just update all drives. Later this will become the template on which + new registered drives will be based. */ +void cdrom_update_settings(void) +{ + struct cdrom_device_info *cdi; + + for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) { + if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY)) + cdi->options |= CDO_AUTO_CLOSE; + else if (!autoclose) + cdi->options &= ~CDO_AUTO_CLOSE; + if (autoeject && CDROM_CAN(CDC_OPEN_TRAY)) + cdi->options |= CDO_AUTO_EJECT; + else if (!autoeject) + cdi->options &= ~CDO_AUTO_EJECT; + if (lockdoor && CDROM_CAN(CDC_LOCK)) + cdi->options |= CDO_LOCK; + else if (!lockdoor) + cdi->options &= ~CDO_LOCK; + if (check_media_type) + cdi->options |= CDO_CHECK_TYPE; + else + cdi->options &= ~CDO_CHECK_TYPE; + } +} + +static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp, + void *buffer, size_t *lenp) +{ + int *valp = ctl->data; + int val = *valp; + int ret; + + ret = proc_dointvec(ctl, write, filp, buffer, lenp); + + if (write && *valp != val) { + + /* we only care for 1 or 0. */ + if (*valp) + *valp = 1; + else + *valp = 0; + + switch (ctl->ctl_name) { + case DEV_CDROM_AUTOCLOSE: { + if (valp == &cdrom_sysctl_settings.autoclose) + autoclose = cdrom_sysctl_settings.autoclose; + break; + } + case DEV_CDROM_AUTOEJECT: { + if (valp == &cdrom_sysctl_settings.autoeject) + autoeject = cdrom_sysctl_settings.autoeject; + break; + } + case DEV_CDROM_DEBUG: { + if (valp == &cdrom_sysctl_settings.debug) + debug = cdrom_sysctl_settings.debug; + break; + } + case DEV_CDROM_LOCK: { + if (valp == &cdrom_sysctl_settings.lock) + lockdoor = cdrom_sysctl_settings.lock; + break; + } + case DEV_CDROM_CHECK_MEDIA: { + if (valp == &cdrom_sysctl_settings.check) + check_media_type = cdrom_sysctl_settings.check; + break; + } + } + /* update the option flags according to the changes. we + don't have per device options through sysctl yet, + but we will have and then this will disappear. */ + cdrom_update_settings(); + } + + return ret; +} + /* Place files in /proc/sys/dev/cdrom */ ctl_table cdrom_table[] = { - {DEV_CDROM_INFO, "info", &cdrom_drive_info, + {DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info, CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info}, + {DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose, + sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, + {DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject, + sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, + {DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug, + sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, + {DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock, + sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, + {DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check, + sizeof(int), 0644, NULL, &cdrom_sysctl_handler }, {0} }; @@ -1198,6 +1835,13 @@ cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1); cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount; + + /* set the defaults */ + cdrom_sysctl_settings.autoclose = autoclose; + cdrom_sysctl_settings.autoeject = autoeject; + cdrom_sysctl_settings.debug = debug; + cdrom_sysctl_settings.lock = lockdoor; + cdrom_sysctl_settings.check = check_media_type; initialized = 1; } diff -u --recursive --new-file v2.3.12/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.3.12/linux/drivers/char/Config.in Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/Config.in Thu Aug 5 14:47:44 1999 @@ -41,6 +41,7 @@ if [ "$CONFIG_SPECIALIX" != "n" ]; then bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS fi + tristate 'Specialix SX (and SI) card support' CONFIG_SX tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m @@ -60,18 +61,22 @@ dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT fi -bool 'Mouse Support (not serial mice)' CONFIG_MOUSE -if [ "$CONFIG_MOUSE" = "y" ]; then - mainmenu_option next_comment - comment 'Mice' - tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE - tristate 'Logitech busmouse support' CONFIG_BUSMOUSE - tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE +mainmenu_option next_comment +comment 'Mice' +tristate 'Bus Mouse Support' CONFIG_BUSMOUSE +if [ "$CONFIG_BUSMOUSE" != "n" ]; then + dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE + dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE + dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE +fi + +tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE +if [ "$CONFIG_MOUSE" != "n" ]; then bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD - endmenu fi +endmenu tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE if [ "$CONFIG_QIC02_TAPE" != "n" ]; then diff -u --recursive --new-file v2.3.12/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.3.12/linux/drivers/char/Makefile Wed Jul 28 14:47:42 1999 +++ linux/drivers/char/Makefile Thu Aug 5 14:47:44 1999 @@ -18,19 +18,19 @@ # FONTMAPFILE = cp437.uni -L_TARGET := char.a +O_TARGET := char.o M_OBJS := -L_OBJS := tty_io.o n_tty.o tty_ioctl.o mem.o random.o raw.o -LX_OBJS := pty.o misc.o +O_OBJS := tty_io.o n_tty.o tty_ioctl.o mem.o random.o raw.o +OX_OBJS := pty.o misc.o ifdef CONFIG_VT -L_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o -LX_OBJS += console.o selection.o +O_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o +OX_OBJS += console.o selection.o endif ifeq ($(CONFIG_SERIAL),y) ifeq ($(CONFIG_SUN_SERIAL),) - LX_OBJS += serial.o + OX_OBJS += serial.o endif else ifeq ($(CONFIG_SERIAL),m) @@ -42,24 +42,24 @@ ifndef CONFIG_SUN_KEYBOARD ifdef CONFIG_VT -LX_OBJS += keyboard.o +OX_OBJS += keyboard.o endif ifneq ($(ARCH),m68k) - L_OBJS += pc_keyb.o defkeymap.o + O_OBJS += pc_keyb.o defkeymap.o endif else ifdef CONFIG_PCI -L_OBJS += defkeymap.o -LX_OBJS += keyboard.o +O_OBJS += defkeymap.o +OX_OBJS += keyboard.o endif endif ifdef CONFIG_MAGIC_SYSRQ -LX_OBJS += sysrq.o +OX_OBJS += sysrq.o endif ifeq ($(CONFIG_ATARI_DSP56K),y) -L_OBJS += dsp56k.o +O_OBJS += dsp56k.o S = y else ifeq ($(CONFIG_ATARI_DSP56K),m) @@ -69,7 +69,7 @@ endif ifeq ($(CONFIG_ROCKETPORT),y) -L_OBJS += rocket.o +O_OBJS += rocket.o else ifeq ($(CONFIG_ROCKETPORT),m) M_OBJS += rocket.o @@ -77,7 +77,7 @@ endif ifeq ($(CONFIG_DIGI),y) -L_OBJS += pcxx.o +O_OBJS += pcxx.o else ifeq ($(CONFIG_DIGI),m) M_OBJS += pcxx.o @@ -85,7 +85,7 @@ endif ifeq ($(CONFIG_DIGIEPCA),y) -L_OBJS += epca.o +O_OBJS += epca.o else ifeq ($(CONFIG_DIGIEPCA),m) M_OBJS += epca.o @@ -93,7 +93,7 @@ endif ifeq ($(CONFIG_CYCLADES),y) -L_OBJS += cyclades.o +O_OBJS += cyclades.o else ifeq ($(CONFIG_CYCLADES),m) M_OBJS += cyclades.o @@ -101,7 +101,7 @@ endif ifeq ($(CONFIG_STALLION),y) -L_OBJS += stallion.o +O_OBJS += stallion.o else ifeq ($(CONFIG_STALLION),m) M_OBJS += stallion.o @@ -109,7 +109,7 @@ endif ifeq ($(CONFIG_ISTALLION),y) -L_OBJS += istallion.o +O_OBJS += istallion.o else ifeq ($(CONFIG_ISTALLION),m) M_OBJS += istallion.o @@ -117,7 +117,7 @@ endif ifeq ($(CONFIG_RISCOM8),y) -L_OBJS += riscom8.o +O_OBJS += riscom8.o else ifeq ($(CONFIG_RISCOM8),m) M_OBJS += riscom8.o @@ -125,7 +125,7 @@ endif ifeq ($(CONFIG_ISI),y) -L_OBJS += isicom.o +O_OBJS += isicom.o else ifeq ($(CONFIG_ISI),m) M_OBJS += isicom.o @@ -133,7 +133,7 @@ endif ifeq ($(CONFIG_ESPSERIAL),y) -L_OBJS += esp.o +O_OBJS += esp.o else ifeq ($(CONFIG_ESPSERIAL),m) M_OBJS += esp.o @@ -149,31 +149,39 @@ endif ifeq ($(CONFIG_SPECIALIX),y) -L_OBJS += specialix.o +O_OBJS += specialix.o else ifeq ($(CONFIG_SPECIALIX),m) M_OBJS += specialix.o endif endif +ifeq ($(CONFIG_SX),y) +L_OBJS += sx.o generic_serial.o +else + ifeq ($(CONFIG_SX),m) + M_OBJS += sx.o + endif +endif + ifeq ($(CONFIG_ATIXL_BUSMOUSE),y) -L_OBJS += atixlmouse.o +O_OBJS += atixlmouse.o else ifeq ($(CONFIG_ATIXL_BUSMOUSE),m) M_OBJS += atixlmouse.o endif endif -ifeq ($(CONFIG_BUSMOUSE),y) -L_OBJS += busmouse.o +ifeq ($(CONFIG_LOGIBUSMOUSE),y) +O_OBJS += logibusmouse.o else - ifeq ($(CONFIG_BUSMOUSE),m) - M_OBJS += busmouse.o + ifeq ($(CONFIG_LOGIBUSMOUSE),m) + M_OBJS += logibusmouse.o endif endif ifeq ($(CONFIG_PRINTER),y) -L_OBJS += lp.o +O_OBJS += lp.o else ifeq ($(CONFIG_PRINTER),m) M_OBJS += lp.o @@ -181,7 +189,7 @@ endif ifeq ($(CONFIG_JOYSTICK),y) -L_OBJS += joystick/js.o +O_OBJS += joystick/js.o SUB_DIRS += joystick MOD_SUB_DIRS += joystick else @@ -190,8 +198,18 @@ endif endif +ifeq ($(CONFIG_MOUSE),y) +M = y +OX_OBJS += busmouse.o +else + ifeq ($(CONFIG_MOUSE),m) + MM = m + MX_OBJS += busmouse.o + endif +endif + ifeq ($(CONFIG_DTLK),y) -L_OBJS += dtlk.o +O_OBJS += dtlk.o else ifeq ($(CONFIG_DTLK),m) M_OBJS += dtlk.o @@ -199,7 +217,7 @@ endif ifeq ($(CONFIG_MS_BUSMOUSE),y) -L_OBJS += msbusmouse.o +O_OBJS += msbusmouse.o else ifeq ($(CONFIG_MS_BUSMOUSE),m) M_OBJS += msbusmouse.o @@ -207,7 +225,7 @@ endif ifeq ($(CONFIG_82C710_MOUSE),y) -L_OBJS += qpmouse.o +O_OBJS += qpmouse.o else ifeq ($(CONFIG_82C710_MOUSE),m) M_OBJS += qpmouse.o @@ -215,7 +233,7 @@ endif ifeq ($(CONFIG_SOFT_WATCHDOG),y) -L_OBJS += softdog.o +O_OBJS += softdog.o else ifeq ($(CONFIG_SOFT_WATCHDOG),m) M_OBJS += softdog.o @@ -223,7 +241,7 @@ endif ifeq ($(CONFIG_PCWATCHDOG),y) -L_OBJS += pcwd.o +O_OBJS += pcwd.o else ifeq ($(CONFIG_PCWATCHDOG),m) M_OBJS += pcwd.o @@ -231,7 +249,7 @@ endif ifeq ($(CONFIG_ACQUIRE_WDT),y) -L_OBJS += acquirewdt.o +O_OBJS += acquirewdt.o else ifeq ($(CONFIG_ACQUIRE_WDT),m) M_OBJS += acquirewdt.o @@ -239,7 +257,7 @@ endif ifeq ($(CONFIG_AMIGAMOUSE),y) -L_OBJS += amigamouse.o +O_OBJS += amigamouse.o else ifeq ($(CONFIG_AMIGAMOUSE),m) M_OBJS += amigamouse.o @@ -247,7 +265,7 @@ endif ifeq ($(CONFIG_ATARIMOUSE),y) -L_OBJS += atarimouse.o +O_OBJS += atarimouse.o else ifeq ($(CONFIG_ATARIMOUSE),m) M_OBJS += atarimouse.o @@ -255,7 +273,7 @@ endif ifeq ($(CONFIG_ADBMOUSE),y) -L_OBJS += adbmouse.o +O_OBJS += adbmouse.o else ifeq ($(CONFIG_ADBMOUSE),m) M_OBJS += adbmouse.o @@ -263,7 +281,7 @@ endif ifeq ($(CONFIG_PC110_PAD),y) -L_OBJS += pc110pad.o +O_OBJS += pc110pad.o else ifeq ($(CONFIG_PC110_PAD),m) M_OBJS += pc110pad.o @@ -271,7 +289,7 @@ endif ifeq ($(CONFIG_WDT),y) -L_OBJS += wdt.o +O_OBJS += wdt.o else ifeq ($(CONFIG_WDT),m) M_OBJS += wdt.o @@ -279,12 +297,12 @@ endif ifeq ($(CONFIG_RTC),y) -L_OBJS += rtc.o +O_OBJS += rtc.o endif ifeq ($(CONFIG_NVRAM),y) ifeq ($(CONFIG_PPC),) - L_OBJS += nvram.o + O_OBJS += nvram.o endif else ifeq ($(CONFIG_NVRAM),m) @@ -295,7 +313,7 @@ endif ifeq ($(CONFIG_VIDEO_DEV),y) -LX_OBJS += videodev.o +OX_OBJS += videodev.o else ifeq ($(CONFIG_VIDEO_DEV),m) MX_OBJS += videodev.o @@ -311,7 +329,7 @@ endif ifeq ($(CONFIG_VIDEO_BT848),y) -L_OBJS += bttv.o msp3400.o tuner.o +O_OBJS += bttv.o msp3400.o tuner.o L_I2C=y else ifeq ($(CONFIG_VIDEO_BT848),m) @@ -321,7 +339,7 @@ endif ifeq ($(CONFIG_VIDEO_SAA5249),y) -L_OBJS += saa5249.o +O_OBJS += saa5249.o L_I2C=y else ifeq ($(CONFIG_VIDEO_SAA5249),m) @@ -331,7 +349,7 @@ endif ifeq ($(CONFIG_I2C_PARPORT),y) -L_OBJS += i2c-parport.o +O_OBJS += i2c-parport.o L_I2C = y else ifeq ($(CONFIG_I2C_PARPORT),m) @@ -341,7 +359,7 @@ endif ifeq ($(CONFIG_VIDEO_BWQCAM),y) -L_OBJS += bw-qcam.o +O_OBJS += bw-qcam.o else ifeq ($(CONFIG_VIDEO_BWQCAM),m) M_OBJS += bw-qcam.o @@ -349,7 +367,7 @@ endif ifeq ($(CONFIG_VIDEO_CQCAM),y) -L_OBJS += c-qcam.o +O_OBJS += c-qcam.o else ifeq ($(CONFIG_VIDEO_CQCAM),m) M_OBJS += c-qcam.o @@ -357,7 +375,7 @@ endif ifeq ($(CONFIG_VIDEO_ZORAN),y) -L_OBJS += buz.o +O_OBJS += buz.o else ifeq ($(CONFIG_VIDEO_LML33),m) M_OBJS += buz.o @@ -365,7 +383,7 @@ endif ifeq ($(CONFIG_VIDEO_LML33),y) -L_OBJS += bt856.o bt819.o +O_OBJS += bt856.o bt819.o else ifeq ($(CONFIG_VIDEO_LML33),m) M_OBJS += bt856.o bt819.o @@ -373,7 +391,7 @@ endif ifeq ($(CONFIG_VIDEO_BUZ),y) -L_OBJS += saa7111.o saa7185.o +O_OBJS += saa7111.o saa7185.o else ifeq ($(CONFIG_VIDEO_BUZ),m) M_OBJS += saa7111.o saa7185.o @@ -381,7 +399,7 @@ endif ifeq ($(CONFIG_VIDEO_PMS),y) -L_OBJS += pms.o +O_OBJS += pms.o else ifeq ($(CONFIG_VIDEO_PMS),m) M_OBJS += pms.o @@ -389,7 +407,7 @@ endif ifeq ($(CONFIG_VIDEO_PLANB),y) -L_OBJS += planb.o +O_OBJS += planb.o else ifeq ($(CONFIG_VIDEO_PLANB),m) M_OBJS += planb.o @@ -397,7 +415,7 @@ endif ifeq ($(CONFIG_VIDEO_VINO),y) -L_OBJS += vino.o +O_OBJS += vino.o else ifeq ($(CONFIG_VIDEO_VINO),m) M_OBJS += vino.o @@ -405,7 +423,7 @@ endif ifeq ($(CONFIG_RADIO_AZTECH),y) -L_OBJS += radio-aztech.o +O_OBJS += radio-aztech.o else ifeq ($(CONFIG_RADIO_AZTECH),m) M_OBJS += radio-aztech.o @@ -413,7 +431,7 @@ endif ifeq ($(CONFIG_RADIO_SF16FMI),y) -L_OBJS += radio-sf16fmi.o +O_OBJS += radio-sf16fmi.o else ifeq ($(CONFIG_RADIO_SF16FMI),m) M_OBJS += radio-sf16fmi.o @@ -421,7 +439,7 @@ endif ifeq ($(CONFIG_RADIO_RTRACK),y) -L_OBJS += radio-aimslab.o +O_OBJS += radio-aimslab.o else ifeq ($(CONFIG_RADIO_RTRACK),m) M_OBJS += radio-aimslab.o @@ -429,7 +447,7 @@ endif ifeq ($(CONFIG_RADIO_RTRACK2),y) -L_OBJS += radio-rtrack2.o +O_OBJS += radio-rtrack2.o else ifeq ($(CONFIG_RADIO_RTRACK2),m) M_OBJS += radio-rtrack2.o @@ -437,7 +455,7 @@ endif ifeq ($(CONFIG_RADIO_TYPHOON),y) -L_OBJS += radio-typhoon.o +O_OBJS += radio-typhoon.o else ifeq ($(CONFIG_RADIO_TYPHOON),m) M_OBJS += radio-typhoon.o @@ -445,7 +463,7 @@ endif ifeq ($(CONFIG_RADIO_ZOLTRIX),y) -L_OBJS += radio-zoltrix.o +O_OBJS += radio-zoltrix.o else ifeq ($(CONFIG_RADIO_ZOLTRIX),m) M_OBJS += radio-zoltrix.o @@ -453,7 +471,7 @@ endif ifeq ($(CONFIG_RADIO_CADET),y) -L_OBJS += radio-cadet.o +O_OBJS += radio-cadet.o else ifeq ($(CONFIG_RADIO_CADET),m) M_OBJS += radio-cadet.o @@ -461,7 +479,7 @@ endif ifeq ($(CONFIG_RADIO_MIROPCM20),y) -L_OBJS += radio-miropcm20.o +O_OBJS += radio-miropcm20.o else ifeq ($(CONFIG_RADIO_MIROPCM20),m) M_OBJS += radio-miropcm20.o @@ -469,7 +487,7 @@ endif ifeq ($(CONFIG_RADIO_GEMTEK),y) -L_OBJS += radio-gemtek.o +O_OBJS += radio-gemtek.o else ifeq ($(CONFIG_RADIO_GEMTEK),m) M_OBJS += radio-gemtek.o @@ -477,7 +495,7 @@ endif ifeq ($(CONFIG_RADIO_TERRATEC),y) -L_OBJS += radio-terratec.o +O_OBJS += radio-terratec.o else ifeq ($(CONFIG_RADIO_TERRATEC),m) M_OBJS += radio-terratec.o @@ -485,7 +503,7 @@ endif ifeq ($(CONFIG_QIC02_TAPE),y) -L_OBJS += tpqic02.o +O_OBJS += tpqic02.o else ifeq ($(CONFIG_QIC02_TAPE),m) M_OBJS += tpqic02.o @@ -493,7 +511,7 @@ endif ifeq ($(CONFIG_FTAPE),y) -L_OBJS += ftape/ftape.o +O_OBJS += ftape/ftape.o SUB_DIRS += ftape ifneq ($(CONFIG_ZFTAPE),n) MOD_SUB_DIRS += ftape @@ -505,11 +523,11 @@ endif ifdef CONFIG_H8 -LX_OBJS += h8.o +OX_OBJS += h8.o endif ifeq ($(CONFIG_PPDEV),y) -L_OBJS += ppdev.o +O_OBJS += ppdev.o else ifeq ($(CONFIG_PPDEV),m) M_OBJS += ppdev.o @@ -517,24 +535,11 @@ endif ifeq ($(L_I2C),y) -LX_OBJS += i2c.o +OX_OBJS += i2c.o else ifeq ($(M_I2C),y) MX_OBJS += i2c.o endif -endif - - -ifeq ($(CONFIG_HFMODEM),y) -ALL_SUB_DIRS += hfmodem -SUB_DIRS += hfmodem -L_OBJS += hfmodem/hfmodem.o -else - ifeq ($(CONFIG_HFMODEM),m) - ALL_SUB_DIRS += hfmodem - MOD_SUB_DIRS += hfmodem - endif - endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.12/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c --- v2.3.12/linux/drivers/char/adbmouse.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/char/adbmouse.c Mon Aug 2 09:54:29 1999 @@ -21,6 +21,9 @@ * 1996/02/11 Andreas Schwab * Module support * Allow multiple open's + * + * Converted to use new generic busmouse code. 11 July 1998 + * Russell King */ #include @@ -34,7 +37,6 @@ #include #include -#include #ifdef __powerpc__ #include #endif @@ -42,227 +44,129 @@ #include #endif -static struct mouse_status mouse; +#include "busmouse.h" + +static int msedev; static unsigned char adb_mouse_buttons[16]; extern void (*adb_mouse_interrupt_hook)(unsigned char *, int); extern int adb_emulate_buttons; extern int adb_button2_keycode; extern int adb_button3_keycode; - extern int console_loglevel; /* - * XXX: need to figure out what ADB mouse packets mean ... - * This is the stuff stolen from the Atari driver ... + * XXX: need to figure out what ADB mouse packets mean ... + * This is the stuff stolen from the Atari driver ... */ static void adb_mouse_interrupt(unsigned char *buf, int nb) { - int buttons, id; + int buttons, id; + char dx, dy; -/* - Handler 1 -- 100cpi original Apple mouse protocol. - Handler 2 -- 200cpi original Apple mouse protocol. + /* + Handler 1 -- 100cpi original Apple mouse protocol. + Handler 2 -- 200cpi original Apple mouse protocol. - For Apple's standard one-button mouse protocol the data array will - contain the following values: + For Apple's standard one-button mouse protocol the data array will + contain the following values: - BITS COMMENTS - data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. - data[1] = bxxx xxxx First button and x-axis motion. - data[2] = byyy yyyy Second button and y-axis motion. - - Handler 4 -- Apple Extended mouse protocol. - - For Apple's 3-button mouse protocol the data array will contain the - following values: - - BITS COMMENTS - data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. - data[1] = bxxx xxxx Left button and x-axis motion. - data[2] = byyy yyyy Second button and y-axis motion. - data[3] = byyy bxxx Third button and fourth button. - Y is additional high bits of y-axis motion. - X is additional high bits of x-axis motion. - - This procedure also gets called from the keyboard code if we - are emulating mouse buttons with keys. In this case data[0] == 0 - (data[0] cannot be 0 for a real ADB packet). - - 'buttons' here means 'button down' states! - Button 1 (left) : bit 2, busmouse button 3 - Button 2 (middle): bit 1, busmouse button 2 - Button 3 (right) : bit 0, busmouse button 1 -*/ - - /* x/y and buttons swapped */ - - if (console_loglevel >= 8) - printk("KERN_DEBUG adb_mouse: %s data; ", buf[0]? "real": "fake"); - - id = (buf[0] >> 4) & 0xf; - buttons = adb_mouse_buttons[id]; - - /* button 1 (left, bit 2) */ - buttons = (buttons&3) | (buf[1] & 0x80 ? 4 : 0); /* 1+2 unchanged */ - - /* button 2 (middle) */ - buttons = (buttons&5) | (buf[2] & 0x80 ? 2 : 0); /* 2+3 unchanged */ - - /* button 3 (right) present? - * on a logitech mouseman, the right and mid buttons sometimes behave - * strangely until they both have been pressed after booting. */ - /* data valid only if extended mouse format ! */ - if (nb >= 4) - buttons = (buttons&6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */ - - add_mouse_randomness(((~buttons&7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f)); - - adb_mouse_buttons[id] = buttons; - /* a button is down if it is down on any mouse */ - for (id = 0; id < 16; ++id) - buttons &= adb_mouse_buttons[id]; - - mouse.buttons = buttons; - mouse.dx += ((buf[2]&0x7f) < 64 ? (buf[2]&0x7f) : (buf[2]&0x7f)-128 ); - mouse.dy -= ((buf[1]&0x7f) < 64 ? (buf[1]&0x7f) : (buf[1]&0x7f)-128 ); - - if (console_loglevel >= 8) - printk(" %X %X %X buttons %x dx %d dy %d \n", - buf[1], buf[2], buf[3], mouse.buttons, mouse.dx, mouse.dy); - - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - if (mouse.fasyncptr) - kill_fasync(mouse.fasyncptr, SIGIO); -} + BITS COMMENTS + data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. + data[1] = bxxx xxxx First button and x-axis motion. + data[2] = byyy yyyy Second button and y-axis motion. -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; + Handler 4 -- Apple Extended mouse protocol. - retval = fasync_helper(fd, filp, on, &mouse.fasyncptr); - if (retval < 0) - return retval; - return 0; -} + For Apple's 3-button mouse protocol the data array will contain the + following values: -static int release_mouse(struct inode *inode, struct file *file) -{ - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; - - adb_mouse_interrupt_hook = NULL; - MOD_DEC_USE_COUNT; - return 0; -} + BITS COMMENTS + data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. + data[1] = bxxx xxxx Left button and x-axis motion. + data[2] = byyy yyyy Second button and y-axis motion. + data[3] = byyy bxxx Third button and fourth button. + Y is additiona. high bits of y-axis motion. + X is additional high bits of x-axis motion. -static int open_mouse(struct inode *inode, struct file *file) -{ - int id; + 'buttons' here means 'button down' states! + Button 1 (left) : bit 2, busmouse button 3 + Button 2 (right) : bit 0, busmouse button 1 + Button 3 (middle): bit 1, busmouse button 2 + */ - if (mouse.active++) - return 0; - - mouse.ready = 0; + /* x/y and buttons swapped */ - mouse.dx = mouse.dy = 0; - for (id = 0; id < 16; ++id) - adb_mouse_buttons[id] = 7; /* all buttons up */ - MOD_INC_USE_COUNT; - adb_mouse_interrupt_hook = adb_mouse_interrupt; - return 0; -} + id = (buf[0] >> 4) & 0xf; -static ssize_t write_mouse(struct file *file, const char *buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} + buttons = adb_mouse_buttons[id]; -static ssize_t read_mouse(struct file *file, char *buffer, size_t count, - loff_t *ppos) -{ - int dx, dy, buttons; + /* button 1 (left, bit 2) */ + buttons = (buttons & 3) | (buf[1] & 0x80 ? 4 : 0); /* 1+2 unchanged */ + + /* button 2 (middle) */ + buttons = (buttons & 5) | (buf[2] & 0x80 ? 2 : 0); /* 2+3 unchanged */ - if (count < 3) - return -EINVAL; - if (!mouse.ready) - return -EAGAIN; - dx = mouse.dx; - dy = mouse.dy; - buttons = mouse.buttons; - if (dx > 127) - dx = 127; - else if (dx < -128) - dx = -128; - if (dy > 127) - dy = 127; - else if (dy < -128) - dy = -128; - mouse.dx -= dx; - mouse.dy -= dy; - if (mouse.dx == 0 && mouse.dy == 0) - mouse.ready = 0; - if (put_user(buttons | 0x80, buffer++) || - put_user((char) dx, buffer++) || - put_user((char) dy, buffer++)) - return -EFAULT; - if (count > 3) - if (clear_user(buffer, count - 3)) - return -EFAULT; - return count; + /* button 3 (right) present? + * on a logitech mouseman, the right and mid buttons sometimes behave + * strangely until they both have been pressed after booting. */ + /* data valid only if extended mouse format ! */ + if (nb >= 4) + buttons = (buttons & 6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */ + + adb_mouse_buttons[id] = buttons; + + /* a button is down if it is down on any mouse */ + for (id = 0; id < 16; ++id) + buttons &= adb_mouse_buttons[id]; + + dx = ((buf[2] & 0x7f) < 64 ? (buf[2] & 0x7f) : (buf[2] & 0x7f) - 128); + dy = ((buf[1] & 0x7f) < 64 ? (buf[1] & 0x7f) : (buf[1] & 0x7f) - 128); + busmouse_add_movementbuttons(msedev, dx, -dy, buttons); + + if (console_loglevel >= 8) + printk(" %X %X %X dx %d dy %d \n", + buf[1], buf[2], buf[3], dx, dy); } -static unsigned int mouse_poll(struct file *file, poll_table *wait) +static int release_mouse(struct inode *inode, struct file *file) { - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) - return POLLIN | POLLRDNORM; + adb_mouse_interrupt_hook = NULL; + MOD_DEC_USE_COUNT; return 0; } -struct file_operations adb_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; - -#define ADB_MOUSE_MINOR 10 +static int open_mouse(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + adb_mouse_interrupt_hook = adb_mouse_interrupt; + return 0; +} -static struct miscdevice adb_mouse = { - ADB_MOUSE_MINOR, "adbmouse", &adb_mouse_fops +static struct busmouse adb_mouse = +{ + ADB_MOUSE_MINOR, "adbmouse", open_mouse, close_mouse, 7 }; __initfunc(int adb_mouse_init(void)) { - mouse.active = 0; - mouse.ready = 0; - init_waitqueue_head(&mouse.wait); - #ifdef __powerpc__ - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) - return -ENODEV; + if ((_machine != _MACH_chrp) && (_machine != _MACH_Pmac)) + return -ENODEV; #endif #ifdef __mc68000__ - if (!MACH_IS_MAC) - return -ENODEV; + if (!MACH_IS_MAC) + return -ENODEV; #endif - printk(KERN_INFO "Macintosh ADB mouse driver installed.\n"); - misc_register(&adb_mouse); - return 0; -} + msedev = register_busmouse(&adb_mouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to register ADB mouse driver.\n"); + else + printk(KERN_INFO "Macintosh ADB mouse driver installed.\n"); + + return msedev < 0 ? msedev : 0; +} /* * XXX this function is misnamed. @@ -286,11 +190,12 @@ int init_module(void) { - return adb_mouse_init(); + return adb_mouse_init(); } void cleanup_module(void) { - misc_deregister(&adb_mouse); + unregister_busmouse(msedev); } + #endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c --- v2.3.12/linux/drivers/char/amigamouse.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/amigamouse.c Mon Aug 2 09:54:29 1999 @@ -30,6 +30,9 @@ * Moved the isr-allocation to the mouse_{open,close} calls, as there * is no reason to service the mouse in the vertical blank isr if * the mouse is not in use. Jes Sorensen + * + * Converted to use new generic busmouse code. 5 Apr 1998 + * Russell King */ #include @@ -44,7 +47,7 @@ #include #include #include -#include +#include #include #include @@ -53,13 +56,15 @@ #include #include +#include "busmouse.h" + +#if 0 #define AMI_MSE_INT_ON() mouseint_allowed = 1 #define AMI_MSE_INT_OFF() mouseint_allowed = 0 - - -static struct mouse_status mouse; - static int mouseint_allowed; +#endif + +static int msedev; static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp) { @@ -70,9 +75,11 @@ unsigned short joy0dat, potgor; +#if 0 if(!mouseint_allowed) return; AMI_MSE_INT_OFF(); +#endif /* * This routine assumes, just like Kickstart, that the mouse @@ -128,44 +135,10 @@ (potgor & 0x0400 ? 1 : 0); /* right button */ - if (dx != 0 || dy != 0 || buttons != mouse.buttons) { - add_mouse_randomness((buttons << 16) + (dy << 8) + dx); - mouse.buttons = buttons; - mouse.dx += dx; - mouse.dy -= dy; - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - - /* - * keep dx/dy reasonable, but still able to track when X (or - * whatever) must page or is busy (i.e. long waits between - * reads) - */ - if (mouse.dx < -2048) - mouse.dx = -2048; - else - if (mouse.dx > 2048) - mouse.dx = 2048; - - if (mouse.dy < -2048) - mouse.dy = -2048; - else - if (mouse.dy > 2048) - mouse.dy = 2048; - - if (mouse.fasyncptr) - kill_fasync(mouse.fasyncptr, SIGIO); - } + busmouse_add_movementbuttons(msedev, dx, -dy, buttons); +#if 0 AMI_MSE_INT_ON(); -} - -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - retval = fasync_helper(fd, filp, on, &mouse.fasyncptr); - if (retval < 0) - return retval; - return 0; +#endif } /* @@ -174,11 +147,10 @@ static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; free_irq(IRQ_AMIGA_VERTB, mouse_interrupt); +#if 0 AMI_MSE_INT_OFF(); +#endif MOD_DEC_USE_COUNT; return 0; } @@ -190,123 +162,25 @@ static int open_mouse(struct inode * inode, struct file * file) { - if (!mouse.present) - return -EINVAL; - if (mouse.active++) - return 0; /* * use VBL to poll mouse deltas */ if(request_irq(IRQ_AMIGA_VERTB, mouse_interrupt, 0, "Amiga mouse", mouse_interrupt)) { - mouse.present = 0; printk(KERN_INFO "Installing Amiga mouse failed.\n"); return -EIO; } - mouse.ready = 0; - mouse.dx = 0; - mouse.dy = 0; - mouse.buttons = 0x87; - mouse.active = 1; MOD_INC_USE_COUNT; +#if 0 AMI_MSE_INT_ON(); +#endif return 0; } -/* - * writes are disallowed - */ - -static ssize_t write_mouse(struct file * file, const char * buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -/* - * read mouse data. Currently never blocks. - */ - -static ssize_t read_mouse(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - int dx; - int dy; - unsigned char buttons; - - if (count < 3) - return -EINVAL; - if (!mouse.ready) - return -EAGAIN; - - /* - * Obtain the current mouse parameters and limit as appropriate for - * the return data format. Interrupts are only disabled while - * obtaining the parameters, NOT during the puts_user() calls, - * so paging in put_user() does not effect mouse tracking. - */ - - AMI_MSE_INT_OFF(); - dx = mouse.dx; - dy = mouse.dy; - if (dx < -127) - dx = -127; - else - if (dx > 127) - dx = 127; - if (dy < -127) - dy = -127; - else - if (dy > 127) - dy = 127; - buttons = mouse.buttons; - mouse.dx -= dx; - mouse.dy -= dy; - mouse.ready = 0; - AMI_MSE_INT_ON(); - - if (put_user(buttons | 0x80, buffer++) || - put_user((char)dx, buffer++) || - put_user((char)dy, buffer++)) - return -EINVAL; - - if (count > 3) - if (clear_user(buffer, count - 3)) - return -EFAULT; - return count; -} - -/* - * poll for mouse input - */ - -static unsigned int mouse_poll(struct file *file, poll_table * wait) -{ - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) - return POLLIN | POLLRDNORM; - return 0; -} - -struct file_operations amiga_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; - -static struct miscdevice amiga_mouse = { - AMIGAMOUSE_MINOR, "amigamouse", &amiga_mouse_fops +static struct busmouse amigamouse = { + AMIGAMOUSE_MINOR, "amigamouse", open_mouse, release_mouse, 7 }; int __init amiga_mouse_init(void) @@ -315,21 +189,15 @@ return -ENODEV; custom.joytest = 0; /* reset counters */ - +#if 0 AMI_MSE_INT_OFF(); - - mouse.active = 0; - mouse.ready = 0; - mouse.buttons = 0x87; - mouse.dx = 0; - mouse.dy = 0; - mouse.wait = NULL; - - mouse.present = 1; - - printk(KERN_INFO "Amiga mouse installed.\n"); - misc_register(&amiga_mouse); - return 0; +#endif + msedev = register_busmouse(&amigamouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to install Amiga mouse driver.\n"); + else + printk(KERN_INFO "Amiga mouse installed.\n"); + return msedev < 0 ? msedev : 0; } #ifdef MODULE @@ -341,6 +209,6 @@ void cleanup_module(void) { - misc_deregister(&amiga_mouse); + unregsiter_busmouse(msedev); } #endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/amikeyb.c linux/drivers/char/amikeyb.c --- v2.3.12/linux/drivers/char/amikeyb.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/amikeyb.c Mon Aug 9 12:32:28 1999 @@ -257,7 +257,7 @@ amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; add_timer(&amikeyb_rep_timer); } - handle_scancode(scancode, !break_flag); + handle_scancode(keycode, !break_flag); } else switch (keycode) { case 0x78: @@ -340,9 +340,4 @@ k->rate = key_repeat_rate * 1000 / HZ; return( 0 ); -} - -/* for "kbd-reset" cmdline param */ -void __init amiga_kbd_reset_setup(char *str, int *ints) -{ } diff -u --recursive --new-file v2.3.12/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c --- v2.3.12/linux/drivers/char/atarimouse.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/atarimouse.c Mon Aug 2 09:54:29 1999 @@ -10,6 +10,9 @@ * 1996/02/11 Andreas Schwab * Module support * Allow multiple open's + * + * Converted to use new generic busmouse code. 5 Apr 1998 + * Russell King */ #include @@ -21,13 +24,15 @@ #include #include #include -#include +#include #include #include #include -static struct mouse_status mouse; +#include "busmouse.h" + +static int msedev; static int mouse_threshold[2] = {2,2}; MODULE_PARM(mouse_threshold, "2i"); extern int atari_mouse_buttons; @@ -42,32 +47,13 @@ | (buf[0] & 2 ? 4 : 0) | (atari_mouse_buttons & 2)); atari_mouse_buttons = buttons; - add_mouse_randomness((buttons << 16) + (buf[2] << 8) + buf[1]); - mouse.buttons = ~buttons & 7; - mouse.dx += buf[1]; - mouse.dy -= buf[2]; - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - if (mouse.fasyncptr) - kill_fasync(mouse.fasyncptr, SIGIO); + busmouse_add_movementbuttons(msedev, buf[1], -buf[2], buttons); /* ikbd_mouse_rel_pos(); */ } -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - retval = fasync_helper(fd, filp, on, &mouse.fasyncptr); - if (retval < 0) - return retval; - return 0; -} - static int release_mouse(struct inode *inode, struct file *file) { - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; ikbd_mouse_disable(); atari_mouse_interrupt_hook = NULL; @@ -77,10 +63,6 @@ static int open_mouse(struct inode *inode, struct file *file) { - if (mouse.active++) - return 0; - mouse.ready = 0; - mouse.dx = mouse.dy = 0; atari_mouse_buttons = 0; ikbd_mouse_y0_top (); ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]); @@ -90,92 +72,20 @@ return 0; } -static ssize_t write_mouse(struct file *file, const char *buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static ssize_t read_mouse(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - int dx, dy, buttons; - - if (count < 3) - return -EINVAL; - if (!mouse.ready) - return -EAGAIN; - /* ikbd_mouse_disable */ - dx = mouse.dx; - dy = mouse.dy; - buttons = mouse.buttons; - if (dx > 127) - dx = 127; - else if (dx < -128) - dx = -128; - if (dy > 127) - dy = 127; - else if (dy < -128) - dy = -128; - mouse.dx -= dx; - mouse.dy -= dy; - if (mouse.dx == 0 && mouse.dy == 0) - mouse.ready = 0; - /* ikbd_mouse_rel_pos(); */ - if (put_user(buttons | 0x80, buffer++) || - put_user((char) dx, buffer++) || - put_user((char) dy, buffer++)) - return -EFAULT; - if (count > 3) - if (clear_user(buffer, count - 3)) - return -EFAULT; - return count; -} - -static unsigned int mouse_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) - return POLLIN | POLLRDNORM; - return 0; -} - -struct file_operations atari_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; - -static struct miscdevice atari_mouse = { - ATARIMOUSE_MINOR, "atarimouse", &atari_mouse_fops +static struct busmouse atarimouse = { + ATARIMOUSE_MINOR, "atarimouse", open_mouse, release_mouse, 0 }; int __init atari_mouse_init(void) { - int r; - - if (!MACH_IS_ATARI) - return -ENODEV; - - mouse.active = 0; - mouse.ready = 0; - mouse.wait = NULL; - - r = misc_register(&atari_mouse); - if (r) - return r; - - printk(KERN_INFO "Atari mouse installed.\n"); - return 0; + if (!MACH_IS_ATARI) + return -ENODEV; + msedev = register_busmouse(&atarimouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to register Atari mouse driver.\n"); + else + printk(KERN_INFO "Atari mouse installed.\n"); + return msedev < 0 ? msedev : 0; } @@ -215,6 +125,6 @@ void cleanup_module(void) { - misc_deregister(&atari_mouse); + unregister_busmouse(msedev); } #endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c --- v2.3.12/linux/drivers/char/atixlmouse.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/atixlmouse.c Mon Aug 2 09:54:29 1999 @@ -7,6 +7,9 @@ * Modified by Chris Colohan (colohan@eecg.toronto.edu) * Modularised 8-Sep-95 Philip Blundell * + * Converted to use new generic busmouse code. 5 Apr 1998 + * Russell King + * * version 0.3a */ @@ -26,6 +29,8 @@ #include #include +#include "busmouse.h" + #define ATIXL_MOUSE_IRQ 5 /* H/W interrupt # set up on ATIXL board */ #define ATIXL_BUSMOUSE 3 /* Minor device # (mknod c 10 3 /dev/bm) */ @@ -59,17 +64,7 @@ /* Same general mouse structure */ -static struct mouse_status { - char buttons; - char latch_buttons; - int dx; - int dy; - int present; - int ready; - int active; - wait_queue_head_t wait; - struct fasync_struct *fasync; -} mouse; +static int msedev; void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs) { @@ -82,35 +77,13 @@ dy = inb( ATIXL_MSE_DATA_PORT); outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */ buttons = inb( ATIXL_MSE_DATA_PORT); - if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) { - add_mouse_randomness((buttons << 16) + (dy << 8) + dx); - mouse.latch_buttons |= buttons; - mouse.dx += dx; - mouse.dy += dy; - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - if (mouse.fasync) - kill_fasync(mouse.fasync, SIGIO); - } + busmouse_add_movementbuttons(msedev, dx, -dy, buttons); ATIXL_MSE_ENABLE_UPDATE(); } -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - retval = fasync_helper(fd, filp, on, &mouse.fasync); - if (retval < 0) - return retval; - return 0; -} - static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */ - mouse.ready = 0; free_irq(ATIXL_MOUSE_IRQ, NULL); MOD_DEC_USE_COUNT; return 0; @@ -118,90 +91,17 @@ static int open_mouse(struct inode * inode, struct file * file) { - if (!mouse.present) - return -EINVAL; - if (mouse.active++) - return 0; - if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL)) { - mouse.active--; + if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL)) return -EBUSY; - } - mouse.ready = 0; - mouse.dx = 0; - mouse.dy = 0; - mouse.buttons = mouse.latch_buttons = 0; ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */ MOD_INC_USE_COUNT; return 0; } - -static ssize_t write_mouse(struct file * file, const char * buffer, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static ssize_t read_mouse(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - ssize_t i; - - if (count < 3) - return -EINVAL; - if (!mouse.ready) - return -EAGAIN; - ATIXL_MSE_DISABLE_UPDATE(); - /* Allowed interrupts to occur during data gathering - shouldn't hurt */ - put_user((char)(~mouse.latch_buttons&7) | 0x80 , buffer); - if (mouse.dx < -127) - mouse.dx = -127; - if (mouse.dx > 127) - mouse.dx = 127; - put_user((char)mouse.dx, buffer + 1); - if (mouse.dy < -127) - mouse.dy = -127; - if (mouse.dy > 127) - mouse.dy = 127; - put_user((char)-mouse.dy, buffer + 2); - for(i = 3; i < count; i++) - put_user(0x00, buffer + i); - mouse.dx = 0; - mouse.dy = 0; - mouse.latch_buttons = mouse.buttons; - mouse.ready = 0; - ATIXL_MSE_ENABLE_UPDATE(); - return i; /* i data bytes returned */ -} - -static unsigned int mouse_poll(struct file *file, poll_table * wait) -{ - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) - return POLLIN | POLLRDNORM; - return 0; -} - -struct file_operations atixl_busmouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, +static struct busmouse atixlmouse = { + ATIXL_BUSMOUSE, "atixl", open_mouse, release_mouse, 0 }; -static struct miscdevice atixl_mouse = { - ATIXL_BUSMOUSE, "atixl", &atixl_busmouse_fops -}; - - int __init atixl_busmouse_init(void) { unsigned char a,b,c; @@ -211,22 +111,18 @@ c = inb( ATIXL_MSE_SIGNATURE_PORT ); if (( a != b ) && ( a == c )) printk(KERN_INFO "\nATI Inport "); - else{ - mouse.present = 0; + else return -EIO; - } outb(0x80, ATIXL_MSE_CONTROL_PORT); /* Reset the Inport device */ outb(0x07, ATIXL_MSE_CONTROL_PORT); /* Select Internal Register 7 */ outb(0x0a, ATIXL_MSE_DATA_PORT); /* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */ - mouse.present = 1; - mouse.active = 0; - mouse.ready = 0; - mouse.buttons = mouse.latch_buttons = 0; - mouse.dx = mouse.dy = 0; - init_waitqueue_head(&mouse.wait); - printk("Bus mouse detected and installed.\n"); - misc_register(&atixl_mouse); - return 0; + + msedev = register_busmouse(&atixlmouse); + if (msedev < 0) + printk("Bus mouse initialisation error.\n"); + else + printk("Bus mouse detected and installed.\n"); + return msedev < 0 ? msedev : 0; } #ifdef MODULE @@ -238,6 +134,6 @@ void cleanup_module(void) { - misc_deregister(&atixl_mouse); + unregister_busmouse(msedev); } #endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.3.12/linux/drivers/char/bttv.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/bttv.c Thu Aug 5 15:04:52 1999 @@ -3538,12 +3538,13 @@ btv->id=dev->device; btv->irq=dev->irq; - btv->bt848_adr=dev->base_address[0]; + btv->bt848_adr=dev->resource[0].start; if (btv->id >= 878) btv->i2c_command = 0x83; else btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); +#if 0 if (remap[bttv_num]) { unsigned int dw = btv->bt848_adr; @@ -3558,7 +3559,7 @@ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dw); btv->dev->base_address[0] = btv->bt848_adr; } - btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; +#endif pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", bttv_num,btv->id, btv->revision); diff -u --recursive --new-file v2.3.12/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v2.3.12/linux/drivers/char/busmouse.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/busmouse.c Mon Aug 2 09:54:29 1999 @@ -1,299 +1,484 @@ /* - * Logitech Bus Mouse Driver for Linux - * by James Banks + * linux/drivers/char/mouse.c * - * Mods by Matthew Dillon - * calls verify_area() - * tracks better when X is busy or paging + * Copyright (C) 1995 - 1998 Russell King + * Protocol taken from busmouse.c + * read() waiting taken from psaux.c * - * Heavily modified by David Giller - * changed from queue- to counter- driven - * hacked out a (probably incorrect) mouse_select + * Medium-level interface for quadrature or bus mice. * - * Modified again by Nathan Laredo to interface with - * 0.96c-pl1 IRQ handling changes (13JUL92) - * didn't bother touching select code. + * Currently, the majority of kernel busmice drivers in the + * kernel common code to talk to userspace. This driver + * attempts to rectify this situation by presenting a + * simple and safe interface to the mice and user. * - * Modified the select() code blindly to conform to the VFS - * requirements. 92.07.14 - Linus. Somebody should test it out. - * - * Modified by Johan Myreen to make room for other mice (9AUG92) - * removed assignment chr_fops[10] = &mouse_fops; see mouse.c - * renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public. - * renamed this file mouse.c => busmouse.c - * - * Minor addition by Cliff Matthews - * added fasync support - * - * Modularised 6-Sep-95 Philip Blundell - * - * Replaced dumb busy loop with udelay() 16 Nov 95 - * Nathan Laredo - * - * Track I/O ports with request_region(). 12 Dec 95 Philip Blundell + * This driver: + * - is SMP safe + * - handles multiple opens + * - handles the wakeups and locking + * - has optional blocking reads */ #include - +#include #include #include -#include #include +#include #include #include #include #include #include -#include -#include #include -#include #include #include -#include +#include -static struct mouse_status mouse; -static int mouse_irq = MOUSE_IRQ; +#include "busmouse.h" -#ifdef MODULE -MODULE_PARM(mouse_irq, "i"); -#endif +/* Uncomment this if your mouse drivers expect the kernel to + * return with EAGAIN if the mouse does not have any events + * available, even if the mouse is opened in nonblocking mode. + * + * Should this be on a per-mouse basis? If so, add an entry to + * the struct busmouse structure and add the relevent flag to + * the drivers. + */ +/*#define BROKEN_MOUSE*/ + +extern int adb_mouse_init(void); +extern int bus_mouse_init(void); +extern int ms_bus_mouse_init(void); +extern int atixl_busmouse_init(void); +extern int amiga_mouse_init(void); +extern int atari_mouse_init(void); +extern int sun_mouse_init(void); +extern void mouse_rpc_init (void); + +struct busmouse_data { + struct miscdevice miscdev; + struct busmouse *ops; + spinlock_t lock; + + wait_queue_head_t wait; + struct fasync_struct *fasyncptr; + char active; + char buttons; + char latch_buttons; + char ready; + int dxpos; + int dypos; +}; -void __init bmouse_setup(char *str, int *ints) +#define NR_MICE 15 +#define FIRST_MOUSE 0 +#define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev)) +#define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE) + +static struct busmouse_data *busmouse_data[NR_MICE]; + +/* a mouse driver just has to interface with these functions + * These are !!!OLD!!! Do not use!!! + */ +void add_mouse_movement(int dx, int dy) +{ + struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)]; + + mse->dxpos += dx; + mse->dypos += dy; + mse->ready = 1; + wake_up(&mse->wait); +} + +int add_mouse_buttonchange(int set, int value) { - if (ints[0] > 0) - mouse_irq=ints[1]; + struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)]; + + mse->buttons = (mse->buttons & ~set) ^ value; + mse->ready = 1; + wake_up(&mse->wait); + return mse->buttons; } -static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +/* New interface. !!! Use this one !!! + * These routines will most probably be called from interrupt. + */ +void +busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons) { - char dx, dy; - unsigned char buttons; - - outb(MSE_READ_X_LOW, MSE_CONTROL_PORT); - dx = (inb(MSE_DATA_PORT) & 0xf); - outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT); - dx |= (inb(MSE_DATA_PORT) & 0xf) << 4; - outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT ); - dy = (inb(MSE_DATA_PORT) & 0xf); - outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT); - buttons = inb(MSE_DATA_PORT); - dy |= (buttons & 0xf) << 4; - buttons = ((buttons >> 5) & 0x07); - if (dx != 0 || dy != 0 || buttons != mouse.buttons) { - add_mouse_randomness((buttons << 16) + (dy << 8) + dx); - mouse.buttons = buttons; - mouse.dx += dx; - mouse.dy -= dy; - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - - /* - * keep dx/dy reasonable, but still able to track when X (or - * whatever) must page or is busy (i.e. long waits between - * reads) - */ - if (mouse.dx < -2048) - mouse.dx = -2048; - if (mouse.dx > 2048) - mouse.dx = 2048; - - if (mouse.dy < -2048) - mouse.dy = -2048; - if (mouse.dy > 2048) - mouse.dy = 2048; + struct busmouse_data *mse = busmouse_data[mousedev]; + int changed; + + spin_lock(&mse->lock); + changed = (dx != 0 || dy != 0 || mse->buttons != buttons); + + if (changed) { + add_mouse_randomness((buttons << 16) + (dy << 8) + dx); + + mse->buttons = buttons; +// mse->latch_buttons |= buttons; + mse->dxpos += dx; + mse->dypos += dy; + mse->ready = 1; + + /* + * keep dx/dy reasonable, but still able to track when X (or + * whatever) must page or is busy (i.e. long waits between + * reads) + */ + if (mse->dxpos < -2048) + mse->dxpos = -2048; + if (mse->dxpos > 2048) + mse->dxpos = 2048; + if (mse->dypos < -2048) + mse->dypos = -2048; + if (mse->dypos > 2048) + mse->dypos = 2048; + } + + spin_unlock(&mse->lock); + + if (changed) { + wake_up(&mse->wait); - if (mouse.fasyncptr) - kill_fasync(mouse.fasyncptr, SIGIO); + if (mse->fasyncptr) + kill_fasync(mse->fasyncptr, SIGIO); } - MSE_INT_ON(); } -static int fasync_mouse(int fd, struct file *filp, int on) +void +busmouse_add_movement(int mousedev, int dx, int dy) { + struct busmouse_data *mse = busmouse_data[mousedev]; + + busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons); +} + +void +busmouse_add_buttons(int mousedev, int clear, int eor) +{ + struct busmouse_data *mse = busmouse_data[mousedev]; + + busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor); +} + +static int +busmouse_fasync(int fd, struct file *filp, int on) +{ + struct busmouse_data *mse = (struct busmouse_data *)filp->private_data; int retval; - retval = fasync_helper(fd, filp, on, &mouse.fasyncptr); + retval = fasync_helper(fd, filp, on, &mse->fasyncptr); if (retval < 0) return retval; return 0; } -/* - * close access to the mouse - */ - -static int close_mouse(struct inode * inode, struct file * file) +static int +busmouse_release(struct inode *inode, struct file *file) { - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; - MSE_INT_OFF(); - free_irq(mouse_irq, NULL); - MOD_DEC_USE_COUNT; - return 0; -} + struct busmouse_data *mse = (struct busmouse_data *)file->private_data; + int ret = 0; -/* - * open access to the mouse - */ + busmouse_fasync(-1, file, 0); -static int open_mouse(struct inode * inode, struct file * file) + if (--mse->active == 0) { + if (mse->ops && + mse->ops->release) + ret = mse->ops->release(inode, file); + + mse->ready = 0; + + MOD_DEC_USE_COUNT; + } + + return ret; +} + +static int +busmouse_open(struct inode *inode, struct file *file) { - if (!mouse.present) + struct busmouse_data *mse; + unsigned long flags; + unsigned int mousedev; + int ret = 0; + + mousedev = DEV_TO_MOUSE(inode->i_rdev); + if (mousedev >= NR_MICE) return -EINVAL; - if (mouse.active++) + mse = busmouse_data[mousedev]; + if (!mse) + /* shouldn't happen, but... */ + return -ENODEV; + + if (mse->ops && + mse->ops->open) + ret = mse->ops->open(inode, file); + + if (ret) + return ret; + + file->private_data = mse; + + if (mse->active++) return 0; - if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL)) { - mouse.active--; - return -EBUSY; - } - mouse.ready = 0; - mouse.dx = 0; - mouse.dy = 0; - mouse.buttons = 0x87; + MOD_INC_USE_COUNT; - MSE_INT_ON(); + + spin_lock_irqsave(&mse->lock, flags); + + mse->ready = 0; + mse->dxpos = 0; + mse->dypos = 0; + if (mse->ops) + mse->buttons = mse->ops->init_button_state; + else + mse->buttons = 7; + + spin_unlock_irqrestore(&mse->lock, flags); + return 0; } -/* - * writes are disallowed - */ - -static ssize_t write_mouse(struct file * file, - const char * buffer, size_t count, loff_t *ppos) +static ssize_t +busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { return -EINVAL; } -/* - * read mouse data. Currently never blocks. - */ - -static ssize_t read_mouse(struct file * file, - char * buffer, size_t count, loff_t *ppos) +static ssize_t +busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { - int r; - int dx; - int dy; - unsigned char buttons; - /* long flags; */ + struct busmouse_data *mse = (struct busmouse_data *)file->private_data; + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int dxpos, dypos, buttons; if (count < 3) return -EINVAL; - if ((r = verify_area(VERIFY_WRITE, buffer, count))) - return r; - if (!mouse.ready) + + spin_lock_irqsave(&mse->lock, flags); + + if (!mse->ready) { +#ifdef BROKEN_MOUSE + spin_unlock_irqrestore(&mse->lock, flags); return -EAGAIN; +#else + if (file->f_flags & O_NONBLOCK) { + spin_unlock_irqrestore(&mse->lock, flags); + return -EAGAIN; + } + + add_wait_queue(&mse->wait, &wait); +repeat: + current->state = TASK_INTERRUPTIBLE; + if (!mse->ready && !signal_pending(current)) { + spin_unlock_irqrestore(&mse->lock, flags); + schedule(); + spin_lock_irqsave(&mse->lock, flags); + goto repeat; + } + + current->state = TASK_RUNNING; + remove_wait_queue(&mse->wait, &wait); + + if (signal_pending(current)) { + spin_unlock_irqrestore(&mse->lock, flags); + return -ERESTARTSYS; + } +#endif + } + + dxpos = mse->dxpos; + dypos = mse->dypos; + buttons = mse->buttons; +// mse->latch_buttons = mse->buttons; + + if (dxpos < -127) + dxpos =- 127; + if (dxpos > 127) + dxpos = 127; + if (dypos < -127) + dypos =- 127; + if (dypos > 127) + dypos = 127; + + mse->dxpos -= dxpos; + mse->dypos -= dypos; + + /* This is something that many drivers have apparantly + * forgotten... If the X and Y positions still contain + * information, we still have some info ready for the + * user program... + */ + mse->ready = mse->dxpos || mse->dypos; + + spin_unlock_irqrestore(&mse->lock, flags); - /* - * Obtain the current mouse parameters and limit as appropriate for - * the return data format. Interrupts are only disabled while - * obtaining the parameters, NOT during the puts_fs_byte() calls, - * so paging in put_user() does not effect mouse tracking. + /* Write out data to the user. Format is: + * byte 0 - identifer (0x80) and (inverted) mouse buttons + * byte 1 - X delta position +/- 127 + * byte 2 - Y delta position +/- 127 */ + if (put_user((char)buttons | 128, buffer) || + put_user((char)dxpos, buffer + 1) || + put_user((char)dypos, buffer + 2)) + return -EFAULT; + + if (count > 3 && clear_user(buffer + 3, count - 3)) + return -EFAULT; + + file->f_dentry->d_inode->i_atime = CURRENT_TIME; - /* save_flags(flags); cli(); */ - disable_irq(mouse_irq); - dx = mouse.dx; - dy = mouse.dy; - if (dx < -127) - dx = -127; - if (dx > 127) - dx = 127; - if (dy < -127) - dy = -127; - if (dy > 127) - dy = 127; - buttons = mouse.buttons; - mouse.dx -= dx; - mouse.dy -= dy; - mouse.ready = 0; - enable_irq(mouse_irq); - /* restore_flags(flags); */ - - put_user(buttons | 0x80, buffer); - put_user((char)dx, buffer + 1); - put_user((char)dy, buffer + 2); - for (r = 3; r < count; r++) - put_user(0x00, buffer + r); - return r; + return count; } -/* - * poll for mouse input - */ -static unsigned int mouse_poll(struct file *file, poll_table * wait) +static unsigned int +busmouse_poll(struct file *file, poll_table *wait) { - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) + struct busmouse_data *mse = (struct busmouse_data *)file->private_data; + + poll_wait(file, &mse->wait, wait); + + if (mse->ready) return POLLIN | POLLRDNORM; + return 0; } -struct file_operations bus_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - close_mouse, +struct file_operations busmouse_fops= +{ + NULL, /* busmouse_seek */ + busmouse_read, + busmouse_write, + NULL, /* busmouse_readdir */ + busmouse_poll, + NULL, /* busmouse_ioctl */ + NULL, /* busmouse_mmap */ + busmouse_open, + NULL, /* busmouse_flush */ + busmouse_release, NULL, - fasync_mouse, + busmouse_fasync, }; -static struct miscdevice bus_mouse = { - LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops -}; +int +register_busmouse(struct busmouse *ops) +{ + unsigned int msedev = MINOR_TO_MOUSE(ops->minor); + struct busmouse_data *mse; + int ret; + + if (msedev >= NR_MICE) { + printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n", + ops->minor); + return -EINVAL; + } -int __init bus_mouse_init(void) + if (busmouse_data[msedev]) + return -EBUSY; + + mse = kmalloc(GFP_KERNEL, sizeof(*mse)); + if (!mse) + return -ENOMEM; + + memset(mse, 0, sizeof(*mse)); + + mse->miscdev.minor = ops->minor; + mse->miscdev.name = ops->name; + mse->miscdev.fops = &busmouse_fops; + mse->ops = ops; + mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&mse->wait); + + busmouse_data[msedev] = mse; + + ret = misc_register(&mse->miscdev); + if (!ret) + ret = msedev; + + return ret; +} + +int +unregister_busmouse(int mousedev) { - if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) { - mouse.present = 0; - return -EIO; + if (mousedev < 0) + return 0; + if (mousedev >= NR_MICE) { + printk(KERN_ERR "busmouse: trying to free mouse on" + " mousedev %d\n", mousedev); + return -EINVAL; + } + + if (!busmouse_data[mousedev]) { + printk(KERN_WARNING "busmouse: trying to free free mouse" + " on mousedev %d\n", mousedev); + return -EINVAL; } - outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT); - outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT); - udelay(100L); /* wait for reply from mouse */ - if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) { - mouse.present = 0; - return -EIO; + if (busmouse_data[mousedev]->active) { + printk(KERN_ERR "busmouse: trying to free active mouse" + " on mousedev %d\n", mousedev); + return -EINVAL; } - outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT); - MSE_INT_OFF(); - - request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse"); - - mouse.present = 1; - mouse.active = 0; - mouse.ready = 0; - mouse.buttons = 0x87; - mouse.dx = 0; - mouse.dy = 0; - init_waitqueue_head(&mouse.wait); - printk(KERN_INFO "Logitech bus mouse detected, using IRQ %d.\n", - mouse_irq); - misc_register(&bus_mouse); + + misc_deregister(&busmouse_data[mousedev]->miscdev); + + kfree(busmouse_data[mousedev]); + busmouse_data[mousedev] = NULL; return 0; } -#ifdef MODULE +__initfunc(int +bus_mouse_init(void)) +{ +#ifdef CONFIG_BUSMOUSE + bus_mouse_init(); +#endif +#ifdef CONFIG_MS_BUSMOUSE + ms_bus_mouse_init(); +#endif +#ifdef CONFIG_ATIXL_BUSMOUSE + atixl_busmouse_init(); +#endif +#ifdef CONFIG_AMIGAMOUSE + amiga_mouse_init(); +#endif +#ifdef CONFIG_ATARIMOUSE + atari_mouse_init(); +#endif +#ifdef CONFIG_MAC_MOUSE + mac_mouse_init(); +#endif +#ifdef CONFIG_SUN_MOUSE + sun_mouse_init(); +#endif +#ifdef CONFIG_ADBMOUSE + adb_mouse_init(); +#endif +#ifdef CONFIG_RPCMOUSE + mouse_rpc_init(); +#endif + return 0; +} + +EXPORT_SYMBOL(busmouse_add_movement); +EXPORT_SYMBOL(busmouse_add_buttons); +EXPORT_SYMBOL(register_busmouse); +EXPORT_SYMBOL(unregister_busmouse); -int init_module(void) +#ifdef MODULE +int +init_module(void) { return bus_mouse_init(); } -void cleanup_module(void) +void +cleanup_module(void) { - misc_deregister(&bus_mouse); - release_region(LOGIBM_BASE, LOGIBM_EXTENT); } #endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/busmouse.h linux/drivers/char/busmouse.h --- v2.3.12/linux/drivers/char/busmouse.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/busmouse.h Mon Aug 2 09:54:29 1999 @@ -0,0 +1,28 @@ +/* + * linux/drivers/char/mouse.h + * + * Copyright (C) 1995 - 1998 Russell King + * + * Prototypes for generic busmouse interface + */ +#ifndef MOUSE_H +#define MOUSE_H + +struct busmouse { + int minor; + const char *name; + int (*open)(struct inode * inode, struct file * file); + int (*release)(struct inode * inode, struct file * file); + int init_button_state; +}; + +extern void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons); +extern void busmouse_add_movement(int mousedev, int dx, int dy); +extern void busmouse_add_buttons(int mousedev, int clear, int eor); + +extern int register_busmouse(struct busmouse *ops); +extern int unregister_busmouse(int mousedev); + +extern int bus_mouse_init(void); + +#endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/buz.c linux/drivers/char/buz.c --- v2.3.12/linux/drivers/char/buz.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/buz.c Thu Aug 5 15:04:52 1999 @@ -3219,7 +3219,7 @@ } /* i2c */ memcpy(&zr->i2c, &zoran_i2c_bus_template, sizeof(struct i2c_bus)); - sprintf(zr->i2c.name, "zoran%u%u", zr->id); + sprintf(zr->i2c.name, "zoran%u", zr->id); zr->i2c.data = zr; if (i2c_register_bus(&zr->i2c) < 0) { kfree((void *) zr->stat_com); @@ -3327,7 +3327,7 @@ spin_lock_init(&zr->lock); - zr->zr36057_adr = zr->pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; + zr->zr36057_adr = zr->pci_dev->resource[0].start; pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); if (zr->revision < 2) { printk(KERN_INFO "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", diff -u --recursive --new-file v2.3.12/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.3.12/linux/drivers/char/cyclades.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/char/cyclades.c Mon Aug 9 10:23:09 1999 @@ -4874,9 +4874,9 @@ /* read PCI configuration area */ cy_pci_irq = pdev->irq; - cy_pci_addr0 = pdev->base_address[0]; - cy_pci_addr1 = pdev->base_address[1]; - cy_pci_addr2 = pdev->base_address[2]; + cy_pci_addr0 = pdev->resource[0].start; + cy_pci_addr1 = pdev->resource[1].start; + cy_pci_addr2 = pdev->resource[2].start; pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); device_id &= ~PCI_DEVICE_ID_MASK; @@ -4891,10 +4891,8 @@ printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); #endif - cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK; - cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK; - if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) { + if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) { printk(" Warning: PCI I/O bit incorrectly set. " "Ignoring it...\n"); cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK; diff -u --recursive --new-file v2.3.12/linux/drivers/char/dn_keyb.c linux/drivers/char/dn_keyb.c --- v2.3.12/linux/drivers/char/dn_keyb.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/dn_keyb.c Mon Aug 9 12:32:28 1999 @@ -55,7 +55,8 @@ static u_char debug_buf1[4096],debug_buf2[4096],*debug_buf=&debug_buf1[0]; static u_char *shadow_buf=&debug_buf2[0]; static short debug_buf_count=0; -static int debug_buf_overrun=0,debug_timer_running=0,debug_buffer_updated=0; +static int debug_buf_overrun=0,debug_timer_running=0; +static unsigned long debug_buffer_updated=0; static struct timer_list debug_keyb_timer = { NULL, NULL, 0, 0, debug_keyb_timer_handler }; #endif @@ -280,7 +281,7 @@ u_char *swap; short length,i; - if((jiffies-debug_buffer_updated) > 100) { + if (time_after(jiffies, debug_buffer_updated + 100)) { save_flags(flags); cli(); length=debug_buf_count; @@ -422,7 +423,7 @@ !(prev_scancode==DNKEY_CTRL || prev_scancode==DNKEY_LSHIFT || prev_scancode==DNKEY_RSHIFT || prev_scancode==DNKEY_REPT || prev_scancode==DNKEY_LALT || prev_scancode==DNKEY_RALT)) { - if(jiffies-lastkeypress > DNKEY_REPEAT_DELAY) { + if (time_after(jiffies, lastkeypress + DNKEY_REPEAT_DELAY)) { /* printk("handle_scancode: %02x\n",prev_scancode); */ handle_scancode(prev_scancode, 1); } @@ -491,8 +492,8 @@ debug_buf[debug_buf_count++]=data; debug_buffer_updated=jiffies; if(!debug_timer_running) { - add_timer(&debug_keyb_timer); debug_keyb_timer.expires=jiffies+10; + add_timer(&debug_keyb_timer); debug_timer_running=1; } } diff -u --recursive --new-file v2.3.12/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c --- v2.3.12/linux/drivers/char/dsp56k.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/dsp56k.c Mon Aug 9 12:32:28 1999 @@ -534,6 +534,8 @@ dsp56k.in_use = 0; printk("DSP56k driver installed\n"); + + return 0; } #ifdef MODULE diff -u --recursive --new-file v2.3.12/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.3.12/linux/drivers/char/epca.c Wed May 12 13:27:37 1999 +++ linux/drivers/char/epca.c Thu Aug 5 15:04:52 1999 @@ -4049,12 +4049,12 @@ if (!dev) return(0); - *base_addr0 = dev->base_address[0]; - *base_addr1 = dev->base_address[1]; - *base_addr2 = dev->base_address[2]; - *base_addr3 = dev->base_address[3]; - *base_addr4 = dev->base_address[4]; - *base_addr5 = dev->base_address[5]; + *base_addr0 = dev->resource[0].start; + *base_addr1 = dev->resource[1].start; + *base_addr2 = dev->resource[2].start; + *base_addr3 = dev->resource[3].start; + *base_addr4 = dev->resource[4].start; + *base_addr5 = dev->resource[5].start; /* ------------------------------------------------------------------------ NOTE - The code below mask out either the 2 or 4 bits dependent on the @@ -4063,36 +4063,6 @@ their first 4 bits mask out.) These bits are flag bits and should always be 0 when used as an address. ---------------------------------------------------------------------------- */ - - if ((*base_addr0) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr0) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr0) &= PCI_BASE_ADDRESS_MEM_MASK; - - if ((*base_addr1) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr1) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr1) &= PCI_BASE_ADDRESS_MEM_MASK; - - if ((*base_addr2) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr2) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr2) &= PCI_BASE_ADDRESS_MEM_MASK; - - if ((*base_addr3) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr3) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr3) &= PCI_BASE_ADDRESS_MEM_MASK; - - if ((*base_addr4) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr4) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr4) &= PCI_BASE_ADDRESS_MEM_MASK; - - if ((*base_addr5) & PCI_BASE_ADDRESS_SPACE_IO) /* Is this an io address ? */ - (*base_addr5) &= PCI_BASE_ADDRESS_IO_MASK; - else - (*base_addr5) &= PCI_BASE_ADDRESS_MEM_MASK; return(1); } /* End get_PCI_configuration */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c --- v2.3.12/linux/drivers/char/generic_serial.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/generic_serial.c Thu Aug 5 14:47:44 1999 @@ -0,0 +1,1074 @@ +/* + * generic_serial.c + * + * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl + * + * written for the SX serial driver. + * Contains the code that should be shared over all the serial drivers. + * + * Credit for the idea to do it this way might go to Alan Cox. + * + * + * Version 0.1 -- December, 1998. Initial version. + * Version 0.2 -- March, 1999. Some more routines. Bugfixes. Etc. + * Version 0.5 -- August, 1999. Some more fixes. Reformat for Linus. + */ + +#include +#include +#include +#include +#include + + +#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */ +#define TWO_ZERO +#else +#if LINUX_VERSION_CODE < 0x020200 /* less than 2.2.x */ +#warning "Please use a 2.2.x kernel. " +#else +#if LINUX_VERSION_CODE < 0x020300 /* less than 2.2.x */ +#define TWO_TWO +#else +#define TWO_THREE +#endif +#endif +#endif + +#ifdef TWO_ZERO + +/* Here is the section that makes the 2.2 compatible driver source + work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, + and provide for compatibility stuff here if possible. */ + +/* Some 200 days (on intel) */ +#define MAX_SCHEDULE_TIMEOUT ((long)(~0UL>>1)) + + +#ifndef MODULE + +#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) + +static inline int copy_from_user(void *to,const void *from, int c) +{ + memcpy_fromfs(to, from, c); + return 0; +} + + +#define capable(x) suser() + +#define queue_task queue_task_irq_off +#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) +#define signal_pending(current) (current->signal & ~current->blocked) +#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) +#define time_after(t1,t2) (((long)t1-t2) > 0) + +#define test_and_set_bit(nr, addr) set_bit(nr, addr) +#define test_and_clear_bit(nr, addr) clear_bit(nr, addr) + +/* Not yet implemented on 2.0 */ +#define ASYNC_SPD_SHI -1 +#define ASYNC_SPD_WARP -1 + + + +/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it + to the "name" field that does exist. As long as the assignments are + done in the right order, there is nothing to worry about. */ +#define driver_name name + + +/* Should be in a header somewhere. */ +#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */ +#define TTY_HW_COOK_IN 15 /* in hardware - output and input */ +#endif + +#endif + +#ifndef TWO_ZERO +/* This include is new with 2.2 (and required!) */ +#include +#endif + +#ifndef TWO_THREE +/* These are new in 2.3. The source now uses 2.3 syntax, and here is + the compatibility define... */ +#define waitq_head_t struct wait_queue * +#define DECLARE_MUTEX(name) struct semaphore name = MUTEX +#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL } + +#endif + +#include "generic_serial.h" + + +#ifndef MODULE +extern void my_hd (unsigned char *ptr, int n); +#endif + +static char * tmp_buf; +static DECLARE_MUTEX(tmp_buf_sem); + +int gs_debug = 0; + + +#ifdef DEBUG +#define gs_dprintk(f, str...) if (gs_debug & f) printk (str) +#else +#define gs_dprintk(f, str...) /* nothing */ +#endif + +#define func_enter() gs_dprintk (SX_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n") +#define func_exit() gs_dprintk (SX_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n") + + + +#if NEW_WRITE_LOCKING +#define DECL /* Nothing */ +#define LOCKIT down (& port->port_write_sem); +#define RELEASEIT up (&port->port_write_sem); +#else +#define DECL unsigned long flags; +#define LOCKIT save_flags (flags);cli () +#define RELEASEIT restore_flags (flags) +#endif + + + +void gs_put_char(struct tty_struct * tty, unsigned char ch) +{ + struct gs_port *port = tty->driver_data; + DECL + + /* func_enter (); */ + + /* Take a lock on the serial tranmit buffer! */ + LOCKIT; + + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { + /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ + RELEASEIT; + return; + } + + port->xmit_buf[port->xmit_head++] = ch; + port->xmit_head &= SERIAL_XMIT_SIZE - 1; + port->xmit_cnt++; /* Characters in buffer */ + + RELEASEIT; + /* func_exit ();*/ +} + + +#ifdef NEW_WRITE_LOCKING + +/* +> Problems to take into account are: +> -1- Interrupts that empty part of the buffer. +> -2- page faults on the access to userspace. +> -3- Other processes that are also trying to do a "write". +*/ + +int gs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + struct gs_port *port = tty->driver_data; + int c, total = 0; + int t; + + /* func_enter (); */ + + if (! (port->flags & ASYNC_INITIALIZED)) + return 0; + + /* get exclusive "write" access to this port (problem 3) */ + /* This is not a spinlock because we can have a disk access (page + fault) in copy_from_user */ + down (& port->port_write_sem); + + while (1) { + + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_sem. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) break; + if (from_user) + copy_from_user (port->xmit_buf + port->xmit_head, buf, c); + else + memcpy (port->xmit_buf + port->xmit_head, buf, c); + + port -> xmit_cnt += c; + port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1); + buf += c; + count -= c; + total += c; + } + up (& port->port_write_sem); + + gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", + (port->flags & GS_TX_INTEN)?"enabled": "disabled"); + + if (port->xmit_cnt && + !tty->stopped && + !tty->hw_stopped && + !(port->flags & GS_TX_INTEN)) { + port->flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + } + /* func_exit (); */ + return total; +} +#else +/* +> Problems to take into account are: +> -1- Interrupts that empty part of the buffer. +> -2- page faults on the access to userspace. +> -3- Other processes that are also trying to do a "write". +*/ + +int gs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + struct gs_port *port; + int c, total = 0; + int t; + unsigned long flags; + + func_enter (); + + /* The standard serial driver returns 0 in this case. + That sounds to me as "No error, I just didn't get to writing any + bytes. Feel free to try again." + The "official" way to write n bytes from buf is: + + for (nwritten = 0;nwritten < n;nwritten += rv) { + rv = write (fd, buf+nwritten, n-nwritten); + if (rv < 0) break; // Error: bail out. // + } + + which will loop endlessly in this case. The manual page for write + agrees with me. In practise almost everybody writes + "write (fd, buf,n);" but some people might have had to deal with + incomplete writes in the past and correctly implemented it by now... + */ + + if (!tty) return -EIO; + + port = tty->driver_data; + if (!port || !port->xmit_buf || !tmp_buf) + return -EIO; + + /* printk ("from_user = %d.\n", from_user); */ + save_flags(flags); + if (from_user) { + /* printk ("Going into the semaphore\n"); */ + down(&tmp_buf_sem); + /* printk ("got out of the semaphore\n"); */ + while (1) { + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_sem. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) break; + + c -= copy_from_user(tmp_buf, buf, c); + if (!c) { + if (!total) + total = -EFAULT; + break; + } + cli(); + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c); + port->xmit_head = ((port->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + port->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + up(&tmp_buf_sem); + } else { + while (1) { + cli(); + c = count; + + /* This is safe because we "OWN" the "head". Noone else can + change the "head": we own the port_write_sem. */ + /* Don't overrun the end of the buffer */ + t = SERIAL_XMIT_SIZE - port->xmit_head; + if (t < c) c = t; + + /* This is safe because the xmit_cnt can only decrease. This + would increase "t", so we might copy too little chars. */ + /* Don't copy past the "head" of the buffer */ + t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; + if (t < c) c = t; + + /* Can't copy more? break out! */ + if (c <= 0) { + restore_flags(flags); + break; + } + memcpy(port->xmit_buf + port->xmit_head, buf, c); + port->xmit_head = ((port->xmit_head + c) & + (SERIAL_XMIT_SIZE-1)); + port->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + } + + if (port->xmit_cnt && + !tty->stopped && + !tty->hw_stopped && + !(port->flags & GS_TX_INTEN)) { + port->flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + } + func_exit (); + return total; +} + +#endif + + + +int gs_write_room(struct tty_struct * tty) +{ + struct gs_port *port = tty->driver_data; + int ret; + + /* func_enter (); */ + ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; + if (ret < 0) + ret = 0; + /* func_exit (); */ + return ret; +} + + +int gs_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + func_enter (); + + func_exit (); + return port->xmit_cnt; +} + + +int gs_real_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + func_enter (); + + if (!tty) return 0; + port = tty->driver_data; + + func_exit (); + return port->xmit_cnt + port->rd->chars_in_buffer (port); +} + + +static void gs_wait_tx_flushed (void * ptr, int timeout) +{ + struct gs_port *port = ptr; + long end_jiffies; + int jiffies_to_transmit, charsleft; + int to, rcib; + + func_enter(); + + gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port); + if (port) { + gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", + port->xmit_cnt, port->xmit_buf, port->tty); + } + + if (!port || port->xmit_cnt < 0 || !port->xmit_buf) { + gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n"); + func_exit(); + return; /* This is an error which we don't know how to handle. */ + } + gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n"); + + rcib = gs_real_chars_in_buffer(port->tty); + + gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 2\n"); + + if(rcib <= 0) { + gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); + func_exit(); + return; + } + gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n"); + + /* stop trying: now + twice the time it would normally take + seconds */ + end_jiffies = jiffies; + if (timeout != MAX_SCHEDULE_TIMEOUT) + end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0; + end_jiffies += timeout; + + gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", + jiffies, end_jiffies, end_jiffies-jiffies); + + to = 100; + /* the expression is actually jiffies < end_jiffies, but that won't + work around the wraparound. Tricky eh? */ + while (to-- && + (charsleft = gs_real_chars_in_buffer (port->tty)) && + time_after (end_jiffies, jiffies)) { + /* Units check: + chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies! + check! */ + + charsleft += 16; /* Allow 16 chars more to be transmitted ... */ + jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0; + /* ^^^ Round up.... */ + if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1; + + gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies " + "(%d chars).\n", jiffies_to_transmit, charsleft); + + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(jiffies_to_transmit); + if (signal_pending (current)) + break; + } + + gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); + current->state = TASK_RUNNING; + + func_exit(); +} + + + +void gs_flush_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + + func_enter (); + /* XXX Would the write semaphore do? */ + save_flags(flags); cli(); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + restore_flags(flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + func_exit (); +} + + +void gs_flush_chars(struct tty_struct * tty) +{ + struct gs_port *port = tty->driver_data; + + func_enter (); + if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !port->xmit_buf) { + func_exit (); + return; + } + + /* Beats me -- REW */ + port->flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + func_exit (); +} + + +void gs_stop(struct tty_struct * tty) +{ + struct gs_port *port = tty->driver_data; + + func_enter (); + if (port->xmit_cnt && + port->xmit_buf && + (port->flags & GS_TX_INTEN) ) { + port->flags &= ~GS_TX_INTEN; + port->rd->disable_tx_interrupts (port); + } + func_exit (); +} + + +void gs_start(struct tty_struct * tty) +{ + struct gs_port *port = tty->driver_data; + + if (port->xmit_cnt && + port->xmit_buf && + !(port->flags & GS_TX_INTEN) ) { + port->flags |= GS_TX_INTEN; + port->rd->enable_tx_interrupts (port); + } + func_exit (); +} + + +void gs_shutdown_port (struct gs_port *port) +{ + long flags; + + if (!(port->flags & ASYNC_INITIALIZED)) + return; + + save_flags (flags); + cli (); + + if (port->xmit_buf) { + free_page((unsigned long) port->xmit_buf); + port->xmit_buf = 0; + } + + if (port->tty) + set_bit(TTY_IO_ERROR, &port->tty->flags); + + port->rd->shutdown_port (port); + + port->flags &= ~ASYNC_INITIALIZED; + restore_flags (flags); +} + + +void gs_hangup(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + + func_enter (); + + tty = port->tty; + if (!tty) return; + + gs_shutdown_port (port); + + /* gs_flush_buffer (tty); */ + port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE |GS_ACTIVE); + port->tty = NULL; + port->count = 0; + + wake_up_interruptible(&port->open_wait); + func_exit (); +} + + +void gs_do_softint(void *private_) +{ + struct gs_port *port = private_; + struct tty_struct *tty; + + tty = port->tty; + if(!tty) return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } + func_exit (); +} + + +int block_til_ready(void *port_, struct file * filp) +{ + struct gs_port *port = port_; + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + int CD; + struct tty_struct *tty; + + func_enter (); + tty = port->tty; + + gs_dprintk (GS_DEBUG_BTR, "Entering block_till_ready.\n"); + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&port->close_wait); + if (port->flags & ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; + } + + gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == GS_TYPE_CALLOUT) { + if (port->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((port->flags & ASYNC_CALLOUT_ACTIVE) && + (port->flags & ASYNC_SESSION_LOCKOUT) && + (port->session != current->session)) + return -EBUSY; + if ((port->flags & ASYNC_CALLOUT_ACTIVE) && + (port->flags & ASYNC_PGRP_LOCKOUT) && + (port->pgrp != current->pgrp)) + return -EBUSY; + port->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + gs_dprintk (GS_DEBUG_BTR, "after subtype\n"); + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (port->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); + + if (port->flags & ASYNC_CALLOUT_ACTIVE) { + if (port->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (C_CLOCAL(tty)) + do_clocal = 1; + } + + gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); + + cli(); + if (!tty_hung_up_p(filp)) + port->count--; + sti(); + port->blocked_open++; + while (1) { + CD = port->rd->get_CD (port); + gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(port->flags & ASYNC_INITIALIZED)) { + if (port->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + if (!(port->flags & ASYNC_CALLOUT_ACTIVE) && + !(port->flags & ASYNC_CLOSING) && + (do_clocal || CD)) + break; + gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", + (int)signal_pending (current), *(long*)(¤t->blocked)); + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", + port->blocked_open); + current->state = TASK_RUNNING; + remove_wait_queue(&port->open_wait, &wait); + if (!tty_hung_up_p(filp)) + port->count++; + port->blocked_open--; + if (retval) + return retval; + + port->flags |= ASYNC_NORMAL_ACTIVE; + func_exit (); + return 0; +} + + +void gs_close(struct tty_struct * tty, struct file * filp) +{ + unsigned long flags; + struct gs_port *port; + + func_enter (); + port = (struct gs_port *) tty->driver_data; + + gs_dprintk (GS_DEBUG_CLOSE, "tty=%p, port=%p port->tty=%p\n", + tty, port, port->tty); + + if(! port) { + func_exit(); + return; + } + if (!port->tty) { + printk (KERN_WARNING "gs: Odd: port->tty is NULL\n"); + port->tty = tty; + } + + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + port->rd->hungup (port); + func_exit (); + return; + } + + if ((tty->count == 1) && (port->count != 1)) { + printk(KERN_ERR "gs: gs_close: bad port count;" + " tty->count is 1, port count is %d\n", port->count); + port->count = 1; + } + if (--port->count < 0) { + printk(KERN_ERR "gs: gs_close: bad port count: %d\n", port->count); + port->count = 0; + } + if (port->count) { + restore_flags(flags); + func_exit (); + return; + } + port->flags |= ASYNC_CLOSING; + + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (port->flags & ASYNC_NORMAL_ACTIVE) + port->normal_termios = *tty->termios; + if (port->flags & ASYNC_CALLOUT_ACTIVE) + port->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + /* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, port->closing_wait); */ + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + + port->rd->disable_rx_interrupts (port); + + if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) + gs_wait_tx_flushed (port, port->closing_wait); + + port->flags &= ~GS_ACTIVE; + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + port->event = 0; + port->tty = 0; + if (port->blocked_open) { + if (port->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(port->close_delay); + } + wake_up_interruptible(&port->open_wait); + } + port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING | ASYNC_INITIALIZED); + wake_up_interruptible(&port->close_wait); + + port->rd->close (port); + port->rd->shutdown_port (port); + restore_flags(flags); + func_exit (); +} + + +static unsigned int gs_baudrates[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 +}; + + +void gs_set_termios (struct tty_struct * tty, + struct termios * old_termios) +{ + struct gs_port *port = tty->driver_data; + int baudrate, tmp; + struct termios *tiosp; + + func_enter(); + + tiosp = tty->termios; + + + if (gs_debug & GS_DEBUG_TERMIOS) { + gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); + my_hd ((unsigned char *)tiosp, sizeof (struct termios)); + } + +#if 0 + /* This is an optimization that is only allowed for dumb cards */ + /* Smart cards require knowledge of iflags and oflags too: that + might change hardware cooking mode.... */ +#endif + if (old_termios) { + if( (tiosp->c_iflag == old_termios->c_iflag) + && (tiosp->c_oflag == old_termios->c_oflag) + && (tiosp->c_cflag == old_termios->c_cflag) + && (tiosp->c_lflag == old_termios->c_lflag) + && (tiosp->c_line == old_termios->c_line) + && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { + gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); + return; + } + } else + gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " + "no optimization\n"); + + if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { + if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); + if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); + if(tiosp->c_cflag != old_termios->c_cflag) printk("c_cflag changed\n"); + if(tiosp->c_lflag != old_termios->c_lflag) printk("c_lflag changed\n"); + if(tiosp->c_line != old_termios->c_line) printk("c_line changed\n"); + if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n"); + } + + baudrate = tiosp->c_cflag & CBAUD; + if (baudrate & CBAUDEX) { + baudrate &= ~CBAUDEX; + if ((baudrate < 1) || (baudrate > 4)) + tiosp->c_cflag &= ~CBAUDEX; + else + baudrate += 15; + } + + baudrate = gs_baudrates[baudrate]; + if ((tiosp->c_cflag & CBAUD) == B38400) { + if ( (port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baudrate = 57600; + else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baudrate = 115200; + else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + baudrate = 230400; + else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + baudrate = 460800; + else if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) + baudrate = (port->baud_base / port->custom_divisor); + } + + /* I recommend using THIS instead of the mess in termios (and + duplicating the above code). Next we should create a clean + interface towards this variable. If your card supports arbitrary + baud rates, (e.g. CD1400 or 16550 based cards) then everything + will be very easy..... */ + port->baud = baudrate; + + /* Two timer ticks seems enough to wakeup something like SLIP driver */ + /* Baudrate/10 is cps. Divide by HZ to get chars per tick. */ + tmp = (baudrate / 10 / HZ) * 2; + + if (tmp < 0) tmp = 0; + if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1; + + port->wakeup_chars = tmp; + + /* We should really wait for the characters to be all sent before + changing the settings. -- CAL */ + gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT); + + port->rd->set_real_termios(port); + + if ((!old_termios || + (old_termios->c_cflag & CRTSCTS)) && + !( tiosp->c_cflag & CRTSCTS)) { + tty->stopped = 0; + gs_start(tty); + } + +#ifdef tytso_patch_94Nov25_1726 + /* This "makes sense", Why is it commented out? */ + + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif + + func_exit(); + return; +} + + + +/* Must be called with interrupts enabled */ +int gs_init_port(struct gs_port *port) +{ + unsigned long flags; + unsigned long page; + + save_flags (flags); + if (!tmp_buf) { + page = get_free_page(GFP_KERNEL); + + cli (); /* Don't expect this to make a difference. */ + if (tmp_buf) + free_page(page); + else + tmp_buf = (unsigned char *) page; + restore_flags (flags); + + if (!tmp_buf) { + return -ENOMEM; + } + } + + if (port->flags & ASYNC_INITIALIZED) + return 0; + + if (!port->xmit_buf) { + /* We may sleep in get_free_page() */ + unsigned long tmp; + + tmp = get_free_page(GFP_KERNEL); + + /* Spinlock? */ + cli (); + if (port->xmit_buf) + free_page (tmp); + else + port->xmit_buf = (unsigned char *) tmp; + restore_flags (flags); + + if (!port->xmit_buf) + return -ENOMEM; + } + + cli(); + + if (port->tty) + clear_bit(TTY_IO_ERROR, &port->tty->flags); + + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + + gs_set_termios(port->tty, NULL); + + port->flags |= ASYNC_INITIALIZED; + port->flags &= ~GS_TX_INTEN; + + restore_flags(flags); + return 0; +} + + +int gs_setserial(struct gs_port *port, struct serial_struct *sp) +{ + struct serial_struct sio; + + copy_from_user(&sio, sp, sizeof(struct serial_struct)); + + if (!capable(CAP_SYS_ADMIN)) { + if ((sio.baud_base != port->baud_base) || + (sio.close_delay != port->close_delay) || + ((sio.flags & ~ASYNC_USR_MASK) != + (port->flags & ~ASYNC_USR_MASK))) + return(-EPERM); + } + + port->flags = (port->flags & ~ASYNC_USR_MASK) | + (sio.flags & ASYNC_USR_MASK); + + port->baud_base = sio.baud_base; + port->close_delay = sio.close_delay; + port->closing_wait = sio.closing_wait; + port->custom_divisor = sio.custom_divisor; + + gs_set_termios (port->tty, NULL); + + return 0; +} + + +/*****************************************************************************/ + +/* + * Generate the serial struct info. + */ + +void gs_getserial(struct gs_port *port, struct serial_struct *sp) +{ + struct serial_struct sio; + + memset(&sio, 0, sizeof(struct serial_struct)); + sio.flags = port->flags; + sio.baud_base = port->baud_base; + sio.close_delay = port->close_delay; + sio.closing_wait = port->closing_wait; + sio.custom_divisor = port->custom_divisor; + sio.hub6 = 0; + + /* If you want you can override these. */ + sio.type = PORT_UNKNOWN; + sio.xmit_fifo_size = -1; + sio.line = -1; + sio.port = -1; + sio.irq = -1; + + if (port->rd->getserial) + port->rd->getserial (port, &sio); + + copy_to_user(sp, &sio, sizeof(struct serial_struct)); +} + diff -u --recursive --new-file v2.3.12/linux/drivers/char/generic_serial.h linux/drivers/char/generic_serial.h --- v2.3.12/linux/drivers/char/generic_serial.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/generic_serial.h Thu Aug 5 14:47:44 1999 @@ -0,0 +1,101 @@ +/* + * generic_serial.h + * + * Copyright (C) 1998 R.E.Wolff@BitWizard.nl + * + * written for the SX serial driver. + * Contains the code that should be shared over all the serial drivers. + * + * Version 0.1 -- December, 1998. + */ + +#ifndef GENERIC_SERIAL_H +#define GENERIC_SERIAL_H + +struct real_driver { + void (*disable_tx_interrupts) (void *); + void (*enable_tx_interrupts) (void *); + void (*disable_rx_interrupts) (void *); + void (*enable_rx_interrupts) (void *); + int (*get_CD) (void *); + void (*shutdown_port) (void*); + void (*set_real_termios) (void*); + int (*chars_in_buffer) (void*); + void (*close) (void*); + void (*hungup) (void*); + void (*getserial) (void*, struct serial_struct *sp); +}; + + + +struct gs_port { + int magic; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + /* struct semaphore port_write_sem; */ + int flags; + struct termios normal_termios; + struct termios callout_termios; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + long session; + long pgrp; + int count; + int blocked_open; + struct tty_struct *tty; + int event; + unsigned short closing_wait; + int close_delay; + struct real_driver *rd; + int wakeup_chars; + int baud_base; + int baud; + int custom_divisor; +}; + + +/* Flags */ +/* Warning: serial.h defines some ASYNC_ flags, they say they are "only" + used in serial.c, but they are also used in all other serial drivers. + Make sure they don't clash with these here... */ +#define GS_TX_INTEN 0x00800000 +#define GS_RX_INTEN 0x00400000 +#define GS_ACTIVE 0x00200000 + + + +#define GS_TYPE_NORMAL 1 +#define GS_TYPE_CALLOUT 2 + + +#define GS_DEBUG_FLUSH 0x00000001 +#define GS_DEBUG_BTR 0x00000002 +#define GS_DEBUG_TERMIOS 0x00000004 +#define GS_DEBUG_STUFF 0x00000008 +#define GS_DEBUG_CLOSE 0x00000010 + + +void gs_put_char(struct tty_struct *tty, unsigned char ch); +int gs_write(struct tty_struct *tty, int from_user, + const unsigned char *buf, int count); +int gs_write_room(struct tty_struct *tty); +int gs_chars_in_buffer(struct tty_struct *tty); +void gs_flush_buffer(struct tty_struct *tty); +void gs_flush_chars(struct tty_struct *tty); +void gs_stop(struct tty_struct *tty); +void gs_start(struct tty_struct *tty); +void gs_hangup(struct tty_struct *tty); +void gs_do_softint(void *private_); +int block_til_ready(void *port, struct file *filp); +void gs_close(struct tty_struct *tty, struct file *filp); +void gs_set_termios (struct tty_struct * tty, + struct termios * old_termios); +int gs_init_port(struct gs_port *port); +int gs_setserial(struct gs_port *port, struct serial_struct *sp); +void gs_getserial(struct gs_port *port, struct serial_struct *sp); + +extern int gs_debug; + +#endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/Config.in linux/drivers/char/hfmodem/Config.in --- v2.3.12/linux/drivers/char/hfmodem/Config.in Tue Dec 29 11:28:49 1998 +++ linux/drivers/char/hfmodem/Config.in Wed Dec 31 16:00:00 1969 @@ -1,6 +0,0 @@ -comment 'Misc. hamradio protocols' -dep_tristate 'Shortwave radio modem driver' CONFIG_HFMODEM $CONFIG_PARPORT -if [ "$CONFIG_HFMODEM" != "n" ]; then - bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC - bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS -fi diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/Makefile linux/drivers/char/hfmodem/Makefile --- v2.3.12/linux/drivers/char/hfmodem/Makefile Mon Jul 20 10:05:16 1998 +++ linux/drivers/char/hfmodem/Makefile Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -# -# Makefile for the hfmodem device driver. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now inherited from the -# parent makes.. -# - -O_TARGET := hfmodem.o - -O_OBJS := refclock.o modem.o main.o -ifeq ($(CONFIG_HFMODEM_SBC),y) -O_OBJS += sbc.o -endif -ifeq ($(CONFIG_HFMODEM_WSS),y) -O_OBJS += wss.o -endif - -M_OBJS := $(O_TARGET) - -all: all_targets -.PHONY: all - -gentbl: gentbl.c - $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm - -TBLHDR := tables.h - -tables.h: gentbl - ./gentbl > $@ - -fastdep: $(TBLHDR) - -include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/gentbl.c linux/drivers/char/hfmodem/gentbl.c --- v2.3.12/linux/drivers/char/hfmodem/gentbl.c Tue Apr 7 07:48:54 1998 +++ linux/drivers/char/hfmodem/gentbl.c Wed Dec 31 16:00:00 1969 @@ -1,69 +0,0 @@ -/*****************************************************************************/ - -/* - * gentbl.c -- Linux soundcard HF FSK driver, - * Table generator. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -/* This is compiled with HOSTCC - do not include any headers. */ -#include -#include - -/* --------------------------------------------------------------------- */ - -#define SINTABBITS 9 -#define SINTABSIZE (1< /* for CONFIG_HFMODEM_WSS and CONFIG_HFMODEM_SBC */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - -/*static*/ const char hfmodem_drvname[] = "hfmodem"; -static const char hfmodem_drvinfo[] = KERN_INFO "hfmodem: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "hfmodem: version 0.2 compiled " __TIME__ " " __DATE__ "\n"; - -/* --------------------------------------------------------------------- */ -/* - * currently we support only one device - */ - -struct hfmodem_state hfmodem_state[NR_DEVICE]; - -/* --------------------------------------------------------------------- */ -/* - * ===================== port checking routines ======================== - */ - - -#define UART_RBR(iobase) (iobase+0) -#define UART_THR(iobase) (iobase+0) -#define UART_IER(iobase) (iobase+1) -#define UART_IIR(iobase) (iobase+2) -#define UART_FCR(iobase) (iobase+2) -#define UART_LCR(iobase) (iobase+3) -#define UART_MCR(iobase) (iobase+4) -#define UART_LSR(iobase) (iobase+5) -#define UART_MSR(iobase) (iobase+6) -#define UART_SCR(iobase) (iobase+7) -#define UART_DLL(iobase) (iobase+0) -#define UART_DLM(iobase) (iobase+1) - -#define SER_EXTENT 8 - -#define LPT_DATA(iobase) (iobase+0) -#define LPT_STATUS(iobase) (iobase+1) -#define LPT_CONTROL(iobase) (iobase+2) -#define LPT_IRQ_ENABLE 0x10 - -#define MIDI_DATA(iobase) (iobase) -#define MIDI_STATUS(iobase) (iobase+1) -#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */ -#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */ - -#define MIDI_EXTENT 2 - -#define SP_SER 1 -#define SP_PAR 2 -#define SP_MIDI 4 - -/* --------------------------------------------------------------------- */ - -static void parptt_wakeup(void *handle) -{ - struct hfmodem_state *dev = (struct hfmodem_state *)handle; - - printk(KERN_DEBUG "%s: parptt: why am I being woken up?\n", hfmodem_drvname); - if (!parport_claim(dev->ptt_out.pardev)) - printk(KERN_DEBUG "%s: parptt: I'm broken.\n", hfmodem_drvname); -} - -/* --------------------------------------------------------------------- */ -static int __init check_lpt(struct hfmodem_state *dev, unsigned int iobase) -{ - struct parport *pp = parport_enumerate(); - - while (pp && pp->base != iobase) - pp = pp->next; - if (!pp) - return 0; - if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, NULL, parptt_wakeup, - NULL, PARPORT_DEV_EXCL, dev))) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A }; -static const char *uart_str[] __initdata = { "unknown", "8250", "16450", "16550", "16550A" }; - -static enum uart __init check_uart(unsigned int iobase) -{ - unsigned char b1,b2,b3; - enum uart u; - enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A }; - - if (iobase <= 0 || iobase > 0x1000-SER_EXTENT) - return c_uart_unknown; - if (check_region(iobase, SER_EXTENT)) - return c_uart_unknown; - b1 = inb(UART_MCR(iobase)); - outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */ - b2 = inb(UART_MSR(iobase)); - outb(0x1a, UART_MCR(iobase)); - b3 = inb(UART_MSR(iobase)) & 0xf0; - outb(b1, UART_MCR(iobase)); /* restore old values */ - outb(b2, UART_MSR(iobase)); - if (b3 != 0x90) - return c_uart_unknown; - inb(UART_RBR(iobase)); - inb(UART_RBR(iobase)); - outb(0x01, UART_FCR(iobase)); /* enable FIFOs */ - u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3]; - if (u == c_uart_16450) { - outb(0x5a, UART_SCR(iobase)); - b1 = inb(UART_SCR(iobase)); - outb(0xa5, UART_SCR(iobase)); - b2 = inb(UART_SCR(iobase)); - if ((b1 != 0x5a) || (b2 != 0xa5)) - u = c_uart_8250; - } - return u; -} - -/* --------------------------------------------------------------------- */ - -static int __init check_midi(unsigned int iobase) -{ - unsigned long timeout; - unsigned long flags; - unsigned char b; - - if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT) - return 0; - if (check_region(iobase, MIDI_EXTENT)) - return 0; - timeout = jiffies + (HZ / 100); - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - save_flags(flags); - cli(); - outb(0xff, MIDI_DATA(iobase)); - b = inb(MIDI_STATUS(iobase)); - restore_flags(flags); - if (!(b & MIDI_WRITE_EMPTY)) - return 0; - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -static void output_status(struct hfmodem_state *dev, int ptt) -{ - int dcd = 0; - - ptt = !!ptt; - if (dev->ptt_out.flags & SP_SER) { - outb(dcd | (ptt << 1), UART_MCR(dev->ptt_out.seriobase)); - outb(0x40 & (-ptt), UART_LCR(dev->ptt_out.seriobase)); - } - if (dev->ptt_out.flags & SP_PAR) { - outb(ptt | (dcd << 1), LPT_DATA(dev->ptt_out.pariobase)); - } - if (dev->ptt_out.flags & SP_MIDI && ptt) { - outb(0, MIDI_DATA(dev->ptt_out.midiiobase)); - } -} - -/* --------------------------------------------------------------------- */ - -static void __init output_check(struct hfmodem_state *dev) -{ - enum uart u = c_uart_unknown; - - if (((u = check_uart(dev->ptt_out.seriobase))) != c_uart_unknown) - printk(KERN_INFO "%s: PTT output: uart found at address 0x%x type %s\n", - hfmodem_drvname, dev->ptt_out.seriobase, uart_str[u]); - else { - if (dev->ptt_out.seriobase > 0) - printk(KERN_WARNING "%s: PTT output: no uart found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.seriobase); - dev->ptt_out.seriobase = 0; - } - if (check_lpt(dev, dev->ptt_out.pariobase)) - printk(KERN_INFO "%s: PTT output: parallel port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.pariobase); - else { - if (dev->ptt_out.pariobase > 0) - printk(KERN_WARNING "%s: PTT output: no parallel port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.pariobase); - dev->ptt_out.pariobase = 0; - dev->ptt_out.pardev = NULL; - } - if (dev->ptt_out.midiiobase > 0 && dev->ptt_out.midiiobase <= 0x1000-MIDI_EXTENT && - check_midi(dev->ptt_out.midiiobase)) - printk(KERN_INFO "%s: PTT output: midi port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - else { - if (dev->ptt_out.midiiobase > 0) - printk(KERN_WARNING "%s: PTT output: no midi port found at address 0x%x\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - dev->ptt_out.midiiobase = 0; - } -} - -/* --------------------------------------------------------------------- */ - -static void output_open(struct hfmodem_state *dev) -{ - dev->ptt_out.flags = 0; - if (dev->ptt_out.seriobase > 0) { - if (!check_region(dev->ptt_out.seriobase, SER_EXTENT)) { - request_region(dev->ptt_out.seriobase, SER_EXTENT, "hfmodem ser ptt"); - dev->ptt_out.flags |= SP_SER; - outb(0, UART_IER(dev->ptt_out.seriobase)); - /* 5 bits, 1 stop, no parity, no break, Div latch access */ - outb(0x80, UART_LCR(dev->ptt_out.seriobase)); - outb(0, UART_DLM(dev->ptt_out.seriobase)); - outb(1, UART_DLL(dev->ptt_out.seriobase)); /* as fast as possible */ - /* LCR and MCR set by output_status */ - } else - printk(KERN_WARNING "%s: PTT output: serial port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.seriobase); - } - if (dev->ptt_out.pariobase > 0) { - if (parport_claim(dev->ptt_out.pardev)) - printk(KERN_WARNING "%s: PTT output: parallel port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.pariobase); - else - dev->ptt_out.flags |= SP_PAR; - } - if (dev->ptt_out.midiiobase > 0) { - if (!check_region(dev->ptt_out.midiiobase, MIDI_EXTENT)) { - request_region(dev->ptt_out.midiiobase, MIDI_EXTENT, "hfmodem midi ptt"); - dev->ptt_out.flags |= SP_MIDI; - } else - printk(KERN_WARNING "%s: PTT output: midi port at 0x%x busy\n", - hfmodem_drvname, dev->ptt_out.midiiobase); - } - output_status(dev, 0); - printk(KERN_INFO "%s: PTT output:", hfmodem_drvname); - if (dev->ptt_out.flags & SP_SER) - printk(" serial interface at 0x%x", dev->ptt_out.seriobase); - if (dev->ptt_out.flags & SP_PAR) - printk(" parallel interface at 0x%x", dev->ptt_out.pariobase); - if (dev->ptt_out.flags & SP_MIDI) - printk(" mpu401 (midi) interface at 0x%x", dev->ptt_out.midiiobase); - if (!dev->ptt_out.flags) - printk(" none"); - printk("\n"); -} - -/* --------------------------------------------------------------------- */ - -static void output_close(struct hfmodem_state *dev) -{ - /* release regions used for PTT output */ - output_status(dev, 0); - if (dev->ptt_out.flags & SP_SER) - release_region(dev->ptt_out.seriobase, SER_EXTENT); - if (dev->ptt_out.flags & SP_PAR) - parport_release(dev->ptt_out.pardev); - if (dev->ptt_out.flags & SP_MIDI) - release_region(dev->ptt_out.midiiobase, MIDI_EXTENT); - dev->ptt_out.flags = 0; -} - -/* --------------------------------------------------------------------- */ - -#define INC_SAMPLE (1000000/HFMODEM_SRATE) -#define INC_FRAGMENT (HFMODEM_FRAGSAMPLES*1000000/HFMODEM_SRATE) -#define SIZE (HFMODEM_FRAGSAMPLES*HFMODEM_NUMFRAGS) - -static void hfmodem_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct hfmodem_state *dev = (struct hfmodem_state *)dev_id; - unsigned int dmaptr; - __s16 *s; - unsigned int curfrag, nfrags; - int i; - hfmodem_time_t l1time; - - dmaptr = dev->scops->intack(dev); - l1time = hfmodem_refclock_current(dev, ((SIZE+dmaptr-dev->dma.last_dmaptr) % SIZE) * - INC_SAMPLE, 1); - curfrag = (dev->dma.last_dmaptr = dmaptr) / HFMODEM_FRAGSAMPLES; - l1time -= INC_SAMPLE * (SIZE+dmaptr-dev->dma.fragptr*HFMODEM_FRAGSAMPLES) % SIZE; - sti(); - /* - * handle receiving - */ - if (dev->dma.ptt_frames <= 0) { - while (dev->dma.fragptr != curfrag) { - if (dev->dma.fragptr < HFMODEM_EXCESSFRAGS) { - s = dev->dma.buf + SIZE + HFMODEM_FRAGSAMPLES * dev->dma.fragptr; - memcpy(s, s - SIZE, HFMODEM_FRAGSIZE); - } else - s = dev->dma.buf + HFMODEM_FRAGSAMPLES * dev->dma.fragptr; - if (dev->sbuf.kbuf && dev->sbuf.kptr && dev->sbuf.rem > 0) { - i = HFMODEM_FRAGSAMPLES; - if (i > dev->sbuf.rem) - i = dev->sbuf.rem; - memcpy(dev->sbuf.kptr, s, i * sizeof(s[0])); - dev->sbuf.rem -= i; - dev->sbuf.kptr += i; - } - hfmodem_input_samples(dev, l1time, INC_SAMPLE, s); - l1time += INC_FRAGMENT; - dev->dma.fragptr++; - if (dev->dma.fragptr >= HFMODEM_NUMFRAGS) - dev->dma.fragptr = 0; - } - /* - * check for output - */ - if (hfmodem_next_tx_event(dev, l1time) > (long)INC_FRAGMENT/2) - goto int_return; - /* - * start output - */ - output_status(dev, 1); - dev->scops->prepare_output(dev); - dev->dma.last_dmaptr = 0; - /* - * clock adjust - */ - l1time = hfmodem_refclock_current(dev, 0, 0); - /* - * fill first two fragments - */ - dev->dma.ptt_frames = 1; - for (i = 0; i < 2 && i < HFMODEM_NUMFRAGS; i++) - if (hfmodem_output_samples(dev, l1time+i*INC_FRAGMENT, INC_SAMPLE, - dev->dma.buf+i*HFMODEM_FRAGSAMPLES)) - dev->dma.ptt_frames = i + 1; - dev->dma.lastfrag = 0; - dev->scops->trigger_output(dev); - /* - * finish already pending rx requests - */ - hfmodem_finish_pending_rx_requests(dev); - goto int_return; - } - /* - * handle transmitting - */ - nfrags = HFMODEM_NUMFRAGS + curfrag - dev->dma.lastfrag; - dev->dma.lastfrag = curfrag; - if (nfrags >= HFMODEM_NUMFRAGS) - nfrags -= HFMODEM_NUMFRAGS; - dev->dma.ptt_frames -= nfrags; - if (dev->dma.ptt_frames < 0) - dev->dma.ptt_frames = 0; - while (dev->dma.ptt_frames < HFMODEM_NUMFRAGS && dev->dma.ptt_frames < 4 && - hfmodem_output_samples(dev, l1time+dev->dma.ptt_frames*INC_FRAGMENT, - INC_SAMPLE, dev->dma.buf + HFMODEM_FRAGSAMPLES * - ((curfrag + dev->dma.ptt_frames) % HFMODEM_NUMFRAGS))) - dev->dma.ptt_frames++; - if (dev->dma.ptt_frames > 0) - goto int_return; - /* - * start receiving - */ - output_status(dev, 0); - dev->dma.last_dmaptr = 0; - dev->dma.lastfrag = 0; - dev->dma.fragptr = 0; - dev->dma.ptt_frames = 0; - dev->scops->prepare_input(dev); - dev->scops->trigger_input(dev); - hfmodem_refclock_current(dev, 0, 0); /* needed to reset the time difference */ -int_return: - hfmodem_wakeup(dev); -} - -/* --------------------------------------------------------------------- */ - -static int hfmodem_close(struct inode *inode, struct file *file) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (!dev->active) - return -EPERM; - dev->active = 0; - dev->scops->stop(dev); - free_irq(dev->io.irq, dev); - disable_dma(dev->io.dma); - free_dma(dev->io.dma); - release_region(dev->io.base_addr, dev->scops->extent); - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - hfmodem_clear_rq(dev); - if (dev->sbuf.kbuf) { - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - } - output_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int hfmodem_open(struct inode *inode, struct file *file) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (dev->active) - return -EBUSY; - if (!dev->scops) - return -EPERM; - /* - * clear vars - */ - memset(&dev->l1, 0, sizeof(dev->l1)); - dev->dma.last_dmaptr = 0; - dev->dma.lastfrag = 0; - dev->dma.fragptr = 0; - dev->dma.ptt_frames = 0; - /* - * allocate memory - */ - if (!(dev->dma.buf = kmalloc(HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - /* - * allocate resources - */ - if (request_dma(dev->io.dma, hfmodem_drvname)) { - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - return -EBUSY; - } - if (request_irq(dev->io.irq, hfmodem_interrupt, SA_INTERRUPT, hfmodem_drvname, dev)) { - free_dma(dev->io.dma); - kfree_s(dev->dma.buf, HFMODEM_FRAGSIZE * (HFMODEM_NUMFRAGS+HFMODEM_EXCESSFRAGS)); - return -EBUSY; - } - request_region(dev->io.base_addr, dev->scops->extent, hfmodem_drvname); - - /* clear requests */ - dev->active++; - MOD_INC_USE_COUNT; - hfmodem_refclock_init(dev); - output_open(dev); - dev->scops->init(dev); - dev->scops->prepare_input(dev); - dev->scops->trigger_input(dev); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static struct file_operations hfmodem_fops = { - NULL, /* hfmodem_seek */ - NULL, /* hfmodem_read */ - NULL, /* hfmodem_write */ - NULL, /* hfmodem_readdir */ -#if LINUX_VERSION_CODE >= 0x20100 - hfmodem_poll, /* hfmodem_poll */ -#else - hfmodem_select, /* hfmodem_select */ -#endif - hfmodem_ioctl, /* hfmodem_ioctl */ - NULL, /* hfmodem_mmap */ - hfmodem_open, /* hfmodem_open */ - NULL, /* flush */ - hfmodem_close, /* hfmodem_close */ - NULL, /* hfmodem_fsync */ - NULL, /* hfmodem_fasync */ - NULL, /* hfmodem_check_media_change */ - NULL /* hfmodem_revalidate */ -}; - -/* --------------------------------------------------------------------- */ - -static struct miscdevice hfmodem_device = { - HFMODEM_MINOR, hfmodem_drvname, &hfmodem_fops -}; - -/* --------------------------------------------------------------------- */ - -#ifdef MODULE - -/* - * Command line parameters - */ - -static int hw = 0; -static unsigned int iobase = 0x220; -static unsigned int irq = 7; -static unsigned int dma = 1; - -static unsigned int serio = 0; -static unsigned int pario = 0; -static unsigned int midiio = 0; - -#if LINUX_VERSION_CODE >= 0x20115 - -MODULE_PARM(hw, "i"); -MODULE_PARM_DESC(hw, "hardware type: 0=SBC, 1=WSS"); -MODULE_PARM(iobase, "i"); -MODULE_PARM_DESC(iobase, "io base address"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(irq, "interrupt number"); -MODULE_PARM(dma, "i"); -MODULE_PARM_DESC(dma, "dma number (>=4 for SB16/32/64/etc, <=3 for the rest)"); -MODULE_PARM(serio, "i"); -MODULE_PARM_DESC(serio, "address of serial port to output PTT"); -MODULE_PARM(pario, "i"); -MODULE_PARM_DESC(pario, "address of parallel port to output PTT"); -MODULE_PARM(midiio, "i"); -MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT"); - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("HF FSK modem code"); - -/* these are the module parameters from refclock.c */ - -MODULE_PARM(scale_tvusec, "i"); -MODULE_PARM_DESC(scale_tvusec, "Scaling value for the tv_usec field (can be obta -ined by refclock)"); - -#ifdef __i386__ -MODULE_PARM(scale_rdtsc, "i"); -MODULE_PARM_DESC(scale_rdtsc, "Scaling value for the rdtsc counter (can be obtai -ned by refclock)"); -MODULE_PARM(rdtsc_ok, "i"); -MODULE_PARM_DESC(rdtsc_ok, "Set to 0 to disable the use of the rdtsc instruction -"); -#endif /* __i386__ */ - -#endif - -int __init init_module(void) -{ - int i; - - printk(hfmodem_drvinfo); - memset(hfmodem_state, 0, sizeof(hfmodem_state)); - memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache)); - hfmodem_state[0].io.base_addr = iobase; - hfmodem_state[0].io.irq = irq; - hfmodem_state[0].io.dma = dma; - hfmodem_state[0].ptt_out.seriobase = serio; - hfmodem_state[0].ptt_out.pariobase = pario; - hfmodem_state[0].ptt_out.midiiobase = midiio; - init_waitqueue_head(&hfmodem_state[0].wait); - hfmodem_refclock_probe(); - output_check(&hfmodem_state[0]); -#if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC) - if (hw) - i = hfmodem_wssprobe(&hfmodem_state[0]); - else - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#else - i = -EINVAL; -#ifdef CONFIG_HFMODEM_WSS - i = hfmodem_wssprobe(&hfmodem_state[0]); -#endif -#ifdef CONFIG_HFMODEM_SBC - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#endif -#endif - if (i) - return i; - if ((i = misc_register(&hfmodem_device))) { - printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname); - return i; - } - return 0; -} - -void cleanup_module(void) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - - if (dev->ptt_out.pariobase > 0) - parport_unregister_device(dev->ptt_out.pardev); - misc_deregister(&hfmodem_device); -} - -#else /* MODULE */ -/* --------------------------------------------------------------------- */ - -static int hw = 0; - -void __init hfmodem_setup(char *str, int *ints) -{ - if (ints[0] < 7) { - printk(KERN_WARNING "%s: setup: too few parameters\n", hfmodem_drvname); - return; - } - memset(hfmodem_state, 0, sizeof(hfmodem_state)); - memset(hfmodem_correlator_cache, 0, sizeof(hfmodem_correlator_cache)); - hw = ints[1]; - hfmodem_state[0].io.base_addr = ints[2]; - hfmodem_state[0].io.irq = ints[3]; - hfmodem_state[0].io.dma = ints[4]; - if (ints[0] >= 8) - hfmodem_state[0].ptt_out.seriobase = ints[5]; - if (ints[0] >= 9) - hfmodem_state[0].ptt_out.pariobase = ints[6]; - if (ints[0] >= 10) - hfmodem_state[0].ptt_out.midiiobase = ints[7]; - hfmodem_refclock_setscale(ints[ints[0]-2], ints[ints[0]-1], ints[ints[0]]); -} - -void __init hfmodem_init(void) -{ - int i; - - printk(hfmodem_drvinfo); - init_waitqueue_head(&hfmode_state[0].wait); - hfmodem_refclock_probe(); - output_check(&hfmodem_state[0]); -#if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC) - if (hw) - i = hfmodem_wssprobe(&hfmodem_state[0]); - else - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#else - i = -EINVAL; -#ifdef CONFIG_HFMODEM_WSS - i = hfmodem_wssprobe(&hfmodem_state[0]); -#endif -#ifdef CONFIG_HFMODEM_SBC - i = hfmodem_sbcprobe(&hfmodem_state[0]); -#endif -#endif - if (i) { - printk(KERN_ERR "%s: soundcard probe failed\n", hfmodem_drvname); - return; - } - if ((i = misc_register(&hfmodem_device))) { - printk(KERN_ERR "%s: cannot register misc device\n", hfmodem_drvname); - return; - } -} - -/* --------------------------------------------------------------------- */ -#endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/modem.c linux/drivers/char/hfmodem/modem.c --- v2.3.12/linux/drivers/char/hfmodem/modem.c Fri Feb 27 09:11:09 1998 +++ linux/drivers/char/hfmodem/modem.c Wed Dec 31 16:00:00 1969 @@ -1,792 +0,0 @@ -/*****************************************************************************/ - -/* - * modem.c -- Linux soundcard HF FSK driver, - * Modem code. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - - -#include -#include -#include - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - -struct hfmodem_correlator_cache hfmodem_correlator_cache[HFMODEM_CORRELATOR_CACHE]; - -/* --------------------------------------------------------------------- */ - -#include "tables.h" - -#define M_PI 3.14159265358979323846 /* pi */ - -/* --------------------------------------------------------------------- */ - -extern __inline__ int isimplecos(unsigned int arg) -{ - return isintab[((arg+0x4000) >> (16-SINTABBITS)) & (SINTABSIZE-1)]; -} - -extern __inline__ int isimplesin(unsigned int arg) -{ - return isintab[(arg >> (16-SINTABBITS)) & (SINTABSIZE-1)]; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ int itblcos(unsigned int arg) -{ - unsigned int x; - int dx; - int s, c; - - x = (arg + (0x8000 >> SINTABBITS)) & (0xffffu & (0xffffu << (16-SINTABBITS))); - dx = arg - x; - x >>= (16-SINTABBITS); - c = isintab[x+(0x4000 >> (16-SINTABBITS))]; - s = isintab[x]; - return c - ((s * dx * (int)(M_PI*64.0)) >> 21); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void itblcossin(unsigned int arg, int *cos, int *sin) -{ - unsigned int x; - int dx; - int s, c; - - x = (arg + (0x8000 >> SINTABBITS)) & (0xffffu & (0xffffu << (16-SINTABBITS))); - dx = arg - x; - x >>= (16-SINTABBITS); - c = isintab[x+(0x4000 >> (16-SINTABBITS))]; - s = isintab[x]; - *cos = c - ((s * dx * (int)(M_PI*64.0)) >> 21); - *sin = s + ((c * dx * (int)(M_PI*64.0)) >> 21); -} - -/* --------------------------------------------------------------------- */ - -static unsigned short random_seed; - -extern __inline__ unsigned short random_num(void) -{ - random_seed = 28629 * random_seed + 157; - return random_seed; -} - -/* --------------------------------------------------------------------- */ -/* - * correlator cache routines - */ - -extern __inline__ void cc_lock(unsigned int u) -{ - if (u >= HFMODEM_CORRELATOR_CACHE) - return; - hfmodem_correlator_cache[u].refcnt++; -} - -extern __inline__ void cc_unlock(unsigned int u) -{ - if (u >= HFMODEM_CORRELATOR_CACHE) - return; - if ((--hfmodem_correlator_cache[u].refcnt) <= 0) { - unsigned int i; - - for (i = 0; i < HFMODEM_CORRELATOR_CACHE; i++) - if (hfmodem_correlator_cache[i].lru < 32767) - hfmodem_correlator_cache[i].lru++; - hfmodem_correlator_cache[u].lru = 0; - hfmodem_correlator_cache[u].refcnt = 0; - } -} - - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int cc_lookup(unsigned short phinc0, unsigned short phinc1) -{ - unsigned int j; - - /* find correlator cache entry */ - for (j = 0; j < HFMODEM_CORRELATOR_CACHE; j++) - if (hfmodem_correlator_cache[j].phase_incs[0] == phinc0 && - hfmodem_correlator_cache[j].phase_incs[1] == phinc1) - return j; - return ~0; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int cc_replace(void) -{ - unsigned int j, k = HFMODEM_CORRELATOR_CACHE; - int l = -1; - - for (j = 0; j < HFMODEM_CORRELATOR_CACHE; j++) - if (hfmodem_correlator_cache[j].refcnt <= 0 && hfmodem_correlator_cache[j].lru > l) { - k = j; - l = hfmodem_correlator_cache[j].lru; - } - if (k < HFMODEM_CORRELATOR_CACHE) - return k; - printk(KERN_ERR "%s: modem: out of filter coefficient cache entries\n", hfmodem_drvname); - return random_num() % HFMODEM_CORRELATOR_CACHE; -} - -/* --------------------------------------------------------------------- */ - -#define SH1 8 /* min. ceil(log2(L1CORR_LEN)) - (31-(2*15-1)) */ -#define SH2 (3*15-2*SH1) - -#ifdef __i386__ - -extern __inline__ int icorr(int n, const int *coeff, const short *inp) -{ - int ret, rethi, tmp1 = 0, tmp2 = 0; - - __asm__("\n1:\n\t" - "movswl (%0),%%eax\n\t" - "imull (%1)\n\t" - "subl $2,%0\n\t" - "addl $4,%1\n\t" - "addl %%eax,%3\n\t" - "adcl %%edx,%4\n\t" - "decl %2\n\t" - "jne 1b\n\t" - : "=&S" (inp), "=&D" (coeff), "=&c" (n), "=m" (tmp1), "=m" (tmp2) - : "0" (inp), "1" (coeff), "2" (n) - : "ax", "dx"); - __asm__("shrdl %2,%1,%0\n\t" - "# sarl %2,%1\n\t" - : "=&r" (ret), "=&r" (rethi) - : "i" (SH1), "0" (tmp1), "1" (tmp2)); - - - return ret; -} - -#else /* __i386__ */ - -extern __inline__ int icorr(int n, const int *coeff, const short *inp) -{ - long long sum = 0; - int i; - - for (i = n; i > 0; i--, coeff++, inp--) - sum += (*coeff) * (*inp); - sum >>= SH1; - return sum; -} - -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -extern __inline__ long long isqr(int x) __attribute__ ((const)); - -extern __inline__ long long isqr(int x) -{ - return ((long long)x) * ((long long)x); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ hfmodem_soft_t do_filter(struct hfmodem_l1_rxslot *slot, short *s) -{ - unsigned int cc = slot->corr_cache; - long long ll; - - if (cc >= HFMODEM_CORRELATOR_CACHE) { - printk(KERN_ERR "do_filter: correlator cache index overrange\n"); - return 0; - } - ll = isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[1][0], s)) + - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[1][1], s)) - - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[0][0], s)) - - isqr(icorr(slot->corrlen, hfmodem_correlator_cache[cc].correlator[0][1], s)); - ll >>= SH2; - return (ll * slot->scale) >> 23; -} - -/* --------------------------------------------------------------------- */ - -static void cc_prepare(struct hfmodem_l1_rxslot *slot, unsigned short phinc0, unsigned short phinc1) -{ - unsigned int j, k, l, ph, phinc; - - slot->scale = (1<<23) / (slot->corrlen*slot->corrlen); - - j = cc_lookup(phinc0, phinc1); - if (j >= HFMODEM_CORRELATOR_CACHE) { - j = cc_replace(); - /* calculate the correlator values */ - printk(KERN_DEBUG "%s: corr cache calc: %u phases: 0x%04x 0x%04x\n", - hfmodem_drvname, j, phinc0, phinc1); - hfmodem_correlator_cache[j].phase_incs[0] = phinc0; - hfmodem_correlator_cache[j].phase_incs[1] = phinc1; - for (k = 0; k < 2; k++) { - phinc = hfmodem_correlator_cache[j].phase_incs[k]; - for (ph = l = 0; l < HFMODEM_MAXCORRLEN; l++, ph = (ph + phinc) & 0xffff) - itblcossin(ph, &hfmodem_correlator_cache[j].correlator[k][0][l], - &hfmodem_correlator_cache[j].correlator[k][1][l]); - } - hfmodem_correlator_cache[j].refcnt = 0; - -#if 0 - printk(KERN_DEBUG "%s: corr: %u ph: 0x%04x 0x%04x\n", hfmodem_drvname, j, - hfmodem_correlator_cache[j].phase_incs[0], - hfmodem_correlator_cache[j].phase_incs[1]); - for (l = 0; l < HFMODEM_MAXCORRLEN; l++) - printk(KERN_DEBUG "%s: corr: %6d %6d %6d %6d\n", hfmodem_drvname, - hfmodem_correlator_cache[j].correlator[0][0][l], - hfmodem_correlator_cache[j].correlator[0][1][l], - hfmodem_correlator_cache[j].correlator[1][0][l], - hfmodem_correlator_cache[j].correlator[1][1][l]); -#endif - } - slot->corr_cache = j; - cc_lock(j); -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_clear_rq(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned int i; - - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_unused) - continue; - dev->l1.rxslots[i].state = ss_unused; - kfree_s(dev->l1.rxslots[i].data, dev->l1.rxslots[i].nbits * sizeof(hfmodem_soft_t)); - } - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_unused) - continue; - dev->l1.txslots[i].state = ss_unused; - kfree_s(dev->l1.txslots[i].data, (dev->l1.txslots[i].nbits + 7) >> 3); - } - for (i = 0; i < HFMODEM_CORRELATOR_CACHE; i++) - hfmodem_correlator_cache[i].refcnt = 0; - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - struct hfmodem_ioctl_fsk_tx_request txrq; - struct hfmodem_ioctl_fsk_rx_request rxrq; - struct hfmodem_ioctl_mixer_params mix; - struct hfmodem_ioctl_sample_params spar; - unsigned long flags; - unsigned int len; - int ret, i, idx; - void *data, *userdata; - hfmodem_id_t id; - hfmodem_time_t tm = 0; - - if (!dev->active) - return -EBUSY; - switch(cmd) { - default: - return -EINVAL; - - case HFMODEM_IOCTL_FSKTXREQUEST: - if ((ret = copy_from_user(&txrq, (void *)arg, sizeof(txrq)))) - return ret; - if (txrq.nbits > HFMODEM_MAXBITS) - return -EINVAL; - len = (txrq.nbits + 7) >> 3; - if (!(data = kmalloc(len, GFP_KERNEL))) - return -ENOMEM; - if (copy_from_user(data, txrq.data, len)) { - kfree_s(data, len); - return -EFAULT; - } - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMTXSLOTS && dev->l1.txslots[i].state != ss_unused; i++); - if (i >= HFMODEM_NUMTXSLOTS) { - restore_flags(flags); - kfree_s(data, len); - return -EBUSY; - } - dev->l1.txslots[i].state = ss_ready; - dev->l1.txslots[i].tstart = txrq.tstart; - dev->l1.txslots[i].tinc = txrq.tinc; - dev->l1.txslots[i].data = data; - dev->l1.txslots[i].nbits = txrq.nbits; - dev->l1.txslots[i].cntbits = 0; - dev->l1.txslots[i].inv = txrq.inv ? 0xff : 0; - dev->l1.txslots[i].id = txrq.id; - dev->l1.txslots[i].phase_incs[0] = ((txrq.freq[0]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) - & 0xffff; - dev->l1.txslots[i].phase_incs[1] = ((txrq.freq[1]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) - & 0xffff; - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_FSKRXREQUEST: - if ((ret = copy_from_user(&rxrq, (void *)arg, sizeof(rxrq)))) - return ret; - if (rxrq.nbits > HFMODEM_MAXBITS) - return -EINVAL; - if (rxrq.baud < HFMODEM_MINBAUD || rxrq.baud > HFMODEM_MAXBAUD) - return -EINVAL; - len = rxrq.nbits * sizeof(hfmodem_soft_t); - if (verify_area(VERIFY_WRITE, rxrq.data, len)) - return -EFAULT; - if (!(data = kmalloc(len, GFP_KERNEL))) - return -ENOMEM; - save_flags(flags); - cli(); - for (i = 0; i < HFMODEM_NUMRXSLOTS && dev->l1.rxslots[i].state != ss_unused; i++); - if (i >= HFMODEM_NUMRXSLOTS) { - restore_flags(flags); - kfree_s(data, len); - return -EBUSY; - } - dev->l1.rxslots[i].state = ss_ready; - dev->l1.rxslots[i].tstart = rxrq.tstart; - dev->l1.rxslots[i].tinc = rxrq.tinc; - dev->l1.rxslots[i].data = data; - dev->l1.rxslots[i].userdata = rxrq.data; - dev->l1.rxslots[i].nbits = rxrq.nbits; - dev->l1.rxslots[i].cntbits = 0; - dev->l1.rxslots[i].id = rxrq.id; - dev->l1.rxslots[i].corrlen = HFMODEM_SRATE/rxrq.baud; - cc_prepare(dev->l1.rxslots+i, - ((rxrq.freq[0]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) & 0xffff, - ((rxrq.freq[1]*0x10000+(HFMODEM_SRATE/2))/HFMODEM_SRATE) & 0xffff); - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_CLEARRQ: - hfmodem_clear_rq(dev); - return 0; - - case HFMODEM_IOCTL_GETCURTIME: - return put_user(dev->l1.last_time + 20000L, (hfmodem_time_t *)arg); /* heuristic */ - - case HFMODEM_IOCTL_WAITRQ: - save_flags(flags); - cli(); - ret = 0; - for (idx = -1, i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_unused) - continue; - if (dev->l1.rxslots[i].state != ss_retired) { - ret++; - continue; - } - if (idx < 0 || (signed)(tm - dev->l1.rxslots[i].tstart) > 0) { - idx = i; - tm = dev->l1.rxslots[i].tstart; - } - } - if (idx >= 0) { - cc_unlock(dev->l1.rxslots[idx].corr_cache); - id = dev->l1.rxslots[idx].id; - data = dev->l1.rxslots[idx].data; - userdata = dev->l1.rxslots[idx].userdata; - len = dev->l1.rxslots[idx].nbits * sizeof(hfmodem_soft_t); - dev->l1.rxslots[idx].state = ss_unused; - restore_flags(flags); - ret = copy_to_user(userdata, data, len); - kfree_s(data, len); - return (put_user(id, (hfmodem_id_t *)arg)) ? -EFAULT : ret; - } - for (idx = -1, i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_unused) - continue; - if (dev->l1.txslots[i].state != ss_retired) { - ret++; - continue; - } - if (idx < 0 || (signed)(tm - dev->l1.txslots[i].tstart) > 0) { - idx = i; - tm = dev->l1.txslots[i].tstart; - } - } - if (idx >= 0) { - id = dev->l1.txslots[idx].id; - data = dev->l1.txslots[idx].data; - len = (dev->l1.txslots[idx].nbits + 7) >> 3; - dev->l1.txslots[idx].state = ss_unused; - restore_flags(flags); - kfree_s(data, len); - return put_user(id, (hfmodem_id_t *)arg); - } - restore_flags(flags); - return ret ? -EAGAIN : -EPIPE; - - case HFMODEM_IOCTL_MIXERPARAMS: - if ((ret = copy_from_user(&mix, (void *)arg, sizeof(mix)))) - return ret; - dev->scops->mixer(dev, mix.src, mix.igain, mix.ogain); - return 0; - - case HFMODEM_IOCTL_SAMPLESTART: - save_flags(flags); - cli(); - if (dev->sbuf.kbuf) - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - restore_flags(flags); - if ((ret = copy_from_user(&spar, (void *)arg, sizeof(spar)))) - return ret; - if (spar.len == 0) - return 0; - if (spar.len < 2 || spar.len > 8192) - return -EINVAL; - if (verify_area(VERIFY_WRITE, spar.data, spar.len * sizeof(__s16))) - return -EFAULT; - if (!(dev->sbuf.kbuf = kmalloc(spar.len * sizeof(__s16), GFP_KERNEL))) - return -ENOMEM; - save_flags(flags); - cli(); - dev->sbuf.kptr = dev->sbuf.kbuf; - dev->sbuf.size = spar.len * sizeof(__s16); - dev->sbuf.rem = spar.len; - dev->sbuf.ubuf = spar.data; - restore_flags(flags); - return 0; - - case HFMODEM_IOCTL_SAMPLEFINISHED: - save_flags(flags); - cli(); - if (dev->sbuf.rem > 0) { - restore_flags(flags); - return -EAGAIN; - } - if (!dev->sbuf.kbuf || !dev->sbuf.size) { - restore_flags(flags); - return -EPIPE; - } - restore_flags(flags); - ret = copy_to_user(dev->sbuf.ubuf, dev->sbuf.kbuf, dev->sbuf.size); - kfree_s(dev->sbuf.kbuf, dev->sbuf.size); - dev->sbuf.kbuf = dev->sbuf.kptr = NULL; - dev->sbuf.size = dev->sbuf.rem = 0; - return ret; - } -} - -/* --------------------------------------------------------------------- */ - -#if LINUX_VERSION_CODE >= 0x20100 - -unsigned int hfmodem_poll(struct file *file, poll_table *wait) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - unsigned long flags; - int i, cnt1, cnt2; - - poll_wait(file, &dev->wait, wait); - save_flags(flags); - cli(); - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - restore_flags(flags); - if (cnt1 || !cnt2) - return POLLIN | POLLRDNORM; - return 0; -} - -#else - -int hfmodem_select(struct inode *inode, struct file *file, int sel_type, select_table *wait) -{ - struct hfmodem_state *dev = &hfmodem_state[0]; - unsigned long flags; - int i, cnt1, cnt2; - - if (sel_type == SEL_IN) { - save_flags(flags); - cli(); - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - restore_flags(flags); - if (cnt1 || !cnt2) - return 1; - select_wait(&dev->wait, wait); - } - return 0; -} - -#endif - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int l1fsk_phinc(struct hfmodem_l1_txslot *txs, unsigned int nbit) -{ - return txs->phase_incs[!!((txs->data[nbit >> 3] ^ txs->inv) & (1 << (nbit & 7)))]; -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_input_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, - hfmodem_time_t tinc, __s16 *samples) -{ - hfmodem_time_t tst, tend; - __s16 *s; - int i, j; - hfmodem_soft_t sample; - - dev->l1.last_time = tstart + (HFMODEM_FRAGSAMPLES-1) * tinc; - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - struct hfmodem_l1_rxslot *rxs = dev->l1.rxslots + i; - - if (rxs->state == ss_unused || rxs->state == ss_retired) - continue; - tst = tstart - (rxs->corrlen-1) * tinc; - tend = tst + (HFMODEM_FRAGSAMPLES-1) * tinc; - if (rxs->state == ss_ready) { - if ((signed)(rxs->tstart - tend) > 0) - continue; - rxs->state = ss_oper; - } - for (s = samples, j = 0; j < HFMODEM_FRAGSAMPLES; j++, s++, tst += tinc) - if ((signed)(rxs->tstart - tst) <= 0) { - sample = do_filter(rxs, s); - while ((signed)(rxs->tstart - tst) <= 0 && - rxs->cntbits < rxs->nbits) { - rxs->data[rxs->cntbits] = sample; - rxs->cntbits++; - rxs->tstart += rxs->tinc; - } - if (rxs->cntbits >= rxs->nbits) { - rxs->state = ss_retired; - break; - } - } - } -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ unsigned int output_one_sample(struct hfmodem_state *dev, hfmodem_time_t tm) -{ - int i, j, k; - struct hfmodem_l1_txslot *txs; - /* - * first activate new output slots - */ - for (j = -1, i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - txs = dev->l1.txslots + i; - if (txs->state == ss_ready && (signed)(txs->tstart - tm) <= 0) { - for (k = 0; k < HFMODEM_NUMTXSLOTS; k++) { - if (dev->l1.txslots[k].state != ss_oper) - continue; - dev->l1.txslots[k].state = ss_retired; - } - txs->state = ss_oper; - txs->tstart += txs->tinc; - txs->phinc = l1fsk_phinc(txs, 0); - txs->cntbits = 1; - }; - if (txs->state != ss_oper) - continue; - j = i; - } - if (j < 0 || j >= HFMODEM_NUMTXSLOTS) - return 0; - /* - * calculate the current slot - */ - txs = dev->l1.txslots + j; - while ((signed)(txs->tstart - tm) <= 0) { - if (txs->cntbits >= txs->nbits) { - txs->state = ss_retired; - return 0; - } - txs->tstart += txs->tinc; - txs->phinc = l1fsk_phinc(txs, txs->cntbits); - txs->cntbits++; - } - return txs->phinc; -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_output_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, - hfmodem_time_t tinc, __s16 *samples) -{ - int i, j; - hfmodem_time_t tend = tstart + (HFMODEM_FRAGSAMPLES-1) * tinc; - - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_oper) - break; - if (dev->l1.txslots[i].state == ss_ready && - (signed)(dev->l1.txslots[i].tstart - tend) <= 0) - break; - } - if (i >= HFMODEM_NUMTXSLOTS) - return 0; - for (j = 0; j < HFMODEM_FRAGSAMPLES; j++, tstart += tinc, samples++) { - *samples = isimplecos(dev->l1.tx_phase); - dev->l1.tx_phase += output_one_sample(dev, tstart); - } - return 1; -} - -/* --------------------------------------------------------------------- */ - -long hfmodem_next_tx_event(struct hfmodem_state *dev, hfmodem_time_t curr) -{ - long diff = LONG_MAX, t; - int i; - - for (i = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_oper) - if (diff > 0) - diff = 0; - if (dev->l1.txslots[i].state == ss_ready) { - t = dev->l1.txslots[i].tstart - curr; - if (t < diff) - diff = t; - } - } - return diff; -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_finish_pending_rx_requests(struct hfmodem_state *dev) -{ - int i; - - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state != ss_oper) - continue; - while (dev->l1.rxslots[i].cntbits < dev->l1.rxslots[i].nbits) { - dev->l1.rxslots[i].data[dev->l1.rxslots[i].cntbits] = 0; - dev->l1.rxslots[i].cntbits++; - } - dev->l1.rxslots[i].state = ss_retired; - } -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_wakeup(struct hfmodem_state *dev) -{ - int i, cnt1, cnt2; - - for (i = cnt1 = cnt2 = 0; i < HFMODEM_NUMTXSLOTS; i++) { - if (dev->l1.txslots[i].state == ss_retired) - cnt1++; - if (dev->l1.txslots[i].state != ss_unused) - cnt2++; - } - for (i = 0; i < HFMODEM_NUMRXSLOTS; i++) { - if (dev->l1.rxslots[i].state == ss_retired) - cnt1++; - if (dev->l1.rxslots[i].state != ss_unused) - cnt2++; - } - if (cnt1 || !cnt2) - wake_up_interruptible(&dev->wait); -} - -/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/refclock.c linux/drivers/char/hfmodem/refclock.c --- v2.3.12/linux/drivers/char/hfmodem/refclock.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/hfmodem/refclock.c Wed Dec 31 16:00:00 1969 @@ -1,154 +0,0 @@ -/*****************************************************************************/ - -/* - * refclock.c -- Linux soundcard HF FSK driver, - * Reference clock routines. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20123 -#include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ -/* - * command line params - */ - -static unsigned int scale_tvusec = 1UL<<24; - -#ifdef __i386__ -static unsigned int scale_rdtsc = 0; -static int rdtsc_ok = 1; -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -#ifdef __i386__ -static void __init i386_capability(void) -{ - if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) - rdtsc_ok = 1; - else - printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname); -} -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -void __init hfmodem_refclock_probe(void) -{ -#ifdef __i386__ - if (rdtsc_ok) { - rdtsc_ok = 0; - i386_capability(); - if (rdtsc_ok) { - unsigned int tmp0, tmp1, tmp2, tmp3; - __asm__("rdtsc" : "=a" (tmp0), "=d" (tmp1)); - __asm__("rdtsc" : "=a" (tmp2), "=d" (tmp3)); - if (tmp0 == tmp2 && tmp1 == tmp3) { - rdtsc_ok = 0; - printk(KERN_WARNING "%s: rdtsc unusable, does not change\n", - hfmodem_drvname); - } - } - } - printk(KERN_INFO "%s: using %s as timing source\n", hfmodem_drvname, - rdtsc_ok ? "rdtsc" : "gettimeofday"); -#endif /* __i386__ */ -} - -/* --------------------------------------------------------------------- */ - -void hfmodem_refclock_init(struct hfmodem_state *dev) -{ - struct timeval tv; - - dev->clk.lasttime = 0; -#ifdef __i386__ - if (rdtsc_ok) { - __asm__("rdtsc;" : "=&d" (dev->clk.starttime_hi), "=&a" (dev->clk.starttime_lo)); - return; - } -#endif /* __i386__ */ - do_gettimeofday(&tv); - dev->clk.last_tvusec = tv.tv_usec; - dev->clk.time_cnt = 0; -} - -/* --------------------------------------------------------------------- */ - -hfmodem_time_t hfmodem_refclock_current(struct hfmodem_state *dev, hfmodem_time_t expected, int exp_valid) -{ - struct timeval tv; - hfmodem_time_t curtime; - long diff; - -#ifdef __i386__ - if (rdtsc_ok) { - unsigned int tmp0, tmp1; - unsigned int tmp2, tmp3; - - __asm__("rdtsc;\n\t" - "subl %2,%%eax\n\t" - "sbbl %3,%%edx\n\t" : "=&a" (tmp0), "=&d" (tmp1) - : "m" (dev->clk.starttime_lo), "m" (dev->clk.starttime_hi) : "ax", "dx"); - __asm__("mull %1" : "=d" (tmp2) : "m" (scale_rdtsc), "a" (tmp0) : "ax"); - __asm__("mull %1" : "=a" (tmp3) : "m" (scale_rdtsc), "a" (tmp1) : "dx"); - curtime = tmp2 + tmp3; - goto time_known; - } -#endif /* __i386__ */ - do_gettimeofday(&tv); - dev->clk.time_cnt += (unsigned)(1000000 + tv.tv_usec - dev->clk.last_tvusec) % 1000000; - dev->clk.last_tvusec = tv.tv_usec; - curtime = (dev->clk.time_cnt * scale_tvusec) >> 24; - time_known: - if (exp_valid && abs(diff = (curtime - dev->clk.lasttime - expected)) >= 1000) - printk(KERN_DEBUG "%s: refclock adjustment %ld more than 1ms\n", - hfmodem_drvname, diff); - return (dev->clk.lasttime = curtime); -} - -/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/sbc.c linux/drivers/char/hfmodem/sbc.c --- v2.3.12/linux/drivers/char/hfmodem/sbc.c Tue Aug 5 09:48:55 1997 +++ linux/drivers/char/hfmodem/sbc.c Wed Dec 31 16:00:00 1969 @@ -1,741 +0,0 @@ -/*****************************************************************************/ - -/* - * sbc.c -- Linux soundcard HF FSK driver, - * Soundblaster specific functions. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* --------------------------------------------------------------------- */ -/* - * the sbc converter's registers - */ -#define DSP_RESET(iobase) (iobase+0x6) -#define DSP_READ_DATA(iobase) (iobase+0xa) -#define DSP_WRITE_DATA(iobase) (iobase+0xc) -#define DSP_WRITE_STATUS(iobase) (iobase+0xc) -#define DSP_DATA_AVAIL(iobase) (iobase+0xe) -#define DSP_MIXER_ADDR(iobase) (iobase+0x4) -#define DSP_MIXER_DATA(iobase) (iobase+0x5) -#define DSP_INTACK_16BIT(iobase) (iobase+0xf) -#define SBC_EXTENT 16 - -/* --------------------------------------------------------------------- */ -/* - * SBC commands - */ - -#define SBC_OUTPUT 0x14 -#define SBC_INPUT 0x24 -#define SBC_BLOCKSIZE 0x48 -#define SBC_HI_OUTPUT 0x91 -#define SBC_HI_INPUT 0x99 -#define SBC_LO_OUTPUT_AUTOINIT 0x1c -#define SBC_LO_INPUT_AUTOINIT 0x2c -#define SBC_HI_OUTPUT_AUTOINIT 0x90 -#define SBC_HI_INPUT_AUTOINIT 0x98 -#define SBC_IMMED_INT 0xf2 -#define SBC_GET_REVISION 0xe1 -#define ESS_GET_REVISION 0xe7 -#define ESS_EXTENDED_MODE 0xc6 -#define SBC_SPEAKER_ON 0xd1 -#define SBC_SPEAKER_OFF 0xd3 -#define SBC_DMA_ON 0xd0 -#define SBC_DMA_OFF 0xd4 -#define SBC_SAMPLE_RATE 0x40 -#define SBC_SAMPLE_RATE_OUT 0x41 -#define SBC_SAMPLE_RATE_IN 0x42 -#define SBC_MONO_8BIT 0xa0 -#define SBC_MONO_16BIT 0xa4 -#define SBC_STEREO_8BIT 0xa8 -#define SBC_STEREO_16BIT 0xac - -#define SBC4_OUT8_AI 0xc6 -#define SBC4_IN8_AI 0xce -#define SBC4_MODE_UNS_MONO 0x00 -#define SBC4_MODE_SIGN_MONO 0x10 - -#define SBC4_OUT16_AI 0xb6 -#define SBC4_IN16_AI 0xbe -#define SBC4_OUT16_AI_NO_FIFO 0xb4 -#define SBC4_IN16_AI_NO_FIFO 0xbc - -/* --------------------------------------------------------------------- */ - -extern const struct hfmodem_scops sbc4_scops; -extern const struct hfmodem_scops ess_scops; - -/* --------------------------------------------------------------------- */ - -static int reset_dsp(struct hfmodem_state *dev) -{ - int i; - - outb(1, DSP_RESET(dev->io.base_addr)); - udelay(3); - outb(0, DSP_RESET(dev->io.base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->io.base_addr)) == 0xaa) - return 1; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void write_dsp(struct hfmodem_state *dev, unsigned char data) -{ - int i; - - for (i = 0; i < 0xffff; i++) - if (!(inb(DSP_WRITE_STATUS(dev->io.base_addr)) & 0x80)) { - outb(data, DSP_WRITE_DATA(dev->io.base_addr)); - return; - } -} - -/* --------------------------------------------------------------------- */ - -static int read_dsp(struct hfmodem_state *dev, unsigned char *data) -{ - int i; - - if (!data) - return 0; - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) { - *data = inb(DSP_READ_DATA(dev->io.base_addr)); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void write_ess(struct hfmodem_state *dev, unsigned char reg, unsigned char data) -{ - write_dsp(dev, reg); - write_dsp(dev, data); -} - -/* --------------------------------------------------------------------- */ - -static int read_ess(struct hfmodem_state *dev, unsigned char reg, unsigned char *data) -{ - write_dsp(dev, 0xc0); - write_dsp(dev, reg); - return read_dsp(dev, data); -} - -/* --------------------------------------------------------------------- */ - -static int reset_ess(struct hfmodem_state *dev) -{ - int i; - - outb(3, DSP_RESET(dev->io.base_addr)); /* reset FIFOs too */ - udelay(3); - outb(0, DSP_RESET(dev->io.base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->io.base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->io.base_addr)) == 0xaa) { - write_dsp(dev, ESS_EXTENDED_MODE); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int config_resources(struct hfmodem_state *dev) -{ - unsigned char irqreg = 0, dmareg = 0, realirq, realdma; - unsigned long flags; - - switch (dev->io.irq) { - case 2: - case 9: - irqreg |= 0x01; - break; - - case 5: - irqreg |= 0x02; - break; - - case 7: - irqreg |= 0x04; - break; - - case 10: - irqreg |= 0x08; - break; - - default: - return -ENODEV; - } - - switch (dev->io.dma) { - case 0: - dmareg |= 0x01; - break; - - case 1: - dmareg |= 0x02; - break; - - case 3: - dmareg |= 0x08; - break; - - case 5: - dmareg |= 0x20; - break; - - case 6: - dmareg |= 0x40; - break; - - case 7: - dmareg |= 0x80; - break; - - default: - return -ENODEV; - } - save_flags(flags); - cli(); - outb(0x80, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(irqreg, DSP_MIXER_DATA(dev->io.base_addr)); - realirq = inb(DSP_MIXER_DATA(dev->io.base_addr)); - outb(0x81, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(dmareg, DSP_MIXER_DATA(dev->io.base_addr)); - realdma = inb(DSP_MIXER_DATA(dev->io.base_addr)); - restore_flags(flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device " - "and IRQ/DMA specified wrongly?\n", hfmodem_drvname); - return -EINVAL; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void sbc_int_ack_8bit(struct hfmodem_state *dev) -{ - inb(DSP_DATA_AVAIL(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void sbc_int_ack_16bit(struct hfmodem_state *dev) -{ - inb(DSP_INTACK_16BIT(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void set_mixer(struct hfmodem_state *dev, unsigned char reg, unsigned char data) -{ - outb(reg, DSP_MIXER_ADDR(dev->io.base_addr)); - outb(data, DSP_MIXER_DATA(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_sbcprobe(struct hfmodem_state *dev) -{ - unsigned char revhi, revlo, essrevhi, essrevlo, tmp; - int ret; - - if (dev->io.base_addr <= 0 || dev->io.base_addr > 0x1000-SBC_EXTENT || - dev->io.irq < 2 || dev->io.irq > 15 || dev->io.dma > 7 || dev->io.dma == 2) - return -ENXIO; - if (check_region(dev->io.base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -ENODEV; - } - set_mixer(dev, 0, 0); /* reset mixer */ - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &revhi) || !read_dsp(dev, &revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%02d\n", hfmodem_drvname, revhi, revlo); - if (revhi == 3 && revlo == 1) { - write_dsp(dev, ESS_GET_REVISION); - if (!read_dsp(dev, &essrevhi) || !read_dsp(dev, &essrevlo)) - return -ENODEV; - if (essrevhi == 0x48 && (essrevlo & 0xf0) == 0x80) { - printk(KERN_INFO "%s: ESS ES488 AudioDrive (rev %d): unsupported.\n", - hfmodem_drvname, essrevlo & 0x0f); - return -ENODEV; - } - if (essrevhi == 0x68 && (essrevlo & 0xf0) == 0x80) { - printk(KERN_INFO "%s: ESS ES%s688 AudioDrive (rev %d)\n", - hfmodem_drvname, ((essrevlo & 0x0f) >= 8) ? "1" : "", essrevlo & 0x0f); - if (dev->io.dma > 3) { - printk(KERN_INFO "%s: DMA number out of range\n", hfmodem_drvname); - return -ENXIO; - } - printk(KERN_INFO "%s: ess: irq: ", hfmodem_drvname); - read_ess(dev, 0xb1, &tmp); - switch (tmp & 0xf) { - case 0: - printk("2, 9, \"all others\""); - break; - - case 5: - printk("5"); - break; - - case 10: - printk("7"); - break; - - case 15: - printk("10"); - break; - - default: - printk("unknown (%d)", tmp & 0xf); - break; - } - printk(" dma: "); - read_ess(dev, 0xb2, &tmp); - switch (tmp & 0xf) { - case 0: - printk("\"all others\""); - break; - - case 5: - printk("0"); - break; - - case 10: - printk("1"); - break; - - case 15: - printk("3"); - break; - - default: - printk("unknown (%d)", tmp & 0xf); - break; - } - printk("\n"); - dev->scops = &ess_scops; - return 0; - } - } - if (revhi < 4) { - printk(KERN_INFO "%s: at least SB16 required\n", hfmodem_drvname); - return -ENODEV; - } - if (dev->io.dma < 4) { - printk(KERN_INFO "%s: DMA number out of range\n", hfmodem_drvname); - return -ENXIO; - } - if ((ret = config_resources(dev))) - return ret; - dev->scops = &sbc4_scops; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_init(struct hfmodem_state *dev) -{ -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE_IN); /* set sampling rate */ - write_dsp(dev, HFMODEM_SRATE >> 8); - write_dsp(dev, HFMODEM_SRATE & 0xff); - write_dsp(dev, SBC_SPEAKER_OFF); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_dsp(dev, SBC4_IN16_AI_NO_FIFO); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE_OUT); /* set sampling rate */ - write_dsp(dev, HFMODEM_SRATE >> 8); - write_dsp(dev, HFMODEM_SRATE & 0xff); - write_dsp(dev, SBC_SPEAKER_ON); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_dsp(dev, SBC4_OUT16_AI_NO_FIFO); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_dsp(dev, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_stop(struct hfmodem_state *dev) -{ - reset_dsp(dev); -} - -/* --------------------------------------------------------------------- */ - -static unsigned int sbc4_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr; - unsigned long flags; - unsigned char intsrc; - - save_flags(flags); - cli(); - outb(0x82, DSP_MIXER_ADDR(dev->io.base_addr)); - intsrc = inb(DSP_MIXER_DATA(dev->io.base_addr)); - if (intsrc & 0x01) - sbc_int_ack_8bit(dev); - if (intsrc & 0x02) - sbc_int_ack_16bit(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - enable_dma(dev->io.dma); - restore_flags(flags); - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void sbc4_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - static const unsigned char srcbits[3] = { 0x18, 0x01, 0x06 }; - - save_flags(flags); - cli(); - if (src >= 0 && src <= 2) { - set_mixer(dev, 0x3d, srcbits[src]); - set_mixer(dev, 0x3e, srcbits[src]); - } - if (ogain >= 0 && ogain <= 255) { - set_mixer(dev, 0x30, ogain); - set_mixer(dev, 0x31, ogain); - } - if (igain >= 0 && igain <= 255) { - set_mixer(dev, 0x36, igain); - set_mixer(dev, 0x37, igain); - set_mixer(dev, 0x38, igain); - set_mixer(dev, 0x39, igain); - set_mixer(dev, 0x3a, igain); - } - set_mixer(dev, 0x32, 0xff); - set_mixer(dev, 0x33, 0xff); - set_mixer(dev, 0x34, 0); - set_mixer(dev, 0x35, 0); - set_mixer(dev, 0x3b, 0); /* pc spkr vol */ - set_mixer(dev, 0x3c, 0); /* output src */ - set_mixer(dev, 0x3f, 0); /* inp gain */ - set_mixer(dev, 0x40, 0); - set_mixer(dev, 0x41, 0); /* outp gain */ - set_mixer(dev, 0x42, 0); - set_mixer(dev, 0x43, 1); /* mic agc off */ - set_mixer(dev, 0x44, 8<<4); /* treble */ - set_mixer(dev, 0x45, 8<<4); - set_mixer(dev, 0x46, 8<<4); /* bass */ - set_mixer(dev, 0x47, 8<<4); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void ess_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - if (!reset_ess(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_8bit(dev); - write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); - /* - * Set filter divider register - * Rolloff at 90% of the half sampling rate - */ - write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); - write_dsp(dev, SBC_SPEAKER_OFF); - write_ess(dev, 0xb8, 0x0e); /* Auto init DMA mode */ - read_ess(dev, 0xa8, &tmp); - write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ - write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - /* 16 bit mono */ - write_ess(dev, 0xb7, 0x71); - write_ess(dev, 0xb7, 0xf4); - - read_ess(dev, 0xb1, &tmp); - write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); - read_ess(dev, 0xb2, &tmp); - write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); - - write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); - write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void ess_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - save_flags(flags); - cli(); - read_ess(dev, 0xb8, &tmp); - write_ess(dev, 0xb8, tmp | 0x0f); /* Go */ - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -void ess_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - if (!reset_ess(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset ess dsp\n", hfmodem_drvname); - return; - } - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - sbc_int_ack_8bit(dev); - write_ess(dev, 0xa1, 128 - (397700 + HFMODEM_SRATE/2) / HFMODEM_SRATE); - /* - * Set filter divider register - * Rolloff at 90% of the half sampling rate - */ - write_ess(dev, 0xa2, 256-(7160000 / (82 * (HFMODEM_SRATE * 9 / 20)))); - write_ess(dev, 0xb8, 0x04); /* Auto init DMA mode */ - read_ess(dev, 0xa8, &tmp); - write_ess(dev, 0xa8, (tmp & ~0x03) | 2); /* Mono */ - write_ess(dev, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - /* 16 bit mono */ - write_ess(dev, 0xb6, 0x00); - write_ess(dev, 0xb7, 0x71); - write_ess(dev, 0xb7, 0xf4); - - read_ess(dev, 0xb1, &tmp); - write_ess(dev, 0xb1, (tmp & 0x0f) | 0x50); - read_ess(dev, 0xb2, &tmp); - write_ess(dev, 0xb2, (tmp & 0x0f) | 0x50); - - write_ess(dev, 0xa4, (unsigned char) ((-HFMODEM_FRAGSIZE) & 0xff)); - write_ess(dev, 0xa5, (unsigned char) (((-HFMODEM_FRAGSIZE) >> 8) & 0xff)); - - write_dsp(dev, SBC_SPEAKER_ON); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -void ess_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char tmp; - - save_flags(flags); - cli(); - read_ess(dev, 0xb8, &tmp); - write_ess(dev, 0xb8, tmp | 0x05); /* Go */ - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -unsigned int ess_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr; - unsigned long flags; - unsigned char st; -#if 0 - static unsigned int cnt = 0; -#endif - - save_flags(flags); - cli(); - st = inb(DSP_WRITE_STATUS(dev->io.base_addr)); - sbc_int_ack_8bit(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - enable_dma(dev->io.dma); - restore_flags(flags); -#if 0 - cnt = (cnt + 1) & 0x3f; - if (!cnt) - printk(KERN_DEBUG "%s: ess: FIFO: full:%c empty:%c half empty:%c IRQ: cpu:%c half empty:%c DMA:%c\n", - hfmodem_drvname, '1'-!(st&0x20), '1'-!(st&0x10), '1'-!(st&0x8), - '1'-!(st&0x4), '1'-!(st&0x2), '1'-!(st&0x1)); -#endif - if (st & 0x20) /* FIFO full, 256 bytes */ - dmaptr += 256; - else if (!(st & 0x10)) /* FIFO not empty, assume half full 128 bytes */ - dmaptr += 128; - if (dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr -= HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void ess_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if (src >= 0 && src <= 2) - set_mixer(dev, 0x0c, ((src+3) & 3) << 1); - if (ogain >= 0 && ogain <= 255) - set_mixer(dev, 0x22, (ogain & 0xf0) | ((ogain >> 4) & 0xf)); - if (igain >= 0 && igain <= 255) { - set_mixer(dev, 0x36, igain); - set_mixer(dev, 0x37, igain); - set_mixer(dev, 0x38, igain); - set_mixer(dev, 0x39, igain); - set_mixer(dev, 0x3a, igain); - } - set_mixer(dev, 0x4, 0xff); - set_mixer(dev, 0xe, 0x0); - set_mixer(dev, 0x26, 0); - set_mixer(dev, 0x28, 0); - set_mixer(dev, 0x2e, 0); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static const struct hfmodem_scops sbc4_scops = { - SBC_EXTENT, sbc4_init, sbc4_prepare_input, sbc4_trigger_input, - sbc4_prepare_output, sbc4_trigger_output, sbc4_stop, sbc4_intack, sbc4_mixer -}; - -static const struct hfmodem_scops ess_scops = { - SBC_EXTENT, sbc4_init, ess_prepare_input, ess_trigger_input, - ess_prepare_output, ess_trigger_output, sbc4_stop, ess_intack, ess_mixer -}; - -/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/hfmodem/wss.c linux/drivers/char/hfmodem/wss.c --- v2.3.12/linux/drivers/char/hfmodem/wss.c Tue Aug 5 09:48:55 1997 +++ linux/drivers/char/hfmodem/wss.c Wed Dec 31 16:00:00 1969 @@ -1,437 +0,0 @@ -/*****************************************************************************/ - -/* - * wss.c -- Linux soundcard HF FSK driver, - * WindowsSoundSystem specific functions. - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Swiss Federal Institute of Technology (ETH), Electronics Lab - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -/* --------------------------------------------------------------------- */ - -#define WSS_CONFIG(iobase) (iobase+0) -#define WSS_STATUS(iobase) (iobase+3) -#define WSS_CODEC_IA(iobase) (iobase+4) -#define WSS_CODEC_ID(iobase) (iobase+5) -#define WSS_CODEC_STATUS(iobase) (iobase+6) -#define WSS_CODEC_DATA(iobase) (iobase+7) - -#define WSS_EXTENT 8 - -/* --------------------------------------------------------------------- */ - -extern const struct hfmodem_scops wss_scops; - -/* --------------------------------------------------------------------- */ - -static void write_codec(struct hfmodem_state *dev, unsigned char idx, - unsigned char data) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80) - timeout--; - outb(idx, WSS_CODEC_IA(dev->io.base_addr)); - outb(data, WSS_CODEC_ID(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static unsigned char read_codec(struct hfmodem_state *dev, unsigned char idx) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->io.base_addr)) & 0x80) - timeout--; - outb(idx & 0x1f, WSS_CODEC_IA(dev->io.base_addr)); - return inb(WSS_CODEC_ID(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern __inline__ void wss_ack_int(struct hfmodem_state *dev) -{ - outb(0, WSS_CODEC_STATUS(dev->io.base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static int wss_srate_tab[16] = { - 8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6620 -}; - -static int wss_srate_index(int srate) -{ - int i; - - for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++) - if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0) - return i; - return -1; -} - -/* --------------------------------------------------------------------- */ - -static int wss_set_codec_fmt(struct hfmodem_state *dev, unsigned char fmt) -{ - unsigned long time; - unsigned long flags; - - save_flags(flags); - cli(); - /* Clock and data format register */ - write_codec(dev, 0x48, fmt); - /* MCE and interface config reg */ - write_codec(dev, 0x49, 0xc); - outb(0xb, WSS_CODEC_IA(dev->io.base_addr)); /* leave MCE */ - /* - * wait for ACI start - */ - time = 1000; - while (!(read_codec(dev, 0x0b) & 0x20)) - if (!(--time)) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", - hfmodem_drvname); - restore_flags(flags); - return -1; - } - /* - * wait for ACI end - */ - sti(); - time = jiffies + HZ/4; - while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0)); - restore_flags(flags); - if ((signed)(jiffies - time) >= 0) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", - hfmodem_drvname); - return -1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_init_codec(struct hfmodem_state *dev) -{ - unsigned char tmp, revwss, revid; - static const signed char irqtab[16] = { - -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, -1, -1 - }; - static const signed char dmatab[4] = { 1, 2, -1, 3 }; - int fmt; - - if ((fmt = wss_srate_index(HFMODEM_SRATE)) < 0) { - printk(KERN_ERR "%s: WSS: sampling rate not supported\n", hfmodem_drvname); - return -1; - } - fmt &= 0x0f; -#ifdef __BIG_ENDIAN - fmt |= 0xc0; -#else /* __BIG_ENDIAN */ - fmt |= 0x40; -#endif /* __BIG_ENDIAN */ - tmp = inb(WSS_STATUS(dev->io.base_addr)); - if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && - (tmp & 0x3f) != 0x0f) { - printk(KERN_WARNING "%s: WSS card id register not found, " - "address 0x%x, ID register 0x%02x\n", hfmodem_drvname, - dev->io.base_addr, (int)tmp); - /* return -1; */ - revwss = 0; - } else { - if ((tmp & 0x80) && ((dev->io.dma == 0) || ((dev->io.irq >= 8) && (dev->io.irq != 9)))) { - printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 " - "(except IRQ9) cannot be used on an 8bit " - "card\n", hfmodem_drvname); - return -1; - } - if (dev->io.irq > 15 || irqtab[dev->io.irq] == -1) { - printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", - hfmodem_drvname, (int)dev->io.irq); - return -1; - } - if (dev->io.dma > 3 || dmatab[dev->io.dma] == -1) { - printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", - hfmodem_drvname, (int)dev->io.dma); - return -1; - } - tmp = irqtab[dev->io.irq] | dmatab[dev->io.dma]; - /* irq probe */ - outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->io.base_addr)); - if (!(inb(WSS_STATUS(dev->io.base_addr)) & 0x40)) { - outb(0, WSS_CONFIG(dev->io.base_addr)); - printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", - hfmodem_drvname, dev->io.irq); - } - outb(tmp, WSS_CONFIG(dev->io.base_addr)); - revwss = inb(WSS_STATUS(dev->io.base_addr)) & 0x3f; - } - /* - * initialize the codec - */ - write_codec(dev, 9, 0); - write_codec(dev, 12, 0); - write_codec(dev, 0, 0x45); - if (read_codec(dev, 0) != 0x45) - goto codec_err; - write_codec(dev, 0, 0xaa); - if (read_codec(dev, 0) != 0xaa) - goto codec_err; - if (wss_set_codec_fmt(dev, fmt)) - goto codec_err; - write_codec(dev, 0, 0x40); /* left input control */ - write_codec(dev, 1, 0x40); /* right input control */ - write_codec(dev, 2, 0x80); /* left aux#1 input control */ - write_codec(dev, 3, 0x80); /* right aux#1 input control */ - write_codec(dev, 4, 0x80); /* left aux#2 input control */ - write_codec(dev, 5, 0x80); /* right aux#2 input control */ - write_codec(dev, 6, 0x80); /* left dac control */ - write_codec(dev, 7, 0x80); /* right dac control */ - write_codec(dev, 0xa, 0x2); /* pin control register */ - write_codec(dev, 0xd, 0x0); /* digital mix control */ - revid = read_codec(dev, 0xc) & 0xf; - /* - * print revisions - */ - printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", - hfmodem_drvname, (int)revwss, (int)revid); - return 0; - codec_err: - outb(0, WSS_CONFIG(dev->io.base_addr)); - printk(KERN_ERR "%s: no WSS soundcard found at address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -1; -} - -/* --------------------------------------------------------------------- */ - -int hfmodem_wssprobe(struct hfmodem_state *dev) -{ - if (dev->io.base_addr <= 0 || dev->io.base_addr > 0x1000-WSS_EXTENT || - dev->io.irq < 2 || dev->io.irq > 15 || dev->io.dma > 3 || dev->io.dma == 2) - return -ENXIO; - if (check_region(dev->io.base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%x\n", - hfmodem_drvname, dev->io.base_addr); - return -ENODEV; - } - dev->scops = &wss_scops; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void wss_init(struct hfmodem_state *dev) -{ - wss_init_codec(dev); -} - -/* --------------------------------------------------------------------- */ - -static void wss_stop(struct hfmodem_state *dev) -{ - unsigned long flags; - unsigned char oldcodecmode; - long abrt; - - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0xc); /* disable codec */ - wss_ack_int(dev); - if (read_codec(dev, 11) & 0x10) { - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, (oldcodecmode & 1) ? - (DMA_MODE_WRITE | DMA_MODE_AUTOINIT) : (DMA_MODE_READ | DMA_MODE_AUTOINIT)); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - abrt = 0; - while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000)); - } - disable_dma(dev->io.dma); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_prepare_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - wss_stop(dev); - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_trigger_input(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_codec(dev, 9, 0x0e); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_prepare_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - wss_stop(dev); - save_flags(flags); - cli(); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - set_dma_mode(dev->io.dma, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dev->io.dma, virt_to_bus(dev->dma.buf)); - set_dma_count(dev->io.dma, HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE); - enable_dma(dev->io.dma); - write_codec(dev, 15, (HFMODEM_FRAGSAMPLES-1) & 0xff); - write_codec(dev, 14, (HFMODEM_FRAGSAMPLES-1) >> 8); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_trigger_output(struct hfmodem_state *dev) -{ - unsigned long flags; - - save_flags(flags); - cli(); - write_codec(dev, 9, 0x0d); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static unsigned int wss_intack(struct hfmodem_state *dev) -{ - unsigned int dmaptr, nums; - unsigned long flags; - - save_flags(flags); - cli(); - wss_ack_int(dev); - disable_dma(dev->io.dma); - clear_dma_ff(dev->io.dma); - dmaptr = get_dma_residue(dev->io.dma); - if (dmaptr == 0 || dmaptr > HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE) - dmaptr = HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE; - nums = (((dmaptr - 1) % HFMODEM_FRAGSIZE) - 1) / 2; - write_codec(dev, 15, nums & 0xff); - write_codec(dev, 14, nums >> 8); - enable_dma(dev->io.dma); - restore_flags(flags); - return (HFMODEM_NUMFRAGS * HFMODEM_FRAGSIZE - dmaptr) / 2; -} - -/* --------------------------------------------------------------------- */ - -static void wss_mixer(struct hfmodem_state *dev, int src, int igain, int ogain) -{ - unsigned long flags; - static const unsigned char srctoreg[3] = { 1, 2, 0 }; - static const unsigned char regtosrc[4] = { 2, 0, 1, 0 }; - unsigned char tmp; - - save_flags(flags); - cli(); - tmp = read_codec(dev, 0x00); - if (src < 0 || src > 2) - src = regtosrc[(tmp >> 6) & 3]; - if (igain < 0 || igain > 255) { - if (src == 1) - igain = ((tmp & 0xf) + ((tmp & 0x20) ? 13 : 0)) << 3; - else - igain = (tmp & 0xf) << 4; - } - if (src == 1) { - if (igain > (28<<3)) - tmp = 0x2f; - else if (igain >= (13<<3)) - tmp = 0x20 + (((igain >> 3) - 13) & 0xf); - else - tmp = (igain >> 3) & 0xf; - } else - tmp = (igain >> 4) & 0xf; - tmp |= srctoreg[src] << 6; - write_codec(dev, 0, tmp); - write_codec(dev, 1, tmp); - if (ogain > 0 && ogain <= 255) { - tmp = 63 - (ogain >> 2); - write_codec(dev, 6, tmp); - write_codec(dev, 7, tmp); - } else if (ogain == 0) { - write_codec(dev, 6, 0x80); - write_codec(dev, 7, 0x80); - } - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static const struct hfmodem_scops wss_scops = { - WSS_EXTENT, wss_init, wss_prepare_input, wss_trigger_input, - wss_prepare_output, wss_trigger_output, wss_stop, wss_intack, wss_mixer -}; - -/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/isicom.c linux/drivers/char/isicom.c --- v2.3.12/linux/drivers/char/isicom.c Wed May 12 13:27:37 1999 +++ linux/drivers/char/isicom.c Mon Aug 9 10:23:09 1999 @@ -14,7 +14,8 @@ * Printk clean up * 9/12/98 alan@redhat.com Rough port to 2.1.x * - * + * 10/6/99 sameer Merged the ISA and PCI drivers to + * a new unified driver. * *********************************************************** * * To use this driver you also need the support package. You @@ -51,8 +52,21 @@ #include #include +#include + #include +static int device_id[] = { 0x2028, + 0x2051, + 0x2052, + 0x2053, + 0x2054, + 0x2055, + 0x2056, + 0x2057, + 0x2058 + }; + static int isicom_refcount = 0; static int prev_card = 3; /* start servicing isi_card[0] */ static struct isi_board * irq_to_board[16] = { NULL, }; @@ -147,7 +161,7 @@ static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - unsigned int card, i, j, signature, status; + unsigned int card, i, j, signature, status, portcount = 0; unsigned short word_count, base; bin_frame frame; /* exec_record exec_rec; */ @@ -180,19 +194,38 @@ printk("."); } signature=(inw(base+0x4)) & 0xff; - - if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) { + if (isi_card[card].isa) { + + if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) { #ifdef ISICOM_DEBUG - printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); + printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); #endif - printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); - return -EIO; - } - + printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); + return -EIO; + } + } + else { + portcount = inw(base+0x2); + if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) { +#ifdef ISICOM_DEBUG + printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); +#endif + printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base); + return -EIO; + } + } switch(signature) { case 0xa5: case 0xbb: - case 0xdd: isi_card[card].port_count = 8; + case 0xdd: + if (isi_card[card].isa) + isi_card[card].port_count = 8; + else { + if (portcount == 4) + isi_card[card].port_count = 4; + else + isi_card[card].port_count = 8; + } isi_card[card].shift_count = 12; break; @@ -310,7 +343,8 @@ outw(0x0, base); outw(0x0, base); InterruptTheCard(base); - + outw(0x0, base+0x4); /* for ISI4608 cards */ + isi_card[card].status |= FIRMWARE_LOADED; return 0; @@ -455,28 +489,7 @@ txcount--; } } -/* - * Replaced the code below with hopefully a faster loop - sameer - */ -/* - while (1) { - wrd = port->xmit_buf[port->xmit_tail++]; - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - if (--txcount > 0) { - wrd |= (port->xmit_buf[port->xmit_tail++] << 8); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); - port->xmit_cnt--; - outw(wrd, base); - if (--txcount <= 0) break; - } - else { - outw(wrd, base); - break; - } - } -*/ InterruptTheCard(base); if (port->xmit_cnt <= 0) port->status &= ~ISI_TXOK; @@ -531,12 +544,34 @@ unsigned char channel; short byte_count; - card = irq_to_board[irq]; + /* + * find the source of interrupt + */ + + for(count = 0; count < BOARD_COUNT; count++) { + card = &isi_card[count]; + if (card->base != 0) { + if (((card->isa == YES) && (card->irq == irq)) || + ((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02))) + break; + } + card = NULL; + } + if (!card || !(card->status & FIRMWARE_LOADED)) { - printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq); +/* printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/ return; } + base = card->base; + if (card->isa == NO) { + /* + * disable any interrupts from the PCI card and lower the + * interrupt line + */ + outw(0x8000, base+0x04); + ClearInterrupt(base); + } inw(base); /* get the dummy word out */ header = inw(base); @@ -548,12 +583,18 @@ if ((channel+1) > card->port_count) { printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n", base, channel+1); - ClearInterrupt(base); + if (card->isa) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } port = card->ports + channel; if (!(port->flags & ASYNC_INITIALIZED)) { - ClearInterrupt(base); + if (card->isa) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } @@ -681,7 +722,10 @@ } queue_task(&tty->flip.tqueue, &tq_timer); } - ClearInterrupt(base); + if (card->isa == YES) + ClearInterrupt(base); + else + outw(0x0000, base+0x04); /* enable interrupts */ return; } @@ -1023,12 +1067,11 @@ return -ENODEV; } - /* open on higher 8 dev files on a 8 port card !!! */ - if (card->port_count == 8) - if (line > ((board * 16)+7)) { - printk(KERN_ERR "ISICOM: Opened >8 on a 8 port card.\n"); - return -ENODEV; - } + /* open on a port greater than the port count for the card !!! */ + if (line > ((board * 16) + card->port_count - 1)) { + printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!\n"); + return -ENODEV; + } port = &isi_ports[line]; if (isicom_paranoia_check(port, tty->device, "isicom_open")) return -ENODEV; @@ -1764,21 +1807,42 @@ static int register_isr(void) { - int count, done=0; + int count, done=0, card; + unsigned char request; for (count=0; count < BOARD_COUNT; count++ ) { if (isi_card[count].base) { - if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) { - printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n", - isi_card[count].irq, count+1); + /* + * verify if the required irq has already been requested for + * another ISI Card, if so we already have it, else request it + */ + request = YES; + for(card = 0; card < count; card++) + if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) { + request = NO; + if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO)) + break; + /* + * ISA cards cannot share interrupts with other + * PCI or ISA devices hence disable this card. + */ release_region(isi_card[count].base,16); - isi_card[count].base=0; + isi_card[count].base = 0; + break; } - else { - printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", - count+1, isi_card[count].base, isi_card[count].irq); - - irq_to_board[isi_card[count].irq]=&isi_card[count]; - done++; + if (request == YES) { + if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) { + printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n", + isi_card[count].irq, count+1); + release_region(isi_card[count].base,16); + isi_card[count].base=0; + } + else { + printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", + count+1, isi_card[count].base, isi_card[count].irq); + + irq_to_board[isi_card[count].irq]=&isi_card[count]; + done++; + } } } } @@ -1787,14 +1851,24 @@ static void unregister_isr(void) { - int count; - for (count=0; count < BOARD_COUNT; count++ ) + int count, card; + unsigned char freeirq; + for (count=0; count < BOARD_COUNT; count++ ) { if (isi_card[count].base) { - free_irq(isi_card[count].irq, NULL); + freeirq = YES; + for(card = 0; card < count; card++) + if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) { + freeirq = NO; + break; + } + if (freeirq == YES) { + free_irq(isi_card[count].irq, NULL); #ifdef ISICOM_DEBUG - printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1); -#endif + printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1); +#endif + } } + } } static int isicom_init(void) @@ -1883,28 +1957,74 @@ int init_module(void) { - int retval, card; - - for(card=0; card < BOARD_COUNT; card++) - { - isi_card[card].base=io[card]; - isi_card[card].irq=irq[card]; - } - - for (card=0 ;card < BOARD_COUNT; card++) { - if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)|| - (isi_card[card].irq==4)||(isi_card[card].irq==5)|| - (isi_card[card].irq==7)||(isi_card[card].irq==10)|| - (isi_card[card].irq==11)||(isi_card[card].irq==12)|| - (isi_card[card].irq==15))) { + struct pci_dev *dev = NULL; + int retval, card, idx, count; + unsigned char pciirq; + unsigned int ioaddr; + + card = 0; + for(idx=0; idx < BOARD_COUNT; idx++) { + if (io[idx]) { + isi_card[idx].base=io[idx]; + isi_card[idx].irq=irq[idx]; + isi_card[idx].isa=YES; + card++; + } + else { + isi_card[idx].base = 0; + isi_card[idx].irq = 0; + } + } + + for (idx=0 ;idx < card; idx++) { + if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)|| + (isi_card[idx].irq==4)||(isi_card[idx].irq==5)|| + (isi_card[idx].irq==7)||(isi_card[idx].irq==10)|| + (isi_card[idx].irq==11)||(isi_card[idx].irq==12)|| + (isi_card[idx].irq==15))) { - if (isi_card[card].base) { + if (isi_card[idx].base) { printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n", - isi_card[card].irq, card+1); - isi_card[card].base=0; + isi_card[idx].irq, idx+1); + isi_card[idx].base=0; + card--; } } } + + if (pci_present() && (card < BOARD_COUNT)) { + for (idx=0; idx < DEVID_COUNT; idx++) { + dev = NULL; + for (;;){ + if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev))) + break; + if (card >= BOARD_COUNT) + break; + + /* found a PCI ISI card! */ + ioaddr = dev->resource[3].start; /* i.e at offset 0x1c in the + * PCI configuration register + * space. + */ + ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + pciirq = dev->irq; + printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]); + /* + * allot the first empty slot in the array + */ + for (count=0; count < BOARD_COUNT; count++) { + if (isi_card[count].base == 0) { + isi_card[count].base = ioaddr; + isi_card[count].irq = pciirq; + isi_card[count].isa = NO; + card++; + break; + } + } + } + if (card >= BOARD_COUNT) break; + } + } if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) { printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); diff -u --recursive --new-file v2.3.12/linux/drivers/char/istallion.c linux/drivers/char/istallion.c --- v2.3.12/linux/drivers/char/istallion.c Fri Apr 16 08:20:23 1999 +++ linux/drivers/char/istallion.c Mon Aug 9 10:23:09 1999 @@ -4387,7 +4387,7 @@ * Probe and initialize the specified board. */ -__initfunc(static int stli_brdinit(stlibrd_t *brdp)) +static int __init stli_brdinit(stlibrd_t *brdp) { #if DEBUG printk("stli_brdinit(brdp=%x)\n", (int) brdp); @@ -5305,7 +5305,7 @@ /*****************************************************************************/ -__initfunc(int stli_init(void)) +int __init stli_init(void) { printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); diff -u --recursive --new-file v2.3.12/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.3.12/linux/drivers/char/keyboard.c Sat May 22 12:57:24 1999 +++ linux/drivers/char/keyboard.c Thu Aug 5 14:43:32 1999 @@ -155,6 +155,7 @@ #ifdef CONFIG_MAGIC_SYSRQ static int sysrq_pressed; +int sysrq_enabled = 1; #endif /* @@ -247,7 +248,7 @@ sysrq_pressed = !up_flag; return; } else if (sysrq_pressed) { - if (!up_flag) { + if (!up_flag && sysrq_enabled) { handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); return; } diff -u --recursive --new-file v2.3.12/linux/drivers/char/logibusmouse.c linux/drivers/char/logibusmouse.c --- v2.3.12/linux/drivers/char/logibusmouse.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/logibusmouse.c Mon Aug 2 09:54:29 1999 @@ -0,0 +1,157 @@ +/* + * Logitech Bus Mouse Driver for Linux + * by James Banks + * + * Mods by Matthew Dillon + * calls verify_area() + * tracks better when X is busy or paging + * + * Heavily modified by David Giller + * changed from queue- to counter- driven + * hacked out a (probably incorrect) mouse_select + * + * Modified again by Nathan Laredo to interface with + * 0.96c-pl1 IRQ handling changes (13JUL92) + * didn't bother touching select code. + * + * Modified the select() code blindly to conform to the VFS + * requirements. 92.07.14 - Linus. Somebody should test it out. + * + * Modified by Johan Myreen to make room for other mice (9AUG92) + * removed assignment chr_fops[10] = &mouse_fops; see mouse.c + * renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public. + * renamed this file mouse.c => busmouse.c + * + * Minor addition by Cliff Matthews + * added fasync support + * + * Modularised 6-Sep-95 Philip Blundell + * + * Replaced dumb busy loop with udelay() 16 Nov 95 + * Nathan Laredo + * + * Track I/O ports with request_region(). 12 Dec 95 Philip Blundell + * + * Converted to use new generic busmouse code. 5 Apr 1998 + * Russell King + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "busmouse.h" + +static int msedev; +static int mouse_irq = MOUSE_IRQ; + +#ifdef MODULE +MODULE_PARM(mouse_irq, "i"); +#endif + +void __init bmouse_setup(char *str, int *ints) +{ + if (ints[0] > 0) + mouse_irq=ints[1]; +} + +static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + char dx, dy; + unsigned char buttons; + + outb(MSE_READ_X_LOW, MSE_CONTROL_PORT); + dx = (inb(MSE_DATA_PORT) & 0xf); + outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT); + dx |= (inb(MSE_DATA_PORT) & 0xf) << 4; + outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT ); + dy = (inb(MSE_DATA_PORT) & 0xf); + outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT); + buttons = inb(MSE_DATA_PORT); + dy |= (buttons & 0xf) << 4; + buttons = ((buttons >> 5) & 0x07); + busmouse_add_movementbuttons(msedev, dx, -dy, buttons); + MSE_INT_ON(); +} + +/* + * close access to the mouse + */ +static int close_mouse(struct inode * inode, struct file * file) +{ + MSE_INT_OFF(); + free_irq(mouse_irq, NULL); + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * open access to the mouse + */ + +static int open_mouse(struct inode * inode, struct file * file) +{ + if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL)) + return -EBUSY; + MOD_INC_USE_COUNT; + MSE_INT_ON(); + return 0; +} + +static struct busmouse busmouse = { + LOGITECH_BUSMOUSE, "busmouse", open_mouse, close_mouse, 7 +}; + +int __init bus_mouse_init(void) +{ + if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) + return -EIO; + + outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT); + outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT); + udelay(100L); /* wait for reply from mouse */ + if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) + return -EIO; + + outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT); + MSE_INT_OFF(); + + request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse"); + + msedev = register_busmouse(&busmouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to register busmouse driver.\n"); + else + printk(KERN_INFO "Logitech busmouse installed.\n"); + return msedev < 0 ? msedev : 0; +} + +#ifdef MODULE + +int init_module(void) +{ + return bus_mouse_init(); +} + +void cleanup_module(void) +{ + unregister_busmouse(msedev); + release_region(LOGIBM_BASE, LOGIBM_EXTENT); +} +#endif diff -u --recursive --new-file v2.3.12/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.3.12/linux/drivers/char/lp.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/char/lp.c Mon Aug 9 10:23:09 1999 @@ -711,7 +711,7 @@ static int parport_ptr = 0; -__initfunc(void lp_setup(char *str, int *ints)) +void __init lp_setup(char *str, int *ints) { if (!str) { if (ints[0] == 0 || ints[1] == 0) { @@ -755,6 +755,17 @@ printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); +#ifdef CONFIG_LP_CONSOLE + if (!nr) { + if (port->modes & PARPORT_MODE_SAFEININT) { + register_console (&lpcons); + printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP); + } else + printk (KERN_ERR "lp%d: cannot run console on %s\n", + CONSOLE_LP, port->name); + } +#endif + return 0; } @@ -842,12 +853,6 @@ printk (KERN_INFO "lp: (is IEEE 1284.3 support enabled?)\n"); #endif } -#ifdef CONFIG_LP_CONSOLE - else { - register_console (&lpcons); - printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP); - } -#endif return 0; } diff -u --recursive --new-file v2.3.12/linux/drivers/char/lp_intern.c linux/drivers/char/lp_intern.c --- v2.3.12/linux/drivers/char/lp_intern.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/lp_intern.c Mon Aug 9 10:23:09 1999 @@ -219,7 +219,7 @@ NULL, }; -__initfunc(int lp_internal_init(void)) +int __init lp_internal_init(void) { #ifdef CONFIG_AMIGA if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) diff -u --recursive --new-file v2.3.12/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c --- v2.3.12/linux/drivers/char/lp_m68k.c Fri Jan 15 17:46:27 1999 +++ linux/drivers/char/lp_m68k.c Mon Aug 9 10:23:09 1999 @@ -474,7 +474,7 @@ EXPORT_SYMBOL(register_parallel); EXPORT_SYMBOL(unregister_parallel); -__initfunc(int lp_m68k_init(void)) +int __init lp_m68k_init(void) { extern char m68k_debug_device[]; @@ -507,7 +507,7 @@ /* * Currently we do not accept any lp-parameters, but that may change. */ -__initfunc(void lp_setup(char *str, int *ints)) +void __init lp_setup(char *str, int *ints) { } diff -u --recursive --new-file v2.3.12/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.3.12/linux/drivers/char/mem.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/char/mem.c Mon Aug 9 12:28:41 1999 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -459,11 +460,23 @@ } } +static int open_port(struct inode * inode, struct file * filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static int open_mem(struct inode * inode, struct file * filp) +{ + return (capable(CAP_SYS_RAWIO) + || !(filp->f_mode & FMODE_WRITE)) ? 0 : -EPERM; +} + #define mmap_kmem mmap_mem #define zero_lseek null_lseek #define full_lseek null_lseek #define write_zero write_null #define read_full read_zero +#define open_kmem open_mem static struct file_operations mem_fops = { memory_lseek, @@ -473,7 +486,7 @@ NULL, /* mem_poll */ NULL, /* mem_ioctl */ mmap_mem, - NULL, /* no special open code */ + open_mem, NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ @@ -487,7 +500,7 @@ NULL, /* kmem_poll */ NULL, /* kmem_ioctl */ mmap_kmem, - NULL, /* no special open code */ + open_kmem, NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ @@ -515,7 +528,7 @@ NULL, /* port_poll */ NULL, /* port_ioctl */ NULL, /* port_mmap */ - NULL, /* no special open code */ + open_port, NULL, /* flush */ NULL, /* no special release code */ NULL /* fsync */ @@ -598,7 +611,7 @@ NULL /* fsync */ }; -__initfunc(int chr_dev_init(void)) +int __init chr_dev_init(void) { if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); diff -u --recursive --new-file v2.3.12/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.3.12/linux/drivers/char/misc.c Wed Jun 30 13:38:19 1999 +++ linux/drivers/char/misc.c Mon Aug 9 12:14:28 1999 @@ -28,7 +28,7 @@ * corrected by Alan Cox * * Changes for kmod (from kerneld): - Cyrus Durgin + * Cyrus Durgin */ #include @@ -43,14 +43,13 @@ #include #include #include -#ifdef CONFIG_APM -#include -#endif #include #include #include +#include "busmouse.h" + /* * Head entry for the doubly linked miscdevice list */ @@ -62,14 +61,7 @@ #define DYNAMIC_MINORS 64 /* like dynamic majors */ static unsigned char misc_minors[DYNAMIC_MINORS / 8]; -extern int bus_mouse_init(void); -extern int qpmouse_init(void); -extern int ms_bus_mouse_init(void); -extern int atixl_busmouse_init(void); -extern int amiga_mouse_init(void); -extern int atari_mouse_init(void); -extern int sun_mouse_init(void); -extern int adb_mouse_init(void); +extern int psaux_init(void); #ifdef CONFIG_SGI_NEWPORT_GFX extern void gfx_register(void); #endif @@ -86,9 +78,12 @@ extern int dsp56k_init(void); extern int nvram_init(void); extern int radio_init(void); -extern void hfmodem_init(void); extern int pc110pad_init(void); extern int pmu_device_init(void); +extern int qpmouse_init(void); +extern int ds1620_init(void); +extern int nwbutton_init(void); +extern int nwflash_init(void); static int misc_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *private) @@ -185,37 +180,19 @@ EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister); -static struct proc_dir_entry *proc_misc; +static struct proc_dir_entry *proc_misc; int __init misc_init(void) { proc_misc = create_proc_entry("misc", 0, 0); if (proc_misc) proc_misc->read_proc = misc_read_proc; -#ifdef CONFIG_BUSMOUSE +#ifdef CONFIG_MOUSE bus_mouse_init(); #endif #if defined CONFIG_82C710_MOUSE qpmouse_init(); #endif -#ifdef CONFIG_MS_BUSMOUSE - ms_bus_mouse_init(); -#endif -#ifdef CONFIG_ATIXL_BUSMOUSE - atixl_busmouse_init(); -#endif -#ifdef CONFIG_AMIGAMOUSE - amiga_mouse_init(); -#endif -#ifdef CONFIG_ATARIMOUSE - atari_mouse_init(); -#endif -#ifdef CONFIG_SUN_MOUSE - sun_mouse_init(); -#endif -#ifdef CONFIG_ADBMOUSE - adb_mouse_init(); -#endif #ifdef CONFIG_PC110_PAD pc110pad_init(); #endif @@ -240,9 +217,6 @@ #ifdef CONFIG_DTLK dtlk_init(); #endif -#ifdef CONFIG_APM - apm_bios_init(); -#endif #ifdef CONFIG_H8 h8_init(); #endif @@ -261,18 +235,12 @@ #ifdef CONFIG_ATARI_DSP56K dsp56k_init(); #endif -#ifdef CONFIG_HFMODEM - hfmodem_init(); -#endif #ifdef CONFIG_NVRAM nvram_init(); #endif #ifdef CONFIG_MISC_RADIO radio_init(); #endif -#ifdef CONFIG_HFMODEM - hfmodem_init(); -#endif #ifdef CONFIG_PMAC_PBOOK pmu_device_init(); #endif @@ -281,6 +249,15 @@ #endif #ifdef CONFIG_SGI streamable_init (); +#endif +#ifdef CONFIG_DS1620 + ds1620_init(); +#endif +#ifdef CONFIG_NWBUTTON + nwbutton_init(); +#endif +#ifdef CONFIG_NWFLASH + nwflash_init(); #endif if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { printk("unable to get major %d for misc devices\n", diff -u --recursive --new-file v2.3.12/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c --- v2.3.12/linux/drivers/char/msbusmouse.c Wed May 12 13:27:37 1999 +++ linux/drivers/char/msbusmouse.c Tue Aug 3 10:04:42 1999 @@ -27,6 +27,9 @@ * * Modularised 8-Sep-95 Philip Blundell * + * Converted to use new generic busmouse code. 5 Apr 1998 + * Russell King + * * version 0.3b */ @@ -35,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +51,9 @@ #include #include -static struct mouse_status mouse; +#include "busmouse.h" + +static int msedev; static int mouse_irq = MOUSE_IRQ; #ifdef MODULE @@ -81,35 +86,17 @@ outb(MS_MSE_COMMAND_MODE, MS_MSE_CONTROL_PORT); outb((inb(MS_MSE_DATA_PORT) & 0xdf), MS_MSE_DATA_PORT); - if (dx != 0 || dy != 0 || buttons != mouse.buttons || ((~buttons) & 0x07)) { - add_mouse_randomness((buttons << 16) + (dy << 8) + dx); - mouse.buttons = buttons; - mouse.dx += dx; - mouse.dy += dy; - mouse.ready = 1; - wake_up_interruptible(&mouse.wait); - if (mouse.fasyncptr) - kill_fasync(mouse.fasyncptr, SIGIO); - } -} - -static int fasync_mouse(int fd, struct file *filp, int on) -{ - int retval; - - retval = fasync_helper(fd, filp, on, &mouse.fasyncptr); - if (retval < 0) - return retval; - return 0; + /* why did the original have: + * if (dx != 0 || dy != 0 || buttons != mouse.buttons || + * ((~buttons) & 0x07)) + * ^^^^^^^^^^^^^^^^^^^ this? + */ + busmouse_add_movementbuttons(msedev, dx, -dy, buttons); } static int release_mouse(struct inode * inode, struct file * file) { - fasync_mouse(-1, file, 0); - if (--mouse.active) - return 0; MS_MSE_INT_OFF(); - mouse.ready = 0; free_irq(mouse_irq, NULL); MOD_DEC_USE_COUNT; return 0; @@ -117,86 +104,24 @@ static int open_mouse(struct inode * inode, struct file * file) { - if (!mouse.present) - return -EINVAL; - if (mouse.active++) - return 0; - if (request_irq(mouse_irq, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) { - mouse.active--; + if (request_irq(mouse_irq, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) return -EBUSY; - } - mouse.ready = mouse.dx = mouse.dy = 0; - mouse.buttons = 0x80; + outb(MS_MSE_START, MS_MSE_CONTROL_PORT); MOD_INC_USE_COUNT; MS_MSE_INT_ON(); return 0; } -static ssize_t write_mouse(struct file * file, - const char * buffer, size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static ssize_t read_mouse(struct file * file, - char * buffer, size_t count, loff_t *ppos) -{ - int i, dx, dy; - - if (count < 3) - return -EINVAL; - if (!mouse.ready) - return -EAGAIN; - put_user(mouse.buttons | 0x80, buffer); - dx = mouse.dx < -127 ? -127 : mouse.dx > 127 ? 127 : mouse.dx; - dy = mouse.dy < -127 ? 127 : mouse.dy > 127 ? -127 : -mouse.dy; - put_user((char)dx, buffer + 1); - put_user((char)dy, buffer + 2); - for (i = 3; i < count; i++) - put_user(0x00, buffer + i); - mouse.dx -= dx; - mouse.dy += dy; - mouse.ready = 0; - return i; -} - -static unsigned int mouse_poll(struct file *file, poll_table * wait) -{ - poll_wait(file, &mouse.wait, wait); - if (mouse.ready) - return POLLIN | POLLRDNORM; - return 0; -} - -struct file_operations ms_bus_mouse_fops = { - NULL, /* mouse_seek */ - read_mouse, - write_mouse, - NULL, /* mouse_readdir */ - mouse_poll, /* mouse_poll */ - NULL, /* mouse_ioctl */ - NULL, /* mouse_mmap */ - open_mouse, - NULL, /* flush */ - release_mouse, - NULL, - fasync_mouse, -}; - -static struct miscdevice ms_bus_mouse = { - MICROSOFT_BUSMOUSE, "msbusmouse", &ms_bus_mouse_fops +static struct busmouse msbusmouse = { + MICROSOFT_BUSMOUSE, "msbusmouse", open_mouse, release_mouse, 0 }; __initfunc(int ms_bus_mouse_init(void)) { + int present = 0; int mse_byte, i; - mouse.present = mouse.active = mouse.ready = 0; - mouse.buttons = 0x80; - mouse.dx = mouse.dy = 0; - init_waitqueue_head(&mouse.wait); - if (check_region(MS_MSE_CONTROL_PORT, 0x04)) return -ENODEV; @@ -207,32 +132,30 @@ for (i = 0; i < 4; i++) { if (inb_p(MS_MSE_SIGNATURE_PORT) == 0xde) { if (inb_p(MS_MSE_SIGNATURE_PORT) == mse_byte) - mouse.present = 1; + present = 1; else - mouse.present = 0; + present = 0; } else - mouse.present = 0; + present = 0; } } - if (mouse.present == 0) + if (present == 0) return -EIO; MS_MSE_INT_OFF(); request_region(MS_MSE_CONTROL_PORT, 0x04, "MS Busmouse"); - printk(KERN_INFO "Microsoft BusMouse detected and installed.\n"); - misc_register(&ms_bus_mouse); - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - return ms_bus_mouse_init(); + msedev = register_busmouse(&msbusmouse); + if (msedev < 0) + printk(KERN_WARNING "Unable to register msbusmouse driver.\n"); + else + printk(KERN_INFO "Microsoft BusMouse detected and installed.\n"); + return msedev < 0 ? msedev : 0; } -void cleanup_module(void) +void ms_bus_mouse_exit(void) { - misc_deregister(&ms_bus_mouse); + unregister_busmouse(msedev); release_region(MS_MSE_CONTROL_PORT, 0x04); } -#endif +module_init(ms_bus_mouse_init) +module_exit(ms_bus_mouse_exit) diff -u --recursive --new-file v2.3.12/linux/drivers/char/nvram.c linux/drivers/char/nvram.c --- v2.3.12/linux/drivers/char/nvram.c Mon Aug 24 13:14:09 1998 +++ linux/drivers/char/nvram.c Thu Aug 5 14:34:01 1999 @@ -413,7 +413,7 @@ }; -__initfunc(int nvram_init(void)) +int __init nvram_init(void) { /* First test whether the driver should init at all */ if (!CHECK_DRIVER_INIT()) @@ -479,7 +479,7 @@ #ifdef CONFIG_PROC_FS static char *floppy_types[] = { - "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M" + "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M", "3.5'' 2.88M" }; static char *gfx_types[] = { @@ -521,14 +521,14 @@ PRINT_PROC( "HD 0 type : " ); type = nvram[4] >> 4; if (type) - PRINT_PROC( " %02x\n", type == 0x0f ? nvram[11] : type ); + PRINT_PROC( "%02x\n", type == 0x0f ? nvram[11] : type ); else PRINT_PROC( "none\n" ); PRINT_PROC( "HD 1 type : " ); type = nvram[4] & 0x0f; if (type) - PRINT_PROC( " %02x\n", type == 0x0f ? nvram[12] : type ); + PRINT_PROC( "%02x\n", type == 0x0f ? nvram[12] : type ); else PRINT_PROC( "none\n" ); diff -u --recursive --new-file v2.3.12/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.3.12/linux/drivers/char/pc_keyb.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/char/pc_keyb.c Mon Aug 2 16:40:36 1999 @@ -518,10 +518,13 @@ #endif /* for "kbd-reset" cmdline param */ -void __init kbd_reset_setup(char *str, int *ints) +static int __init kbd_reset_setup(char *str) { kbd_startup_reset = 1; + return 1; } + +__setup("kbd-reset", kbd_reset_setup); #define KBD_NO_DATA (-1) /* No data */ #define KBD_BAD_DATA (-2) /* Parity or other error */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c --- v2.3.12/linux/drivers/char/pcxx.c Sat May 15 15:05:36 1999 +++ linux/drivers/char/pcxx.c Thu Aug 5 14:34:01 1999 @@ -894,7 +894,7 @@ * Driver setup function when linked into the kernel to optionally parse multible * "digi="-lines and initialize the driver at boot time. No probing. */ -__initfunc(void pcxx_setup(char *str, int *ints)) +void __init pcxx_setup(char *str, int *ints) { struct board_info board; @@ -1085,7 +1085,7 @@ * function to initialize the driver with the given parameters, which are either * the default values from this file or the parameters given at boot. */ -__initfunc(int pcxe_init(void)) +int __init pcxe_init(void) { ulong memory_seg=0, memory_size=0; int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L; diff -u --recursive --new-file v2.3.12/linux/drivers/char/planb.c linux/drivers/char/planb.c --- v2.3.12/linux/drivers/char/planb.c Sat May 15 15:05:36 1999 +++ linux/drivers/char/planb.c Thu Aug 5 14:34:01 1999 @@ -2359,7 +2359,7 @@ int init_module(void) { #else -__initfunc(int init_planbs(struct video_init *unused)) +int __init init_planbs(struct video_init *unused) { #endif int i; diff -u --recursive --new-file v2.3.12/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c --- v2.3.12/linux/drivers/char/ppdev.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/char/ppdev.c Fri Jul 30 12:28:26 1999 @@ -21,6 +21,8 @@ * CLAIM (register device first time) parport_claim_or_block * RELEASE parport_release * SETMODE set the IEEE 1284 protocol to use for read/write + * SETPHASE set the IEEE 1284 phase of a particular mode. Not to be + * confused with ioctl(fd, SETPHASER, &stun). ;-) * DATADIR data_forward / data_reverse * WDATA write_data * RDATA read_data @@ -56,7 +58,6 @@ struct pardevice * pdev; wait_queue_head_t irq_wait; atomic_t irqc; - int mode; unsigned int flags; int irqresponse; unsigned char irqctl; @@ -84,105 +85,6 @@ return -ESPIPE; } -/* This looks a bit like parport_read. The difference is that we don't - * determine the mode to use from the port data, but rather from the - * mode the driver told us to use. */ -static ssize_t do_read (struct pp_struct *pp, void *buf, size_t len) -{ - size_t (*fn) (struct parport *, void *, size_t, int); - struct parport *port = pp->pdev->port; - int addr = pp->mode & IEEE1284_ADDR; - int mode = pp->mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - - switch (mode) { - case IEEE1284_MODE_COMPAT: - /* This is a write-only mode. */ - return -EIO; - - case IEEE1284_MODE_NIBBLE: - fn = port->ops->nibble_read_data; - break; - - case IEEE1284_MODE_BYTE: - fn = port->ops->byte_read_data; - break; - - case IEEE1284_MODE_EPP: - if (addr) - fn = port->ops->epp_read_addr; - else - fn = port->ops->epp_read_data; - break; - - case IEEE1284_MODE_ECP: - case IEEE1284_MODE_ECPRLE: - fn = port->ops->ecp_read_data; - break; - - case IEEE1284_MODE_ECPSWE: - fn = parport_ieee1284_ecp_read_data; - break; - - default: - printk (KERN_DEBUG "%s: unknown mode 0x%02x\n", - pp->pdev->name, pp->mode); - return -EINVAL; - } - - return (*fn) (port, buf, len, 0); -} - -/* This looks a bit like parport_write. The difference is that we don't - * determine the mode to use from the port data, but rather from the - * mode the driver told us to use. */ -static ssize_t do_write (struct pp_struct *pp, const void *buf, size_t len) -{ - size_t (*fn) (struct parport *, const void *, size_t, int); - struct parport *port = pp->pdev->port; - int addr = pp->mode & IEEE1284_ADDR; - int mode = pp->mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - - switch (mode) { - case IEEE1284_MODE_NIBBLE: - case IEEE1284_MODE_BYTE: - /* Read-only modes. */ - return -EIO; - - case IEEE1284_MODE_COMPAT: - fn = port->ops->compat_write_data; - break; - - case IEEE1284_MODE_EPP: - if (addr) - fn = port->ops->epp_write_addr; - else - fn = port->ops->epp_write_data; - break; - - case IEEE1284_MODE_ECP: - case IEEE1284_MODE_ECPRLE: - if (addr) - fn = port->ops->ecp_write_addr; - else - fn = port->ops->ecp_write_data; - break; - - case IEEE1284_MODE_ECPSWE: - if (addr) - fn = parport_ieee1284_ecp_write_addr; - else - fn = parport_ieee1284_ecp_write_data; - break; - - default: - printk (KERN_DEBUG "%s: unknown mode 0x%02x\n", - pp->pdev->name, pp->mode); - return -EINVAL; - } - - return (*fn) (port, buf, len, 0); -} - static ssize_t pp_read (struct file * file, char * buf, size_t count, loff_t * ppos) { @@ -206,7 +108,7 @@ while (bytes_read < count) { ssize_t need = min(count - bytes_read, PP_BUFFER_SIZE); - got = do_read (pp, kbuffer, need); + got = parport_read (pp->pdev->port, kbuffer, need); if (got <= 0) { if (!bytes_read) @@ -265,7 +167,7 @@ break; } - wrote = do_write (pp, kbuffer, n); + wrote = parport_write (pp->pdev->port, kbuffer, n); if (wrote < 0) { if (!bytes_written) @@ -341,6 +243,17 @@ return 0; } +static enum ieee1284_phase init_phase (int mode) +{ + switch (mode & ~(IEEE1284_DEVICEID + | IEEE1284_ADDR)) { + case IEEE1284_MODE_NIBBLE: + case IEEE1284_MODE_BYTE: + return IEEE1284_PH_REV_IDLE; + } + return IEEE1284_PH_FWD_IDLE; +} + static int pp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -351,7 +264,6 @@ /* First handle the cases that don't take arguments. */ if (cmd == PPCLAIM) { struct ieee1284_info *info; - int first_claim = 0; if (pp->flags & PP_CLAIMED) { printk (KERN_DEBUG CHRDEV @@ -364,8 +276,6 @@ int err = register_device (minor, pp); if (err) return err; - - first_claim = 1; } parport_claim_or_block (pp->pdev); @@ -379,24 +289,8 @@ info = &pp->pdev->port->ieee1284; pp->saved_state.mode = info->mode; pp->saved_state.phase = info->phase; - if (pp->mode != info->mode) { - int phase = IEEE1284_PH_FWD_IDLE; - - if (first_claim) { - info->mode = pp->mode; - switch (pp->mode & ~(IEEE1284_DEVICEID - | IEEE1284_ADDR)) { - case IEEE1284_MODE_NIBBLE: - case IEEE1284_MODE_BYTE: - phase = IEEE1284_PH_REV_IDLE; - } - info->phase = phase; - } else { - /* Just restore the state. */ - info->mode = pp->state.mode; - info->phase = pp->state.phase; - } - } + info->mode = pp->state.mode; + info->phase = pp->state.phase; return 0; } @@ -423,7 +317,27 @@ if (copy_from_user (&mode, (int *) arg, sizeof (mode))) return -EFAULT; /* FIXME: validate mode */ - pp->mode = mode; + pp->state.mode = mode; + pp->state.phase = init_phase (mode); + + if (pp->flags & PP_CLAIMED) { + pp->pdev->port->ieee1284.mode = mode; + pp->pdev->port->ieee1284.phase = pp->state.phase; + } + + return 0; + } + + if (cmd == PPSETPHASE) { + int phase; + if (copy_from_user (&phase, (int *) arg, sizeof (phase))) + return -EFAULT; + /* FIXME: validate phase */ + pp->state.phase = phase; + + if (pp->flags & PP_CLAIMED) + pp->pdev->port->ieee1284.phase = phase; + return 0; } @@ -559,7 +473,8 @@ if (!pp) return -ENOMEM; - pp->mode = IEEE1284_MODE_COMPAT; + pp->state.mode = IEEE1284_MODE_COMPAT; + pp->state.phase = init_phase (pp->state.mode); pp->flags = 0; atomic_set (&pp->irqc, 0); init_waitqueue_head (&pp->irq_wait); diff -u --recursive --new-file v2.3.12/linux/drivers/char/ppdev.h linux/drivers/char/ppdev.h --- v2.3.12/linux/drivers/char/ppdev.h Wed Jul 28 14:47:42 1999 +++ linux/drivers/char/ppdev.h Fri Jul 30 12:28:26 1999 @@ -69,3 +69,6 @@ /* Clear (and return) interrupt count. */ #define PPCLRIRQ _IOR(PP_IOCTL, 0x93, int) + +/* Set the IEEE 1284 phase that we're in (e.g. IEEE1284_PH_FWD_IDLE) */ +#define PPSETPHASE _IOW(PP_IOCTL, 0x94, int) diff -u --recursive --new-file v2.3.12/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.3.12/linux/drivers/char/pty.c Wed May 12 08:41:15 1999 +++ linux/drivers/char/pty.c Thu Aug 5 14:34:01 1999 @@ -334,7 +334,7 @@ tty->termios->c_cflag |= (CS8 | CREAD); } -__initfunc(int pty_init(void)) +int __init pty_init(void) { int i; diff -u --recursive --new-file v2.3.12/linux/drivers/char/q40_keyb.c linux/drivers/char/q40_keyb.c --- v2.3.12/linux/drivers/char/q40_keyb.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/q40_keyb.c Mon Aug 9 12:32:28 1999 @@ -0,0 +1,471 @@ +/* + * linux/drivers/char/q40_keyb.c + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Some configuration switches are present in the include file... */ + +#define KBD_REPORT_ERR + +/* Simple translation table for the SysRq keys */ + +#define SYSRQ_KEY 0x54 + +#ifdef CONFIG_MAGIC_SYSRQ +unsigned char q40kbd_sysrq_xlate[128] = + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/"; /* 0x60 - 0x6f */ +#endif + +/* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/ +/* 0x00 means not a valid entry or no conversion known */ + +unsigned static char q40cl[256] = +{/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ + 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00, /* 0x00 - 0x0f */ + 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00, /* 0x10 - 0x1f */ + 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00, /* 0x20 - 0x2f 'f' is at 0x2b, what is 0x28 ???*/ + 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00, /* 0x30 - 0x3f */ + 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00, /* 0x40 - 0x4f */ + 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00, /* 0x50 - 0x5f*/ + 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f */ + 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00, /* 0x70 - 0x7f */ + 0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f 0x84/0x37 is SySrq*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf0 - 0xff */ +}; + +/* another table, AT 0xe0 codes to PC 0xe0 codes, + 0xff special entry for SysRq - DROPPED right now */ +static unsigned char q40ecl[]= +{/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x00 - 0x0f*/ + 0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x10 - 0x1f */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x20 - 0x2f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x30 - 0x3f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00, /* 0x40 - 0x4f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00, /* 0x50 - 0x5f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, /* 0x60 - 0x6f*/ + 0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00, /* 0x70 - 0x7f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x80 - 0x8f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x90 - 0x9f*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa0 - 0xaf*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xb0 - 0xbf*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 - 0xcf*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 - 0xdf*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xe0 - 0xef*/ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 0xf0 - 0xff*/ +}; + + +spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED; + + +/* + * Translation of escaped scancodes to keycodes. + * This is now user-settable. + * The keycodes 1-88,96-111,119 are fairly standard, and + * should probably not be changed - changing might confuse X. + * X also interprets scancode 0x5d (KEY_Begin). + * + * For 1-88 keycode equals scancode. + */ + +#define E0_KPENTER 96 +#define E0_RCTRL 97 +#define E0_KPSLASH 98 +#define E0_PRSCR 99 +#define E0_RALT 100 +#define E0_BREAK 101 /* (control-pause) */ +#define E0_HOME 102 +#define E0_UP 103 +#define E0_PGUP 104 +#define E0_LEFT 105 +#define E0_RIGHT 106 +#define E0_END 107 +#define E0_DOWN 108 +#define E0_PGDN 109 +#define E0_INS 110 +#define E0_DEL 111 + +#define E1_PAUSE 119 + +/* + * The keycodes below are randomly located in 89-95,112-118,120-127. + * They could be thrown away (and all occurrences below replaced by 0), + * but that would force many users to use the `setkeycodes' utility, where + * they needed not before. It does not matter that there are duplicates, as + * long as no duplication occurs for any single keyboard. + */ +#define SC_LIM 89 + +#define FOCUS_PF1 85 /* actual code! */ +#define FOCUS_PF2 89 +#define FOCUS_PF3 90 +#define FOCUS_PF4 91 +#define FOCUS_PF5 92 +#define FOCUS_PF6 93 +#define FOCUS_PF7 94 +#define FOCUS_PF8 95 +#define FOCUS_PF9 120 +#define FOCUS_PF10 121 +#define FOCUS_PF11 122 +#define FOCUS_PF12 123 + +#define JAP_86 124 +/* tfj@olivia.ping.dk: + * The four keys are located over the numeric keypad, and are + * labelled A1-A4. It's an rc930 keyboard, from + * Regnecentralen/RC International, Now ICL. + * Scancodes: 59, 5a, 5b, 5c. + */ +#define RGN1 124 +#define RGN2 125 +#define RGN3 126 +#define RGN4 127 + +static unsigned char high_keys[128 - SC_LIM] = { + RGN1, RGN2, RGN3, RGN4, 0, 0, 0, /* 0x59-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12, /* 0x68-0x6f */ + 0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3, /* 0x70-0x77 */ + FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7, /* 0x78-0x7b */ + FOCUS_PF8, JAP_86, FOCUS_PF10, 0 /* 0x7c-0x7f */ +}; + +/* BTC */ +#define E0_MACRO 112 +/* LK450 */ +#define E0_F13 113 +#define E0_F14 114 +#define E0_HELP 115 +#define E0_DO 116 +#define E0_F17 117 +#define E0_KPMINPLUS 118 +/* + * My OmniKey generates e0 4c for the "OMNI" key and the + * right alt key does nada. [kkoller@nyx10.cs.du.edu] + */ +#define E0_OK 124 +/* + * New microsoft keyboard is rumoured to have + * e0 5b (left window button), e0 5c (right window button), + * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] + * [or: Windows_L, Windows_R, TaskMan] + */ +#define E0_MSLW 125 +#define E0_MSRW 126 +#define E0_MSTM 127 + +/* this can be changed using setkeys : */ +static unsigned char e0_keys[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ + 0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0, /* 0x18-0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */ + 0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR, /* 0x30-0x37 */ + E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP, /* 0x38-0x3f */ + E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME, /* 0x40-0x47 */ + E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */ + E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0, /* 0x50-0x57 */ + 0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0, /* 0x58-0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ + 0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ + 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ +}; + +static unsigned int prev_scancode = 0; /* remember E0, E1 */ + +int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode) +{ + if (scancode < SC_LIM || scancode > 255 || keycode > 127) + return -EINVAL; + if (scancode < 128) + high_keys[scancode - SC_LIM] = keycode; + else + e0_keys[scancode - 128] = keycode; + return 0; +} + +int q40kbd_getkeycode(unsigned int scancode) +{ + return + (scancode < SC_LIM || scancode > 255) ? -EINVAL : + (scancode < 128) ? high_keys[scancode - SC_LIM] : + e0_keys[scancode - 128]; +} + + +#define disable_keyboard() +#define enable_keyboard() + + + +int q40kbd_pretranslate(unsigned char scancode, char raw_mode) +{ + if (scancode == 0xff) { + /* in scancode mode 1, my ESC key generates 0xff */ + /* the calculator keys on a FOCUS 9000 generate 0xff */ +#ifndef KBD_IS_FOCUS_9000 +#ifdef KBD_REPORT_ERR + if (!raw_mode) + printk(KERN_DEBUG "Keyboard error\n"); +#endif +#endif + prev_scancode = 0; + return 0; + } + + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; + return 0; + } + return 1; +} + +int q40kbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) +{ + /*printk("translate ...\n");*/ + if (prev_scancode) { + /* + * usually it will be 0xe0, but a Pause key generates + * e1 1d 45 e1 9d c5 when pressed, and nothing when released + */ + if (prev_scancode != 0xe0) { + if (prev_scancode == 0xe1 && scancode == 0x1d) { + prev_scancode = 0x100; + return 0; + } else if (prev_scancode == 0x100 && scancode == 0x45) { + *keycode = E1_PAUSE; + prev_scancode = 0; + } else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown e1 escape sequence\n"); +#endif + prev_scancode = 0; + return 0; + } + } else { + prev_scancode = 0; + /* + * The keyboard maintains its own internal caps lock and + * num lock statuses. In caps lock mode E0 AA precedes make + * code and E0 2A follows break code. In num lock mode, + * E0 2A precedes make code and E0 AA follows break code. + * We do our own book-keeping, so we will just ignore these. + */ + /* + * For my keyboard there is no caps lock mode, but there are + * both Shift-L and Shift-R modes. The former mode generates + * E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs. + * So, we should also ignore the latter. - aeb@cwi.nl + */ + if (scancode == 0x2a || scancode == 0x36) + return 0; + + if (e0_keys[scancode]) + *keycode = e0_keys[scancode]; + else { +#ifdef KBD_REPORT_UNKN + if (!raw_mode) + printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n", + scancode); +#endif + return 0; + } + } + } else if (scancode >= SC_LIM) { + /* This happens with the FOCUS 9000 keyboard + Its keys PF1..PF12 are reported to generate + 55 73 77 78 79 7a 7b 7c 74 7e 6d 6f + Moreover, unless repeated, they do not generate + key-down events, so we have to zero up_flag below */ + /* Also, Japanese 86/106 keyboards are reported to + generate 0x73 and 0x7d for \ - and \ | respectively. */ + /* Also, some Brazilian keyboard is reported to produce + 0x73 and 0x7e for \ ? and KP-dot, respectively. */ + + *keycode = high_keys[scancode - SC_LIM]; + + if (!*keycode) { + if (!raw_mode) { +#ifdef KBD_REPORT_UNKN + printk(KERN_INFO "keyboard: unrecognized scancode (%02x)" + " - ignored\n", scancode); +#endif + } + return 0; + } + } else + *keycode = scancode; + return 1; +} + +char q40kbd_unexpected_up(unsigned char keycode) +{ + /* unexpected, but this can happen: maybe this was a key release for a + FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ + if (keycode >= SC_LIM || keycode == 85) + return 0; + else + return 0200; +} + +static int keyup=0; +static int qprev=0; + +static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + unsigned char status; + + disable_keyboard(); + spin_lock_irqsave(&kbd_controller_lock, flags); + kbd_pt_regs = regs; + + status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG); + if (status ) + { + unsigned char scancode,qcode; + + qcode = master_inb(KEYCODE_REG); + + if (qcode != 0xf0) + { + if (qcode == 0xe0) + { + qprev=0xe0; + handle_scancode(qprev); + goto exit; + } + + scancode=qprev ? q40ecl[qcode] : q40cl[qcode]; +#if 0 +/* next line is last resort to hanlde some oddities */ + if (qprev && !scancode) scancode=q40cl[qcode]; +#endif + qprev=0; + if (!scancode) + { + printk("unknown scancode %x\n",qcode); + goto exit; + } + if (scancode==0xff) /* SySrq */ + scancode=SYSRQ_KEY; + + handle_scancode(scancode | (keyup ? 0200 : 0)); + keyup=0; + mark_bh(KEYBOARD_BH); + + } + else + keyup=1; + } +exit: + spin_unlock_irqrestore(&kbd_controller_lock, flags); + master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */ + enable_keyboard(); +} + + + + +#ifdef CONFIG_MAGIC_SYSRQ +int kbd_is_sysrq(unsigned char keycode) +{ + return( keycode == SYSRQ_KEY ); +} +#endif /* CONFIG_MAGIC_SYSRQ */ + + + + +#define KBD_NO_DATA (-1) /* No data */ +#define KBD_BAD_DATA (-2) /* Parity or other error */ + +static int __init kbd_read_input(void) +{ + int retval = KBD_NO_DATA; + unsigned char status; + + status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG); + if (status) { + unsigned char data = master_inb(KEYCODE_REG); + + retval = data; + master_outb(-1,KEYBOARD_UNLOCK_REG); + } + return retval; +} + +extern void q40kbd_leds(unsigned char leds) +{ /* nothing can be done */ } + +static void __init kbd_clear_input(void) +{ + int maxread = 100; /* Random number */ + + do { + if (kbd_read_input() == KBD_NO_DATA) + break; + } while (--maxread); +} + + +void __init q40kbd_init_hw(void) +{ +#if 0 + /* Get the keyboard controller registers (incomplete decode) */ + request_region(0x60, 16, "keyboard"); +#endif + /* Flush any pending input. */ + kbd_clear_input(); + + /* Ok, finally allocate the IRQ, and off we go.. */ + request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL); + master_outb(-1,KEYBOARD_UNLOCK_REG); + master_outb(1,KEY_IRQ_ENABLE_REG); + +} + diff -u --recursive --new-file v2.3.12/linux/drivers/char/raw.c linux/drivers/char/raw.c --- v2.3.12/linux/drivers/char/raw.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/char/raw.c Mon Aug 9 12:28:41 1999 @@ -13,6 +13,7 @@ #include #include #include +#include #include #define dprintk(x...) @@ -233,6 +234,15 @@ } if (command == RAW_SETBIND) { + /* + * This is like making block devices, so demand the + * same capability + */ + if (!capable(CAP_SYS_ADMIN)) { + err = -EPERM; + break; + } + /* * For now, we don't need to check that the underlying * block device is present or not: we can do that when diff -u --recursive --new-file v2.3.12/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c --- v2.3.12/linux/drivers/char/riscom8.c Wed May 12 13:27:37 1999 +++ linux/drivers/char/riscom8.c Thu Aug 5 14:34:01 1999 @@ -232,7 +232,7 @@ } /* Reset and setup CD180 chip */ -__initfunc(static void rc_init_CD180(struct riscom_board const * bp)) +static void __init rc_init_CD180(struct riscom_board const * bp) { unsigned long flags; @@ -257,7 +257,7 @@ } /* Main probing routine, also sets irq. */ -__initfunc(static int rc_probe(struct riscom_board *bp)) +static int __init rc_probe(struct riscom_board *bp) { unsigned char val1, val2; int irqs = 0; @@ -1820,7 +1820,7 @@ * addresses in this case. * */ -__initfunc(void riscom8_setup(char *str, int * ints)) +void __init riscom8_setup(char *str, int * ints) { int i; @@ -1836,7 +1836,7 @@ /* * This routine must be called by kernel at boot time */ -__initfunc(int riscom8_init(void)) +int __init riscom8_init(void) { int i; int found = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/char/rocket.c linux/drivers/char/rocket.c --- v2.3.12/linux/drivers/char/rocket.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/rocket.c Thu Aug 5 15:04:52 1999 @@ -1958,7 +1958,7 @@ } #endif -__initfunc(int register_PCI(int i, unsigned int bus, unsigned int device_fn)) +int __init register_PCI(int i, unsigned int bus, unsigned int device_fn) { int num_aiops, aiop, max_num_aiops, num_chan, chan; unsigned int aiopio[MAX_AIOPS_PER_BOARD]; @@ -1973,15 +1973,7 @@ if (!dev) return 0; -#if (LINUX_VERSION_CODE >= 0x020163) /* 2.1.99 */ - rcktpt_io_addr[i] = dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; -#else - ret = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, - &port); - if (ret) - return 0; - rcktpt_io_addr[i] = port & PCI_BASE_ADDRESS_IO_MASK; -#endif + rcktpt_io_addr[i] = dev->resource[0].start; switch(dev->device) { case PCI_DEVICE_ID_RP4QUAD: str = "Quadcable"; @@ -2047,7 +2039,7 @@ return(1); } -__initfunc(static int init_PCI(int boards_found)) +static int __init init_PCI(int boards_found) { unsigned char bus, device_fn; int i, count = 0; @@ -2102,7 +2094,7 @@ } #endif -__initfunc(static int init_ISA(int i, int *reserved_controller)) +static int __init init_ISA(int i, int *reserved_controller) { int num_aiops, num_chan; int aiop, chan; @@ -2154,7 +2146,7 @@ /* * The module "startup" routine; it's run when the module is loaded. */ -__initfunc(int rp_init(void)) +int __init rp_init(void) { int i, retval, pci_boards_found, isa_boards_found; int reserved_controller = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.3.12/linux/drivers/char/rtc.c Wed Jun 9 14:44:25 1999 +++ linux/drivers/char/rtc.c Thu Aug 5 14:34:02 1999 @@ -524,7 +524,7 @@ &rtc_fops }; -__initfunc(int rtc_init(void)) +int __init rtc_init(void) { unsigned long flags; #ifdef __alpha__ diff -u --recursive --new-file v2.3.12/linux/drivers/char/softdog.c linux/drivers/char/softdog.c --- v2.3.12/linux/drivers/char/softdog.c Wed Jun 2 11:29:13 1999 +++ linux/drivers/char/softdog.c Thu Aug 5 14:34:02 1999 @@ -178,7 +178,7 @@ &softdog_fops }; -__initfunc(void watchdog_init(void)) +void __init watchdog_init(void) { misc_register(&softdog_miscdev); init_timer(&watchdog_ticktock); diff -u --recursive --new-file v2.3.12/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.3.12/linux/drivers/char/stallion.c Wed May 26 09:31:45 1999 +++ linux/drivers/char/stallion.c Thu Aug 5 14:34:02 1999 @@ -2280,7 +2280,7 @@ * interrupt across multiple boards. */ -__initfunc(static int stl_mapirq(int irq, char *name)) +static int __init stl_mapirq(int irq, char *name) { int rc, i; @@ -2311,7 +2311,7 @@ * Initialize all the ports on a panel. */ -__initfunc(static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)) +static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) { stlport_t *portp; int chipmask, i; @@ -2700,7 +2700,7 @@ * since the initial search and setup is very different. */ -__initfunc(static int stl_brdinit(stlbrd_t *brdp)) +static int __init stl_brdinit(stlbrd_t *brdp) { int i; @@ -3204,7 +3204,7 @@ /*****************************************************************************/ -__initfunc(int stl_init(void)) +int __init stl_init(void) { printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); diff -u --recursive --new-file v2.3.12/linux/drivers/char/sx.c linux/drivers/char/sx.c --- v2.3.12/linux/drivers/char/sx.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/sx.c Thu Aug 5 14:47:44 1999 @@ -0,0 +1,2684 @@ + +/* sx.c -- driver for the Specialix SX series cards. + * + * This driver will also support the older SI, and XIO cards. + * + * + * (C) 1998 R.E.Wolff@BitWizard.nl + * + * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous + * version of this driver. Some fragments may have been copied. (none + * yet :-) + * + * Specialix pays for the development and support of this driver. + * Please DO contact support@specialix.co.uk if you require + * support. But please read the documentation (sx.txt) first. + * + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * Revision history: + * $Log: sx.c,v $ + * Revision 1.26 1999/08/05 15:22:14 wolff + * - Port to 2.3.x + * - Reformatted to Linus' liking. + * + * Revision 1.25 1999/07/30 14:24:08 wolff + * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0). + * + * Revision 1.24 1999/07/28 09:41:52 wolff + * - I noticed the remark about use-count straying in sx.txt. I checked + * sx_open, and found a few places where that could happen. I hope it's + * fixed now. + * + * Revision 1.23 1999/07/28 08:56:06 wolff + * - Fixed crash when sx_firmware run twice. + * - Added sx_slowpoll as a module parameter (I guess nobody really wanted + * to change it from the default... ) + * - Fixed a stupid editing problem I introduced in 1.22. + * - Fixed dropping characters on a termios change. + * + * Revision 1.22 1999/07/26 21:01:43 wolff + * Russell Brown noticed that I had overlooked 4 out of six modem control + * signals in sx_getsignals. Ooops. + * + * Revision 1.21 1999/07/23 09:11:33 wolff + * I forgot to free dynamically allocated memory when the driver is unloaded. + * + * Revision 1.20 1999/07/20 06:25:26 wolff + * The "closing wait" wasn't honoured. Thanks to James Griffiths for + * reporting this. + * + * Revision 1.19 1999/07/11 08:59:59 wolff + * Fixed an oops in close, when an open was pending. Changed the memtest + * a bit. Should also test the board in word-mode, however my card fails the + * memtest then. I still have to figure out what is wrong... + * + * Revision 1.18 1999/06/10 09:38:42 wolff + * Changed the format of the firmware revision from %04x to %x.%02x . + * + * Revision 1.17 1999/06/04 09:44:35 wolff + * fixed problem: reference to pci stuff when config_pci was off... + * Thanks to Jorge Novo for noticing this. + * + * Revision 1.16 1999/06/02 08:30:15 wolff + * added/removed the workaround for the DCD bug in the Firmware. + * A bit more debugging code to locate that... + * + * Revision 1.15 1999/06/01 11:35:30 wolff + * when DCD is left low (floating?), on TA's the firmware first tells us + * that DCD is high, but after a short while suddenly comes to the + * conclusion that it is low. All this would be fine, if it weren't that + * Unix requires us to send a "hangup" signal in that case. This usually + * all happens BEFORE the program has had a chance to ioctl the device + * into clocal mode.. + * + * Revision 1.14 1999/05/25 11:18:59 wolff + * Added PCI-fix. + * Added checks for return code of sx_sendcommand. + * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...) + * + * Revision 1.13 1999/04/29 15:18:01 wolff + * Fixed an "oops" that showed on SuSE 6.0 systems. + * Activate DTR again after stty 0. + * + * Revision 1.12 1999/04/29 07:49:52 wolff + * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming + * the connection would be dropped anyway. That is not always the case, + * and confuses people). + * Told the card to always monitor the modem signals. + * Added support for dynamic gs_debug adjustments. + * Now tells the rest of the system the number of ports. + * + * Revision 1.11 1999/04/24 11:11:30 wolff + * Fixed two stupid typos in the memory test. + * + * Revision 1.10 1999/04/24 10:53:39 wolff + * Added some of Christian's suggestions. + * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the + * card to send the signal to the process.....) + * + * Revision 1.9 1999/04/23 07:26:38 wolff + * Included Christian Lademann's 2.0 compile-warning fixes and interrupt + * assignment redesign. + * Cleanup of some other stuff. + * + * Revision 1.8 1999/04/16 13:05:30 wolff + * fixed a DCD change unnoticed bug. + * + * Revision 1.7 1999/04/14 22:19:51 wolff + * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!) + * + * Revision 1.6 1999/04/13 18:40:20 wolff + * changed misc-minor to 161, as assigned by HPA. + * + * Revision 1.5 1999/04/13 15:12:25 wolff + * Fixed use-count leak when "hangup" occurred. + * Added workaround for a stupid-PCIBIOS bug. + * + * + * Revision 1.4 1999/04/01 22:47:40 wolff + * Fixed < 1M linux-2.0 problem. + * (vremap isn't compatible with ioremap in that case) + * + * Revision 1.3 1999/03/31 13:45:45 wolff + * Firmware loading is now done through a separate IOCTL. + * + * Revision 1.2 1999/03/28 12:22:29 wolff + * rcs cleanup + * + * Revision 1.1 1999/03/28 12:10:34 wolff + * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). + * + * Revision 0.12 1999/03/28 09:20:10 wolff + * Fixed problem in 0.11, continueing cleanup. + * + * Revision 0.11 1999/03/28 08:46:44 wolff + * cleanup. Not good. + * + * Revision 0.10 1999/03/28 08:09:43 wolff + * Fixed loosing characters on close. + * + * Revision 0.9 1999/03/21 22:52:01 wolff + * Ported back to 2.2.... (minor things) + * + * Revision 0.8 1999/03/21 22:40:33 wolff + * Port to 2.0 + * + * Revision 0.7 1999/03/21 19:06:34 wolff + * Fixed hangup processing. + * + * Revision 0.6 1999/02/05 08:45:14 wolff + * fixed real_raw problems. Inclusion into kernel imminent. + * + * Revision 0.5 1998/12/21 23:51:06 wolff + * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it + * shouldn't have. THATs why I want to have transmit interrupts even when + * the buffer is empty. + * + * Revision 0.4 1998/12/17 09:34:46 wolff + * PPP works. ioctl works. Basically works! + * + * Revision 0.3 1998/12/15 13:05:18 wolff + * It works! Wow! Gotta start implementing IOCTL and stuff.... + * + * Revision 0.2 1998/12/01 08:33:53 wolff + * moved over to 2.1.130 + * + * Revision 0.1 1998/11/03 21:23:51 wolff + * Initial revision. Detects SX card. + * + * */ + + +#define RCS_ID "$Id: sx.c,v 1.26 1999/08/05 15:22:14 wolff Exp $" +#define RCS_REV "$Revision: 1.26 $" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The 3.0.0 version of sxboards/sxwindow.h uses BYTE and WORD.... */ +#define BYTE u8 +#define WORD u16 + +/* .... but the 3.0.4 version uses _u8 and _u16. */ +#define _u8 u8 +#define _u16 u16 + +#include "sxboards.h" +#include "sxwindow.h" + + +/* I don't think that this driver can handle more than 256 ports on + one machine. You'll have to increase the number of boards in sx.h + if you want more than 4 boards. */ + + +/* ************************************************************** */ +/* * This section can be removed when 2.0 becomes outdated.... * */ +/* ************************************************************** */ + + +#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */ +#define TWO_ZERO +#else +#if LINUX_VERSION_CODE < 0x020200 /* less than 2.2.x */ +#warning "Please use a 2.2.x kernel. " +#else +#if LINUX_VERSION_CODE < 0x020300 /* less than 2.3.x */ +#define TWO_TWO +#else +#define TWO_THREE +#endif +#endif +#endif + +#ifdef TWO_ZERO + +/* Here is the section that makes the 2.2 compatible driver source + work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, + and provide for compatibility stuff here if possible. */ + +#include + +#define Get_user(a,b) a = get_user(b) +#define Put_user(a,b) 0,put_user(a,b) +#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) + +static inline int copy_from_user(void *to,const void *from, int c) +{ + memcpy_fromfs(to, from, c); + return 0; +} + +#define pci_present pcibios_present +#define pci_read_config_word pcibios_read_config_word +#define pci_read_config_dword pcibios_read_config_dword + +static inline unsigned char get_irq (unsigned char bus, unsigned char fn) +{ + unsigned char t; + pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t); + return t; +} + +static inline void *ioremap(unsigned long base, long length) +{ + if (base < 0x100000) return (void *)base; + return vremap (base, length); +} + +#define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x)) + +#define capable(x) suser() + +#define queue_task queue_task_irq_off +#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) +#define signal_pending(current) (current->signal & ~current->blocked) +#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) +#define time_after(t1,t2) (((long)t1-t2) > 0) + + +#define test_and_set_bit(nr, addr) set_bit(nr, addr) +#define test_and_clear_bit(nr, addr) clear_bit(nr, addr) + +/* Not yet implemented on 2.0 */ +#define ASYNC_SPD_SHI -1 +#define ASYNC_SPD_WARP -1 + + +/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it + to the "name" field that does exist. As long as the assignments are + done in the right order, there is nothing to worry about. */ +#define driver_name name + +/* Should be in a header somewhere. They are in tty.h on 2.2 */ +#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */ +#define TTY_HW_COOK_IN 15 /* in hardware - output and input */ + +/* The return type of a "close" routine. */ +#define INT void +#define NO_ERROR /* Nothing */ + +#else + +/* The 2.2.x compatibility section. */ +#include + + +#define Get_user(a,b) get_user(a,b) +#define Put_user(a,b) put_user(a,b) +#define get_irq(pdev) pdev->irq + +#define INT int +#define NO_ERROR 0 + +#define my_iounmap(x,b) (iounmap((char *)(b))) + +#endif + +#ifndef TWO_THREE +/* These are new in 2.3. The source now uses 2.3 syntax, and here is + the compatibility define... */ +#define wait_queue_head_t struct wait_queue * +#define DECLARE_MUTEX(name) struct semaphore name = MUTEX +#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL } + +#endif + + + +#include "generic_serial.h" +#include "sx.h" + + +/* ************************************************************** */ +/* * End of compatibility section.. * */ +/* ************************************************************** */ + + + +/* Why the hell am I defining these here? */ +#define SX_TYPE_NORMAL 1 +#define SX_TYPE_CALLOUT 2 + +#ifndef SX_NORMAL_MAJOR +/* This allows overriding on the compiler commandline, or in a "major.h" + include or something like that */ +#define SX_NORMAL_MAJOR 32 +#define SX_CALLOUT_MAJOR 33 +#endif + +#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 +#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 +#endif + + + +/* Configurable options: + (Don't be too sure that it'll work if you toggle them) */ + +/* Am I paranoid or not ? ;-) */ +#undef SX_PARANOIA_CHECK + + +/* 20 -> 2000 per second. The card should rate-limit interrupts at 100 + Hz, but it is user configurable. I don't recommend going above 1000 + Hz. The interrupt ratelimit might trigger if the interrupt is + shared with a very active other device. */ +#define IRQ_RATE_LIMIT 20 + +/* Sharing interrupts is possible now. If the other device wants more + than 2000 interrupts per second, we'd gracefully decline further + interrupts. That's not what we want. On the other hand, if the + other device interrupts 2000 times a second, don't use the SX + interrupt. Use polling. */ +#undef IRQ_RATE_LIMIT + + +#if 0 +/* Not implemented */ +/* + * The following defines are mostly for testing purposes. But if you need + * some nice reporting in your syslog, you can define them also. + */ +#define SX_REPORT_FIFO +#define SX_REPORT_OVERRUN +#endif + + +/* Function prototypes */ +static void sx_disable_tx_interrupts (void * ptr); +static void sx_enable_tx_interrupts (void * ptr); +static void sx_disable_rx_interrupts (void * ptr); +static void sx_enable_rx_interrupts (void * ptr); +static int sx_get_CD (void * ptr); +static void sx_shutdown_port (void * ptr); +static void sx_set_real_termios (void *ptr); +static void sx_hungup (void *ptr); +static void sx_close (void *ptr); +static int sx_chars_in_buffer (void * ptr); +static int sx_init_board (struct sx_board *board); +static int sx_init_portstructs (int nboards, int nports); +static int sx_fw_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int sx_fw_open(struct inode *inode, struct file *filp); +static INT sx_fw_release(struct inode *inode, struct file *filp); +static int sx_init_drivers(void); +void my_hd (unsigned char *addr, int len); + + + +static struct tty_driver sx_driver, sx_callout_driver; + +static struct tty_struct * sx_table[SX_NPORTS] = { NULL, }; +static struct termios ** sx_termios; +static struct termios ** sx_termios_locked; + +struct sx_board boards[SX_NBOARDS]; +struct sx_port *sx_ports; +int sx_refcount; +int sx_initialized = 0; +int sx_nports = 0; +int sx_debug = 0; + + +/* You can have the driver poll your card. + - Set sx_poll to 1 to poll every timer tick (10ms on Intel). + This is used when the card cannot use an interrupt for some reason. + + - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If + the driver misses an interrupt (report this if it DOES happen to you!) + everything will continue to work.... + */ +int sx_poll = 1; +int sx_slowpoll = 0; + +/* The card limits the number of interrupts per second. + At 115k2 "100" should be sufficient. + If you're using higher baudrates, you can increase this... + */ + +int sx_maxints = 100; + +/* These are the only open spaces in my computer. Yours may have more + or less.... */ +int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000}; +int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000}; + +#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int)) +#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int)) + + +/* Set the mask to all-ones. This alas, only supports 32 interrupts. + Some architectures may need more. */ +int sx_irqmask = -1; + +#ifndef TWO_ZERO +#ifdef MODULE +MODULE_PARM(sx_poll, "i"); +MODULE_PARM(sx_slowpoll, "i"); +MODULE_PARM(sx_maxints, "i"); +MODULE_PARM(sx_debug, "i"); +MODULE_PARM(sx_irqmask, "i"); +#endif +#endif + +static struct real_driver sx_real_driver = { + sx_disable_tx_interrupts, + sx_enable_tx_interrupts, + sx_disable_rx_interrupts, + sx_enable_rx_interrupts, + sx_get_CD, + sx_shutdown_port, + sx_set_real_termios, + sx_chars_in_buffer, + sx_close, + sx_hungup, + NULL +}; + + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ +#define DEBUG + + +#ifdef DEBUG +#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) +#else +#define sx_dprintk(f, str...) /* nothing */ +#endif + + + +#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter " __FUNCTION__ "\n") +#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit " __FUNCTION__ "\n") + +#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter " __FUNCTION__ \ + "(port %d)\n", port->line) + + + + +/* + * Firmware loader driver specific routines + * + */ + +static struct file_operations sx_fw_fops = { + NULL, /* lseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* select */ + sx_fw_ioctl, + NULL, /* mmap */ + sx_fw_open, +#ifndef TWO_ZERO + NULL, /* flush */ +#endif + sx_fw_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ +}; + +struct miscdevice sx_fw_device = { + SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops +}; + + + + + +#ifdef SX_PARANOIA_CHECK + +/* This doesn't work. Who's paranoid around here? Not me! */ + +static inline int sx_paranoia_check(struct sx_port const * port, + kdev_t device, const char *routine) +{ + + static const char *badmagic = + KERN_ERR "sx: Warning: bad sx port magic number for device %s in %s\n"; + static const char *badinfo = + KERN_ERR "sx: Warning: null sx port for device %s in %s\n"; + + if (!port) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (port->magic != SX_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } + + return 0; +} +#else +#define sx_paranoia_check(a,b,c) 0 +#endif + +/* The timeouts. First try 30 times as fast as possible. Then give + the card some time to breathe between accesses. (Otherwise the + processor on the card might not be able to access its OWN bus... */ + +#define TIMEOUT_1 30 +#define TIMEOUT_2 1000000 + + +/* This needs redoing for Alpha -- REW -- Done. */ + +inline void write_sx_byte (struct sx_board *board, int offset, u8 byte) +{ + writeb (byte, board->base+offset); +} + +inline u8 read_sx_byte (struct sx_board *board, int offset) +{ + return readb (board->base+offset); +} + + +inline void write_sx_word (struct sx_board *board, int offset, u16 word) +{ + writew (word, board->base+offset); +} + +inline u16 read_sx_word (struct sx_board *board, int offset) +{ + return readw (board->base + offset); +} + + +int sx_busy_wait_eq (struct sx_board *board, + int offset, + int mask, + int correctval) +{ + int i; + + func_enter (); + + for (i=0; i < TIMEOUT_1 > 0;i++) + if ((read_sx_byte (board, offset) & mask) == correctval) { + func_exit (); + return 1; + } + + for (i=0; i < TIMEOUT_2 > 0;i++) { + if ((read_sx_byte (board, offset) & mask) == correctval) { + func_exit (); + return 1; + } + udelay (1); + } + + func_exit (); + return 0; +} + + +int sx_busy_wait_neq (struct sx_board *board, + int offset, + int mask, + int badval) +{ + int i; + + func_enter (); + + for (i=0; i < TIMEOUT_1 > 0;i++) + if ((read_sx_byte (board, offset) & mask) != badval) { + func_exit (); + return 1; + } + + for (i=0; i < TIMEOUT_2 > 0;i++) { + if ((read_sx_byte (board, offset) & mask) != badval) { + func_exit (); + return 1; + } + udelay (1); + } + + func_exit (); + return 0; +} + + + +/* 5.6.4 of 6210028 r2.3 */ +int sx_reset (struct sx_board *board) +{ + func_enter (); + + if (IS_SX_BOARD (board)) { + + write_sx_byte (board, SX_CONFIG, 0); + write_sx_byte (board, SX_RESET, 1); /* Value doesn't matter */ + + if (!sx_busy_wait_eq (board, SX_RESET_STATUS, 1, 0)) { + printk (KERN_INFO "sx: Card doesn't respond to reset....\n"); + return 0; + } + } else { + /* Gory details of the SI/ISA board */ + write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET); + write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); + write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); + write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); + write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte (board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); + } + + func_exit (); + return 1; +} + + +/* This doesn't work on machines where "NULL" isn't 0 */ +/* If you have one of those, someone will need to write + the equivalent of this, which will amount to about 3 lines. I don't + want to complicate this right now. -- REW + (See, I do write comments every now and then :-) */ +#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) + + +#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) +#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) +#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) + + +#define sx_write_channel_byte(port, elem, val) \ + write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) + +#define sx_read_channel_byte(port, elem) \ + read_sx_byte (port->board, CHAN_OFFSET (port, elem)) + +#define sx_write_channel_word(port, elem, val) \ + write_sx_word (port->board, CHAN_OFFSET (port, elem), val) + +#define sx_read_channel_word(port, elem) \ + read_sx_word (port->board, CHAN_OFFSET (port, elem)) + + +#define sx_write_module_byte(board, addr, elem, val) \ + write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) + +#define sx_read_module_byte(board, addr, elem) \ + read_sx_byte (board, MODU_OFFSET (board, addr, elem)) + +#define sx_write_module_word(board, addr, elem, val) \ + write_sx_word (board, MODU_OFFSET (board, addr, elem), val) + +#define sx_read_module_word(board, addr, elem) \ + read_sx_word (board, MODU_OFFSET (board, addr, elem)) + + +#define sx_write_board_byte(board, elem, val) \ + write_sx_byte (board, BRD_OFFSET (board, elem), val) + +#define sx_read_board_byte(board, elem) \ + read_sx_byte (board, BRD_OFFSET (board, elem)) + +#define sx_write_board_word(board, elem, val) \ + write_sx_word (board, BRD_OFFSET (board, elem), val) + +#define sx_read_board_word(board, elem) \ + read_sx_word (board, BRD_OFFSET (board, elem)) + + +int sx_start_board (struct sx_board *board) +{ + if (IS_SX_BOARD (board)) { + write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN); + } else { + /* Don't bug me about the clear_set. + I haven't the foggiest idea what it's about -- REW*/ + write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); + write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + } + return 1; +} + +#define SX_IRQ_REG_VAL(board) \ + ((board->flags & SX_ISA_BOARD)?(board->irq << 4):0) + +/* Note. The SX register is write-only. Therefore, we have to enable the + bus too. This is a no-op, if you don't mess with this driver... */ +int sx_start_interrupts (struct sx_board *board) +{ + + /* Don't call this with board->irq == 0 */ + + if (IS_SX_BOARD(board)) { + write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | + SX_CONF_BUSEN | + SX_CONF_HOSTIRQ); + } else { + switch (board->irq) { + case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break; + case 12:write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);break; + case 15:write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);break; + default:printk (KERN_INFO "sx: SI/XIO card doesn't support interrupt %d.\n", + board->irq); + return 0; + } + write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + } + + return 1; +} + + +int sx_send_command (struct sx_port *port, + int command, + int mask, + int newstat) +{ + func_enter2 (); + write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command); + func_exit (); + return sx_busy_wait_eq (port->board, CHAN_OFFSET (port, hi_hstat), mask, newstat); +} + + +char *mod_type_s (int module_type) +{ + switch (module_type) { + case TA4: return "TA4"; + case TA8: return "TA8"; + case TA4_ASIC: return "TA4_ASIC"; + case TA8_ASIC: return "TA8_ASIC"; + case MTA_CD1400:return "MTA_CD1400"; + case SXDC: return "SXDC"; + default:return "Unknown/invalid"; + } +} + + +char *pan_type_s (int pan_type) +{ + switch (pan_type) { + case MOD_RS232DB25: return "MOD_RS232DB25"; + case MOD_RS232RJ45: return "MOD_RS232RJ45"; + case MOD_RS422DB25: return "MOD_RS422DB25"; + case MOD_PARALLEL: return "MOD_PARALLEL"; + case MOD_2_RS232DB25: return "MOD_2_RS232DB25"; + case MOD_2_RS232RJ45: return "MOD_2_RS232RJ45"; + case MOD_2_RS422DB25: return "MOD_2_RS422DB25"; + case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE"; + case MOD_2_PARALLEL: return "MOD_2_PARALLEL"; + case MOD_BLANK: return "empty"; + default:return "invalid"; + } +} + + +int mod_compat_type (int module_type) +{ + return module_type >> 4; +} + + +static void sx_setsignals (struct sx_port *port, int dtr, int rts) +{ + int t; + func_enter2 (); + + t = sx_read_channel_byte (port, hi_op); + if (dtr >= 0) t = dtr? (t | OP_DTR): (t & ~OP_DTR); + if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS); + sx_write_channel_byte (port, hi_op, t); + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); + func_exit (); +} + + + +static int sx_getsignals (struct sx_port *port) +{ + int i_stat,o_stat; + + o_stat = sx_read_channel_byte (port, hi_op); + i_stat = sx_read_channel_byte (port, hi_ip); + + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) %02x/%02x\n", + (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, + port->c_dcd, sx_get_CD (port), + sx_read_channel_byte (port, hi_ip), + sx_read_channel_byte (port, hi_state)); + + return (((o_stat & OP_DTR)?TIOCM_DTR:0) | + ((o_stat & OP_RTS)?TIOCM_RTS:0) | + ((i_stat & IP_CTS)?TIOCM_CTS:0) | + ((i_stat & IP_DCD)?TIOCM_CAR:0) | + ((i_stat & IP_DSR)?TIOCM_DSR:0) | + ((i_stat & IP_RI)?TIOCM_RNG:0) + ); +} + + +static void sx_set_baud (struct sx_port *port) +{ + int t; + + if (port->board->ta_type == MOD_SXDC) { + switch (port->gs.baud) { + /* Save some typing work... */ +#define e(x) case x:t= BAUD_ ## x ; break + e(50);e(75);e(110);e(150);e(200);e(300);e(600); + e(1200);e(1800);e(2000);e(2400);e(4800);e(7200); + e(9600);e(14400);e(19200);e(28800);e(38400); + e(56000);e(57600);e(64000);e(76800);e(115200); + e(128000);e(150000);e(230400);e(256000);e(460800); + e(921600); + case 134 :t = BAUD_134_5; break; + case 0 :t = -1; + break; + default: + /* Can I return "invalid"? */ + t = BAUD_9600; + printk (KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud); + break; + } +#undef e + if (t > 0) { + /* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ + sx_setsignals (port, 1, -1); + /* XXX This is not TA & MTA compatible */ + sx_write_channel_byte (port, hi_csr, 0xff); + + sx_write_channel_byte (port, hi_txbaud, t); + sx_write_channel_byte (port, hi_rxbaud, t); + } else { + sx_setsignals (port, 0, -1); + } + } else { + switch (port->gs.baud) { +#define e(x) case x:t= CSR_ ## x ; break + e(75);e(150);e(300);e(600);e(1200);e(2400);e(4800); + e(1800);e(9600); + e(19200);e(57600);e(38400); + /* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ + case 110: + if (port->board->ta_type == MOD_TA) { + t = CSR_110; + break; + } else { + t = CSR_9600; + printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + break; + } + case 115200: + if (port->board->ta_type == MOD_TA) { + t = CSR_9600; + printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + break; + } else { + t = CSR_110; + break; + } + case 0 :t = -1; + break; + default: + t = CSR_9600; + printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + break; + } +#undef e + if (t >= 0) { + sx_setsignals (port, 1, -1); + sx_write_channel_byte (port, hi_csr, t * 0x11); + } else { + sx_setsignals (port, 0, -1); + } + } +} + + +/* Simon Allen's version of this routine was 225 lines long. 85 is a lot + better. -- REW */ + +static void sx_set_real_termios (void *ptr) +{ + struct sx_port *port = ptr; + + func_enter2(); + + /* What is this doing here? -- REW + Ha! figured it out. It is to allow you to get DTR active again + if you've dropped it with stty 0. Moved to set_baud, where it + belongs (next to the drop dtr if baud == 0) -- REW */ + /* sx_setsignals (port, 1, -1); */ + + sx_set_baud (port); + +#define CFLAG port->gs.tty->termios->c_cflag + sx_write_channel_byte (port, hi_mr1, + (C_PARENB (port->gs.tty)? MR1_WITH:MR1_NONE) | + (C_PARODD (port->gs.tty)? MR1_ODD:MR1_EVEN) | + (C_CRTSCTS(port->gs.tty)? MR1_RTS_RXFLOW:0) | + (((CFLAG & CSIZE)==CS8) ? MR1_8_BITS:0) | + (((CFLAG & CSIZE)==CS7) ? MR1_7_BITS:0) | + (((CFLAG & CSIZE)==CS6) ? MR1_6_BITS:0) | + (((CFLAG & CSIZE)==CS5) ? MR1_5_BITS:0) ); + + sx_write_channel_byte (port, hi_mr2, + (C_CRTSCTS(port->gs.tty)?MR2_CTS_TXFLOW:0) | + (C_CSTOPB (port->gs.tty)?MR2_2_STOP:MR2_1_STOP)); + + switch (CFLAG & CSIZE) { + case CS8:sx_write_channel_byte (port, hi_mask, 0xff);break; + case CS7:sx_write_channel_byte (port, hi_mask, 0x7f);break; + case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; + case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; + default: + printk (KERN_INFO "sx: Invalid wordsize: %d\n", CFLAG & CSIZE); + break; + } + + sx_write_channel_byte (port, hi_prtcl, + (I_IXON (port->gs.tty)?SP_TXEN:0) | + (I_IXOFF (port->gs.tty)?SP_RXEN:0) | + (I_IXANY (port->gs.tty)?SP_TANY:0) | + SP_DCEN); + + sx_write_channel_byte (port, hi_break, + I_OTHER(port->gs.tty) ? 0: + (I_IGNBRK(port->gs.tty)?BR_IGN:0 | + I_BRKINT(port->gs.tty)?BR_INT:0)); + + sx_write_channel_byte (port, hi_txon, START_CHAR (port->gs.tty)); + sx_write_channel_byte (port, hi_rxon, START_CHAR (port->gs.tty)); + sx_write_channel_byte (port, hi_txoff, STOP_CHAR (port->gs.tty)); + sx_write_channel_byte (port, hi_rxoff, STOP_CHAR (port->gs.tty)); + + if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) { + if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { + printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n"); + } + } else { + sx_dprintk (SX_DEBUG_TERMIOS, + "sx: Not sending reconfigure: port isn't open (%02x).\n", + sx_read_channel_byte (port, hi_hstat)); + } + + + /* Tell line discipline whether we will do input cooking */ + if(I_OTHER(port->gs.tty)) { + clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); + } else { + set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); + } + sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", + port->gs.tty->termios->c_iflag, + I_OTHER(port->gs.tty)); + + +/* Tell line discipline whether we will do output cooking. + * If OPOST is set and no other output flags are set then we can do output + * processing. Even if only *one* other flag in the O_OTHER group is set + * we do cooking in software. + */ + if(O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) { + set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); + } else { + clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); + } + sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", + port->gs.tty->termios->c_oflag, + O_OTHER(port->gs.tty)); + /* port->c_dcd = sx_get_CD (port); */ + func_exit (); +} + + + +/* ********************************************************************** * + * the interrupt related routines * + * ********************************************************************** */ + +/* Note: + Other drivers use the macro "MIN" to calculate how much to copy. + This has the disadvantage that it will evaluate parts twice. That's + expensive when it's IO (and the compiler cannot optimize those away!). + Moreover, I'm not sure that you're race-free. + + I assign a value, and then only allow the value to decrease. This + is always safe. This makes the code a few lines longer, and you + know I'm dead against that, but I think it is required in this + case. */ + + +void sx_transmit_chars (struct sx_port *port) +{ + int c; + int tx_ip; + int txroom; + + func_enter2 (); + sx_dprintk (SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", + port, port->gs.xmit_cnt); + + if (test_and_set_bit (SX_PORT_TRANSMIT_LOCK, &port->locks)) { + return; + } + + while (1) { + c = port->gs.xmit_cnt; + + sx_dprintk (SX_DEBUG_TRANSMIT, "Copying %d ", c); + tx_ip = sx_read_channel_byte (port, hi_txipos); + + /* Took me 5 minutes to deduce this formula. + Luckily it is literally in the manual in section 6.5.4.3.5 */ + txroom = (sx_read_channel_byte (port, hi_txopos) - tx_ip - 1) & 0xff; + + /* Don't copy more bytes than there is room for in the buffer */ + if (c > txroom) + c = txroom; + sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom ); + + /* Don't copy past the end of the hardware transmit buffer */ + if (c > 0x100 - tx_ip) + c = 0x100 - tx_ip; + + sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100-tx_ip ); + + /* Don't copy pas the end of the source buffer */ + if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) + c = SERIAL_XMIT_SIZE - port->gs.xmit_tail; + + sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) \n", + c, SERIAL_XMIT_SIZE- port->gs.xmit_tail); + + /* If for one reason or another, we can't copy more data, we're done! */ + if (c == 0) break; + + + memcpy_toio (port->board->base + CHAN_OFFSET(port,hi_txbuf) + tx_ip, + port->gs.xmit_buf + port->gs.xmit_tail, c); + + /* Update the pointer in the card */ + sx_write_channel_byte (port, hi_txipos, (tx_ip+c) & 0xff); + + /* Update the kernel buffer end */ + port->gs.xmit_tail = (port->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1); + + /* This one last. (this is essential) + It would allow others to start putting more data into the buffer! */ + port->gs.xmit_cnt -= c; + } + + if (port->gs.xmit_cnt == 0) { + sx_disable_tx_interrupts (port); + } + + if (port->gs.xmit_cnt <= port->gs.wakeup_chars) { + if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + port->gs.tty->ldisc.write_wakeup) + (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); + sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", + port->gs.wakeup_chars); + wake_up_interruptible(&port->gs.tty->write_wait); + } + + clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks); + func_exit (); +} + + +/* Note the symmetry between receiving chars and transmitting them! + Note: The kernel should have implemented both a receive buffer and + a transmit buffer. */ + +/* Inlined: Called only once. Remove the inline when you add another call */ +inline void sx_receive_chars (struct sx_port *port) +{ + int c; + int rx_op; + struct tty_struct *tty; + int copied=0; + + /* func_enter2 (); */ + tty = port->gs.tty; + while (1) { + rx_op = sx_read_channel_byte (port, hi_rxopos); + c = (sx_read_channel_byte (port, hi_rxipos) - rx_op) & 0xff; + + sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); + + /* Don't copy more bytes than there is room for in the buffer */ + if (tty->flip.count + c > TTY_FLIPBUF_SIZE) + c = TTY_FLIPBUF_SIZE - tty->flip.count; + + sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + + /* Don't copy past the end of the hardware receive buffer */ + if (rx_op + c > 0x100) c = 0x100 - rx_op; + + sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + + /* If for one reason or another, we can't copy more data, we're done! */ + if (c == 0) break; + + sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, + read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op), + CHAN_OFFSET(port, hi_rxbuf)); + memcpy_fromio (tty->flip.char_buf_ptr, + port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c); + memset(tty->flip.flag_buf_ptr, TTY_NORMAL, c); + + /* Update the kernel buffer end */ + tty->flip.count += c; + tty->flip.char_buf_ptr += c; + tty->flip.flag_buf_ptr += c; + + /* This one last. ( Not essential.) + It allows the card to start putting more data into the buffer! + Update the pointer in the card */ + sx_write_channel_byte (port, hi_rxopos, (rx_op + c) & 0xff); + + copied += c; + } + if (copied) { + struct timeval tv; + + do_gettimeofday (&tv); + sx_dprintk (SX_DEBUG_RECEIVE, + "pushing flipq port %d (%3d chars): %d.%06d (%d/%d)\n", + port->line, copied, + (int) (tv.tv_sec % 60), (int)tv.tv_usec, tty->raw, tty->real_raw); + + /* Tell the rest of the system the news. Great news. New characters! */ + tty_flip_buffer_push (tty); + /* tty_schedule_flip (tty); */ + } + + /* func_exit (); */ +} + +/* Inlined: it is called only once. Remove the inline if you add another + call */ +inline void sx_check_modem_signals (struct sx_port *port) +{ + int hi_state; + int c_dcd; + + hi_state = sx_read_channel_byte (port, hi_state); + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", + port->c_dcd, sx_get_CD (port)); + + if (hi_state & ST_BREAK) { + hi_state &= ~ST_BREAK; + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n"); + + sx_write_channel_byte (port, hi_state, hi_state); + if (port->gs.flags & ASYNC_SAK) { + do_SAK (port->gs.tty); + } + } + if (hi_state & ST_DCD) { + hi_state &= ~ST_DCD; + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); + sx_write_channel_byte (port, hi_state, hi_state); + c_dcd = sx_get_CD (port); + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); + if (c_dcd != port->c_dcd) { + port->c_dcd = c_dcd; + if (sx_get_CD (port)) { + /* DCD went UP */ + if( (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) || + ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) && + (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) { + /* Are we blocking in open?*/ + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n"); + wake_up_interruptible(&port->gs.open_wait); + } else { + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD raised. Ignoring.\n"); + } + } else { + /* DCD went down! */ + if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) && + (port->gs.flags & ASYNC_CALLOUT_NOHUP))) { + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n"); + tty_hangup (port->gs.tty); + } else { + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. ignoring.\n"); + } + } + } else { + sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us DCD changed, but it didn't.\n"); + } + } +} + + +/* This is what an interrupt routine should look like. + * Small, elegant, clear. + */ + +static void sx_interrupt (int irq, void *ptr, struct pt_regs *regs) +{ + struct sx_board *board = ptr; + struct sx_port *port; + int i; + + /* func_enter (); */ + sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); + + /* AAargh! The order in which to do these things is essential and + not trivial. + + - Rate limit goes before "recursive". Otherwise a series of + recursive calls will hang the machine in the interrupt routine. + + - hardware twiddling goes before "recursive". Otherwise when we + poll the card, and a recursive interrupt happens, we wont + ack the card, so it might keep on interrupting us. (especially + level sensitive interrupt systems like PCI). + + - Rate limit goes before hardware twiddling. Otherwise we won't + catch a card that has gone bonkers. + + - The "initialized" test goes after the hardware twiddling. Otherwise + the card will stick us in the interrupt routine again. + + - The initialized test goes before recursive. + */ + + + +#ifdef IRQ_RATE_LIMIT + /* Aaargh! I'm ashamed. This costs more lines-of-code than the + actual interrupt routine!. (Well, used to when I wrote that comment) */ + { + static int lastjif; + static int nintr=0; + + if (lastjif == jiffies) { + if (++nintr > IRQ_RATE_LIMIT) { + free_irq (board->irq, board); + printk (KERN_ERR "sx: Too many interrupts. Turning off interrupt %d.\n", + board->irq); + } + } else { + lastjif = jiffies; + nintr = 0; + } + } +#endif + + + if (board->irq == irq) { + /* Tell the card we've noticed the interrupt. */ + + sx_write_board_word (board, cc_int_pending, 0); + if (IS_SX_BOARD (board)) { + write_sx_byte (board, SX_RESET_IRQ, 1); + } else { + write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + } + } + + if (!sx_initialized) return; + if (!(board->flags & SX_BOARD_INITIALIZED)) return; + + if (test_and_set_bit (SX_BOARD_INTR_LOCK, &board->locks)) { + printk (KERN_ERR "Recursive interrupt! (%d)\n", board->irq); + return; + } + + for (i=0;inports;i++) { + port = &board->ports[i]; + if (port->gs.flags & GS_ACTIVE) { + if (sx_read_channel_byte (port, hi_state)) { + sx_dprintk (SX_DEBUG_INTERRUPTS, + "Port %d: modem signal change?... \n", i); + sx_check_modem_signals (port); + } + if (port->gs.xmit_cnt) { + sx_transmit_chars (port); + } + if (!(port->gs.flags & SX_RX_THROTTLE)) { + sx_receive_chars (port); + } + } + } + + clear_bit (SX_BOARD_INTR_LOCK, &board->locks); + + sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); + /* func_exit (); */ +} + + +static void sx_pollfunc (unsigned long data) +{ + struct sx_board *board = (struct sx_board *) data; + + func_enter (); + + sx_interrupt (0, board, NULL); + + board->timer.expires = jiffies + sx_poll; + add_timer (&board->timer); + func_exit (); +} + + + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the generic_serial driver * + * ********************************************************************** */ + +/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */ +/* Hmm. Ok I figured it out. You don't. */ + +static void sx_disable_tx_interrupts (void * ptr) +{ + struct sx_port *port = ptr; + func_enter2(); + + port->gs.flags &= ~GS_TX_INTEN; + + func_exit(); +} + + +static void sx_enable_tx_interrupts (void * ptr) +{ + struct sx_port *port = ptr; + int data_in_buffer; + func_enter2(); + + /* First transmit the characters that we're supposed to */ + sx_transmit_chars (port); + + /* The sx card will never interrupt us if we don't fill the buffer + past 25%. So we keep considering interrupts off if that's the case. */ + data_in_buffer = (sx_read_channel_byte (port, hi_txipos) - + sx_read_channel_byte (port, hi_txopos)) & 0xff; + + /* XXX Must be "HIGH_WATER" for SI card according to doc. */ + if (data_in_buffer < LOW_WATER) + port->gs.flags &= ~GS_TX_INTEN; + + func_exit(); +} + + +static void sx_disable_rx_interrupts (void * ptr) +{ + /* struct sx_port *port = ptr; */ + func_enter(); + + func_exit(); +} + +static void sx_enable_rx_interrupts (void * ptr) +{ + /* struct sx_port *port = ptr; */ + func_enter(); + + func_exit(); +} + + +/* Jeez. Isn't this simple? */ +static int sx_get_CD (void * ptr) +{ + struct sx_port *port = ptr; + func_enter2(); + + func_exit(); + return ((sx_read_channel_byte (port, hi_ip) & IP_DCD) != 0); +} + + +/* Jeez. Isn't this simple? */ +static int sx_chars_in_buffer (void * ptr) +{ + struct sx_port *port = ptr; + func_enter2(); + + func_exit(); + return ((sx_read_channel_byte (port, hi_txipos) - + sx_read_channel_byte (port, hi_txopos)) & 0xff); +} + + +static void sx_shutdown_port (void * ptr) +{ + struct sx_port *port = ptr; + + func_enter(); + + port->gs.flags &= ~ GS_ACTIVE; + if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { + sx_setsignals (port, 0, 0); + } + + func_exit(); +} + + + + + +/* ********************************************************************** * + * Here are the routines that actually * + * interface with the rest of the system * + * ********************************************************************** */ + + +static int sx_fw_open(struct inode *inode, struct file *filp) +{ + func_enter (); + MOD_INC_USE_COUNT; + func_exit (); + return 0; +} + + +static INT sx_fw_release(struct inode *inode, struct file *filp) +{ + func_enter (); + MOD_DEC_USE_COUNT; + func_exit (); + return NO_ERROR; +} + + +static int sx_open (struct tty_struct * tty, struct file * filp) +{ + struct sx_port *port; + int retval, line; + + func_enter(); + + if (!sx_initialized) { + return -EIO; + } + + line = MINOR(tty->device); + sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n", + current->pid, line, tty, current->tty, sx_nports); + + if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports)) + return -ENODEV; + + port = & sx_ports[line]; + port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a + 1 -> 0 transition. */ + + + sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); + + tty->driver_data = port; + port->gs.tty = tty; + port->gs.count++; + + sx_dprintk (SX_DEBUG_OPEN, "starting port\n"); + + /* + * Start up serial port + */ + retval = gs_init_port(&port->gs); + sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n"); + if (retval) { + port->gs.count--; + return retval; + } + + port->gs.flags |= GS_ACTIVE; + sx_setsignals (port, 1,1); + + sx_dprintk (SX_DEBUG_OPEN, "before inc_use_count (count=%d.\n", + port->gs.count); + if (port->gs.count == 1) { + MOD_INC_USE_COUNT; + } + sx_dprintk (SX_DEBUG_OPEN, "after inc_use_count\n"); + +#if 0 + if (sx_debug & SX_DEBUG_OPEN) + my_hd ((unsigned char *)port, sizeof (*port)); +#else + if (sx_debug & SX_DEBUG_OPEN) + my_hd ((unsigned char *)port->board->base + port->ch_base, + sizeof (*port)); +#endif + + if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { + printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n"); + MOD_DEC_USE_COUNT; + port->gs.count--; + return -EIO; + } + + retval = block_til_ready(port, filp); + sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", + retval, port->gs.count); + + if (retval) { + MOD_DEC_USE_COUNT; + port->gs.count--; + return retval; + } + /* tty->low_latency = 1; */ + + if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = port->gs.normal_termios; + else + *tty->termios = port->gs.callout_termios; + sx_set_real_termios (port); + } + + port->gs.session = current->session; + port->gs.pgrp = current->pgrp; + port->c_dcd = sx_get_CD (port); + sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); + func_exit(); + return 0; + +} + + +/* I haven't the foggiest why the decrement use count has to happen + here. The whole linux serial drivers stuff needs to be redesigned. + My guess is that this is a hack to minimize the impact of a bug + elsewhere. Thinking about it some more. (try it sometime) Try + running minicom on a serial port that is driven by a modularized + driver. Have the modem hangup. Then remove the driver module. Then + exit minicom. I expect an "oops". -- REW */ +static void sx_hungup (void *ptr) +{ + func_enter (); + MOD_DEC_USE_COUNT; + func_exit (); +} + + +static void sx_close (void *ptr) +{ + struct sx_port *port = ptr; + /* Give the port 5 seconds to close down. */ + int to = 5 * HZ; + + func_enter (); + sx_send_command (port, HS_CLOSE, 0, 0); + + while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout (1); + if (signal_pending (current)) + break; + } + current->state = TASK_RUNNING; + if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) { + if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) { + printk (KERN_ERR + "sx: sent the force_close command, but card didn't react\n"); + } else + sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n"); + } + + sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", + 5 * HZ - to - 1, port->gs.count); + + MOD_DEC_USE_COUNT; + func_exit (); +} + + + +/* This is relatively thorough. But then again it is only 20 lines. */ +#define MARCHUP for (i=min;i=min;i--) +#define W0 write_sx_byte (board, i, 0x55) +#define W1 write_sx_byte (board, i, 0xaa) +#define R0 if (read_sx_byte (board, i) != 0x55) return 1 +#define R1 if (read_sx_byte (board, i) != 0xaa) return 1 + +/* This memtest takes a human-noticable time. You normally only do it + once a boot, so I guess that it is worth it. */ +int do_memtest (struct sx_board *board, int min, int max) +{ + int i; + + /* This is a marchb. Theoretically, marchb catches much more than + simpler tests. In practise, the longer test just catches more + intermittent errors. -- REW + (For the theory behind memory testing see: + Testing Semiconductor Memories by A.J. van de Goor.) */ + MARCHUP {W0;} + MARCHUP {R0;W1;R1;W0;R0;W1;} + MARCHUP {R1;W0;W1;} + MARCHDOWN {R1;W0;W1;W0;} + MARCHDOWN {R0;W1;W0;} + + return 0; +} + + +#undef MARCHUP +#undef MARCHDOWN +#undef W0 +#undef W1 +#undef R0 +#undef R1 + +#define MARCHUP for (i=min;i=min;i-=2) +#define W0 write_sx_word (board, i, 0x55aa) +#define W1 write_sx_word (board, i, 0xaa55) +#define R0 if (read_sx_word (board, i) != 0x55aa) return 1 +#define R1 if (read_sx_word (board, i) != 0xaa55) return 1 + +/* This memtest takes a human-noticable time. You normally only do it + once a boot, so I guess that it is worth it. */ +int do_memtest_w (struct sx_board *board, int min, int max) +{ + int i; + + MARCHUP {W0;} + MARCHUP {R0;W1;R1;W0;R0;W1;} + MARCHUP {R1;W0;W1;} + MARCHDOWN {R1;W0;W1;W0;} + MARCHDOWN {R0;W1;W0;} + + return 0; +} + + +static int sx_fw_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int rc = 0; + int *descr = (int *)arg, i; + static struct sx_board *board = NULL; + int nbytes, offset, data; + char *tmp; + + func_enter(); + +#if 0 + /* Removed superuser check: Sysops can use the permissions on the device + file to restrict access. Recommendation: Root only. (root.root 600) */ + if (!suser ()) { + return -EPERM; + } +#endif + + sx_dprintk (SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); + + if (!board) board = &boards[0]; + if (board->flags & SX_BOARD_PRESENT) { + sx_dprintk (SX_DEBUG_FIRMWARE, "Board present! (%x)\n", + board->flags); + } else { + sx_dprintk (SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", + board->flags); + for (i=0;i< SX_NBOARDS;i++) + sx_dprintk (SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); + sx_dprintk (SX_DEBUG_FIRMWARE, "\n"); + return -EIO; + } + + switch (cmd) { + case SXIO_SET_BOARD: + sx_dprintk (SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + if (arg > SX_NBOARDS) return -EIO; + sx_dprintk (SX_DEBUG_FIRMWARE, "not out of range\n"); + if (!(boards[arg].flags & SX_BOARD_PRESENT)) return -EIO; + sx_dprintk (SX_DEBUG_FIRMWARE, ".. and present!\n"); + board = &boards[arg]; + break; + case SXIO_GET_TYPE: + rc = IS_SX_BOARD (board)? SX_TYPE_SX:SX_TYPE_SI; + sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); + break; + case SXIO_DO_RAMTEST: + if (sx_initialized) /* Already initialized: better not ramtest the board. */ + return -EPERM; + if (IS_SX_BOARD (board)) { + rc = do_memtest (board, 0, 0x7000); + if (!rc) rc = do_memtest (board, 0, 0x7000); + /*if (!rc) rc = do_memtest_w (board, 0, 0x7000);*/ + } else { + rc = do_memtest (board, 0, 0x7ff8); + /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ + } + sx_dprintk (SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", rc); + break; + case SXIO_DOWNLOAD: + if (sx_initialized) /* Already initialized */ + return -EEXIST; + if (!sx_reset (board)) + return -EIO; + sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); + + tmp = kmalloc (SX_CHUNK_SIZE, GFP_USER); + if (!tmp) return -ENOMEM; + Get_user (nbytes, descr++); + Get_user (offset, descr++); + Get_user (data, descr++); + while (nbytes && data) { + for (i=0;inbytes)?nbytes-i:SX_CHUNK_SIZE); + memcpy_toio ((char *) (board->base + offset + i), tmp, + (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); + } + + Get_user (nbytes, descr++); + Get_user (offset, descr++); + Get_user (data, descr++); + } + kfree (tmp); + sx_nports += sx_init_board (board); + rc = sx_nports; + break; + case SXIO_INIT: + if (sx_initialized) /* Already initialized */ + return -EEXIST; + /* This is not allowed until all boards are initialized... */ + for (i=0;i= 0) + sx_initialized++; + break; + case SXIO_SETDEBUG: + sx_debug = arg; + break; + case SXIO_GETDEBUG: + rc = sx_debug; + break; + case SXIO_SETGSDEBUG: + gs_debug = arg; + break; + case SXIO_GETGSDEBUG: + rc = gs_debug; + break; + default: + printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd); + break; + } + func_exit (); + return rc; +} + + +static int sx_ioctl (struct tty_struct * tty, struct file * filp, + unsigned int cmd, unsigned long arg) +{ + int rc; + struct sx_port *port = tty->driver_data; + int ival; + + /* func_enter2(); */ + + rc = 0; + switch (cmd) { + case TIOCGSOFTCAR: + rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), + (unsigned int *) arg); + break; + case TIOCSSOFTCAR: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(int))) == 0) { + Get_user(ival, (unsigned int *) arg); + tty->termios->c_cflag = + (tty->termios->c_cflag & ~CLOCAL) | + (ival ? CLOCAL : 0); + } + break; + case TIOCGSERIAL: + if ((rc = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct))) == 0) + gs_getserial(&port->gs, (struct serial_struct *) arg); + break; + case TIOCSSERIAL: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(struct serial_struct))) == 0) + rc = gs_setserial(&port->gs, (struct serial_struct *) arg); + break; + case TIOCMGET: + if ((rc = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int))) == 0) { + ival = sx_getsignals(port); + put_user(ival, (unsigned int *) arg); + } + break; + case TIOCMBIS: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(unsigned int))) == 0) { + Get_user(ival, (unsigned int *) arg); + sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), + ((ival & TIOCM_RTS) ? 1 : -1)); + } + break; + case TIOCMBIC: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(unsigned int))) == 0) { + Get_user(ival, (unsigned int *) arg); + sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), + ((ival & TIOCM_RTS) ? 0 : -1)); + } + break; + case TIOCMSET: + if ((rc = verify_area(VERIFY_READ, (void *) arg, + sizeof(unsigned int))) == 0) { + Get_user(ival, (unsigned int *) arg); + sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), + ((ival & TIOCM_RTS) ? 1 : 0)); + } + break; + + default: + rc = -ENOIOCTLCMD; + break; + } + + /* func_exit(); */ + return rc; +} + + +/* The throttle/unthrottle scheme for the Specialix card is different + * from other drivers and deserves some explanation. + * The Specialix hardware takes care of XON/XOFF + * and CTS/RTS flow control itself. This means that all we have to + * do when signalled by the upper tty layer to throttle/unthrottle is + * to make a note of it here. When we come to read characters from the + * rx buffers on the card (sx_receive_chars()) we look to see if the + * upper layer can accept more (as noted here in sx_rx_throt[]). + * If it can't we simply don't remove chars from the cards buffer. + * When the tty layer can accept chars, we again note that here and when + * sx_receive_chars() is called it will remove them from the cards buffer. + * The card will notice that a ports buffer has drained below some low + * water mark and will unflow control the line itself, using whatever + * flow control scheme is in use for that port. -- Simon Allen + */ + +static void sx_throttle (struct tty_struct * tty) +{ + struct sx_port *port = (struct sx_port *)tty->driver_data; + + func_enter2(); + /* If the port is using any type of input flow + * control then throttle the port. + */ + if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) { + port->gs.flags |= SX_RX_THROTTLE; + } + func_exit(); +} + + +static void sx_unthrottle (struct tty_struct * tty) +{ + struct sx_port *port = (struct sx_port *)tty->driver_data; + + func_enter2(); + /* Always unthrottle even if flow control is not enabled on + * this port in case we disabled flow control while the port + * was throttled + */ + port->gs.flags &= ~SX_RX_THROTTLE; + func_exit(); + return; +} + + +/* ********************************************************************** * + * Here are the initialization routines. * + * ********************************************************************** */ + + + + +static int sx_init_board (struct sx_board *board) +{ + int addr; + int chans; + int type; + + func_enter(); + + /* This is preceded by downloading the download code. */ + + board->flags |= SX_BOARD_INITIALIZED; + + /* This resets the processor again, to make sure it didn't do any + foolish things while we were downloading the image */ + if (!sx_reset (board)) + return 0; + + sx_start_board (board); + + if (!sx_busy_wait_neq (board, 0, 0xff, 0)) { + printk (KERN_ERR "sx: Ooops. Board won't initialize.\n"); + return 0; + } + + /* Ok. So now the processor on the card is running. It gathered + some info for us... */ + sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n"); + if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base), 0x10); + sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n"); + if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base + 0x80), 0x30); + + sx_dprintk (SX_DEBUG_INIT, + "init_status: %x, %dk memory, firmware V%x.%02x,\n", + read_sx_byte (board, 0), read_sx_byte(board, 1), + read_sx_byte (board, 5), read_sx_byte(board, 4)); + + if (read_sx_byte (board, 0) == 0xff) { + printk (KERN_INFO "sx: No modules found. Sorry.\n"); + board->nports = 0; + return 0; + } + + chans = 0; + + if (IS_SX_BOARD(board)) { + sx_write_board_word (board, cc_int_count, sx_maxints); + } else { + if (sx_maxints) + sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints); + } + + /* grab the first module type... */ + /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ + board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip)); + + /* XXX byteorder */ + for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { + type = sx_read_module_byte (board, addr, mc_chip); + sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n", + addr, read_sx_byte (board, addr + 2)); + + chans += sx_read_module_byte (board, addr, mc_type); + + sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n", + mod_type_s (type), + pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf), + pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4)); + + sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n", + sx_read_module_byte (board, addr, mc_rev1), + sx_read_module_byte (board, addr, mc_rev2), + sx_read_module_byte (board, addr, mc_mtaasic_rev)); + + /* The following combinations are illegal: It should theoretically + work, but timing problems make the bus HANG. */ + + if (mod_compat_type (type) != board->ta_type) { + printk (KERN_ERR "sx: This is an invalid configuration.\n" + "Don't mix TA/MTA/SXDC on the same hostadapter.\n"); + chans=0; + break; + } + if (IS_SI_BOARD(board) && (mod_compat_type(type) == 4)) { + printk (KERN_ERR "sx: This is an invalid configuration.\n" + "Don't use SXDCs on an SI/XIO adapter.\n"); + chans=0; + break; + } +#if 0 /* Problem fixed: firmware 3.05 */ + if (IS_SX_BOARD(board) && (type == TA8)) { + /* There are some issues with the firmware and the DCD/RTS + lines. It might work if you tie them together or something. + It might also work if you get a newer sx_firmware. Therefore + this is just a warning. */ + printk (KERN_WARNING "sx: The SX host doesn't work too well " + "with the TA8 adapters.\nSpecialix is working on it.\n"); + } +#endif + } + + if (chans) { + /* board->flags |= SX_BOARD_PRESENT; */ + if(board->irq > 0) { + /* fixed irq, probably PCI */ + if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ + if(request_irq(board->irq, sx_interrupt, SA_SHIRQ | SA_INTERRUPT, "sx", board)) { + printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq); + board->irq = 0; + } + } else + board->irq = 0; + } else if(board->irq < 0 && sx_irqmask) { + /* auto-allocate irq */ + int irqnr; + int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); + for(irqnr = 15; irqnr > 0; irqnr--) + if(irqmask & (1 << irqnr)) + if(! request_irq(irqnr, sx_interrupt, SA_SHIRQ | SA_INTERRUPT, "sx", board)) + break; + if(! irqnr) + printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); + board->irq = irqnr; + } else + board->irq = 0; + + if (board->irq) { + /* Found a valid interrupt, start up interrupts! */ + sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq); + sx_start_interrupts (board); + board->poll = sx_slowpoll; + board->flags |= SX_IRQ_ALLOCATED; + } else { + /* no irq: setup board for polled operation */ + board->poll = sx_poll; + sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll); + } + + /* The timer should be initialized anyway: That way we can safely + del_timer it when the module is unloaded. */ + init_timer (&board->timer); + + if (board->poll) { + board->timer.data = (unsigned long) board; + board->timer.function = sx_pollfunc; + board->timer.expires = jiffies + board->poll; + add_timer (&board->timer); + } + } else { + board->irq = 0; + } + + board->nports = chans; + sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports); + + func_exit(); + return chans; +} + + +void printheader(void) +{ + static int header_printed = 0; + + if (!header_printed) { + printk (KERN_INFO "Specialix SX driver " + "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n"); + printk (KERN_INFO "sx: version %s\n", RCS_ID); + header_printed = 1; + } +} + + +int probe_sx (struct sx_board *board) +{ + struct vpd_prom vpdp; + char *p; + int i; + + func_enter(); + sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %x.\n", + board->base + SX_VPD_ROM); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd ((char *)(board->base + SX_VPD_ROM), 0x40); + + p = (char *) &vpdp; + for (i=0;i< sizeof (struct vpd_prom);i++) + *p++ = read_sx_byte (board, SX_VPD_ROM + i*2); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd ((char *)&vpdp, 0x20); + + sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n"); + + if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { + sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", + vpdp.identifier); + return 0; + } + + printheader (); + + printk (KERN_DEBUG "sx: Found an SX board at %x\n", board->hw_base); + printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", + vpdp.hwrev, vpdp.hwass, vpdp.uniqid); + printk ( "Manufactured: %d/%d\n", + 1970 + vpdp.myear, vpdp.mweek); + + + if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) && + (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { + /* This might be a bit harsh. This was the primary reason the + SX/ISA card didn't work at first... */ + printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n"); + return (0); + } + + if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { + if (board->base & 0x8000) { + printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %x.\n", board->base); + printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); + } + } + + + board->nports = -1; + + /* This resets the processor, and keeps it off the bus. */ + if (!sx_reset (board)) + return 0; + sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); + + board->flags |= SX_BOARD_PRESENT; + + func_exit(); + return 1; +} + + + +/* Specialix probes for this card at 32k increments from 640k to 16M. + I consider machines with less than 16M unlikely nowadays, so I'm + not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA + card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves + 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */ + +int probe_si (struct sx_board *board) +{ + int i; + + func_enter(); + sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %x.\n", + board->base + SI2_ISA_ID_BASE); + + if (sx_debug & SX_DEBUG_PROBE) + my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8); + + for (i=0;i<8;i++) { + if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { + return 0; + } + } + + printheader (); + + printk (KERN_DEBUG "sx: Found an SI board at %x\n", board->hw_base); + /* Compared to the SX boards, it is a complete guess as to what + this card is up to... */ + + board->nports = -1; + + /* This resets the processor, and keeps it off the bus. */ + if (!sx_reset (board)) + return 0; + sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); + + board->flags |= SX_BOARD_PRESENT; + + func_exit(); + return 1; +} + + +static int sx_init_drivers(void) +{ + int error; + + func_enter(); + + memset(&sx_driver, 0, sizeof(sx_driver)); + sx_driver.magic = TTY_DRIVER_MAGIC; + sx_driver.driver_name = "specialix_sx"; + sx_driver.name = "ttyX"; + sx_driver.major = SX_NORMAL_MAJOR; + sx_driver.num = sx_nports; + sx_driver.type = TTY_DRIVER_TYPE_SERIAL; + sx_driver.subtype = SX_TYPE_NORMAL; + sx_driver.init_termios = tty_std_termios; + sx_driver.init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver.flags = TTY_DRIVER_REAL_RAW; + sx_driver.refcount = &sx_refcount; + sx_driver.table = sx_table; + sx_driver.termios = sx_termios; + sx_driver.termios_locked = sx_termios_locked; + + sx_driver.open = sx_open; + sx_driver.close = gs_close; + sx_driver.write = gs_write; + sx_driver.put_char = gs_put_char; + sx_driver.flush_chars = gs_flush_chars; + sx_driver.write_room = gs_write_room; + sx_driver.chars_in_buffer = gs_chars_in_buffer; + sx_driver.flush_buffer = gs_flush_buffer; + sx_driver.ioctl = sx_ioctl; + sx_driver.throttle = sx_throttle; + sx_driver.unthrottle = sx_unthrottle; + sx_driver.set_termios = gs_set_termios; + sx_driver.stop = gs_stop; + sx_driver.start = gs_start; + sx_driver.hangup = gs_hangup; + + sx_callout_driver = sx_driver; + sx_callout_driver.name = "cux"; + sx_callout_driver.major = SX_CALLOUT_MAJOR; + sx_callout_driver.subtype = SX_TYPE_CALLOUT; + + if ((error = tty_register_driver(&sx_driver))) { + printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n", + error); + return 1; + } + if ((error = tty_register_driver(&sx_callout_driver))) { + tty_unregister_driver(&sx_driver); + printk(KERN_ERR "sx: Couldn't register sx callout driver, error = %d\n", + error); + return 1; + } + + func_exit(); + return 0; +} + + +void * ckmalloc (int size) +{ + void *p; + + p = kmalloc(size, GFP_KERNEL); + if (p) + memset(p, 0, size); + return p; +} + + +static int sx_init_portstructs (int nboards, int nports) +{ + struct sx_board *board; + struct sx_port *port; + int i, j; + int addr, chans; + int portno; + + func_enter(); + + /* Many drivers statically allocate the maximum number of ports + There is no reason not to allocate them dynamically. Is there? -- REW */ + sx_ports = ckmalloc(nports * sizeof (struct sx_port)); + if (!sx_ports) + return -ENOMEM; + + sx_termios = ckmalloc(nports * sizeof (struct termios *)); + if (!sx_termios) { + kfree (sx_ports); + return -ENOMEM; + } + + sx_termios_locked = ckmalloc(nports * sizeof (struct termios *)); + if (!sx_termios_locked) { + kfree (sx_ports); + kfree (sx_termios); + return -ENOMEM; + } + + /* Adjust the values in the "driver" */ + sx_driver.termios = sx_termios; + sx_driver.termios_locked = sx_termios_locked; + + port = sx_ports; + for (i = 0; i < nboards; i++) { + board = &boards[i]; + board->ports = port; + for (j=0; j < boards[i].nports;j++) { + sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j); + port->gs.callout_termios = tty_std_termios; + port->gs.normal_termios = tty_std_termios; + port->gs.magic = SX_MAGIC; + port->gs.close_delay = HZ/2; + port->gs.closing_wait = 30 * HZ; + port->board = board; + port->gs.rd = &sx_real_driver; +#ifdef NEW_WRITE_LOCKING + port->gs.port_write_sem = MUTEX; +#endif + port++; + } + } + + port = sx_ports; + portno = 0; + for (i = 0; i < nboards; i++) { + board = &boards[i]; + board->port_base = portno; + /* Possibly the configuration was rejected. */ + sx_dprintk (SX_DEBUG_PROBE, "Board has %d channels\n", board->nports); + if (board->nports <= 0) continue; + /* XXX byteorder ?? */ + for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { + chans = sx_read_module_byte (board, addr, mc_type); + sx_dprintk (SX_DEBUG_PROBE, "Module at %x: %d channels\n", addr, chans); + sx_dprintk (SX_DEBUG_PROBE, "Port at"); + for (j=0;jch_base = sx_read_module_word (board, addr+j*2, mc_chan_pointer); + else + port->ch_base = addr + 0x100 + 0x300*j; + + sx_dprintk (SX_DEBUG_PROBE, " %x", port->ch_base); + port->line = portno++; + port++; + } + sx_dprintk (SX_DEBUG_PROBE, "\n"); + } + /* This has to be done earlier. */ + /* board->flags |= SX_BOARD_INITIALIZED; */ + } + + func_exit(); + return 0; +} + + +static void sx_release_drivers(void) +{ + func_enter(); + tty_unregister_driver(&sx_driver); + tty_unregister_driver(&sx_callout_driver); + func_exit(); +} + +#ifdef TWO_ZERO +#define PDEV unsigned char pci_bus, unsigned pci_fun +#define pdev pci_bus, pci_fun +#else +#define PDEV struct pci_dev *pdev +#endif + + +#ifdef CONFIG_PCI + /******************************************************** + * Setting bit 17 in the CNTRL register of the PLX 9050 * + * chip forces a retry on writes while a read is pending.* + * This is to prevent the card locking up on Intel Xeon * + * multiprocessor systems with the NX chipset. -- NV * + ********************************************************/ + +/* Newer cards are produced with this bit set from the configuration + EEprom. As the bit is read/write for the CPU, we can fix it here, + if we detect that it isn't set correctly. -- REW */ + +void fix_sx_pci (PDEV, struct sx_board *board) +{ + unsigned int hwbase; + unsigned long rebase; + int t; + +#define CNTRL_REG_OFFSET 0x14 + + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); + hwbase &= PCI_BASE_ADDRESS_MEM_MASK; + rebase = (ulong) ioremap(hwbase, 0x80); + t = readb (rebase + CNTRL_REG_OFFSET*4 + 2); + if (t != 0x06) { + printk (KERN_DEBUG "sx: performing cntrl reg fix: %02x -> 06\n", t); + writeb (0x06, rebase + CNTRL_REG_OFFSET*4+2); + } + my_iounmap (hwbase, rebase); + +} +#endif + + +#ifdef MODULE +#define sx_init init_module +#endif + +int sx_init(void) +{ + int i; + int found = 0; + struct sx_board *board; + +#ifdef CONFIG_PCI +#ifndef TWO_ZERO + struct pci_dev *pdev = NULL; +#else + unsigned char pci_bus, pci_fun; + /* in 2.2.x pdev is a pointer defining a PCI device. In 2.0 its the bus/fn */ +#endif + unsigned int tint; + unsigned short tshort; +#endif + + func_enter(); + sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug); + if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) { + printk (KERN_WARNING "sx: sx_debug is an address, instead of a value. " + "Assuming -1.\n"); + printk ("(%p)\n", &sx_debug); + sx_debug=-1; + } + +#ifdef CONFIG_PCI + if (pci_present ()) { +#ifndef TWO_ZERO + while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + pdev))) { +#else + for (i=0;i< SX_NBOARDS;i++) { + if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, i, + &pci_bus, &pci_fun)) break; +#endif + /* Specialix has a whole bunch of cards with + 0x2000 as the device ID. They say its because + the standard requires it. Stupid standard. */ + /* It seems that reading a word doesn't work reliably on 2.0. + Also, reading a non-aligned dword doesn't work. So we read the + whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) + ourselves */ + /* I don't know why the define doesn't work, constant 0x2c does --REW */ + pci_read_config_dword (pdev, 0x2c, &tint); + tshort = (tint >> 16) & 0xffff; + sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); + /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ + if (tshort != 0x0200) { + sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", + tshort); + continue; + } + board = &boards[found]; + + pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint); + board->hw_base = tint & PCI_BASE_ADDRESS_MEM_MASK; + board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN); + board->irq = get_irq (pdev); + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SX_PCI_BOARD; + + sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%x(%d).\n", + tint, boards[found].base, board->irq); + + if (probe_sx (board)) { + found++; + fix_sx_pci (pdev, board); + } else + my_iounmap (board->hw_base, board->base); + } + } +#endif + + for (i=0;ihw_base = sx_probe_addrs[i]; + board->base = (ulong) ioremap(board->hw_base, SX_WINDOW_LEN); + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SX_ISA_BOARD; + board->irq = sx_irqmask?-1:0; + + if (probe_sx (board)) { + found++; + } else { + my_iounmap (board->hw_base, board->base); + } + } + + for (i=0;ihw_base = si_probe_addrs[i]; + board->base = (ulong) ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_ISA_BOARD; + board->irq = sx_irqmask ?-1:0; + + if (probe_si (board)) { + found++; + } else { + my_iounmap (board->hw_base, board->base); + } + } + + if (found) { + printk (KERN_INFO "sx: total of %d boards detected.\n", found); + + if (misc_register(&sx_fw_device) < 0) { + printk(KERN_ERR "SX: Unable to register firmware loader driver.\n"); + return -EIO; + } + } + + func_exit(); + return found?0:-EIO; +} + + + +void cleanup_module(void) +{ + int i; + struct sx_board *board; + + func_enter(); + for (i = 0; i < SX_NBOARDS; i++) { + board = &boards[i]; + if (board->flags & SX_BOARD_INITIALIZED) { + sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %x\n", board->base); + /* The board should stop messing with us. + (actually I mean the interrupt) */ + sx_reset (board); + if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) + free_irq (board->irq, board); + + /* It is safe/allowed to del_timer a non-active timer */ + del_timer (& board->timer); + my_iounmap (board->hw_base, board->base); + } + } + if (misc_deregister(&sx_fw_device) < 0) { + printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); + } + sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); + if (sx_initialized) + sx_release_drivers (); + + kfree (sx_ports); + kfree (sx_termios); + kfree (sx_termios_locked); + func_exit(); +} + + +#ifdef DEBUG +void my_hd (unsigned char *addr, int len) +{ + int i, j, ch; + + for (i=0;i 0x7f)?'.':ch)); + } + printk ("\n"); + } +} +#endif + +#ifdef MODULE +#undef func_enter +#undef func_exit + +#include "generic_serial.c" +#endif + + +/* + * Anybody who knows why this doesn't work for me, please tell me -- REW. + * Snatched from scsi.c (fixed one spelling error): + * Overrides for Emacs so that we follow Linus' tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/sx.h linux/drivers/char/sx.h --- v2.3.12/linux/drivers/char/sx.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/sx.h Thu Aug 5 14:47:44 1999 @@ -0,0 +1,180 @@ + +/* + * sx.h + * + * Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl + * + * SX serial driver. + * -- Supports SI, XIO and SX host cards. + * -- Supports TAs, MTAs and SXDCs. + * + * Version 1.3 -- March, 1999. + * + */ + +#define SX_NBOARDS 4 +#define SX_PORTSPERBOARD 32 +#define SX_NPORTS (SX_NBOARDS * SX_PORTSPERBOARD) + +#ifdef __KERNEL__ + +#define SX_MAGIC 0x12345678 + +struct sx_port { + struct gs_port gs; + /* + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + */ + struct wait_queue *shutdown_wait; + int ch_base; + int c_dcd; + struct sx_board *board; + int line; + int locks; +}; + +struct sx_board { + int magic; + unsigned int base; + unsigned int hw_base; + int port_base; /* Number of the first port */ + struct sx_port *ports; + int nports; + int flags; + int irq; + int poll; + int ta_type; + struct timer_list timer; + int locks; +}; + +struct vpd_prom { + unsigned short id; + char hwrev; + char hwass; + int uniqid; + char myear; + char mweek; + char hw_feature[5]; + char oem_id; + char identifier[16]; +}; + +#ifndef MOD_RS232DB25MALE +#define MOD_RS232DB25MALE 0x0a +#endif + + +#define SX_BOARD_PRESENT 0x00000001 +#define SX_ISA_BOARD 0x00000002 +#define SX_PCI_BOARD 0x00000004 +#define SI_ISA_BOARD 0x00000008 +#define SX_BOARD_INITIALIZED 0x00000010 +#define SX_IRQ_ALLOCATED 0x00000020 + +#define SX_BOARD_TYPE (SX_ISA_BOARD|SX_PCI_BOARD|SI_ISA_BOARD) + +#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_ISA_BOARD)) +#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD) + + +#define SERIAL_TYPE_NORMAL 1 + +/* The SI processor clock is required to calculate the cc_int_count register + value for the SI cards. */ +#define SI_PROCESSOR_CLOCK 25000000 + + +/* port flags */ +/* Make sure these don't clash with gs flags or async flags */ +#define SX_RX_THROTTLE 0x0000001 + + + +#define SX_PORT_TRANSMIT_LOCK 0 +#define SX_BOARD_INTR_LOCK 0 + + + +/* Debug flags. Add these together to get more debug info. */ + +#define SX_DEBUG_OPEN 0x00000001 +#define SX_DEBUG_SETTING 0x00000002 +#define SX_DEBUG_FLOW 0x00000004 +#define SX_DEBUG_MODEMSIGNALS 0x00000008 +#define SX_DEBUG_TERMIOS 0x00000010 +#define SX_DEBUG_TRANSMIT 0x00000020 +#define SX_DEBUG_RECEIVE 0x00000040 +#define SX_DEBUG_INTERRUPTS 0x00000080 +#define SX_DEBUG_PROBE 0x00000100 +#define SX_DEBUG_INIT 0x00000200 +#define SX_DEBUG_CLEANUP 0x00000400 +#define SX_DEBUG_CLOSE 0x00000800 +#define SX_DEBUG_FIRMWARE 0x00001000 +#define SX_DEBUG_MEMTEST 0x00002000 + +#define SX_DEBUG_ALL 0xffffffff + + +#define O_OTHER(tty) \ + ((O_OLCUC(tty)) ||\ + (O_ONLCR(tty)) ||\ + (O_OCRNL(tty)) ||\ + (O_ONOCR(tty)) ||\ + (O_ONLRET(tty)) ||\ + (O_OFILL(tty)) ||\ + (O_OFDEL(tty)) ||\ + (O_NLDLY(tty)) ||\ + (O_CRDLY(tty)) ||\ + (O_TABDLY(tty)) ||\ + (O_BSDLY(tty)) ||\ + (O_VTDLY(tty)) ||\ + (O_FFDLY(tty))) + +/* Same for input. */ +#define I_OTHER(tty) \ + ((I_INLCR(tty)) ||\ + (I_IGNCR(tty)) ||\ + (I_ICRNL(tty)) ||\ + (I_IUCLC(tty)) ||\ + (L_ISIG(tty))) + +#define MOD_TA ( TA>>4) +#define MOD_MTA (MTA_CD1400>>4) +#define MOD_SXDC ( SXDC>>4) + + +/* We copy the download code over to the card in chunks of ... bytes */ +#define SX_CHUNK_SIZE 128 + +#endif /* __KERNEL__ */ + + + +/* Specialix document 6210046-11 page 3 */ +#define SPX(X) (('S'<<24) | ('P' << 16) | (X)) + +/* Specialix-Linux specific IOCTLS. */ +#define SPXL(X) (SPX(('L' << 8) | (X))) + + +#define SXIO_SET_BOARD SPXL(0x01) +#define SXIO_GET_TYPE SPXL(0x02) +#define SXIO_DOWNLOAD SPXL(0x03) +#define SXIO_INIT SPXL(0x04) +#define SXIO_SETDEBUG SPXL(0x05) +#define SXIO_GETDEBUG SPXL(0x06) +#define SXIO_DO_RAMTEST SPXL(0x07) +#define SXIO_SETGSDEBUG SPXL(0x08) +#define SXIO_GETGSDEBUG SPXL(0x09) + + +#ifndef SXCTL_MISC_MINOR +/* Allow others to gather this into "major.h" or something like that */ +#define SXCTL_MISC_MINOR 167 +#endif + +#define SX_TYPE_SX 0x01 +#define SX_TYPE_SI 0x02 + diff -u --recursive --new-file v2.3.12/linux/drivers/char/sxboards.h linux/drivers/char/sxboards.h --- v2.3.12/linux/drivers/char/sxboards.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/sxboards.h Thu Aug 5 14:47:44 1999 @@ -0,0 +1,181 @@ +/************************************************************************/ +/* */ +/* Title : SX/SI/XIO Board Hardware Definitions */ +/* */ +/* Author : N.P.Vassallo */ +/* */ +/* Creation : 16th March 1998 */ +/* */ +/* Version : 3.0.0 */ +/* */ +/* Copyright : (c) Specialix International Ltd. 1998 */ +/* */ +/* Description : Prototypes, structures and definitions */ +/* describing the SX/SI/XIO board hardware */ +/* */ +/************************************************************************/ + +/* History... + +3.0.0 16/03/98 NPV Creation. + +*/ + +#ifndef _sxboards_h /* If SXBOARDS.H not already defined */ +#define _sxboards_h 1 + +/***************************************************************************** +******************************* ****************************** +******************************* Board Types ****************************** +******************************* ****************************** +*****************************************************************************/ + +/* BUS types... */ +#define BUS_ISA 0 +#define BUS_MCA 1 +#define BUS_EISA 2 +#define BUS_PCI 3 + +/* Board phases... */ +#define SI1_Z280 1 +#define SI2_Z280 2 +#define SI3_T225 3 + +/* Board types... */ +#define CARD_TYPE(bus,phase) (bus<<4|phase) +#define CARD_BUS(type) ((type>>4)&0xF) +#define CARD_PHASE(type) (type&0xF) + +#define TYPE_SI2_ISA CARD_TYPE(BUS_ISA,SI2_Z280) +#define TYPE_SI2_EISA CARD_TYPE(BUS_EISA,SI2_Z280) +#define TYPE_SI2_PCI CARD_TYPE(BUS_PCI,SI2_Z280) + +#define TYPE_SX_ISA CARD_TYPE(BUS_ISA,SI3_T225) +#define TYPE_SX_PCI CARD_TYPE(BUS_PCI,SI3_T225) + +/***************************************************************************** +****************************** ****************************** +****************************** Phase 2 Z280 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* ISA board details... */ +#define SI2_ISA_WINDOW_LEN 0x8000 /* 32 Kbyte shared memory window */ +#define SI2_ISA_MEMORY_LEN 0x7FF8 /* Usable memory */ +#define SI2_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +#define SI2_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +#define SI2_ISA_ADDR_STEP SI2_ISA_WINDOW_LEN/* ISA board address step */ +#define SI2_ISA_IRQ_MASK 0x9800 /* IRQs 15,12,11 */ + +/* ISA board, register definitions... */ +#define SI2_ISA_ID_BASE 0x7FF8 /* READ: Board ID string */ +#define SI2_ISA_RESET SI2_ISA_ID_BASE /* WRITE: Host Reset */ +#define SI2_ISA_IRQ11 (SI2_ISA_ID_BASE+1) /* WRITE: Set IRQ11 */ +#define SI2_ISA_IRQ12 (SI2_ISA_ID_BASE+2) /* WRITE: Set IRQ12 */ +#define SI2_ISA_IRQ15 (SI2_ISA_ID_BASE+3) /* WRITE: Set IRQ15 */ +#define SI2_ISA_IRQSET (SI2_ISA_ID_BASE+4) /* WRITE: Set Host Interrupt */ +#define SI2_ISA_INTCLEAR (SI2_ISA_ID_BASE+5) /* WRITE: Enable Host Interrupt */ + +#define SI2_ISA_IRQ11_SET 0x10 +#define SI2_ISA_IRQ11_CLEAR 0x00 +#define SI2_ISA_IRQ12_SET 0x10 +#define SI2_ISA_IRQ12_CLEAR 0x00 +#define SI2_ISA_IRQ15_SET 0x10 +#define SI2_ISA_IRQ15_CLEAR 0x00 +#define SI2_ISA_INTCLEAR_SET 0x10 +#define SI2_ISA_INTCLEAR_CLEAR 0x00 +#define SI2_ISA_IRQSET_CLEAR 0x10 +#define SI2_ISA_IRQSET_SET 0x00 +#define SI2_ISA_RESET_SET 0x00 +#define SI2_ISA_RESET_CLEAR 0x10 + +/* PCI board details... */ +#define SI2_PCI_WINDOW_LEN 0x100000 /* 1 Mbyte memory window */ + +/* PCI board register definitions... */ +#define SI2_PCI_SET_IRQ 0x40001 /* Set Host Interrupt */ +#define SI2_PCI_RESET 0xC0001 /* Host Reset */ + +/***************************************************************************** +****************************** ****************************** +****************************** Phase 3 T225 ****************************** +****************************** ****************************** +*****************************************************************************/ + +/* General board details... */ +#define SX_WINDOW_LEN 64*1024 /* 64 Kbyte memory window */ + +/* ISA board details... */ +#define SX_ISA_ADDR_LOW 0x0A0000 /* Lowest address = 640 Kbyte */ +#define SX_ISA_ADDR_HIGH 0xFF8000 /* Highest address = 16Mbyte - 32Kbyte */ +#define SX_ISA_ADDR_STEP SX_WINDOW_LEN /* ISA board address step */ +#define SX_ISA_IRQ_MASK 0x9E00 /* IRQs 15,12,11,10,9 */ + +/* Hardware register definitions... */ +#define SX_EVENT_STATUS 0x7800 /* READ: T225 Event Status */ +#define SX_EVENT_STROBE 0x7800 /* WRITE: T225 Event Strobe */ +#define SX_EVENT_ENABLE 0x7880 /* WRITE: T225 Event Enable */ +#define SX_VPD_ROM 0x7C00 /* READ: Vital Product Data ROM */ +#define SX_CONFIG 0x7C00 /* WRITE: Host Configuration Register */ +#define SX_IRQ_STATUS 0x7C80 /* READ: Host Interrupt Status */ +#define SX_SET_IRQ 0x7C80 /* WRITE: Set Host Interrupt */ +#define SX_RESET_STATUS 0x7D00 /* READ: Host Reset Status */ +#define SX_RESET 0x7D00 /* WRITE: Host Reset */ +#define SX_RESET_IRQ 0x7D80 /* WRITE: Reset Host Interrupt */ + +/* SX_VPD_ROM definitions... */ +#define SX_VPD_SLX_ID1 0x00 +#define SX_VPD_SLX_ID2 0x01 +#define SX_VPD_HW_REV 0x02 +#define SX_VPD_HW_ASSEM 0x03 +#define SX_VPD_UNIQUEID4 0x04 +#define SX_VPD_UNIQUEID3 0x05 +#define SX_VPD_UNIQUEID2 0x06 +#define SX_VPD_UNIQUEID1 0x07 +#define SX_VPD_MANU_YEAR 0x08 +#define SX_VPD_MANU_WEEK 0x09 +#define SX_VPD_IDENT 0x10 +#define SX_VPD_IDENT_STRING "JET HOST BY KEV#" + +/* SX unique identifiers... */ +#define SX_UNIQUEID_MASK 0xF0 +#define SX_ISA_UNIQUEID1 0x20 +#define SX_PCI_UNIQUEID1 0x50 + +/* SX_CONFIG definitions... */ +#define SX_CONF_BUSEN 0x02 /* Enable T225 memory and I/O */ +#define SX_CONF_HOSTIRQ 0x04 /* Enable board to host interrupt */ + +/* SX bootstrap... */ +#define SX_BOOTSTRAP "\x28\x20\x21\x02\x60\x0a" +#define SX_BOOTSTRAP_SIZE 6 +#define SX_BOOTSTRAP_ADDR (0x8000-SX_BOOTSTRAP_SIZE) + +/***************************************************************************** +********************************** ********************************** +********************************** EISA ********************************** +********************************** ********************************** +*****************************************************************************/ + +#define SI2_EISA_OFF 0x42 +#define SI2_EISA_VAL 0x01 + +/***************************************************************************** +*********************************** ********************************** +*********************************** PCI ********************************** +*********************************** ********************************** +*****************************************************************************/ + +/* General definitions... */ + +#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ +#define SPX_DEVICE_ID 0x4000 /* SI/XIO boards */ +#define SPX_PLXDEVICE_ID 0x2000 /* SX boards */ + +#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ +#define SI2_SUB_SYS_ID 0x400 /* Phase 2 (Z280) board */ +#define SX_SUB_SYS_ID 0x200 /* Phase 3 (t225) board */ + +#endif /*_sxboards_h */ + +/* End of SXBOARDS.H */ diff -u --recursive --new-file v2.3.12/linux/drivers/char/sxwindow.h linux/drivers/char/sxwindow.h --- v2.3.12/linux/drivers/char/sxwindow.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/sxwindow.h Thu Aug 5 14:47:44 1999 @@ -0,0 +1,393 @@ +/************************************************************************/ +/* */ +/* Title : SX Shared Memory Window Structure */ +/* */ +/* Author : N.P.Vassallo */ +/* */ +/* Creation : 16th March 1998 */ +/* */ +/* Version : 3.0.0 */ +/* */ +/* Copyright : (c) Specialix International Ltd. 1998 */ +/* */ +/* Description : Prototypes, structures and definitions */ +/* describing the SX/SI/XIO cards shared */ +/* memory window structure: */ +/* SXCARD */ +/* SXMODULE */ +/* SXCHANNEL */ +/* */ +/************************************************************************/ + +/* History... + +3.0.0 16/03/98 NPV Creation. (based on STRUCT.H) + +*/ + +#ifndef _sxwindow_h /* If SXWINDOW.H not already defined */ +#define _sxwindow_h 1 + +/***************************************************************************** +*************************** *************************** +*************************** Common Definitions *************************** +*************************** *************************** +*****************************************************************************/ + +typedef struct _SXCARD *PSXCARD; /* SXCARD structure pointer */ +typedef struct _SXMODULE *PMOD; /* SXMODULE structure pointer */ +typedef struct _SXCHANNEL *PCHAN; /* SXCHANNEL structure pointer */ + +/***************************************************************************** +********************************* ********************************* +********************************* SXCARD ********************************* +********************************* ********************************* +*****************************************************************************/ + +typedef struct _SXCARD +{ + BYTE cc_init_status; /* 0x00 Initialisation status */ + BYTE cc_mem_size; /* 0x01 Size of memory on card */ + WORD cc_int_count; /* 0x02 Interrupt count */ + WORD cc_revision; /* 0x04 Download code revision */ + BYTE cc_isr_count; /* 0x06 Count when ISR is run */ + BYTE cc_main_count; /* 0x07 Count when main loop is run */ + WORD cc_int_pending; /* 0x08 Interrupt pending */ + WORD cc_poll_count; /* 0x0A Count when poll is run */ + BYTE cc_int_set_count; /* 0x0C Count when host interrupt is set */ + BYTE cc_rfu[0x80 - 0x0D]; /* 0x0D Pad structure to 128 bytes (0x80) */ + +} SXCARD; + +/* SXCARD.cc_init_status definitions... */ +#define ADAPTERS_FOUND (BYTE)0x01 +#define NO_ADAPTERS_FOUND (BYTE)0xFF + +/* SXCARD.cc_mem_size definitions... */ +#define SX_MEMORY_SIZE (BYTE)0x40 + +/* SXCARD.cc_int_count definitions... */ +#define INT_COUNT_DEFAULT 100 /* Hz */ + +/***************************************************************************** +******************************** ******************************** +******************************** SXMODULE ******************************** +******************************** ******************************** +*****************************************************************************/ + +#define TOP_POINTER(a) ((a)|0x8000) /* Sets top bit of word */ +#define UNTOP_POINTER(a) ((a)&~0x8000) /* Clears top bit of word */ + +typedef struct _SXMODULE +{ + WORD mc_next; /* 0x00 Next module "pointer" (ORed with 0x8000) */ + BYTE mc_type; /* 0x02 Type of TA in terms of number of channels */ + BYTE mc_mod_no; /* 0x03 Module number on SI bus cable (0 closest to card) */ + BYTE mc_dtr; /* 0x04 Private DTR copy (TA only) */ + BYTE mc_rfu1; /* 0x05 Reserved */ + WORD mc_uart; /* 0x06 UART base address for this module */ + BYTE mc_chip; /* 0x08 Chip type / number of ports */ + BYTE mc_current_uart; /* 0x09 Current uart selected for this module */ +#ifdef DOWNLOAD + PCHAN mc_chan_pointer[8]; /* 0x0A Pointer to each channel structure */ +#else + WORD mc_chan_pointer[8]; /* 0x0A Define as WORD if not compiling into download */ +#endif + WORD mc_rfu2; /* 0x1A Reserved */ + BYTE mc_opens1; /* 0x1C Number of open ports on first four ports on MTA/SXDC */ + BYTE mc_opens2; /* 0x1D Number of open ports on second four ports on MTA/SXDC */ + BYTE mc_mods; /* 0x1E Types of connector module attached to MTA/SXDC */ + BYTE mc_rev1; /* 0x1F Revision of first CD1400 on MTA/SXDC */ + BYTE mc_rev2; /* 0x20 Revision of second CD1400 on MTA/SXDC */ + BYTE mc_mtaasic_rev; /* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */ + BYTE mc_rfu3[0x100 - 0x22]; /* 0x22 Pad structure to 256 bytes (0x100) */ + +} SXMODULE; + +/* SXMODULE.mc_type definitions... */ +#define FOUR_PORTS (BYTE)4 +#define EIGHT_PORTS (BYTE)8 + +/* SXMODULE.mc_chip definitions... */ +#define CHIP_MASK 0xF0 +#define TA (BYTE)0 +#define TA4 (TA | FOUR_PORTS) +#define TA8 (TA | EIGHT_PORTS) +#define TA4_ASIC (BYTE)0x0A +#define TA8_ASIC (BYTE)0x0B +#define MTA_CD1400 (BYTE)0x28 +#define SXDC (BYTE)0x48 + +/* SXMODULE.mc_mods definitions... */ +#define MOD_RS232DB25 0x00 /* RS232 DB25 (socket/plug) */ +#define MOD_RS232RJ45 0x01 /* RS232 RJ45 (shielded/opto-isolated) */ +#define MOD_RESERVED_2 0x02 /* Reserved (RS485) */ +#define MOD_RS422DB25 0x03 /* RS422 DB25 Socket */ +#define MOD_RESERVED_4 0x04 /* Reserved */ +#define MOD_PARALLEL 0x05 /* Parallel */ +#define MOD_RESERVED_6 0x06 /* Reserved (RS423) */ +#define MOD_RESERVED_7 0x07 /* Reserved */ +#define MOD_2_RS232DB25 0x08 /* Rev 2.0 RS232 DB25 (socket/plug) */ +#define MOD_2_RS232RJ45 0x09 /* Rev 2.0 RS232 RJ45 */ +#define MOD_RESERVED_A 0x0A /* Rev 2.0 Reserved */ +#define MOD_2_RS422DB25 0x0B /* Rev 2.0 RS422 DB25 */ +#define MOD_RESERVED_C 0x0C /* Rev 2.0 Reserved */ +#define MOD_2_PARALLEL 0x0D /* Rev 2.0 Parallel */ +#define MOD_RESERVED_E 0x0E /* Rev 2.0 Reserved */ +#define MOD_BLANK 0x0F /* Blank Panel */ + +/***************************************************************************** +******************************** ******************************* +******************************** SXCHANNEL ******************************* +******************************** ******************************* +*****************************************************************************/ + +#define TX_BUFF_OFFSET 0x60 /* Transmit buffer offset in channel structure */ +#define BUFF_POINTER(a) (((a)+TX_BUFF_OFFSET)|0x8000) +#define UNBUFF_POINTER(a) (jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) +#define BUFFER_SIZE 256 +#define HIGH_WATER ((BUFFER_SIZE / 4) * 3) +#define LOW_WATER (BUFFER_SIZE / 4) + +typedef struct _SXCHANNEL +{ + WORD next_item; /* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */ + WORD addr_uart; /* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */ + WORD module; /* 0x04 Offset from window base of parent SXMODULE structure */ + BYTE type; /* 0x06 Chip type / number of ports (copy of mc_chip) */ + BYTE chan_number; /* 0x07 Channel number on the TA/MTA/SXDC */ + WORD xc_status; /* 0x08 Flow control and I/O status */ + BYTE hi_rxipos; /* 0x0A Receive buffer input index */ + BYTE hi_rxopos; /* 0x0B Receive buffer output index */ + BYTE hi_txopos; /* 0x0C Transmit buffer output index */ + BYTE hi_txipos; /* 0x0D Transmit buffer input index */ + BYTE hi_hstat; /* 0x0E Command register */ + BYTE dtr_bit; /* 0x0F INTERNAL DTR control byte (TA only) */ + BYTE txon; /* 0x10 INTERNAL copy of hi_txon */ + BYTE txoff; /* 0x11 INTERNAL copy of hi_txoff */ + BYTE rxon; /* 0x12 INTERNAL copy of hi_rxon */ + BYTE rxoff; /* 0x13 INTERNAL copy of hi_rxoff */ + BYTE hi_mr1; /* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/ + BYTE hi_mr2; /* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/ + BYTE hi_csr; /* 0x16 Clock Select Register (baud rate) */ + BYTE hi_op; /* 0x17 Modem Output Signal */ + BYTE hi_ip; /* 0x18 Modem Input Signal */ + BYTE hi_state; /* 0x19 Channel status */ + BYTE hi_prtcl; /* 0x1A Channel protocol (flow control) */ + BYTE hi_txon; /* 0x1B Transmit XON character */ + BYTE hi_txoff; /* 0x1C Transmit XOFF character */ + BYTE hi_rxon; /* 0x1D Receive XON character */ + BYTE hi_rxoff; /* 0x1E Receive XOFF character */ + BYTE close_prev; /* 0x1F INTERNAL channel previously closed flag */ + BYTE hi_break; /* 0x20 Break and error control */ + BYTE break_state; /* 0x21 INTERNAL copy of hi_break */ + BYTE hi_mask; /* 0x22 Mask for received data */ + BYTE mask; /* 0x23 INTERNAL copy of hi_mask */ + BYTE mod_type; /* 0x24 MTA/SXDC hardware module type */ + BYTE ccr_state; /* 0x25 INTERNAL MTA/SXDC state of CCR register */ + BYTE ip_mask; /* 0x26 Input handshake mask */ + BYTE hi_parallel; /* 0x27 Parallel port flag */ + BYTE par_error; /* 0x28 Error code for parallel loopback test */ + BYTE any_sent; /* 0x29 INTERNAL data sent flag */ + BYTE asic_txfifo_size; /* 0x2A INTERNAL SXDC transmit FIFO size */ + BYTE rfu1[2]; /* 0x2B Reserved */ + BYTE csr; /* 0x2D INTERNAL copy of hi_csr */ +#ifdef DOWNLOAD + PCHAN nextp; /* 0x2E Offset from window base of next channel structure */ +#else + WORD nextp; /* 0x2E Define as WORD if not compiling into download */ +#endif + BYTE prtcl; /* 0x30 INTERNAL copy of hi_prtcl */ + BYTE mr1; /* 0x31 INTERNAL copy of hi_mr1 */ + BYTE mr2; /* 0x32 INTERNAL copy of hi_mr2 */ + BYTE hi_txbaud; /* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */ + BYTE hi_rxbaud; /* 0x34 Extended receive baud rate (SXDC only if((hi_csr&0xF0)==0xF0) */ + BYTE txbreak_state; /* 0x35 INTERNAL MTA/SXDC transmit break state */ + BYTE txbaud; /* 0x36 INTERNAL copy of hi_txbaud */ + BYTE rxbaud; /* 0x37 INTERNAL copy of hi_rxbaud */ + WORD err_framing; /* 0x38 Count of receive framing errors */ + WORD err_parity; /* 0x3A Count of receive parity errors */ + WORD err_overrun; /* 0x3C Count of receive overrun errors */ + WORD err_overflow; /* 0x3E Count of receive buffer overflow errors */ + BYTE rfu2[TX_BUFF_OFFSET - 0x40]; /* 0x40 Reserved until hi_txbuf */ + BYTE hi_txbuf[BUFFER_SIZE]; /* 0x060 Transmit buffer */ + BYTE hi_rxbuf[BUFFER_SIZE]; /* 0x160 Receive buffer */ + BYTE rfu3[0x300 - 0x260]; /* 0x260 Reserved until 768 bytes (0x300) */ + +} SXCHANNEL; + +/* SXCHANNEL.addr_uart definitions... */ +#define FASTPATH 0x1000 /* Set to indicate fast rx/tx processing (TA only) */ + +/* SXCHANNEL.xc_status definitions... */ +#define X_TANY 0x0001 /* XON is any character (TA only) */ +#define X_TION 0x0001 /* Tx interrupts on (MTA only) */ +#define X_TXEN 0x0002 /* Tx XON/XOFF enabled (TA only) */ +#define X_RTSEN 0x0002 /* RTS FLOW enabled (MTA only) */ +#define X_TXRC 0x0004 /* XOFF received (TA only) */ +#define X_RTSLOW 0x0004 /* RTS dropped (MTA only) */ +#define X_RXEN 0x0008 /* Rx XON/XOFF enabled */ +#define X_ANYXO 0x0010 /* XOFF pending/sent or RTS dropped */ +#define X_RXSE 0x0020 /* Rx XOFF sent */ +#define X_NPEND 0x0040 /* Rx XON pending or XOFF pending */ +#define X_FPEND 0x0080 /* Rx XOFF pending */ +#define C_CRSE 0x0100 /* Carriage return sent (TA only) */ +#define C_TEMR 0x0100 /* Tx empty requested (MTA only) */ +#define C_TEMA 0x0200 /* Tx empty acked (MTA only) */ +#define C_ANYP 0x0200 /* Any protocol bar tx XON/XOFF (TA only) */ +#define C_EN 0x0400 /* Cooking enabled (on MTA means port is also || */ +#define C_HIGH 0x0800 /* Buffer previously hit high water */ +#define C_CTSEN 0x1000 /* CTS automatic flow-control enabled */ +#define C_DCDEN 0x2000 /* DCD/DTR checking enabled */ +#define C_BREAK 0x4000 /* Break detected */ +#define C_RTSEN 0x8000 /* RTS automatic flow control enabled (MTA only) */ +#define C_PARITY 0x8000 /* Parity checking enabled (TA only) */ + +/* SXCHANNEL.hi_hstat definitions... */ +#define HS_IDLE_OPEN 0x00 /* Channel open state */ +#define HS_LOPEN 0x02 /* Local open command (no modem monitoring) */ +#define HS_MOPEN 0x04 /* Modem open command (wait for DCD signal) */ +#define HS_IDLE_MPEND 0x06 /* Waiting for DCD signal state */ +#define HS_CONFIG 0x08 /* Configuration command */ +#define HS_CLOSE 0x0A /* Close command */ +#define HS_START 0x0C /* Start transmit break command */ +#define HS_STOP 0x0E /* Stop transmit break command */ +#define HS_IDLE_CLOSED 0x10 /* Closed channel state */ +#define HS_IDLE_BREAK 0x12 /* Transmit break state */ +#define HS_FORCE_CLOSED 0x14 /* Force close command */ +#define HS_RESUME 0x16 /* Clear pending XOFF command */ +#define HS_WFLUSH 0x18 /* Flush transmit buffer command */ +#define HS_RFLUSH 0x1A /* Flush receive buffer command */ +#define HS_SUSPEND 0x1C /* Suspend output command (like XOFF received) */ +#define PARALLEL 0x1E /* Parallel port loopback test command (Diagnostics Only) */ +#define ENABLE_RX_INTS 0x20 /* Enable receive interrupts command (Diagnostics Only) */ +#define ENABLE_TX_INTS 0x22 /* Enable transmit interrupts command (Diagnostics Only) */ +#define ENABLE_MDM_INTS 0x24 /* Enable modem interrupts command (Diagnostics Only) */ +#define DISABLE_INTS 0x26 /* Disable interrupts command (Diagnostics Only) */ + +/* SXCHANNEL.hi_mr1 definitions... */ +#define MR1_BITS 0x03 /* Data bits mask */ +#define MR1_5_BITS 0x00 /* 5 data bits */ +#define MR1_6_BITS 0x01 /* 6 data bits */ +#define MR1_7_BITS 0x02 /* 7 data bits */ +#define MR1_8_BITS 0x03 /* 8 data bits */ +#define MR1_PARITY 0x1C /* Parity mask */ +#define MR1_ODD 0x04 /* Odd parity */ +#define MR1_EVEN 0x00 /* Even parity */ +#define MR1_WITH 0x00 /* Parity enabled */ +#define MR1_FORCE 0x08 /* Force parity */ +#define MR1_NONE 0x10 /* No parity */ +#define MR1_NOPARITY MR1_NONE /* No parity */ +#define MR1_ODDPARITY (MR1_WITH|MR1_ODD) /* Odd parity */ +#define MR1_EVENPARITY (MR1_WITH|MR1_EVEN) /* Even parity */ +#define MR1_MARKPARITY (MR1_FORCE|MR1_ODD) /* Mark parity */ +#define MR1_SPACEPARITY (MR1_FORCE|MR1_EVEN) /* Space parity */ +#define MR1_RTS_RXFLOW 0x80 /* RTS receive flow control */ + +/* SXCHANNEL.hi_mr2 definitions... */ +#define MR2_STOP 0x0F /* Stop bits mask */ +#define MR2_1_STOP 0x07 /* 1 stop bit */ +#define MR2_2_STOP 0x0F /* 2 stop bits */ +#define MR2_CTS_TXFLOW 0x10 /* CTS transmit flow control */ +#define MR2_RTS_TOGGLE 0x20 /* RTS toggle on transmit */ +#define MR2_NORMAL 0x00 /* Normal mode */ +#define MR2_AUTO 0x40 /* Auto-echo mode (TA only) */ +#define MR2_LOCAL 0x80 /* Local echo mode */ +#define MR2_REMOTE 0xC0 /* Remote echo mode (TA only) */ + +/* SXCHANNEL.hi_csr definitions... */ +#define CSR_75 0x0 /* 75 baud */ +#define CSR_110 0x1 /* 110 baud (TA), 115200 (MTA/SXDC) */ +#define CSR_38400 0x2 /* 38400 baud */ +#define CSR_150 0x3 /* 150 baud */ +#define CSR_300 0x4 /* 300 baud */ +#define CSR_600 0x5 /* 600 baud */ +#define CSR_1200 0x6 /* 1200 baud */ +#define CSR_2000 0x7 /* 2000 baud */ +#define CSR_2400 0x8 /* 2400 baud */ +#define CSR_4800 0x9 /* 4800 baud */ +#define CSR_1800 0xA /* 1800 baud */ +#define CSR_9600 0xB /* 9600 baud */ +#define CSR_19200 0xC /* 19200 baud */ +#define CSR_57600 0xD /* 57600 baud */ +#define CSR_EXTBAUD 0xF /* Extended baud rate (hi_txbaud/hi_rxbaud) */ + +/* SXCHANNEL.hi_op definitions... */ +#define OP_RTS 0x01 /* RTS modem output signal */ +#define OP_DTR 0x02 /* DTR modem output signal */ + +/* SXCHANNEL.hi_ip definitions... */ +#define IP_CTS 0x02 /* CTS modem input signal */ +#define IP_DCD 0x04 /* DCD modem input signal */ +#define IP_DSR 0x20 /* DTR modem input signal */ +#define IP_RI 0x40 /* RI modem input signal */ + +/* SXCHANNEL.hi_state definitions... */ +#define ST_BREAK 0x01 /* Break received (clear with config) */ +#define ST_DCD 0x02 /* DCD signal changed state */ + +/* SXCHANNEL.hi_prtcl definitions... */ +#define SP_TANY 0x01 /* Transmit XON/XANY (if SP_TXEN enabled) */ +#define SP_TXEN 0x02 /* Transmit XON/XOFF flow control */ +#define SP_CEN 0x04 /* Cooking enabled */ +#define SP_RXEN 0x08 /* Rx XON/XOFF enabled */ +#define SP_DCEN 0x20 /* DCD / DTR check */ +#define SP_DTR_RXFLOW 0x40 /* DTR receive flow control */ +#define SP_PAEN 0x80 /* Parity checking enabled */ + +/* SXCHANNEL.hi_break definitions... */ +#define BR_IGN 0x01 /* Ignore any received breaks */ +#define BR_INT 0x02 /* Interrupt on received break */ +#define BR_PARMRK 0x04 /* Enable parmrk parity error processing */ +#define BR_PARIGN 0x08 /* Ignore chars with parity errors */ +#define BR_ERRINT 0x80 /* Treat parity/framing/overrun errors as exceptions */ + +/* SXCHANNEL.par_error definitions.. */ +#define DIAG_IRQ_RX 0x01 /* Indicate serial receive interrupt (diags only) */ +#define DIAG_IRQ_TX 0x02 /* Indicate serial transmit interrupt (diags only) */ +#define DIAG_IRQ_MD 0x04 /* Indicate serial modem interrupt (diags only) */ + +/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */ +#define BAUD_75 0x00 /* 75 baud */ +#define BAUD_115200 0x01 /* 115200 baud */ +#define BAUD_38400 0x02 /* 38400 baud */ +#define BAUD_150 0x03 /* 150 baud */ +#define BAUD_300 0x04 /* 300 baud */ +#define BAUD_600 0x05 /* 600 baud */ +#define BAUD_1200 0x06 /* 1200 baud */ +#define BAUD_2000 0x07 /* 2000 baud */ +#define BAUD_2400 0x08 /* 2400 baud */ +#define BAUD_4800 0x09 /* 4800 baud */ +#define BAUD_1800 0x0A /* 1800 baud */ +#define BAUD_9600 0x0B /* 9600 baud */ +#define BAUD_19200 0x0C /* 19200 baud */ +#define BAUD_57600 0x0D /* 57600 baud */ +#define BAUD_230400 0x0E /* 230400 baud */ +#define BAUD_460800 0x0F /* 460800 baud */ +#define BAUD_921600 0x10 /* 921600 baud */ +#define BAUD_50 0x11 /* 50 baud */ +#define BAUD_110 0x12 /* 110 baud */ +#define BAUD_134_5 0x13 /* 134.5 baud */ +#define BAUD_200 0x14 /* 200 baud */ +#define BAUD_7200 0x15 /* 7200 baud */ +#define BAUD_56000 0x16 /* 56000 baud */ +#define BAUD_64000 0x17 /* 64000 baud */ +#define BAUD_76800 0x18 /* 76800 baud */ +#define BAUD_128000 0x19 /* 128000 baud */ +#define BAUD_150000 0x1A /* 150000 baud */ +#define BAUD_14400 0x1B /* 14400 baud */ +#define BAUD_256000 0x1C /* 256000 baud */ +#define BAUD_28800 0x1D /* 28800 baud */ + +/* SXCHANNEL.txbreak_state definiions... */ +#define TXBREAK_OFF 0 /* Not sending break */ +#define TXBREAK_START 1 /* Begin sending break */ +#define TXBREAK_START1 2 /* Begin sending break, part 1 */ +#define TXBREAK_ON 3 /* Sending break */ +#define TXBREAK_STOP 4 /* Stop sending break */ +#define TXBREAK_STOP1 5 /* Stop sending break, part 1 */ + +#endif /* _sxwindow_h */ + +/* End of SXWINDOW.H */ + diff -u --recursive --new-file v2.3.12/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.3.12/linux/drivers/char/tty_io.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/char/tty_io.c Thu Aug 5 14:47:44 1999 @@ -125,11 +125,15 @@ int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); +#ifdef CONFIG_SX +extern int sx_init (void); +#endif #ifdef CONFIG_8xx extern long console_8xx_init(long, long); extern int rs_8xx_init(void); #endif /* CONFIG_8xx */ + #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif @@ -2080,7 +2084,7 @@ * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -__initfunc(int tty_init(void)) +int __init tty_init(void) { if (sizeof(struct tty_struct) > PAGE_SIZE) panic("size of tty structure > PAGE_SIZE!"); @@ -2177,6 +2181,9 @@ #endif #ifdef CONFIG_SPECIALIX specialix_init(); +#endif +#ifdef CONFIG_SX + sx_init(); #endif #ifdef CONFIG_8xx rs_8xx_init(); diff -u --recursive --new-file v2.3.12/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c --- v2.3.12/linux/drivers/char/vc_screen.c Thu Feb 25 10:02:12 1999 +++ linux/drivers/char/vc_screen.c Thu Aug 5 14:34:02 1999 @@ -310,7 +310,7 @@ NULL /* fsync */ }; -__initfunc(int vcs_init(void)) +int __init vcs_init(void) { int error; diff -u --recursive --new-file v2.3.12/linux/drivers/dio/dio.c linux/drivers/dio/dio.c --- v2.3.12/linux/drivers/dio/dio.c Sat Jun 13 13:14:31 1998 +++ linux/drivers/dio/dio.c Thu Aug 5 14:34:02 1999 @@ -112,7 +112,7 @@ static struct dioboard *blist = NULL; -__initfunc(static int dio_find_slow(int deviceid)) +static int __init dio_find_slow(int deviceid) { /* Called to find a DIO device before the full bus scan has run. Basically only used by the console driver. */ @@ -151,7 +151,7 @@ /* This is the function that scans the DIO space and works out what * hardware is actually present. */ -__initfunc(void dio_init(void)) +void __init dio_init(void) { int scode; struct dioboard *b, *bprev = NULL; diff -u --recursive --new-file v2.3.12/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c --- v2.3.12/linux/drivers/fc4/soc.c Fri Mar 26 13:57:41 1999 +++ linux/drivers/fc4/soc.c Thu Aug 5 14:34:02 1999 @@ -672,7 +672,7 @@ } #ifndef MODULE -__initfunc(int soc_probe(void)) +int __init soc_probe(void) #else int init_module(void) #endif diff -u --recursive --new-file v2.3.12/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c --- v2.3.12/linux/drivers/fc4/socal.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/fc4/socal.c Thu Aug 5 14:34:02 1999 @@ -798,7 +798,7 @@ } #ifndef MODULE -__initfunc(int socal_probe(void)) +int __init socal_probe(void) #else int init_module(void) #endif diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/Makefile linux/drivers/i2o/Makefile --- v2.3.12/linux/drivers/i2o/Makefile Wed Jun 2 14:40:22 1999 +++ linux/drivers/i2o/Makefile Thu Aug 5 15:04:52 1999 @@ -27,7 +27,7 @@ L_OBJS += i2o_pci.o else ifeq ($(CONFIG_I2O_PCI),m) - M_OBJS += i2o_pci.o + MX_OBJS += i2o_pci.o endif endif diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.3.12/linux/drivers/i2o/i2o_block.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_block.c Thu Aug 5 15:04:52 1999 @@ -323,7 +323,8 @@ { i2o_block_reply, "I2O Block OSM", - 0 + 0, + I2O_CLASS_RANDOM_BLOCK_STORAGE }; @@ -576,15 +577,6 @@ } /* - * Issue UTIL_CLAIM messages - */ - -static int i2ob_claim_device(struct i2ob_device *dev, int onoff) -{ - return i2o_issue_claim(dev->controller, dev->tid, i2ob_context, onoff, &dev->done_flag); -} - -/* * Close the block device down */ @@ -625,10 +617,10 @@ i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); /* - * Now unclaim the device. - */ - if (i2ob_claim_device(dev, 0)<0) - printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n"); + * Now unclaim the device. + */ + if (i2o_release_device(dev->i2odev, &i2o_block_handler, I2O_CLAIM_PRIMARY)<0) + printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n"); } MOD_DEC_USE_COUNT; @@ -657,7 +649,7 @@ int *query_done; - if(i2ob_claim_device(dev, 1)<0) + if(i2o_claim_device(dev->i2odev, &i2o_block_handler, I2O_CLAIM_PRIMARY)<0) { dev->refcnt--; return -EBUSY; @@ -809,36 +801,35 @@ if(uniti2odev = d; + * Get the device and fill in the + * Tid and controller. + */ + struct i2ob_device *dev=&i2ob_dev[unit]; + dev->i2odev = d; dev->controller = c; - dev->tid = d->id; + dev->tid = d->id; - /* - * Insure the device can be claimed - * before installing it. - */ - if(i2ob_claim_device(dev, 1)==0) - { - printk(KERN_INFO "Claimed Dev %p Tid %d Unit %d\n",dev,dev->tid,unit); - i2ob_install_device(c,d,unit); + /* + * Insure the device can be claimed + * before installing it. + */ + if(i2o_claim_device(dev->i2odev, &i2o_block_handler, I2O_CLAIM_PRIMARY )==0) + { + printk(KERN_INFO "Claimed Dev %p Tid %d Unit %d\n",dev,dev->tid,unit); + i2ob_install_device(c,d,unit); unit+=16; - /* - * Now that the device has been - * installed, unclaim it so that - * it can be claimed by either - * the block or scsi driver. - */ - if (i2ob_claim_device(dev, 0)<0) - printk(KERN_INFO "Could not unclaim Dev %p Tid %d\n",dev,dev->tid); - - } - else - printk(KERN_INFO "TID %d not claimed\n",dev->tid); + /* + * Now that the device has been + * installed, unclaim it so that + * it can be claimed by either + * the block or scsi driver. + */ + if(i2o_release_device(dev->i2odev, &i2o_block_handler, I2O_CLAIM_PRIMARY)) + printk(KERN_INFO "Could not unclaim Dev %p Tid %d\n",dev,dev->tid); + } + else + printk(KERN_INFO "TID %d not claimed\n",dev->tid); } else { diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c --- v2.3.12/linux/drivers/i2o/i2o_config.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_config.c Thu Aug 5 15:04:52 1999 @@ -75,7 +75,8 @@ { i2o_cfg_reply, "Configuration", - 0 + 0, + 0xffffffff // All classes }; static long long cfg_llseek(struct file *file, long long offset, int origin) diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c --- v2.3.12/linux/drivers/i2o/i2o_core.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_core.c Thu Aug 5 15:04:52 1999 @@ -14,15 +14,20 @@ * Red Creek RCPCI45 adapter driver by Red Creek Communications * * Fixes by Philipp Rumpf - * Juha Sievänen + * Juha Sievänen * Auvo Häkkinen + * Deepak Saxena */ - + #include #include #include #include + +#if defined(CONFIG_I2O_PCI) || defined (CONFIG_I2O_PCI_MODULE) #include +#endif + #include #include #include @@ -32,6 +37,7 @@ #include "i2o_lan.h" +#define DRIVERDEBUG /* * Size of the I2O module table @@ -46,6 +52,32 @@ extern int i2o_online_controller(struct i2o_controller *c); static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *, struct i2o_message *); +static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *); +static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *); +static void i2o_dump_message(u32 *); + +#ifdef MODULE +/* + * Function table to send to bus specific layers + * See for explanation of this + */ +static struct i2o_core_func_table i2o_core_functions = +{ + i2o_install_controller, + i2o_activate_controller, + i2o_find_controller, + i2o_unlock_controller, + i2o_run_queue, + i2o_delete_controller +}; + +#ifdef CONFIG_I2O_PCI_MODULE +extern int i2o_pci_core_attach(struct i2o_core_func_table *); +extern void i2o_pci_core_detach(void); +#endif /* CONFIG_I2O_PCI_MODULE */ + +#endif /* MODULE */ + /* Message handler */ static struct i2o_handler i2o_core_handler = @@ -133,12 +165,19 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d) { + int i; + spin_lock(&i2o_configuration_lock); d->controller=c; d->owner=NULL; d->next=c->devices; c->devices=d; *d->dev_name = 0; + d->owner = NULL; + + for(i = 0; i < I2O_MAX_MANAGERS; i++) + d->managers[i] = NULL; + spin_unlock(&i2o_configuration_lock); return 0; } @@ -247,9 +286,12 @@ while(*p) { if(*p!=c) + { + printk("Quiescing controller %p != %p\n", c, *p); if(i2o_quiesce_controller(*p)<0) printk(KERN_INFO "Unable to quiesce iop%d\n", (*p)->unit); + } p=&((*p)->next); } @@ -308,11 +350,23 @@ /* - * Track if a device is being used by a driver + * Claim a device for use as either the primary user or just + * as a management/secondary user */ - -int i2o_claim_device(struct i2o_device *d, struct i2o_driver *r) +int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type) { + /* Device already has a primary user or too many managers */ + if((type == I2O_CLAIM_PRIMARY && d->owner) || + (d->num_managers == I2O_MAX_MANAGERS)) + { + return -EBUSY; + } + + if(i2o_issue_claim(d->controller,d->id, h->context, 1, &reply_flag, type) < 0) + { + return -EBUSY; + } + spin_lock(&i2o_configuration_lock); if(d->owner) { @@ -320,25 +374,92 @@ return -EBUSY; } atomic_inc(&d->controller->users); - d->owner=r; + + if(type == I2O_CLAIM_PRIMARY) + d->owner=h; + else + i2o_add_management_user(d, h); + spin_unlock(&i2o_configuration_lock); return 0; } -int i2o_release_device(struct i2o_device *d) +int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type) { + int err = 0; + spin_lock(&i2o_configuration_lock); - if(d->owner==NULL) + + /* Primary user */ + if(type == I2O_CLAIM_PRIMARY) { + if(d->owner != h) + err = -ENOENT; + else + { + if(i2o_issue_claim(d->controller,d->id, h->context, 0, &reply_flag, type) < 0) + { + err = -ENXIO; + } + else + { + d->owner = NULL; + atomic_dec(&d->controller->users); + } + } + spin_unlock(&i2o_configuration_lock); - return -EINVAL; + return err; } - atomic_dec(&d->controller->users); - d->owner=NULL; + + /* Management or other user */ + if(i2o_remove_management_user(d, h)) + err = -ENOENT; + else + { + atomic_dec(&d->controller->users); + + if(i2o_issue_claim(d->controller,d->id, h->context, 0, + &reply_flag, type) < 0) + err = -ENXIO; + } + spin_unlock(&i2o_configuration_lock); + return err; +} + +int i2o_add_management_user(struct i2o_device *d, struct i2o_handler *h) +{ + int i; + + if(d->num_managers == I2O_MAX_MANAGERS) + return 1; + + for(i = 0; i < I2O_MAX_MANAGERS; i++) + if(!d->managers[i]) + d->managers[i] = h; + + d->num_managers++; + return 0; } +int i2o_remove_management_user(struct i2o_device *d, struct i2o_handler *h) +{ + int i; + + for(i=0; i < I2O_MAX_MANAGERS; i++) + { + if(d->managers[i] == h) + { + d->managers[i] = NULL; + return 0; + } + } + + return -ENOENT; +} + /* * This is called by the bus specific driver layer when an interrupt * or poll of this card interface is desired. @@ -363,7 +484,11 @@ if(i) i->reply(i,c,m); else - printk("Spurious reply\n"); + { + printk("Spurious reply to handler %d\n", + m->initiator_context&(MAX_I2O_MODULES-1)); + i2o_dump_message((u32*)m); + } i2o_flush_reply(c,mv); mb(); } @@ -803,7 +928,8 @@ msg[2]=core_context; msg[3]=(u32)&reply_flag; - return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10); + /* Long timeout needed for quiesce if lots of devices */ + return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 120); } @@ -839,11 +965,15 @@ /* First stop external operations */ for(iop=i2o_controller_chain; iop != NULL; iop=iop->next) { - if(i2o_quiesce_controller(iop)<0) - printk(KERN_INFO "Unable to quiesce iop%d\n", - iop->unit); - else - printk(KERN_DEBUG "%s quiesced\n", iop->name); + /* Quiesce is rejected on hold state */ + if(iop->status != ADAPTER_STATE_HOLD) + { + if(i2o_quiesce_controller(iop)<0) + printk(KERN_INFO "Unable to quiesce iop%d\n", + iop->unit); + else + printk(KERN_DEBUG "%s quiesced\n", iop->name); + } } /* Then reset the IOP */ @@ -1398,7 +1528,7 @@ * Issue UTIL_CLAIM messages */ -int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, int *flag) +int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, int *flag, u32 type) { u32 msg[6]; @@ -1412,7 +1542,7 @@ msg[2] = 0x80000000|context; msg[3] = (u32)flag; - msg[4] = 0x01<<24; /* Primary user */ + msg[4] = type; return i2o_post_wait(c, tid, msg, 20, flag,2); } @@ -1999,8 +2129,19 @@ return; } +/* Used to dump a message to syslog during debugging */ +static void i2o_dump_message(u32 *msg) +{ +#ifdef DRIVERDEBUG + int i; + + printk(KERN_INFO "Dumping I2O message @ %p\n", msg); + for(i = 0; i < ((msg[0]>>16)&0xffff); i++) + printk(KERN_INFO "\tmsg[%d] = %#10x\n", i, msg[i]); +#endif +} -#ifdef CONFIG_MODULE +#ifdef MODULE EXPORT_SYMBOL(i2o_install_handler); EXPORT_SYMBOL(i2o_remove_handler); @@ -2040,19 +2181,31 @@ int init_module(void) { - if (i2o_install_handler(&i2o_core_handler) < 0) - { - printk(KERN_ERR "i2o_core: Unable to install core handler.\n"); - return 0; - } + if (i2o_install_handler(&i2o_core_handler) < 0) + { + printk(KERN_ERR "i2o_core: Unable to install core handler.\n"); + return 0; + } - core_context = i2o_core_handler.context; + core_context = i2o_core_handler.context; - return 0; + /* + * Attach core to I2O PCI subsystem + */ +#ifdef CONFIG_I2O_PCI_MODULE + if(i2o_pci_core_attach(&i2o_core_functions) < 0) + printk(KERN_INFO "No PCI I2O controllers found\n"); +#endif + + return 0; } void cleanup_module(void) { +#ifdef CONFIG_I2O_PCI_MODULE + i2o_pci_core_detach(); +#endif + i2o_remove_handler(&i2o_core_handler); } @@ -2093,4 +2246,4 @@ return 0; } -#endif \ No newline at end of file +#endif diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c --- v2.3.12/linux/drivers/i2o/i2o_lan.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_lan.c Thu Aug 5 15:04:52 1999 @@ -1,7 +1,7 @@ /* * linux/drivers/i2o/i2o_lan.c * - * I2O LAN CLASS OSM Prototyping, June 4th 1999 + * I2O LAN CLASS OSM Prototyping, July 16th 1999 * * (C) Copyright 1999 University of Helsinki, * Department of Computer Science @@ -15,17 +15,16 @@ * * Authors: Auvo Häkkinen * Juha Sievänen + * Deepak Saxena * * Tested: in FDDI environment (using SysKonnect's DDM) * in Ethernet environment (using Intel 82558 DDM proto) * * TODO: batch mode networking - * - this one assumes that we always get one packet - * in a bucket * - we've not been able to test batch replies and * batch receives - * - error checking / timeouts - * - code / test for other LAN classes + * error checking / timeouts + * code / test for other LAN classes */ #include @@ -39,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,7 +48,7 @@ //#define DRIVERDEBUG #ifdef DRIVERDEBUG -#define dprintk(s, args...) printk(s, ## args) +#define dprintk(s, args...) printk(s, ## args) #else #define dprintk(s, args...) #endif @@ -64,17 +64,25 @@ u32 packet_tresh; /* treshold for incoming skb's */ struct fddi_statistics stats; /* see also struct net_device_stats */ unsigned short (*type_trans)(struct sk_buff *, struct device *); + /* + * Due to way that interrupts can pile up, we need to keep track + * of buckets ourselves. Otherwise we'll end up flooding + * the DDM with buckets. + */ + u32 bucket_count; }; /* function prototypes */ static int i2o_lan_receive_post(struct device *dev); static int i2o_lan_receive_post_reply(struct device *dev, struct i2o_message *m); +static void i2o_lan_release_buckets(u32 *msg, struct i2o_lan_local *priv); /* * Module params */ -static u32 bucketpost = 64; -static u32 bucketthresh = 8; +static u32 bucketpost = I2O_BUCKET_COUNT; +static u32 bucketthresh = I2O_BUCKET_THRESH; +static u32 rx_copybreak = 200; static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m) @@ -82,6 +90,15 @@ u32 *msg = (u32 *)m; u8 unit = (u8)(msg[2]>>16); // InitiatorContext struct device *dev = i2o_landevs[unit]; + struct i2o_lan_local *priv; + + if(dev) + priv = (struct i2o_lan_local *)dev->priv; + else + priv = NULL; + + dprintk("Unit: %d Function: %#x\n", + unit, msg[1]>>24); if (msg[0] & (1<<13)) // Fail bit is set { @@ -97,36 +114,41 @@ return; } -#ifdef DRIVERDEBUG -// if (msg[4] >> 24) /* ReqStatus != SUCCESS */ - i2o_report_status(KERN_INFO, "i2o_lan", msg); +#ifndef DRIVERDEBUG + if (msg[4] >> 24) /* ReqStatus != SUCCESS */ #endif + i2o_report_status(KERN_INFO, dev->name, msg); switch (msg[1] >> 24) { case LAN_RECEIVE_POST: - if (dev->start) - i2o_lan_receive_post_reply(dev,m); - else { - // we are getting unused buckets back - u8 trl_count = msg[3] & 0x000000FF; - struct i2o_bucket_descriptor *bucket = - (struct i2o_bucket_descriptor *)&msg[6]; - do { - dprintk("%s: Releasing unused bucket\n",dev->name); - dev_kfree_skb((struct sk_buff *)bucket->context); - bucket++; - } while (--trl_count); - } - break; + { + if (dev->start) + { + if(!(msg[4]>>24)) + { + i2o_lan_receive_post_reply(dev,m); + break; + } + else + { + // Something VERY wrong if this is happening + printk( KERN_WARNING "i2olan: Device %s rejected bucket post\n", dev->name); + i2o_lan_release_buckets(msg,priv); + } + } + else + { + i2o_lan_release_buckets(msg,priv); + } + + break; + } case LAN_PACKET_SEND: case LAN_SDU_SEND: { u8 trl_count = msg[3] & 0x000000FF; - if (msg[4] >> 24) // ReqStatus != SUCCESS - i2o_report_status(KERN_WARNING, dev->name, msg); - do { // The HDM has handled the outgoing packet dev_kfree_skb((struct sk_buff *)msg[4 + trl_count]); dprintk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n", @@ -135,29 +157,47 @@ dev->tbusy = 0; mark_bh(NET_BH); /* inform upper layers */ + + break; } - break; default: if (msg[2] & 0x80000000) // reply to a UtilParamsGet/Set { - int *flag = (int *)msg[3]; // flag for i2o_post_wait + int *flag = (int *)msg[3]; // flag for i2o_post_wait if (msg[4] >> 24) // ReqStatus != SUCCESS { - i2o_report_status(KERN_WARNING, dev->name, msg); - *flag = -(msg[4] & 0xFFFF); // DetailedStatus - } - else - *flag = I2O_POST_WAIT_OK; + *flag = -(msg[4] & 0xFFFF); // DetailedStatus + } + else + *flag = I2O_POST_WAIT_OK; } } } +void i2o_lan_release_buckets(u32 *msg, struct i2o_lan_local *priv) +{ + u8 trl_count = (u8)(msg[3] & 0x000000FF); + u32 *pskb = &msg[6]; + + while (trl_count) + { + dprintk("%s: Releasing unused sk_buff %p\n",dev->name, + (struct sk_buff*)(*pskb)); + dev_kfree_skb((struct sk_buff*)(*pskb)); + pskb++; + if(priv) + priv->bucket_count--; + trl_count--; + } +} + static struct i2o_handler i2o_lan_handler = { i2o_lan_reply, "I2O Lan OSM", - 0 // context + 0, // context + I2O_CLASS_LAN }; static int lan_context; @@ -177,22 +217,25 @@ "msgsize = %d, buckets_remaining = %d\n", msg[3]>>24, msg[3]&0x0000FF00, trl_count, msg[0]>>16, msg[5]); #endif - dprintk(KERN_INFO "Buckets_remaining = %d\n",msg[5]); + + dprintk(KERN_INFO "Buckets_remaining = %d, bucket_count = %d\n", + msg[5], priv->bucket_count); do { skb = (struct sk_buff *)(bucket->context); packet = (struct i2o_packet_info *)bucket->packet_info; + priv->bucket_count--; #if 0 - dprintk(KERN_INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n", + dprintk(KERN)INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n", packet->flags, packet->offset, packet->status, packet->len); #endif - if (packet->len < priv->packet_tresh) { + if (packet->len < rx_copybreak) { newskb = (struct sk_buff *) dev_alloc_skb(packet->len+2); if (newskb) { skb_reserve(newskb,2); memcpy(skb_put(newskb,packet->len), - skb->data, packet->len); + skb->data, packet->len); newskb->dev = dev; newskb->protocol = priv->type_trans(newskb, dev); @@ -200,10 +243,11 @@ dev_kfree_skb(skb); // FIXME: reuse this skb? } else { - printk("Can't allocate skb.\n"); + printk("I2OLAN-%s: Can't allocate skb.\n", dev->name); return -ENOMEM; } } else { + skb_put(skb,packet->len); skb->dev = dev; skb->protocol = priv->type_trans(skb, dev); @@ -216,9 +260,18 @@ bucket++; // to next Packet Descriptor Block } while (--trl_count); - - if (msg[5] <= bucketthresh) // BucketsRemaining + if (priv->bucket_count <= bucketthresh) // BucketsRemaining + { + dprintk("Bucket_count = %d, ",priv->bucket_count); i2o_lan_receive_post(dev); + } + + + if((msg[4]& 0x0000ffff) == 0x05) // I2O_LAN_RECEIVE_OVERRUN + { + printk("Bucket overrun! priv->bucketcount = %d\n", + priv->bucket_count); + } return 0; } @@ -267,6 +320,9 @@ if (skb == NULL) return -ENOMEM; skb_reserve(skb, 2); + + priv->bucket_count++; + msg[4 + 3*i] = 0x51000000 | bucket_len; msg[5 + 3*i] = (u32)skb; msg[6 + 3*i] = virt_to_bus(skb->data); @@ -279,6 +335,7 @@ total += bucket_count; } + return 0; } @@ -317,6 +374,7 @@ struct i2o_controller *iop = i2o_dev->controller; u32 msg[5]; + dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name ); msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->id; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext @@ -350,7 +408,7 @@ // enable batch mode, toggle automatically val = 0x00000000; // val = 0x00000001; // turn off batch mode - if (i2o_set_scalar(iop, i2o_dev->id, lan_context, 0x0003, 0, + if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0003, 0, &val, 4, &priv->reply_flag) <0) printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n"); else @@ -364,7 +422,7 @@ /* set LAN_OPERATION attributes */ val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit - if (i2o_set_scalar(iop, i2o_dev->id, lan_context, 0x0004, 2, + if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0004, 2, &val, 4, &priv->reply_flag) < 0) printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n"); else @@ -384,8 +442,10 @@ struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; - if (i2o_issue_claim(iop, i2o_dev->id, lan_context, 1, +/* if (i2o_issue_claim(iop, i2o_dev->id, priv->unit << 16 | lan_context, 1, &priv->reply_flag) < 0) +*/ + if(i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) { printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name); return -EAGAIN; @@ -424,8 +484,12 @@ i2o_lan_suspend(dev); - if (i2o_issue_claim(iop, i2o_dev->id, lan_context, 0, +/* + if (i2o_issue_claim(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0, &priv->reply_flag) < 0) +*/ + + if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device " "(tid=%d)\n", dev->name, i2o_dev->id); @@ -513,7 +577,6 @@ msg[6] = virt_to_bus(skb->data); i2o_post_message(iop,m); - dprintk(KERN_INFO "%s: Packet (%d bytes) sent to network.\n", dev->name, skb->len); @@ -528,7 +591,7 @@ u64 val64[16]; u64 supported_group[4] = { 0, 0, 0, 0 }; - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0100, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0100, -1, val64, sizeof(val64), &priv->reply_flag) < 0) dprintk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name); else { @@ -542,11 +605,11 @@ priv->stats.rx_dropped = val64[6]; } - i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0180, -1, + i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0180, -1, &supported_group, sizeof(supported_group), &priv->reply_flag); if (supported_group[2]) { - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0183, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0183, -1, val64, sizeof(val64), &priv->reply_flag) < 0) dprintk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name); else { @@ -561,23 +624,24 @@ { u64 supported_stats = 0; - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0200, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0200, -1, val64, sizeof(val64), &priv->reply_flag) < 0) dprintk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name); else { - dprintk("%s: LAN_802_3_HISTORICAL_STATS queried.\n",dev->name); +// dprintk("%s: LAN_802_3_HISTORICAL_STATS queried.\n",dev->name); priv->stats.transmit_collision = val64[1] + val64[2]; priv->stats.rx_frame_errors = val64[0]; priv->stats.tx_carrier_errors = val64[6]; } - - i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0280, -1, - &supported_stats, 8, &priv->reply_flag); - + + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0280, -1, + &supported_stats, 8, &priv->reply_flag) < 0) + dprintk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name); + if (supported_stats != 0) { - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0281, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0281, -1, val64, sizeof(val64), &priv->reply_flag) < 0) - dprintk("%s: Unable to query LAN_OPTIONLA_802_3_HISTORICAL_STATS.\n",dev->name); + dprintk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name); if (supported_stats & 0x1) @@ -586,18 +650,19 @@ priv->stats.tx_heartbeat_errors = val64[2]; } } + } #ifdef CONFIG_TR if (i2o_dev->subclass == I2O_LAN_TR) { - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0300, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0300, -1, val64, sizeof(val64), &priv->reply_flag) < 0) dprintk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name); else { struct tr_statistics *stats = (struct tr_statistics *)&priv->stats; - dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name); +// dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name); stats->line_errors = val64[0]; stats->internal_errors = val64[7]; @@ -617,11 +682,11 @@ #ifdef CONFIG_FDDI if (i2o_dev->subclass == I2O_LAN_FDDI) { - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0400, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0400, -1, val64, sizeof(val64), &priv->reply_flag) < 0) dprintk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name); else { - dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name); +// dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name); priv->stats.smt_cf_state = val64[0]; memcpy(priv->stats.mac_upstream_nbr, &val64[1], FDDI_K_ALEN); memcpy(priv->stats.mac_downstream_nbr, &val64[2], FDDI_K_ALEN); @@ -654,15 +719,29 @@ dprintk(KERN_INFO "%s: Entered i2o_lan_set_multicast_list().\n", dev->name); +if (dev==NULL) + printk("dev is NULL\n"); +else if (dev->priv==NULL) + printk("dev->priv is NULL\n"); +else if (priv->i2o_dev==NULL) + printk("i2o_dev is NULL\n"); +else if (i2o_dev->controller==NULL) + printk("iop is NULL\n"); +else { + printk("Everything seems to be OK in i2o_lan_set_multicast_list().\n"); + printk("id = %d, unit = %d, lan_context = %d\n", + i2o_dev->id, priv->unit, lan_context); +} + return; /* FIXME: Why does the next call kill the interrupt handler? - * The same works fine in function lan_open(), and in i2o_proc.c + * The same piece of code works fine in function lan_open(), and in i2o_proc.c * - * *because its trying to sleep in an irq - this must be async - Alan + * *because its trying to sleep in an irq - this must be async - Alan */ - if (i2o_query_scalar(iop, i2o_dev->id, lan_context, 0x0001, -1, + if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, -1, &work32, sizeof(work32), &priv->reply_flag) < 0 ) { printk(KERN_WARNING "i2o_lan: Unable to query " @@ -705,11 +784,11 @@ mclist = mclist->next; } - if (i2o_clear_table(iop, i2o_dev->id, lan_context, 0x0002, + if (i2o_clear_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, &priv->reply_flag) < 0 ) dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); - if (i2o_row_add_table(iop, i2o_dev->id, lan_context, 0x0002, -1, + if (i2o_row_add_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, -1, work32, dev->mc_count*8, &priv->reply_flag) < 0) dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); } @@ -719,7 +798,7 @@ dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n"); } - if (i2o_set_scalar(iop, i2o_dev->id, lan_context, 0x0001, 3, + if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, 3, &filter_mask, 4, &priv->reply_flag) <0) printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n"); @@ -744,12 +823,14 @@ unregister_dev = unregister_netdev; break; + #ifdef CONFIG_ANYLAN case I2O_LAN_100VG: printk(KERN_ERR "i2o_lan: 100base VG not yet supported\n"); break; #endif + #ifdef CONFIG_TR case I2O_LAN_TR: dev = init_trdev(NULL, sizeof(struct i2o_lan_local)); @@ -802,11 +883,18 @@ priv = (struct i2o_lan_local *)dev->priv; priv->i2o_dev = i2o_dev; priv->type_trans = type_trans; - - if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id, lan_context, - 0x0001, 0, &hw_addr, 8, &priv->reply_flag) < 0) + priv->bucket_count = 0; + + unit++; + i2o_landevs[unit] = dev; + priv->unit = unit; + + if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id, + priv->unit << 16 | lan_context, + 0x0001, 0, &hw_addr, 8, &priv->reply_flag) < 0) { printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name); + unit--; unregister_dev(dev); kfree(dev); return NULL; @@ -835,29 +923,33 @@ __init int i2o_lan_init(void) { struct device *dev; - struct i2o_lan_local *priv; - int i; + int i; - if (i2o_install_handler(&i2o_lan_handler) < 0) + bucketpost = bucketpost - bucketthresh; + + if (i2o_install_handler(&i2o_lan_handler) < 0) { printk(KERN_ERR "Unable to register I2O LAN OSM.\n"); return -EINVAL; - } + } + + for(i=0; i <= MAX_LAN_CARDS; i++) + i2o_landevs[i] = NULL; lan_context = i2o_lan_handler.context; - for (i=0; i < MAX_I2O_CONTROLLERS; i++) + for (i=0; i < MAX_I2O_CONTROLLERS; i++) { - struct i2o_controller *iop = i2o_find_controller(i); - struct i2o_device *i2o_dev; + struct i2o_controller *iop = i2o_find_controller(i); + struct i2o_device *i2o_dev; - if (iop==NULL) + if (iop==NULL) continue; - for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) + for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) { - if (i2o_dev->class != I2O_CLASS_LAN) - continue; + if (i2o_dev->class != I2O_CLASS_LAN) + continue; if (unit == MAX_LAN_CARDS) { @@ -872,19 +964,15 @@ printk(KERN_ERR "Unable to register I2O LAN device\n"); continue; // try next one } - priv = (struct i2o_lan_local *)dev->priv; - - unit++; - i2o_landevs[unit] = dev; - priv->unit = unit; printk(KERN_INFO "%s: I2O LAN device registered, tid = %d," " subclass = 0x%08X, unit = %d.\n", - dev->name, i2o_dev->id, i2o_dev->subclass, - priv->unit); - } + dev->name, i2o_dev->id, i2o_dev->subclass, + ((struct i2o_lan_local *)dev->priv)->unit); + } + i2o_unlock_controller(iop); - } + } dprintk(KERN_INFO "%d I2O LAN devices found and registered.\n", unit+1); @@ -940,5 +1028,6 @@ MODULE_PARM(bucketpost, "i"); // Number of buckets to post MODULE_PARM(bucketthresh, "i"); // Bucket post threshold +MODULE_PARM(rx_copybreak, "i"); #endif diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_lan.h linux/drivers/i2o/i2o_lan.h --- v2.3.12/linux/drivers/i2o/i2o_lan.h Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_lan.h Thu Aug 5 15:04:52 1999 @@ -17,8 +17,8 @@ /* Tunable parameters first */ -#define I2O_BUCKET_COUNT 16 -#define I2O_BUCKET_THRESH 0 +#define I2O_BUCKET_COUNT 64 +#define I2O_BUCKET_THRESH 16 /* LAN types */ #define I2O_LAN_ETHERNET 0x0030 diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c --- v2.3.12/linux/drivers/i2o/i2o_pci.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_pci.c Fri Aug 6 11:16:54 1999 @@ -5,16 +5,17 @@ * (C) Copyright 1999 Red Hat Software * * Written by Alan Cox, Building Number Three Ltd + * Modified by Deepak Saxena * * 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 + * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * TODO: * Support polled I2O PCI controllers. */ - + #include #include #include @@ -24,10 +25,21 @@ #include #include +#ifdef MODULE +/* + * Core function table + * See for an explanation + */ +static struct i2o_core_func_table *core; + +/* Core attach function */ +extern int i2o_pci_core_attach(struct i2o_core_func_table *); +extern void i2o_pci_core_detach(void); +#endif /* MODULE */ + /* * Free bus specific resources */ - static void i2o_pci_dispose(struct i2o_controller *c) { I2O_IRQ_WRITE32(c,0xFFFFFFFF); @@ -60,7 +72,11 @@ static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) { struct i2o_controller *c = dev_id; +#ifdef MODULE + core->run_queue(c); +#else i2o_run_queue(c); +#endif /* MODULE */ } /* @@ -76,20 +92,20 @@ u32 size; int i; - + if(c==NULL) { printk(KERN_ERR "i2o_pci: insufficient memory to add controller.\n"); return -ENOMEM; } memset(c, 0, sizeof(*c)); - + for(i=0; i<6; i++) { /* Skip I/O spaces */ - if(!(dev->base_address[i]&PCI_BASE_ADDRESS_SPACE)) + if(!(dev->resource[i].flags&PCI_BASE_ADDRESS_SPACE)) { - memptr=PCI_BASE_ADDRESS_MEM_MASK&dev->base_address[i]; + memptr=dev->resource[i].flags; break; } } @@ -100,10 +116,7 @@ return -ENOMEM; } - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+4*i, 0xFFFFFFFF); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+4*i, &size); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+4*i, dev->base_address[i]); - + size = dev->resource[i].end-dev->resource[i].start+1; /* Map the I2O controller */ printk(KERN_INFO "PCI I2O controller at 0x%08X size=%d\n", memptr, -size); @@ -125,8 +138,12 @@ c->type = I2O_TYPE_PCI; I2O_IRQ_WRITE32(c,0xFFFFFFFF); - + +#ifdef MODULE + i = core->install(c); +#else i = i2o_install_controller(c); +#endif /* MODULE */ if(i<0) { @@ -144,7 +161,11 @@ printk(KERN_ERR "%s: unable to allocate interrupt %d.\n", c->name, dev->irq); c->bus.pci.irq = -1; +#ifdef MODULE + core->delete(c); +#else i2o_delete_controller(c); +#endif /* MODULE */ return -EBUSY; } } @@ -187,12 +208,27 @@ for(i = 0; i < MAX_I2O_CONTROLLERS; i++) { +#ifdef MODULE + c=core->find(i); +#else c=i2o_find_controller(i); +#endif /* MODULE */ + if(c==NULL) continue; + +#ifdef MODULE + core->unlock(c); +#else i2o_unlock_controller(c); +#endif /* MODULE */ + if(c->type == I2O_TYPE_PCI) +#ifdef MODULE + core->delete(c); +#else i2o_delete_controller(c); +#endif /* MODULE */ } } @@ -203,50 +239,102 @@ for(i = 0; i < MAX_I2O_CONTROLLERS; i++) { +#ifdef MODULE + c=core->find(i); +#else c=i2o_find_controller(i); +#endif /* MODULE */ + if(c==NULL) continue; if(c->type == I2O_TYPE_PCI) { +#ifdef MODULE + if(core->activate(c)) +#else if(i2o_activate_controller(c)) +#endif /* MODULE */ { printk("I2O: Failed to initialize iop%d\n", c->unit); +#ifdef MODULE + core->unlock(c); + core->delete(c); +#else i2o_unlock_controller(c); i2o_delete_controller(c); +#endif continue; } I2O_IRQ_WRITE32(c,0); } +#ifdef MODULE + core->unlock(c); +#else i2o_unlock_controller(c); +#endif } } + #ifdef MODULE -EXPORT_NO_SYMBOLS; -MODULE_AUTHOR("Red Hat Software"); -MODULE_DESCRIPTION("I2O PCI Interface"); +int i2o_pci_core_attach(struct i2o_core_func_table *table) +{ + int i; + + MOD_INC_USE_COUNT; + + core = table; + + if((i = i2o_pci_scan())<0) + return -ENODEV; + i2o_pci_activate(); + + return i; +} + +void i2o_pci_core_detach(void) +{ + i2o_pci_unload(); + + MOD_DEC_USE_COUNT; +} int init_module(void) { - if(i2o_pci_scan()<0) - return -ENODEV; - i2o_pci_activate(); - return 0; + printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n"); + +/* + * Let the core call the scan function for module dependency + * reasons. See include/linux/i2o.h for the reason why this + * is done. + * + * if(i2o_pci_scan()<0) + * return -ENODEV; + * i2o_pci_activate(); + */ + + return 0; + } void cleanup_module(void) { - i2o_pci_unload(); } +EXPORT_SYMBOL(i2o_pci_core_attach); +EXPORT_SYMBOL(i2o_pci_core_detach); + +MODULE_AUTHOR("Red Hat Software"); +MODULE_DESCRIPTION("I2O PCI Interface"); + #else __init void i2o_pci_init(void) { + printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n"); if(i2o_pci_scan()>=0) { - printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n"); i2o_pci_activate(); } } diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c --- v2.3.12/linux/drivers/i2o/i2o_proc.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_proc.c Fri Aug 6 11:16:54 1999 @@ -3,7 +3,7 @@ * * Copyright (c) 1999 Intel Corporation * - * Originally written by Deepak Saxena(deepak.saxena@intel.com) + * Originally written by Deepak Saxena(deepak@plexity.net) * * This program is free software. You can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -143,7 +143,8 @@ { (void *)i2o_proc_reply, "I2O procfs Layer", - 0 + 0, + 0xffffffff // All classes }; /* @@ -3089,7 +3090,7 @@ #ifdef MODULE -MODULE_AUTHOR("Intel Corporation"); +MODULE_AUTHOR("Deepak Saxena"); MODULE_DESCRIPTION("I2O procfs Handler"); void cleanup_module(void) diff -u --recursive --new-file v2.3.12/linux/drivers/i2o/i2o_scsi.c linux/drivers/i2o/i2o_scsi.c --- v2.3.12/linux/drivers/i2o/i2o_scsi.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/i2o/i2o_scsi.c Thu Aug 5 15:04:52 1999 @@ -293,7 +293,8 @@ { i2o_scsi_reply, "I2O SCSI OSM", - 0 + 0, + I2O_CLASS_SCSI_PERIPHERAL }; static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun) diff -u --recursive --new-file v2.3.12/linux/drivers/isdn/hisax/diva.c linux/drivers/isdn/hisax/diva.c --- v2.3.12/linux/drivers/isdn/hisax/diva.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/isdn/hisax/diva.c Fri Aug 6 11:43:09 1999 @@ -510,7 +510,7 @@ /* get IRQ */ cs->irq = dev_diva->irq; /* get IO address */ - cs->hw.diva.cfg_reg = dev_diva->base_address[2] + cs->hw.diva.cfg_reg = dev_diva->resource[2].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_U_ID, dev_diva_u))) { @@ -518,7 +518,7 @@ /* get IRQ */ cs->irq = dev_diva_u->irq; /* get IO address */ - cs->hw.diva.cfg_reg = dev_diva_u->base_address[2] + cs->hw.diva.cfg_reg = dev_diva_u->resource[2].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Diva: No PCI card found\n"); diff -u --recursive --new-file v2.3.12/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c --- v2.3.12/linux/drivers/isdn/hisax/elsa.c Sun May 23 10:03:41 1999 +++ linux/drivers/isdn/hisax/elsa.c Fri Aug 6 11:43:09 1999 @@ -1027,17 +1027,17 @@ dev_qs1000))) { cs->subtyp = ELSA_QS1000PCI; cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = dev_qs1000->base_address[1] & + cs->hw.elsa.cfg = dev_qs1000->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = dev_qs1000->base_address[3] & + cs->hw.elsa.base = dev_qs1000->resource[3].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS3000_ID, dev_qs3000))) { cs->subtyp = ELSA_QS3000PCI; cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = dev_qs3000->base_address[1] & + cs->hw.elsa.cfg = dev_qs3000->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = dev_qs3000->base_address[3] & + cs->hw.elsa.base = dev_qs3000->resource[3].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); diff -u --recursive --new-file v2.3.12/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c --- v2.3.12/linux/drivers/isdn/hisax/netjet.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/isdn/hisax/netjet.c Fri Aug 6 11:43:09 1999 @@ -1074,7 +1074,7 @@ printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); return(0); } - cs->hw.njet.base = dev_netjet->base_address[0] & + cs->hw.njet.base = dev_netjet->resource[0].start & PCI_BASE_ADDRESS_IO_MASK; if (!cs->hw.njet.base) { printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); diff -u --recursive --new-file v2.3.12/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c --- v2.3.12/linux/drivers/isdn/hisax/niccy.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/isdn/hisax/niccy.c Fri Aug 6 11:43:09 1999 @@ -319,16 +319,16 @@ return(0); } cs->irq = niccy_dev->irq; - if (!niccy_dev->base_address[0]) { + if (!niccy_dev->resource[0].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); return(0); } - cs->hw.niccy.cfg_reg = niccy_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; - if (!niccy_dev->base_address[1]) { + cs->hw.niccy.cfg_reg = niccy_dev->resource[0].start & PCI_BASE_ADDRESS_IO_MASK; + if (!niccy_dev->resource[1].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr = niccy_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = niccy_dev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.3.12/linux/drivers/macintosh/adb.c Mon Jun 7 12:12:32 1999 +++ linux/drivers/macintosh/adb.c Wed Aug 4 16:36:41 1999 @@ -31,7 +31,7 @@ #include #include #include -#include +#include EXPORT_SYMBOL(adb_controller); EXPORT_SYMBOL(adb_client_list); diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.3.12/linux/drivers/macintosh/mac_keyb.c Mon Jun 7 12:12:32 1999 +++ linux/drivers/macintosh/mac_keyb.c Mon Aug 9 10:23:09 1999 @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include @@ -673,7 +673,7 @@ } -__initfunc(void mackbd_init_hw(void)) +void __init mackbd_init_hw(void) { if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) return; diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/macio-adb.c linux/drivers/macintosh/macio-adb.c --- v2.3.12/linux/drivers/macintosh/macio-adb.c Thu Apr 29 12:53:48 1999 +++ linux/drivers/macintosh/macio-adb.c Wed Aug 4 16:36:41 1999 @@ -14,7 +14,7 @@ #include #include #include -#include +#include struct preg { unsigned char r; diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.3.12/linux/drivers/macintosh/macserial.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/macintosh/macserial.c Mon Aug 9 10:23:09 1999 @@ -39,7 +39,7 @@ #ifdef CONFIG_KGDB #include #endif -#include +#include #include "macserial.h" @@ -2121,7 +2121,7 @@ * - initialize the serial port * Return non-zero if we didn't find a serial port. */ -__initfunc(static int serial_console_setup(struct console *co, char *options)) +static int __init serial_console_setup(struct console *co, char *options) { struct mac_serial *info = zs_soft + co->index; int baud = 38400; @@ -2306,7 +2306,7 @@ /* * Register console. */ -__initfunc (long serial_console_init(long kmem_start, long kmem_end)) +long __init serial_console_init(long kmem_start, long kmem_end) { register_console(&sercons); return kmem_start; @@ -2376,7 +2376,7 @@ * boot command line flags. * XXX at the moment probably only channel A will work */ -__initfunc(void zs_kgdb_hook(int tty_num)) +void __init zs_kgdb_hook(int tty_num) { /* Find out how many Z8530 SCCs we have */ if (zs_chain == 0) diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c --- v2.3.12/linux/drivers/macintosh/mediabay.c Mon Dec 21 08:37:28 1998 +++ linux/drivers/macintosh/mediabay.c Wed Aug 4 16:36:41 1999 @@ -25,7 +25,7 @@ #include #include #include -#include +#include #undef MB_USE_INTERRUPTS diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.3.12/linux/drivers/macintosh/nvram.c Thu Apr 29 12:53:48 1999 +++ linux/drivers/macintosh/nvram.c Mon Aug 9 10:23:09 1999 @@ -108,7 +108,7 @@ &nvram_fops }; -__initfunc(int nvram_init(void)) +int nvram_init(void) { printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", NVRAM_VERSION); diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c --- v2.3.12/linux/drivers/macintosh/via-cuda.c Thu Apr 29 12:53:48 1999 +++ linux/drivers/macintosh/via-cuda.c Wed Aug 4 16:36:41 1999 @@ -20,7 +20,7 @@ #include #include #include -#include +#include static volatile unsigned char *via; diff -u --recursive --new-file v2.3.12/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.3.12/linux/drivers/macintosh/via-pmu.c Thu Apr 29 12:53:48 1999 +++ linux/drivers/macintosh/via-pmu.c Wed Aug 4 16:36:41 1999 @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.3.12/linux/drivers/net/3c59x.c Tue Jan 19 14:47:15 1999 +++ linux/drivers/net/3c59x.c Thu Aug 5 15:04:52 1999 @@ -655,20 +655,9 @@ continue; { -#if LINUX_VERSION_CODE >= 0x20155 struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->base_address[0] & ~3; + ioaddr = pdev->resource[0].start; 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 } /* Power-up the card. */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.3.12/linux/drivers/net/Config.in Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/Config.in Fri Aug 6 10:44:11 1999 @@ -194,9 +194,11 @@ dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT fi -tristate 'PPP (point-to-point) support' CONFIG_PPP +tristate 'PPP (point-to-point protocol) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then - comment 'CCP compressors for PPP are only built as modules.' + dep_tristate 'PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP + dep_tristate 'PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP + dep_tristate 'PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m fi tristate 'SLIP (serial line) support' CONFIG_SLIP diff -u --recursive --new-file v2.3.12/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.3.12/linux/drivers/net/Makefile Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/Makefile Mon Aug 9 12:32:28 1999 @@ -302,16 +302,38 @@ # bsd_comp.o is *always* a module, for some documented reason # (licensing). ifeq ($(CONFIG_PPP),y) -LX_OBJS += ppp.o -M_OBJS += bsd_comp.o +LX_OBJS += ppp_generic.o CONFIG_SLHC_BUILTIN = y -CONFIG_PPPDEF_BUILTIN = y + ifeq ($(CONFIG_PPP_ASYNC),y) + LX_OBJS += ppp_async.o + else + ifeq ($(CONFIG_PPP_ASYNC),m) + MX_OBJS += ppp_async.o + endif + endif + ifeq ($(CONFIG_PPP_DEFLATE),y) + CONFIG_PPPDEF_BUILTIN = y + else + ifeq ($(CONFIG_PPP_DEFLATE),m) + CONFIG_PPPDEF_MODULE = y + endif + endif + ifeq ($(CONFIG_PPP_BSDCOMP),m) + M_OBJS += bsd_comp.o + endif else ifeq ($(CONFIG_PPP),m) + MX_OBJS += ppp_generic.o CONFIG_SLHC_MODULE = y - CONFIG_PPPDEF_MODULE = y - MX_OBJS += ppp.o - M_OBJS += bsd_comp.o + ifeq ($(CONFIG_PPP_ASYNC),m) + MX_OBJS += ppp_async.o + endif + ifeq ($(CONFIG_PPP_DEFLATE),m) + CONFIG_PPPDEF_MODULE = y + endif + ifeq ($(CONFIG_PPP_BSDCOMP),m) + M_OBJS += bsd_comp.o + endif endif endif @@ -845,13 +867,11 @@ # if anything built-in uses ppp_deflate, then build it into the kernel also. # If not, but a module uses it, build as a module. -# ... NO!!! ppp_deflate.o does not work as resident; -# it works only as a module! ifdef CONFIG_PPPDEF_BUILTIN -MX_OBJS += ppp_deflate.o +L_OBJS += ppp_deflate.o else ifdef CONFIG_PPPDEF_MODULE - MX_OBJS += ppp_deflate.o + M_OBJS += ppp_deflate.o endif endif @@ -884,6 +904,17 @@ M_OBJS += hplance.o endif endif + +ifeq ($(CONFIG_MVME147_NET),y) +L_OBJS += mvme147.o +CONFIG_7990_BUILTIN = y +else + ifeq ($(CONFIG_MVME147_NET),m) + CONFIG_7990_MODULE = y + M_OBJS += mvme147.o + endif +endif + # If we need generic LANCE support, either in the kernel or as a module, # build it in the appropriate way. ifdef CONFIG_7990_BUILTIN @@ -1054,6 +1085,10 @@ ifeq ($(CONFIG_MACE),m) M_OBJS += mace.o endif +endif + +ifeq ($(CONFIG_MACSONIC),y) +L_OBJS += macsonic.o endif ifeq ($(CONFIG_BMAC),y) diff -u --recursive --new-file v2.3.12/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.3.12/linux/drivers/net/Space.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/Space.c Mon Aug 9 12:32:28 1999 @@ -114,10 +114,12 @@ extern int hplance_probe(struct device *dev); extern int bagetlance_probe(struct device *); extern int dec_lance_probe(struct device *); +extern int mvme147lance_probe(struct device *dev); extern int via_rhine_probe(struct device *dev); extern int tc515_probe(struct device *dev); extern int lance_probe(struct device *dev); extern int rcpci_probe(struct device *); +extern int mac_onboard_sonic_probe(struct device *dev); /* Gigabit Ethernet adapters */ extern int yellowfin_probe(struct device *dev); @@ -425,6 +427,12 @@ #ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */ {hplance_probe, 0}, #endif +#ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ + {mvme147lance_probe, 0}, +#endif +#ifdef CONFIG_MACSONIC /* Mac 68k Quadra builtin Ethernet */ + {mac_onboard_sonic_probe, 0}, +#endif {NULL, 0}, }; @@ -679,6 +687,14 @@ #undef NEXT_DEV #define NEXT_DEV (&mkiss_bootstrap) #endif /* MKISS */ + +#if defined(CONFIG_YAM) +extern int yam_init(struct device *); +static struct device yam_bootstrap = { + "yam", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, yam_init, }; +#undef NEXT_DEV +#define NEXT_DEV (&yam_bootstrap) +#endif /* CONFIG_YAM */ #if defined(CONFIG_STRIP) extern int strip_init_ctrl_dev(struct device *); diff -u --recursive --new-file v2.3.12/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.3.12/linux/drivers/net/acenic.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/acenic.c Thu Aug 5 15:04:52 1999 @@ -288,13 +288,13 @@ break; } printk("Gigabit Ethernet at 0x%08lx, irq %i, PCI latency %i " - "clks\n", pdev->base_address[0], dev->irq, pci_latency); + "clks\n", pdev->resource[0].start, dev->irq, pci_latency); /* * Remap the regs into kernel space. */ - ap->regs = (struct ace_regs *)ioremap(pdev->base_address[0], + ap->regs = (struct ace_regs *)ioremap(pdev->resource[0].start, 0x4000); if (!ap->regs){ printk(KERN_ERR "%s: Unable to map I/O register, " diff -u --recursive --new-file v2.3.12/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c --- v2.3.12/linux/drivers/net/ariadne2.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/ariadne2.c Mon Aug 9 12:32:28 1999 @@ -177,6 +177,7 @@ name = "NE2000"; dev->base_addr = ioaddr; + dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, 0, "AriadNE2 Ethernet", @@ -191,7 +192,9 @@ ((struct ei_device *)dev->priv)->priv = key; for(i = 0; i < ETHER_ADDR_LEN; i++) { +#ifdef DEBUG printk(" %2.2x", SA_prom[i]); +#endif dev->dev_addr[i] = SA_prom[i]; } diff -u --recursive --new-file v2.3.12/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c --- v2.3.12/linux/drivers/net/atari_bionet.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/atari_bionet.c Mon Aug 9 12:32:28 1999 @@ -446,7 +446,7 @@ } else { int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned long buf = VTOP(skb->data); + unsigned long buf = virt_to_phys(skb->data); int stat; stdma_lock(bionet_intr, NULL); diff -u --recursive --new-file v2.3.12/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c --- v2.3.12/linux/drivers/net/atari_pamsnet.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/atari_pamsnet.c Mon Aug 9 12:32:28 1999 @@ -439,7 +439,7 @@ unsigned char *buffer; { int ret = -1; - unsigned char *vbuffer = (unsigned char *)PTOV(buffer); + unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); unsigned char cmd_buffer[5]; if (send_first(target, INQUIRY)) @@ -487,7 +487,7 @@ !acsi_wait_for_IRQ(TIMEOUTDMA) || get_status()) goto bad; - ret = (HADDR *)PTOV(&(((DMAHWADDR *)buffer)->hwaddr)); + ret = phys_to_virt(&(((DMAHWADDR *)buffer)->hwaddr)); dma_cache_maintenance((unsigned long)buffer, 512, 0); bad: return (ret); @@ -707,7 +707,7 @@ } else { int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned long buf = VTOP(skb->data); + unsigned long buf = virt_to_phys(skb->data); int stat; stdma_lock(pamsnet_intr, NULL); diff -u --recursive --new-file v2.3.12/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.3.12/linux/drivers/net/de4x5.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/de4x5.c Thu Aug 5 15:04:52 1999 @@ -2192,7 +2192,7 @@ lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ - iobase = pdev->base_address[0] & CBIO_MASK; + iobase = pdev->resource[0].start; /* Fetch the IRQ to be used */ irq = pdev->irq; @@ -2278,7 +2278,7 @@ lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ - iobase = dev->base_address[0] & CBIO_MASK; + iobase = dev->resource[0].start; /* Fetch the IRQ to be used */ irq = dev->irq; diff -u --recursive --new-file v2.3.12/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.3.12/linux/drivers/net/dgrs.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/dgrs.c Thu Aug 5 15:04:52 1999 @@ -1395,28 +1395,14 @@ &pci_device_fn)) break; -#if LINUX_VERSION_CODE < 0x20100 - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &plxreg); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &io); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &mem); -#else pdev = pci_find_slot(pci_bus, pci_device_fn); pci_irq = pdev->irq; - plxreg = pdev->base_address[0]; - io = pdev->base_address[1]; - mem = pdev->base_address[2]; -#endif + plxreg = pdev->resource[0].start; + io = pdev->resource[1].start; + mem = pdev->resource[2].start; pcibios_read_config_dword(pci_bus, pci_device_fn, 0x30, &plxdma); irq = pci_irq; - plxreg &= ~15; - io &= ~3; - mem &= ~15; plxdma &= ~15; /* diff -u --recursive --new-file v2.3.12/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.3.12/linux/drivers/net/eepro100.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/eepro100.c Mon Aug 9 10:26:12 1999 @@ -1,14 +1,14 @@ -/* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. */ +/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */ /* NOTICE: this version tested with kernels 1.3.72 and later only! - Written 1996-1998 by Donald Becker. + Written 1996-1999 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 Intel EtherExpress Pro 100B boards. - It should work with other i82557 and i82558 boards. - To use a built-in driver, install as drivers/net/eepro100.c. + This driver is for the Intel EtherExpress Pro100 (Speedo3) design. + It should work with all i82557/558/559 boards. + To use as a module, use the compile-command at the end of the file. The author may be reached as becker@CESDIS.usra.edu, or C/O @@ -16,15 +16,17 @@ Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 For updates see http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html - There is also a mailing list based at + For installation instructions + http://cesdis.gsfc.nasa.gov/linux/misc/modules.html + There is a Majordomo mailing list based at linux-eepro100@cesdis.gsfc.nasa.gov */ static const char *version = -"eepro100.c:v1.06 10/16/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"; +"eepro100.c:v1.09j 7/27/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"; /* A few user-configurable values that apply to all boards. - First set are undocumented and spelled per Intel recommendations. */ + First set is undocumented and spelled per Intel recommendations. */ static int congenb = 0; /* Enable congestion control in the DP83840. */ static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ @@ -38,14 +40,48 @@ static int rx_copybreak = 200; /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 200; +static int max_interrupt_work = 20; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */ -static int multicast_filter_limit = 3; +static int multicast_filter_limit = 64; -#include +/* 'options' is used to pass a transceiver override or full-duplex flag + e.g. "options=16" for FD, "options=32" for 100mbps-only. */ +static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; +#ifdef MODULE +static int debug = -1; /* The debug level */ +#endif + +/* A few values that may be tweaked. */ +/* The ring sizes should be a power of two for efficiency. */ +#define TX_RING_SIZE 32 /* Effectively 2 entries fewer. */ +#define RX_RING_SIZE 32 +/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */ +#define TX_QUEUE_LIMIT 12 + +/* Operational parameters that usually are not changed. */ + +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (2*HZ) +/* Size of an pre-allocated Rx buffer: + slack.*/ +#define PKT_BUF_SZ 1536 + +#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif #include +#include +#ifdef MODVERSIONS +#include +#endif + +#if LINUX_VERSION_CODE < 0x20200 && defined(MODVERSIONS) +#include +#endif #include #include #include @@ -53,19 +89,24 @@ #include #include #include +#ifdef HAS_PCI_NETIF +#include "pci-netif.h" +#else #include +#if LINUX_VERSION_CODE < 0x20155 +#include /* Ignore the bogus warning in 2.1.100+ */ +#endif +#endif +#include +#include +#include + #include #include #include #include -#include -#include -#include - -/* - * Module documentation - */ +#if LINUX_VERSION_CODE > 0x20118 && defined(MODULE) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver"); MODULE_PARM(debug, "i"); @@ -79,16 +120,39 @@ MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(multicast_filter_limit, "i"); +#endif #define RUN_AT(x) (jiffies + (x)) - +/* Condensed bus+endian portability operations. */ +#define virt_to_le32bus(addr) cpu_to_le32(virt_to_bus(addr)) +#define le32bus_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) + +#if (LINUX_VERSION_CODE < 0x20123) +#define test_and_set_bit(val, addr) set_bit(val, addr) +#define le16_to_cpu(val) (val) +#define cpu_to_le16(val) (val) +#define le32_to_cpu(val) (val) +#define cpu_to_le32(val) (val) +#define spin_lock_irqsave(&sp->lock, flags) save_flags(flags); cli(); +#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags); +#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 +#if ! defined(CAP_NET_ADMIN) +#define capable(CAP_XXX) (suser()) +#endif +#if ! defined(HAS_NETIF_QUEUE) +#define netif_wake_queue(dev) mark_bh(NET_BH); +#endif /* The total I/O port extent of the board. The registers beyond 0x18 only exist on the i82558. */ #define SPEEDO3_TOTAL_SIZE 0x20 -int speedo_debug = 0; +int speedo_debug = 1; /* Theory of Operation @@ -222,15 +286,52 @@ */ -/* A few values that may be tweaked. */ -/* The ring sizes should be a power of two for efficiency. */ -#define TX_RING_SIZE 16 /* Effectively 2 entries fewer. */ -#define RX_RING_SIZE 16 -/* Size of an pre-allocated Rx buffer: + slack.*/ -#define PKT_BUF_SZ 1536 +/* This table drives the PCI probe routines. */ +static struct device * +speedo_found1(int pci_bus, int pci_devfn, struct device *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); + +#ifdef USE_IO +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1 +#define SPEEDO_SIZE 32 +#else +#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0 +#define SPEEDO_SIZE 0x1000 +#endif -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT ((800*HZ)/1000) +#if defined(HAS_PCI_NETIF) +struct pci_id_info static pci_tbl[] = { + { "Intel PCI EtherExpress Pro100", + { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE, + 0, speedo_found1 }, + {0,}, /* 0 terminated list. */ +}; +#else +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 pci_tbl[] = { + { "Intel PCI EtherExpress Pro100", + 0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 }, + {0,}, /* 0 terminated list. */ +}; +#endif + +#ifndef USE_IO +#define inb readb +#define inw readw +#define inl readl +#define outb writeb +#define outw writew +#define outl writel +#endif /* How to wait for the command unit to accept a command. Typically this takes 0 ticks. */ @@ -241,10 +342,6 @@ while(inb(cmd_ioaddr) && --wait >= 0); } -/* Operational parameter that usually are not changed. */ - -/* The rest of these values should never change. */ - /* Offsets to the various registers. All accesses need not be longword aligned. */ enum speedo_offsets { @@ -257,33 +354,41 @@ }; /* Commands that can be put in a command list entry. */ enum commands { - CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7, - CmdSuspend = 0x4000, /* Suspend after completion. */ - CmdIntr = 0x2000, /* Interrupt after completion. */ - CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ + CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000, + CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000, + CmdDump = 0x60000, CmdDiagnose = 0x70000, + CmdSuspend = 0x40000000, /* Suspend after completion. */ + CmdIntr = 0x20000000, /* Interrupt after completion. */ + CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */ }; +/* Do atomically if possible. */ +#if defined(__i386__) || defined(__alpha__) +#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status) +#elif defined(__powerpc__) +#define clear_suspend(cmd) clear_bit(6, &(cmd)->cmd_status) +#else +#define clear_suspend(cmd) (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend) +#endif -/* The SCB accepts the following controls for the Tx and Rx units: */ -#define CU_START 0x0010 -#define CU_RESUME 0x0020 -#define CU_STATSADDR 0x0040 -#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ -#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */ -#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ - -#define RX_START 0x0001 -#define RX_RESUME 0x0002 -#define RX_ABORT 0x0004 -#define RX_ADDR_LOAD 0x0006 -#define RX_RESUMENR 0x0007 -#define INT_MASK 0x0100 -#define DRVR_INT 0x0200 /* Driver generated interrupt. */ +enum SCBCmdBits { + SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000, + SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400, + SCBTriggerIntr=0x0200, SCBMaskAll=0x0100, + /* The rest are Rx and Tx commands. */ + CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050, + CUCmdBase=0x0060, /* CU Base address (set to zero) . */ + CUDumpStats=0x0070, /* Dump then reset stats counters. */ + RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006, + RxResumeNoResources=0x0007, +}; + +enum SCBPort_cmds { + PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3, +}; /* The Speedo3 Rx and Tx frame/buffer descriptors. */ struct descriptor { /* A generic descriptor. */ - s16 status; /* Offset 0. */ - s16 command; /* Offset 2. */ + s32 cmd_status; /* All command and status fields. */ u32 link; /* struct descriptor * */ unsigned char params[0]; }; @@ -293,8 +398,7 @@ s32 status; u32 link; /* struct RxFD * */ u32 rx_buf_addr; /* void * */ - u16 count; - u16 size; + u32 count; }; /* Selected elements of the Tx/RxFD.status word. */ @@ -302,7 +406,7 @@ RxComplete=0x8000, RxOK=0x2000, RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010, RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002, - StatusComplete=0x8000, + TxUnderrun=0x1000, StatusComplete=0x8000, }; struct TxFD { /* Transmit frame descriptor set. */ @@ -338,49 +442,57 @@ u32 done_marker; }; +/* Do not change the position (alignment) of the first few elements! + The later elements are grouped for cache locality. */ struct speedo_private { - char devname[8]; /* Used only for kernel debugging. */ - const char *product_name; - struct device *next_module; - spinlock_t lock; - struct TxFD tx_ring[TX_RING_SIZE] /* Commands (usually CmdTxPacket). */ - __attribute__ ((aligned (L1_CACHE_BYTES)));; - /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct TxFD tx_ring[TX_RING_SIZE]; /* Commands (usually CmdTxPacket). */ + struct RxFD *rx_ringp[RX_RING_SIZE]; /* Rx descriptor, used as ring. */ + /* The addresses of a Tx/Rx-in-place packets/buffers. */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; - struct descriptor *last_cmd; /* Last command sent. */ - /* Rx descriptor ring & addresses of receive-in-place skbuffs. */ - struct RxFD *rx_ringp[RX_RING_SIZE]; struct sk_buff* rx_skbuff[RX_RING_SIZE]; + struct descriptor *last_cmd; /* Last command sent. */ + unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */ + spinlock_t lock; /* Group with Tx control cache line. */ + u32 tx_threshold; /* The value for txdesc.count. */ struct RxFD *last_rxf; /* Last command sent. */ + unsigned int cur_rx, dirty_rx; /* The next free ring entry */ + long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ + const char *product_name; + struct device *next_module; + void *priv_addr; /* Unaligned address for kfree */ struct enet_statistics stats; struct speedo_stats lstats; + int chip_id; + unsigned char pci_bus, pci_devfn, acpi_pwr; struct timer_list timer; /* Media selection timer. */ - long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ int mc_setup_frm_len; /* The length of an allocated.. */ struct descriptor *mc_setup_frm; /* ..multicast setup frame. */ int mc_setup_busy; /* Avoid double-use of setup frame. */ + int in_interrupt; /* Word-aligned dev->interrupt */ char rx_mode; /* Current PROMISC/ALLMULTI setting. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int default_port:1; /* Last dev->if_port value. */ + unsigned int flow_ctrl:1; /* Use 802.3x flow control. */ unsigned int rx_bug:1; /* Work around receiver hang errata. */ unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */ unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */ + unsigned char default_port:8; /* Last dev->if_port value. */ unsigned short phy[2]; /* PHY media interfaces available. */ + unsigned short advertising; /* Current PHY advertised caps. */ + unsigned short partner; /* Link partner caps. */ + long last_reset; }; /* The parameters for a CmdConfigure operation. There are so many options that it would be difficult to document each bit. We mostly use the default or recommended settings. */ const char i82557_config_cmd[22] = { - 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 0x3f, 0x05, }; const char i82558_config_cmd[22] = { - 22, 0x08, 0, 1, 0, 0x80, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ + 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0x08, 0x88, 0x68, 0, 0x40, 0xf2, 0xBD, /* 0xBD->0xFD=Force full-duplex */ 0x31, 0x05, }; @@ -394,16 +506,16 @@ enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240, S80C24, I82555, DP83840A=10, }; static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 }; +#define EE_READ_CMD (6) -static void speedo_found1(struct device *dev, long ioaddr, int irq, - int card_idx); - -static int read_eeprom(long ioaddr, int location, int addr_len); +static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); static int mdio_write(long ioaddr, int phy_id, int location, int value); static int speedo_open(struct device *dev); +static void speedo_resume(struct device *dev); static void speedo_timer(unsigned long data); static void speedo_init_rx_ring(struct device *dev); +static void speedo_tx_timeout(struct device *dev); static int speedo_start_xmit(struct sk_buff *skb, struct device *dev); static int speedo_rx(struct device *dev); static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -414,15 +526,6 @@ -/* The parameters that may be passed in... */ -/* 'options' is used to pass a transceiver override or full-duplex flag - e.g. "options=16" for FD, "options=32" for 100mbps-only. */ -static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; -#ifdef MODULE -static int debug = -1; /* The debug level */ -#endif - #ifdef honor_default_port /* Optional driver feature to allow forcing the transceiver setting. Not recommended. */ @@ -433,6 +536,7 @@ /* A list of all installed Speedo devices, for removing the driver module. */ static struct device *root_speedo_dev = NULL; +#if ! defined(HAS_PCI_NETIF) int eepro100_init(struct device *dev) { int cards_found = 0; @@ -443,6 +547,7 @@ for (; pci_index < 8; pci_index++) { unsigned char pci_bus, pci_device_fn, pci_latency; + u32 pciaddr; long ioaddr; int irq; @@ -453,13 +558,42 @@ pci_index, &pci_bus, &pci_device_fn)) break; +#if LINUX_VERSION_CODE >= 0x20155 || PCI_SUPPORT_1 { struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->base_address[1]; /* Use [0] to mem-map */ +#ifdef USE_IO + pciaddr = pdev->resource[1].start; +#else + pciaddr = pdev->resource[0].start; +#endif irq = pdev->irq; } +#else + { + u8 pci_irq_line; + pcibios_read_config_byte(pci_bus, pci_device_fn, + PCI_INTERRUPT_LINE, &pci_irq_line); + /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */ +#ifdef USE_IO + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_1, &pciaddr); +#else + pcibios_read_config_dword(pci_bus, pci_device_fn, + PCI_BASE_ADDRESS_0, &pciaddr); +#endif + irq = pci_irq_line; + } +#endif /* Remove I/O space marker in bit 0. */ - ioaddr &= ~3; + if (pciaddr & 1) { + ioaddr = pciaddr & ~3; + if (check_region(ioaddr, 32)) + continue; + } else if ((ioaddr = (long)ioremap(pciaddr & ~0xf, 0x1000)) == 0) { + printk(KERN_INFO "Failed to map PCI address %#x.\n", + pciaddr); + continue; + } if (speedo_debug > 2) printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", ioaddr, irq); @@ -485,25 +619,29 @@ } else if (speedo_debug > 1) printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency); - speedo_found1(dev, ioaddr, irq, cards_found); + speedo_found1(pci_bus, pci_device_fn, dev, ioaddr, irq, 0,cards_found); dev = NULL; cards_found++; } return cards_found; } +#endif -static void speedo_found1(struct device *dev, long ioaddr, int irq, - int card_idx) +static struct device * +speedo_found1(int pci_bus, int pci_devfn, struct device *dev, + long ioaddr, int irq, int chip_idx, int card_idx) { - static int did_version = 0; /* Already printed version info. */ struct speedo_private *sp; - char *product; + const char *product; int i, option; - u16 eeprom[0x40]; - + u16 eeprom[0x100]; + int acpi_idle_state = 0; +#ifndef MODULE + static int did_version = 0; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); +#endif dev = init_etherdev(dev, sizeof(struct speedo_private)); @@ -514,16 +652,31 @@ else option = 0; +#if defined(HAS_PCI_NETIF) + acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0); +#endif + /* Read the station address EEPROM before doing the reset. - Perhaps this should even be done before accepting the device, - then we wouldn't have a device name with which to report the error. */ + Nominally his should even be done before accepting the device, but + then we wouldn't have a device name with which to report the error. + The size test is for 6 bit vs. 8 bit address serial EEPROMs. + */ { u16 sum = 0; int j; - int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6; + int read_cmd, ee_size; - for (j = 0, i = 0; i < 0x40; i++) { - u16 value = read_eeprom(ioaddr, i, addr_len); + if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000) + == 0xffe0000) { + ee_size = 0x100; + read_cmd = EE_READ_CMD << 24; + } else { + ee_size = 0x40; + read_cmd = EE_READ_CMD << 22; + } + + for (j = 0, i = 0; i < ee_size; i++) { + u16 value = do_eeprom_cmd(ioaddr, read_cmd | (i << 16), 27); eeprom[i] = value; sum += value; if (i < 3) { @@ -542,12 +695,12 @@ /* Reset the chip: stop Tx and Rx processes and clear counters. This takes less than 10usec and will easily finish before the next action. */ - outl(0, ioaddr + SCBPort); + outl(PortReset, ioaddr + SCBPort); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else - product = "Intel EtherExpress Pro 10/100"; + product = pci_tbl[chip_idx].name; printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr); @@ -600,7 +753,7 @@ self_test_results = (s32*) ((((long) str) + 15) & ~0xf); self_test_results[0] = 0; self_test_results[1] = -1; - outl(virt_to_bus(self_test_results) | 1, ioaddr + SCBPort); + outl(virt_to_bus(self_test_results) | PortSelfTest, ioaddr + SCBPort); do { udelay(10); } while (self_test_results[1] == -1 && --boguscnt >= 0); @@ -624,19 +777,33 @@ } #endif /* kernel_bloat */ + outl(PortReset, ioaddr + SCBPort); +#if defined(HAS_PCI_NETIF) + /* Return the chip to its original power state. */ + acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state); +#endif + /* We do a request_region() only to register /proc/ioports info. */ request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet"); dev->base_addr = ioaddr; dev->irq = irq; - if (dev->priv == NULL) - dev->priv = kmalloc(sizeof(*sp), GFP_KERNEL); sp = dev->priv; + if (dev->priv == NULL) { + void *mem = kmalloc(sizeof(*sp), GFP_KERNEL); + dev->priv = sp = mem; /* Cache align here if kmalloc does not. */ + sp->priv_addr = mem; + } memset(sp, 0, sizeof(*sp)); sp->next_module = root_speedo_dev; root_speedo_dev = dev; + sp->pci_bus = pci_bus; + sp->pci_devfn = pci_devfn; + sp->chip_id = chip_idx; + sp->acpi_pwr = acpi_idle_state; + sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { if (full_duplex[card_idx] >= 0) @@ -659,7 +826,7 @@ dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; - return; + return dev; } /* Serial EEPROM section. @@ -668,47 +835,33 @@ #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ #define EE_CS 0x02 /* EEPROM chip select. */ #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x01 -#define EE_WRITE_1 0x05 #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ #define EE_ENB (0x4800 | EE_CS) +#define EE_WRITE_0 0x4802 +#define EE_WRITE_1 0x4806 +#define EE_OFFSET SCBeeprom /* Delay between EEPROM clock transitions. - This will actually work with no delay on 33Mhz PCI. */ -#define eeprom_delay(nanosec) udelay(1); + The code works with no delay on 33Mhz PCI. */ +#define eeprom_delay() inw(ee_addr) -/* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << addr_len) -#define EE_READ_CMD (6 << addr_len) -#define EE_ERASE_CMD (7 << addr_len) - -static int read_eeprom(long ioaddr, int location, int addr_len) -{ - unsigned short retval = 0; - int ee_addr = ioaddr + SCBeeprom; - int read_cmd = location | EE_READ_CMD; - int i; +static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len) +{ + unsigned retval = 0; + long ee_addr = ioaddr + SCBeeprom; - outw(EE_ENB & ~EE_CS, ee_addr); - outw(EE_ENB, ee_addr); + outw(EE_ENB | EE_SHIFT_CLK, ee_addr); - /* Shift the read command bits out. */ - for (i = 12; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outw(EE_ENB | dataval, ee_addr); - eeprom_delay(100); - outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(150); - } - outw(EE_ENB, ee_addr); - - for (i = 15; i >= 0; i--) { - outw(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(100); + /* Shift the command bits out. */ + do { + short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + outw(dataval, ee_addr); + eeprom_delay(); + outw(dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); - outw(EE_ENB, ee_addr); - eeprom_delay(100); - } + } while (--cmd_len >= 0); + outw(EE_ENB, ee_addr); /* Terminate the EEPROM access. */ outw(EE_ENB & ~EE_CS, ee_addr); @@ -723,6 +876,7 @@ val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val); + break; } } while (! (val & 0x10000000)); return val & 0xffff; @@ -737,6 +891,7 @@ val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val); + break; } } while (! (val & 0x10000000)); return val & 0xffff; @@ -749,21 +904,31 @@ struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; -#ifdef notdef - /* We could reset the chip, but should not need to. */ - /* In fact we MUST NOT, unless we also re-do the init */ - outl(0, ioaddr + SCBPort); - udelay(10); +#if defined(HAS_PCI_NETIF) + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); #endif - /* This had better be initialized before we initialize the interrupt! */ - sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; - if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); -#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us - /* Retrigger negotiation to reset previous errors. */ + /* Set up the Tx queue early.. */ + sp->cur_tx = 0; + sp->dirty_tx = 0; + sp->last_cmd = 0; + sp->tx_full = 0; + sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + sp->in_interrupt = 0; + + /* .. we can safely take handler calls during init. */ + if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { + return -EAGAIN; + } + MOD_INC_USE_COUNT; + + dev->if_port = sp->default_port; +#if 0 + /* With some transceivers we must retrigger negotiation to reset + power-up errors. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f ; /* Use 0x3300 for restarting NWay, other values to force xcvr: @@ -780,85 +945,30 @@ } #endif - /* Load the statistics block address. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer); - outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd); - sp->lstats.done_marker = 0; - speedo_init_rx_ring(dev); - wait_for_cmd_done(ioaddr + SCBCmd); - outl(0, ioaddr + SCBPointer); - outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd); - - /* Todo: verify that we must wait for previous command completion. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(sp->rx_ringp[0]), ioaddr + SCBPointer); - outw(INT_MASK | RX_START, ioaddr + SCBCmd); - - /* Fill the first command with our physical address. */ - { - u16 *eaddrs = (u16 *)dev->dev_addr; - u16 *setup_frm = (u16 *)&(sp->tx_ring[0].tx_desc_addr); - /* Avoid a bug(?!) here by marking the command already completed. */ - sp->tx_ring[0].status = ((CmdSuspend | CmdIASetup) << 16) | 0xa000; - sp->tx_ring[0].link = virt_to_bus(&(sp->tx_ring[1])); - *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; - } - sp->last_cmd = (struct descriptor *)&sp->tx_ring[0]; - sp->cur_tx = 1; - sp->dirty_tx = 0; - sp->tx_full = 0; - - wait_for_cmd_done(ioaddr + SCBCmd); - outl(0, ioaddr + SCBPointer); - outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd); - - dev->if_port = sp->default_port; + /* Fire up the hardware. */ + speedo_resume(dev); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; - /* Start the chip's Tx process and unmask interrupts. */ - /* Todo: verify that we must wait for previous command completion. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outl(virt_to_bus(&sp->tx_ring[0]), ioaddr + SCBPointer); - outw(CU_START, ioaddr + SCBCmd); - /* Setup the chip and configure the multicast list. */ sp->mc_setup_frm = NULL; sp->mc_setup_frm_len = 0; sp->mc_setup_busy = 0; sp->rx_mode = -1; /* Invalid -> always reset the mode. */ + sp->flow_ctrl = sp->partner = 0; set_rx_mode(dev); + if ((sp->phy[0] & 0x8000) == 0) + sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4); if (speedo_debug > 2) { printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n", dev->name, inw(ioaddr + SCBStatus)); } - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_DUMPSTATS, ioaddr + SCBCmd); - - /* - * Request the IRQ last, after we have set up all data structures. - * It would be bad to get an interrupt before we're ready. - */ - if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, - "Intel EtherExpress Pro 10/100 Ethernet", dev)) { - return -EAGAIN; - } - - /* No need to wait for the command unit to accept here. */ - if ((sp->phy[0] & 0x8000) == 0) - mdio_read(ioaddr, sp->phy[0] & 0x1f, 0); - - MOD_INC_USE_COUNT; - /* Set the timer. The timer serves a dual purpose: 1) to monitor the media interface (e.g. link beat) and perhaps switch to an alternate media type @@ -870,20 +980,104 @@ sp->timer.function = &speedo_timer; /* timer handler */ add_timer(&sp->timer); + /* No need to wait for the command unit to accept here. */ + if ((sp->phy[0] & 0x8000) == 0) + mdio_read(ioaddr, sp->phy[0] & 0x1f, 0); return 0; } +/* Start the chip hardware after a full reset. */ +static void speedo_resume(struct device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + + outw(SCBMaskAll, ioaddr + SCBCmd); + + /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */ + sp->tx_threshold = 0x01208000; + + /* Set the segment registers to '0'. */ + wait_for_cmd_done(ioaddr + SCBCmd); + outl(0, ioaddr + SCBPointer); + outb(RxAddrLoad, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + outb(CUCmdBase, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + + /* Load the statistics block and rx ring addresses. */ + outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer); + outb(CUStatsAddr, ioaddr + SCBCmd); + sp->lstats.done_marker = 0; + wait_for_cmd_done(ioaddr + SCBCmd); + + outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), + ioaddr + SCBPointer); + outb(RxStart, ioaddr + SCBCmd); + wait_for_cmd_done(ioaddr + SCBCmd); + + outb(CUDumpStats, ioaddr + SCBCmd); + + /* Fill the first command with our physical address. */ + { + int entry = sp->cur_tx++ % TX_RING_SIZE; + struct descriptor *cur_cmd = (struct descriptor *)&sp->tx_ring[entry]; + + /* Avoid a bug(?!) here by marking the command already completed. */ + cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); + cur_cmd->link = + virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); + memcpy(cur_cmd->params, dev->dev_addr, 6); + if (sp->last_cmd) + clear_suspend(sp->last_cmd); + sp->last_cmd = cur_cmd; + } + + /* Start the chip's Tx process and unmask interrupts. */ + wait_for_cmd_done(ioaddr + SCBCmd); + outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), + ioaddr + SCBPointer); + outw(CUStart, ioaddr + SCBCmd); +} + /* Media monitoring and control. */ static void speedo_timer(unsigned long data) { struct device *dev = (struct device *)data; struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; + + /* We have MII and lost link beat. */ + if ((sp->phy[0] & 0x8000) == 0) { + int partner = mdio_read(ioaddr, phy_num, 5); + if (partner != sp->partner) { + int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0; + sp->partner = partner; + if (flow_ctrl != sp->flow_ctrl) { + sp->flow_ctrl = flow_ctrl; + sp->rx_mode = -1; /* Trigger a reload. */ + } + /* Clear sticky bit. */ + mdio_read(ioaddr, phy_num, 1); + /* If link beat has returned... */ + if (mdio_read(ioaddr, phy_num, 1) & 0x0004) + dev->flags |= IFF_RUNNING; + else + dev->flags &= ~IFF_RUNNING; + } + } if (speedo_debug > 3) { - long ioaddr = dev->base_addr; printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); } + /* This has a small false-trigger window. */ + if (test_bit(0, (void*)&dev->tbusy) && + (jiffies - dev->trans_start) > TX_TIMEOUT) { + speedo_tx_timeout(dev); + sp->last_reset = jiffies; + } if (sp->rx_mode < 0 || (sp->rx_bug && jiffies - sp->last_rx_time > 2*HZ)) { /* We haven't received a packet in a Long Time. We might have been @@ -896,6 +1090,39 @@ add_timer(&sp->timer); } +static void speedo_show_state(struct device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; + int i; + + /* Print a few items for debugging. */ + if (speedo_debug > 0) { + int i; + printk(KERN_DEBUG "%s: Tx ring dump, Tx queue %d / %d:\n", dev->name, + sp->cur_tx, sp->dirty_tx); + for (i = 0; i < TX_RING_SIZE; i++) + printk(KERN_DEBUG "%s: %c%c%d %8.8x.\n", dev->name, + i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ', + i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ', + i, sp->tx_ring[i].status); + } + printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n", + dev->name, sp->cur_rx); + + for (i = 0; i < RX_RING_SIZE; i++) + printk(KERN_DEBUG " Rx ring entry %d %8.8x.\n", + i, (int)sp->rx_ringp[i]->status); + + for (i = 0; i < 16; i++) { + if (i == 6) i = 21; + printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", + phy_num, i, mdio_read(ioaddr, phy_num, i)); + } + +} + /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void speedo_init_rx_ring(struct device *dev) @@ -917,9 +1144,9 @@ sp->rx_ringp[i] = rxf; skb_reserve(skb, sizeof(struct RxFD)); if (last_rxf) - last_rxf->link = virt_to_bus(rxf); + last_rxf->link = virt_to_le32bus(rxf); last_rxf = rxf; - rxf->status = 0x00000001; /* '1' is flag value only. */ + rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */ rxf->link = 0; /* None yet. */ /* This field unused by i82557, we use it as a consistency check. */ #ifdef final_version @@ -927,12 +1154,11 @@ #else rxf->rx_buf_addr = virt_to_bus(skb->tail); #endif - rxf->count = 0; - rxf->size = PKT_BUF_SZ; + rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); } sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); /* Mark the last entry as end-of-list. */ - last_rxf->status = 0xC0000002; /* '2' is flag value only. */ + last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */ sp->last_rxf = last_rxf; } @@ -940,22 +1166,33 @@ { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; + int status = inw(ioaddr + SCBStatus); + + /* Trigger a stats dump to give time before the reset. */ + speedo_get_stats(dev); printk(KERN_WARNING "%s: Transmit timed out: status %4.4x " " %4.4x at %d/%d command %8.8x.\n", - dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd), + dev->name, status, inw(ioaddr + SCBCmd), sp->dirty_tx, sp->cur_tx, sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status); - if ((inw(ioaddr + SCBStatus) & 0x00C0) != 0x0080) { + speedo_show_state(dev); + if ((status & 0x00C0) != 0x0080 + && (status & 0x003C) == 0x0010) { + /* Only the command unit has stopped. */ printk(KERN_WARNING "%s: Trying to restart the transmitter...\n", dev->name); outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]), ioaddr + SCBPointer); - outw(CU_START, ioaddr + SCBCmd); + outw(CUStart, ioaddr + SCBCmd); } else { - outw(DRVR_INT, ioaddr + SCBCmd); + /* Reset the Tx and Rx units. */ + outl(PortReset, ioaddr + SCBPort); + if (speedo_debug > 0) + speedo_show_state(dev); + udelay(10); + speedo_resume(dev); } -#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f; @@ -967,7 +1204,6 @@ mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]); #endif } -#endif sp->stats.tx_errors++; dev->trans_start = jiffies; return; @@ -989,7 +1225,7 @@ return 1; if (tickssofar < TX_TIMEOUT) { /* Reap sent packets from the full Tx queue. */ - outw(DRVR_INT, ioaddr + SCBCmd); + outw(SCBTriggerIntr, ioaddr + SCBCmd); return 1; } speedo_tx_timeout(dev); @@ -1003,43 +1239,39 @@ unsigned long flags; spin_lock_irqsave(&sp->lock, flags); - /* Calculate the Tx descriptor entry. */ entry = sp->cur_tx++ % TX_RING_SIZE; sp->tx_skbuff[entry] = skb; /* Todo: be a little more clever about setting the interrupt bit. */ sp->tx_ring[entry].status = - (CmdSuspend | CmdTx | CmdTxFlex) << 16; + cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex); sp->tx_ring[entry].link = - virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); + virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); sp->tx_ring[entry].tx_desc_addr = - virt_to_bus(&sp->tx_ring[entry].tx_buf_addr0); - /* The data region is always in one buffer descriptor, Tx FIFO - threshold of 256. */ - sp->tx_ring[entry].count = 0x01208000; - sp->tx_ring[entry].tx_buf_addr0 = virt_to_bus(skb->data); - sp->tx_ring[entry].tx_buf_size0 = skb->len; + virt_to_le32bus(&sp->tx_ring[entry].tx_buf_addr0); + /* The data region is always in one buffer descriptor. */ + sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold); + sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32bus(skb->data); + sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len); /* Todo: perhaps leave the interrupt bit set if the Tx queue is more than half full. Argument against: we should be receiving packets and scavenging the queue. Argument for: if so, it shouldn't matter. */ - sp->last_cmd->command &= ~(CmdSuspend | CmdIntr); - sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; - /* Trigger the command unit resume. */ - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); - + { + struct descriptor *last_cmd = sp->last_cmd; + sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; + clear_suspend(last_cmd); + } + if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) + sp->tx_full = 1; + else + clear_bit(0, (void*)&dev->tbusy); spin_unlock_irqrestore(&sp->lock, flags); } - - /* Leave room for set_rx_mode() to fill two entries. */ - if (sp->cur_tx - sp->dirty_tx > TX_RING_SIZE - 3) - sp->tx_full = 1; - else - clear_bit(0, (void*)&dev->tbusy); - + wait_for_cmd_done(ioaddr + SCBCmd); + outw(CUResume, ioaddr + SCBCmd); dev->trans_start = jiffies; return 0; @@ -1063,9 +1295,14 @@ ioaddr = dev->base_addr; sp = (struct speedo_private *)dev->priv; - spin_lock(&sp->lock); - #ifndef final_version + /* A lock to prevent simultaneous entry on SMP machines. */ + if (test_and_set_bit(0, (void*)&sp->in_interrupt)) { + printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", + dev->name); + sp->in_interrupt = 0; /* Avoid halting machine. */ + return; + } dev->interrupt = 1; #endif @@ -1085,37 +1322,44 @@ speedo_rx(dev); if (status & 0x1000) { - if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */ - outw(RX_RESUMENR, ioaddr + SCBCmd); - else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */ - /* No idea of what went wrong. Restart the receiver. */ - outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), - ioaddr + SCBPointer); - outw(RX_START, ioaddr + SCBCmd); - } - sp->stats.rx_errors++; + if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */ + outw(RxResumeNoResources, ioaddr + SCBCmd); + else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */ + /* No idea of what went wrong. Restart the receiver. */ + outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), + ioaddr + SCBPointer); + outw(RxStart, ioaddr + SCBCmd); + } + sp->stats.rx_errors++; } /* User interrupt, Command/Tx unit interrupt or CU not active. */ if (status & 0xA400) { - unsigned int dirty_tx = sp->dirty_tx; + unsigned int dirty_tx; + spin_lock(&sp->lock); + dirty_tx = sp->dirty_tx; while (sp->cur_tx - dirty_tx > 0) { int entry = dirty_tx % TX_RING_SIZE; - int status = sp->tx_ring[entry].status; + int status = le32_to_cpu(sp->tx_ring[entry].status); if (speedo_debug > 5) printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n", entry, status); if ((status & StatusComplete) == 0) break; /* It still hasn't been processed. */ + if (status & TxUnderrun) + if (sp->tx_threshold < 0x01e08000) + sp->tx_threshold += 0x00040000; /* Free the original skb. */ if (sp->tx_skbuff[entry]) { sp->stats.tx_packets++; /* Count only user packets. */ - sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */ +#if LINUX_VERSION_CODE > 0x20127 + sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; +#endif dev_free_skb(sp->tx_skbuff[entry]); sp->tx_skbuff[entry] = 0; - } else if ((sp->tx_ring[entry].status&0x70000) == CmdNOp << 16) + } else if ((status & 0x70000) == CmdNOp) sp->mc_setup_busy = 0; dirty_tx++; } @@ -1129,15 +1373,16 @@ } #endif - if (sp->tx_full && dev->tbusy - && dirty_tx > sp->cur_tx - TX_RING_SIZE + 2) { + sp->dirty_tx = dirty_tx; + if (sp->tx_full + && sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) { /* The ring is no longer full, clear tbusy. */ sp->tx_full = 0; clear_bit(0, (void*)&dev->tbusy); - mark_bh(NET_BH); - } - - sp->dirty_tx = dirty_tx; + spin_unlock(&sp->lock); + netif_wake_queue(dev); + } else + spin_unlock(&sp->lock); } if (--boguscnt < 0) { @@ -1154,7 +1399,7 @@ dev->name, inw(ioaddr + SCBStatus)); dev->interrupt = 0; - spin_unlock(&sp->lock); + clear_bit(0, (void*)&sp->in_interrupt); return; } @@ -1170,26 +1415,25 @@ printk(KERN_DEBUG " In speedo_rx().\n"); /* If we own the next entry, it's a new packet. Send it up. */ while (sp->rx_ringp[entry] != NULL && - (status = sp->rx_ringp[entry]->status) & RxComplete) { + (status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete) { + int pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; if (--rx_work_limit < 0) break; if (speedo_debug > 4) printk(KERN_DEBUG " speedo_rx() status %8.8x len %d.\n", status, - sp->rx_ringp[entry]->count & 0x3fff); - if ((status & (RxErrTooBig|RxOK)) != RxOK) { + pkt_len); + if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) { if (status & RxErrTooBig) printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, " "status %8.8x!\n", dev->name, status); - else if ( ! (status & 0x2000)) { + else if ( ! (status & RxOK)) { /* There was a fatal error. This *should* be impossible. */ sp->stats.rx_errors++; printk(KERN_ERR "%s: Anomalous event in speedo_rx(), " - "status %8.8x.\n", - dev->name, status); + "status %8.8x.\n", dev->name, status); } } else { - int pkt_len = sp->rx_ringp[entry]->count & 0x3fff; struct sk_buff *skb; /* Check if the packet is long enough to just accept without @@ -1201,13 +1445,11 @@ /* 'skb_put()' points to the start of sk_buff data area. */ #if 1 || USE_IP_CSUM /* Packet is in one chunk -- we can copy + cksum. */ - eth_copy_and_sum(skb, - bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), - pkt_len, 0); + eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), - bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), pkt_len); + memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail, + pkt_len); #endif } else { void *temp; @@ -1220,24 +1462,28 @@ } sp->rx_skbuff[entry] = NULL; temp = skb_put(skb, pkt_len); +#if !defined(final_version) && !defined(__powerpc__) if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp) printk(KERN_ERR "%s: Rx consistency error -- the skbuff " "addresses do not match in speedo_rx: %p vs. %p " "/ %p.\n", dev->name, bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), skb->head, temp); +#endif sp->rx_ringp[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); sp->stats.rx_packets++; - sp->stats.rx_bytes += pkt_len; /* Count received bytes */ +#if LINUX_VERSION_CODE > 0x20127 + sp->stats.rx_bytes += pkt_len; +#endif } entry = (++sp->cur_rx) % RX_RING_SIZE; } /* Refill the Rx ring buffers. */ - for (; sp->dirty_rx < sp->cur_rx; sp->dirty_rx++) { + for (; sp->cur_rx - sp->dirty_rx > 0; sp->dirty_rx++) { struct RxFD *rxf; entry = sp->dirty_rx % RX_RING_SIZE; if (sp->rx_skbuff[entry] == NULL) { @@ -1252,16 +1498,15 @@ rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail; skb->dev = dev; skb_reserve(skb, sizeof(struct RxFD)); - rxf->rx_buf_addr = virt_to_bus(skb->tail); + rxf->rx_buf_addr = virt_to_le32bus(skb->tail); } else { rxf = sp->rx_ringp[entry]; } - rxf->status = 0xC0000001; /* '1' for driver use only. */ + rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */ rxf->link = 0; /* None yet. */ - rxf->count = 0; - rxf->size = PKT_BUF_SZ; - sp->last_rxf->link = virt_to_bus(rxf); - sp->last_rxf->status &= ~0xC0000000; + rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); + sp->last_rxf->link = virt_to_le32bus(rxf); + sp->last_rxf->status &= cpu_to_le32(~0xC0000000); sp->last_rxf = rxf; } @@ -1287,8 +1532,8 @@ del_timer(&sp->timer); /* Disable interrupts, and stop the chip's Rx process. */ - outw(INT_MASK, ioaddr + SCBCmd); - outw(INT_MASK | RX_ABORT, ioaddr + SCBCmd); + outw(SCBMaskAll, ioaddr + SCBCmd); + outw(SCBMaskAll | RxAbort, ioaddr + SCBCmd); free_irq(dev->irq, dev); @@ -1297,8 +1542,12 @@ struct sk_buff *skb = sp->rx_skbuff[i]; sp->rx_skbuff[i] = 0; /* Clear the Rx descriptors. */ - if (skb) + if (skb) { +#if LINUX_VERSION_CODE < 0x20100 + skb->free = 1; +#endif dev_free_skb(skb); + } } for (i = 0; i < TX_RING_SIZE; i++) { @@ -1314,22 +1563,13 @@ } /* Print a few items for debugging. */ - if (speedo_debug > 3) { - int phy_num = sp->phy[0] & 0x1f; - printk(KERN_DEBUG "%s:Printing Rx ring (next to receive into %d).\n", - dev->name, sp->cur_rx); - - for (i = 0; i < RX_RING_SIZE; i++) - printk(KERN_DEBUG " Rx ring entry %d %8.8x.\n", - i, (int)sp->rx_ringp[i]->status); - - for (i = 0; i < 5; i++) - printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", - phy_num, i, mdio_read(ioaddr, phy_num, i)); - for (i = 21; i < 26; i++) - printk(KERN_DEBUG " PHY index %d register %d is %4.4x.\n", - phy_num, i, mdio_read(ioaddr, phy_num, i)); - } + if (speedo_debug > 3) + speedo_show_state(dev); + +#if defined(HAS_PCI_NETIF) + /* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */ + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2); +#endif MOD_DEC_USE_COUNT; return 0; @@ -1353,22 +1593,23 @@ struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; - if (sp->lstats.done_marker == 0xA007) { /* Previous dump finished */ - sp->stats.tx_aborted_errors += sp->lstats.tx_coll16_errs; - sp->stats.tx_window_errors += sp->lstats.tx_late_colls; - sp->stats.tx_fifo_errors += sp->lstats.tx_underruns; - sp->stats.tx_fifo_errors += sp->lstats.tx_lost_carrier; - /*sp->stats.tx_deferred += sp->lstats.tx_deferred;*/ - sp->stats.collisions += sp->lstats.tx_total_colls; - sp->stats.rx_crc_errors += sp->lstats.rx_crc_errs; - sp->stats.rx_frame_errors += sp->lstats.rx_align_errs; - sp->stats.rx_over_errors += sp->lstats.rx_resource_errs; - sp->stats.rx_fifo_errors += sp->lstats.rx_overrun_errs; - sp->stats.rx_length_errors += sp->lstats.rx_runt_errs; + /* Update only if the previous dump finished. */ + if (sp->lstats.done_marker == le32_to_cpu(0xA007)) { + sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats.tx_coll16_errs); + sp->stats.tx_window_errors += le32_to_cpu(sp->lstats.tx_late_colls); + sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_underruns); + sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_lost_carrier); + /*sp->stats.tx_deferred += le32_to_cpu(sp->lstats.tx_deferred);*/ + sp->stats.collisions += le32_to_cpu(sp->lstats.tx_total_colls); + sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats.rx_crc_errs); + sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats.rx_align_errs); + sp->stats.rx_over_errors += le32_to_cpu(sp->lstats.rx_resource_errs); + sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats.rx_overrun_errs); + sp->stats.rx_length_errors += le32_to_cpu(sp->lstats.rx_runt_errs); sp->lstats.done_marker = 0x0000; if (dev->start) { wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_DUMPSTATS, ioaddr + SCBCmd); + outw(CUDumpStats, ioaddr + SCBCmd); } } return &sp->stats; @@ -1380,17 +1621,32 @@ long ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_data; int phy = sp->phy[0] & 0x1f; +#if defined(HAS_PCI_NETIF) + int saved_acpi; +#endif switch(cmd) { case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ +#if defined(HAS_PCI_NETIF) + saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); data[3] = mdio_read(ioaddr, data[0], data[1]); + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); +#else + data[3] = mdio_read(ioaddr, data[0], data[1]); +#endif return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; +#if defined(HAS_PCI_NETIF) + saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0); + mdio_write(ioaddr, data[0], data[1], data[2]); + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi); +#else mdio_write(ioaddr, data[0], data[1], data[2]); +#endif return 0; default: return -EOPNOTSUPP; @@ -1406,8 +1662,7 @@ loaded the link -- we convert the current command block, normally a Tx command, into a no-op and link it to the new command. */ -static void -set_rx_mode(struct device *dev) +static void set_rx_mode(struct device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; @@ -1440,9 +1695,9 @@ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; sp->tx_skbuff[entry] = 0; /* Redundant. */ - sp->tx_ring[entry].status = (CmdSuspend | CmdConfigure) << 16; + sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure); sp->tx_ring[entry].link = - virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); + virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr; /* Construct a full CmdConfig frame. */ memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd)); @@ -1450,6 +1705,7 @@ config_cmd_data[4] = rxdmacount; config_cmd_data[5] = txdmacount + 0x80; config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0; + config_cmd_data[19] = sp->flow_ctrl ? 0xBD : 0x80; config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0; config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05; if (sp->phy[0] & 0x8000) { /* Use the AUI port instead. */ @@ -1457,11 +1713,9 @@ config_cmd_data[8] = 0; } /* Trigger the command unit resume. */ - last_cmd->command &= ~CmdSuspend; - wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); - + clear_suspend(last_cmd); + outw(CUResume, ioaddr + SCBCmd); spin_unlock_irqrestore(&sp->lock, flags); } @@ -1477,12 +1731,12 @@ sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry]; sp->tx_skbuff[entry] = 0; - sp->tx_ring[entry].status = (CmdSuspend | CmdMulticastList) << 16; + sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList); sp->tx_ring[entry].link = - virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); + virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]); sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */ setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr; - *setup_params++ = dev->mc_count*6; + *setup_params++ = cpu_to_le16(dev->mc_count*6); /* Fill in the multicast addresses. */ for (i = 0, mclist = dev->mc_list; i < dev->mc_count; i++, mclist = mclist->next) { @@ -1492,12 +1746,10 @@ *setup_params++ = *eaddrs++; } - last_cmd->command &= ~CmdSuspend; - - /* Immediately trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); - + clear_suspend(last_cmd); + /* Immediately trigger the command unit resume. */ + outw(CUResume, ioaddr + SCBCmd); spin_unlock_irqrestore(&sp->lock, flags); } else if (new_rx_mode == 0) { struct dev_mc_list *mclist; @@ -1521,7 +1773,7 @@ } } /* If we are busy, someone might be quickly adding to the MC list. - Try again later when the list changes stop. */ + Try again later when the list updates stop. */ if (sp->mc_setup_busy) { sp->rx_mode = -1; return; @@ -1532,11 +1784,11 @@ printk(KERN_DEBUG "%s: Constructing a setup frame at %p, " "%d bytes.\n", dev->name, sp->mc_setup_frm, sp->mc_setup_frm_len); - mc_setup_frm->status = 0; - mc_setup_frm->command = CmdSuspend | CmdIntr | CmdMulticastList; + mc_setup_frm->cmd_status = + cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList); /* Link set below. */ setup_params = (u16 *)&mc_setup_frm->params; - *setup_params++ = dev->mc_count*6; + *setup_params++ = cpu_to_le16(dev->mc_count*6); /* Fill in the multicast addresses. */ for (i = 0, mclist = dev->mc_list; i < dev->mc_count; i++, mclist = mclist->next) { @@ -1548,7 +1800,6 @@ /* Disable interrupts while playing with the Tx Cmd list. */ spin_lock_irqsave(&sp->lock, flags); - entry = sp->cur_tx++ % TX_RING_SIZE; last_cmd = sp->last_cmd; sp->last_cmd = mc_setup_frm; @@ -1556,21 +1807,18 @@ /* Change the command to a NoOp, pointing to the CmdMulti command. */ sp->tx_skbuff[entry] = 0; - sp->tx_ring[entry].status = CmdNOp << 16; - sp->tx_ring[entry].link = virt_to_bus(mc_setup_frm); + sp->tx_ring[entry].status = cpu_to_le32(CmdNOp); + sp->tx_ring[entry].link = virt_to_le32bus(mc_setup_frm); /* Set the link in the setup frame. */ mc_setup_frm->link = - virt_to_bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE])); - - last_cmd->command &= ~CmdSuspend; + virt_to_le32bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE])); - /* Immediately trigger the command unit resume. */ wait_for_cmd_done(ioaddr + SCBCmd); - outw(CU_RESUME, ioaddr + SCBCmd); - + clear_suspend(last_cmd); + /* Immediately trigger the command unit resume. */ + outw(CUResume, ioaddr + SCBCmd); spin_unlock_irqrestore(&sp->lock, flags); - if (speedo_debug > 5) printk(" CmdMCSetup frame length %d in entry %d.\n", dev->mc_count, entry); @@ -1581,42 +1829,64 @@ #ifdef MODULE -int -init_module(void) +int init_module(void) { int cards_found; if (debug >= 0) speedo_debug = debug; + /* Always emit the version message. */ if (speedo_debug) printk(KERN_INFO "%s", version); - root_speedo_dev = NULL; +#if defined(HAS_PCI_NETIF) + cards_found = netif_pci_probe(pci_tbl, NULL); + if (cards_found < 0) + printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); + return cards_found; +#else cards_found = eepro100_init(NULL); - return cards_found ? 0 : -ENODEV; + if (cards_found <= 0) { + printk(KERN_INFO "eepro100: No cards found, driver not installed.\n"); + return -ENODEV; + } +#endif + return 0; } -void -cleanup_module(void) +void cleanup_module(void) { struct device *next_dev; /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_speedo_dev) { - next_dev = ((struct speedo_private *)root_speedo_dev->priv)->next_module; + struct speedo_private *sp = (void *)root_speedo_dev->priv; unregister_netdev(root_speedo_dev); +#ifdef USE_IO release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE); +#else + iounmap((char *)root_speedo_dev->base_addr); +#endif +#if defined(HAS_PCI_NETIF) + acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr); +#endif + next_dev = sp->next_module; + if (sp->priv_addr) + kfree(sp->priv_addr); kfree(root_speedo_dev); root_speedo_dev = next_dev; } } + #else /* not MODULE */ + int eepro100_probe(struct device *dev) { int cards_found = 0; cards_found = eepro100_init(dev); + /* Only emit the version if the driver is being used. */ if (speedo_debug > 0 && cards_found) printk(version); @@ -1626,8 +1896,9 @@ /* * Local variables: - * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" - * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`" + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * simple-compile-command: "gcc -DMODULE -D__KERNEL__ -O6 -c eepro100.c" * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 diff -u --recursive --new-file v2.3.12/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.3.12/linux/drivers/net/epic100.c Thu Apr 29 11:53:41 1999 +++ linux/drivers/net/epic100.c Thu Aug 5 15:04:52 1999 @@ -285,7 +285,7 @@ struct pci_dev *pcidev = NULL; while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev)) != NULL) { - long pci_ioaddr = pcidev->base_address[0] & ~3; + long pci_ioaddr = pcidev->resource[0].start; int vendor = pcidev->vendor; int device = pcidev->device; diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/Config.in linux/drivers/net/hamradio/Config.in --- v2.3.12/linux/drivers/net/hamradio/Config.in Tue Dec 29 11:30:56 1998 +++ linux/drivers/net/hamradio/Config.in Thu Aug 5 14:35:52 1999 @@ -16,7 +16,7 @@ dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_PARPORT dep_tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP $CONFIG_PARPORT -tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM +dep_tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM $CONFIG_PARPORT if [ "$CONFIG_SOUNDMODEM" != "n" ]; then bool ' soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC bool ' soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS @@ -28,3 +28,5 @@ bool ' soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800 bool ' soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600 fi + +tristate 'YAM driver for AX.25' CONFIG_YAM diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/Makefile linux/drivers/net/hamradio/Makefile --- v2.3.12/linux/drivers/net/hamradio/Makefile Sun Jun 7 11:13:45 1998 +++ linux/drivers/net/hamradio/Makefile Thu Aug 5 14:35:52 1999 @@ -53,6 +53,14 @@ endif endif +ifeq ($(CONFIG_YAM),y) +L_OBJS += yam.o +else + ifeq ($(CONFIG_YAM),m) + M_OBJS += yam.o + endif +endif + ifeq ($(CONFIG_PI),y) L_OBJS += pi2.o else diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c --- v2.3.12/linux/drivers/net/hamradio/baycom_epp.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/net/hamradio/baycom_epp.c Wed Aug 4 09:27:34 1999 @@ -31,6 +31,8 @@ * Integrated FPGA EPP modem configuration routines * 0.3 11.05.98 Took FPGA config out and moved it into a separate program * 0.4 26.07.99 Adapted to new lowlevel parport driver interface + * 0.5 03.08.99 adapt to Linus' new __setup/__initcall + * removed some pre-2.2 kernel compatibility cruft * */ @@ -39,25 +41,13 @@ #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 @@ -71,56 +61,6 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - #define BAYCOM_DEBUG #define BAYCOM_MAGIC 19730510 @@ -148,8 +88,8 @@ /* --------------------------------------------------------------------- */ static const char bc_drvname[] = "baycom_epp"; -static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_epp: version 0.4 compiled " __TIME__ " " __DATE__ "\n"; +static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "baycom_epp: version 0.5 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -157,11 +97,6 @@ static struct device baycom_device[NR_PORTS]; -static struct { - const char *mode; - int iobase; -} baycom_ports[NR_PORTS] = { { NULL, 0 }, }; - /* --------------------------------------------------------------------- */ /* EPP status register */ @@ -1477,7 +1412,18 @@ /* --------------------------------------------------------------------- */ -__initfunc(int baycom_epp_init(void)) +/* + * command line settable parameters + */ +static const char *mode[NR_PORTS] = { "", }; +static int iobase[NR_PORTS] = { 0x378, }; + +/* --------------------------------------------------------------------- */ + +#ifndef MODULE +static +#endif +int __init init_module(void) { struct device *dev; int i, found = 0; @@ -1490,10 +1436,10 @@ */ for (i = 0; i < NR_PORTS; i++) { dev = baycom_device+i; - if (!baycom_ports[i].mode) + if (!mode[i]) set_hw = 0; if (!set_hw) - baycom_ports[i].iobase = 0; + iobase[i] = 0; memset(dev, 0, sizeof(struct device)); if (!(bc = dev->priv = kmalloc(sizeof(struct baycom_state), GFP_KERNEL))) return -ENOMEM; @@ -1513,7 +1459,7 @@ dev->init = baycom_probe; dev->start = 0; dev->tbusy = 1; - dev->base_addr = baycom_ports[i].iobase; + dev->base_addr = iobase[i]; dev->irq = 0; dev->dma = 0; if (register_netdev(dev)) { @@ -1521,7 +1467,7 @@ kfree(dev->priv); return -ENXIO; } - if (set_hw && baycom_setmode(bc, baycom_ports[i].mode)) + if (set_hw && baycom_setmode(bc, mode[i])) set_hw = 0; found++; } @@ -1534,39 +1480,14 @@ #ifdef MODULE -/* - * command line settable parameters - */ -static const char *mode[NR_PORTS] = { "epp", }; -static int iobase[NR_PORTS] = { 0x378, }; - -#if LINUX_VERSION_CODE >= 0x20115 - -MODULE_PARM(mode, "s"); -MODULE_PARM_DESC(mode, "baycom operating mode; epp"); -MODULE_PARM(iobase, "i"); +MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); +MODULE_PARM_DESC(mode, "baycom operating mode"); +MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(iobase, "baycom io base address"); MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom epp amateur radio modem driver"); -#endif - -__initfunc(int init_module(void)) -{ - int i; - - for (i = 0; (i < NR_PORTS) && (mode[i]); i++) { - baycom_ports[i].mode = mode[i]; - baycom_ports[i].iobase = iobase[i]; - } - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; - return baycom_epp_init(); -} - -/* --------------------------------------------------------------------- */ - void cleanup_module(void) { struct device *dev; @@ -1587,27 +1508,30 @@ } #else /* MODULE */ -/* --------------------------------------------------------------------- */ + /* - * format: baycom=io,mode - * mode: epp + * format: baycom_epp=io,mode + * mode: fpga config options */ -__initfunc(void baycom_epp_setup(char *str, int *ints)) +static int __init baycom_epp_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[11]; - for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 1)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", bc_drvname); - return; - } - baycom_ports[i].mode = str; - baycom_ports[i].iobase = ints[1]; - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, ints); + if (ints[0] < 1) + return 0; + mode[nr_dev] = str; + iobase[nr_dev] = ints[1]; + nr_dev++; + return 1; } + +__setup("baycom_epp=", baycom_epp_setup); +__initcall(init_module); #endif /* MODULE */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/baycom_par.c linux/drivers/net/hamradio/baycom_par.c --- v2.3.12/linux/drivers/net/hamradio/baycom_par.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/baycom_par.c Fri Aug 6 11:16:54 1999 @@ -3,7 +3,7 @@ /* * baycom_par.c -- baycom par96 and picpar radio modem driver. * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -58,10 +58,13 @@ * 0.3 26.04.97 init code/data tagged * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints) * 0.5 11.11.97 split into separate files for ser12/par96 + * 0.6 03.08.99 adapt to Linus' new __setup/__initcall + * removed some pre-2.2 kernel compatibility cruft */ /*****************************************************************************/ +#include #include #include #include @@ -74,6 +77,8 @@ #include #include #include +#include +#include #include #include #include @@ -83,56 +88,6 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern __inline__ int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern __inline__ int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - #define BAYCOM_DEBUG /* @@ -143,8 +98,8 @@ /* --------------------------------------------------------------------- */ static const char bc_drvname[] = "baycom_par"; -static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1997 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_par: version 0.5 compiled " __TIME__ " " __DATE__ "\n"; +static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "baycom_par: version 0.6 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -152,11 +107,6 @@ static struct device baycom_device[NR_PORTS]; -static struct { - const char *mode; - int iobase; -} baycom_ports[NR_PORTS] = { { NULL, 0 }, }; - /* --------------------------------------------------------------------- */ #define SER12_EXTENT 8 @@ -533,14 +483,24 @@ /* --------------------------------------------------------------------- */ -int __init baycom_par_init(void) +/* + * command line settable parameters + */ +static const char *mode[NR_PORTS] = { "picpar", }; +static int iobase[NR_PORTS] = { 0x378, }; + +/* --------------------------------------------------------------------- */ + +#ifndef MODULE +static +#endif +int __init init_module(void) { int i, j, found = 0; char set_hw = 1; struct baycom_state *bc; char ifname[HDLCDRV_IFNAMELEN]; - printk(bc_drvinfo); /* * register net devices @@ -549,16 +509,15 @@ struct device *dev = baycom_device+i; sprintf(ifname, "bcp%d", i); - if (!baycom_ports[i].mode) + if (!mode[i]) set_hw = 0; if (!set_hw) - baycom_ports[i].iobase = 0; - j = hdlcdrv_register_hdlcdrv(dev, &par96_ops, - sizeof(struct baycom_state), - ifname, baycom_ports[i].iobase, 0, 0); + iobase[i] = 0; + j = hdlcdrv_register_hdlcdrv(dev, &par96_ops, sizeof(struct baycom_state), + ifname, iobase[i], 0, 0); if (!j) { bc = (struct baycom_state *)dev->priv; - if (set_hw && baycom_setmode(bc, baycom_ports[i].mode)) + if (set_hw && baycom_setmode(bc, mode[i])) set_hw = 0; found++; } else { @@ -575,14 +534,6 @@ #ifdef MODULE -/* - * command line settable parameters - */ -static const char *mode[NR_PORTS] = { "picpar", }; -static int iobase[NR_PORTS] = { 0x378, }; - -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar"); MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); @@ -591,23 +542,6 @@ MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver"); -#endif - -int __init init_module(void) -{ - int i; - - for (i = 0; (i < NR_PORTS) && (mode[i]); i++) { - baycom_ports[i].mode = mode[i]; - baycom_ports[i].iobase = iobase[i]; - } - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; - return baycom_par_init(); -} - -/* --------------------------------------------------------------------- */ - void cleanup_module(void) { int i; @@ -627,27 +561,30 @@ } #else /* MODULE */ -/* --------------------------------------------------------------------- */ + /* * format: baycom_par=io,mode * mode: par96,picpar */ -void __init baycom_par_setup(char *str, int *ints) +static int __init baycom_par_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[11]; - for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 1)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", bc_drvname); - return; - } - baycom_ports[i].mode = str; - baycom_ports[i].iobase = ints[1]; - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, ints); + if (ints[0] < 1) + return 0; + mode[nr_dev] = str; + iobase[nr_dev] = ints[1]; + nr_dev++; + return 1; } + +__setup("baycom_par=", baycom_par_setup); +__initcall(init_module); #endif /* MODULE */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/baycom_ser_fdx.c linux/drivers/net/hamradio/baycom_ser_fdx.c --- v2.3.12/linux/drivers/net/hamradio/baycom_ser_fdx.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/baycom_ser_fdx.c Fri Aug 6 11:16:54 1999 @@ -3,7 +3,7 @@ /* * baycom_ser_fdx.c -- baycom ser12 fullduplex radio modem driver. * - * Copyright (C) 1997-1998 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -60,30 +60,20 @@ * 0.6 24.01.98 Thorsten Kranzkowski, dl8bcu and Thomas Sailer: * reduced interrupt load in transmit case * reworked receiver + * 0.7 03.08.99 adapt to Linus' new __setup/__initcall */ /*****************************************************************************/ +#include #include -#include -#include -#include -#include -#include #include -#include #include #include -#include #include -#include #include -#include -#include -#include #include #include -#include /* --------------------------------------------------------------------- */ @@ -97,8 +87,8 @@ /* --------------------------------------------------------------------- */ static const char bc_drvname[] = "baycom_ser_fdx"; -static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1997-1998 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_fdx: version 0.6 compiled " __TIME__ " " __DATE__ "\n"; +static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "baycom_ser_fdx: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -106,11 +96,6 @@ static struct device baycom_device[NR_PORTS]; -static struct { - char *mode; - int iobase, irq, baud; -} baycom_ports[NR_PORTS] = { { NULL, 0, 0 }, }; - /* --------------------------------------------------------------------- */ #define RBR(iobase) (iobase+0) @@ -605,7 +590,20 @@ /* --------------------------------------------------------------------- */ -int __init baycom_ser_fdx_init(void) +/* + * command line settable parameters + */ +static char *mode[NR_PORTS] = { "ser12*", }; +static int iobase[NR_PORTS] = { 0x3f8, }; +static int irq[NR_PORTS] = { 4, }; +static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 }; + +/* --------------------------------------------------------------------- */ + +#ifndef MODULE +static +#endif +int __init init_module(void) { int i, j, found = 0; char set_hw = 1; @@ -621,19 +619,17 @@ struct device *dev = baycom_device+i; sprintf(ifname, "bcsf%d", i); - if (!baycom_ports[i].mode) + if (!mode[i]) set_hw = 0; if (!set_hw) - baycom_ports[i].iobase = baycom_ports[i].irq = 0; - j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, - sizeof(struct baycom_state), - ifname, baycom_ports[i].iobase, - baycom_ports[i].irq, 0); + iobase[i] = irq[i] = 0; + j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, sizeof(struct baycom_state), + ifname, iobase[i], irq[i], 0); if (!j) { bc = (struct baycom_state *)dev->priv; - if (set_hw && baycom_setmode(bc, baycom_ports[i].mode)) + if (set_hw && baycom_setmode(bc, mode[i])) set_hw = 0; - bc->baud = baycom_ports[i].baud; + bc->baud = baud[i]; found++; } else { printk(KERN_WARNING "%s: cannot register net device\n", @@ -649,16 +645,6 @@ #ifdef MODULE -/* - * command line settable parameters - */ -static char *mode[NR_PORTS] = { "ser12*", }; -static int iobase[NR_PORTS] = { 0x3f8, }; -static int irq[NR_PORTS] = { 4, }; -static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 }; - -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD"); MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); @@ -671,25 +657,6 @@ MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver"); -#endif - -int __init init_module(void) -{ - int i; - - for (i = 0; (i < NR_PORTS) && (mode[i]); i++) { - baycom_ports[i].mode = mode[i]; - baycom_ports[i].iobase = iobase[i]; - baycom_ports[i].irq = irq[i]; - baycom_ports[i].baud = baud[i]; - } - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; - return baycom_ser_fdx_init(); -} - -/* --------------------------------------------------------------------- */ - void cleanup_module(void) { int i; @@ -709,33 +676,34 @@ } #else /* MODULE */ -/* --------------------------------------------------------------------- */ + /* * format: baycom_ser_fdx=io,irq,mode * mode: [*] * * indicates sofware DCD */ -void __init baycom_ser_fdx_setup(char *str, int *ints) +static int __init baycom_ser_fdx_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[11]; - for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 2)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", bc_drvname); - return; - } - baycom_ports[i].mode = str; - baycom_ports[i].iobase = ints[1]; - baycom_ports[i].irq = ints[2]; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, ints); + if (ints[0] < 2) + return 0; + mode[nr_dev] = str; + iobase[nr_dev] = ints[1]; + irq[nr_dev] = ints[2]; if (ints[0] >= 3) - baycom_ports[i].baud = ints[3]; - else - baycom_ports[i].baud = 1200; - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; + baud[nr_dev] = ints[3]; + nr_dev++; + return 1; } + +__setup("baycom_ser_fdx=", baycom_ser_fdx_setup); +__initcall(init_module); #endif /* MODULE */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/baycom_ser_hdx.c linux/drivers/net/hamradio/baycom_ser_hdx.c --- v2.3.12/linux/drivers/net/hamradio/baycom_ser_hdx.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/baycom_ser_hdx.c Fri Aug 6 11:16:54 1999 @@ -3,7 +3,7 @@ /* * baycom_ser_hdx.c -- baycom ser12 halfduplex radio modem driver. * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -49,30 +49,20 @@ * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints) * 0.5 11.11.97 ser12/par96 split into separate files * 0.6 14.04.98 cleanups + * 0.7 03.08.99 adapt to Linus' new __setup/__initcall */ /*****************************************************************************/ +#include #include -#include -#include -#include -#include -#include #include -#include #include #include #include -#include -#include #include -#include -#include -#include #include #include -#include /* --------------------------------------------------------------------- */ @@ -86,8 +76,8 @@ /* --------------------------------------------------------------------- */ static const char bc_drvname[] = "baycom_ser_hdx"; -static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1997-1998 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_ser_hdx: version 0.6 compiled " __TIME__ " " __DATE__ "\n"; +static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "baycom_ser_hdx: version 0.7 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -95,11 +85,6 @@ static struct device baycom_device[NR_PORTS]; -static struct { - char *mode; - int iobase, irq; -} baycom_ports[NR_PORTS] = { { NULL, 0, 0 }, }; - /* --------------------------------------------------------------------- */ #define RBR(iobase) (iobase+0) @@ -643,7 +628,19 @@ /* --------------------------------------------------------------------- */ -int __init baycom_ser_hdx_init(void) +/* + * command line settable parameters + */ +static char *mode[NR_PORTS] = { "ser12*", }; +static int iobase[NR_PORTS] = { 0x3f8, }; +static int irq[NR_PORTS] = { 4, }; + +/* --------------------------------------------------------------------- */ + +#ifndef MODULE +static +#endif +int __init init_module(void) { int i, j, found = 0; char set_hw = 1; @@ -659,17 +656,15 @@ struct device *dev = baycom_device+i; sprintf(ifname, "bcsh%d", i); - if (!baycom_ports[i].mode) + if (!mode[i]) set_hw = 0; if (!set_hw) - baycom_ports[i].iobase = baycom_ports[i].irq = 0; - j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, - sizeof(struct baycom_state), - ifname, baycom_ports[i].iobase, - baycom_ports[i].irq, 0); + iobase[i] = irq[i] = 0; + j = hdlcdrv_register_hdlcdrv(dev, &ser12_ops, sizeof(struct baycom_state), + ifname, iobase[i], irq[i], 0); if (!j) { bc = (struct baycom_state *)dev->priv; - if (set_hw && baycom_setmode(bc, baycom_ports[i].mode)) + if (set_hw && baycom_setmode(bc, mode[i])) set_hw = 0; found++; } else { @@ -686,15 +681,6 @@ #ifdef MODULE -/* - * command line settable parameters - */ -static char *mode[NR_PORTS] = { "ser12*", }; -static int iobase[NR_PORTS] = { 0x3f8, }; -static int irq[NR_PORTS] = { 4, }; - -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD"); MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); @@ -705,24 +691,6 @@ MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Baycom ser12 half duplex amateur radio modem driver"); -#endif - -int __init init_module(void) -{ - int i; - - for (i = 0; (i < NR_PORTS) && (mode[i]); i++) { - baycom_ports[i].mode = mode[i]; - baycom_ports[i].iobase = iobase[i]; - baycom_ports[i].irq = irq[i]; - } - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; - return baycom_ser_hdx_init(); -} - -/* --------------------------------------------------------------------- */ - void cleanup_module(void) { int i; @@ -742,29 +710,32 @@ } #else /* MODULE */ -/* --------------------------------------------------------------------- */ + /* - * format: baycom_ser_=io,irq,mode + * format: baycom_ser_hdx=io,irq,mode * mode: [*] * * indicates sofware DCD */ -void __init baycom_ser_hdx_setup(char *str, int *ints) +static int __init baycom_ser_hdx_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[11]; - for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 2)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", bc_drvname); - return; - } - baycom_ports[i].mode = str; - baycom_ports[i].iobase = ints[1]; - baycom_ports[i].irq = ints[2]; - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, ints); + if (ints[0] < 2) + return 0; + mode[nr_dev] = str; + iobase[nr_dev] = ints[1]; + irq[nr_dev] = ints[2]; + nr_dev++; + return 1; } + +__setup("baycom_ser_hdx=", baycom_ser_hdx_setup); +__initcall(init_module); #endif /* MODULE */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c --- v2.3.12/linux/drivers/net/hamradio/hdlcdrv.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/hdlcdrv.c Wed Aug 4 09:27:34 1999 @@ -3,7 +3,7 @@ /* * hdlcdrv.c -- HDLC packet radio network driver. * - * Copyright (C) 1996-1998 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -36,6 +36,7 @@ * 0.5 30.07.97 made HDLC buffers bigger (solves a problem with the * soundmodem driver) * 0.6 05.04.98 add spinlocks + * 0.7 03.08.99 removed some old compatibility cruft */ /*****************************************************************************/ @@ -516,11 +517,7 @@ /* --------------------------------------------------------------------- */ -#if LINUX_VERSION_CODE >= 0x20119 static struct net_device_stats *hdlcdrv_get_stats(struct device *dev) -#else -static struct enet_statistics *hdlcdrv_get_stats(struct device *dev) -#endif { struct hdlcdrv_state *sm; @@ -695,9 +692,6 @@ bi.data.ocs.ptt = hdlcdrv_ptt(s); bi.data.ocs.dcd = s->hdlcrx.dcd; bi.data.ocs.ptt_keyed = s->ptt_keyed; -#if LINUX_VERSION_CODE < 0x20100 - bi.data.ocs.stats = s->stats; -#endif break; case HDLCDRVCTL_CALIBRATE: @@ -900,48 +894,25 @@ /* --------------------------------------------------------------------- */ -#if LINUX_VERSION_CODE >= 0x20115 - EXPORT_SYMBOL(hdlcdrv_receiver); EXPORT_SYMBOL(hdlcdrv_transmitter); EXPORT_SYMBOL(hdlcdrv_arbitrate); EXPORT_SYMBOL(hdlcdrv_register_hdlcdrv); EXPORT_SYMBOL(hdlcdrv_unregister_hdlcdrv); -#else - -static struct symbol_table hdlcdrv_syms = { -#include - X(hdlcdrv_receiver), - X(hdlcdrv_transmitter), - X(hdlcdrv_arbitrate), - X(hdlcdrv_register_hdlcdrv), - X(hdlcdrv_unregister_hdlcdrv), -#include -}; - -#endif - /* --------------------------------------------------------------------- */ #ifdef MODULE -#if LINUX_VERSION_CODE >= 0x20115 - MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder"); -#endif - /* --------------------------------------------------------------------- */ int __init init_module(void) { printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n"); - printk(KERN_INFO "hdlcdrv: version 0.6 compiled " __TIME__ " " __DATE__ "\n"); -#if LINUX_VERSION_CODE < 0x20115 - register_symtab(&hdlcdrv_syms); -#endif + printk(KERN_INFO "hdlcdrv: version 0.7 compiled " __TIME__ " " __DATE__ "\n"); return 0; } diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/soundmodem/sm.c linux/drivers/net/hamradio/soundmodem/sm.c --- v2.3.12/linux/drivers/net/hamradio/soundmodem/sm.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/soundmodem/sm.c Wed Aug 4 09:27:34 1999 @@ -3,7 +3,7 @@ /* * sm.c -- soundcard radio modem driver. * - * Copyright (C) 1996-1998 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -41,34 +41,28 @@ * 0.6 16.04.97 init code/data tagged * 0.7 30.07.97 fixed halfduplex interrupt handlers/hotfix for CS423X * 0.8 14.04.98 cleanups + * 0.9 03.08.99 adapt to Linus' new __setup/__initcall + * use parport lowlevel drivers instead of directly writing to a parallel port + * removed some pre-2.2 kernel compatibility cruft */ /*****************************************************************************/ #include +#include #include -#include -#include -#include #include -#include -#include #include #include +#include #include -#include -#include -#include -#include -#include -#include #include "sm.h" /* --------------------------------------------------------------------- */ /*static*/ const char sm_drvname[] = "soundmodem"; -static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-1998 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "soundmodem: version 0.8 compiled " __TIME__ " " __DATE__ "\n"; +static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "soundmodem: version 0.9 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ @@ -146,17 +140,8 @@ #define NR_PORTS 4 -/* --------------------------------------------------------------------- */ - static struct device sm_device[NR_PORTS]; -static struct { - char *mode; - int iobase, irq, dma, dma2, seriobase, pariobase, midiiobase; -} sm_ports[NR_PORTS] = { - { NULL, -1, 0, 0, 0, -1, -1, -1 }, -}; - /* --------------------------------------------------------------------- */ #define UART_RBR(iobase) (iobase+0) @@ -174,13 +159,6 @@ #define SER_EXTENT 8 -#define LPT_DATA(iobase) (iobase+0) -#define LPT_STATUS(iobase) (iobase+1) -#define LPT_CONTROL(iobase) (iobase+2) -#define LPT_IRQ_ENABLE 0x10 - -#define LPT_EXTENT 3 - #define MIDI_DATA(iobase) (iobase) #define MIDI_STATUS(iobase) (iobase+1) #define MIDI_READ_FULL 0x80 /* attention: negative logic!! */ @@ -202,47 +180,10 @@ #define SP_PAR 2 #define SP_MIDI 4 -/* --------------------------------------------------------------------- */ /* * ===================== port checking routines ======================== */ -/* - * returns 0 if ok and != 0 on error; - * the same behaviour as par96_check_lpt in baycom.c - */ - -/* - * returns 0 if ok and != 0 on error; - * the same behaviour as par96_check_lpt in baycom.c - */ - -static int check_lpt(unsigned int iobase) -{ - unsigned char b1,b2; - int i; - - if (iobase <= 0 || iobase > 0x1000-LPT_EXTENT) - return 0; - if (check_region(iobase, LPT_EXTENT)) - return 0; - b1 = inb(LPT_DATA(iobase)); - b2 = inb(LPT_CONTROL(iobase)); - outb(0xaa, LPT_DATA(iobase)); - i = inb(LPT_DATA(iobase)) == 0xaa; - outb(0x55, LPT_DATA(iobase)); - i &= inb(LPT_DATA(iobase)) == 0x55; - outb(0x0a, LPT_CONTROL(iobase)); - i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x0a; - outb(0x05, LPT_CONTROL(iobase)); - i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x05; - outb(b1, LPT_DATA(iobase)); - outb(b2, LPT_CONTROL(iobase)); - return !i; -} - -/* --------------------------------------------------------------------- */ - enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A}; static const char *uart_str[] = @@ -326,12 +267,10 @@ outb(dcd | (ptt << 1), UART_MCR(sm->hdrv.ptt_out.seriobase)); outb(0x40 & (-ptt), UART_LCR(sm->hdrv.ptt_out.seriobase)); } - if (sm->hdrv.ptt_out.flags & SP_PAR) { - outb(ptt | (dcd << 1), LPT_DATA(sm->hdrv.ptt_out.pariobase)); - } - if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv)) { + if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev && sm->pardev->port) + parport_write_data(sm->pardev->port, ptt | (dcd << 1)); + if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv)) outb(0, MIDI_DATA(sm->hdrv.ptt_out.midiiobase)); - } } /* --------------------------------------------------------------------- */ @@ -339,6 +278,7 @@ static void sm_output_open(struct sm_state *sm) { enum uart u = c_uart_unknown; + struct parport *pp = NULL; sm->hdrv.ptt_out.flags = 0; if (sm->hdrv.ptt_out.seriobase > 0 && @@ -353,11 +293,27 @@ outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */ /* LCR and MCR set by output_status */ } - if (sm->hdrv.ptt_out.pariobase > 0 && - sm->hdrv.ptt_out.pariobase <= 0x1000-LPT_EXTENT && - !check_lpt(sm->hdrv.ptt_out.pariobase)) { - sm->hdrv.ptt_out.flags |= SP_PAR; - request_region(sm->hdrv.ptt_out.pariobase, LPT_EXTENT, "sm par ptt"); + sm->pardev = NULL; + if (sm->hdrv.ptt_out.pariobase > 0) { + pp = parport_enumerate(); + while (pp && pp->base != sm->hdrv.ptt_out.pariobase) + pp = pp->next; + if (!pp) + printk(KERN_WARNING "%s: parport at address 0x%x not found\n", sm_drvname, sm->hdrv.ptt_out.pariobase); + else { + sm->pardev = parport_register_device(pp, sm->hdrv.ifname, NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); + if (!sm->pardev) { + pp = NULL; + printk(KERN_WARNING "%s: cannot register parport device (address 0x%x)\n", sm_drvname, sm->hdrv.ptt_out.pariobase); + } else { + if (parport_claim(sm->pardev)) { + parport_unregister_device(sm->pardev); + sm->pardev = NULL; + printk(KERN_WARNING "%s: cannot claim parport at address 0x%x\n", sm_drvname, sm->hdrv.ptt_out.pariobase); + } else + sm->hdrv.ptt_out.flags |= SP_PAR; + } + } } if (sm->hdrv.ptt_out.midiiobase > 0 && sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT && @@ -390,8 +346,10 @@ sm_output_status(sm); if (sm->hdrv.ptt_out.flags & SP_SER) release_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT); - if (sm->hdrv.ptt_out.flags & SP_PAR) - release_region(sm->hdrv.ptt_out.pariobase, LPT_EXTENT); + if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev) { + parport_release(sm->pardev); + parport_unregister_device(sm->pardev); + } if (sm->hdrv.ptt_out.flags & SP_MIDI) release_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT); sm->hdrv.ptt_out.flags = 0; @@ -639,11 +597,24 @@ /* --------------------------------------------------------------------- */ -#ifdef MODULE -static int __init sm_init(void) -#else /* MODULE */ -int __init sm_init(void) -#endif /* MODULE */ +/* + * command line settable parameters + */ +static char *mode[NR_PORTS] = { [0 ... NR_PORTS-1] = NULL }; +static int iobase[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; +static int irq[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; +static int dma[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; +static int dma2[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; +static int serio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; +static int pario[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; +static int midiio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; + +/* --------------------------------------------------------------------- */ + +#ifndef MODULE +static +#endif +int __init init_module(void) { int i, j, found = 0; char set_hw = 1; @@ -658,25 +629,39 @@ struct device *dev = sm_device+i; sprintf(ifname, "sm%d", i); - if (!sm_ports[i].mode) + if (!mode[i]) set_hw = 0; + else { + if (!strncmp(mode[i], "sbc", 3)) { + if (iobase[i] == -1) + iobase[i] = 0x220; + if (irq[i] == -1) + irq[i] = 5; + if (dma[i] == -1) + dma[i] = 1; + } else { + if (iobase[i] == -1) + iobase[i] = 0x530; + if (irq[i] == -1) + irq[i] = 11; + if (dma[i] == -1) + dma[i] = 1; + } + } if (!set_hw) - sm_ports[i].iobase = sm_ports[i].irq = 0; - j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), - ifname, sm_ports[i].iobase, - sm_ports[i].irq, sm_ports[i].dma); + iobase[i] = irq[i] = 0; + j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), ifname, iobase[i], irq[i], dma[i]); if (!j) { sm = (struct sm_state *)dev->priv; - sm->hdrv.ptt_out.dma2 = sm_ports[i].dma2; - sm->hdrv.ptt_out.seriobase = sm_ports[i].seriobase; - sm->hdrv.ptt_out.pariobase = sm_ports[i].pariobase; - sm->hdrv.ptt_out.midiiobase = sm_ports[i].midiiobase; - if (set_hw && sethw(dev, sm, sm_ports[i].mode)) + sm->hdrv.ptt_out.dma2 = dma2[i]; + sm->hdrv.ptt_out.seriobase = serio[i]; + sm->hdrv.ptt_out.pariobase = pario[i]; + sm->hdrv.ptt_out.midiiobase = midiio[i]; + if (set_hw && sethw(dev, sm, mode[i])) set_hw = 0; found++; } else { - printk(KERN_WARNING "%s: cannot register net device\n", - sm_drvname); + printk(KERN_WARNING "%s: cannot register net device\n", sm_drvname); } } if (!found) @@ -688,67 +673,26 @@ #ifdef MODULE -/* - * command line settable parameters - */ -static char *mode = NULL; -static int iobase = -1; -static int irq = -1; -static int dma = -1; -static int dma2 = -1; -static int serio = 0; -static int pario = 0; -static int midiio = 0; - -#if LINUX_VERSION_CODE >= 0x20115 - -MODULE_PARM(mode, "s"); +MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); MODULE_PARM_DESC(mode, "soundmodem operating mode; eg. sbc:afsk1200 or wss:fsk9600"); -MODULE_PARM(iobase, "i"); +MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(iobase, "soundmodem base address"); -MODULE_PARM(irq, "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(irq, "soundmodem interrupt"); -MODULE_PARM(dma, "i"); +MODULE_PARM(dma, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(dma, "soundmodem dma channel"); -MODULE_PARM(dma2, "i"); +MODULE_PARM(dma2, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(dma2, "soundmodem 2nd dma channel; full duplex only"); -MODULE_PARM(serio, "i"); +MODULE_PARM(serio, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(serio, "soundmodem PTT output on serial port"); -MODULE_PARM(pario, "i"); +MODULE_PARM(pario, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(pario, "soundmodem PTT output on parallel port"); -MODULE_PARM(midiio, "i"); +MODULE_PARM(midiio, "1-" __MODULE_STRING(NR_PORTS) "i"); MODULE_PARM_DESC(midiio, "soundmodem PTT output on midi port"); MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("Soundcard amateur radio modem driver"); -#endif - -int __init init_module(void) -{ - if (mode) { - if (iobase == -1) - iobase = (!strncmp(mode, "sbc", 3)) ? 0x220 : 0x530; - if (irq == -1) - irq = (!strncmp(mode, "sbc", 3)) ? 5 : 11; - if (dma == -1) - dma = 1; - } - sm_ports[0].mode = mode; - sm_ports[0].iobase = iobase; - sm_ports[0].irq = irq; - sm_ports[0].dma = dma; - sm_ports[0].dma2 = dma2; - sm_ports[0].seriobase = serio; - sm_ports[0].pariobase = pario; - sm_ports[0].midiiobase = midiio; - sm_ports[1].mode = NULL; - - return sm_init(); -} - -/* --------------------------------------------------------------------- */ - void cleanup_module(void) { int i; @@ -770,35 +714,43 @@ } #else /* MODULE */ -/* --------------------------------------------------------------------- */ + /* - * format: sm=io,irq,dma[,dma2[,serio[,pario]]],mode + * format: soundmodem=io,irq,dma[,dma2[,serio[,pario]]],mode * mode: hw:modem * hw: sbc, wss, wssfdx * modem: afsk1200, fsk9600 */ -void __init sm_setup(char *str, int *ints) +static int __init sm_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[11]; - for (i = 0; (i < NR_PORTS) && (sm_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 3)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", sm_drvname); - return; - } - sm_ports[i].mode = str; - sm_ports[i].iobase = ints[1]; - sm_ports[i].irq = ints[2]; - sm_ports[i].dma = ints[3]; - sm_ports[i].dma2 = (ints[0] >= 4) ? ints[4] : 0; - sm_ports[i].seriobase = (ints[0] >= 5) ? ints[5] : 0; - sm_ports[i].pariobase = (ints[0] >= 6) ? ints[6] : 0; - sm_ports[i].midiiobase = (ints[0] >= 7) ? ints[7] : 0; - if (i < NR_PORTS-1) - sm_ports[i+1].mode = NULL; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, ints); + mode[nr_dev] = str; + if (ints[0] >= 1) + iobase[nr_dev] = ints[1]; + if (ints[0] >= 2) + irq[nr_dev] = ints[2]; + if (ints[0] >= 3) + dma[nr_dev] = ints[3]; + if (ints[0] >= 4) + dma2[nr_dev] = ints[4]; + if (ints[0] >= 5) + serio[nr_dev] = ints[5]; + if (ints[0] >= 6) + pario[nr_dev] = ints[6]; + if (ints[0] >= 7) + midiio[nr_dev] = ints[7]; + nr_dev++; + return 1; } + +__setup("soundmodem=", sm_setup); +__initcall(init_module); #endif /* MODULE */ /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/soundmodem/sm.h linux/drivers/net/hamradio/soundmodem/sm.h --- v2.3.12/linux/drivers/net/hamradio/soundmodem/sm.h Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/hamradio/soundmodem/sm.h Wed Aug 4 09:27:34 1999 @@ -3,7 +3,7 @@ /* * sm.h -- soundcard radio modem driver internal header. * - * Copyright (C) 1996-1998 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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 @@ -34,6 +34,7 @@ #include #include #include +#include #define SM_DEBUG @@ -49,6 +50,8 @@ const struct modem_rx_info *mode_rx; const struct hardware_info *hwdrv; + + struct pardevice *pardev; /* * Hardware (soundcard) access routines state diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c --- v2.3.12/linux/drivers/net/hamradio/yam.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/hamradio/yam.c Thu Aug 5 14:35:52 1999 @@ -0,0 +1,1297 @@ +/*****************************************************************************/ + +/* + * yam.c -- YAM radio modem driver. + * + * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr) + * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.0 F1OAT 06.06.98 Begin of work with baycom.c source code V 0.3 + * 0.1 F1OAT 07.06.98 Add timer polling routine for channel arbitration + * 0.2 F6FBB 08.06.98 Added delay after FPGA programming + * 0.3 F6FBB 29.07.98 Delayed PTT implementation for dupmode=2 + * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistance + * 0.5 F6FBB 01.08.98 Shared IRQs, /proc/net and network statistics + * 0.6 F6FBB 25.08.98 Added 1200Bds format + * 0.7 F6FBB 12.09.98 Added to the kernel configuration + * 0.8 F6FBB 14.10.98 Fixed slottime/persistance timing bug + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +/* prototypes for ax25_encapsulate and ax25_rebuild_header */ +#include +#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + +/* make genksyms happy */ +#include +#include +#include + +#include +#include + +#include +#include "yam9600.h" +#include "yam1200.h" + +/* --------------------------------------------------------------------- */ + +/* + * currently this module is supposed to support both module styles, i.e. + * the old one present up to about 2.1.9, and the new one functioning + * starting with 2.1.21. The reason is I have a kit allowing to compile + * this module also under 2.0.x which was requested by several people. + * This will go in 2.2 + */ +#include + +#if LINUX_VERSION_CODE >= 0x20100 +#include +#else +#include +#include + +#undef put_user +#undef get_user + +#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) +#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) + +extern inline int copy_from_user(void *to, const void *from, unsigned long n) +{ + int i = verify_area(VERIFY_READ, from, n); + if (i) + return i; + memcpy_fromfs(to, from, n); + return 0; +} + +extern inline int copy_to_user(void *to, const void *from, unsigned long n) +{ + int i = verify_area(VERIFY_WRITE, to, n); + if (i) + return i; + memcpy_tofs(to, from, n); + return 0; +} +#endif + +#if LINUX_VERSION_CODE < 0x20115 +extern __inline__ void dev_init_buffers(struct device *dev) +{ + int i; + for (i = 0; i < DEV_NUMBUFFS; i++) { + skb_queue_head_init(&dev->buffs[i]); + } +} +#endif + +#if LINUX_VERSION_CODE >= 0x20123 +#include +#else +#define __init +#define __initdata +#define __initfunc(x) x +#endif + +/* --------------------------------------------------------------------- */ + +static const char yam_drvname[] = "yam"; +static const char yam_drvinfo[] = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n"; + +/* --------------------------------------------------------------------- */ + +#define YAM_9600 1 +#define YAM_1200 2 + +#define NR_PORTS 4 +#define YAM_MAGIC 0xF10A7654 + +/* Transmitter states */ + +#define TX_OFF 0 +#define TX_HEAD 1 +#define TX_DATA 2 +#define TX_CRC1 3 +#define TX_CRC2 4 +#define TX_TAIL 5 + +#define YAM_MAX_FRAME 1024 + +#define DEFAULT_BITRATE 9600 /* bps */ +#define DEFAULT_HOLDD 10 /* sec */ +#define DEFAULT_TXD 300 /* ms */ +#define DEFAULT_TXTAIL 10 /* ms */ +#define DEFAULT_SLOT 100 /* ms */ +#define DEFAULT_PERS 64 /* 0->255 */ + +struct yam_port { + int magic; + int bitrate; + int baudrate; + int iobase; + int irq; + int dupmode; + char name[16]; + + struct device dev; + + /* Stats section */ + +#if LINUX_VERSION_CODE < 0x20119 + struct enet_statistics stats; +#else + struct net_device_stats stats; +#endif + int nb_rxint; + int nb_mdint; + + /* Parameters section */ + + int txd; /* tx delay */ + int holdd; /* duplex ptt delay */ + int txtail; /* txtail delay */ + int slot; /* slottime */ + int pers; /* persistence */ + + /* Tx section */ + + int tx_state; + int tx_count; + int slotcnt; + unsigned char tx_buf[YAM_MAX_FRAME]; + int tx_len; + int tx_crcl, tx_crch; + struct sk_buff_head send_queue; /* Packets awaiting transmission */ + + /* Rx section */ + + int dcd; + unsigned char rx_buf[YAM_MAX_FRAME]; + int rx_len; + int rx_crcl, rx_crch; +}; + +struct yam_mcs { + unsigned char bits[YAM_FPGA_SIZE]; + int bitrate; + struct yam_mcs *next; +}; + +static struct yam_port yam_ports[NR_PORTS]; + +static struct yam_mcs *yam_data = NULL; + +static unsigned irqs[16]; + +static char ax25_bcast[7] = +{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1}; +static char ax25_test[7] = +{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1}; + +static struct timer_list yam_timer; + +/* --------------------------------------------------------------------- */ + +#define RBR(iobase) (iobase+0) +#define THR(iobase) (iobase+0) +#define IER(iobase) (iobase+1) +#define IIR(iobase) (iobase+2) +#define FCR(iobase) (iobase+2) +#define LCR(iobase) (iobase+3) +#define MCR(iobase) (iobase+4) +#define LSR(iobase) (iobase+5) +#define MSR(iobase) (iobase+6) +#define SCR(iobase) (iobase+7) +#define DLL(iobase) (iobase+0) +#define DLM(iobase) (iobase+1) + +#define YAM_EXTENT 8 + +/* Interrupt Identification Register Bit Masks */ +#define IIR_NOPEND 1 +#define IIR_MSR 0 +#define IIR_TX 2 +#define IIR_RX 4 +#define IIR_LSR 6 +#define IIR_TIMEOUT 12 /* Fifo mode only */ + +#define IIR_MASK 0x0F + +/* Interrupt Enable Register Bit Masks */ +#define IER_RX 1 /* enable rx interrupt */ +#define IER_TX 2 /* enable tx interrupt */ +#define IER_LSR 4 /* enable line status interrupts */ +#define IER_MSR 8 /* enable modem status interrupts */ + +/* Modem Control Register Bit Masks */ +#define MCR_DTR 0x01 /* DTR output */ +#define MCR_RTS 0x02 /* RTS output */ +#define MCR_OUT1 0x04 /* OUT1 output (not accessible in RS232) */ +#define MCR_OUT2 0x08 /* Master Interrupt enable (must be set on PCs) */ +#define MCR_LOOP 0x10 /* Loopback enable */ + +/* Modem Status Register Bit Masks */ +#define MSR_DCTS 0x01 /* Delta CTS input */ +#define MSR_DDSR 0x02 /* Delta DSR */ +#define MSR_DRIN 0x04 /* Delta RI */ +#define MSR_DDCD 0x08 /* Delta DCD */ +#define MSR_CTS 0x10 /* CTS input */ +#define MSR_DSR 0x20 /* DSR input */ +#define MSR_RING 0x40 /* RI input */ +#define MSR_DCD 0x80 /* DCD input */ + +/* line status register bit mask */ +#define LSR_RXC 0x01 +#define LSR_OE 0x02 +#define LSR_PE 0x04 +#define LSR_FE 0x08 +#define LSR_BREAK 0x10 +#define LSR_THRE 0x20 +#define LSR_TSRE 0x40 + +/* Line Control Register Bit Masks */ +#define LCR_DLAB 0x80 +#define LCR_BREAK 0x40 +#define LCR_PZERO 0x28 +#define LCR_PEVEN 0x18 +#define LCR_PODD 0x08 +#define LCR_STOP1 0x00 +#define LCR_STOP2 0x04 +#define LCR_BIT5 0x00 +#define LCR_BIT6 0x02 +#define LCR_BIT7 0x01 +#define LCR_BIT8 0x03 + +/* YAM Modem <-> UART Port mapping */ + +#define TX_RDY MSR_DCTS /* transmitter ready to send */ +#define RX_DCD MSR_DCD /* carrier detect */ +#define RX_FLAG MSR_RING /* hdlc flag received */ +#define FPGA_DONE MSR_DSR /* FPGA is configured */ +#define PTT_ON (MCR_RTS|MCR_OUT2) /* activate PTT */ +#define PTT_OFF (MCR_DTR|MCR_OUT2) /* release PTT */ + +#define ENABLE_RXINT IER_RX /* enable uart rx interrupt during rx */ +#define ENABLE_TXINT IER_MSR /* enable uart ms interrupt during tx */ +#define ENABLE_RTXINT (IER_RX|IER_MSR) /* full duplex operations */ + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/************************************************************************* +* CRC Tables +************************************************************************/ + +static const unsigned char chktabl[256] = +{0x00, 0x89, 0x12, 0x9b, 0x24, 0xad, 0x36, 0xbf, 0x48, 0xc1, 0x5a, 0xd3, 0x6c, 0xe5, 0x7e, + 0xf7, 0x81, 0x08, 0x93, 0x1a, 0xa5, 0x2c, 0xb7, 0x3e, 0xc9, 0x40, 0xdb, 0x52, 0xed, 0x64, + 0xff, 0x76, 0x02, 0x8b, 0x10, 0x99, 0x26, 0xaf, 0x34, 0xbd, 0x4a, 0xc3, 0x58, 0xd1, 0x6e, + 0xe7, 0x7c, 0xf5, 0x83, 0x0a, 0x91, 0x18, 0xa7, 0x2e, 0xb5, 0x3c, 0xcb, 0x42, 0xd9, 0x50, + 0xef, 0x66, 0xfd, 0x74, 0x04, 0x8d, 0x16, 0x9f, 0x20, 0xa9, 0x32, 0xbb, 0x4c, 0xc5, 0x5e, + 0xd7, 0x68, 0xe1, 0x7a, 0xf3, 0x85, 0x0c, 0x97, 0x1e, 0xa1, 0x28, 0xb3, 0x3a, 0xcd, 0x44, + 0xdf, 0x56, 0xe9, 0x60, 0xfb, 0x72, 0x06, 0x8f, 0x14, 0x9d, 0x22, 0xab, 0x30, 0xb9, 0x4e, + 0xc7, 0x5c, 0xd5, 0x6a, 0xe3, 0x78, 0xf1, 0x87, 0x0e, 0x95, 0x1c, 0xa3, 0x2a, 0xb1, 0x38, + 0xcf, 0x46, 0xdd, 0x54, 0xeb, 0x62, 0xf9, 0x70, 0x08, 0x81, 0x1a, 0x93, 0x2c, 0xa5, 0x3e, + 0xb7, 0x40, 0xc9, 0x52, 0xdb, 0x64, 0xed, 0x76, 0xff, 0x89, 0x00, 0x9b, 0x12, 0xad, 0x24, + 0xbf, 0x36, 0xc1, 0x48, 0xd3, 0x5a, 0xe5, 0x6c, 0xf7, 0x7e, 0x0a, 0x83, 0x18, 0x91, 0x2e, + 0xa7, 0x3c, 0xb5, 0x42, 0xcb, 0x50, 0xd9, 0x66, 0xef, 0x74, 0xfd, 0x8b, 0x02, 0x99, 0x10, + 0xaf, 0x26, 0xbd, 0x34, 0xc3, 0x4a, 0xd1, 0x58, 0xe7, 0x6e, 0xf5, 0x7c, 0x0c, 0x85, 0x1e, + 0x97, 0x28, 0xa1, 0x3a, 0xb3, 0x44, 0xcd, 0x56, 0xdf, 0x60, 0xe9, 0x72, 0xfb, 0x8d, 0x04, + 0x9f, 0x16, 0xa9, 0x20, 0xbb, 0x32, 0xc5, 0x4c, 0xd7, 0x5e, 0xe1, 0x68, 0xf3, 0x7a, 0x0e, + 0x87, 0x1c, 0x95, 0x2a, 0xa3, 0x38, 0xb1, 0x46, 0xcf, 0x54, 0xdd, 0x62, 0xeb, 0x70, 0xf9, + 0x8f, 0x06, 0x9d, 0x14, 0xab, 0x22, 0xb9, 0x30, 0xc7, 0x4e, 0xd5, 0x5c, 0xe3, 0x6a, 0xf1, + 0x78}; +static const unsigned char chktabh[256] = +{0x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8c, 0x9d, 0xaf, 0xbe, 0xca, 0xdb, 0xe9, + 0xf8, 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9c, 0x8d, 0xbf, 0xae, 0xda, 0xcb, + 0xf9, 0xe8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xad, 0xbc, 0x8e, 0x9f, 0xeb, + 0xfa, 0xc8, 0xd9, 0x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xbd, 0xac, 0x9e, 0x8f, + 0xfb, 0xea, 0xd8, 0xc9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xce, 0xdf, 0xed, + 0xfc, 0x88, 0x99, 0xab, 0xba, 0x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xde, 0xcf, + 0xfd, 0xec, 0x98, 0x89, 0xbb, 0xaa, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xef, + 0xfe, 0xcc, 0xdd, 0xa9, 0xb8, 0x8a, 0x9b, 0x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07, + 0xff, 0xee, 0xdc, 0xcd, 0xb9, 0xa8, 0x9a, 0x8b, 0x84, 0x95, 0xa7, 0xb6, 0xc2, 0xd3, 0xe1, + 0xf0, 0x08, 0x19, 0x2b, 0x3a, 0x4e, 0x5f, 0x6d, 0x7c, 0x94, 0x85, 0xb7, 0xa6, 0xd2, 0xc3, + 0xf1, 0xe0, 0x18, 0x09, 0x3b, 0x2a, 0x5e, 0x4f, 0x7d, 0x6c, 0xa5, 0xb4, 0x86, 0x97, 0xe3, + 0xf2, 0xc0, 0xd1, 0x29, 0x38, 0x0a, 0x1b, 0x6f, 0x7e, 0x4c, 0x5d, 0xb5, 0xa4, 0x96, 0x87, + 0xf3, 0xe2, 0xd0, 0xc1, 0x39, 0x28, 0x1a, 0x0b, 0x7f, 0x6e, 0x5c, 0x4d, 0xc6, 0xd7, 0xe5, + 0xf4, 0x80, 0x91, 0xa3, 0xb2, 0x4a, 0x5b, 0x69, 0x78, 0x0c, 0x1d, 0x2f, 0x3e, 0xd6, 0xc7, + 0xf5, 0xe4, 0x90, 0x81, 0xb3, 0xa2, 0x5a, 0x4b, 0x79, 0x68, 0x1c, 0x0d, 0x3f, 0x2e, 0xe7, + 0xf6, 0xc4, 0xd5, 0xa1, 0xb0, 0x82, 0x93, 0x6b, 0x7a, 0x48, 0x59, 0x2d, 0x3c, 0x0e, 0x1f, + 0xf7, 0xe6, 0xd4, 0xc5, 0xb1, 0xa0, 0x92, 0x83, 0x7b, 0x6a, 0x58, 0x49, 0x3d, 0x2c, 0x1e, + 0x0f}; + +/************************************************************************* +* FPGA functions +************************************************************************/ + +static void delay(int ms) +{ + unsigned long timeout = jiffies + ((ms * HZ) / 1000); + while (jiffies < timeout); +} + +/* + * reset FPGA + */ + +static void fpga_reset(int iobase) +{ + outb(0, IER(iobase)); + outb(LCR_DLAB | LCR_BIT5, LCR(iobase)); + outb(1, DLL(iobase)); + outb(0, DLM(iobase)); + + outb(LCR_BIT5, LCR(iobase)); + inb(LSR(iobase)); + inb(MSR(iobase)); + /* turn off FPGA supply voltage */ + outb(MCR_OUT1 | MCR_OUT2, MCR(iobase)); + delay(100); + /* turn on FPGA supply voltage again */ + outb(MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2, MCR(iobase)); + delay(100); +} + +/* + * send one byte to FPGA + */ + +static int fpga_write(int iobase, unsigned char wrd) +{ + unsigned char bit; + int k; + unsigned long timeout = jiffies + HZ / 10; + + for (k = 0; k < 8; k++) { + bit = (wrd & 0x80) ? (MCR_RTS | MCR_DTR) : MCR_DTR; + outb(bit | MCR_OUT1 | MCR_OUT2, MCR(iobase)); + wrd <<= 1; + outb(0xfc, THR(iobase)); + while ((inb(LSR(iobase)) & LSR_TSRE) == 0) + if (jiffies > timeout) + return -1; + } + + return 0; +} + +#ifdef MODULE +static void free_mcs(void) +{ + struct yam_mcs *p; + + while (yam_data) { + p = yam_data; + yam_data = yam_data->next; + kfree(p); + } +} +#endif + +static unsigned char * + add_mcs(unsigned char *bits, int bitrate) +{ + struct yam_mcs *p; + + /* If it already exists, replace the bit data */ + p = yam_data; + while (p) { + if (p->bitrate == bitrate) { + memcpy(p->bits, bits, YAM_FPGA_SIZE); + return p->bits; + } + p = p->next; + } + + /* Allocate a new mcs */ + p = kmalloc(sizeof(struct yam_mcs), GFP_ATOMIC); + if (p == NULL) { + printk(KERN_WARNING "YAM: no memory to allocate mcs\n"); + return NULL; + } + memcpy(p->bits, bits, YAM_FPGA_SIZE); + p->bitrate = bitrate; + p->next = yam_data; + yam_data = p; + + return p->bits; +} + +static unsigned char *get_mcs(int bitrate) +{ + struct yam_mcs *p; + + p = yam_data; + while (p) { + if (p->bitrate == bitrate) + return p->bits; + p = p->next; + } + + /* Load predefined mcs data */ + switch (bitrate) { + case 1200: + return add_mcs(bits_1200, bitrate); + default: + return add_mcs(bits_9600, bitrate); + } +} + +/* + * download bitstream to FPGA + * data is contained in bits[] array in fpgaconf.h + */ + +static int fpga_download(int iobase, int bitrate) +{ + int i, rc; + unsigned char *pbits; + + pbits = get_mcs(bitrate); + if (pbits == NULL) + return -1; + + fpga_reset(iobase); + for (i = 0; i < YAM_FPGA_SIZE; i++) { + if (fpga_write(iobase, pbits[i])) { + printk("yam: error in write cycle\n"); + return -1; /* write... */ + } + } + + fpga_write(iobase, 0xFF); + rc = inb(MSR(iobase)); /* check DONE signal */ + + /* Needed for some hardwares */ + delay(50); + + return (rc & MSR_DSR) ? 0 : -1; +} + + +/************************************************************************ +* Serial port init +************************************************************************/ + +static void yam_set_uart(struct device *dev) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + int divisor = 115200 / yp->baudrate; + + outb(0, IER(dev->base_addr)); + outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr)); + outb(divisor, DLL(dev->base_addr)); + outb(0, DLM(dev->base_addr)); + outb(LCR_BIT8, LCR(dev->base_addr)); + outb(PTT_OFF, MCR(dev->base_addr)); + outb(0x00, FCR(dev->base_addr)); + + /* Flush pending irq */ + + inb(RBR(dev->base_addr)); + inb(MSR(dev->base_addr)); + + /* Enable rx irq */ + + outb(ENABLE_RTXINT, IER(dev->base_addr)); +} + + +/* --------------------------------------------------------------------- */ + +enum uart { + c_uart_unknown, c_uart_8250, + c_uart_16450, c_uart_16550, c_uart_16550A +}; + +static const char *uart_str[] = +{"unknown", "8250", "16450", "16550", "16550A"}; + +static enum uart yam_check_uart(unsigned int iobase) +{ + unsigned char b1, b2, b3; + enum uart u; + enum uart uart_tab[] = + {c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A}; + + b1 = inb(MCR(iobase)); + outb(b1 | 0x10, MCR(iobase)); /* loopback mode */ + b2 = inb(MSR(iobase)); + outb(0x1a, MCR(iobase)); + b3 = inb(MSR(iobase)) & 0xf0; + outb(b1, MCR(iobase)); /* restore old values */ + outb(b2, MSR(iobase)); + if (b3 != 0x90) + return c_uart_unknown; + inb(RBR(iobase)); + inb(RBR(iobase)); + outb(0x01, FCR(iobase)); /* enable FIFOs */ + u = uart_tab[(inb(IIR(iobase)) >> 6) & 3]; + if (u == c_uart_16450) { + outb(0x5a, SCR(iobase)); + b1 = inb(SCR(iobase)); + outb(0xa5, SCR(iobase)); + b2 = inb(SCR(iobase)); + if ((b1 != 0x5a) || (b2 != 0xa5)) + u = c_uart_8250; + } + return u; +} + +/****************************************************************************** +* Rx Section +******************************************************************************/ +static void inline + yam_rx_flag(struct device *dev, struct yam_port *yp) +{ + if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) { + int pkt_len = yp->rx_len - 2 + 1; /* -CRC + kiss */ + struct sk_buff *skb; + + if ((yp->rx_crch & yp->rx_crcl) != 0xFF) { + /* Bad crc */ + } else { + if (!(skb = dev_alloc_skb(pkt_len))) { + printk("%s: memory squeeze, dropping packet\n", dev->name); + ++yp->stats.rx_dropped; + } else { + unsigned char *cp; + skb->dev = dev; + cp = skb_put(skb, pkt_len); + *cp++ = 0; /* KISS kludge */ + memcpy(cp, yp->rx_buf, pkt_len - 1); + skb->protocol = htons(ETH_P_AX25); + skb->mac.raw = skb->data; + netif_rx(skb); + ++yp->stats.rx_packets; + } + } + } + yp->rx_len = 0; + yp->rx_crcl = 0x21; + yp->rx_crch = 0xf3; +} + +static void inline + yam_rx_byte(struct device *dev, struct yam_port *yp, unsigned char rxb) +{ + if (yp->rx_len < YAM_MAX_FRAME) { + unsigned char c = yp->rx_crcl; + yp->rx_crcl = (chktabl[c] ^ yp->rx_crch); + yp->rx_crch = (chktabh[c] ^ rxb); + yp->rx_buf[yp->rx_len++] = rxb; + } +} + +/******************************************************************************** +* TX Section +********************************************************************************/ + +static void ptt_on(struct device *dev) +{ + outb(PTT_ON, MCR(dev->base_addr)); +} + +static void ptt_off(struct device *dev) +{ + outb(PTT_OFF, MCR(dev->base_addr)); +} + +static int yam_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct yam_port *yp = dev->priv; + + if (skb == NULL) { + return 0; + } + skb_queue_tail(&yp->send_queue, skb); + dev->trans_start = jiffies; + return 0; +} + +static void yam_start_tx(struct device *dev, struct yam_port *yp) +{ + if ((yp->tx_state == TX_TAIL) || (yp->txd == 0)) + yp->tx_count = 1; + else + yp->tx_count = (yp->bitrate * yp->txd) / 8000; + yp->tx_state = TX_HEAD; + ptt_on(dev); +} + +static unsigned short random_seed; + +static inline unsigned short random_num(void) +{ + random_seed = 28629 * random_seed + 157; + return random_seed; +} + +static void yam_arbitrate(struct device *dev) +{ + struct yam_port *yp = dev->priv; + + if (!yp || yp->magic != YAM_MAGIC + || yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) { + return; + } + /* tx_state is TX_OFF and there is data to send */ + + if (yp->dupmode) { + /* Full duplex mode, don't wait */ + yam_start_tx(dev, yp); + return; + } + if (yp->dcd) { + /* DCD on, wait slotime ... */ + yp->slotcnt = yp->slot / 10; + return; + } + /* Is slottime passed ? */ + if ((--yp->slotcnt) > 0) + return; + + yp->slotcnt = yp->slot / 10; + + /* is random > persist ? */ + if ((random_num() % 256) > yp->pers) + return; + + yam_start_tx(dev, yp); +} + +static void yam_dotimer(unsigned long dummy) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) { + struct device *dev = &yam_ports[i].dev; + if (dev->start) + yam_arbitrate(dev); + } + yam_timer.expires = jiffies + HZ / 100; + add_timer(&yam_timer); +} + +static void yam_tx_byte(struct device *dev, struct yam_port *yp) +{ + struct sk_buff *skb; + unsigned char b, temp; + + switch (yp->tx_state) { + case TX_OFF: + break; + case TX_HEAD: + if (--yp->tx_count <= 0) { + if (!(skb = skb_dequeue(&yp->send_queue))) { + ptt_off(dev); + yp->tx_state = TX_OFF; + break; + } + yp->tx_state = TX_DATA; + if (skb->data[0] != 0) { +/* do_kiss_params(s, skb->data, skb->len); */ + dev_kfree_skb(skb); + break; + } + yp->tx_len = skb->len - 1; /* strip KISS byte */ + if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) { + dev_kfree_skb(skb); + break; + } + memcpy(yp->tx_buf, skb->data + 1, yp->tx_len); + dev_kfree_skb(skb); + yp->tx_count = 0; + yp->tx_crcl = 0x21; + yp->tx_crch = 0xf3; + yp->tx_state = TX_DATA; + } + break; + case TX_DATA: + b = yp->tx_buf[yp->tx_count++]; + outb(b, THR(dev->base_addr)); + temp = yp->tx_crcl; + yp->tx_crcl = chktabl[temp] ^ yp->tx_crch; + yp->tx_crch = chktabh[temp] ^ b; + if (yp->tx_count >= yp->tx_len) { + yp->tx_state = TX_CRC1; + } + break; + case TX_CRC1: + yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch; + yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff; + outb(yp->tx_crcl, THR(dev->base_addr)); + yp->tx_state = TX_CRC2; + break; + case TX_CRC2: + outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr)); + if (skb_queue_empty(&yp->send_queue)) { + yp->tx_count = (yp->bitrate * yp->txtail) / 8000; + if (yp->dupmode == 2) + yp->tx_count += (yp->bitrate * yp->holdd) / 8; + if (yp->tx_count == 0) + yp->tx_count = 1; + yp->tx_state = TX_TAIL; + } else { + yp->tx_count = 1; + yp->tx_state = TX_HEAD; + } + ++yp->stats.tx_packets; + break; + case TX_TAIL: + if (--yp->tx_count <= 0) { + yp->tx_state = TX_OFF; + ptt_off(dev); + } + break; + } +} + +/*********************************************************************************** +* ISR routine +************************************************************************************/ + +static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct device *dev; + struct yam_port *yp; + unsigned char iir; + int counter = 100; + int i; + + sti(); + + for (i = 0; i < NR_PORTS; i++) { + yp = &yam_ports[i]; + dev = &yp->dev; + + if (!dev->start) + continue; + + while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) { + unsigned char msr = inb(MSR(dev->base_addr)); + unsigned char lsr = inb(LSR(dev->base_addr)); + unsigned char rxb; + + if (lsr & LSR_OE) + ++yp->stats.rx_fifo_errors; + + yp->dcd = (msr & RX_DCD) ? 1 : 0; + + if (--counter <= 0) { + printk("%s: too many irq iir=%d\n", dev->name, iir); + return; + } + if (msr & TX_RDY) { + ++yp->nb_mdint; + yam_tx_byte(dev, yp); + } + if (lsr & LSR_RXC) { + ++yp->nb_rxint; + rxb = inb(RBR(dev->base_addr)); + if (msr & RX_FLAG) + yam_rx_flag(dev, yp); + else + yam_rx_byte(dev, yp, rxb); + } + } + } +} + +static int yam_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy) +{ + int len = 0; + int i; + off_t pos = 0; + off_t begin = 0; + + cli(); + + for (i = 0; i < NR_PORTS; i++) { + if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0) + continue; + len += sprintf(buffer + len, "Device %s\n", yam_ports[i].name); + len += sprintf(buffer + len, " Up %d\n", yam_ports[i].dev.start); + len += sprintf(buffer + len, " Speed %u\n", yam_ports[i].bitrate); + len += sprintf(buffer + len, " IoBase 0x%x\n", yam_ports[i].iobase); + len += sprintf(buffer + len, " BaudRate %u\n", yam_ports[i].baudrate); + len += sprintf(buffer + len, " IRQ %u\n", yam_ports[i].irq); + len += sprintf(buffer + len, " TxState %u\n", yam_ports[i].tx_state); + len += sprintf(buffer + len, " Duplex %u\n", yam_ports[i].dupmode); + len += sprintf(buffer + len, " HoldDly %u\n", yam_ports[i].holdd); + len += sprintf(buffer + len, " TxDelay %u\n", yam_ports[i].txd); + len += sprintf(buffer + len, " TxTail %u\n", yam_ports[i].txtail); + len += sprintf(buffer + len, " SlotTime %u\n", yam_ports[i].slot); + len += sprintf(buffer + len, " Persist %u\n", yam_ports[i].pers); + len += sprintf(buffer + len, " TxFrames %lu\n", yam_ports[i].stats.tx_packets); + len += sprintf(buffer + len, " RxFrames %lu\n", yam_ports[i].stats.rx_packets); + len += sprintf(buffer + len, " TxInt %u\n", yam_ports[i].nb_mdint); + len += sprintf(buffer + len, " RxInt %u\n", yam_ports[i].nb_rxint); + len += sprintf(buffer + len, " RxOver %lu\n", yam_ports[i].stats.rx_fifo_errors); + len += sprintf(buffer + len, "\n"); + + pos = begin + len; + + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + break; + } + + sti(); + + *start = buffer + (offset - begin); + len -= (offset - begin); + + if (len > length) + len = length; + + return len; +} + +#ifdef CONFIG_INET +#ifndef PROC_NET_YAM +#define PROC_NET_YAM (PROC_NET_LAST+10) /* Sorry again... */ +#endif + +struct proc_dir_entry yam_proc_dir_entry = +{ + PROC_NET_YAM, 3, "yam", S_IFREG | S_IRUGO, 1, 0, 0, 0, + &proc_net_inode_operations, yam_net_get_info +}; + +#define yam_net_procfs_init() proc_net_register(&yam_proc_dir_entry); +#define yam_net_procfs_remove() proc_net_unregister(PROC_NET_YAM); +#else +#define yam_net_procfs_init() +#define yam_net_procfs_remove() +#endif + +/* --------------------------------------------------------------------- */ + +#if LINUX_VERSION_CODE >= 0x20119 +static struct net_device_stats * + yam_get_stats(struct device *dev) +#else +static struct enet_statistics * + yam_get_stats(struct device *dev) +#endif +{ + struct yam_port *yp; + + if (!dev || !dev->priv) + return NULL; + + yp = (struct yam_port *) dev->priv; + if (yp->magic != YAM_MAGIC) + return NULL; + + /* + * Get the current statistics. This may be called with the + * card open or closed. + */ + return &yp->stats; +} + +/* --------------------------------------------------------------------- */ + +static int yam_open(struct device *dev) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + enum uart u; + int i; + + printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq); + + if (!dev || !yp || !yp->bitrate) + return -ENXIO; + if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT || + dev->irq < 2 || dev->irq > 15) { + return -ENXIO; + } + if (check_region(dev->base_addr, YAM_EXTENT)) { + printk("%s: cannot 0x%lx busy\n", dev->name, dev->base_addr); + return -EACCES; + } + if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) { + printk("%s: cannot find uart type\n", dev->name); + return -EIO; + } + if (fpga_download(dev->base_addr, yp->bitrate)) { + printk("%s: cannot init FPGA\n", dev->name); + return -EIO; + } + outb(0, IER(dev->base_addr)); + if (request_irq(dev->irq, yam_interrupt, SA_INTERRUPT | SA_SHIRQ, dev->name, NULL)) { + printk("%s: irq %d busy\n", dev->name, dev->irq); + return -EBUSY; + } + request_region(dev->base_addr, YAM_EXTENT, dev->name); + + yam_set_uart(dev); + dev->start = 1; + yp->slotcnt = yp->slot / 10; + + /* Reset overruns for all ports - FPGA programming makes overruns */ + for (i = 0; i < NR_PORTS; i++) { + inb(LSR(yam_ports[i].dev.base_addr)); + yam_ports[i].stats.rx_fifo_errors = 0; + } + + printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq, + uart_str[u]); + MOD_INC_USE_COUNT; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_close(struct device *dev) +{ + struct sk_buff *skb; + struct yam_port *yp = (struct yam_port *) dev->priv; + + if (!dev || !yp) + return -EINVAL; + /* + * disable interrupts + */ + outb(0, IER(dev->base_addr)); + outb(1, MCR(dev->base_addr)); + /* Remove IRQ handler if last */ + free_irq(dev->irq, NULL); + release_region(dev->base_addr, YAM_EXTENT); + dev->start = 0; + dev->tbusy = 1; + while ((skb = skb_dequeue(&yp->send_queue))) + dev_kfree_skb(skb); + + printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n", + yam_drvname, dev->base_addr, dev->irq); + MOD_DEC_USE_COUNT; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct yam_port *yp = (struct yam_port *) dev->priv; + struct yamdrv_ioctl_cfg yi; + struct yamdrv_ioctl_mcs *ym; + int ioctl_cmd; + + if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int))) + return -EFAULT; + + if (yp == NULL || yp->magic != YAM_MAGIC) + return -EINVAL; + + if (!suser()) + return -EPERM; + + if (cmd != SIOCDEVPRIVATE) + return -EINVAL; + + switch (ioctl_cmd) { + + case SIOCYAMRESERVED: + return -EINVAL; /* unused */ + + case SIOCYAMSMCS: + if (dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC); + ym->bitrate = 9600; + if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) + return -EFAULT; + if (ym->bitrate > YAM_MAXBITRATE) + return -EINVAL; + add_mcs(ym->bits, ym->bitrate); + kfree(ym); + break; + + case SIOCYAMSCFG: + if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg))) + return -EFAULT; + + if ((yi.cfg.mask & YAM_IOBASE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_IRQ) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_BITRATE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + if ((yi.cfg.mask & YAM_BAUDRATE) && dev->start) + return -EINVAL; /* Cannot change this parameter when up */ + + if (yi.cfg.mask & YAM_IOBASE) { + yp->iobase = yi.cfg.iobase; + dev->base_addr = yi.cfg.iobase; + } + if (yi.cfg.mask & YAM_IRQ) { + if (yi.cfg.irq > 15) + return -EINVAL; + yp->irq = yi.cfg.irq; + dev->irq = yi.cfg.irq; + } + if (yi.cfg.mask & YAM_BITRATE) { + if (yi.cfg.bitrate > YAM_MAXBITRATE) + return -EINVAL; + yp->bitrate = yi.cfg.bitrate; + } + if (yi.cfg.mask & YAM_BAUDRATE) { + if (yi.cfg.baudrate > YAM_MAXBAUDRATE) + return -EINVAL; + yp->baudrate = yi.cfg.baudrate; + } + if (yi.cfg.mask & YAM_MODE) { + if (yi.cfg.mode > YAM_MAXMODE) + return -EINVAL; + yp->dupmode = yi.cfg.mode; + } + if (yi.cfg.mask & YAM_HOLDDLY) { + if (yi.cfg.holddly > YAM_MAXHOLDDLY) + return -EINVAL; + yp->holdd = yi.cfg.holddly; + } + if (yi.cfg.mask & YAM_TXDELAY) { + if (yi.cfg.txdelay > YAM_MAXTXDELAY) + return -EINVAL; + yp->txd = yi.cfg.txdelay; + } + if (yi.cfg.mask & YAM_TXTAIL) { + if (yi.cfg.txtail > YAM_MAXTXTAIL) + return -EINVAL; + yp->txtail = yi.cfg.txtail; + } + if (yi.cfg.mask & YAM_PERSIST) { + if (yi.cfg.persist > YAM_MAXPERSIST) + return -EINVAL; + yp->pers = yi.cfg.persist; + } + if (yi.cfg.mask & YAM_SLOTTIME) { + if (yi.cfg.slottime > YAM_MAXSLOTTIME) + return -EINVAL; + yp->slot = yi.cfg.slottime; + yp->slotcnt = yp->slot / 10; + } + break; + + case SIOCYAMGCFG: + yi.cfg.mask = 0xffffffff; + yi.cfg.iobase = yp->iobase; + yi.cfg.irq = yp->irq; + yi.cfg.bitrate = yp->bitrate; + yi.cfg.baudrate = yp->baudrate; + yi.cfg.mode = yp->dupmode; + yi.cfg.txdelay = yp->txd; + yi.cfg.holddly = yp->holdd; + yi.cfg.txtail = yp->txtail; + yi.cfg.persist = yp->pers; + yi.cfg.slottime = yp->slot; + if (copy_to_user(ifr->ifr_data, &yi, sizeof(struct yamdrv_ioctl_cfg))) + return -EFAULT; + break; + + default: + return -EINVAL; + + } + + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_set_mac_address(struct device *dev, void *addr) +{ + struct sockaddr *sa = (struct sockaddr *) addr; + + /* addr is an AX.25 shifted ASCII mac address */ + memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); + return 0; +} + +/* --------------------------------------------------------------------- */ + +static int yam_probe(struct device *dev) +{ + struct yam_port *yp; + + if (!dev) + return -ENXIO; + + yp = (struct yam_port *) dev->priv; + + dev->open = yam_open; + dev->stop = yam_close; + dev->do_ioctl = yam_ioctl; + dev->hard_start_xmit = yam_send_packet; + dev->get_stats = yam_get_stats; + + dev_init_buffers(dev); + skb_queue_head_init(&yp->send_queue); + +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) + dev->hard_header = ax25_encapsulate; + dev->rebuild_header = ax25_rebuild_header; +#else /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + dev->hard_header = NULL; + dev->rebuild_header = NULL; +#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ + + dev->set_mac_address = yam_set_mac_address; + + dev->type = ARPHRD_AX25; /* AF_AX25 device */ + dev->hard_header_len = 73; /* We do digipeaters now */ + dev->mtu = 256; /* AX25 is the default */ + dev->addr_len = 7; /* sizeof an ax.25 address */ + memcpy(dev->broadcast, ax25_bcast, 7); + memcpy(dev->dev_addr, ax25_test, 7); + + /* New style flags */ + dev->flags = 0; + + return 0; +} + +/* --------------------------------------------------------------------- */ + +__initfunc(int yam_init(struct device *dev)) +{ + int i; + + printk(yam_drvinfo); + + /* Clears the IRQ table */ + memset(irqs, 0, sizeof(irqs)); + memset(yam_ports, 0, sizeof(yam_ports)); + + for (i = 0; i < NR_PORTS; i++) { + sprintf(yam_ports[i].name, "yam%d", i); + yam_ports[i].magic = YAM_MAGIC; + yam_ports[i].bitrate = DEFAULT_BITRATE; + yam_ports[i].baudrate = DEFAULT_BITRATE * 2; + yam_ports[i].iobase = 0; + yam_ports[i].irq = 0; + yam_ports[i].dupmode = 0; + yam_ports[i].holdd = DEFAULT_HOLDD; + yam_ports[i].txd = DEFAULT_TXD; + yam_ports[i].txtail = DEFAULT_TXTAIL; + yam_ports[i].slot = DEFAULT_SLOT; + yam_ports[i].pers = DEFAULT_PERS; + + dev = &yam_ports[i].dev; + + dev->priv = &yam_ports[i]; + dev->name = yam_ports[i].name; + dev->base_addr = yam_ports[i].iobase; + dev->irq = yam_ports[i].irq; + dev->init = yam_probe; + dev->if_port = 0; + dev->start = 0; + dev->tbusy = 1; + + if (register_netdev(dev)) { + printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name); + return -ENXIO; + } + } + + yam_timer.function = yam_dotimer; + yam_timer.expires = jiffies + HZ / 100; + add_timer(&yam_timer); + + yam_net_procfs_init(); + + /* do not keep this device */ + return 1; +} + +/* --------------------------------------------------------------------- */ + +#ifdef MODULE + +/* + * command line settable parameters + */ + +#if LINUX_VERSION_CODE >= 0x20115 + +MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr"); +MODULE_DESCRIPTION("Yam amateur radio modem driver"); + +#endif + +__initfunc(int init_module(void)) +{ + int ret = yam_init(NULL); + + return (ret == 1) ? 0 : ret; +} + +/* --------------------------------------------------------------------- */ + +void cleanup_module(void) +{ + int i; + + del_timer(&yam_timer); + for (i = 0; i < NR_PORTS; i++) { + struct device *dev = &yam_ports[i].dev; + if (!dev->priv) + continue; + if (dev->start) + yam_close(dev); + unregister_netdev(dev); + } + free_mcs(); + yam_net_procfs_remove(); +} + +#endif /* MODULE */ +/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/yam1200.h linux/drivers/net/hamradio/yam1200.h --- v2.3.12/linux/drivers/net/hamradio/yam1200.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/hamradio/yam1200.h Thu Aug 5 14:35:52 1999 @@ -0,0 +1,343 @@ +/* + * + * File yam1k2b5.mcs converted to h format by mcs2h + * + * (C) F6FBB 1998 + * + * Tue Aug 25 20:24:08 1998 + * + */ + +static unsigned char bits_1200[]= { +0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xf3,0xcb,0xff,0xdb,0xfc,0xf2, +0xff,0xf6,0xff,0x3c,0xbf,0xfd,0xbf,0xdf,0x6e,0x3f,0x6f,0xf1,0x7d,0xb4,0xfd,0xbf, +0xdf,0x6f,0x3f,0x6f,0xf7,0x0b,0xff,0xdb,0xfd,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xef,0xff,0xff,0xff, +0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xbf, +0xff,0xff,0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff,0xf0, +0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xf1,0xff,0xff,0xfe,0x7f,0xbf,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xff,0xff,0xf0,0x9f, +0xff,0xff,0xff,0xfe,0xff,0xfd,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xff, +0xff,0xff,0xfb,0xff,0xfb,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xf0,0x5f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xbf,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xfb,0xfe,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb, +0xff,0xff,0xff,0xfd,0xff,0xbf,0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xfb, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xf7,0xff,0xff,0xf1,0xff,0xff,0xf7,0xbf,0xe7,0xff,0xff,0xff,0xff,0xfb, +0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdb, +0xff,0xff,0xf5,0xa5,0xfd,0x4b,0x6e,0xef,0x33,0x32,0xdd,0xd3,0x4a,0xd6,0x92,0xfe, +0xb3,0x3f,0xbd,0xf1,0xfa,0xdb,0xfe,0xf7,0xf6,0x96,0xbd,0xbd,0xff,0xbd,0xff,0xed, +0x7f,0x6b,0x7f,0xfb,0xdf,0xfe,0xfb,0xfe,0x90,0xcf,0xff,0xff,0xff,0xfe,0xbe,0xef, +0xff,0xff,0xdb,0x5f,0xf6,0xff,0xf6,0x8f,0xfd,0xa5,0xdd,0xff,0xff,0xff,0xff,0x6f, +0x7f,0xdb,0xf1,0xfc,0xbf,0xff,0x6f,0xff,0xef,0xfc,0x5b,0x5d,0xda,0xdf,0xf4,0xff, +0xf2,0xff,0xfd,0xbf,0xff,0xff,0xff,0xd0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xfb,0xef,0xb7,0xfc,0x33,0xff,0xfb,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0, +0x0f,0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x72,0x0f,0xf1,0x6f,0xff,0xfe,0x94,0x3f, +0xff,0xff,0xff,0x7b,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf0, +0xf7,0xef,0xb7,0xfc,0x33,0xff,0xff,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,0x0f, +0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x73,0x8f,0xf2,0x6f,0xff,0xfe,0x94,0x3f,0xff, +0xff,0xff,0x7d,0x9f,0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x9e, +0xff,0xfc,0xef,0xd3,0xfb,0xff,0x7f,0xf5,0x5f,0xfe,0x59,0xff,0xff,0xff,0xfc,0xf1, +0xfe,0x7f,0xff,0xff,0xfa,0x17,0xff,0xe7,0xef,0xef,0xff,0xff,0x3f,0xf1,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xfc,0xea, +0xff,0xf0,0xff,0xff,0xbf,0xf9,0x3f,0xb1,0xef,0xff,0xd7,0xff,0xfb,0xff,0xf0,0xff, +0xff,0xf3,0xff,0xdf,0xff,0x7b,0xff,0xfd,0xff,0xf6,0xff,0xbf,0xff,0xff,0xbf,0xff, +0xff,0xff,0xda,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x01,0x00,0x00,0x02,0x02, +0x02,0x02,0x00,0x40,0x40,0x40,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x19,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, +0x00,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfb,0xff,0xfd,0xff, +0xff,0x7f,0xff,0xff,0xbf,0xff,0xef,0xff,0xff,0xfd,0xff,0xff,0xf1,0xff,0xdf,0xff, +0xff,0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xdf, +0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xdf,0xff,0x7f,0xff,0xff,0xff,0xff, +0xdf,0xdf,0xff,0xef,0xff,0x9e,0xef,0xff,0xff,0x7f,0xff,0xf1,0xef,0xff,0xff,0xff, +0xf7,0xfa,0xbf,0xff,0xff,0xfe,0x47,0xef,0xff,0xbd,0xf6,0xff,0xff,0xdf,0xf5,0xf0, +0xf0,0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x01,0x02,0x08, +0x16,0x00,0x00,0x00,0x80,0x00,0x01,0x02,0x00,0x80,0x01,0x0c,0x02,0x00,0x00,0x01, +0x00,0x00,0x20,0x00,0x00,0x06,0x00,0x20,0x00,0x10,0x00,0x14,0x00,0x04,0xc1,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f, +0xec,0xff,0xff,0xfa,0xff,0xbf,0xff,0x6f,0xff,0xe1,0xff,0xff,0xff,0xff,0xbd,0xfe, +0x46,0xff,0xef,0x7f,0xcd,0xdf,0xff,0xff,0xfd,0xff,0xbd,0xff,0x7f,0x7f,0xf0,0x4f, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa4,0xbc,0xcd,0x6d,0x6b,0x6f,0x5b,0xdc,0x33, +0x5a,0xf6,0xf7,0xf6,0xb3,0x3f,0xbd,0xc1,0xfa,0x5a,0xf6,0xf6,0xb6,0xf7,0xff,0xbd, +0xbb,0x3c,0xce,0xcf,0x34,0xef,0x33,0xbb,0xcc,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff, +0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xd6,0xff,0xfd,0xfd,0xbf,0xff,0xad, +0xbf,0xf9,0x7f,0x6f,0xfc,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0xff,0xda,0xdb,0xfc, +0xdb,0xff,0x76,0x8f,0xf6,0xff,0xcd,0xab,0xfe,0xfb,0xff,0xd0,0xff,0xff,0xff,0xff, +0xfe,0xff,0x9f,0xff,0xf4,0x20,0xaf,0x6d,0x0b,0xc1,0x7b,0xff,0xff,0xff,0xcb,0xff, +0x3f,0xf0,0xef,0x7f,0x0f,0xf1,0xc3,0x3c,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x0b, +0x1d,0x6a,0x64,0x05,0x6b,0x99,0x01,0xff,0xfd,0xef,0xf0,0x2f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xf4,0x00,0x2f,0xcc,0x0b,0xc3,0x7f,0xff,0xff,0xff,0x0a,0xdf,0xbf, +0xfd,0x7f,0xff,0xff,0xf1,0xc3,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x4a,0x0e, +0x96,0x64,0x02,0x97,0x99,0x10,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xfe,0x84,0xf9,0xd5,0x27,0xf1,0x7f,0xff,0xf8,0xeb,0xdf,0xf3,0xcf,0x3f, +0x1f,0xff,0xf7,0x11,0xff,0xcf,0xff,0xfe,0x67,0xff,0xff,0xff,0xff,0xc4,0xff,0xff, +0xb3,0xa1,0xff,0xf9,0xe0,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff, +0xff,0xfb,0x7f,0xe0,0xff,0xc7,0xfe,0x7f,0x3f,0xff,0xfd,0x77,0x8d,0x7f,0x0f,0xff, +0xc3,0xff,0xf1,0xbf,0x8f,0xcf,0xff,0xff,0xdd,0x7b,0xff,0xf6,0xfa,0xf7,0xff,0x40, +0x9f,0xf9,0x7f,0xd8,0xff,0xff,0xfa,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00, +0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x10,0x00,0x00,0x10, +0x00,0x01,0x00,0x10,0x20,0x20,0x00,0x00,0x10,0x00,0x04,0x01,0x05,0x00,0x00,0x00, +0x00,0x40,0x40,0x00,0x00,0x3c,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff, +0xff,0xff,0xfe,0x7f,0x7f,0xff,0xef,0xff,0xff,0xdf,0xff,0xff,0xdf,0xff,0xef,0xf7, +0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xfc,0xfd,0xff,0x7f, +0x7e,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0xff,0xff, +0xff,0xff,0xfe,0xeb,0xfd,0x6f,0xff,0xf7,0xfe,0xf5,0x7f,0xff,0xff,0x7f,0xbf,0xb1, +0xff,0xff,0x9f,0xbf,0xfb,0xff,0xfe,0xff,0xfe,0xff,0xf7,0xeb,0xdf,0xbf,0x5f,0xdd, +0xff,0xdb,0xfd,0xd0,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x00,0x42,0x00, +0x00,0x00,0x30,0x18,0x04,0x08,0x09,0x21,0x82,0x80,0x02,0x00,0x08,0x00,0x01,0x00, +0x00,0x00,0x0c,0x20,0x10,0x00,0x11,0x00,0x44,0x84,0x00,0x20,0x20,0x84,0x80,0x00, +0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xf7,0xff,0xfb,0xdd,0xf9,0xff, +0xda,0xff,0xdc,0xdd,0xfc,0xfb,0xff,0xbf,0xfb,0x3e,0xd7,0x96,0xfe,0x61,0xf7,0xff, +0x7f,0xff,0x3f,0xfd,0xff,0xdf,0xcf,0xf7,0xdf,0xf7,0xbf,0xfd,0xff,0xfe,0xef,0xef, +0xfe,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf3,0xbd,0xfd,0x4b,0x74,0xcf, +0x73,0x5b,0xcb,0x3b,0xdf,0xfe,0xf7,0xfe,0xd3,0x75,0xac,0xa1,0xfb,0xdf,0xfe,0xf7, +0x76,0x96,0xb5,0x24,0xbd,0xa5,0xad,0x49,0x2f,0x69,0x2b,0x52,0x5b,0xbd,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0xff,0xcc, +0xa7,0xfb,0xad,0xff,0x7f,0x6f,0xff,0x6d,0x7f,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff, +0x6f,0xff,0xdb,0xff,0xdb,0xff,0xf6,0x97,0xf6,0xff,0xb5,0xb5,0xff,0xff,0xff,0xd0, +0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa5,0xbc,0x43,0xfc,0x7c,0x03,0xe7, +0xff,0xff,0x20,0xff,0xff,0xff,0xcc,0xfd,0x7d,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59, +0xba,0x56,0x66,0x6a,0xad,0x9a,0xa9,0x9a,0x97,0xa5,0xaa,0xbb,0xff,0xff,0xf0,0x0f, +0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xfd,0xf7,0xfd,0x43,0xff,0xfd,0x6b,0xe7,0xff, +0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0x3f,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,0xb5, +0xa6,0x66,0x6a,0xad,0x9a,0xa9,0x99,0x6b,0x5a,0xaa,0xff,0xff,0xb7,0xf0,0x3f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x9c,0xf7,0xfd,0xd2,0x41,0xff,0xff,0xf2,0x7f, +0x8f,0xff,0xff,0x3d,0xf3,0xff,0x17,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,0xdf,0xfc, +0x8f,0x38,0xff,0xef,0x23,0xff,0xfb,0xf7,0xc8,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff, +0xff,0xfe,0xf5,0x7f,0xff,0xfd,0xff,0xe4,0xff,0xeb,0xff,0xcf,0xbf,0xfa,0xff,0xab, +0xef,0xff,0xfb,0xff,0xf3,0xfd,0x61,0xff,0xff,0xff,0xff,0xfa,0xff,0xfb,0xfd,0x0d, +0xff,0xfe,0xff,0x43,0x7f,0xfe,0xbf,0xd0,0xfd,0xff,0xfa,0xf0,0x3f,0xff,0xff,0xff, +0xfe,0xf3,0xc0,0x00,0x00,0x00,0x02,0x00,0x02,0x01,0x00,0x60,0xc0,0x40,0x00,0x00, +0x00,0x00,0x34,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x88,0x00, +0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x3c,0xf0,0x3f,0xff,0xff,0xff,0xfe, +0xfd,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfd,0xff, +0xff,0xff,0xff,0xfe,0xfe,0x5f,0xff,0xff,0xcb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0, +0xff,0xff,0xfd,0xff,0xef,0xe3,0xde,0xee,0xd9,0xc5,0x93,0xff,0xff,0xfe,0xfe,0xff, +0xfb,0xee,0xfe,0xf1,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xbf,0xf7,0xff,0xff,0x7f, +0xaf,0xbd,0xdf,0xdf,0xfb,0xf3,0xf3,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x34, +0x00,0x06,0x61,0x00,0x18,0x01,0xa0,0x05,0x17,0x00,0x20,0x05,0x28,0x20,0x00,0x00, +0x05,0x00,0x41,0x00,0x00,0x40,0x00,0x09,0x00,0x01,0x20,0x86,0x82,0x08,0x40,0x03, +0x80,0x30,0x70,0x08,0x14,0x02,0xc1,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xbd,0xef,0xfb,0xff,0xff,0xfb,0x9c,0x7f,0xef,0xdf,0xff,0xbf,0xeb,0xde, +0xff,0xc1,0x7f,0xff,0xfb,0x7f,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xdf,0xbf,0xef, +0x3f,0xf7,0x8f,0xef,0x7f,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbd, +0xdf,0xef,0x7d,0x6d,0x2b,0x5a,0x5d,0xd2,0xdf,0xf6,0x92,0xb6,0xb2,0xb3,0xac,0xa1, +0xfb,0xdf,0xfe,0xf1,0xee,0xf5,0xf6,0xbc,0x6b,0xbd,0x7d,0xaf,0x1a,0xef,0x5f,0x6b, +0xc6,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff, +0xf6,0xff,0xf6,0xb7,0xfd,0xad,0xfd,0xbf,0xf3,0x6f,0xff,0x6f,0xff,0xdb,0xd1,0xfd, +0xbf,0xff,0x6f,0xf5,0x6b,0xbc,0x5b,0x3c,0xda,0xef,0x16,0xaf,0x16,0xff,0xcd,0xab, +0xff,0x6f,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfc,0xbf,0xff,0xff, +0xff,0x6c,0x03,0x10,0xc1,0xf3,0xff,0xf3,0x3a,0xf3,0xca,0xff,0xaf,0xf1,0xff,0xff, +0xff,0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff, +0xff,0x5f,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff, +0xea,0x0f,0x50,0xc3,0xf3,0x7f,0xff,0xf3,0xf3,0xc3,0xff,0xaf,0xf1,0xff,0xff,0xff, +0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,0xff, +0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xd7,0xff,0xff,0x5f,0xc1, +0x3f,0xf7,0x5e,0xf5,0xce,0x9e,0x5f,0x3f,0x17,0xff,0xf3,0xe1,0xff,0xff,0xff,0xff, +0xd8,0xff,0xfa,0xfe,0x67,0xff,0xfe,0xbf,0x5a,0xff,0xff,0xaf,0xf5,0xff,0xff,0xff, +0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfd,0xff,0xf7,0xff,0xfd,0x4e,0x3d, +0x3f,0xe7,0x0b,0xbf,0x8f,0xf9,0xff,0xeb,0xe3,0xff,0xe1,0xff,0xff,0xfc,0xff,0xc7, +0x9f,0xff,0x3e,0x39,0xe5,0xff,0xcf,0x9b,0xf9,0xff,0xff,0xc5,0xff,0xff,0xfa,0xf0, +0x5f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, +0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x20, +0x00,0x01,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf0,0x4f, +0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xbf, +0x3f,0xff,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf1,0xff,0xff,0xff,0xff,0xf7,0xff,0xf7, +0xff,0xed,0xff,0xfb,0xfe,0xff,0x7f,0xff,0x7f,0xdf,0xff,0xff,0xdd,0xf0,0x3f,0xff, +0xff,0xff,0xfe,0xf0,0xff,0xff,0xf3,0xff,0xf7,0xff,0xfe,0x5f,0xff,0xf7,0xff,0xff, +0xdf,0xff,0xff,0xff,0xf7,0xfe,0x7b,0xf1,0xff,0xfd,0xfd,0xff,0xdf,0xdf,0xff,0x7d, +0x73,0xf9,0xff,0xc3,0x7e,0xfe,0xff,0xef,0xd7,0xff,0xcf,0xd0,0xf0,0x6f,0xff,0xff, +0xff,0xfe,0xf8,0x30,0x00,0x00,0x40,0x04,0x00,0x01,0x41,0x20,0x00,0x04,0x00,0x02, +0xd5,0x09,0x00,0x02,0x80,0x02,0x01,0x00,0x00,0x00,0x0a,0x04,0x00,0x07,0x00,0x01, +0x50,0x01,0x80,0x02,0x61,0x40,0x41,0x0c,0x14,0x08,0xc1,0xf0,0x9f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0xdf,0xcb,0x5f,0xfe,0xef,0xff,0xfe, +0xff,0x3f,0xff,0x7f,0xfd,0xc1,0xff,0xff,0x7f,0xff,0xdf,0xfd,0xfc,0xfd,0xf7,0xee, +0xff,0xff,0x4e,0xff,0xdf,0xcf,0xdb,0xeb,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0x7f, +0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff, +0xf7,0xfb,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0x7f,0xff,0xff,0xff,0x7f,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdd,0xff, +0xff,0xff,0xa5,0xff,0x6f,0x6b,0xe9,0x6f,0xda,0xca,0xfb,0xdd,0xee,0xf7,0xf6,0xb2, +0xb3,0xa4,0xa1,0x5b,0x5b,0xf6,0xd7,0xf4,0xf7,0x7b,0xbd,0xbd,0xad,0xcf,0xef,0x7f, +0x6b,0x7f,0x3b,0xdf,0xdb,0xff,0xff,0x30,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xff,0xff,0xf6,0xfe,0x96,0xff,0xfd,0xb5,0xfd,0xbf,0xad,0x7f,0xff,0x6f,0xff, +0xde,0xd1,0xad,0xad,0xe9,0xff,0xf1,0xec,0xef,0xde,0x3f,0xcb,0xff,0xf6,0xff,0x32, +0xff,0xc5,0xbd,0xff,0xff,0xff,0xd0,0xbf,0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xf4, +0x28,0xbf,0xff,0xfd,0xfb,0xd3,0xff,0xff,0x42,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3, +0xc1,0xff,0x33,0xff,0xc0,0x15,0x6b,0x70,0xff,0xf0,0xf2,0x4f,0xff,0xfc,0x3e,0x97, +0x3c,0xff,0xff,0xfd,0xef,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x78, +0xbf,0xff,0xfd,0xf3,0xef,0x55,0xff,0x7e,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,0xc1, +0xff,0x33,0xff,0xc0,0x15,0x6f,0xff,0x0f,0xf0,0xf0,0x0f,0xff,0xfc,0x3d,0x6b,0xc3, +0xff,0xff,0xfe,0xf7,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff, +0xff,0x23,0xf8,0x7f,0xff,0x4e,0xff,0xff,0xff,0xfb,0xf9,0x17,0xff,0xf6,0xf1,0xff, +0xcf,0xef,0xff,0xff,0x13,0xdf,0xe6,0x2f,0xc7,0xff,0xff,0xe7,0xc1,0xfd,0xff,0xfe, +0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xfe,0xae,0xff, +0xff,0x7f,0x3b,0x3f,0xfc,0x7f,0xfc,0xef,0xff,0xfc,0xe2,0x7b,0xff,0xf1,0xfd,0xed, +0xef,0xff,0xff,0x35,0x73,0xff,0xff,0xfe,0xfa,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xfa,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x00,0x0c,0x04,0x01,0x40,0x40,0x00, +0x00,0x30,0x28,0x04,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00, +0x38,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xfb,0xff,0x7f, +0xff,0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xdf,0xdf,0xff, +0xff,0xff,0xff,0xed,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xbf,0xbf,0xff,0xff,0xc3, +0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xfd,0xff,0xbf,0xff,0xff,0xfd,0xff,0xff, +0xff,0xff,0xff,0xfd,0x7b,0xff,0x7f,0xff,0xbd,0xff,0xf1,0xef,0xff,0xff,0xfd,0xdf, +0xfd,0xfb,0xff,0xff,0xbf,0xbe,0xff,0xcd,0x7f,0xfc,0xf7,0xf7,0x6f,0xbf,0xd8,0xf0, +0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x00,0xa0,0x00,0x00, +0xc0,0x00,0x00,0x20,0x34,0x00,0x00,0x00,0x0c,0x81,0x00,0x20,0xa4,0x20,0x00,0x10, +0x08,0x04,0x48,0x08,0x00,0x40,0x93,0x00,0x10,0x00,0x38,0x18,0x20,0xc1,0xf0,0x3f, +0xff,0xff,0xff,0xfe,0xff,0xfb,0xff,0xff,0xb9,0xdf,0xfe,0xb3,0xff,0xff,0xe7,0xfd, +0xff,0xff,0x3b,0xff,0x7f,0xff,0xbf,0xff,0xc1,0xff,0xfc,0xff,0xff,0x3f,0x77,0xfe, +0xfe,0xcf,0xff,0xbf,0xfd,0xbf,0xff,0xfe,0xed,0xf2,0xfd,0xf7,0xff,0xf0,0x2f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xf3,0xad,0xcf,0xef,0x70,0xc9,0x73,0x3b,0xdf,0x5b,0x4a, +0xf6,0xb7,0xfe,0xd7,0xf5,0xbc,0xc1,0x33,0xca,0xd6,0xb7,0x6e,0xf7,0xfb,0xbd,0xc5, +0x24,0xcf,0x6f,0x2f,0x4d,0x2b,0xba,0x5a,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff, +0xfe,0xbf,0xff,0xff,0xff,0xff,0xf6,0xf6,0xd7,0xff,0xff,0xad,0xbd,0xff,0xff,0xff, +0xef,0xf7,0x7f,0xfc,0x5b,0xb1,0xfd,0xbd,0x75,0x6f,0xef,0x6a,0xfd,0x5b,0xfb,0xdb, +0x3a,0xbf,0x8e,0x9f,0xff,0xbf,0xfd,0xff,0x6f,0xff,0xd0,0x6f,0xff,0xff,0xff,0xfe, +0xff,0xbb,0xff,0xf0,0x3f,0xff,0xff,0xfd,0xfb,0x7f,0xde,0xff,0xff,0x5a,0xd6,0xbf, +0xd8,0x2a,0xbf,0xbf,0xf1,0xe5,0xff,0xcc,0xc0,0xa9,0x70,0xff,0xf3,0x3c,0x3c,0xfd, +0x57,0xfd,0x98,0x03,0x00,0xc3,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0x3d,0xbf,0xff,0xfd,0xfb,0xff,0xdb,0xff,0xff,0x0f,0xfc,0x3f,0xd8, +0x2a,0xbf,0xbf,0xf1,0xef,0xff,0xcc,0xc0,0x96,0xbe,0xff,0xf3,0x3f,0xff,0xfd,0x57, +0xfd,0x99,0x0f,0xff,0xc3,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xf1,0xe7,0xff,0xff,0xf3,0x8e,0x7b,0xff,0xa8,0xff,0xdf,0x7f,0x8e,0x78,0x73, +0xff,0xf1,0x51,0x62,0xff,0xfc,0x4b,0xff,0xf3,0xff,0x7e,0xcf,0xf9,0xff,0xfd,0xff, +0xff,0x7f,0xff,0xe0,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff, +0xfb,0xfd,0xae,0xff,0xfc,0xfe,0x6f,0x3f,0xf8,0xfd,0x77,0xaf,0xfe,0x37,0xfe,0x7b, +0xff,0xb1,0x8c,0xff,0xef,0xfd,0xf8,0xe7,0xbf,0xff,0xf1,0xfe,0x3e,0xf7,0xfe,0x95, +0x3e,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00, +0x01,0x04,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x08, +0x41,0x80,0x10,0x00,0x00,0x08,0x10,0x84,0x00,0x0c,0x04,0x02,0x61,0x00,0x00,0x81, +0x00,0x00,0x00,0x00,0x3d,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff, +0xff,0xff,0x7f,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0x7f,0xbf,0xf7,0x7f,0xef,0xff,0xef,0xff,0xf7,0xfd,0xff,0xff,0xfd,0x7f,0xff,0xbe, +0xdf,0xff,0xff,0xd9,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0x7f,0xfb,0xff, +0xfb,0xff,0xbf,0xff,0xf3,0x7f,0xfb,0xfd,0xeb,0x7f,0xdf,0xfa,0xff,0xde,0xf0,0xed, +0xff,0xb1,0xf7,0xf9,0x1f,0xb5,0x5b,0xfe,0x7e,0xf7,0xbe,0xfd,0x7f,0x5f,0xb5,0xf7, +0xff,0xff,0xd0,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x01,0x00,0x07,0x42,0x01, +0x00,0x6a,0x18,0x50,0x80,0x00,0x00,0x02,0x40,0x01,0x01,0x20,0x01,0x01,0x24,0x14, +0x21,0x10,0x02,0x08,0x07,0x08,0x00,0x40,0x10,0x80,0x58,0x00,0x84,0x80,0x18,0x10, +0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xff,0xdb,0xb7,0xf3, +0xdf,0x7c,0xf8,0x74,0xff,0xff,0x6f,0x7d,0x3f,0x7e,0xec,0x7f,0xc1,0xf5,0xff,0xcf, +0x6f,0x9f,0xf9,0xdf,0xbe,0xe5,0xe7,0xff,0xd7,0xf3,0xdd,0xfb,0xff,0xfc,0xff,0xbf, +0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0x2f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xff,0xb4,0xcf,0xef,0x77,0x6f,0x73, +0x3a,0x4a,0x3a,0xcb,0xd4,0xf7,0x2e,0xd6,0xbd,0xbd,0xa1,0x3b,0xdf,0xd6,0xf7,0xee, +0xd3,0x35,0xbd,0xfb,0xbd,0xce,0xeb,0x2b,0x4d,0x2f,0xbb,0xda,0xff,0xff,0xfe,0xb0, +0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdf,0x5f,0x36,0xaf,0x3f,0xed,0xb7, +0xf5,0xfd,0xf3,0x2b,0xef,0x77,0xff,0xfb,0xda,0xb1,0xbd,0xa3,0x77,0x69,0x7f,0x4f, +0xff,0xdb,0xfa,0x5b,0xff,0xf2,0xfe,0xff,0x96,0xff,0xff,0xfe,0xdf,0xff,0xd0,0xaf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x8f,0xfd,0x40,0x6f,0x9e,0x83,0x5a,0x0f, +0xfa,0xc3,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xd0,0x00,0xfe,0xbf,0xcd,0x3f,0xf0, +0xef,0xfc,0xc5,0x0c,0x3f,0xfd,0x68,0x0b,0xff,0xff,0xff,0xfe,0xdf,0xf0,0xff,0xff, +0xff,0xff,0xfe,0xff,0xbb,0xff,0xfd,0x85,0xff,0xd4,0x6f,0x9f,0xc3,0x5a,0x0f,0xff, +0xff,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xf0,0xfb,0xc2,0xbf,0xfc,0x00,0x37,0xef, +0xfc,0xcd,0xbc,0x3f,0xff,0x0c,0xbf,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xd9,0xf7,0xd1,0xb7,0x7e,0x7f,0xf1,0xe4,0xfd,0xff, +0xfb,0xfb,0xff,0x5f,0xff,0x7f,0xb1,0xbc,0x0f,0x67,0xeb,0xb8,0x3f,0xff,0xe2,0xff, +0xe9,0xff,0xfd,0xe3,0xff,0x3f,0x9f,0xc2,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff, +0xfe,0xf5,0x7f,0xff,0xf0,0x3f,0xbc,0xff,0xd5,0xf5,0xce,0x3f,0xfe,0xff,0xfe,0x6d, +0xff,0xf1,0xbf,0x7b,0xff,0xf1,0xfd,0xff,0x4f,0xff,0x87,0xff,0xae,0xff,0xb1,0xf8, +0xfe,0xff,0xff,0x78,0x01,0xb9,0xff,0xff,0xff,0xfa,0xf0,0x2f,0xff,0xff,0xff,0xfe, +0xf3,0xc0,0x00,0x00,0x00,0x04,0x02,0x13,0x02,0x00,0x80,0x40,0x00,0x90,0x10,0x00, +0x10,0x00,0x02,0x00,0x01,0x20,0x80,0x12,0x10,0x00,0x40,0x08,0x00,0x04,0x00,0x00, +0x02,0x00,0x01,0x40,0x00,0x80,0x00,0x00,0x3c,0xf0,0xef,0xff,0xff,0xff,0xfe,0xfd, +0x1f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xf7,0xdf,0xf7,0xff, +0xf7,0xfb,0xeb,0xd1,0xff,0xff,0xff,0xff,0xef,0xf7,0xff,0xff,0xfb,0xff,0xfe,0xff, +0xff,0x7e,0xff,0xfb,0xff,0xff,0xff,0xdb,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf0,0xff, +0xff,0xb7,0xeb,0xf7,0xdf,0xff,0xfe,0xf5,0x6b,0xe7,0xed,0xf7,0x3e,0xec,0xff,0x54, +0xef,0x6f,0xf1,0xf5,0xaf,0x6f,0xf6,0xfd,0xff,0xdd,0x7b,0xff,0xef,0xbf,0x7f,0xff, +0xff,0xf7,0xff,0xf3,0x5f,0xf7,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00, +0x80,0x40,0x04,0x00,0x81,0x2c,0x04,0x24,0x00,0x02,0x01,0xc8,0x02,0x00,0x02,0x24, +0x00,0x01,0xb4,0x42,0xdc,0x44,0x02,0x15,0x90,0x02,0x03,0x48,0x39,0x10,0x02,0x24, +0xa0,0xba,0x00,0x00,0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xfe,0xfc,0xf7,0xf0,0xee,0xb6,0x5d,0xfd,0xf5,0xff,0xdb,0xf7,0x7f,0x7f,0xbe,0xff, +0xc1,0xfe,0xbf,0xfa,0xfa,0x5f,0xff,0xad,0xff,0xef,0xff,0x7f,0xdf,0x7f,0xfe,0xbf, +0xb7,0x94,0xbf,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xfb,0xb5,0xff, +0xef,0x7c,0xeb,0x2b,0x52,0x5b,0x3b,0xda,0xd4,0xf3,0x36,0x96,0xb5,0xbd,0xf1,0xfb, +0xda,0xee,0xf6,0xfe,0xd3,0x35,0xbd,0xdf,0xad,0xcf,0xef,0x7e,0xcd,0x6b,0xbb,0xdf, +0xff,0xff,0xfd,0xb0,0xef,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xd3,0x5f,0xf6, +0xff,0xf6,0xff,0xfd,0xad,0xfd,0xff,0x7f,0xef,0xff,0x6f,0x7f,0xdb,0xf1,0xa5,0xa3, +0x7f,0x6f,0x6b,0x4f,0xff,0xdb,0xfb,0xcb,0xff,0xf6,0xff,0xf4,0xd7,0xfd,0xbf,0xfe, +0xdf,0xff,0xd0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdf,0xff,0xff,0xff, +0x3f,0x7f,0xfc,0xe5,0xff,0x20,0xfe,0xff,0xff,0xdf,0x7f,0xff,0xf1,0x7f,0xff,0xfe, +0xff,0xf0,0x7c,0x3d,0x4f,0xf3,0xc3,0x3f,0xff,0xff,0x6f,0xc3,0xff,0x0f,0xff,0xff, +0xaf,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0xb7,0xe0,0x0f,0xff,0xff,0x2b, +0xff,0x7d,0xbf,0xff,0xdf,0xff,0xff,0xf8,0x9f,0x7f,0xff,0xf1,0x55,0xff,0xff,0xff, +0xfd,0x7c,0x3c,0xff,0xf3,0xc3,0x3f,0xff,0xff,0xef,0xc3,0xff,0xdf,0xff,0xff,0xff, +0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0x9f,0xbf,0x7f, +0xf9,0x19,0x47,0x8e,0xe7,0x9f,0x3f,0x17,0xff,0xfc,0x81,0xc1,0x7e,0xf3,0xd9,0xf9, +0x73,0xdf,0xf4,0x7f,0xfa,0xff,0xff,0xff,0xfb,0x7f,0x77,0xc7,0xff,0xff,0xff,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xf5,0xf7,0xff,0xfb,0xff,0xf7,0x3f,0xfc,0xbf,0x3e,0x3f, +0xec,0xff,0x81,0xaf,0xfe,0x4f,0xf3,0xbb,0xff,0xf0,0x7e,0xff,0x6f,0xff,0x87,0xff, +0xbb,0xff,0xd5,0xfc,0xff,0x7f,0xfc,0x6f,0xff,0xef,0xe7,0xff,0xff,0xfa,0xf0,0x3f, +0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, +0x00,0x30,0x10,0x60,0x20,0x00,0x08,0x00,0x01,0x20,0x80,0x00,0x10,0x00,0x04,0x00, +0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x40,0x00,0x08,0x20,0x3c,0xf0,0x6f,0xff, +0xff,0xff,0xfe,0xf5,0xbf,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x3f,0xff, +0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xf1,0xdf,0xdf,0xff,0xff,0xff,0x7f,0xdf,0xff, +0xfd,0xbd,0xff,0xff,0xff,0xfb,0xdf,0xff,0xff,0xff,0xff,0x5b,0xf0,0xff,0xff,0xff, +0xff,0xfe,0xf0,0xbf,0xbf,0xbf,0xff,0xf7,0xfb,0xff,0xfe,0xee,0xfa,0xff,0xff,0xff, +0x3d,0x3b,0xff,0xff,0xfe,0xfb,0xf1,0xff,0xbf,0x7b,0xff,0xff,0xef,0xff,0xbf,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xf7,0xef,0xff,0xfb,0xd0,0xf0,0xdf,0xff,0xff,0xff, +0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x00,0x0b,0x10,0x05,0x01,0x00,0x08,0x00,0x02, +0x01,0x01,0x00,0x00,0x10,0x01,0xc8,0x08,0x00,0x00,0x00,0x00,0x42,0x02,0x00,0x00, +0x00,0x80,0x02,0x00,0x00,0x40,0x24,0x80,0x00,0xc1,0xf0,0x3f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xf7,0xfd,0xf7,0xfa,0xef,0xee,0xf9,0xfd,0xff,0xf7,0xfe,0xbf, +0x1f,0xfd,0x9e,0xfd,0xd1,0xef,0xff,0xf7,0x7f,0x9f,0xff,0xef,0xff,0xf6,0xff,0xfe, +0xfe,0x7b,0xff,0xbd,0xff,0x7e,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xf7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xdf,0xfd,0xff,0xff,0xdf,0xff, +0xff,0x5f,0xf1,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xef,0xff, +0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfb,0xff,0xff,0xef,0xfb,0xfd, +0xff,0xf1,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf7,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xe7,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0xff,0xfb,0xff,0xfb,0xf1, +0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7b,0xff,0xff,0xff,0x7f,0xff,0xf1,0xff, +0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x57,0xff,0xfe,0xbf,0xfb,0xf1,0xff,0xff, +0xfd,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xd7,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd, +0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xef,0x2f,0xf1,0x3c,0xbf,0xbc, +0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff, +0x01,0xe2,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff }; diff -u --recursive --new-file v2.3.12/linux/drivers/net/hamradio/yam9600.h linux/drivers/net/hamradio/yam9600.h --- v2.3.12/linux/drivers/net/hamradio/yam9600.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/hamradio/yam9600.h Thu Aug 5 14:35:52 1999 @@ -0,0 +1,343 @@ +/* + * + * File yam111.mcs converted to h format by mcs2h + * + * (C) F6FBB 1998 + * + * Tue Aug 25 20:23:03 1998 + * + */ + +static unsigned char bits_9600[]= { +0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xfb,0xcb,0xff,0xdb,0xfe,0xf2, +0xff,0xf6,0xff,0x9c,0xbf,0xfd,0xbf,0xef,0x2e,0x3f,0x6f,0xf1,0xfd,0xb4,0xfd,0xbf, +0xff,0x6f,0xff,0x6f,0xff,0x0b,0xff,0xdb,0xff,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff, +0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xfd,0xdf,0xff,0xff,0xff,0xf7,0xff,0xff,0xff, +0xfb,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0x7f,0xf1,0xff,0xfe,0xff,0xbf,0xbf, +0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0xfe,0xff,0xff,0xff,0xf0, +0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xf7, +0xff,0xff,0xf7,0xef,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0x7e,0xff,0xff, +0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xef,0xff,0xf3,0xfb,0xfe,0xff,0xf1,0xff,0xfd,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xdf,0xff,0xf0,0x7f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff, +0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xef,0xff,0x7f,0xff,0xef, +0xff,0xef,0xff,0x7f,0xef,0xf1,0xff,0xef,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xbd,0xff,0xef,0x7f,0xef,0x7f,0xfb,0xdf,0xd3,0x5a,0xfe,0xd7,0xd6, +0xf7,0x7f,0xbd,0xf1,0xbb,0x5d,0xd6,0xf7,0xfe,0x96,0xff,0xbd,0xaf,0xad,0xbf,0xef, +0x7f,0x6b,0x7f,0xfb,0xd6,0xfe,0xf7,0xff,0x10,0xef,0xff,0xff,0xff,0xfe,0xbe,0xef, +0xff,0xff,0xdb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xbf,0xff,0x7f,0xff,0x7f, +0xdf,0xdb,0xf1,0xfd,0x35,0xff,0x6f,0xff,0x6f,0xff,0xdb,0xff,0xcb,0xff,0xf6,0xff, +0xf2,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff, +0xff,0xf1,0x24,0xf0,0xff,0xff,0xcf,0xef,0x3f,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f, +0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,0xff, +0xf1,0x00,0xf0,0xff,0xff,0xcf,0xdf,0xff,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,0xff, +0xff,0xff,0x7d,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0x7f,0xdf,0xff,0xff,0xff,0xf1, +0xff,0xcf,0xff,0xf3,0xff,0x97,0xff,0xff,0x8f,0xe7,0xff,0xff,0xfc,0x71,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xf7,0xef,0xff,0xff,0xfc,0x7b,0xff,0xf1,0x3f, +0xff,0xef,0xff,0xcf,0xe3,0xe3,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xbf,0xff, +0xbf,0xff,0xda,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00, +0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0x9f,0xff, +0xff,0xff,0xf7,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xdb,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xdf,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xdf,0xbf,0xf1,0xfe,0xfd,0xf7,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xfd,0xf2, +0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0x0c,0x01,0x00,0x00,0x04,0x24,0x00, +0x40,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0xc0,0xf0, +0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xbf,0xff,0xff,0x6f,0xff,0xdf,0xff,0xd1,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xdf,0xff,0xfb,0xff,0xfb,0xef,0xff,0xff,0xee,0xff,0xff,0x7f,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xad,0xff,0x69,0x2a,0xed,0x6b,0xfb,0xdf,0x3a, +0xdc,0xf4,0x96,0xee,0xb3,0x3d,0x35,0xc1,0xbb,0xdd,0xfe,0xf6,0xfe,0xd6,0xb5,0xad, +0xbf,0xa5,0xad,0x49,0x2f,0x4f,0x2b,0xda,0x5f,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff, +0xff,0xfe,0xbf,0xff,0xff,0xfb,0x5b,0xf7,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xa5, +0xf3,0x6f,0xf3,0x6e,0xfa,0x7b,0xd1,0xfd,0xb5,0x77,0x6f,0xe9,0x6f,0xff,0xdb,0xfb, +0xdb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0x3f,0xfe,0xf7,0xff,0xd0,0x4f,0xff,0xff,0xff, +0xfe,0xff,0x9f,0xff,0xff,0x0f,0xff,0xc0,0x3f,0x9c,0x03,0xff,0xff,0x8b,0xa5,0xfe, +0x80,0x3e,0xc2,0xbf,0xac,0xb1,0x24,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xa3, +0xff,0xfd,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0x0f,0xff,0xc0,0x3f,0xd4,0x6b,0xff,0xff,0xdb,0xff,0xfe,0x86, +0xbf,0xc2,0xbf,0x30,0xa1,0x24,0xff,0xff,0xff,0xff,0xcc,0xff,0x0f,0xff,0xa3,0xff, +0x05,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xfb,0xc7,0xff,0xc4,0xff,0xff,0x7f,0xff,0xec,0xfe,0x7f,0xdf,0xd8,0xb9, +0x47,0xfc,0x36,0xc1,0xdf,0xff,0xff,0xf9,0xff,0xf3,0xff,0xf7,0xff,0xfc,0xff,0xfd, +0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff, +0xff,0xff,0xff,0xfe,0xff,0xff,0x7e,0xbd,0x3f,0xff,0x2b,0xfe,0x2f,0xf5,0xa3,0xfc, +0x5b,0xfe,0x61,0x9f,0x7f,0xef,0xff,0xff,0xa7,0xfb,0xff,0xff,0xfa,0xfe,0xff,0x33, +0xf1,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x24,0x04, +0x00,0x01,0x00,0x80,0x40,0x00,0x08,0x00,0x00,0x00,0x02,0x01,0x01,0x00,0x02,0x00, +0x00,0x00,0x00,0x00,0x01,0x3d,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xfd,0xbd,0xff,0xfd, +0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,0xf6,0xef,0xbf,0xf7,0xff,0x73,0xeb, +0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xf9,0xff,0xfd,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xd9,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,0xbf,0x7f,0xff,0xff, +0xff,0x7f,0xff,0xff,0xde,0xff,0xff,0xef,0xdd,0xde,0x77,0xf2,0xfb,0xed,0xe7,0xf1, +0x73,0xfd,0xfd,0xdf,0xff,0x7d,0xbe,0xdf,0xff,0xfb,0xff,0xef,0xff,0xef,0xff,0xff, +0xff,0xff,0xff,0xd0,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x02,0x00,0x22, +0x40,0xc0,0x00,0x00,0x00,0x08,0x00,0x02,0x41,0x02,0x12,0x00,0x21,0x87,0x81,0x00, +0x00,0x80,0x04,0x0b,0x28,0x01,0xb0,0x00,0x82,0x00,0x40,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xfd,0xff, +0xf7,0xff,0xfe,0x7f,0xed,0x79,0xff,0xde,0xeb,0x7f,0x74,0xf7,0xf7,0xe1,0xf9,0xff, +0xf6,0x5f,0x7f,0xff,0xff,0xff,0xd7,0xdb,0xef,0xff,0xbb,0xff,0xff,0xff,0xcc,0xff, +0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x3d,0xcd,0x49,0x7f,0x6f, +0x2b,0xba,0x5c,0xd2,0xda,0xf6,0xf3,0x3e,0xf7,0xff,0xbd,0xf1,0xfa,0xdf,0xfe,0xf7, +0xcc,0xf6,0xbb,0xa5,0xb3,0xad,0xbf,0x6f,0x7d,0x6f,0x6b,0xdb,0xdf,0xbd,0xff,0xfe, +0xb0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xfb,0xdb,0x57,0xf6,0xfe,0x9f,0xd5, +0xb7,0xff,0xaf,0xe5,0x3f,0xff,0xff,0x6f,0xff,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0x69, +0x6c,0xdf,0xda,0xdf,0xcb,0xff,0xf6,0xff,0x76,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0, +0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfd,0xbd,0x08,0x03,0x89,0x4f,0x5a, +0x0f,0xf0,0xff,0xf8,0xbf,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xf3, +0xfa,0xa0,0xf0,0xf2,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xfd,0x00,0x6b,0xff,0xff,0x5a,0x0f, +0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xb3,0xf5, +0x50,0xf0,0xf0,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xbc,0xff,0xe4,0xe7,0x71,0xff,0xf9,0xc4,0xf4, +0x7f,0x7f,0xcf,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xfb,0xf7,0x73,0xbf,0x14, +0xff,0xe6,0xff,0xff,0xe1,0x7d,0xff,0xff,0xe7,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff, +0xff,0xfe,0xf5,0xff,0xff,0xfe,0xd2,0xfa,0xff,0xc4,0xf4,0x5c,0xbf,0xfa,0xff,0xff, +0xec,0x7e,0xbf,0xff,0xff,0xff,0xf1,0xff,0xff,0xef,0xff,0xff,0x6b,0xdb,0xff,0xdf, +0xf9,0xfb,0xbf,0xff,0xf1,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf0,0xbf,0xff,0xff,0xff, +0xfe,0xf3,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x00,0x80,0x00, +0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x20,0x00,0x00,0x00,0x00, +0x01,0x00,0x01,0x00,0x00,0x80,0x02,0x00,0x01,0x3c,0xf0,0x5f,0xff,0xff,0xff,0xfe, +0xfd,0xbf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0x7f,0xff,0xdf,0xff,0xef,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff, +0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xc3,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf0, +0xff,0xdf,0xff,0xff,0xf7,0x23,0xff,0xff,0xfd,0xff,0xef,0xff,0xfe,0x7f,0x7d,0xf7, +0xfe,0xff,0x7f,0x71,0xff,0xfb,0x7f,0xff,0xff,0xff,0x6e,0xfd,0xf7,0xfd,0xff,0xbf, +0xff,0xbf,0xf9,0xfd,0xff,0xdf,0xef,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x30, +0x40,0x01,0x00,0x83,0x00,0x00,0x00,0x0c,0x06,0x08,0x04,0x26,0x26,0x00,0x00,0x06, +0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x70,0x08,0x80,0x00,0x20,0x01,0x20, +0x00,0x02,0x00,0x30,0x00,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0x7b,0x3f,0xf7,0xff,0xd7,0xfe,0xfe,0xfb,0xfe,0x3b,0xfe,0xbd,0xff,0x2f, +0xff,0x71,0xff,0xfb,0x7f,0xe7,0xff,0xf9,0xef,0xff,0xd7,0xfa,0xff,0xb7,0xbb,0xfe, +0xff,0xff,0x74,0xff,0xf7,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xb5, +0xbd,0x6f,0x7c,0xeb,0x7f,0xfb,0xdb,0xd3,0x4b,0xee,0xd6,0xf6,0xb7,0xfd,0xac,0xa1, +0xfb,0xdf,0xfe,0xf7,0xf4,0x96,0xbd,0xb4,0xc5,0xa5,0xaf,0x6f,0x69,0x4f,0x7f,0xba, +0xdb,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff, +0xf6,0xff,0xf6,0xff,0xbd,0xbf,0xa5,0xbf,0xff,0x7d,0x7f,0xef,0xff,0xfb,0xf1,0xfd, +0xbf,0xff,0x6f,0xff,0x6b,0x7a,0xdb,0xff,0xdb,0xdf,0xf6,0xfe,0xb6,0xfd,0xfd,0xbf, +0xfe,0xf7,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf4,0x2f,0xff, +0xfc,0x43,0x6b,0xff,0xff,0xff,0x0d,0xff,0xfc,0x33,0x3f,0xf0,0x5f,0xf1,0xff,0xff, +0xff,0xff,0xf9,0xde,0xf0,0x4c,0xfe,0x77,0xaf,0xff,0xff,0xef,0xff,0xf0,0xff,0xdb, +0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xfe,0xf7,0xff,0xf0,0x2f,0xff,0xfd, +0x43,0x7f,0xff,0xff,0xf1,0x0f,0xff,0xfc,0x33,0x3f,0xff,0xaf,0xf1,0xff,0xff,0xff, +0xff,0xf6,0xd7,0xff,0xbc,0xfd,0xbd,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff, +0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xfb,0xf1, +0xbf,0xff,0xf9,0xfd,0xcf,0xf2,0x70,0xff,0x1f,0x9f,0xf3,0xf1,0xff,0xff,0xff,0xff, +0xfc,0xf7,0xff,0x13,0x9f,0xfc,0xff,0xff,0x84,0xf7,0xff,0xff,0x47,0xff,0xff,0xff, +0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xf1,0xfc,0xff,0xfe,0xfe,0x79, +0x3f,0xff,0x1d,0x46,0xcf,0xff,0xcf,0xfc,0x7b,0xff,0xf1,0xff,0xff,0xff,0xff,0xed, +0xf3,0xab,0xff,0xcb,0xff,0xf8,0xff,0xfc,0xf5,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0, +0x8f,0xff,0xff,0xff,0xfe,0xf3,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, +0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x04,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x20, +0x0c,0x00,0x00,0x04,0x01,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x01,0x3c,0xf0,0x7f, +0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfd,0xfe,0xff,0xff,0xff,0xff,0xfe,0xff, +0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xef,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xeb, +0xff,0xdf,0xff,0xff,0xfb,0xf7,0x7f,0xff,0xfe,0xff,0xff,0xbf,0xdb,0xf0,0xff,0xff, +0xff,0xff,0xfe,0xf0,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0x7f,0xf7,0xff, +0xbf,0xbf,0xcf,0xff,0xff,0xff,0x3e,0xf1,0x7f,0xff,0xff,0xef,0xff,0xff,0xff,0xfe, +0xff,0xfd,0xff,0xbf,0xbd,0xfe,0xff,0xfb,0xf7,0xdf,0xfb,0xd0,0xf0,0x9f,0xff,0xff, +0xff,0xfe,0xf8,0x30,0x20,0x00,0x40,0x01,0x80,0xc0,0x30,0x00,0x00,0x20,0x00,0x10, +0x50,0x88,0x20,0x00,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x00,0x01,0x80,0x08,0x00,0x00,0xa0,0x00,0x10,0xc1,0xf0,0xef,0xff,0xff,0xff, +0xfe,0xfd,0xef,0x7f,0xff,0xff,0xbf,0xff,0xf7,0xff,0xef,0xfb,0xfd,0x77,0xef,0xbf, +0xf7,0x7f,0xff,0xff,0xbf,0xd1,0x7f,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xaf,0xff, +0xdf,0xf7,0xfb,0xff,0xfd,0xff,0xfc,0xff,0xfd,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x3f,0xff,0xff,0xff,0xfe,0xdd,0xff, +0xff,0xff,0xa5,0xfd,0x6f,0x7d,0x6d,0x7f,0x52,0xdf,0x5a,0x4b,0xee,0xb6,0xee,0xf2, +0xbb,0xac,0xa1,0x5b,0x4d,0xd6,0xf7,0xfe,0xb2,0xbd,0x35,0xb5,0xb5,0xdd,0x6f,0x7f, +0xe9,0x5f,0x52,0xdf,0xbd,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff, +0xff,0xdb,0xfe,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xb5,0xbf,0xf9,0x7f,0x6f,0xff, +0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0x69,0x7f,0xdb,0xff,0xd3,0xff,0xf6,0xfe,0xf2, +0xff,0xad,0xbf,0xff,0xff,0xff,0xd0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5, +0x30,0x0f,0xff,0xff,0xfd,0x6b,0xca,0xff,0xf0,0x0f,0xd6,0xbf,0xcf,0x3f,0xff,0xff, +0xf1,0xff,0xff,0xff,0xca,0xfe,0xbf,0xff,0xf0,0x05,0xaf,0x0f,0xff,0xfc,0xf0,0xcf, +0xf0,0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0x30, +0x0f,0xff,0xff,0xfc,0x3f,0xca,0xff,0x0f,0x0f,0xd6,0xbf,0xff,0xff,0xf5,0x5f,0xf1, +0xff,0x8b,0xff,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xfc,0xf0,0xcf,0xf0, +0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xcf,0xff, +0xff,0xbf,0x9f,0x3f,0xfe,0xfc,0xff,0x4f,0xff,0xff,0xff,0xff,0xff,0xf7,0xf1,0xff, +0xdf,0xfe,0x7e,0x3f,0x9f,0xf4,0xfc,0x7f,0xfc,0xff,0xff,0x3f,0xff,0x3f,0xfe,0x3f, +0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfb,0xff,0xfe,0xff, +0xff,0xff,0xff,0xbf,0xfb,0xff,0xf8,0xed,0xff,0x8f,0xff,0xbb,0xff,0xb1,0xf3,0xef, +0x8f,0xf7,0xff,0xff,0xdb,0xff,0xff,0xff,0xef,0xbf,0xfd,0x79,0xbf,0xbf,0xff,0xff, +0xff,0xfb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x04,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x04,0x08,0x08,0x01,0x01,0x00,0x90, +0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x01, +0x3c,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0x9f,0xff,0xaf,0xdf,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xbf,0xef,0xff,0xff,0xff,0xed,0xff,0xff,0xff,0xef,0xff,0xbf,0xff,0xff,0xff,0xc3, +0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xfd,0xff,0xff,0xff,0xfb,0xff,0xbb,0xff, +0xff,0xff,0x7f,0xf6,0xff,0x7f,0xfb,0xfd,0xed,0xff,0xf1,0xff,0xfe,0x7f,0xff,0xff, +0xff,0x5f,0xff,0xf7,0xff,0x7e,0xff,0xfd,0xff,0xef,0xff,0xff,0xff,0xef,0xf0,0xf0, +0x8f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x80,0x00,0x04,0x00,0x00,0x40,0x02,0x00,0x03, +0x00,0x05,0x04,0x20,0x00,0x00,0x01,0xd0,0x00,0x81,0x00,0x20,0x04,0x04,0x00,0x00, +0x81,0x04,0x08,0x80,0x10,0x00,0xc0,0x00,0x00,0x00,0x20,0x00,0x08,0xc1,0xf0,0x6f, +0xff,0xff,0xff,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xf3,0xfd,0xff,0xed,0xfc, +0xff,0xff,0x9f,0xfb,0xfd,0xff,0xff,0xff,0xf1,0xff,0xff,0x7f,0xfb,0x3e,0xff,0x9f, +0xff,0xff,0xff,0xff,0xfd,0xf9,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0x6f,0xff, +0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xfd,0xbd,0xff,0xef,0x7c,0xeb,0x7f,0xfb,0xdb,0xfa,0xdc, +0xee,0xf7,0xf6,0xd7,0xf5,0x2d,0xa1,0xbb,0xdd,0xee,0xf7,0x54,0xf7,0xfb,0x2c,0xb5, +0xb4,0xbd,0x6b,0x6f,0xef,0x6f,0xbb,0xdf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff, +0xfe,0xbf,0xff,0xff,0xff,0xfb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xff,0xbf,0xef, +0x6f,0xff,0x6f,0xfa,0xdb,0xf1,0xc5,0xbd,0xf5,0x6f,0xff,0x6f,0xca,0xdb,0xff,0xdb, +0xfb,0xf6,0x97,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x9f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0x7f,0xff,0xff,0xe7,0x63,0xff,0xff, +0xff,0xfc,0x77,0xdf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff, +0xc3,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xfc,0xff,0xcf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,0xc3, +0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xbf,0xff,0xca,0xff,0x9f,0xff,0xfa,0xb9,0xe7, +0x9f,0xf3,0x81,0xff,0xff,0xfc,0x73,0xd7,0xff,0xff,0x77,0xff,0xfd,0xff,0xfc,0xff, +0xff,0xff,0xff,0xcf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff, +0xff,0xf7,0xde,0xff,0xfe,0x7e,0xff,0xbf,0xff,0xbf,0xf1,0xb3,0xff,0xff,0xe3,0xfb, +0xff,0xe1,0x1f,0x7f,0xff,0xf8,0x78,0xff,0xfb,0x1e,0xff,0xf7,0xfe,0xe7,0xff,0xff, +0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x04,0x00, +0x01,0x80,0x40,0x40,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, +0x80,0x00,0x00,0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xff, +0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xf7,0xf1, +0xfd,0xff,0xff,0xff,0xdf,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff, +0xff,0xff,0xff,0xdb,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xdf,0xff,0xff,0x7f, +0xff,0xff,0xff,0xbe,0xd7,0xff,0xed,0xbd,0x7e,0xbf,0xfe,0xf6,0x7f,0xbf,0x71,0xff, +0xff,0xda,0xff,0xf9,0xff,0xbf,0x7f,0xfe,0xff,0x6f,0x7f,0xff,0xff,0xff,0xff,0xff, +0x7f,0xff,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x42,0x00,0x00,0x00,0x00, +0x80,0xc1,0x00,0x00,0x90,0x00,0xc4,0x00,0x00,0x12,0x20,0x43,0x22,0x81,0x84,0x00, +0x00,0x14,0x00,0x01,0x00,0x08,0x80,0x00,0x02,0x00,0x02,0x00,0x04,0x02,0x00,0x00, +0x10,0xc1,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfd,0xff,0xff,0xdd,0xfe,0xff, +0xb6,0x76,0xe5,0xbc,0xf9,0xf7,0xaf,0x5f,0xbf,0xfc,0xdf,0xcf,0xf1,0xff,0xef,0x79, +0xff,0xbd,0xff,0xef,0xff,0xff,0xf7,0x6f,0x5f,0xff,0xff,0xfd,0xef,0xef,0xbf,0xff, +0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xff,0xff,0xff,0xff,0xfe,0xdb,0xff,0xff,0xfd,0x2d,0xff,0x69,0x2a,0xef,0x77, +0xbb,0xdd,0x5a,0xdf,0xf6,0xf6,0xd6,0xf7,0x7d,0xbd,0xd1,0xb2,0x4a,0xd6,0xb2,0xbe, +0x97,0xf5,0xbd,0xb3,0xad,0xff,0xef,0x7f,0x69,0x6b,0xfb,0xdf,0xff,0xff,0xff,0xf0, +0x2f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0x9f,0xd4,0xbf, +0xed,0xaf,0xff,0x6b,0x6f,0xf7,0xff,0xdd,0xdb,0x31,0xfd,0xbf,0xff,0x6f,0x7f,0xff, +0xff,0xdb,0xff,0xcb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x8f, +0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff, +0xa5,0xff,0xff,0xff,0xdf,0xb7,0xff,0xff,0xf1,0xff,0xff,0xff,0xf7,0xe9,0x6a,0xbf, +0xff,0xff,0xfd,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xaf,0xf0,0x4f,0xff, +0xff,0xff,0xfe,0xfe,0xdf,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,0xa5, +0xff,0xff,0xff,0xc0,0x37,0xff,0xff,0xf1,0x99,0x8e,0xdc,0x7f,0xe9,0x6a,0xbf,0xff, +0xf0,0x0f,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0x07,0xff,0xc0,0xbe,0xff,0xff,0xcf,0xef,0x9f,0xff, +0xff,0xfb,0xff,0xe7,0xff,0xff,0xa1,0xe3,0xce,0x3c,0x58,0x3f,0xf3,0xff,0xfd,0xef, +0xf9,0xff,0xff,0xf7,0xf1,0x7f,0xff,0xcb,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff, +0xfe,0xf5,0x7f,0xff,0xf0,0xff,0xfe,0xff,0xc4,0x75,0xe7,0xb9,0xff,0xff,0xff,0xef, +0xff,0xc7,0x37,0x3b,0xff,0xf0,0x13,0x9e,0x0f,0xf4,0xff,0xfe,0xfb,0xff,0xff,0xf9, +0xfc,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xef,0xff,0xff,0xff,0xfe, +0xf3,0xc0,0x01,0x00,0x00,0x02,0x00,0x02,0x22,0x00,0x00,0xc0,0x40,0x00,0x40,0x00, +0x04,0x08,0x04,0x0a,0x01,0x01,0x10,0x20,0x20,0x00,0x00,0x04,0x08,0x08,0x04,0x00, +0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3c,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xfd, +0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0xcf,0x9d,0xff, +0xff,0xf7,0xfd,0xf1,0xff,0xff,0xff,0xee,0xbf,0xff,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xff, +0xff,0xff,0xf7,0xf7,0xff,0xff,0xfe,0xbf,0xf7,0xff,0xff,0x5b,0xff,0xbf,0xf7,0xff, +0xfd,0x7f,0x71,0xfd,0xff,0xed,0xf7,0xfe,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xff, +0xff,0xff,0xef,0xff,0x7f,0xff,0xd0,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf8,0x30,0x11, +0x00,0x48,0x60,0x40,0x82,0x60,0x24,0x60,0x00,0xcc,0x00,0x80,0x04,0x01,0x00,0x00, +0x14,0x01,0x0c,0x04,0x00,0x30,0x00,0x00,0x00,0x08,0x08,0x00,0x01,0x00,0xc2,0x00, +0x00,0x02,0x00,0x80,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, +0xf7,0x7b,0xff,0xf3,0xeb,0xbf,0xff,0xf7,0xff,0xff,0xff,0xe7,0x5d,0x3f,0xff,0xf6, +0xd1,0xfd,0xff,0xeb,0xf7,0x3d,0xff,0xff,0xff,0x5f,0xff,0x7f,0x7f,0xf3,0xff,0xff, +0xef,0xfd,0xbf,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xb5,0xdf, +0x6f,0x7d,0x69,0x7f,0xfb,0xdf,0x52,0x5f,0xf6,0xf7,0xfe,0xf6,0xf3,0xbd,0xb1,0xda, +0xcd,0xfe,0xf6,0xee,0xd2,0xbd,0xa5,0xaf,0xbd,0xff,0x6f,0x7c,0xeb,0x2b,0xfa,0xda, +0xff,0xfe,0xdf,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6, +0xff,0xf6,0xff,0xbd,0xbf,0xcd,0xbf,0xeb,0x6f,0xf7,0x6f,0xdf,0xdb,0x51,0xfd,0xbd, +0xff,0x6f,0xff,0x6f,0xfb,0x5b,0xff,0xdb,0xff,0xf6,0xfe,0xf6,0xfd,0xfd,0xbf,0xfe, +0xf7,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfa,0x50,0xff,0xff,0xff, +0xf0,0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0xfc,0xff,0xff, +0xf7,0xdb,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff, +0xaf,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xa0,0xff,0xff,0xff,0xf0, +0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff, +0xf3,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,0xff, +0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0x9f,0xf0,0x7f, +0xff,0xf9,0xfc,0x4f,0xf3,0xff,0x27,0xeb,0xff,0xfc,0x81,0xfc,0x7f,0xfe,0x7b,0xff, +0xf7,0xff,0x12,0x7f,0xff,0xff,0xff,0xff,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, +0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xdf,0xfe,0xff,0xfc,0x7e,0x7f,0xbf, +0xff,0xff,0xaf,0xef,0xff,0xdf,0xdf,0xfb,0xff,0xf1,0xc3,0xfe,0x6f,0xf1,0xcf,0x3f, +0xfb,0xff,0xff,0xcf,0xfe,0xff,0xff,0xfe,0x7f,0xbf,0xff,0xff,0xbf,0xfa,0xf0,0xdf, +0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00, +0x20,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x00,0x02,0x80,0x00,0x02,0x3c,0xf0,0x2f,0xff, +0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xf1,0xff,0x7f,0xff,0xff,0xff,0xff,0xef,0xff, +0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x2f,0xff,0xff, +0xff,0xfe,0xf0,0xff,0xff,0xff,0xfb,0xff,0xbf,0xff,0xff,0xff,0xff,0xf7,0xbf,0xfb, +0xff,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xf7,0xbf,0xfb,0xff,0xff,0xff,0x7f,0xde,0xff, +0xff,0xff,0xff,0xff,0xff,0xed,0xf7,0xff,0xff,0x7f,0xd0,0xf0,0x3f,0xff,0xff,0xff, +0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x80, +0x20,0x01,0x01,0x92,0x00,0x01,0x01,0x00,0xe0,0x1c,0x60,0x20,0x30,0x08,0x08,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xc1,0xf0,0x6f,0xff,0xff,0xff,0xfe, +0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0xff,0xdf,0xff,0xfc,0x7f,0xfb,0xbf,0xff, +0xff,0xff,0xff,0xff,0xf1,0xf6,0xff,0xf7,0x7e,0x3f,0xff,0x7f,0xff,0xff,0xff,0xf7, +0xff,0xff,0xff,0xed,0xff,0xdf,0xff,0xb7,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff, +0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xbf,0xff,0xdf, +0x57,0xef,0xf1,0xfd,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfb,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, +0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xdf,0xff, +0xff,0xf1,0xfd,0xff,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xf7,0xfd,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff, +0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1, +0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0x6f,0xff,0xfe,0xbf,0xff,0xf1,0xff, +0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd, +0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0x57,0xff,0xfd,0xbf,0xff,0xf1,0xff,0xef, +0xfe,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, +0xde,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd, +0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xe7,0x2f,0xf1,0x3c,0xbf,0xfd, +0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff, +0x02,0x01,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff }; diff -u --recursive --new-file v2.3.12/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.3.12/linux/drivers/net/hp100.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/net/hp100.c Thu Aug 5 15:04:52 1999 @@ -419,7 +419,7 @@ continue; } /* found... */ - ioaddr = pci_dev -> base_address[ 0 ] & ~3; + ioaddr = pci_dev ->resource[ 0 ].start; if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; pci_read_config_word( pci_dev, PCI_COMMAND, &pci_command ); if ( !( pci_command & PCI_COMMAND_IO ) ) { diff -u --recursive --new-file v2.3.12/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.3.12/linux/drivers/net/irda/toshoboe.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/irda/toshoboe.c Thu Aug 5 15:04:52 1999 @@ -713,7 +713,7 @@ dev_self[i] = self; self->pdev = pci_dev; - self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + self->base = pci_dev->resource[0].start; idev = &self->idev; @@ -850,7 +850,7 @@ if (pci_dev) { printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n", - pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK, + pci_dev->resource[0], pci_dev->irq); if (!toshoboe_open (pci_dev)) diff -u --recursive --new-file v2.3.12/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.3.12/linux/drivers/net/lance.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/lance.c Thu Aug 5 15:04:52 1999 @@ -382,7 +382,7 @@ unsigned short pci_command; pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = pdev->resource[0].start; /* PCI Spec 2.1 states that it is either the driver or PCI card's * responsibility to set the PCI Master Enable Bit if needed. * (From Mark Stockton ) diff -u --recursive --new-file v2.3.12/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c --- v2.3.12/linux/drivers/net/macsonic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/macsonic.c Mon Aug 9 12:32:28 1999 @@ -0,0 +1,485 @@ +/* + * macsonic.c + * + * (C) 1998 Alan Cox + * + * Debugging Andreas Ehliar, Michael Schmitz + * + * Based on code + * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de) + * + * This driver is based on work from Andreas Busse, but most of + * the code is rewritten. + * + * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) + * + * A driver for the Mac onboard Sonic ethernet chip. + * + * 98/12/21 MSch: judged from tests on Q800, it's basically working, + * but eating up both receive and transmit resources + * and duplicating packets. Needs more testing. + * + * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed. + */ + +#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 + +#define SREGS_PAD(n) u16 n; + +#include "sonic.h" + +extern int mac_onboard_sonic_probe(void); + +static int setup_debug = -1; +static int setup_offset = -1; +static int setup_shift = -1; + +/* + * This seems to be the right default for the Q800 + */ + +static int reg_offset = 0; +static int reg_shift = 0; + +/* + * Macros to access SONIC registers + */ + +#define MAC_SONIC_REGISTERS 0x50F0A000 +#define MAC_SONIC_PROM_BASE 0x50f08000 +#define MAC_SONIC_IRQ 9 /* Nubus 9 */ + +/* + * FIXME: We may need to invert the byte ordering. These should + * be ok for other aspects as they are uncached spaces. + * The original macros from jazzsonic.c works for me + * on my LC 630, YMMV /Andreas Ehliar + */ + +#if 0 +#define SONIC_READ(reg) \ + *((volatile unsigned int *)base_addr+((reg)<<2)+2) + +#define SONIC_WRITE(reg,val) \ + *((volatile unsigned int *)base_addr+((reg)<<2)+2) = val +#else +#define SONIC_READ(reg) \ + *((volatile unsigned int *)base_addr+reg) + +#define SONIC_WRITE(reg,val) \ + *((volatile unsigned int *)base_addr+reg) = val +#endif + +#define SONIC_READ_PROM(addr) \ + *((volatile unsigned char *)prom_addr+addr) +/* + * Function : mac_sonic_setup(char *str, int *ints) + * + * Purpose : booter command line initialization of the overrides array, + * + * Inputs : str - unused, ints - array of integer parameters with ints[0] + * equal to the number of ints. + * + * Currently unused in the new driver; need to add settable parameters to the + * detect function. + * + */ + +void mac_sonic_setup(char *str, int *ints) { + /* Format of macsonic parameter is: + * macsonic=,, + * Negative values mean don't change. + */ + + /* Grmbl... the standard parameter parsing can't handle negative numbers + * :-( So let's do it ourselves! + */ + + int i = ints[0]+1, fact; + + while( str && (isdigit(*str) || *str == '-') && i <= 10) { + if (*str == '-') + fact = -1, ++str; + else + fact = 1; + ints[i++] = simple_strtoul( str, NULL, 0 ) * fact; + if ((str = strchr( str, ',' )) != NULL) + ++str; + } + ints[0] = i-1; + + if (ints[0] < 1) { + printk( "mac_sonic_setup: no arguments!\n" ); + return; + } + + if (ints[0] >= 1) { + /* 0 <= n <= 2 */ + if (ints[1] >= 0 && ints[1] <= 8) + setup_debug = ints[1]; + else if (ints[1] > 16) + printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] ); + } + if (ints[0] >= 2) { + /* 0 <= n <= 2 */ + if (ints[2] >= 0 && ints[2] <= 16) + setup_offset = ints[2]; + else if (ints[2] > 16) + printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] ); + } + if (ints[0] >= 3) { + /* 0 <= n <= 2 */ + if (ints[3] >= 0 && ints[3] <= 16) + setup_shift = ints[3]; + else if (ints[3] > 16) + printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] ); + } +} + +static int sonic_debug = 0; + +/* + * For reversing the PROM address + */ + +static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14, + 1, 9, 5, 13, 3, 11, 7, 15}; + +__initfunc(int mac_onboard_sonic_probe(void)) +{ + struct device *dev; + unsigned int silicon_revision; + unsigned int val; + struct sonic_local *lp; + int i; + int base_addr = MAC_SONIC_REGISTERS; + int prom_addr = MAC_SONIC_PROM_BASE; + static int one=0; + + if (!MACH_IS_MAC) + return -ENODEV; + + if(++one!=1) /* Only one is allowed */ + return -ENODEV; + + printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. "); + + if (macintosh_config->ether_type != MAC_ETHER_SONIC) + { + printk("none.\n"); + return -ENODEV; + } + + printk("yes\n"); + + if (setup_debug >= 0) + sonic_debug = setup_debug; + + /* + * This may depend on the actual Mac model ... works for me. + */ + reg_offset = + (setup_offset >= 0) ? setup_offset : 0; + reg_shift = + (setup_shift >= 0) ? setup_shift : 0; + + /* + * get the Silicon Revision ID. If this is one of the known + * one assume that we found a SONIC ethernet controller at + * the expected location. + * (This is not implemented in the Macintosh driver yet; need + * to collect values from various sources. Mine is 0x4 ...) + */ + + silicon_revision = SONIC_READ(SONIC_SR); + if (sonic_debug > 1) + printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision); + + /* + * We need to allocate sonic_local later on, making sure it's + * aligned on a 64k boundary. So, no space for dev->priv allocated + * here ... + */ + dev = init_etherdev(0,0); + + if(dev==NULL) + return -ENOMEM; + + printk("%s: %s found at 0x%08x, ", + dev->name, "SONIC ethernet", base_addr); + + if (sonic_debug > 1) + printk("using offset %d shift %d,", reg_offset, reg_shift); + + /* Fill in the 'dev' fields. */ + dev->base_addr = base_addr; + dev->irq = MAC_SONIC_IRQ; + + /* + * Put the sonic into software reset, then + * retrieve and print the ethernet address. + */ + + SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); + + /* + * We can't trust MacOS to initialise things it seems. + */ + + if (sonic_debug > 1) + printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR)); + + SONIC_WRITE(SONIC_DCR, + SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW); + + /* + * We don't want floating spare IRQ's around, not on + * level triggered systems! + * Strange though - writing to the ISR only clears currently + * pending IRQs, but doesn't disable them... Does this make + * a difference?? Seems it does ... + */ +#if 1 + SONIC_WRITE(SONIC_ISR,0x7fff); + SONIC_WRITE(SONIC_IMR,0); +#else + SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT); +#endif + + /* This is how it is done in jazzsonic.c + * It doesn't seem to work here though. + */ + if (sonic_debug > 2) { + printk("Retreiving CAM entry 0. This should be the HW address.\n"); + + SONIC_WRITE(SONIC_CEP, 0); + for (i = 0; i < 3; i++) + { + val = SONIC_READ(SONIC_CAP0 - i); + dev->dev_addr[i * 2] = val; + dev->dev_addr[i * 2 + 1] = val >> 8; + } + + printk("HW Address from CAM 0: "); + for (i = 0; i < 6; i++) + { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + printk("\n"); + + printk("Retreiving CAM entry 15. Another candidate...\n"); + + /* + * MacOS seems to use CAM entry 15 ... + */ + SONIC_WRITE(SONIC_CEP, 15); + for (i = 0; i < 3; i++) + { + val = SONIC_READ(SONIC_CAP0 - i); + dev->dev_addr[i * 2] = val; + dev->dev_addr[i * 2 + 1] = val >> 8; + } + + printk("HW Address from CAM 15: "); + for (i = 0; i < 6; i++) + { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + printk("\n"); + } + + /* + * if we can read the PROM, we're safe :-) + */ + if (sonic_debug > 1) + printk("Retreiving HW address from the PROM: "); + + for(i=0;i<6;i++){ + dev->dev_addr[i]=SONIC_READ_PROM(i); + } + if (sonic_debug > 1) { + for (i = 0; i < 6; i++) + { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + printk("\n"); + } + /* + * If its not one of these we have + * screwed up on this Mac model + */ + + if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && + memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && + memcmp(dev->dev_addr, "\x00\x05\x02", 3)) + { + /* + * Try bit reversed + */ + for(i=0;i<6;i++){ + val = SONIC_READ_PROM(i); + dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) | + nibbletab[(val >> 4) &0xf]; + } + if (sonic_debug > 1) { + printk("Trying bit reversed: "); + for (i = 0; i < 6; i++) + { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + printk("\n"); + } + if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && + memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && + memcmp(dev->dev_addr, "\x00\x05\x02", 3)) + { + /* + * Still nonsense ... messed up someplace! + */ + printk("ERROR (INVALID MAC)\n"); + return -EIO; + } + } + + printk(" MAC "); + for (i = 0; i < 6; i++) + { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + + printk(" IRQ %d\n", MAC_SONIC_IRQ); + + /* Initialize the device structure. */ + if (dev->priv == NULL) + { + if (sonic_debug > 2) { + printk("Allocating memory for dev->priv aka lp\n"); + printk("Memory to allocate: %d\n",sizeof(*lp)); + } + /* + * the memory be located in the same 64kb segment + */ + lp = NULL; + i = 0; + do + { + lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL); + if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16) + { + /* FIXME, free the memory later */ + kfree(lp); + lp = NULL; + } + } + while (lp == NULL && i++ < 20); + + if (lp == NULL) + { + printk("%s: couldn't allocate memory for descriptors\n", + dev->name); + return -ENOMEM; + } + + if (sonic_debug > 2) { + printk("Memory allocated after %d tries\n",i); + } + + /* XXX sonic_local has the TDA, RRA, RDA, don't cache */ + kernel_set_cachemode((u32)lp, 8192, IOMAP_NOCACHE_SER); + memset(lp, 0, sizeof(struct sonic_local)); + + lp->cda_laddr = (u32)lp; + if (sonic_debug > 2) { + printk("memory allocated for sonic at 0x%x\n",lp); + } + lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda); + lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda); + lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra); + + /* allocate receive buffer area */ + /* FIXME, maybe we should use skbs */ + if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) + { + printk("%s: couldn't allocate receive buffers\n", dev->name); + return -ENOMEM; + } + /* XXX RBA written by Sonic, not cached either */ + kernel_set_cachemode((u32)lp->rba, 6*8192, IOMAP_NOCACHE_SER); + lp->rba_laddr = (u32)lp->rba; + flush_cache_all(); + dev->priv = (struct sonic_local *) lp; + } + lp = (struct sonic_local *) dev->priv; + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; +} + +/* + * SONIC uses a nubus IRQ + */ + +#define sonic_request_irq(irq, vec, flags, name, dev) \ + nubus_request_irq(irq, dev, vec) +#define sonic_free_irq(irq,id) nubus_free_irq(irq) + +/* + * No funnies on memory mapping. + */ + +#define sonic_chiptomem(x) (x) + +/* + * No VDMA on a Macintosh. So we need request no such facility. + */ + +#define vdma_alloc(x,y) ((u32)(x)) +#define vdma_free(x) +#define PHYSADDR(x) (x) + +#include "sonic.c" diff -u --recursive --new-file v2.3.12/linux/drivers/net/mvme147.c linux/drivers/net/mvme147.c --- v2.3.12/linux/drivers/net/mvme147.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/mvme147.c Mon Aug 9 12:32:28 1999 @@ -0,0 +1,209 @@ +/* mvme147.c : the Linux/mvme147/lance ethernet driver + * + * Copyright (C) 05/1998 Peter Maydell + * Based on the Sun Lance driver and the NetBSD HP Lance driver + * Uses the generic 7990.c LANCE code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Used for the temporal inet entries and routing */ +#include +#include + +#include + +#include +#include +#include + +#include + +/* We have 16834 bytes of RAM for the init block and buffers. This places + * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx + * buffers and 2 Tx buffers. + */ +#define LANCE_LOG_TX_BUFFERS 1 +#define LANCE_LOG_RX_BUFFERS 3 + +#include "7990.h" /* use generic LANCE code */ + +/* Our private data structure */ +struct m147lance_private { + struct lance_private lance; + void *base; + void *ram; +}; + +/* function prototypes... This is easy because all the grot is in the + * generic LANCE support. All we have to support is probing for boards, + * plus board-specific init, open and close actions. + * Oh, and we need to tell the generic code how to read and write LANCE registers... + */ +int mvme147lance_probe(struct device *dev); +static int m147lance_open(struct device *dev); +static int m147lance_close(struct device *dev); +static void m147lance_writerap(struct m147lance_private *lp, unsigned short value); +static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value); +static unsigned short m147lance_readrdp(struct m147lance_private *lp); + +typedef void (*writerap_t)(void *, unsigned short); +typedef void (*writerdp_t)(void *, unsigned short); +typedef void (*readrdp_t)(void *); + +#ifdef MODULE +static struct m147lance_private *root_m147lance_dev = NULL; +#endif + +/* Initialise the one and only on-board 7990 */ +__initfunc(int mvme147lance_probe(struct device *dev)) +{ + static int called = 0; + static const char name[] = "MVME147 LANCE"; + struct m147lance_private *lp; + u_long *addr; + u_long address; + + if (!MACH_IS_MVME147 || called) + return(ENODEV); + called++; + + dev->priv = kmalloc(sizeof(struct m147lance_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct m147lance_private)); + + /* Fill the dev fields */ + dev->base_addr = (unsigned long)MVME147_LANCE_BASE; + dev->open = &m147lance_open; + dev->stop = &m147lance_close; + dev->hard_start_xmit = &lance_start_xmit; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &lance_set_multicast; + dev->dma = 0; + + addr=(u_long *)ETHERNET_ADDRESS; + address = *addr; + dev->dev_addr[0]=0x08; + dev->dev_addr[1]=0x00; + dev->dev_addr[2]=0x3e; + address=address>>8; + dev->dev_addr[5]=address&0xff; + address=address>>8; + dev->dev_addr[4]=address&0xff; + address=address>>8; + dev->dev_addr[3]=address&0xff; + + printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, dev->base_addr, MVME147_LANCE_IRQ, + dev->dev_addr[0], + dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], + dev->dev_addr[5]); + + lp = (struct m147lance_private *)dev->priv; + lp->ram = (void *)__get_dma_pages(GFP_ATOMIC, 3); /* 16K */ + if (!lp->ram) + { + printk("%s: No memory for LANCE buffers\n", dev->name); + return -ENODEV; + } + + lp->lance.name = (char*)name; /* discards const, shut up gcc */ + lp->lance.ll = (struct lance_regs *)(dev->base_addr); + lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */ + lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram); /* LANCE addr of same RAM */ + lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ + lp->lance.irq = MVME147_LANCE_IRQ; + lp->lance.writerap = (writerap_t)m147lance_writerap; + lp->lance.writerdp = (writerdp_t)m147lance_writerdp; + lp->lance.readrdp = (readrdp_t)m147lance_readrdp; + lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS; + lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS; + lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK; + lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK; + ether_setup(dev); + +#ifdef MODULE + dev->ifindex = dev_new_index(); + lp->next_module = root_m147lance_dev; + root_m147lance_dev = lp; +#endif /* MODULE */ + + return 0; +} + +static void m147lance_writerap(struct m147lance_private *lp, unsigned short value) +{ + lp->lance.ll->rap = value; +} + +static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value) +{ + lp->lance.ll->rdp = value; +} + +static unsigned short m147lance_readrdp(struct m147lance_private *lp) +{ + return lp->lance.ll->rdp; +} + +static int m147lance_open(struct device *dev) +{ + int status; + + status = lance_open(dev); /* call generic lance open code */ + if (status) + return status; + /* enable interrupts at board level. */ + m147_pcc->lan_cntrl=0; /* clear the interrupts (if any) */ + m147_pcc->lan_cntrl=0x08 | 0x04; /* Enable irq 4 */ + + MOD_INC_USE_COUNT; + return 0; +} + +static int m147lance_close(struct device *dev) +{ + /* disable interrupts at boardlevel */ + m147_pcc->lan_cntrl=0x0; /* disable interrupts */ + lance_close(dev); + MOD_DEC_USE_COUNT; + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + root_lance_dev = NULL; + return mvme147lance_probe(NULL); +} + +void cleanup_module(void) +{ + /* Walk the chain of devices, unregistering them */ + struct m147lance_private *lp; + while (root_m147lance_dev) { + lp = root_m147lance_dev->next_module; + unregister_netdev(root_lance_dev->dev); + free_pages(lp->ram, 3); + kfree(root_lance_dev->dev); + root_lance_dev = lp; + } +} + +#endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.3.12/linux/drivers/net/ne.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/ne.c Thu Aug 5 15:04:52 1999 @@ -218,7 +218,7 @@ unsigned int pci_ioaddr; while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) { - pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = pdev->resource[0].start; /* Avoid already found cards from previous calls */ if (check_region(pci_ioaddr, NE_IO_EXTENT)) continue; diff -u --recursive --new-file v2.3.12/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c --- v2.3.12/linux/drivers/net/ne2k-pci.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/ne2k-pci.c Thu Aug 5 15:04:52 1999 @@ -208,7 +208,7 @@ if (pci_clone_list[i].vendor == 0) continue; - pci_ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = pdev->resource[0].start; pci_irq_line = pdev->irq; pci_read_config_word(pdev, PCI_COMMAND, &pci_command); diff -u --recursive --new-file v2.3.12/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v2.3.12/linux/drivers/net/net_init.c Tue May 25 13:06:34 1999 +++ linux/drivers/net/net_init.c Thu Aug 5 14:34:02 1999 @@ -111,6 +111,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); @@ -233,6 +235,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); @@ -563,6 +567,8 @@ alloc_size &= ~3; /* Round to dword boundary. */ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + if(dev==NULL) + return NULL; memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); diff -u --recursive --new-file v2.3.12/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c --- v2.3.12/linux/drivers/net/ni5010.c Wed Oct 7 15:51:45 1998 +++ linux/drivers/net/ni5010.c Thu Aug 5 14:34:02 1999 @@ -119,7 +119,7 @@ static void show_registers(struct device *dev); -__initfunc(int ni5010_probe(struct device *dev)) +int __init ni5010_probe(struct device *dev) { int *port; @@ -157,7 +157,7 @@ return inb(IE_SAPROM); } -__initfunc(void trigger_irq(int ioaddr)) +void __init trigger_irq(int ioaddr) { outb(0x00, EDLC_RESET); /* Clear EDLC hold RESET state */ outb(0x00, IE_RESET); /* Board reset */ @@ -182,7 +182,7 @@ * verifies that the correct device exists and functions. */ -__initfunc(static int ni5010_probe1(struct device *dev, int ioaddr)) +static int __init ni5010_probe1(struct device *dev, int ioaddr) { static unsigned version_printed = 0; int i; diff -u --recursive --new-file v2.3.12/linux/drivers/net/ni52.c linux/drivers/net/ni52.c --- v2.3.12/linux/drivers/net/ni52.c Tue Jun 8 10:27:18 1999 +++ linux/drivers/net/ni52.c Thu Aug 5 14:34:02 1999 @@ -358,7 +358,7 @@ /********************************************** * probe the ni5210-card */ -__initfunc(int ni52_probe(struct device *dev)) +int __init ni52_probe(struct device *dev) { #ifndef MODULE int *port; @@ -409,7 +409,7 @@ return ENODEV; } -__initfunc(static int ni52_probe1(struct device *dev,int ioaddr)) +static int __init ni52_probe1(struct device *dev,int ioaddr) { int i,size; diff -u --recursive --new-file v2.3.12/linux/drivers/net/ni65.c linux/drivers/net/ni65.c --- v2.3.12/linux/drivers/net/ni65.c Tue Jun 8 10:27:18 1999 +++ linux/drivers/net/ni65.c Thu Aug 5 14:34:02 1999 @@ -326,7 +326,7 @@ #ifdef MODULE static #endif -__initfunc(int ni65_probe(struct device *dev)) +int __init ni65_probe(struct device *dev) { int *port; static int ports[] = {0x360,0x300,0x320,0x340, 0}; @@ -348,7 +348,7 @@ /* * this is the real card probe .. */ -__initfunc(static int ni65_probe1(struct device *dev,int ioaddr)) +static int __init ni65_probe1(struct device *dev,int ioaddr) { int i,j; struct priv *p; diff -u --recursive --new-file v2.3.12/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.3.12/linux/drivers/net/pcnet32.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/net/pcnet32.c Thu Aug 5 15:06:47 1999 @@ -461,10 +461,7 @@ if (pcnet32_tbl[chip_idx].vendor_id == 0) continue; - ioaddr = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; -#if defined(ADDR_64BITS) && defined(__alpha__) - ioaddr |= ((long)pdev->base_address[1]) << 32; -#endif + ioaddr = pdev->resource[0].start; irq_line = pdev->irq; /* Avoid already found cards from previous pcnet32_probe() calls */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/plip.c linux/drivers/net/plip.c --- v2.3.12/linux/drivers/net/plip.c Sun Mar 7 15:47:46 1999 +++ linux/drivers/net/plip.c Thu Aug 5 14:34:02 1999 @@ -233,8 +233,8 @@ then calls us here. */ -__initfunc(int -plip_init_dev(struct device *dev, struct parport *pb)) +int __init +plip_init_dev(struct device *dev, struct parport *pb) { struct net_local *nl; struct pardevice *pardev; @@ -1223,8 +1223,8 @@ return 0; } -__initfunc(int -plip_init(void)) +int __init +plip_init(void) { struct parport *pb = parport_enumerate(); int i=0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/ppp_async.c linux/drivers/net/ppp_async.c --- v2.3.12/linux/drivers/net/ppp_async.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/ppp_async.c Fri Aug 6 10:44:11 1999 @@ -0,0 +1,957 @@ +/* + * PPP async serial channel driver for Linux. + * + * Copyright 1999 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This driver provides the encapsulation and framing for sending + * and receiving PPP frames over async serial lines. It relies on + * the generic PPP layer to give it frames to send and to process + * received frames. It implements the PPP line discipline. + * + * Part of the code in this driver was inspired by the old async-only + * PPP driver, written by Michael Callahan and Al Longyear, and + * subsequently hacked by Paul Mackerras. + * + * ==FILEVERSION 990806== + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPP_VERSION "2.4.0" + +#define OBUFSIZE 256 + +/* Structure for storing local state. */ +struct asyncppp { + struct tty_struct *tty; + unsigned int flags; + unsigned int state; + unsigned int rbits; + int mru; + unsigned long busy; + u32 xaccm[8]; + u32 raccm; + unsigned int bytes_sent; + unsigned int bytes_rcvd; + + struct sk_buff *tpkt; + int tpkt_pos; + u16 tfcs; + unsigned char *optr; + unsigned char *olim; + struct sk_buff_head xq; + unsigned long last_xmit; + + struct sk_buff *rpkt; + struct sk_buff_head rq; + wait_queue_head_t rwait; + + struct ppp_channel chan; /* interface to generic ppp layer */ + int connected; + unsigned char obuf[OBUFSIZE]; +}; + +/* Bit numbers in busy */ +#define XMIT_BUSY 0 +#define RECV_BUSY 1 +#define XMIT_WAKEUP 2 +#define XMIT_FULL 3 + +/* State bits */ +#define SC_TOSS 0x20000000 +#define SC_ESCAPE 0x40000000 + +/* Bits in rbits */ +#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) + +#define PPPASYNC_MAX_RQLEN 32 /* arbitrary */ + +static int flag_time = HZ; +MODULE_PARM(flag_time, "i"); + +/* + * Prototypes. + */ +static int ppp_async_encode(struct asyncppp *ap); +static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb); +static int ppp_async_push(struct asyncppp *ap); +static void ppp_async_flush_output(struct asyncppp *ap); +static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf, + char *flags, int count); + +struct ppp_channel_ops async_ops = { + ppp_async_send +}; + +/* + * Routines for locking and unlocking the transmit and receive paths. + */ +static inline void +lock_path(struct asyncppp *ap, int bit) +{ + do { + while (test_bit(bit, &ap->busy)) + mb(); + } while (test_and_set_bit(bit, &ap->busy)); + mb(); +} + +static inline int +trylock_path(struct asyncppp *ap, int bit) +{ + if (test_and_set_bit(bit, &ap->busy)) + return 0; + mb(); + return 1; +} + +static inline void +unlock_path(struct asyncppp *ap, int bit) +{ + mb(); + clear_bit(bit, &ap->busy); +} + +#define lock_xmit_path(ap) lock_path(ap, XMIT_BUSY) +#define trylock_xmit_path(ap) trylock_path(ap, XMIT_BUSY) +#define unlock_xmit_path(ap) unlock_path(ap, XMIT_BUSY) +#define lock_recv_path(ap) lock_path(ap, RECV_BUSY) +#define trylock_recv_path(ap) trylock_path(ap, RECV_BUSY) +#define unlock_recv_path(ap) unlock_path(ap, RECV_BUSY) + +static inline void +flush_skb_queue(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(q)) != 0) + kfree_skb(skb); +} + +/* + * Routines implementing the PPP line discipline. + */ + +/* + * Called when a tty is put into PPP line discipline. + */ +static int +ppp_async_open(struct tty_struct *tty) +{ + struct asyncppp *ap; + + ap = kmalloc(sizeof(*ap), GFP_KERNEL); + if (ap == 0) + return -ENOMEM; + + MOD_INC_USE_COUNT; + + /* initialize the asyncppp structure */ + memset(ap, 0, sizeof(*ap)); + ap->tty = tty; + ap->mru = PPP_MRU; + ap->xaccm[0] = ~0U; + ap->xaccm[3] = 0x60000000U; + ap->raccm = ~0U; + ap->optr = ap->obuf; + ap->olim = ap->obuf; + skb_queue_head_init(&ap->xq); + skb_queue_head_init(&ap->rq); + init_waitqueue_head(&ap->rwait); + + tty->disc_data = ap; + + return 0; +} + +/* + * Called when the tty is put into another line discipline + * (or it hangs up). + */ +static void +ppp_async_close(struct tty_struct *tty) +{ + struct asyncppp *ap = tty->disc_data; + + if (ap == 0) + return; + tty->disc_data = 0; + lock_xmit_path(ap); + lock_recv_path(ap); + if (ap->rpkt != 0) + kfree_skb(ap->rpkt); + flush_skb_queue(&ap->rq); + if (ap->tpkt != 0) + kfree_skb(ap->tpkt); + flush_skb_queue(&ap->xq); + if (ap->connected) + ppp_unregister_channel(&ap->chan); + kfree(ap); + MOD_DEC_USE_COUNT; +} + +/* + * Read a PPP frame. pppd can use this to negotiate over the + * channel before it joins it to a bundle. + */ +static ssize_t +ppp_async_read(struct tty_struct *tty, struct file *file, + unsigned char *buf, size_t count) +{ + struct asyncppp *ap = tty->disc_data; + DECLARE_WAITQUEUE(wait, current); + ssize_t ret; + struct sk_buff *skb = 0; + + ret = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + + add_wait_queue(&ap->rwait, &wait); + current->state = TASK_INTERRUPTIBLE; + for (;;) { + ret = -EAGAIN; + skb = skb_dequeue(&ap->rq); + if (skb) + break; + if (file->f_flags & O_NONBLOCK) + break; + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&ap->rwait, &wait); + + if (skb == 0) + goto out; + + ret = -EOVERFLOW; + if (skb->len > count) + goto outf; + ret = -EFAULT; + if (copy_to_user(buf, skb->data, skb->len)) + goto outf; + ret = skb->len; + + outf: + kfree_skb(skb); + out: + return ret; +} + +/* + * Write a ppp frame. pppd can use this to send frames over + * this particular channel. + */ +static ssize_t +ppp_async_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t count) +{ + struct asyncppp *ap = tty->disc_data; + struct sk_buff *skb; + ssize_t ret; + + ret = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + + ret = -ENOMEM; + skb = alloc_skb(count + 2, GFP_KERNEL); + if (skb == 0) + goto out; + skb_reserve(skb, 2); + ret = -EFAULT; + if (copy_from_user(skb_put(skb, count), buf, count)) { + kfree_skb(skb); + goto out; + } + + skb_queue_tail(&ap->xq, skb); + ppp_async_push(ap); + + ret = count; + + out: + return ret; +} + +static int +ppp_async_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct asyncppp *ap = tty->disc_data; + int err, val; + u32 accm[8]; + struct sk_buff *skb; + + err = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + goto out; + + err = -EFAULT; + switch (cmd) { + case PPPIOCGFLAGS: + val = ap->flags | ap->rbits; + if (put_user(ap->flags, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSFLAGS: + if (get_user(val, (int *) arg)) + break; + ap->flags = val & ~SC_RCV_BITS; + ap->rbits = val & SC_RCV_BITS; + err = 0; + break; + + case PPPIOCGASYNCMAP: + if (put_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSASYNCMAP: + if (get_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGRASYNCMAP: + if (put_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSRASYNCMAP: + if (get_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGXASYNCMAP: + if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm))) + break; + err = 0; + break; + case PPPIOCSXASYNCMAP: + if (copy_from_user(accm, (void *) arg, sizeof(accm))) + break; + accm[2] &= ~0x40000000U; /* can't escape 0x5e */ + accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ + memcpy(ap->xaccm, accm, sizeof(ap->xaccm)); + err = 0; + break; + + case PPPIOCGMRU: + if (put_user(ap->mru, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSMRU: + if (get_user(val, (int *) arg)) + break; + if (val < PPP_MRU) + val = PPP_MRU; + ap->mru = val; + err = 0; + break; + + case PPPIOCATTACH: + if (get_user(val, (int *) arg)) + break; + err = -EALREADY; + if (ap->connected) + break; + ap->chan.private = ap; + ap->chan.ops = &async_ops; + err = ppp_register_channel(&ap->chan, val); + if (err != 0) + break; + ap->connected = 1; + break; + case PPPIOCDETACH: + err = -ENXIO; + if (!ap->connected) + break; + ppp_unregister_channel(&ap->chan); + ap->connected = 0; + err = 0; + break; + + case TCGETS: + case TCGETA: + err = n_tty_ioctl(tty, file, cmd, arg); + break; + + case TCFLSH: + /* flush our buffers and the serial port's buffer */ + if (arg == TCIFLUSH || arg == TCIOFLUSH) + flush_skb_queue(&ap->rq); + if (arg == TCIOFLUSH || arg == TCOFLUSH) + ppp_async_flush_output(ap); + err = n_tty_ioctl(tty, file, cmd, arg); + break; + + case FIONREAD: + val = 0; + if ((skb = skb_peek(&ap->rq)) != 0) + val = skb->len; + if (put_user(val, (int *) arg)) + break; + err = 0; + break; + + default: + err = -ENOIOCTLCMD; + } + out: + return err; +} + +static unsigned int +ppp_async_poll(struct tty_struct *tty, struct file *file, poll_table *wait) +{ + struct asyncppp *ap = tty->disc_data; + unsigned int mask; + + if (ap == 0) + return 0; /* should never happen */ + poll_wait(file, &ap->rwait, wait); + mask = POLLOUT | POLLWRNORM; + if (skb_peek(&ap->rq)) + mask |= POLLIN | POLLRDNORM; + if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file)) + mask |= POLLHUP; + return mask; +} + +static int +ppp_async_room(struct tty_struct *tty) +{ + return 65535; +} + +static void +ppp_async_receive(struct tty_struct *tty, const unsigned char *buf, + char *flags, int count) +{ + struct asyncppp *ap = tty->disc_data; + + if (ap == 0) + return; + trylock_recv_path(ap); + ppp_async_input(ap, buf, flags, count); + unlock_recv_path(ap); + if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) + && tty->driver.unthrottle) + tty->driver.unthrottle(tty); +} + +static void +ppp_async_wakeup(struct tty_struct *tty) +{ + struct asyncppp *ap = tty->disc_data; + + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + if (ap == 0) + return; + if (ppp_async_push(ap) && ap->connected) + ppp_output_wakeup(&ap->chan); +} + + +static struct tty_ldisc ppp_ldisc = { + magic: TTY_LDISC_MAGIC, + name: "ppp", + open: ppp_async_open, + close: ppp_async_close, + read: ppp_async_read, + write: ppp_async_write, + ioctl: ppp_async_ioctl, + poll: ppp_async_poll, + receive_room: ppp_async_room, + receive_buf: ppp_async_receive, + write_wakeup: ppp_async_wakeup, +}; + +int +ppp_async_init(void) +{ + int err; + + err = tty_register_ldisc(N_PPP, &ppp_ldisc); + if (err != 0) + printk(KERN_ERR "PPP_async: error %d registering line disc.\n", + err); + return err; +} + +/* + * Procedures for encapsulation and framing. + */ + +u16 ppp_crc16_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +EXPORT_SYMBOL(ppp_crc16_table); +#define fcstab ppp_crc16_table /* for PPP_FCS macro */ + +/* + * Procedure to encode the data for async serial transmission. + * Does octet stuffing (escaping), puts the address/control bytes + * on if A/C compression is disabled, and does protocol compression. + * Assumes ap->tpkt != 0 on entry. + * Returns 1 if we finished the current frame, 0 otherwise. + */ + +#define PUT_BYTE(ap, buf, c, islcp) do { \ + if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\ + *buf++ = PPP_ESCAPE; \ + *buf++ = c ^ 0x20; \ + } else \ + *buf++ = c; \ +} while (0) + +static int +ppp_async_encode(struct asyncppp *ap) +{ + int fcs, i, count, c, proto; + unsigned char *buf, *buflim; + unsigned char *data; + int islcp; + + buf = ap->obuf; + ap->olim = buf; + ap->optr = buf; + i = ap->tpkt_pos; + data = ap->tpkt->data; + count = ap->tpkt->len; + fcs = ap->tfcs; + proto = (data[0] << 8) + data[1]; + + /* + * LCP packets with code values between 1 (configure-reqest) + * and 7 (code-reject) must be sent as though no options + * had been negotiated. + */ + islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7; + + if (i == 0) { + /* + * Start of a new packet - insert the leading FLAG + * character if necessary. + */ + if (islcp || flag_time == 0 + || jiffies - ap->last_xmit >= flag_time) + *buf++ = PPP_FLAG; + ap->last_xmit = jiffies; + fcs = PPP_INITFCS; + + /* + * Put in the address/control bytes if necessary + */ + if ((ap->flags & SC_COMP_AC) == 0 || islcp) { + PUT_BYTE(ap, buf, 0xff, islcp); + fcs = PPP_FCS(fcs, 0xff); + PUT_BYTE(ap, buf, 0x03, islcp); + fcs = PPP_FCS(fcs, 0x03); + } + } + + /* + * Once we put in the last byte, we need to put in the FCS + * and closing flag, so make sure there is at least 7 bytes + * of free space in the output buffer. + */ + buflim = ap->obuf + OBUFSIZE - 6; + while (i < count && buf < buflim) { + c = data[i++]; + if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT)) + continue; /* compress protocol field */ + fcs = PPP_FCS(fcs, c); + PUT_BYTE(ap, buf, c, islcp); + } + + if (i < count) { + /* + * Remember where we are up to in this packet. + */ + ap->olim = buf; + ap->tpkt_pos = i; + ap->tfcs = fcs; + return 0; + } + + /* + * We have finished the packet. Add the FCS and flag. + */ + fcs = ~fcs; + c = fcs & 0xff; + PUT_BYTE(ap, buf, c, islcp); + c = (fcs >> 8) & 0xff; + PUT_BYTE(ap, buf, c, islcp); + *buf++ = PPP_FLAG; + ap->olim = buf; + + kfree_skb(ap->tpkt); + ap->tpkt = 0; + return 1; +} + +/* + * Transmit-side routines. + */ + +/* + * Send a packet to the peer over an async tty line. + * Returns 1 iff the packet was accepted. + * If the packet was not accepted, we will call ppp_output_wakeup + * at some later time. + */ +static int +ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb) +{ + struct asyncppp *ap = chan->private; + + ppp_async_push(ap); + + if (test_and_set_bit(XMIT_FULL, &ap->busy)) + return 0; /* already full */ + ap->tpkt = skb; + ap->tpkt_pos = 0; + + ppp_async_push(ap); + return 1; +} + +/* + * Push as much data as possible out to the tty. + */ +static int +ppp_async_push(struct asyncppp *ap) +{ + int avail, sent, done = 0; + struct tty_struct *tty = ap->tty; + int tty_stuffed = 0; + + if (!trylock_xmit_path(ap)) { + set_bit(XMIT_WAKEUP, &ap->busy); + return 0; + } + for (;;) { + if (test_and_clear_bit(XMIT_WAKEUP, &ap->busy)) + tty_stuffed = 0; + if (!tty_stuffed && ap->optr < ap->olim) { + avail = ap->olim - ap->optr; + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + sent = tty->driver.write(tty, 0, ap->optr, avail); + if (sent < 0) + goto flush; /* error, e.g. loss of CD */ + ap->optr += sent; + if (sent < avail) + tty_stuffed = 1; + continue; + } + if (ap->optr == ap->olim && ap->tpkt != 0) { + if (ppp_async_encode(ap)) { + /* finished processing ap->tpkt */ + struct sk_buff *skb = skb_dequeue(&ap->xq); + if (skb != 0) { + ap->tpkt = skb; + } else { + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + } + continue; + } + /* haven't made any progress */ + unlock_xmit_path(ap); + if (!(test_bit(XMIT_WAKEUP, &ap->busy) + || (!tty_stuffed && ap->tpkt != 0))) + break; + if (!trylock_xmit_path(ap)) + break; + } + return done; + +flush: + if (ap->tpkt != 0) { + kfree_skb(ap->tpkt); + ap->tpkt = 0; + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + ap->optr = ap->olim; + unlock_xmit_path(ap); + return done; +} + +/* + * Flush output from our internal buffers. + * Called for the TCFLSH ioctl. + */ +static void +ppp_async_flush_output(struct asyncppp *ap) +{ + int done = 0; + + flush_skb_queue(&ap->xq); + lock_xmit_path(ap); + ap->optr = ap->olim; + if (ap->tpkt != NULL) { + kfree_skb(ap->tpkt); + ap->tpkt = 0; + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + unlock_xmit_path(ap); + if (done && ap->connected) + ppp_output_wakeup(&ap->chan); +} + +/* + * Receive-side routines. + */ + +/* see how many ordinary chars there are at the start of buf */ +static inline int +scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count) +{ + int i, c; + + for (i = 0; i < count; ++i) { + c = buf[i]; + if (c == PPP_ESCAPE || c == PPP_FLAG + || (c < 0x20 && (ap->raccm & (1 << c)) != 0)) + break; + } + return i; +} + +/* called when a flag is seen - do end-of-packet processing */ +static inline void +process_input_packet(struct asyncppp *ap) +{ + struct sk_buff *skb; + unsigned char *p; + unsigned int len, fcs; + int code = 0; + + skb = ap->rpkt; + ap->rpkt = 0; + if ((ap->state & (SC_TOSS | SC_ESCAPE)) || skb == 0) { + ap->state &= ~(SC_TOSS | SC_ESCAPE); + if (skb != 0) + kfree_skb(skb); + return; + } + + /* check the FCS */ + p = skb->data; + len = skb->len; + if (len < 3) + goto err; /* too short */ + fcs = PPP_INITFCS; + for (; len > 0; --len) + fcs = PPP_FCS(fcs, *p++); + if (fcs != PPP_GOODFCS) + goto err; /* bad FCS */ + skb_trim(skb, skb->len - 2); + + /* check for address/control and protocol compression */ + p = skb->data; + if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { + /* chop off address/control */ + if (skb->len < 3) + goto err; + p = skb_pull(skb, 2); + } + if (p[0] & 1) { + /* protocol is compressed */ + skb_push(skb, 1)[0] = 0; + } else if (skb->len < 2) + goto err; + + /* all OK, give it to the generic layer or queue it */ + if (ap->connected) { + ppp_input(&ap->chan, skb); + } else { + skb_queue_tail(&ap->rq, skb); + /* drop old frames if queue too long */ + while (ap->rq.qlen > PPPASYNC_MAX_RQLEN + && (skb = skb_dequeue(&ap->rq)) != 0) + kfree(skb); + wake_up_interruptible(&ap->rwait); + } + return; + + err: + kfree_skb(skb); + if (ap->connected) + ppp_input_error(&ap->chan, code); +} + +static inline void +input_error(struct asyncppp *ap, int code) +{ + ap->state |= SC_TOSS; + if (ap->connected) + ppp_input_error(&ap->chan, code); +} + +/* called when the tty driver has data for us. */ +static void +ppp_async_input(struct asyncppp *ap, const unsigned char *buf, + char *flags, int count) +{ + struct sk_buff *skb; + int c, i, j, n, s, f; + unsigned char *sp; + + /* update bits used for 8-bit cleanness detection */ + if (~ap->rbits & SC_RCV_BITS) { + s = 0; + for (i = 0; i < count; ++i) { + c = buf[i]; + if (flags != 0 && flags[i] != 0) + continue; + s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0; + c = ((c >> 4) ^ c) & 0xf; + s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP; + } + ap->rbits |= s; + } + + while (count > 0) { + /* scan through and see how many chars we can do in bulk */ + if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE) + n = 1; + else + n = scan_ordinary(ap, buf, count); + + f = 0; + if (flags != 0 && (ap->state & SC_TOSS) == 0) { + /* check the flags to see if any char had an error */ + for (j = 0; j < n; ++j) + if ((f = flags[j]) != 0) + break; + } + if (f != 0) { + /* start tossing */ + input_error(ap, f); + + } else if (n > 0 && (ap->state & SC_TOSS) == 0) { + /* stuff the chars in the skb */ + skb = ap->rpkt; + if (skb == 0) { + skb = alloc_skb(ap->mru + PPP_HDRLEN + 2, + GFP_ATOMIC); + if (skb == 0) + goto nomem; + /* Try to get the payload 4-byte aligned */ + if (buf[0] != PPP_ALLSTATIONS) + skb_reserve(skb, 2 + (buf[0] & 1)); + ap->rpkt = skb; + } + if (n > skb_tailroom(skb)) { + /* packet overflowed MRU */ + input_error(ap, 1); + } else { + sp = skb_put(skb, n); + memcpy(sp, buf, n); + if (ap->state & SC_ESCAPE) { + sp[0] ^= 0x20; + ap->state &= ~SC_ESCAPE; + } + } + } + + if (n >= count) + break; + + c = buf[n]; + if (c == PPP_FLAG) { + process_input_packet(ap); + } else if (c == PPP_ESCAPE) { + ap->state |= SC_ESCAPE; + } + /* otherwise it's a char in the recv ACCM */ + ++n; + + buf += n; + if (flags != 0) + flags += n; + count -= n; + } + return; + + nomem: + printk(KERN_ERR "PPPasync: no memory (input pkt)\n"); + input_error(ap, 0); +} + +#ifdef MODULE +int +init_module(void) +{ + return ppp_async_init(); +} + +void +cleanup_module(void) +{ + if (tty_register_ldisc(N_PPP, NULL) != 0) + printk(KERN_ERR "failed to unregister PPP line discipline\n"); +} +#endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c --- v2.3.12/linux/drivers/net/ppp_generic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/ppp_generic.c Fri Aug 6 10:44:11 1999 @@ -0,0 +1,1576 @@ +/* + * Generic PPP layer for Linux. + * + * Copyright 1999 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * The generic PPP layer handles the PPP network interfaces, the + * /dev/ppp device, packet and VJ compression, and multilink. + * It talks to PPP `channels' via the interface defined in + * include/linux/ppp_channel.h. Channels provide the basic means for + * sending and receiving PPP frames on some kind of communications + * channel. + * + * Part of the code in this driver was inspired by the old async-only + * PPP driver, written by Michael Callahan and Al Longyear, and + * subsequently hacked by Paul Mackerras. + * + * ==FILEVERSION 990806== + */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPP_VERSION "2.4.0" + +EXPORT_SYMBOL(ppp_register_channel); +EXPORT_SYMBOL(ppp_unregister_channel); +EXPORT_SYMBOL(ppp_input); +EXPORT_SYMBOL(ppp_input_error); +EXPORT_SYMBOL(ppp_output_wakeup); +EXPORT_SYMBOL(ppp_register_compressor); +EXPORT_SYMBOL(ppp_unregister_compressor); + +/* + * Network protocols we support. + */ +#define NP_IP 0 /* Internet Protocol V4 */ +#define NP_IPV6 1 /* Internet Protocol V6 */ +#define NP_IPX 2 /* IPX protocol */ +#define NP_AT 3 /* Appletalk protocol */ +#define NUM_NP 4 /* Number of NPs. */ + +/* + * Data structure describing one ppp unit. + * A ppp unit corresponds to a ppp network interface device + * and represents a multilink bundle. + * It may have 0 or more ppp channels connected to it. + */ +struct ppp { + struct list_head list; /* link in list of ppp units */ + int index; /* interface unit number */ + char name[16]; /* unit name */ + int refcnt; /* # open /dev/ppp attached */ + unsigned long busy; /* lock and other bits */ + struct list_head channels; /* list of attached channels */ + int n_channels; /* how many channels are attached */ + int mru; /* max receive unit */ + unsigned int flags; /* control bits */ + unsigned int xstate; /* transmit state bits */ + unsigned int rstate; /* receive state bits */ + int debug; /* debug flags */ + struct slcompress *vj; /* state for VJ header compression */ + struct sk_buff_head xq; /* pppd transmit queue */ + struct sk_buff_head rq; /* receive queue for pppd */ + wait_queue_head_t rwait; /* for poll on reading /dev/ppp */ + enum NPmode npmode[NUM_NP]; /* what to do with each net proto */ + struct sk_buff *xmit_pending; /* a packet ready to go out */ + struct sk_buff_head recv_pending;/* pending input packets */ + struct compressor *xcomp; /* transmit packet compressor */ + void *xc_state; /* its internal state */ + struct compressor *rcomp; /* receive decompressor */ + void *rc_state; /* its internal state */ + unsigned long last_xmit; /* jiffies when last pkt sent */ + unsigned long last_recv; /* jiffies when last pkt rcvd */ + struct device dev; /* network interface device */ + struct net_device_stats stats; /* statistics */ +}; + +static LIST_HEAD(all_ppp_units); +static spinlock_t all_ppp_lock = SPIN_LOCK_UNLOCKED; + +/* + * Private data structure for each channel. + * Ultimately this will have multilink stuff etc. in it. + */ +struct channel { + struct list_head list; /* link in list of channels per unit */ + struct ppp_channel *chan; /* public channel data structure */ + int blocked; /* if channel refused last packet */ + struct ppp *ppp; /* ppp unit we're connected to */ +}; + +/* Bit numbers in busy */ +#define XMIT_BUSY 0 +#define RECV_BUSY 1 +#define XMIT_WAKEUP 2 + +/* + * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC. + * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. + * Bits in xstate: SC_COMP_RUN + */ +#define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC) + +/* Get the PPP protocol number from a skb */ +#define PPP_PROTO(skb) (((skb)->data[0] << 8) + (skb)->data[1]) + +/* We limit the length of ppp->rq to this (arbitrary) value */ +#define PPP_MAX_RQLEN 32 + +/* Prototypes. */ +static void ppp_xmit_unlock(struct ppp *ppp); +static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); +static void ppp_push(struct ppp *ppp); +static void ppp_recv_unlock(struct ppp *ppp); +static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb); +static struct sk_buff *ppp_decompress_frame(struct ppp *ppp, + struct sk_buff *skb); +static int ppp_set_compress(struct ppp *ppp, unsigned long arg); +static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound); +static void ppp_ccp_closed(struct ppp *ppp); +static struct compressor *find_compressor(int type); +static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st); +static struct ppp *ppp_create_unit(int unit, int *retp); +static struct ppp *ppp_find_unit(int unit); + +/* Translates a PPP protocol number to a NP index (NP == network protocol) */ +static inline int proto_to_npindex(int proto) +{ + switch (proto) { + case PPP_IP: + return NP_IP; + case PPP_IPV6: + return NP_IPV6; + case PPP_IPX: + return NP_IPX; + case PPP_AT: + return NP_AT; + } + return -EINVAL; +} + +/* Translates an NP index into a PPP protocol number */ +static const int npindex_to_proto[NUM_NP] = { + PPP_IP, + PPP_IPV6, + PPP_IPX, + PPP_AT, +}; + +/* Translates an ethertype into an NP index */ +static inline int ethertype_to_npindex(int ethertype) +{ + switch (ethertype) { + case ETH_P_IP: + return NP_IP; + case ETH_P_IPV6: + return NP_IPV6; + case ETH_P_IPX: + return NP_IPX; + case ETH_P_PPPTALK: + case ETH_P_ATALK: + return NP_AT; + } + return -1; +} + +/* Translates an NP index into an ethertype */ +static const int npindex_to_ethertype[NUM_NP] = { + ETH_P_IP, + ETH_P_IPV6, + ETH_P_IPX, + ETH_P_PPPTALK, +}; + +/* + * Routines for locking and unlocking the transmit and receive paths + * of each unit. + */ +static inline void +lock_path(struct ppp *ppp, int bit) +{ + int timeout = 1000000; + + do { + while (test_bit(bit, &ppp->busy)) { + mb(); + if (--timeout == 0) { + printk(KERN_ERR "lock_path timeout ppp=%p bit=%x\n", ppp, bit); + return; + } + } + } while (test_and_set_bit(bit, &ppp->busy)); + mb(); +} + +static inline int +trylock_path(struct ppp *ppp, int bit) +{ + if (test_and_set_bit(bit, &ppp->busy)) + return 0; + mb(); + return 1; +} + +static inline void +unlock_path(struct ppp *ppp, int bit) +{ + mb(); + clear_bit(bit, &ppp->busy); +} + +#define lock_xmit_path(ppp) lock_path(ppp, XMIT_BUSY) +#define trylock_xmit_path(ppp) trylock_path(ppp, XMIT_BUSY) +#define unlock_xmit_path(ppp) unlock_path(ppp, XMIT_BUSY) +#define lock_recv_path(ppp) lock_path(ppp, RECV_BUSY) +#define trylock_recv_path(ppp) trylock_path(ppp, RECV_BUSY) +#define unlock_recv_path(ppp) unlock_path(ppp, RECV_BUSY) + +static inline void +free_skbs(struct sk_buff_head *head) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(head)) != 0) + kfree_skb(skb); +} + +/* + * /dev/ppp device routines. + * The /dev/ppp device is used by pppd to control the ppp unit. + * It supports the read, write, ioctl and poll functions. + */ +static int ppp_open(struct inode *inode, struct file *file) +{ + /* + * This could (should?) be enforced by the permissions on /dev/ppp. + */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + MOD_INC_USE_COUNT; + return 0; +} + +static int ppp_release(struct inode *inode, struct file *file) +{ + struct ppp *ppp = (struct ppp *) file->private_data; + struct list_head *list, *next; + int ref; + + if (ppp == 0) + goto out; + file->private_data = 0; + spin_lock(&all_ppp_lock); + ref = --ppp->refcnt; + if (ref == 0) + list_del(&ppp->list); + spin_unlock(&all_ppp_lock); + if (ref != 0) + goto out; + + /* Last fd open to this ppp unit is being closed - + mark the interface down, free the ppp unit */ + rtnl_lock(); + dev_close(&ppp->dev); + rtnl_unlock(); + for (list = ppp->channels.next; list != &ppp->channels; list = next) { + /* forcibly detach this channel */ + struct channel *chan; + chan = list_entry(list, struct channel, list); + chan->chan->ppp = 0; + next = list->next; + kfree(chan); + } + + /* Free up resources. */ + ppp_ccp_closed(ppp); + lock_xmit_path(ppp); + lock_recv_path(ppp); + if (ppp->vj) { + slhc_free(ppp->vj); + ppp->vj = 0; + } + free_skbs(&ppp->xq); + free_skbs(&ppp->rq); + free_skbs(&ppp->recv_pending); + unregister_netdev(&ppp->dev); + kfree(ppp); + + out: + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t ppp_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct ppp *ppp = (struct ppp *) file->private_data; + DECLARE_WAITQUEUE(wait, current); + ssize_t ret; + struct sk_buff *skb = 0; + + ret = -ENXIO; + if (ppp == 0) + goto out; /* not currently attached */ + + add_wait_queue(&ppp->rwait, &wait); + current->state = TASK_INTERRUPTIBLE; + for (;;) { + ret = -EAGAIN; + skb = skb_dequeue(&ppp->rq); + if (skb) + break; + if (file->f_flags & O_NONBLOCK) + break; + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&ppp->rwait, &wait); + + if (skb == 0) + goto out; + + ret = -EOVERFLOW; + if (skb->len > count) + goto outf; + ret = -EFAULT; + if (copy_to_user(buf, skb->data, skb->len)) + goto outf; + ret = skb->len; + + outf: + kfree_skb(skb); + out: + return ret; +} + +static ssize_t ppp_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct ppp *ppp = (struct ppp *) file->private_data; + struct sk_buff *skb; + ssize_t ret; + + ret = -ENXIO; + if (ppp == 0) + goto out; + + ret = -ENOMEM; + skb = alloc_skb(count + 2, GFP_KERNEL); + if (skb == 0) + goto out; + skb_reserve(skb, 2); + ret = -EFAULT; + if (copy_from_user(skb_put(skb, count), buf, count)) { + kfree_skb(skb); + goto out; + } + + skb_queue_tail(&ppp->xq, skb); + if (trylock_xmit_path(ppp)) + ppp_xmit_unlock(ppp); + + ret = count; + + out: + return ret; +} + +static unsigned int ppp_poll(struct file *file, poll_table *wait) +{ + struct ppp *ppp = (struct ppp *) file->private_data; + unsigned int mask; + + if (ppp == 0) + return 0; + poll_wait(file, &ppp->rwait, wait); + mask = POLLOUT | POLLWRNORM; + if (skb_peek(&ppp->rq) != 0) + mask |= POLLIN | POLLRDNORM; + return mask; +} + +static int ppp_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct ppp *ppp = (struct ppp *) file->private_data; + int err, val, val2, i; + struct ppp_idle idle; + struct npioctl npi; + + if (cmd == PPPIOCNEWUNIT) { + /* Create a new ppp unit */ + int unit, ret; + + if (ppp != 0) + return -EINVAL; + if (get_user(unit, (int *) arg)) + return -EFAULT; + ppp = ppp_create_unit(unit, &ret); + if (ppp == 0) + return ret; + file->private_data = ppp; + if (put_user(ppp->index, (int *) arg)) + return -EFAULT; + return 0; + } + if (cmd == PPPIOCATTACH) { + /* Attach to an existing ppp unit */ + int unit; + + if (ppp != 0) + return -EINVAL; + if (get_user(unit, (int *) arg)) + return -EFAULT; + spin_lock(&all_ppp_lock); + ppp = ppp_find_unit(unit); + if (ppp != 0) + ++ppp->refcnt; + spin_unlock(&all_ppp_lock); + if (ppp == 0) + return -ENXIO; + file->private_data = ppp; + return 0; + } + + if (ppp == 0) + return -ENXIO; + err = -EFAULT; + switch (cmd) { + case PPPIOCSMRU: + if (get_user(val, (int *) arg)) + break; + ppp->mru = val; + err = 0; + break; + + case PPPIOCSFLAGS: + if (get_user(val, (int *) arg)) + break; + if (ppp->flags & ~val & SC_CCP_OPEN) + ppp_ccp_closed(ppp); + ppp->flags = val & SC_FLAG_BITS; + err = 0; + break; + + case PPPIOCGFLAGS: + val = ppp->flags | ppp->xstate | ppp->rstate; + if (put_user(val, (int *) arg)) + break; + err = 0; + break; + + case PPPIOCSCOMPRESS: + err = ppp_set_compress(ppp, arg); + break; + + case PPPIOCGUNIT: + if (put_user(ppp->index, (int *) arg)) + break; + err = 0; + break; + + case PPPIOCSDEBUG: + if (get_user(val, (int *) arg)) + break; + ppp->debug = val; + err = 0; + break; + + case PPPIOCGDEBUG: + if (put_user(ppp->debug, (int *) arg)) + break; + err = 0; + break; + + case PPPIOCGIDLE: + idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; + idle.recv_idle = (jiffies - ppp->last_recv) / HZ; + if (copy_to_user((void *) arg, &idle, sizeof(idle))) + break; + err = 0; + break; + + case PPPIOCSMAXCID: + if (get_user(val, (int *) arg)) + break; + val2 = 15; + if ((val >> 16) != 0) { + val2 = val >> 16; + val &= 0xffff; + } + lock_xmit_path(ppp); + lock_recv_path(ppp); + if (ppp->vj != 0) + slhc_free(ppp->vj); + ppp->vj = slhc_init(val2+1, val+1); + ppp_recv_unlock(ppp); + ppp_xmit_unlock(ppp); + err = -ENOMEM; + if (ppp->vj == 0) { + printk(KERN_ERR "PPP: no memory (VJ compressor)\n"); + break; + } + err = 0; + break; + + case PPPIOCGNPMODE: + case PPPIOCSNPMODE: + if (copy_from_user(&npi, (void *) arg, sizeof(npi))) + break; + err = proto_to_npindex(npi.protocol); + if (err < 0) + break; + i = err; + if (cmd == PPPIOCGNPMODE) { + err = -EFAULT; + npi.mode = ppp->npmode[i]; + if (copy_to_user((void *) arg, &npi, sizeof(npi))) + break; + } else { + ppp->npmode[i] = npi.mode; + /* we may be able to transmit more packets now (??) */ + mark_bh(NET_BH); + } + err = 0; + break; + + default: + err = -ENOTTY; + } + return err; +} + +static struct file_operations ppp_device_fops = { + NULL, /* seek */ + ppp_read, + ppp_write, + NULL, /* readdir */ + ppp_poll, + ppp_ioctl, + NULL, /* mmap */ + ppp_open, + NULL, /* flush */ + ppp_release +}; + +#define PPP_MAJOR 108 + +/* Called at boot time if ppp is compiled into the kernel, + or at module load time (from init_module) if compiled as a module. */ +int +ppp_init(struct device *dev) +{ + int err; +#ifndef MODULE + extern struct compressor ppp_deflate, ppp_deflate_draft; + extern int ppp_async_init(void); +#endif + + printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); + err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); + if (err) + printk(KERN_ERR "failed to register PPP device (%d)\n", err); +#ifndef MODULE +#ifdef CONFIG_PPP_ASYNC + ppp_async_init(); +#endif +#ifdef CONFIG_PPP_DEFLATE + if (ppp_register_compressor(&ppp_deflate) == 0) + printk(KERN_INFO "PPP Deflate compression module registered\n"); + ppp_register_compressor(&ppp_deflate_draft); +#endif +#endif /* MODULE */ + + return -ENODEV; +} + +/* + * Network interface unit routines. + */ +static int +ppp_start_xmit(struct sk_buff *skb, struct device *dev) +{ + struct ppp *ppp = (struct ppp *) dev->priv; + int npi, proto; + unsigned char *pp; + + if (skb == 0) + return 0; + /* can skb->data ever be 0? */ + + npi = ethertype_to_npindex(ntohs(skb->protocol)); + if (npi < 0) + goto outf; + + /* Drop, accept or reject the packet */ + switch (ppp->npmode[npi]) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: + /* it would be nice to have a way to tell the network + system to queue this one up for later. */ + goto outf; + case NPMODE_DROP: + case NPMODE_ERROR: + goto outf; + } + + /* The transmit side of the ppp interface is serialized by + the XMIT_BUSY bit in ppp->busy. */ + if (!trylock_xmit_path(ppp)) { + dev->tbusy = 1; + return 1; + } + if (ppp->xmit_pending) + ppp_push(ppp); + if (ppp->xmit_pending) { + dev->tbusy = 1; + ppp_xmit_unlock(ppp); + return 1; + } + dev->tbusy = 0; + + /* Put the 2-byte PPP protocol number on the front, + making sure there is room for the address and control fields. */ + if (skb_headroom(skb) < PPP_HDRLEN) { + struct sk_buff *ns; + + ns = alloc_skb(skb->len + PPP_HDRLEN, GFP_ATOMIC); + if (ns == 0) + goto outnbusy; + skb_reserve(ns, PPP_HDRLEN); + memcpy(skb_put(ns, skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = ns; + } + pp = skb_push(skb, 2); + proto = npindex_to_proto[npi]; + pp[0] = proto >> 8; + pp[1] = proto; + + ppp_send_frame(ppp, skb); + ppp_xmit_unlock(ppp); + return 0; + + outnbusy: + ppp_xmit_unlock(ppp); + + outf: + kfree_skb(skb); + return 0; +} + +static struct net_device_stats * +ppp_net_stats(struct device *dev) +{ + struct ppp *ppp = (struct ppp *) dev->priv; + + return &ppp->stats; +} + +static int +ppp_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct ppp *ppp = dev->priv; + int err = -EFAULT; + void *addr = (void *) ifr->ifr_ifru.ifru_data; + struct ppp_stats stats; + struct ppp_comp_stats cstats; + char *vers; + + switch (cmd) { + case SIOCGPPPSTATS: + ppp_get_stats(ppp, &stats); + if (copy_to_user(addr, &stats, sizeof(stats))) + break; + err = 0; + break; + + case SIOCGPPPCSTATS: + memset(&cstats, 0, sizeof(cstats)); + if (ppp->xc_state != 0) + ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c); + if (ppp->rc_state != 0) + ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d); + if (copy_to_user(addr, &cstats, sizeof(cstats))) + break; + err = 0; + break; + + case SIOCGPPPVER: + vers = PPP_VERSION; + if (copy_to_user(addr, vers, strlen(vers) + 1)) + break; + err = 0; + break; + + default: + err = -EINVAL; + } + + return err; +} + +int +ppp_net_init(struct device *dev) +{ + dev->hard_header_len = PPP_HDRLEN; + dev->mtu = PPP_MTU; + dev->hard_start_xmit = ppp_start_xmit; + dev->get_stats = ppp_net_stats; + dev->do_ioctl = ppp_net_ioctl; + dev->addr_len = 0; + dev->tx_queue_len = 3; + dev->type = ARPHRD_PPP; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + + dev_init_buffers(dev); + return 0; +} + +/* + * Transmit-side routines. + */ + +/* + * Called to unlock the transmit side of the ppp unit, + * making sure that any work queued up gets done. + */ +static void +ppp_xmit_unlock(struct ppp *ppp) +{ + struct sk_buff *skb; + + for (;;) { + if (test_and_clear_bit(XMIT_WAKEUP, &ppp->busy)) + ppp_push(ppp); + while (ppp->xmit_pending == 0 + && (skb = skb_dequeue(&ppp->xq)) != 0) + ppp_send_frame(ppp, skb); + unlock_xmit_path(ppp); + if (!(test_bit(XMIT_WAKEUP, &ppp->busy) + || (ppp->xmit_pending == 0 && skb_peek(&ppp->xq)))) + break; + if (!trylock_xmit_path(ppp)) + break; + } +} + +/* + * Compress and send a frame. + * The caller should have locked the xmit path, + * and xmit_pending should be 0. + */ +static void +ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) +{ + int proto = PPP_PROTO(skb); + struct sk_buff *new_skb; + int len; + unsigned char *cp; + + ++ppp->stats.tx_packets; + ppp->stats.tx_bytes += skb->len - 2; + + switch (proto) { + case PPP_IP: + if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0) + break; + /* try to do VJ TCP header compression */ + new_skb = alloc_skb(skb->len + 2, GFP_ATOMIC); + if (new_skb == 0) { + printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n"); + goto drop; + } + skb_reserve(new_skb, 2); + cp = skb->data + 2; + len = slhc_compress(ppp->vj, cp, skb->len - 2, + new_skb->data + 2, &cp, + !(ppp->flags & SC_NO_TCP_CCID)); + if (cp == skb->data + 2) { + /* didn't compress */ + kfree_skb(new_skb); + } else { + if (cp[0] & SL_TYPE_COMPRESSED_TCP) { + proto = PPP_VJC_COMP; + cp[0] &= ~SL_TYPE_COMPRESSED_TCP; + } else { + proto = PPP_VJC_UNCOMP; + cp[0] = skb->data[2]; + } + kfree_skb(skb); + skb = new_skb; + cp = skb_put(skb, len + 2); + cp[0] = 0; + cp[1] = proto; + } + break; + + case PPP_CCP: + /* peek at outbound CCP frames */ + ppp_ccp_peek(ppp, skb, 0); + break; + } + + /* try to do packet compression */ + if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 + && proto != PPP_LCP && proto != PPP_CCP) { + new_skb = alloc_skb(ppp->dev.mtu + PPP_HDRLEN, GFP_ATOMIC); + if (new_skb == 0) { + printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + goto drop; + } + + /* compressor still expects A/C bytes in hdr */ + len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, + new_skb->data, skb->len + 2, + ppp->dev.mtu + PPP_HDRLEN); + if (len > 0 && (ppp->flags & SC_CCP_UP)) { + kfree_skb(skb); + skb = new_skb; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off A/C bytes */ + } else { + /* didn't compress, or CCP not up yet */ + kfree_skb(new_skb); + } + } + + /* + * If we are waiting for traffic (demand dialling), + * queue it up for pppd to receive. + */ + if (ppp->flags & SC_LOOP_TRAFFIC) { + if (ppp->rq.qlen > PPP_MAX_RQLEN) + goto drop; + skb_queue_tail(&ppp->rq, skb); + wake_up_interruptible(&ppp->rwait); + return; + } + + ppp->xmit_pending = skb; + ppp_push(ppp); + return; + + drop: + kfree_skb(skb); + ++ppp->stats.tx_errors; +} + +/* + * Try to send the frame in xmit_pending. + * The caller should have the xmit path locked. + */ +static void +ppp_push(struct ppp *ppp) +{ + struct list_head *list; + struct channel *chan; + struct sk_buff *skb = ppp->xmit_pending; + + if (skb == 0) + return; + + list = &ppp->channels; + if (list_empty(list)) { + /* nowhere to send the packet, just drop it */ + ppp->xmit_pending = 0; + kfree_skb(skb); + return; + } + + /* If we are doing multilink, decide which channel gets the + packet, and/or fragment the packet over several links. */ + /* XXX for now, just take the first channel */ + list = list->next; + chan = list_entry(list, struct channel, list); + + if (chan->chan->ops->start_xmit(chan->chan, skb)) { + ppp->xmit_pending = 0; + chan->blocked = 0; + } else + chan->blocked = 1; +} + +/* + * Receive-side routines. + */ +static inline void +ppp_do_recv(struct ppp *ppp, struct sk_buff *skb) +{ + skb_queue_tail(&ppp->recv_pending, skb); + if (trylock_recv_path(ppp)) + ppp_recv_unlock(ppp); +} + +void +ppp_input(struct ppp_channel *chan, struct sk_buff *skb) +{ + struct channel *pch = chan->ppp; + + if (pch == 0 || skb->len == 0) { + kfree_skb(skb); + return; + } + ppp_do_recv(pch->ppp, skb); +} + +/* Put a 0-length skb in the receive queue as an error indication */ +void +ppp_input_error(struct ppp_channel *chan, int code) +{ + struct channel *pch = chan->ppp; + struct sk_buff *skb; + + if (pch == 0) + return; + skb = alloc_skb(0, GFP_ATOMIC); + if (skb == 0) + return; + skb->len = 0; /* probably unnecessary */ + skb->cb[0] = code; + ppp_do_recv(pch->ppp, skb); +} + +static void +ppp_recv_unlock(struct ppp *ppp) +{ + struct sk_buff *skb; + + for (;;) { + while ((skb = skb_dequeue(&ppp->recv_pending)) != 0) + ppp_receive_frame(ppp, skb); + unlock_recv_path(ppp); + if (skb_peek(&ppp->recv_pending) == 0) + break; + if (!trylock_recv_path(ppp)) + break; + } +} + +static void +ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb) +{ + struct sk_buff *ns; + int proto, len, npi; + + if (skb->len == 0) { + /* XXX should do something with code in skb->cb[0] */ + goto err; /* error indication */ + } + + if (skb->len < 2) { + ++ppp->stats.rx_length_errors; + goto err; + } + + /* Decompress the frame, if compressed. */ + if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN) + && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) + skb = ppp_decompress_frame(ppp, skb); + + proto = PPP_PROTO(skb); + switch (proto) { + case PPP_VJC_COMP: + /* decompress VJ compressed packets */ + if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + goto err; + if (skb_tailroom(skb) < 124) { + /* copy to a new sk_buff with more tailroom */ + ns = alloc_skb(skb->len + 128, GFP_ATOMIC); + if (ns == 0) { + printk(KERN_ERR"PPP: no memory (VJ decomp)\n"); + goto err; + } + skb_reserve(ns, 2); + memcpy(skb_put(ns, skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = ns; + } + len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); + if (len <= 0) { + printk(KERN_ERR "PPP: VJ decompression error\n"); + goto err; + } + len += 2; + if (len > skb->len) + skb_put(skb, len - skb->len); + else if (len < skb->len) + skb_trim(skb, len); + proto = PPP_IP; + break; + + case PPP_VJC_UNCOMP: + if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + goto err; + if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) { + printk(KERN_ERR "PPP: VJ uncompressed error\n"); + goto err; + } + proto = PPP_IP; + break; + + case PPP_CCP: + ppp_ccp_peek(ppp, skb, 1); + break; + } + + ++ppp->stats.rx_packets; + ppp->stats.rx_bytes += skb->len - 2; + + npi = proto_to_npindex(proto); + if (npi < 0) { + /* control or unknown frame - pass it to pppd */ + skb_queue_tail(&ppp->rq, skb); + /* limit queue length by dropping old frames */ + while (ppp->rq.qlen > PPP_MAX_RQLEN) { + skb = skb_dequeue(&ppp->rq); + if (skb) + kfree_skb(skb); + } + /* wake up any process polling or blocking on read */ + wake_up_interruptible(&ppp->rwait); + + } else { + /* network protocol frame - give it to the kernel */ + ppp->last_recv = jiffies; + if ((ppp->dev.flags & IFF_UP) == 0 + || ppp->npmode[npi] != NPMODE_PASS) { + kfree_skb(skb); + } else { + skb_pull(skb, 2); /* chop off protocol */ + skb->dev = &ppp->dev; + skb->protocol = htons(npindex_to_ethertype[npi]); + skb->mac.raw = skb->data; + netif_rx(skb); + } + } + return; + + err: + ++ppp->stats.rx_errors; + if (ppp->vj != 0) + slhc_toss(ppp->vj); + kfree_skb(skb); +} + +static struct sk_buff * +ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) +{ + int proto = PPP_PROTO(skb); + struct sk_buff *ns; + int len; + + if (proto == PPP_COMP) { + ns = alloc_skb(ppp->mru + PPP_HDRLEN, GFP_ATOMIC); + if (ns == 0) { + printk(KERN_ERR "ppp_receive: no memory\n"); + goto err; + } + /* the decompressor still expects the A/C bytes in the hdr */ + len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2, + skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN); + if (len < 0) { + /* Pass the compressed frame to pppd as an + error indication. */ + if (len == DECOMP_FATALERROR) + ppp->rstate |= SC_DC_FERROR; + goto err; + } + + kfree_skb(skb); + skb = ns; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off the A/C bytes */ + + } else { + /* Uncompressed frame - pass to decompressor so it + can update its dictionary if necessary. */ + if (ppp->rcomp->incomp) + ppp->rcomp->incomp(ppp->rc_state, skb->data - 2, + skb->len + 2); + } + + return skb; + + err: + ppp->rstate |= SC_DC_ERROR; + if (ppp->vj != 0) + slhc_toss(ppp->vj); + ++ppp->stats.rx_errors; + return skb; +} + +/* + * Channel interface. + */ + +/* + * Connect a channel to a given PPP unit. + * The channel MUST NOT be connected to a PPP unit already. + */ +int +ppp_register_channel(struct ppp_channel *chan, int unit) +{ + struct ppp *ppp; + struct channel *pch; + int ret = -ENXIO; + + spin_lock(&all_ppp_lock); + ppp = ppp_find_unit(unit); + if (ppp == 0) + goto out; + pch = kmalloc(sizeof(struct channel), GFP_ATOMIC); + ret = -ENOMEM; + if (pch == 0) + goto out; + memset(pch, 0, sizeof(struct channel)); + pch->ppp = ppp; + pch->chan = chan; + list_add(&pch->list, &ppp->channels); + chan->ppp = pch; + ++ppp->n_channels; + ret = 0; + out: + spin_unlock(&all_ppp_lock); + return ret; +} + +/* + * Disconnect a channel from its PPP unit. + */ +void +ppp_unregister_channel(struct ppp_channel *chan) +{ + struct channel *pch; + + spin_lock(&all_ppp_lock); + if ((pch = chan->ppp) != 0) { + chan->ppp = 0; + list_del(&pch->list); + --pch->ppp->n_channels; + kfree(pch); + } + spin_unlock(&all_ppp_lock); +} + +/* + * Callback from a channel when it can accept more to transmit. + * This should ideally be called at BH level, not interrupt level. + */ +void +ppp_output_wakeup(struct ppp_channel *chan) +{ + struct channel *pch = chan->ppp; + struct ppp *ppp; + + if (pch == 0) + return; + ppp = pch->ppp; + pch->blocked = 0; + set_bit(XMIT_WAKEUP, &ppp->busy); + if (trylock_xmit_path(ppp)) + ppp_xmit_unlock(ppp); + if (ppp->xmit_pending == 0) { + ppp->dev.tbusy = 0; + mark_bh(NET_BH); + } +} + +/* + * Compression control. + */ + +/* Process the PPPIOCSCOMPRESS ioctl. */ +static int +ppp_set_compress(struct ppp *ppp, unsigned long arg) +{ + int err; + struct compressor *cp; + struct ppp_option_data data; + unsigned char ccp_option[CCP_MAX_OPTION_LENGTH]; +#ifdef CONFIG_KMOD + char modname[32]; +#endif + + err = -EFAULT; + if (copy_from_user(&data, (void *) arg, sizeof(data)) + || (data.length <= CCP_MAX_OPTION_LENGTH + && copy_from_user(ccp_option, data.ptr, data.length))) + goto out; + err = -EINVAL; + if (data.length > CCP_MAX_OPTION_LENGTH + || ccp_option[1] < 2 || ccp_option[1] > data.length) + goto out; + + cp = find_compressor(ccp_option[0]); +#ifdef CONFIG_KMOD + if (cp == 0) { + sprintf(modname, "ppp-compress-%d", ccp_option[0]); + request_module(modname); + cp = find_compressor(ccp_option[0]); + } +#endif /* CONFIG_KMOD */ + if (cp == 0) + goto out; + + err = -ENOBUFS; + if (data.transmit) { + lock_xmit_path(ppp); + ppp->xstate &= ~SC_COMP_RUN; + if (ppp->xc_state != 0) { + ppp->xcomp->comp_free(ppp->xc_state); + ppp->xc_state = 0; + } + + ppp->xcomp = cp; + ppp->xc_state = cp->comp_alloc(ccp_option, data.length); + ppp_xmit_unlock(ppp); + if (ppp->xc_state == 0) + goto out; + + } else { + lock_recv_path(ppp); + ppp->rstate &= ~SC_DECOMP_RUN; + if (ppp->rc_state != 0) { + ppp->rcomp->decomp_free(ppp->rc_state); + ppp->rc_state = 0; + } + + ppp->rcomp = cp; + ppp->rc_state = cp->decomp_alloc(ccp_option, data.length); + ppp_recv_unlock(ppp); + if (ppp->rc_state == 0) + goto out; + } + err = 0; + + out: + return err; +} + +/* + * Look at a CCP packet and update our state accordingly. + * We assume the caller has the xmit or recv path locked. + */ +static void +ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) +{ + unsigned char *dp = skb->data + 2; + int len; + + if (skb->len < CCP_HDRLEN + 2 + || skb->len < (len = CCP_LENGTH(dp)) + 2) + return; /* too short */ + + switch (CCP_CODE(dp)) { + case CCP_CONFREQ: + case CCP_TERMREQ: + case CCP_TERMACK: + /* + * CCP is going down - disable compression. + */ + if (inbound) + ppp->rstate &= ~SC_DECOMP_RUN; + else + ppp->xstate &= ~SC_COMP_RUN; + break; + + case CCP_CONFACK: + if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN) + break; + dp += CCP_HDRLEN; + len -= CCP_HDRLEN; + if (len < CCP_OPT_MINLEN || len < CCP_OPT_LENGTH(dp)) + break; + if (inbound) { + /* we will start receiving compressed packets */ + if (ppp->rc_state == 0) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, + ppp->index, 0, ppp->mru, ppp->debug)) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } + } else { + /* we will soon start sending compressed packets */ + if (ppp->xc_state == 0) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, + ppp->index, 0, ppp->debug)) + ppp->xstate |= SC_COMP_RUN; + } + break; + + case CCP_RESETACK: + /* reset the [de]compressor */ + if ((ppp->flags & SC_CCP_UP) == 0) + break; + if (inbound) { + if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)) { + ppp->rcomp->decomp_reset(ppp->rc_state); + ppp->rstate &= ~SC_DC_ERROR; + } + } else { + if (ppp->xc_state && (ppp->xstate & SC_COMP_RUN)) + ppp->xcomp->comp_reset(ppp->xc_state); + } + break; + } +} + +/* Free up compression resources. */ +static void +ppp_ccp_closed(struct ppp *ppp) +{ + ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP); + + lock_xmit_path(ppp); + ppp->xstate &= ~SC_COMP_RUN; + if (ppp->xc_state) { + ppp->xcomp->comp_free(ppp->xc_state); + ppp->xc_state = 0; + } + ppp_xmit_unlock(ppp); + + lock_recv_path(ppp); + ppp->xstate &= ~SC_DECOMP_RUN; + if (ppp->rc_state) { + ppp->rcomp->decomp_free(ppp->rc_state); + ppp->rc_state = 0; + } + ppp_recv_unlock(ppp); +} + +/* List of compressors. */ +static LIST_HEAD(compressor_list); +static spinlock_t compressor_list_lock = SPIN_LOCK_UNLOCKED; + +struct compressor_entry { + struct list_head list; + struct compressor *comp; +}; + +static struct compressor_entry * +find_comp_entry(int proto) +{ + struct compressor_entry *ce; + struct list_head *list = &compressor_list; + + while ((list = list->next) != &compressor_list) { + ce = list_entry(list, struct compressor_entry, list); + if (ce->comp->compress_proto == proto) + return ce; + } + return 0; +} + +/* Register a compressor */ +int +ppp_register_compressor(struct compressor *cp) +{ + struct compressor_entry *ce; + int ret; + + spin_lock(&compressor_list_lock); + ret = -EEXIST; + if (find_comp_entry(cp->compress_proto) != 0) + goto out; + ret = -ENOMEM; + ce = kmalloc(sizeof(struct compressor_entry), GFP_KERNEL); + if (ce == 0) + goto out; + ret = 0; + ce->comp = cp; + list_add(&ce->list, &compressor_list); + out: + spin_unlock(&compressor_list_lock); + return ret; +} + +/* Unregister a compressor */ +void +ppp_unregister_compressor(struct compressor *cp) +{ + struct compressor_entry *ce; + + spin_lock(&compressor_list_lock); + ce = find_comp_entry(cp->compress_proto); + if (ce != 0 && ce->comp == cp) { + list_del(&ce->list); + kfree(ce); + } + spin_unlock(&compressor_list_lock); +} + +/* Find a compressor. */ +static struct compressor * +find_compressor(int type) +{ + struct compressor_entry *ce; + struct compressor *cp = 0; + + spin_lock(&compressor_list_lock); + ce = find_comp_entry(type); + if (ce != 0) + cp = ce->comp; + spin_unlock(&compressor_list_lock); + return cp; +} + +/* + * Miscelleneous stuff. + */ + +static void +ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) +{ + struct slcompress *vj = ppp->vj; + + memset(st, 0, sizeof(*st)); + st->p.ppp_ipackets = ppp->stats.rx_packets; + st->p.ppp_ierrors = ppp->stats.rx_errors; + st->p.ppp_ibytes = ppp->stats.rx_bytes; + st->p.ppp_opackets = ppp->stats.tx_packets; + st->p.ppp_oerrors = ppp->stats.tx_errors; + st->p.ppp_obytes = ppp->stats.tx_bytes; + if (vj == 0) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; + st->vj.vjs_compressed = vj->sls_o_compressed; + st->vj.vjs_searches = vj->sls_o_searches; + st->vj.vjs_misses = vj->sls_o_misses; + st->vj.vjs_errorin = vj->sls_i_error; + st->vj.vjs_tossed = vj->sls_i_tossed; + st->vj.vjs_uncompressedin = vj->sls_i_uncompressed; + st->vj.vjs_compressedin = vj->sls_i_compressed; +} + +/* + * Stuff for handling the list of ppp units and for initialization. + */ + +/* + * Create a new ppp unit. Fails if it can't allocate memory or + * if there is already a unit with the requested number. + * unit == -1 means allocate a new number. + */ +static struct ppp * +ppp_create_unit(int unit, int *retp) +{ + struct ppp *ppp; + struct list_head *list; + int last_unit = -1; + int ret = -EEXIST; + int i; + + spin_lock(&all_ppp_lock); + list = &all_ppp_units; + while ((list = list->next) != &all_ppp_units) { + ppp = list_entry(list, struct ppp, list); + if ((unit < 0 && ppp->index > last_unit + 1) + || (unit >= 0 && unit < ppp->index)) + break; + if (unit == ppp->index) + goto out; /* unit already exists */ + last_unit = ppp->index; + } + if (unit < 0) + unit = last_unit + 1; + + /* Create a new ppp structure and link it before `list'. */ + ret = -ENOMEM; + ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL); + if (ppp == 0) + goto out; + memset(ppp, 0, sizeof(struct ppp)); + + ppp->index = unit; + sprintf(ppp->name, "ppp%d", unit); + ppp->mru = PPP_MRU; + skb_queue_head_init(&ppp->xq); + skb_queue_head_init(&ppp->rq); + init_waitqueue_head(&ppp->rwait); + ppp->refcnt = 1; + for (i = 0; i < NUM_NP; ++i) + ppp->npmode[i] = NPMODE_PASS; + INIT_LIST_HEAD(&ppp->channels); + skb_queue_head_init(&ppp->recv_pending); + + ppp->dev.init = ppp_net_init; + ppp->dev.name = ppp->name; + ppp->dev.priv = ppp; + + ret = register_netdev(&ppp->dev); + if (ret != 0) { + printk(KERN_ERR "PPP: couldn't register device (%d)\n", ret); + kfree(ppp); + goto out; + } + + list_add(&ppp->list, list->prev); + out: + spin_unlock(&all_ppp_lock); + *retp = ret; + if (ret != 0) + ppp = 0; + return ppp; +} + +/* + * Locate an existing ppp unit. + * The caller should have locked the all_ppp_lock. + */ +static struct ppp * +ppp_find_unit(int unit) +{ + struct ppp *ppp; + struct list_head *list; + + list = &all_ppp_units; + while ((list = list->next) != &all_ppp_units) { + ppp = list_entry(list, struct ppp, list); + if (ppp->index == unit) + return ppp; + } + return 0; +} + +/* + * Module stuff. + */ +#ifdef MODULE +int +init_module(void) +{ + ppp_init(0); + return 0; +} + +void +cleanup_module(void) +{ + /* should never happen */ + if (all_ppp_units.next != &all_ppp_units) + printk(KERN_ERR "PPP: removing module but units remain!\n"); + if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) + printk(KERN_ERR "PPP: failed to unregister PPP device\n"); +} +#endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c --- v2.3.12/linux/drivers/net/ptifddi.c Wed Jun 9 14:45:36 1999 +++ linux/drivers/net/ptifddi.c Mon Aug 9 11:29:37 1999 @@ -1,4 +1,4 @@ -/* $Id: ptifddi.c,v 1.7 1999/06/09 08:19:01 davem Exp $ +/* $Id: ptifddi.c,v 1.8 1999/08/08 01:35:56 davem Exp $ * ptifddi.c: Network driver for Performance Technologies single-attach * and dual-attach FDDI sbus cards. * @@ -213,7 +213,7 @@ pti_load_main_firmware(pp); } -__initfunc(int ptifddi_sbus_probe(struct device *dev)) +int __init ptifddi_sbus_probe(struct device *dev) { struct linux_sbus *bus; struct linux_sbus_device *sdev = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c --- v2.3.12/linux/drivers/net/rcpci45.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/net/rcpci45.c Thu Aug 5 15:07:42 1999 @@ -226,8 +226,7 @@ !((pdev = pci_find_slot(pci_bus, pci_device_fn)))) break; pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0]; - pci_ioaddr &= PCI_BASE_ADDRESS_MEM_MASK; + pci_ioaddr = pdev->resource[0].start; #ifdef RCDEBUG printk("rc: Found RedCreek PCI adapter\n"); diff -u --recursive --new-file v2.3.12/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c --- v2.3.12/linux/drivers/net/rrunner.c Sat Apr 24 17:51:48 1999 +++ linux/drivers/net/rrunner.c Mon Aug 9 10:23:09 1999 @@ -72,7 +72,7 @@ static int probed __initdata = 0; -__initfunc(int rr_hippi_probe (struct device *dev)) +int __init rr_hippi_probe (struct device *dev) { int boards_found = 0; int version_disp; /* was version info already displayed? */ @@ -152,14 +152,14 @@ printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI " "at 0x%08lx, irq %i, PCI latency %i\n", dev->name, - pdev->base_address[0], dev->irq, pci_latency); + pdev->resource[0].start, dev->irq, pci_latency); /* * Remap the regs into kernel space. */ rrpriv->regs = (struct rr_regs *) - ioremap(pdev->base_address[0], 0x1000); + ioremap(pdev->resource[0].start, 0x1000); if (!rrpriv->regs){ printk(KERN_ERR "%s: Unable to map I/O register, " @@ -502,7 +502,7 @@ } -__initfunc(static int rr_init(struct device *dev)) +static int __init rr_init(struct device *dev) { struct rr_private *rrpriv; struct rr_regs *regs; diff -u --recursive --new-file v2.3.12/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c --- v2.3.12/linux/drivers/net/rtl8139.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/net/rtl8139.c Thu Aug 5 15:07:42 1999 @@ -353,7 +353,7 @@ { #if defined(PCI_SUPPORT_VER2) struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->base_address[0] & ~3; + ioaddr = pdev->resource[0].start; irq = pdev->irq; #else u32 pci_ioaddr; diff -u --recursive --new-file v2.3.12/linux/drivers/net/sdla.c linux/drivers/net/sdla.c --- v2.3.12/linux/drivers/net/sdla.c Tue Dec 29 11:32:06 1998 +++ linux/drivers/net/sdla.c Thu Aug 5 14:34:02 1999 @@ -1624,7 +1624,7 @@ return(&flp->stats); } -__initfunc(int sdla_init(struct device *dev)) +int __init sdla_init(struct device *dev) { struct frad_local *flp; @@ -1666,7 +1666,7 @@ return(0); } -__initfunc(void sdla_setup(void)) +void __init sdla_setup(void) { printk("%s.\n", version); register_frad(devname); diff -u --recursive --new-file v2.3.12/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.3.12/linux/drivers/net/shaper.c Wed Jun 2 11:29:13 1999 +++ linux/drivers/net/shaper.c Thu Aug 5 14:35:52 1999 @@ -51,14 +51,19 @@ * will render your machine defunct. Don't for now shape over * PPP or SLIP therefore! * This will be fixed in BETA4 - */ - -/* - * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe - * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper() - * because it's going to be recalled from an irq handler, and synchronize_bh() - * is a nono if called from irq context. + * + * Update History : + * + * bh_atomic() SMP races fixes and rewritten the locking code to + * be SMP safe and irq-mask friendly. + * NOTE: we can't use start_bh_atomic() in kick_shaper() + * because it's going to be recalled from an irq handler, + * and synchronize_bh() is a nono if called from irq context. * 1999 Andrea Arcangeli + * + * Device statistics (tx_pakets, tx_bytes, + * tx_drops: queue_over_time and collisions: max_queue_exceded) + * 1999/06/18 Jordi Murgo */ #include @@ -228,18 +233,20 @@ /* * Queue over time. Spill packet. */ - if(skb->shapeclock-jiffies > SHAPER_LATENCY) + if(skb->shapeclock-jiffies > SHAPER_LATENCY) { dev_kfree_skb(skb); - else + shaper->stats.tx_dropped++; + } else skb_queue_tail(&shaper->sendq, skb); } #endif - if(sh_debug) + if(sh_debug) printk("Frame queued.\n"); if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN) { ptr=skb_dequeue(&shaper->sendq); - dev_kfree_skb(ptr); + dev_kfree_skb(ptr); + shaper->stats.collisions++; } shaper_unlock(shaper); return 0; @@ -262,7 +269,11 @@ printk("Kick new frame to %s, %d\n", shaper->dev->name,newskb->priority); dev_queue_xmit(newskb); - if(sh_debug) + + shaper->stats.tx_bytes+=newskb->len; + shaper->stats.tx_packets++; + + if(sh_debug) printk("Kicked new frame out.\n"); dev_kfree_skb(skb); } @@ -415,7 +426,8 @@ static struct net_device_stats *shaper_get_stats(struct device *dev) { - return NULL; + struct shaper *sh=dev->priv; + return &sh->stats; } static int shaper_header(struct sk_buff *skb, struct device *dev, @@ -590,7 +602,7 @@ * Add a shaper device to the system */ -__initfunc(int shaper_probe(struct device *dev)) +int __init shaper_probe(struct device *dev) { /* * Set up the shaper. @@ -665,7 +677,9 @@ void cleanup_module(void) { - /* + struct shaper *sh=dev_shape.priv; + + /* * No need to check MOD_IN_USE, as sys_delete_module() checks. * To be unloadable we must be closed and detached so we don't * need to flush things. @@ -674,10 +688,9 @@ unregister_netdev(&dev_shape); /* - * Free up the private structure, or leak memory :-) + * Free up the private structure, or leak memory :-) */ - - kfree(dev_shape.priv); + kfree(sh); dev_shape.priv = NULL; } diff -u --recursive --new-file v2.3.12/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v2.3.12/linux/drivers/net/sk_g16.c Sun Mar 7 15:47:46 1999 +++ linux/drivers/net/sk_g16.c Thu Aug 5 14:35:52 1999 @@ -531,7 +531,7 @@ * (detachable devices only). */ -__initfunc(int SK_init(struct device *dev)) +int __init SK_init(struct device *dev) { int ioaddr = 0; /* I/O port address used for POS regs */ int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */ @@ -614,7 +614,7 @@ * 94/06/30 pwe SK_ADDR now checked and at the correct place -*/ -__initfunc(int SK_probe(struct device *dev, short ioaddr)) +int __init SK_probe(struct device *dev, short ioaddr) { int i,j; /* Counters */ int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */ @@ -1737,7 +1737,7 @@ * YY/MM/DD uid Description -*/ -__initfunc(unsigned int SK_rom_addr(void)) +unsigned int __init SK_rom_addr(void) { int i,j; int rom_found = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- v2.3.12/linux/drivers/net/skeleton.c Tue Feb 10 12:56:45 1998 +++ linux/drivers/net/skeleton.c Thu Aug 5 14:35:52 1999 @@ -127,8 +127,8 @@ struct netdev_entry netcard_drv = {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist}; #else -__initfunc(int -netcard_probe(struct device *dev)) +int __init +netcard_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -155,7 +155,7 @@ * probes on the ISA bus. A good device probes avoids doing writes, and * verifies that the correct device exists and functions. */ -__initfunc(static int netcard_probe1(struct device *dev, int ioaddr)) +static int __init netcard_probe1(struct device *dev, int ioaddr) { static unsigned version_printed = 0; int i; diff -u --recursive --new-file v2.3.12/linux/drivers/net/sktr.c linux/drivers/net/sktr.c --- v2.3.12/linux/drivers/net/sktr.c Wed May 12 13:27:37 1999 +++ linux/drivers/net/sktr.c Mon Aug 9 10:23:09 1999 @@ -186,7 +186,7 @@ * If dev->base_addr == 0, probe all likely locations. * If dev->base_addr == 1, always return failure. */ -__initfunc(int sktr_probe(struct device *dev)) +int __init sktr_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -217,7 +217,7 @@ /* * Detect and setup the PCI SysKonnect TR cards in slot order. */ -__initfunc(static int sktr_pci_chk_card(struct device *dev)) +static int __init sktr_pci_chk_card(struct device *dev) { static int pci_index = 0; unsigned char pci_bus, pci_device_fn; @@ -246,7 +246,7 @@ pdev = pci_find_slot(pci_bus, pci_device_fn); pci_irq_line = pdev->irq; - pci_ioaddr = pdev->base_address[0]; + pci_ioaddr = pdev->resource[0].start; pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command); @@ -295,7 +295,7 @@ /* * Detect and setup the ISA SysKonnect TR cards. */ -__initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr)) +static int __init sktr_isa_chk_card(struct device *dev, int ioaddr) { int i, err; unsigned long flags; @@ -386,7 +386,7 @@ return (0); } -__initfunc(static int sktr_probe1(struct device *dev, int ioaddr)) +static int __init sktr_probe1(struct device *dev, int ioaddr) { static unsigned version_printed = 0; struct net_local *tp; @@ -428,7 +428,7 @@ } /* Dummy function */ -__initfunc(static int sktr_init_card(struct device *dev)) +static int __init sktr_init_card(struct device *dev) { if(sktr_debug > 3) printk("%s: sktr_init_card\n", dev->name); @@ -440,7 +440,7 @@ * This function tests if an adapter is really installed at the * given I/O address. Return negative if no adapter at IO addr. */ -__initfunc(static int sktr_isa_chk_ioaddr(int ioaddr)) +static int __init sktr_isa_chk_ioaddr(int ioaddr) { unsigned char old, chk1, chk2; diff -u --recursive --new-file v2.3.12/linux/drivers/net/slhc.c linux/drivers/net/slhc.c --- v2.3.12/linux/drivers/net/slhc.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/slhc.c Thu Aug 5 14:35:52 1999 @@ -752,8 +752,7 @@ } #else /* MODULE */ - -__initfunc(void slhc_install(void)) +void __init slhc_install(void) { } diff -u --recursive --new-file v2.3.12/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.3.12/linux/drivers/net/slip.c Wed May 20 18:55:04 1998 +++ linux/drivers/net/slip.c Thu Aug 5 14:35:52 1999 @@ -1318,7 +1318,7 @@ #ifdef MODULE static int slip_init_ctrl_dev(void) #else /* !MODULE */ -__initfunc(int slip_init_ctrl_dev(struct device *dummy)) +int __init slip_init_ctrl_dev(struct device *dummy) #endif /* !MODULE */ { int status; diff -u --recursive --new-file v2.3.12/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.3.12/linux/drivers/net/smc-mca.c Wed Dec 16 13:35:49 1998 +++ linux/drivers/net/smc-mca.c Thu Aug 5 14:35:52 1999 @@ -66,8 +66,7 @@ #define ULTRA_IO_EXTENT 32 #define EN0_ERWCNT 0x08 /* Early receive warning count. */ - -__initfunc(int ultramca_probe(struct device *dev)) +int __init ultramca_probe(struct device *dev) { unsigned short ioaddr; unsigned char reg4, num_pages; diff -u --recursive --new-file v2.3.12/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.3.12/linux/drivers/net/smc-ultra.c Wed May 26 09:31:50 1999 +++ linux/drivers/net/smc-ultra.c Thu Aug 5 14:35:52 1999 @@ -106,7 +106,7 @@ {"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist}; #else -__initfunc(int ultra_probe(struct device *dev)) +int __init ultra_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -128,7 +128,7 @@ } #endif -__initfunc(int ultra_probe1(struct device *dev, int ioaddr)) +int __init ultra_probe1(struct device *dev, int ioaddr) { int i; int checksum = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c --- v2.3.12/linux/drivers/net/smc-ultra32.c Wed Dec 16 13:35:49 1998 +++ linux/drivers/net/smc-ultra32.c Thu Aug 5 14:35:52 1999 @@ -103,7 +103,7 @@ following. */ -__initfunc(int ultra32_probe(struct device *dev)) +int __init ultra32_probe(struct device *dev) { const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; int ioaddr, edge, media; @@ -126,7 +126,7 @@ return ENODEV; } -__initfunc(int ultra32_probe1(struct device *dev, int ioaddr)) +int __init ultra32_probe1(struct device *dev, int ioaddr) { int i; int checksum = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.3.12/linux/drivers/net/smc9194.c Wed Mar 10 16:51:35 1999 +++ linux/drivers/net/smc9194.c Thu Aug 5 14:35:52 1999 @@ -750,7 +750,7 @@ | --------------------------------------------------------------------------- */ -__initfunc(int smc_init(struct device *dev)) +int __init smc_init(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -795,7 +795,7 @@ . interrupt, so an auto-detect routine can detect it, and find the IRQ, ------------------------------------------------------------------------ */ -__initfunc(int smc_findirq( int ioaddr )) +int __init smc_findirq( int ioaddr ) { int timeout = 20; @@ -877,7 +877,7 @@ .--------------------------------------------------------------------- */ -__initfunc(static int smc_probe( int ioaddr )) +static int __init smc_probe( int ioaddr ) { unsigned int bank; word revision_register; @@ -942,7 +942,7 @@ . o GRAB the region .----------------------------------------------------------------- */ -__initfunc(static int smc_initcard(struct device *dev, int ioaddr)) +static int __init smc_initcard(struct device *dev, int ioaddr) { int i; diff -u --recursive --new-file v2.3.12/linux/drivers/net/sonic.h linux/drivers/net/sonic.h --- v2.3.12/linux/drivers/net/sonic.h Wed Jun 30 13:38:20 1999 +++ linux/drivers/net/sonic.h Mon Aug 9 12:32:28 1999 @@ -9,6 +9,9 @@ * and pad structure members must be exchanged. Also, the structures * need to be changed accordingly to the bus size. * + * 981229 MSch: did just that for the 68k Mac port (32 bit, big endian), + * see CONFIG_MACSONIC branch below. + * */ #ifndef SONIC_H @@ -213,6 +216,108 @@ #define SONIC_END_OF_LINKS 0x0001 +#ifdef CONFIG_MACSONIC +/* Big endian like structures on Mac + * (680x0) + */ + +typedef struct { + u32 rx_bufadr_l; /* receive buffer ptr */ + u32 rx_bufadr_h; + + u32 rx_bufsize_l; /* no. of words in the receive buffer */ + u32 rx_bufsize_h; +} sonic_rr_t; + +/* + * Sonic receive descriptor. Receive descriptors are + * kept in a linked list of these structures. + */ + +typedef struct { + SREGS_PAD(pad0); + u16 rx_status; /* status after reception of a packet */ + SREGS_PAD(pad1); + u16 rx_pktlen; /* length of the packet incl. CRC */ + + /* + * Pointers to the location in the receive buffer area (RBA) + * where the packet resides. A packet is always received into + * a contiguous piece of memory. + */ + SREGS_PAD(pad2); + u16 rx_pktptr_l; + SREGS_PAD(pad3); + u16 rx_pktptr_h; + + SREGS_PAD(pad4); + u16 rx_seqno; /* sequence no. */ + + SREGS_PAD(pad5); + u16 link; /* link to next RDD (end if EOL bit set) */ + + /* + * Owner of this descriptor, 0= driver, 1=sonic + */ + + SREGS_PAD(pad6); + u16 in_use; + + caddr_t rda_next; /* pointer to next RD */ +} sonic_rd_t; + + +/* + * Describes a Transmit Descriptor + */ +typedef struct { + SREGS_PAD(pad0); + u16 tx_status; /* status after transmission of a packet */ + SREGS_PAD(pad1); + u16 tx_config; /* transmit configuration for this packet */ + SREGS_PAD(pad2); + u16 tx_pktsize; /* size of the packet to be transmitted */ + SREGS_PAD(pad3); + u16 tx_frag_count; /* no. of fragments */ + + SREGS_PAD(pad4); + u16 tx_frag_ptr_l; + SREGS_PAD(pad5); + u16 tx_frag_ptr_h; + SREGS_PAD(pad6); + u16 tx_frag_size; + + SREGS_PAD(pad7); + u16 link; /* ptr to next descriptor */ +} sonic_td_t; + + +/* + * Describes an entry in the CAM Descriptor Area. + */ + +typedef struct { + SREGS_PAD(pad0); + u16 cam_entry_pointer; + SREGS_PAD(pad1); + u16 cam_cap0; + SREGS_PAD(pad2); + u16 cam_cap1; + SREGS_PAD(pad3); + u16 cam_cap2; +} sonic_cd_t; + +#define CAM_DESCRIPTORS 16 + + +typedef struct { + sonic_cd_t cam_desc[CAM_DESCRIPTORS]; + SREGS_PAD(pad); + u16 cam_enable; +} sonic_cda_t; + +#else /* original declarations, little endian 32 bit */ + /* * structure definitions */ @@ -311,14 +416,23 @@ u16 cam_enable; SREGS_PAD(pad); } sonic_cda_t; +#endif /* endianness */ /* * Some tunables for the buffer areas. Power of 2 is required * the current driver uses one receive buffer for each descriptor. + * + * MSch: use more buffer space for the slow m68k Macs! */ +#ifdef CONFIG_MACSONIC +#define SONIC_NUM_RRS 32 /* number of receive resources */ +#define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ +#define SONIC_NUM_TDS 32 /* number of transmit descriptors */ +#else #define SONIC_NUM_RRS 16 /* number of receive resources */ #define SONIC_NUM_RDS SONIC_NUM_RRS /* number of receive descriptors */ #define SONIC_NUM_TDS 16 /* number of transmit descriptors */ +#endif #define SONIC_RBSIZE 1520 /* size of one resource buffer */ #define SONIC_RDS_MASK (SONIC_NUM_RDS-1) diff -u --recursive --new-file v2.3.12/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c --- v2.3.12/linux/drivers/net/sunbmac.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/sunbmac.c Thu Aug 5 14:35:52 1999 @@ -1253,7 +1253,7 @@ bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE; } -__initfunc(static int bigmac_ether_init(struct device *dev, struct linux_sbus_device *qec_sdev)) +static int __init bigmac_ether_init(struct device *dev, struct linux_sbus_device *qec_sdev) { static unsigned version_printed = 0; struct bigmac *bp = 0; @@ -1492,7 +1492,7 @@ return res; /* Return error code. */ } -__initfunc(int bigmac_probe(struct device *dev)) +int __init bigmac_probe(struct device *dev) { struct linux_sbus *bus; struct linux_sbus_device *sdev = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.3.12/linux/drivers/net/sunhme.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/sunhme.c Mon Aug 9 11:29:37 1999 @@ -3324,12 +3324,11 @@ qp->happy_meals[qfe_slot] = dev; } - hpreg_base = pdev->base_address[0]; - if((hpreg_base & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + hpreg_base = pdev->resource[0].start; + if ((pdev->resource[0].flags & IORESOURCE_IOPORT) != 0) { printk("happymeal(PCI): Cannot find proper PCI device base address.\n"); return ENODEV; } - hpreg_base &= PCI_BASE_ADDRESS_MEM_MASK; if (qfe_slot != -1 && prom_getproplen(node, "local-mac-address") == 6) prom_getproperty(node, "local-mac-address", dev->dev_addr, 6); diff -u --recursive --new-file v2.3.12/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h --- v2.3.12/linux/drivers/net/sunhme.h Mon Mar 15 16:11:30 1999 +++ linux/drivers/net/sunhme.h Fri Aug 6 11:58:00 1999 @@ -604,107 +604,75 @@ /* We use this to acquire receive skb's that we can DMA directly into. */ #define ALIGNED_RX_SKB_ADDR(addr) \ ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr)) -static inline struct sk_buff *happy_meal_alloc_skb(unsigned int length, int gfp_flags) -{ - struct sk_buff *skb; - - skb = alloc_skb(length + 64, gfp_flags); - if(skb) { - int offset = ALIGNED_RX_SKB_ADDR(skb->data); - - if(offset) - skb_reserve(skb, offset); - } - return skb; -} +#define happy_meal_alloc_skb(__length, __gfp_flags) \ +({ struct sk_buff *__skb; \ + __skb = alloc_skb((__length) + 64, (__gfp_flags)); \ + if(__skb) { \ + int __offset = ALIGNED_RX_SKB_ADDR(__skb->data); \ + if(__offset) \ + skb_reserve(__skb, __offset); \ + } \ + __skb; \ +}) /* Register/DMA access stuff, used to cope with differences between * PCI and SBUS happy meals. */ -extern inline u32 kva_to_hva(struct happy_meal *hp, char *addr) -{ -#ifdef CONFIG_PCI - if(hp->happy_flags & HFLAG_PCI) - return (u32) virt_to_bus((volatile void *)addr); - else -#endif - { -#ifdef __sparc_v9__ - if (((unsigned long) addr) >= MAX_DMA_ADDRESS) { - printk("sunhme: Bogus DMA buffer address " - "[%016lx]\n", ((unsigned long) addr)); - panic("DMA address too large, tell DaveM"); - } -#endif - return sbus_dvma_addr(addr); - } -} - -extern inline unsigned int hme_read32(struct happy_meal *hp, - volatile unsigned int *reg) -{ -#ifdef CONFIG_PCI - if(hp->happy_flags & HFLAG_PCI) - return readl((unsigned long)reg); - else -#endif - return *reg; -} - -extern inline void hme_write32(struct happy_meal *hp, - volatile unsigned int *reg, - unsigned int val) -{ -#ifdef CONFIG_PCI - if(hp->happy_flags & HFLAG_PCI) - writel(val, (unsigned long)reg); - else +#if defined(CONFIG_PCI) +#define kva_to_hva(__hp, __addr) \ +({ u32 __ret; \ + if ((__hp)->happy_flags & HFLAG_PCI) \ + (__ret) = (u32) virt_to_bus((volatile void *)(__addr)); \ + else \ + (__ret) = sbus_dvma_addr(__addr); \ + __ret; \ +}) +#define hme_read32(__hp, __reg) \ +({ unsigned int __ret; \ + if ((__hp)->happy_flags & HFLAG_PCI) \ + __ret = readl((unsigned long)(__reg)); \ + else \ + __ret = *(__reg); \ + __ret; \ +}) +#define hme_write32(__hp, __reg, __val) \ +do { if ((__hp)->happy_flags & HFLAG_PCI) \ + writel((__val), (unsigned long)(__reg)); \ + else \ + *(__reg) = (__val); \ +} while(0) +#else +#define kva_to_hva(__hp, __addr) ((u32)sbus_dvma_addr(__addr)) +#define hme_read32(__hp, __reg) (*(__reg)) +#define hme_write32(__hp, __reg, __val) ((*(__reg)) = (__val)) #endif - *reg = val; -} #ifdef CONFIG_PCI #ifdef __sparc_v9__ -extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp, - unsigned int flags, - unsigned int addr) -{ - __asm__ __volatile__(" - stwa %3, [%0] %2 - stwa %4, [%1] %2 -" : /* no outputs */ - : "r" (&rp->rx_addr), "r" (&rp->rx_flags), - "i" (ASI_PL), "r" (addr), "r" (flags)); -} - -extern inline void pcihme_write_txd(struct happy_meal_txd *tp, - unsigned int flags, - unsigned int addr) -{ - __asm__ __volatile__(" - stwa %3, [%0] %2 - stwa %4, [%1] %2 -" : /* no outputs */ - : "r" (&tp->tx_addr), "r" (&tp->tx_flags), - "i" (ASI_PL), "r" (addr), "r" (flags)); -} +#define pcihme_write_rxd(__rp, __flags, __addr) \ + __asm__ __volatile__("stwa %3, [%0] %2\n\t" \ + "stwa %4, [%1] %2" \ + : /* no outputs */ \ + : "r" (&(__rp)->rx_addr), "r" (&(__rp)->rx_flags), \ + "i" (ASI_PL), "r" (__addr), "r" (__flags)) + +#define pcihme_write_txd(__tp, __flags, __addr) \ + __asm__ __volatile__("stwa %3, [%0] %2\n\t" \ + "stwa %4, [%1] %2" \ + : /* no outputs */ \ + : "r" (&(__tp)->tx_addr), "r" (&(__tp)->tx_flags), \ + "i" (ASI_PL), "r" (__addr), "r" (__flags)) #else -extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp, - unsigned int flags, - unsigned int addr) -{ - rp->rx_addr = flip_dword(addr); - rp->rx_flags = flip_dword(flags); -} +#define pcihme_write_rxd(__rp, __flags, __addr) \ +do { (__rp)->rx_addr = flip_dword(__addr); \ + (__rp)->rx_flags = flip_dword(__flags); \ +} while(0) -extern inline void pcihme_write_txd(struct happy_meal_txd *tp, - unsigned int flags, - unsigned int addr) -{ - tp->tx_addr = flip_dword(addr); - tp->tx_flags = flip_dword(flags); -} +#define pcihme_write_txd(__tp, __flags, __addr) \ +do { (__tp)->tx_addr = flip_dword(__addr); \ + (__tp)->tx_flags = flip_dword(__flags); \ +} while(0) #endif /* def __sparc_v9__ */ #endif /* def CONFIG_PCI */ diff -u --recursive --new-file v2.3.12/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c --- v2.3.12/linux/drivers/net/sunlance.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/sunlance.c Mon Aug 9 11:29:37 1999 @@ -1,4 +1,4 @@ -/* $Id: sunlance.c,v 1.85 1999/03/21 05:22:05 davem Exp $ +/* $Id: sunlance.c,v 1.87 1999/08/08 01:36:14 davem Exp $ * lance.c: Linux/Sparc/Lance driver * * Written 1995, 1996 by Miguel de Icaza @@ -965,10 +965,10 @@ mark_bh(NET_BH); } -__initfunc(static int +static int __init sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev, struct Linux_SBus_DMA *ledma, - struct linux_sbus_device *lebuffer)) + struct linux_sbus_device *lebuffer) { static unsigned version_printed = 0; int i; @@ -1157,7 +1157,7 @@ #include /* Find all the lance cards on the system and initialize them */ -__initfunc(int sparc_lance_probe (struct device *dev)) +int __init sparc_lance_probe (struct device *dev) { static struct linux_sbus_device sdev; static int called = 0; @@ -1179,7 +1179,7 @@ #else /* !CONFIG_SUN4 */ /* Find all the lance cards on the system and initialize them */ -__initfunc(int sparc_lance_probe (struct device *dev)) +int __init sparc_lance_probe (struct device *dev) { struct linux_sbus *bus; struct linux_sbus_device *sdev = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c --- v2.3.12/linux/drivers/net/sunqe.c Mon Mar 15 16:11:30 1999 +++ linux/drivers/net/sunqe.c Thu Aug 5 14:35:52 1999 @@ -1173,7 +1173,7 @@ return res; } -__initfunc(int qec_probe(struct device *dev)) +int __init qec_probe(struct device *dev) { struct linux_sbus *bus; struct linux_sbus_device *sdev = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.3.12/linux/drivers/net/tlan.c Mon Apr 12 16:18:33 1999 +++ linux/drivers/net/tlan.c Thu Aug 5 15:07:42 1999 @@ -554,7 +554,7 @@ ); *pci_irq = pdev->irq; - *pci_io_base = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + *pci_io_base = pdev->resource[0].start; *pci_dfn = pdev->devfn; pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev); pci_read_config_word ( pdev, PCI_COMMAND, &pci_command); diff -u --recursive --new-file v2.3.12/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v2.3.12/linux/drivers/net/tulip.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/tulip.c Fri Aug 6 10:41:47 1999 @@ -497,7 +497,7 @@ continue; } #if LINUX_VERSION_CODE >= 0x20155 - pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->base_address[0]; + pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start; #else pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &pci_ioaddr); @@ -572,23 +572,8 @@ dev = init_etherdev(dev, 0); -#if LINUX_VERSION_CODE >= 0x20155 irq = pci_find_slot(pci_bus, pci_device_fn)->irq; - ioaddr = pci_find_slot(pci_bus, pci_device_fn)->base_address[0]; -#else - { - u8 pci_irq_line; - u32 pci_ioaddr; - 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); - irq = pci_irq_line; - ioaddr = pci_ioaddr; - } -#endif - /* Remove I/O space marker in bit 0. */ - ioaddr &= ~3; + ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start; printk(KERN_INFO "%s: %s at %#3lx,", dev->name, tulip_tbl[chip_id].chip_name, ioaddr); diff -u --recursive --new-file v2.3.12/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- v2.3.12/linux/drivers/net/via-rhine.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/net/via-rhine.c Thu Aug 5 15:07:42 1999 @@ -431,9 +431,9 @@ #if defined(PCI_SUPPORT_VER2) struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); #ifdef VIA_USE_IO - pciaddr = pdev->base_address[0]; + pciaddr = pdev->resource[0].start; #else - pciaddr = pdev->base_address[1]; + pciaddr = pdev->resource[1].start; #endif irq = pdev->irq; #else diff -u --recursive --new-file v2.3.12/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v2.3.12/linux/drivers/net/wd.c Thu Dec 17 09:04:49 1998 +++ linux/drivers/net/wd.c Thu Aug 5 14:35:52 1999 @@ -86,7 +86,7 @@ {"wd", wd_probe1, WD_IO_EXTENT, wd_portlist}; #else -__initfunc(int wd_probe(struct device *dev)) +int __init wd_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; @@ -108,7 +108,7 @@ } #endif -__initfunc(int wd_probe1(struct device *dev, int ioaddr)) +int __init wd_probe1(struct device *dev, int ioaddr) { int i; int checksum = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/net/x25_asy.c linux/drivers/net/x25_asy.c --- v2.3.12/linux/drivers/net/x25_asy.c Fri Feb 20 18:28:22 1998 +++ linux/drivers/net/x25_asy.c Thu Aug 5 14:35:52 1999 @@ -818,7 +818,7 @@ #ifdef MODULE static int x25_asy_init_ctrl_dev(void) #else /* !MODULE */ -__initfunc(int x25_asy_init_ctrl_dev(struct device *dummy)) +int __init x25_asy_init_ctrl_dev(struct device *dummy) #endif /* !MODULE */ { int status; diff -u --recursive --new-file v2.3.12/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.3.12/linux/drivers/net/yellowfin.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/net/yellowfin.c Thu Aug 5 15:07:42 1999 @@ -377,23 +377,10 @@ 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]; + ioaddr = pdev->resource[0].start; 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. */ - ioaddr &= ~3; if (yellowfin_debug > 2) printk(KERN_INFO "Found %s at I/O %#lx, IRQ %d.\n", diff -u --recursive --new-file v2.3.12/linux/drivers/net/znet.c linux/drivers/net/znet.c --- v2.3.12/linux/drivers/net/znet.c Thu Jan 14 10:31:41 1999 +++ linux/drivers/net/znet.c Thu Aug 5 14:35:52 1999 @@ -200,7 +200,7 @@ BIOS area. We just scan for the signature, and pull the vital parameters out of the structure. */ -__initfunc(int znet_probe(struct device *dev)) +int __init znet_probe(struct device *dev) { int i; struct netidblk *netinfo; diff -u --recursive --new-file v2.3.12/linux/drivers/parport/Config.in linux/drivers/parport/Config.in --- v2.3.12/linux/drivers/parport/Config.in Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/Config.in Tue Aug 3 15:30:44 1999 @@ -11,6 +11,11 @@ if [ "$CONFIG_PARPORT_PC" != "n" ]; then bool ' Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO fi + if [ "$CONFIG_PARPORT_PC" = "y" ]; then + # Don't bother with this if parport_pc is a module; it only affects + # the presence or not of some __init's, which are no-ops for modules. + bool ' Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA + fi if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT fi diff -u --recursive --new-file v2.3.12/linux/drivers/parport/Makefile linux/drivers/parport/Makefile --- v2.3.12/linux/drivers/parport/Makefile Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/Makefile Mon Aug 2 11:16:02 1999 @@ -33,7 +33,7 @@ LX_OBJS += parport_pc.o else ifeq ($(CONFIG_PARPORT_PC),m) - M_OBJS += parport_pc.o + MX_OBJS += parport_pc.o endif endif ifeq ($(CONFIG_PARPORT_AMIGA),y) @@ -71,10 +71,7 @@ M_OBJS += parport.o endif ifeq ($(CONFIG_PARPORT_PC),m) - M_OBJS += parport_pc.o - endif - ifeq ($(CONFIG_PARPORT_AX),m) - M_OBJS += parport_ax.o + MX_OBJS += parport_pc.o endif ifeq ($(CONFIG_PARPORT_AMIGA),m) M_OBJS += parport_amiga.o diff -u --recursive --new-file v2.3.12/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c --- v2.3.12/linux/drivers/parport/ieee1284.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/ieee1284.c Fri Aug 6 15:25:47 1999 @@ -310,13 +310,9 @@ /* Event 6: nAck goes high */ if (parport_wait_peripheral (port, - PARPORT_STATUS_ACK - | PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_ACK, PARPORT_STATUS_ACK)) { - if (parport_read_status (port) & PARPORT_STATUS_ACK) - printk (KERN_DEBUG - "%s: working around buggy peripheral: tell " - "Tim what make it is\n", port->name); + /* This shouldn't really happen with a compliant device. */ DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported? (0x%02x)\n", port->name, mode, port->ops->read_status (port)); diff -u --recursive --new-file v2.3.12/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c --- v2.3.12/linux/drivers/parport/ieee1284_ops.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/ieee1284_ops.c Fri Aug 6 15:25:47 1999 @@ -43,6 +43,7 @@ const void *buffer, size_t len, int flags) { + int no_irq; ssize_t count = 0; const unsigned char *addr = buffer; unsigned char byte; @@ -54,6 +55,7 @@ parport_enable_irq (port); port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; + no_irq = polling (dev); while (count < len) { long expire = jiffies + dev->timeout; long wait = (HZ + 99) / 100; @@ -97,7 +99,7 @@ first time around the loop, don't let go of the port. This way, we find out if we have our interrupt handler called. */ - if (count && polling (dev)) { + if (count && no_irq) { parport_release (dev); current->state = TASK_INTERRUPTIBLE; schedule_timeout (wait); @@ -129,14 +131,30 @@ parport_write_control (port, ctl); udelay (1); /* hold */ - /* Wait until it's received (up to 20us). */ - for (i = 0; i < 20; i++) { + if (no_irq) + /* Assume the peripheral received it. */ + goto done; + + /* Wait until it's received, up to 500us (this ought to be + * tuneable). */ + for (i = 500; i; i--) { if (!down_trylock (&port->physport->ieee1284.irq) || !(parport_read_status (port) & PARPORT_STATUS_ACK)) - break; + goto done; udelay (1); } + /* Two choices: + * 1. Assume that the peripheral got the data and just + * hasn't acknowledged it yet. + * 2. Assume that the peripheral never saw the strobe pulse. + * + * We can't know for sure, so let's be conservative. + */ + DPRINTK (KERN_DEBUG "%s: no ack", port->name); + break; + + done: count++; /* Let another process run if it needs to. */ @@ -344,14 +362,14 @@ /* Event 38: Set nAutoFd low */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); + 0); parport_data_reverse (port); udelay (5); /* Event 39: Set nInit low to initiate bus reversal */ parport_frob_control (port, PARPORT_CONTROL_INIT, - PARPORT_CONTROL_INIT); + 0); /* Event 40: PError goes low */ retval = parport_wait_peripheral (port, @@ -373,9 +391,10 @@ /* Event 47: Set nInit high */ parport_frob_control (port, - PARPORT_CONTROL_INIT, - PARPORT_CONTROL_INIT); - parport_data_reverse (port); + PARPORT_CONTROL_INIT + | PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_INIT + | PARPORT_CONTROL_AUTOFD); /* Event 49: PError goes high */ retval = parport_wait_peripheral (port, @@ -404,7 +423,6 @@ #else const unsigned char *buf = buffer; size_t written; - int ctl = parport_read_control (port) & ~PARPORT_CONTROL_AUTOFD; int retry; port = port->physport; @@ -416,7 +434,11 @@ port->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* HostAck high (data, not command) */ - parport_write_control (port, ctl); + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD + | PARPORT_CONTROL_STROBE + | PARPORT_CONTROL_INIT, + PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { long expire = jiffies + port->cad->timeout; unsigned char byte; @@ -424,7 +446,8 @@ byte = *buf; try_again: parport_write_data (port, byte); - parport_write_control (port, ctl | PARPORT_CONTROL_STROBE); + parport_frob_control (port, PARPORT_CONTROL_STROBE, + PARPORT_CONTROL_STROBE); udelay (5); for (retry = 0; retry < 100; retry++) { if (!parport_wait_peripheral (port, @@ -432,7 +455,9 @@ goto success; if (signal_pending (current)) { - parport_write_control (port, ctl); + parport_frob_control (port, + PARPORT_CONTROL_STROBE, + 0); break; } } @@ -440,15 +465,16 @@ /* Time for Host Transfer Recovery (page 41 of IEEE1284) */ DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name); - parport_write_control (port, ctl | PARPORT_CONTROL_INIT); + parport_frob_control (port, PARPORT_CONTROL_INIT, + PARPORT_CONTROL_INIT); udelay (50); if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) { /* It's buggered. */ - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_INIT, 0); break; } - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_INIT, 0); udelay (50); if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT)) break; @@ -459,7 +485,7 @@ if (time_after_eq (jiffies, expire)) break; goto try_again; success: - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); udelay (5); if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, @@ -496,7 +522,10 @@ port->ieee1284.phase = IEEE1284_PH_REV_DATA; /* Set HostAck low to start accepting data. */ - parport_frob_control (port, PARPORT_CONTROL_AUTOFD, + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD + | PARPORT_CONTROL_STROBE + | PARPORT_CONTROL_INIT, PARPORT_CONTROL_AUTOFD); while (count < len) { long expire = jiffies + dev->timeout; @@ -505,9 +534,7 @@ /* Event 43: Peripheral sets nAck low. It can take as long as it wants. */ - while (parport_wait_peripheral (port, - PARPORT_STATUS_ACK, - PARPORT_STATUS_ACK)) { + while (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { /* The peripheral hasn't given us data in 35ms. If we have data to give back to the caller, do it now. */ @@ -578,7 +605,8 @@ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); /* Event 45: The peripheral has 35ms to set nAck high. */ - if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { + if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, + PARPORT_STATUS_ACK)) { /* It's gone wrong. Return what data we have to the caller. */ DPRINTK (KERN_DEBUG "ECP read timed out at 45\n"); @@ -615,6 +643,7 @@ } out: + port->ieee1284.phase = IEEE1284_PH_REV_IDLE; return count; #endif /* IEEE1284 support */ } @@ -629,7 +658,6 @@ #else const unsigned char *buf = buffer; size_t written; - int ctl = parport_read_control (port) | PARPORT_CONTROL_AUTOFD; int retry; port = port->physport; @@ -641,7 +669,12 @@ port->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* HostAck low (command, not data) */ - parport_write_control (port, ctl); + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD + | PARPORT_CONTROL_STROBE + | PARPORT_CONTROL_INIT, + PARPORT_CONTROL_AUTOFD + | PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { long expire = jiffies + port->cad->timeout; unsigned char byte; @@ -649,7 +682,8 @@ byte = *buf; try_again: parport_write_data (port, byte); - parport_write_control (port, ctl | PARPORT_CONTROL_STROBE); + parport_frob_control (port, PARPORT_CONTROL_STROBE, + PARPORT_CONTROL_STROBE); udelay (5); for (retry = 0; retry < 100; retry++) { if (!parport_wait_peripheral (port, @@ -657,7 +691,9 @@ goto success; if (signal_pending (current)) { - parport_write_control (port, ctl); + parport_frob_control (port, + PARPORT_CONTROL_STROBE, + 0); break; } } @@ -665,15 +701,16 @@ /* Time for Host Transfer Recovery (page 41 of IEEE1284) */ DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name); - parport_write_control (port, ctl | PARPORT_CONTROL_INIT); + parport_frob_control (port, PARPORT_CONTROL_INIT, + PARPORT_CONTROL_INIT); udelay (50); if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) { /* It's buggered. */ - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_INIT, 0); break; } - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_INIT, 0); udelay (50); if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT)) break; @@ -684,7 +721,7 @@ if (time_after_eq (jiffies, expire)) break; goto try_again; success: - parport_write_control (port, ctl); + parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); udelay (5); if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, diff -u --recursive --new-file v2.3.12/linux/drivers/parport/init.c linux/drivers/parport/init.c --- v2.3.12/linux/drivers/parport/init.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/init.c Tue Aug 3 15:24:27 1999 @@ -11,7 +11,7 @@ #include #include #include - +#include #include #include #include @@ -28,71 +28,86 @@ static int parport_setup_ptr __initdata = 0; -__initfunc(void parport_setup(char *str, int *ints)) +/* + * Acceptable parameters: + * + * parport=0 + * parport=auto + * parport=0xBASE[,IRQ[,DMA]] + * + * IRQ/DMA may be numeric or 'auto' or 'none' + */ +static int __init parport_setup (char *str) { - if (ints[0] == 0) { - if (str && !strncmp(str, "auto", 4)) { - irq[0] = PARPORT_IRQ_AUTO; - dma[0] = PARPORT_DMA_AUTO; - } - else if (str) - printk (KERN_ERR "parport: `%s': huh?\n", str); - else - printk (KERN_ERR "parport: parport=.. what?\n"); - - return; - } - else if (ints[1] == 0) { + char *endptr; + char *sep; + int val; + + if (!str || !*str || (*str == '0' && !*(str+1))) { /* Disable parport if "parport=0" in cmdline */ - io[0] = PARPORT_DISABLE; - return; + io[0] = PARPORT_DISABLE; + return 0; } - if (parport_setup_ptr < PARPORT_MAX) { - char *sep; - io[parport_setup_ptr] = ints[1]; - irq[parport_setup_ptr] = PARPORT_IRQ_NONE; - dma[parport_setup_ptr] = PARPORT_DMA_NONE; - if (ints[0] > 1) { - irq[parport_setup_ptr] = ints[2]; - if (ints[0] > 2) { - dma[parport_setup_ptr] = ints[3]; - goto done; - } + if (!strncmp (str, "auto", 4)) { + irq[0] = PARPORT_IRQ_AUTO; + dma[0] = PARPORT_DMA_AUTO; + return 0; + } - if (str == NULL) - goto done; + val = simple_strtoul (str, &endptr, 0); + if (endptr == str) { + printk (KERN_WARNING "parport=%s not understood\n", str); + return 1; + } - goto dma_from_str; - } - else if (str == NULL) - goto done; - else if (!strncmp(str, "auto", 4)) + if (parport_setup_ptr == PARPORT_MAX) { + printk(KERN_ERR "parport=%s ignored, too many ports\n", str); + return 1; + } + + io[parport_setup_ptr] = val; + irq[parport_setup_ptr] = PARPORT_IRQ_NONE; + dma[parport_setup_ptr] = PARPORT_DMA_NONE; + + sep = strchr (str, ','); + if (sep++) { + if (!strncmp (sep, "auto", 4)) irq[parport_setup_ptr] = PARPORT_IRQ_AUTO; - else if (strncmp(str, "none", 4) != 0) { - printk(KERN_ERR "parport: bad irq `%s'\n", str); - return; + else if (strncmp (sep, "none", 4)) { + val = simple_strtoul (sep, &endptr, 0); + if (endptr == sep) { + printk (KERN_WARNING + "parport=%s: irq not understood\n", + str); + return 1; + } + irq[parport_setup_ptr] = val; } + } - if ((sep = strchr(str, ',')) == NULL) goto done; - str = sep+1; - dma_from_str: - if (!strncmp(str, "auto", 4)) + sep = strchr (sep, ','); + if (sep++) { + if (!strncmp (sep, "auto", 4)) dma[parport_setup_ptr] = PARPORT_DMA_AUTO; - else if (strncmp(str, "none", 4) != 0) { - char *ep; - dma[parport_setup_ptr] = simple_strtoul(str, &ep, 0); - if (ep == str) { - printk(KERN_ERR "parport: bad dma `%s'\n", - str); - return; + else if (strncmp (sep, "none", 4)) { + val = simple_strtoul (sep, &endptr, 0); + if (endptr == sep) { + printk (KERN_WARNING + "parport=%s: dma not understood\n", + str); + return 1; } + dma[parport_setup_ptr] = val; } - done: - parport_setup_ptr++; - } else - printk(KERN_ERR "parport=%s ignored, too many ports\n", str); + } + + parport_setup_ptr++; + return 0; } + +__setup ("parport=", parport_setup); + #endif #ifdef MODULE @@ -113,7 +128,7 @@ #else -__initfunc(int parport_init(void)) +int __init parport_init (void) { if (io[0] == PARPORT_DISABLE) return 1; @@ -139,6 +154,9 @@ #endif return 0; } + +__initcall (parport_init); + #endif /* Exported symbols for modules. */ diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_amiga.c linux/drivers/parport/parport_amiga.c --- v2.3.12/linux/drivers/parport/parport_amiga.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/parport_amiga.c Mon Aug 9 12:32:28 1999 @@ -25,7 +25,7 @@ #ifdef DEBUG #define DPRINTK printk #else -static inline int DPRINTK() {return 0;} +#define DPRINTK(format, args...) #endif static struct parport *this_port = NULL; @@ -48,10 +48,6 @@ { unsigned char ret = 0; - if (control & PARPORT_CONTROL_DIRECTION) /* XXX: What is this? */ - ; - if (control & PARPORT_CONTROL_INTEN) /* XXX: What is INTEN? */ - ; if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */ ; if (control & PARPORT_CONTROL_INIT) /* INITP */ @@ -66,7 +62,7 @@ static unsigned char control_amiga_to_pc(unsigned char control) { - return PARPORT_CONTROL_INTEN | PARPORT_CONTROL_SELECT | + return PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE; /* fake value: interrupt enable, select in, no reset, no autolf, no strobe - seems to be closest the wiring diagram */ @@ -127,12 +123,6 @@ return ret; } -static void amiga_write_status( struct parport *p, unsigned char status) -{ -DPRINTK("write_status %02x\n",status); - ciab.pra |= (ciab.pra & 0xf8) | status_pc_to_amiga(status); -} - static unsigned char amiga_read_status(struct parport *p) { unsigned char status; @@ -142,20 +132,13 @@ return status; } -static void amiga_change_mode( struct parport *p, int m) -{ - /* XXX: This port only has one mode, and I am - not sure about the corresponding PC-style mode*/ -} - /* as this ports irq handling is already done, we use a generic funktion */ static void amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs) { parport_generic_irq(irq, (struct parport *) dev_id, regs); } - -static void amiga_init_state(struct parport_state *s) +static void amiga_init_state(struct pardevice *dev, struct parport_state *s) { s->u.amiga.data = 0; s->u.amiga.datadir = 255; @@ -215,8 +198,6 @@ NULL, /* data_forward */ NULL, /* data_reverse */ - amiga_interrupt, - amiga_init_state, amiga_save_state, amiga_restore_state, @@ -224,18 +205,18 @@ amiga_inc_use_count, amiga_dec_use_count, - parport_ieee1284_epp_write_data, - parport_ieee1284_epp_read_data, /* impossible? */ - parport_ieee1284_epp_write_addr, - parport_ieee1284_epp_read_addr, /* impossible? */ - - parport_ieee1284_ecp_write_data, - parport_ieee1284_ecp_read_data, /* impossible? */ - parport_ieee1284_ecp_write_addr, - - parport_ieee1284_write_compat, /* FIXME - need to write amiga one */ - parport_ieee1284_read_nibble, - parport_ieee1284_read_byte, /* impossible? */ + NULL, /* epp_write_data */ + NULL, /* epp_read_data */ + NULL, /* epp_write_addr */ + NULL, /* epp_read_addr */ + + NULL, /* ecp_write_data */ + NULL, /* ecp_read_data */ + NULL, /* ecp_write_addr */ + + NULL, /* compat_write_data */ + NULL, /* nibble_read_data */ + NULL, /* byte_read_data */ }; /* ----------- Initialisation code --------------------------------- */ @@ -251,20 +232,17 @@ IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE, &pp_amiga_ops))) return 0; - this_port = p; - printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); - /* XXX: set operating mode */ - parport_proc_register(p); - if (request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, - p->name, p)) { + if (!request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p)) { parport_unregister_port (p); return 0; } - if (parport_probe_hook) - (*parport_probe_hook)(p); + this_port = p; + printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); + /* XXX: set operating mode */ + parport_proc_register(p); - parport_announce_port (p); + parport_announce_port(p); return 1; @@ -285,8 +263,8 @@ void cleanup_module(void) { - if (p->irq != PARPORT_IRQ_NONE) - free_irq(IRQ_AMIGA_CIAA_FLG, p); + if (this_port->irq != PARPORT_IRQ_NONE) + free_irq(IRQ_MFP_BUSY, this_port); parport_proc_unregister(this_port); parport_unregister_port(this_port); } diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_arc.c linux/drivers/parport/parport_arc.c --- v2.3.12/linux/drivers/parport/parport_arc.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/parport_arc.c Thu Aug 5 14:23:14 1999 @@ -96,8 +96,6 @@ arc_data_forward, arc_data_reverse, - arc_interrupt, - arc_init_state, arc_save_state, arc_restore_state, diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_atari.c linux/drivers/parport/parport_atari.c --- v2.3.12/linux/drivers/parport/parport_atari.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/parport_atari.c Mon Aug 9 12:32:28 1999 @@ -92,7 +92,7 @@ } static void -parport_atari_init_state(struct parport_state *s) +parport_atari_init_state(struct pardevice *d, struct parport_state *s) { } @@ -140,8 +140,6 @@ NULL, /* data_forward - FIXME */ NULL, /* data_reverse - FIXME */ - parport_atari_interrupt, - parport_atari_init_state, parport_atari_save_state, parport_atari_restore_state, @@ -149,18 +147,18 @@ parport_atari_inc_use_count, parport_atari_dec_use_count, - parport_ieee1284_epp_write_data, - parport_ieee1284_epp_read_data, - parport_ieee1284_epp_write_addr, - parport_ieee1284_epp_read_addr, - - parport_ieee1284_ecp_write_data, - parport_ieee1284_ecp_read_data, - parport_ieee1284_ecp_write_addr, - - parport_ieee1284_write_compat, - parport_ieee1284_read_nibble, - parport_ieee1284_read_byte, + NULL, /* epp_write_data */ + NULL, /* epp_read_data */ + NULL, /* epp_write_addr */ + NULL, /* epp_read_addr */ + + NULL, /* ecp_write_data */ + NULL, /* ecp_read_data */ + NULL, /* ecp_write_addr */ + + NULL, /* compat_write_data */ + NULL, /* nibble_read_data */ + NULL, /* byte_read_data */ }; @@ -221,8 +219,8 @@ void cleanup_module(void) { - if (p->irq != PARPORT_IRQ_NONE) - free_irq(IRQ_MFP_BUSY, p); + if (this_port->irq != PARPORT_IRQ_NONE) + free_irq(IRQ_MFP_BUSY, this_port); parport_proc_unregister(this_port); parport_unregister_port(this_port); } diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_mfc3.c linux/drivers/parport/parport_mfc3.c --- v2.3.12/linux/drivers/parport/parport_mfc3.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/parport_mfc3.c Thu Aug 5 14:23:14 1999 @@ -290,8 +290,6 @@ NULL, /* data_forward - FIXME */ NULL, /* data_reverse - FIXME */ - mfc3_interrupt, - mfc3_init_state, mfc3_save_state, mfc3_restore_state, diff -u --recursive --new-file v2.3.12/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.3.12/linux/drivers/parport/parport_pc.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/parport_pc.c Mon Aug 9 11:37:37 1999 @@ -10,7 +10,6 @@ * * Cleaned up include files - Russell King * DMA support - Bert De Jonghe - * Better EPP probing - Carlos Henrique Bauer */ /* This driver should work with any hardware that is broadly compatible @@ -34,6 +33,9 @@ * only in register addresses (eg because your registers are on 32-bit * word boundaries) then you can alter the constants in parport_pc.h to * accomodate this. + * + * Note that the ECP registers may not start at offset 0x400 for PCI cards, + * but rather will start at port->base_hi. */ #include @@ -74,7 +76,7 @@ outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb)); } -#ifdef CONFIG_PARPORT_1284 +#if defined(CONFIG_PARPORT_1284) || defined(CONFIG_PARPORT_PC_FIFO) /* Safely change the mode bits in the ECR */ static int change_mode(struct parport *p, int m) { @@ -179,7 +181,7 @@ return residue; } -#endif /* IEEE 1284 support */ +#endif /* IEEE 1284 support or FIFO support */ /* * Clear TIMEOUT BIT in EPP MODE @@ -229,12 +231,16 @@ unsigned char __frob_control (struct parport *p, unsigned char mask, unsigned char val) { + const unsigned char wm = (PARPORT_CONTROL_STROBE | + PARPORT_CONTROL_AUTOFD | + PARPORT_CONTROL_INIT | + PARPORT_CONTROL_SELECT); struct parport_pc_private *priv = p->physport->private_data; unsigned char ctr = priv->ctr; ctr = (ctr & ~mask) ^ val; ctr &= priv->ctr_writable; /* only write writable bits. */ outb (ctr, CONTROL (p)); - return priv->ctr = ctr; /* update soft copy */ + return priv->ctr = ctr & wm; /* update soft copy */ } void parport_pc_write_control(struct parport *p, unsigned char d) @@ -939,7 +945,6 @@ parport_pc_data_forward, parport_pc_data_reverse, - parport_pc_interrupt, parport_pc_init_state, parport_pc_save_state, parport_pc_restore_state, @@ -966,7 +971,7 @@ /* * Checks for port existence, all ports support SPP MODE */ -static int __init parport_SPP_supported(struct parport *pb) +static int __maybe_init parport_SPP_supported(struct parport *pb) { unsigned char r, w; @@ -1043,7 +1048,7 @@ * two bits of ECR aren't writable, so we check by writing ECR and * reading it back to see if it's what we expect. */ -static int __init parport_ECR_present(struct parport *pb) +static int __maybe_init parport_ECR_present(struct parport *pb) { struct parport_pc_private *priv = pb->private_data; unsigned char r = 0xc; @@ -1096,7 +1101,7 @@ * be misdetected here is rather academic. */ -static int __init parport_PS2_supported(struct parport *pb) +static int __maybe_init parport_PS2_supported(struct parport *pb) { int ok = 0; @@ -1124,7 +1129,7 @@ return ok; } -static int __init parport_ECP_supported(struct parport *pb) +static int __maybe_init parport_ECP_supported(struct parport *pb) { int i; int config; @@ -1235,7 +1240,7 @@ return 1; } -static int __init parport_ECPPS2_supported(struct parport *pb) +static int __maybe_init parport_ECPPS2_supported(struct parport *pb) { const struct parport_pc_private *priv = pb->private_data; int result; @@ -1255,7 +1260,7 @@ /* EPP mode detection */ -static int __init parport_EPP_supported(struct parport *pb) +static int __maybe_init parport_EPP_supported(struct parport *pb) { const struct parport_pc_private *priv = pb->private_data; @@ -1290,15 +1295,15 @@ pb->modes |= PARPORT_MODE_EPP; /* Set up access functions to use EPP hardware. */ - parport_pc_ops.epp_read_data = parport_pc_epp_read_data; - parport_pc_ops.epp_write_data = parport_pc_epp_write_data; - parport_pc_ops.epp_read_addr = parport_pc_epp_read_addr; - parport_pc_ops.epp_write_addr = parport_pc_epp_write_addr; + pb->ops->epp_read_data = parport_pc_epp_read_data; + pb->ops->epp_write_data = parport_pc_epp_write_data; + pb->ops->epp_read_addr = parport_pc_epp_read_addr; + pb->ops->epp_write_addr = parport_pc_epp_write_addr; return 1; } -static int __init parport_ECPEPP_supported(struct parport *pb) +static int __maybe_init parport_ECPEPP_supported(struct parport *pb) { struct parport_pc_private *priv = pb->private_data; int result; @@ -1317,10 +1322,10 @@ if (result) { /* Set up access functions to use ECP+EPP hardware. */ - parport_pc_ops.epp_read_data = parport_pc_ecpepp_read_data; - parport_pc_ops.epp_write_data = parport_pc_ecpepp_write_data; - parport_pc_ops.epp_read_addr = parport_pc_ecpepp_read_addr; - parport_pc_ops.epp_write_addr = parport_pc_ecpepp_write_addr; + pb->ops->epp_read_data = parport_pc_ecpepp_read_data; + pb->ops->epp_write_data = parport_pc_ecpepp_write_data; + pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr; + pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr; } return result; @@ -1329,18 +1334,18 @@ #else /* No IEEE 1284 support */ /* Don't bother probing for modes we know we won't use. */ -static int __init parport_PS2_supported(struct parport *pb) { return 0; } -static int __init parport_ECP_supported(struct parport *pb) { return 0; } -static int __init parport_EPP_supported(struct parport *pb) { return 0; } -static int __init parport_ECPEPP_supported(struct parport *pb) { return 0; } -static int __init parport_ECPPS2_supported(struct parport *pb) { return 0; } +static int __maybe_init parport_PS2_supported(struct parport *pb) { return 0; } +static int __maybe_init parport_ECP_supported(struct parport *pb) { return 0; } +static int __maybe_init parport_EPP_supported(struct parport *pb) { return 0; } +static int __maybe_init parport_ECPEPP_supported(struct parport *pb){return 0;} +static int __maybe_init parport_ECPPS2_supported(struct parport *pb){return 0;} #endif /* No IEEE 1284 support */ /* --- IRQ detection -------------------------------------- */ /* Only if supports ECP mode */ -static int __init programmable_irq_support(struct parport *pb) +static int __maybe_init programmable_irq_support(struct parport *pb) { int irq, intrLine; unsigned char oecr = inb (ECONTROL (pb)); @@ -1357,7 +1362,7 @@ return irq; } -static int __init irq_probe_ECP(struct parport *pb) +static int __maybe_init irq_probe_ECP(struct parport *pb) { int i; unsigned long irqs; @@ -1386,7 +1391,7 @@ * This detection seems that only works in National Semiconductors * This doesn't work in SMC, LGS, and Winbond */ -static int __init irq_probe_EPP(struct parport *pb) +static int __maybe_init irq_probe_EPP(struct parport *pb) { #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; @@ -1426,7 +1431,7 @@ #endif /* Advanced detection */ } -static int __init irq_probe_SPP(struct parport *pb) +static int __maybe_init irq_probe_SPP(struct parport *pb) { /* Don't even try to do this. */ return PARPORT_IRQ_NONE; @@ -1439,7 +1444,7 @@ * When ECP is available we can autoprobe for IRQs. * NOTE: If we can autoprobe it, we can register the IRQ. */ -static int __init parport_irq_probe(struct parport *pb) +static int __maybe_init parport_irq_probe(struct parport *pb) { const struct parport_pc_private *priv = pb->private_data; @@ -1473,7 +1478,7 @@ /* --- DMA detection -------------------------------------- */ /* Only if supports ECP mode */ -static int __init programmable_dma_support (struct parport *p) +static int __maybe_init programmable_dma_support (struct parport *p) { unsigned char oecr = inb (ECONTROL (p)); int dma; @@ -1488,7 +1493,7 @@ return dma; } -static int __init parport_dma_probe (struct parport *p) +static int __maybe_init parport_dma_probe (struct parport *p) { const struct parport_pc_private *priv = p->private_data; if (priv->ecr) @@ -1499,27 +1504,27 @@ /* --- Initialisation code -------------------------------- */ -static int __init probe_one_port(unsigned long int base, - unsigned long int base_hi, - int irq, int dma) +struct parport *__maybe_init parport_pc_probe_port (unsigned long int base, + unsigned long int base_hi, + int irq, int dma) { struct parport_pc_private *priv; struct parport_operations *ops; struct parport tmp; struct parport *p = &tmp; int probedirq = PARPORT_IRQ_NONE; - if (check_region(base, 3)) return 0; + if (check_region(base, 3)) return NULL; priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); if (!priv) { printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); - return 0; + return NULL; } ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); if (!ops) { printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", base); kfree (priv); - return 0; + return NULL; } memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations)); priv->ctr = 0xc; @@ -1531,7 +1536,7 @@ p->base_hi = base_hi; p->irq = irq; p->dma = dma; - p->modes = PARPORT_MODE_PCSPP; + p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; p->ops = ops; p->private_data = priv; p->physport = p; @@ -1550,7 +1555,7 @@ if (!parport_SPP_supported (p)) { /* No port. */ kfree (priv); - return 0; + return NULL; } parport_PS2_supported (p); @@ -1559,7 +1564,7 @@ PARPORT_DMA_NONE, ops))) { kfree (priv); kfree (ops); - return 0; + return NULL; } p->base_hi = base_hi; @@ -1591,21 +1596,22 @@ } if (p->dma == PARPORT_DMA_AUTO) p->dma = PARPORT_DMA_NONE; - if (p->dma != PARPORT_DMA_NONE) - printk(", dma %d", p->dma); #ifdef CONFIG_PARPORT_PC_FIFO if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) { - parport_pc_ops.compat_write_data = - parport_pc_compat_write_block_pio; + p->ops->compat_write_data = parport_pc_compat_write_block_pio; #ifdef CONFIG_PARPORT_1284 - parport_pc_ops.ecp_write_data = - parport_pc_ecp_write_block_pio; + p->ops->ecp_write_data = parport_pc_ecp_write_block_pio; #endif /* IEEE 1284 support */ - if (p->dma != PARPORT_DMA_NONE) + if (p->dma != PARPORT_DMA_NONE) { + printk(", dma %d", p->dma); p->modes |= PARPORT_MODE_DMA; - printk(", using FIFO"); + } + else printk(", using FIFO"); } + else + /* We can't use the DMA channel after all. */ + p->dma = PARPORT_DMA_NONE; #endif /* Allowed to use FIFO/DMA */ printk(" ["); @@ -1648,7 +1654,8 @@ p->name, p->dma); p->dma = PARPORT_DMA_NONE; } else { - priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 1); + priv->dma_buf = + (char *)__get_dma_pages(GFP_KERNEL, 0); if (! priv->dma_buf) { printk (KERN_WARNING "%s: " "cannot get buffer for DMA, " @@ -1668,7 +1675,7 @@ /* * Put the ECP detected port in PS2 mode. */ - outb (0x24, ECONTROL (p)); + outb (0x34, ECONTROL (p)); parport_pc_write_data(p, 0); parport_pc_data_forward (p); @@ -1684,7 +1691,7 @@ know about it. */ parport_announce_port (p); - return 1; + return p; } /* Look for PCI parallel port cards. */ @@ -1746,6 +1753,7 @@ { 0, } }; + struct pci_dev *pcidev; int count = 0; int i; @@ -1753,7 +1761,7 @@ return 0; for (i = 0; cards[i].vendor; i++) { - struct pci_dev *pcidev = NULL; + pcidev = NULL; while ((pcidev = pci_find_device (cards[i].vendor, cards[i].device, pcidev)) != NULL) { @@ -1761,24 +1769,58 @@ for (n = 0; n < cards[i].numports; n++) { unsigned long lo = cards[i].addr[n].lo; unsigned long hi = cards[i].addr[n].hi; - unsigned long io_lo = pcidev->base_address[lo]; - unsigned long io_hi = ((hi < 0) ? 0 : - pcidev->base_address[hi]); - io_lo &= PCI_BASE_ADDRESS_IO_MASK; - io_hi &= PCI_BASE_ADDRESS_IO_MASK; - if (irq == PARPORT_IRQ_AUTO) - count += probe_one_port (io_lo, io_hi, - pcidev->irq, - dma); - else - count += probe_one_port (io_lo, io_hi, - irq, dma); + unsigned long io_lo, io_hi; + io_lo = pcidev->resource[lo].start; + io_hi = ((hi < 0) ? 0 : + pcidev->resource[hi].start); + if (irq == PARPORT_IRQ_AUTO) { + if (parport_pc_probe_port (io_lo, + io_hi, + pcidev->irq, + dma)) + count++; + } else if (parport_pc_probe_port (io_lo, io_hi, + irq, dma)) + count++; } } } + /* Look for parallel controllers that we don't know about. */ + for (pcidev = pci_devices; pcidev; pcidev = pcidev->next) { + const int class_noprogif = pcidev->class & ~0xff; + if (class_noprogif != (PCI_CLASS_COMMUNICATION_PARALLEL << 8)) + continue; + + for (i = 0; cards[i].vendor; i++) + if ((cards[i].vendor == pcidev->vendor) && + (cards[i].device == pcidev->device)) + break; + if (cards[i].vendor) + /* We know about this one. */ + continue; + + printk (KERN_INFO + "Unknown PCI parallel I/O card (%04x/%04x)\n" + "Please send 'lspci' output to " + "tim@cyberelk.demon.co.uk\n", + pcidev->vendor, pcidev->device); + } + return count; } + +/* Exported symbols. */ +#ifdef CONFIG_PARPORT_PC_PCMCIA + +/* parport_cs needs this in order to dyncamically get us to find ports. */ +EXPORT_SYMBOL (parport_pc_probe_port); + +#else + +EXPORT_NO_SYMBOLS; + +#endif #ifdef MODULE static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; diff -u --recursive --new-file v2.3.12/linux/drivers/parport/share.c linux/drivers/parport/share.c --- v2.3.12/linux/drivers/parport/share.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/parport/share.c Thu Aug 5 14:23:14 1999 @@ -48,7 +48,6 @@ static unsigned char dead_frob_lines (struct parport *p, unsigned char b, unsigned char c) { return 0; } static void dead_onearg (struct parport *p){} -static void dead_irq (int i, void *p, struct pt_regs *r) { } static void dead_initstate (struct pardevice *d, struct parport_state *s) { } static void dead_state (struct parport *p, struct parport_state *s) { } static void dead_noargs (void) { } @@ -67,7 +66,6 @@ dead_onearg, /* disable_irq */ dead_onearg, /* data_forward */ dead_onearg, /* data_reverse */ - dead_irq, dead_initstate, /* init_state */ dead_state, dead_state, diff -u --recursive --new-file v2.3.12/linux/drivers/pci/Makefile linux/drivers/pci/Makefile --- v2.3.12/linux/drivers/pci/Makefile Tue Apr 28 22:41:33 1998 +++ linux/drivers/pci/Makefile Thu Aug 5 18:44:28 1999 @@ -15,7 +15,7 @@ ifeq ($(CONFIG_MODULES),y) O_TARGET = pci_syms.o OX_OBJS = pcisyms.o -O_OBJS = pci.o +O_OBJS = pci.o names.o L_OBJS := pci_syms.o else L_OBJS := pci.o @@ -23,9 +23,6 @@ ifdef CONFIG_PROC_FS L_OBJS += proc.o -ifdef CONFIG_PCI_OLD_PROC -L_OBJS += oldproc.o -endif endif ifdef CONFIG_PCI_QUIRKS diff -u --recursive --new-file v2.3.12/linux/drivers/pci/devlist.h linux/drivers/pci/devlist.h --- v2.3.12/linux/drivers/pci/devlist.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/pci/devlist.h Thu Aug 5 18:44:28 1999 @@ -0,0 +1,962 @@ +VENDOR( COMPAQ, "Compaq" ) + DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p") + DEVICE( COMPAQ, COMPAQ_SMART2P, "Smart-2/P RAID Controller") + DEVICE( COMPAQ, COMPAQ_NETEL100,"Netelligent 10/100") + DEVICE( COMPAQ, COMPAQ_NETEL10, "Netelligent 10") + DEVICE( COMPAQ, COMPAQ_NETFLEX3I,"NetFlex 3") + DEVICE( COMPAQ, COMPAQ_NETEL100D,"Netelligent 10/100 Dual") + DEVICE( COMPAQ, COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant") + DEVICE( COMPAQ, COMPAQ_NETEL100I,"Netelligent 10/100 Integrated") + DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN") + DEVICE( COMPAQ, COMPAQ_NETFLEX3B,"NetFlex 3 BNC") +ENDVENDOR() + +VENDOR( NCR, "NCR" ) + DEVICE( NCR, NCR_53C810, "53c810") + DEVICE( NCR, NCR_53C820, "53c820") + DEVICE( NCR, NCR_53C825, "53c825") + DEVICE( NCR, NCR_53C815, "53c815") + DEVICE( NCR, NCR_53C860, "53c860") + DEVICE( NCR, NCR_53C896, "53c896") + DEVICE( NCR, NCR_53C895, "53c895") + DEVICE( NCR, NCR_53C885, "53c885") + DEVICE( NCR, NCR_53C875, "53c875") + DEVICE( NCR, NCR_53C875J, "53c875J") +ENDVENDOR() + +VENDOR( ATI, "ATI" ) + DEVICE( ATI, ATI_68800, "68800AX") + DEVICE( ATI, ATI_215CT222, "215CT222") + DEVICE( ATI, ATI_210888CX, "210888CX") + DEVICE( ATI, ATI_215GB, "Mach64 GB") + DEVICE( ATI, ATI_215GD, "Mach64 GD (Rage Pro)") + DEVICE( ATI, ATI_215GI, "Mach64 GI (Rage Pro)") + DEVICE( ATI, ATI_215GP, "Mach64 GP (Rage Pro)") + DEVICE( ATI, ATI_215GQ, "Mach64 GQ (Rage Pro)") + DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)") + DEVICE( ATI, ATI_215GTB, "Mach64 GTB (Rage II)") + DEVICE( ATI, ATI_210888GX, "210888GX") + DEVICE( ATI, ATI_215LG, "Mach64 LG (Rage Pro)") + DEVICE( ATI, ATI_264LT, "Mach64 LT") + DEVICE( ATI, ATI_264VT, "Mach64 VT") +ENDVENDOR() + +VENDOR( VLSI, "VLSI" ) + DEVICE( VLSI, VLSI_82C592, "82C592-FC1") + DEVICE( VLSI, VLSI_82C593, "82C593-FC1") + DEVICE( VLSI, VLSI_82C594, "82C594-AFC2") + DEVICE( VLSI, VLSI_82C597, "82C597-AFC2") + DEVICE( VLSI, VLSI_82C541, "82C541 Lynx") + DEVICE( VLSI, VLSI_82C543, "82C543 Lynx ISA") + DEVICE( VLSI, VLSI_82C532, "82C532") + DEVICE( VLSI, VLSI_82C534, "82C534") + DEVICE( VLSI, VLSI_82C535, "82C535") + DEVICE( VLSI, VLSI_82C147, "82C147") + DEVICE( VLSI, VLSI_VAS96011, "VAS96011 (Golden Gate II)") +ENDVENDOR() + +VENDOR( ADL, "Avance Logic" ) + DEVICE( ADL, ADL_2301, "2301") +ENDVENDOR() + +VENDOR( NS, "NS" ) + DEVICE( NS, NS_87415, "87415") + DEVICE( NS, NS_87410, "87410") +ENDVENDOR() + +VENDOR( TSENG, "Tseng'Lab" ) + DEVICE( TSENG, TSENG_W32P_2, "ET4000W32P") + DEVICE( TSENG, TSENG_W32P_b, "ET4000W32P rev B") + DEVICE( TSENG, TSENG_W32P_c, "ET4000W32P rev C") + DEVICE( TSENG, TSENG_W32P_d, "ET4000W32P rev D") + DEVICE( TSENG, TSENG_ET6000, "ET6000") +ENDVENDOR() + +VENDOR( WEITEK, "Weitek" ) + DEVICE( WEITEK, WEITEK_P9000, "P9000") + DEVICE( WEITEK, WEITEK_P9100, "P9100") +ENDVENDOR() + +VENDOR( DEC, "DEC" ) + DEVICE( DEC, DEC_BRD, "DC21050") + DEVICE( DEC, DEC_TULIP, "DC21040") + DEVICE( DEC, DEC_TGA, "TGA") + DEVICE( DEC, DEC_TULIP_FAST, "DC21140") + DEVICE( DEC, DEC_TGA2, "TGA2") + DEVICE( DEC, DEC_FDDI, "DEFPA") + DEVICE( DEC, DEC_TULIP_PLUS, "DC21041") + DEVICE( DEC, DEC_21142, "DC21142") + DEVICE( DEC, DEC_21052, "DC21052") + DEVICE( DEC, DEC_21150, "DC21150") + DEVICE( DEC, DEC_21152, "DC21152") + DEVICE( DEC, DEC_21153, "DC21153") + DEVICE( DEC, DEC_21154, "DC21154") +ENDVENDOR() + +VENDOR( CIRRUS, "Cirrus Logic" ) + DEVICE( CIRRUS, CIRRUS_7548, "GD 7548") + DEVICE( CIRRUS, CIRRUS_5430, "GD 5430") + DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434") + DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434") + DEVICE( CIRRUS, CIRRUS_5436, "GD 5436") + DEVICE( CIRRUS, CIRRUS_5446, "GD 5446") + DEVICE( CIRRUS, CIRRUS_5480, "GD 5480") + DEVICE( CIRRUS, CIRRUS_5464, "GD 5464") + DEVICE( CIRRUS, CIRRUS_5465, "GD 5465") + DEVICE( CIRRUS, CIRRUS_6729, "CL 6729") + DEVICE( CIRRUS, CIRRUS_6832, "PD 6832") + DEVICE( CIRRUS, CIRRUS_7542, "CL 7542") + DEVICE( CIRRUS, CIRRUS_7543, "CL 7543") + DEVICE( CIRRUS, CIRRUS_7541, "CL 7541") +ENDVENDOR() + +VENDOR( IBM, "IBM" ) + DEVICE( IBM, IBM_FIRE_CORAL, "Fire Coral") + DEVICE( IBM, IBM_TR, "Token Ring") + DEVICE( IBM, IBM_82G2675, "82G2675") + DEVICE( IBM, IBM_MCA, "MicroChannel") + DEVICE( IBM, IBM_82351, "82351") + DEVICE( IBM, IBM_PYTHON, "Python") + DEVICE( IBM, IBM_SERVERAID, "ServeRAID") + DEVICE( IBM, IBM_TR_WAKE, "Wake On LAN Token Ring") + DEVICE( IBM, IBM_MPIC, "MPIC-2 Interrupt Controller") + DEVICE( IBM, IBM_3780IDSP, "MWave DSP") + DEVICE( IBM, IBM_MPIC_2, "MPIC-2 ASIC Interrupt Controller") +ENDVENDOR() + +VENDOR( WD, "Western Digital" ) + DEVICE( WD, WD_7197, "WD 7197") +ENDVENDOR() + +VENDOR( AMD, "AMD" ) + DEVICE( AMD, AMD_LANCE, "79C970") + DEVICE( AMD, AMD_SCSI, "53C974") +ENDVENDOR() + +VENDOR( TRIDENT, "Trident" ) + DEVICE( TRIDENT, TRIDENT_9397, "Cyber9397") + DEVICE( TRIDENT, TRIDENT_9420, "TG 9420") + DEVICE( TRIDENT, TRIDENT_9440, "TG 9440") + DEVICE( TRIDENT, TRIDENT_9660, "TG 9660 / Cyber9385") + DEVICE( TRIDENT, TRIDENT_9750, "Image 975") +ENDVENDOR() + +VENDOR( AI, "Acer Incorporated" ) + DEVICE( AI, AI_M1435, "M1435") +ENDVENDOR() + +VENDOR( MATROX, "Matrox" ) + DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085") + DEVICE( MATROX, MATROX_MIL, "Millennium") + DEVICE( MATROX, MATROX_MYS, "Mystique") + DEVICE( MATROX, MATROX_MIL_2, "Millennium II") + DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP") + DEVICE( MATROX, MATROX_G200_PCI,"G200 PCI") + DEVICE( MATROX, MATROX_G200_AGP,"G200 AGP") + DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression") + DEVICE( MATROX, MATROX_G100_MM, "G100 multi monitor") + DEVICE( MATROX, MATROX_G100_AGP,"G100 AGP") +ENDVENDOR() + +VENDOR( CT, "Chips & Technologies" ) + DEVICE( CT, CT_65545, "65545") + DEVICE( CT, CT_65548, "65548") + DEVICE( CT, CT_65550, "65550") + DEVICE( CT, CT_65554, "65554") + DEVICE( CT, CT_65555, "65555") +ENDVENDOR() + +VENDOR( MIRO, "Miro" ) + DEVICE( MIRO, MIRO_36050, "ZR36050") +ENDVENDOR() + +VENDOR( NEC, "NEC" ) + DEVICE( NEC, NEC_PCX2, "PowerVR PCX2") +ENDVENDOR() + +VENDOR( FD, "Future Domain" ) + DEVICE( FD, FD_36C70, "TMC-18C30") +ENDVENDOR() + +VENDOR( SI, "Silicon Integrated Systems" ) + DEVICE( SI, SI_5591_AGP, "5591/5592 AGP") + DEVICE( SI, SI_6202, "6202") + DEVICE( SI, SI_503, "85C503") + DEVICE( SI, SI_ACPI, "ACPI") + DEVICE( SI, SI_5597_VGA, "5597/5598 VGA") + DEVICE( SI, SI_6205, "6205") + DEVICE( SI, SI_501, "85C501") + DEVICE( SI, SI_496, "85C496") + DEVICE( SI, SI_601, "85C601") + DEVICE( SI, SI_5107, "5107") + DEVICE( SI, SI_5511, "85C5511") + DEVICE( SI, SI_5513, "85C5513") + DEVICE( SI, SI_5571, "5571") + DEVICE( SI, SI_5591, "5591/5592 Host") + DEVICE( SI, SI_5597, "5597/5598 Host") + DEVICE( SI, SI_7001, "7001 USB") +ENDVENDOR() + +VENDOR( HP, "Hewlett Packard" ) + DEVICE( HP, HP_J2585A, "J2585A") + DEVICE( HP, HP_J2585B, "J2585B (Lassen)") +ENDVENDOR() + +VENDOR( PCTECH, "PCTECH" ) + DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)") + DEVICE( PCTECH, PCTECH_RZ1001, "RZ1001 (buggy?)") + DEVICE( PCTECH, PCTECH_SAMURAI_0,"Samurai 0") + DEVICE( PCTECH, PCTECH_SAMURAI_1,"Samurai 1") + DEVICE( PCTECH, PCTECH_SAMURAI_IDE,"Samurai IDE") +ENDVENDOR() + +VENDOR( DPT, "DPT" ) + DEVICE( DPT, DPT, "SmartCache/Raid") +ENDVENDOR() + +VENDOR( OPTI, "OPTi" ) + DEVICE( OPTI, OPTI_92C178, "92C178") + DEVICE( OPTI, OPTI_82C557, "82C557 Viper-M") + DEVICE( OPTI, OPTI_82C558, "82C558 Viper-M ISA+IDE") + DEVICE( OPTI, OPTI_82C621, "82C621") + DEVICE( OPTI, OPTI_82C700, "82C700") + DEVICE( OPTI, OPTI_82C701, "82C701 FireStar Plus") + DEVICE( OPTI, OPTI_82C814, "82C814 Firebridge 1") + DEVICE( OPTI, OPTI_82C822, "82C822") + DEVICE( OPTI, OPTI_82C825, "82C825 Firebridge 2") +ENDVENDOR() + +VENDOR( SGS, "SGS Thomson" ) + DEVICE( SGS, SGS_2000, "STG 2000X") + DEVICE( SGS, SGS_1764, "STG 1764X") +ENDVENDOR() + +VENDOR( BUSLOGIC, "BusLogic" ) + DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC") + DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER, "MultiMaster") + DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint") +ENDVENDOR() + +VENDOR( TI, "Texas Instruments" ) + DEVICE( TI, TI_TVP4010, "TVP4010 Permedia") + DEVICE( TI, TI_TVP4020, "TVP4020 Permedia 2") + DEVICE( TI, TI_PCI1130, "PCI1130") + DEVICE( TI, TI_PCI1131, "PCI1131") + DEVICE( TI, TI_PCI1250, "PCI1250") +ENDVENDOR() + +VENDOR( OAK, "OAK" ) + DEVICE( OAK, OAK_OTI107, "OTI107") +ENDVENDOR() + +VENDOR( WINBOND2, "Winbond" ) + DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI") +ENDVENDOR() + +VENDOR( MOTOROLA, "Motorola" ) + DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle") + DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle") + DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven") + DEVICE( MOTOROLA, MOTOROLA_FALCON,"Falcon") + DEVICE( MOTOROLA, MOTOROLA_CPX8216,"CPX8216") +ENDVENDOR() + +VENDOR( PROMISE, "Promise Technology" ) + DEVICE( PROMISE, PROMISE_20246, "IDE UltraDMA/33") + DEVICE( PROMISE, PROMISE_20262, "IDE UltraDMA/66") + DEVICE( PROMISE, PROMISE_5300, "DC5030") +ENDVENDOR() + +VENDOR( N9, "Number Nine" ) + DEVICE( N9, N9_I128, "Imagine 128") + DEVICE( N9, N9_I128_2, "Imagine 128v2") + DEVICE( N9, N9_I128_T2R, "Revolution 3D") +ENDVENDOR() + +VENDOR( UMC, "UMC" ) + DEVICE( UMC, UMC_UM8673F, "UM8673F") + DEVICE( UMC, UMC_UM8891A, "UM8891A") + DEVICE( UMC, UMC_UM8886BF, "UM8886BF") + DEVICE( UMC, UMC_UM8886A, "UM8886A") + DEVICE( UMC, UMC_UM8881F, "UM8881F") + DEVICE( UMC, UMC_UM8886F, "UM8886F") + DEVICE( UMC, UMC_UM9017F, "UM9017F") + DEVICE( UMC, UMC_UM8886N, "UM8886N") + DEVICE( UMC, UMC_UM8891N, "UM8891N") +ENDVENDOR() + +VENDOR( X, "X Technology" ) + DEVICE( X, X_AGX016, "ITT AGX016") +ENDVENDOR() + +VENDOR( PICOP, "PicoPower" ) + DEVICE( PICOP, PICOP_PT86C52X, "PT86C52x Vesuvius") + DEVICE( PICOP, PICOP_PT80C524, "PT80C524 Nile") +ENDVENDOR() + +VENDOR( APPLE, "Apple" ) + DEVICE( APPLE, APPLE_BANDIT, "Bandit") + DEVICE( APPLE, APPLE_GC, "Grand Central") + DEVICE( APPLE, APPLE_HYDRA, "Hydra") +ENDVENDOR() + +VENDOR( NEXGEN, "Nexgen" ) + DEVICE( NEXGEN, NEXGEN_82C501, "82C501") +ENDVENDOR() + +VENDOR( QLOGIC, "Q Logic" ) + DEVICE( QLOGIC, QLOGIC_ISP1020, "ISP1020") + DEVICE( QLOGIC, QLOGIC_ISP1022, "ISP1022") +ENDVENDOR() + +VENDOR( CYRIX, "Cyrix" ) + DEVICE( CYRIX, CYRIX_5510, "5510") + DEVICE( CYRIX, CYRIX_PCI_MASTER,"PCI Master") + DEVICE( CYRIX, CYRIX_5520, "5520") + DEVICE( CYRIX, CYRIX_5530_LEGACY,"5530 Kahlua Legacy") + DEVICE( CYRIX, CYRIX_5530_SMI, "5530 Kahlua SMI") + DEVICE( CYRIX, CYRIX_5530_IDE, "5530 Kahlua IDE") + DEVICE( CYRIX, CYRIX_5530_AUDIO,"5530 Kahlua Audio") + DEVICE( CYRIX, CYRIX_5530_VIDEO,"5530 Kahlua Video") +ENDVENDOR() + +VENDOR( LEADTEK, "Leadtek Research" ) + DEVICE( LEADTEK, LEADTEK_805, "S3 805") +ENDVENDOR() + +VENDOR( CONTAQ, "Contaq" ) + DEVICE( CONTAQ, CONTAQ_82C599, "82C599") + DEVICE( CONTAQ, CONTAQ_82C693, "82C693") +ENDVENDOR() + +VENDOR( FOREX, "Forex" ) +ENDVENDOR() + +VENDOR( OLICOM, "Olicom" ) + DEVICE( OLICOM, OLICOM_OC3136, "OC-3136/3137") + DEVICE( OLICOM, OLICOM_OC2315, "OC-2315") + DEVICE( OLICOM, OLICOM_OC2325, "OC-2325") + DEVICE( OLICOM, OLICOM_OC2183, "OC-2183/2185") + DEVICE( OLICOM, OLICOM_OC2326, "OC-2326") + DEVICE( OLICOM, OLICOM_OC6151, "OC-6151/6152") +ENDVENDOR() + +VENDOR( SUN, "Sun Microsystems" ) + DEVICE( SUN, SUN_EBUS, "PCI-EBus Bridge") + DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal Ethernet") + DEVICE( SUN, SUN_SIMBA, "Advanced PCI Bridge") + DEVICE( SUN, SUN_PBM, "PCI Bus Module") + DEVICE( SUN, SUN_SABRE, "Ultra IIi PCI") +ENDVENDOR() + +VENDOR( CMD, "CMD" ) + DEVICE( CMD, CMD_640, "640 (buggy)") + DEVICE( CMD, CMD_643, "643") + DEVICE( CMD, CMD_646, "646") + DEVICE( CMD, CMD_670, "670") +ENDVENDOR() + +VENDOR( VISION, "Vision" ) + DEVICE( VISION, VISION_QD8500, "QD-8500") + DEVICE( VISION, VISION_QD8580, "QD-8580") +ENDVENDOR() + +VENDOR( BROOKTREE, "Brooktree" ) + DEVICE( BROOKTREE, BROOKTREE_848, "Bt848") + DEVICE( BROOKTREE, BROOKTREE_849A, "Bt849") + DEVICE( BROOKTREE, BROOKTREE_878_1,"Bt878 2nd Contr. (?)") + DEVICE( BROOKTREE, BROOKTREE_878, "Bt878") + DEVICE( BROOKTREE, BROOKTREE_8474, "Bt8474") +ENDVENDOR() + +VENDOR( SIERRA, "Sierra" ) + DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64") +ENDVENDOR() + +VENDOR( SGI, "Silicon Graphics Inc" ) + DEVICE( SGI, SGI_IOC3, "IOC3") +ENDVENDOR() + +VENDOR( ACC, "ACC MICROELECTRONICS" ) + DEVICE( ACC, ACC_2056, "2056") +ENDVENDOR() + +VENDOR( WINBOND, "Winbond" ) + DEVICE( WINBOND, WINBOND_83769, "W83769F") + DEVICE( WINBOND, WINBOND_82C105, "SL82C105") + DEVICE( WINBOND, WINBOND_83C553, "W83C553") +ENDVENDOR() + +VENDOR( DATABOOK, "Databook" ) + DEVICE( DATABOOK, DATABOOK_87144, "DB87144") +ENDVENDOR() + +VENDOR( PLX, "PLX" ) + DEVICE( PLX, PLX_9050, "PCI9050 I2O") + DEVICE( PLX, PLX_9080, "PCI9080 I2O") +ENDVENDOR() + +VENDOR( MADGE, "Madge Networks" ) + DEVICE( MADGE, MADGE_MK2, "Smart 16/4 BM Mk2 Ringnode") + DEVICE( MADGE, MADGE_C155S, "Collage 155 Server") +ENDVENDOR() + +VENDOR( 3COM, "3Com" ) + DEVICE( 3COM, 3COM_3C339, "3C339 TokenRing") + DEVICE( 3COM, 3COM_3C590, "3C590 10bT") + DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX") + DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4") + DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII") + DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO") + DEVICE( 3COM, 3COM_3C900COMBO,"3C900 10b Combo") + DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX") + DEVICE( 3COM, 3COM_3C905T4, "3C905 100bT4") + DEVICE( 3COM, 3COM_3C905B_TX, "3C905B 100bTX") +ENDVENDOR() + +VENDOR( SMC, "SMC" ) + DEVICE( SMC, SMC_EPIC100, "9432 TX") +ENDVENDOR() + +VENDOR( AL, "Acer Labs" ) + DEVICE( AL, AL_M1445, "M1445") + DEVICE( AL, AL_M1449, "M1449") + DEVICE( AL, AL_M1451, "M1451") + DEVICE( AL, AL_M1461, "M1461") + DEVICE( AL, AL_M1489, "M1489") + DEVICE( AL, AL_M1511, "M1511") + DEVICE( AL, AL_M1513, "M1513") + DEVICE( AL, AL_M1521, "M1521") + DEVICE( AL, AL_M1523, "M1523") + DEVICE( AL, AL_M1531, "M1531 Aladdin IV") + DEVICE( AL, AL_M1533, "M1533 Aladdin IV") + DEVICE( AL, AL_M1541, "M1541 Aladdin V") + DEVICE( AL, AL_M1543, "M1543 Aladdin V") + DEVICE( AL, AL_M3307, "M3307 MPEG-1 decoder") + DEVICE( AL, AL_M4803, "M4803") + DEVICE( AL, AL_M5219, "M5219") + DEVICE( AL, AL_M5229, "M5229 TXpro") + DEVICE( AL, AL_M5237, "M5237 USB") + DEVICE( AL, AL_M5243, "M5243 AGP") + DEVICE( AL, AL_M7101, "M7101 PMU") +ENDVENDOR() + +VENDOR( MITSUBISHI, "Mitsubishi" ) +ENDVENDOR() + +VENDOR( SURECOM, "Surecom" ) + DEVICE( SURECOM, SURECOM_NE34, "NE-34PCI LAN") +ENDVENDOR() + +VENDOR( NEOMAGIC, "Neomagic" ) + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070") + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V") + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV") + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160") + DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+") +ENDVENDOR() + +VENDOR( ASP, "Advanced System Products" ) + DEVICE( ASP, ASP_ABP940, "ABP940") + DEVICE( ASP, ASP_ABP940U, "ABP940U") + DEVICE( ASP, ASP_ABP940UW, "ABP940UW") +ENDVENDOR() + +VENDOR( MACRONIX, "Macronix" ) + DEVICE( MACRONIX, MACRONIX_MX98713,"MX98713") + DEVICE( MACRONIX, MACRONIX_MX987x5,"MX98715 / MX98725") +ENDVENDOR() + +VENDOR( CERN, "CERN" ) + DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)") + DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)") + DEVICE( CERN, CERN_HIPPI_DST, "HIPPI destination") + DEVICE( CERN, CERN_HIPPI_SRC, "HIPPI source") +ENDVENDOR() + +VENDOR( NVIDIA, "NVidia" ) +ENDVENDOR() + +VENDOR( IMS, "IMS" ) + DEVICE( IMS, IMS_8849, "8849") +ENDVENDOR() + +VENDOR( TEKRAM2, "Tekram" ) + DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c") +ENDVENDOR() + +VENDOR( TUNDRA, "Tundra" ) + DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe") +ENDVENDOR() + +VENDOR( AMCC, "AMCC" ) + DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)") + DEVICE( AMCC, AMCC_PARASTATION,"ParaStation Interface") + DEVICE( AMCC, AMCC_S5933, "S5933 PCI44") + DEVICE( AMCC, AMCC_S5933_HEPC3,"S5933 Traquair HEPC3") +ENDVENDOR() + +VENDOR( INTERG, "Intergraphics" ) + DEVICE( INTERG, INTERG_1680, "IGA-1680") + DEVICE( INTERG, INTERG_1682, "IGA-1682") +ENDVENDOR() + +VENDOR( REALTEK, "Realtek" ) + DEVICE( REALTEK, REALTEK_8029, "8029") + DEVICE( REALTEK, REALTEK_8129, "8129") + DEVICE( REALTEK, REALTEK_8139, "8139") +ENDVENDOR() + +VENDOR( TRUEVISION, "Truevision" ) + DEVICE( TRUEVISION, TRUEVISION_T1000,"TARGA 1000") +ENDVENDOR() + +VENDOR( INIT, "Initio Corp" ) + DEVICE( INIT, INIT_320P, "320 P") + DEVICE( INIT, INIT_360P, "360 P") +ENDVENDOR() + +VENDOR( TTI, "Triones Technologies, Inc." ) + DEVICE( TTI, TTI_HPT343, "HPT343") +ENDVENDOR() + +VENDOR( VIA, "VIA Technologies" ) + DEVICE( VIA, VIA_82C505, "VT 82C505") + DEVICE( VIA, VIA_82C561, "VT 82C561") + DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo IDE") + DEVICE( VIA, VIA_82C576, "VT 82C576 3V") + DEVICE( VIA, VIA_82C585, "VT 82C585 Apollo VP1/VPX") + DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA") + DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2") + DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3") + DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3") + DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon") + DEVICE( VIA, VIA_82C416, "VT 82C416MV") + DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97") + DEVICE( VIA, VIA_82C586_2, "VT 82C586 Apollo USB") + DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI") + DEVICE( VIA, VIA_86C100A, "VT 86C100A") + DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP") + DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP") +ENDVENDOR() + +VENDOR( SMC2, "SMC" ) + DEVICE( SMC2, SMC2_1211TX, "1211 TX") +ENDVENDOR() + +VENDOR( VORTEX, "VORTEX" ) + DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0") + DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b") + DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510") + DEVICE( VORTEX, VORTEX_GDT6x20, "GDT 6120/6520") + DEVICE( VORTEX, VORTEX_GDT6530, "GDT 6530") + DEVICE( VORTEX, VORTEX_GDT6550, "GDT 6550") + DEVICE( VORTEX, VORTEX_GDT6x17, "GDT 6117/6517") + DEVICE( VORTEX, VORTEX_GDT6x27, "GDT 6127/6527") + DEVICE( VORTEX, VORTEX_GDT6537, "GDT 6537") + DEVICE( VORTEX, VORTEX_GDT6557, "GDT 6557") + DEVICE( VORTEX, VORTEX_GDT6x15, "GDT 6115/6515") + DEVICE( VORTEX, VORTEX_GDT6x25, "GDT 6125/6525") + DEVICE( VORTEX, VORTEX_GDT6535, "GDT 6535") + DEVICE( VORTEX, VORTEX_GDT6555, "GDT 6555") + DEVICE( VORTEX, VORTEX_GDT6x17RP,"GDT 6117RP/6517RP") + DEVICE( VORTEX, VORTEX_GDT6x27RP,"GDT 6127RP/6527RP") + DEVICE( VORTEX, VORTEX_GDT6537RP,"GDT 6537RP") + DEVICE( VORTEX, VORTEX_GDT6557RP,"GDT 6557RP") + DEVICE( VORTEX, VORTEX_GDT6x11RP,"GDT 6111RP/6511RP") + DEVICE( VORTEX, VORTEX_GDT6x21RP,"GDT 6121RP/6521RP") + DEVICE( VORTEX, VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1") + DEVICE( VORTEX, VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1") + DEVICE( VORTEX, VORTEX_GDT6537RP1,"GDT 6537RP1") + DEVICE( VORTEX, VORTEX_GDT6557RP1,"GDT 6557RP1") + DEVICE( VORTEX, VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1") + DEVICE( VORTEX, VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1") + DEVICE( VORTEX, VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2") + DEVICE( VORTEX, VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2") + DEVICE( VORTEX, VORTEX_GDT6537RP2,"GDT 6537RP2") + DEVICE( VORTEX, VORTEX_GDT6557RP2,"GDT 6557RP2") + DEVICE( VORTEX, VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2") + DEVICE( VORTEX, VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2") +ENDVENDOR() + +VENDOR( EF, "Efficient Networks" ) + DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)") + DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)") +ENDVENDOR() + +VENDOR( FORE, "Fore Systems" ) + DEVICE( FORE, FORE_PCA200PC, "PCA-200PC") + DEVICE( FORE, FORE_PCA200E, "PCA-200E") +ENDVENDOR() + +VENDOR( IMAGINGTECH, "Imaging Technology" ) + DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI") +ENDVENDOR() + +VENDOR( PHILIPS, "Philips" ) + DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145") + DEVICE( PHILIPS, PHILIPS_SAA7146,"SAA7146") +ENDVENDOR() + +VENDOR( CYCLONE, "Cyclone" ) + DEVICE( CYCLONE, CYCLONE_SDK, "SDK") +ENDVENDOR() + +VENDOR( ALLIANCE, "Alliance" ) + DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410") + DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo") + DEVICE( ALLIANCE, ALLIANCE_AT24, "AT24") + DEVICE( ALLIANCE, ALLIANCE_AT3D, "AT3D") +ENDVENDOR() + +VENDOR( VMIC, "VMIC" ) + DEVICE( VMIC, VMIC_VME, "VMIVME-7587") +ENDVENDOR() + +VENDOR( DIGI, "Digi Intl." ) + DEVICE( DIGI, DIGI_EPC, "AccelPort EPC") + DEVICE( DIGI, DIGI_RIGHTSWITCH, "RightSwitch SE-6") + DEVICE( DIGI, DIGI_XEM, "AccelPort Xem") + DEVICE( DIGI, DIGI_XR, "AccelPort Xr") + DEVICE( DIGI, DIGI_CX, "AccelPort C/X") + DEVICE( DIGI, DIGI_XRJ, "AccelPort Xr/J") + DEVICE( DIGI, DIGI_EPCJ, "AccelPort EPC/J") + DEVICE( DIGI, DIGI_XR_920, "AccelPort Xr 920") +ENDVENDOR() + +VENDOR( MUTECH, "Mutech" ) + DEVICE( MUTECH, MUTECH_MV1000, "MV-1000") +ENDVENDOR() + +VENDOR( RENDITION, "Rendition" ) + DEVICE( RENDITION, RENDITION_VERITE,"Verite 1000") + DEVICE( RENDITION, RENDITION_VERITE2100,"Verite 2100") +ENDVENDOR() + +VENDOR( TOSHIBA, "Toshiba" ) + DEVICE( TOSHIBA, TOSHIBA_601, "Laptop") + DEVICE( TOSHIBA, TOSHIBA_TOPIC95,"ToPIC95") + DEVICE( TOSHIBA, TOSHIBA_TOPIC97,"ToPIC97") +ENDVENDOR() + +VENDOR( RICOH, "Ricoh" ) + DEVICE( RICOH, RICOH_RL5C466, "RL5C466") +ENDVENDOR() + +VENDOR( ARTOP, "Artop Electronics" ) + DEVICE( ARTOP, ARTOP_ATP8400, "ATP8400") + DEVICE( ARTOP, ARTOP_ATP850UF, "ATP850UF") +ENDVENDOR() + +VENDOR( ZEITNET, "ZeitNet" ) + DEVICE( ZEITNET, ZEITNET_1221, "1221") + DEVICE( ZEITNET, ZEITNET_1225, "1225") +ENDVENDOR() + +VENDOR( OMEGA, "Omega Micro" ) + DEVICE( OMEGA, OMEGA_82C092G, "82C092G") +ENDVENDOR() + +VENDOR( LITEON, "LiteOn" ) + DEVICE( LITEON, LITEON_LNE100TX,"LNE100TX") +ENDVENDOR() + +VENDOR( NP, "Network Peripherals" ) + DEVICE( NP, NP_PCI_FDDI, "NP-PCI") +ENDVENDOR() + +VENDOR( ATT, "Lucent Microelectronics" ) + DEVICE( ATT, ATT_L56XMF, "L56xMF") +ENDVENDOR() + +VENDOR( SPECIALIX, "Specialix" ) + DEVICE( SPECIALIX, SPECIALIX_IO8, "IO8+/PCI") + DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host") + DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host") +ENDVENDOR() + +VENDOR( AURAVISION, "Auravision" ) + DEVICE( AURAVISION, AURAVISION_VXP524,"VXP524") +ENDVENDOR() + +VENDOR( IKON, "Ikon" ) + DEVICE( IKON, IKON_10115, "10115 Greensheet") + DEVICE( IKON, IKON_10117, "10117 Greensheet") +ENDVENDOR() + +VENDOR( ZORAN, "Zoran" ) + DEVICE( ZORAN, ZORAN_36057, "ZR36057") + DEVICE( ZORAN, ZORAN_36120, "ZR36120") +ENDVENDOR() + +VENDOR( KINETIC, "Kinetic" ) + DEVICE( KINETIC, KINETIC_2915, "2915 CAMAC") +ENDVENDOR() + +VENDOR( COMPEX, "Compex" ) + DEVICE( COMPEX, COMPEX_ENET100VG4, "Readylink ENET100-VG4") + DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000") +ENDVENDOR() + +VENDOR( RP, "Comtrol" ) + DEVICE( RP, RP32INTF, "RocketPort 32 Intf") + DEVICE( RP, RP8INTF, "RocketPort 8 Intf") + DEVICE( RP, RP16INTF, "RocketPort 16 Intf") + DEVICE( RP, RP4QUAD, "Rocketport 4 Quad") + DEVICE( RP, RP8OCTA, "RocketPort 8 Oct") + DEVICE( RP, RP8J, "RocketPort 8 J") + DEVICE( RP, RPP4, "RocketPort Plus 4 Quad") + DEVICE( RP, RPP8, "RocketPort Plus 8 Oct") + DEVICE( RP, RP8M, "RocketModem 8 J") +ENDVENDOR() + +VENDOR( CYCLADES, "Cyclades" ) + DEVICE( CYCLADES, CYCLOM_Y_Lo, "Cyclom-Y below 1Mbyte") + DEVICE( CYCLADES, CYCLOM_Y_Hi, "Cyclom-Y above 1Mbyte") + DEVICE( CYCLADES, CYCLOM_4Y_Lo, "Cyclom-4Y below 1Mbyte") + DEVICE( CYCLADES, CYCLOM_4Y_Hi, "Cyclom-4Y above 1Mbyte") + DEVICE( CYCLADES, CYCLOM_8Y_Lo, "Cyclom-8Y below 1Mbyte") + DEVICE( CYCLADES, CYCLOM_8Y_Hi, "Cyclom-8Y above 1Mbyte") + DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclades-Z below 1Mbyte") + DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclades-Z above 1Mbyte") +ENDVENDOR() + +VENDOR( ESSENTIAL, "Essential Communications" ) + DEVICE( ESSENTIAL, ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI") +ENDVENDOR() + +VENDOR( O2, "O2 Micro" ) + DEVICE( O2, O2_6832, "6832") +ENDVENDOR() + +VENDOR( 3DFX, "3Dfx" ) + DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo") + DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2") + DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee") + DEVICE( 3DFX, 3DFX_VOODOO3, "Voodoo3") +ENDVENDOR() + +VENDOR( SIGMADES, "Sigma Designs" ) + DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX") +ENDVENDOR() + +VENDOR( AVM, "AVM" ) + DEVICE( AVM, AVM_A1, "A1 (Fritz)") +ENDVENDOR() + +VENDOR( CCUBE, "C-Cube" ) +ENDVENDOR() + +VENDOR( DIPIX, "Dipix" ) +ENDVENDOR() + +VENDOR( STALLION, "Stallion" ) + DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32") + DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64") + DEVICE( STALLION, STALLION_EIOPCI,"EasyIO") +ENDVENDOR() + +VENDOR( OPTIBASE, "Optibase" ) + DEVICE( OPTIBASE, OPTIBASE_FORGE, "MPEG Forge") + DEVICE( OPTIBASE, OPTIBASE_FUSION,"MPEG Fusion") + DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex") + DEVICE( OPTIBASE, OPTIBASE_VPLEXCC,"VideoPlex CC") + DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest") +ENDVENDOR() + +VENDOR( SATSAGEM, "SatSagem" ) + DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver") + DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB") +ENDVENDOR() + +VENDOR( HUGHES, "Hughes" ) + DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC") +ENDVENDOR() + +VENDOR( ENSONIQ, "Ensoniq" ) + DEVICE( ENSONIQ, ENSONIQ_ES1371, "ES1371") + DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI") +ENDVENDOR() + +VENDOR( ALTEON, "Alteon" ) + DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC") +ENDVENDOR() + +VENDOR( PICTUREL, "Picture Elements" ) + DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST") +ENDVENDOR() + +VENDOR( NVIDIA_SGS, "NVidia/SGS Thomson" ) + DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128") +ENDVENDOR() + +VENDOR( CBOARDS, "ComputerBoards" ) + DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16") +ENDVENDOR() + +VENDOR( MOTOROLA_OOPS, "Motorola" ) + DEVICE( MOTOROLA_OOPS, MOTOROLA_FALCON,"Falcon") +ENDVENDOR() + +VENDOR( SYMPHONY, "Symphony" ) + DEVICE( SYMPHONY, SYMPHONY_101, "82C101") +ENDVENDOR() + +VENDOR( TEKRAM, "Tekram" ) + DEVICE( TEKRAM, TEKRAM_DC290, "DC-290") +ENDVENDOR() + +VENDOR( 3DLABS, "3Dlabs" ) + DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX") + DEVICE( 3DLABS, 3DLABS_500TX, "GLINT 500TX") + DEVICE( 3DLABS, 3DLABS_DELTA, "GLINT Delta") + DEVICE( 3DLABS, 3DLABS_PERMEDIA,"PERMEDIA") + DEVICE( 3DLABS, 3DLABS_MX, "GLINT MX") +ENDVENDOR() + +VENDOR( AVANCE, "Avance" ) + DEVICE( AVANCE, AVANCE_ALG2064, "ALG2064i") + DEVICE( AVANCE, AVANCE_2302, "ALG-2302") +ENDVENDOR() + +VENDOR( NETVIN, "NetVin" ) + DEVICE( NETVIN, NETVIN_NV5000SC,"NV5000") +ENDVENDOR() + +VENDOR( S3, "S3 Inc." ) + DEVICE( S3, S3_PLATO_PXS, "PLATO/PX (system)") + DEVICE( S3, S3_ViRGE, "ViRGE") + DEVICE( S3, S3_TRIO, "Trio32/Trio64") + DEVICE( S3, S3_AURORA64VP, "Aurora64V+") + DEVICE( S3, S3_TRIO64UVP, "Trio64UV+") + DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX") + DEVICE( S3, S3_868, "Vision 868") + DEVICE( S3, S3_928, "Vision 928-P") + DEVICE( S3, S3_864_1, "Vision 864-P") + DEVICE( S3, S3_864_2, "Vision 864-P") + DEVICE( S3, S3_964_1, "Vision 964-P") + DEVICE( S3, S3_964_2, "Vision 964-P") + DEVICE( S3, S3_968, "Vision 968") + DEVICE( S3, S3_TRIO64V2, "Trio64V2/DX or /GX") + DEVICE( S3, S3_PLATO_PXG, "PLATO/PX (graphics)") + DEVICE( S3, S3_ViRGE_DXGX, "ViRGE/DX or /GX") + DEVICE( S3, S3_ViRGE_GX2, "ViRGE/GX2") + DEVICE( S3, S3_ViRGE_MX, "ViRGE/MX") + DEVICE( S3, S3_ViRGE_MXP, "ViRGE/MX+") + DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV") + DEVICE( S3, S3_SONICVIBES, "SonicVibes") +ENDVENDOR() + +VENDOR( DCI, "Decision Computer Int." ) + DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter") +ENDVENDOR() + +VENDOR( GENROCO, "Genroco" ) + DEVICE( GENROCO, GENROCO_HFP832, "TURBOstor HFP832") +ENDVENDOR() + +VENDOR( INTEL, "Intel" ) + DEVICE( INTEL, INTEL_82375, "82375EB") + DEVICE( INTEL, INTEL_82424, "82424ZX Saturn") + DEVICE( INTEL, INTEL_82378, "82378IB") + DEVICE( INTEL, INTEL_82430, "82430ZX Aries") + DEVICE( INTEL, INTEL_82434, "82434LX Mercury/Neptune") + DEVICE( INTEL, INTEL_82092AA_0,"82092AA PCMCIA bridge") + DEVICE( INTEL, INTEL_82092AA_1,"82092AA EIDE") + DEVICE( INTEL, INTEL_7116, "SAA7116") + DEVICE( INTEL, INTEL_82596, "82596") + DEVICE( INTEL, INTEL_82865, "82865") + DEVICE( INTEL, INTEL_82557, "EtherExpress Pro100") + DEVICE( INTEL, INTEL_82437, "82437") + DEVICE( INTEL, INTEL_82371FB_0,"82371FB PIIX ISA") + DEVICE( INTEL, INTEL_82371FB_1,"82371FB PIIX IDE") + DEVICE( INTEL, INTEL_82371MX, "430MX - 82371MX MPIIX") + DEVICE( INTEL, INTEL_82437MX, "430MX - 82437MX MTSC") + DEVICE( INTEL, INTEL_82441, "82441FX Natoma") + DEVICE( INTEL, INTEL_82380FB, "82380FB Mobile") + DEVICE( INTEL, INTEL_82439, "82439HX Triton II") + DEVICE( INTEL, INTEL_82371SB_0,"82371SB PIIX3 ISA") + DEVICE( INTEL, INTEL_82371SB_1,"82371SB PIIX3 IDE") + DEVICE( INTEL, INTEL_82371SB_2,"82371SB PIIX3 USB") + DEVICE( INTEL, INTEL_82437VX, "82437VX Triton II") + DEVICE( INTEL, INTEL_82439TX, "82439TX") + DEVICE( INTEL, INTEL_82371AB_0,"82371AB PIIX4 ISA") + DEVICE( INTEL, INTEL_82371AB, "82371AB PIIX4 IDE") + DEVICE( INTEL, INTEL_82371AB_2,"82371AB PIIX4 USB") + DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 ACPI") + DEVICE( INTEL, INTEL_82443LX_0,"440LX - 82443LX PAC Host") + DEVICE( INTEL, INTEL_82443LX_1,"440LX - 82443LX PAC AGP") + DEVICE( INTEL, INTEL_82443BX_0,"440BX - 82443BX Host") + DEVICE( INTEL, INTEL_82443BX_1,"440BX - 82443BX AGP") + DEVICE( INTEL, INTEL_82443BX_2,"440BX - 82443BX Host (no AGP)") + DEVICE( INTEL, INTEL_P6, "Orion P6") + DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6") +ENDVENDOR() + +VENDOR( KTI, "KTI" ) + DEVICE( KTI, KTI_ET32P2, "ET32P2") +ENDVENDOR() + +VENDOR( ADAPTEC, "Adaptec" ) + DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID") + DEVICE( ADAPTEC, ADAPTEC_7821, "AIC-7860") + DEVICE( ADAPTEC, ADAPTEC_38602, "AIC-7860") + DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850") + DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855") + DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800") + DEVICE( ADAPTEC, ADAPTEC_3860, "AIC-7860") + DEVICE( ADAPTEC, ADAPTEC_7860, "AIC-7860") + DEVICE( ADAPTEC, ADAPTEC_7861, "AIC-7861") + DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870") + DEVICE( ADAPTEC, ADAPTEC_7871, "AIC-7871") + DEVICE( ADAPTEC, ADAPTEC_7872, "AIC-7872") + DEVICE( ADAPTEC, ADAPTEC_7873, "AIC-7873") + DEVICE( ADAPTEC, ADAPTEC_7874, "AIC-7874") + DEVICE( ADAPTEC, ADAPTEC_7895, "AIC-7895U") + DEVICE( ADAPTEC, ADAPTEC_7880, "AIC-7880U") + DEVICE( ADAPTEC, ADAPTEC_7881, "AIC-7881U") + DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U") + DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U") + DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U") + DEVICE( ADAPTEC, ADAPTEC_7885, "AIC-7885U") + DEVICE( ADAPTEC, ADAPTEC_7886, "AIC-7886U") + DEVICE( ADAPTEC, ADAPTEC_7887, "AIC-7887U") + DEVICE( ADAPTEC, ADAPTEC_7888, "AIC-7888U") + DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver") +ENDVENDOR() + +VENDOR( ADAPTEC2, "Adaptec" ) + DEVICE( ADAPTEC2, ADAPTEC2_2940U2,"AHA-2940U2") + DEVICE( ADAPTEC2, ADAPTEC2_2930U2,"AHA-2930U2") + DEVICE( ADAPTEC2, ADAPTEC2_7890B, "AIC-7890/1") + DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1") + DEVICE( ADAPTEC2, ADAPTEC2_3940U2,"AHA-3940U2") + DEVICE( ADAPTEC2, ADAPTEC2_3950U2D,"AHA-3950U2D") + DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7") + DEVICE( ADAPTEC2, ADAPTEC2_7892A, "AIC-7892") + DEVICE( ADAPTEC2, ADAPTEC2_7892B, "AIC-7892") + DEVICE( ADAPTEC2, ADAPTEC2_7892D, "AIC-7892") + DEVICE( ADAPTEC2, ADAPTEC2_7892P, "AIC-7892") + DEVICE( ADAPTEC2, ADAPTEC2_7899A, "AIC-7899") + DEVICE( ADAPTEC2, ADAPTEC2_7899B, "AIC-7899") + DEVICE( ADAPTEC2, ADAPTEC2_7899D, "AIC-7899") + DEVICE( ADAPTEC2, ADAPTEC2_7899P, "AIC-7899") +ENDVENDOR() + +VENDOR( ATRONICS, "Atronics" ) + DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL") +ENDVENDOR() + +VENDOR( TIGERJET, "TigerJet" ) + DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN") +ENDVENDOR() + +VENDOR( ARK, "ARK" ) + DEVICE( ARK, ARK_STING, "Stingray") + DEVICE( ARK, ARK_STINGARK, "Stingray ARK 2000PV") + DEVICE( ARK, ARK_2000MT, "2000MT") +ENDVENDOR() + +#undef VENDOR +#undef ENDVENDOR +#undef DEVICE diff -u --recursive --new-file v2.3.12/linux/drivers/pci/names.c linux/drivers/pci/names.c --- v2.3.12/linux/drivers/pci/names.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/pci/names.c Fri Aug 6 11:16:54 1999 @@ -0,0 +1,98 @@ +/* + * $Id: oldproc.c,v 1.24 1998/10/11 15:13:04 mj Exp $ + * + * Backward-compatible procfs interface for PCI. + * + * Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter, + * David Mosberger-Tang, Martin Mares + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +struct pci_device_info { + unsigned short device; + unsigned short seen; + const char *name; +}; + +struct pci_vendor_info { + unsigned short vendor; + unsigned short nr; + const char *name; + struct pci_device_info *devices; +}; + +/* + * This is ridiculous, but we want the strings in + * the .init section so that they don't take up + * real memory.. Parse the same file multiple times + * to get all the info. + */ +#define VENDOR( vendor, name ) static const char __vendorstr_##vendor[] __initdata = name; +#define ENDVENDOR() +#define DEVICE( vendor, device, name ) static const char __devicestr_##vendor##device[] __initdata = name; +#include "devlist.h" + + +#define VENDOR( vendor, name ) static struct pci_device_info __devices_##vendor[] __initdata = { +#define ENDVENDOR() }; +#define DEVICE( vendor, device, name ) { PCI_DEVICE_ID_##device, 0, __devicestr_##vendor##device }, +#include "devlist.h" + +static const struct pci_vendor_info __initdata pci_vendor_list[] = { +#define VENDOR( vendor, name ) { PCI_VENDOR_ID_##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor }, +#define ENDVENDOR() +#define DEVICE( vendor, device, name ) +#include "devlist.h" +}; + +#define VENDORS (sizeof(pci_vendor_list)/sizeof(struct pci_vendor_info)) + +void __init pci_namedevice(struct pci_dev *dev) +{ + const struct pci_vendor_info *vendor_p = pci_vendor_list; + int i = VENDORS; + + do { + if (vendor_p->vendor == dev->vendor) + goto match_vendor; + vendor_p++; + } while (--i); + + /* Coulding find either the vendor nor the device */ + sprintf(dev->name, "PCI<%d:%04x> %04x:%04x", dev->bus->number, dev->devfn, dev->vendor, dev->device); + return; + + match_vendor: { + struct pci_device_info *device_p = vendor_p->devices; + int i = vendor_p->nr; + + while (i > 0) { + if (device_p->device == dev->device) + goto match_device; + device_p++; + i--; + } + + /* Ok, found the vendor, but unknown device */ + sprintf(dev->name, "PCI<%d:%04x> %04x:%04x (%s)", dev->bus->number, dev->devfn, dev->vendor, dev->device, vendor_p->name); + return; + + /* Full match */ + match_device: { + char *n = dev->name + sprintf(dev->name, "%s %s", vendor_p->name, device_p->name); + int nr = device_p->seen + 1; + device_p->seen = nr; + if (nr > 1) + sprintf(n, " (#%d)", nr); + } + } +} diff -u --recursive --new-file v2.3.12/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.3.12/linux/drivers/pci/oldproc.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/pci/oldproc.c Wed Dec 31 16:00:00 1969 @@ -1,1041 +0,0 @@ -/* - * $Id: oldproc.c,v 1.24 1998/10/11 15:13:04 mj Exp $ - * - * Backward-compatible procfs interface for PCI. - * - * Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter, - * David Mosberger-Tang, Martin Mares - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_PROC_FS - -struct pci_dev_info { - unsigned short vendor; /* vendor id */ - unsigned short device; /* device id */ - - const char *name; /* device name */ -}; - -#define DEVICE(vid,did,name) \ - {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name)} - -/* - * Sorted in ascending order by vendor and device. - * Use binary search for lookup. If you add a device make sure - * it is sequential by both vendor and device id. - */ -struct pci_dev_info dev_info[] = { - DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p"), - DEVICE( COMPAQ, COMPAQ_SMART2P, "Smart-2/P RAID Controller"), - DEVICE( COMPAQ, COMPAQ_NETEL100,"Netelligent 10/100"), - DEVICE( COMPAQ, COMPAQ_NETEL10, "Netelligent 10"), - DEVICE( COMPAQ, COMPAQ_NETFLEX3I,"NetFlex 3"), - DEVICE( COMPAQ, COMPAQ_NETEL100D,"Netelligent 10/100 Dual"), - DEVICE( COMPAQ, COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant"), - DEVICE( COMPAQ, COMPAQ_NETEL100I,"Netelligent 10/100 Integrated"), - DEVICE( COMPAQ, COMPAQ_THUNDER, "ThunderLAN"), - DEVICE( COMPAQ, COMPAQ_NETFLEX3B,"NetFlex 3 BNC"), - DEVICE( NCR, NCR_53C810, "53c810"), - DEVICE( NCR, NCR_53C820, "53c820"), - DEVICE( NCR, NCR_53C825, "53c825"), - DEVICE( NCR, NCR_53C815, "53c815"), - DEVICE( NCR, NCR_53C860, "53c860"), - DEVICE( NCR, NCR_53C896, "53c896"), - DEVICE( NCR, NCR_53C895, "53c895"), - DEVICE( NCR, NCR_53C885, "53c885"), - DEVICE( NCR, NCR_53C875, "53c875"), - DEVICE( NCR, NCR_53C875J, "53c875J"), - DEVICE( ATI, ATI_68800, "68800AX"), - DEVICE( ATI, ATI_215CT222, "215CT222"), - DEVICE( ATI, ATI_210888CX, "210888CX"), - DEVICE( ATI, ATI_215GB, "Mach64 GB"), - DEVICE( ATI, ATI_215GD, "Mach64 GD (Rage Pro)"), - DEVICE( ATI, ATI_215GI, "Mach64 GI (Rage Pro)"), - DEVICE( ATI, ATI_215GP, "Mach64 GP (Rage Pro)"), - DEVICE( ATI, ATI_215GQ, "Mach64 GQ (Rage Pro)"), - DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)"), - DEVICE( ATI, ATI_215GTB, "Mach64 GT (Rage II)"), - DEVICE( ATI, ATI_210888GX, "210888GX"), - DEVICE( ATI, ATI_215LG, "Mach64 LG (Rage Pro)"), - DEVICE( ATI, ATI_264LT, "Mach64 LT"), - DEVICE( ATI, ATI_264VT, "Mach64 VT"), - DEVICE( VLSI, VLSI_82C592, "82C592-FC1"), - DEVICE( VLSI, VLSI_82C593, "82C593-FC1"), - DEVICE( VLSI, VLSI_82C594, "82C594-AFC2"), - DEVICE( VLSI, VLSI_82C597, "82C597-AFC2"), - DEVICE( VLSI, VLSI_82C541, "82C541 Lynx"), - DEVICE( VLSI, VLSI_82C543, "82C543 Lynx ISA"), - DEVICE( VLSI, VLSI_82C532, "82C532"), - DEVICE( VLSI, VLSI_82C534, "82C534"), - DEVICE( VLSI, VLSI_82C535, "82C535"), - DEVICE( VLSI, VLSI_82C147, "82C147"), - DEVICE( VLSI, VLSI_VAS96011, "VAS96011 (Golden Gate II)"), - DEVICE( ADL, ADL_2301, "2301"), - DEVICE( NS, NS_87415, "87415"), - DEVICE( NS, NS_87410, "87410"), - DEVICE( TSENG, TSENG_W32P_2, "ET4000W32P"), - DEVICE( TSENG, TSENG_W32P_b, "ET4000W32P rev B"), - DEVICE( TSENG, TSENG_W32P_c, "ET4000W32P rev C"), - DEVICE( TSENG, TSENG_W32P_d, "ET4000W32P rev D"), - DEVICE( TSENG, TSENG_ET6000, "ET6000"), - DEVICE( WEITEK, WEITEK_P9000, "P9000"), - DEVICE( WEITEK, WEITEK_P9100, "P9100"), - DEVICE( DEC, DEC_BRD, "DC21050"), - DEVICE( DEC, DEC_TULIP, "DC21040"), - DEVICE( DEC, DEC_TGA, "TGA"), - DEVICE( DEC, DEC_TULIP_FAST, "DC21140"), - DEVICE( DEC, DEC_TGA2, "TGA2"), - DEVICE( DEC, DEC_FDDI, "DEFPA"), - DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), - DEVICE( DEC, DEC_21142, "DC21142"), - DEVICE( DEC, DEC_21052, "DC21052"), - DEVICE( DEC, DEC_21150, "DC21150"), - DEVICE( DEC, DEC_21152, "DC21152"), - DEVICE( DEC, DEC_21153, "DC21153"), - DEVICE( DEC, DEC_21154, "DC21154"), - DEVICE( CIRRUS, CIRRUS_7548, "GD 7548"), - DEVICE( CIRRUS, CIRRUS_5430, "GD 5430"), - DEVICE( CIRRUS, CIRRUS_5434_4, "GD 5434"), - DEVICE( CIRRUS, CIRRUS_5434_8, "GD 5434"), - DEVICE( CIRRUS, CIRRUS_5436, "GD 5436"), - DEVICE( CIRRUS, CIRRUS_5446, "GD 5446"), - DEVICE( CIRRUS, CIRRUS_5480, "GD 5480"), - DEVICE( CIRRUS, CIRRUS_5464, "GD 5464"), - DEVICE( CIRRUS, CIRRUS_5465, "GD 5465"), - DEVICE( CIRRUS, CIRRUS_6729, "CL 6729"), - DEVICE( CIRRUS, CIRRUS_6832, "PD 6832"), - DEVICE( CIRRUS, CIRRUS_7542, "CL 7542"), - DEVICE( CIRRUS, CIRRUS_7543, "CL 7543"), - DEVICE( CIRRUS, CIRRUS_7541, "CL 7541"), - DEVICE( IBM, IBM_FIRE_CORAL, "Fire Coral"), - DEVICE( IBM, IBM_TR, "Token Ring"), - DEVICE( IBM, IBM_82G2675, "82G2675"), - DEVICE( IBM, IBM_MCA, "MicroChannel"), - DEVICE( IBM, IBM_82351, "82351"), - DEVICE( IBM, IBM_PYTHON, "Python"), - DEVICE( IBM, IBM_SERVERAID, "ServeRAID"), - DEVICE( IBM, IBM_TR_WAKE, "Wake On LAN Token Ring"), - DEVICE( IBM, IBM_MPIC, "MPIC-2 Interrupt Controller"), - DEVICE( IBM, IBM_3780IDSP, "MWave DSP"), - DEVICE( IBM, IBM_MPIC_2, "MPIC-2 ASIC Interrupt Controller"), - DEVICE( WD, WD_7197, "WD 7197"), - DEVICE( AMD, AMD_LANCE, "79C970"), - DEVICE( AMD, AMD_SCSI, "53C974"), - DEVICE( TRIDENT, TRIDENT_9397, "Cyber9397"), - DEVICE( TRIDENT, TRIDENT_9420, "TG 9420"), - DEVICE( TRIDENT, TRIDENT_9440, "TG 9440"), - DEVICE( TRIDENT, TRIDENT_9660, "TG 9660 / Cyber9385"), - DEVICE( TRIDENT, TRIDENT_9750, "Image 975"), - DEVICE( AI, AI_M1435, "M1435"), - DEVICE( MATROX, MATROX_MGA_2, "Atlas PX2085"), - DEVICE( MATROX, MATROX_MIL, "Millennium"), - DEVICE( MATROX, MATROX_MYS, "Mystique"), - DEVICE( MATROX, MATROX_MIL_2, "Millennium II"), - DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP"), - DEVICE( MATROX, MATROX_G200_PCI,"Matrox G200 PCI"), - DEVICE( MATROX, MATROX_G200_AGP,"Matrox G200 AGP"), - DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"), - DEVICE( MATROX, MATROX_G100_MM, "Matrox G100 multi monitor"), - DEVICE( MATROX, MATROX_G100_AGP,"Matrox G100 AGP"), - DEVICE( CT, CT_65545, "65545"), - DEVICE( CT, CT_65548, "65548"), - DEVICE( CT, CT_65550, "65550"), - DEVICE( CT, CT_65554, "65554"), - DEVICE( CT, CT_65555, "65555"), - DEVICE( MIRO, MIRO_36050, "ZR36050"), - DEVICE( NEC, NEC_PCX2, "PowerVR PCX2"), - DEVICE( FD, FD_36C70, "TMC-18C30"), - DEVICE( SI, SI_5591_AGP, "5591/5592 AGP"), - DEVICE( SI, SI_6202, "6202"), - DEVICE( SI, SI_503, "85C503"), - DEVICE( SI, SI_ACPI, "ACPI"), - DEVICE( SI, SI_5597_VGA, "5597/5598 VGA"), - DEVICE( SI, SI_6205, "6205"), - DEVICE( SI, SI_501, "85C501"), - DEVICE( SI, SI_496, "85C496"), - DEVICE( SI, SI_601, "85C601"), - DEVICE( SI, SI_5107, "5107"), - DEVICE( SI, SI_5511, "85C5511"), - DEVICE( SI, SI_5513, "85C5513"), - DEVICE( SI, SI_5571, "5571"), - DEVICE( SI, SI_5591, "5591/5592 Host"), - DEVICE( SI, SI_5597, "5597/5598 Host"), - DEVICE( SI, SI_7001, "7001 USB"), - DEVICE( HP, HP_J2585A, "J2585A"), - DEVICE( HP, HP_J2585B, "J2585B (Lassen)"), - DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)"), - DEVICE( PCTECH, PCTECH_RZ1001, "RZ1001 (buggy?)"), - DEVICE( PCTECH, PCTECH_SAMURAI_0,"Samurai 0"), - DEVICE( PCTECH, PCTECH_SAMURAI_1,"Samurai 1"), - DEVICE( PCTECH, PCTECH_SAMURAI_IDE,"Samurai IDE"), - DEVICE( DPT, DPT, "SmartCache/Raid"), - DEVICE( OPTI, OPTI_92C178, "92C178"), - DEVICE( OPTI, OPTI_82C557, "82C557 Viper-M"), - DEVICE( OPTI, OPTI_82C558, "82C558 Viper-M ISA+IDE"), - DEVICE( OPTI, OPTI_82C621, "82C621"), - DEVICE( OPTI, OPTI_82C700, "82C700"), - DEVICE( OPTI, OPTI_82C701, "82C701 FireStar Plus"), - DEVICE( OPTI, OPTI_82C814, "82C814 Firebridge 1"), - DEVICE( OPTI, OPTI_82C822, "82C822"), - DEVICE( OPTI, OPTI_82C825, "82C825 Firebridge 2"), - DEVICE( SGS, SGS_2000, "STG 2000X"), - DEVICE( SGS, SGS_1764, "STG 1764X"), - DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"), - DEVICE( BUSLOGIC, BUSLOGIC_MULTIMASTER, "MultiMaster"), - DEVICE( BUSLOGIC, BUSLOGIC_FLASHPOINT, "FlashPoint"), - DEVICE( TI, TI_TVP4010, "TVP4010 Permedia"), - DEVICE( TI, TI_TVP4020, "TVP4020 Permedia 2"), - DEVICE( TI, TI_PCI1130, "PCI1130"), - DEVICE( TI, TI_PCI1131, "PCI1131"), - DEVICE( TI, TI_PCI1250, "PCI1250"), - DEVICE( OAK, OAK_OTI107, "OTI107"), - DEVICE( WINBOND2, WINBOND2_89C940,"NE2000-PCI"), - DEVICE( MOTOROLA, MOTOROLA_MPC105,"MPC105 Eagle"), - DEVICE( MOTOROLA, MOTOROLA_MPC106,"MPC106 Grackle"), - DEVICE( MOTOROLA, MOTOROLA_RAVEN, "Raven"), - DEVICE( MOTOROLA, MOTOROLA_FALCON,"Falcon"), - DEVICE( MOTOROLA, MOTOROLA_CPX8216,"CPX8216"), - DEVICE( PROMISE, PROMISE_20246, "IDE UltraDMA/33"), - DEVICE( PROMISE, PROMISE_20262, "IDE UltraDMA/66"), - DEVICE( PROMISE, PROMISE_5300, "DC5030"), - DEVICE( N9, N9_I128, "Imagine 128"), - DEVICE( N9, N9_I128_2, "Imagine 128v2"), - DEVICE( N9, N9_I128_T2R, "Revolution 3D"), - DEVICE( UMC, UMC_UM8673F, "UM8673F"), - DEVICE( UMC, UMC_UM8891A, "UM8891A"), - DEVICE( UMC, UMC_UM8886BF, "UM8886BF"), - DEVICE( UMC, UMC_UM8886A, "UM8886A"), - DEVICE( UMC, UMC_UM8881F, "UM8881F"), - DEVICE( UMC, UMC_UM8886F, "UM8886F"), - DEVICE( UMC, UMC_UM9017F, "UM9017F"), - DEVICE( UMC, UMC_UM8886N, "UM8886N"), - DEVICE( UMC, UMC_UM8891N, "UM8891N"), - DEVICE( X, X_AGX016, "ITT AGX016"), - DEVICE( PICOP, PICOP_PT86C52X, "PT86C52x Vesuvius"), - DEVICE( PICOP, PICOP_PT80C524, "PT80C524 Nile"), - DEVICE( APPLE, APPLE_BANDIT, "Bandit"), - DEVICE( APPLE, APPLE_GC, "Grand Central"), - DEVICE( APPLE, APPLE_HYDRA, "Hydra"), - DEVICE( NEXGEN, NEXGEN_82C501, "82C501"), - DEVICE( QLOGIC, QLOGIC_ISP1020, "ISP1020"), - DEVICE( QLOGIC, QLOGIC_ISP1022, "ISP1022"), - DEVICE( CYRIX, CYRIX_5510, "5510"), - DEVICE( CYRIX, CYRIX_PCI_MASTER,"PCI Master"), - DEVICE( CYRIX, CYRIX_5520, "5520"), - DEVICE( CYRIX, CYRIX_5530_LEGACY,"5530 Kahlua Legacy"), - DEVICE( CYRIX, CYRIX_5530_SMI, "5530 Kahlua SMI"), - DEVICE( CYRIX, CYRIX_5530_IDE, "5530 Kahlua IDE"), - DEVICE( CYRIX, CYRIX_5530_AUDIO,"5530 Kahlua Audio"), - DEVICE( CYRIX, CYRIX_5530_VIDEO,"5530 Kahlua Video"), - DEVICE( LEADTEK, LEADTEK_805, "S3 805"), - DEVICE( CONTAQ, CONTAQ_82C599, "82C599"), - DEVICE( CONTAQ, CONTAQ_82C693, "82C693"), - DEVICE( OLICOM, OLICOM_OC3136, "OC-3136/3137"), - DEVICE( OLICOM, OLICOM_OC2315, "OC-2315"), - DEVICE( OLICOM, OLICOM_OC2325, "OC-2325"), - DEVICE( OLICOM, OLICOM_OC2183, "OC-2183/2185"), - DEVICE( OLICOM, OLICOM_OC2326, "OC-2326"), - DEVICE( OLICOM, OLICOM_OC6151, "OC-6151/6152"), - DEVICE( SUN, SUN_EBUS, "PCI-EBus Bridge"), - DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal Ethernet"), - DEVICE( SUN, SUN_SIMBA, "Advanced PCI Bridge"), - DEVICE( SUN, SUN_PBM, "PCI Bus Module"), - DEVICE( SUN, SUN_SABRE, "Ultra IIi PCI"), - DEVICE( CMD, CMD_640, "640 (buggy)"), - DEVICE( CMD, CMD_643, "643"), - DEVICE( CMD, CMD_646, "646"), - DEVICE( CMD, CMD_670, "670"), - DEVICE( VISION, VISION_QD8500, "QD-8500"), - DEVICE( VISION, VISION_QD8580, "QD-8580"), - DEVICE( BROOKTREE, BROOKTREE_848, "Bt848"), - DEVICE( BROOKTREE, BROOKTREE_849A, "Bt849"), - DEVICE( BROOKTREE, BROOKTREE_878_1,"Bt878 2nd Contr. (?)"), - DEVICE( BROOKTREE, BROOKTREE_878, "Bt878"), - DEVICE( BROOKTREE, BROOKTREE_8474, "Bt8474"), - DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64"), - DEVICE( SGI, SGI_IOC3, "IOC3"), - DEVICE( ACC, ACC_2056, "2056"), - DEVICE( WINBOND, WINBOND_83769, "W83769F"), - DEVICE( WINBOND, WINBOND_82C105, "SL82C105"), - DEVICE( WINBOND, WINBOND_83C553, "W83C553"), - DEVICE( DATABOOK, DATABOOK_87144, "DB87144"), - DEVICE( PLX, PLX_9050, "PCI9050 I2O"), - DEVICE( PLX, PLX_9080, "PCI9080 I2O"), - DEVICE( MADGE, MADGE_MK2, "Smart 16/4 BM Mk2 Ringnode"), - DEVICE( MADGE, MADGE_C155S, "Collage 155 Server"), - DEVICE( 3COM, 3COM_3C339, "3C339 TokenRing"), - DEVICE( 3COM, 3COM_3C590, "3C590 10bT"), - DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX"), - DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4"), - DEVICE( 3COM, 3COM_3C595MII, "3C595 100b-MII"), - DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO"), - DEVICE( 3COM, 3COM_3C900COMBO,"3C900 10b Combo"), - DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX"), - DEVICE( 3COM, 3COM_3C905T4, "3C905 100bT4"), - DEVICE( 3COM, 3COM_3C905B_TX, "3C905B 100bTX"), - DEVICE( SMC, SMC_EPIC100, "9432 TX"), - DEVICE( AL, AL_M1445, "M1445"), - DEVICE( AL, AL_M1449, "M1449"), - DEVICE( AL, AL_M1451, "M1451"), - DEVICE( AL, AL_M1461, "M1461"), - DEVICE( AL, AL_M1489, "M1489"), - DEVICE( AL, AL_M1511, "M1511"), - DEVICE( AL, AL_M1513, "M1513"), - DEVICE( AL, AL_M1521, "M1521"), - DEVICE( AL, AL_M1523, "M1523"), - DEVICE( AL, AL_M1531, "M1531 Aladdin IV"), - DEVICE( AL, AL_M1533, "M1533 Aladdin IV"), - DEVICE( AL, AL_M1541, "M1541 Aladdin V"), - DEVICE( AL, AL_M1543, "M1543 Aladdin V"), - DEVICE( AL, AL_M3307, "M3307 MPEG-1 decoder"), - DEVICE( AL, AL_M4803, "M4803"), - DEVICE( AL, AL_M5219, "M5219"), - DEVICE( AL, AL_M5229, "M5229 TXpro"), - DEVICE( AL, AL_M5237, "M5237 USB"), - DEVICE( AL, AL_M5243, "M5243 AGP"), - DEVICE( AL, AL_M7101, "M7101 PMU"), - DEVICE( SURECOM, SURECOM_NE34, "NE-34PCI LAN"), - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2070, "Magicgraph NM2070"), - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"), - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"), - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"), - DEVICE( NEOMAGIC, NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+"), - DEVICE( ASP, ASP_ABP940, "ABP940"), - DEVICE( ASP, ASP_ABP940U, "ABP940U"), - DEVICE( ASP, ASP_ABP940UW, "ABP940UW"), - DEVICE( MACRONIX, MACRONIX_MX98713,"MX98713"), - DEVICE( MACRONIX, MACRONIX_MX987x5,"MX98715 / MX98725"), - DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"), - DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)"), - DEVICE( CERN, CERN_HIPPI_DST, "HIPPI destination"), - DEVICE( CERN, CERN_HIPPI_SRC, "HIPPI source"), - DEVICE( IMS, IMS_8849, "8849"), - DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"), - DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe"), - DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)"), - DEVICE( AMCC, AMCC_PARASTATION,"ParaStation Interface"), - DEVICE( AMCC, AMCC_S5933, "S5933 PCI44"), - DEVICE( AMCC, AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"), - DEVICE( INTERG, INTERG_1680, "IGA-1680"), - DEVICE( INTERG, INTERG_1682, "IGA-1682"), - DEVICE( REALTEK, REALTEK_8029, "8029"), - DEVICE( REALTEK, REALTEK_8129, "8129"), - DEVICE( REALTEK, REALTEK_8139, "8139"), - DEVICE( TRUEVISION, TRUEVISION_T1000,"TARGA 1000"), - DEVICE( INIT, INIT_320P, "320 P"), - DEVICE( INIT, INIT_360P, "360 P"), - DEVICE( TTI, TTI_HPT343, "HPT343"), - DEVICE( VIA, VIA_82C505, "VT 82C505"), - DEVICE( VIA, VIA_82C561, "VT 82C561"), - DEVICE( VIA, VIA_82C586_1, "VT 82C586 Apollo IDE"), - DEVICE( VIA, VIA_82C576, "VT 82C576 3V"), - DEVICE( VIA, VIA_82C585, "VT 82C585 Apollo VP1/VPX"), - DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA"), - DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2"), - DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3"), - DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3"), - DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon"), - DEVICE( VIA, VIA_82C416, "VT 82C416MV"), - DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97"), - DEVICE( VIA, VIA_82C586_2, "VT 82C586 Apollo USB"), - DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI"), - DEVICE( VIA, VIA_86C100A, "VT 86C100A"), - DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"), - DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP"), - DEVICE( SMC2, SMC2_1211TX, "1211 TX"), - DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"), - DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"), - DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510"), - DEVICE( VORTEX, VORTEX_GDT6x20, "GDT 6120/6520"), - DEVICE( VORTEX, VORTEX_GDT6530, "GDT 6530"), - DEVICE( VORTEX, VORTEX_GDT6550, "GDT 6550"), - DEVICE( VORTEX, VORTEX_GDT6x17, "GDT 6117/6517"), - DEVICE( VORTEX, VORTEX_GDT6x27, "GDT 6127/6527"), - DEVICE( VORTEX, VORTEX_GDT6537, "GDT 6537"), - DEVICE( VORTEX, VORTEX_GDT6557, "GDT 6557"), - DEVICE( VORTEX, VORTEX_GDT6x15, "GDT 6115/6515"), - DEVICE( VORTEX, VORTEX_GDT6x25, "GDT 6125/6525"), - DEVICE( VORTEX, VORTEX_GDT6535, "GDT 6535"), - DEVICE( VORTEX, VORTEX_GDT6555, "GDT 6555"), - DEVICE( VORTEX, VORTEX_GDT6x17RP,"GDT 6117RP/6517RP"), - DEVICE( VORTEX, VORTEX_GDT6x27RP,"GDT 6127RP/6527RP"), - DEVICE( VORTEX, VORTEX_GDT6537RP,"GDT 6537RP"), - DEVICE( VORTEX, VORTEX_GDT6557RP,"GDT 6557RP"), - DEVICE( VORTEX, VORTEX_GDT6x11RP,"GDT 6111RP/6511RP"), - DEVICE( VORTEX, VORTEX_GDT6x21RP,"GDT 6121RP/6521RP"), - DEVICE( VORTEX, VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1"), - DEVICE( VORTEX, VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1"), - DEVICE( VORTEX, VORTEX_GDT6537RP1,"GDT 6537RP1"), - DEVICE( VORTEX, VORTEX_GDT6557RP1,"GDT 6557RP1"), - DEVICE( VORTEX, VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1"), - DEVICE( VORTEX, VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1"), - DEVICE( VORTEX, VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2"), - DEVICE( VORTEX, VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2"), - DEVICE( VORTEX, VORTEX_GDT6537RP2,"GDT 6537RP2"), - DEVICE( VORTEX, VORTEX_GDT6557RP2,"GDT 6557RP2"), - DEVICE( VORTEX, VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"), - DEVICE( VORTEX, VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"), - DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"), - DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"), - DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"), - DEVICE( FORE, FORE_PCA200E, "PCA-200E"), - DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"), - DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145"), - DEVICE( PHILIPS, PHILIPS_SAA7146,"SAA7146"), - DEVICE( CYCLONE, CYCLONE_SDK, "SDK"), - DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410"), - DEVICE( ALLIANCE, ALLIANCE_PROVIDEO, "Provideo"), - DEVICE( ALLIANCE, ALLIANCE_AT24, "AT24"), - DEVICE( ALLIANCE, ALLIANCE_AT3D, "AT3D"), - DEVICE( VMIC, VMIC_VME, "VMIVME-7587"), - DEVICE( DIGI, DIGI_EPC, "AccelPort EPC"), - DEVICE( DIGI, DIGI_RIGHTSWITCH, "RightSwitch SE-6"), - DEVICE( DIGI, DIGI_XEM, "AccelPort Xem"), - DEVICE( DIGI, DIGI_XR, "AccelPort Xr"), - DEVICE( DIGI, DIGI_CX, "AccelPort C/X"), - DEVICE( DIGI, DIGI_XRJ, "AccelPort Xr/J"), - DEVICE( DIGI, DIGI_EPCJ, "AccelPort EPC/J"), - DEVICE( DIGI, DIGI_XR_920, "AccelPort Xr 920"), - DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"), - DEVICE( RENDITION, RENDITION_VERITE,"Verite 1000"), - DEVICE( RENDITION, RENDITION_VERITE2100,"Verite 2100"), - DEVICE( TOSHIBA, TOSHIBA_601, "Laptop"), - DEVICE( TOSHIBA, TOSHIBA_TOPIC95,"ToPIC95"), - DEVICE( TOSHIBA, TOSHIBA_TOPIC97,"ToPIC97"), - DEVICE( RICOH, RICOH_RL5C466, "RL5C466"), - DEVICE( ARTOP, ARTOP_ATP8400, "ATP8400"), - DEVICE( ARTOP, ARTOP_ATP850UF, "ATP850UF"), - DEVICE( ZEITNET, ZEITNET_1221, "1221"), - DEVICE( ZEITNET, ZEITNET_1225, "1225"), - DEVICE( OMEGA, OMEGA_82C092G, "82C092G"), - DEVICE( LITEON, LITEON_LNE100TX,"LNE100TX"), - DEVICE( NP, NP_PCI_FDDI, "NP-PCI"), - DEVICE( ATT, ATT_L56XMF, "L56xMF"), - DEVICE( SPECIALIX, SPECIALIX_IO8, "IO8+/PCI"), - DEVICE( SPECIALIX, SPECIALIX_XIO, "XIO/SIO host"), - DEVICE( SPECIALIX, SPECIALIX_RIO, "RIO host"), - DEVICE( AURAVISION, AURAVISION_VXP524,"VXP524"), - DEVICE( IKON, IKON_10115, "10115 Greensheet"), - DEVICE( IKON, IKON_10117, "10117 Greensheet"), - DEVICE( ZORAN, ZORAN_36057, "ZR36057"), - DEVICE( ZORAN, ZORAN_36120, "ZR36120"), - DEVICE( KINETIC, KINETIC_2915, "2915 CAMAC"), - DEVICE( COMPEX, COMPEX_ENET100VG4, "Readylink ENET100-VG4"), - DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000"), - DEVICE( RP, RP32INTF, "RocketPort 32 Intf"), - DEVICE( RP, RP8INTF, "RocketPort 8 Intf"), - DEVICE( RP, RP16INTF, "RocketPort 16 Intf"), - DEVICE( RP, RP4QUAD, "Rocketport 4 Quad"), - DEVICE( RP, RP8OCTA, "RocketPort 8 Oct"), - DEVICE( RP, RP8J, "RocketPort 8 J"), - DEVICE( RP, RPP4, "RocketPort Plus 4 Quad"), - DEVICE( RP, RPP8, "RocketPort Plus 8 Oct"), - DEVICE( RP, RP8M, "RocketModem 8 J"), - DEVICE( CYCLADES, CYCLOM_Y_Lo, "Cyclom-Y below 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_Y_Hi, "Cyclom-Y above 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_4Y_Lo, "Cyclom-4Y below 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_4Y_Hi, "Cyclom-4Y above 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_8Y_Lo, "Cyclom-8Y below 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_8Y_Hi, "Cyclom-8Y above 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclades-Z below 1Mbyte"), - DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclades-Z above 1Mbyte"), - DEVICE( ESSENTIAL, ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI"), - DEVICE( O2, O2_6832, "6832"), - DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"), - DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"), - DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee"), - DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"), - DEVICE( AVM, AVM_A1, "A1 (Fritz)"), - DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"), - DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"), - DEVICE( STALLION, STALLION_EIOPCI,"EasyIO"), - DEVICE( OPTIBASE, OPTIBASE_FORGE, "MPEG Forge"), - DEVICE( OPTIBASE, OPTIBASE_FUSION,"MPEG Fusion"), - DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex"), - DEVICE( OPTIBASE, OPTIBASE_VPLEXCC,"VideoPlex CC"), - DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest"), - DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver"), - DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"), - DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC"), - DEVICE( ENSONIQ, ENSONIQ_ES1371, "ES1371"), - DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"), - DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC"), - DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"), - DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"), - DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16"), - DEVICE( MOTOROLA_OOPS, MOTOROLA_FALCON,"Falcon"), - DEVICE( SYMPHONY, SYMPHONY_101, "82C101"), - DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"), - DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"), - DEVICE( 3DLABS, 3DLABS_500TX, "GLINT 500TX"), - DEVICE( 3DLABS, 3DLABS_DELTA, "GLINT Delta"), - DEVICE( 3DLABS, 3DLABS_PERMEDIA,"PERMEDIA"), - DEVICE( 3DLABS, 3DLABS_MX, "GLINT MX"), - DEVICE( AVANCE, AVANCE_ALG2064, "ALG2064i"), - DEVICE( AVANCE, AVANCE_2302, "ALG-2302"), - DEVICE( NETVIN, NETVIN_NV5000SC,"NV5000"), - DEVICE( S3, S3_PLATO_PXS, "PLATO/PX (system)"), - DEVICE( S3, S3_ViRGE, "ViRGE"), - DEVICE( S3, S3_TRIO, "Trio32/Trio64"), - DEVICE( S3, S3_AURORA64VP, "Aurora64V+"), - DEVICE( S3, S3_TRIO64UVP, "Trio64UV+"), - DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX"), - DEVICE( S3, S3_868, "Vision 868"), - DEVICE( S3, S3_928, "Vision 928-P"), - DEVICE( S3, S3_864_1, "Vision 864-P"), - DEVICE( S3, S3_864_2, "Vision 864-P"), - DEVICE( S3, S3_964_1, "Vision 964-P"), - DEVICE( S3, S3_964_2, "Vision 964-P"), - DEVICE( S3, S3_968, "Vision 968"), - DEVICE( S3, S3_TRIO64V2, "Trio64V2/DX or /GX"), - DEVICE( S3, S3_PLATO_PXG, "PLATO/PX (graphics)"), - DEVICE( S3, S3_ViRGE_DXGX, "ViRGE/DX or /GX"), - DEVICE( S3, S3_ViRGE_GX2, "ViRGE/GX2"), - DEVICE( S3, S3_ViRGE_MX, "ViRGE/MX"), - DEVICE( S3, S3_ViRGE_MXP, "ViRGE/MX+"), - DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV"), - DEVICE( S3, S3_SONICVIBES, "SonicVibes"), - DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter"), - DEVICE( GENROCO, GENROCO_HFP832, "TURBOstor HFP832"), - DEVICE( INTEL, INTEL_82375, "82375EB"), - DEVICE( INTEL, INTEL_82424, "82424ZX Saturn"), - DEVICE( INTEL, INTEL_82378, "82378IB"), - DEVICE( INTEL, INTEL_82430, "82430ZX Aries"), - DEVICE( INTEL, INTEL_82434, "82434LX Mercury/Neptune"), - DEVICE( INTEL, INTEL_82092AA_0,"82092AA PCMCIA bridge"), - DEVICE( INTEL, INTEL_82092AA_1,"82092AA EIDE"), - DEVICE( INTEL, INTEL_7116, "SAA7116"), - DEVICE( INTEL, INTEL_82596, "82596"), - DEVICE( INTEL, INTEL_82865, "82865"), - DEVICE( INTEL, INTEL_82557, "82557"), - DEVICE( INTEL, INTEL_82437, "82437"), - DEVICE( INTEL, INTEL_82371FB_0,"82371FB PIIX ISA"), - DEVICE( INTEL, INTEL_82371FB_1,"82371FB PIIX IDE"), - DEVICE( INTEL, INTEL_82371MX, "430MX - 82371MX MPIIX"), - DEVICE( INTEL, INTEL_82437MX, "430MX - 82437MX MTSC"), - DEVICE( INTEL, INTEL_82441, "82441FX Natoma"), - DEVICE( INTEL, INTEL_82380FB, "82380FB Mobile"), - DEVICE( INTEL, INTEL_82439, "82439HX Triton II"), - DEVICE( INTEL, INTEL_82371SB_0,"82371SB PIIX3 ISA"), - DEVICE( INTEL, INTEL_82371SB_1,"82371SB PIIX3 IDE"), - DEVICE( INTEL, INTEL_82371SB_2,"82371SB PIIX3 USB"), - DEVICE( INTEL, INTEL_82437VX, "82437VX Triton II"), - DEVICE( INTEL, INTEL_82439TX, "82439TX"), - DEVICE( INTEL, INTEL_82371AB_0,"82371AB PIIX4 ISA"), - DEVICE( INTEL, INTEL_82371AB, "82371AB PIIX4 IDE"), - DEVICE( INTEL, INTEL_82371AB_2,"82371AB PIIX4 USB"), - DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 ACPI"), - DEVICE( INTEL, INTEL_82443LX_0,"440LX - 82443LX PAC Host"), - DEVICE( INTEL, INTEL_82443LX_1,"440LX - 82443LX PAC AGP"), - DEVICE( INTEL, INTEL_82443BX_0,"440BX - 82443BX Host"), - DEVICE( INTEL, INTEL_82443BX_1,"440BX - 82443BX AGP"), - DEVICE( INTEL, INTEL_82443BX_2,"440BX - 82443BX Host (no AGP)"), - DEVICE( INTEL, INTEL_P6, "Orion P6"), - DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6"), - DEVICE( KTI, KTI_ET32P2, "ET32P2"), - DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID"), - DEVICE( ADAPTEC, ADAPTEC_7821, "AIC-7860"), - DEVICE( ADAPTEC, ADAPTEC_38602, "AIC-7860"), - DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"), - DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"), - DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800"), - DEVICE( ADAPTEC, ADAPTEC_3860, "AIC-7860"), - DEVICE( ADAPTEC, ADAPTEC_7860, "AIC-7860"), - DEVICE( ADAPTEC, ADAPTEC_7861, "AIC-7861"), - DEVICE( ADAPTEC, ADAPTEC_7870, "AIC-7870"), - DEVICE( ADAPTEC, ADAPTEC_7871, "AIC-7871"), - DEVICE( ADAPTEC, ADAPTEC_7872, "AIC-7872"), - DEVICE( ADAPTEC, ADAPTEC_7873, "AIC-7873"), - DEVICE( ADAPTEC, ADAPTEC_7874, "AIC-7874"), - DEVICE( ADAPTEC, ADAPTEC_7895, "AIC-7895U"), - DEVICE( ADAPTEC, ADAPTEC_7880, "AIC-7880U"), - DEVICE( ADAPTEC, ADAPTEC_7881, "AIC-7881U"), - DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U"), - DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U"), - DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"), - DEVICE( ADAPTEC, ADAPTEC_7885, "AIC-7885U"), - DEVICE( ADAPTEC, ADAPTEC_7886, "AIC-7886U"), - DEVICE( ADAPTEC, ADAPTEC_7887, "AIC-7887U"), - DEVICE( ADAPTEC, ADAPTEC_7888, "AIC-7888U"), - DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver"), - DEVICE( ADAPTEC2, ADAPTEC2_2940U2,"AHA-2940U2"), - DEVICE( ADAPTEC2, ADAPTEC2_2930U2,"AHA-2930U2"), - DEVICE( ADAPTEC2, ADAPTEC2_7890B, "AIC-7890/1"), - DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1"), - DEVICE( ADAPTEC2, ADAPTEC2_3940U2,"AHA-3940U2"), - DEVICE( ADAPTEC2, ADAPTEC2_3950U2D,"AHA-3950U2D"), - DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7"), - DEVICE( ADAPTEC2, ADAPTEC2_7892A, "AIC-7892"), - DEVICE( ADAPTEC2, ADAPTEC2_7892B, "AIC-7892"), - DEVICE( ADAPTEC2, ADAPTEC2_7892D, "AIC-7892"), - DEVICE( ADAPTEC2, ADAPTEC2_7892P, "AIC-7892"), - DEVICE( ADAPTEC2, ADAPTEC2_7899A, "AIC-7899"), - DEVICE( ADAPTEC2, ADAPTEC2_7899B, "AIC-7899"), - DEVICE( ADAPTEC2, ADAPTEC2_7899D, "AIC-7899"), - DEVICE( ADAPTEC2, ADAPTEC2_7899P, "AIC-7899"), - DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"), - DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN"), - DEVICE( ARK, ARK_STING, "Stingray"), - DEVICE( ARK, ARK_STINGARK, "Stingray ARK 2000PV"), - DEVICE( ARK, ARK_2000MT, "2000MT") -}; - - -/* - * device_info[] is sorted so we can use binary search - */ -static struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev) -{ - int min = 0, - max = sizeof(dev_info)/sizeof(dev_info[0]) - 1; - - for ( ; ; ) - { - int i = (min + max) >> 1; - long order; - - order = dev_info[i].vendor - (long) vendor; - if (!order) - order = dev_info[i].device - (long) dev; - - if (order < 0) - { - min = i + 1; - if ( min > max ) - return 0; - continue; - } - - if (order > 0) - { - max = i - 1; - if ( min > max ) - return 0; - continue; - } - - return & dev_info[ i ]; - } -} - -static const char *pci_strclass (unsigned int class) -{ - switch (class >> 8) { - case PCI_CLASS_NOT_DEFINED: return "Non-VGA device"; - case PCI_CLASS_NOT_DEFINED_VGA: return "VGA compatible device"; - - case PCI_CLASS_STORAGE_SCSI: return "SCSI storage controller"; - case PCI_CLASS_STORAGE_IDE: return "IDE interface"; - case PCI_CLASS_STORAGE_FLOPPY: return "Floppy disk controller"; - case PCI_CLASS_STORAGE_IPI: return "IPI bus controller"; - case PCI_CLASS_STORAGE_RAID: return "RAID bus controller"; - case PCI_CLASS_STORAGE_OTHER: return "Unknown mass storage controller"; - - case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet controller"; - case PCI_CLASS_NETWORK_TOKEN_RING: return "Token ring network controller"; - case PCI_CLASS_NETWORK_FDDI: return "FDDI network controller"; - case PCI_CLASS_NETWORK_ATM: return "ATM network controller"; - case PCI_CLASS_NETWORK_OTHER: return "Network controller"; - - case PCI_CLASS_DISPLAY_VGA: return "VGA compatible controller"; - case PCI_CLASS_DISPLAY_XGA: return "XGA compatible controller"; - case PCI_CLASS_DISPLAY_OTHER: return "Display controller"; - - case PCI_CLASS_MULTIMEDIA_VIDEO: return "Multimedia video controller"; - case PCI_CLASS_MULTIMEDIA_AUDIO: return "Multimedia audio controller"; - case PCI_CLASS_MULTIMEDIA_OTHER: return "Multimedia controller"; - - case PCI_CLASS_MEMORY_RAM: return "RAM memory"; - case PCI_CLASS_MEMORY_FLASH: return "FLASH memory"; - case PCI_CLASS_MEMORY_OTHER: return "Memory"; - - case PCI_CLASS_BRIDGE_HOST: return "Host bridge"; - case PCI_CLASS_BRIDGE_ISA: return "ISA bridge"; - case PCI_CLASS_BRIDGE_EISA: return "EISA bridge"; - case PCI_CLASS_BRIDGE_MC: return "MicroChannel bridge"; - case PCI_CLASS_BRIDGE_PCI: return "PCI bridge"; - case PCI_CLASS_BRIDGE_PCMCIA: return "PCMCIA bridge"; - case PCI_CLASS_BRIDGE_NUBUS: return "NuBus bridge"; - case PCI_CLASS_BRIDGE_CARDBUS: return "CardBus bridge"; - case PCI_CLASS_BRIDGE_OTHER: return "Bridge"; - - case PCI_CLASS_COMMUNICATION_SERIAL: return "Serial controller"; - case PCI_CLASS_COMMUNICATION_PARALLEL: return "Parallel controller"; - case PCI_CLASS_COMMUNICATION_OTHER: return "Communication controller"; - - case PCI_CLASS_SYSTEM_PIC: return "PIC"; - case PCI_CLASS_SYSTEM_DMA: return "DMA controller"; - case PCI_CLASS_SYSTEM_TIMER: return "Timer"; - case PCI_CLASS_SYSTEM_RTC: return "RTC"; - case PCI_CLASS_SYSTEM_OTHER: return "System peripheral"; - - case PCI_CLASS_INPUT_KEYBOARD: return "Keyboard controller"; - case PCI_CLASS_INPUT_PEN: return "Digitizer Pen"; - case PCI_CLASS_INPUT_MOUSE: return "Mouse controller"; - case PCI_CLASS_INPUT_OTHER: return "Input device controller"; - - case PCI_CLASS_DOCKING_GENERIC: return "Generic Docking Station"; - case PCI_CLASS_DOCKING_OTHER: return "Docking Station"; - - case PCI_CLASS_PROCESSOR_386: return "386"; - case PCI_CLASS_PROCESSOR_486: return "486"; - case PCI_CLASS_PROCESSOR_PENTIUM: return "Pentium"; - case PCI_CLASS_PROCESSOR_ALPHA: return "Alpha"; - case PCI_CLASS_PROCESSOR_POWERPC: return "Power PC"; - case PCI_CLASS_PROCESSOR_CO: return "Co-processor"; - - case PCI_CLASS_SERIAL_FIREWIRE: return "FireWire (IEEE 1394)"; - case PCI_CLASS_SERIAL_ACCESS: return "ACCESS Bus"; - case PCI_CLASS_SERIAL_SSA: return "SSA"; - case PCI_CLASS_SERIAL_USB: return "USB Controller"; - case PCI_CLASS_SERIAL_FIBER: return "Fiber Channel"; - - case PCI_CLASS_HOT_SWAP_CONTROLLER: return "Hot Swap Controller"; - - default: return "Unknown class"; - } -} - - -static const char *pci_strvendor(unsigned int vendor) -{ - switch (vendor) { - case PCI_VENDOR_ID_COMPAQ: return "Compaq"; - case PCI_VENDOR_ID_NCR: return "NCR"; - case PCI_VENDOR_ID_ATI: return "ATI"; - case PCI_VENDOR_ID_VLSI: return "VLSI"; - case PCI_VENDOR_ID_ADL: return "Avance Logic"; - case PCI_VENDOR_ID_NS: return "NS"; - case PCI_VENDOR_ID_TSENG: return "Tseng'Lab"; - case PCI_VENDOR_ID_WEITEK: return "Weitek"; - case PCI_VENDOR_ID_DEC: return "DEC"; - case PCI_VENDOR_ID_CIRRUS: return "Cirrus Logic"; - case PCI_VENDOR_ID_IBM: return "IBM"; - case PCI_VENDOR_ID_WD: return "Western Digital"; - case PCI_VENDOR_ID_AMD: return "AMD"; - case PCI_VENDOR_ID_TRIDENT: return "Trident"; - case PCI_VENDOR_ID_AI: return "Acer Incorporated"; - case PCI_VENDOR_ID_MATROX: return "Matrox"; - case PCI_VENDOR_ID_CT: return "Chips & Technologies"; - case PCI_VENDOR_ID_MIRO: return "Miro"; - case PCI_VENDOR_ID_NEC: return "NEC"; - case PCI_VENDOR_ID_FD: return "Future Domain"; - case PCI_VENDOR_ID_SI: return "Silicon Integrated Systems"; - case PCI_VENDOR_ID_HP: return "Hewlett Packard"; - case PCI_VENDOR_ID_PCTECH: return "PCTECH"; - case PCI_VENDOR_ID_DPT: return "DPT"; - case PCI_VENDOR_ID_OPTI: return "OPTi"; - case PCI_VENDOR_ID_SGS: return "SGS Thomson"; - case PCI_VENDOR_ID_BUSLOGIC: return "BusLogic"; - case PCI_VENDOR_ID_TI: return "Texas Instruments"; - case PCI_VENDOR_ID_OAK: return "OAK"; - case PCI_VENDOR_ID_WINBOND2: return "Winbond"; - case PCI_VENDOR_ID_MOTOROLA: return "Motorola"; - case PCI_VENDOR_ID_MOTOROLA_OOPS: return "Motorola"; - case PCI_VENDOR_ID_PROMISE: return "Promise Technology"; - case PCI_VENDOR_ID_N9: return "Number Nine"; - case PCI_VENDOR_ID_UMC: return "UMC"; - case PCI_VENDOR_ID_X: return "X TECHNOLOGY"; - case PCI_VENDOR_ID_PICOP: return "PicoPower"; - case PCI_VENDOR_ID_APPLE: return "Apple"; - case PCI_VENDOR_ID_NEXGEN: return "Nexgen"; - case PCI_VENDOR_ID_QLOGIC: return "Q Logic"; - case PCI_VENDOR_ID_CYRIX: return "Cyrix"; - case PCI_VENDOR_ID_LEADTEK: return "Leadtek Research"; - case PCI_VENDOR_ID_CONTAQ: return "Contaq"; - case PCI_VENDOR_ID_FOREX: return "Forex"; - case PCI_VENDOR_ID_OLICOM: return "Olicom"; - case PCI_VENDOR_ID_SUN: return "Sun Microsystems"; - case PCI_VENDOR_ID_CMD: return "CMD"; - case PCI_VENDOR_ID_VISION: return "Vision"; - case PCI_VENDOR_ID_BROOKTREE: return "Brooktree"; - case PCI_VENDOR_ID_SIERRA: return "Sierra"; - case PCI_VENDOR_ID_ACC: return "ACC MICROELECTRONICS"; - case PCI_VENDOR_ID_WINBOND: return "Winbond"; - case PCI_VENDOR_ID_DATABOOK: return "Databook"; - case PCI_VENDOR_ID_PLX: return "PLX"; - case PCI_VENDOR_ID_MADGE: return "Madge Networks"; - case PCI_VENDOR_ID_3COM: return "3Com"; - case PCI_VENDOR_ID_SMC: return "SMC"; - case PCI_VENDOR_ID_AL: return "Acer Labs"; - case PCI_VENDOR_ID_MITSUBISHI: return "Mitsubishi"; - case PCI_VENDOR_ID_SURECOM: return "Surecom"; - case PCI_VENDOR_ID_NEOMAGIC: return "Neomagic"; - case PCI_VENDOR_ID_ASP: return "Advanced System Products"; - case PCI_VENDOR_ID_MACRONIX: return "Macronix"; - case PCI_VENDOR_ID_CERN: return "CERN"; - case PCI_VENDOR_ID_NVIDIA: return "NVidia"; - case PCI_VENDOR_ID_IMS: return "IMS"; - case PCI_VENDOR_ID_TEKRAM2: return "Tekram"; - case PCI_VENDOR_ID_TUNDRA: return "Tundra"; - case PCI_VENDOR_ID_AMCC: return "AMCC"; - case PCI_VENDOR_ID_INTERG: return "Intergraphics"; - case PCI_VENDOR_ID_REALTEK: return "Realtek"; - case PCI_VENDOR_ID_TRUEVISION: return "Truevision"; - case PCI_VENDOR_ID_INIT: return "Initio Corp"; - case PCI_VENDOR_ID_TTI: return "Triones Technologies, Inc."; - case PCI_VENDOR_ID_VIA: return "VIA Technologies"; - case PCI_VENDOR_ID_SMC2: return "SMC"; - case PCI_VENDOR_ID_VORTEX: return "VORTEX"; - case PCI_VENDOR_ID_EF: return "Efficient Networks"; - case PCI_VENDOR_ID_FORE: return "Fore Systems"; - case PCI_VENDOR_ID_IMAGINGTECH: return "Imaging Technology"; - case PCI_VENDOR_ID_PHILIPS: return "Philips"; - case PCI_VENDOR_ID_CYCLONE: return "Cyclone"; - case PCI_VENDOR_ID_ALLIANCE: return "Alliance"; - case PCI_VENDOR_ID_VMIC: return "VMIC"; - case PCI_VENDOR_ID_DIGI: return "Digi Intl."; - case PCI_VENDOR_ID_MUTECH: return "Mutech"; - case PCI_VENDOR_ID_RENDITION: return "Rendition"; - case PCI_VENDOR_ID_TOSHIBA: return "Toshiba"; - case PCI_VENDOR_ID_RICOH: return "Ricoh"; - case PCI_VENDOR_ID_ARTOP: return "Artop Electronics"; - case PCI_VENDOR_ID_ZEITNET: return "ZeitNet"; - case PCI_VENDOR_ID_OMEGA: return "Omega Micro"; - case PCI_VENDOR_ID_LITEON: return "LiteOn"; - case PCI_VENDOR_ID_NP: return "Network Peripherals"; - case PCI_VENDOR_ID_ATT: return "Lucent (ex-AT&T) Microelectronics"; - case PCI_VENDOR_ID_SPECIALIX: return "Specialix"; - case PCI_VENDOR_ID_AURAVISION: return "Auravision"; - case PCI_VENDOR_ID_IKON: return "Ikon"; - case PCI_VENDOR_ID_ZORAN: return "Zoran"; - case PCI_VENDOR_ID_KINETIC: return "Kinetic"; - case PCI_VENDOR_ID_COMPEX: return "Compex"; - case PCI_VENDOR_ID_RP: return "Comtrol"; - case PCI_VENDOR_ID_CYCLADES: return "Cyclades"; - case PCI_VENDOR_ID_ESSENTIAL: return "Essential Communications"; - case PCI_VENDOR_ID_O2: return "O2 Micro"; - case PCI_VENDOR_ID_3DFX: return "3Dfx"; - case PCI_VENDOR_ID_SIGMADES: return "Sigma Designs"; - case PCI_VENDOR_ID_AVM: return "AVM"; - case PCI_VENDOR_ID_CCUBE: return "C-Cube"; - case PCI_VENDOR_ID_DIPIX: return "Dipix"; - case PCI_VENDOR_ID_STALLION: return "Stallion Technologies"; - case PCI_VENDOR_ID_OPTIBASE: return "Optibase"; - case PCI_VENDOR_ID_SATSAGEM: return "SatSagem"; - case PCI_VENDOR_ID_HUGHES: return "Hughes"; - case PCI_VENDOR_ID_ENSONIQ: return "Ensoniq"; - case PCI_VENDOR_ID_ALTEON: return "Alteon"; - case PCI_VENDOR_ID_PICTUREL: return "Picture Elements"; - case PCI_VENDOR_ID_NVIDIA_SGS: return "NVidia/SGS Thomson"; - case PCI_VENDOR_ID_CBOARDS: return "ComputerBoards"; - case PCI_VENDOR_ID_SYMPHONY: return "Symphony"; - case PCI_VENDOR_ID_TEKRAM: return "Tekram"; - case PCI_VENDOR_ID_3DLABS: return "3Dlabs"; - case PCI_VENDOR_ID_AVANCE: return "Avance"; - case PCI_VENDOR_ID_NETVIN: return "NetVin"; - case PCI_VENDOR_ID_S3: return "S3 Inc."; - case PCI_VENDOR_ID_DCI: return "Decision Computer Int."; - case PCI_VENDOR_ID_GENROCO: return "Genroco"; - case PCI_VENDOR_ID_INTEL: return "Intel"; - case PCI_VENDOR_ID_KTI: return "KTI"; - case PCI_VENDOR_ID_ADAPTEC: return "Adaptec"; - case PCI_VENDOR_ID_ADAPTEC2: return "Adaptec"; - case PCI_VENDOR_ID_ATRONICS: return "Atronics"; - case PCI_VENDOR_ID_TIGERJET: return "TigerJet"; - case PCI_VENDOR_ID_ARK: return "ARK Logic"; - default: return "Unknown vendor"; - } -} - - -static const char *pci_strdev(unsigned int vendor, unsigned int device) -{ - struct pci_dev_info *info; - - info = pci_lookup_dev(vendor, device); - return info ? info->name : "Unknown device"; -} - - -/* - * Convert some of the configuration space registers of the device at - * address (bus,devfn) into a string (possibly several lines each). - * The configuration string is stored starting at buf[len]. If the - * string would exceed the size of the buffer (SIZE), 0 is returned. - */ -static int sprint_dev_config(struct pci_dev *dev, char *buf, int size) -{ - unsigned long base; - unsigned int class_rev, bus, devfn; - unsigned short vendor, device, status; - unsigned char bist, latency, min_gnt, max_lat; - int reg, len = 0; - const char *str; - - bus = dev->bus->number; - devfn = dev->devfn; - - pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev); - pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor); - pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device); - pcibios_read_config_word (bus, devfn, PCI_STATUS, &status); - pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist); - pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency); - pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt); - pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat); - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, " %s: %s %s (rev %d).\n ", - pci_strclass(class_rev >> 8), pci_strvendor(vendor), - pci_strdev(vendor, device), class_rev & 0xff); - - if (!pci_lookup_dev(vendor, device)) { - len += sprintf(buf + len, - "Vendor id=%x. Device id=%x.\n ", - vendor, device); - } - - switch (status & PCI_STATUS_DEVSEL_MASK) { - case PCI_STATUS_DEVSEL_FAST: str = "Fast devsel. "; break; - case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel. "; break; - case PCI_STATUS_DEVSEL_SLOW: str = "Slow devsel. "; break; - default: str = "Unknown devsel. "; - } - if (len + strlen(str) > size) { - return -1; - } - len += sprintf(buf + len, str); - - if (status & PCI_STATUS_FAST_BACK) { -# define fast_b2b_capable "Fast back-to-back capable. " - if (len + strlen(fast_b2b_capable) > size) { - return -1; - } - len += sprintf(buf + len, fast_b2b_capable); -# undef fast_b2b_capable - } - - if (bist & PCI_BIST_CAPABLE) { -# define BIST_capable "BIST capable. " - if (len + strlen(BIST_capable) > size) { - return -1; - } - len += sprintf(buf + len, BIST_capable); -# undef BIST_capable - } - - if (dev->irq) { - if (len + 40 > size) { - return -1; - } - len += sprintf(buf + len, "IRQ %d. ", dev->irq); - } - - if (dev->master) { - if (len + 80 > size) { - return -1; - } - len += sprintf(buf + len, "Master Capable. "); - if (latency) - len += sprintf(buf + len, "Latency=%d. ", latency); - else - len += sprintf(buf + len, "No bursts. "); - if (min_gnt) - len += sprintf(buf + len, "Min Gnt=%d.", min_gnt); - if (max_lat) - len += sprintf(buf + len, "Max Lat=%d.", max_lat); - } - - for (reg = 0; reg < 6; reg++) { - if (len + 40 > size) { - return -1; - } - base = dev->base_address[reg]; - if (!base) - continue; - - if (base & PCI_BASE_ADDRESS_SPACE_IO) { - len += sprintf(buf + len, - "\n I/O at 0x%lx [0x%lx].", - base & PCI_BASE_ADDRESS_IO_MASK, - dev->base_address[reg]); - } else { - const char *pref, *type = "unknown"; - - if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) { - pref = "P"; - } else { - pref = "Non-p"; - } - switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { - case PCI_BASE_ADDRESS_MEM_TYPE_32: - type = "32 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_1M: - type = "20 bit"; break; - case PCI_BASE_ADDRESS_MEM_TYPE_64: - type = "64 bit"; break; - } - len += sprintf(buf + len, - "\n %srefetchable %s memory at " - "0x%lx [0x%lx].", pref, type, - base & PCI_BASE_ADDRESS_MEM_MASK, - dev->base_address[reg]); - } - } - - len += sprintf(buf + len, "\n"); - return len; -} - - -/* - * Return list of PCI devices as a character string for /proc/pci. - * BUF is a buffer that is PAGE_SIZE bytes long. - */ -int get_pci_list(char *buf) -{ - int nprinted, len, size; - struct pci_dev *dev; - static int complained = 0; -# define MSG "\nwarning: page-size limit reached!\n" - - if (!complained) { - complained++; - printk(KERN_INFO "%s uses obsolete /proc/pci interface\n", - current->comm); - } - - /* reserve same for truncation warning message: */ - size = PAGE_SIZE - (strlen(MSG) + 1); - len = sprintf(buf, "PCI devices found:\n"); - - for (dev = pci_devices; dev; dev = dev->next) { - nprinted = sprint_dev_config(dev, buf + len, size - len); - if (nprinted < 0) { - return len + sprintf(buf + len, MSG); - } - len += nprinted; - } - return len; -} - -static struct proc_dir_entry proc_old_pci = { - PROC_PCI, 3, "pci", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations -}; - -void __init proc_old_pci_init(void) -{ - proc_register(&proc_root, &proc_old_pci); -} - -#endif /* CONFIG_PROC_FS */ diff -u --recursive --new-file v2.3.12/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.3.12/linux/drivers/pci/pci.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/pci/pci.c Fri Aug 6 11:58:00 1999 @@ -29,8 +29,9 @@ struct pci_bus pci_root; struct pci_dev *pci_devices = NULL; +int pci_reverse __initdata = 0; + static struct pci_dev **pci_last_dev_p = &pci_devices; -static int pci_reverse __initdata = 0; struct pci_dev * pci_find_slot(unsigned int bus, unsigned int devfn) @@ -143,25 +144,56 @@ unsigned int reg; u32 l; - for(reg=0; regresource + reg; + unsigned int mask, newval, size; + + res->name = dev->name; pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l); if (l == 0xffffffff) continue; - dev->base_address[reg] = l; + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), 0xffffffff); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &newval); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), l); + + mask = PCI_BASE_ADDRESS_MEM_MASK; + if (l & PCI_BASE_ADDRESS_SPACE_IO) + mask = PCI_BASE_ADDRESS_IO_MASK; + + newval &= mask; + if (!newval) + continue; + + res->start = l & mask; + res->flags = l & ~mask; + + size = 1; + do { + size <<= 1; + } while (!(size & newval)); + + /* 64-bit memory? */ if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { + unsigned int high; reg++; - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l); - if (l) { + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &high); + if (high) { #if BITS_PER_LONG == 64 - dev->base_address[reg-1] |= ((unsigned long) l) << 32; + res->start |= ((unsigned long) high) << 32; #else printk("PCI: Unable to handle 64-bit address for device %02x:%02x\n", dev->bus->number, dev->devfn); - dev->base_address[reg-1] = 0; + res->flags = 0; + res->start = 0; + res->end = 0; + continue; #endif } } + res->end = res->start + size - 1; + request_resource((l & PCI_BASE_ADDRESS_SPACE_IO) ? &ioport_resource : &iomem_resource, res); } } @@ -202,6 +234,7 @@ dev->devfn = devfn; dev->vendor = l & 0xffff; dev->device = (l >> 16) & 0xffff; + pci_namedevice(dev); /* non-destructively determine if device can be a master: */ pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd); @@ -419,13 +452,9 @@ #ifdef CONFIG_PCI_QUIRKS pci_quirks_init(); #endif - -#ifdef CONFIG_PROC_FS - pci_proc_init(); -#endif } -void __init pci_setup (char *str, int *ints) +static int __init pci_setup(char *str) { while (str) { char *k = strchr(str, ','); @@ -438,4 +467,7 @@ } str = k; } + return 1; } + +__setup("pci=", pci_setup); diff -u --recursive --new-file v2.3.12/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.3.12/linux/drivers/pci/proc.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/pci/proc.c Sat Aug 7 12:59:40 1999 @@ -6,12 +6,12 @@ * Copyright (c) 1997, 1998 Martin Mares */ -#include #include #include #include #include #include + #include #include @@ -247,14 +247,15 @@ dev->vendor, dev->device, dev->irq); - for(i=0; i<6; i++) + for(i=0; i<6; i++) { len += sprintf(buf+len, #if BITS_PER_LONG == 32 "\t%08lx", #else "\t%016lx", #endif - dev->base_address[i]); + dev->resource[i].start | (dev->resource[i].flags & 0xf)); + } len += sprintf(buf+len, #if BITS_PER_LONG == 32 "\t%08lx", @@ -321,7 +322,7 @@ return 0; } -__initfunc(void proc_bus_pci_add(struct pci_bus *bus)) +void __init proc_bus_pci_add(struct pci_bus *bus) { while (bus) { struct pci_dev *dev; @@ -334,15 +335,266 @@ } } -__initfunc(void pci_proc_init(void)) +static const char *pci_strclass (unsigned int class) { - if (!pci_present()) - return; - proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus); - proc_register(proc_bus_pci_dir, &proc_pci_devices); - proc_bus_pci_add(&pci_root); + switch (class >> 8) { + case PCI_CLASS_NOT_DEFINED: return "Non-VGA device"; + case PCI_CLASS_NOT_DEFINED_VGA: return "VGA compatible device"; + + case PCI_CLASS_STORAGE_SCSI: return "SCSI storage controller"; + case PCI_CLASS_STORAGE_IDE: return "IDE interface"; + case PCI_CLASS_STORAGE_FLOPPY: return "Floppy disk controller"; + case PCI_CLASS_STORAGE_IPI: return "IPI bus controller"; + case PCI_CLASS_STORAGE_RAID: return "RAID bus controller"; + case PCI_CLASS_STORAGE_OTHER: return "Unknown mass storage controller"; + + case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet controller"; + case PCI_CLASS_NETWORK_TOKEN_RING: return "Token ring network controller"; + case PCI_CLASS_NETWORK_FDDI: return "FDDI network controller"; + case PCI_CLASS_NETWORK_ATM: return "ATM network controller"; + case PCI_CLASS_NETWORK_OTHER: return "Network controller"; + + case PCI_CLASS_DISPLAY_VGA: return "VGA compatible controller"; + case PCI_CLASS_DISPLAY_XGA: return "XGA compatible controller"; + case PCI_CLASS_DISPLAY_OTHER: return "Display controller"; + + case PCI_CLASS_MULTIMEDIA_VIDEO: return "Multimedia video controller"; + case PCI_CLASS_MULTIMEDIA_AUDIO: return "Multimedia audio controller"; + case PCI_CLASS_MULTIMEDIA_OTHER: return "Multimedia controller"; + + case PCI_CLASS_MEMORY_RAM: return "RAM memory"; + case PCI_CLASS_MEMORY_FLASH: return "FLASH memory"; + case PCI_CLASS_MEMORY_OTHER: return "Memory"; + + case PCI_CLASS_BRIDGE_HOST: return "Host bridge"; + case PCI_CLASS_BRIDGE_ISA: return "ISA bridge"; + case PCI_CLASS_BRIDGE_EISA: return "EISA bridge"; + case PCI_CLASS_BRIDGE_MC: return "MicroChannel bridge"; + case PCI_CLASS_BRIDGE_PCI: return "PCI bridge"; + case PCI_CLASS_BRIDGE_PCMCIA: return "PCMCIA bridge"; + case PCI_CLASS_BRIDGE_NUBUS: return "NuBus bridge"; + case PCI_CLASS_BRIDGE_CARDBUS: return "CardBus bridge"; + case PCI_CLASS_BRIDGE_OTHER: return "Bridge"; + + case PCI_CLASS_COMMUNICATION_SERIAL: return "Serial controller"; + case PCI_CLASS_COMMUNICATION_PARALLEL: return "Parallel controller"; + case PCI_CLASS_COMMUNICATION_OTHER: return "Communication controller"; + + case PCI_CLASS_SYSTEM_PIC: return "PIC"; + case PCI_CLASS_SYSTEM_DMA: return "DMA controller"; + case PCI_CLASS_SYSTEM_TIMER: return "Timer"; + case PCI_CLASS_SYSTEM_RTC: return "RTC"; + case PCI_CLASS_SYSTEM_OTHER: return "System peripheral"; + + case PCI_CLASS_INPUT_KEYBOARD: return "Keyboard controller"; + case PCI_CLASS_INPUT_PEN: return "Digitizer Pen"; + case PCI_CLASS_INPUT_MOUSE: return "Mouse controller"; + case PCI_CLASS_INPUT_OTHER: return "Input device controller"; + + case PCI_CLASS_DOCKING_GENERIC: return "Generic Docking Station"; + case PCI_CLASS_DOCKING_OTHER: return "Docking Station"; + + case PCI_CLASS_PROCESSOR_386: return "386"; + case PCI_CLASS_PROCESSOR_486: return "486"; + case PCI_CLASS_PROCESSOR_PENTIUM: return "Pentium"; + case PCI_CLASS_PROCESSOR_ALPHA: return "Alpha"; + case PCI_CLASS_PROCESSOR_POWERPC: return "Power PC"; + case PCI_CLASS_PROCESSOR_CO: return "Co-processor"; + + case PCI_CLASS_SERIAL_FIREWIRE: return "FireWire (IEEE 1394)"; + case PCI_CLASS_SERIAL_ACCESS: return "ACCESS Bus"; + case PCI_CLASS_SERIAL_SSA: return "SSA"; + case PCI_CLASS_SERIAL_USB: return "USB Controller"; + case PCI_CLASS_SERIAL_FIBER: return "Fiber Channel"; -#ifdef CONFIG_PCI_OLD_PROC - proc_old_pci_init(); -#endif + case PCI_CLASS_HOT_SWAP_CONTROLLER: return "Hot Swap Controller"; + + default: return "Unknown class"; + } +} + +/* + * Convert some of the configuration space registers of the device at + * address (bus,devfn) into a string (possibly several lines each). + * The configuration string is stored starting at buf[len]. If the + * string would exceed the size of the buffer (SIZE), 0 is returned. + */ +static int sprint_dev_config(struct pci_dev *dev, char *buf, int size) +{ + unsigned int class_rev, bus, devfn; + unsigned short vendor, device, status; + unsigned char bist, latency, min_gnt, max_lat; + int reg, len = 0; + const char *str; + + bus = dev->bus->number; + devfn = dev->devfn; + + pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev); + pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor); + pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device); + pcibios_read_config_word (bus, devfn, PCI_STATUS, &status); + pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist); + pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency); + pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt); + pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat); + if (len + 80 > size) { + return -1; + } + len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + if (len + 80 > size) { + return -1; + } + len += sprintf(buf + len, " %s: %s (rev %d).\n ", + pci_strclass(class_rev >> 8), + dev->name, + class_rev & 0xff); + + switch (status & PCI_STATUS_DEVSEL_MASK) { + case PCI_STATUS_DEVSEL_FAST: str = "Fast devsel. "; break; + case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel. "; break; + case PCI_STATUS_DEVSEL_SLOW: str = "Slow devsel. "; break; + default: str = "Unknown devsel. "; + } + if (len + strlen(str) > size) { + return -1; + } + len += sprintf(buf + len, str); + + if (status & PCI_STATUS_FAST_BACK) { +# define fast_b2b_capable "Fast back-to-back capable. " + if (len + strlen(fast_b2b_capable) > size) { + return -1; + } + len += sprintf(buf + len, fast_b2b_capable); +# undef fast_b2b_capable + } + + if (bist & PCI_BIST_CAPABLE) { +# define BIST_capable "BIST capable. " + if (len + strlen(BIST_capable) > size) { + return -1; + } + len += sprintf(buf + len, BIST_capable); +# undef BIST_capable + } + + if (dev->irq) { + if (len + 40 > size) { + return -1; + } + len += sprintf(buf + len, "IRQ %d. ", dev->irq); + } + + if (dev->master) { + if (len + 80 > size) { + return -1; + } + len += sprintf(buf + len, "Master Capable. "); + if (latency) + len += sprintf(buf + len, "Latency=%d. ", latency); + else + len += sprintf(buf + len, "No bursts. "); + if (min_gnt) + len += sprintf(buf + len, "Min Gnt=%d.", min_gnt); + if (max_lat) + len += sprintf(buf + len, "Max Lat=%d.", max_lat); + } + + for (reg = 0; reg < 6; reg++) { + struct resource *res = dev->resource + reg; + unsigned long base, end, flags; + + if (len + 40 > size) { + return -1; + } + base = res->start; + end = res->end; + flags = res->flags; + if (!end) + continue; + + if (flags & PCI_BASE_ADDRESS_SPACE_IO) { + len += sprintf(buf + len, + "\n I/O at 0x%lx [0x%lx].", + base, end); + } else { + const char *pref, *type = "unknown"; + + if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) { + pref = "P"; + } else { + pref = "Non-p"; + } + switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + type = "32 bit"; break; + case PCI_BASE_ADDRESS_MEM_TYPE_1M: + type = "20 bit"; break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + type = "64 bit"; break; + } + len += sprintf(buf + len, + "\n %srefetchable %s memory at " + "0x%lx [0x%lx].", pref, type, + base, + end); + } + } + + len += sprintf(buf + len, "\n"); + return len; +} + + +/* + * Return list of PCI devices as a character string for /proc/pci. + * BUF is a buffer that is PAGE_SIZE bytes long. + */ +int get_pci_list(char *buf) +{ + int nprinted, len, size; + struct pci_dev *dev; + static int complained = 0; +# define MSG "\nwarning: page-size limit reached!\n" + + if (!complained) { + complained++; + printk(KERN_INFO "%s uses obsolete /proc/pci interface\n", + current->comm); + } + + /* reserve same for truncation warning message: */ + size = PAGE_SIZE - (strlen(MSG) + 1); + len = sprintf(buf, "PCI devices found:\n"); + + for (dev = pci_devices; dev; dev = dev->next) { + nprinted = sprint_dev_config(dev, buf + len, size - len); + if (nprinted < 0) { + return len + sprintf(buf + len, MSG); + } + len += nprinted; + } + return len; } + +static struct proc_dir_entry proc_old_pci = { + PROC_PCI, 3, "pci", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations +}; + +static int __init pci_proc_init(void) +{ + if (pci_present()) { + proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus); + proc_register(proc_bus_pci_dir, &proc_pci_devices); + proc_bus_pci_add(&pci_root); + proc_register(&proc_root, &proc_old_pci); + } + return 0; +} + +__initcall(pci_proc_init); diff -u --recursive --new-file v2.3.12/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c --- v2.3.12/linux/drivers/pci/quirks.c Thu Jan 7 09:21:53 1999 +++ linux/drivers/pci/quirks.c Thu Aug 5 18:44:28 1999 @@ -76,7 +76,7 @@ {0x0 ,0x0 ,0x0 }, }; -__initfunc(static void quirk_bridge(struct pci_dev *dev, int pos)) +static void __init quirk_bridge(struct pci_dev *dev, int pos) { struct bridge_mapping_type *bmap; unsigned char val; @@ -108,7 +108,7 @@ /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ -__initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg)) +static void __init quirk_passive_release(struct pci_dev *dev, int arg) { struct pci_dev *d = NULL; unsigned char dlc; @@ -135,7 +135,7 @@ int isa_dma_bridge_buggy = 0; /* Exported */ -__initfunc(static void quirk_isa_dma_hangs(struct pci_dev *dev, int arg)) +static void __init quirk_isa_dma_hangs(struct pci_dev *dev, int arg) { if(!isa_dma_bridge_buggy) { @@ -204,7 +204,7 @@ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs, 0x00 }, }; -__initfunc(void pci_quirks_init(void)) +void __init pci_quirks_init(void) { struct pci_dev *d; int i; diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.3.12/linux/drivers/sbus/audio/audio.c Wed May 12 08:41:15 1999 +++ linux/drivers/sbus/audio/audio.c Fri Aug 6 11:58:00 1999 @@ -313,7 +313,7 @@ kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); /* Stop the lowlevel driver from outputing. */ - /* drv->ops->stop_output(drv); Should not be necessary -- DJB 5/25/98 */ + drv->ops->stop_output(drv); drv->output_active = 0; /* Wake up any waiting writers or syncers and return. */ @@ -669,7 +669,7 @@ case SOUND_MIXER_WRITE_CD: case SOUND_MIXER_WRITE_LINE: case SOUND_MIXER_WRITE_IMIX: - if(get_user(k, arg)) + if(COPY_IN(arg, k)) return -EFAULT; tprintk(("setting input volume (0x%x)", k)); if (drv->ops->get_input_channels) @@ -700,7 +700,7 @@ case SOUND_MIXER_WRITE_PCM: case SOUND_MIXER_WRITE_VOLUME: case SOUND_MIXER_WRITE_SPEAKER: - if(get_user(k, arg)) + if(COPY_IN(arg, k)) return -EFAULT; tprintk(("setting output volume (0x%x)", k)); if (drv->ops->get_output_channels) @@ -741,7 +741,7 @@ case SOUND_MIXER_WRITE_RECSRC: if (!drv->ops->set_input_port) return -EINVAL; - if(get_user(k, arg)) + if(COPY_IN(arg, k)) return -EFAULT; /* only one should ever be selected */ if (k & SOUND_MASK_IMIX) j = AUDIO_ANALOG_LOOPBACK; diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.3.12/linux/drivers/sbus/audio/cs4231.c Wed Apr 28 08:47:39 1999 +++ linux/drivers/sbus/audio/cs4231.c Fri Aug 6 11:58:00 1999 @@ -1421,7 +1421,7 @@ status += 2; } - sparcaudio_input_done(drv, 1); + sparcaudio_input_done(drv, status); return 1; } @@ -1484,26 +1484,23 @@ cs4231_chip->perchip_info.play.active = 1; cs4231_chip->playing_count = 0; + cs4231_playintr(drv); if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) || !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) { - cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY; - cs4231_chip->regs->dmacsr &= ~APC_PPAUSE; - - cs4231_playintr(drv); - - cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP; + cs4231_chip->regs->dmacsr &= ~(APC_XINT_PLAY | APC_PPAUSE); + cs4231_chip->regs->dmacsr |= APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY + | APC_XINT_GENL | APC_XINT_PENA | APC_PDMA_READY; cs4231_enable_play(drv); - + cs4231_ready(drv); - } else - cs4231_playintr(drv); + } } #ifdef EB4231_SUPPORT static void eb4231_stop_output(struct sparcaudio_driver *drv) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int dcsr; + unsigned int dcsr; dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n", readl(&cs4231_chip->eb2p->dcsr), @@ -1525,6 +1522,7 @@ /* Else subsequent speed setting changes are ignored by the chip. */ cs4231_disable_play(drv); + cs4231_chip->perchip_info.play.active = 0; } #endif @@ -1547,9 +1545,14 @@ cs4231_chip->output_next_dma_handle = 0; cs4231_chip->output_next_dma_size = 0; } -#if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */ +#if 1 /* Not safe without shutting off the DMA controller as well. -DaveM */ /* Else subsequent speed setting changes are ignored by the chip. */ + cs4231_chip->regs->dmacsr &= ~(APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY + | APC_XINT_GENL | APC_PDMA_READY + | APC_XINT_PENA | APC_PPAUSE ); + printk("in cs4231_stop_output: 0x%x\n", cs4231_chip->regs->dmacsr); cs4231_disable_play(drv); + cs4231_chip->perchip_info.play.active = 0; #endif } @@ -1635,6 +1638,68 @@ cs4231_pollinput(drv); } +#ifdef EB4231_SUPPORT +static void eb4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, + unsigned long count) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int dcsr; + + cs4231_chip->input_ptr = buffer; + cs4231_chip->input_size = count; + + if (cs4231_chip->perchip_info.record.active || + (cs4231_chip->perchip_info.record.pause)) + return; + + cs4231_ready(drv); + + cs4231_chip->perchip_info.record.active = 1; + cs4231_chip->recording_count = 0; + + dcsr = readl(&cs4231_chip->eb2c->dcsr); + if (!(dcsr & EBUS_DCSR_EN_DMA)) { + writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr)); + + eb4231_recintr(drv); + + writel(EBUS_DCSR_BURST_SZ_16 | + (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), + &(cs4231_chip->eb2c->dcsr)); + + cs4231_enable_rec(drv); + cs4231_ready(drv); + } else + eb4231_recintr(drv); +} + +static void eb4231_stop_input(struct sparcaudio_driver *drv) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + unsigned int dcsr; + + cs4231_chip->perchip_info.record.active = 0; + + cs4231_chip->input_ptr = NULL; + cs4231_chip->input_size = 0; + if (cs4231_chip->input_dma_handle) { + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + } + if (cs4231_chip->input_next_dma_handle) { + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + } + + dcsr = readl(&(cs4231_chip->eb2c->dcsr)); + if (dcsr & EBUS_DCSR_EN_DMA) + writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2c->dcsr)); + + cs4231_disable_rec(drv); +} +#endif + static int cs4231_set_output_pause(struct sparcaudio_driver *drv, int value) { struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; @@ -1763,13 +1828,25 @@ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; int dummy; - /* Read status. */ - dummy = readl(&cs4231_chip->eb2c->dcsr); + /* Clear the interrupt. */ + dummy = readl(&(cs4231_chip->eb2c->dcsr)); + writel(dummy, &(cs4231_chip->eb2c->dcsr)); - cs4231_chip->perchip_info.record.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), - cs4231_chip->reclen); - eb4231_recintr(drv); + if ((dummy & EBUS_DCSR_TC) != 0 + /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + eb4231_recintr(drv); + } + + if ((dummy & EBUS_DCSR_A_LOADED) == 0) { + cs4231_chip->perchip_info.record.active = 0; + eb4231_recintr(drv); +#if 1 + eb4231_getsamplecount(drv, cs4231_chip->reclen, 1); +#endif + } } /* ebus audio play interrupt handler. */ @@ -1797,7 +1874,6 @@ } if((dummy & EBUS_DCSR_A_LOADED) == 0) { - cs4231_chip->perchip_info.play.active = 0; eb4231_playintr(drv); eb4231_getsamplecount(drv, cs4231_chip->playlen, 0); @@ -1822,13 +1898,11 @@ * if anything since we may be doing shared interrupts */ - if (dummy & APC_PLAY_INT) { - if (dummy & APC_XINT_PNVA) { + if (dummy & (APC_PLAY_INT|APC_XINT_PNVA|APC_XINT_PLAY|APC_XINT_EMPT|APC_XINT_PEMP)) { cs4231_chip->perchip_info.play.samples += cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), cs4231_chip->playlen); cs4231_playintr(drv); - } /* Any other conditions we need worry about? */ } @@ -1853,6 +1927,7 @@ } if (dummy & APC_XINT_EMPT) { +#if 0 /* Call to stop_output from midlevel will get this */ if (!cs4231_chip->output_next_dma_handle) { cs4231_chip->regs->dmacsr |= (APC_PPAUSE); cs4231_disable_play(drv); @@ -1860,6 +1935,7 @@ } cs4231_chip->perchip_info.play.active = 0; cs4231_playintr(drv); +#endif cs4231_getsamplecount(drv, cs4231_chip->playlen, 0); } @@ -1937,8 +2013,8 @@ cs4231_ioctl, eb4231_start_output, eb4231_stop_output, - cs4231_start_input, - cs4231_stop_input, + eb4231_start_input, + eb4231_stop_input, cs4231_audio_getdev, cs4231_set_output_volume, cs4231_get_output_volume, diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c --- v2.3.12/linux/drivers/sbus/char/bpp.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/sbus/char/bpp.c Fri Aug 6 11:58:00 1999 @@ -148,18 +148,18 @@ */ struct bpp_regs { /* DMA registers */ - __u32 p_csr; /* DMA Control/Status Register */ - __u32 p_addr; /* Address Register */ - __u32 p_bcnt; /* Byte Count Register */ - __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */ + __volatile__ __u32 p_csr; /* DMA Control/Status Register */ + __volatile__ __u32 p_addr; /* Address Register */ + __volatile__ __u32 p_bcnt; /* Byte Count Register */ + __volatile__ __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */ /* Parallel Port registers */ - __u16 p_hcr; /* Hardware Configuration Register */ - __u16 p_ocr; /* Operation Configuration Register */ - __u8 p_dr; /* Parallel Data Register */ - __u8 p_tcr; /* Transfer Control Register */ - __u8 p_or; /* Output Register */ - __u8 p_ir; /* Input Register */ - __u16 p_icr; /* Interrupt Control Register */ + __volatile__ __u16 p_hcr; /* Hardware Configuration Register */ + __volatile__ __u16 p_ocr; /* Operation Configuration Register */ + __volatile__ __u8 p_dr; /* Parallel Data Register */ + __volatile__ __u8 p_tcr; /* Transfer Control Register */ + __volatile__ __u8 p_or; /* Output Register */ + __volatile__ __u8 p_ir; /* Input Register */ + __volatile__ __u16 p_icr; /* Interrupt Control Register */ }; /* P_CSR. Bits of type RW1 are cleared with writting '1'. */ diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.3.12/linux/drivers/sbus/char/sunkbd.c Wed May 12 08:41:15 1999 +++ linux/drivers/sbus/char/sunkbd.c Mon Aug 2 22:07:16 1999 @@ -79,11 +79,6 @@ struct l1a_kbd_state l1a_state = { 0, 0 }; -/* Dummy function for now, we need it to link. -DaveM */ -void kbd_reset_setup(char *str, int *ints) -{ -} - #ifndef CONFIG_PCI DECLARE_WAIT_QUEUE_HEAD(keypress_wait); #endif @@ -1305,7 +1300,7 @@ p = buffer; for (; p < end && kbd_head != kbd_tail;){ #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c --- v2.3.12/linux/drivers/sbus/char/sunmouse.c Wed May 12 08:41:15 1999 +++ linux/drivers/sbus/char/sunmouse.c Mon Aug 2 22:07:16 1999 @@ -386,7 +386,7 @@ while (p < end && !queue_empty ()){ #ifdef CONFIG_SPARC32_COMPAT - if (current->tss.flags & SPARC_FLAG_32BIT) { + if (current->thread.flags & SPARC_FLAG_32BIT) { Firm_event *q = get_from_queue(); copy_to_user_ret((Firm_event *)p, q, diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.3.12/linux/drivers/sbus/char/zs.c Wed May 12 08:41:15 1999 +++ linux/drivers/sbus/char/zs.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.42 1999/05/12 11:15:26 davem Exp $ +/* $Id: zs.c,v 1.43 1999/07/17 06:03:58 zaitcev Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1844,7 +1844,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.42 $"; + char *revision = "$Revision: 1.43 $"; char *version, *p; version = strchr(revision, ' '); @@ -2012,9 +2012,8 @@ /* Can use the prom for other machine types */ zsnode = prom_getchild(prom_root_node); if (sparc_cpu_model == sun4d) { - int node; int no = 0; - + tmpnode = zsnode; zsnode = 0; bbnode = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- v2.3.12/linux/drivers/sbus/sbus.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/sbus/sbus.c Mon Aug 2 22:07:16 1999 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.77 1999/05/29 06:25:57 davem Exp $ +/* $Id: sbus.c,v 1.78 1999/07/23 02:00:27 davem Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c --- v2.3.12/linux/drivers/scsi/53c7,8xx.c Thu May 14 18:48:16 1998 +++ linux/drivers/scsi/53c7,8xx.c Mon Aug 9 10:23:09 1999 @@ -1198,10 +1198,10 @@ * */ -__initfunc(static int +static int __init normal_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, int pci_valid, - unsigned char pci_bus, unsigned char pci_device_fn, long long options)) { + unsigned char pci_bus, unsigned char pci_device_fn, long long options){ struct Scsi_Host *instance; struct NCR53c7x0_hostdata *hostdata; char chip_str[80]; @@ -1411,9 +1411,9 @@ * */ -__initfunc(static int +static int __init ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, - unsigned char bus, unsigned char device_fn, long long options)) { + unsigned char bus, unsigned char device_fn, long long options){ unsigned short command; #ifdef LINUX_1_2 unsigned long @@ -1445,8 +1445,8 @@ " perhaps you specified an incorrect PCI bus, device, or function.\n", error); return -1; } - io_port = pdev->base_address[0]; - base = pdev->base_address[1]; + io_port = pdev->resource[0].start; + base = pdev->resource[1].start; irq = pdev->irq; /* If any one ever clones the NCR chips, this will have to change */ @@ -1560,8 +1560,8 @@ * */ -__initfunc(int -NCR53c7xx_detect(Scsi_Host_Template *tpnt)) { +int __init +NCR53c7xx_detect(Scsi_Host_Template *tpnt){ int i; int current_override; int count; /* Number of boards detected */ diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c --- v2.3.12/linux/drivers/scsi/53c7xx.c Thu Jul 8 15:42:20 1999 +++ linux/drivers/scsi/53c7xx.c Mon Aug 9 12:32:28 1999 @@ -296,6 +296,10 @@ */ #undef inb #undef outb +#undef inw +#undef outw +#undef inl +#undef outl #define inb(x) 1 #define inw(x) 1 #define inl(x) 1 @@ -1207,7 +1211,7 @@ memset((void *)instance->hostdata[0], 0, 8192); cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192); cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192); - kernel_set_cachemode(instance->hostdata[0], 8192, KERNELMAP_NOCACHE_SER); + kernel_set_cachemode(instance->hostdata[0], 8192, IOMAP_NOCACHE_SER); /* FIXME : if we ever support an ISA NCR53c7xx based board, we need to check if the chip is running in a 16 bit mode, and if so @@ -1897,7 +1901,7 @@ if (left < 0) printk("scsi%d: loop detected in ncr reconncect list\n", host->host_no); - else if (ncr_search) + else if (ncr_search) { if (found) printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n", host->host_no, c->pid); @@ -1908,6 +1912,7 @@ /* If we're at the tail end of the issue queue, update that pointer too. */ found = 1; } + } /* * Traverse the host running list until we find this command or discover @@ -2958,14 +2963,14 @@ NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM); else NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl); -#if 0 - /* Following disables snooping - run with caches disabled at first */ + /* Following disables snooping - snooping is not required, as non- + * cached pages are used for shared data, and appropriate use is + * made of cache_push/cache_clear. Indeed, for 68060 + * enabling snooping causes disk corruption of ext2fs free block + * bitmaps and the like. If you have a 68060 with snooping hardwared + * on, then you need to enable CONFIG_060_WRITETHROUGH. + */ NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD); -#else - /* Setup CTEST7 for SC1=0, SC0=1 - sink/source data without invalidating - * cache lines. */ - NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD|CTEST7_10_SC0); -#endif /* Actually burst of eight, according to my 53c710 databook */ NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2); NCR53c7x0_write8(SCID_REG, 1 << host->this_id); @@ -3028,10 +3033,10 @@ static void my_free_page (void *addr, int dummy) { - /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which + /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which * XXX may be invalid (CONFIG_060_WRITETHROUGH) */ - kernel_set_cachemode((u32)addr, 4096, KERNELMAP_FULL_CACHING); + kernel_set_cachemode((u32)addr, 4096, IOMAP_FULL_CACHING); free_page ((u32)addr); } @@ -3087,7 +3092,7 @@ memset((void *)real, 0, 4096); cache_push(virt_to_phys((void *)real), 4096); cache_clear(virt_to_phys((void *)real), 4096); - kernel_set_cachemode(real, 4096, KERNELMAP_NOCACHE_SER); + kernel_set_cachemode(real, 4096, IOMAP_NOCACHE_SER); tmp = ROUNDUP(real, void *); #ifdef FORCE_DSA_ALIGNMENT { @@ -3190,7 +3195,6 @@ case MODE_SELECT: case WRITE_6: case WRITE_10: - case START_STOP: /* also SCAN, which may do DATA OUT */ #if 0 printk("scsi%d : command is ", host->host_no); print_command(cmd->cmnd); @@ -3211,6 +3215,7 @@ */ case TEST_UNIT_READY: case ALLOW_MEDIUM_REMOVAL: + case START_STOP: datain = dataout = 0; break; /* @@ -5945,11 +5950,12 @@ } } } - if (!(istat & (ISTAT_SIP|ISTAT_DIP))) + if (!(istat & (ISTAT_SIP|ISTAT_DIP))) { if (stage == 0) ++stage; else if (stage == 3) break; + } } hostdata->state = STATE_HALTED; restore_flags(flags); @@ -6090,10 +6096,10 @@ if (hostdata->events) vfree ((void *)hostdata->events); - /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which + /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which * XXX may be invalid (CONFIG_060_WRITETHROUGH) */ - kernel_set_cachemode((u32)hostdata, 8192, KERNELMAP_FULL_CACHING); + kernel_set_cachemode((u32)hostdata, 8192, IOMAP_FULL_CACHING); free_pages ((u32)hostdata, 1); return 1; } diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c --- v2.3.12/linux/drivers/scsi/AM53C974.c Mon Jan 11 13:46:47 1999 +++ linux/drivers/scsi/AM53C974.c Mon Aug 9 10:23:09 1999 @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -659,7 +660,7 @@ * * Returns : number of host adapters detected **************************************************************************/ -__initfunc(int AM53C974_detect(Scsi_Host_Template * tpnt)) +int __init AM53C974_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ @@ -686,7 +687,7 @@ * set up by the BIOS (as reflected by contents of register CNTLREG1). * This is the only BIOS assistance we need. **************************************************************************/ -__initfunc(static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev)) +static int __init AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev) { AM53C974_local_declare(); int i, j; @@ -701,7 +702,7 @@ instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata)); hostdata = (struct AM53C974_hostdata *) instance->hostdata; instance->base = NULL; - instance->io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + instance->io_port = pdev->resource[0].start; instance->irq = pdev->irq; instance->dma_channel = -1; AM53C974_setio(instance); @@ -2467,5 +2468,9 @@ #ifdef MODULE static Scsi_Host_Template driver_template = AM53C974; +/* You can specify overrides=a,b,c,d in the same format at AM53C974=a,b,c,d + on boot up */ + +MODULE_PARM(overrides, "1-32i"); #include "scsi_module.c" #endif diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.3.12/linux/drivers/scsi/BusLogic.c Mon Aug 17 01:01:01 1998 +++ linux/drivers/scsi/BusLogic.c Fri Aug 6 11:43:09 1999 @@ -781,8 +781,8 @@ unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = PCI_Device->base_address[0]; - unsigned long BaseAddress1 = PCI_Device->base_address[1]; + unsigned long BaseAddress0 = PCI_Device->resource[0].start; + unsigned long BaseAddress1 = PCI_Device->resource[1].start; BusLogic_IO_Address_T IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; BusLogic_PCI_Address_T PCI_Address = @@ -987,7 +987,7 @@ unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; BusLogic_IO_Address_T IO_Address = - PCI_Device->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + PCI_Device->resource[0].start & PCI_BASE_ADDRESS_IO_MASK; if (IO_Address == 0 || IRQ_Channel == 0) continue; for (i = 0; i < BusLogic_ProbeInfoCount; i++) { @@ -1030,8 +1030,8 @@ unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = PCI_Device->base_address[0]; - unsigned long BaseAddress1 = PCI_Device->base_address[1]; + unsigned long BaseAddress0 = PCI_Device->resource[0].start; + unsigned long BaseAddress1 = PCI_Device->resource[1].start; BusLogic_IO_Address_T IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK; BusLogic_PCI_Address_T PCI_Address = diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c --- v2.3.12/linux/drivers/scsi/NCR5380.c Thu Apr 15 05:45:12 1999 +++ linux/drivers/scsi/NCR5380.c Mon Aug 9 10:25:01 1999 @@ -736,12 +736,12 @@ static int probe_irq __initdata = 0; -__initfunc(static void probe_intr(int irq, void *dev_id, struct pt_regs *regs)) +static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs) { probe_irq = irq; } -__initfunc(static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible)) +static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible) { NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) @@ -797,7 +797,7 @@ * Inputs : instance, pointer to this instance. Unused. */ -__initfunc(static void NCR5380_print_options(struct Scsi_Host *instance)) +static void __init NCR5380_print_options(struct Scsi_Host *instance) { printk(" generic options" #ifdef AUTOPROBE_IRQ @@ -1018,7 +1018,7 @@ * */ -__initfunc(static void NCR5380_init(struct Scsi_Host *instance, int flags)) +static void __init NCR5380_init(struct Scsi_Host *instance, int flags) { NCR5380_local_declare(); int i, pass; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c --- v2.3.12/linux/drivers/scsi/NCR53c406a.c Fri Jan 15 14:41:04 1999 +++ linux/drivers/scsi/NCR53c406a.c Mon Aug 9 10:25:01 1999 @@ -461,8 +461,8 @@ } #endif USE_PIO -__initfunc(int -NCR53c406a_detect(Scsi_Host_Template * tpnt)){ +int __init +NCR53c406a_detect(Scsi_Host_Template * tpnt){ struct Scsi_Host *shpnt; #ifndef PORT_BASE int i; @@ -593,7 +593,7 @@ } /* called from init/main.c */ -__initfunc(void NCR53c406a_setup(char *str, int *ints)) +void __init NCR53c406a_setup(char *str, int *ints) { static size_t setup_idx = 0; size_t i; @@ -1022,7 +1022,7 @@ outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ } -__initfunc(void calc_port_addr(void)) +void __init calc_port_addr(void) { /* Control Register Set 0 */ TC_LSB = (port_base+0x00); diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/README.st linux/drivers/scsi/README.st --- v2.3.12/linux/drivers/scsi/README.st Sat May 22 14:50:07 1999 +++ linux/drivers/scsi/README.st Mon Aug 9 10:23:42 1999 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai M{kisara (email Kai.Makisara@metla.fi) -Last modified: Sun Apr 18 13:24:43 1999 by makisara@home +Last modified: Sat Aug 7 13:52:16 1999 by makisara@kai.makisara.local BASICS @@ -130,22 +130,26 @@ 2^n * (page size). Because of this the actual buffer size may be larger than the buffer size specified with ST_BUFFER_BLOCKS. -Allocation of the buffers is done at run-time when they are -needed. Allocation of the specified number of buffers can be done at -initialization if ST_RUNTIME_BUFFERS is defined non-zero. The -advantage of run-time allocation is that memory is not wasted for -buffers not being used. The disadvantage is that there may not be -memory available at the time when a buffer is needed for the first -time (once a buffer is allocated, it is not released). - -The maximum number of buffers allocated at initialization is defined by -ST_MAX_BUFFERS. One buffer is allocated for each drive detected when -the driver is initialized up to the maximum. The minimum number of -allocated buffers is ST_EXTRA_DEVS (in hosts.h). This ensures some -functionality also for the drives found after tape driver -initialization (a SCSI adapter driver is loaded as a module). The -default for ST_EXTRA_DEVS is two. The driver tries to allocate new -buffers at run-time if necessary. +A small number of buffers are allocated at driver initialisation. The +maximum number of these buffers is defined by ST_MAX_BUFFERS. The +maximum can be changed with kernel or module startup options. One +buffer is allocated for each drive detected when the driver is +initialized up to the maximum. The minimum number of allocated buffers +is ST_EXTRA_DEVS (in hosts.h) (unless this number exceeds the defined +maximum). This ensures some functionality also for the drives found +after tape driver initialization (a SCSI adapter driver is loaded as a +module). The default for ST_EXTRA_DEVS is two. + +The driver tries to allocate new buffers at run-time if +necessary. These buffers are freed after use. If the maximum number of +initial buffers is set to zero, all buffer allocation is done at +run-time. The advantage of run-time allocation is that memory is not +wasted for buffers not being used. The disadvantage is that there may +not be memory available at the time when a buffer is needed for the +first time (once a buffer is allocated, it is not released). This risk +should not be big if the tape drive is connected to a PCI adapter that +supports scatter/gather (the allocation is not limited to "DMA memory" +and the buffer can be composed of several fragments). The threshold for triggering asynchronous write in fixed block mode is defined by ST_WRITE_THRESHOLD. This may be optimized for each @@ -178,31 +182,43 @@ extending the buffer will always fail. -BOOT TIME CONFIGURATION +MODULE PARAMETERS The buffer size, write threshold, and the maximum number of allocated buffers -are configurable at boot time using, e.g., the LILO command line. The option -syntax is the following: +are configurable when the driver is loaded as a module. The keywords are: + +buffer_kbs=xxx the buffer size in kilobytes is set to xxx +write_threshold_kbs=xxx the write threshold in kilobytes set to xxx +max_buffers=xxx the maximum number of tape buffer set to xxx +max_sg_segs=xxx the maximum number of scatter/gather + segments + +Note that if the buffer size is changed but the write threshold is not +set, the write threshold is set to the new buffer size - 2 kB. + + +BOOT TIME CONFIGURATION + +If the driver is compiled into the kernel, the same parameters can be +also set using, e.g., the LILO command line. The preferred syntax is +to use the same keywords as when loading the driver as module. If +several parameters are set, the keyword-value pairs are separated with +a comma (no spaces allowed). A colon can be used instead of the equal +mark. The definition is prepended by the string st=. Here is an +example: - st=aa[,bb[,cc]] + st=buffer_kbs:64,max_buffers:2 + +The following syntax used by the old kernel versions is also supported: + + st=aa[,bb[,cc[,dd]]] where aa is the buffer size in 1024 byte units bb is the write threshold in 1024 byte units cc is the maximum number of tape buffers to allocate (the number of buffers is bounded also by the number of drives detected) - - -MODULE PARAMETERS - -The same parameters can be also set when the driver is loaded as a -module. The keywords are: - -buffer_kbs=xxx the buffer size in kilobytes is set to xxx -write_threshold_kbs=xxx the write threshold in kilobytes set to xxx -max_buffers=xxx the maximum number of tape buffer set to xxx -max_sg_segs=xxx the maximum number of scatter/gather - segments + dd is the maximum number of scatter/gather segments IOCTLS diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v2.3.12/linux/drivers/scsi/advansys.c Tue Dec 29 11:35:48 1998 +++ linux/drivers/scsi/advansys.c Thu Aug 5 15:07:42 1999 @@ -4370,7 +4370,7 @@ ASC_DBG2(2, "advansys_detect: devfn %d, bus number %d\n", pci_devp->devfn, pci_devp->bus->number); - iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; + iop = pci_devp->resource[0].start; ASC_DBG2(1, "advansys_detect: vendorID %X, deviceID %X\n", pci_devp->vendor, pci_devp->device); @@ -4484,7 +4484,7 @@ #endif /* ASC_CONFIG_PCI */ #else /* version >= v2.1.93 */ #ifdef CONFIG_PCI - pci_memory_address = pci_devp->base_address[1]; + pci_memory_address = pci_devp->resource[1].start; if ((boardp->ioremap_addr = ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) { diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c --- v2.3.12/linux/drivers/scsi/aic7xxx.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/scsi/aic7xxx.c Wed Aug 4 22:53:14 1999 @@ -9536,10 +9536,8 @@ temp_p->pdev = pdev; temp_p->pci_bus = pdev->bus->number; temp_p->pci_device_fn = pdev->devfn; - temp_p->base = pdev->base_address[0]; - temp_p->mbase = pdev->base_address[1]; - temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; - temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; + temp_p->base = pdev->resource[0].start; + temp_p->mbase = pdev->resource[1].start; current_p = list_p; while(current_p) { diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.3.12/linux/drivers/scsi/eata.c Fri Oct 9 11:56:59 1998 +++ linux/drivers/scsi/eata.c Mon Aug 9 10:25:01 1999 @@ -516,7 +516,6 @@ #define ASOK 0x00 #define ASST 0x01 -#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) #define YESNO(a) ((a) ? 'y' : 'n') #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) @@ -829,8 +828,8 @@ return FALSE; } -__initfunc (static inline int - get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) { +static inline int __init +get_pci_irq(unsigned long port_base, unsigned char *apic_irq){ #if defined(CONFIG_PCI) @@ -867,8 +866,8 @@ return FALSE; } -__initfunc (static inline int port_detect \ - (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { +static inline int __init port_detect \ + (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt){ unsigned char irq, dma_channel, subversion, i; unsigned char protocol_rev, apic_irq; struct eata_info info; @@ -1152,7 +1151,7 @@ return TRUE; } -__initfunc (void eata2x_setup(char *str, int *ints)) { +void __init eata2x_setup(char *str, int *ints){ int i, argc = ints[0]; char *cur = str, *pc; @@ -1188,7 +1187,7 @@ return; } -__initfunc (static void add_pci_ports(void)) { +static void __init add_pci_ports(void){ #if defined(CONFIG_PCI) @@ -1254,7 +1253,7 @@ return; } -__initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { +int __init eata2x_detect(Scsi_Host_Template *tpnt){ unsigned int j = 0, k; IRQ_FLAGS diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.3.12/linux/drivers/scsi/eata_dma.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/scsi/eata_dma.c Thu Aug 5 15:08:56 1999 @@ -1414,12 +1414,12 @@ DBG(DBG_PROBE && DBG_PCI, printk("eata_dma: find_PCI, HBA at %s\n", dev->name)); pci_set_master(dev); - base = dev->base_address[0]; + base = dev->resource[0].flags; if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { printk("eata_dma: invalid base address of device %s\n", dev->name); continue; } - base &= PCI_BASE_ADDRESS_IO_MASK; + base = dev->resource[0].start; /* EISA tag there ? */ pal1 = inb(base); pal2 = inb(base + 1); diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.3.12/linux/drivers/scsi/eata_pio.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/scsi/eata_pio.c Thu Aug 5 15:08:56 1999 @@ -890,12 +890,12 @@ DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); pci_set_master(dev); - base = dev->base_address[0]; + base = dev->resource[0].flags; if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { printk("eata_pio: invalid base address of device %s\n", dev->name); continue; } - base &= PCI_BASE_ADDRESS_IO_MASK; + base = dev->resource[0].start; /* EISA tag there ? */ if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) continue; /* Jep, it's forced, so move on */ diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.3.12/linux/drivers/scsi/fdomain.c Tue Dec 29 11:44:53 1998 +++ linux/drivers/scsi/fdomain.c Mon Aug 9 10:25:01 1999 @@ -840,14 +840,14 @@ /* We now have the appropriate device function for the FD board so we just read the PCI config info from the registers. */ - pci_base = pdev->base_address[0]; + pci_base = pdev->resource[0].start; pci_irq = pdev->irq; /* Now we have the I/O base address and interrupt from the PCI configuration registers. */ *irq = pci_irq; - *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK); + *iobase = pci_base; #if DEBUG_DETECT printk( "scsi: TMC-3260 detect:" diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v2.3.12/linux/drivers/scsi/g_NCR5380.c Sun Dec 27 10:53:45 1998 +++ linux/drivers/scsi/g_NCR5380.c Mon Aug 9 10:25:01 1999 @@ -158,7 +158,7 @@ * */ -__initfunc(static void internal_setup(int board, char *str, int *ints)) { +static void __init internal_setup(int board, char *str, int *ints){ static int commandline_current = 0; switch (board) { case BOARD_NCR5380: @@ -204,7 +204,7 @@ * equal to the number of ints. */ -__initfunc(void generic_NCR5380_setup (char *str, int *ints)) { +void __init generic_NCR5380_setup (char *str, int *ints){ internal_setup (BOARD_NCR5380, str, ints); } @@ -217,7 +217,7 @@ * equal to the number of ints. */ -__initfunc(void generic_NCR53C400_setup (char *str, int *ints)) { +void __init generic_NCR53C400_setup (char *str, int *ints){ internal_setup (BOARD_NCR53C400, str, ints); } @@ -259,7 +259,7 @@ * */ -__initfunc(int generic_NCR5380_detect(Scsi_Host_Template * tpnt)) { +int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt){ static int current_override = 0; int count, i; u_int *ports; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.3.12/linux/drivers/scsi/gdth.c Mon Apr 12 09:56:16 1999 +++ linux/drivers/scsi/gdth.c Mon Aug 9 10:25:01 1999 @@ -598,7 +598,7 @@ /* controller search and initialization functions */ -__initfunc (static int gdth_search_eisa(ushort eisa_adr)) +static int __init gdth_search_eisa(ushort eisa_adr) { ulong32 id; @@ -616,7 +616,7 @@ } -__initfunc (static int gdth_search_isa(ulong32 bios_adr)) +static int __init gdth_search_isa(ulong32 bios_adr) { void *addr; ulong32 id; @@ -632,7 +632,7 @@ } -__initfunc (static int gdth_search_pci(gdth_pci_str *pcistr)) +static int __init gdth_search_pci(gdth_pci_str *pcistr) { ulong32 base0, base1, base2; ushort device_id, cnt; @@ -651,7 +651,6 @@ if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 && device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP) continue; -#if LINUX_VERSION_CODE >= 0x2015C pdev = NULL; while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) != NULL) { @@ -663,15 +662,15 @@ pcistr[cnt].bus = pdev->bus->number; pcistr[cnt].device_fn = pdev->devfn; pcistr[cnt].irq = pdev->irq; - base0 = pdev->base_address[0]; - base1 = pdev->base_address[1]; - base2 = pdev->base_address[2]; + base0 = pdev->resource[0].flags; + base1 = pdev->resource[1].flags; + base2 = pdev->resource[2].flags; if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ if ((base0 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) continue; - pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; + pcistr[cnt].dpmem = pdev->resource[0].start; } else { /* GDT6110, GDT6120, .. */ if ((base0 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY || @@ -680,77 +679,21 @@ (base1 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; - pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; + pcistr[cnt].dpmem = pdev->resource[2].start; + pcistr[cnt].io_mm = pdev->resource[0].start; + pcistr[cnt].io = pdev->resource[1].start; } TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n", pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), pcistr[cnt].irq, pcistr[cnt].dpmem)); cnt++; } -#else - idx = 0; - while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++, - &pcistr[cnt].bus,&pcistr[cnt].device_fn)) { - if (cnt >= MAXHA) - return cnt; - /* GDT PCI ctr. found, now read resources from config space */ -#if LINUX_VERSION_CODE >= 0x010300 -#define GDTH_BASEP (int *) -#else -#define GDTH_BASEP -#endif - if ((error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_byte(pcistr[cnt].bus, - pcistr[cnt].device_fn, - PCI_INTERRUPT_LINE, - &pcistr[cnt].irq))) { - printk("GDT-PCI: error %d reading configuration space", error); - continue; - } - pcistr[cnt].device_id = device_id; - if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n", - pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), - pcistr[cnt].irq, pcistr[cnt].dpmem)); - cnt++; - } -#endif } return cnt; } -__initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt)) +static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) { gdth_pci_str temp; int i, changed; @@ -788,7 +731,7 @@ } -__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)) +static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha) { ulong32 retries,id; unchar prot_ver,eisacf,i,irq_found; @@ -877,7 +820,7 @@ } -__initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)) +static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) { register gdt2_dpram_str *dp2_ptr; int i; @@ -974,7 +917,7 @@ } -__initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) +static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) { register gdt6_dpram_str *dp6_ptr; register gdt6c_dpram_str *dp6c_ptr; @@ -1241,7 +1184,7 @@ /* controller protocol functions */ -__initfunc (static void gdth_enable_int(int hanum)) +static void __init gdth_enable_int(int hanum) { gdth_ha_str *ha; ulong flags; @@ -1574,7 +1517,7 @@ /* search for devices */ -__initfunc (static int gdth_search_drives(int hanum)) +static int __init gdth_search_drives(int hanum) { register gdth_ha_str *ha; ushort cdev_cnt, i; @@ -3287,7 +3230,7 @@ #endif -__initfunc (int gdth_detect(Scsi_Host_Template *shtp)) +int __init gdth_detect(Scsi_Host_Template *shtp) { struct Scsi_Host *shp; gdth_ha_str *ha; @@ -3959,7 +3902,7 @@ /* called from init/main.c */ -__initfunc (void gdth_setup(char *str,int *ints)) +void __init gdth_setup(char *str,int *ints) { int i, argc; char *cur_str, *argv; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v2.3.12/linux/drivers/scsi/hosts.c Tue May 11 14:37:40 1999 +++ linux/drivers/scsi/hosts.c Mon Aug 9 10:25:01 1999 @@ -752,7 +752,7 @@ shpnt->eh_notify = NULL; } -__initfunc(unsigned int scsi_init(void)) +unsigned int __init scsi_init(void) { static int called = 0; int i, pcount; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c --- v2.3.12/linux/drivers/scsi/ini9100u.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/ini9100u.c Mon Aug 9 10:25:01 1999 @@ -348,7 +348,7 @@ dRegValue = 0; wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); if (Addi91u_into_Adapter_table(wBIOS, - (pDev->base_address[0] & 0xFFFE), + (pDev->resource[0].start), pDev->irq, pDev->bus->number, (pDev->devfn >> 3) diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c --- v2.3.12/linux/drivers/scsi/inia100.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/inia100.c Mon Aug 9 10:25:01 1999 @@ -330,7 +330,7 @@ #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) bPCIBusNum = pdev->bus->number; bPCIDeviceNum = pdev->devfn; - dRegValue = pdev->base_address[0]; + dRegValue = pdev->resource[0].start; if (dRegValue == -1) { /* Check return code */ printk("\n\rinia100: orchid read configuration error.\n"); return (0); /* Read configuration space error */ diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.3.12/linux/drivers/scsi/megaraid.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/megaraid.c Mon Aug 9 10:25:01 1999 @@ -1267,17 +1267,8 @@ PCI_FUNC (pciDevFun)); /* Read the base port and IRQ from PCI */ -#if LINUX_VERSION_CODE < 0x20100 - pcibios_read_config_dword (pciBus, pciDevFun, - PCI_BASE_ADDRESS_0, - (u_int *) & megaBase); - pcibios_read_config_byte (pciBus, pciDevFun, - PCI_INTERRUPT_LINE, - &megaIrq); -#else - megaBase = pdev->base_address[0]; + megaBase = pdev->resource[0].start; megaIrq = pdev->irq; -#endif pciIdx++; if (flag & BOARD_QUARTZ) { diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c --- v2.3.12/linux/drivers/scsi/pas16.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/pas16.c Mon Aug 9 10:25:01 1999 @@ -213,8 +213,8 @@ * */ -__initfunc(static void - enable_board( int board_num, unsigned short port )) +static void __init + enable_board( int board_num, unsigned short port ) { outb( 0xbc + board_num, MASTER_ADDRESS_PTR ); outb( port >> 2, MASTER_ADDRESS_PTR ); @@ -233,8 +233,8 @@ * */ -__initfunc (static void - init_board( unsigned short io_port, int irq, int force_irq )) +static void __init + init_board( unsigned short io_port, int irq, int force_irq ) { unsigned int tmp; unsigned int pas_irq_code; @@ -282,8 +282,8 @@ * Returns : 0 if board not found, 1 if found. */ -__initfunc(static int - pas16_hw_detect( unsigned short board_num )) +static int __init + pas16_hw_detect( unsigned short board_num ) { unsigned char board_rev, tmp; unsigned short io_port = bases[ board_num ].io_port; @@ -342,7 +342,8 @@ * */ -__initfunc(void pas16_setup(char *str, int *ints)) { +void __init pas16_setup(char *str, int *ints) +{ static int commandline_current = 0; int i; if (ints[0] != 2) @@ -373,7 +374,8 @@ * */ -__initfunc(int pas16_detect(Scsi_Host_Template * tpnt)) { +int __init pas16_detect(Scsi_Host_Template * tpnt) +{ static int current_override = 0; static unsigned short current_base = 0; struct Scsi_Host *instance; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c --- v2.3.12/linux/drivers/scsi/pci2000.c Tue Apr 13 07:54:02 1999 +++ linux/drivers/scsi/pci2000.c Thu Aug 5 15:08:56 1999 @@ -640,12 +640,8 @@ pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); padapter = HOSTDATA(pshost); -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) - padapter->basePort = pdev->base_address[1] & 0xFFFE; -#else - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort); - padapter->basePort &= 0xFFFE; -#endif + padapter->basePort = pdev->resource[1].start; + DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c --- v2.3.12/linux/drivers/scsi/pci2220i.c Tue Apr 13 07:54:02 1999 +++ linux/drivers/scsi/pci2220i.c Thu Aug 5 15:08:56 1999 @@ -1822,12 +1822,7 @@ padapter = HOSTDATA(pshost); memset (padapter, 0, sizeof (ADAPTER2220I)); -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) - zs = pdev->base_address[1] & 0xFFFE; -#else - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs); - zs &= 0xFFFE; -#endif + zs = pdev->resource[1].start; padapter->basePort = zs; padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor @@ -1835,12 +1830,7 @@ padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) - zs = pdev->base_address[2] & 0xFFFE; -#else - pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs); - zs &= 0xFFFE; -#endif + zs = pdev->resource[2].start; padapter->regBase = zs; padapter->regData = zs + REG_DATA; // data register I/O address padapter->regError = zs + REG_ERROR; // error register I/O address diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c --- v2.3.12/linux/drivers/scsi/qlogicfc.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/qlogicfc.c Thu Aug 5 15:11:52 1999 @@ -1828,7 +1828,7 @@ printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id); return 1; } - io_base = pdev->base_address[0]; + io_base = pdev->resource[0].start; irq = pdev->irq; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.3.12/linux/drivers/scsi/qlogicisp.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/qlogicisp.c Thu Aug 5 15:11:52 1999 @@ -1188,7 +1188,7 @@ printk("qlogicisp : error reading PCI configuration\n"); return 1; } - io_base = pdev->base_address[0]; + io_base = pdev->resource[0].start; irq = pdev->irq; if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) { diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.3.12/linux/drivers/scsi/scsi.c Tue Jun 8 10:41:03 1999 +++ linux/drivers/scsi/scsi.c Fri Aug 6 11:43:09 1999 @@ -32,6 +32,8 @@ * Converted cli() code to spinlocks, Ingo Molnar * * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli + * + * out_of_space hacks, D. Gilbert (dpg) 990608 */ #include @@ -180,6 +182,7 @@ int * sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt, struct Scsi_Host *shpnt, char * scsi_result); void scsi_build_commandblocks(Scsi_Device * SDpnt); +static int scsi_unregister_device(struct Scsi_Device_Template * tpnt); /* * These are the interface to the old error handling code. It should go away @@ -403,30 +406,43 @@ up(SCpnt->request.sem); } -__initfunc(void scsi_logging_setup(char *str, int *ints)) +static int __init scsi_logging_setup (char *str) { - if (ints[0] != 1) { - printk("scsi_logging_setup : usage scsi_logging_level=n " + int tmp; + + if (get_option(&str, &tmp)==1) { + scsi_logging_level = (tmp ? ~0 : 0); + return 1; + } else { + printk("scsi_logging_setup : usage scsi_logging_level=n " "(n should be 0 or non-zero)\n"); - } else { - scsi_logging_level = (ints[1])? ~0 : 0; + return 0; } } +__setup("scsi_logging=", scsi_logging_setup); + #ifdef CONFIG_SCSI_MULTI_LUN static int max_scsi_luns = 8; #else static int max_scsi_luns = 1; #endif -__initfunc(void scsi_luns_setup(char *str, int *ints)) +static int __init scsi_luns_setup (char *str) { - if (ints[0] != 1) - printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n"); - else - max_scsi_luns = ints[1]; + int tmp; + + if (get_option(&str, &tmp)==1) { + max_scsi_luns = tmp; + return 1; + } else { + printk("scsi_luns_setup : usage max_scsi_luns=n " + "(n should be between 1 and 8)\n"); + return 0; + } } +__setup("max_scsi_luns=", scsi_luns_setup); /* * Detecting SCSI devices : * We scan all present host adapter's busses, from ID 0 to ID (max_id). @@ -451,16 +467,18 @@ Scsi_Device * SDtail; int sparse_lun; - SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA); - memset (SCpnt, 0, sizeof (Scsi_Cmnd)); - - SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC); - memset (SDpnt, 0, sizeof (Scsi_Device)); - - - /* Make sure we have something that is valid for DMA purposes */ - scsi_result = ( ( !shpnt->unchecked_isa_dma ) - ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); + scsi_result = NULL; + SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), + GFP_ATOMIC | GFP_DMA); + if (SCpnt) { + SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), + GFP_ATOMIC); + if (SDpnt) { + /* Make sure we have something that is valid for DMA purposes */ + scsi_result = ( ( !shpnt->unchecked_isa_dma ) + ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA)); + } + } if (scsi_result == NULL) { @@ -517,15 +535,23 @@ if(SDpnt!=oldSDpnt) { /* it could happen the blockdevice hasn't yet been inited */ - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); - oldSDpnt->scsi_request_fn = NULL; - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->attach) { - (*sdtpnt->attach)(oldSDpnt); - if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);} - resize_dma_pool(); + oldSDpnt->scsi_request_fn = NULL; + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { + if(sdtpnt->attach) { + (*sdtpnt->attach)(oldSDpnt); + if(oldSDpnt->attached) { + scsi_build_commandblocks(oldSDpnt); + if (0 == oldSDpnt->has_cmdblocks) { + printk("scan_scsis: DANGER, no command blocks\n"); + /* What to do now ?? */ + } + } + } + } + resize_dma_pool(); for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) { if(sdtpnt->finish && sdtpnt->nr_dev) @@ -886,8 +912,6 @@ return 0; } - memset (SDpnt, 0, sizeof (Scsi_Device)); - /* * And hook up our command block to the new device we will be testing * for. @@ -1903,9 +1927,9 @@ for (order = 0, a_size = PAGE_SIZE; a_size < size; order++, a_size <<= 1) ; - retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); + retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); } else - retval = kmalloc(size, gfp_mask); + retval = kmalloc(size, gfp_mask); if (retval) memset(retval, 0, size); @@ -1974,9 +1998,10 @@ printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n", SDpnt->queue_depth, j); SDpnt->queue_depth = j; - /* Still problem if 0==j , continue anyway ... */ + SDpnt->has_cmdblocks = (0 != j); } - SDpnt->has_cmdblocks = 1; + else + SDpnt->has_cmdblocks = 1; } #ifndef MODULE /* { */ @@ -1985,7 +2010,7 @@ * initialization, bus scanning, and sd/st initialization routines. * This is only used at boot time. */ -__initfunc(int scsi_dev_init(void)) +int __init scsi_dev_init(void) { Scsi_Device * SDpnt; struct Scsi_Host * shpnt; @@ -2040,7 +2065,13 @@ /* SDpnt->scsi_request_fn = NULL; */ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); + if(SDpnt->attached) { + scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) { + printk("scsi_dev_init: DANGER, no command blocks\n"); + /* What to do now ?? */ + } + } } } @@ -2433,7 +2464,7 @@ */ static void resize_dma_pool(void) { - int i; + int i, k; unsigned long size; struct Scsi_Host * shpnt; struct Scsi_Host * host = NULL; @@ -2442,6 +2473,7 @@ unsigned int new_dma_sectors = 0; unsigned int new_need_isa_buffer = 0; unsigned char ** new_dma_malloc_pages = NULL; + int out_of_space = 0; if( !scsi_hostlist ) { @@ -2533,27 +2565,67 @@ * race conditions that I would rather not even think * about right now. */ - if( new_dma_sectors < dma_sectors ) +#if 0 /* Why do this? No gain and risks out_of_space */ + if( new_dma_sectors < dma_sectors ) new_dma_sectors = dma_sectors; +#endif + if( new_dma_sectors <= dma_sectors ) + return; /* best to quit while we are in front */ - if (new_dma_sectors) - { - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_freelist, 0, size); - - size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages); - new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC); - memset(new_dma_malloc_pages, 0, size); - } + for (k = 0; k < 20; ++k) { /* just in case */ + out_of_space = 0; + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(FreeSectorBitmap); + new_dma_malloc_freelist = (FreeSectorBitmap *) + scsi_init_malloc(size, GFP_ATOMIC); + if (new_dma_malloc_freelist) { + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(*new_dma_malloc_pages); + new_dma_malloc_pages = (unsigned char **) + scsi_init_malloc(size, GFP_ATOMIC); + if (! new_dma_malloc_pages) { + size = (new_dma_sectors / SECTORS_PER_PAGE) * + sizeof(FreeSectorBitmap); + scsi_init_free((char *)new_dma_malloc_freelist, size); + out_of_space = 1; + } + } + else + out_of_space = 1; + + if ((! out_of_space) && (new_dma_sectors > dma_sectors)) { + for(i = dma_sectors / SECTORS_PER_PAGE; + i < new_dma_sectors / SECTORS_PER_PAGE; i++) { + new_dma_malloc_pages[i] = (unsigned char *) + scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + if (! new_dma_malloc_pages[i]) + break; + } + if (i != new_dma_sectors / SECTORS_PER_PAGE) { /* clean up */ + int k = i; - /* - * If we need more buffers, expand the list. - */ - if( new_dma_sectors > dma_sectors ) { - for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++) - new_dma_malloc_pages[i] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + out_of_space = 1; + for (i = 0; i < k; ++i) + scsi_init_free(new_dma_malloc_pages[i], PAGE_SIZE); + } + } + if (out_of_space) { /* try scaling down new_dma_sectors request */ + printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, " + "wanted=%u, scaling\n", dma_sectors, new_dma_sectors); + if (new_dma_sectors < (8 * SECTORS_PER_PAGE)) + break; /* pretty well hopeless ... */ + new_dma_sectors = (new_dma_sectors * 3) / 4; + new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; + if (new_dma_sectors <= dma_sectors) + break; /* stick with what we have got */ + } + else + break; /* found space ... */ + } /* end of for loop */ + if (out_of_space) { + scsi_need_isa_buffer = new_need_isa_buffer; /* some useful info */ + printk(" WARNING, not enough memory, pool not expanded\n"); + return; } /* When we dick with the actual DMA list, we need to @@ -2600,6 +2672,7 @@ struct Scsi_Device_Template * sdtpnt; const char * name; unsigned long flags; + int out_of_space = 0; if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or * no detect routine available @@ -2699,11 +2772,11 @@ { if(shpnt->hostt == tpnt) { - scan_scsis(shpnt,0,0,0,0); - if (shpnt->select_queue_depths != NULL) - { - (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); - } + scan_scsis(shpnt,0,0,0,0); + if (shpnt->select_queue_depths != NULL) + { + (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); + } } } @@ -2722,14 +2795,19 @@ { for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt); - if(SDpnt->attached) scsi_build_commandblocks(SDpnt); + if(SDpnt->attached) { + scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) + out_of_space = 1; + } } } /* * Now that we have all of the devices, resize the DMA pool, * as required. */ - resize_dma_pool(); + if (! out_of_space) + resize_dma_pool(); /* This does any final handling that is required. */ @@ -2750,7 +2828,13 @@ #endif MOD_INC_USE_COUNT; - return 0; + + if (out_of_space) { + scsi_unregister_host(tpnt); /* easiest way to clean up?? */ + return 1; + } + else + return 0; } /* @@ -3011,6 +3095,7 @@ { Scsi_Device * SDpnt; struct Scsi_Host * shpnt; + int out_of_space = 0; if (tpnt->next) return 1; @@ -3052,6 +3137,8 @@ { SDpnt->online = TRUE; scsi_build_commandblocks(SDpnt); + if (0 == SDpnt->has_cmdblocks) + out_of_space = 1; } } } @@ -3060,9 +3147,16 @@ * This does any final handling that is required. */ if(tpnt->finish && tpnt->nr_dev) (*tpnt->finish)(); - resize_dma_pool(); + if (! out_of_space) + resize_dma_pool(); MOD_INC_USE_COUNT; - return 0; + + if (out_of_space) { + scsi_unregister_device(tpnt); /* easiest way to clean up?? */ + return 1; + } + else + return 0; } static int scsi_unregister_device(struct Scsi_Device_Template * tpnt) @@ -3298,6 +3392,7 @@ int init_module(void) { unsigned long size; + int has_space = 0; /* * This makes /proc/scsi visible. @@ -3313,7 +3408,6 @@ proc_scsi_register(0, &proc_scsi_scsi); #endif - dma_sectors = PAGE_SIZE / SECTOR_SIZE; scsi_dma_free_sectors= dma_sectors; /* @@ -3322,15 +3416,31 @@ */ /* One bit per sector to indicate free/busy */ - size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap); - dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC); - memset(dma_malloc_freelist, 0, size); - - /* One pointer per page for the page list */ - dma_malloc_pages = (unsigned char **) - scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC); - dma_malloc_pages[0] = (unsigned char *) - scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap); + dma_malloc_freelist = (FreeSectorBitmap *) + scsi_init_malloc(size, GFP_ATOMIC); + if (dma_malloc_freelist) { + /* One pointer per page for the page list */ + dma_malloc_pages = (unsigned char **)scsi_init_malloc( + (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages), + GFP_ATOMIC); + if (dma_malloc_pages) { + dma_malloc_pages[0] = (unsigned char *) + scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); + if (dma_malloc_pages[0]) + has_space = 1; + } + } + if (! has_space) { + if (dma_malloc_freelist) { + scsi_init_free((char *)dma_malloc_freelist, size); + if (dma_malloc_pages) + scsi_init_free((char *)dma_malloc_pages, + (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages)); + } + printk("scsi::init_module: failed, out of memory\n"); + return 1; + } /* * This is where the processing takes place for most everything diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.3.12/linux/drivers/scsi/sr.c Tue May 11 14:37:40 1999 +++ linux/drivers/scsi/sr.c Mon Aug 9 12:34:22 1999 @@ -34,6 +34,7 @@ #include #include #include +#include #define MAJOR_NR SCSI_CDROM_MAJOR #include @@ -70,6 +71,7 @@ void requeue_sr_request (Scsi_Cmnd * SCpnt); static int sr_media_change(struct cdrom_device_info*, int); +static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *); static void sr_release(struct cdrom_device_info *cdi) { @@ -99,8 +101,10 @@ sr_dev_ioctl, /* device-specific ioctl */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, - 0 + CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | + CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET, + 0, + sr_packet }; /* @@ -988,25 +992,85 @@ scsi_CDs[i].cdi.speed = 1; /* disable speed select, drive probably can't do this either */ scsi_CDs[i].cdi.mask |= CDC_SELECT_SPEED; - } else { - n = buffer[3]+4; - scsi_CDs[i].cdi.speed = ((buffer[n+8] << 8) + buffer[n+9])/176; - scsi_CDs[i].readcd_known = 1; - scsi_CDs[i].readcd_cdda = buffer[n+5] & 0x01; - /* print some capability bits */ - printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s\n",i, - ((buffer[n+14] << 8) + buffer[n+15])/176, - scsi_CDs[i].cdi.speed, - buffer[n+3]&0x01 ? "writer " : "", /* CD Writer */ - buffer[n+2]&0x02 ? "cd/rw " : "", /* can read rewriteable */ - buffer[n+4]&0x20 ? "xa/form2 " : "", /* can read xa/from2 */ - buffer[n+5]&0x01 ? "cdda " : "", /* can read audio data */ - loadmech[buffer[n+6]>>5]); - if ((buffer[n+6] >> 5) == 0) - /* caddy drives can't close tray... */ - scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; + scsi_free(buffer, 512); + return; } + + n = buffer[3]+4; + scsi_CDs[i].cdi.speed = ((buffer[n+8] << 8) + buffer[n+9])/176; + scsi_CDs[i].readcd_known = 1; + scsi_CDs[i].readcd_cdda = buffer[n+5] & 0x01; + /* print some capability bits */ + printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s\n",i, + ((buffer[n+14] << 8) + buffer[n+15])/176, + scsi_CDs[i].cdi.speed, + buffer[n+3]&0x01 ? "writer " : "", /* CD Writer */ + buffer[n+2]&0x02 ? "cd/rw " : "", /* can read rewriteable */ + buffer[n+4]&0x20 ? "xa/form2 " : "", /* can read xa/from2 */ + buffer[n+5]&0x01 ? "cdda " : "", /* can read audio data */ + loadmech[buffer[n+6]>>5]); + if ((buffer[n+6] >> 5) == 0) + /* caddy drives can't close tray... */ + scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; + if ((buffer[n+2] & 0x8) == 0) + /* not a DVD drive */ + scsi_CDs[i].cdi.mask |= CDC_DVD; + if ((buffer[n+3] & 0x20) == 0) + /* can't write DVD-RAM media */ + scsi_CDs[i].cdi.mask |= CDC_DVD_RAM; + if ((buffer[n+3] & 0x10) == 0) + /* can't write DVD-R media */ + scsi_CDs[i].cdi.mask |= CDC_DVD_R; + if ((buffer[n+3] & 0x2) == 0) + /* can't write CD-RW media */ + scsi_CDs[i].cdi.mask |= CDC_CD_RW; + if ((buffer[n+3] & 0x1) == 0) + /* can't write CD-R media */ + scsi_CDs[i].cdi.mask |= CDC_CD_R; + scsi_free(buffer, 512); +} + +/* + * sr_packet() is the entry point for the generic commands generated + * by the Uniform CD-ROM layer. +*/ +static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc) +{ + Scsi_Cmnd *SCpnt; + Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device; + DECLARE_MUTEX_LOCKED(sem); + unsigned long flags; + int stat; + + /* get the device */ + SCpnt = scsi_allocate_device(NULL, device, 1); + if (SCpnt == NULL) + return -ENODEV; /* this just doesn't seem right /axboe */ + + /* set the LUN */ + cgc->cmd[1] |= device->lun << 5; + + /* do the locking and issue the command */ + SCpnt->request.rq_dev = cdi->dev; + SCpnt->request.rq_status = RQ_SCSI_BUSY; + /* scsi_do_cmd sets the command length */ + SCpnt->cmd_len = 0; + SCpnt->request.sem = &sem; + spin_lock_irqsave(&io_request_lock, flags); + scsi_do_cmd (SCpnt, (void *)cgc->cmd, (void *)cgc->buffer, cgc->buflen, + sr_init_done, SR_TIMEOUT, MAX_RETRIES); + spin_unlock_irqrestore(&io_request_lock, flags); + down(&sem); + + stat = SCpnt->result; + + /* release */ + SCpnt->request.rq_dev = MKDEV(0,0); + scsi_release_command(SCpnt); + SCpnt = NULL; + + return stat; } static int sr_registered = 0; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.3.12/linux/drivers/scsi/sr_ioctl.c Sat May 15 23:43:04 1999 +++ linux/drivers/scsi/sr_ioctl.c Thu Aug 5 16:24:15 1999 @@ -240,9 +240,8 @@ int sr_get_mcn(struct cdrom_device_info *cdi,struct cdrom_mcn *mcn) { u_char sr_cmd[10]; - char * buffer; + char buffer[32]; int result; - unsigned long flags; sr_cmd[0] = SCMD_READ_SUBCHANNEL; sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5); @@ -254,20 +253,11 @@ sr_cmd[8] = 24; sr_cmd[9] = 0; - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char*) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0); memcpy (mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - return result; } @@ -395,8 +385,7 @@ case CDROMREADTOCHDR: { struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg; - char * buffer; - unsigned long flags; + char buffer[32]; sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5); @@ -406,27 +395,18 @@ sr_cmd[8] = 12; /* LSB of length */ sr_cmd[9] = 0; - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1); tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); break; } case CDROMREADTOCENTRY: { struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg; - unsigned char * buffer; - unsigned long flags; + unsigned char buffer[32]; sr_cmd[0] = SCMD_READ_TOC; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | @@ -437,11 +417,6 @@ sr_cmd[8] = 12; /* LSB of length */ sr_cmd[9] = 0; - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - result = sr_do_ioctl (target, sr_cmd, buffer, 12, 0); tocentry->cdte_ctrl = buffer[5] & 0xf; @@ -455,151 +430,13 @@ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8) + buffer[10]) << 8) + buffer[11]; - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - - case CDROMSTOP: - sr_cmd[0] = START_STOP; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; - sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; - sr_cmd[4] = 0; - - result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); - break; - - case CDROMSTART: - sr_cmd[0] = START_STOP; - sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1; - sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; - sr_cmd[4] = 1; - - result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0); - break; - - case CDROMVOLCTRL: - { - char * buffer, * mask; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - unsigned long flags; - - /* First we get the current params so we can just twiddle the volume */ - - sr_cmd[0] = MODE_SENSE; - sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; - sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ - sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - - if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0))) { - printk ("Hosed while obtaining audio mode page\n"); - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - - sr_cmd[0] = MODE_SENSE; - sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; - sr_cmd[2] = 0x4e; /* Want the mask for mode page 0xe */ - sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - spin_lock_irqsave(&io_request_lock, flags); - mask = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!mask) { - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - result = -ENOMEM; - break; - }; - - if ((result = sr_do_ioctl (target, sr_cmd, mask, 28, 0))) { - printk ("Hosed while obtaining mask for audio mode page\n"); - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - scsi_free(mask, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - - /* Now mask and substitute our own volume and reuse the rest */ - buffer[0] = 0; /* Clear reserved field */ - - buffer[21] = volctrl->channel0 & mask[21]; - buffer[23] = volctrl->channel1 & mask[23]; - buffer[25] = volctrl->channel2 & mask[25]; - buffer[27] = volctrl->channel3 & mask[27]; - - sr_cmd[0] = MODE_SELECT; - sr_cmd[1] = ((scsi_CDs[target].device -> lun) << 5) | 0x10; /* Params are SCSI-2 */ - sr_cmd[2] = sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0); - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - scsi_free(mask, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - - case CDROMVOLREAD: - { - char * buffer; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - unsigned long flags; - - /* Get the current params */ - - sr_cmd[0] = MODE_SENSE; - sr_cmd[1] = (scsi_CDs[target].device -> lun) << 5; - sr_cmd[2] = 0xe; /* Want mode page 0xe, CDROM audio params */ - sr_cmd[3] = 0; - sr_cmd[4] = 28; - sr_cmd[5] = 0; - - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - - if ((result = sr_do_ioctl (target, sr_cmd, buffer, 28, 0))) { - printk ("(CDROMVOLREAD) Hosed while obtaining audio mode page\n"); - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); - break; - } - - volctrl->channel0 = buffer[21]; - volctrl->channel1 = buffer[23]; - volctrl->channel2 = buffer[25]; - volctrl->channel3 = buffer[27]; - - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); break; } case CDROMSUBCHNL: { struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg; - char * buffer; - unsigned long flags; + char buffer[32]; sr_cmd[0] = SCMD_READ_SUBCHANNEL; sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02; /* MSF format */ @@ -611,11 +448,6 @@ sr_cmd[8] = 16; sr_cmd[9] = 0; - spin_lock_irqsave(&io_request_lock, flags); - buffer = (unsigned char *) scsi_malloc(512); - spin_unlock_irqrestore(&io_request_lock, flags); - if(!buffer) return -ENOMEM; - result = sr_do_ioctl(target, sr_cmd, buffer, 16, 0); subchnl->cdsc_audiostatus = buffer[1]; @@ -631,9 +463,6 @@ subchnl->cdsc_absaddr.msf.second = buffer[10]; subchnl->cdsc_absaddr.msf.frame = buffer[11]; - spin_lock_irqsave(&io_request_lock, flags); - scsi_free(buffer, 512); - spin_unlock_irqrestore(&io_request_lock, flags); break; } default: diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.3.12/linux/drivers/scsi/st.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/scsi/st.c Mon Aug 9 10:25:01 1999 @@ -11,7 +11,7 @@ Copyright 1992 - 1999 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Tue May 18 08:32:34 1999 by makisara@home + Last modified: Sat Aug 7 13:54:31 1999 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 */ @@ -55,17 +55,29 @@ #include "constants.h" +static int buffer_kbs = 0; +static int write_threshold_kbs = 0; +static int max_buffers = (-1); +static int max_sg_segs = 0; #ifdef MODULE +MODULE_AUTHOR("Kai Makisara"); +MODULE_DESCRIPTION("SCSI Tape Driver"); MODULE_PARM(buffer_kbs, "i"); MODULE_PARM(write_threshold_kbs, "i"); MODULE_PARM(max_buffers, "i"); MODULE_PARM(max_sg_segs, "i"); -static int buffer_kbs = 0; -static int write_threshold_kbs = 0; -static int max_buffers = 0; -static int max_sg_segs = 0; +#else +static struct st_dev_parm { + char *name; + int *val; +} parms[] __initdata = { + {"buffer_kbs", &buffer_kbs}, + {"write_threshold_kbs", &write_threshold_kbs}, + {"max_buffers", &max_buffers}, + {"max_sg_segs", &max_sg_segs}}; #endif + /* The default definitions have been moved to st_options.h */ #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE) @@ -183,7 +195,7 @@ else printk(KERN_WARNING "st%d: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", - dev, result, suggestion(result), driver_byte(result), + dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK, host_byte(result)); } @@ -3318,23 +3330,66 @@ } +/* Validate the options from command line or module parameters */ +static void validate_options(void) +{ + if (buffer_kbs > 0) + st_buffer_size = buffer_kbs * ST_KILOBYTE; + if (write_threshold_kbs > 0) + st_write_threshold = write_threshold_kbs * ST_KILOBYTE; + else if (buffer_kbs > 0) + st_write_threshold = st_buffer_size - 2048; + if (st_write_threshold > st_buffer_size) { + st_write_threshold = st_buffer_size; + printk(KERN_WARNING "st: write_threshold limited to %d bytes.\n", + st_write_threshold); + } + if (max_buffers >= 0) + st_max_buffers = max_buffers; + if (max_sg_segs >= ST_FIRST_SG) + st_max_sg_segs = max_sg_segs; +} + #ifndef MODULE -/* Set the boot options. Syntax: st=xxx,yyy - where xxx is buffer size in 1024 byte blocks and yyy is write threshold - in 1024 byte blocks. */ - __initfunc( void -st_setup(char *str, int *ints)) -{ - if (ints[0] > 0 && ints[1] > 0) - st_buffer_size = ints[1] * ST_KILOBYTE; - if (ints[0] > 1 && ints[2] > 0) { - st_write_threshold = ints[2] * ST_KILOBYTE; - if (st_write_threshold > st_buffer_size) - st_write_threshold = st_buffer_size; - } - if (ints[0] > 2 && ints[3] > 0) - st_max_buffers = ints[3]; +/* Set the boot options. Syntax is defined in README.st. +*/ +static int __init st_setup(char *str) +{ + int i, len, ints[5]; + char *stp; + + stp = get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) { + for (i=0; i < ints[0] && i < ARRAY_SIZE(parms) ; i++) + *parms[i].val = ints[i + 1]; + } + else { + while (stp != NULL) { + for (i=0; i < ARRAY_SIZE(parms); i++) { + len = strlen(parms[i].name); + if (!strncmp(stp, parms[i].name, len) && + (*(stp + len) == ':' || *(stp + len) == '=')) { + *parms[i].val = simple_strtoul(stp + len + 1, NULL, 0); + break; + } + } + if (i >= sizeof(parms) / sizeof(struct st_dev_parm)) + printk(KERN_WARNING "st: illegal parameter in '%s'\n", + stp); + stp = strchr(stp, ','); + if (stp) + stp++; + } + } + + validate_options(); + + return 1; } + +__setup("st=", st_setup); + #endif @@ -3449,12 +3504,13 @@ { int i; Scsi_Tape * STp; -#if !ST_RUNTIME_BUFFERS int target_nbr; -#endif if (st_template.dev_noticed == 0) return 0; + printk(KERN_INFO "st: bufsize %d, wrt %d, max init. buffers %d, s/g segs %d.\n", + st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs); + if(!st_registered) { if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) { printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR); @@ -3505,9 +3561,6 @@ return 1; } -#if ST_RUNTIME_BUFFERS - st_nbr_buffers = 0; -#else target_nbr = st_template.dev_noticed; if (target_nbr < ST_EXTRA_DEVS) target_nbr = ST_EXTRA_DEVS; @@ -3517,24 +3570,14 @@ for (i=st_nbr_buffers=0; i < target_nbr; i++) { if (!new_tape_buffer(TRUE, TRUE)) { if (i == 0) { -#if 0 - printk(KERN_ERR "Can't continue without at least one tape buffer.\n"); - unregister_chrdev(SCSI_TAPE_MAJOR, "st"); - scsi_init_free((char *) st_buffers, - st_template.dev_max * sizeof(ST_buffer *)); - scsi_init_free((char *) scsi_tapes, - st_template.dev_max * sizeof(Scsi_Tape)); - return 1; -#else printk(KERN_INFO "No tape buffers allocated at initialization.\n"); break; -#endif } printk(KERN_INFO "Number of tape buffers adjusted.\n"); break; } } -#endif + return 0; } @@ -3557,21 +3600,10 @@ #ifdef MODULE -int init_module(void) { +int __init init_module(void) { int result; - if (buffer_kbs > 0) - st_buffer_size = buffer_kbs * ST_KILOBYTE; - if (write_threshold_kbs > 0) - st_write_threshold = write_threshold_kbs * ST_KILOBYTE; - if (st_write_threshold > st_buffer_size) - st_write_threshold = st_buffer_size; - if (max_buffers > 0) - st_max_buffers = max_buffers; - if (max_sg_segs >= ST_FIRST_SG) - st_max_sg_segs = max_sg_segs; - printk(KERN_INFO "st: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n", - st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs); + validate_options(); st_template.module = &__this_module; result = scsi_register_module(MODULE_SCSI_DEV, &st_template); diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/st_options.h linux/drivers/scsi/st_options.h --- v2.3.12/linux/drivers/scsi/st_options.h Sun Sep 6 09:48:30 1998 +++ linux/drivers/scsi/st_options.h Mon Aug 9 10:23:42 1999 @@ -1,20 +1,14 @@ /* The compile-time configurable defaults for the Linux SCSI tape driver. - Copyright 1995 Kai Makisara. + Copyright 1995-1999 Kai Makisara. - Last modified: Wed Sep 2 21:24:07 1998 by root@home + Last modified: Sat Aug 7 13:42:21 1999 by makisara@kai.makisara.local */ #ifndef _ST_OPTIONS_H #define _ST_OPTIONS_H -/* The driver allocates the tape buffers when needed if ST_RUNTIME_BUFFERS - is nonzero. Otherwise a number of buffers are allocated at initialization. - The drawback of runtime allocation is that allocation may fail. In any - case the driver tries to allocate a new tape buffer when none is free. */ -#define ST_RUNTIME_BUFFERS 0 - /* The minimum limit for the number of SCSI tape devices is determined by ST_MAX_TAPES. If the number of tape devices and the "slack" defined by ST_EXTRA_DEVS exceeds ST_MAX_TAPES, the large number is used. */ @@ -49,9 +43,10 @@ below. */ #define ST_WRITE_THRESHOLD_BLOCKS 30 -/* The maximum number of tape buffers the driver allocates. The number - is also constrained by the number of drives detected. Determines the - maximum number of concurrently active tape drives. */ +/* The maximum number of tape buffers the driver tries to allocate at + driver initialisation. The number is also constrained by the number + of drives detected. If more buffers are needed, they are allocated + at run time and freed after use. */ #define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS) /* Maximum number of scatter/gather segments */ diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.3.12/linux/drivers/scsi/sym53c8xx.c Mon Apr 12 09:51:04 1999 +++ linux/drivers/scsi/sym53c8xx.c Wed Aug 4 10:54:13 1999 @@ -10115,14 +10115,14 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) ) { - *base = pdev->base_address[index++]; - if ((*base & 0x7) == 0x4) { -#if BITS_PER_LONG > 32 - *base |= (((u_long)pdev->base_address[index]) << 32); -#endif + /* FIXME! This is just unbelieably horrible backwards compatibility code */ + struct resource *res = pdev->resource + index; + + *base = res->start | (res->flags & 0xf); + if ((res->flags & 0x7) == 0x4) { ++index; } - return index; + return index+1; } #endif diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c --- v2.3.12/linux/drivers/scsi/t128.c Sat Sep 5 17:01:45 1998 +++ linux/drivers/scsi/t128.c Mon Aug 9 10:25:01 1999 @@ -168,7 +168,7 @@ * */ -__initfunc(void t128_setup(char *str, int *ints)) { +void __init t128_setup(char *str, int *ints){ static int commandline_current = 0; int i; if (ints[0] != 2) @@ -199,7 +199,7 @@ * */ -__initfunc(int t128_detect(Scsi_Host_Template * tpnt)) { +int __init t128_detect(Scsi_Host_Template * tpnt){ static int current_override = 0, current_base = 0; struct Scsi_Host *instance; unsigned char *base; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c --- v2.3.12/linux/drivers/scsi/tmscsim.c Fri Dec 25 16:41:39 1998 +++ linux/drivers/scsi/tmscsim.c Mon Aug 9 10:25:01 1999 @@ -319,7 +319,7 @@ # define PCI_PRESENT pci_present () # define PCI_SET_MASTER pci_set_master (pdev) # define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev)) -# define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq +# define PCI_GET_IO_AND_IRQ io_port = pdev->resource[0].start; irq = pdev->irq #else # include # define PDEV pbus, pdevfn diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.3.12/linux/drivers/scsi/u14-34f.c Fri Oct 9 11:56:59 1998 +++ linux/drivers/scsi/u14-34f.c Mon Aug 9 10:25:01 1999 @@ -467,7 +467,6 @@ #define ASOK 0x00 #define ASST 0x91 -#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) #define YESNO(a) ((a) ? 'y' : 'n') #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) @@ -701,8 +700,8 @@ return FALSE; } -__initfunc (static inline int port_detect \ - (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { +static inline int __init port_detect \ + (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { unsigned char irq, dma_channel, subversion, i; unsigned char in_byte; char *bus_type, dma_name[16]; @@ -915,7 +914,8 @@ return TRUE; } -__initfunc (void u14_34f_setup(char *str, int *ints)) { +void __init u14_34f_setup(char *str, int *ints) +{ int i, argc = ints[0]; char *cur = str, *pc; @@ -949,7 +949,8 @@ return; } -__initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) { +int __init u14_34f_detect(Scsi_Host_Template *tpnt) +{ unsigned int j = 0, k; IRQ_FLAGS diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c --- v2.3.12/linux/drivers/scsi/ultrastor.c Sat Apr 11 11:13:25 1998 +++ linux/drivers/scsi/ultrastor.c Fri Aug 6 11:43:09 1999 @@ -162,8 +162,6 @@ #define VERSION "1.12" -#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) - #define PACKED __attribute__((packed)) #define ALIGNED(x) __attribute__((aligned(x))) diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/wd33c93.c linux/drivers/scsi/wd33c93.c --- v2.3.12/linux/drivers/scsi/wd33c93.c Mon Apr 12 16:18:26 1999 +++ linux/drivers/scsi/wd33c93.c Mon Aug 9 12:33:30 1999 @@ -75,6 +75,7 @@ #include #include #include +#include #include #if LINUX_VERSION_CODE >= 0x010300 @@ -176,6 +177,7 @@ static inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num) { regp->SASR = reg_num; + mb(); return(regp->SCMD); } @@ -186,14 +188,18 @@ static inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value) { regp->SASR = reg_num; + mb(); regp->SCMD = value; + mb(); } static inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd) { regp->SASR = WD_COMMAND; + mb(); regp->SCMD = cmd; + mb(); } @@ -216,9 +222,11 @@ static void write_wd33c93_count(wd33c93_regs *regp,unsigned long value) { regp->SASR = WD_TRANSFER_COUNT_MSB; + mb(); regp->SCMD = value >> 16; regp->SCMD = value >> 8; regp->SCMD = value; + mb(); } @@ -227,9 +235,11 @@ unsigned long value; regp->SASR = WD_TRANSFER_COUNT_MSB; + mb(); value = regp->SCMD << 16; value |= regp->SCMD << 8; value |= regp->SCMD; + mb(); return value; } @@ -1587,10 +1597,10 @@ static char setup_used[MAX_SETUP_ARGS]; static int done_setup = 0; -void wd33c93_setup (char *str, int *ints) +int wd33c93_setup (char *str) { -int i,x; -char *p1,*p2; + int i; + char *p1,*p2; /* The kernel does some processing of the command-line before calling * this function: If it begins with any decimal or hex number arguments, @@ -1603,12 +1613,17 @@ p1 = setup_buffer; *p1 = '\0'; +#if 0 +/* + * Old style command line arguments are now dead + */ if (ints[0]) { for (i=0; ihostdata; diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/wd33c93.h linux/drivers/scsi/wd33c93.h --- v2.3.12/linux/drivers/scsi/wd33c93.h Wed Jul 16 19:22:51 1997 +++ linux/drivers/scsi/wd33c93.h Mon Aug 9 12:33:30 1999 @@ -223,13 +223,13 @@ uchar clock_freq; uchar chip; /* what kind of wd33c93? */ uchar microcode; /* microcode rev */ + uchar dma_buffer_pool; /* FEF: buffer from chip_ram? */ int dma_dir; /* data transfer dir. */ dma_setup_t dma_setup; dma_stop_t dma_stop; unsigned int dma_xfer_mask; uchar *dma_bounce_buffer; unsigned int dma_bounce_len; - uchar dma_buffer_pool; /* FEF: buffer from chip_ram? */ volatile uchar busy[8]; /* index = target, bit = lun */ volatile Scsi_Cmnd *input_Q; /* commands waiting to be started */ volatile Scsi_Cmnd *selecting; /* trying to select this command */ diff -u --recursive --new-file v2.3.12/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c --- v2.3.12/linux/drivers/scsi/wd7000.c Thu Jan 7 09:24:00 1999 +++ linux/drivers/scsi/wd7000.c Thu Aug 5 14:43:32 1999 @@ -1561,19 +1561,16 @@ break; if (i == pass) { -#if (LINUX_VERSION_CODE < 0x020100) -#else void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, signatures[sig_ptr].len); -#endif - short bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, + short bios_match=0; + + if(biosaddr) + bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); -#if (LINUX_VERSION_CODE < 0x020100) -#else iounmap (biosaddr); -#endif if (! bios_match) goto bios_matched; diff -u --recursive --new-file v2.3.12/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.3.12/linux/drivers/sound/Config.in Wed May 26 09:35:00 1999 +++ linux/drivers/sound/Config.in Mon Aug 9 12:13:39 1999 @@ -11,16 +11,8 @@ dep_tristate 'C-Media PCI (CMI8338/8378)' CONFIG_SOUND_CMPCI $CONFIG_SOUND dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND -if [ "$CONFIG_SOUND_ES1370" = "y" ]; then - bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT -fi dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND -if [ "$CONFIG_SOUND_ES1371" = "y" ]; then - bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT - if [ "$CONFIG_SOUND_ES1371_JOYPORT_BOOT" = "y" ]; then - hex 'Gameport I/O 200,208,210,218' CONFIG_SOUND_ES1371_GAMEPORT 200 - fi -fi +dep_tristate 'ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND dep_tristate 'Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND diff -u --recursive --new-file v2.3.12/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.3.12/linux/drivers/sound/Makefile Wed May 26 09:35:00 1999 +++ linux/drivers/sound/Makefile Mon Aug 9 12:13:39 1999 @@ -75,11 +75,11 @@ obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o obj-$(CONFIG_SOUND_WAVEFRONT) += wavefront.o -#jnx +obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o obj-$(CONFIG_SOUND_CMPCI) += cmpci.o obj-$(CONFIG_SOUND_ES1370) += es1370.o obj-$(CONFIG_SOUND_ES1371) += es1371.o -obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o +obj-$(CONFIG_SOUND_ESSSOLO1) += esssolo1.o # Declare multi-part drivers. diff -u --recursive --new-file v2.3.12/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.3.12/linux/drivers/sound/cmpci.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/cmpci.c Thu Aug 5 15:11:52 1999 @@ -2232,7 +2232,7 @@ init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); s->magic = CM_MAGIC; - s->iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + s->iobase = pcidev->resource[0].start; #ifdef CONFIG_SOUND_CMPCI_FM s->iosynth = 0x388; #endif diff -u --recursive --new-file v2.3.12/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.3.12/linux/drivers/sound/es1370.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/sound/es1370.c Fri Aug 6 11:43:09 1999 @@ -101,6 +101,11 @@ * 15.06.99 0.23 Fix bad allocation bug. * Thanks to Deti Fliegl * 28.06.99 0.24 Add pci_set_master + * 02.08.99 0.25 Added workaround for the "phantom write" bug first + * documented by Dave Sharpless from Anchor Games + * 03.08.99 0.26 adapt to Linus' new __setup/__initcall + * added kernel command line option "es1370=joystick[,lineout[,micbias]]" + * removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge * * some important things missing in Ensoniq documentation: * @@ -123,7 +128,6 @@ /*****************************************************************************/ -#include #include #include #include @@ -175,12 +179,14 @@ #define ES1370_REG_DAC2_SCOUNT 0x28 #define ES1370_REG_ADC_SCOUNT 0x2c -#define ES1370_REG_DAC1_FRAMEADR 0xc30 -#define ES1370_REG_DAC1_FRAMECNT 0xc34 -#define ES1370_REG_DAC2_FRAMEADR 0xc38 -#define ES1370_REG_DAC2_FRAMECNT 0xc3c -#define ES1370_REG_ADC_FRAMEADR 0xd30 -#define ES1370_REG_ADC_FRAMECNT 0xd34 +#define ES1370_REG_DAC1_FRAMEADR 0xc30 +#define ES1370_REG_DAC1_FRAMECNT 0xc34 +#define ES1370_REG_DAC2_FRAMEADR 0xc38 +#define ES1370_REG_DAC2_FRAMECNT 0xc3c +#define ES1370_REG_ADC_FRAMEADR 0xd30 +#define ES1370_REG_ADC_FRAMECNT 0xd34 +#define ES1370_REG_PHANTOM_FRAMEADR 0xd38 +#define ES1370_REG_PHANTOM_FRAMECNT 0xd3c #define ES1370_FMT_U8_MONO 0 #define ES1370_FMT_U8_STEREO 1 @@ -360,6 +366,13 @@ static struct es1370_state *devs = NULL; +/* + * The following buffer is used to point the phantom write channel to, + * so that it cannot wreak havoc. The attribute makes sure it doesn't + * cross a page boundary and ensures dword alignment for the DMA engine + */ +static unsigned char bugbuf[16] __attribute__ ((aligned (16))); + /* --------------------------------------------------------------------- */ extern inline unsigned ld2(unsigned int x) @@ -2282,11 +2295,8 @@ /* maximum number of devices */ #define NR_DEVICE 5 -#ifdef CONFIG_SOUND_ES1370_JOYPORT_BOOT -static int joystick[NR_DEVICE] = { 1, 0, }; -#else + static int joystick[NR_DEVICE] = { 0, }; -#endif static int lineout[NR_DEVICE] = { 0, }; static int micbias[NR_DEVICE] = { 0, }; @@ -2308,11 +2318,10 @@ { SOUND_MIXER_WRITE_OGAIN, 0x4040 } }; -#ifdef MODULE -int __init init_module(void) -#else -int __init init_es1370(void) +#ifndef MODULE +static #endif +int __init init_module(void) { struct es1370_state *s; struct pci_dev *pcidev = NULL; @@ -2321,11 +2330,11 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.24 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.26 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { - if (pcidev->base_address[0] == 0 || - (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pcidev->resource[0].flags == 0 || + (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; if (pcidev->irq == 0) continue; @@ -2342,7 +2351,7 @@ init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); s->magic = ES1370_MAGIC; - s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + s->io = pcidev->resource[0].start; s->irq = pcidev->irq; if (check_region(s->io, ES1370_EXTENT)) { printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1); @@ -2385,6 +2394,10 @@ /* initialize the chips */ outl(s->ctrl, s->io+ES1370_REG_CONTROL); outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL); + /* point phantom write channel to "bugbuf" */ + outl((ES1370_REG_PHANTOM_FRAMEADR >> 8) & 15, s->io+ES1370_REG_MEMPAGE); + outl(virt_to_bus(bugbuf), s->io+(ES1370_REG_PHANTOM_FRAMEADR & 0xff)); + outl(0, s->io+(ES1370_REG_PHANTOM_FRAMECNT & 0xff)); pci_set_master(pcidev); /* enable bus mastering */ wrcodec(s, 0x16, 3); /* no RST, PD */ wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!! */ @@ -2458,5 +2471,28 @@ } printk(KERN_INFO "es1370: unloading\n"); } + +#else /* MODULE */ + +/* format is: es1370=[joystick[,lineout[,micbias]]] */ + +static int __init es1370_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + + if (nr_dev >= NR_DEVICE) + return 0; + + ( (get_option(&str,&joystick[nr_dev]) == 2) + && (get_option(&str,&lineout [nr_dev]) == 2) + && get_option(&str,&micbias [nr_dev]) + ); + + nr_dev++; + return 1; +} + +__setup("es1370=", es1370_setup); +__initcall(init_module); #endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.3.12/linux/drivers/sound/es1371.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/sound/es1371.c Fri Aug 6 11:43:09 1999 @@ -68,12 +68,14 @@ * 15.06.99 0.12 Fix bad allocation bug. * Thanks to Deti Fliegl * 28.06.99 0.13 Add pci_set_master + * 03.08.99 0.14 adapt to Linus' new __setup/__initcall + * added kernel command line option "es1371=joystickaddr" + * removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge * */ /*****************************************************************************/ -#include #include #include #include @@ -2694,13 +2696,7 @@ /* maximum number of devices */ #define NR_DEVICE 5 -#if CONFIG_SOUND_ES1371_JOYPORT_BOOT -static int joystick[NR_DEVICE] = { -CONFIG_SOUND_ES1371_GAMEPORT -, 0, }; -#else static int joystick[NR_DEVICE] = { 0, }; -#endif /* --------------------------------------------------------------------- */ @@ -2723,11 +2719,10 @@ { SOUND_MIXER_WRITE_IGAIN, 0x4040 } }; -#ifdef MODULE -int __init init_module(void) -#else -int __init init_es1371(void) +#ifndef MODULE +static #endif +int __init init_module(void) { struct es1371_state *s; struct pci_dev *pcidev = NULL; @@ -2736,11 +2731,11 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.13 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.14 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) { - if (pcidev->base_address[0] == 0 || - (pcidev->base_address[0] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pcidev->resource[0].flags == 0 || + (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; if (pcidev->irq == 0) continue; @@ -2757,7 +2752,7 @@ init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); s->magic = ES1371_MAGIC; - s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + s->io = pcidev->resource[0].start; s->irq = pcidev->irq; if (check_region(s->io, ES1371_EXTENT)) { printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1); @@ -2917,5 +2912,24 @@ } printk(KERN_INFO "es1371: unloading\n"); } + +#else /* MODULE */ + +/* format is: es1371=[joystick] */ + +static int __init es1371_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + int ints[11]; + + if (nr_dev >= NR_DEVICE) + return 0; + get_option(&str, &joystick[nr_dev]); + nr_dev++; + return 1; +} + +__setup("es1371=", es1371_setup); +__initcall(init_module); #endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.3.12/linux/drivers/sound/esssolo1.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/esssolo1.c Mon Aug 9 12:13:39 1999 @@ -0,0 +1,2239 @@ +/*****************************************************************************/ + +/* + * esssolo1.c -- ESS Technology Solo1 (ES1946) audio driver. + * + * Copyright (C) 1998-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module command line parameters: + * none so far + * + * Supported devices: + * /dev/dsp standard /dev/dsp device, (mostly) OSS compatible + * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible + * /dev/midi simple MIDI UART interface, no ioctl + * + * Revision history + * 10.11.98 0.1 Initial release (without any hardware) + * 22.03.99 0.2 cinfo.blocks should be reset after GETxPTR ioctl. + * reported by Johan Maes + * return EAGAIN instead of EBUSY when O_NONBLOCK + * read/write cannot be executed + * 07.04.99 0.3 implemented the following ioctl's: SOUND_PCM_READ_RATE, + * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; + * Alpha fixes reported by Peter Jones + * 15.06.99 0.4 Fix bad allocation bug. + * Thanks to Deti Fliegl + * 28.06.99 0.5 Add pci_set_master + * + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm.h" + +/* --------------------------------------------------------------------- */ + +#ifndef PCI_VENDOR_ID_ESS +#define PCI_VENDOR_ID_ESS 0x125d +#endif +#ifndef PCI_DEVICE_ID_ESS_SOLO1 +#define PCI_DEVICE_ID_ESS_SOLO1 0x1969 +#endif + +#define SOLO1_MAGIC ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1) + +#define IOBASE_EXTENT 16 +#define SBBASE_EXTENT 16 +#define VCBASE_EXTENT 16 +#define MPUBASE_EXTENT 4 +#define GPBASE_EXTENT 4 + + +/* MIDI buffer sizes */ + +#define MIDIINBUF 256 +#define MIDIOUTBUF 256 + +#define FMODE_MIDI_SHIFT 3 +#define FMODE_MIDI_READ (FMODE_READ << FMODE_MIDI_SHIFT) +#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT) + +#define FMODE_DMFM 0x10 + +/* --------------------------------------------------------------------- */ + +#define DEBUGREC + +/* --------------------------------------------------------------------- */ + +struct solo1_state { + /* magic */ + unsigned int magic; + + /* we keep sb cards in a linked list */ + struct solo1_state *next; + + /* soundcore stuff */ + int dev_audio; + int dev_mixer; + int dev_midi; + int dev_dmfm; + + /* hardware resources */ + unsigned long iobase, sbbase, vcbase, mpubase, gpbase; /* long for SPARC */ + unsigned int irq; + + /* mixer registers; there is no HW readback */ + struct { + unsigned short vol[10]; + unsigned int recsrc; + unsigned int modcnt; + unsigned short micpreamp; + } mix; + + /* wave stuff */ + unsigned fmt; + unsigned channels; + unsigned rate; + unsigned char clkdiv; + unsigned ena; + + spinlock_t lock; + struct semaphore open_sem; + mode_t open_mode; + wait_queue_head_t open_wait; + + struct dmabuf { + void *rawbuf; + unsigned buforder; + unsigned numfrag; + unsigned fragshift; + unsigned hwptr, swptr; + unsigned total_bytes; + int count; + unsigned error; /* over/underrun */ + wait_queue_head_t wait; + /* redundant, but makes calculations easier */ + unsigned fragsize; + unsigned dmasize; + unsigned fragsamples; + /* OSS stuff */ + unsigned mapped:1; + unsigned ready:1; + unsigned endcleared:1; + unsigned ossfragshift; + int ossmaxfrags; + unsigned subdivision; + } dma_dac, dma_adc; + + /* midi stuff */ + struct { + unsigned ird, iwr, icnt; + unsigned ord, owr, ocnt; + wait_queue_head_t iwait; + wait_queue_head_t owait; + struct timer_list timer; + unsigned char ibuf[MIDIINBUF]; + unsigned char obuf[MIDIOUTBUF]; + } midi; +}; + +/* --------------------------------------------------------------------- */ + +struct solo1_state *devs = NULL; + +/* --------------------------------------------------------------------- */ + +extern inline void write_seq(struct solo1_state *s, unsigned char data) +{ + int i; + unsigned long flags; + + /* the __cli stunt is to send the data within the command window */ + for (i = 0; i < 0xffff; i++) { + __save_flags(flags); + __cli(); + if (!(inb(s->sbbase+0xc) & 0x80)) { + outb(data, s->sbbase+0xc); + __restore_flags(flags); + return; + } + __restore_flags(flags); + } +} + +extern inline int read_seq(struct solo1_state *s, unsigned char *data) +{ + int i; + + if (!data) + return 0; + for (i = 0; i < 0xffff; i++) + if (inb(s->sbbase+0xe) & 0x80) { + *data = inb(s->sbbase+0xa); + return 1; + } + return 0; +} + +static int inline reset_ctrl(struct solo1_state *s) +{ + int i; + + outb(3, s->sbbase+6); /* clear sequencer and FIFO */ + udelay(10); + outb(0, s->sbbase+6); + for (i = 0; i < 0xffff; i++) + if (inb(s->sbbase+0xe) & 0x80) + if (inb(s->sbbase+0xa) == 0xaa) { + write_seq(s, 0xc6); /* enter enhanced mode */ + return 1; + } + return 0; +} + +static void write_ctrl(struct solo1_state *s, unsigned char reg, unsigned char data) +{ + write_seq(s, reg); + write_seq(s, data); +} + +static unsigned char read_ctrl(struct solo1_state *s, unsigned char reg) +{ + unsigned char r; + + write_seq(s, 0xc0); + write_seq(s, reg); + read_seq(s, &r); + return r; +} + +static void write_mixer(struct solo1_state *s, unsigned char reg, unsigned char data) +{ + outb(reg, s->sbbase+4); + outb(data, s->sbbase+5); +} + +static unsigned char read_mixer(struct solo1_state *s, unsigned char reg) +{ + outb(reg, s->sbbase+4); + return inb(s->sbbase+5); +} + +/* --------------------------------------------------------------------- */ + +extern inline unsigned ld2(unsigned int x) +{ + unsigned r = 0; + + if (x >= 0x10000) { + x >>= 16; + r += 16; + } + if (x >= 0x100) { + x >>= 8; + r += 8; + } + if (x >= 0x10) { + x >>= 4; + r += 4; + } + if (x >= 4) { + x >>= 2; + r += 2; + } + if (x >= 2) + r++; + return r; +} + +/* --------------------------------------------------------------------- */ + +extern inline void stop_dac(struct solo1_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + s->ena &= ~FMODE_WRITE; + write_mixer(s, 0x78, 0x10); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_dac(struct solo1_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) { + s->ena |= FMODE_WRITE; + write_mixer(s, 0x78, 0x13); + } + spin_unlock_irqrestore(&s->lock, flags); +} + +extern inline void stop_adc(struct solo1_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + s->ena &= ~FMODE_READ; + write_ctrl(s, 0xb8, 0xe); + spin_unlock_irqrestore(&s->lock, flags); +} + +static void start_adc(struct solo1_state *s) +{ + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + if (!(s->ena & FMODE_READ) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) + && s->dma_adc.ready) { + s->ena |= FMODE_READ; + write_ctrl(s, 0xb8, 0xf); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMAbuffer: 0x%08lx\n", (long)s->dma_adc.rawbuf); + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(0, s->vcbase+0xd); /* master reset */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. clr)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(1, s->vcbase+0xf); /* mask */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. mask)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(0x54/*0x14*/, s->vcbase+0xb); /* DMA_MODE_READ | DMA_MODE_AUTOINIT */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. wrmode)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outl(virt_to_bus(s->dma_adc.rawbuf), s->vcbase); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. wrbase)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outw(s->dma_adc.dmasize-1, s->vcbase+4); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. wrcnt)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(0, s->vcbase+0xf); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x (a. clrmask)\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + } + spin_unlock_irqrestore(&s->lock, flags); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x DMAstat: 0x%02x DMAcnt: 0x%04x DMAmask: 0x%02x SBstat: 0x%02x\n", + read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->vcbase+0xf), inb(s->sbbase+0xc)); + + printk(KERN_DEBUG "solo1: A1: 0x%02x A2: 0x%02x A4: 0x%02x A5: 0x%02x A8: 0x%02x\n" + KERN_DEBUG "solo1: B1: 0x%02x B2: 0x%02x B4: 0x%02x B7: 0x%02x B8: 0x%02x B9: 0x%02x\n", + read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), + read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb4), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), + read_ctrl(s, 0xb9)); +#endif +} + +/* --------------------------------------------------------------------- */ + +#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +extern inline void dealloc_dmabuf(struct dmabuf *db) +{ + unsigned long map, mapend; + + if (db->rawbuf) { + /* undo marking the pages as reserved */ + mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (map = MAP_NR(db->rawbuf); map <= mapend; map++) + clear_bit(PG_reserved, &mem_map[map].flags); + free_pages((unsigned long)db->rawbuf, db->buforder); + } + db->rawbuf = NULL; + db->mapped = db->ready = 0; +} + +static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, int gfp_mask) +{ + int order; + unsigned bytespersec; + unsigned bufs, sample_shift = 0; + unsigned long map, mapend; + + db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; + if (!db->rawbuf) { + db->ready = db->mapped = 0; + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if ((db->rawbuf = (void *)__get_free_pages(gfp_mask, order))) + break; + if (!db->rawbuf) + return -ENOMEM; + db->buforder = order; + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (map = MAP_NR(db->rawbuf); map <= mapend; map++) + set_bit(PG_reserved, &mem_map[map].flags); + } + if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + sample_shift++; + if (s->channels > 1) + sample_shift++; + bytespersec = s->rate << sample_shift; + bufs = PAGE_SIZE << db->buforder; + if (db->ossfragshift) { + if ((1000 << db->ossfragshift) < bytespersec) + db->fragshift = ld2(bytespersec/1000); + else + db->fragshift = db->ossfragshift; + } else { + db->fragshift = ld2(bytespersec/100/(db->subdivision ? db->subdivision : 1)); + if (db->fragshift < 3) + db->fragshift = 3; + } + db->numfrag = bufs >> db->fragshift; + while (db->numfrag < 4 && db->fragshift > 3) { + db->fragshift--; + db->numfrag = bufs >> db->fragshift; + } + db->fragsize = 1 << db->fragshift; + if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) + db->numfrag = db->ossmaxfrags; + db->fragsamples = db->fragsize >> sample_shift; + db->dmasize = db->numfrag << db->fragshift; + return 0; +} + +extern inline int prog_dmabuf_adc(struct solo1_state *s) +{ + unsigned long va; + int c; + + stop_adc(s); + if ((c = prog_dmabuf(s, &s->dma_adc, GFP_KERNEL | GFP_DMA))) + return c; + va = virt_to_bus(s->dma_adc.rawbuf); + if ((va & ~((1<<24)-1))) + panic("solo1: buffer above 16M boundary"); + outb(0, s->vcbase+0xd); /* clear */ + outb(1, s->vcbase+0xf); /* mask */ + //outb(0, s->vcbase+8); /* enable (enable is active low!) */ + outb(0x54, s->vcbase+0xb); /* DMA_MODE_READ | DMA_MODE_AUTOINIT */ + outl(va, s->vcbase); + outw(s->dma_adc.dmasize-1, s->vcbase+4); + c = - s->dma_adc.fragsamples; + write_ctrl(s, 0xa4, c); + write_ctrl(s, 0xa5, c >> 8); + outb(0, s->vcbase+0xf); + s->dma_adc.ready = 1; + return 0; +} + +extern inline int prog_dmabuf_dac(struct solo1_state *s) +{ + unsigned long va; + int c; + + stop_dac(s); + if ((c = prog_dmabuf(s, &s->dma_dac, GFP_KERNEL))) + return c; + memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80, s->dma_dac.dmasize); /* almost correct for U16 */ + va = virt_to_bus(s->dma_dac.rawbuf); + if ((va ^ (va + s->dma_dac.dmasize - 1)) & ~((1<<20)-1)) + panic("solo1: buffer crosses 1M boundary"); + outl(va, s->iobase); + /* warning: s->dma_dac.dmasize & 0xffff must not be zero! i.e. this limits us to a 32k buffer */ + outw(s->dma_dac.dmasize, s->iobase+4); + c = - s->dma_dac.fragsamples; + write_mixer(s, 0x74, c); + write_mixer(s, 0x76, c >> 8); + outb(0xa, s->iobase+6); + s->dma_dac.ready = 1; + return 0; +} + +extern inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c) +{ + if (bptr + len > bsize) { + unsigned x = bsize - bptr; + memset(((char *)buf) + bptr, c, x); + bptr = 0; + len -= x; + } + memset(((char *)buf) + bptr, c, len); +} + +/* call with spinlock held! */ + +static void solo1_update_ptr(struct solo1_state *s) +{ + int diff; + unsigned hwptr; + + /* update ADC pointer */ + if (s->ena & FMODE_READ) { + hwptr = (s->dma_adc.dmasize - 1 - inw(s->vcbase+4)) % s->dma_adc.dmasize; + diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; + s->dma_adc.hwptr = hwptr; + s->dma_adc.total_bytes += diff; + s->dma_adc.count += diff; +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: rd: hwptr %u swptr %u dmasize %u count %u\n", + s->dma_adc.hwptr, s->dma_adc.swptr, s->dma_adc.dmasize, s->dma_adc.count); +#endif + if (s->dma_adc.mapped) { + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + wake_up(&s->dma_adc.wait); + } else { + if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) { + s->ena &= ~FMODE_READ; + write_ctrl(s, 0xb8, 0xe); + s->dma_adc.error++; + } + if (s->dma_adc.count > 0) + wake_up(&s->dma_adc.wait); + } + } + /* update DAC pointer */ + if (s->ena & FMODE_WRITE) { + hwptr = (s->dma_dac.dmasize - inw(s->iobase+4)) % s->dma_dac.dmasize; + diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; + s->dma_dac.hwptr = hwptr; + s->dma_dac.total_bytes += diff; +#if 0 + printk(KERN_DEBUG "solo1: wr: hwptr %u swptr %u dmasize %u count %u\n", + s->dma_dac.hwptr, s->dma_dac.swptr, s->dma_dac.dmasize, s->dma_dac.count); +#endif + if (s->dma_dac.mapped) { + s->dma_dac.count += diff; + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + wake_up(&s->dma_dac.wait); + } else { + s->dma_dac.count -= diff; + if (s->dma_dac.count <= 0) { + s->ena &= ~FMODE_WRITE; + write_mixer(s, 0x78, 0x12); + s->dma_dac.error++; + } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) { + clear_advance(s->dma_dac.rawbuf, s->dma_dac.dmasize, s->dma_dac.swptr, + s->dma_dac.fragsize, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80); + s->dma_dac.endcleared = 1; + } + if (s->dma_dac.count < (signed)s->dma_dac.dmasize) + wake_up(&s->dma_dac.wait); + } + } +} + +/* --------------------------------------------------------------------- */ + +static void prog_codec(struct solo1_state *s) +{ + unsigned long flags; + int fdiv, filter; + unsigned char c; + + reset_ctrl(s); + write_seq(s, 0xd3); + /* program sampling rates */ + filter = s->rate * 9 / 20; /* Set filter roll-off to 90% of rate/2 */ + fdiv = 256 - 7160000 / (filter * 82); + spin_lock_irqsave(&s->lock, flags); + write_ctrl(s, 0xa1, s->clkdiv); + write_ctrl(s, 0xa2, fdiv); + write_mixer(s, 0x70, s->clkdiv); + write_mixer(s, 0x72, fdiv); + /* program ADC parameters */ + write_ctrl(s, 0xb8, 0xe); + write_ctrl(s, 0xb9, /*0x1*/0); + write_ctrl(s, 0xa8, (s->channels > 1) ? 0x11 : 0x12); + c = 0xd0; + if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + c |= 0x04; + if (s->fmt & (AFMT_S16_LE | AFMT_S8)) + c |= 0x20; + if (s->channels > 1) + c ^= 0x48; + write_ctrl(s, 0xb7, (c & 0x70) | 1); + write_ctrl(s, 0xb7, c); + write_ctrl(s, 0xb1, 0x50); + write_ctrl(s, 0xb2, 0x50); + /* program DAC parameters */ + c = 0x40; + if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + c |= 1; + if (s->fmt & (AFMT_S16_LE | AFMT_S8)) + c |= 4; + if (s->channels > 1) + c |= 2; + write_mixer(s, 0x7a, c); + write_mixer(s, 0x78, 0x10); + s->ena = 0; + spin_unlock_irqrestore(&s->lock, flags); +} + +/* --------------------------------------------------------------------- */ + +static const char invalid_magic[] = KERN_CRIT "solo1: invalid magic value\n"; + +#define VALIDATE_STATE(s) \ +({ \ + if (!(s) || (s)->magic != SOLO1_MAGIC) { \ + printk(invalid_magic); \ + return -ENXIO; \ + } \ +}) + +/* --------------------------------------------------------------------- */ + +static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long arg) +{ + static const unsigned int mixer_src[8] = { + SOUND_MASK_MIC, SOUND_MASK_MIC, SOUND_MASK_CD, SOUND_MASK_VOLUME, + SOUND_MASK_MIC, 0, SOUND_MASK_LINE, 0 + }; + static const unsigned char mixtable[SOUND_MIXER_NRDEVICES] = { + [SOUND_MIXER_PCM] = 0x7c, /* voice */ + [SOUND_MIXER_SYNTH] = 0x36, /* FM */ + [SOUND_MIXER_CD] = 0x38, /* CD */ + [SOUND_MIXER_LINE] = 0x3e, /* Line */ + [SOUND_MIXER_LINE1] = 0x3a, /* AUX */ + [SOUND_MIXER_MIC] = 0x1a, /* Mic */ + [SOUND_MIXER_LINE2] = 0x6d /* Mono in */ + }; + unsigned char l, r, rl, rr; + int i, val; + + VALIDATE_STATE(s); + + if (cmd == SOUND_MIXER_PRIVATE1) { + /* enable/disable/query mixer preamp */ + get_user_ret(val, (int *)arg, -EFAULT); + if (val != -1) { + val = val ? 0xff : 0xf7; + write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val); + } + val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0; + return put_user(val, (int *)arg); + } + if (cmd == SOUND_MIXER_PRIVATE1) { + /* enable/disable/query mixer preamp */ + get_user_ret(val, (int *)arg, -EFAULT); + if (val != -1) { + val = val ? 0xff : 0xf7; + write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val); + } + val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0; + return put_user(val, (int *)arg); + } + if (cmd == SOUND_MIXER_PRIVATE2) { + /* enable/disable/query spatializer */ + get_user_ret(val, (int *)arg, -EFAULT); + if (val != -1) { + val &= 0x3f; + write_mixer(s, 0x52, val); + write_mixer(s, 0x50, val ? 0x08 : 0); + } + return put_user(read_mixer(s, 0x52), (int *)arg); + } + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strncpy(info.id, "Solo1", sizeof(info.id)); + strncpy(info.name, "ESS Solo1", sizeof(info.name)); + info.modify_counter = s->mix.modcnt; + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == SOUND_OLD_MIXER_INFO) { + _old_mixer_info info; + strncpy(info.id, "Solo1", sizeof(info.id)); + strncpy(info.name, "ESS Solo1", sizeof(info.name)); + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, (int *)arg); + if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + return -EINVAL; + if (_IOC_DIR(cmd) == _IOC_READ) { + switch (_IOC_NR(cmd)) { + case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ + return put_user(mixer_src[read_mixer(s, 0x1c) & 7], (int *)arg); + + case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | + SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | SOUND_MASK_LINE2 | SOUND_MASK_RECLEV | + SOUND_MASK_SPEAKER, (int *)arg); + + case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ + return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME, (int *)arg); + + case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | + SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | SOUND_MASK_LINE2 | SOUND_MASK_RECLEV, (int *)arg); + + case SOUND_MIXER_CAPS: + return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); + + case SOUND_MIXER_VOLUME: + rl = read_mixer(s, 0x60); + rr = read_mixer(s, 0x62); + l = (rl * 3 + 11) / 2; + if (rl & 0x40) + l = 0; + r = (rr * 3 + 11) / 2; + if (rr & 0x40) + r = 0; + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + + case SOUND_MIXER_SPEAKER: + rl = read_mixer(s, 0x3c); + l = (rl & 7) * 14 + 2; + return put_user(l * 0x101, (int *)arg); + + case SOUND_MIXER_RECLEV: + rl = read_ctrl(s, 0xb4); + r = ((rl & 0xf) * 13 + 5) / 2; + l = (((rl >> 4) & 0xf) * 13 + 5) / 2; + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + + default: + i = _IOC_NR(cmd); + if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i]) + return -EINVAL; + rl = read_mixer(s, mixtable[i]); + r = ((rl & 0xf) * 13 + 5) / 2; + l = (((rl >> 4) & 0xf) * 13 + 5) / 2; + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + } + } + if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + return -EINVAL; + s->mix.modcnt++; + switch (_IOC_NR(cmd)) { + case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ + + { + static const unsigned char regs[] = { + 0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c + }; + int i; + + for (i = 0; i < sizeof(regs); i++) + printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n", + regs[i], read_mixer(s, regs[i])); + printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n", + 0xb4, read_ctrl(s, 0xb4)); + } + + get_user_ret(val, (int *)arg, -EFAULT); + i = hweight32(val); + if (i == 0) + return 0; + else if (i > 1) + val &= ~mixer_src[read_mixer(s, 0x1c) & 7]; + for (i = 0; i < 8; i++) { + if (mixer_src[i] & val) + break; + } + if (i > 7) + return 0; + write_mixer(s, 0x1c, i); + return 0; + + case SOUND_MIXER_VOLUME: + get_user_ret(val, (int *)arg, -EFAULT); + l = val & 0xff; + if (l > 100) + l = 100; + r = (val >> 8) & 0xff; + if (r > 100) + r = 100; + if (l < 6) { + rl = 0x40; + l = 0; + } else { + rl = (l * 2 - 11) / 3; + l = (rl * 3 + 11) / 2; + } + if (r < 6) { + rr = 0x40; + r = 0; + } else { + rr = (r * 2 - 11) / 3; + r = (rr * 3 + 11) / 2; + } + write_mixer(s, 0x60, rl); + write_mixer(s, 0x62, rr); + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + + case SOUND_MIXER_SPEAKER: + get_user_ret(val, (int *)arg, -EFAULT); + l = val & 0xff; + if (l > 100) + l = 100; + else if (l < 2) + l = 2; + rl = (l - 2) / 14; + l = rl * 14 + 2; + write_mixer(s, 0x3c, rl); + return put_user(l * 0x101, (int *)arg); + + case SOUND_MIXER_RECLEV: + get_user_ret(val, (int *)arg, -EFAULT); + l = (val << 1) & 0x1fe; + if (l > 200) + l = 200; + else if (l < 5) + l = 5; + r = (val >> 7) & 0x1fe; + if (r > 200) + r = 200; + else if (r < 5) + r = 5; + rl = (l - 5) / 13; + rr = (r - 5) / 13; + r = (rl * 13 + 5) / 2; + l = (rr * 13 + 5) / 2; + write_ctrl(s, 0xb4, (rl << 4) | rr); + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + + default: + i = _IOC_NR(cmd); + if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i]) + return -EINVAL; + get_user_ret(val, (int *)arg, -EFAULT); + l = (val << 1) & 0x1fe; + if (l > 200) + l = 200; + else if (l < 5) + l = 5; + r = (val >> 7) & 0x1fe; + if (r > 200) + r = 200; + else if (r < 5) + r = 5; + rl = (l - 5) / 13; + rr = (r - 5) / 13; + r = (rl * 13 + 5) / 2; + l = (rr * 13 + 5) / 2; + write_mixer(s, mixtable[i], (rl << 4) | rr); + return put_user((((unsigned int)r) << 8) | l, (int *)arg); + } +} + +/* --------------------------------------------------------------------- */ + +static loff_t solo1_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +/* --------------------------------------------------------------------- */ + +static int solo1_open_mixdev(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct solo1_state *s = devs; + + while (s && s->dev_mixer != minor) + s = s->next; + if (!s) + return -ENODEV; + VALIDATE_STATE(s); + file->private_data = s; + MOD_INC_USE_COUNT; + return 0; +} + +static int solo1_release_mixdev(struct inode *inode, struct file *file) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + + VALIDATE_STATE(s); + MOD_DEC_USE_COUNT; + return 0; +} + +static int solo1_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + return mixer_ioctl((struct solo1_state *)file->private_data, cmd, arg); +} + +static /*const*/ struct file_operations solo1_mixer_fops = { + &solo1_llseek, + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + &solo1_ioctl_mixdev, + NULL, /* mmap */ + &solo1_open_mixdev, + NULL, /* flush */ + &solo1_release_mixdev, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ +#if 0 + NULL, /* revalidate */ + NULL, /* lock */ +#endif +}; + +/* --------------------------------------------------------------------- */ + +static int drain_dac(struct solo1_state *s, int nonblock) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int count, tmo; + + if (s->dma_dac.mapped) + return 0; + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&s->dma_dac.wait, &wait); + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (nonblock) { + remove_wait_queue(&s->dma_dac.wait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = (count * HZ) / s->rate; + if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + tmo >>= 1; + if (s->channels > 1) + tmo >>= 1; + if (!schedule_timeout(tmo ? : 1) && tmo) + printk(KERN_DEBUG "solo1: dma timed out??\n"); + } + remove_wait_queue(&s->dma_dac.wait, &wait); + current->state = TASK_RUNNING; + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + +/* --------------------------------------------------------------------- */ + +static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned swptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->dma_adc.mapped) + return -ENXIO; + if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) + return ret; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + swptr = s->dma_adc.swptr; + cnt = s->dma_adc.dmasize-swptr; + if (s->dma_adc.count < cnt) + cnt = s->dma_adc.count; + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x DMAstat: 0x%02x DMAcnt: 0x%04x SBstat: 0x%02x cnt: %u\n", + read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc), cnt); +#endif + if (cnt <= 0) { + start_adc(s); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x A2: 0x%02x A4: 0x%02x A5: 0x%02x A8: 0x%02x\n" + KERN_DEBUG "solo1_read: regs: B1: 0x%02x B2: 0x%02x B7: 0x%02x B8: 0x%02x B9: 0x%02x\n" + KERN_DEBUG "solo1_read: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x mask: 0x%02x\n" + KERN_DEBUG "solo1_read: SBstat: 0x%02x cnt: %u\n", + read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), + read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), + inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt); +#endif + if (inb(s->vcbase+15) & 1) { + printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n"); + return -EIO; + } + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&s->dma_adc.wait); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x A2: 0x%02x A4: 0x%02x A5: 0x%02x A8: 0x%02x\n" + KERN_DEBUG "solo1_read: regs: B1: 0x%02x B2: 0x%02x B7: 0x%02x B8: 0x%02x B9: 0x%02x\n" + KERN_DEBUG "solo1_read: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x mask: 0x%02x\n" + KERN_DEBUG "solo1_read: SBstat: 0x%02x cnt: %u\n", + read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), + read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), + inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt); +#endif + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) + return ret ? ret : -EFAULT; + swptr = (swptr + cnt) % s->dma_adc.dmasize; + spin_lock_irqsave(&s->lock, flags); + s->dma_adc.swptr = swptr; + s->dma_adc.count -= cnt; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + start_adc(s); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x DMAstat: 0x%02x DMAcnt: 0x%04x SBstat: 0x%02x\n", + read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc)); +#endif + } + return ret; +} + +static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned swptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (s->dma_dac.mapped) + return -ENXIO; + if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) + return ret; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; +#if 0 + printk(KERN_DEBUG "solo1_write: reg 70: 0x%02x 71: 0x%02x 72: 0x%02x 74: 0x%02x 76: 0x%02x 78: 0x%02x 7A: 0x%02x\n" + KERN_DEBUG "solo1_write: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x SBstat: 0x%02x\n", + read_mixer(s, 0x70), read_mixer(s, 0x71), read_mixer(s, 0x72), read_mixer(s, 0x74), read_mixer(s, 0x76), + read_mixer(s, 0x78), read_mixer(s, 0x7a), inl(s->iobase), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc)); + printk(KERN_DEBUG "solo1_write: reg 78: 0x%02x reg 7A: 0x%02x DMAcnt: 0x%04x DMAstat: 0x%02x SBstat: 0x%02x\n", + read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc)); +#endif + ret = 0; + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + if (s->dma_dac.count < 0) { + s->dma_dac.count = 0; + s->dma_dac.swptr = s->dma_dac.hwptr; + } + swptr = s->dma_dac.swptr; + cnt = s->dma_dac.dmasize-swptr; + if (s->dma_dac.count + cnt > s->dma_dac.dmasize) + cnt = s->dma_dac.dmasize - s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + start_dac(s); + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&s->dma_dac.wait); + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) + return ret ? ret : -EFAULT; + swptr = (swptr + cnt) % s->dma_dac.dmasize; + spin_lock_irqsave(&s->lock, flags); + s->dma_dac.swptr = swptr; + s->dma_dac.count += cnt; + s->dma_dac.endcleared = 0; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + start_dac(s); + } + return ret; +} + +static unsigned int solo1_poll(struct file *file, struct poll_table_struct *wait) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + VALIDATE_STATE(s); + if (file->f_mode & FMODE_WRITE) + poll_wait(file, &s->dma_dac.wait, wait); + if (file->f_mode & FMODE_READ) + poll_wait(file, &s->dma_adc.wait, wait); + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + if (file->f_mode & FMODE_READ) { + if (s->dma_adc.mapped) { + if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + mask |= POLLIN | POLLRDNORM; + } else { + if (s->dma_adc.count > 0) + mask |= POLLIN | POLLRDNORM; + } + } + if (file->f_mode & FMODE_WRITE) { + if (s->dma_dac.mapped) { + if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + mask |= POLLOUT | POLLWRNORM; + } else { + if ((signed)s->dma_dac.dmasize > s->dma_dac.count) + mask |= POLLOUT | POLLWRNORM; + } + } + spin_unlock_irqrestore(&s->lock, flags); + return mask; +} + + +static int solo1_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + struct dmabuf *db; + int ret; + unsigned long size; + + VALIDATE_STATE(s); + if (vma->vm_flags & VM_WRITE) { + if ((ret = prog_dmabuf_dac(s)) != 0) + return ret; + db = &s->dma_dac; + } else if (vma->vm_flags & VM_READ) { + if ((ret = prog_dmabuf_adc(s)) != 0) + return ret; + db = &s->dma_adc; + } else + return -EINVAL; + if (vma->vm_offset != 0) + return -EINVAL; + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE << db->buforder)) + return -EINVAL; + if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) + return -EAGAIN; + db->mapped = 1; + return 0; +} + +static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + unsigned long flags; + audio_buf_info abinfo; + count_info cinfo; + int val, mapped, ret; + int div1, div2; + unsigned rate1, rate2; + + VALIDATE_STATE(s); + mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || + ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, (int *)arg); + + case SNDCTL_DSP_SYNC: + if (file->f_mode & FMODE_WRITE) + return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/); + return 0; + + case SNDCTL_DSP_SETDUPLEX: + return 0; + + case SNDCTL_DSP_GETCAPS: + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + synchronize_irq(); + s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0; + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + synchronize_irq(); + s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0; + } + prog_codec(s); + return 0; + + case SNDCTL_DSP_SPEED: + get_user_ret(val, (int *)arg, -EFAULT); + if (val >= 0) { + stop_adc(s); + stop_dac(s); + s->dma_adc.ready = s->dma_dac.ready = 0; + /* program sampling rates */ + if (val > 48000) + val = 48000; + if (val < 6300) + val = 6300; + div1 = (768000 + val / 2) / val; + rate1 = (768000 + div1 / 2) / div1; + div1 = -div1; + div2 = (793800 + val / 2) / val; + rate2 = (793800 + div2 / 2) / div2; + div2 = (-div2) & 0x7f; + if (abs(val - rate2) < abs(val - rate1)) { + rate1 = rate2; + div1 = div2; + } + s->rate = rate1; + s->clkdiv = div1; + prog_codec(s); + } + return put_user(s->rate, (int *)arg); + + case SNDCTL_DSP_STEREO: + get_user_ret(val, (int *)arg, -EFAULT); + stop_adc(s); + stop_dac(s); + s->dma_adc.ready = s->dma_dac.ready = 0; + /* program channels */ + s->channels = val ? 2 : 1; + prog_codec(s); + return 0; + + case SNDCTL_DSP_CHANNELS: + get_user_ret(val, (int *)arg, -EFAULT); + if (val != 0) { + stop_adc(s); + stop_dac(s); + s->dma_adc.ready = s->dma_dac.ready = 0; + /* program channels */ + s->channels = val ? 2 : 1; + prog_codec(s); + } + return put_user(s->channels, (int *)arg); + + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); + + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ + get_user_ret(val, (int *)arg, -EFAULT); + if (val != AFMT_QUERY) { + stop_adc(s); + stop_dac(s); + s->dma_adc.ready = s->dma_dac.ready = 0; + /* program format */ + if (val != AFMT_S16_LE && val != AFMT_U16_LE && + val != AFMT_S8 && val != AFMT_U8) + val = AFMT_U8; + s->fmt = val; + prog_codec(s); + } + return put_user(s->fmt, (int *)arg); + + case SNDCTL_DSP_POST: + return 0; + + case SNDCTL_DSP_GETTRIGGER: + val = 0; + if (file->f_mode & s->ena & FMODE_READ) + val |= PCM_ENABLE_INPUT; + if (file->f_mode & s->ena & FMODE_WRITE) + val |= PCM_ENABLE_OUTPUT; + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETTRIGGER: + get_user_ret(val, (int *)arg, -EFAULT); + if (file->f_mode & FMODE_READ) { + if (val & PCM_ENABLE_INPUT) { + if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) + return ret; + start_adc(s); + if (inb(s->vcbase+15) & 1) + printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n"); + } else + stop_adc(s); + } + if (file->f_mode & FMODE_WRITE) { + if (val & PCM_ENABLE_OUTPUT) { + if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) + return ret; + start_dac(s); + } else + stop_dac(s); + } + return 0; + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0) + return val; + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + abinfo.fragsize = s->dma_dac.fragsize; + abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; + abinfo.fragstotal = s->dma_dac.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0) + return val; + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + abinfo.fragsize = s->dma_adc.fragsize; + abinfo.bytes = s->dma_adc.count; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + val = s->dma_dac.count; + spin_unlock_irqrestore(&s->lock, flags); + return put_user(val, (int *)arg); + + case SNDCTL_DSP_GETIPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + cinfo.bytes = s->dma_adc.total_bytes; + cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + cinfo.ptr = s->dma_adc.hwptr; + if (s->dma_adc.mapped) + s->dma_adc.count &= s->dma_adc.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETOPTR: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&s->lock, flags); + solo1_update_ptr(s); + cinfo.bytes = s->dma_dac.total_bytes; + cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + cinfo.ptr = s->dma_dac.hwptr; + if (s->dma_dac.mapped) + s->dma_dac.count &= s->dma_dac.fragsize-1; + spin_unlock_irqrestore(&s->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) { + if ((val = prog_dmabuf_dac(s))) + return val; + return put_user(s->dma_dac.fragsize, (int *)arg); + } + if ((val = prog_dmabuf_adc(s))) + return val; + return put_user(s->dma_adc.fragsize, (int *)arg); + + case SNDCTL_DSP_SETFRAGMENT: + get_user_ret(val, (int *)arg, -EFAULT); + if (file->f_mode & FMODE_READ) { + s->dma_adc.ossfragshift = val & 0xffff; + s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_adc.ossfragshift < 4) + s->dma_adc.ossfragshift = 4; + if (s->dma_adc.ossfragshift > 15) + s->dma_adc.ossfragshift = 15; + if (s->dma_adc.ossmaxfrags < 4) + s->dma_adc.ossmaxfrags = 4; + } + if (file->f_mode & FMODE_WRITE) { + s->dma_dac.ossfragshift = val & 0xffff; + s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; + if (s->dma_dac.ossfragshift < 4) + s->dma_dac.ossfragshift = 4; + if (s->dma_dac.ossfragshift > 15) + s->dma_dac.ossfragshift = 15; + if (s->dma_dac.ossmaxfrags < 4) + s->dma_dac.ossmaxfrags = 4; + } + return 0; + + case SNDCTL_DSP_SUBDIVIDE: + if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || + (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) + return -EINVAL; + get_user_ret(val, (int *)arg, -EFAULT); + if (val != 1 && val != 2 && val != 4) + return -EINVAL; + if (file->f_mode & FMODE_READ) + s->dma_adc.subdivision = val; + if (file->f_mode & FMODE_WRITE) + s->dma_dac.subdivision = val; + return 0; + + case SOUND_PCM_READ_RATE: + return put_user(s->rate, (int *)arg); + + case SOUND_PCM_READ_CHANNELS: + return put_user(s->channels, (int *)arg); + + case SOUND_PCM_READ_BITS: + return put_user((s->fmt & (AFMT_S8|AFMT_U8)) ? 8 : 16, (int *)arg); + + case SOUND_PCM_WRITE_FILTER: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + + } + return mixer_ioctl(s, cmd, arg); +} + +static int solo1_release(struct inode *inode, struct file *file) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + + VALIDATE_STATE(s); + if (file->f_mode & FMODE_WRITE) + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem); + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + outb(0, s->iobase+6); /* disable DMA */ + dealloc_dmabuf(&s->dma_dac); + } + if (file->f_mode & FMODE_READ) { + stop_adc(s); + outb(1, s->vcbase+0xf); /* mask DMA channel */ + //outb(0, s->vcbase+0xd); /* DMA master clear */ + dealloc_dmabuf(&s->dma_adc); + } + s->open_mode &= ~(FMODE_READ | FMODE_WRITE); + up(&s->open_sem); + wake_up(&s->open_wait); + MOD_DEC_USE_COUNT; + return 0; +} + +static int solo1_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct solo1_state *s = devs; + + while (s && ((s->dev_audio ^ minor) & ~0xf)) + s = s->next; + if (!s) + return -ENODEV; + VALIDATE_STATE(s); + file->private_data = s; + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & (FMODE_READ | FMODE_WRITE)) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EBUSY; + } + up(&s->open_sem); + interruptible_sleep_on(&s->open_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + s->fmt = AFMT_U8; + s->channels = 1; + s->rate = 8000; + s->clkdiv = 96 | 0x80; + s->ena = 0; + s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; + s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + up(&s->open_sem); + MOD_INC_USE_COUNT; + if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) { + solo1_release(inode, file); + return -ENOMEM; + } + prog_codec(s); + return 0; +} + +static /*const*/ struct file_operations solo1_audio_fops = { + &solo1_llseek, + &solo1_read, + &solo1_write, + NULL, /* readdir */ + &solo1_poll, + &solo1_ioctl, + &solo1_mmap, + &solo1_open, + NULL, /* flush */ + &solo1_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ +#if 0 + NULL, /* revalidate */ + NULL, /* lock */ +#endif +}; + +/* --------------------------------------------------------------------- */ + +/* hold spinlock for the following! */ +static void solo1_handle_midi(struct solo1_state *s) +{ + unsigned char ch; + int wake; + + if (!(s->mpubase)) + return; + wake = 0; + while (inb(s->mpubase+1) & 0x80) { + ch = inb(s->mpubase); + if (s->midi.icnt < MIDIINBUF) { + s->midi.ibuf[s->midi.iwr] = ch; + s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF; + s->midi.icnt++; + } + wake = 1; + } + if (wake) + wake_up(&s->midi.iwait); + wake = 0; + while ((inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) { + outb(s->midi.obuf[s->midi.ord], s->mpubase); + s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF; + s->midi.ocnt--; + if (s->midi.ocnt < MIDIOUTBUF-16) + wake = 1; + } + if (wake) + wake_up(&s->midi.owait); +} + +static void solo1_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct solo1_state *s = (struct solo1_state *)dev_id; + unsigned int intsrc; + + static unsigned lim = 0; + + /* fastpath out, to ease interrupt sharing */ + intsrc = inb(s->iobase+7); /* get interrupt source(s) */ + if (!intsrc) + return; + (void)inb(s->sbbase+0xe); /* clear interrupt */ +#ifdef DEBUGREC + if (intsrc & 0x10 && lim < 20) { + lim++; + printk(KERN_DEBUG "solo1: audio1int reg B8: 0x%02x DMAstat: 0x%02x DMAcnt: 0x%04x SBstat: 0x%02x\n", + read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc)); + } + //printk(KERN_DEBUG "solo1: interrupt 0x%02x\n", intsrc); +#endif + spin_lock(&s->lock); + /* clear audio interrupts first */ + if (intsrc & 0x20) + write_mixer(s, 0x7a, read_mixer(s, 0x7a) & 0x7f); + solo1_update_ptr(s); + solo1_handle_midi(s); + spin_unlock(&s->lock); +} + +static void solo1_midi_timer(unsigned long data) +{ + struct solo1_state *s = (struct solo1_state *)data; + unsigned long flags; + + spin_lock_irqsave(&s->lock, flags); + solo1_handle_midi(s); + spin_unlock_irqrestore(&s->lock, flags); + s->midi.timer.expires = jiffies+1; + add_timer(&s->midi.timer); +} + +/* --------------------------------------------------------------------- */ + +static ssize_t solo1_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned ptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + ptr = s->midi.ird; + cnt = MIDIINBUF - ptr; + if (s->midi.icnt < cnt) + cnt = s->midi.icnt; + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&s->midi.iwait); + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) + return ret ? ret : -EFAULT; + ptr = (ptr + cnt) % MIDIINBUF; + spin_lock_irqsave(&s->lock, flags); + s->midi.ird = ptr; + s->midi.icnt -= cnt; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + } + return ret; +} + +static ssize_t solo1_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned ptr; + int cnt; + + VALIDATE_STATE(s); + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + while (count > 0) { + spin_lock_irqsave(&s->lock, flags); + ptr = s->midi.owr; + cnt = MIDIOUTBUF - ptr; + if (s->midi.ocnt + cnt > MIDIOUTBUF) + cnt = MIDIOUTBUF - s->midi.ocnt; + if (cnt <= 0) + solo1_handle_midi(s); + spin_unlock_irqrestore(&s->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&s->midi.owait); + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) + return ret ? ret : -EFAULT; + ptr = (ptr + cnt) % MIDIOUTBUF; + spin_lock_irqsave(&s->lock, flags); + s->midi.owr = ptr; + s->midi.ocnt += cnt; + spin_unlock_irqrestore(&s->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + spin_lock_irqsave(&s->lock, flags); + solo1_handle_midi(s); + spin_unlock_irqrestore(&s->lock, flags); + } + return ret; +} + +static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct *wait) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + VALIDATE_STATE(s); + if (file->f_flags & FMODE_WRITE) + poll_wait(file, &s->midi.owait, wait); + if (file->f_flags & FMODE_READ) + poll_wait(file, &s->midi.iwait, wait); + spin_lock_irqsave(&s->lock, flags); + if (file->f_flags & FMODE_READ) { + if (s->midi.icnt > 0) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_flags & FMODE_WRITE) { + if (s->midi.ocnt < MIDIOUTBUF) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_irqrestore(&s->lock, flags); + return mask; +} + +static int solo1_midi_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct solo1_state *s = devs; + unsigned long flags; + + while (s && s->dev_midi != minor) + s = s->next; + if (!s) + return -ENODEV; + VALIDATE_STATE(s); + file->private_data = s; + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EBUSY; + } + up(&s->open_sem); + interruptible_sleep_on(&s->open_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + spin_lock_irqsave(&s->lock, flags); + if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { + s->midi.ird = s->midi.iwr = s->midi.icnt = 0; + s->midi.ord = s->midi.owr = s->midi.ocnt = 0; + outb(0xff, s->mpubase+1); /* reset command */ + outb(0x3f, s->mpubase+1); /* uart command */ + if (!(inb(s->mpubase+1) & 0x80)) + inb(s->mpubase); + s->midi.ird = s->midi.iwr = s->midi.icnt = 0; + outb(0xb0, s->iobase + 7); /* enable A1, A2, MPU irq's */ + init_timer(&s->midi.timer); + s->midi.timer.expires = jiffies+1; + s->midi.timer.data = (unsigned long)s; + s->midi.timer.function = solo1_midi_timer; + add_timer(&s->midi.timer); + } + if (file->f_mode & FMODE_READ) { + s->midi.ird = s->midi.iwr = s->midi.icnt = 0; + } + if (file->f_mode & FMODE_WRITE) { + s->midi.ord = s->midi.owr = s->midi.ocnt = 0; + } + spin_unlock_irqrestore(&s->lock, flags); + s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); + up(&s->open_sem); + MOD_INC_USE_COUNT; + return 0; +} + +static int solo1_midi_release(struct inode *inode, struct file *file) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + unsigned count, tmo; + + VALIDATE_STATE(s); + + if (file->f_mode & FMODE_WRITE) { + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&s->midi.owait, &wait); + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->midi.ocnt; + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (file->f_flags & O_NONBLOCK) { + remove_wait_queue(&s->midi.owait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = (count * HZ) / 3100; + if (!schedule_timeout(tmo ? : 1) && tmo) + printk(KERN_DEBUG "solo1: midi timed out??\n"); + } + remove_wait_queue(&s->midi.owait, &wait); + current->state = TASK_RUNNING; + } + down(&s->open_sem); + s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE); + spin_lock_irqsave(&s->lock, flags); + if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { + outb(0x30, s->iobase + 7); /* enable A1, A2 irq's */ + del_timer(&s->midi.timer); + } + spin_unlock_irqrestore(&s->lock, flags); + up(&s->open_sem); + wake_up(&s->open_wait); + MOD_DEC_USE_COUNT; + return 0; +} + +static /*const*/ struct file_operations solo1_midi_fops = { + &solo1_llseek, + &solo1_midi_read, + &solo1_midi_write, + NULL, /* readdir */ + &solo1_midi_poll, + NULL, /* ioctl */ + NULL, /* mmap */ + &solo1_midi_open, + NULL, /* flush */ + &solo1_midi_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ +#if 0 + NULL, /* revalidate */ + NULL, /* lock */ +#endif +}; + +/* --------------------------------------------------------------------- */ + +static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + static const unsigned char op_offset[18] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 + }; + struct solo1_state *s = (struct solo1_state *)file->private_data; + struct dm_fm_voice v; + struct dm_fm_note n; + struct dm_fm_params p; + unsigned int io; + unsigned int regb; + + switch (cmd) { + case FM_IOCTL_RESET: + for (regb = 0xb0; regb < 0xb9; regb++) { + outb(regb, s->sbbase); + outb(0, s->sbbase+1); + outb(regb, s->sbbase+2); + outb(0, s->sbbase+3); + } + return 0; + + case FM_IOCTL_PLAY_NOTE: + if (copy_from_user(&n, (void *)arg, sizeof(n))) + return -EFAULT; + if (n.voice >= 18) + return -EINVAL; + if (n.voice >= 9) { + regb = n.voice - 9; + io = s->sbbase+2; + } else { + regb = n.voice; + io = s->sbbase; + } + outb(0xa0 + regb, io); + outb(n.fnum & 0xff, io+1); + outb(0xb0 + regb, io); + outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1); + return 0; + + case FM_IOCTL_SET_VOICE: + if (copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + if (v.voice >= 18) + return -EINVAL; + regb = op_offset[v.voice]; + io = s->sbbase + ((v.op & 1) << 1); + outb(0x20 + regb, io); + outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) | + ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1); + outb(0x40 + regb, io); + outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1); + outb(0x60 + regb, io); + outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1); + outb(0x80 + regb, io); + outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1); + outb(0xe0 + regb, io); + outb(v.waveform & 0x7, io+1); + if (n.voice >= 9) { + regb = n.voice - 9; + io = s->sbbase+2; + } else { + regb = n.voice; + io = s->sbbase; + } + outb(0xc0 + regb, io); + outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) | + (v.connection & 1), io+1); + return 0; + + case FM_IOCTL_SET_PARAMS: + if (copy_from_user(&p, (void *)arg, sizeof(p))) + return -EFAULT; + outb(0x08, s->sbbase); + outb((p.kbd_split & 1) << 6, s->sbbase+1); + outb(0xbd, s->sbbase); + outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) | + ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->sbbase+1); + return 0; + + case FM_IOCTL_SET_OPL: + outb(4, s->sbbase+2); + outb(arg, s->sbbase+3); + return 0; + + case FM_IOCTL_SET_MODE: + outb(5, s->sbbase+2); + outb(arg & 1, s->sbbase+3); + return 0; + + default: + return -EINVAL; + } +} + +static int solo1_dmfm_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct solo1_state *s = devs; + + while (s && s->dev_dmfm != minor) + s = s->next; + if (!s) + return -ENODEV; + VALIDATE_STATE(s); + file->private_data = s; + /* wait for device to become free */ + down(&s->open_sem); + while (s->open_mode & FMODE_DMFM) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem); + return -EBUSY; + } + up(&s->open_sem); + interruptible_sleep_on(&s->open_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem); + } + /* init the stuff */ + outb(1, s->sbbase); + outb(0x20, s->sbbase+1); /* enable waveforms */ + outb(4, s->sbbase+2); + outb(0, s->sbbase+3); /* no 4op enabled */ + outb(5, s->sbbase+2); + outb(1, s->sbbase+3); /* enable OPL3 */ + s->open_mode |= FMODE_DMFM; + up(&s->open_sem); + MOD_INC_USE_COUNT; + return 0; +} + +static int solo1_dmfm_release(struct inode *inode, struct file *file) +{ + struct solo1_state *s = (struct solo1_state *)file->private_data; + unsigned int regb; + + VALIDATE_STATE(s); + down(&s->open_sem); + s->open_mode &= ~FMODE_DMFM; + for (regb = 0xb0; regb < 0xb9; regb++) { + outb(regb, s->sbbase); + outb(0, s->sbbase+1); + outb(regb, s->sbbase+2); + outb(0, s->sbbase+3); + } + up(&s->open_sem); + wake_up(&s->open_wait); + MOD_DEC_USE_COUNT; + return 0; +} + +static /*const*/ struct file_operations solo1_dmfm_fops = { + &solo1_llseek, + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + &solo1_dmfm_ioctl, + NULL, /* mmap */ + &solo1_dmfm_open, + NULL, /* flush */ + &solo1_dmfm_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ +#if 0 + NULL, /* revalidate */ + NULL, /* lock */ +#endif +}; + +/* --------------------------------------------------------------------- */ + +/* maximum number of devices */ +#define NR_DEVICE 5 + +/* --------------------------------------------------------------------- */ + +static struct initvol { + int mixch; + int vol; +} initvol[] __initdata = { + { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, + { SOUND_MIXER_WRITE_PCM, 0x4040 }, + { SOUND_MIXER_WRITE_SYNTH, 0x4040 }, + { SOUND_MIXER_WRITE_CD, 0x4040 }, + { SOUND_MIXER_WRITE_LINE, 0x4040 }, + { SOUND_MIXER_WRITE_LINE1, 0x4040 }, + { SOUND_MIXER_WRITE_LINE2, 0x4040 }, + { SOUND_MIXER_WRITE_RECLEV, 0x4040 }, + { SOUND_MIXER_WRITE_SPEAKER, 0x4040 }, + { SOUND_MIXER_WRITE_MIC, 0x4040 } +}; + +static int __init init_solo1(void) +{ + struct solo1_state *s; + struct pci_dev *pcidev = NULL; + mm_segment_t fs; + int i, val, index = 0; + u16 ddmabase; + + if (!pci_present()) /* No PCI bus in this machine! */ + return -ENODEV; + printk(KERN_INFO "solo1: version v0.5 time " __TIME__ " " __DATE__ "\n"); + while (index < NR_DEVICE && + (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) { + if (pcidev->resource[0].start == 0 || + (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO || + pcidev->resource[1].start == 0 || + (pcidev->resource[1].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO || + pcidev->resource[2].start == 0 || + (pcidev->resource[2].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO || + pcidev->resource[3].start == 0 || + (pcidev->resource[3].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + continue; + if (pcidev->irq == 0) + continue; + if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) { + printk(KERN_WARNING "solo1: out of memory\n"); + continue; + } + memset(s, 0, sizeof(struct solo1_state)); + init_waitqueue_head(&s->dma_adc.wait); + init_waitqueue_head(&s->dma_dac.wait); + init_waitqueue_head(&s->open_wait); + init_waitqueue_head(&s->midi.iwait); + init_waitqueue_head(&s->midi.owait); + init_MUTEX(&s->open_sem); + s->magic = SOLO1_MAGIC; + s->iobase = pcidev->resource[0].start; + s->sbbase = pcidev->resource[1].start; + s->vcbase = pcidev->resource[2].start; + s->mpubase = pcidev->resource[3].start; + s->gpbase = pcidev->resource[4].start; + s->irq = pcidev->irq; + if (check_region(s->iobase, IOBASE_EXTENT) || + check_region(s->sbbase, SBBASE_EXTENT) || + check_region(s->vcbase, VCBASE_EXTENT) || + check_region(s->mpubase, MPUBASE_EXTENT)) { + printk(KERN_ERR "solo1: io ports in use\n"); + goto err_region; + } + request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1"); + request_region(s->sbbase, SBBASE_EXTENT, "ESS Solo1"); + request_region(s->vcbase, VCBASE_EXTENT, "ESS Solo1"); + request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1"); + if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) { + printk(KERN_ERR "solo1: irq %u in use\n", s->irq); + goto err_irq; + } + /* initialize DDMA base address */ + /* use PCI config reg, and not vcbase, we need the bus view */ + pci_read_config_word(pcidev, 0x18, &ddmabase); + pci_write_config_word(pcidev, 0x60, (ddmabase & (~0xf)) | 1); +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + /* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */ + pci_write_config_dword(pcidev, 0x50, 0); + /* disable legacy audio address decode */ + pci_write_config_word(pcidev, 0x40, 0x907f); + + printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1); + + /* register devices */ + if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) + goto err_dev1; + if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0) + goto err_dev2; + if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0) + goto err_dev3; + if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0) + goto err_dev4; + /* initialize the chips */ + outb(0xb0, s->iobase+7); /* enable A1, A2, MPU irq's */ + + /* initialize mixer regs */ + write_mixer(s, 0x7f, 0); /* disable music digital recording */ + write_mixer(s, 0x7d, 0x0c); /* enable mic preamp, MONO_OUT is 2nd DAC right channel */ + write_mixer(s, 0x64, 0x45); /* volume control */ + write_mixer(s, 0x48, 0x10); /* enable music DAC/ES6xx interface */ + write_mixer(s, 0x50, 0); /* disable spatializer */ + write_mixer(s, 0x52, 0); + write_mixer(s, 0x14, 0); /* DAC1 minimum volume */ + write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(0, s->vcbase+0xd); /* DMA master clear */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + outb(1, s->vcbase+0xf); /* mask channel */ +#ifdef DEBUGREC + printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x stat: 0x%02x\n", + inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8)); +#endif + //outb(0, s->vcbase+0x8); /* enable controller (enable is low active!!) */ + + pci_set_master(pcidev); /* enable bus mastering */ + + fs = get_fs(); + set_fs(KERNEL_DS); + val = SOUND_MASK_LINE; + mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); + for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { + val = initvol[i].vol; + mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val); + } + set_fs(fs); + /* queue it for later freeing */ + s->next = devs; + devs = s; + index++; + continue; + + err_dev4: + unregister_sound_dsp(s->dev_midi); + err_dev3: + unregister_sound_mixer(s->dev_mixer); + err_dev2: + unregister_sound_dsp(s->dev_audio); + err_dev1: + printk(KERN_ERR "solo1: cannot register misc device\n"); + free_irq(s->irq, s); + err_irq: + release_region(s->iobase, IOBASE_EXTENT); + release_region(s->sbbase, SBBASE_EXTENT); + release_region(s->vcbase, VCBASE_EXTENT); + release_region(s->mpubase, MPUBASE_EXTENT); + err_region: + kfree_s(s, sizeof(struct solo1_state)); + } + if (!devs) + return -ENODEV; + return 0; +} + +/* --------------------------------------------------------------------- */ + +MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); +MODULE_DESCRIPTION("ESS Solo1 Driver"); + +static void __exit cleanup_solo1(void) +{ + struct solo1_state *s; + + while ((s = devs)) { + devs = devs->next; + /* stop DMA controller */ + outb(0, s->iobase+6); + outb(0, s->vcbase+0xd); /* DMA master clear */ + outb(3, s->sbbase+6); /* reset sequencer and FIFO */ + synchronize_irq(); + free_irq(s->irq, s); + release_region(s->iobase, IOBASE_EXTENT); + release_region(s->sbbase, SBBASE_EXTENT); + release_region(s->vcbase, VCBASE_EXTENT); + release_region(s->mpubase, MPUBASE_EXTENT); + unregister_sound_dsp(s->dev_audio); + unregister_sound_mixer(s->dev_mixer); + unregister_sound_midi(s->dev_midi); + unregister_sound_special(s->dev_dmfm); + kfree_s(s, sizeof(struct solo1_state)); + } + printk(KERN_INFO "solo1: unloading\n"); +} + +/* --------------------------------------------------------------------- */ + +module_init(init_solo1); +module_exit(cleanup_solo1); + diff -u --recursive --new-file v2.3.12/linux/drivers/sound/lowlevel/awe_compat-fbsd.h linux/drivers/sound/lowlevel/awe_compat-fbsd.h --- v2.3.12/linux/drivers/sound/lowlevel/awe_compat-fbsd.h Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/lowlevel/awe_compat-fbsd.h Thu Aug 5 14:43:32 1999 @@ -51,6 +51,7 @@ #ifdef AWE_OBSOLETE_VOXWARE +#include #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32) #define CONFIG_AWE32_SYNTH #endif diff -u --recursive --new-file v2.3.12/linux/drivers/sound/maui.c linux/drivers/sound/maui.c --- v2.3.12/linux/drivers/sound/maui.c Thu Jul 8 15:42:21 1999 +++ linux/drivers/sound/maui.c Wed Aug 4 16:36:41 1999 @@ -23,7 +23,7 @@ #include #include -#include +#include #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS diff -u --recursive --new-file v2.3.12/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c --- v2.3.12/linux/drivers/sound/sb_common.c Wed May 26 09:35:00 1999 +++ linux/drivers/sound/sb_common.c Wed Aug 4 15:48:00 1999 @@ -18,7 +18,7 @@ */ #include #include -#include +#include #include "sound_config.h" #include "sound_firmware.h" diff -u --recursive --new-file v2.3.12/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.3.12/linux/drivers/sound/sonicvibes.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/sound/sonicvibes.c Fri Aug 6 11:43:09 1999 @@ -71,6 +71,8 @@ * 15.06.99 0.15 Fix bad allocation bug. * Thanks to Deti Fliegl * 28.06.99 0.16 Add pci_set_master + * 03.08.99 0.17 adapt to Linus' new __setup/__initcall + * added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr" * */ @@ -2312,11 +2314,10 @@ { SOUND_MIXER_WRITE_PCM, 0x4040 } }; -#ifdef MODULE -int __init init_module(void) -#else -int __init init_sonicvibes(void) +#ifndef MODULE +static #endif +int __init init_module(void) { struct sv_state *s; struct pci_dev *pcidev = NULL; @@ -2325,21 +2326,21 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.16 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.17 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); #endif while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, pcidev))) { - if (pcidev->base_address[1] == 0 || - (pcidev->base_address[1] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pcidev->resource[1].flags == 0 || + (pcidev->resource[1].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; - if (pcidev->base_address[2] == 0 || - (pcidev->base_address[2] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pcidev->resource[2].flags == 0 || + (pcidev->resource[2].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; - if (pcidev->base_address[3] == 0 || - (pcidev->base_address[3] & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pcidev->resource[3].flags == 0 || + (pcidev->resource[3].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; if (pcidev->irq == 0) continue; @@ -2355,11 +2356,11 @@ init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); s->magic = SV_MAGIC; - s->iosb = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; - s->ioenh = pcidev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; - s->iosynth = pcidev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK; - s->iomidi = pcidev->base_address[3] & PCI_BASE_ADDRESS_IO_MASK; - s->iogame = pcidev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; + s->iosb = pcidev->resource[0].start; + s->ioenh = pcidev->resource[1].start; + s->iosynth = pcidev->resource[2].start; + s->iomidi = pcidev->resource[3].start; + s->iogame = pcidev->resource[4].start; pci_read_config_dword(pcidev, 0x40, &s->iodmaa); pci_read_config_dword(pcidev, 0x48, &s->iodmac); dmaio &= ~(SV_EXTENT_DMA-1); @@ -2525,8 +2526,8 @@ synchronize_irq(); inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */ wrindir(s, SV_CIENABLE, 0); /* disable DMAA and DMAC */ - //outb(0, s->iodmaa + SV_DMA_RESET); - //outb(0, s->iodmac + SV_DMA_RESET); + /*outb(0, s->iodmaa + SV_DMA_RESET);*/ + /*outb(0, s->iodmac + SV_DMA_RESET);*/ free_irq(s->irq, s); release_region(s->iodmac, SV_EXTENT_DMA); release_region(s->iodmaa, SV_EXTENT_DMA); @@ -2543,5 +2544,40 @@ free_pages(wavetable_mem, 20-PAGE_SHIFT); printk(KERN_INFO "sv: unloading\n"); } + +#else /* MODULE */ + +/* format is: sonicvibes=[reverb] sonicvibesdmaio=dmaioaddr */ + +static int __init sonicvibes_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + + if (nr_dev >= NR_DEVICE) + return 0; + + ( (get_option(&str, &reverb [nr_dev]) == 2) +#if 0 + && get_option(&str, &wavetable[nr_dev]) +#endif + }; + + nr_dev++; + return 1; +} + +static int __init sonicvibesdmaio_setup(char *str) +{ + int ints[11]; + + get_options(str, ints); + if (ints[0] >= 1) + dmaio = ints[1]; + return 1; +} + +__setup("sonicvibes=", sonicvibes_setup); +__setup("sonicvibesdmaio=", sonicvibesdmaio_setup); +__initcall(init_module); #endif /* MODULE */ diff -u --recursive --new-file v2.3.12/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c --- v2.3.12/linux/drivers/sound/sound_core.c Mon Jun 7 11:06:10 1999 +++ linux/drivers/sound/sound_core.c Wed Aug 4 09:27:54 1999 @@ -52,15 +52,6 @@ struct sound_unit *next; }; -#ifdef CONFIG_SOUND_SONICVIBES -extern int init_sonicvibes(void); -#endif -#ifdef CONFIG_SOUND_ES1370 -extern int init_es1370(void); -#endif -#ifdef CONFIG_SOUND_ES1371 -extern int init_es1371(void); -#endif #ifdef CONFIG_SOUND_MSNDCLAS extern int msnd_classic_init(void); #endif @@ -395,17 +386,8 @@ /* * Now init non OSS drivers */ -#ifdef CONFIG_SOUND_SONICVIBES - init_sonicvibes(); -#endif #ifdef CONFIG_SOUND_CMPCI init_cmpci(); -#endif -#ifdef CONFIG_SOUND_ES1370 - init_es1370(); -#endif -#ifdef CONFIG_SOUND_ES1371 - init_es1371(); #endif #ifdef CONFIG_SOUND_MSNDCLAS msnd_classic_init(); diff -u --recursive --new-file v2.3.12/linux/drivers/tc/tc.c linux/drivers/tc/tc.c --- v2.3.12/linux/drivers/tc/tc.c Wed Jun 30 13:38:20 1999 +++ linux/drivers/tc/tc.c Wed Aug 4 16:36:45 1999 @@ -12,7 +12,7 @@ */ #include -#include +#include #include #include #include diff -u --recursive --new-file v2.3.12/linux/drivers/usb/CREDITS linux/drivers/usb/CREDITS --- v2.3.12/linux/drivers/usb/CREDITS Thu Jul 8 15:42:21 1999 +++ linux/drivers/usb/CREDITS Mon Aug 2 14:29:08 1999 @@ -31,6 +31,10 @@ The following corporations have helped us in the development of Linux USB / UUSBD: + - 3Com GmbH for donating a ISDN Pro TA and supporting me + in technical questions and with test equipment. I'd never + expect such a great help. + - USAR Systems provided us with one of their excellent USB Evaluation Kits. It allows us to test the Linux-USB driver for compilance with the latest USB specification. USAR diff -u --recursive --new-file v2.3.12/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.12/linux/drivers/usb/Config.in Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/Config.in Mon Aug 9 12:15:53 1999 @@ -28,13 +28,15 @@ dep_tristate 'USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB dep_tristate 'USB keyboard support' CONFIG_USB_KBD $CONFIG_USB dep_tristate 'USB audio parsing support' CONFIG_USB_AUDIO $CONFIG_USB - dep_tristate 'USB Abstract Control Model support' CONFIG_USB_ACM $CONFIG_USB + dep_tristate 'USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB dep_tristate 'USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB + dep_tristate 'USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB dep_tristate 'USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB if [ "$CONFIG_USB_SCSI" != "n" ]; then dep_tristate ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG $CONFIG_USB_SCSI fi dep_tristate 'EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB + dep_tristate 'USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT if [ "$CONFIG_PROC_FS" != "n" ]; then bool 'Preliminary /proc/bus/usb support' CONFIG_USB_PROC fi diff -u --recursive --new-file v2.3.12/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.3.12/linux/drivers/usb/Makefile Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/Makefile Mon Aug 9 12:15:53 1999 @@ -85,6 +85,15 @@ MIX_OBJS += printer.o endif +ifeq ($(CONFIG_USB_CPIA),y) + L_OBJS += cpia.o +endif + +ifeq ($(CONFIG_USB_CPIA),m) + M_OBJS += cpia.o + MIX_OBJS += cpia.o +endif + ifeq ($(CONFIG_USB_KBD),y) L_OBJS += keyboard.o keymap.o endif @@ -119,6 +128,14 @@ endif endif +ifeq ($(CONFIG_USB_SCSI),m) + M_OBJS += usb-scsi.o + MIX_OBJS += usb_scsi.o + ifeq ($(CONFIG_USB_SCSI_DEBUG),y) + MIX_OBJS += usb_scsi_debug.o + endif +endif + ifeq ($(CONFIG_USB_EZUSB),y) L_OBJS += ezusb.o endif @@ -128,6 +145,15 @@ MIX_OBJS += ezusb.o endif +ifeq ($(CONFIG_USB_USS720),y) + L_OBJS += uss720.o +endif + +ifeq ($(CONFIG_USB_USS720),m) + M_OBJS += uss720.o + MIX_OBJS += uss720.o +endif + include $(TOPDIR)/Rules.make keymap.o: keymap.c @@ -145,6 +171,14 @@ else usb-keyboard.o: keymap-mac.o keyboard.o $(LD) $(LD_RFLAG) -r -o $@ keymap-mac.o keyboard.o +endif + +ifeq ($(CONFIG_USB_SCSI_DEBUG),y) +usb-scsi.o: usb_scsi.o usb_scsi_debug.o + $(LD) $(LD_RFLAG) -r -o $@ usb_scsi.o usb_scsi_debug.o +else +usb-scsi.o: usb_scsi.o + $(LD) $(LD_RFLAG) -r -o $@ usb_scsi.o endif usb-uhci.o: uhci.o uhci-debug.o diff -u --recursive --new-file v2.3.12/linux/drivers/usb/README.acm linux/drivers/usb/README.acm --- v2.3.12/linux/drivers/usb/README.acm Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/README.acm Mon Aug 2 14:29:08 1999 @@ -0,0 +1,94 @@ +The ACM driver works with modems and ISDN TAs that use the USB Abstract +Control Model standard. + +**************************** +Test it: +Watch out, the driver is not stable and tested. Sync often, make backups, +most importand: don't blame me... + +Create device files: +mknod /dev/ttyACM0 c 166 0 +mknod /dev/ttyACM1 c 166 1 +mknod /dev/ttyACM2 c 166 2 +mknod /dev/ttyACM3 c 166 3 +Compile a kernel with support for your host controller (uhci only for now!) +and support for ACM. Boot this kernel. If you connect your device to the +USB bus you should see messages like the following: + +Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 +Jul 19 20:14:29 office kernel: Found 02:09 +Jul 19 20:14:29 office kernel: Found 04:09 +Jul 19 20:14:29 office kernel: Found 05:07 +Jul 19 20:14:29 office last message repeated 2 times +Jul 19 20:14:29 office kernel: parsed = 39 len = 67 +Jul 19 20:14:29 office kernel: Expected descriptor 04/09, got 02/09 - skipping +Jul 19 20:14:29 office kernel: 0 09 +Jul 19 20:14:29 office kernel: 1 02 +Jul 19 20:14:29 office kernel: 2 43 +Jul 19 20:14:29 office kernel: 3 00 +Jul 19 20:14:29 office kernel: 4 02 +Jul 19 20:14:29 office kernel: 5 02 +Jul 19 20:14:29 office kernel: 6 04 +Jul 19 20:14:29 office kernel: 7 60 +Jul 19 20:14:29 office kernel: 8 00 +Jul 19 20:14:29 office kernel: Found 04:09 +Jul 19 20:14:29 office kernel: Found 02:09 +Jul 19 20:14:29 office kernel: Found 04:09 +Jul 19 20:14:29 office kernel: Found 05:07 +Jul 19 20:14:29 office kernel: Found 04:09 +Jul 19 20:14:29 office kernel: Found 05:07 +Jul 19 20:14:29 office kernel: Found 05:07 +Jul 19 20:14:29 office kernel: parsed = 67 len = 0 +Jul 19 20:14:29 office kernel: getstringtable +Jul 19 20:14:29 office kernel: acm_probe +Jul 19 20:14:29 office kernel: USB ACM found + +Watch out for the line: +Jul 19 20:14:29 office kernel: USB new device connect, assigned device number 1 +and the line: +Jul 19 20:14:29 office kernel: USB ACM found +These two lines show that the device was seen by the usb host controller and +then recognized by the acm driver as a valid device. + +If you use a terminal emulation software like minicom with /dev/ttyACM0 you +should be able to send AT commands to your device and get responses. I've +been able to do zmodem downloads to another pc. However downloads from one +ISDN TA to another ISDN TA connected to the same PC didn't work. Don't +know why. Flow control is not finised after all and i'd guess there might +be problems on heavily loades PCs. I also did some tests with ppp but i'm +not finised with this. There might be a chance to get it working. However +i'd like to know if your device is recognized as an ACM device. I'm also +interested if the thing is stable or if it crashes. +(should i say how it crases?) + +You should be able to add and remove devices from the bus. The driver will +always try to fill up unused ttys. This means if you hotplug devices their +order may have changed after reboot. This is not the behaviour Linus liked +to see but it's ok for now. (I hope ;-) + +Please report your experiences to me: +fuerst@in.tum.de + +*************************** +I've tested it with: +3Com ISDN Pro TA. + +It should work with (That means i know these devices conform to ACM): +3Com Office Connect Modem +3Com Sportster USB (I think that's what it's called) + +*************************** +Many thanks to 3Com which did not only support me with hardware but also +with technical support in USB questions. They also allowed me to do tests in +their lab. Great! + +*************************** +Known bugs: +Flow control not tested (likely not to work) +Some tty function calls not implemented (putchar, etc...) +Huge amounts of debug output (compile in [*] Magic SysRq key and press ALT+PRTSCR+0 ) +Not all mem is freed at close (need terminate irq in hcd) + +*************************** +Have fun, + Armin Fuerst diff -u --recursive --new-file v2.3.12/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.12/linux/drivers/usb/acm.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/acm.c Mon Aug 2 14:29:08 1999 @@ -3,6 +3,35 @@ * * Armin Fuerst 5/8/1999 * + * version 0.7: Added usb flow control. Fixed bug in uhci.c (what idiot + * wrote this code? ...Oops that was me). Fixed module cleanup. Did some + * testing at 3Com => zmodem uload+download works, pppd had trouble but + * seems to work now. Changed Menuconfig texts "Communications Device + * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch. + * (2/8/99) + * + * version 0.6: Modularized driver, added disconnect code, improved + * assignment of device to tty minor number. + * (21/7/99) + * + * version 0.5: Driver now generates a tty instead of a simple character + * device. Moved async bulk transfer to 2.3.10 kernel version. fixed a bug + * in uhci_td_allocate. Commenetd out getstringtable which causes crash. + * (13/7/99) + * + * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in + * uhci.c. Should have the correct interface now. + * (6/6/99) + * + * version 0.5 driver now generates a tty instead of a simple character + * device + * + * version 0.3: Mayor changes. Changed Bulk transfer to interrupt based + * transfer. Using FIFO Buffers now. Consistent handling of open/close + * file state and detected/nondetected device. File operations behave + * according to this. Driver is able to send+receive now! Heureka! + * (27/5/99) + * * version 0.2: Improved Bulk transfer. TX led now flashes every time data is * sent. Send Encapsulated Data is not needed, nor does it do anything. * Why's that ?!? Thanks to Thomas Sailer for his close look at the bulk code. @@ -22,171 +51,448 @@ #include #include #include -#include #include #include #include +#include +#include +#include +#include #include - +//#include #include - #include "usb.h" -#define USB_ACM_MINOR 32 +#define NR_PORTS 3 +#define ACM_MAJOR 166 + +#define info(message); printk(message); +//#define info(message); + +#define CTRL_STAT_DTR 1 +#define CTRL_STAT_RTS 2 + +static int acm_refcount; + +static struct tty_driver acm_tty_driver; +static struct tty_struct *acm_tty[NR_PORTS]; +static struct termios *acm_termios[NR_PORTS]; +static struct termios *acm_termios_locked[NR_PORTS]; +static struct acm_state acm_state_table[NR_PORTS]; struct acm_state { - int present; /* this acm is plugged in */ - int active; /* someone is has this acm's device open */ - int serstate; /* Status of the serial port (rate, handshakelines,...) */ - struct usb_device *dev; - unsigned ctrlbuffer; /*buffer for control messages*/ - unsigned int readendp,writeendp,ctrlendp; - unsigned int readpipe,writepipe,ctrlpipe; - char buffer; + struct usb_device *dev; //the coresponding usb device + struct tty_struct *tty; //the coresponding tty + char present; //a device for this struct was detected => this tty is used + char active; //someone has this acm's device open + unsigned int ctrlstate; //Status of the serial control lines (handshake,...) + unsigned int linecoding; //Status of the line coding (Bits, Stop, Parity) + int writesize, readsize; //size of the usb buffers + char *writebuffer, *readbuffer; //the usb buffers + void *readtransfer, *writetransfer; + void *ctrltransfer; //ptr to HC internal transfer struct + char writing, reading; //flag if transfer is running + unsigned int readendp,writeendp,ctrlendp; //endpoints and + unsigned int readpipe,writepipe,ctrlpipe; //pipes (are one of these obsolete?) + unsigned ctrlinterval; //interval to poll from device }; -static struct acm_state static_acm_state; -spinlock_t usb_acm_lock = SPIN_LOCK_UNLOCKED; +//functions for various ACM requests + +void Set_Control_Line_Status (unsigned int status,struct acm_state *acm) +{ + devrequest dr; + + info("Set_control_Line_Status\n"); + + dr.requesttype = 0x22; + dr.request = 0x22; + dr.value = status; + dr.index = 0; + dr.length = 0; + acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0); + + acm->ctrlstate=status; +} + +void Set_Line_Coding (unsigned int coding,struct acm_state *acm) +{ + devrequest dr; + + info("Set_Line_Coding\n"); + + dr.requesttype = 0x22; + dr.request = 0x30; + dr.value = coding; + dr.index = 0; + dr.length = 0; + acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0); + + acm->linecoding=coding; +} -static int acm_irq(int state, void *__buffer, int len, void *dev_id) +//Interrupt handler for various usb events +static int acm_irq(int state, void *__buffer, int count, void *dev_id) { -// unsigned char *data = __buffer; - struct acm_state *acm = &static_acm_state; + + unsigned char *data; + struct acm_state *acm = (struct acm_state *) dev_id; devrequest *dr; + + info("ACM_USB_IRQ\n"); + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return 0; + } + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return 1; + } + dr=__buffer; - printk("ACM_USB_IRQ\n"); + data=__buffer; + data+=sizeof(dr); + +#if 1 printk("reqtype: %02X\n",dr->requesttype); printk("request: %02X\n",dr->request); printk("wValue: %02X\n",dr->value); printk("wIndex: %02X\n",dr->index); printk("wLength: %02X\n",dr->length); +#endif switch(dr->request) { //Network connection case 0x00: printk("Network connection: "); - if (dr->request==0) printk("disconnected\n"); - if (dr->request==1) printk("connected\n"); + if (dr->request==0) info("disconnected\n"); + if (dr->request==1) info("connected\n"); break; - + //Response available case 0x01: printk("Response available\n"); - acm->buffer=1; break; //Set serial line state case 0x20: + printk("Set serial control line state\n"); if ((dr->index==1)&&(dr->length==2)) { - acm->serstate=acm->ctrlbuffer; - printk("Serstate: %02X\n",acm->ctrlbuffer); + acm->ctrlstate=* ((unsigned short int *)data); + printk("Serstate: %02X\n",acm->ctrlstate); } break; } -/* - if(!acm->active) - return 1; -*/ + + //info("Done\n"); + //Continue transfer + return 1; +} + +static int acm_read_irq(int state, void *__buffer, int count, void *dev_id) +{ + struct acm_state *acm = (struct acm_state *) dev_id; + struct tty_struct *tty = acm->tty; + unsigned char* data=__buffer; + int i; + + info("ACM_READ_IRQ\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + //Stop transfer + return 0; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + //Stop transfer + return 0; + } + +// printk("%d %s\n",count,data); + for (i=0;itty; + + info("ACM_WRITE_IRQ\n"); -// fasync_acm(-1, file, 0); - if (--acm->active) + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + //Stop transfer return 0; + } + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + //Stop transfer + return 0; + } + + usb_terminate_bulk(acm->dev, acm->writetransfer); + acm->writing=0; + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + + //info("Done\n"); + //Stop transfer return 0; } -static int open_acm(struct inode * inode, struct file * file) +/*TTY STUFF*/ +static int rs_open(struct tty_struct *tty, struct file * filp) { - struct acm_state *acm = &static_acm_state; - printk("USB_FILE_OPEN\n"); + struct acm_state *acm; + + + info("USB_FILE_OPEN\n"); - if (!acm->present) + tty->driver_data=acm=&acm_state_table[MINOR(tty->device)-tty->driver.minor_start]; + acm->tty=tty; + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); return -EINVAL; - if (acm->active++) - return 0; + } + + if (acm->active) { + info ("ACM DEVICE ALREADY OPEN\n"); + return -EINVAL; + } + acm->active=1; + + /*Start reading from the device*/ + acm->ctrltransfer=usb_request_irq(acm->dev,acm->ctrlpipe, acm_irq, acm->ctrlinterval, acm); + + acm->reading=1; + acm->readtransfer=usb_request_bulk(acm->dev,acm->readpipe, acm_read_irq, acm->readbuffer, acm->readsize, acm ); + + Set_Control_Line_Status (CTRL_STAT_DTR | CTRL_STAT_RTS, acm); + return 0; } -static ssize_t write_acm(struct file * file, - const char * buffer, size_t count, loff_t *ppos) +static void rs_close(struct tty_struct *tty, struct file * filp) { - devrequest dr; - struct acm_state *acm = &static_acm_state; - unsigned long retval; - - printk("USB_FILE_WRITE\n"); -//Huh, i seem to got that wrong, we don't need this ?!? -/* - dr.requesttype = USB_TYPE_CLASS | USB_RT_ENDPOINT; - dr.request = 0; - dr.value = 0; - dr.index = acm->writeendp; - dr.length = count; - acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), &dr, NULL, 0); -*/ + struct acm_state *acm = (struct acm_state *) tty->driver_data; + info("rs_close\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return; + } - acm->dev->bus->op->bulk_msg(acm->dev,&acm->writepipe,buffer, count, &retval); - return -EINVAL; + Set_Control_Line_Status (0, acm); + + if (acm->writing){ + usb_terminate_bulk(acm->dev, acm->writetransfer); + acm->writing=0; + } + if (acm->reading){ + usb_terminate_bulk(acm->dev, acm->readtransfer); + acm->reading=0; + } +// usb_release_irq(acm->dev,acm->ctrltransfer); + + acm->active=0; } +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + struct acm_state *acm = (struct acm_state *) tty->driver_data; + int written; + + info("rs_write\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return -EINVAL; + } -static ssize_t read_acm(struct file * file, const char * buffer, size_t count, loff_t *ppos) + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return -EINVAL; + } + + if (acm->writing) { + info ("already writing\n"); + return 0; + } + + written=(count>acm->writesize) ? acm->writesize : count; + + if (from_user) { + //info("fromuser\n"); + copy_from_user(acm->writebuffer,buf,written); + } + else { + //info("notfromuser\n"); + memcpy(acm->writebuffer,buf,written); + } + + //start the transfer + acm->writing=1; + acm->writetransfer=usb_request_bulk(acm->dev,acm->writepipe, acm_write_irq, acm->writebuffer, written, acm); + + return written; +} + +static void rs_put_char(struct tty_struct *tty, unsigned char ch) { - devrequest dr; - struct acm_state *acm = &static_acm_state; - unsigned long retval; - printk("USB_FILE_READ\n"); -// if (!acm->buffer) return -1; - acm->buffer=0; -//We don't need this -/* - printk("writing control msg\n"); - dr.requesttype = USB_TYPE_CLASS | USB_RT_ENDPOINT | 0x80; - dr.request = 1; - dr.value = 0; - dr.index = acm->readendp; - dr.length = 0; - acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), &dr, NULL, 0); -*/ - printk("reading:>%s<\n",buffer); - acm->dev->bus->op->bulk_msg(acm->dev,&acm->readpipe,buffer, 1,&retval); - printk("done:>%s<\n",buffer); - return 1; + struct acm_state *acm = (struct acm_state *) tty->driver_data; + + info("rs_put_char\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return; + } +// printk("%c\n",ch); +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct acm_state *acm = (struct acm_state *) tty->driver_data; + + info("rs_write_room\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return -EINVAL; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return -EINVAL; + } + + if (acm->writing) { + return 0; + } + return acm->writesize; } -struct file_operations usb_acm_fops = { - NULL, /* acm_seek */ - read_acm, - write_acm, - NULL, /* acm_readdir */ - NULL, /* acm_poll */ - NULL, /* acm_ioctl */ - NULL, /* acm_mmap */ - open_acm, - NULL, /* flush */ - release_acm, - NULL, - NULL, /*fasync*/ -}; +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct acm_state *acm = (struct acm_state *) tty->driver_data; -static struct miscdevice usb_acm = { - USB_ACM_MINOR, "USB ACM", &usb_acm_fops -}; + info("rs_chars_in_buffer\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return -EINVAL; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return -EINVAL; + } + + if (acm->writing) { + return acm->writesize; + } + return 0; +} + +static void rs_throttle(struct tty_struct * tty) +{ + struct acm_state *acm = (struct acm_state *) tty->driver_data; + + info("rs_throttle\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return; + } + +/* + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); +*/ + + if (tty->termios->c_cflag & CRTSCTS) + Set_Control_Line_Status (acm->ctrlstate & ~CTRL_STAT_RTS, acm); +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct acm_state *acm = (struct acm_state *) tty->driver_data; + + info("rs_unthrottle\n"); + + if (!acm->present) { + info("NO ACM DEVICE REGISTERED\n"); + return; + } + + if (!acm->active) { + info ("ACM DEVICE NOT OPEN\n"); + return; + } + +/* + if (I_IXOFF(tty)) + rs_send_xchar(tty, STOP_CHAR(tty)); +*/ + + if (tty->termios->c_cflag & CRTSCTS) + Set_Control_Line_Status (acm->ctrlstate | CTRL_STAT_RTS, acm); +} + +static int get_free_acm() +{ + int i; + + for (i=0;i(acmno=get_free_acm())) { + info("Too many acm devices connected\n"); + return -1; + } + acm = &acm_state_table[acmno]; /* Only use CDC */ if (dev->descriptor.bDeviceClass != 2 || @@ -230,34 +536,74 @@ (endpoint->bmAttributes & 3) != 2) continue; - printk("USB ACM found\n"); - if (usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue)) { - printk (KERN_INFO " Failed usb_set_configuration: ACM\n"); - continue; - } + printk("USB ACM %d found\n",acmno); + usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue); + acm->dev=dev; + dev->private=acm; + acm->readendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].bEndpointAddress; - acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress; - acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress; acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp); + acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].wMaxPacketSize,GFP_KERNEL); + acm->reading=0; + if (!acm->readbuffer) { + printk("ACM: Couldn't allocate readbuffer\n"); + return -1; + } + + acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress; acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp); - usb_request_irq(dev,acm->ctrlpipe=usb_rcvctrlpipe(dev,acm->ctrlendp), acm_irq, dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval, &acm->ctrlbuffer); - acm->present = 1; - acm->buffer=0; + acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].wMaxPacketSize, GFP_KERNEL); + acm->writing=0; + if (!acm->writebuffer) { + printk("ACM: Couldn't allocate writebuffer\n"); + kfree(acm->readbuffer); + return -1; + } + + acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress; + acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp); + acm->ctrlinterval=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval; + + acm->present=1; + MOD_INC_USE_COUNT; return 0; } - return -1; } static void acm_disconnect(struct usb_device *dev) { - struct acm_state *acm = &static_acm_state; + struct acm_state *acm = (struct acm_state *) dev->private; - /* this might need work */ - acm->present = 0; + info("acm_disconnect\n"); + + if (!acm->present) { + printk("device not present\n"); + return; + } + + printk("disconnecting\n"); + + if (acm->writing){ + usb_terminate_bulk(acm->dev, acm->writetransfer); + acm->writing=0; + } + if (acm->reading){ + usb_terminate_bulk(acm->dev, acm->readtransfer); + acm->reading=0; + } +// usb_release_irq(acm->dev,acm->ctrltransfer); + //BUG: What to do if a device is open?? Notify process or not allow cleanup? + acm->active=0; + acm->present=0; + kfree(acm->writebuffer); + kfree(acm->readbuffer); + + MOD_DEC_USE_COUNT; } +/*USB DRIVER STUFF*/ static struct usb_driver acm_driver = { "acm", acm_probe, @@ -267,19 +613,83 @@ int usb_acm_init(void) { - struct acm_state *acm = &static_acm_state; - - misc_register(&usb_acm); - - acm->present = acm->active = 0; + int cnt; + + info("usb_acm_init\n"); + + //INITIALIZE GLOBAL DATA STRUCTURES + for (cnt=0;cntpresent) { + printk("disconnecting %d\n",i); + acm_disconnect(acm->dev); + } + } + tty_unregister_driver(&acm_tty_driver); + + usb_deregister(&acm_driver); + +} + +#ifdef MODULE int init_module(void) { return usb_acm_init(); @@ -287,9 +697,6 @@ void cleanup_module(void) { - /* this, too, probably needs work */ - usb_deregister(&acm_driver); - misc_deregister(&usb_acm); + usb_acm_cleanup(); } - -#endif +#endif \ No newline at end of file diff -u --recursive --new-file v2.3.12/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.12/linux/drivers/usb/audio.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/audio.c Sat Aug 7 13:01:44 1999 @@ -11,24 +11,25 @@ static void usb_audio_disconnect(struct usb_device *dev); static LIST_HEAD(usb_audio_list); -struct usb_audio -{ +struct usb_audio { struct usb_device *dev; struct list_head list; }; -static struct usb_driver usb_audio_driver = -{ +static struct usb_driver usb_audio_driver = { "audio", usb_audio_probe, usb_audio_disconnect, - {NULL, NULL} + { NULL, NULL } }; static int usb_audio_irq(int state, void *buffer, int len, void *dev_id) { - struct usb_audio *aud = (struct usb_audio*) dev_id; + struct usb_audio *aud = (struct usb_audio *)dev_id; + + printk("irq on %p\n", aud); + return 1; } @@ -37,16 +38,12 @@ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_audio *aud; - int i; int na=0; interface = &dev->config[0].altsetting[0].interface[0]; - for(i=0;iconfig[0].bNumInterfaces;i++) - { - int x; - + for (i=0; iconfig[0].bNumInterfaces; i++) { endpoint = &interface->endpoint[i]; if(interface->bInterfaceClass != 1) @@ -54,8 +51,7 @@ printk(KERN_INFO "USB audio device detected.\n"); - switch(interface->bInterfaceSubClass) - { + switch(interface->bInterfaceSubClass) { case 0x01: printk(KERN_INFO "audio: Control device.\n"); break; @@ -69,12 +65,11 @@ na++; } - if(na==0) + if (!na) return -1; aud = kmalloc(sizeof(struct usb_audio), GFP_KERNEL); - if(aud) - { + if (aud) { memset(aud, 0, sizeof(*aud)); aud->dev = dev; dev->private = aud; @@ -107,8 +102,8 @@ static void usb_audio_disconnect(struct usb_device *dev) { struct usb_audio *aud = (struct usb_audio*) dev->private; - if(aud) - { + + if (aud) { dev->private = NULL; list_del(&aud->list); kfree(aud); @@ -146,3 +141,4 @@ } #endif + diff -u --recursive --new-file v2.3.12/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c --- v2.3.12/linux/drivers/usb/cpia.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/cpia.c Fri Jul 30 12:31:45 1999 @@ -25,6 +25,8 @@ #include "usb.h" #include "cpia.h" +#define CPIA_DEBUG /* Gobs of debugging info */ + #define MAX_FRAME_SIZE (384 * 288 * 3) /*******************************/ @@ -319,11 +321,13 @@ return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); } +/* How much data is left in the scratch buf? */ #define scratch_left(x) (cpia->scratchlen - (int)((char *)x - (char *)cpia->scratch)) static void cpia_parse_data(struct usb_cpia *cpia) { unsigned char *data = cpia->scratch; + unsigned long l; int done; done = 0; @@ -339,6 +343,7 @@ break; } + /* 0x1968 is magic */ printk("header: %X\n", (*data << 8) + *(data + 1)); if ((*data == 0x19) && (*(data + 1) == 0x68)) { cpia->state = STATE_HEADER; @@ -346,6 +351,7 @@ break; } + /* Woops, lost the header, find the end of the frame */ if (scratch_left(data) < 4) { done = 1; break; @@ -362,7 +368,9 @@ } data++; } -printk("scan: scanned %d bytes\n", data-begin); +#ifdef CPIA_DEBUG + printk("scan: scanned %d bytes\n", data-begin); +#endif break; } case STATE_HEADER: @@ -372,7 +380,9 @@ break; } -printk("header: framerate %d\n", data[41]); +#ifdef CPIA_DEBUG + printk("header: framerate %d\n", data[41]); +#endif data += 64; @@ -390,11 +400,11 @@ found = 1; break; } else if ((*data == 0xFF) && - (scratch_left(data) >= 3) && - (*(data + 1) == 0xFF) && - (*(data + 2) == 0xFF) && - (*(data + 3) == 0xFF)) { - data+=4; + (scratch_left(data) >= 3) && + (*(data + 1) == 0xFF) && + (*(data + 2) == 0xFF) && + (*(data + 3) == 0xFF)) { + data += 4; cpia->curline = 144; found = 1; break; @@ -402,25 +412,21 @@ data++; } -#if 0 -printk("line %d: scanned %d bytes\n", cpia->curline, data-begin); -#endif -if (data-begin == 355 && cpia->frame[cpia->curframe].width != 64) { - int i; - char *f = cpia->frame[cpia->curframe].data, *b = begin; -#if 0 -printk("copying\n"); -#endif + if (data-begin == 355 && cpia->frame[cpia->curframe].width != 64) { + int i; + char *f = cpia->frame[cpia->curframe].data, *b = begin; + + b += 2; + f += (cpia->frame[cpia->curframe].width * 3) * cpia->curline; + + for (i = 0; i < 176; i++) + f[(i * 3) + 0] = + f[(i * 3) + 1] = + f[(i * 3) + 2] = + b[(i * 2)]; + } - b+=2; - f+=(cpia->frame[cpia->curframe].width*3)*cpia->curline; - for (i = 0; i < 176; i++) - f[(i * 3) + 0] = - f[(i * 3) + 1] = - f[(i * 3) + 2] = - b[(i * 2)]; -} if (found) { cpia->curline++; if (cpia->curline >= 144) { @@ -440,13 +446,11 @@ } } - { - int l; - + /* Grab the remaining */ l = scratch_left(data); memmove(cpia->scratch, data, l); + cpia->scratchlen = l; - } } static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id) @@ -466,13 +470,21 @@ if (cpia->frame[0].state == FRAME_READY) { cpia->curframe = 0; cpia->frame[0].state = FRAME_GRABBING; -printk("capturing to frame 0\n"); +#ifdef CPIA_DEBUG + printk("capturing to frame 0\n"); +#endif } else if (cpia->frame[1].state == FRAME_READY) { cpia->curframe = 1; cpia->frame[1].state = FRAME_GRABBING; -printk("capturing to frame 1\n"); +#ifdef CPIA_DEBUG + printk("capturing to frame 1\n"); +#endif +#ifdef CPIA_DEBUG } else -printk("no frame available\n"); + printk("no frame available\n"); +#else + } +#endif } sbuf = &cpia->sbuf[cpia->receivesbuf]; @@ -482,8 +494,10 @@ /* Do something to it now */ sbuf->len = usb_compress_isochronous(dev, sbuf->isodesc); +#ifdef CPIA_DEBUG if (sbuf->len) - printk("%d bytes received\n", sbuf->len); + printk("%d bytes received\n", sbuf->len); +#endif if (sbuf->len && cpia->curframe >= 0) { if (sbuf->len > (SCRATCH_BUF_SIZE - cpia->scratchlen)) { @@ -511,10 +525,6 @@ cpia->receivesbuf = 0; -#if 0 - cpia->parsesbuf = 0; - cpia->parsepos = 0; -#endif cpia->scratchlen = 0; cpia->curline = 0; cpia->state = STATE_SCANNING; @@ -524,15 +534,20 @@ cpia->sbuf[1].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); cpia->sbuf[2].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia); +#ifdef CPIA_DEBUG printk("isodesc[0] @ %p\n", cpia->sbuf[0].isodesc); printk("isodesc[1] @ %p\n", cpia->sbuf[1].isodesc); printk("isodesc[2] @ %p\n", cpia->sbuf[2].isodesc); +#endif /* Schedule the queues */ usb_schedule_isochronous(dev, cpia->sbuf[0].isodesc, NULL); usb_schedule_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc); usb_schedule_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc); +#ifdef CPIA_DEBUG + printk("done scheduling\n"); +#endif if (usb_set_interface(cpia->dev, 1, 3)) { printk("cpia_set_interface error\n"); return -EINVAL; @@ -541,6 +556,9 @@ usb_cpia_startstreamcap(cpia->dev); cpia->streaming = 1; +#ifdef CPIA_DEBUG + printk("now streaming\n"); +#endif return 0; } @@ -579,7 +597,9 @@ { struct usb_cpia *cpia = (struct usb_cpia *)dev; -printk("cpia_open\n"); +#ifdef CPIA_DEBUG + printk("cpia_open\n"); +#endif cpia->fbuf = rvmalloc(2 * MAX_FRAME_SIZE); if (!cpia->fbuf) @@ -590,8 +610,10 @@ cpia->frame[0].data = cpia->fbuf; cpia->frame[1].data = cpia->fbuf + MAX_FRAME_SIZE; +#ifdef CPIA_DEBUG printk("frame [0] @ %p\n", cpia->frame[0].data); printk("frame [1] @ %p\n", cpia->frame[1].data); +#endif cpia->sbuf[0].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL); if (!cpia->sbuf[0].data) @@ -605,9 +627,11 @@ if (!cpia->sbuf[2].data) goto open_err_on2; +#ifdef CPIA_DEBUG printk("sbuf[0] @ %p\n", cpia->sbuf[0].data); printk("sbuf[1] @ %p\n", cpia->sbuf[1].data); printk("sbuf[2] @ %p\n", cpia->sbuf[2].data); +#endif cpia->curframe = -1; cpia->receivesbuf = 0; @@ -632,7 +656,9 @@ { struct usb_cpia *cpia = (struct usb_cpia *)dev; -printk("cpia_close\n"); +#ifdef CPIA_DEBUG + printk("cpia_close\n"); +#endif cpia_stop_isoc(cpia); @@ -655,90 +681,6 @@ return -EINVAL; } -#if 0 - if (usb_set_interface(dev, 1, 3)) { - printk("cpia_set_interface error\n"); - return -EINVAL; - } - - if (usb_cpia_grab_frame(dev, 0)) { - printk("cpia_grab_frame error\n"); - return -EINVAL; - } - - if (usb_cpia_upload_frame(dev, 0)) { - printk("cpia_upload_frame error\n"); - return -EINVAL; - } - - buf = cpia->ibuf; - uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), buf, 176*144*4); - - { - printk("header magic: %X\n", (buf[0] << 8) + buf[1]); - - while ((buf[0] != 0x19) || (buf[1] != 0x68)) { - int i; - - printk("resync'ing\n"); - for (i=0;i<(176*144*4)-4;i++, buf++) - if ( - (buf[0] == 0xFF) && - (buf[1] == 0xFF) && - (buf[2] == 0xFF) && - (buf[3] == 0xFF)) { - buf+=4; - i+=4; - break; - } - - memmove(cpia->ibuf, buf, (176*144*4) - i); - uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->ibuf + (176*144*4) - i, i); - buf = cpia->ibuf; - -#if 0 - printk("header magic: %X\n", (buf[0] << 8) + buf[1]); -#endif - } - - printk("size: %d, sample: %d, order: %d\n", buf[16], buf[17], buf[18]); - printk("comp: %d, decimation: %d\n", buf[28], buf[29]); - printk("roi: top left: %d, %d bottom right: %d, %d\n", - buf[26] * 4, buf[24] * 8, - buf[27] * 4, buf[25] * 8); - - printk("vm->frame: %d\n", vm->frame); - - { - int i, i1; - char *b = buf + 64, *fbuf = &cpia->fbuffer[MAX_FRAME_SIZE * (vm->frame & 1)]; - for (i=0;i<144;i++) { -#if 0 - printk("line len: %d\n", (b[1] << 8) + b[0]); -#endif - b += 2; - for (i1=0;i1<176;i1++) { - fbuf[(i * vm->width * 3) + (i1 * 3)] = - fbuf[(i * vm->width * 3) + (i1 * 3) + 1] = - fbuf[(i * vm->width * 3) + (i1 * 3) + 2] = - b[i1 * 2]; -#if 0 - *((short *)&fbuf[(i * vm->width * 2) + (i1 * 2)]) = - ((b[i1 * 2] >> 3) << 11) + ((b[i1 * 2] >> 2) << 6) + (b[i1 * 2] >> 3); -#endif - } - b += (176 * 2) + 1; - } - } - - } - - if (usb_set_interface(dev, 1, 0)) { - printk("cpia_set_interface error\n"); - return -EINVAL; - } -#endif - static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct usb_cpia *cpia = (struct usb_cpia *)dev; @@ -752,10 +694,10 @@ b.type = VID_TYPE_CAPTURE /* | VID_TYPE_SUBCAPTURE */; b.channels = 1; b.audios = 0; - b.maxwidth = 176 /* 352 */; - b.maxheight = 144 /* 240 */; - b.minwidth = 176 /* (Something small?) */; - b.minheight = 144 /* " " */; + b.maxwidth = 176 /* 352 */; + b.maxheight = 144 /* 240 */; + b.minwidth = 176 /* (Something small?) */; + b.minheight = 144 /* " " */; if (copy_to_user(arg, &b, sizeof(b))) return -EFAULT; @@ -855,13 +797,9 @@ if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; -printk("Attempting to set palette %d, depth %d\n", p.palette, p.depth); - -#if 0 - if (p.palette != VIDEO_PALETTE_YUYV) - return -EINVAL; - if (p.depth != 16) - return -EINVAL; +#ifdef CPIA_DEBUG + printk("Attempting to set palette %d, depth %d\n", + p.palette, p.depth); #endif return 0; @@ -870,7 +808,10 @@ { struct video_window vw; -printk("VIDIOCSWIN\n"); +#ifdef CPIA_DEBUG + printk("VIDIOCSWIN\n"); +#endif + if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; if (vw.flags) @@ -888,7 +829,10 @@ { struct video_window vw; -printk("VIDIOCGWIN\n"); +#ifdef CPIA_DEBUG + printk("VIDIOCGWIN\n"); +#endif + vw.x = 0; vw.y = 0; vw.width = 176; @@ -923,8 +867,11 @@ if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; -printk("MCAPTURE\n"); -printk("frame: %d, size: %dx%d, format: %d\n", vm.frame, vm.width, vm.height, vm.format); +#ifdef CPIA_DEBUG + printk("MCAPTURE\n"); + printk("frame: %d, size: %dx%d, format: %d\n", + vm.frame, vm.width, vm.height, vm.format); +#endif if (vm.format != VIDEO_PALETTE_RGB24) return -EINVAL; @@ -947,7 +894,9 @@ if (copy_from_user((void *)&frame, arg, sizeof(int))) return -EFAULT; +#ifdef CPIA_DEBUG printk("syncing to frame %d\n", frame); +#endif switch (cpia->frame[frame].state) { case FRAME_UNUSED: return -EINVAL; @@ -958,7 +907,9 @@ cpia->frame[frame].state = FRAME_UNUSED; break; } +#ifdef CPIA_DEBUG printk("synced to frame %d\n", frame); +#endif return 0; } case VIDIOCCAPTURE: @@ -988,7 +939,9 @@ struct usb_cpia *cpia = (struct usb_cpia *)dev; int len; +#ifdef CPIA_DEBUG printk("cpia_read: %ld bytes\n", count); +#endif #if 0 len = cpia_capture(cpia, buf, count); @@ -1003,17 +956,12 @@ unsigned long start = (unsigned long)adr; unsigned long page, pos; +#ifdef CPIA_DEBUG printk("mmap: %ld (%lX) bytes\n", size, size); +#endif if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; -#if 0 - if (!cpia->fbuffer) { - if ((cpia->fbuffer = rvmalloc(2 * MAX_FRAME_SIZE)) == NULL) - return -EINVAL; - } -#endif - pos = (unsigned long)cpia->fbuf; while (size > 0) { @@ -1123,39 +1071,6 @@ printk("cpia_set_compression error\n"); return; } - -#if 0 - if (usb_cpia_grab_frame(dev, 0)) { - printk("cpia_grab_frame error\n"); - return; - } - - if (usb_cpia_upload_frame(dev, 1)) { - printk("cpia_upload_frame error\n"); - return; - } - - buf = (void *)__get_free_page(GFP_KERNEL); - - { - int i; - for (i=0;i<448;i++) - buf[i]=0; - } - uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), buf, 448); - - { - int i; - for (i=0;i<448;i++) { - printk("%02X ", buf[i]); - if ((i % 16) == 15) - printk("\n"); - } - printk("\n"); - } - - free_page((unsigned long)buf); -#endif } static int cpia_probe(struct usb_device *dev) @@ -1168,29 +1083,9 @@ if (dev->descriptor.bNumConfigurations != 1) return -1; -#if 0 - /* We don't handle multi-interface hubs */ - if (dev->config[0].bNumInterfaces != 1) - return -1; -#endif - interface = &dev->config[0].altsetting[0].interface[0]; /* Is it a CPiA? */ -/* -Apr 24 17:49:04 bjorn kernel: Vendor: 0545 -Apr 24 17:49:04 bjorn kernel: Product: 8080 -*/ -/* - if (dev->descriptor.idVendor != 0x0545) - return -1; - if (dev->descriptor.idProduct != 0x8080) - return -1; - if (interface->bInterfaceClass != 0xFF) - return -1; - if (interface->bInterfaceSubClass != 0xFF) - return -1; -*/ if (dev->descriptor.idVendor != 0x0553) return -1; if (dev->descriptor.idProduct != 0x0002) @@ -1200,22 +1095,6 @@ if (interface->bInterfaceSubClass != 0x00) return -1; -#if 0 - /* Multiple endpoints? What kind of mutant ninja-hub is this? */ - if (interface->bNumEndpoints != 1) - return -1; - - endpoint = &interface->endpoint[0]; - - /* Output endpoint? Curiousier and curiousier.. */ - if (!(endpoint->bEndpointAddress & 0x80)) - return -1; - - /* If it's not an interrupt endpoint, we'd better punt! */ - if ((endpoint->bmAttributes & 3) != 3) - return -1; -#endif - /* We found a CPiA */ printk("USB CPiA camera found\n"); @@ -1231,10 +1110,6 @@ usb_cpia_configure(cpia); -#if 0 - usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), pport_irq, endpoint->bInterval, pport); -#endif - return 0; } @@ -1270,6 +1145,7 @@ { return usb_cpia_init(); } + void cleanup_module(void) { } diff -u --recursive --new-file v2.3.12/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.12/linux/drivers/usb/hub.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/hub.c Sat Aug 7 13:01:44 1999 @@ -14,23 +14,91 @@ #include #include +#include #include "usb.h" #include "hub.h" /* Wakes up khubd */ -static DECLARE_WAIT_QUEUE_HEAD(usb_hub_wait); static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED; -/* List of hubs needing servicing */ -static struct list_head hub_event_list; +static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ +static LIST_HEAD(hub_list); /* List containing all of the hubs (for cleanup) */ -/* List containing all of the hubs (for cleanup) */ -static struct list_head all_hubs_list; +static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); +static int khubd_pid = 0; /* PID of khubd */ +static int khubd_running = 0; -/* PID of khubd */ -static int khubd_pid = 0; +static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) +{ + devrequest dr; + + dr.requesttype = USB_DIR_IN | USB_RT_HUB; + dr.request = USB_REQ_GET_DESCRIPTOR; + dr.value = (USB_DT_HUB << 8); + dr.index = 0; + dr.length = size; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, + data, size); +} + +static int usb_clear_port_feature(struct usb_device *dev, int port, int feature) +{ + devrequest dr; + + dr.requesttype = USB_RT_PORT; + dr.request = USB_REQ_CLEAR_FEATURE; + dr.value = feature; + dr.index = port; + dr.length = 0; + + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, + NULL, 0); +} + +static int usb_set_port_feature(struct usb_device *dev, int port, int feature) +{ + devrequest dr; + + dr.requesttype = USB_RT_PORT; + dr.request = USB_REQ_SET_FEATURE; + dr.value = feature; + dr.index = port; + dr.length = 0; + + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, + NULL, 0); +} + +static int usb_get_hub_status(struct usb_device *dev, void *data) +{ + devrequest dr; + + dr.requesttype = USB_DIR_IN | USB_RT_HUB; + dr.request = USB_REQ_GET_STATUS; + dr.value = 0; + dr.index = 0; + dr.length = 4; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, + data, 4); +} + +static int usb_get_port_status(struct usb_device *dev, int port, void *data) +{ + devrequest dr; + + dr.requesttype = USB_DIR_IN | USB_RT_PORT; + dr.request = USB_REQ_GET_STATUS; + dr.value = 0; + dr.index = port; + dr.length = 4; + + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, + data, 4); +} /* * A irq handler returns non-zero to indicate to @@ -42,13 +110,13 @@ struct usb_hub *hub = dev_id; unsigned long flags; - if (waitqueue_active(&usb_hub_wait)) { + if (waitqueue_active(&khubd_wait)) { /* Add the hub to the event queue */ spin_lock_irqsave(&hub_event_lock, flags); if (hub->event_list.next == &hub->event_list) { list_add(&hub->event_list, &hub_event_list); /* Wake up khubd */ - wake_up(&usb_hub_wait); + wake_up(&khubd_wait); } spin_unlock_irqrestore(&hub_event_lock, flags); } @@ -68,83 +136,63 @@ return; hub->nports = dev->maxchild = hubdescriptor[2]; - printk("hub: %d-port%s detected\n", hub->nports, + printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports, (hub->nports == 1) ? "" : "s"); charac = (hubdescriptor[4] << 8) + hubdescriptor[3]; switch (charac & HUB_CHAR_LPSM) { case 0x00: - printk("hub: ganged power switching\n"); + printk(KERN_INFO "hub: ganged power switching\n"); break; case 0x01: - printk("hub: individual port power switching\n"); + printk(KERN_INFO "hub: individual port power switching\n"); break; case 0x02: case 0x03: - printk("hub: unknown reserved power switching mode\n"); + printk(KERN_INFO "hub: unknown reserved power switching mode\n"); break; } if (charac & HUB_CHAR_COMPOUND) - printk("hub: part of a compound device\n"); + printk(KERN_INFO "hub: part of a compound device\n"); else - printk("hub: standalone hub\n"); + printk(KERN_INFO "hub: standalone hub\n"); switch (charac & HUB_CHAR_OCPM) { case 0x00: - printk("hub: global over current protection\n"); + printk(KERN_INFO "hub: global over current protection\n"); break; case 0x08: - printk("hub: individual port over current protection\n"); + printk(KERN_INFO "hub: individual port over current protection\n"); break; case 0x10: case 0x18: - printk("hub: no over current protection\n"); + printk(KERN_INFO "hub: no over current protection\n"); break; } - printk("hub: power on to power good time: %dms\n", + printk(KERN_INFO "hub: power on to power good time: %dms\n", hubdescriptor[5] * 2); - printk("hub: hub controller current requirement: %dmA\n", + printk(KERN_INFO "hub: hub controller current requirement: %dmA\n", hubdescriptor[6]); for (i = 0; i < dev->maxchild; i++) - printk("hub: port %d is%s removable\n", i + 1, + printk(KERN_INFO "hub: port %d is%s removable\n", i + 1, hubdescriptor[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8)) ? " not" : ""); if (usb_get_hub_status(dev, buf)) return; - printk("hub: local power source is %s\n", + printk(KERN_INFO "hub: local power source is %s\n", (buf[0] & 1) ? "lost (inactive)" : "good"); - printk("hub: %sover current condition exists\n", + printk(KERN_INFO "hub: %sover current condition exists\n", (buf[0] & 2) ? "" : "no "); -#if 0 - for (i = 0; i < hub->nports; i++) { - int portstat, portchange; - unsigned char portstatus[4]; - - if (usb_get_port_status(dev, i + 1, portstatus)) - return; - portstat = (portstatus[1] << 8) + portstatus[0]; - portchange = (portstatus[3] << 8) + portstatus[2]; - - printk("hub: port %d status\n", i + 1); - printk("hub: %sdevice present\n", (portstat & 1) ? "" : "no "); - printk("hub: %s\n", (portstat & 2) ? "enabled" : "disabled"); - printk("hub: %ssuspended\n", (portstat & 4) ? "" : "not "); - printk("hub: %sover current\n", (portstat & 8) ? "" : "not "); - printk("hub: has %spower\n", (portstat & 0x100) ? "" : "no "); - printk("hub: %s speed\n", (portstat & 0x200) ? "low" : "full"); - } -#endif - /* Enable power to the ports */ - printk("enabling power on all ports\n"); + printk(KERN_INFO "hub: enabling power on all ports\n"); for (i = 0; i < hub->nports; i++) usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); } @@ -180,7 +228,7 @@ endpoint = &interface->endpoint[0]; /* Output endpoint? Curiousier and curiousier.. */ - if (!(endpoint->bEndpointAddress & 0x80)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) return -1; /* If it's not an interrupt endpoint, we'd better punt! */ @@ -188,10 +236,10 @@ return -1; /* We found a hub */ - printk("USB hub found\n"); + printk(KERN_INFO "USB hub found\n"); if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) { - printk("couldn't kmalloc hub struct\n"); + printk(KERN_ERR "couldn't kmalloc hub struct\n"); return -1; } @@ -205,15 +253,16 @@ /* Record the new hub's existence */ spin_lock_irqsave(&hub_list_lock, flags); INIT_LIST_HEAD(&hub->hub_list); - list_add(&hub->hub_list, &all_hubs_list); + list_add(&hub->hub_list, &hub_list); spin_unlock_irqrestore(&hub_list_lock, flags); usb_hub_configure(hub); - hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub); + hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev, + endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub); /* Wake up khubd */ - wake_up(&usb_hub_wait); + wake_up(&khubd_wait); return 0; } @@ -246,40 +295,51 @@ unsigned char buf[4]; unsigned short portstatus, portchange; + /* Disconnect anything that may have been there */ usb_disconnect(&hub->children[port]); + /* Reset the port */ usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); wait_ms(50); /* FIXME: This is from the *BSD stack, thanks! :) */ + /* Check status */ if (usb_get_port_status(hub, port + 1, buf)) { - printk("get_port_status failed\n"); + printk(KERN_ERR "get_port_status failed\n"); return; } portstatus = le16_to_cpup((unsigned short *)buf + 0); portchange = le16_to_cpup((unsigned short *)buf + 1); + /* If it's not in CONNECT and ENABLE state, we're done */ if ((!(portstatus & USB_PORT_STAT_CONNECTION)) && - (!(portstatus & USB_PORT_STAT_ENABLE))) { + (!(portstatus & USB_PORT_STAT_ENABLE))) /* We're done now, we already disconnected the device */ - /* printk("not connected/enabled\n"); */ return; - } + /* Allocate a new device struct for it */ usb = hub->bus->op->allocate(hub); if (!usb) { - printk("couldn't allocate usb_device\n"); + printk(KERN_ERR "couldn't allocate usb_device\n"); return; } - usb_connect(usb); - usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0; hub->children[port] = usb; - usb_new_device(usb); + /* Find a new device ID for it */ + usb_connect(usb); + + /* Run it through the hoops (find a driver, etc) */ + if (usb_new_device(usb)) { + /* Woops, disable the port */ + printk(KERN_DEBUG "hub: disabling malfunctioning port %d\n", + port + 1); + usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); + usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_POWER); + } } static void usb_hub_events(void) @@ -306,7 +366,7 @@ for (i = 0; i < hub->nports; i++) { if (usb_get_port_status(dev, i + 1, buf)) { - printk("get_port_status failed\n"); + printk(KERN_ERR "get_port_status failed\n"); continue; } @@ -314,7 +374,8 @@ portchange = le16_to_cpup((unsigned short *)buf + 1); if (portchange & USB_PORT_STAT_C_CONNECTION) { - printk("hub: port %d connection change\n", i + 1); + printk(KERN_INFO "hub: port %d connection change\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_CONNECTION); @@ -323,46 +384,29 @@ } if (portchange & USB_PORT_STAT_C_ENABLE) { - printk("hub: port %d enable change\n", i + 1); + printk(KERN_INFO "hub: port %d enable change\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); } if (portchange & USB_PORT_STAT_C_SUSPEND) - printk("hub: port %d suspend change\n", i + 1); + printk(KERN_INFO "hub: port %d suspend change\n", + i + 1); if (portchange & USB_PORT_STAT_C_OVERCURRENT) - printk("hub: port %d over-current change\n", i + 1); + printk(KERN_INFO "hub: port %d over-current change\n", + i + 1); if (portchange & USB_PORT_STAT_C_RESET) { - printk("hub: port %d reset change\n", i + 1); + printk(KERN_INFO "hub: port %d reset change\n", + i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } -#if 0 - if (!portchange) - continue; - - if (usb_get_port_status(dev, i + 1, buf)) - return; - - portstatus = (buf[1] << 8) + buf[0]; - portchange = (buf[3] << 8) + buf[2]; - - printk("hub: port %d status\n", i + 1); - printk("hub: %sdevice present\n", (portstatus & 1) ? "" : "no "); - printk("hub: %s\n", (portstatus & 2) ? "enabled" : "disabled"); - printk("hub: %ssuspended\n", (portstatus & 4) ? "" : "not "); - printk("hub: %sover current\n", (portstatus & 8) ? "" : "not "); - printk("hub: has %spower\n", (portstatus & 0x100) ? "" : "no "); - printk("hub: %s speed\n", (portstatus & 0x200) ? "low" : "full"); -#endif } tmp = next; -#if 0 - wait_ms(1000); -#endif } spin_unlock_irqrestore(&hub_event_lock, flags); @@ -370,9 +414,11 @@ static int usb_hub_thread(void *__hub) { +/* MOD_INC_USE_COUNT; +*/ - printk(KERN_INFO "USB hub driver registered\n"); + khubd_running = 1; lock_kernel(); @@ -389,13 +435,16 @@ /* Send me a signal to get me die (for debugging) */ do { - interruptible_sleep_on(&usb_hub_wait); usb_hub_events(); + interruptible_sleep_on(&khubd_wait); } while (!signal_pending(current)); +/* MOD_DEC_USE_COUNT; +*/ printk("usb_hub_thread exiting\n"); + khubd_running = 0; return 0; } @@ -414,24 +463,44 @@ { int pid; - INIT_LIST_HEAD(&hub_event_list); - INIT_LIST_HEAD(&all_hubs_list); - usb_register(&hub_driver); - pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + printk(KERN_INFO "USB hub driver registered\n"); + + pid = kernel_thread(usb_hub_thread, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); if (pid >= 0) { khubd_pid = pid; + return 0; } /* Fall through if kernel_thread failed */ usb_deregister(&hub_driver); - return 0; + return 1; } void usb_hub_cleanup(void) { + struct list_head *next, *tmp, *head = &hub_list; + struct usb_hub *hub; + unsigned long flags, flags2; + int ret; + + /* Kill the thread */ + ret = kill_proc(khubd_pid, SIGTERM, 1); + if (!ret) { + int count = 10; + + while (khubd_running && --count) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + if (!count) + printk(KERN_ERR "hub: giving up on killing khubd\n"); + } + /* * Hub resources are freed for us by usb_deregister. It * usb_driver_purge on every device which in turn calls that @@ -443,11 +512,14 @@ } /* usb_hub_cleanup() */ #ifdef MODULE -int init_module(void){ +int init_module(void) +{ return usb_hub_init(); } -void cleanup_module(void){ +void cleanup_module(void) +{ usb_hub_cleanup(); } #endif + diff -u --recursive --new-file v2.3.12/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c --- v2.3.12/linux/drivers/usb/ohci-hcd.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/ohci-hcd.c Thu Aug 5 15:11:52 1999 @@ -1449,14 +1449,14 @@ static int start_ohci(struct pci_dev *dev) { - unsigned int mem_base = dev->base_address[0]; + unsigned int mem_base = dev->resource[0].flags; /* If its OHCI, its memory */ if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) return -ENODEV; /* Get the memory address and map it for IO */ - mem_base &= PCI_BASE_ADDRESS_MEM_MASK; + mem_base = dev->resource[0].start; /* * FIXME ioremap_nocache isn't implemented on all CPUs (such diff -u --recursive --new-file v2.3.12/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c --- v2.3.12/linux/drivers/usb/ohci.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/ohci.c Mon Aug 9 11:27:39 1999 @@ -2607,14 +2607,14 @@ */ static int init_ohci(struct pci_dev *dev) { - unsigned long mem_base = dev->base_address[0]; + unsigned long mem_base = dev->resource[0].flags; /* If its OHCI, its memory */ if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) return -ENODEV; /* Get the memory address and map it for IO */ - mem_base &= PCI_BASE_ADDRESS_MEM_MASK; + mem_base = dev->resource[0].start; /* no interrupt won't work... */ if (dev->irq == 0) { diff -u --recursive --new-file v2.3.12/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.12/linux/drivers/usb/printer.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/printer.c Mon Aug 2 14:31:40 1999 @@ -241,7 +241,7 @@ return -EIO; if (this_read) { - if (copy_to_user(buffer, p->obuf, this_read)) + if (copy_to_user(buffer, buf, this_read)) return -EFAULT; count -= this_read; read_count += this_read; diff -u --recursive --new-file v2.3.12/linux/drivers/usb/uhci-debug.c linux/drivers/usb/uhci-debug.c --- v2.3.12/linux/drivers/usb/uhci-debug.c Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/uhci-debug.c Sat Aug 7 13:01:44 1999 @@ -115,12 +115,12 @@ #define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x)) -struct uhci_td * uhci_link_to_td(unsigned int link) +struct uhci_td *uhci_link_to_td(unsigned int link) { - if (link & 1) + if (link & UHCI_PTR_TERM) return NULL; - return bus_to_virt(link & ~15); + return bus_to_virt(link & ~UHCI_PTR_BITS); } void show_queue(struct uhci_qh *qh) @@ -128,18 +128,24 @@ struct uhci_td *td; int i = 0; -#if 0 - printk(" link = %p, element = %p\n", qh->link, qh->element); -#endif - if(!(qh->element & ~0xF)) { - printk(" td 0 = NULL\n"); + if (qh->element & UHCI_PTR_QH) + printk(" Element points to QH?\n"); + + if (qh->element & UHCI_PTR_DEPTH) + printk(" Depth traverse\n"); + + if (qh->element & UHCI_PTR_TERM) + printk(" Terminate\n"); + + if (!(qh->element & ~UHCI_PTR_BITS)) { + printk(" td 0 = NULL\n"); return; } for(td = uhci_link_to_td(qh->element); td; td = uhci_link_to_td(td->link)) { - printk(" td %d = %p\n", i++, td); - printk(" "); + printk(" td %d = %p\n", i++, td); + printk(" "); show_td(td); } } @@ -147,39 +153,39 @@ int is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh) { int j; - struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub); - for (j = 0; j < UHCI_MAXQH; j++) - if (qh == root_hub->qh + j) + + for (j = 0; j < UHCI_NUM_SKELQH; j++) + if (qh == uhci->skelqh + j) return 1; return 0; } -static const char *qh_names[] = {"isochronous", "interrupt2", "interrupt4", - "interrupt8", "interrupt16", "interrupt32", - "interrupt64", "interrupt128", "interrupt256", - "control", "bulk0", "bulk1", "bulk2", "bulk3", - "unused", "unused"}; +static const char *qh_names[] = {"interrupt2", "interrupt4", "interrupt8", + "interrupt16", "interrupt32", "interrupt64", + "interrupt128", "interrupt256", "control", + "bulk"}; void show_queues(struct uhci *uhci) { int i; struct uhci_qh *qh; - struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub); - for (i = 0; i < UHCI_MAXQH; ++i) { - printk(" %s:\n", qh_names[i]); -#if 0 - printk(" qh #%d, %p\n", i, virt_to_bus(root_hub->qh + i)); - show_queue(uhci->root_hub->qh + i); -#endif + for (i = 0; i < UHCI_NUM_SKELQH; ++i) { + printk(" %s: [%p] (%08X) (%08X)\n", qh_names[i], + &uhci->skelqh[i], + uhci->skelqh[i].link, uhci->skelqh[i].element); - qh = uhci_link_to_qh(root_hub->qh[i].link); + qh = uhci_link_to_qh(uhci->skelqh[i].link); for (; qh; qh = uhci_link_to_qh(qh->link)) { if (is_skeleton_qh(uhci, qh)) break; + printk(" [%p] (%08X) (%08x)\n", + qh, qh->link, qh->element); + show_queue(qh); } } } + diff -u --recursive --new-file v2.3.12/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.12/linux/drivers/usb/uhci.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/uhci.c Mon Aug 9 11:27:39 1999 @@ -2,6 +2,7 @@ * Universal Host Controller Interface driver for USB. * * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -54,32 +55,40 @@ static DECLARE_WAIT_QUEUE_HEAD(uhci_configure); +static kmem_cache_t *uhci_td_cachep; +static kmem_cache_t *uhci_qh_cachep; + +static LIST_HEAD(uhci_list); + +#define UHCI_DEBUG + /* * Map status to standard result codes */ static int uhci_map_status(int status, int dir_out) { - if (!status) - return USB_ST_NOERROR; - if (status & 0x02) /* Bitstuff error*/ - return USB_ST_BITSTUFF; - if (status & 0x04) { /* CRC/Timeout */ - if (dir_out) - return USB_ST_NORESPONSE; - else - return USB_ST_CRC; - } - if (status & 0x08) /* NAK */ - return USB_ST_TIMEOUT; - if (status & 0x10) /* Babble */ - return USB_ST_STALL; - if (status & 0x20) /* Buffer error */ - return USB_ST_BUFFERUNDERRUN; - if (status & 0x40) /* Stalled */ - return USB_ST_STALL; - if (status & 0x80) /* Active */ - return USB_ST_NOERROR; - return USB_ST_INTERNALERROR; + if (!status) + return USB_ST_NOERROR; + if (status & 0x02) /* Bitstuff error*/ + return USB_ST_BITSTUFF; + if (status & 0x04) { /* CRC/Timeout */ + if (dir_out) + return USB_ST_NORESPONSE; + else + return USB_ST_CRC; + } + if (status & 0x08) /* NAK */ + return USB_ST_TIMEOUT; + if (status & 0x10) /* Babble */ + return USB_ST_STALL; + if (status & 0x20) /* Buffer error */ + return USB_ST_BUFFERUNDERRUN; + if (status & 0x40) /* Stalled */ + return USB_ST_STALL; + if (status & 0x80) /* Active */ + return USB_ST_NOERROR; + + return USB_ST_INTERNALERROR; } /* * Return the result of a TD.. @@ -87,9 +96,14 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned long *rval) { unsigned int status; - struct uhci_td *tmp = td->first; + struct uhci_td *tmp; + + if (!td->qh) + tmp = td; + else + tmp = uhci_ptr_to_virt(td->qh->element); - if(rval) + if (rval) *rval = 0; /* locate the first failing td, if any */ @@ -99,52 +113,54 @@ if (status) { /* must reset the toggle on first error */ if (uhci_debug) { - printk("Set toggle from %x rval %ld\n", (unsigned int)tmp, rval ? *rval : 0); + printk(KERN_DEBUG "Set toggle from %x rval %ld\n", + (unsigned int)tmp, rval ? *rval : 0); } - usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), usb_pipeout(tmp->info), (tmp->info >> 19) & 1); + usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), + usb_pipeout(tmp->info), (tmp->info >> 19) & 1); break; } else { - if(rval) + if (rval) *rval += (tmp->status & 0x3ff) + 1; } - if ((tmp->link & 1) || (tmp->link & 2)) + if ((tmp->link & UHCI_PTR_TERM) || + (tmp->link & UHCI_PTR_QH)) break; - tmp = bus_to_virt(tmp->link & ~0xF); + tmp = uhci_ptr_to_virt(tmp->link); } while (1); - if (!status) return USB_ST_NOERROR; /* Some debugging code */ - if (uhci_debug /* && (!usb_pipeendpoint(tmp->info) || !(status & 0x08))*/ ) { - int i = 10; + if (uhci_debug) { + int count = 10; - tmp = td->first; - printk("uhci_td_result() failed with status %x\n", status); - //show_status(dev->uhci); + if (!td->qh) + tmp = td; + else + tmp = uhci_ptr_to_virt(td->qh->element); + printk(KERN_DEBUG "uhci_td_result() failed with status %x\n", + status); do { show_td(tmp); - if ((tmp->link & 1) || (tmp->link & 2)) - break; - tmp = bus_to_virt(tmp->link & ~0xF); - if (!--i) + if ((tmp->link & UHCI_PTR_TERM) || + (tmp->link & UHCI_PTR_QH)) break; - } while (1); + tmp = uhci_ptr_to_virt(tmp->link); + } while (--count); } if (status & 0x40) { - /* endpoint has stalled - mark it halted */ - - usb_endpoint_halt(dev->usb, usb_pipeendpoint(tmp->info)); - return USB_ST_STALL; - + /* endpoint has stalled - mark it halted */ + usb_endpoint_halt(dev->usb, usb_pipeendpoint(tmp->info)); + return USB_ST_STALL; } if (status == 0x80) { - /* still active */ - if (!rval) - return USB_ST_DATAUNDERRUN; + /* still active */ + if (!rval) + return USB_ST_DATAUNDERRUN; } return uhci_map_status(status, usb_pipeout(tmp->info)); } @@ -163,7 +179,7 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, struct uhci_td *last) { unsigned int link = qh->element; - unsigned int new = 4 | virt_to_bus(first); + unsigned int new = virt_to_bus(first) | UHCI_PTR_DEPTH; for (;;) { unsigned char success; @@ -175,9 +191,9 @@ :"m" (qh->element), "1" (link), "r" (new) :"memory"); if (success) { - /* Was there a successor entry? Fix it's backpointer.. */ - if ((link & 1) == 0) { - struct uhci_td *next = bus_to_virt(link & ~15); + /* Was there a successor entry? Fix it's backpointer */ + if ((link & UHCI_PTR_TERM) == 0) { + struct uhci_td *next = uhci_ptr_to_virt(link); next->backptr = &last->link; } break; @@ -193,23 +209,22 @@ static void uhci_insert_qh(struct uhci_qh *qh, struct uhci_qh *newqh) { newqh->link = qh->link; - qh->link = virt_to_bus(newqh) | 2; + qh->link = virt_to_bus(newqh) | UHCI_PTR_QH; } static void uhci_remove_qh(struct uhci_qh *qh, struct uhci_qh *remqh) { - unsigned int remphys = virt_to_bus(remqh); struct uhci_qh *lqh = qh; - while ((lqh->link & ~0xF) != remphys) { - if (lqh->link & 1) + while (uhci_ptr_to_virt(lqh->link) != remqh) { + if (lqh->link & UHCI_PTR_TERM) break; - lqh = bus_to_virt(lqh->link & ~0xF); + lqh = uhci_ptr_to_virt(lqh->link); } - if (lqh->link & 1) { - printk("couldn't find qh in chain!\n"); + if (lqh->link & UHCI_PTR_TERM) { + printk(KERN_DEBUG "couldn't find qh in chain!\n"); return; } @@ -244,8 +259,8 @@ * so we can always just look at that and fix up the backpointer * of any next element.. */ - if (!(link & 1)) { - struct uhci_td *next = bus_to_virt(link & ~15); + if (!(link & UHCI_PTR_TERM)) { + struct uhci_td *next = uhci_ptr_to_virt(link); next->backptr = backptr; } @@ -262,60 +277,67 @@ :"memory"); } -static struct uhci_qh *uhci_qh_allocate(struct uhci_device *dev) +static struct uhci_td *uhci_td_alloc(struct uhci_device *dev) { - struct uhci_qh *qh; - int inuse; + struct uhci_td *td; - qh = dev->qh; - for (; (inuse = test_and_set_bit(0, &qh->inuse)) != 0 && qh < &dev->qh[UHCI_MAXQH]; qh++) - ; + td = kmem_cache_alloc(uhci_td_cachep, SLAB_KERNEL); + if (!td) + return NULL; - if (!inuse) - return(qh); +#ifdef UHCI_DEBUG + if ((__u32)td & UHCI_PTR_BITS) + printk("qh not 16 byte aligned!\n"); +#endif - printk("ran out of qh's for dev %p\n", dev); - return(NULL); -} + td->link = UHCI_PTR_TERM; + td->buffer = 0; -static void uhci_qh_deallocate(struct uhci_qh *qh) -{ -// if (qh->element != 1) -// printk("qh %p leaving dangling entries? (%X)\n", qh, qh->element); + td->backptr = NULL; + td->qh = NULL; + td->dev_id = NULL; + td->dev = dev; + td->flags = 0; + INIT_LIST_HEAD(&td->irq_list); + atomic_set(&td->refcnt, 1); - qh->element = 1; - qh->link = 1; + return td; +} - clear_bit(0, &qh->inuse); +static void uhci_td_free(struct uhci_td *td) +{ + if (atomic_dec_and_test(&td->refcnt)) + kmem_cache_free(uhci_td_cachep, td); } -static struct uhci_td *uhci_td_allocate(struct uhci_device *dev) +static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev) { - struct uhci_td *td; - int inuse; + struct uhci_qh *qh; - td = dev->td; - for (; (inuse = test_and_set_bit(0, &td->inuse)) != 0 && td < &dev->td[UHCI_MAXTD]; td++) - ; + qh = kmem_cache_alloc(uhci_qh_cachep, SLAB_KERNEL); + if (!qh) + return NULL; - if (!inuse) { - td->inuse = 1; - return(td); - } +#ifdef UHCI_DEBUG + if ((__u32)qh & UHCI_PTR_BITS) + printk("qh not 16 byte aligned!\n"); +#endif + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; - printk("ran out of td's for dev %p\n", dev); - return(NULL); + qh->dev = dev; + qh->skel = NULL; + init_waitqueue_head(&qh->wakeup); + atomic_set(&qh->refcnt, 1); + + return qh; } -/* - * This MUST only be called when it has been removed from a QH already (or - * the QH has been removed from the skeleton - */ -static void uhci_td_deallocate(struct uhci_td *td) +static void uhci_qh_free(struct uhci_qh *qh) { - td->link = 1; - - clear_bit(0, &td->inuse); + if (atomic_dec_and_test(&qh->refcnt)) + kmem_cache_free(uhci_qh_cachep, qh); } /* @@ -344,6 +366,45 @@ spin_unlock_irqrestore(&irqlist_lock, flags); } +/* + * This function removes and disallcoates all structures set up for an transfer. + * It takes the qh out of the skeleton, removes the tq and the td's. + * It only removes the associated interrupt handler if removeirq ist set. + * The *td argument is any td in the list of td's. + */ +static void uhci_remove_transfer(struct uhci_td *td, char removeirq) +{ + int maxcount = 1000; + struct uhci_td *curtd; + unsigned int nextlink; + + if (!td->qh) + curtd = td; + else + curtd = uhci_ptr_to_virt(td->qh->element); + + /* Remove it from the skeleton */ + uhci_remove_qh(td->qh->skel, td->qh); + uhci_qh_free(td->qh); + do { + nextlink = curtd->link; + + /* IOC? => remove handler */ + if (removeirq && (td->status & TD_CTRL_IOC)) + uhci_remove_irq_list(td); + + uhci_remove_td(curtd); + uhci_td_free(curtd); + if (nextlink & UHCI_PTR_TERM) /* Tail? */ + break; + + curtd = bus_to_virt(nextlink & ~UHCI_PTR_BITS); + if (!--maxcount) { + printk(KERN_ERR "runaway td's!?\n"); + break; + } + } while (1); +} /* * Request a interrupt handler.. @@ -351,101 +412,50 @@ * Returns: a "handle pointer" that release_irq can use to stop this * interrupt. (It's really a pointer to the TD). */ -static void* uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) +static void *uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) { struct uhci_device *dev = usb_to_uhci(usb_dev); - struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub); - struct uhci_td *td = uhci_td_allocate(dev); - struct uhci_qh *interrupt_qh = uhci_qh_allocate(dev); - + struct uhci_td *td = uhci_td_alloc(dev); + struct uhci_qh *qh = uhci_qh_alloc(dev); unsigned int destination, status; - /* Destination: pipe destination with INPUT */ - destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); + if (!td || !qh) + return NULL; - /* Status: slow/fast, Interrupt, Active, Short Packet Detect Infinite Errors */ - status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23) | (1 << 29) | (0 << 27); + /* Destination: pipe destination with INPUT */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe); - if(interrupt_qh->element != 1) - printk("interrupt_qh->element = 0x%x\n", - interrupt_qh->element); + /* Infinite errors is 0, so no bits */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_IOC | TD_CTRL_ACTIVE | + TD_CTRL_SPD; - td->link = 1; - td->status = status; + td->link = UHCI_PTR_TERM; /* Terminate */ + td->status = status; /* In */ td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) | - (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); + (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), + usb_pipeout(pipe)) << 19); td->buffer = virt_to_bus(dev->data); - td->first = td; - td->qh = interrupt_qh; - td->dev = usb_dev; + td->qh = qh; + td->dev = dev; /* if period 0, insert into fast q */ - if (period == 0) { - td->inuse |= 2; - interrupt_qh->skel = &root_hub->skel_int2_qh; + td->flags |= UHCI_TD_REMOVE; + qh->skel = &dev->uhci->skel_int2_qh; } else - interrupt_qh->skel = &root_hub->skel_int8_qh; + qh->skel = &dev->uhci->skel_int8_qh; uhci_add_irq_list(dev->uhci, td, handler, dev_id); - uhci_insert_td_in_qh(interrupt_qh, td); + uhci_insert_td_in_qh(qh, td); /* Add it into the skeleton */ - uhci_insert_qh(interrupt_qh->skel, interrupt_qh); + uhci_insert_qh(qh->skel, qh); - return (void*)td; + return (void *)td; } /* - * Remove running irq td from queues - * - * This function is not used anymore. - */ -#if 0 -static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) -{ - struct uhci_device *dev = usb_to_uhci(usb_dev); - struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub); - struct uhci_td *td; - struct uhci_qh *interrupt_qh; - unsigned long flags; - struct list_head *head = &dev->uhci->interrupt_list; - struct list_head *tmp; - - spin_lock_irqsave(&irqlist_lock, flags); - - /* find the TD in the interrupt list */ - - tmp = head->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, irq_list); - if (td->dev_id == dev_id && td->completed == handler) { - - /* found the right one - let's remove it */ - - /* notify removal */ - - td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id); - - /* this is DANGEROUS - not sure whether this is right */ - - list_del(&td->irq_list); - uhci_remove_td(td); - interrupt_qh = td->qh; - uhci_remove_qh(interrupt_qh->skel, interrupt_qh); - uhci_td_deallocate(td); - uhci_qh_deallocate(interrupt_qh); - spin_unlock_irqrestore(&irqlist_lock, flags); - return USB_ST_NOERROR; - } - } - spin_unlock_irqrestore(&irqlist_lock, flags); - return USB_ST_INTERNALERROR; -} -#endif - -/* * Release an interrupt handler previously allocated using * uhci_request_irq. This function does no validity checking, so make * sure you're not releasing an already released handle as it may be @@ -453,45 +463,40 @@ * * This function can NOT be called from an interrupt. */ -int uhci_release_irq(void* handle) +int uhci_release_irq(void *handle) { struct uhci_td *td; - struct uhci_qh *interrupt_qh; - unsigned long flags; + struct uhci_qh *qh; #ifdef UHCI_DEBUG - printk("usb-uhci: Releasing irq handle %p\n", handle); + printk(KERN_DEBUG "usb-uhci: releasing irq handle %p\n", handle); #endif - td = (struct uhci_td*)handle; - if (td == NULL) + td = (struct uhci_td *)handle; + if (!td) return USB_ST_INTERNALERROR; /* Remove it from the internal irq_list */ - spin_lock_irqsave(&irqlist_lock, flags); - list_del(&td->irq_list); - spin_unlock_irqrestore(&irqlist_lock, flags); + uhci_remove_irq_list(td); /* Remove the interrupt TD and QH */ uhci_remove_td(td); - interrupt_qh = td->qh; - uhci_remove_qh(interrupt_qh->skel, interrupt_qh); + qh = td->qh; + uhci_remove_qh(qh->skel, qh); if (td->completed != NULL) td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id); /* Free the TD and QH */ - uhci_td_deallocate(td); - uhci_qh_deallocate(interrupt_qh); + uhci_td_free(td); + uhci_qh_free(qh); return USB_ST_NOERROR; } /* uhci_release_irq() */ - /* - * Isochronous thread operations + * Isochronous operations */ - static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc) { struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc; @@ -499,18 +504,19 @@ int i, totlen = 0; for (i = 0; i < isodesc->num; i++) { - char *cdata = bus_to_virt(isodesc->td[i].buffer & ~0xF); - int n = (isodesc->td[i].status + 1) & 0x7FF; + struct uhci_td *td = &isodesc->td[i]; + char *cdata = uhci_ptr_to_virt(td->buffer); + int n = (td->status + 1) & 0x7FF; if ((cdata != data) && (n)) memmove(data, cdata, n); -#if 0 -if (n && n != 960) - printk("underrun: %d %d\n", i, n); +#ifdef UHCI_DEBUG + /* Debugging */ + if ((td->status >> 16) & 0xFF) + printk(KERN_DEBUG "error: %d %X\n", i, + (td->status >> 16)); #endif -if ((isodesc->td[i].status >> 16) & 0xFF) - printk("error: %d %X\n", i, (isodesc->td[i].status >> 16)); data += n; totlen += n; @@ -526,14 +532,22 @@ struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc; int i; - if ((isodesc->frame < 0) || (isodesc->frame > 1023)) + if ((isodesc->frame < 0) || (isodesc->frame > 1023)) { + printk(KERN_ERR "illegal frame number %d\n", isodesc->frame); return 1; + } + + /* FIXME: Use uhci_remove_td */ /* Remove from previous frames */ for (i = 0; i < isodesc->num; i++) { + struct uhci_td *td = &isodesc->td[i]; + /* Turn off Active and IOC bits */ - isodesc->td[i].status &= ~(3 << 23); - uhci->fl->frame[(isodesc->frame + i) % 1024] = isodesc->td[i].link; + td->status &= ~(3 << 23); + td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC); + + uhci->fl->frame[(isodesc->frame + i) % 1024] = td->link; } isodesc->frame = -1; @@ -551,43 +565,36 @@ int frame, i; if (isodesc->frame != -1) { - printk("isoc queue not removed\n"); + printk(KERN_ERR "isoc queue not removed\n"); uhci_unschedule_isochronous(usb_dev, isodesc); } /* Insert TD into list */ if (!pisodesc) { + /* It's not guaranteed to be 1-1024 */ frame = inw(uhci->io_addr + USBFRNUM) % 1024; + /* HACK: Start 2 frames from now */ frame = (frame + 2) % 1024; } else frame = (pisodesc->endframe + 1) % 1024; -#if 0 -printk("scheduling first at frame %d\n", frame); -#endif - for (i = 0; i < isodesc->num; i++) { + struct uhci_td *td = &isodesc->td[i]; + /* Active */ - isodesc->td[i].status |= (1 << 23); - isodesc->td[i].backptr = &uhci->fl->frame[(frame + i) % 1024]; - isodesc->td[i].link = uhci->fl->frame[(frame + i) % 1024]; - uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(&isodesc->td[i]); + td->status |= TD_CTRL_ACTIVE; + td->backptr = &uhci->fl->frame[(frame + i) % 1024]; + td->link = uhci->fl->frame[(frame + i) % 1024]; + uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(td); } -#if 0 -printk("last at frame %d\n", (frame + i - 1) % 1024); -#endif - - /* Interrupt */ - isodesc->td[i - 1].status |= (1 << 24); + /* IOC on the last TD */ + isodesc->td[i - 1].status |= TD_CTRL_IOC; isodesc->frame = frame; isodesc->endframe = (frame + isodesc->num - 1) % 1024; -#if 0 - return uhci_td_result(dev, td[num - 1]); -#endif return 0; } @@ -604,20 +611,21 @@ isodesc = kmalloc(sizeof(*isodesc), GFP_KERNEL); if (!isodesc) { - printk("Couldn't allocate isodesc!\n"); + printk(KERN_ERR "Couldn't allocate isodesc!\n"); return NULL; } + memset(isodesc, 0, sizeof(*isodesc)); /* Carefully work around the non contiguous pages */ - isodesc->num = (len / PAGE_SIZE) * (PAGE_SIZE / maxsze); + isodesc->num = len / maxsze; isodesc->td = kmalloc(sizeof(struct uhci_td) * isodesc->num, GFP_KERNEL); isodesc->frame = isodesc->endframe = -1; isodesc->data = data; isodesc->maxsze = maxsze; if (!isodesc->td) { - printk("Couldn't allocate td's\n"); + printk(KERN_ERR "couldn't allocate td's\n"); kfree(isodesc); return NULL; } @@ -634,10 +642,9 @@ /* The "pipe" thing contains the destination in bits 8--18 */ destination = (pipe & PIPE_DEVEP_MASK) - | usb_packetid (pipe); /* add IN or OUT */ + | usb_packetid (pipe); /* add IN or OUT */ - /* Status: slow/fast, Active, Isochronous */ - status = (pipe & (1 << 26)) | (1 << 23) | (1 << 25); + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOS; /* * Build the TD for the control request @@ -645,21 +652,14 @@ td->status = status; td->info = destination | ((maxsze - 1) << 21); td->buffer = virt_to_bus(data); - td->first = td; td->backptr = NULL; i++; data += maxsze; - - if (((int)data % PAGE_SIZE) + maxsze >= PAGE_SIZE) - data = (char *)(((int)data + maxsze) & ~(PAGE_SIZE - 1)); - len -= maxsze; } while (i < isodesc->num); - /* IOC on the last TD */ - td->status |= (1 << 24); uhci_add_irq_list(dev->uhci, td, completed, dev_id); return isodesc; @@ -688,11 +688,16 @@ * We need to remove the TD from the lists (both interrupt * list and TD lists) by hand if something bad happens! */ -static DECLARE_WAIT_QUEUE_HEAD(control_wakeup); -static int uhci_control_completed(int status, void *buffer, int len, void *dev_id) +static int uhci_generic_completed(int status, void *buffer, int len, void *dev_id) { - wake_up(&control_wakeup); + wait_queue_head_t *wakeup = (wait_queue_head_t *)dev_id; + + if (waitqueue_active(wakeup)) + wake_up(wakeup); + else + printk("waitqueue empty!\n"); + return 0; /* Don't re-instate */ } @@ -700,62 +705,52 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last) { DECLARE_WAITQUEUE(wait, current); - struct uhci_qh *ctrl_qh = uhci_qh_allocate(dev); - struct uhci_td *curtd; - struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub); + struct uhci_qh *qh = uhci_qh_alloc(dev); + + if (!qh) + return -1; + current->state = TASK_UNINTERRUPTIBLE; - add_wait_queue(&control_wakeup, &wait); + add_wait_queue(&qh->wakeup, &wait); - uhci_add_irq_list(dev->uhci, last, uhci_control_completed, NULL); + uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup); +#if 0 /* FIXME: This is kinda kludged */ /* Walk the TD list and update the QH pointer */ { - int maxcount = 100; + struct uhci_td *curtd; + int count = 100; curtd = first; do { curtd->qh = ctrl_qh; - if (curtd->link & 1) + if (curtd->link & TD_CTRL_TERM) break; - curtd = bus_to_virt(curtd->link & ~0xF); - if (!--maxcount) { - printk("runaway tds!\n"); - break; - } - } while (1); + curtd = uhci_ptr_to_virt(curtd->link); + } while (--count); + if (!count) + printk(KERN_DEBUG "runaway tds!\n"); } +#endif - uhci_insert_tds_in_qh(ctrl_qh, first, last); + uhci_insert_tds_in_qh(qh, first, last); /* Add it into the skeleton */ - uhci_insert_qh(&root_hub->skel_control_qh, ctrl_qh); + uhci_insert_qh(&dev->uhci->skel_control_qh, qh); -// control should be full here... -// printk("control\n"); -// show_status(dev->uhci); -// show_queues(dev->uhci); + schedule_timeout(HZ * 5); /* 5 seconds */ - schedule_timeout(HZ*5); - -// control should be empty here... -// show_status(dev->uhci); -// show_queues(dev->uhci); - - remove_wait_queue(&control_wakeup, &wait); + remove_wait_queue(&qh->wakeup, &wait); /* Clean up in case it failed.. */ uhci_remove_irq_list(last); -#if 0 - printk("Looking for tds [%p, %p]\n", dev->control_td, td); -#endif - /* Remove it from the skeleton */ - uhci_remove_qh(&root_hub->skel_control_qh, ctrl_qh); + uhci_remove_qh(&dev->uhci->skel_control_qh, qh); - uhci_qh_deallocate(ctrl_qh); + uhci_qh_free(qh); return uhci_td_result(dev, last, NULL); } @@ -786,19 +781,19 @@ struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci_td *first, *td, *prevtd; unsigned long destination, status; - int ret; + int ret, count; int maxsze = usb_maxpacket(usb_dev, pipe); + __u32 nextlink; - if (len > maxsze * 29) - printk("Warning, too much data for a control packet, crashing\n"); - - first = td = uhci_td_allocate(dev); + first = td = uhci_td_alloc(dev); + if (!td) + return -ENOMEM; /* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */ destination = (pipe & PIPE_DEVEP_MASK) | 0x2D; - /* Status: slow/fast, Active, Short Packet Detect Three Errors */ - status = (pipe & (1 << 26)) | (1 << 23) | (1 << 29) | (3 << 27); + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD | (3 << 27); /* * Build the TD for the control request @@ -806,7 +801,6 @@ td->status = status; /* Try forever */ td->info = destination | (7 << 21); /* 8 bytes of data */ td->buffer = virt_to_bus(cmd); - td->first = td; /* * If direction is "send", change the frame from SETUP (0x2D) @@ -817,8 +811,11 @@ destination ^= (0xE1 ^ 0x69); /* IN -> OUT */ prevtd = td; - td = uhci_td_allocate(dev); - prevtd->link = 4 | virt_to_bus(td); + td = uhci_td_alloc(dev); + if (!td) + return -ENOMEM; + + prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH; /* * Build the DATA TD's @@ -834,18 +831,18 @@ destination ^= 1 << 19; td->status = status; /* Status */ - td->info = destination | ((pktsze-1) << 21); /* pktsze bytes of data */ + td->info = destination | ((pktsze - 1) << 21); /* pktsze bytes of data */ td->buffer = virt_to_bus(data); - td->first = first; td->backptr = &prevtd->link; data += pktsze; len -= pktsze; prevtd = td; - td = uhci_td_allocate(dev); - prevtd->link = 4 | virt_to_bus(td); /* Update previous TD */ - + td = uhci_td_alloc(dev); + if (!td) + return -ENOMEM; + prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH; /* Update previous TD */ } /* @@ -854,47 +851,40 @@ destination ^= (0xE1 ^ 0x69); /* OUT -> IN */ destination |= 1 << 19; /* End in Data1 */ - td->backptr = &prevtd->link; - td->status = (status /* & ~(3 << 27) */) | (1 << 24); /* no limit on final packet */ + td->status = status | TD_CTRL_IOC; /* no limit on errors on final packet */ td->info = destination | (UHCI_NULL_DATA_SIZE << 21); /* 0 bytes of data */ td->buffer = 0; - td->first = first; - td->link = 1; /* Terminate */ - + td->backptr = &prevtd->link; + td->link = UHCI_PTR_TERM; /* Terminate */ /* Start it up.. */ ret = uhci_run_control(dev, first, td); - { - int maxcount = 100; - struct uhci_td *curtd = first; - unsigned int nextlink; + count = 100; + td = first; + do { + nextlink = td->link; + uhci_remove_td(td); + uhci_td_free(td); - do { - nextlink = curtd->link; - uhci_remove_td(curtd); - uhci_td_deallocate(curtd); - if (nextlink & 1) /* Tail? */ - break; + if (nextlink & UHCI_PTR_TERM) /* Tail? */ + break; - curtd = bus_to_virt(nextlink & ~0xF); - if (!--maxcount) { - printk("runaway td's!?\n"); - break; - } - } while (1); - } + td = uhci_ptr_to_virt(nextlink); + } while (--count); + + if (!count) + printk(KERN_ERR "runaway td's!?\n"); if (uhci_debug && ret) { __u8 *p = (__u8 *)cmd; - printk("Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n", + printk(KERN_DEBUG "Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } return ret; } - /* * Bulk thread operations: we just mark the last TD * in a bulk thread as an interrupt TD, and wake up @@ -903,74 +893,56 @@ * We need to remove the TD from the lists (both interrupt * list and TD lists) by hand if something bad happens! */ -static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup); - -static int uhci_bulk_completed(int status, void *buffer, int len, void *dev_id) -{ - wake_up(&bulk_wakeup); - return 0; /* Don't re-instate */ -} /* td points to the last td in the list, which interrupts on completion */ static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last, unsigned long *rval) { DECLARE_WAITQUEUE(wait, current); - struct uhci_qh *bulk_qh = uhci_qh_allocate(dev); - struct uhci_td *curtd; - struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub); + struct uhci_qh *qh = uhci_qh_alloc(dev); + + if (!qh) + return -ENOMEM; current->state = TASK_UNINTERRUPTIBLE; - add_wait_queue(&bulk_wakeup, &wait); + add_wait_queue(&qh->wakeup, &wait); - uhci_add_irq_list(dev->uhci, last, uhci_bulk_completed, NULL); + uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup); +#if 0 /* FIXME: This is kinda kludged */ /* Walk the TD list and update the QH pointer */ { - int maxcount = 100; + struct uhci_td *curtd; + int count = 100; curtd = first; do { curtd->qh = bulk_qh; - if (curtd->link & 1) + if (curtd->link & UHCI_PTR_TERM) break; - curtd = bus_to_virt(curtd->link & ~0xF); - if (!--maxcount) { - printk("runaway tds!\n"); - break; - } - } while (1); + curtd = uhci_ptr_to_virt(curtd->link); + } while (--count); + if (!count) + printk(KERN_ERR "runaway tds!\n"); } +#endif - uhci_insert_tds_in_qh(bulk_qh, first, last); + uhci_insert_tds_in_qh(qh, first, last); /* Add it into the skeleton */ - uhci_insert_qh(&root_hub->skel_bulk0_qh, bulk_qh); + uhci_insert_qh(&dev->uhci->skel_bulk_qh, qh); -// now we're in the queue... but don't ask WHAT is in there ;-( -// printk("bulk\n"); -// show_status(dev->uhci); -// show_queues(dev->uhci); - - schedule_timeout(HZ*5); -// show_status(dev->uhci); -// show_queues(dev->uhci); + schedule_timeout(HZ*5); /* 5 seconds */ - //show_queue(first->qh); - remove_wait_queue(&bulk_wakeup, &wait); + remove_wait_queue(&qh->wakeup, &wait); /* Clean up in case it failed.. */ uhci_remove_irq_list(last); -#if 0 - printk("Looking for tds [%p, %p]\n", dev->control_td, td); -#endif + uhci_remove_qh(&dev->uhci->skel_bulk_qh, qh); - /* Remove it from the skeleton */ - uhci_remove_qh(&root_hub->skel_bulk0_qh, bulk_qh); - - uhci_qh_deallocate(bulk_qh); + uhci_qh_free(qh); return uhci_td_result(dev, last, rval); } @@ -983,13 +955,6 @@ * * A bulk message is only built up from * the data phase - * - * The data phase can be an arbitrary number of TD's - * although we currently had better not have more than - * 31 TD's here. - * - * 31 TD's is a minimum of 248 bytes worth of bulk - * information. */ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *rval) { @@ -1003,19 +968,19 @@ usb_clear_halt(usb_dev, usb_pipeendpoint(pipe) | (pipe & 0x80))) return USB_ST_STALL; - if (len > maxsze * 31) - printk("Warning, too much data for a bulk packet, crashing (%d/%d)\n", len, maxsze); - /* The "pipe" thing contains the destination in bits 8--18 */ destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); - /* Status: slow/fast, Active, Short Packet Detect Three Errors */ - status = (pipe & (1 << 26)) | (1 << 23) | (1 << 29) | (3 << 27); + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD | (3 << 27); /* * Build the TDs for the bulk request */ - first = td = uhci_td_allocate(dev); + first = td = uhci_td_alloc(dev); + if (!td) + return -ENOMEM; + prevtd = first; //This is fake, but at least it's not NULL while (len > 0) { /* Build the TD for control status */ @@ -1029,22 +994,25 @@ (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */ td->buffer = virt_to_bus(data); td->backptr = &prevtd->link; - td->first = first; data += maxsze; len -= maxsze; if (len > 0) { prevtd = td; - td = uhci_td_allocate(dev); - prevtd->link = 4 | virt_to_bus(td); /* Update previous TD */ + td = uhci_td_alloc(dev); + if (!td) + return -ENOMEM; + + prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;/* Update previous TD */ } /* Alternate Data0/1 (start with Data0) */ usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); } + td->link = 1; /* Terminate */ - td->status |= (1 << 24); /* IOC */ + td->status |= TD_CTRL_IOC; /* CHANGE DIRECTION HERE! SAVE IT SOMEWHERE IN THE ENDPOINT!!! */ @@ -1052,43 +1020,120 @@ ret = uhci_run_bulk(dev, first, td, rval); { - int maxcount = 100; + int count = 100; struct uhci_td *curtd = first; unsigned int nextlink; do { nextlink = curtd->link; uhci_remove_td(curtd); - uhci_td_deallocate(curtd); - if (nextlink & 1) /* Tail? */ - break; + uhci_td_free(curtd); - curtd = bus_to_virt(nextlink & ~0xF); - if (!--maxcount) { - printk("runaway td's!?\n"); + if (nextlink & UHCI_PTR_TERM) /* Tail? */ break; - } - } while (1); + + curtd = uhci_ptr_to_virt(nextlink); + } while (--count); + + if (!count) + printk(KERN_DEBUG "runaway td's!?\n"); } return ret; } -static struct usb_device *uhci_usb_allocate(struct usb_device *parent) +static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id) +{ + struct uhci_device *dev = usb_to_uhci(usb_dev); + struct uhci *uhci = dev->uhci; + struct uhci_td *first, *td, *prevtd; + struct uhci_qh *bulk_qh = uhci_qh_alloc(dev); + unsigned long destination, status; + int maxsze = usb_maxpacket(usb_dev, pipe); + + /* The "pipe" thing contains the destination in bits 8--18, 0x69 is IN */ + destination = (pipe & 0x0007ff00) | usb_packetid(pipe); + + /* Infinite errors is 0 */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD; + + /* Build the TDs for the bulk request */ + first = td = uhci_td_alloc(dev); + prevtd = td; + while (len > 0) { + /* Build the TD for control status */ + int pktsze = len; + + if (pktsze > maxsze) + pktsze = maxsze; + + td->status = status; /* Status */ + td->info = destination | ((pktsze-1) << 21) | + (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */ + td->buffer = virt_to_bus(data); + td->backptr = &prevtd->link; + td->qh = bulk_qh; + td->dev = dev; + data += pktsze; + len -= pktsze; + + if (len > 0) { + prevtd = td; + td = uhci_td_alloc(dev); + prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH; + } + + /* Alternate Data0/1 */ + usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + } + + first->backptr = NULL; + td->link = 1; /* Terminate */ + td->status = status | TD_CTRL_IOC; /* IOC */ + + uhci_add_irq_list(dev->uhci, td, handler, dev_id); + + uhci_insert_tds_in_qh(bulk_qh, first, td); + + bulk_qh->skel = &uhci->skel_bulk_qh; + uhci_insert_qh(&uhci->skel_bulk_qh, bulk_qh); + + /* Return last td for removal */ + return td; +} + +/* + *Remove a handler from a pipe. This terminates the transfer. + *We have some assumptions here: + * There is only one queue using this pipe. (the one we remove) + * Any data that is in the queue is useless for us, we throw it away. + */ +static int uhci_terminate_bulk(struct usb_device *dev, void * first) +{ + /* none found? there is nothing to remove! */ + if (!first) + return 0; + + uhci_remove_transfer(first,1); + + return 1; +} + +static struct usb_device *uhci_usb_alloc(struct usb_device *parent) { struct usb_device *usb_dev; struct uhci_device *dev; - int i; + /* Allocate the USB device */ usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL); if (!usb_dev) return NULL; memset(usb_dev, 0, sizeof(*usb_dev)); + /* Allocate the UHCI device private data */ dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { - usb_destroy_configuration(usb_dev); kfree(usb_dev); return NULL; } @@ -1106,49 +1151,12 @@ dev->uhci = usb_to_uhci(parent)->uhci; } - /* Reset the QH's and TD's */ - for (i = 0; i < UHCI_MAXQH; i++) { - dev->qh[i].link = 1; - dev->qh[i].element = 1; - dev->qh[i].inuse = 0; - } - - for (i = 0; i < UHCI_MAXTD; i++) { - dev->td[i].link = 1; - dev->td[i].inuse = 0; - } - return usb_dev; } -static int uhci_usb_deallocate(struct usb_device *usb_dev) +static int uhci_usb_free(struct usb_device *usb_dev) { struct uhci_device *dev = usb_to_uhci(usb_dev); - int i; - - /* There are UHCI_MAXTD preallocated tds */ - for (i = 0; i < UHCI_MAXTD; ++i) { - struct uhci_td *td = dev->td + i; - - if (td->inuse & 1) { - uhci_remove_td(td); - - /* And remove it from the irq list, if it's active */ - if (td->status & (1 << 23)) - td->status &= ~(1 << 23); -#if 0 - uhci_remove_irq_list(td); -#endif - } - } - - /* Remove the td from any queues */ - for (i = 0; i < UHCI_MAXQH; ++i) { - struct uhci_qh *qh = dev->qh + i; - - if (qh->inuse & 1) - uhci_remove_qh(qh->skel, qh); - } kfree(dev); usb_destroy_configuration(usb_dev); @@ -1158,12 +1166,14 @@ } struct usb_operations uhci_device_operations = { - uhci_usb_allocate, - uhci_usb_deallocate, + uhci_usb_alloc, + uhci_usb_free, uhci_control_msg, uhci_bulk_msg, uhci_request_irq, uhci_release_irq, + uhci_request_bulk, + uhci_terminate_bulk, uhci_allocate_isochronous, uhci_delete_isochronous, uhci_schedule_isochronous, @@ -1200,7 +1210,6 @@ } - /* * This gets called if the connect status on the root * hub (and the root hub only) changes. @@ -1210,8 +1219,11 @@ struct usb_device *usb_dev; struct uhci_device *dev; unsigned short status; - struct uhci_device *root_hub=usb_to_uhci(uhci->bus->root_hub); - printk("uhci_connect_change: called for %d\n", nr); + struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub); + +#ifdef UHCI_DEBUG + printk(KERN_INFO "uhci_connect_change: called for %d\n", nr); +#endif /* * Even if the status says we're connected, @@ -1235,14 +1247,12 @@ * Ok, we got a new connection. Allocate a device to it, * and find out what it wants to do.. */ - usb_dev = uhci_usb_allocate(root_hub->usb); + usb_dev = uhci_usb_alloc(root_hub->usb); if (!usb_dev) return; dev = usb_dev->hcpriv; - dev->uhci = uhci; - usb_connect(usb_dev); root_hub->usb->children[nr] = usb_dev; @@ -1258,7 +1268,13 @@ * The rest is generic for any new USB attach, regardless of * hub type. */ - usb_new_device(usb_dev); + if (usb_new_device(usb_dev)) { + unsigned short status = inw(port); + + printk(KERN_INFO "uhci: disabling malfunctioning port %d\n", + nr + 1); + outw(status | USBPORTSC_PE, port); + } } /* @@ -1268,7 +1284,7 @@ */ static void uhci_check_configuration(struct uhci *uhci) { - struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub); + struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub); unsigned int io_addr = uhci->io_addr + USBPORTSC1; int maxchild = root_hub->usb->maxchild; int nr = 0; @@ -1285,54 +1301,70 @@ static void uhci_interrupt_notify(struct uhci *uhci) { - struct list_head *head = &uhci->interrupt_list; - struct list_head *tmp; + struct list_head *tmp, *head = &uhci->interrupt_list; int status; spin_lock(&irqlist_lock); tmp = head->next; while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list); - struct list_head *next; + struct uhci_td *first, *td = list_entry(tmp, + struct uhci_td, irq_list); - next = tmp->next; + tmp = tmp->next; - if (!((status = td->status) & (1 << 23)) || /* No longer active? */ - ((td->qh->element & ~15) && - !((status = uhci_link_to_td(td->qh->element)->status) & (1 <<23)) && - (status & 0x760000) /* is in error state (Stall, db, babble, timeout, bitstuff) */)) { - /* remove from IRQ list */ - __list_del(tmp->prev, next); - INIT_LIST_HEAD(tmp); - if (td->completed(uhci_map_status(status, 0), bus_to_virt(td->buffer), -1, td->dev_id)) { - list_add(&td->irq_list, &uhci->interrupt_list); - - if (!(td->status & (1 << 25))) { - struct uhci_qh *interrupt_qh = td->qh; - - usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); - td->info &= ~(1 << 19); /* clear data toggle */ - td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */ - td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */ - - /* Remove then readd? Is that necessary */ - uhci_remove_td(td); - uhci_insert_td_in_qh(interrupt_qh, td); - } - } else if (td->inuse & 2) { - struct uhci_qh *interrupt_qh = td->qh; - /* marked for removal */ - td->inuse &= ~2; - usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); - uhci_remove_qh(interrupt_qh->skel, interrupt_qh); - uhci_qh_deallocate(interrupt_qh); - uhci_td_deallocate(td); + /* We check the TD which had the IOC bit as well as the */ + /* first TD */ + /* XXX: Shouldn't we check all of the TD's in the chain? */ + if ((td->qh) && (td->qh->element & ~UHCI_PTR_BITS)) + first = uhci_link_to_td(td->qh->element); + else + first = NULL; + + /* If any of the error bits are set OR the active is NOT set */ + /* then we're interested in this TD */ + status = td->status & 0xF60000; + + if ((!(status ^ TD_CTRL_ACTIVE)) && (first) && + (!(first->status & TD_CTRL_ACTIVE))) + status = first->status & 0xF60000; + + if (!(status ^ TD_CTRL_ACTIVE)) + continue; + + + /* remove from IRQ list */ + list_del(&td->irq_list); + INIT_LIST_HEAD(&td->irq_list); + + if (td->completed(uhci_map_status(status, 0), + bus_to_virt(td->buffer), -1, td->dev_id)) { + list_add(&td->irq_list, &uhci->interrupt_list); + + /* Isochronous TD's don't need this */ + if (!(td->status & TD_CTRL_IOS)) { + struct usb_device *usb_dev = td->dev->usb; + + usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); + td->info &= ~(1 << 19); /* clear data toggle */ + td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */ + td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC; + /* The HC removes it, so readd it */ + uhci_insert_td_in_qh(td->qh, td); } - /* If completed wants to not reactivate, then it's */ - /* responsible for free'ing the TD's and QH's */ - /* or another function (such as run_control) */ - } - tmp = next; + } else if (td->flags & UHCI_TD_REMOVE) { + struct usb_device *usb_dev = td->dev->usb; + + /* marked for removal */ + td->flags &= ~UHCI_TD_REMOVE; + usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)); + uhci_remove_qh(td->qh->skel, td->qh); + uhci_qh_free(td->qh); + uhci_td_free(td); + } + + /* If completed does not wants to reactivate, then */ + /* it's responsible for free'ing the TD's and QH's */ + /* or another function (such as run_control) */ } spin_unlock(&irqlist_lock); } @@ -1348,8 +1380,9 @@ static void uhci_root_hub_events(struct uhci *uhci, unsigned int io_addr) { if (waitqueue_active(&uhci_configure)) { - struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub); + struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub); int ports = root_hub->usb->maxchild; + io_addr += USBPORTSC1; do { if (inw(io_addr) & USBPORTSC_CSC) { @@ -1373,9 +1406,6 @@ status = inw(io_addr + USBSTS); outw(status, io_addr + USBSTS); -// if ((status & ~0x21) != 0) -// printk("interrupt: %X\n", status); - /* Walk the list of pending TD's to see which ones completed.. */ uhci_interrupt_notify(uhci); @@ -1393,16 +1423,23 @@ static void uhci_init_ticktd(struct uhci *uhci) { struct uhci_device *dev = usb_to_uhci(uhci->bus->root_hub); - struct uhci_td *td = uhci_td_allocate(dev); + struct uhci_td *td = uhci_td_alloc(dev); - td->link = 1; - td->status = (1 << 24); /* interrupt on completion */ + if (!td) { + printk(KERN_ERR "unable to allocate ticktd\n"); + return; + } + + /* Don't clobber the frame */ + td->link = uhci->fl->frame[0]; + td->status = TD_CTRL_IOC; td->info = (15 << 21) | 0x7f69; /* (ignored) input packet, 16 bytes, device 127 */ td->buffer = 0; - td->first = td; td->qh = NULL; uhci->fl->frame[0] = virt_to_bus(td); + + uhci->ticktd = td; } static void reset_hc(struct uhci *uhci) @@ -1410,9 +1447,9 @@ unsigned int io_addr = uhci->io_addr; /* Global reset for 50ms */ - outw(USBCMD_GRESET, io_addr+USBCMD); + outw(USBCMD_GRESET, io_addr + USBCMD); wait_ms(50); - outw(0, io_addr+USBCMD); + outw(0, io_addr + USBCMD); wait_ms(10); } @@ -1432,13 +1469,15 @@ outw(USBCMD_HCRESET, io_addr + USBCMD); while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { if (!--timeout) { - printk("USBCMD_HCRESET timed out!\n"); + printk(KERN_ERR "USBCMD_HCRESET timed out!\n"); break; } } - + /* Turn on all interrupts */ outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); + + /* Start at frame 0 */ outw(0, io_addr + USBFRNUM); outl(virt_to_bus(uhci->fl), io_addr + USBFLBASEADD); @@ -1463,6 +1502,9 @@ * We could certainly have multiple queues of the same * type, and maybe we should. We could have per-device * queues, for example. We begin small. + * + * Queues are dynamically allocated for devices now, + * this code only sets up the skeleton queue */ static struct uhci *alloc_uhci(unsigned int io_addr) { @@ -1487,33 +1529,27 @@ if (!uhci->fl) goto au_free_uhci; - bus = kmalloc(sizeof(*bus), GFP_KERNEL); + bus = usb_alloc_bus(&uhci_device_operations); if (!bus) goto au_free_fl; - memset(bus, 0, sizeof(*bus)); - uhci->bus = bus; bus->hcpriv = uhci; - bus->op = &uhci_device_operations; /* - * We allocate a 8kB area for the UHCI hub. The area - * is described by the uhci_device structure, and basically - * contains everything needed for normal operation. - * - * The first page is the actual device descriptor for the - * hub. - * - * The second page is used for the frame list. + * Allocate the root_hub */ - usb = uhci_usb_allocate(NULL); + usb = uhci_usb_alloc(NULL); if (!usb) goto au_free_bus; usb->bus = bus; + dev = usb_to_uhci(usb); - uhci->bus->root_hub=uhci_to_usb(dev); + dev->uhci = uhci; + + uhci->bus->root_hub = uhci_to_usb(dev); + /* Initialize the root hub */ /* UHCI specs says devices must have 2 ports, but goes on to say */ /* they may have more but give no way to determine how many they */ @@ -1521,29 +1557,20 @@ usb->maxchild = 2; usb_init_root_hub(usb); - /* - * Initialize the queues. They all start out empty, - * linked to each other in the proper order. - */ - for (i = 1 ; i < 9; i++) { - dev->qh[i].link = 2 | virt_to_bus(&dev->skel_control_qh); - dev->qh[i].element = 1; - } - - dev->skel_control_qh.link = 2 | virt_to_bus(&dev->skel_bulk0_qh); - dev->skel_control_qh.element = 1; - - dev->skel_bulk0_qh.link = 2 | virt_to_bus(&dev->skel_bulk1_qh); - dev->skel_bulk0_qh.element = 1; + /* 8 Interrupt queues */ + for (i = 0; i < 8; i++) { + struct uhci_qh *qh = &uhci->skelqh[i]; - dev->skel_bulk1_qh.link = 2 | virt_to_bus(&dev->skel_bulk2_qh); - dev->skel_bulk1_qh.element = 1; + qh->link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH; + qh->element = UHCI_PTR_TERM; + } - dev->skel_bulk2_qh.link = 2 | virt_to_bus(&dev->skel_bulk3_qh); - dev->skel_bulk2_qh.element = 1; + uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) | + UHCI_PTR_QH; + uhci->skel_control_qh.element = UHCI_PTR_TERM; - dev->skel_bulk3_qh.link = 1; - dev->skel_bulk3_qh.element = 1; + uhci->skel_bulk_qh.link = UHCI_PTR_TERM; + uhci->skel_bulk_qh.element = UHCI_PTR_TERM; /* * Fill the frame list: make all entries point to @@ -1554,7 +1581,7 @@ * us a reasonable dynamic range for irq latencies. */ for (i = 0; i < 1024; i++) { - struct uhci_qh * irq = &dev->skel_int2_qh; + struct uhci_qh *irq = &uhci->skel_int2_qh; if (i & 1) { irq++; if (i & 2) { @@ -1576,7 +1603,7 @@ } } } - uhci->fl->frame[i] = 2 | virt_to_bus(irq); + uhci->fl->frame[i] = virt_to_bus(irq) | UHCI_PTR_QH; } return uhci; @@ -1586,15 +1613,14 @@ */ au_free_bus: - kfree (bus); + usb_free_bus(bus); au_free_fl: - free_page ((unsigned long)uhci->fl); + free_page((unsigned long)uhci->fl); au_free_uhci: - kfree (uhci); + kfree(uhci); return NULL; } - /* * De-allocate all resources.. */ @@ -1605,51 +1631,44 @@ uhci->irq = -1; } -#if 0 - if (uhci->bus->root_hub) { - uhci_usb_deallocate(uhci_to_usb(uhci->bus->root_hub)); - uhci->bus->root_hub = NULL; + if (uhci->ticktd) { + uhci_td_free(uhci->ticktd); + uhci->ticktd = NULL; } -#endif if (uhci->fl) { free_page((unsigned long)uhci->fl); uhci->fl = NULL; } - kfree(uhci->bus); + usb_free_bus(uhci->bus); kfree(uhci); } static int uhci_control_thread(void * __uhci) { struct uhci *uhci = (struct uhci *)__uhci; - struct uhci_device * root_hub =usb_to_uhci(uhci->bus->root_hub); + + uhci->control_running = 1; lock_kernel(); - request_region(uhci->io_addr, 32, "usb-uhci"); /* * This thread doesn't need any user-level access, * so get rid of all our resources.. */ - printk("uhci_control_thread at %p\n", &uhci_control_thread); exit_mm(current); exit_files(current); - //exit_fs(current); strcpy(current->comm, "uhci-control"); /* * Ok, all systems are go.. */ - start_hc(uhci); - usb_register_bus(uhci->bus); - for(;;) { + do { siginfo_t info; int unsigned long signr; - interruptible_sleep_on(&uhci_configure); #ifdef CONFIG_APM if (apm_resume) { apm_resume = 0; @@ -1659,40 +1678,31 @@ #endif uhci_check_configuration(uhci); - if(signal_pending(current)) { + interruptible_sleep_on(&uhci_configure); + + if (signal_pending(current)) { /* sending SIGUSR1 makes us print out some info */ spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); - if(signr == SIGUSR1) { - printk("UHCI queue dump:\n"); + if (signr == SIGUSR1) { + printk(KERN_DEBUG "UHCI queue dump:\n"); show_queues(uhci); } else if (signr == SIGUSR2) { uhci_debug = !uhci_debug; - printk("UHCI debug toggle = %x\n", uhci_debug); - } else { + printk(KERN_DEBUG "UHCI debug toggle = %x\n", + uhci_debug); + } else break; - } } - } + } while (uhci->control_continue); - { - int i; - if(root_hub) - for(i = 0; i < root_hub->usb->maxchild; i++) - usb_disconnect(root_hub->usb->children + i); - } - - usb_deregister_bus(uhci->bus); - - reset_hc(uhci); - release_region(uhci->io_addr, 32); - - release_uhci(uhci); +/* MOD_DEC_USE_COUNT; +*/ - printk("uhci_control_thread exiting\n"); + uhci->control_running = 0; return 0; } @@ -1710,21 +1720,37 @@ if (!uhci) return -ENOMEM; + INIT_LIST_HEAD(&uhci->uhci_list); + list_add(&uhci->uhci_list, &uhci_list); + + request_region(uhci->io_addr, 32, "usb-uhci"); + reset_hc(uhci); + usb_register_bus(uhci->bus); + start_hc(uhci); + + uhci->control_continue = 1; + retval = -EBUSY; - if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb", uhci) == 0) { + if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "uhci", uhci) == 0) { int pid; - MOD_INC_USE_COUNT; + uhci->irq = irq; pid = kernel_thread(uhci_control_thread, uhci, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (pid >= 0) - return 0; + if (pid >= 0) { + uhci->control_pid = pid; + + return(pid); + } - MOD_DEC_USE_COUNT; retval = pid; } + + reset_hc(uhci); + release_region(uhci->io_addr, 32); + release_uhci(uhci); return retval; } @@ -1735,17 +1761,17 @@ /* Search for the IO base address.. */ for (i = 0; i < 6; i++) { - unsigned int io_addr = dev->base_address[i]; + unsigned int io_addr = dev->resource[i].start; /* IO address? */ - if (!(io_addr & 1)) + if (!(dev->resource[i].flags & 1)) continue; - io_addr &= PCI_BASE_ADDRESS_IO_MASK; - +#if 0 /* Is it already in use? */ if (check_region(io_addr, 32)) break; +#endif return found_uhci(dev->irq, io_addr); } @@ -1783,16 +1809,44 @@ } #endif - int uhci_init(void) { int retval; struct pci_dev *dev = NULL; u8 type; + char *name; + + /* FIXME: This is lame, but I guess it's better to leak memory than */ + /* crash */ + name = kmalloc(10, GFP_KERNEL); + if (!name) + return -ENOMEM; + + strcpy(name, "uhci_td"); + + uhci_td_cachep = kmem_cache_create(name, + sizeof(struct uhci_td), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (!uhci_td_cachep) + return -ENOMEM; + + name = kmalloc(10, GFP_KERNEL); + if (!name) + return -ENOMEM; + + strcpy(name, "uhci_qh"); + + uhci_qh_cachep = kmem_cache_create(name, + sizeof(struct uhci_qh), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (!uhci_qh_cachep) + return -ENOMEM; retval = -ENODEV; for (;;) { - dev = pci_find_class(PCI_CLASS_SERIAL_USB<<8, dev); + dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev); if (!dev) break; /* Is it UHCI */ @@ -1812,6 +1866,59 @@ return retval; } +void uhci_cleanup(void) +{ + struct list_head *next, *tmp, *head = &uhci_list; + int ret, i; + + tmp = head->next; + while (tmp != head) { + struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list); + struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub); + + next = tmp->next; + + list_del(&uhci->uhci_list); + INIT_LIST_HEAD(&uhci->uhci_list); + + /* Check if the process is still running */ + ret = kill_proc(uhci->control_pid, 0, 1); + if (!ret) { + int count = 10; + + uhci->control_continue = 0; + wake_up(&uhci_configure); + + while (uhci->control_running && --count) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + + if (!count) + printk(KERN_ERR "uhci: giving up on killing uhci-control\n"); + } + + if (root_hub) + for (i = 0; i < root_hub->usb->maxchild; i++) + usb_disconnect(root_hub->usb->children + i); + + usb_deregister_bus(uhci->bus); + + reset_hc(uhci); + release_region(uhci->io_addr, 32); + + release_uhci(uhci); + + tmp = next; + } + + if (kmem_cache_destroy(uhci_qh_cachep)) + printk(KERN_INFO "uhci: not all QH's were freed\n"); + + if (kmem_cache_destroy(uhci_td_cachep)) + printk(KERN_INFO "uhci: not all TD's were freed\n"); +} + #ifdef MODULE int init_module(void) { @@ -1823,5 +1930,7 @@ #ifdef CONFIG_APM apm_unregister_callback(&handle_apm_event); #endif + uhci_cleanup(); } #endif //MODULE + diff -u --recursive --new-file v2.3.12/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h --- v2.3.12/linux/drivers/usb/uhci.h Wed Jul 21 15:46:48 1999 +++ linux/drivers/usb/uhci.h Sat Aug 7 13:01:44 1999 @@ -55,17 +55,44 @@ #define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + struct uhci_qh { - unsigned int link; /* Next queue */ - unsigned int element; /* Queue element pointer */ - int inuse; /* Inuse? */ - struct uhci_qh *skel; /* Skeleton head */ + /* Hardware fields */ + __u32 link; /* Next queue */ + __u32 element; /* Queue element pointer */ + + /* Software fields */ + atomic_t refcnt; /* Reference counting */ + struct uhci_device *dev; /* The owning device */ + struct uhci_qh *skel; /* Skeleton head */ + + wait_queue_head_t wakeup; } __attribute__((aligned(16))); struct uhci_framelist { - unsigned int frame[1024]; + __u32 frame[1024]; } __attribute__((aligned(4096))); +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIME (1 << 18) /* CTC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ + +#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS) + +#define UHCI_TD_REMOVE 0x0001 /* Remove when done */ + /* * The documentation says "4 words for hardware, 4 words for software". * @@ -77,7 +104,7 @@ * On 64-bit machines we probably want to take advantage of the fact that * hw doesn't really care about the size of the sw-only area. * - * Alas, not anymore, we have more than 4 words of software, woops + * Alas, not anymore, we have more than 4 words for software, woops */ struct uhci_td { /* Hardware fields */ @@ -87,25 +114,27 @@ __u32 buffer; /* Software fields */ + unsigned int *backptr; /* Where to remove this from.. */ struct list_head irq_list; /* Active interrupt list.. */ + usb_device_irq completed; /* Completion handler routine */ - unsigned int *backptr; /* Where to remove this from.. */ void *dev_id; - int inuse; /* Inuse? (b0) Remove (b1)*/ - struct uhci_qh *qh; - struct uhci_td *first; - struct usb_device *dev; /* the owning device */ -} __attribute__((aligned(32))); + + atomic_t refcnt; /* Reference counting */ + struct uhci_device *dev; /* The owning device */ + struct uhci_qh *qh; /* QH this TD is a part of (ignored for Isochronous) */ + int flags; /* Remove, etc */ +} __attribute__((aligned(16))); struct uhci_iso_td { - int num; - char *data; - int maxsze; + int num; /* Total number of TD's */ + char *data; /* Beginning of buffer */ + int maxsze; /* Maximum size of each data block */ - struct uhci_td *td; + struct uhci_td *td; /* Pointer to first TD */ - int frame; - int endframe; + int frame; /* Beginning frame */ + int endframe; /* End frame */ }; /* @@ -117,17 +146,21 @@ */ struct uhci; +#if 0 #define UHCI_MAXTD 64 #define UHCI_MAXQH 16 +#endif /* The usb device part must be first! */ struct uhci_device { struct usb_device *usb; struct uhci *uhci; +#if 0 struct uhci_qh qh[UHCI_MAXQH]; /* These are the "common" qh's for each device */ struct uhci_td td[UHCI_MAXTD]; +#endif unsigned long data[16]; }; @@ -136,16 +169,6 @@ #define usb_to_uhci(usb) ((struct uhci_device *)(usb)->hcpriv) /* - * The root hub pre-allocated QH's and TD's have - * some special global uses.. - */ -#if 0 -#define control_td td /* Td's 0-30 */ -/* This is only for the root hub's TD list */ -#define tick_td td[31] -#endif - -/* * There are various standard queues. We set up several different * queues for each of the three basic queue types: interrupt, * control, and bulk. @@ -180,37 +203,25 @@ * transfers in QH's and all of their pictures don't have that either) but * other than that, that is what we're doing now * - * To keep with Linus' nomenclature, this is called the qh skeleton. These - * labels (below) are only signficant to the root hub's qh's + * And now we don't put Iso transfers in QH's, so we don't waste one on it + * + * To keep with Linus' nomenclature, this is called the QH skeleton. These + * labels (below) are only signficant to the root hub's QH's */ -#define skel_iso_qh qh[0] +#define UHCI_NUM_SKELQH 10 -#define skel_int2_qh qh[1] -#define skel_int4_qh qh[2] -#define skel_int8_qh qh[3] -#define skel_int16_qh qh[4] -#define skel_int32_qh qh[5] -#define skel_int64_qh qh[6] -#define skel_int128_qh qh[7] -#define skel_int256_qh qh[8] - -#define skel_control_qh qh[9] - -#define skel_bulk0_qh qh[10] -#define skel_bulk1_qh qh[11] -#define skel_bulk2_qh qh[12] -#define skel_bulk3_qh qh[13] +#define skel_int2_qh skelqh[0] +#define skel_int4_qh skelqh[1] +#define skel_int8_qh skelqh[2] +#define skel_int16_qh skelqh[3] +#define skel_int32_qh skelqh[4] +#define skel_int64_qh skelqh[5] +#define skel_int128_qh skelqh[6] +#define skel_int256_qh skelqh[7] -/* - * These are significant to the devices allocation of QH's - */ -#if 0 -#define iso_qh qh[0] -#define int_qh qh[1] /* We have 2 "common" interrupt QH's */ -#define control_qh qh[3] -#define bulk_qh qh[4] /* We have 4 "common" bulk QH's */ -#define extra_qh qh[8] /* The rest, anything goes */ -#endif +#define skel_control_qh skelqh[8] + +#define skel_bulk_qh skelqh[9] /* * This describes the full uhci information. @@ -222,14 +233,20 @@ int irq; unsigned int io_addr; + int control_pid; + int control_running; + int control_continue; + + struct list_head uhci_list; + struct usb_bus *bus; -#if 0 - /* These are "standard" QH's for the entire bus */ - struct uhci_qh qh[UHCI_MAXQH]; -#endif + struct uhci_qh skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ + struct uhci_framelist *fl; /* Frame list */ struct list_head interrupt_list; /* List of interrupt-active TD's for this uhci */ + + struct uhci_td *ticktd; }; /* needed for the debugging code */ diff -u --recursive --new-file v2.3.12/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.12/linux/drivers/usb/usb.c Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/usb.c Mon Aug 9 11:27:39 1999 @@ -51,40 +51,49 @@ int usb_register(struct usb_driver *new_driver) { - struct list_head *tmp = usb_bus_list.next; + struct list_head *tmp; + + printk("usbcore: Registering new driver %s\n", new_driver->name); + /* Add it to the list of known drivers */ list_add(&new_driver->driver_list, &usb_driver_list); /* - * We go through all existing devices, and see if any of them would - * be acceptable to the new driver.. This is done using a depth-first - * search for devices without a registered driver already, then + * We go through all existing devices, and see if any of them would + * be acceptable to the new driver.. This is done using a depth-first + * search for devices without a registered driver already, then * running 'probe' with each of the drivers registered on every one * of these. */ - while (tmp!= &usb_bus_list) { - struct usb_bus * bus = list_entry(tmp,struct - usb_bus,bus_list); - tmp=tmp->next; + tmp = usb_bus_list.next; + while (tmp != &usb_bus_list) { + struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list); + + tmp = tmp->next; usb_check_support(bus->root_hub); - } + } return 0; } void usb_deregister(struct usb_driver *driver) { - struct list_head *tmp = usb_bus_list.next; - /*first we remove the driver, to be sure it doesn't get used by - *another thread while we are stepping through removing entries - */ + struct list_head *tmp; + + printk("usbcore: Deregistering driver %s\n", driver->name); + + /* + * first we remove the driver, to be sure it doesn't get used by + * another thread while we are stepping through removing entries + */ list_del(&driver->driver_list); - printk("usbcore: deregistering driver\n"); - while (tmp!= &usb_bus_list) { - struct usb_bus * bus = list_entry(tmp,struct - usb_bus,bus_list); - tmp=tmp->next; - usb_driver_purge(driver,bus->root_hub); - } + + tmp = usb_bus_list.next; + while (tmp != &usb_bus_list) { + struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list); + + tmp = tmp->next; + usb_driver_purge(driver, bus->root_hub); + } } /* This function is part of a depth-first search down the device tree, @@ -93,45 +102,82 @@ void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev) { int i; - if (dev==NULL){ - printk("null device being passed in!!!\n"); - return; - } - for (i=0;ichildren[i]!=NULL) - usb_driver_purge(driver,dev->children[i]); - /*now we check this device*/ - if(dev->driver==driver) { - /* - * Note: this is not the correct way to do this, this - * uninitializes and reinitializes EVERY driver - */ - printk("disconnecting driverless device\n"); - dev->driver->disconnect(dev); - dev->driver=NULL; - /* This will go back through the list looking for a driver - * that can handle the device - */ - usb_device_descriptor(dev); - } + + if (!dev) { + printk(KERN_ERR "usbcore: null device being purged!!!\n"); + return; + } + + for (i=0; ichildren[i]) + usb_driver_purge(driver, dev->children[i]); + + /* now we check this device */ + if (dev->driver == driver) { + /* + * Note: this is not the correct way to do this, this + * uninitializes and reinitializes EVERY driver + */ + printk(KERN_INFO "disconnect driverless device %d\n", + dev->devnum); + dev->driver->disconnect(dev); + dev->driver = NULL; + + /* + * This will go back through the list looking for a driver + * that can handle the device + */ + usb_find_driver(dev); + } } /* * New functions for (de)registering a controller */ +struct usb_bus *usb_alloc_bus(struct usb_operations *op) +{ + struct usb_bus *bus; + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return NULL; + + memset(&bus->devmap, 0, sizeof(struct usb_devmap)); + + bus->op = op; + bus->root_hub = NULL; + bus->hcpriv = NULL; + + INIT_LIST_HEAD(&bus->bus_list); + + return bus; +} + +void usb_free_bus(struct usb_bus *bus) +{ + if (!bus) + return; + + if (bus->bus_list.next != &bus->bus_list) + printk(KERN_ERR "usbcore: freeing non-empty bus\n"); + + kfree(bus); +} + void usb_register_bus(struct usb_bus *new_bus) { - /* Add it to the list of buses */ - list_add(&new_bus->bus_list, &usb_bus_list); - printk("New bus registered\n"); + /* Add it to the list of buses */ + list_add(&new_bus->bus_list, &usb_bus_list); + printk("New USB bus registered\n"); } void usb_deregister_bus(struct usb_bus *bus) { - /* NOTE: make sure that all the devices are removed by the - * controller code, as well as having it call this when cleaning + /* + * NOTE: make sure that all the devices are removed by the + * controller code, as well as having it call this when cleaning * itself up - */ + */ list_del(&bus->bus_list); } @@ -141,18 +187,20 @@ */ void usb_check_support(struct usb_device *dev) { - int i; - if (dev==NULL) - { - printk("null device being passed in!!!\n"); - return; - } - for (i=0;ichildren[i]!=NULL) - usb_check_support(dev->children[i]); - /*now we check this device*/ - if (dev->driver==NULL) - usb_device_descriptor(dev); + int i; + + if (!dev) { + printk(KERN_ERR "usbcore: null device being checked!!!\n"); + return; + } + + for (i=0; ichildren[i]) + usb_check_support(dev->children[i]); + + /* now we check this device */ + if (!dev->driver && dev->devnum > 0) + usb_find_driver(dev); } /* * This entrypoint gets called for each new device. @@ -161,7 +209,7 @@ * looking for one that will accept this device as * his.. */ -int usb_device_descriptor(struct usb_device *dev) +int usb_find_driver(struct usb_device *dev) { struct list_head *tmp = usb_driver_list.next; @@ -174,6 +222,7 @@ dev->driver = driver; return 1; } + /* * Ok, no driver accepted the device, so show the info * for debugging.. @@ -243,8 +292,7 @@ if (len <= 0) return -1; - if (n_len < 2 || n_len > len) - { + if (n_len < 2 || n_len > len) { int i; printk("Short descriptor. (%d, %d):\n", len, n_len); for (i = 0; i < len; ++i) @@ -272,8 +320,7 @@ parsed += ptr[parsed]; len -= parsed; - while((i = usb_check_descriptor(ptr+parsed, len, 0x25))>=0) - { + while((i = usb_check_descriptor(ptr+parsed, len, 0x25)) >= 0) { usb_audio_endpoint(endpoint, ptr+parsed+i); len -= ptr[parsed+i]; parsed += ptr[parsed+i]; @@ -295,23 +342,20 @@ len -= ptr[parsed]; parsed += ptr[parsed]; - while((i=usb_check_descriptor(ptr+parsed, len, 0x24))>=0) - { + while((i=usb_check_descriptor(ptr+parsed, len, 0x24)) >= 0) { usb_audio_interface(interface, ptr+parsed+i); len -= ptr[parsed+i]; parsed += ptr[parsed+i]; } - if (interface->bNumEndpoints > USB_MAXENDPOINTS) - { + if (interface->bNumEndpoints > USB_MAXENDPOINTS) { printk(KERN_WARNING "usb: too many endpoints.\n"); return -1; } interface->endpoint = (struct usb_endpoint_descriptor *) kmalloc(interface->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL); - if(interface->endpoint==NULL) - { + if (!interface->endpoint) { printk(KERN_WARNING "usb: out of memory.\n"); return -1; } @@ -323,7 +367,8 @@ // len -= 9; // } retval = usb_parse_endpoint(dev, interface->endpoint + i, ptr + parsed, len); - if (retval < 0) return retval; + if (retval < 0) + return retval; parsed += retval; len -= retval; } @@ -345,13 +390,7 @@ parsed += *ptr; le16_to_cpus(&config->wTotalLength); - if (config->MaxPower == 200) { - printk("bNumInterfaces kludge\n"); - config->bNumInterfaces += 3; - } - - if (config->bNumInterfaces > USB_MAXINTERFACES) - { + if (config->bNumInterfaces > USB_MAXINTERFACES) { printk(KERN_WARNING "usb: too many interfaces.\n"); return -1; @@ -359,17 +398,16 @@ config->altsetting = (struct usb_alternate_setting *) kmalloc(USB_MAXALTSETTING * sizeof(struct usb_alternate_setting), GFP_KERNEL); - if (config->altsetting == NULL) { - printk(KERN_WARNING "usb: out of memory.\n"); - return -1; + if (!config->altsetting) { + printk(KERN_WARNING "usb: out of memory.\n"); + return -1; } config->act_altsetting = 0; config->num_altsetting = 1; config->altsetting->interface = (struct usb_interface_descriptor *) kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL); - if(config->altsetting->interface==NULL) - { + if (!config->altsetting->interface) { printk(KERN_WARNING "usb: out of memory.\n"); return -1; } @@ -389,26 +427,26 @@ // now parse for additional alternate settings for (j = 1; j < USB_MAXALTSETTING; j++) { - retval = usb_expect_descriptor(ptr + parsed, len, USB_DT_INTERFACE, 9); - if (retval) - break; - config->num_altsetting++; - as = config->altsetting + j; - as->interface = (struct usb_interface_descriptor *) - kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL); - if (as->interface == NULL) { - printk(KERN_WARNING "usb: out of memory.\n"); - return -1; - } - memset(as->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface_descriptor)); - for (i = 0; i < config->bNumInterfaces; i++) { - retval = usb_parse_interface(dev, as->interface + i, + retval = usb_expect_descriptor(ptr + parsed, len, USB_DT_INTERFACE, 9); + if (retval) + break; + config->num_altsetting++; + as = config->altsetting + j; + as->interface = (struct usb_interface_descriptor *) + kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL); + if (!as->interface) { + printk(KERN_WARNING "usb: out of memory.\n"); + return -1; + } + memset(as->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface_descriptor)); + for (i = 0; i < config->bNumInterfaces; i++) { + retval = usb_parse_interface(dev, as->interface + i, ptr + parsed, len); - if (retval < 0) - return parsed; - parsed += retval; - len -= retval; - } + if (retval < 0) + return parsed; + parsed += retval; + len -= retval; + } } return parsed; } @@ -418,16 +456,14 @@ int i; unsigned char *ptr = __buf; - if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) - { + if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { printk(KERN_WARNING "usb: too many configurations.\n"); return -1; } dev->config = (struct usb_config_descriptor *) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL); - if(dev->config==NULL) - { + if (!dev->config) { printk(KERN_WARNING "usb: out of memory.\n"); return -1; } @@ -451,21 +487,18 @@ struct usb_alternate_setting *as; struct usb_interface_descriptor *ifp; - if(dev->config==NULL) + if (!dev->config) return; - for(c = 0; c < dev->descriptor.bNumConfigurations; c++) - { + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { cf = &dev->config[c]; - if (cf->altsetting == NULL) + if (!cf->altsetting) break; - for (a = 0; a < cf->num_altsetting; a++) - { + for (a = 0; a < cf->num_altsetting; a++) { as = &cf->altsetting[a]; if (as->interface == NULL) break; - for(i=0;ibNumInterfaces;i++) - { + for(i=0;ibNumInterfaces;i++) { ifp = &as->interface[i]; if(ifp->endpoint==NULL) break; @@ -609,45 +642,6 @@ return ret; } -int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) -{ - devrequest dr; - - dr.requesttype = USB_RT_HUB | 0x80; - dr.request = USB_REQ_GET_DESCRIPTOR; - dr.value = (USB_DT_HUB << 8); - dr.index = 0; - dr.length = size; - - return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, size); -} - -int usb_clear_port_feature(struct usb_device *dev, int port, int feature) -{ - devrequest dr; - - dr.requesttype = USB_RT_PORT; - dr.request = USB_REQ_CLEAR_FEATURE; - dr.value = feature; - dr.index = port; - dr.length = 0; - - return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); -} - -int usb_set_port_feature(struct usb_device *dev, int port, int feature) -{ - devrequest dr; - - dr.requesttype = USB_RT_PORT; - dr.request = USB_REQ_SET_FEATURE; - dr.value = feature; - dr.index = port; - dr.length = 0; - - return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); -} - int usb_get_status (struct usb_device *dev, int type, int target, void *data) { devrequest dr; @@ -661,32 +655,6 @@ return dev->bus->op->control_msg (dev, usb_rcvctrlpipe (dev,0), &dr, data, 2); } -int usb_get_hub_status(struct usb_device *dev, void *data) -{ - devrequest dr; - - dr.requesttype = USB_RT_HUB | 0x80; - dr.request = USB_REQ_GET_STATUS; - dr.value = 0; - dr.index = 0; - dr.length = 4; - - return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4); -} - -int usb_get_port_status(struct usb_device *dev, int port, void *data) -{ - devrequest dr; - - dr.requesttype = USB_RT_PORT | 0x80; - dr.request = USB_REQ_GET_STATUS; - dr.value = 0; - dr.index = port; - dr.length = 4; - - return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4); -} - int usb_get_protocol(struct usb_device *dev) { unsigned char buf[8]; @@ -741,21 +709,19 @@ static void usb_set_maxpacket(struct usb_device *dev) { int i; - struct usb_endpoint_descriptor *ep; int act_as = dev->actconfig->act_altsetting; struct usb_alternate_setting *as = dev->actconfig->altsetting + act_as; - struct usb_interface_descriptor *ip = as->interface; for (i=0; iactconfig->bNumInterfaces; i++) { - if (as->interface[i].bInterfaceNumber == dev->ifnum) { - ip = &as->interface[i]; - break; + struct usb_interface_descriptor *ip = &as->interface[i]; + struct usb_endpoint_descriptor *ep = ip->endpoint; + int e; + + for (e=0; ebNumEndpoints; e++) { + dev->epmaxpacket[ep[e].bEndpointAddress & 0x0f] = + ep[e].wMaxPacketSize; } } - ep = ip->endpoint; - for (i=0; ibNumEndpoints; i++) { - dev->epmaxpacket[ep[i].bEndpointAddress & 0x0f] = ep[i].wMaxPacketSize; - } } int usb_clear_halt(struct usb_device *dev, int endp) @@ -776,9 +742,8 @@ result = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0); /* dont clear if failed */ - if (result) { + if (result) return result; - } #if 1 /* lets be really tough */ dr.requesttype = 0x80 | USB_RT_ENDPOINT; @@ -788,12 +753,10 @@ result = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, &status, 2); - if (result) { + if (result) return result; - } - if (status & 1) { + if (status & 1) return 1; /* still halted */ - } #endif usb_endpoint_running(dev, endp & 0x0f); @@ -1014,37 +977,27 @@ * and is in the default state. We need to identify the thing and * get the ball rolling.. */ -void usb_new_device(struct usb_device *dev) +int usb_new_device(struct usb_device *dev) { - int addr, i; + int addr; - printk("USB new device connect, assigned device number %d\n", + printk(KERN_INFO "USB new device connect, assigned device number %d\n", dev->devnum); dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ dev->epmaxpacket[0] = 8; + /* We still haven't set the Address yet */ addr = dev->devnum; dev->devnum = 0; -#if 1 /* Slow devices */ - for (i = 0; i < 5; i++) { - if (!usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) - break; - - printk("get_descriptor failed, waiting\n"); - wait_ms(200); - } - if (i == 5) { - printk("giving up\n"); - return; + if (usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) { + printk(KERN_ERR "USB device not responding, giving up\n"); + dev->devnum = -1; + return 1; } -#endif -#if 0 - printk("maxpacketsize: %d\n", dev->descriptor.bMaxPacketSize0); -#endif dev->epmaxpacket[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { case 8: dev->maxpacketsize = 0; break; @@ -1052,36 +1005,29 @@ case 32: dev->maxpacketsize = 2; break; case 64: dev->maxpacketsize = 3; break; } -#if 0 - printk("dev->mps: %d\n", dev->maxpacketsize); -#endif dev->devnum = addr; -#if 1 if (usb_set_address(dev)) { - printk("Unable to set address\n"); - /* FIXME: We should disable the port */ - return; + printk(KERN_ERR "USB device not accepting new address\n"); + dev->devnum = -1; + return 1; } -#else - usb_set_address(dev); -#endif wait_ms(10); /* Let the SET_ADDRESS settle */ if (usb_get_device_descriptor(dev)) { - printk("Unable to get device descriptor\n"); - return; + printk(KERN_ERR "Unable to get device descriptor\n"); + dev->devnum = -1; + return 1; } if (usb_get_configuration(dev)) { - printk("Unable to get configuration\n"); - return; + printk(KERN_ERR "Unable to get configuration\n"); + dev->devnum = -1; + return 1; } - /* usb_get_stringtable(dev); */ - dev->actconfig = dev->config; dev->ifnum = 0; usb_set_maxpacket(dev); @@ -1090,20 +1036,16 @@ usb_show_string(dev, "Product", dev->descriptor.iProduct); usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); -#if 0 - printk("Vendor: %X\n", dev->descriptor.idVendor); - printk("Product: %X\n", dev->descriptor.idProduct); -#endif - - if (usb_device_descriptor(dev)==0) - { + if (!usb_find_driver(dev)) { /* * Ok, no driver accepted the device, so show the info for * debugging */ - printk ("Unknown new USB device:\n"); + printk(KERN_DEBUG "Unknown new USB device:\n"); usb_show_device(dev); } + + return 0; } void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id) @@ -1111,6 +1053,15 @@ return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id); } +void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id) +{ + return dev->bus->op->request_bulk(dev, pipe, handler, data, len, dev_id); +} + +int usb_terminate_bulk(struct usb_device *dev, void *first) +{ + return dev->bus->op->terminate_bulk(dev, first); +} void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id) { diff -u --recursive --new-file v2.3.12/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.12/linux/drivers/usb/usb.h Wed Jul 28 14:47:42 1999 +++ linux/drivers/usb/usb.h Mon Aug 9 11:27:39 1999 @@ -290,6 +290,9 @@ int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *); void* (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *); int (*release_irq)(void* handle); + void *(*request_bulk)(struct usb_device *, unsigned int, usb_device_irq, + void *, int, void *); + int (*terminate_bulk)(struct usb_device *, void *); void *(*alloc_isoc)(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id); void (*delete_isoc)(struct usb_device *dev, void *_isodesc); int (*sched_isoc)(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc); @@ -346,17 +349,22 @@ extern int usb_register(struct usb_driver *); extern void usb_deregister(struct usb_driver *); +extern struct usb_bus *usb_alloc_bus(struct usb_operations *); +extern void usb_free_bus(struct usb_bus *); extern void usb_register_bus(struct usb_bus *); extern void usb_deregister_bus(struct usb_bus *); extern void* usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *); extern int usb_release_irq(struct usb_device *dev, void *handle); +extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *); +extern int usb_terminate_bulk(struct usb_device *, void *); + extern void usb_init_root_hub(struct usb_device *dev); extern void usb_connect(struct usb_device *dev); extern void usb_disconnect(struct usb_device **); -extern int usb_device_descriptor(struct usb_device *dev); +extern int usb_find_driver(struct usb_device *dev); void usb_check_support(struct usb_device *); void usb_driver_purge(struct usb_driver *,struct usb_device *); extern int usb_parse_configuration(struct usb_device *dev, void *buf, int len); @@ -453,17 +461,12 @@ /* * Send and receive control messages.. */ -void usb_new_device(struct usb_device *dev); +int usb_new_device(struct usb_device *dev); int usb_set_address(struct usb_device *dev); int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); int usb_get_device_descriptor(struct usb_device *dev); -int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size); -int usb_clear_port_feature(struct usb_device *dev, int port, int feature); -int usb_set_port_feature(struct usb_device *dev, int port, int feature); int usb_get_status (struct usb_device *dev, int type, int target, void *data); -int usb_get_hub_status(struct usb_device *dev, void *data); -int usb_get_port_status(struct usb_device *dev, int port, void *data); int usb_get_protocol(struct usb_device *dev); int usb_set_protocol(struct usb_device *dev, int protocol); int usb_set_interface(struct usb_device *dev, int interface, int alternate); diff -u --recursive --new-file v2.3.12/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c --- v2.3.12/linux/drivers/usb/uss720.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/uss720.c Mon Aug 9 12:15:53 1999 @@ -0,0 +1,678 @@ +/*****************************************************************************/ + +/* + * uss720.c -- USS720 USB Parport Cable. + * + * Copyright (C) 1999 + * Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based on parport_pc.c + * + * History: + * 0.1 04.08.99 Created + * 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh + * Interrupt handling currently disabled because + * usb_request_irq crashes somewhere within ohci.c + * for no apparent reason (that is for me, anyway) + * ECP currently untested + * + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "usb.h" + +/* --------------------------------------------------------------------- */ + +struct parport_uss720_private { + struct usb_device *usbdev; + void *irqhandle; + unsigned char reg[7]; /* USB registers */ +}; + +/* --------------------------------------------------------------------- */ + +static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val) +{ + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + static const unsigned char regindex[9] = { + 4, 0, 1, 5, 5, 0, 2, 3, 6 + }; + devrequest dr; + int ret; + + if (!usbdev) + return -1; + dr.requesttype = 0xc0; + dr.request = 3; + dr.value = ((unsigned int)reg) << 8; + dr.index = 0; + dr.length = 7; + ret = usbdev->bus->op->control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), &dr, priv->reg, 7); + if (ret) { + printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x\n", + (unsigned int)reg, ret); + } else { +#if 0 + printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], + (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], + (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]); +#endif + /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ + if (priv->reg[2] & priv->reg[1] & 0x10) + parport_generic_irq(0, pp, NULL); + } + if (val) + *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]]; + return ret; +} + +static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val) +{ + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + devrequest dr; + int ret; + + if (!usbdev) + return -1; + dr.requesttype = 0x40; + dr.request = 4; + dr.value = (((unsigned int)reg) << 8) | val; + dr.index = 0; + dr.length = 0; + ret = usbdev->bus->op->control_msg(usbdev, usb_sndctrlpipe(usbdev,0), &dr, NULL, 0); + if (ret) { + printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", + (unsigned int)reg, (unsigned int)val, ret); + } else { +#if 0 + printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", + (unsigned int)reg, (unsigned int)val); +#endif + } + return ret; +} + +/* --------------------------------------------------------------------- */ + +/* ECR modes */ +#define ECR_SPP 00 +#define ECR_PS2 01 +#define ECR_PPF 02 +#define ECR_ECP 03 +#define ECR_EPP 04 + +/* Safely change the mode bits in the ECR */ +static int change_mode(struct parport *pp, int m) +{ + struct parport_uss720_private *priv = pp->private_data; + int mode; + + if (get_1284_register(pp, 6, NULL)) + return -EIO; + /* Bits <7:5> contain the mode. */ + mode = (priv->reg[2] >> 5) & 0x7; + if (mode == m) + return 0; + /* We have to go through mode 000 or 001 */ + if (mode > ECR_PS2 && m > ECR_PS2) + if (change_mode(pp, ECR_PS2)) + return -EIO; + + if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) { + /* This mode resets the FIFO, so we may + * have to wait for it to drain first. */ + long expire = jiffies + pp->physport->cad->timeout; + switch (mode) { + case ECR_PPF: /* Parallel Port FIFO mode */ + case ECR_ECP: /* ECP Parallel Port mode */ + /* Poll slowly. */ + for (;;) { + if (get_1284_register(pp, 6, NULL)) + return -EIO; + if (priv->reg[2] & 0x01) + break; + if (time_after_eq (jiffies, expire)) + /* The FIFO is stuck. */ + return -EBUSY; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((HZ + 99) / 100); + if (signal_pending (current)) + break; + } + } + } + /* Set the mode. */ + if (set_1284_register(pp, 6, m << 5)) + return -EIO; + return 0; +} + +/* + * Clear TIMEOUT BIT in EPP MODE + */ +static int clear_epp_timeout(struct parport *pp) +{ + unsigned char stat; + + if (get_1284_register(pp, 1, &stat)) + return 1; + return stat & 1; +} + +/* + * Access functions. + */ + +static void parport_uss720_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ +} + +static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id) +{ + struct parport *pp = (struct parport *)dev_id; + struct parport_uss720_private *priv = pp->private_data; + + if (usbstatus != USB_ST_NOERROR || len < 4 || !buffer) + return 1; + memcpy(priv->reg, buffer, 4); + /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */ + if (priv->reg[2] & priv->reg[1] & 0x10) + parport_generic_irq(0, pp, NULL); + return 1; +} + +static void parport_uss720_write_data(struct parport *pp, unsigned char d) +{ + set_1284_register(pp, 0, d); +} + +static unsigned char parport_uss720_read_data(struct parport *pp) +{ + unsigned char ret; + + if (get_1284_register(pp, 0, &ret)) + return 0; + return ret; +} + +static void parport_uss720_write_control(struct parport *pp, unsigned char d) +{ + struct parport_uss720_private *priv = pp->private_data; + + d = (d & 0xf) | (priv->reg[1] & 0xf0); + if (set_1284_register(pp, 2, d)) + return; + priv->reg[1] = d; +} + +static unsigned char parport_uss720_read_control(struct parport *pp) +{ + struct parport_uss720_private *priv = pp->private_data; + return priv->reg[1] & 0xf; /* Use soft copy */ +} + +static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val) +{ + struct parport_uss720_private *priv = pp->private_data; + unsigned char d; + + mask &= 0x0f; + val &= 0x0f; + d = (priv->reg[1] & (~mask)) ^ val; + if (set_1284_register(pp, 2, d)) + return 0; + priv->reg[1] = d; + return d & 0xf; +} + +static unsigned char parport_uss720_read_status(struct parport *pp) +{ + unsigned char ret; + + if (get_1284_register(pp, 1, &ret)) + return 0; + return ret & 0xf8; +} + +static void parport_uss720_disable_irq(struct parport *pp) +{ + struct parport_uss720_private *priv = pp->private_data; + unsigned char d; + + d = priv->reg[1] & ~0x10; + if (set_1284_register(pp, 2, d)) + return; + priv->reg[1] = d; +} + +static void parport_uss720_enable_irq(struct parport *pp) +{ + struct parport_uss720_private *priv = pp->private_data; + unsigned char d; + + d = priv->reg[1] | 0x10; + if (set_1284_register(pp, 2, d)) + return; + priv->reg[1] = d; +} + +static void parport_uss720_data_forward (struct parport *pp) +{ + struct parport_uss720_private *priv = pp->private_data; + unsigned char d; + + d = priv->reg[1] & ~0x20; + if (set_1284_register(pp, 2, d)) + return; + priv->reg[1] = d; +} + +static void parport_uss720_data_reverse (struct parport *pp) +{ + struct parport_uss720_private *priv = pp->private_data; + unsigned char d; + + d = priv->reg[1] | 0x20; + if (set_1284_register(pp, 2, d)) + return; + priv->reg[1] = d; +} + +static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s) +{ + s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); + s->u.pc.ecr = 0x24; +} + +static void parport_uss720_save_state(struct parport *pp, struct parport_state *s) +{ + struct parport_uss720_private *priv = pp->private_data; + + if (get_1284_register(pp, 2, NULL)) + return; + s->u.pc.ctr = priv->reg[1]; + s->u.pc.ecr = priv->reg[2]; +} + +static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s) +{ + set_1284_register(pp, 2, s->u.pc.ctr); + set_1284_register(pp, 6, s->u.pc.ecr); + get_1284_register(pp, 2, NULL); +} + +static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + size_t got = 0; + + if (change_mode(pp, ECR_EPP)) + return 0; + for (; got < length; got++) { + if (get_1284_register(pp, 4, (char *)buf)) + break; + ((char*)buf)++; + if (priv->reg[0] & 0x01) { + clear_epp_timeout(pp); + break; + } + } + change_mode(pp, ECR_PS2); + return got; +} + +static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags) +{ +#if 0 + struct parport_uss720_private *priv = pp->private_data; + size_t written = 0; + + if (change_mode(pp, ECR_EPP)) + return 0; + for (; written < length; written++) { + if (set_1284_register(pp, 4, (char *)buf)) + break; + ((char*)buf)++; + if (get_1284_register(pp, 1, NULL)) + break; + if (priv->reg[0] & 0x01) { + clear_epp_timeout(pp); + break; + } + } + change_mode(pp, ECR_PS2); + return written; +#else + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + unsigned long rlen; + int i; + + if (!usbdev) + return 0; + if (change_mode(pp, ECR_EPP)) + return 0; + i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buf, length, &rlen); + if (i) + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen); + change_mode(pp, ECR_PS2); + return rlen; +#endif +} + +static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + size_t got = 0; + + if (change_mode(pp, ECR_EPP)) + return 0; + for (; got < length; got++) { + if (get_1284_register(pp, 3, (char *)buf)) + break; + ((char*)buf)++; + if (priv->reg[0] & 0x01) { + clear_epp_timeout(pp); + break; + } + } + change_mode(pp, ECR_PS2); + return got; +} + +static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + size_t written = 0; + + if (change_mode(pp, ECR_EPP)) + return 0; + for (; written < length; written++) { + if (set_1284_register(pp, 3, *(char *)buf)) + break; + ((char*)buf)++; + if (get_1284_register(pp, 1, NULL)) + break; + if (priv->reg[0] & 0x01) { + clear_epp_timeout(pp); + break; + } + } + change_mode(pp, ECR_PS2); + return written; +} + +static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + unsigned long rlen; + int i; + + if (!usbdev) + return 0; + if (change_mode(pp, ECR_ECP)) + return 0; + i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen); + if (i) + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); + change_mode(pp, ECR_PS2); + return rlen; +} + +static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + unsigned long rlen; + int i; + + if (!usbdev) + return 0; + if (change_mode(pp, ECR_ECP)) + return 0; + i = usbdev->bus->op->bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen); + if (i) + printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %u rlen %lu\n", buffer, len, rlen); + change_mode(pp, ECR_PS2); + return rlen; +} + +static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags) +{ + size_t written = 0; + + if (change_mode(pp, ECR_ECP)) + return 0; + for (; written < len; written++) { + if (set_1284_register(pp, 5, *(char *)buffer)) + break; + ((char*)buffer)++; + } + change_mode(pp, ECR_PS2); + return written; +} + +static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags) +{ + struct parport_uss720_private *priv = pp->private_data; + struct usb_device *usbdev = priv->usbdev; + unsigned long rlen; + int i; + + if (!usbdev) + return 0; + if (change_mode(pp, ECR_PPF)) + return 0; + i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen); + if (i) + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); + change_mode(pp, ECR_PS2); + return rlen; +} + +void parport_uss720_inc_use_count(void) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +void parport_uss720_dec_use_count(void) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + +/* --------------------------------------------------------------------- */ + +static struct parport_operations parport_uss720_ops = +{ + parport_uss720_write_data, + parport_uss720_read_data, + + parport_uss720_write_control, + parport_uss720_read_control, + parport_uss720_frob_control, + + parport_uss720_read_status, + + parport_uss720_enable_irq, + parport_uss720_disable_irq, + + parport_uss720_data_forward, + parport_uss720_data_reverse, + + parport_uss720_init_state, + parport_uss720_save_state, + parport_uss720_restore_state, + + parport_uss720_inc_use_count, + parport_uss720_dec_use_count, + + parport_uss720_epp_write_data, + parport_uss720_epp_read_data, + parport_uss720_epp_write_addr, + parport_uss720_epp_read_addr, + + parport_uss720_ecp_write_data, + parport_uss720_ecp_read_data, + parport_uss720_ecp_write_addr, + + parport_uss720_write_compat, + parport_ieee1284_read_nibble, + parport_ieee1284_read_byte, +}; + +/* --------------------------------------------------------------------- */ + +static int uss720_probe(struct usb_device *usbdev) +{ + struct usb_interface_descriptor *interface; + struct usb_endpoint_descriptor *endpoint; + struct parport_uss720_private *priv; + struct parport *pp; + int i; + + printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); + + if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) && + (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001)) + return -1; + + /* We don't handle multiple configurations */ + if (usbdev->descriptor.bNumConfigurations != 1) + return -1; + + /* We don't handle multiple interfaces */ + if (usbdev->config[0].bNumInterfaces != 1) + return -1; + + /* We don't handle multiple interfaces */ + if (usbdev->config[0].num_altsetting != 3) + return -1; + + printk(KERN_DEBUG "uss720: set configuration\n"); + usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue); + + i = usb_set_interface(usbdev, 0, 2); + printk(KERN_DEBUG "uss720: set inteface result %d\n", i); + + interface = &usbdev->config[0].altsetting[2].interface[0]; + + //printk(KERN_DEBUG "uss720: get interface\n"); + //i = usb_get_interface(usbdev, 0); + //printk(KERN_DEBUG "uss720: is in alternate setting %d\n", i); + + /* + * Allocate parport interface + */ + printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, \n"); + + if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) + return -1; + if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) { + kfree(priv); + return -1; + } + pp->private_data = priv; + usbdev->private = pp; + priv->usbdev = usbdev; + pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT; + + /* set the USS720 control register to manual mode, no ECP compression, enable all ints */ + set_1284_register(pp, 7, 0x00); + set_1284_register(pp, 6, 0x30); /* PS/2 mode */ + set_1284_register(pp, 2, 0x0c); + /* debugging */ + get_1284_register(pp, 0, NULL); + printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n", + priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]); + + endpoint = &interface->endpoint[2]; + printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->bEndpointAddress, endpoint->bInterval); +#if 0 + priv->irqhandle = usb_request_irq(usbdev, usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress), + uss720_irq, endpoint->bInterval, pp); +#endif + parport_proc_register(pp); + parport_announce_port(pp); + + MOD_INC_USE_COUNT; + return 0; +} + +static void uss720_disconnect(struct usb_device *usbdev) +{ + struct parport *pp = (struct parport *)usbdev->private; + struct parport_uss720_private *priv = pp->private_data; + +#if 0 + usb_release_irq(usbdev, priv->irqhandle); +#endif + usbdev->private = NULL; + priv->usbdev = NULL; + parport_proc_unregister(pp); + parport_unregister_port(pp); + kfree(priv); + MOD_DEC_USE_COUNT; +} + +static struct usb_driver uss720_driver = { + "uss720", + uss720_probe, + uss720_disconnect, + { NULL, NULL } +}; + +/* --------------------------------------------------------------------- */ + +#define __exit +#define module_exit(x) void cleanup_module(void) { x(); } +#define module_init(x) int init_module(void) { return x(); } + +/* --------------------------------------------------------------------- */ + +static int __init uss720_init(void) +{ + usb_register(&uss720_driver); + printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.2 registered.\n" + KERN_INFO "uss720: (C) 1999 by Thomas Sailer, \n"); + return 0; +} + +static void __exit uss720_cleanup(void) +{ + usb_deregister(&uss720_driver); +} + +module_init(uss720_init); +module_exit(uss720_cleanup); + +/* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.3.12/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.3.12/linux/drivers/video/Config.in Thu May 13 23:48:20 1999 +++ linux/drivers/video/Config.in Mon Aug 9 11:56:25 1999 @@ -49,7 +49,7 @@ fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Atari native chipset support' CONFIG_FB_ATARI - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY fi if [ "$CONFIG_PPC" = "y" ]; then bool 'Open Firmware frame buffer device support' CONFIG_FB_OF @@ -57,11 +57,12 @@ bool 'Apple "control" display support' CONFIG_FB_CONTROL bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT bool 'Chips 65550 display support' CONFIG_FB_CT65550 bool 'S3 Trio display support' CONFIG_FB_S3TRIO fi + tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16 fi if [ "$CONFIG_MAC" = "y" ]; then define_bool CONFIG_FB_MAC y @@ -74,7 +75,7 @@ fi if [ "$ARCH" = "i386" ]; then bool 'VESA VGA graphics console' CONFIG_FB_VESA - bool 'VGA 16-color graphics console' CONFIG_FB_VGA16 + tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16 define_bool CONFIG_VIDEO_SELECT y fi if [ "$CONFIG_VISWS" = "y" ]; then @@ -86,10 +87,10 @@ if [ "$CONFIG_FB_MATROX" != "n" ]; then bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM bool ' Mystique support' CONFIG_FB_MATROX_MYSTIQUE - bool ' G100/G200 support' CONFIG_FB_MATROX_G100 + bool ' G100/G200/G400 support' CONFIG_FB_MATROX_G100 bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY fi fi if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then @@ -120,7 +121,7 @@ if [ "$CONFIG_PCI" != "n" ]; then bool 'PCI framebuffers' CONFIG_FB_PCI if [ "$CONFIG_FB_PCI" != "n" ]; then - bool ' ATI Mach64 display support' CONFIG_FB_ATY + tristate ' ATI Mach64 display support' CONFIG_FB_ATY fi fi fi @@ -142,7 +143,7 @@ tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 # tristate 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC - bool 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES + tristate 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA else # Guess what we need @@ -287,6 +288,10 @@ fi if [ "$CONFIG_FB_VGA16" = "y" ]; then define_bool CONFIG_FBCON_VGA_PLANES y + else + if [ "$CONFIG_FB_VGA16" = "m" ]; then + define_bool CONFIG_FBCON_VGA_PLANES m + fi fi if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then define_bool CONFIG_FBCON_VGA y diff -u --recursive --new-file v2.3.12/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.3.12/linux/drivers/video/Makefile Thu Jul 8 15:42:21 1999 +++ linux/drivers/video/Makefile Mon Aug 9 11:39:37 1999 @@ -102,6 +102,10 @@ ifeq ($(CONFIG_FB_ATY),y) L_OBJS += atyfb.o +else + ifeq ($(CONFIG_FB_ATY),m) + M_OBJS += atyfb.o + endif endif ifeq ($(CONFIG_FB_IGA),y) @@ -206,6 +210,10 @@ ifeq ($(CONFIG_FB_VGA16),y) L_OBJS += vga16fb.o +else + ifeq ($(CONFIG_FB_VGA16),m) + M_OBJS += vga16fb.o + endif endif ifeq ($(CONFIG_FB_VIRGE),y) diff -u --recursive --new-file v2.3.12/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c --- v2.3.12/linux/drivers/video/S3triofb.c Thu Oct 1 10:02:21 1998 +++ linux/drivers/video/S3triofb.c Mon Aug 9 10:25:01 1999 @@ -288,7 +288,7 @@ return -EINVAL; } -__initfunc(void s3triofb_init(void)) +void __init s3triofb_init(void) { #ifdef __powerpc__ /* We don't want to be called like this. */ @@ -298,7 +298,7 @@ #endif /* !__powerpc__ */ } -__initfunc(void s3trio_resetaccel(void)) { +void __init s3trio_resetaccel(void){ #define EC01_ENH_ENB 0x0005 @@ -341,7 +341,7 @@ outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX, 0xbee8); } -__initfunc(int s3trio_init(struct device_node *dp)) { +int __init s3trio_init(struct device_node *dp){ u_char bus, dev; unsigned int t32; @@ -402,7 +402,7 @@ * We heavily rely on OF for the moment. This needs fixing. */ -__initfunc(void s3triofb_init_of(struct device_node *dp)) +void __init s3triofb_init_of(struct device_node *dp) { int i, *pp, len; unsigned long address; diff -u --recursive --new-file v2.3.12/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c --- v2.3.12/linux/drivers/video/acornfb.c Thu Jun 17 01:11:35 1999 +++ linux/drivers/video/acornfb.c Mon Aug 9 10:25:01 1999 @@ -1429,8 +1429,8 @@ } }; -__initfunc(static int -acornfb_lookup_timing(struct fb_var_screeninfo *var)) +static int __init +acornfb_lookup_timing(struct fb_var_screeninfo *var) { const struct modex_params *x; const struct modey_params *y; @@ -1518,8 +1518,8 @@ return 0; } -__initfunc(static void -acornfb_init_fbinfo(void)) +static void __init +acornfb_init_fbinfo(void) { static int first = 1; @@ -1612,14 +1612,14 @@ * size can optionally be followed by 'M' or 'K' for * MB or KB respectively. */ -__initfunc(static void -acornfb_parse_font(char *opt)) +static void __init +acornfb_parse_font(char *opt) { strcpy(fb_info.fontname, opt); } -__initfunc(static void -acornfb_parse_mon(char *opt)) +static void __init +acornfb_parse_mon(char *opt) { fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0); if (*opt == '-') @@ -1652,8 +1652,8 @@ init_var.height = simple_strtoul(opt + 1, NULL, 0); } -__initfunc(static void -acornfb_parse_montype(char *opt)) +static void __init +acornfb_parse_montype(char *opt) { current_par.montype = -2; @@ -1694,8 +1694,8 @@ } } -__initfunc(static void -acornfb_parse_dram(char *opt)) +static void __init +acornfb_parse_dram(char *opt) { unsigned int size; @@ -1728,8 +1728,8 @@ { NULL, NULL } }; -__initfunc(void -acornfb_setup(char *options, int *ints)) +void __init +acornfb_setup(char *options, int *ints) { struct options *optp; char *opt; @@ -1765,8 +1765,8 @@ * Detect type of monitor connected * For now, we just assume SVGA */ -__initfunc(static int -acornfb_detect_monitortype(void)) +static int __init +acornfb_detect_monitortype(void) { return 4; } @@ -1802,8 +1802,8 @@ printk("acornfb: freed %dK memory\n", mb_freed); } -__initfunc(void -acornfb_init(void)) +void __init +acornfb_init(void) { unsigned long size; u_int h_sync, v_sync; diff -u --recursive --new-file v2.3.12/linux/drivers/video/amifb.c linux/drivers/video/amifb.c --- v2.3.12/linux/drivers/video/amifb.c Tue Jan 19 10:47:48 1999 +++ linux/drivers/video/amifb.c Mon Aug 9 10:25:01 1999 @@ -1259,8 +1259,7 @@ amifb_pan_display, amifb_ioctl }; - -__initfunc(void amifb_setup(char *options, int *ints)) +void __init amifb_setup(char *options, int *ints) { char *this_opt; char mcap_spec[80]; @@ -1715,7 +1714,7 @@ * Initialisation */ -__initfunc(void amifb_init(void)) +void __init amifb_init(void) { int tag, i; u_long chipptr; @@ -2053,7 +2052,7 @@ * Get a Video Mode */ -__initfunc(static void get_video_mode(const char *name)) +static void __init get_video_mode(const char *name) { int i; @@ -2070,7 +2069,7 @@ * Probe the Video Modes */ -__initfunc(static void check_default_mode(void)) +static void __init check_default_mode(void) { struct amifb_par par; int mode; @@ -2090,7 +2089,7 @@ * Allocate, Clear and Align a Block of Chip Memory */ -__initfunc(static u_long chipalloc(u_long size)) +static u_long __init chipalloc(u_long size) { u_long ptr; @@ -2107,7 +2106,7 @@ * A strtok which returns empty strings, too */ -__initfunc(static char *strtoke(char *s,const char *ct)) +static char __init *strtoke(char *s,const char *ct) { char *sbegin, *send; static char *ssave = NULL; @@ -3314,7 +3313,7 @@ * Initialise the Copper Initialisation List */ -__initfunc(static void ami_init_copper(void)) +static void __init ami_init_copper(void) { copins *cop = copdisplay.init; u_long p; diff -u --recursive --new-file v2.3.12/linux/drivers/video/atafb.c linux/drivers/video/atafb.c --- v2.3.12/linux/drivers/video/atafb.c Thu Feb 25 10:02:11 1999 +++ linux/drivers/video/atafb.c Mon Aug 9 11:39:38 1999 @@ -2745,7 +2745,7 @@ do_install_cmap(currcon, info); } -__initfunc(void atafb_init(void)) +void __init atafb_init(void) { int pad; int detected_mode; @@ -2828,9 +2828,12 @@ /* Map the video memory (physical address given) to somewhere * in the kernel address space. */ - external_addr = ioremap_writethrough(external_addr, external_len); + external_addr = + ioremap_writethrough((unsigned long)external_addr, + external_len); if (external_vgaiobase) - external_vgaiobase = ioremap(external_vgaiobase, 0x10000 ); + external_vgaiobase = + (unsigned long)ioremap(external_vgaiobase, 0x10000); screen_base = real_screen_base = external_addr; screen_len = external_len & PAGE_MASK; @@ -2892,7 +2895,7 @@ return sbegin; } -__initfunc(void atafb_setup( char *options, int *ints )) +void __init atafb_setup( char *options, int *ints ) { char *this_opt; int temp; @@ -3069,7 +3072,7 @@ external_yres = yres; external_depth = depth; external_pmode = planes; - external_addr = addr; + external_addr = (void *)addr; external_len = len; if (external_card_type == IS_MV300) diff -u --recursive --new-file v2.3.12/linux/drivers/video/aty.h linux/drivers/video/aty.h --- v2.3.12/linux/drivers/video/aty.h Wed Nov 25 14:53:50 1998 +++ linux/drivers/video/aty.h Mon Aug 9 11:39:37 1999 @@ -88,6 +88,8 @@ #define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 0_2D */ #define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 0_2E */ +#define I2C_CNTL_1 0x00BC /* Dword offset 0_2F */ + #define DAC_REGS 0x00C0 /* Dword offset 0_30 */ #define DAC_W_INDEX 0x00C0 /* Dword offset 0_30 */ #define DAC_DATA 0x00C1 /* Dword offset 0_30 */ diff -u --recursive --new-file v2.3.12/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.3.12/linux/drivers/video/atyfb.c Wed Jun 9 14:44:25 1999 +++ linux/drivers/video/atyfb.c Mon Aug 9 11:40:29 1999 @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $ +/* $Id: atyfb.c,v 1.109 1999/08/08 01:38:05 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -72,8 +72,8 @@ #ifdef __sparc__ #include #include -#include #endif +#include #include