diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/CREDITS linux.ac/CREDITS --- linux.vanilla/CREDITS Thu May 25 17:46:15 2000 +++ linux.ac/CREDITS Fri Jun 9 15:47:11 2000 @@ -38,10 +38,11 @@ S: Ireland N: Tigran A. Aivazian -E: tigran@ocston.org +E: tigran@veritas.com W: http://www.ocston.org/~tigran D: BFS filesystem D: Intel P6 CPU microcode update support +D: Various kernel patches S: United Kingdom N: Werner Almesberger @@ -407,8 +408,8 @@ N: Lennert Buytenhek E: buytenh@gnu.org D: Rewrite of the ethernet bridging code -S: Handelstraat 35 -S: 3131 EK Vlaardingen +S: Ravenhorst 58B +S: 2317 AK Leiden S: The Netherlands N: Michael Callahan @@ -970,7 +971,8 @@ D: Random SMP kernel hacker... D: Uniform Multi-Platform E-IDE driver D: Active-ATA-Chipset maddness.......... -D: Ultra DMA 66/33 +D: Ultra DMA 100/66/33 +D: ATA-Disconnect D: ATA-Smart Kernel Daemon S: Linux ATA Development (LAD) S: Concord, CA @@ -1109,6 +1111,14 @@ S: D-71679 Asperg S: Germany +N: Gareth Hughes +E: gareth@valinux.com +E: gareth@precisioninsight.com +D: Pentium III FXSR, SSE support +S: 11/187 West Street +S: Crows Nest NSW 2065 +S: Australia + N: Kenn Humborg E: kenn@wombat.ie D: Mods to loop device to support sparse backing files @@ -2102,6 +2112,15 @@ S: 9725 GA Groningen S: The Netherlands +N: Pekka Riikonen +E: priikone@poseidon.pspt.fi +E: priikone@ssh.com +D: Random kernel hacking and bug fixes +D: International kernel patch project +S: Kasarmikatu 11 A4 +S: 70110 Kuopio +S: Finland + N: William E. Roadcap E: roadcapw@cfw.com W: http://www.cfw.com/~roadcapw @@ -2155,6 +2174,14 @@ S: The Australian National University, ACT 0200 S: Australia +N: Aristeu Sergio Rozanski Filho +E: aris@conectiva.com.br +D: Support for EtherExpress 10 ISA (i82595) in eepro driver +S: Conectiva S.A. +S: R. Tocantins, 89 - Cristo Rei +S: 80050-430 - Curitiba - Paraná +S: Brazil + N: Alessandro Rubini E: rubini@ipvvis.unipv.it D: the gpm mouse server and kernel support for it @@ -2168,7 +2195,7 @@ N: Paul `Rusty' Russell E: rusty@linuxcare.com -W: http://www.rustcorp.com +W: http://www.samba.org/netfilter D: Ruggedly handsome. D: netfilter, ipchains with Michael Neuling. S: 301/222 City Walk @@ -2779,15 +2806,15 @@ S: The Netherlands N: David Woodhouse -E: David.Woodhouse@mvhi.com -E: Dave@imladris.demon.co.uk -D: Extensive ARCnet rewrite -D: ARCnet COM20020, COM90xx IO-MAP drivers -D: SO_BINDTODEVICE in 2.1.x (from Elliot Poger's code in 2.0.31) -D: Contributed to NCPFS rewrite for 2.1.x dcache -D: Alpha platforms: SX164, LX164 and Ruffian ported to 2.1.x -S: 29, David Bull Way -S: Milton, Cambridge. CB4 6DP +E: dwmw2@infradead.org +E: dwmw2@redhat.com +D: ARCnet stuff, Applicom board driver, SO_BINDTODEVICE, +D: some Alpha platform porting from 2.0, Memory Technology Devices, +D: Acquire watchdog timer, PC speaker driver maintenance, +D: various other stuff that annoyed me by not working. +S: c/o Red Hat UK Limited +S: 35-36 Cambridge Place +S: Cambridge. CB2 1NS S: England N: Frank Xia diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/Changes linux.ac/Documentation/Changes --- linux.vanilla/Documentation/Changes Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/Changes Tue Jun 6 16:13:53 2000 @@ -72,12 +72,17 @@ General Information =================== - To use System V shared memory, you have to mount the shm filesystem -somewhere. You can do that automatically by adding this line to /etc/fstab: + System V shared memory is now implemented via a filesystem. You do +not have to mount it to use it as long as you can live with the +default maxima for shared memory and segments. If you wish to change +these variables, you have to mount it with the options nr_blocks +and/or nr_inodes. If you want to use POSIX shm, then it needs to be +mounted somewhere. The recommended place is /dev/shm and this can be +done by adding the following line to /etc/fstab: -none /var/shm shm defaults 0 0 +none /dev/shm shm defaults 0 0 -Remember to create the mountpoint directory; it does not have to be /var/shm. +Remember to create the directory that you intend to mount shm on. now performs a cold reboot instead of a warm reboot for increased hardware compatibility. If you want a warm reboot and @@ -127,6 +132,14 @@ more information, see the files in Documentation/fb/ ; you may also need to download the fbset utilities. + Intel P6 microcode update driver can now be accessed both via devfs +regular file and as a normal (misc) character device. If you are not using +devfs you may need to: + + - mkdir /dev/cpu + - mknod /dev/cpu/microcode c 10 184 + - chmod 0644 /dev/cpu/microcode + Libc (libc5) ============ @@ -246,7 +259,7 @@ The IP firewalling and NAT code has been replaced again. The userspace tool `iptables' is distributed at: - http://antarctica.penguincomputing.com/~netfilter/ + http://netfilter.filewatcher.org http://www.samba.org/netfilter/ http://netfilter.kernelnotes.org @@ -740,7 +753,7 @@ ========= The 1.1.0 release: -http://antarctica.penguincomputing.com/~netfilter/iptables-1.1.0.tar.bz2 +http://netfilter.filewatcher.org/iptables-1.1.0.tar.bz2 http://www.samba.org/netfilter/iptables-1.1.0.tar.bz2 http://netfilter.kernelnotes.org/iptables-1.1.0.tar.bz2 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/Configure.help linux.ac/Documentation/Configure.help --- linux.vanilla/Documentation/Configure.help Thu May 25 17:46:15 2000 +++ linux.ac/Documentation/Configure.help Sat Jun 10 22:00:33 2000 @@ -9,8 +9,8 @@ # http://www.linux.or.jp/JF/JFdocs/Configure.help/ # - Russian, by kaf@linux.nevod.perm.su, at # http://nevod.perm.su/service/linux/doc/kernel/Configure.help -# - French, by Tane Pierre (tanep@bigfoot.com), at -# http://www.kernelfr.org +# - French, by Pierre Tane (tanep@bigfoot.com), at +# http://www.traduc.org/kernelfr # - Spanish, by Carlos Perelló Marín (fperllo@ehome.encis.es), at # http://visar.csustan.edu/~carlos/ # - Italian, by Alessandro Rubini (rubini@linux.it), at @@ -125,7 +125,7 @@ used on systems with several CPU's. If you have a single-CPU system which uses APIC, you can say Y here to use it. If you say Y here even though your machine doesn't have APIC, then the kernel will - still run with now slowdown at all. + still run with no slowdown at all. If you have system with several CPU's, you do not need to say Y here: APIC will be used automatically. @@ -358,7 +358,7 @@ Western Digital and Compaq Computer in 1984. It was then named ST506. Quite a number of disks use the IDE interface. - AT Attachment (ATA) is a subset of the IDE specifications. + AT Attachment (ATA) is the superset of the IDE specifications. ST506 was also called ATA-1. Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is @@ -699,6 +699,14 @@ 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. +IGNORE word93 Validation BITS +CONFIG_IDEDMA_IVB + Since various rules were applied and created ... et al. as it relates + the detection of vaild cable signals. This is a result of unclear terms + in ATA-4 and ATA-5 standards. + + It is normally safe to answer Y; however, the default is N. + Various ATA, Work(s) In Progress (EXPERIMENTAL) CONFIG_IDEDMA_PCI_WIP If you enable this you will be able to use and test highly @@ -733,7 +741,7 @@ If you say Y here, then say Y to "Use DMA by default when available" as well. -AEC62XX Tuning support (WIP) +AEC62XX Tuning support CONFIG_AEC62XX_TUNING Please read the comments at the top of drivers/ide/aec62xx.c If unsure, say N. @@ -763,7 +771,7 @@ SAY NO! -AMD7409 chipset support (EXPERIMENTAL) +AMD7409 chipset support CONFIG_BLK_DEV_AMD7409 This driver ensures (U)DMA support for the AMD756 Viper chipset. @@ -784,12 +792,7 @@ Say Y here if you have an IDE controller which uses any of these chipsets: CMD643, CMD646, or CMD648. -CMD64X chipset RAID support (WIP) -CONFIG_CMD64X_RAID - Work in progress for hardware raid ata-33/66..........rev 7 minimum. - Say N for now. - -CY82C693 chipset support (EXPERIMENTAL) +CY82C693 chipset support CONFIG_BLK_DEV_CY82C693 This driver adds detection and support for the CY82C693 chipset used on Digital's PC-Alpha 164SX boards. @@ -826,11 +829,13 @@ HPT366 chipset support CONFIG_BLK_DEV_HPT366 HPT366 is an Ultra DMA chipset for ATA-66. - + HPT368 is an Ultra DMA chipset for ATA-66 RAID Based. + HPT370 is an Ultra DMA chipset for ATA-100. + This driver adds up to 4 more EIDE devices sharing a single interrupt. - The HPT366 chipset in its current form is non-bootable. One solution + The HPT366 chipset in its current form is bootable. One solution for this problem are special LILO commands for redirecting the reference to device 0x80. The other solution is to say Y to "Boot off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless @@ -842,15 +847,6 @@ ide-probe at boot. It is reported to support DVD II drives, by the manufacturer. -HPT366 Fast Interrupts (WIP) -CONFIG_HPT366_FIP - If unsure, say N. - -HPT366 mode three unsupported (EXPERIMENTAL) (WIP) -CONFIG_HPT366_MODE3 - This is an undocumented mode that the HA366 can default to in many - cases. If unsure, say N. - NS87415 support (EXPERIMENTAL) CONFIG_BLK_DEV_NS87415 This driver adds detection and support for the NS87415 chip @@ -877,7 +873,7 @@ If unsure, say N. -PIIXn Tuning support (EXPERIMENTAL) +PIIXn Tuning support CONFIG_PIIX_TUNING This driver extension adds DMA mode setting and tuning for all PIIX IDE controllers by Intel. Since the BIOS can sometimes improperly @@ -889,9 +885,11 @@ If unsure, say N. -PROMISE PDC20246/PDC20262 support +PROMISE PDC20246/PDC20262/PDC20267 support CONFIG_BLK_DEV_PDC202XX Promise Ultra33 or PDC20246 + Promise Ultra66 or PDC20262 + Promise Ultra100 or PDC20267 This driver adds up to 4 more EIDE devices sharing a single interrupt. This add-on card is a bootable PCI UDMA controller. Since @@ -902,14 +900,6 @@ for more than one card. This card may require that you say Y to "Special UDMA Feature (EXPERIMENTAL)". - Promise Ultra66 or PDC20262 - - This driver adds up to 4 more EIDE devices sharing a single - interrupt. This add-on card is a bootable PCI UDMA ATA-66 - controller. The driver attempts to dynamic tuning of the chipset at - boot-time for max-speed. Note tested limits are UDMA-2. Ultra66 BIOS - 1.11 or newer required. - If you say Y here, you need to say Y to "Use DMA by default when available" as well. @@ -919,21 +909,16 @@ Special UDMA Feature (EXPERIMENTAL) CONFIG_PDC202XX_BURST - For PDC20246 and PDC20262 Ultra DMA chipsets. Designed originally - for PDC20246/Ultra33 that has BIOS setup failures when using 3 or - more cards. + For PDC20246, PDC20262 and PDC20267 Ultra DMA chipsets. Designed + originally for PDC20246/Ultra33 that has BIOS setup failures when + using 3 or more cards. + + Unknown for PDC20267 Ultra DMA 100. Please read the comments at the top of drivers/ide/pdc202xx.c If unsure, say N. -Special Mode Feature (WIP) -CONFIG_PDC202XX_MASTER - For PDC20246 and PDC20262 Ultra DMA chipsets. This is reserved for - possible Hardware RAID 0,1 for the FastTrak Series. - - Say N. - SiS5513 chipset support CONFIG_BLK_DEV_SIS5513 This driver ensures (U)DMA support for SIS5513 chipset based @@ -958,7 +943,7 @@ needed for further tweaking and development. Please read the comments at the top of drivers/ide/trm290.c. -VIA82CXXX chipset support (EXPERIMENTAL) +VIA82CXXX chipset support CONFIG_BLK_DEV_VIA82CXXX 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 @@ -1781,7 +1766,8 @@ Various modules exist for netfilter which replace the previous masquerading (ipmasqadm), packet filtering (ipchains), transparent proxying, and portforwarding mechanisms. Please see - Documentation/Changes for the location of these packages. + Documentation/Changes under "iptables" for the location of these + packages. Make sure to say N to "Fast switching" below if you intend to say Y here, as Fast switching currently bypasses netfilter. @@ -2571,11 +2557,10 @@ http://www.linuxdoc.org/docs.html#guide . Shared memory is now implemented using a new (minimal) virtual file - system, which you need to mount before programs can use shared - memory. To do this automatically at system startup just add the + system. To mount it automatically at system startup just add the following line to your /etc/fstab: - none /var/shm shm defaults 0 0 + none /dev/shm shm defaults 0 0 Saying Y here enlarges your kernel by about 18 KB. Just say Y. @@ -2729,25 +2714,26 @@ all x86 CPU types (albeit not optimally fast), you can specify "386" here. - If you specify one of "486" or "586" or "Pentium" or "PPro" or - "Athlon", then the kernel will not necessarily run on earlier - architectures (e.g. a Pentium optimized kernel will run on a PPro, - but not necessarily on a i486). + The kernel will not necessarily run on earlier architectures than + the one you have chosen, e.g. a Pentium optimized kernel will run on + a PPro, but not necessarily on a i486. Here are the settings recommended for greatest speed: - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI - 486DLC/DLC2 and UMC 486SX-S. Only "386" kernels will run on a 386 - class machine. + 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels will + run on a 386 class machine. - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or - SL/SLC/SLC2/SLC3/SX/SX2, AMD/Cyrix 5x86, NexGen Nx586 and - UMC U5D or U5S. + SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. - "586" for generic Pentium CPUs, possibly lacking the TSC (time stamp counter) register. - - "Pentium" for the Intel Pentium/Pentium MMX, and AMD K5. - - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and - Intel Pentium Pro/Celeron/Pentium II/Pentium III. - - "K6/II/III" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Pentium" for the Intel Pentium/Pentium MMX. + - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. + - "Pentium-III" for the Intel Pentium III. + - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Crusoe" for the Transmeta Crusoe series. - "Athlon" for the AMD Athlon (K7). + - "Winchip-C6" for original IDT Winchip. + - "Winchip-2A/3" for IDT Winchips with 3dNow! capabilities. If you don't know what to do, choose "386". @@ -4609,11 +4595,6 @@ addresses on the local network) small. The ethertap device, which lets user space programs read and write raw Ethernet frames, also needs the network link driver. - - This driver is also available as a module called netlink_dev.o ( = - code which can be inserted in and removed from the running kernel - whenever you want). If you want to compile it as a module, say M - here and read Documentation/modules.txt. If unsure, say Y. @@ -5616,8 +5597,8 @@ synchronous data transfers frequency CONFIG_SCSI_NCR53C8XX_SYNC - The SCSI Parallel Interface-2 Standard defines 4 classes of transfer - rates: FAST-5, FAST-10, FAST-20 and FAST-40. The numbers are + The SCSI Parallel Interface-2 Standard defines 5 classes of transfer + rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers are respectively the maximum data transfer rates in mega-transfers per second for each class. For example, a FAST-20 Wide 16 device is able to transfer data at 20 million 16 bit packets per second for a total @@ -5625,9 +5606,9 @@ You may specify 0 if you want to only use asynchronous data transfers. This is the safest and slowest option. Otherwise, specify - a value between 5 and 40, depending on the capability of your SCSI + a value between 5 and 80, depending on the capability of your SCSI controller. The higher the number, the faster the data transfer. - Note that 40 should normally be ok since the driver decreases the + Note that 80 should normally be ok since the driver decreases the value automatically according to the controller's capabilities. Your answer to this question is ignored for controllers with NVRAM, @@ -5638,7 +5619,7 @@ second). The normal answer therefore is not to go with the default but to - select the maximum value 40 allowing the driver to use the maximum + select the maximum value 80 allowing the driver to use the maximum value supported by each controller. If this causes problems with your SCSI devices, you should come back and decrease the value. @@ -8527,9 +8508,10 @@ EtherExpress PRO support CONFIG_EEXPRESS_PRO - If you have a network (Ethernet) card of this type, say Y. Note - however that the EtherExpress PRO/100 Ethernet card has its own - separate driver. Please read the Ethernet-HOWTO, available from + If you have a network (Ethernet) card of this type, say Y. This + driver supports intel i82595{FX,TX} based boards. Note however + that the EtherExpress PRO/100 Ethernet card has its own separate + driver. Please read the Ethernet-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . This driver is also available as a module ( = code which can be @@ -8641,6 +8623,22 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +IBM LAN Adapter/A support +CONFIG_IBMLANA + This is a Micro Channel ethernet adapter. You need to set CONFIG_MCA + to use this driver. It is both available as an in-kernel driver and + as a module ( = code which can be inserted in and removed from the + running kernel whenever you want). If you want to compile it as a module, + say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. If you plan to use more than + one network card under linux, read the Multiple-Ethernet-mini-HOWTO, + available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. The only + currently supported card is the IBM LAN Adapter/A for Ethernet. It will + both support 16K and 32K memory windows, however a 32K window gives + a better security against packet losses. Usage of multiple boards with + this driver should be possible, but has not been tested up to now due + to lack of hardware. + EISA, VLB, PCI and on board controllers CONFIG_NET_PCI This is another class of network cards which attach directly to the @@ -9584,7 +9582,7 @@ USB Human Interface Device (HID) support CONFIG_USB_HID Say Y here if you want to connect keyboards, mice, joysticks, - graphic tablets, UPS's or any other HID based devices to your + graphic tablets, or any other HID based devices to your computer via USB. More information is available: Documentation/usb/input.txt. @@ -9616,16 +9614,16 @@ This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called usbmouse.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + The module will be called usbmouse.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. Wacom Intuos/Graphire tablet support CONFIG_USB_WACOM - Say Y here if you want to use the USB version of the Wacom Intuos or - Graphire tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and "Event interface support" + Say Y here if you want to use the USB version of the Wacom Intuos + or Graphire tablet. Make sure to say Y to "Mouse support" + (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well. This driver is also available as a module ( = code which can be @@ -9636,7 +9634,7 @@ Logitech WingMan Force joystick support CONFIG_USB_WMFORCE Say Y here if you want to use the Logitech WingMan Force with Linux - on the USB port. No force-feedback support yet, but other than that, + on the USB port. No force-feedback support yet, but other than that it should work like a normal joystick. This driver is also available as a module ( = code which can be @@ -9657,31 +9655,35 @@ Mouse support CONFIG_INPUT_MOUSEDEV Say Y here if you want your USB HID mouse to be accessible as - misc devices 32+ under /dev/, as an emulated PS/2 mouse. That way, - all user space programs will be able to use your mouse. + char devices 13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice + as an emulated PS/2 mouse. That way, all user space programs will + be able to use your mouse. If unsure, say Y. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called mousedev.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + The module will be called mousedev.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. Horizontal screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_X - For the mouse emulation to be correct, the mousedev driver needs to - know the screen resolution you are using (in the X window system). + If you're using a digitizer, or a graphic tablet, and want to use + it as a mouse then the mousedev driver needs to know the X window + screen resolution you are using to correctly scale the data. If + you're not using a digitizer, this value is ignored. Vertical screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_Y - For the mouse emulation to be correct, the mousedev driver needs to - know the screen resolution you are using (in the X window system). + If you're using a digitizer, or a graphic tablet, and want to use + it as a mouse then the mousedev driver needs to know the X window + screen resolution you are using to correctly scale the data. If + you're not using a digitizer, this value is ignored. Joystick support CONFIG_INPUT_JOYDEV Say Y here if you want your USB HID joystick or gamepad to be - accessible as a /dev/js device. You can't use a normal (non-USB) - joystick if you say Y here. + accessible as char device 13:0+ - /dev/input/jsX device. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9691,7 +9693,7 @@ Event interface support CONFIG_INPUT_EVDEV Say Y here if you want your USB HID device events be accessible - under /dev/inputX (misc 64+) in a generic way. + under char device 13:64+ - /dev/inputX in a generic way. This is the future ... USB Scanner support @@ -9998,6 +10000,15 @@ The module will be called dsbr100.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +Microtek USB scanner support +CONFIG_USB_MICROTEK + Say Y here if you want support for the Microtek X6USB and possibly + some other scanners. The scanner will appear as a scsi device to the + rest of the system. A patched version of SANE is necessary to use the + scanner. It's available at + http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html + This driver can be compiled as a module. + Minix fs support CONFIG_MINIX_FS Minix is a simple operating system used in many classes about OS's. @@ -10438,6 +10449,13 @@ If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. +Provide NFS over TCP server support DEVELOPER ONLY +CONFIG_NFSD_TCP + If you are a developer and want to work on fixing problems with + NFS server over TCP support, say Y here. If unsure, say Y. + + Some problems can be found by looking for FIXME in net/sunrpc/svcsock.c + OS/2 HPFS file system support CONFIG_HPFS_FS OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS @@ -11661,7 +11679,7 @@ If you want kernel messages to be printed out as they occur, you can have a console on the printer. This option adds support for doing that; to actually get it to happen you need to pass the - option "console=lp" to the kernel at boot time. + option "console=lp0" to the kernel at boot time. Note that kernel messages can get lost if the printer is out of paper (or off, or unplugged, or too busy..), but this behaviour @@ -12640,7 +12658,7 @@ For latest news and information on obtaining all the required ingredients for this driver, check: - http://www.ocston.org/~tigran/patches/microcode . + http://www.urbanmyth.org/microcode/ This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -13525,16 +13543,19 @@ differs slightly from OSS/Free, so PLEASE READ Documentation/sound/sonicvibes. -Trident 4DWave DX/NX or SiS 7018 PCI Audio Core +Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core CONFIG_SOUND_TRIDENT Say Y or M if you have a PCI sound card utilizing the Trident 4DWave-DX/NX chipset or your mother board chipset has SiS 7018 - built-in. The SiS 7018 PCI Audio Core is embedded in SiS960 - Super South Bridge and SiS540/630 Single Chipset. + or ALi 5451 built-in. The SiS 7018 PCI Audio Core is embedded + in SiS960 Super South Bridge and SiS540/630 Single Chipset. + The ALi 5451 PCI Audio Core is embedded in ALi M1535, M1535D, + M1535+ or M1535D+ South Bridge. Use lspci -n to find out if your sound card or chipset uses Trident 4DWave or SiS 7018. PCI ID 1023:2000 or 1023:2001 stands - for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. + for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. PCI ID + 10B9:5451 stands for ALi5451. This driver differs slightly from OSS/Free, so PLEASE READ the comments at the top of driver/sound/trident.c @@ -14739,6 +14760,22 @@ embedded MBX boards from Motorola. Currently, a single kernel binary only supports one type or the other. However, there is very early work on support for CHRP, PReP and PowerMac's from a single binary. + +Power management support for PowerBooks +CONFIG_PMAC_PBOOK + This provides support for putting a PowerBook to sleep; it also + enables media bay support. Power management works on the + PB2400/3400/3500, Wallstreet, Lombard, and Bronze PowerBook G3. You + must get the power management daemon, pmud, to make it work and you + must have the /dev/pmu device (see the pmud README). + + Get pmud from ftp://linuxcare.com.au/pub/ppclinux/pmud/ + + If you have a PowerBook, you should say Y. + + You may also want to compile the dma sound driver as a module and + have it autoloaded. The act of removing the module shuts down the + sound hardware for more power savings. Support for Open Firmware device tree in /proc CONFIG_PROC_DEVICETREE diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/DocBook/Makefile linux.ac/Documentation/DocBook/Makefile --- linux.vanilla/Documentation/DocBook/Makefile Thu May 25 17:46:15 2000 +++ linux.ac/Documentation/DocBook/Makefile Thu Jun 8 15:01:34 2000 @@ -1,7 +1,13 @@ -BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml kernel-hacking.sgml kernel-locking.sgml +BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \ + kernel-api.sgml parportbook.sgml kernel-hacking.sgml \ + kernel-locking.sgml via-audio.sgml mousedrivers.sgml PS := $(patsubst %.sgml, %.ps, $(BOOKS)) PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) +HTML := $(patsubst %.sgml, %, $(BOOKS)) +IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig +EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook)) +JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook)) $(BOOKS): $(TOPDIR)/scripts/docproc @@ -13,7 +19,9 @@ pdf: $(PDF) -db2ps db2pdf: +html: $(HTML) + +db2ps db2pdf db2html: @(which $@ > /dev/null 2>&1) || \ (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) @@ -21,9 +29,15 @@ %.eps: %.fig -fig2dev -Leps $< $@ +%.jpeg: %.fig + -fig2dev -Ljpeg $< $@ + $(TOPDIR)/scripts/docproc: $(MAKE) -C $(TOPDIR)/scripts docproc +mousedrivers.sgml: mousedrivers.tmpl + $(TOPDIR)/scripts/docgen <$< >$@ + kernel-hacking.sgml: kernel-hacking.tmpl $(TOPDIR)/scripts/docgen <$< >$@ @@ -38,6 +52,10 @@ $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/z85230.c \ z8530book.sgml +via-audio.sgml: via-audio.tmpl + $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/sound/via82cxxx_audio.c \ + via-audio.sgml + mcabook.sgml: mcabook.tmpl $(TOPDIR)/scripts/docgen $(TOPDIR)/arch/i386/kernel/mca.c \ mcabook.sgml @@ -66,6 +84,8 @@ $(TOPDIR)/net/netsyms.c \ kernel-api.sgml +parportbook: $(JPG-parportbook) +parportbook.ps: $(EPS-parportbook) parportbook.sgml: parportbook.tmpl $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/parport/init.c \ parportbook.sgml @@ -74,23 +94,28 @@ AUX := $(patsubst %.sgml, %.aux, $(BOOKS)) TEX := $(patsubst %.sgml, %.tex, $(BOOKS)) LOG := $(patsubst %.sgml, %.log, $(BOOKS)) +OUT := $(patsubst %.sgml, %.out, $(BOOKS)) clean: -$(RM) core *~ -$(RM) $(BOOKS) - -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) - -$(RM) parport-share.eps parport-multi.eps parport-structure.eps + -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) $(OUT) + -$(RM) $(JPG-parportbook) $(EPS-parportbook) mrproper: clean -$(RM) $(PS) $(PDF) - -parportbook.ps: parport-share.eps parport-multi.eps parport-structure.eps + -$(RM) -r $(HTML) %.ps : %.sgml db2ps db2ps $< -%.pdf : %.sgml +%.pdf : %.sgml db2pdf db2pdf $< + +%: %.sgml db2html + -$(RM) -r $@ + db2html $< + if [ ! -z "$(JPG-$@)" ]; then cp $(JPG-$@) $@; fi include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/DocBook/kernel-locking.tmpl linux.ac/Documentation/DocBook/kernel-locking.tmpl --- linux.vanilla/Documentation/DocBook/kernel-locking.tmpl Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/DocBook/kernel-locking.tmpl Sun Jun 4 21:26:29 2000 @@ -208,7 +208,12 @@ your task will put itself on the queue, and be woken up when the semaphore is released. This means the CPU will do something else while you are waiting, but there are many cases when you - simply can't sleep, and so have to use a spinlock instead. + simply can't sleep (see ), and so + have to use a spinlock instead. + + + Neither type of lock is recursive: see + . @@ -430,7 +435,7 @@ Hardware interrupts usually communicate with a bottom half, - tasklet or softirq. Frequently this involved putting work in a + tasklet or softirq. Frequently this involves putting work in a queue, which the BH/softirq will take out. @@ -522,8 +527,8 @@ There is a coding bug where a piece of code tries to grab a spinlock twice: it will spin forever, waiting for the lock to - be released (spinlocks and writelocks are not re-entrant in - Linux). This is trivial to diagnose: not a + be released (spinlocks, rwlocks and semaphores are not + recursive in Linux). This is trivial to diagnose: not a stay-up-five-nights-talk-to-fluffy-code-bunnies kind of problem. @@ -754,37 +759,15 @@ - Dropping or gaining a spinlock, and any atomic operation are - all defined to act as memory barriers (ie. as per the - mb() macro). - - - - There is a similar, but unrelated, problem with code like the - following: - - - - if (!(ctrack->status & IPS_CONFIRMED)) { - spin_lock_bh(&ip_conntrack_lock); - if (!(ctrack->status & IPS_CONFIRMED)) { - clean_from_lists(h->ctrack); - h->ctrack->status |= IPS_CONFIRMED; - } - spin_unlock_bh(&ip_conntrack_lock); - } - - - - In this case, the author has tried to be tricky: knowing that - the CONFIRMED bit is set and never reset in the status word, - you can test it outside the lock, and frequently avoid - grabbing the lock at all. However, the compiler could cache - the value in a register, rather than rereading it once the - lock is obtained, creating a subtle race. The way to get - around this is to declare the status field `volatile', or use - a temporary volatile pointer to achieve the same effect in - this one place. + Any atomic operation is defined to act as a memory barrier + (ie. as per the mb() macro). Also, + spinlock operations act as partial barriers: operations after + gaining a spinlock will never be moved to precede the + spin_lock() call, and operations before + releasing a spinlock will never be moved after the + spin_unlock() call. + @@ -911,7 +894,8 @@ You can never call the following routines while holding a - spinlock, as they may sleep: + spinlock, as they may sleep. This also means you need to be in + user context. @@ -952,11 +936,19 @@ - printk(), which can be called from - user context, interestingly enough. + down_interruptible() and + down() + + + There is a down_trylock() which can be + used inside interrupt context, as it will not sleep. + up() will also never sleep. + + printk() can be called in + any context, interestingly enough. @@ -1047,9 +1039,11 @@ Another common problem is deleting timers which restart themselves (by calling add_timer() at the end of their timer function). Because this is a fairly common case - which is prone to races, the function del_timer_sync() - (include/linux/timer.h) is - provided to handle this case. It returns the number of times the timer + which is prone to races, you can put a call to + timer_exit() at the very end of your timer function, + and user del_timer_sync() + (include/linux/timer.h) + to handle this case. It returns the number of times the timer had to be deleted before we finally stopped it from adding itself back in. @@ -1093,8 +1087,8 @@ Thanks to Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul - Mackerras, Ruedi Aschwanden, Alan Cox for proofreading, - correcting, flaming, commenting. + Mackerras, Ruedi Aschwanden, Alan Cox, Manfred Spraul and Tim + Waugh for proofreading, correcting, flaming, commenting. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/DocBook/mousedrivers.tmpl linux.ac/Documentation/DocBook/mousedrivers.tmpl --- linux.vanilla/Documentation/DocBook/mousedrivers.tmpl Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/DocBook/mousedrivers.tmpl Fri Jun 9 17:48:45 2000 @@ -0,0 +1,1019 @@ + + + + + Mouse Drivers + + + + Alan + Cox + +
+ alan@redhat.com +
+
+
+
+ + + 2000 + Alan Cox + + + + + This documentation 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., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + Earlier publication + + Parts of this document first appeared in Linux Magazine under a + ninety day exclusivity. + + + + + Mice are conceptually one of the simplest device interfaces in the + Linux operating system. Not all mice are handled by the kernel. + Instead there is a two layer abstraction. + + + + The kernel mouse drivers and userspace drivers for the serial mice are + all managed by a system daemon called gpm + - the general purpose mouse driver. gpm + handles cutting and pasting on the text consoles. It provides a + general library for mouse-aware applications and it handles the + sharing of mouse services with the + X Window System user interface. + + + Sometimes a mouse speaks a sufficiently convoluted protocol that the + protocol is handled by Gpm itself. Most + of the mouse drivers follow a common interface called the bus mouse + protocol. + + + Each read from a bus mouse interface device returns a block of data. + The first three bytes of each read are defined as follows: + + + Mouse Data Encoding + + + + Byte 0 + 0x80 + the buttons currently down. + + + Byte 1 + A signed value for the shift in X position + + + Byte 2 + A signed value for the shift in Y position + + + +
+ + An application can choose to read more than 3 bytes. The rest of the + bytes will be zero, or may optionally return some additional + device-specific information. +
+ + The position values are truncated if they exceed the 8bit range (that + is -127 <= delta <= 127). While the value -128 does fit into a + byte is not allowed. + + + The buttons are numbered left to right as + 0, 1, 2, 3.. and each button sets the relevant bit. So a user pressing + the left and right button of a three button mouse will set bits 0 and 2. + + + All mice are required to support the poll + operation. Indeed pretty much every user of a mouse device uses + poll to wait for mouse events to occur. + + + Finally the mice support asynchronous I/O. This is a topic we have not + yet covered but which I will explain after looking at a simple mouse + driver. + +
+ + + A simple mouse driver + + First we will need the set up functions for our mouse device. To keep + this simple our imaginary mouse device has three I/O ports fixed at I/O + address 0x300 and always lives on interrupt 5. The ports will be the X + position, the Y position and the buttons in that order. + + + +#define OURMOUSE_BASE 0x300 + +static struct miscdevice our_mouse = { + OURMOUSE_MINOR, "ourmouse", &our_mouse_fops +}; + +__init ourmouse_init(void) +{ + + if(check_region(OURMOUSE_BASE, 3)) + return -ENODEV; + request_region(OURMOUSE_BASE, 3, "ourmouse"); + + misc_register(&our_mouse); + return 0; +} + + + + The miscdevice is new here. Linux normally + parcels devices out by major number, and each device has 256 units. + For things like mice this is extremely wasteful so a device exists + which is used to accumulate all the odd individual devices that + computers tend to have. + + + Minor numbers in this space are allocated by a central source, although + you can look in the kernel Documentation/devices.txt + file and pick a free one for development use. This kernel file also + carries instructions for registering a device. This may change over time + so it is a good idea to obtain a current copy of this file first. + + + Our code then is fairly simple. We check nobody else has taken our + address space. Having done so we reserve it to ensure nobody stamps + on our device while probing for other ISA bus devices. Such a probe + might confuse our device. + + + Then we tell the misc driver that we wish to own a minor number. We also + hand it our name (which is used in + /proc/misc) and a set of file + operations that are to be used. The file operations work exactly like the + file operations you would register for a normal character device. The misc + device itself is simply acting as a redirector for requests. + + + Next, in order to be able to use and test our code we need to add some + module code to support it. This too is fairly simple: + + +#ifdef MODULE + +int init_module(void) +{ + if(ourmouse_init()<0) + return -ENODEV: + return 0; +} + +void cleanup_module(void) +{ + misc_deregister(&our_mouse); + free_region(OURMOUSE_BASE, 3); +} + + +#endif + + + + The module code provides the normal two functions. The + init_module function is called when the module is + loaded. In our case it simply calls the initialising function we wrote + and returns an error if this fails. This ensures the module will only + be loaded if it was successfully set up. + + + The cleanup_module function is called when the + module is unloaded. We give the miscellaneous device entry back, and + then free our I/O resources. If we didn't free the I/O resources then + the next time the module loaded it would think someone else had its I/O + space. + + + Once the misc_deregister has been called any + attempts to open the mouse device will fail with the error + ENODEV (No such device). + + + Next we need to fill in our file operations. A mouse doesn't need many + of these. We need to provide open, release, read and poll. That makes + for a nice simple structure: + + + +struct file_operations our_mouse_fops = { + NULL, /* Mice don't seek */ + read_mouse, /* You can read a mouse */ + write_mouse, /* This won't do a lot */ + NULL, /* No readdir - not a directory */ + poll_mouse, /* Poll */ + NULL, /* No ioctl calls */ + NULL, /* No mmap */ + open_mouse, /* Called on open */ + NULL, /* Flush - 2.2+ only */ + close_mouse, /* Called on close */ +}; + + + + There is nothing particularly special needed here. We provide functions + for all the relevant or required operations and little else. There is + nothing stopping us providing an ioctl function for this mouse. Indeed + if you have a configurable mouse it may be very appropriate to provide + configuration interfaces via ioctl calls. + + + The open and close routines need to manage enabling and disabling the + interrupts for the mouse as well as stopping the mouse being unloaded + when it is no longer required. + + + +static int mouse_users = 0; /* User count */ +static int mouse_dx = 0; /* Position changes */ +static int mouse_dy = 0; +static int mouse_event = 0; /* Mouse has moved */ + +static int open_mouse(struct inode *inode, struct file *file) +{ + if(mouse_users++) + return 0; + if(request_irq(mouse_intr, OURMOUSE_IRQ, 0, "ourmouse", NULL)) + { + mouse_users--; + MOD_DEC_USE_COUNT; + return -EBUSY; + } + mouse_dx = 0; + mouse_dy = 0; + mouse_event = 0; + mouse_buttons = 0; + return 0; +} + + + The open function has to do a small amount of housework. We keep a count + of the number of times the mouse is open. This is because we do not want + to request the interrupt multiple times. If the mouse has at least one + user then it is set up and we simply add to the user count and return + 0 for success. + + + We grab the interrupt and thus start mouse interrupts. If the interrupt + has been borrowed by some other driver then request_irq + will fail and we will return an error. If we were capable of sharing an + interrupt line we would specify SA_SHIRQ instead of + zero. Provided that everyone claiming an interrupt + sets this flag, they get to share the line. PCI can + share interrupts, ISA normally however cannot. + + + We do the housekeeping. We make the current mouse position the starting + point for accumulated changes and declare that nothing has happened + since the mouse driver was opened. + + + Finally we use MOD_INC_USE_COUNT to ensure that + while the mouse is open nobody will unload it and cause a nasty crash. + + + The release function needs to unwind all these: + + +static int close_mouse(struct inode *inode, struct file *file) +{ + if(--mouse_users) + return 0; + free_irq(OURMOUSE_IRQ, NULL); + MOD_DEC_USE_COUNT; + return 0; +} + + + We count off a user and provided that there are still other users need + take no further action. The last person closing the mouse causes us to + free up the interrupt. This stopps interrupts from the mouse from using + our CPU time, and lets us use MOD_DEC_USE_COUNT so + that the mouse can now be unloaded. + + + We can fill in the write handler at this point as the write function for + our mouse simply declines to allow writes: + + + +static ssize_t write_mouse(struct file *file, const char *buffer, size_t + count, loff_t *ppos) +{ + return -EINVAL; +} + + + + This is pretty much self-explanatory. Whenever you write you get told + it was an invalid function. + + + To make the poll and read functions work we have to consider how we + handle the mouse interrupt. + + + +static struct wait_queue *mouse_wait; +static spinlock_t mouse_lock = SPIN_LOCK_UNLOCKED; + +static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + char delta_x; + char delta_y; + unsigned char new_buttons; + + delta_x = inb(OURMOUSE_BASE); + delta_y = inb(OURMOUSE_BASE+1); + new_buttons = inb(OURMOUSE_BASE+2); + + if(delta_x || delta_y || new_buttons != mouse_buttons) + { + /* Something happened */ + + spin_lock(&mouse_lock); + mouse_event = 1; + mouse_dx += delta_x; + mouse_dy += delta_y; + mouse_buttons = new_buttons; + spin_unlock(&mouse_lock); + + wake_up_interruptible(&mouse_wait); + } +} + + + + The interrupt handler reads the mouse status. The next thing we do is + to check whether something has changed. If the mouse was smart it would + only interrupt us if something had changed, but let's assume our mouse + is stupid as most mice actually tend to be. + + + If the mouse has changed we need to update the status variables. What we + don't want is the mouse functions reading these variables to read them + during a change. We add a spinlock that protects these variables while we + play with them. + + + If a change has occured we also need to wake sleeping processes, so we + add a wakeup call and a wait_queue to use when + we wish to await a mouse event. + + + Now we have the wait queue we can implement the poll function for the + mouse relatively easily: + + + +static unsigned int mouse_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &mouse_wait, wait); + if(mouse_event) + return POLLIN | POLLRDNORM; + return 0; +} + + + + This is fairly standard poll code. First we add the wait queue to the + list of queues we want to monitor for an event. Secondly we check if an + event has occured. We only have one kind of event - the + mouse_event flag tells us that something happened. + We know that this something can only be mouse data. We return the flags + indicating input and normal reading will succeed. + + + You may be wondering what happens if the function returns saying 'no + event yet'. In this case the wake up from the wait queue we added to + the poll table will cause the function to be called again. Eventually + we will be woken up and have an event ready. At this point the + poll call will exit back to the user. + + + After the poll completes the user will want to read the data. We now + need to think about how our mouse_read function + will work: + + +static ssize_t mouse_read(struct file *file, char *buffer, + size_t count, loff_t *pos) +{ + int dx, dy; + unsigned char button; + unsigned long flags; + int n; + + if(count<3) + return -EINVAL; + + /* + * Wait for an event + */ + + while(!mouse_event) + { + if(file->f_flags&O_NDELAY) + return -EAGAIN; + interruptible_sleep_on(&mouse_wait); + if(signal_pending(current)) + return -ERESTARTSYS; + } + + + + We start by validating that the user is reading enough data. We could + handle partial reads if we wanted but it isn't terribly useful and the + mouse drivers don't bother to try. + + + Next we wait for an event to occur. The loop is fairly standard event + waiting in Linux. Having checked that the event has not yet occured, we + then check if an event is pending and if not we need to sleep. + + + A user process can set the O_NDELAY flag on a file + to indicate that it wishes to be told immediately if no event is + pending. We check this and give the appropriate error if so. + + + Next we sleep until the mouse or a signal awakens us. A signal will + awaken us as we have used wakeup_interruptible. + This is important as it means a user can kill processes waiting for + the mouse - clearly a desireable property. If we are interrupted we + exit the call and the kernel will then process signals and maybe + restart the call again - from the beginning. + + + This code contains a classic Linux bug. All will be revealed later in this + article as well as explanations for how to avoid it. + + + /* Grab the event */ + + spinlock_irqsave(&mouse_lock, flags); + + dx = mouse_dx; + dy = mouse_dy; + button = mouse_buttons + + if(dx<=-127) + dx=-127; + if(dx>=127) + dx=127; + if(dy<=-127) + dy=-127; + if(dy>=127) + dy=127; + + mouse_dx -= dx; + mouse_dy -= dy; + + if(mouse_dx == 0 && mouse_dy == 0) + mouse_event = 0; + + spin_unlock_irqrestore(&mouse_lock, flags); + + + This is the next stage. Having established that there is an event + going, we capture it. To be sure that the event is not being updated + as we capture it we also take the spinlock and thus prevent parallel + updates. Note here we use spinlock_irqsave. We + need to disable interrupts on the local processor otherwise bad things + will happen. + + + What will occur is that we take the spinlock. While we hold the lock + an interrupt will occur. At this point our interrupt handler will try + and take the spinlock. It will sit in a loop waiting for the read + routine to release the lock. However because we are sitting in a loop + in the interrupt handler we will never release the lock. The machine + hangs and the user gets upset. + + + By blocking the interrupt on this processor we ensure that the lock + holder will always give the lock back without deadlocking. + + + There is a little cleverness in the reporting mechanism too. We can + only report a move of 127 per read. We don't however want to lose + information by throwing away further movement. Instead we keep + returning as much information as possible. Each time we return a + report we remove the amount from the pending movement in + mouse_dx and mouse_dy. Eventually + when these counts hit zero we clear the mouse_event + flag as there is nothing else left to report. + + + + if(put_user(button|0x80, buffer)) + return -EFAULT; + if(put_user((char)dx, buffer+1)) + return -EFAULT; + if(put_user((char)dy, buffer+2)) + return -EFAULT; + + for(n=3; n < count; n++) + if(put_user(0x00, buffer+n)) + return -EFAULT; + + return count; +} + + + + Finally we must put the results in the user supplied buffer. We cannot + do this while holding the lock as a write to user memory may sleep. + For example the user memory may be residing on disk at this instant. + Thus we did our computation beforehand and now copy the data. Each + put_user call is filling in one byte of the buffer. + If it returns an error we inform the program that it passed us an + invalid buffer and abort. + + + Having written the data we blank the rest of the buffer that was read + and report the read as being successful. + + + + + Debugging the mouse driver + + + We now have an almost perfectly usable mouse driver. If you were to + actually try and use it however you would eventually find a couple of + problems with it. A few programs will also not work with as it does not + yet support asynchronous I/O. + + + First let us look at the bugs. The most obvious one isn't really a driver + bug but a failure to consider the consequences. Imagine you bumped the + mouse hard by accident and sent it skittering across the desk. The mouse + interrupt routine will add up all that movement and report it in steps of + 127 until it has reported all of it. Clearly there is a point beyond + which mouse movement isn't worth reporting. We need to add this as a + limit to the interrupt handler: + + + +static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + char delta_x; + char delta_y; + unsigned char new_buttons; + + delta_x = inb(OURMOUSE_BASE); + delta_y = inb(OURMOUSE_BASE+1); + new_buttons = inb(OURMOUSE_BASE+2); + + if(delta_x || delta_y || new_buttons != mouse_buttons) + { + /* Something happened */ + + spin_lock(&mouse_lock); + mouse_event = 1; + mouse_dx += delta_x; + mouse_dy += delta_y; + + if(mouse_dx < -4096) + mouse_dx = -4096; + if(mouse_dx > 4096) + mouse_dx = 4096; + + if(mouse_dy < -4096) + mouse_dy = -4096; + if(mouse_dy > 4096) + mouse_dy = 4096; + + mouse_buttons = new_buttons; + spin_unlock(&mouse_lock); + + wake_up_interruptible(&mouse_wait); + } +} + + + + By adding these checks we limit the range of accumulated movement to + something sensible. + + + The second bug is a bit more subtle, and that is perhaps why this is + such a common mistake. Remember, I said the waiting loop for the read + handler had a bug in it. Think about what happens when we execute: + + + + while(!mouse_event) + { + + + + and an interrupt occurs at this point here. This causes a mouse movement + and wakes up the queue. + + + + interruptible_sleep_on(&mouse_wait); + + + + Now we sleep on the queue. We missed the wake up and the application + will not see an event until the next mouse event occurs. This will + lead to just the odd instance when a mouse button gets delayed. The + consequences to the user will probably be almost undetectable with a + mouse driver. With other drivers this bug could be a lot more severe. + + + There are two ways to solve this. The first is to disable interrupts + during the testing and the sleep. This works because when a task sleeps + it ceases to disable interrupts, and when it resumes it disables them + again. Our code thus becomes: + + + + save_flags(flags); + cli(); + + while(!mouse_event) + { + if(file->f_flags&O_NDELAY) + { + restore_flags(flags); + return -EAGAIN; + } + interruptible_sleep_on(&mouse_wait); + if(signal_pending(current)) + { + restore_flags(flags); + return -ERESTARTSYS; + } + } + restore_flags(flags); + + + + This is the sledgehammer approach. It works but it means we spend a + lot more time turning interrupts on and off. It also affects + interrupts globally and has bad properties on multiprocessor machines + where turning interrupts off globally is not a simple operation, but + instead involves kicking each processor, waiting for them to disable + interrupts and reply. + + + The real problem is the race between the event testing and the sleeping. + We can avoid that by using the scheduling functions more directly. + Indeed this is the way they generally should be used for an interrupt. + + + + struct wait_queue wait = { current, NULL }; + + add_wait_queue(&mouse_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + + while(!mouse_event) + { + if(file->f_flags&O_NDELAY) + { + remove_wait_queue(&mouse_wait, &wait); + current->state = TASK_RUNNING; + return -EWOULDBLOCK; + } + if(signal_pending(current)) + { + remove_wait_queue(&mouse_wait, &wait); + current->state = TASK_RUNNING; + return -ERESTARTSYS; + } + schedule(); + current->state = TASK_INTERRUPTIBLE; + } + + remove_wait_wait(&mouse_wait, &wait); + current->state = TASK_RUNNING; + + + + At first sight this probably looks like deep magic. To understand how + this works you need to understand how scheduling and events work on + Linux. Having a good grasp of this is one of the keys to writing clean + efficient device drivers. + + + add_wait_queue does what its name suggests. It adds + an entry to the mouse_wait list. The entry in this + case is the entry for our current process (current + is the current task pointer). + + + So we start by adding an entry for ourself onto the + mouse_wait list. This does not put us to sleep + however. We are merely tagged onto the list. + + + Next we set our status to TASK_INTERRUPTIBLE. Again + this does not mean we are now asleep. This flag says what should happen + next time the process sleeps. TASK_INTERRUPTIBLE says + that the process should not be rescheduled. It will run from now until it + sleeps and then will need to be woken up. + + + The wakeup_interruptible call in the interrupt + handler can now be explained in more detail. This function is also very + simple. It goes along the list of processes on the queue it is given and + any that are marked as TASK_INTERRUPTIBLE it changes + to TASK_RUNNING and tells the kernel that new + processes are runnable. + + + Behind all the wrappers in the original code what is happening is this + + + + + + We add ourself to the mouse wait queue + + + + + We mark ourself as sleeping + + + + + We ask the kernel to schedule tasks again + + + + + The kernel sees we are asleep and schedules someone else. + + + + + The mouse interrupt sets our state to TASK_RUNNING + and makes a note that the kernel should reschedule tasks + + + + + The kernel sees we are running again and continues our execution + + + + + This is why the apparent magic works. Because we mark ourself as + TASK_INTERRUPTIBLE and as we add ourselves + to the queue before we check if there are events pending, the race + condition is removed. + + + Now if an interrupt occurs after we check the queue status and before + we call the schedule function in order to sleep, + things work out. Instead of missing an event, we are set back to + TASK_RUNNING by the mouse interrupt. We still call + schedule but it will continue running our task. + We go back around the loop and this time there may be an event. + + + There will not always be an event. Thus we set ourselves back to + TASK_INTERRUPTIBLE before resuming the loop. + Another process doing a read may already have cleared the event flag, + and if so we will need to go back to sleep again. Eventually we will + get our event and escape. + + + Finally when we exit the loop we remove ourselves from the + mouse_wait queue as we are no longer interested + in mouse events, and we set ourself back to + TASK_RUNNABLE as we do not wish to go to sleep + again just yet. + + + Note + + This isn't an easy topic. Don't be afraid to reread the description a + few times and also look at other device drivers to see how it works. + Finally if you can't grasp it just yet, you can use the code as + boilerplate to write other drivers and trust me instead. + + + + + + Asynchronous I/O + + This leaves the missing feature - Asynchronous I/O. Normally UNIX + programs use the poll call (or its variant form + select) to wait for an event to occur on one of + multiple input or output devices. This model works well for most tasks + but because poll and select + wait for an event isn't suitable for tasks that are also continually + doing computation work. Such programs really want the kernel to kick + them when something happens rather than watch for events. + + + Poll is akin to having a row of lights in front of you. You can see at a + glance which ones if any are lit. You cannot however get anything useful + done while watching them. Asynchronous I/O uses signals which work more + like a door bell. Instead of you watching, it tells you that something + is up. + + + Asynchronous I/O sends the signal SIGIO to a user process when the I/O + events occur. In this case that means when people move the mouse. The + SIGIO signal causes the user process to jump to its signal handler and + execute code in that handler before returning to whatever was going on + previously. It is the application equivalent of an interrupt handler. + + + Most of the code needed for this operation is common to all its users. + The kernel provides a simple set of functions for managing asynchronous + I/O. + + + Our first job is to allow users to set asynchronous I/O on file handles. + To do that we need to add a new function to the file operations table for + our mouse: + + + +struct file_operations our_mouse_fops = { + NULL, /* Mice don't seek */ + read_mouse, /* You can read a mouse */ + write_mouse, /* This won't do a lot */ + NULL, /* No readdir - not a directory */ + poll_mouse, /* Poll */ + NULL, /* No ioctl calls */ + NULL, /* No mmap */ + open_mouse, /* Called on open */ + NULL, /* Flush */ + close_mouse, /* Called on close */ + NULL, /* No fsync on a mouse */ + fasync_mouse, /* Asynchronous I/O */ +}; + + + + Once we have installed this entry the kernel knows we support + asynchronous I/O and will allow all the relevant operations on the + device. Whenever a user adds or removes asynchronous I/O notification + on a file handle it calls our fasync_mouse routine + we just added. This routine uses the helper functions to keep the queue + of handles up to date: + + + +static struct fasync_struct *mouse_fasync = NULL; + +static int fasync_mouse(int fd, struct file *filp, int on) +{ + int retval = fasync_helper(fd, filp, on, &mouse_fasync); + + if (retval < 0) + return retval; + return 0; +} + + + + The fasync helper adds and deletes entries by managing the supplied + list. We also need to remove entries from this list when the file is + closed. This requires we add one line to our close function: + + + +static int close_mouse(struct inode *inode, struct file *file) +{ + fasync_mouse(-1, file, 0) + if(--mouse_users) + return 0; + free_irq(OURMOUSE_IRQ, NULL); + MOD_DEC_USE_COUNT; + return 0; +} + + + + When we close the file we now call our own fasync handler as if the + user had requested that this file cease to be used for asynchronous + I/O. This rather neatly cleans up any loose ends. We certainly don't + wait to deliver a signal for a file that no longer exists. + + + At this point the mouse driver supports all the asynchronous I/O + operations, and applications using them will not error. They won't + however work yet. We need to actually send the signals. Again the + kernel provides a function for handling this. + + + We update our interrupt handler a little: + + + +static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + char delta_x; + char delta_y; + unsigned char new_buttons; + + delta_x = inb(OURMOUSE_BASE); + delta_y = inb(OURMOUSE_BASE+1); + new_buttons = inb(OURMOUSE_BASE+2); + + if(delta_x || delta_y || new_buttons != mouse_buttons) + { + /* Something happened */ + + spin_lock(&mouse_lock); + mouse_event = 1; + mouse_dx += delta_x; + mouse_dy += delta_y; + + if(mouse_dx < -4096) + mouse_dx = -4096; + if(mouse_dx > 4096) + mouse_dx = 4096; + + if(mouse_dy < -4096) + mouse_dy = -4096; + if(mouse_dy > 4096) + mouse_dy = 4096; + + mouse_buttons = new_buttons; + spin_unlock(&mouse_lock); + + /* Now we do asynchronous I/O */ + if(mouse_fasync) + kill_fasync(mouse_fasync, SIGIO); ***FIXME*** + + wake_up_interruptible(&mouse_wait); + } +} + + + + The new code simply calls the kill_fasync routine + provided by the kernel if the queue is non-empty. This sends the + required signal (SIGIO in this case) to the process each file handle + says should be informed about the exciting new mouse movement that + just happened. + + + With this in place and the bugs in the original version fixed, you now + have a fully functional mouse driver using the bus mouse protocol. It + will work with the X window system, will work + with GPM and should work with every other + application you need. Doom is of course the + ideal way to test your new mouse driver is functioning properly. Be sure + to test it thoroughly. + + +
+ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/DocBook/via-audio.tmpl linux.ac/Documentation/DocBook/via-audio.tmpl --- linux.vanilla/Documentation/DocBook/via-audio.tmpl Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/DocBook/via-audio.tmpl Thu Jun 8 15:01:35 2000 @@ -0,0 +1,383 @@ + + + + + Via 686 Audio Driver for Linux + + + + Jeff + Garzik + +
+ jgarzik@mandrakesoft.com +
+
+
+
+ + + 2000 + Jeff Garzik + + + + + This documentation 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., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + + Introduction + + The Via VT82C686A and VT82C686A "super southbridge" chips contain + AC97-compatible audio logic which features dual full-duplex 16-bit stereo + PCM sound channels, plus a third PCM channel intended for use + in hardware-assisted FM synthesis. + + + The current Linux kernel audio driver for this family of chips + supports audio playback, but recording and hardware-assisted + FM support features are not yet available. + + + This driver supports any Linux kernel version after 2.3.50. + + + Please send bug reports to the mailing list linux-via@gtf.org. + To subscribe, e-mail majordomo@gtf.org with + + + subscribe linux-via + + + in the body of the message. + + + + + Driver Installation + + To use this audio driver, select the + CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel configuration. + Follow the usual kernel procedures for rebuilding the kernel, + or building and installing driver modules. + + + To make this driver the default audio driver, you can add the + following to your /etc/conf.modules file: + + + alias sound via82cxxx_audio + + + Note that soundcore and ac97_codec support modules + are also required for working audio, in addition to + the via82cxxx_audio module itself. + + + + + Submitting a bug report + Description of problem + + Describe the application you were using to play/record sound, and how + to reproduce the problem. + + + Diagnostic output + + Obtain the via-audio-diag diagnostics program from + http://gtf.org/garzik/drivers/via82cxxx/ and provide a dump of the + audio chip's registers while the problem is occurring. Sample command line: + + + ./via-audio-diag -aps > diag-output.txt + + + Driver debug output + + Define VIA_DEBUG at the beginning of the driver, then capture and email + the kernel log output. This can be viewed in the system kernel log (if + enabled), or via the dmesg program. Sample command line: + + + dmesg > /tmp/dmesg-output.txt + + + Bigger kernel message buffer + + If you wish to increase the size of the buffer displayed by dmesg, then + change the LOG_BUF_LEN macro at the top of linux/kernel/printk.c, recompile + your kernel, and pass the LOG_BUF_LEN value to dmesg. Sample command line with + LOG_BUF_LEN == 32768: + + + dmesg -s 32768 > /tmp/dmesg-output.txt + + + + + + Known Bugs And Assumptions + + + Recording support + + + Recording support is currently missing. + + + + MMAP support + + + MMAP support is currently missing. Make sure to + test with Quake. + + + + AC97 codec timeout during init + + + A warning message "via82cxxx: timeout while reading AC97 + codec" is printed during driver initialization. This + message can safely be ignored. + + + + Low volume + + + Volume too low on many systems. Workaround: use mixer program + such as xmixer to increase volume. + + + + RealPlayer trouble + + + RealPlayer output very scratchy. Workaround: use esd, and + configure RealPlayer to output to esd. + + + + Broken apps + + + Applications which attempt to open the sound device in read/write + mode (O_RDWR) will fail. This is incorrect OSS behavior, but since + this driver will eventually support recording as well as playback, + we will be able to (in the future) support even broken programs which + unconditionally use O_RDWR. + + + + + + + + + + Thanks + + Via for providing e-mail support, specs, and NDA'd source code. + + + MandrakeSoft for providing hacking time. + + + AC97 mixer interface fixes and debugging by Ron Cemer roncemer@gte.net. + + + + + Random Notes + + Two /proc pseudo-files provide diagnostic information. This is generally + not useful to most users. Power users can disable VIA_PROC_FS macro in the + driver source code, and remove the /proc support code. In any case, once + version 2.0.0 is released, the /proc support code will be disabled by + default. Available /proc pseudo-files: + + + /proc/driver/via/0/info + /proc/driver/via/0/ac97 + + + This driver by default supports all PCI audio devices which report + a vendor id of 0x1106, and a device id of 0x3058. Subsystem vendor + and device ids are not examined. + + + Only supports a single sound chip, as this is a motherboard chipset. + Some architecture remains for multiple cards, feel free to submit + a patch to clean some of that up. + + + No consideration for SMP, this chipset is not known to be found on + any SMP motherboards. However, spin_locks must be used anyway in order + to handle interrupts correctly. + + + GNU indent formatting options: -kr -i8 -pcs + + + Via has graciously donated e-mail support and source code to help further + the development of this driver. Their assistance has been invaluable + in the design and coding of the next major version of this driver. + + + The Via audio chip apparently provides a second PCM scatter-gather + DMA channel just for FM data, but does not have a full hardware MIDI + processor. I haven't put much thought towards a solution here, but it + might involve using SoftOSS midi wave table, or simply disabling MIDI + support altogether and using the FM PCM channel as a second (input? output?) + + + + + Driver ChangeLog + + +Version 1.1.8 + + + + + Clean up interrupt handler output. Fixes the following kernel error message: + + + unhandled interrupt ... + + + + + + Convert documentation to DocBook, so that PDF, HTML and PostScript (.ps) output is readily + available. + + + + + + + +Version 1.1.7 + + + + + Fix module unload bug where mixer device left registered + after driver exit + + + + + + +Version 1.1.6 + + + + + Rewrite via_set_rate to mimic ALSA basic AC97 rate setting + + + + + Remove much dead code + + + + + Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl + + + + + Fix build problem in via_dsp_ioctl + + + + + Optimize included headers to eliminate headers found in linux/drivers/sound + + + + + + +Version 1.1.5 + + + + + Disable some overly-verbose debugging code + + + + + Remove unnecessary sound locks + + + + + Fix some ioctls for better time resolution + + + + + Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl + + + + + + +Version 1.1.4 + + + + + Completed rewrite of driver. Eliminated SoundBlaster compatibility + completely, and now uses the much-faster scatter-gather DMA engine. + + + + + + + + + Internal Functions +!Idrivers/sound/via82cxxx_audio.c + + +
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/filesystems/bfs.txt linux.ac/Documentation/filesystems/bfs.txt --- linux.vanilla/Documentation/filesystems/bfs.txt Thu May 25 17:38:37 2000 +++ linux.ac/Documentation/filesystems/bfs.txt Thu May 25 23:36:46 2000 @@ -54,4 +54,4 @@ If you have any patches, questions or suggestions regarding this BFS implementation please contact the author: -Tigran A. Aivazian . +Tigran A. Aivazian diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/floppy.txt linux.ac/Documentation/floppy.txt --- linux.vanilla/Documentation/floppy.txt Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/floppy.txt Thu Jun 8 14:56:28 2000 @@ -201,11 +201,10 @@ The latest version can be found at fdutils homepage: http://fdutils.linux.lu -The fdutils-5.3 release can be found at: - http://fdutils.linux.lu/fdutils-5.3.src.tar.gz - http://www.tux.org/pub/knaff/fdutils/fdutils-5.3.src.tar.gz - ftp://tsx-11.mit.edu/pub/linux/sources/sbin/fdutils-5.3.src.tar.gz - ftp://metalab.unc.edu/pub/Linux/utils/disk-management/fdutils-5.3.src.tar.gz +The fdutils-5.4 release can be found at: + http://fdutils.linux.lu/fdutils-5.4.src.tar.gz + http://www.tux.org/pub/knaff/fdutils/fdutils-5.4.src.tar.gz + ftp://metalab.unc.edu/pub/Linux/utils/disk-management/fdutils-5.4.src.tar.gz Reporting problems about the floppy driver ========================================== diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/ioctl-number.txt linux.ac/Documentation/ioctl-number.txt --- linux.vanilla/Documentation/ioctl-number.txt Thu May 25 17:38:40 2000 +++ linux.ac/Documentation/ioctl-number.txt Tue Jun 6 16:13:53 2000 @@ -74,6 +74,8 @@ 0x22 all scsi/sg.h '1' 00-1F PPS kit from Ulrich Windl +'6' 00-10 Intel P6 microcode update driver + '8' all SNP8023 advanced NIC card 'A' 00-1F linux/apm_bios.h diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/kernel-doc-nano-HOWTO.txt linux.ac/Documentation/kernel-doc-nano-HOWTO.txt --- linux.vanilla/Documentation/kernel-doc-nano-HOWTO.txt Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/kernel-doc-nano-HOWTO.txt Sun Jun 4 22:21:48 2000 @@ -123,6 +123,25 @@ Take a look around the source tree for examples. + +How to make new SGML template files +----------------------------------- + +SGML template files (*.tmpl) are like normal SGML files, except that +they can contain escape sequences where extracted documentation should +be inserted. + +!E is replaced by the documentation, in , for +functions that are exported using EXPORT_SYMBOL: the function list is +collected from files listed in Documentation/DocBook/Makefile. + +!I is replaced by the documentation for functions that are +_not_ exported using EXPORT_SYMBOL. + +!F is replaced by the +documentation, in , for the functions listed. + + Tim. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/networking/8139too.txt linux.ac/Documentation/networking/8139too.txt --- linux.vanilla/Documentation/networking/8139too.txt Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/networking/8139too.txt Wed May 31 11:25:23 2000 @@ -181,11 +181,20 @@ 11) RTL8139C support untested. +12) 10base-T support flaky + Change History -------------- +Version 0.9.6 - May 30, 2000 + +* Fix 4-extra-bytes bug + (thanks to Markus Westergren, via Santiago Garcia Mantinan) +* Yet more improved chip recognition + + Version 0.9.5 - May 17, 2000 * Improved chip version recognition diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/networking/sk98lin.txt linux.ac/Documentation/networking/sk98lin.txt --- linux.vanilla/Documentation/networking/sk98lin.txt Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/networking/sk98lin.txt Thu May 25 01:40:13 2000 @@ -3,7 +3,7 @@ sk98lin.txt created 11-Nov-1999 -Readme File for sk98lin.o v3.02 +Readme File for sk98lin.o v3.04 SK-NET Gigabit Ethernet Adapter SK-98xx Driver for Linux This file contains @@ -24,8 +24,8 @@ ============ The sk98lin driver supports the SysKonnect SK-NET Gigabit Ethernet -Adapter SK-98xx family on Linux 2.2.x. -It has been tested with Linux on Intel/x86 and ALPHA machines. +Adapter SK-98xx family on Linux 2.2.x and above. +It has been tested with Linux on Intel/x86, ALPHA and UltraSPARC machines. From v3.02 on, the driver is integrated in the linux kernel source. *** @@ -132,7 +132,8 @@ module with 'insmod'. The configuration tools of some distributions can also give parameters to the driver module. If you use the kernel module loader, you can set driver parameters -in the file /etc/conf.modules. Insert a line of the form: +in the file /etc/modules.conf (or old name: /etc/conf.modules). +Insert a line of the form: options sk98lin ... @@ -281,14 +282,12 @@ the large frames. If one adapter is not set to receive large frames, it will simply drop them. -NOTE: If you look at the statistics (with netstat) in large frame - mode while there is traffic on the net, you will see the - RX error counter go up. This is because the adapter hardware - counts received large frames as errors, although they are - received correctly. So ignore this counter in that case. - You can switch back to the standard ethernet frame size with: ifconfig eth0 mtu 1500 + +To make this setting persitent, add a script with the 'ifconfig' +line to the system startup sequence (named something like "S99sk98lin" +in /etc/rc.d/rc2.d). *** @@ -374,15 +373,27 @@ (8) HISTORY =========== -VERSION 3.02 +VERSION 3.04 (In-Kernel version) +Problems fixed: +- Driver start failed on UltraSPARC +- Rx checksum calculation for big endian machines did not work +- Jumbo frames were counted as input-errors in netstat + +VERSION 3.03 (Standalone version) +Problems fixed: +- Compilation did not find script "printver.sh" if "." not in PATH +Known limitations: +- None + +VERSION 3.02 (In-Kernel version) Problems fixed: - None New Features: -- Integration in linux kernel source. +- Integration in Linux kernel source (2.2.14 and 2.3.29) Known limitations: - None -VERSION 3.02 +VERSION 3.01 Problems fixed: - None New Features: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/networking/tlan.txt linux.ac/Documentation/networking/tlan.txt --- linux.vanilla/Documentation/networking/tlan.txt Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/networking/tlan.txt Mon May 29 19:34:42 2000 @@ -2,7 +2,10 @@ (C) 1998 James Banks (C) 1999-2000 Torben Mathiasen -TLAN driver for Linux, version 1.5 +For driver information/updates visit http://tlan.kernel.dk + + +TLAN driver for Linux, version 1.8a README @@ -65,12 +68,15 @@ if a card which only supports 10Mbs is forced into 100Mbs mode.) - 5. If the driver is built into the kernel, you can use the 3rd + 5. You have to use speed=X duplex=Y together now. If you just + do "insmod tlan.o speed=100" the driver will do Auto-Neg. + To force a 10Mbps Half-Duplex link do "insmod tlan.o speed=10 + duplex=1". + + 6. If the driver is built into the kernel, you can use the 3rd and 4th parameters to set aui and debug respectively. For example: -/* kernel-parameters are currently not supported. I will fix this asap. */ - ether=0,0,0x1,0x7,eth0 This sets aui to 0x1 and debug to 0x7, assuming eth0 is a @@ -79,11 +85,14 @@ The bits in the third byte are assigned as follows: 0x01 = aui - 0x04 = use half duplex - 0x08 = use full duplex - 0x10 = use 10BaseT - 0x20 = use 100BaseTx - + 0x02 = use half duplex + 0x04 = use full duplex + 0x08 = use 10BaseT + 0x10 = use 100BaseTx + + You also need to set both speed and duplex settings when forcing + speeds with kernel-parameters. + ether=0,0,0x12,0,eth0 will force link to 100Mbps Half-Duplex. III. Things to try if you have problems. 1. Make sure your card's PCI id is among those listed in @@ -94,5 +103,5 @@ There is also a tlan mailing list which you can join by sending "subscribe tlan" in the body of an email to majordomo@vuser.vu.union.edu. - +There is also a tlan website at http://tlan.kernel.dk diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/networking/tulip.txt linux.ac/Documentation/networking/tulip.txt --- linux.vanilla/Documentation/networking/tulip.txt Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/networking/tulip.txt Thu Jun 8 15:13:13 2000 @@ -142,6 +142,24 @@ Version history =============== +0.9.6 (May 31, 2000): +* Revert 21143-related support flag patch +* Add HPPA/media-table debugging printk + +0.9.5 (May 30, 2000): +* HPPA support (willy@puffingroup) +* CSR6 bits and tulip.h cleanup (Chris Smith) +* Improve debugging messages a bit +* Add delay after CSR13 write in t21142_start_nway +* Remove unused ETHER_STATS code +* Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith) +* Update DS21143 support flags in tulip_chip_info[] +* Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit() +* Add locking to set_rx_mode() +* Fix race with chip setting DescOwned bit (Hal Murray) +* Request 100% of PIO and MMIO resource space assigned to card +* Remove error message from pci_enable_device failure + 0.9.4.3 (April 14, 2000): * mod_timer fix (Hal Murray) * PNIC2 resusitation (Chris Smith) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/networking/vortex.txt linux.ac/Documentation/networking/vortex.txt --- linux.vanilla/Documentation/networking/vortex.txt Thu May 25 17:38:38 2000 +++ linux.ac/Documentation/networking/vortex.txt Tue Jun 6 17:43:20 2000 @@ -156,7 +156,12 @@ "Variables to work-around the Compaq PCI BIOS32 problem".... +watchdog=N + Sets the time duration (in milliseconds) after which the kernel + decides that the transmitter has become stuck and needs to be reset. + This is mainly for debugging purposes. The default value is 400 (0.4 + seconds). Additional resources -------------------- diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/powerpc/00-INDEX linux.ac/Documentation/powerpc/00-INDEX --- linux.vanilla/Documentation/powerpc/00-INDEX Thu May 25 17:38:40 2000 +++ linux.ac/Documentation/powerpc/00-INDEX Thu Jun 8 17:03:00 2000 @@ -1,7 +1,7 @@ Index of files in Documentation/powerpc. If you think something about Linux/PPC needs an entry here, needs correction or you've written one please mail me. - Cort Dougan (cort@cs.nmt.edu) + Cort Dougan (cort@fsmlabs.com) 00-INDEX - this file @@ -9,6 +9,8 @@ - info about the Linux/PPC /proc/ppc_htab entry smp.txt - use and state info about Linux/PPC on MP machines +SBC8260_memory_mapping.txt + - EST SBC8260 board info sound.txt - info on sound support under Linux/PPC zImage_layout.txt diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/powerpc/SBC8260_memory_mapping.txt linux.ac/Documentation/powerpc/SBC8260_memory_mapping.txt --- linux.vanilla/Documentation/powerpc/SBC8260_memory_mapping.txt Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/powerpc/SBC8260_memory_mapping.txt Thu Jun 8 17:03:00 2000 @@ -0,0 +1,197 @@ +Please mail me (Jon Diekema, diekema_jon@si.com or diekema@cideas.com) +if you have questions, comments or corrections. + + * EST SBC8260 Linux memory mapping rules + + http://www.estc.com/ + http://www.estc.com/products/boards/SBC8260-8240_ds.html + + Initial conditions: + ------------------- + + Tasks that need to be perform by the boot ROM before control is + transferred to zImage (compressed Linux kernel): + + - Define the IMMR to 0xf0000000 + + - Initialize the memory controller so that RAM is available at + physical address 0x00000000. On the SBC8260 is this 16M (64M) + SDRAM. + + - The boot ROM should only clear the RAM that it is using. + + The reason for doing this is to enhances the chances of a + successful post mortem on a Linux panic. One of the first + items to examine is the 16k (LOG_BUF_LEN) circular console + buffer called log_buf which is defined in kernel/printk.c. + + - To enhance boot ROM performance, the I-cache can be enabled. + + Date: Mon, 22 May 2000 14:21:10 -0700 + From: Neil Russell + + LiMon (LInux MONitor) runs with and starts Linux with MMU + off, I-cache enabled, D-cache disabled. The I-cache doesn't + need hints from the MMU to work correctly as the D-cache + does. No D-cache means no special code to handle devices in + the presence of cache (no snooping, etc). The use of the + I-cache means that the monitor can run acceptably fast + directly from ROM, rather than having to copy it to RAM. + + - Build the board information structure (see + include/asm-ppc/est8260.h for its definition) + + - The compressed Linux kernel (zImage) contains a bootstrap loader + that is position independent; you can load it into any RAM, + ROM or FLASH memory address >= 0x00500000 (above 5 MB), or + at its link address of 0x00400000 (4 MB). + + Note: If zImage is loaded at its link address of 0x00400000 (4 MB), + then zImage will skip the step of moving itself to + its link address. + + - Load R3 with the address of the board information structure + + - Transfer control to zImage + + - The Linux console port is SMC1, and the baud rate is controlled + from the bi_baudrate field of the board information structure. + On thing to keep in mind when picking the baud rate, is that + there is no flow control on the SMC ports. I would stick + with something safe and standard like 19200. + + On the EST SBC8260, the SMC1 port is on the COM1 connector of + the board. + + + EST SBC8260 defaults: + --------------------- + + Chip + Memory Sel Bus Use + --------------------- --- --- ---------------------------------- + 0x00000000-0x03FFFFFF CS2 60x (16M or 64M)/64M SDRAM + 0x04000000-0x04FFFFFF CS4 local 4M/16M SDRAM (soldered to the board) + 0x21000000-0x21000000 CS7 60x 1B/64K Flash present detect (from the flash SIMM) + 0x21000001-0x21000001 CS7 60x 1B/64K Switches (read) and LEDs (write) + 0x22000000-0x2200FFFF CS5 60x 8K/64K EEPROM + 0xFC000000-0xFCFFFFFF CS6 60x 2M/16M flash (8 bits wide, soldered to the board) + 0xFE000000-0xFFFFFFFF CS0 60x 4M/16M flash (SIMM) + + Notes: + ------ + + - The chip selects can map 32K blocks and up (powers of 2) + + - The SDRAM machine can handled up to 128Mbytes per chip select + + - Linux uses the 60x bus memory (the SDRAM DIMM) for the + communications buffers. + + - BATs can map 128K-256Mbytes each. There are four data BATs and + four instruction BATs. Generally the data and instruction BATs + are mapped the same. + + - The IMMR must be set above the kernel virtual memory addresses, + which start at 0xC0000000. Otherwise, the kernel may crash as + soon as you start any threads or processes due to VM collisions + in the kernel or user process space. + + + Details from Dan Malek on 10/29/1999: + + The user application virtual space consumes the first 2 Gbytes + (0x00000000 to 0x7FFFFFFF). The kernel virtual text starts at + 0xC0000000, with data following. There is a "protection hole" + between the end of kernel data and the start of the kernel + dynamically allocated space, but this space is still within + 0xCxxxxxxx. + + Obviously the kernel can't map any physical addresses 1:1 in + these ranges. + + + Details from Dan Malek on 5/19/2000: + + During the early kernel initialization, the kernel virtual + memory allocator is not operational. Prior to this KVM + initialization, we choose to map virtual to physical addresses + 1:1. That is, the kernel virtual address exactly matches the + physical address on the bus. These mappings are typically done + in arch/ppc/kernel/head.S, or arch/ppc/mm/init.c. Only + absolutely necessary mappings should be done at this time, for + example board control registers or a serial uart. Normal device + driver initialization should map resources later when necessary. + + Although platform dependent, and certainly the case for embedded + 8xx, traditionally memory is mapped at physical address zero, + and I/O devices above phsical address 0x80000000. The lowest + and highest (above 0xf0000000) I/O addresses are traditionally + used for devices or registers we need to map during kernel + initialization and prior to KVM operation. For this reason, + and since it followed prior PowerPC platform examples, I chose + to map the embedded 8xx kernel to the 0xc0000000 virtual address. + This way, we can enable the MMU to map the kernel for proper + operation, and still map a few windows before the KVM is operational. + + On some systems, you could possibly run the kernel at the + 0x80000000 or any other virtual address. It just depends upon + mapping that must be done prior to KVM operational. You can never + map devices or kernel spaces that overlap with the user virtual + space. This is why default IMMR mapping used by most BDM tools + won't work. They put the IMMR at something like 0x10000000 or + 0x02000000 for example. You simply can't map these addresses early + in the kernel, and continue proper system operation. + + The embedded 8xx/82xx kernel is mature enough that all you should + need to do is map the IMMR someplace at or above 0xf0000000 and it + should boot far enough to get serial console messages and KGDB + connected on any platform. There are lots of other subtle memory + management design features that you simply don't need to worry + about. If you are changing functions related to MMU initialization, + you are likely breaking things that are known to work and are + heading down a path of disaster and frustration. Your changes + should be to make the flexibility of the processor fit Linux, + not force arbitrary and non-workable memory mappings into Linux. + + - You don't want to change KERNELLOAD or KERNELBASE, otherwise the + virtual memory and MMU code will get confused. + + arch/ppc/Makefile:KERNELLOAD = 0xc0000000 + + include/asm-ppc/page.h:#define PAGE_OFFSET 0xc0000000 + include/asm-ppc/page.h:#define KERNELBASE PAGE_OFFSET + + - RAM is at physical address 0x00000000, and gets mapped to + virtual address 0xC0000000 for the kernel. + + + Physical addresses used by the Linux kernel: + -------------------------------------------- + + 0x00000000-0x3FFFFFFF 1GB reserved for RAM + 0xF0000000-0xF001FFFF 128K IMMR 64K used for dual port memory, + 64K for 8260 registers + + + Logical addresses used by the Linux kernel: + ------------------------------------------- + + 0xF0000000-0xFFFFFFFF 256M BAT0 (IMMR: dual port RAM, registers) + 0xE0000000-0xEFFFFFFF 256M BAT1 (I/O space for custom boards) + 0xC0000000-0xCFFFFFFF 256M BAT2 (RAM) + 0xD0000000-0xDFFFFFFF 256M BAT3 (if RAM > 256MByte) + + + EST SBC8260 Linux mapping: + -------------------------- + + DBAT0, IBAT0, cache inhibited: + + Chip + Memory Sel Use + --------------------- --- --------------------------------- + 0xF0000000-0xF001FFFF n/a IMMR: dual port RAM, registers + + DBAT1, IBAT1, cache inhibited: + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/sound/Maestro linux.ac/Documentation/sound/Maestro --- linux.vanilla/Documentation/sound/Maestro Thu May 25 17:38:40 2000 +++ linux.ac/Documentation/sound/Maestro Sat May 27 15:32:55 2000 @@ -6,7 +6,7 @@ ------------------------------ The most recent version of this driver will hopefully always be available at - http://people.redhat.com/zab/maestro/ + http://www.zabbo.net/maestro/ I will try and maintain the most recent stable version of the driver in both the stable and development kernel lines. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/sound/README.ymfsb linux.ac/Documentation/sound/README.ymfsb --- linux.vanilla/Documentation/sound/README.ymfsb Thu Jan 1 01:00:00 1970 +++ linux.ac/Documentation/sound/README.ymfsb Sun Jun 4 21:42:08 2000 @@ -0,0 +1,107 @@ +Legacy audio driver for YMF7xx PCI cards. + + +FIRST OF ALL +============ + + This code references YAMAHA's sample codes and data sheets. + I respect and thank for all people they made open the informations + about YMF7xx cards. + + And this codes heavily based on Jeff Garzik 's + old VIA 82Cxxx driver (via82cxxx.c). I also respect him. + + +DISCLIMER +========= + + This driver is currently at early ALPHA stage. It may cause serious + damage to your computer when used. + PLEASE USE IT AT YOUR OWN RISK. + + +ABOUT THIS DRIVER +================= + + This code enables you to use your YMF724[A-F], YMF740[A-C], YMF744, YMF754 + cards. When enabled, your card acts as "SoundBlaster Pro" compatible card. + It can only play 22.05kHz / 8bit / Stereo samples, control external MIDI + port. + If you want to use your card as recent "16-bit" card, you should use + Alsa or OSS/Linux driver. Ofcource you can write native PCI driver for + your cards :) + + +USAGE +===== + + # modprobe ymfsb (options) + + +OPTIONS FOR MODULE +================== + + io : SB base address (0x220, 0x240, 0x260, 0x280) + synth_io : OPL3 base address (0x388, 0x398, 0x3a0, 0x3a8) + dma : DMA number (0,1,3) + master_volume: AC'97 PCM out Vol (0-100) + spdif_out : SPDIF-out flag (0:disable 1:enable) + + These options will change in future... + + +FREQUENCY +========= + + When playing sounds via this driver, you will hear its pitch is slightly + lower than original sounds. Since this driver recognizes your card acts + with 21.739kHz sample rates rather than 22.050kHz (I think it must be + hardware restriction). So many players become tone deafness. + To prevent this, you should express some options to your sound player + that specify correct sample frequency. For example, to play your MP3 file + correctly with mpg123, specify the frequency like following: + + % mpg123 -r 21739 foo.mp3 + + +SPDIF OUT +========= + + With installing modules with option 'spdif_out=1', you can enjoy your + sounds from SPDIF-out of your card (if it had). + Its Fs is fixed to 48kHz (It never means the sample frequency become + up to 48kHz. All sounds via SPDIF-out also 22kHz samples). So your + digital-in capable components has to be able to handle 48kHz Fs. + + +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, 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. + + +TODO +==== + * support for multiple cards + (set the different SB_IO,MPU_IO,OPL_IO for each cards) + + * support for OPL (dmfm) : There will be no requirements... :-< + + +AUTHOR +====== + + Daisuke Nagano + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/sound/via82cxxx.txt linux.ac/Documentation/sound/via82cxxx.txt --- linux.vanilla/Documentation/sound/via82cxxx.txt Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/sound/via82cxxx.txt Sun Jun 4 22:05:16 2000 @@ -48,6 +48,15 @@ Driver notes ------------------------------------------------------------------------ +Two /proc pseudo-files provide diagnostic information. This is generally +not useful to most users. Power users can disable VIA_PROC_FS macro in the +driver source code, and remove the /proc support code. In any case, once +version 2.0.0 is released, the /proc support code will be disabled by +default. Available /proc pseudo-files: + + /proc/driver/via/0/info + /proc/driver/via/0/ac97 + This driver by default supports all PCI audio devices which report a vendor id of 0x1106, and a device id of 0x3058. Subsystem vendor and device ids are not examined. @@ -110,7 +119,8 @@ 1) Volume too low on many systems. Workaround: use mixer program such as xmixer to increase volume. -2) RealPlayer output very scratchy. +2) RealPlayer output very scratchy. Workaround: use esd, and +configure RealPlayer to output to esd. 3) Applications which attempt to open the sound device in read/write mode (O_RDWR) will fail. This is incorrect OSS behavior, but since @@ -137,5 +147,30 @@ If you wish to increase the size of the buffer displayed by 'dmesg', then change the LOG_BUF_LEN macro at the top of linux/kernel/printk.c, recompile your kernel, and pass the "-s " option to 'dmesg'. + + + +Change history +------------------------------------------------------------------------ +Version 1.1.7: +* Fix module unload bug where mixer device left registered + after driver exit + +Version 1.1.6: +* Rewrite via_set_rate to mimic ALSA basic AC97 rate setting +* Remove much dead code +* Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl +* Fix build problem in via_dsp_ioctl +* Optimize included headers to eliminate headers found in linux/drivers/sound + +Version 1.1.5: +* Disable some overly-verbose debugging code +* Remove unnecessary sound locks +* Fix some ioctls for better time resolution +* Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl + +Version 1.1.4: +* Completed rewrite of driver. Eliminated SoundBlaster compatibility + completely, and now uses the much-faster scatter-gather DMA engine. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/usb/input.txt linux.ac/Documentation/usb/input.txt --- linux.vanilla/Documentation/usb/input.txt Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/usb/input.txt Tue May 30 21:28:07 2000 @@ -1,6 +1,7 @@ - Linux Input drivers v0.9 - (c) 1999 Vojtech Pavlik + Linux Input drivers v1.0 + (c) 1999-2000 Vojtech Pavlik Sponsored by SuSE + $Id: input.txt,v 1.4 2000/05/28 17:57:22 vojtech Exp $ ---------------------------------------------------------------------------- 0. Disclaimer @@ -62,27 +63,27 @@ hid.o After this, the USB keyboard will work straight away, and the USB mouse -will be available as a character device on major 13, minor 32: +will be available as a character device on major 13, minor 63: - crw-r--r-- 1 root root 13, 32 Mar 28 22:45 mouse0 + crw-r--r-- 1 root root 13, 63 Mar 28 22:45 mice This device, has to be created, unless you use devfs, in which case it's created automatically. The commands to do that are: cd /dev mkdir input - mknod input/mouse0 c 13 32 + mknod input/mice c 13 63 After that you have to point GPM (the textmode mouse cut&paste tool) and XFree to this device to use it - GPM should be called like: - gpm -t ps2 -m /dev/input/mouse0 + gpm -t ps2 -m /dev/input/mice And in X: Section "Pointer" Protocol "ImPS/2" - Device "/dev/input/mouse0" + Device "/dev/input/mice" ZAxisMapping 4 5 EndSection @@ -199,10 +200,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are the size of your screen (in pixels) in XFree86. This is needed if you want to use your digitizer in X, because it's movement is sent to X via a virtual PS/2 -mouse. These values won't be used if you use a mouse only. +mouse and thus needs to be scaled accordingly. These values won't be used if +you use a mouse only. - Mousedev.c will generate either PS/2, ImPS/2 (microsoft intellimouse) or -GenPS/2 (genius netmouse/netscroll) protocols, depending on what the program + Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or +GenPS/2 (Genius NetMouse/NetScroll) protocols, depending on what the program reading the data wishes. You can set GPM and X to any of these. You'll need ImPS/2 if you want to make use of a wheel on a USB mouse and GenPS/2 if you want to use extra (up to 5) buttons. I'm not sure how much is GenPS/2 supported @@ -249,8 +251,12 @@ http://www.suse.cz/development/input/ -You'll find both the latest HID driver and the complete Input driver there. -There is also a mailing list for this: +You'll find both the latest HID driver and the complete Input driver there +as well as information how to access the CVS repository for latest revisions +of the drivers. + + + There is also a mailing list for this: majordomo@atrey.karlin.mff.cuni.cz @@ -278,8 +284,8 @@ to be extended, but not changed incompatibly as time goes: You can use blocking and nonblocking reads, also select() on the -/dev/inputX devices, and you'll always get a whole number of input events on -a read. Their layout is: +/dev/input/eventX devices, and you'll always get a whole number of input +events on a read. Their layout is: struct input_event { struct timeval time; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/video4linux/bttv/CARDLIST linux.ac/Documentation/video4linux/bttv/CARDLIST --- linux.vanilla/Documentation/video4linux/bttv/CARDLIST Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/video4linux/bttv/CARDLIST Sun Jun 4 21:51:41 2000 @@ -42,6 +42,8 @@ card=40 - STB2 card=41 - AVerMedia TVPhone 98 card=42 - ProVideo PV951 + card=43 - Little OnAir TV + card=44 - Sigma TVII-FM tuner.o type=0 - Temic PAL diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/video4linux/bttv/Insmod-options linux.ac/Documentation/video4linux/bttv/Insmod-options --- linux.vanilla/Documentation/video4linux/bttv/Insmod-options Thu May 25 17:38:41 2000 +++ linux.ac/Documentation/video4linux/bttv/Insmod-options Sun Jun 4 21:51:41 2000 @@ -3,7 +3,7 @@ the bt848 (grabber chip) driver insmod args: - card=n card type, see cardlist for a list. + card=n card type, see CARDLIST for a list. radio=0/1 card supports radio pll=0/1/2 pll settings 0: don't use PLL @@ -31,6 +31,29 @@ remap, card, radio and pll accept up to four comma-separated arguments (for multiple boards). +tuner.o + The tuner driver. You need this unless you want to use only + with a camera or external tuner ... + + insmod args: + debug=1 print some debug info to the syslog + type=n type of the tuner chip. n as follows: + see CARDLIST for a complete list. + +tvmixer.o + registers a mixer device for the TV card's volume/bass/treble + controls (requires a i2c audio control chip like the msp3400). + + insmod args: + debug=1 print some debug info to the syslog. + devnr=n allocate device #n (0 == /dev/mixer, + 1 = /dev/mixer1, ...), default is to + use the first free one. + +tvaudio.o + new, experimental module which is supported to provide a single + driver for all simple i2c audio control chips (tda/tea*). + msp3400.o The driver for the msp34xx sound processor chips. If you have a stereo card, you probably want to insmod this one. @@ -47,8 +70,6 @@ amsound=1 Audio carrier is AM/NICAM at 6.5 Mhz. This should improve things for french people, the carrier autoscan seems to work with FM only... - mixer=n allocate mixer device #n. Default is the - first free slot. tea6300.o The driver for the tea6300 fader chip. If you have a stereo @@ -73,20 +94,3 @@ insmod args: debug=1 print some debug info to the syslog. chip=9850/9855 set the chip type. - -tuner.o - The tuner driver. You need this unless you want to use only - with a camera or external tuner ... - - insmod args: - debug=1 print some debug info to the syslog - type=n type of the tuner chip. n as follows: - 0: Temic PAL tuner - 1: Philips PAL_I tuner - 2: Philips NTSC tuner - 3: Philips SECAM tuner - 4: no tuner - 5: Philips PAL tuner - 6: Temic NTSC tuner - 7: Temic PAL tuner - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/MAINTAINERS linux.ac/MAINTAINERS --- linux.vanilla/MAINTAINERS Thu May 25 17:46:15 2000 +++ linux.ac/MAINTAINERS Sat Jun 10 21:38:29 2000 @@ -178,7 +178,7 @@ BFS FILE SYSTEM P: Tigran A. Aivazian -M: tigran@ocston.org +M: tigran@veritas.com L: linux-kernel@vger.rutgers.edu W: http://www.ocston.org/~tigran/patches/bfs S: Maintained @@ -234,6 +234,11 @@ W: http://www.fi.muni.cz/~kas/cosa/ S: Maintained +CPUID/MSR DRIVER +P: H. Peter Anvin +M: hpa@zytor.com +S: Maintained + CREDITS FILE P: John A. Martin M: jam@acm.org @@ -300,11 +305,19 @@ DIGI RIGHTSWITCH NETWORK DRIVER P: Rick Richardson -M: rick@dgii.com +M: rick@remotepoint.com L: linux-net@vger.rutgers.edu W: http://www.dgii.com/linux/ S: Maintained +DISK GEOMETRY AND PARTITION HANDLING +P: Andries Brouwer +M: aeb@veritas.com +W: http://www.win.tue.nl/~aeb/linux/Large-Disk.html +W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html +W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html +S: Maintained + DISKQUOTA: P: Marco van Wieringen M: mvw@planets.elm.net @@ -540,7 +553,7 @@ INTEL P6 MICROCODE UPDATE SUPPORT P: Tigran Aivazian -M: tigran@sco.com +M: tigran@veritas.com S: Maintained IP MASQUERADING: @@ -580,6 +593,13 @@ W: http://www.isdn4linux.de S: Maintained +ISDN SUBSYSTEM (Eicon active card driver) +P: Armin Schindler +M: mac@melware.de +L: isdn4linux@listserv.isdn4linux.de +W: http://www.melware.de +S: Maintained + JOYSTICK DRIVER P: Vojtech Pavlik M: vojtech@suse.cz @@ -659,7 +679,8 @@ MISCELLANEOUS MCA-SUPPORT P: David Weinehall -M: tao@acc.umu.se (personal) +M: Project MCA Team +M: David Weinehall W: http://www.acc.umu.se/~tao/ W: http://www.acc.umu.se/~mcalinux/ L: linux-kernel@vger.rutgers.edu @@ -699,12 +720,12 @@ NETFILTER P: Rusty Russell -M: Rusty.Russell@rustcorp.com.au +M: rusty@linuxcare.com P: Marc Boucher M: marc@mbsi.ca W: http://www.samba.org/netfilter/ W: http://netfilter.kernelnotes.org -W: http://antarctica.penguincomputing.com/~netfilter/ +W: http://netfilter.filewatcher.org L: netfilter@lists.samba.org S: Supported @@ -744,8 +765,8 @@ NI5010 NETWORK DRIVER P: Jan-Pascal van Best and Andreas Mohr -M: jvbest@qv3pluto.leidenuniv.nl (Best) -M: 100.30936@germany.net (Mohr) +M: Jan-Pascal van Best +M: Andreas Mohr <100.30936@germany.net> L: linux-net@vger.rutgers.edu S: Maintained @@ -793,12 +814,12 @@ P: Andrea Arcangeli M: andrea@e-mind.com L: linux-parport@torque.net -W: http://www.cyberelk.demon.co.uk/parport.html +W: http://people.redhat.com/twaugh/parport/ S: Maintained PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES -P: Grant Guenther -M: grant@torque.net +P: Tim Waugh +M: tim@cyberelk.demon.co.uk L: linux-parport@torque.net W: http://www.torque.net/linux-pp.html S: Maintained @@ -1051,6 +1072,8 @@ M: torben.mathiasen@compaq.com M: tmm@image.dk L: tlan@vuser.vu.union.edu +L: linux-net@vger.rutgers.edu +W: http://tlan.kernel.dk S: Maintained TOKEN-RING NETWORK DRIVER diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Makefile linux.ac/Makefile --- linux.vanilla/Makefile Thu May 25 17:46:15 2000 +++ linux.ac/Makefile Sat Jun 10 22:20:12 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test1 +EXTRAVERSION = -test1-ac13 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -142,7 +142,7 @@ DRIVERS-$(CONFIG_WAN) += drivers/net/wan/wan.a DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnet.a DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o -DRIVERS-$(CONFIG_IDE) += drivers/ide/ide.a +DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsi.a DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394.a @@ -421,7 +421,10 @@ pdfdocs: sgmldocs $(MAKE) -C Documentation/DocBook pdf - + +htmldocs: sgmldocs + $(MAKE) -C Documentation/DocBook html + sums: find . -type f -print | sort | xargs sum > .SUMS diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/alpha/defconfig linux.ac/arch/alpha/defconfig --- linux.vanilla/arch/alpha/defconfig Thu May 25 17:38:24 2000 +++ linux.ac/arch/alpha/defconfig Mon May 29 19:25:14 2000 @@ -83,10 +83,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/Makefile linux.ac/arch/arm/Makefile --- linux.vanilla/arch/arm/Makefile Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/Makefile Sun Jun 4 21:14:16 2000 @@ -19,7 +19,7 @@ AFLAGS += -mno-fpu CFLAGS_PIPE := -pipe -CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) +CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) -msoft-float ifdef CONFIG_FRAME_POINTER CFLAGS := $(CFLAGS:-fomit-frame-pointer=) @@ -29,11 +29,13 @@ CFLAGS += -g endif +GZFLAGS = -9 + # Ensure this is ld "2.9.4" or later NEW_LINKER := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi) ifneq ($(NEW_LINKER),y) -dummy:; @echo '*** 2.3 kernels no longer build correctly with old versions of binutils.' +dummy:; @echo '*** ${VERSION}.${PATCHLEVEL} kernels no longer build correctly with old versions of binutils.' @echo '*** Please upgrade your binutils to 2.9.5.' @false endif @@ -45,7 +47,7 @@ # select flags depending on the compiler # ifeq ($(NEW_GCC),y) -CFLAGS += -mshort-load-bytes -msoft-float +CFLAGS += -mshort-load-bytes CFLAGS_PROC_CPU_26 := -mcpu=arm3 -Os CFLAGS_PROC_CPU_32v3 := -march=armv3 CFLAGS_PROC_CPU_32v4 := -march=armv4 @@ -110,7 +112,7 @@ LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) -export LIBGCC MACHINE PROCESSOR TEXTADDR +export LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS ifeq ($(CONFIG_ARCH_A5K),y) MACHINE = a5k diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/boot/compressed/Makefile linux.ac/arch/arm/boot/compressed/Makefile --- linux.vanilla/arch/arm/boot/compressed/Makefile Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/boot/compressed/Makefile Sun Jun 4 21:14:16 2000 @@ -89,7 +89,7 @@ piggy.o: $(SYSTEM) $(OBJCOPY) $(SYSTEM) piggy - gzip -9 < piggy > piggy.gz + gzip $(GZFLAGS) < piggy > piggy.gz $(LD) -r -o $@ -b binary piggy.gz rm -f piggy piggy.gz diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/boot/compressed/head-sa1100.S linux.ac/arch/arm/boot/compressed/head-sa1100.S --- linux.vanilla/arch/arm/boot/compressed/head-sa1100.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/boot/compressed/head-sa1100.S Sun Jun 4 21:14:16 2000 @@ -133,6 +133,5 @@ #endif @ Restore initial r0/r1 - @ (r8 preserved) mov r0, r8 mov r1, r9 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/boot/compressed/head.S linux.ac/arch/arm/boot/compressed/head.S --- linux.vanilla/arch/arm/boot/compressed/head.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/boot/compressed/head.S Sun Jun 4 21:14:16 2000 @@ -178,9 +178,13 @@ .align 5 cache_on: ldr r1, proc_sa110_type eor r1, r1, r6 - movs r1, r1, lsr #5 + movs r1, r1, lsr #5 @ catch SA110 and SA1100 + beq 1f + ldr r1, proc_sa1110_type + eor r1, r1, r6 + movs r1, r1, lsr #4 movne pc, lr - +1: sub r3, r4, #16384 @ Page directory size bic r3, r3, #0xff @ Align the pointer bic r3, r3, #0x3f @@ -259,6 +263,11 @@ .word 0x4401a100 .size proc_sa110_type, . - proc_sa110_type + .type proc_sa1110_type,#object +proc_sa1110_type: + .word 0x6901b110 + .size proc_sa1110_type, . - proc_sa1110_type + /* * Turn off StrongARM cache and MMU. It is safe to * leave the I-cache on. @@ -273,8 +282,13 @@ .align 5 cache_off: ldr r1, proc_sa110_type eor r1, r1, r6 - movs r1, r1, lsr #5 + movs r1, r1, lsr #5 @ catch SA110 and SA1100 + beq 1f + ldr r1, proc_sa1110_type + eor r1, r1, r6 + movs r1, r1, lsr #4 movne pc, lr +1: mrc p15, 0, r0, c1, c0 bic r0, r0, #0x000d mcr p15, 0, r0, c1, c0 @@ -292,11 +306,15 @@ */ .align 5 cache_clean_flush: - ldr r1, proc_sa110_type @ SA-110 or SA-1100? + ldr r1, proc_sa110_type + eor r1, r1, r6 + movs r1, r1, lsr #5 @ catch SA110 and SA1100 + beq 1f + ldr r1, proc_sa1110_type eor r1, r1, r6 - movs r1, r1, lsr #5 + movs r1, r1, lsr #4 movne pc, lr - +1: bic r1, pc, #31 add r2, r1, #32768 1: ldr r12, [r1], #32 @ s/w flush D cache diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/config.in linux.ac/arch/arm/config.in --- linux.vanilla/arch/arm/config.in Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/config.in Sun Jun 4 21:14:16 2000 @@ -19,39 +19,43 @@ choice 'ARM system type' \ "Archimedes CONFIG_ARCH_ARC \ A5000 CONFIG_ARCH_A5K \ - RiscPC CONFIG_ARCH_RPC \ EBSA-110 CONFIG_ARCH_EBSA110 \ - FootBridge-based CONFIG_FOOTBRIDGE" RiscPC + FootBridge-based CONFIG_FOOTBRIDGE \ + RiscPC CONFIG_ARCH_RPC \ + SA1100-based CONFIG_ARCH_SA1100" RiscPC # the following are placeholders for when they are fully integrated +# Cirrus CL-PS7500FE CONFIG_ARCH_CLPS7500 \ # LinkUp-L7200 CONFIG_ARCH_L7200 -# SA1100-based CONFIG_ARCH_SA1100 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE - if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then - define_bool CONFIG_ADDIN_FOOTBRIDGE n + comment 'Footbridge Implementations' + + bool ' CATS support' CONFIG_ARCH_CATS + bool ' Compaq Personal Server support' CONFIG_ARCH_PERSONAL_SERVER + bool ' EBSA285 (host mode) support' CONFIG_ARCH_EBSA285 + bool ' NetWinder support' CONFIG_ARCH_NETWINDER + + if [ "$CONFIG_ARCH_EBSA285" = "y" -o \ + "$CONFIG_ARCH_CATS" = "y" -o \ + "$CONFIG_ARCH_NETWINDER" = "y" -o \ + "$CONFIG_ARCH_PERSONAL_SERVER" = "y" ]; then + define_bool CONFIG_FOOTBRIDGE_HOST y + define_bool CONFIG_FOOTBRIDGE_ADDIN n else - define_bool CONFIG_ADDIN_FOOTBRIDGE y + define_bool CONFIG_FOOTBRIDGE_HOST n + define_bool CONFIG_FOOTBRIDGE_ADDIN y fi -fi - -if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then - comment 'Footbridge Implementations' - bool ' Include support for EBSA285' CONFIG_ARCH_EBSA285 - bool ' Include support for CATS' CONFIG_ARCH_CATS - bool ' Include support for NetWinder' CONFIG_ARCH_NETWINDER - bool ' Include support for Compaq Personal Server' CONFIG_ARCH_PERSONAL_SERVER -fi -if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then - # If we get any other footbridge-based plug-in boards, then - # add your architecture options here - define_bool CONFIG_ARCH_CO285 y + if [ "$CONFIG_FOOTBRIDGE_ADDIN" = "y" ]; then + # If we get any other footbridge-based plug-in boards, then + # add your architecture options here + define_bool CONFIG_ARCH_CO285 y + fi fi if [ "$CONFIG_ARCH_SA1100" = "y" ]; then comment 'SA11x0 Implementations' - bool ' Include support for Assabet' CONFIG_SA110_ASSABET + bool ' Include support for Assabet' CONFIG_SA1100_ASSABET bool ' Include support for Bitsy' CONFIG_SA1100_BITSY bool ' Include support for Brutus' CONFIG_SA1100_BRUTUS # bool ' Include support for Empeg' CONFIG_SA1100_EMPEG @@ -113,6 +117,10 @@ define_bool CONFIG_CPU_32v4 y define_bool CONFIG_CPU_SA110 y fi +if [ "$CONFIG_ARCH_CLPS7500" = "y" ]; then + define_bool CONFIG_CPU_32v4 y + define_bool CONFIG_CPU_ARM7 y +fi if [ "$CONFIG_ARCH_L7200" = "y" ]; then define_bool CONFIG_CPU_32v4 y define_bool CONFIG_CPU_ARM720 y @@ -126,7 +134,7 @@ # These machines always have PCI # if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \ - "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then + "$CONFIG_FOOTBRIDGE_HOST" = "y" ]; then define_bool CONFIG_PCI y source drivers/pci/Config.in else @@ -189,20 +197,25 @@ "$CONFIG_ARCH_NETWINDER" = "y" -o \ "$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \ "$CONFIG_ARCH_CATS" = "y" ]; then - string 'Initial kernel command string' CONFIG_CMDLINE + string 'Initial kernel command string' CONFIG_CMDLINE "" fi if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ "$CONFIG_ARCH_EBSA110" = "y" -o \ "$CONFIG_ARCH_EBSA285" = "y" -o \ - "$CONFIG_ARCH_CO285" = "y" ]; then + "$CONFIG_ARCH_CO285" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" ]; then bool 'Timer and CPU usage LEDs' CONFIG_LEDS if [ "$CONFIG_LEDS" = "y" ]; then if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \ "$CONFIG_ARCH_EBSA285" = "y" -o \ - "$CONFIG_ARCH_CO285" = "y" ]; then + "$CONFIG_ARCH_CO285" = "y" -o \ + "$CONFIG_ARCH_SA1100" = "y" ]; then bool ' Timer LED' CONFIG_LEDS_TIMER bool ' CPU usage LED' CONFIG_LEDS_CPU fi + fi + if [ "$CONFIG_ARCH_EBSA110" = "y" ]; then + define_bool CONFIG_LEDS_TIMER y fi fi endmenu diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/a5k linux.ac/arch/arm/def-configs/a5k --- linux.vanilla/arch/arm/def-configs/a5k Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/a5k Mon May 29 19:25:14 2000 @@ -94,10 +94,6 @@ # CONFIG_BLK_DEV_IDEDMA_ICS is not set # CONFIG_BLK_DEV_IDE_RAPIDE is not set # CONFIG_IDE_CHIPSETS is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/assabet linux.ac/arch/arm/def-configs/assabet --- linux.vanilla/arch/arm/def-configs/assabet Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/assabet Mon May 29 19:25:14 2000 @@ -91,10 +91,6 @@ # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/brutus linux.ac/arch/arm/def-configs/brutus --- linux.vanilla/arch/arm/def-configs/brutus Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/brutus Sun Jun 4 21:14:16 2000 @@ -95,10 +95,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set @@ -216,10 +212,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -227,11 +225,16 @@ # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_NCPFS_NLS is not set # # Partition Types diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/ebsa110 linux.ac/arch/arm/def-configs/ebsa110 --- linux.vanilla/arch/arm/def-configs/ebsa110 Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/ebsa110 Mon May 29 19:25:14 2000 @@ -90,10 +90,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/footbridge linux.ac/arch/arm/def-configs/footbridge --- linux.vanilla/arch/arm/def-configs/footbridge Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/footbridge Mon May 29 19:25:14 2000 @@ -138,10 +138,6 @@ CONFIG_PARIDE_ON26=m # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/graphicsclient linux.ac/arch/arm/def-configs/graphicsclient --- linux.vanilla/arch/arm/def-configs/graphicsclient Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/graphicsclient Mon May 29 19:25:14 2000 @@ -84,10 +84,6 @@ # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/lart linux.ac/arch/arm/def-configs/lart --- linux.vanilla/arch/arm/def-configs/lart Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/lart Mon May 29 19:25:14 2000 @@ -85,10 +85,6 @@ # # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/lusl7200 linux.ac/arch/arm/def-configs/lusl7200 --- linux.vanilla/arch/arm/def-configs/lusl7200 Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/lusl7200 Mon May 29 19:25:14 2000 @@ -79,10 +79,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/rpc linux.ac/arch/arm/def-configs/rpc --- linux.vanilla/arch/arm/def-configs/rpc Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/rpc Mon May 29 19:25:14 2000 @@ -91,10 +91,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/thinclient linux.ac/arch/arm/def-configs/thinclient --- linux.vanilla/arch/arm/def-configs/thinclient Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/thinclient Sun Jun 4 21:14:16 2000 @@ -94,10 +94,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set @@ -336,10 +332,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -347,23 +345,39 @@ # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/def-configs/victor linux.ac/arch/arm/def-configs/victor --- linux.vanilla/arch/arm/def-configs/victor Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/def-configs/victor Mon May 29 19:25:14 2000 @@ -80,10 +80,6 @@ # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_IDE_CHIPSETS is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/defconfig linux.ac/arch/arm/defconfig --- linux.vanilla/arch/arm/defconfig Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/defconfig Mon May 29 19:25:14 2000 @@ -134,10 +134,6 @@ CONFIG_PARIDE_ON26=m # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_MD=y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/Makefile linux.ac/arch/arm/kernel/Makefile --- linux.vanilla/arch/arm/kernel/Makefile Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/Makefile Sun Jun 4 21:14:16 2000 @@ -17,6 +17,7 @@ O_OBJS_rpc = dma-rpc.o O_OBJS_ebsa110 = dma-dummy.o O_OBJS_footbridge = dma.o dma-footbridge.o $(ISA_DMA_OBJS) hw-footbridge.o isa.o +O_OBJS_clps7500 = dma-dummy.o O_OBJS_nexuspci = dma-dummy.o O_OBJS_sa1100 = dma-dummy.o fiq.o O_OBJS_l7200 = dma-dummy.o fiq.o @@ -25,9 +26,9 @@ # Object file lists. -obj-y := arch.o $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o \ - semaphore.o setup.o signal.o sys_arm.o time.o traps.o \ - $(O_OBJS_$(MACHINE)) +obj-y := arch.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ + semaphore.o setup.o signal.o sys_arm.o time.o \ + traps.o $(O_OBJS_$(MACHINE)) obj-m := obj-n := obj- := diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/arch.c linux.ac/arch/arm/kernel/arch.c --- linux.vanilla/arch/arm/kernel/arch.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/arch.c Sun Jun 4 21:14:16 2000 @@ -55,6 +55,7 @@ for (i = 0; i < 4; i++) { mi->bank[i].start = PHYS_OFFSET + (i << 26); + mi->bank[i].node = 0; mi->bank[i].size = params->u1.s.pages_in_bank[i] * params->u1.s.page_size; @@ -181,6 +182,7 @@ mi->nr_banks = 1; mi->bank[0].start = PHYS_OFFSET; mi->bank[0].size = boot_memory_end; + mi->bank[0].node = 0; *cmdline = boot_command_line; } @@ -197,7 +199,8 @@ extern void select_sa1100_io_desc(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ - mi->bank[__nr].size = (__size) + mi->bank[__nr].size = (__size), \ + mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) static void __init fixup_sa1100(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) @@ -252,7 +255,7 @@ setup_initrd(0xc0400000, 4*1024*1024); } - else if (machine_is_thinclient()) { + else if (machine_is_thinclient() || machine_is_graphicsclient()) { SET_BANK( 0, 0xc0000000, 16*1024*1024 ); mi->nr_banks = 1; @@ -312,6 +315,12 @@ FIXUP(fixup_sa1100) MACHINE_END #endif +#ifdef CONFIG_SA1100_GRAPHICSCLIENT +MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END +#endif #ifdef CONFIG_SA1100_ITSY MACHINE_START(ITSY, "Compaq Itsy") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) @@ -349,6 +358,29 @@ FIXUP(fixup_sa1100) MACHINE_END #endif +#endif + +#ifdef CONFIG_ARCH_L7200 + +static void __init +fixup_l7200(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].size = (32*1024*1024); + mi->bank[0].node = 0; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xf1000000), 0x00162b0d); +} + +MACHINE_START(L7200, "LinkUp Systems L7200SDB") + MAINTAINER("Steve Hill") + BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000) + FIXUP(fixup_l7200) +MACHINE_END #endif #ifdef CONFIG_ARCH_EBSA110 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/bios32.c linux.ac/arch/arm/kernel/bios32.c --- linux.vanilla/arch/arm/kernel/bios32.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/bios32.c Sun Jun 4 21:14:16 2000 @@ -21,65 +21,94 @@ extern void hw_init(void); -void pcibios_report_device_errors(int warn) +void pcibios_report_status(u_int status_mask, int warn) { struct pci_dev *dev; pci_for_each_dev(dev) { u16 status; + /* + * ignore host bridge - we handle + * that separately + */ + if (dev->bus->number == 0 && dev->devfn == 0) + continue; + pci_read_config_word(dev, PCI_STATUS, &status); - if ((status & 0xf900) == 0) + status &= status_mask; + if (status == 0) continue; - pci_write_config_word(dev, PCI_STATUS, status & 0xf900); + /* clear the status errors */ + pci_write_config_word(dev, PCI_STATUS, status); if (warn) - printk(KERN_DEBUG "PCI: %02X:%02X: status %04X " - "on %s\n", dev->bus->number, dev->devfn, - status, dev->name); + printk("(%02x:%02x.%d: %04X) ", dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), + status); } } /* * We don't use this to fix the device, but initialisation of it. - * It's not the correct use for this, but it works. The actions we - * take are: - * - enable only IO - * - set memory region to start at zero - * - (0x48) enable all memory requests from ISA to be channeled to PCI - * - (0x42) disable ping-pong (as per errata) - * - (0x40) enable PCI packet retry + * It's not the correct use for this, but it works. + * Note that the arbiter/ISA bridge appears to be buggy, specifically in + * the following area: + * 1. park on CPU + * 2. ISA bridge ping-pong + * 3. ISA bridge master handling of target RETRY + * + * Bug 3 is responsible for the sound DMA grinding to a halt. We now + * live with bug 2. */ static void __init pci_fixup_83c553(struct pci_dev *dev) { + /* + * Set memory region to start at address 0, and enable IO + */ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_MEMORY); pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO); dev->resource[0].end -= dev->resource[0].start; dev->resource[0].start = 0; + /* + * All memory requests from ISA to be channelled to PCI + */ pci_write_config_byte(dev, 0x48, 0xff); - pci_write_config_byte(dev, 0x42, 0x00); + + /* + * Enable ping-pong on bus master to ISA bridge transactions. + * This improves the sound DMA substantially. The fixed + * priority arbiter also helps (see below). + */ + pci_write_config_byte(dev, 0x42, 0x01); + + /* + * Enable PCI retry + */ pci_write_config_byte(dev, 0x40, 0x22); /* - * We used to set the arbiter to "park on last master" - * (bit 1 set), but unfortunately the CyberPro does not - * park the bus. We must therefore park on CPU. + * We used to set the arbiter to "park on last master" (bit + * 1 set), but unfortunately the CyberPro does not park the + * bus. We must therefore park on CPU. Unfortunately, this + * may trigger yet another bug in the 553. */ - pci_write_config_byte(dev, 0x83, 0x00); + pci_write_config_byte(dev, 0x83, 0x02); /* - * Rotate priorities of each PCI request + * Make the ISA DMA request lowest priority, and disable + * rotating priorities completely. */ - pci_write_config_byte(dev, 0x80, 0xe0); - pci_write_config_byte(dev, 0x81, 0x01); + pci_write_config_byte(dev, 0x80, 0x11); + pci_write_config_byte(dev, 0x81, 0x00); /* - * Route INTA input to IRQ 11, and set - * IRQ11 to be level sensitive. + * Route INTA input to IRQ 11, and set IRQ11 to be level + * sensitive. */ pci_write_config_word(dev, 0x44, 0xb000); outb(0x08, 0x4d1); @@ -193,8 +222,8 @@ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -/* - * Called after each bus is probed, but before its children +/** + * pcibios_fixup_bus - Called after each bus is probed, but before its children * are examined. */ void __init pcibios_fixup_bus(struct pci_bus *bus) @@ -209,6 +238,8 @@ else BUG(); + busdata->max_lat = 255; + /* * Walk the devices on this bus, working out what we can * and can't support. @@ -216,6 +247,7 @@ for (walk = walk->next; walk != &bus->devices; walk = walk->next) { struct pci_dev *dev = pci_dev_b(walk); u16 status; + u8 max_lat, min_gnt; pci_read_config_word(dev, PCI_STATUS, &status); @@ -227,6 +259,17 @@ busdata->features &= ~PCI_COMMAND_FAST_BACK; /* + * If we encounter a CyberPro 2000, then we disable + * SERR and PERR reporting - this chip doesn't drive the + * parity line correctly. + */ +#if 1 /* !testing */ + if (dev->vendor == PCI_VENDOR_ID_INTERG && + dev->device == PCI_DEVICE_ID_INTERG_2000) + busdata->features &= ~(PCI_COMMAND_SERR | + PCI_COMMAND_PARITY); +#endif + /* * Calculate the maximum devsel latency. */ if (busdata->maxdevsel < (status & PCI_STATUS_DEVSEL_MASK)) @@ -240,6 +283,16 @@ if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) have_isa_bridge = !0; + + /* + * Calculate the maximum latency on this bus. Note + * that we ignore any device which reports its max + * latency is the same as its use. + */ + pci_read_config_byte(dev, PCI_MAX_LAT, &max_lat); + pci_read_config_byte(dev, PCI_MIN_GNT, &min_gnt); + if (max_lat && max_lat != min_gnt && max_lat < busdata->max_lat) + busdata->max_lat = max_lat; } /* @@ -249,6 +302,7 @@ for (walk = walk->next; walk != &bus->devices; walk = walk->next) { struct pci_dev *dev = pci_dev_b(walk); u16 cmd; + u8 min_gnt, latency; /* * architecture specific hacks. I don't really want @@ -263,11 +317,27 @@ pci_write_config_dword(dev, 0x40, 0x80000000); /* - * Set latency timer to 32, and a cache line size to 32 bytes. + * Calculate this masters latency timer value. + * This is rather primitive - it does not take + * account of the number of masters in a system + * wanting to use the bus. + */ + pci_read_config_byte(dev, PCI_MIN_GNT, &min_gnt); + if (min_gnt) { + if (min_gnt > busdata->max_lat) + min_gnt = busdata->max_lat; + + latency = (int)min_gnt * 25 / 3; + } else + latency = 32; /* 1us */ + + pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); + + /* + * Set the cache line size to 32 bytes. * Also, set system error enable, parity error enable. * Disable ROM. */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -520,15 +590,6 @@ pci_assign_unassigned_resources(); pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq); pci_set_bus_ranges(); - -#ifdef CONFIG_FOOTBRIDGE - /* - * Initialise any other hardware after we've got the PCI bus - * initialised. We may need the PCI bus to talk to this other - * hardware. - */ - hw_init(); -#endif } char * __init pcibios_setup(char *str) @@ -544,10 +605,18 @@ { } +/** + * pcibios_set_master - Setup device for bus mastering. + * @dev: PCI device to be setup + */ void pcibios_set_master(struct pci_dev *dev) { } +/** + * pcibios_enable_device - Enable I/O and memory. + * @dev: PCI device to be enabled + */ int pcibios_enable_device(struct pci_dev *dev) { u16 cmd, old_cmd; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/bios32.h linux.ac/arch/arm/kernel/bios32.h --- linux.vanilla/arch/arm/kernel/bios32.h Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/bios32.h Sun Jun 4 21:14:16 2000 @@ -10,6 +10,11 @@ * Maximum devsel for this bus. */ u16 maxdevsel; + /* + * The maximum latency that devices on this + * bus can withstand. + */ + u8 max_lat; }; struct arm_pci_sysdata { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/calls.S linux.ac/arch/arm/kernel/calls.S --- linux.vanilla/arch/arm/kernel/calls.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/calls.S Sun Jun 4 21:14:16 2000 @@ -119,7 +119,7 @@ .long SYMBOL_NAME(sys_newlstat) .long SYMBOL_NAME(sys_newfstat) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */ -/* 110 */ .long SYMBOL_NAME(sys_iopl) +/* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */ .long SYMBOL_NAME(sys_vhangup) .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_syscall) /* call a syscall */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/debug-armv.S linux.ac/arch/arm/kernel/debug-armv.S --- linux.vanilla/arch/arm/kernel/debug-armv.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/debug-armv.S Sun Jun 4 21:14:16 2000 @@ -64,7 +64,7 @@ beq 1001b .endm -#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) +#elif defined(CONFIG_FOOTBRIDGE) #ifndef CONFIG_DEBUG_DC21285_PORT /* For NetWinder debugging */ .macro addruart,rx diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/dec21285.c linux.ac/arch/arm/kernel/dec21285.c --- linux.vanilla/arch/arm/kernel/dec21285.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/dec21285.c Mon Jun 5 19:54:47 2000 @@ -1,9 +1,8 @@ /* * arch/arm/kernel/dec21285.c: PCI functions for DC21285 * - * Copyright (C) 1998-1999 Russell King, Phil Blundell + * Copyright (C) 1998-2000 Russell King, Phil Blundell */ -#include #include #include #include @@ -23,7 +22,7 @@ #define MAX_SLOTS 21 extern int setup_arm_irq(int, struct irqaction *); -extern void pcibios_report_device_errors(int warn); +extern void pcibios_report_status(u_int status_mask, int warn); static unsigned long dc21285_base_address(struct pci_dev *dev) @@ -145,76 +144,112 @@ dc21285_write_config_dword, }; +static struct timer_list serr_timer; +static struct timer_list perr_timer; + +static void dc21285_enable_error(unsigned long __data) +{ + switch (__data) { + case IRQ_PCI_SERR: + del_timer(&serr_timer); + break; + + case IRQ_PCI_PERR: + del_timer(&perr_timer); + break; + } + + enable_irq(__data); +} + /* * Warn on PCI errors. */ -static void -dc21285_error(int irq, void *dev_id, struct pt_regs *regs) +static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) { - static unsigned long next_warn; - unsigned long cmd = *CSR_PCICMD & 0x0000ffff; - unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07; - unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; - int warn = time_after_eq(jiffies, next_warn); - - if (machine_is_netwinder()) - warn = 0; - - ctrl |= SA110_CNTL_DISCARDTIMER; - - if (warn) { - next_warn = jiffies + HZ; - printk(KERN_DEBUG "PCI: "); - } + unsigned int cmd; + unsigned int status; - if (irqstatus & (1 << 31)) { - if (warn) - printk("parity error "); - cmd |= 1 << 31; - } + cmd = *CSR_PCICMD; + status = cmd >> 16; + cmd = cmd & 0xffff; + + if (status & PCI_STATUS_REC_MASTER_ABORT) { + printk(KERN_DEBUG "PCI: master abort: "); + pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT, 1); + printk("\n"); - if (irqstatus & (1 << 30)) { - if (warn) - printk("target abort "); - cmd |= 1 << 28; + cmd |= PCI_STATUS_REC_MASTER_ABORT << 16; } - if (irqstatus & (1 << 29)) { - if (warn) - printk("master abort "); - cmd |= 1 << 29; - } + if (status & PCI_STATUS_REC_TARGET_ABORT) { + printk(KERN_DEBUG "PCI: target abort: "); + pcibios_report_status(PCI_STATUS_SIG_TARGET_ABORT, 1); + printk("\n"); - if (irqstatus & (1 << 28)) { - if (warn) - printk("data parity error "); - cmd |= 1 << 24; + cmd |= PCI_STATUS_REC_TARGET_ABORT << 16; } - if (irqstatus & (1 << 27)) { - if (warn) - printk("discard timer expired "); - ctrl &= ~SA110_CNTL_DISCARDTIMER; - } + *CSR_PCICMD = cmd; +} - if (irqstatus & (1 << 23)) { - if (warn) - printk("system error "); - ctrl |= SA110_CNTL_RXSERR; - } +static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct timer_list *timer = dev_id; + unsigned int cntl; - if (warn) - printk("pc=[<%08lX>]\n", instruction_pointer(regs)); + printk(KERN_DEBUG "PCI: system error received: "); + pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1); + printk("\n"); - pcibios_report_device_errors(warn); + cntl = *CSR_SA110_CNTL & 0xffffdf07; + *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; - *CSR_PCICMD = cmd; - *CSR_SA110_CNTL = ctrl; + /* + * back off this interrupt + */ + disable_irq(irq); + timer->expires = jiffies + HZ; + add_timer(timer); } -static struct irqaction dc21285_error_action = { - dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL -}; +static void dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_DEBUG "PCI: discard timer expired\n"); + *CSR_SA110_CNTL &= 0xffffde07; +} + +static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int cmd; + + printk(KERN_DEBUG "PCI: data parity error detected: "); + pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); + printk("\n"); + + cmd = *CSR_PCICMD & 0xffff; + *CSR_PCICMD = cmd | 1 << 24; +} + +static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct timer_list *timer = dev_id; + unsigned int cmd; + + printk(KERN_DEBUG "PCI: parity error detected: "); + pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); + printk("\n"); + + cmd = *CSR_PCICMD & 0xffff; + *CSR_PCICMD = cmd | 1 << 31; + + /* + * back off this interrupt + */ + disable_irq(irq); + timer->expires = jiffies + HZ; + add_timer(timer); +} void __init dc21285_init(void) { @@ -233,32 +268,31 @@ *CSR_CSRBASEOFFSET = 0; *CSR_PCIADDR_EXTN = 0; -#ifdef CONFIG_HOST_FOOTBRIDGE - - csrio.flags = IORESOURCE_IO; - csrio.name = "DC21285"; - csrmem.flags = IORESOURCE_MEM; - csrmem.name = "DC21285"; - - allocate_resource(&ioport_resource, &csrio, 128, - 0xff00, 0xffff, 128, NULL, NULL); - allocate_resource(&iomem_resource, &csrmem, 128, - 0xf4000000, 0xf8000000, 128, NULL, NULL); - - /* - * Map our SDRAM at a known address in PCI space, just in case - * the firmware had other ideas. Using a nonzero base is - * necessary, since some VGA cards forcefully use PCI addresses - * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). - */ - *CSR_PCICACHELINESIZE = 0x00002008; - *CSR_PCICSRBASE = csrmem.start; - *CSR_PCICSRIOBASE = csrio.start; - *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); - *CSR_PCIROMBASE = 0; - *CSR_PCICMD = pci_cmd | + if (footbridge_cfn_mode()) { + csrio.flags = IORESOURCE_IO; + csrio.name = "DC21285"; + csrmem.flags = IORESOURCE_MEM; + csrmem.name = "DC21285"; + + allocate_resource(&ioport_resource, &csrio, 128, + 0xff00, 0xffff, 128, NULL, NULL); + allocate_resource(&iomem_resource, &csrmem, 128, + 0xf4000000, 0xf8000000, 128, NULL, NULL); + + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is + * necessary, since some VGA cards forcefully use PCI addresses + * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). + */ + *CSR_PCICACHELINESIZE = 0x00002008; + *CSR_PCICSRBASE = csrmem.start; + *CSR_PCICSRIOBASE = csrio.start; + *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); + *CSR_PCIROMBASE = 0; + *CSR_PCICMD = pci_cmd | (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); -#endif + } printk(KERN_DEBUG "PCI: DC21285 footbridge, revision %02lX\n", *CSR_CLASSREV & 0xff); @@ -288,5 +322,20 @@ /* * Initialise PCI error IRQ after we've finished probing */ - setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action); + request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT, "PCI abort", NULL); + request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT, "Discard timer", NULL); + request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT, "PCI data parity", NULL); + + init_timer(&serr_timer); + init_timer(&perr_timer); + + serr_timer.data = IRQ_PCI_SERR; + serr_timer.function = dc21285_enable_error; + perr_timer.data = IRQ_PCI_PERR; + perr_timer.function = dc21285_enable_error; + + request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT, + "PCI system error", &serr_timer); + request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT, + "PCI parity error", &perr_timer); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/dma-a5k.c linux.ac/arch/arm/kernel/dma-a5k.c --- linux.vanilla/arch/arm/kernel/dma-a5k.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/dma-a5k.c Sun Jun 4 21:14:16 2000 @@ -15,7 +15,9 @@ #include "dma.h" -static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; +static struct fiq_handler fh = { + name: "floppydma" +}; int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/dma-rpc.c linux.ac/arch/arm/kernel/dma-rpc.c --- linux.vanilla/arch/arm/kernel/dma-rpc.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/dma-rpc.c Sun Jun 4 21:14:16 2000 @@ -20,7 +20,9 @@ #include "dma.h" -static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; +static struct fiq_handler fh = { + name: "floppydma" +}; #if 0 typedef enum { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/ecard.c linux.ac/arch/arm/kernel/ecard.c --- linux.vanilla/arch/arm/kernel/ecard.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/ecard.c Sun Jun 4 21:14:16 2000 @@ -52,6 +52,10 @@ #define oldlatch_init() #endif +#ifndef CONFIG_ARCH_RPC +#define HAVE_EXPMASK +#endif + enum req { req_readbytes, req_reset diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/entry-armv.S linux.ac/arch/arm/kernel/entry-armv.S --- linux.vanilla/arch/arm/kernel/entry-armv.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/entry-armv.S Sun Jun 4 21:14:16 2000 @@ -233,14 +233,12 @@ .macro irq_prio_table .endm -#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) +#elif defined(CONFIG_FOOTBRIDGE) #include .macro disable_fiq .endm - .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000 - .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ffffff .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff @@ -311,10 +309,24 @@ movne \irqnr, #IRQ_CONTX bne 1001f - tst \irqstat, #irq_mask_pci_err_high - tsteq \irqstat, #irq_mask_pci_err_low - movne \irqnr, #IRQ_PCI_ERR + tst \irqstat, #IRQ_MASK_PCI_ABORT + movne \irqnr, #IRQ_PCI_ABORT bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_SERR + movne \irqnr, #IRQ_PCI_SERR + bne 1001f + + tst \irqstat, #IRQ_MASK_DISCARD_TIMER + movne \irqnr, #IRQ_DISCARD_TIMER + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_DPERR + movne \irqnr, #IRQ_PCI_DPERR + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_PERR + movne \irqnr, #IRQ_PCI_PERR 1001: .endm @@ -441,7 +453,8 @@ .macro restore_user_regs ldr r0, [sp, #S_PSR] @ Get calling cpsr - msr cpsr_c, #I_BIT | MODE_SVC @ disable IRQs + mov ip, #I_BIT | MODE_SVC + msr cpsr_c, ip @ disable IRQs msr spsr, r0 @ save in spsr_svc ldmia sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 @@ -592,9 +605,10 @@ bl cpu_data_abort #endif msr cpsr_c, r9 - mov r3, sp + mov r2, sp bl SYMBOL_NAME(do_DataAbort) - msr cpsr_c, #I_BIT | MODE_SVC + mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 ldr r0, [sp, #S_PSR] msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr @@ -636,7 +650,8 @@ mov r1, sp @ struct pt_regs *regs bl SYMBOL_NAME(do_undefinstr) -1: msr cpsr_c, #I_BIT | MODE_SVC +1: mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 ldr lr, [sp, #S_PSR] @ Get SVC cpsr msr spsr, lr ldmia sp, {r0 - pc}^ @ Restore SVC registers @@ -675,8 +690,9 @@ #else bl cpu_data_abort #endif - msr cpsr_c, #MODE_SVC @ Enable interrupts - mov r3, sp + mov r2, #MODE_SVC + msr cpsr_c, r2 @ Enable interrupts + mov r2, sp adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_DataAbort) @@ -720,9 +736,10 @@ add r10, r10, #TSS_FPESAVE @ r10 = workspace ldr pc, [r4] @ Call FP module USR entry point -fpundefinstr: mov r0, lr +fpundefinstr: mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts + mov r0, lr mov r1, sp - msr cpsr_c, #MODE_SVC @ Enable interrupts adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_undefinstr) @@ -736,7 +753,8 @@ stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr alignment_trap r4, r7, __temp_abt zero_fp - msr cpsr_c, #MODE_SVC @ Enable interrupts + mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts mov r0, r5 @ address (pc) mov r1, sp @ regs bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler @@ -816,7 +834,8 @@ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -856,7 +875,8 @@ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -897,7 +917,8 @@ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode ands lr, lr, #15 ldreq lr, .LCtab_pabt @@ -924,7 +945,8 @@ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/hw-footbridge.c linux.ac/arch/arm/kernel/hw-footbridge.c --- linux.vanilla/arch/arm/kernel/hw-footbridge.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/hw-footbridge.c Sun Jun 4 21:14:16 2000 @@ -662,7 +662,12 @@ #endif -void __init hw_init(void) +/* + * Initialise any other hardware after we've got the PCI bus + * initialised. We may need the PCI bus to talk to this other + * hardware. + */ +static int __init hw_init(void) { extern void register_isa_ports(unsigned int, unsigned int, unsigned int); @@ -702,6 +707,7 @@ if (machine_is_cats()) cats_hw_init(); #endif - - leds_event(led_start); + return 0; } + +__initcall(hw_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/ioport.c linux.ac/arch/arm/kernel/ioport.c --- linux.vanilla/arch/arm/kernel/ioport.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/ioport.c Thu Jan 1 01:00:00 1970 @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/kernel/ioport.c - * - * IO permission support for ARM. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef CONFIG_CPU_32 -asmlinkage int sys_iopl(unsigned long turn_on) -{ - if (turn_on && !capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* - * We only support an on_off approach - */ - modify_domain(DOMAIN_IO, turn_on ? DOMAIN_MANAGER : DOMAIN_CLIENT); - - return 0; -} -#else -asmlinkage int sys_iopl(unsigned long turn_on) -{ - return -ENOSYS; -} -#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/irq.c linux.ac/arch/arm/kernel/irq.c --- linux.vanilla/arch/arm/kernel/irq.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/irq.c Sun Jun 4 21:14:16 2000 @@ -15,7 +15,7 @@ * IRQ's are in fact implemented a bit like signal handlers for the kernel. * Naturally it's not a 1:1 relation, but there are similarities. */ -#include /* for CONFIG_DEBUG_ERRORS */ +#include #include #include #include @@ -33,13 +33,6 @@ #include #include -#ifndef SMP -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) -#else -#error SMP not supported -#endif - #ifndef cliIF #define cliIF() #endif @@ -85,6 +78,7 @@ }; static struct irqdesc irq_desc[NR_IRQS]; +static volatile unsigned long irq_err_count; /* * Get architecture specific interrupt handlers @@ -133,8 +127,8 @@ action = irq_desc[i].action; if (!action) continue; - p += sprintf(p, "%3d: %10u %s", - i, kstat_irqs(i), action->name); + p += sprintf(p, "%3d: %10u ", i, kstat_irqs(i)); + p += sprintf(p, " %s", action->name); for (action = action->next; action; action = action->next) { p += sprintf(p, ", %s", action->name); } @@ -144,6 +138,7 @@ #ifdef CONFIG_ARCH_ACORN p += get_fiq_list(p); #endif + p += sprintf(p, "Err: %10lu\n", irq_err_count); return p - buf; } @@ -181,10 +176,17 @@ { struct irqdesc * desc; struct irqaction * action; - int status, cpu; + int cpu; irq = fixup_irq(irq); + /* + * Some hardware gives randomly wrong interrupts. Rather + * than crashing, do something sensible. + */ + if (irq >= NR_IRQS) + goto bad_irq; + desc = irq_desc + irq; spin_lock(&irq_controller_lock); @@ -197,10 +199,11 @@ desc->triggered = 1; /* Return with this interrupt masked if no action */ - status = 0; action = desc->action; if (action) { + int status = 0; + if (desc->nomask) { spin_lock(&irq_controller_lock); desc->unmask(irq); @@ -237,9 +240,15 @@ if (softirq_state[cpu].active & softirq_state[cpu].mask) do_softirq(); + return; + +bad_irq: + irq_err_count += 1; + printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); + return; } -#if defined(CONFIG_ARCH_ACORN) +#ifdef CONFIG_ARCH_ACORN void do_ecard_IRQ(int irq, struct pt_regs *regs) { struct irqdesc * desc; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/leds-footbridge.c linux.ac/arch/arm/kernel/leds-footbridge.c --- linux.vanilla/arch/arm/kernel/leds-footbridge.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/leds-footbridge.c Sun Jun 4 21:14:16 2000 @@ -46,7 +46,7 @@ switch (evt) { case led_start: hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN; -#ifndef CONFIG_LEDS_IDLE +#ifndef CONFIG_LEDS_CPU hw_led_state |= XBUS_LED_AMBER; #endif led_state |= LED_STATE_ENABLED; @@ -223,11 +223,12 @@ { } -static void __init -init_leds_event(led_event_t evt) -{ - leds_event = dummy_leds_event; +void (*leds_event)(led_event_t) = dummy_leds_event; + +EXPORT_SYMBOL(leds_event); +static int __init leds_init(void) +{ #ifdef CONFIG_FOOTBRIDGE if (machine_is_ebsa285() || machine_is_co285()) leds_event = ebsa285_leds_event; @@ -237,9 +238,9 @@ leds_event = netwinder_leds_event; #endif - leds_event(evt); -} + leds_event(led_start); -void (*leds_event)(led_event_t) = init_leds_event; + return 0; +} -EXPORT_SYMBOL(leds_event); +__initcall(leds_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/leds-sa1100.c linux.ac/arch/arm/kernel/leds-sa1100.c --- linux.vanilla/arch/arm/kernel/leds-sa1100.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/kernel/leds-sa1100.c Sun Jun 4 21:14:16 2000 @@ -0,0 +1,333 @@ +/* + * linux/arch/arm/kernel/leds-sa1100.c + * + * Copyright (C) 2000 John Dorsey + * + * Original (leds-footbridge.c) by Russell King + * + * Added Brutus LEDs support + * Nicolas Pitre, Mar 19, 2000 + * + * Added LART LED support + * Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000 + * + * + * Assabet uses the LEDs as follows: + * - Green - toggles state every 50 timer interrupts + * - Red - on if system is not idle + * + * Brutus uses the LEDs as follows: + * - D3 (Green, GPIO9) - toggles state every 50 timer interrupts + * - D17 (Red, GPIO20) - on if system is not idle + * - D4 (Green, GPIO8) - misc function + * + * LART uses the LED as follows: + * - GPIO23 is the LED, on if system is not idle + * You can use both CONFIG_LEDS_CPU and CONFIG_LEDS_TIMER at the same + * time, but in that case the timer events will still dictate the + * pace of the LED. + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + + +#ifdef CONFIG_SA1100_ASSABET + +#define BCR_LED_MASK (BCR_LED_GREEN | BCR_LED_RED) + +static void assabet_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch (evt) { + case led_start: + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= BCR_LED_GREEN; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= BCR_LED_RED; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~BCR_LED_RED; + break; +#endif + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~BCR_LED_GREEN; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= BCR_LED_GREEN; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~BCR_LED_RED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= BCR_LED_RED; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + BCR = BCR_value = (BCR_value & ~BCR_LED_MASK) | hw_led_state; + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_ASSABET */ + +#ifdef CONFIG_SA1100_BRUTUS + +#define LED_D3 GPIO_GPIO(9) +#define LED_D4 GPIO_GPIO(8) +#define LED_D17 GPIO_GPIO(20) +#define LED_MASK (LED_D3|LED_D4|LED_D17) + +static void brutus_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch (evt) { + case led_start: + hw_led_state = LED_MASK; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_D3; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_D17; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_D17; + break; +#endif + + case led_green_on: + hw_led_state &= ~LED_D4; + break; + + case led_green_off: + hw_led_state |= LED_D4; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_D17; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_D17; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_BRUTUS */ + +#ifdef CONFIG_SA1100_LART + +#define LED_23 GPIO_GPIO23 +#define LED_MASK (LED_23) + + +static void lart_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch(evt) { + case led_start: + hw_led_state = LED_MASK; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_23; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + /* The LART people like the LED to be off when the + system is idle... */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_23; + break; + + case led_idle_end: + /* ... and on if the system is not idle */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_23; + break; +#endif + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_23; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_23; + break; + + default: + break; + } + + /* Now set the GPIO state, or nothing will happen at all */ + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_LART */ + +static void dummy_leds_event(led_event_t evt) +{ +} + +void (*leds_event)(led_event_t) = dummy_leds_event; + +EXPORT_SYMBOL(leds_event); + +static int __init +sa1100_leds_init(void) +{ +#ifdef CONFIG_SA1100_ASSABET + if (machine_is_assabet()) + leds_event = assabet_leds_event; +#endif +#ifdef CONFIG_SA1100_BRUTUS + if (machine_is_brutus()) + leds_event = brutus_leds_event; +#endif +#ifdef CONFIG_SA1100_LART + if (machine_is_lart()) + leds_event = lart_leds_event; +#endif + + leds_event(led_start); + return 0; +} + +__initcall(sa1100_leds_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/process.c linux.ac/arch/arm/kernel/process.c --- linux.vanilla/arch/arm/kernel/process.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/process.c Sun Jun 4 21:14:16 2000 @@ -353,10 +353,12 @@ pid_t __ret; __asm__ __volatile__( - "mov r0, %1 @ kernel_thread sys_clone\n" -" mov r1, #0\n" - __syscall(clone)"\n" -" mov %0, r0" + "mov r0, %1 @ kernel_thread sys_clone + mov r1, #0 + "__syscall(clone)" + teq r0, #0 @ if we are the child + moveq fp, #0 @ ensure that fp is zero + mov %0, r0" : "=r" (__ret) : "Ir" (flags | CLONE_VM) : "r0", "r1"); if (__ret == 0) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/semaphore.c linux.ac/arch/arm/kernel/semaphore.c --- linux.vanilla/arch/arm/kernel/semaphore.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/semaphore.c Sun Jun 4 21:14:16 2000 @@ -290,68 +290,95 @@ * need to convert that sequence back into the C sequence when * there is contention on the semaphore. * - * r0 contains the semaphore pointer on entry. Save the C-clobbered - * registers (r0 to r3, ip and lr) except r0 in the cases where it - * is used as a return value.. + * ip contains the semaphore pointer on entry. Save the C-clobbered + * registers (r0 to r3 and lr), but not ip, as we use it as a return + * value in some cases.. */ asm(" .section .text.lock, \"ax\" .align 5 .globl __down_failed __down_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_interruptible_failed __down_interruptible_failed: - stmfd sp!, {r1 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down_interruptible - ldmfd sp!, {r1 - r3, ip, pc} + mov ip, r0 + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_trylock_failed __down_trylock_failed: - stmfd sp!, {r1 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down_trylock - ldmfd sp!, {r1 - r3, ip, pc} + mov ip, r0 + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __up_wakeup __up_wakeup: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __up - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_read_failed __down_read_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bcc 1f - bl down_read_failed_biased - ldmfd sp!, {r0 - r3, ip, pc} -1: bl down_read_failed - /***/ +1: bl down_read_failed_biased + ldmfd sp!, {r0 - r3, pc} +2: bl down_read_failed + mrs r1, cpsr + orr r2, r1, #128 + msr cpsr_c, r2 + ldr r3, [r0] + subs r3, r3, #1 + str r3, [r0] + msr cpsr_c, r1 + ldmplfd sp!, {r0 - r3, pc} + bcc 2b + b 1b .align 5 .globl __down_write_failed __down_write_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bcc 1f - bl down_write_failed_biased - ldmfd sp!, {r0 - r3, ip, pc} -1: bl down_write_failed - /***/ +1: bl down_write_failed_biased + ldmfd sp!, {r0 - r3, pc} +2: bl down_write_failed + mrs r1, cpsr + orr r2, r1, #128 + msr cpsr_c, r2 + ldr r3, [r0] + subs r3, r3, #"RW_LOCK_BIAS_STR" + str r3, [r0] + msr cpsr_c, r1 + ldmeqfd sp!, {r0 - r3, pc} + bcc 2b + b 1b .align 5 .globl __rwsem_wake __rwsem_wake: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip beq 1f bl rwsem_wake_readers - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} 1: bl rwsem_wake_writer - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .previous "); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/setup.c linux.ac/arch/arm/kernel/setup.c --- linux.vanilla/arch/arm/kernel/setup.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/setup.c Sun Jun 4 21:14:16 2000 @@ -217,6 +217,7 @@ mi->bank[mi->nr_banks].start = start; mi->bank[mi->nr_banks].size = size; + mi->bank[mi->nr_banks].node = 0; mi->nr_banks += 1; } c = *from++; @@ -378,6 +379,7 @@ if (meminfo.nr_banks == 0) { meminfo.nr_banks = 1; meminfo.bank[0].start = PHYS_OFFSET; + meminfo.bank[0].node = 0; if (params) meminfo.bank[0].size = params->u1.s.nr_pages << PAGE_SHIFT; else @@ -393,8 +395,8 @@ saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(&meminfo, cmdline_p, from); bootmem_init(&meminfo); - request_standard_resources(&meminfo, mdesc); paging_init(&meminfo); + request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/kernel/time.c linux.ac/arch/arm/kernel/time.c --- linux.vanilla/arch/arm/kernel/time.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/kernel/time.c Sun Jun 4 21:14:16 2000 @@ -154,21 +154,29 @@ static void do_leds(void) { - static unsigned int count = 50; - static int last_pid; +#ifdef CONFIG_LEDS_CPU + { + static int last_pid; - if (current->pid != last_pid) { - last_pid = current->pid; - if (last_pid) - leds_event(led_idle_end); - else - leds_event(led_idle_start); + if (current->pid != last_pid) { + last_pid = current->pid; + if (last_pid) + leds_event(led_idle_end); + else + leds_event(led_idle_start); + } } - - if (--count == 0) { - count = 50; - leds_event(led_timer); +#endif +#ifdef CONFIG_LEDS_TIMER + { + static unsigned int count = 50; + + if (--count == 0) { + count = 50; + leds_event(led_timer); + } } +#endif } #else #define do_leds() diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/changebit.S linux.ac/arch/arm/lib/changebit.S --- linux.vanilla/arch/arm/lib/changebit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/changebit.S Sun Jun 4 21:14:16 2000 @@ -9,18 +9,15 @@ .text /* Purpose : Function to change a bit - * Prototype: int change_bit(int bit,int *addr) + * Prototype: int change_bit(int bit, void *addr) */ ENTRY(change_bit) - and r2, r0, #7 - mov r3, #1 - mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + save_and_disable_irqs ip, r2 ldrb r2, [r1, r0, lsr #3] eor r2, r2, r3 strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) + restore_irqs ip RETINSTR(mov,pc,lr) - - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/clearbit.S linux.ac/arch/arm/lib/clearbit.S --- linux.vanilla/arch/arm/lib/clearbit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/clearbit.S Sun Jun 4 21:14:16 2000 @@ -8,19 +8,20 @@ #include .text -@ Purpose : Function to clear a bit -@ Prototype: int clear_bit(int bit,int *addr) +/* + * Purpose : Function to clear a bit + * Prototype: int clear_bit(int bit, void *addr) + */ ENTRY(clear_bit) and r2, r0, #7 mov r3, #1 mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) + save_and_disable_irqs ip, r2 ldrb r2, [r1, r0, lsr #3] bic r2, r2, r3 strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) + restore_irqs ip RETINSTR(mov,pc,lr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/findbit.S linux.ac/arch/arm/lib/findbit.S --- linux.vanilla/arch/arm/lib/findbit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/findbit.S Sun Jun 4 21:14:16 2000 @@ -1,65 +1,53 @@ /* - * linux/arch/arm/lib/bitops.S + * linux/arch/arm/lib/findbit.S * - * Copyright (C) 1995-1996 Russell King + * Copyright (C) 1995-2000 Russell King */ #include #include .text -@ Purpose : Find a 'zero' bit -@ Prototype: int find_first_zero_bit(char *addr,int maxbit); - +/* + * Purpose : Find a 'zero' bit + * Prototype: int find_first_zero_bit(void *addr, int maxbit); + */ ENTRY(find_first_zero_bit) - mov r2, #0 @ Initialise bit position -Lfindzbit1lp: ldrb r3, [r0, r2, lsr #3] @ Check byte, if 0xFF, then all bits set - teq r3, #0xFF - bne Lfoundzbit - add r2, r2, #8 - cmp r2, r1 @ Check to see if we have come to the end - bcc Lfindzbit1lp - add r0, r1, #1 @ Make sure that we flag an error - RETINSTR(mov,pc,lr) -Lfoundzbit: tst r3, #1 @ Check individual bits - moveq r0, r2 - RETINSTR(moveq,pc,lr) - tst r3, #2 - addeq r0, r2, #1 - RETINSTR(moveq,pc,lr) - tst r3, #4 - addeq r0, r2, #2 - RETINSTR(moveq,pc,lr) - tst r3, #8 - addeq r0, r2, #3 - RETINSTR(moveq,pc,lr) - tst r3, #16 - addeq r0, r2, #4 - RETINSTR(moveq,pc,lr) - tst r3, #32 - addeq r0, r2, #5 - RETINSTR(moveq,pc,lr) - tst r3, #64 - addeq r0, r2, #6 - RETINSTR(moveq,pc,lr) - add r0, r2, #7 + mov r2, #0 +.bytelp: ldrb r3, [r0, r2, lsr #3] + eors r3, r3, #0xff @ invert bits + bne .found @ any now set - found zero bit + add r2, r2, #8 @ next bit pointer + cmp r2, r1 @ any more? + bcc .bytelp + add r0, r1, #1 @ no free bits RETINSTR(mov,pc,lr) -@ Purpose : Find next 'zero' bit -@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset) - +/* + * Purpose : Find next 'zero' bit + * Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset) + */ ENTRY(find_next_zero_bit) - tst r2, #7 - beq Lfindzbit1lp @ If new byte, goto old routine + ands ip, r2, #7 + beq .bytelp @ If new byte, goto old routine ldrb r3, [r0, r2, lsr#3] - orr r3, r3, #0xFF00 @ Set top bits so we wont get confused - str r4, [sp, #-4]! - and r4, r2, #7 - mov r3, r3, lsr r4 @ Shift right by no. of bits - ldr r4, [sp], #4 - and r3, r3, #0xFF - teq r3, #0xFF - orreq r2, r2, #7 + eor r3, r3, #0xff @ now looking for a 1 bit + movs r3, r3, lsr ip @ shift off unused bits + orreq r2, r2, #7 @ if zero, then no bits here + addeq r2, r2, #1 @ align bit pointer + beq .bytelp @ loop for next bit + +/* + * One or more bits in the LSB of r3 are assumed to be set. + */ +.found: tst r3, #0x0f + addeq r2, r2, #4 + movne r3, r3, lsl #4 + tst r3, #0x30 + addeq r2, r2, #2 + movne r3, r3, lsl #2 + tst r3, #0x40 addeq r2, r2, #1 - beq Lfindzbit1lp @ If all bits are set, goto old routine - b Lfoundzbit + mov r0, r2 + RETINSTR(mov,pc,lr) + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/setbit.S linux.ac/arch/arm/lib/setbit.S --- linux.vanilla/arch/arm/lib/setbit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/setbit.S Sun Jun 4 21:14:16 2000 @@ -8,19 +8,20 @@ #include .text -@ Purpose : Function to set a bit -@ Prototype: int set_bit(int bit,int *addr) +/* + * Purpose : Function to set a bit + * Prototype: int set_bit(int bit, void *addr) + */ ENTRY(set_bit) and r2, r0, #7 mov r3, #1 mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) + save_and_disable_irqs ip, r2 ldrb r2, [r1, r0, lsr #3] orr r2, r2, r3 strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) + restore_irqs ip RETINSTR(mov,pc,lr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/testchangebit.S linux.ac/arch/arm/lib/testchangebit.S --- linux.vanilla/arch/arm/lib/testchangebit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/testchangebit.S Sun Jun 4 21:14:16 2000 @@ -12,14 +12,13 @@ add r1, r1, r0, lsr #3 and r3, r0, #7 mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) + save_and_disable_irqs ip, r2 ldrb r2, [r1] tst r2, r0, lsl r3 eor r2, r2, r0, lsl r3 - moveq r0, #0 strb r2, [r1] - RESTOREIRQS(ip) + restore_irqs ip + moveq r0, #0 RETINSTR(mov,pc,lr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/testclearbit.S linux.ac/arch/arm/lib/testclearbit.S --- linux.vanilla/arch/arm/lib/testclearbit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/testclearbit.S Sun Jun 4 21:14:16 2000 @@ -10,16 +10,15 @@ ENTRY(test_and_clear_bit) add r1, r1, r0, lsr #3 @ Get byte offset - and r3, r0, #7 @ Get bit offset + and r3, r0, #7 @ Get bit offset mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) + save_and_disable_irqs ip, r2 ldrb r2, [r1] tst r2, r0, lsl r3 bic r2, r2, r0, lsl r3 - moveq r0, #0 strb r2, [r1] - RESTOREIRQS(ip) + restore_irqs ip + moveq r0, #0 RETINSTR(mov,pc,lr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/testsetbit.S linux.ac/arch/arm/lib/testsetbit.S --- linux.vanilla/arch/arm/lib/testsetbit.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/testsetbit.S Sun Jun 4 21:14:16 2000 @@ -12,14 +12,13 @@ add r1, r1, r0, lsr #3 @ Get byte offset and r3, r0, #7 @ Get bit offset mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) + save_and_disable_irqs ip, r2 ldrb r2, [r1] tst r2, r0, lsl r3 orr r2, r2, r0, lsl r3 - moveq r0, #0 strb r2, [r1] - RESTOREIRQS(ip) + restore_irqs ip + moveq r0, #0 RETINSTR(mov,pc,lr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/lib/uaccess.S linux.ac/arch/arm/lib/uaccess.S --- linux.vanilla/arch/arm/lib/uaccess.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/lib/uaccess.S Sun Jun 4 21:14:16 2000 @@ -538,13 +538,18 @@ .section .fixup,"ax" .align 0 - /* We took an exception. Zero out the buffer and pretend no - data was copied. */ -9001: ldr r0, [sp], #4 - ldr r1, [sp] - teq r1, #0 + /* + * We took an exception. r0 contains a pointer to + * the byte not copied. + */ +9001: ldr r2, [sp], #4 @ void *to + sub r2, r0, r2 @ bytes copied + ldr r1, [sp], #4 @ unsigned long count + subs r4, r1, r2 @ bytes left to copy + movne r1, r4 blne SYMBOL_NAME(__memzero) - LOADREGS(fd,sp!, {r0, r4 - r7, pc}) + mov r0, r4 + LOADREGS(fd,sp!, {r4 - r7, pc}) .previous /* Prototype: int __arch_clear_user(void *addr, size_t sz) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/Makefile linux.ac/arch/arm/mm/Makefile --- linux.vanilla/arch/arm/mm/Makefile Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/Makefile Sun Jun 4 21:14:16 2000 @@ -22,6 +22,9 @@ ifeq ($(CONFIG_CPU_ARM7),y) P_OBJS += proc-arm6,7.o endif + ifeq ($(CONFIG_CPU_ARM720),y) + P_OBJS += proc-arm720.o + endif ifeq ($(CONFIG_CPU_SA110),y) P_OBJS += proc-sa110.o endif @@ -41,5 +44,6 @@ fault-armo.o: fault-common.c proc-arm2,3.o: ../lib/constants.h proc-arm6,7.o: ../lib/constants.h +proc-arm720.o: ../lib/constants.h proc-sa110.o: ../lib/constants.h diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/consistent.c linux.ac/arch/arm/mm/consistent.c --- linux.vanilla/arch/arm/mm/consistent.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/consistent.c Sun Jun 4 21:14:16 2000 @@ -9,8 +9,10 @@ #include #include #include +#include #include +#include #include /* @@ -19,6 +21,8 @@ * whether this could be called from an interrupt context or not. For * now, we expressly forbid it, especially as some of the stuff we do * here is not interrupt context safe. + * + * Note that this does *not* zero the allocated area! */ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) { @@ -36,15 +40,21 @@ if (!page) goto no_page; - memset((void *)page, 0, size); - clean_cache_area(page, size); - - *dma_handle = virt_to_bus((void *)page); - ret = __ioremap(virt_to_phys((void *)page), size, 0); if (ret) { /* free wasted pages */ unsigned long end = page + (PAGE_SIZE << order); + + /* + * we need to ensure that there are no + * cachelines in use, or worse dirty in + * this area. + */ + dma_cache_inv(page, size); + dma_cache_inv(ret, size); + + *dma_handle = virt_to_bus((void *)page); + page += size; while (page < end) { free_page(page); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/fault-armv.c linux.ac/arch/arm/mm/fault-armv.c --- linux.vanilla/arch/arm/mm/fault-armv.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/fault-armv.c Sun Jun 4 21:14:16 2000 @@ -250,6 +250,8 @@ } } +if (addr != eaddr) +printk("PC = %08lx, instr = %08x, addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr); if (LDST_L_BIT(instr)) { regs->uregs[rd] = get_unaligned((unsigned long *)eaddr); if (rd == 15) @@ -383,29 +385,38 @@ "more information\n" asmlinkage void -do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) +do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr) { - const struct fsr_info *inf; + const struct fsr_info *inf = fsr_info + (fsr & 15); - if (user_mode(regs) && addr == regs->ARM_pc) { + if (addr == regs->ARM_pc) + goto weirdness; + + if (!inf->fn) + goto bad; + + if (!inf->fn(addr, error_code, regs)) + return; +bad: + force_sig(inf->sig, current); + die_if_kernel(inf->name, regs, fsr); + return; + +weirdness: + if (user_mode(regs)) { static int first = 1; - if (first) { + if (first) /* * I want statistical information on this problem, * but we don't want to hastle the users too much. */ printk(BUG_PROC_MSG, fsr); - first = 0; - } + first = 0; return; } - inf = fsr_info + (fsr & 15); - - if (!inf->fn || inf->fn(addr, error_code, regs)) { - force_sig(inf->sig, current); - die_if_kernel(inf->name, regs, fsr); - } + if (!inf->fn || inf->fn(addr, error_code, regs)) + goto bad; } asmlinkage int diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/fault-common.c linux.ac/arch/arm/mm/fault-common.c --- linux.vanilla/arch/arm/mm/fault-common.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/fault-common.c Sun Jun 4 21:14:16 2000 @@ -16,6 +16,10 @@ { pgd_t *pgd; + if (!mm) + mm = &init_mm; + + printk(KERN_ALERT "pgd = %p\n", mm->pgd); pgd = pgd_offset(mm, addr); printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd)); @@ -52,39 +56,78 @@ printk("\n"); } -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ -static void -kernel_page_fault(unsigned long addr, int write_access, struct pt_regs *regs, - struct task_struct *tsk, struct mm_struct *mm) +static int __do_page_fault(struct mm_struct *mm, unsigned long addr, int mode, struct task_struct *tsk) { - char *reason; + struct vm_area_struct *vma; + int fault, mask; + + vma = find_vma(mm, addr); + fault = -2; /* bad map area */ + if (!vma) + goto out; + if (vma->vm_start > addr) + goto check_stack; - if (addr < PAGE_SIZE) - reason = "NULL pointer dereference"; + /* + * Ok, we have a good vm_area for this + * memory access, so we can handle it. + */ +good_area: + if (READ_FAULT(mode)) /* read? */ + mask = VM_READ|VM_EXEC; else - reason = "paging request"; + mask = VM_WRITE; - printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", - reason, addr); - if (!mm) - mm = &init_mm; + fault = -1; /* bad access type */ + if (!(vma->vm_flags & mask)) + goto out; - printk(KERN_ALERT "pgd = %p\n", mm->pgd); - show_pte(mm, addr); - die("Oops", regs, write_access); + /* + * If for any reason at all we couldn't handle + * the fault, make sure we exit gracefully rather + * than endlessly redo the fault. + */ +survive: + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(mode)); - do_exit(SIGKILL); + /* + * Handle the "normal" cases first - successful and sigbus + */ + switch (fault) { + case 2: + tsk->maj_flt++; + return fault; + case 1: + tsk->min_flt++; + case 0: + return fault; + } + + fault = -3; /* out of memory */ + if (tsk->pid != 1) + goto out; + + /* + * If we are out of memory for pid1, + * sleep for a while and retry + */ + tsk->policy |= SCHED_YIELD; + schedule(); + goto survive; + +check_stack: + if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) + goto good_area; +out: + return fault; } static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; - struct vm_area_struct *vma; unsigned long fixup; + int fault; tsk = current; mm = tsk->mm; @@ -97,57 +140,77 @@ goto no_context; down(&mm->mmap_sem); - vma = find_vma(mm, addr); - if (!vma) - goto bad_area; - if (vma->vm_start <= addr) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, addr)) - goto bad_area; + fault = __do_page_fault(mm, addr, mode, tsk); + up(&mm->mmap_sem); /* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. + * Handle the "normal" case first */ -good_area: - if (READ_FAULT(mode)) { /* read? */ - if (!(vma->vm_flags & (VM_READ|VM_EXEC))) - goto bad_area; - } else { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } + if (fault > 0) + return 0; /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. + * We had some memory, but were unable to + * successfully fix up this page fault. */ - if (!handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(mode))) + if (fault == 0) goto do_sigbus; - up(&mm->mmap_sem); - return 0; - /* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. + * If we are in kernel mode at this point, we + * have no context to handle this fault with. */ -bad_area: - up(&mm->mmap_sem); + if (!user_mode(regs)) + goto no_context; + + if (fault == -3) { + /* + * We ran out of memory, or some other thing happened to + * us that made us unable to handle the page fault gracefully. + */ + printk("VM: killing process %s\n", tsk->comm); + do_exit(SIGKILL); + } else { + /* + * Something tried to access memory that isn't in our memory map.. + * User mode accesses just cause a SIGSEGV + */ + struct siginfo si; + +#ifdef CONFIG_DEBUG_USER + printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, " + "lr=0x%08lx (bad address=0x%08lx, code %d)\n", + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); +#endif - /* User mode accesses just cause a SIGSEGV */ - if (user_mode(regs)) { tsk->thread.address = addr; 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); -#endif - force_sig(SIGSEGV, tsk); - return 0; + si.si_signo = SIGSEGV; + si.si_code = fault == -1 ? SEGV_ACCERR : SEGV_MAPERR; + si.si_addr = (void *)addr; + force_sig_info(SIGSEGV, &si, tsk); } + return 0; + + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +do_sigbus: + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.address = addr; + tsk->thread.error_code = mode; + tsk->thread.trap_no = 14; + force_sig(SIGBUS, tsk); + + /* Kernel mode? Handle exceptions or die */ + if (user_mode(regs)) + return 0; no_context: /* Are we prepared to handle this kernel fault? */ @@ -160,29 +223,16 @@ return 0; } - kernel_page_fault(addr, mode, regs, tsk, mm); - return 0; - -do_sigbus: /* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. */ - up(&mm->mmap_sem); + printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", + (addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr); - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - tsk->thread.address = addr; - tsk->thread.error_code = mode; - tsk->thread.trap_no = 14; - force_sig(SIGBUS, tsk); + show_pte(mm, addr); + die("Oops", regs, mode); + do_exit(SIGKILL); - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; return 0; } - - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/init.c linux.ac/arch/arm/mm/init.c --- linux.vanilla/arch/arm/mm/init.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/init.c Sun Jun 4 21:14:16 2000 @@ -31,16 +31,23 @@ #include "map.h" +#ifndef CONFIG_DISCONTIGMEM +#define NR_NODES 1 +#else +#define NR_NODES 4 +#endif + #ifdef CONFIG_CPU_32 #define TABLE_OFFSET (PTRS_PER_PTE) #else #define TABLE_OFFSET 0 #endif + #define TABLE_SIZE ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *)) static unsigned long totalram_pages; pgd_t swapper_pg_dir[PTRS_PER_PGD]; -extern int _stext, _text, _etext, _edata, _end; +extern char _stext, _text, _etext, _end, __init_begin, __init_end; /* * The sole use of this is to pass memory configuration @@ -173,6 +180,12 @@ show_buffers(); } +struct node_info { + unsigned int start; + unsigned int end; + int bootmap_pages; +}; + #define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) @@ -183,34 +196,24 @@ #define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ (((unsigned long)(s)) & PAGE_MASK)) +/* + * FIXME: We really want to avoid allocating the bootmap bitmap + * over the top of the initrd. Hopefully, this is located towards + * the start of a bank, so if we allocate the bootmap bitmap at + * the end, we won't clash. + */ static unsigned int __init -find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages) +find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) { unsigned int start_pfn, bank, bootmap_pfn; start_pfn = V_PFN_UP(&_end); bootmap_pfn = 0; - /* - * FIXME: We really want to avoid allocating the bootmap - * over the top of the initrd. - */ -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - if (__pa(initrd_end) > mi->end) { - printk ("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx) - disabling initrd\n", - __pa(initrd_end), mi->end); - initrd_start = 0; - initrd_end = 0; - } - } -#endif - for (bank = 0; bank < mi->nr_banks; bank ++) { unsigned int start, end; - if (mi->bank[bank].size == 0) + if (mi->bank[bank].node != node) continue; start = O_PFN_UP(mi->bank[bank].start); @@ -239,99 +242,224 @@ } /* - * Initialise one node of the bootmem allocator. For now, we - * only initialise node 0. Notice that we have a bootmem - * bitmap per node. + * Scan the memory info structure and pull out: + * - the end of memory + * - the number of nodes + * - the pfn range of each node + * - the number of bootmem bitmap pages */ -static void __init setup_bootmem_node(int node, struct meminfo *mi) +static unsigned int __init +find_memend_and_nodes(struct meminfo *mi, struct node_info *np) { - unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn; - unsigned int i; + unsigned int i, bootmem_pages = 0, memend_pfn = 0; + + for (i = 0; i < NR_NODES; i++) { + np[i].start = -1U; + np[i].end = 0; + np[i].bootmap_pages = 0; + } + + for (i = 0; i < mi->nr_banks; i++) { + unsigned long start, end; + int node; + + if (mi->bank[i].size == 0) { + /* + * Mark this bank with an invalid node number + */ + mi->bank[i].node = -1; + continue; + } + + node = mi->bank[i].node; + + if (node >= numnodes) { + numnodes = node + 1; - if (node != 0) /* only initialise node 0 for now */ - return; + /* + * Make sure we haven't exceeded the maximum number + * of nodes that we have in this configuration. If + * we have, we're in trouble. (maybe we ought to + * limit, instead of bugging?) + */ + if (numnodes > NR_NODES) + BUG(); + } + + /* + * Get the start and end pfns for this bank + */ + start = O_PFN_UP(mi->bank[i].start); + end = O_PFN_DOWN(mi->bank[i].start + mi->bank[i].size); - start_pfn = O_PFN_UP(PHYS_OFFSET); - end_pfn = O_PFN_DOWN(mi->end); - bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bootmap_pfn = find_bootmap_pfn(mi, bootmap_pages); + if (np[node].start > start) + np[node].start = start; + + if (np[node].end < end) + np[node].end = end; + + if (memend_pfn < end) + memend_pfn = end; + } /* - * Initialise the boot-time allocator + * Calculate the number of pages we require to + * store the bootmem bitmaps. */ - init_bootmem_node(node, bootmap_pfn, start_pfn, end_pfn); + for (i = 0; i < numnodes; i++) { + if (np[i].end == 0) + continue; + + np[i].bootmap_pages = bootmem_bootmap_pages(np[i].end - + np[i].start); + bootmem_pages += np[i].bootmap_pages; + } /* - * Register all available RAM with the bootmem allocator. + * This doesn't seem to be used by the Linux memory + * manager any more. If we can get rid of it, we + * also get rid of some of the stuff above as well. */ - for (i = 0; i < mi->nr_banks; i++) - if (mi->bank[i].size) - free_bootmem_node(node, mi->bank[i].start, - PFN_SIZE(mi->bank[i].size) << PAGE_SHIFT); + max_low_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET); + mi->end = memend_pfn << PAGE_SHIFT; - reserve_bootmem_node(node, bootmap_pfn << PAGE_SHIFT, - bootmap_pages << PAGE_SHIFT); + return bootmem_pages; } -/* - * Initialise the bootmem allocator. - */ -void __init bootmem_init(struct meminfo *mi) +static int __init check_initrd(struct meminfo *mi) { - unsigned int i, node; + int initrd_node = -2; +#ifdef CONFIG_BLK_DEV_INITRD /* - * Calculate the physical address of the top of memory. - * Note that there are no guarantees assumed about the - * ordering of the bank information. + * Make sure that the initrd is within a valid area of + * memory. */ - mi->end = 0; - for (i = 0; i < mi->nr_banks; i++) { - unsigned long end; + if (initrd_start) { + unsigned long phys_initrd_start, phys_initrd_end; + unsigned int i; + + phys_initrd_start = __pa(initrd_start); + phys_initrd_end = __pa(initrd_end); + + for (i = 0; i < mi->nr_banks; i++) { + unsigned long bank_end; - if (mi->bank[i].size != 0) { - end = mi->bank[i].start + mi->bank[i].size; - if (mi->end < end) - mi->end = end; + bank_end = mi->bank[i].start + mi->bank[i].size; + + if (mi->bank[i].start <= phys_initrd_start && + phys_initrd_end <= bank_end) + initrd_node = mi->bank[i].node; } } - max_low_pfn = O_PFN_DOWN(mi->end - PHYS_OFFSET); + if (initrd_node == -1) { + printk(KERN_ERR "initrd (0x%08lx - 0x%08lx) extends beyond " + "physical memory - disabling initrd\n", + initrd_start, initrd_end); + initrd_start = initrd_end = 0; + } +#endif - /* - * Setup each node - */ - for (node = 0; node < numnodes; node++) - setup_bootmem_node(node, mi); + return initrd_node; +} +/* + * Reserve the various regions of node 0 + */ +static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages) +{ /* * Register the kernel text and data with bootmem. * Note that this can only be in node 0. */ - reserve_bootmem_node(0, V_PFN_DOWN(&_stext) << PAGE_SHIFT, - PFN_RANGE(&_stext, &_end) << PAGE_SHIFT); + reserve_bootmem_node(0, __pa(&_stext), &_end - &_stext); #ifdef CONFIG_CPU_32 /* * Reserve the page tables. These are already in use, * and can only be in node 0. */ - reserve_bootmem_node(0, V_PFN_DOWN(swapper_pg_dir) << PAGE_SHIFT, - PFN_SIZE(PTRS_PER_PGD * sizeof(void *)) << PAGE_SHIFT); + reserve_bootmem_node(0, __pa(swapper_pg_dir), + PTRS_PER_PGD * sizeof(void *)); #endif -#ifdef CONFIG_BLK_DEV_INITRD /* - * This may be in any bank. Currently, we assume that - * it is in bank 0. + * And don't forget to reserve the allocator bitmap, + * which will be freed later. */ - if (initrd_start) - reserve_bootmem_node(0, V_PFN_DOWN(initrd_start) << PAGE_SHIFT, - PFN_RANGE(initrd_start, initrd_end) << PAGE_SHIFT); + reserve_bootmem_node(0, bootmap_pfn << PAGE_SHIFT, + bootmap_pages << PAGE_SHIFT); +} + +/* + * Register all available RAM in this node with the bootmem allocator. + */ +static inline void free_bootmem_node_bank(int node, struct meminfo *mi) +{ + int bank; + + for (bank = 0; bank < mi->nr_banks; bank++) + if (mi->bank[bank].node == node) + free_bootmem_node(node, mi->bank[bank].start, + mi->bank[bank].size); +} + +/* + * Initialise the bootmem allocator for all nodes. This is called + * early during the architecture specific initialisation. + */ +void __init bootmem_init(struct meminfo *mi) +{ + struct node_info node_info[NR_NODES], *np = node_info; + unsigned int bootmap_pages, bootmap_pfn, map_pg; + int node, initrd_node; + + bootmap_pages = find_memend_and_nodes(mi, np); + bootmap_pfn = find_bootmap_pfn(0, mi, bootmap_pages); + initrd_node = check_initrd(mi); + + map_pg = bootmap_pfn; + + for (node = 0; node < numnodes; node++, np++) { + /* + * If there are no pages in this node, ignore it. + * Note that node 0 must always have some pages. + */ + if (np->end == 0) { + if (node == 0) + BUG(); + continue; + } + + /* + * Initialise the bootmem allocator. + */ + init_bootmem_node(node, map_pg, np->start, np->end); + free_bootmem_node_bank(node, mi); + map_pg += np->bootmap_pages; + + /* + * If this is node 0, we need to reserve some areas ASAP - + * we may use bootmem on node 0 to setup the other nodes. + */ + if (node == 0) + reserve_node_zero(bootmap_pfn, bootmap_pages); + } + + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_node >= 0) + reserve_bootmem_node(initrd_node, __pa(initrd_start), + initrd_end - initrd_start); #endif + + if (map_pg != bootmap_pfn + bootmap_pages) + BUG(); } /* - * paging_init() sets up the page tables... + * paging_init() sets up the page tables, initialises the zone memory + * maps, and sets up the zero page, bad page and bad page tables. */ void __init paging_init(struct meminfo *mi) { @@ -378,11 +506,23 @@ * The size of this node has already been determined. * If we need to do anything fancy with the allocation * of this memory to the zones, now is the time to do - * it. For now, we don't touch zhole_size. + * it. */ zone_size[0] = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT); + /* + * For each bank in this node, calculate the size of the + * holes. holes = node_size - sum(bank_sizes_in_node) + */ + zhole_size[0] = zone_size[0]; + for (i = 0; i < mi->nr_banks; i++) { + if (mi->bank[i].node != node) + continue; + + zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT; + } + free_area_init_node(node, pgdat, zone_size, bdata->node_boot_start, zhole_size); } @@ -399,31 +539,6 @@ empty_bad_pte_table = ((pte_t *)bad_table) + TABLE_OFFSET; } -static inline void free_unused_mem_map(void) -{ - struct page *page, *end; - - end = mem_map + max_mapnr; - - for (page = mem_map; page < end; page++) { - unsigned long low, high; - - if (!PageSkip(page)) - continue; - - low = PAGE_ALIGN((unsigned long)(page + 1)); - if (page->next_hash < page) - high = ((unsigned long)end) & PAGE_MASK; - else - high = ((unsigned long)page->next_hash) & PAGE_MASK; - - while (low < high) { - ClearPageReserved(mem_map + MAP_NR(low)); - low += PAGE_SIZE; - } - } -} - /* * mem_init() marks the free areas in the mem_map and tells us how much * memory is free. This is done after various parts of the system have @@ -431,7 +546,6 @@ */ void __init mem_init(void) { - extern char __init_begin, __init_end; unsigned int codepages, datapages, initpages; int i, node; @@ -443,8 +557,7 @@ max_mapnr = MAP_NR(high_memory); /* - * We may have non-contiguous memory. Setup the PageSkip stuff, - * and mark the areas of mem_map which can be freed + * We may have non-contiguous memory. */ if (meminfo.nr_banks != 1) create_memmap_holes(&meminfo); @@ -500,8 +613,6 @@ void free_initmem(void) { - extern char __init_begin, __init_end; - printk("Freeing unused kernel memory:"); free_area((unsigned long)(&__init_begin), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/mm-armv.c linux.ac/arch/arm/mm/mm-armv.c --- linux.vanilla/arch/arm/mm/mm-armv.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/mm-armv.c Sun Jun 4 21:14:16 2000 @@ -411,50 +411,41 @@ } /* - * The mem_map array can get very big. Mark the end of the valid mem_map - * banks with PG_skip, and setup the address validity bitmap. + * The mem_map array can get very big. Free the unused area of the memory map. */ -void __init create_memmap_holes(struct meminfo *mi) +static inline void free_unused_memmap_node(int node, struct meminfo *mi) { - unsigned int start_pfn, end_pfn = -1; - struct page *pg = NULL; + unsigned long bank_start, prev_bank_end = 0; unsigned int i; -#define PFN(x) (((x) - PHYS_OFFSET) >> PAGE_SHIFT) -#define free_bootmem(s,sz) free_bootmem(((s)<nr_banks; i++) { - if (mi->bank[i].size == 0) + if (mi->bank[i].size == 0 || mi->bank[i].node != node) continue; - start_pfn = PFN(mi->bank[i].start); + bank_start = mi->bank[i].start & PAGE_MASK; /* - * subtle here - if we have a full bank, then - * start_pfn == end_pfn, and we don't want to - * set PG_skip, or next_hash + * If we had a previous bank, and there is a space + * between the current bank and the previous, free it. */ - if (pg && start_pfn != end_pfn) { - set_bit(PG_skip, &pg->flags); - pg->next_hash = mem_map + start_pfn; - - start_pfn = PFN(PAGE_ALIGN(__pa(pg + 1))); - end_pfn = PFN(__pa(pg->next_hash) & PAGE_MASK); - - if (end_pfn != start_pfn) - free_bootmem(start_pfn, end_pfn - start_pfn); - - pg = NULL; - } + if (prev_bank_end && prev_bank_end != bank_start) + free_bootmem_node(node, prev_bank_end, + bank_start - prev_bank_end); - end_pfn = PFN(mi->bank[i].start + mi->bank[i].size); - - if (end_pfn != PFN(mi->end)) - pg = mem_map + end_pfn; + prev_bank_end = PAGE_ALIGN(mi->bank[i].start + + mi->bank[i].size); } +} - if (pg) { - set_bit(PG_skip, &pg->flags); - pg->next_hash = NULL; - } +void __init create_memmap_holes(struct meminfo *mi) +{ + int node; + + for (node = 0; node < numnodes; node++) + free_unused_memmap_node(node, mi); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/mm-footbridge.c linux.ac/arch/arm/mm/mm-footbridge.c --- linux.vanilla/arch/arm/mm/mm-footbridge.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/mm-footbridge.c Sun Jun 4 21:14:16 2000 @@ -29,7 +29,7 @@ * You can then access the PCI bus at 0xe0000000 and 0xffe00000. */ -#ifdef CONFIG_HOST_FOOTBRIDGE +#ifdef CONFIG_FOOTBRIDGE_HOST /* * The mapping when the footbridge is in host mode. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/mm-l7200.c linux.ac/arch/arm/mm/mm-l7200.c --- linux.vanilla/arch/arm/mm/mm-l7200.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/arm/mm/mm-l7200.c Sun Jun 4 21:14:16 2000 @@ -0,0 +1,25 @@ +/* + * arch/arm/mm/mm-lusl7200.c + * + * Extra MM routines for LUSL7200 architecture + * + * Copyright (C) 2000 Steven J. Hill + */ + +#include + +#include +#include +#include +#include + +#include "map.h" + +#define SIZE(x) (sizeof(x) / sizeof(x[0])) + +struct map_desc io_desc[] __initdata = { + { IO_BASE, IO_START, IO_SIZE, DOMAIN_IO, 0, 1 ,0 ,0}, + { IO_BASE_2, IO_START_2, IO_SIZE_2, DOMAIN_IO, 0, 1 ,0 ,0}, +}; + +unsigned int __initdata io_desc_size = SIZE(io_desc); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/mm-sa1100.c linux.ac/arch/arm/mm/mm-sa1100.c --- linux.vanilla/arch/arm/mm/mm-sa1100.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/mm-sa1100.c Sun Jun 4 21:14:16 2000 @@ -11,13 +11,14 @@ * Memory is listed physically now. * * 2000/04/07 Nicolas Pitre - * Reworked for real-time selection of memory definitions + * Reworked for run-time selection of memory definitions * */ #include #include #include +#include #include #include @@ -140,4 +141,21 @@ io_desc_size = SIZE(default_io_desc); } } + +#ifdef CONFIG_DISCONTIGMEM + +/* + * Our node_data structure for discontigous memory. + * There is 4 possible nodes i.e. the 4 SA1100 RAM banks. + */ + +static bootmem_data_t node_bootmem_data[4]; + +pg_data_t sa1100_node_data[4] = +{ { bdata: &node_bootmem_data[0] }, + { bdata: &node_bootmem_data[1] }, + { bdata: &node_bootmem_data[2] }, + { bdata: &node_bootmem_data[3] } }; + +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/proc-arm6,7.S linux.ac/arch/arm/mm/proc-arm6,7.S --- linux.vanilla/arch/arm/mm/proc-arm6,7.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/proc-arm6,7.S Sun Jun 4 21:14:16 2000 @@ -93,37 +93,30 @@ * Purpose : obtain information about current aborted instruction * * Returns : r0 = address of abort - * : r1 = FSR - * : r2 != 0 if writing + * : r1 != 0 if writing + * : r3 = FSR * : sp = pointer to registers */ -Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0" - .align - -msg: .ascii "DA*%p=%p\n\0" - .align - ENTRY(cpu_arm6_data_abort) ldr r4, [r0] @ read instruction causing problem - mov r2, r4, lsr #19 @ r2 b1 = L - and r1, r4, #14 << 24 - and r2, r2, #2 @ check read/write bit - teq r1, #4 << 23 + mov r1, r4, lsr #19 @ r1 b1 = L + and r2, r4, #14 << 24 + and r1, r1, #2 @ check read/write bit + teq r2, #8 << 24 @ was it ldm/stm bne Ldata_simple - Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit beq Ldata_simple mov r7, #0x11 orr r7, r7, r7, lsl #8 and r0, r4, r7 - and r1, r4, r7, lsl #1 - add r0, r0, r1, lsr #1 - and r1, r4, r7, lsl #2 - add r0, r0, r1, lsr #2 - and r1, r4, r7, lsl #3 - add r0, r0, r1, lsr #3 + and r2, r4, r7, lsl #1 + add r0, r0, r2, lsr #1 + and r2, r4, r7, lsl #2 + add r0, r0, r2, lsr #2 + and r2, r4, r7, lsl #3 + add r0, r0, r2, lsr #3 add r0, r0, r0, lsr #8 add r0, r0, r0, lsr #4 and r7, r0, #15 @ r7 = no. of registers to transfer. @@ -134,16 +127,16 @@ addeq r7, r0, r7, lsl #2 @ Do correction (signed) Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR - mrc p15, 0, r1, c5, c0, 0 @ get FSR - and r1, r1, #255 + mrc p15, 0, r3, c5, c0, 0 @ get FSR + and r3, r3, #255 mov pc, lr ENTRY(cpu_arm7_data_abort) ldr r4, [r0] @ read instruction causing problem - mov r2, r4, lsr #19 @ r2 b1 = L - and r1, r4, #15 << 24 - and r2, r2, #2 @ check read/write bit - add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine + mov r1, r4, lsr #19 @ r1 b1 = L + and r2, r4, #15 << 24 + and r1, r1, #2 @ check read/write bit + add pc, pc, r2, lsr #22 @ Now branch to the relevent processing routine movs pc, lr b Ldata_unknown @@ -162,7 +155,7 @@ b Ldata_simple @ ldc rd, [rn, #m] b Ldata_unknown Ldata_unknown: @ Part of jumptable - mov r0, r1 + mov r0, r2 mov r1, r4 mov r2, r3 b baddataabort @@ -172,13 +165,13 @@ tst r4, #1 << 21 @ check writeback bit beq Ldata_simple Ldata_lateldrpostconst: - movs r1, r4, lsl #20 @ Get offset + movs r2, r4, lsl #20 @ Get offset beq Ldata_simple and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit - subne r7, r0, r1, lsr #20 - addeq r7, r0, r1, lsr #20 + subne r7, r0, r2, lsr #20 + addeq r7, r0, r2, lsr #20 b Ldata_saver7 Ldata_lateldrprereg: @@ -186,7 +179,7 @@ beq Ldata_simple Ldata_lateldrpostreg: and r5, r4, #15 - ldr r1, [sp, r5, lsl #2] @ Get Rm + ldr r2, [sp, r5, lsl #2] @ Get Rm mov r3, r4, lsr #7 ands r3, r3, #31 and r6, r4, #0x70 @@ -194,7 +187,7 @@ add pc, pc, r6 mov r0, r0 - mov r1, r1, lsl r3 @ 0: LSL #!0 + mov r2, r2, lsl r3 @ 0: LSL #!0 b 1f b 1f @ 1: LSL #0 mov r0, r0 @@ -202,25 +195,25 @@ mov r0, r0 b 1f @ 3: MUL? mov r0, r0 - mov r1, r1, lsr r3 @ 4: LSR #!0 + mov r2, r2, lsr r3 @ 4: LSR #!0 b 1f - mov r1, r1, lsr #32 @ 5: LSR #32 + mov r2, r2, lsr #32 @ 5: LSR #32 b 1f b 1f @ 6: MUL? mov r0, r0 b 1f @ 7: MUL? mov r0, r0 - mov r1, r1, asr r3 @ 8: ASR #!0 + mov r2, r2, asr r3 @ 8: ASR #!0 b 1f - mov r1, r1, asr #32 @ 9: ASR #32 + mov r2, r2, asr #32 @ 9: ASR #32 b 1f b 1f @ A: MUL? mov r0, r0 b 1f @ B: MUL? mov r0, r0 - mov r1, r1, ror r3 @ C: ROR #!0 + mov r2, r2, ror r3 @ C: ROR #!0 b 1f - mov r1, r1, rrx @ D: RRX + mov r2, r2, rrx @ D: RRX b 1f mov r0, r0 @ E: MUL? mov r0, r0 @@ -230,8 +223,8 @@ 1: and r5, r4, #15 << 16 @ Get Rn ldr r0, [sp, r5, lsr #14] tst r4, #1 << 23 @ U bit - subne r7, r0, r1 - addeq r7, r0, r1 + subne r7, r0, r2 + addeq r7, r0, r2 b Ldata_saver7 /* @@ -254,7 +247,8 @@ ENTRY(cpu_arm6_proc_fin) ENTRY(cpu_arm7_proc_fin) - msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov r0, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, r0 mov r0, #0x31 @ ....S..DP...M mcr p15, 0, r0, c1, c0, 0 @ disable caches mov pc, lr @@ -364,7 +358,8 @@ .section ".text.init", #alloc, #execinstr -__arm6_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE +__arm6_setup: mov r0, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, r0 mov r0, #0 mcr p15, 0, r0, c7, c0 @ flush caches on v3 mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 @@ -375,7 +370,8 @@ orr r0, r0, #0x100 mov pc, lr -__arm7_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE +__arm7_setup: mov r0, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, r0 mov r0, #0 mcr p15, 0, r0, c7, c0 @ flush caches on v3 mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/arm/mm/proc-sa110.S linux.ac/arch/arm/mm/proc-sa110.S --- linux.vanilla/arch/arm/mm/proc-sa110.S Thu May 25 17:38:34 2000 +++ linux.ac/arch/arm/mm/proc-sa110.S Sun Jun 4 21:14:16 2000 @@ -300,19 +300,18 @@ * Params : r0 = address of aborted instruction * Purpose : obtain information about current aborted instruction * Returns : r0 = address of abort - * : r1 = FSR - * : r2 != 0 if writing + * : r1 != 0 if writing + * : r3 = FSR */ .align 5 ENTRY(cpu_sa110_data_abort) ENTRY(cpu_sa1100_data_abort) - ldr r2, [r0] @ read instruction causing problem + ldr r1, [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 r1, r1, lsr #19 @ b1 = L + and r1, r1, #2 + mrc p15, 0, r3, c5, c0, 0 @ get FSR + and r3, r3, #255 mov pc, lr .align 5 @@ -423,7 +422,8 @@ ENTRY(cpu_sa110_proc_fin) stmfd sp!, {r1, lr} - msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip bl cpu_sa110_flush_cache_all @ clean caches 1: mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching @@ -435,7 +435,8 @@ ENTRY(cpu_sa1100_proc_fin) stmfd sp!, {r1, lr} - msr cpsr_c, #F_BIT | I_BIT | SVC_MODE + mov ip, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, ip bl cpu_sa1100_flush_cache_all @ clean caches b 1b @@ -501,7 +502,8 @@ .section ".text.init", #alloc, #execinstr -__sa110_setup: msr cpsr_c, #F_BIT | I_BIT | SVC_MODE +__sa110_setup: mov r0, #F_BIT | I_BIT | SVC_MODE + msr cpsr_c, r0 mov r0, #0 mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/Makefile linux.ac/arch/i386/Makefile --- linux.vanilla/arch/i386/Makefile Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/Makefile Sun Jun 4 21:47:46 2000 @@ -49,7 +49,7 @@ CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi) endif -ifdef CONFIG_M686FX +ifdef CONFIG_M686FXSR CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi) endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/config.in linux.ac/arch/i386/config.in --- linux.vanilla/arch/i386/config.in Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/config.in Thu Jun 8 16:50:41 2000 @@ -19,14 +19,16 @@ comment 'Processor type and features' choice 'Processor family' \ "386 CONFIG_M386 \ - 486/Cx486 CONFIG_M486 \ + 486 CONFIG_M486 \ 586/K5/5x86/6x86/6x86MX CONFIG_M586 \ - Pentium/TSC CONFIG_M586TSC \ - PPro/Pentium-II CONFIG_M686 \ - Pentium-III CONFIG_M686FX \ + Pentium/Pentium-MMX CONFIG_M586TSC \ + Pentium-Pro/Celeron/Pentium-II CONFIG_M686 \ + Pentium-III CONFIG_M686FXSR \ K6/K6-II/K6-III CONFIG_MK6 \ - Athlon CONFIG_MK7 \ - Crusoe CONFIG_MCRUSOE" PPro + Athlon/K7 CONFIG_MK7 \ + Crusoe CONFIG_MCRUSOE \ + Winchip-C6 CONFIG_MWINCHIP \ + Winchip-2A/3 CONFIG_MWINCHIP3D" Pentium-Pro # # Define implied options from the CPU selection here # @@ -62,13 +64,16 @@ define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi -if [ "$CONFIG_M686FX" = "y" ]; then +if [ "$CONFIG_M686FXSR" = "y" ]; then define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y - define_bool CONFIG_X86_FX y + define_bool CONFIG_X86_FXSR y + define_bool CONFIG_X86_XMM y +else + define_bool CONFIG_X86_FXSR n fi if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_BYTES 32 @@ -84,6 +89,19 @@ define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi +if [ "$CONFIG_MWINCHIP" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 + define_bool CONFIG_X86_ALIGNMENT_16 y + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y +fi +if [ "$CONFIG_MWINCHIP3D" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_BYTES 32 + define_bool CONFIG_X86_ALIGNMENT_16 y + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_USE_3DNOW y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y +fi if [ "$CONFIG_MCRUSOE" = "y" ]; then define_int CONFIG_X86_L1_CACHE_BYTES 32 define_bool CONFIG_X86_TSC y @@ -105,7 +123,7 @@ define_bool CONFIG_X86_PAE y fi -if [ "$CONFIG_X86_FX" != "y" ]; then +if [ "$CONFIG_X86_FXSR" != "y" ]; then bool 'Math emulation' CONFIG_MATH_EMULATION fi bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/defconfig linux.ac/arch/i386/defconfig --- linux.vanilla/arch/i386/defconfig Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/defconfig Sun Jun 4 21:47:46 2000 @@ -19,7 +19,7 @@ # CONFIG_M586 is not set # CONFIG_M586TSC is not set CONFIG_M686=y -# CONFIG_M686FX is not set +# CONFIG_M686FXSR is not set # CONFIG_MK6 is not set # CONFIG_MK7 is not set # CONFIG_MCRUSOE is not set @@ -33,6 +33,7 @@ CONFIG_X86_GOOD_APIC=y CONFIG_X86_PGE=y CONFIG_X86_USE_PPRO_CHECKSUM=y +# CONFIG_X86_FXSR is not set # CONFIG_MICROCODE is not set # CONFIG_X86_MSR is not set # CONFIG_X86_CPUID is not set @@ -105,10 +106,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set @@ -179,6 +176,8 @@ # CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set # CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set # CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set @@ -228,6 +227,7 @@ # CONFIG_VIA82CXXX_TUNING is not set # CONFIG_IDE_CHIPSETS is not set # CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y # diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/acpi.c linux.ac/arch/i386/kernel/acpi.c --- linux.vanilla/arch/i386/kernel/acpi.c Thu May 25 17:38:24 2000 +++ linux.ac/arch/i386/kernel/acpi.c Sun Jun 4 22:17:47 2000 @@ -700,7 +700,7 @@ if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) return -ENODEV; - base = dev->resource[PCI_BRIDGE_RESOURCES].start & PCI_BASE_ADDRESS_IO_MASK; + base = pci_resource_start (dev, PCI_BRIDGE_RESOURCES); if (!base) return -ENODEV; @@ -759,7 +759,6 @@ if (!base) return -ENODEV; } - base &= PCI_BASE_ADDRESS_IO_MASK; pci_read_config_byte(dev, 0x42, &irq); @@ -824,7 +823,7 @@ {acpi_init_via}, }; -const static struct pci_device_id acpi_pci_tbl[] = +static struct pci_device_id acpi_pci_tbl[] __initdata = { {0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4}, {0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586}, @@ -1169,6 +1168,8 @@ acpi_sleep_start = get_cmos_time(); acpi_enter_dx(ACPI_D3); + // disable interrupts globally while suspended + cli(); acpi_sleep_state = state; facp = (struct acpi_facp*) acpi_facp.table; @@ -1191,6 +1192,8 @@ // finished sleeping, update system time acpi_update_clock(); acpi_enter_dx(ACPI_D0); + // reenable interrupts globally after resume + sti(); acpi_sleep_state = ACPI_S0; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/apic.c linux.ac/arch/i386/kernel/apic.c --- linux.vanilla/arch/i386/kernel/apic.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/apic.c Mon May 29 19:44:19 2000 @@ -701,7 +701,7 @@ ack_APIC_irq(); /* see sw-dev-man vol 3, chapter 7.4.13.5 */ - printk("spurious APIC interrupt on CPU#%d, should never happen.\n", + printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n", smp_processor_id()); } @@ -718,32 +718,32 @@ spin_lock(&err_lock); v = apic_read(APIC_ESR); - printk("APIC error interrupt on CPU#%d, should never happen.\n", + printk(KERN_INFO "APIC error interrupt on CPU#%d, should never happen.\n", smp_processor_id()); - printk("... APIC ESR0: %08lx\n", v); + printk(KERN_INFO "... APIC ESR0: %08lx\n", v); apic_write(APIC_ESR, 0); v |= apic_read(APIC_ESR); - printk("... APIC ESR1: %08lx\n", v); + printk(KERN_INFO "... APIC ESR1: %08lx\n", v); /* * Be a bit more verbose. (multiple bits can be set) */ if (v & 0x01) - printk("... bit 0: APIC Send CS Error (hw problem).\n"); + printk(KERN_INFO "... bit 0: APIC Send CS Error (hw problem).\n"); if (v & 0x02) - printk("... bit 1: APIC Receive CS Error (hw problem).\n"); + printk(KERN_INFO "... bit 1: APIC Receive CS Error (hw problem).\n"); if (v & 0x04) - printk("... bit 2: APIC Send Accept Error.\n"); + printk(KERN_INFO "... bit 2: APIC Send Accept Error.\n"); if (v & 0x08) - printk("... bit 3: APIC Receive Accept Error.\n"); + printk(KERN_INFO "... bit 3: APIC Receive Accept Error.\n"); if (v & 0x10) - printk("... bit 4: Reserved!.\n"); + printk(KERN_INFO "... bit 4: Reserved!.\n"); if (v & 0x20) - printk("... bit 5: Send Illegal Vector (kernel bug).\n"); + printk(KERN_INFO "... bit 5: Send Illegal Vector (kernel bug).\n"); if (v & 0x40) - printk("... bit 6: Received Illegal Vector.\n"); + printk(KERN_INFO "... bit 6: Received Illegal Vector.\n"); if (v & 0x80) - printk("... bit 7: Illegal Register Address.\n"); + printk(KERN_INFO "... bit 7: Illegal Register Address.\n"); ack_APIC_irq(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/apm.c linux.ac/arch/i386/kernel/apm.c --- linux.vanilla/arch/i386/kernel/apm.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/apm.c Fri May 26 14:27:53 2000 @@ -135,6 +135,13 @@ * Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS * is now the way life works). * Fix thinko in suspend() (wrong return). + * Notify drivers on critical suspend. + * Make kapmd absorb more idle time (Pavel Machek + * modified by sfr). + * Disable interrupts while we are suspended (Andy Henroid + * fixed by sfr). + * Make power off work on SMP again (Tony Hoyle + * and ) modified by sfr. * * APM 1.1 Reference: * @@ -864,19 +871,51 @@ #endif } +static int send_event(apm_event_t event) +{ + switch (event) { + case APM_SYS_SUSPEND: + case APM_CRITICAL_SUSPEND: + case APM_USER_SUSPEND: + /* map all suspends to ACPI D3 */ + if (pm_send_all(PM_SUSPEND, (void *)3)) { + if (event == APM_CRITICAL_SUSPEND) { + printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armageddon\n" ); + return 0; + } + if (apm_bios_info.version > 0x100) + apm_set_power_state(APM_STATE_REJECT); + return 0; + } + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + /* map all resumes to ACPI D0 */ + (void) pm_send_all(PM_RESUME, (void *)0); + break; + } + + return 1; +} + static int suspend(void) { int err; struct apm_user *as; get_time_diff(); + cli(); err = apm_set_power_state(APM_STATE_SUSPEND); reinit_timer(); set_time(); if (err == APM_NO_ERROR) err = APM_SUCCESS; - if (err != APM_SUCCESS) + if (err != APM_SUCCESS) { apm_error("suspend", err); + send_event(APM_NORMAL_RESUME); + sti(); + queue_event(APM_NORMAL_RESUME, NULL); + } for (as = user_list; as != NULL; as = as->next) { as->suspend_wait = 0; as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO); @@ -914,33 +953,6 @@ return 0; } -static int send_event(apm_event_t event, struct apm_user *sender) -{ - switch (event) { - case APM_SYS_SUSPEND: - case APM_CRITICAL_SUSPEND: - case APM_USER_SUSPEND: - /* map all suspends to ACPI D3 */ - if (pm_send_all(PM_SUSPEND, (void *)3)) { - if (event == APM_CRITICAL_SUSPEND) { - printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armagedon\n" ); - return 0; - } - if (apm_bios_info.version > 0x100) - apm_set_power_state(APM_STATE_REJECT); - return 0; - } - break; - case APM_NORMAL_RESUME: - case APM_CRITICAL_RESUME: - /* map all resumes to ACPI D0 */ - (void) pm_send_all(PM_RESUME, (void *)0); - break; - } - - return 1; -} - static void check_events(void) { apm_event_t event; @@ -966,7 +978,7 @@ switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: - if (send_event(event, NULL)) { + if (send_event(event)) { queue_event(event, NULL); if (standbys_pending <= 0) standby(); @@ -984,17 +996,17 @@ if (ignore_bounce) break; #endif - /* - * If we are already processing a SUSPEND, - * then further SUSPEND events from the BIOS - * will be ignored. We also return here to - * cope with the fact that the Thinkpads keep - * sending a SUSPEND event until something else - * happens! - */ + /* + * If we are already processing a SUSPEND, + * then further SUSPEND events from the BIOS + * will be ignored. We also return here to + * cope with the fact that the Thinkpads keep + * sending a SUSPEND event until something else + * happens! + */ if (waiting_for_resume) - return; - if (send_event(event, NULL)) { + return; + if (send_event(event)) { queue_event(event, NULL); waiting_for_resume = 1; if (suspends_pending <= 0) @@ -1011,14 +1023,16 @@ ignore_bounce = 1; #endif set_time(); - send_event(event, NULL); + send_event(event); + sti(); queue_event(event, NULL); break; case APM_CAPABILITY_CHANGE: case APM_LOW_BATTERY: case APM_POWER_STATUS_CHANGE: - send_event(event, NULL); + send_event(event); + queue_event(event, NULL); break; case APM_UPDATE_TIME: @@ -1026,7 +1040,11 @@ break; case APM_CRITICAL_SUSPEND: - send_event(event, NULL); /* We can only hope it worked; critical suspend may not fail */ + send_event(event); + /* + * We can only hope it worked - we are not allowed + * to reject a critical suspend. + */ (void) suspend(); break; } @@ -1066,11 +1084,8 @@ int timeout = HZ; DECLARE_WAITQUEUE(wait, current); - if (smp_num_cpus > 1) - return; - add_wait_queue(&apm_waitqueue, &wait); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); for (;;) { /* Nothing to do, just sleep for the timeout */ timeout = 2*timeout; @@ -1084,7 +1099,7 @@ * Ok, check all events, check for idle (and mark us sleeping * so as not to count towards the load average).. */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); apm_event_handler(); #ifdef CONFIG_APM_CPU_IDLE if (!system_idle()) @@ -1093,7 +1108,7 @@ unsigned long start = jiffies; while ((!exit_kapmd) && system_idle()) { apm_do_idle(); - if (jiffies - start > (5*APM_CHECK_TIMEOUT)) { + if ((jiffies - start) > APM_CHECK_TIMEOUT) { apm_event_handler(); start = jiffies; } @@ -1137,7 +1152,7 @@ schedule(); goto repeat; } - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&apm_waitqueue, &wait); } i = count; @@ -1199,8 +1214,10 @@ as->standbys_read--; as->standbys_pending--; standbys_pending--; - } else if (!send_event(APM_USER_STANDBY, as)) + } else if (!send_event(APM_USER_STANDBY)) return -EAGAIN; + else + queue_event(APM_USER_STANDBY, as); if (standbys_pending <= 0) standby(); break; @@ -1209,8 +1226,10 @@ as->suspends_read--; as->suspends_pending--; suspends_pending--; - } else if (!send_event(APM_USER_SUSPEND, as)) + } else if (!send_event(APM_USER_SUSPEND)) return -EAGAIN; + else + queue_event(APM_USER_SUSPEND, as); if (suspends_pending <= 0) { if (suspend() != APM_SUCCESS) return -EIO; @@ -1224,7 +1243,7 @@ break; schedule(); } - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&apm_suspend_waitqueue, &wait); return as->suspend_result; } @@ -1403,6 +1422,7 @@ strcpy(current->comm, "kapmd"); sigfillset(¤t->blocked); + current->tty = NULL; /* get rid of controlling tty */ if (apm_bios_info.version > 0x100) { /* @@ -1487,27 +1507,15 @@ #ifdef CONFIG_MAGIC_SYSRQ sysrq_power_off = apm_power_off; #endif + if (smp_num_cpus == 1) { #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) - if (smp_num_cpus == 1) console_blank_hook = apm_console_blank; #endif - - pm_active = 1; - - apm_mainloop(); - - pm_active = 0; - + apm_mainloop(); #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT) - if (smp_num_cpus == 1) console_blank_hook = NULL; #endif -#ifdef CONFIG_MAGIC_SYSRQ - sysrq_power_off = NULL; -#endif - if (power_off) - pm_power_off = NULL; - + } kapmd_running = 0; return 0; @@ -1618,6 +1626,7 @@ printk(KERN_NOTICE "apm: overridden by ACPI.\n"); APM_INIT_ERROR_RETURN; } + pm_active = 1; /* * Set up a segment that references the real mode segment 0x40 @@ -1676,9 +1685,15 @@ { misc_deregister(&apm_device); remove_proc_entry("apm", NULL); +#ifdef CONFIG_MAGIC_SYSRQ + sysrq_power_off = NULL; +#endif + if (power_off) + pm_power_off = NULL; exit_kapmd = 1; while (kapmd_running) schedule(); + pm_active = 0; } module_init(apm_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/cpuid.c linux.ac/arch/i386/kernel/cpuid.c --- linux.vanilla/arch/i386/kernel/cpuid.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/cpuid.c Thu May 25 23:33:29 2000 @@ -64,11 +64,11 @@ if ( cpu == smp_processor_id() ) { cpuid(reg, &data[0], &data[1], &data[2], &data[3]); } else { - cmd->cpu = cpu; - cmd->reg = reg; - cmd->data = data; + cmd.cpu = cpu; + cmd.reg = reg; + cmd.data = data; - smp_call_function(cpuid_smp_cpuid, (void *)cmd, 1, 1); + smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1); } } #else /* ! CONFIG_SMP */ @@ -120,9 +120,12 @@ static int cpuid_open(struct inode *inode, struct file *file) { int cpu = MINOR(file->f_dentry->d_inode->i_rdev); - + struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + if ( !(cpu_online_map & (1UL << cpu)) ) - return -ENXIO; /* No such CPU */ + return -ENXIO; /* No such CPU */ + if ( c->cpuid_level < 0 ) + return -EIO; /* CPUID not supported */ MOD_INC_USE_COUNT; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/entry.S linux.ac/arch/i386/kernel/entry.S --- linux.vanilla/arch/i386/kernel/entry.S Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/entry.S Tue May 30 16:47:56 2000 @@ -322,13 +322,20 @@ pushl $ SYMBOL_NAME(do_coprocessor_error) jmp error_code +#ifdef CONFIG_X86_XMM +ENTRY(simd_coprocessor_error) + pushl $0 + pushl $ SYMBOL_NAME(do_simd_coprocessor_error) + jmp error_code +#endif + ENTRY(device_not_available) pushl $-1 # mark this as an int SAVE_ALL GET_CURRENT(%ebx) pushl $ret_from_exception movl %cr0,%eax - testl $0x4,%eax # EM (math emulation bit) + testl $0x4,%eax # EM (math emulation bit) je SYMBOL_NAME(math_state_restore) pushl $0 # temporary storage for ORIG_EIP call SYMBOL_NAME(math_emulate) @@ -411,11 +418,6 @@ ENTRY(spurious_interrupt_bug) pushl $0 pushl $ SYMBOL_NAME(do_spurious_interrupt_bug) - jmp error_code - -ENTRY(xmm_fault) - pushl $0 - pushl $ SYMBOL_NAME(do_xmm_fault) jmp error_code .data diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/microcode.c linux.ac/arch/i386/kernel/microcode.c --- linux.vanilla/arch/i386/kernel/microcode.c Thu May 25 17:38:24 2000 +++ linux.ac/arch/i386/kernel/microcode.c Sat Jun 10 21:49:51 2000 @@ -25,6 +25,11 @@ * and frees the saved copy of applied microcode. * 1.03 29 February 2000, Tigran Aivazian * Made to use devfs (/dev/cpu/microcode) + cleanups. + * 1.04 06 June 2000, Simon Trimmer + * Added misc device support (now uses both devfs and misc). + * Added MICROCODE_IOCFREE ioctl to clear memory. + * 1.05 09 June 2000, Simon Trimmer + * Messages for error cases (non intel & no suitable microcode). */ #include @@ -33,16 +38,17 @@ #include #include #include +#include #include #include #include #include -#define MICROCODE_VERSION "1.03" +#define MICROCODE_VERSION "1.05" -MODULE_DESCRIPTION("CPU (P6) microcode update driver"); -MODULE_AUTHOR("Tigran Aivazian "); +MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver"); +MODULE_AUTHOR("Tigran Aivazian "); EXPORT_NO_SYMBOLS; /* VFS interface */ @@ -50,6 +56,7 @@ static int microcode_release(struct inode *, struct file *); static ssize_t microcode_read(struct file *, char *, size_t, loff_t *); static ssize_t microcode_write(struct file *, const char *, size_t, loff_t *); +static int microcode_ioctl(struct inode *, struct file *, unsigned int, unsigned long); /* internal helpers to do the work */ @@ -60,43 +67,61 @@ * Bits in microcode_status. (31 bits of room for future expansion) */ #define MICROCODE_IS_OPEN 0 /* set if device is in use */ -static unsigned long microcode_status = 0; + +static unsigned long microcode_status; /* the actual array of microcode blocks, each 2048 bytes */ -static struct microcode *microcode = NULL; -static unsigned int microcode_num = 0; -static char *mc_applied = NULL; /* holds an array of applied microcode blocks */ -static unsigned int mc_fsize; /* used often, so compute once at microcode_init() */ +static struct microcode *microcode; +static unsigned int microcode_num; +static char *mc_applied; /* holds an array of applied microcode blocks */ +static unsigned int mc_fsize; static struct file_operations microcode_fops = { read: microcode_read, write: microcode_write, + ioctl: microcode_ioctl, open: microcode_open, release: microcode_release, }; +static struct miscdevice microcode_dev = { + minor: MICROCODE_MINOR, + name: "microcode", + fops: µcode_fops, +}; + static devfs_handle_t devfs_handle; static int __init microcode_init(void) { - devfs_handle = devfs_register(NULL, "cpu/microcode", 0, DEVFS_FL_DEFAULT, 0, 0, - S_IFREG | S_IRUSR | S_IWUSR, 0, 0, µcode_fops, NULL); - if (!devfs_handle) { - printk(KERN_ERR "microcode: can't create /dev/cpu/microcode\n"); - return -ENOMEM; - } - /* XXX assume no hotplug CPUs so smp_num_cpus does not change */ - mc_fsize = smp_num_cpus * sizeof(struct microcode); - printk(KERN_INFO "P6 Microcode Update Driver v%s registered\n", MICROCODE_VERSION); + int error = 0; + + if (misc_register(µcode_dev) < 0) { + printk(KERN_WARNING + "microcode: can't misc_register on minor=%d\n", + MICROCODE_MINOR); + error = 1; + } + devfs_handle = devfs_register(NULL, "cpu/microcode", 0, + DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR, + 0, 0, µcode_fops, NULL); + if (devfs_handle == NULL && error) { + printk(KERN_ERR "microcode: failed to devfs_register()\n"); + return -EINVAL; + } + printk(KERN_INFO "P6 Microcode Update Driver v%s registered\n", + MICROCODE_VERSION); return 0; } static void __exit microcode_exit(void) { + misc_deregister(µcode_dev); devfs_unregister(devfs_handle); if (mc_applied) kfree(mc_applied); - printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n", MICROCODE_VERSION); + printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n", + MICROCODE_VERSION); } module_init(microcode_init); @@ -114,13 +139,6 @@ if (test_and_set_bit(MICROCODE_IS_OPEN, µcode_status)) return -EBUSY; - if ((file->f_flags & O_ACCMODE) == O_WRONLY && mc_applied) { - devfs_set_file_size(devfs_handle, 0); - memset(mc_applied, 0, mc_fsize); - kfree(mc_applied); - mc_applied = NULL; - } - MOD_INC_USE_COUNT; return 0; } @@ -132,7 +150,7 @@ return 0; } -/* a pointer to 'struct update_req' is passed to the IPI hanlder = do_update_one() +/* a pointer to 'struct update_req' is passed to the IPI handler = do_update_one() * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode */ @@ -167,12 +185,14 @@ struct cpuinfo_x86 *c = cpu_data + cpu_num; struct update_req *req = (struct update_req *)arg + cpu_num; unsigned int pf = 0, val[2], rev, sig; - int i; + int i,found=0; req->err = 1; /* be pessimistic */ - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6) + if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6){ + printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num ); return; + } sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8); @@ -186,6 +206,8 @@ if (microcode[i].sig == sig && microcode[i].pf == pf && microcode[i].ldrver == 1 && microcode[i].hdrver == 1) { + found=1; + rdmsr(0x8B, val[0], rev); if (microcode[i].rev <= rev) { printk(KERN_ERR @@ -205,7 +227,7 @@ } wrmsr(0x79, (unsigned int)(m->bits), 0); - __asm__ __volatile__ ("cpuid"); + __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx", "cc"); rdmsr(0x8B, val[0], val[1]); req->err = 0; @@ -216,6 +238,9 @@ } break; } + + if(!found) + printk(KERN_ERR "microcode: found no data for CPU%d (sig=%x, pflags=%d)\n", cpu_num, sig, pf); } static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos) @@ -240,7 +265,8 @@ return -EINVAL; } if (!mc_applied) { - mc_applied = kmalloc(mc_fsize, GFP_KERNEL); + mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode), + GFP_KERNEL); if (!mc_applied) { printk(KERN_ERR "microcode: out of memory for saved microcode\n"); return -ENOMEM; @@ -257,17 +283,45 @@ } if (copy_from_user(microcode, buf, len)) { ret = -EFAULT; - goto out_vfree; + goto out_fsize; } if(do_microcode_update()) { ret = -EIO; - goto out_vfree; + goto out_fsize; + } else { + mc_fsize = smp_num_cpus * sizeof(struct microcode); + ret = (ssize_t)len; } +out_fsize: devfs_set_file_size(devfs_handle, mc_fsize); - ret = (ssize_t)len; -out_vfree: vfree(microcode); out_unlock: unlock_kernel(); return ret; +} + +static int microcode_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch(cmd) { + case MICROCODE_IOCFREE: + if (mc_applied) { + devfs_set_file_size(devfs_handle, 0); + memset(mc_applied, 0, mc_fsize); + kfree(mc_applied); + mc_applied = NULL; + printk(KERN_WARNING + "microcode: freed %d bytes\n", mc_fsize); + mc_fsize = 0; + return 0; + } + return -ENODATA; + + default: + printk(KERN_ERR "microcode: unknown ioctl cmd=%d\n", + cmd); + return -EINVAL; + } + /* NOT REACHED */ + return -EINVAL; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/msr.c linux.ac/arch/i386/kernel/msr.c --- linux.vanilla/arch/i386/kernel/msr.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/msr.c Wed May 31 11:35:48 2000 @@ -40,44 +40,47 @@ #include #include +/* Note: "err" is handled in a funny way below. Otherwise one version + of gcc or another breaks. */ + extern inline int wrmsr_eio(u32 reg, u32 eax, u32 edx) { - int err = 0; + int err; asm volatile( "1: wrmsr\n" "2:\n" ".section .fixup,\"ax\"\n" "3: movl %4,%0\n" - " jmp 1b\n" + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b,3b\n" ".previous" - : "+r" (err) - : "a" (eax), "d" (edx), "c" (reg), "i" (-EIO)); + : "=&bDS" (err) + : "a" (eax), "d" (edx), "c" (reg), "i" (-EIO), "0" (0)); return err; } extern inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx) { - int err = 0; + int err; asm volatile( "1: rdmsr\n" "2:\n" ".section .fixup,\"ax\"\n" "3: movl %4,%0\n" - " jmp 1b\n" + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b,3b\n" ".previous" - : "+r" (err), "=a" (*eax), "=d" (*eax) - : "c" (reg), "i" (-EIO)); + : "=&bDS" (err), "=a" (*eax), "=d" (*edx) + : "c" (reg), "i" (-EIO), "0" (0)); return err; } @@ -96,7 +99,7 @@ struct msr_command *cmd = (struct msr_command *) cmd_block; if ( cmd->cpu == smp_processor_id() ) - cmd->err = wrmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); + cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); } static void msr_smp_rdmsr(void *cmd_block) @@ -119,7 +122,7 @@ cmd.data[0] = eax; cmd.data[1] = edx; - smp_call_function(msr_smp_wrmsr, (void *)cmd, 1, 1); + smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); return cmd.err; } } @@ -134,7 +137,7 @@ cmd.cpu = cpu; cmd.reg = reg; - smp_call_function(msr_smp_rdmsr, (void *)cmd, 1, 1); + smp_call_function(msr_smp_rdmsr, &cmd, 1, 1); *eax = cmd.data[0]; *edx = cmd.data[1]; @@ -224,10 +227,12 @@ static int msr_open(struct inode *inode, struct file *file) { int cpu = MINOR(file->f_dentry->d_inode->i_rdev); + struct cpuinfo_x86 *c = &(cpu_data)[cpu]; - if ( !(cpu_online_map & (1UL << cpu)) || - !((cpu_data)[cpu].x86_capability & X86_FEATURE_MSR) ) - return -ENXIO; /* No such CPU */ + if ( !(cpu_online_map & (1UL << cpu)) ) + return -ENXIO; /* No such CPU */ + if ( !(c->x86_capability & X86_FEATURE_MSR) ) + return -EIO; /* MSR not supported */ MOD_INC_USE_COUNT; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/pci-i386.c linux.ac/arch/i386/kernel/pci-i386.c --- linux.vanilla/arch/i386/kernel/pci-i386.c Thu May 25 17:38:24 2000 +++ linux.ac/arch/i386/kernel/pci-i386.c Sun Jun 4 21:40:00 2000 @@ -106,6 +106,7 @@ reg = PCI_BASE_ADDRESS_0 + 4*resource; } else if (resource == PCI_ROM_RESOURCE) { res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; reg = dev->rom_base_reg; } else { /* Somebody might have asked allocation of a non-standard resource */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/process.c linux.ac/arch/i386/kernel/process.c --- linux.vanilla/arch/i386/kernel/process.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/process.c Sat Jun 10 21:56:01 2000 @@ -2,8 +2,9 @@ * linux/arch/i386/kernel/process.c * * Copyright (C) 1995 Linus Torvalds - * Pentium III code by Ingo Molnar with changes and support for - * OS exception support by Goutham Rao + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 */ /* @@ -471,94 +472,6 @@ return; } -#ifdef CONFIG_X86_FX - -int i387_hard_to_user ( struct _fpstate * user, - struct i387_hard_struct * hard) -{ - int i, err = 0; - short *tmp, *tmp2; - long *ltmp1, *ltmp2; - - err |= put_user(hard->cwd, &user->cw); - err |= put_user(hard->swd, &user->sw); - err |= put_user(fputag_KNIto387(hard->twd), &user->tag); - err |= put_user(hard->fip, &user->ipoff); - err |= put_user(hard->fcs, &user->cssel); - err |= put_user(hard->fdp, &user->dataoff); - err |= put_user(hard->fds, &user->datasel); - err |= put_user(hard->mxcsr, &user->mxcsr); - - tmp = (short *)&user->_st; - tmp2 = (short *)&hard->st_space; - - /* - * Transform the two layouts: - * (we do not mix 32-bit access with 16-bit access because - * thats suboptimal on PPros) - */ - for (i = 0; i < 8; i++) - { - err |= put_user(*tmp2, tmp); tmp++; tmp2++; - err |= put_user(*tmp2, tmp); tmp++; tmp2++; - err |= put_user(*tmp2, tmp); tmp++; tmp2++; - err |= put_user(*tmp2, tmp); tmp++; tmp2++; - err |= put_user(*tmp2, tmp); tmp++; tmp2 += 3; - } - - ltmp1 = (unsigned long *)&(user->_xmm[0]); - ltmp2 = (unsigned long *)&(hard->xmm_space[0]); - for(i = 0; i < 88; i++) - { - err |= put_user(*ltmp2, ltmp1); - ltmp1++; ltmp2++; - } - - return err; -} - -int i387_user_to_hard (struct i387_hard_struct * hard, - struct _fpstate * user) -{ - int i, err = 0; - short *tmp, *tmp2; - long *ltmp1, *ltmp2; - - err |= get_user(hard->cwd, &user->cw); - err |= get_user(hard->swd, &user->sw); - err |= get_user(hard->twd, &user->tag); - hard->twd = fputag_387toKNI(hard->twd); - err |= get_user(hard->fip, &user->ipoff); - err |= get_user(hard->fcs, &user->cssel); - err |= get_user(hard->fdp, &user->dataoff); - err |= get_user(hard->fds, &user->datasel); - err |= get_user(hard->mxcsr, &user->mxcsr); - - tmp2 = (short *)&hard->st_space; - tmp = (short *)&user->_st; - - for (i = 0; i < 8; i++) - { - err |= get_user(*tmp2, tmp); tmp++; tmp2++; - err |= get_user(*tmp2, tmp); tmp++; tmp2++; - err |= get_user(*tmp2, tmp); tmp++; tmp2++; - err |= get_user(*tmp2, tmp); tmp++; tmp2++; - err |= get_user(*tmp2, tmp); tmp++; tmp2 += 3; - } - - ltmp1 = (unsigned long *)(&user->_xmm[0]); - ltmp2 = (unsigned long *)(&hard->xmm_space[0]); - for(i = 0; i < (88); i++) - { - err |= get_user(*ltmp2, ltmp1); - ltmp2++; ltmp1++; - } - - return err; -} - -#endif - /* * Save a segment. */ @@ -596,11 +509,26 @@ { int fpvalid; struct task_struct *tsk = current; - +#ifdef CONFIG_X86_FXSR + unsigned short *to; + unsigned short *from; + int i; +#endif fpvalid = tsk->used_math; if (fpvalid) { unlazy_fpu(tsk); - memcpy(fpu,&tsk->thread.i387.hard,sizeof(*fpu)); +#ifdef CONFIG_X86_FXSR + memcpy(fpu, &tsk->thread.i387.hard, 7 * sizeof(long)); + + to = (unsigned short *)&fpu->st_space[0]; + from = (unsigned short *)&tsk->thread.i387.hard.st_space[0]; + for (i = 0; i < 8; i++, to += 5, from += 8) { + memcpy(to, from, 5 * sizeof(unsigned short)); + } +#else + memcpy(fpu, &tsk->thread.i387.hard, + sizeof(struct user_i387_struct)); +#endif } return fpvalid; @@ -659,8 +587,8 @@ /* * switch_to(x,yn) should switch tasks from x to y. * - * We fsave/fwait so that an exception goes off at the right time - * (as a call from the fsave or fwait in effect) rather than to + * We f*save/fwait so that an exception goes off at the right time + * (as a call from the f*save or fwait in effect) rather than to * the wrong process. Lazy FP saving no longer makes any sense * with modern CPU's, and this simplifies a lot of things (SMP * and UP become the same). diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/ptrace.c linux.ac/arch/i386/kernel/ptrace.c --- linux.vanilla/arch/i386/kernel/ptrace.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/ptrace.c Sat Jun 10 21:56:01 2000 @@ -1,7 +1,9 @@ /* ptrace.c */ /* By Ross Biro 1/23/92 */ -/* FXSAVE/FXRSTOR support by Ingo Molnar and modifications by Goutham Rao */ -/* edited by Linus Torvalds */ +/* + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 + */ #include /* for CONFIG_MATH_EMULATION */ #include @@ -131,6 +133,54 @@ return retval; } +static inline int save_i387_user(struct user_i387_struct *buf, + struct i387_hard_struct *hard) +{ +#ifdef CONFIG_X86_FXSR + unsigned short *to; + unsigned short *from; + int i; + + if (__copy_to_user(buf, hard, 7 * sizeof(long))) + return 1; + + to = (unsigned short *)&buf->st_space[0]; + from = (unsigned short *)&hard->st_space[0]; + for (i = 0; i < 8; i++, to += 5, from += 8) { + if (__copy_to_user(to, from, 5 * sizeof(unsigned short))) + return 1; + } +#else + if (__copy_to_user(buf, hard, sizeof(struct user_i387_struct))) + return 1; +#endif + return 0; +} + +static inline int restore_i387_user(struct i387_hard_struct *hard, + struct user_i387_struct *buf) +{ +#ifdef CONFIG_X86_FXSR + unsigned short *to; + unsigned short *from; + int i; + + if (__copy_from_user(hard, buf, 7 * sizeof(long))) + return 1; + + to = (unsigned short *)&hard->st_space[0]; + from = (unsigned short *)&buf->st_space[0]; + for (i = 0; i < 8; i++, to += 8, from += 5) { + if (__copy_from_user(to, from, 5 * sizeof(unsigned short))) + return 1; + } +#else + if (__copy_from_user(hard, buf, sizeof(struct user_i387_struct))) + return 1; +#endif + return 0; +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -399,14 +449,14 @@ ret = 0; if ( !child->used_math ) { /* Simulate an empty FPU. */ - i387_set_cwd(child->thread.i387.hard, 0x037f); - i387_set_swd(child->thread.i387.hard, 0x0000); - i387_set_twd(child->thread.i387.hard, 0xffff); - } + child->thread.i387.hard.cwd = 0xffff037f; + child->thread.i387.hard.swd = 0xffff0000; + child->thread.i387.hard.twd = 0xffffffff; + } #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - i387_hard_to_user((struct _fpstate *)data, &child->thread.i387.hard); + save_i387_user((struct user_i387_struct *)data, &child->thread.i387.hard); #ifdef CONFIG_MATH_EMULATION } else { save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); @@ -424,13 +474,58 @@ #ifdef CONFIG_MATH_EMULATION if ( boot_cpu_data.hard_math ) { #endif - i387_user_to_hard(&child->thread.i387.hard,(struct _fpstate *)data); + restore_i387_user(&child->thread.i387.hard, (struct user_i387_struct *)data); #ifdef CONFIG_MATH_EMULATION } else { restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); } #endif ret = 0; + break; + } + + case PTRACE_GETXFPREGS: { /* Get the child extended FPU state. */ +#ifdef CONFIG_X86_FXSR + if (!access_ok(VERIFY_WRITE, (unsigned *)data, + sizeof(struct user_xfpregs_struct))) { + ret = -EIO; + break; + } + ret = 0; + if ( !child->used_math ) { + /* Simulate an empty FPU. */ + child->thread.i387.hard.cwd = 0xffff037f; + child->thread.i387.hard.swd = 0xffff0000; + child->thread.i387.hard.twd = 0xffffffff; + } + printk("PTRACE_GETXFPREGS: copying %d bytes from %p to %p\n", + sizeof(struct user_xfpregs_struct), + &child->thread.i387.hard, data); + __copy_to_user((void *)data, &child->thread.i387.hard, + sizeof(struct user_xfpregs_struct)); +#else + ret = -EIO; +#endif + break; + } + + case PTRACE_SETXFPREGS: { /* Set the child extended FPU state. */ +#ifdef CONFIG_X86_FXSR + if (!access_ok(VERIFY_READ, (unsigned *)data, + sizeof(struct user_xfpregs_struct))) { + ret = -EIO; + break; + } + child->used_math = 1; + printk("PTRACE_SETXFPREGS: copying %d bytes from %p to %p\n", + sizeof(struct user_xfpregs_struct), + data, &child->thread.i387.hard); + __copy_from_user(&child->thread.i387.hard, (void *)data, + sizeof(struct user_xfpregs_struct)); + ret = 0; +#else + ret = -EIO; +#endif break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/setup.c linux.ac/arch/i386/kernel/setup.c --- linux.vanilla/arch/i386/kernel/setup.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/setup.c Fri Jun 9 20:51:21 2000 @@ -40,6 +40,13 @@ * and a few other clean ups. * Dave Jones , April 2000 * Pentium-III code by Ingo Molnar and modifications by Goutham Rao + * Updated to: + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 + * + * Added proper Cascades CPU and L2 cache detection for Cascades + * and 8-way type cache happy bunch from Intel:^) + * Dragan Stancevic , May 2000 * */ @@ -528,6 +535,7 @@ else { start_at = HIGH_MEMORY; mem_size -= HIGH_MEMORY; + usermem=0; } add_memory_region(start_at, mem_size, E820_RAM); } @@ -801,20 +809,6 @@ conswitchp = &dummy_con; #endif #endif -#ifdef CONFIG_X86_FX - if (boot_cpu_data.x86_capability & X86_FEATURE_FXSR) - { - printk("Enabling extended fast FPU save and restore ... "); - set_in_cr4(X86_CR4_OSFXSR); - printk("done.\n"); - } - if (boot_cpu_data.x86_capability & X86_FEATURE_XMM) - { - printk("Enabling KNI unmasked exception support ... "); - set_in_cr4(X86_CR4_OSXMMEXCPT); - printk("done.\n"); - } -#endif } static int __init get_model_name(struct cpuinfo_x86 *c) @@ -1337,8 +1331,8 @@ { X86_VENDOR_INTEL, 6, { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", NULL, "Pentium II (Deschutes)", "Mobile Pentium II", - "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL, NULL, - NULL, NULL, NULL, NULL }}, + "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL, + "Pentium III (Cascades)", NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 4, { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", @@ -1367,6 +1361,28 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, }; +/* + * Detect a NexGen CPU running without BIOS hypercode new enough + * to have CPUID. (Thanks to Herbert Oppmann) + */ + +static int deep_magic_nexgen_probe(void) +{ + int ret; + + __asm__ __volatile__ ( + " movw $0x5555, %%ax\n" + " xorw %%dx,%%dx\n" + " movw $2, %%cx\n" + " divw %%cx\n" + " movl $0, %%eax\n" + " jnz 1f\n" + " movl $1, %%eax\n" + "1:\n" + : "=a" (ret) : : "cx", "dx" ); + return ret; +} + void __init identify_cpu(struct cpuinfo_x86 *c) { int i=0; @@ -1377,21 +1393,20 @@ get_cpu_vendor(c); - /* It should be possible for the user to override this. */ - if(c->x86_capability&(1<<18)) { - /* Disable processor serial number */ - unsigned long lo,hi; - rdmsr(0x119,lo,hi); - lo |= 0x200000; - wrmsr(0x119,lo,hi); - printk(KERN_INFO "CPU serial number disabled.\n"); - } switch (c->x86_vendor) { case X86_VENDOR_UNKNOWN: if (c->cpuid_level < 0) + { + /* It may be a nexgen with cpuid disabled.. */ + if(deep_magic_nexgen_probe()) + { + strcpy(c->x86_model_id, "Nx586"); + c->x86_vendor = X86_VENDOR_NEXGEN; + } return; + } break; case X86_VENDOR_CYRIX: @@ -1408,6 +1423,14 @@ return; case X86_VENDOR_INTEL: + if(c->x86_capability&(1<<18)) { + /* Disable processor serial number */ + unsigned long lo,hi; + rdmsr(0x119,lo,hi); + lo |= 0x200000; + wrmsr(0x119,lo,hi); + printk(KERN_INFO "CPU serial number disabled.\n"); + } if (c->cpuid_level > 1) { /* supports eax=2 call */ int edx, dummy; @@ -1422,24 +1445,26 @@ c->x86_cache_size = 0; break; - case 0x41: + case 0x41: /* 4-way 128 */ c->x86_cache_size = 128; break; - case 0x42: - case 0x82: /*Detect 256-Kbyte cache on Coppermine*/ + case 0x42: /* 4-way 256 */ + case 0x82: /* 8-way 256 */ c->x86_cache_size = 256; break; - case 0x43: + case 0x43: /* 4-way 512 */ c->x86_cache_size = 512; break; - case 0x44: + case 0x44: /* 4-way 1024 */ + case 0x84: /* 8-way 1024 */ c->x86_cache_size = 1024; break; - case 0x45: + case 0x45: /* 4-way 2048 */ + case 0x85: /* 8-way 2048 */ c->x86_cache_size = 2048; break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/signal.c linux.ac/arch/i386/kernel/signal.c --- linux.vanilla/arch/i386/kernel/signal.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/signal.c Sat Jun 10 21:56:01 2000 @@ -4,8 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson - * Pentium III support by Ingo Molnar, modifications and OS Exception support - * by Goutham Rao + * 2000-05-25 Pentium III FXSR, SSE support by Gareth Hughes */ #include @@ -187,12 +186,36 @@ char retcode[8]; }; - static inline int restore_i387_hard(struct _fpstate *buf) { struct task_struct *tsk = current; +#ifdef CONFIG_X86_FXSR + struct _fpreg *from; + struct _fpxreg *to; + int i; +#endif clear_fpu(tsk); - return i387_user_to_hard(&tsk->thread.i387.hard, buf); + +#ifdef CONFIG_X86_FXSR + if (__copy_from_user(&tsk->thread.i387.hard, buf, 7 * sizeof(long))) + return 1; + + from = &buf->_st[0]; + to = (struct _fpxreg *) &tsk->thread.i387.hard.st_space[0]; + for (i = 0; i < 8; i++, to++, from++) { + if (__copy_from_user(to, from, sizeof(*from))) + return 1; + } + + if (__copy_from_user(&tsk->thread.i387.hard.fxsr_space[0], + &buf->_fxsr_env[0], X86_FXSR_SIZE)) + return 1; +#else + if (__copy_from_user(&tsk->thread.i387.hard, buf, + sizeof(struct i387_hard_struct))) + return 1; +#endif + return 0; } static inline int restore_i387(struct _fpstate *buf) @@ -343,11 +366,39 @@ static inline int save_i387_hard(struct _fpstate * buf) { struct task_struct *tsk = current; - +#ifdef CONFIG_X86_FXSR + struct _fpreg *to; + struct _fpxreg *from; + int i; + int err = 0; +#endif unlazy_fpu(tsk); tsk->thread.i387.hard.status = tsk->thread.i387.hard.swd; - if (i387_hard_to_user(buf, &tsk->thread.i387.hard)) + +#ifdef CONFIG_X86_FXSR + if (__copy_to_user(buf, &tsk->thread.i387.hard, 7 * sizeof(long))) return -1; + + to = &buf->_st[0]; + from = (struct _fpxreg *) &tsk->thread.i387.hard.st_space[0]; + for (i = 0; i < 8; i++, to++, from++) { + if (__copy_to_user(to, from, sizeof(*to))) + return -1; + } + err |= __put_user(tsk->thread.i387.hard.swd & 0xffff, &buf->status); + err |= __put_user(X86_FXSR_MAGIC, &buf->magic); + if (err) + return -1; + + if (__copy_to_user(&buf->_fxsr_env[0], + &tsk->thread.i387.hard.fxsr_space[0], + X86_FXSR_SIZE)) + return -1; +#else + if (__copy_to_user(buf, &tsk->thread.i387.hard, + sizeof(struct i387_hard_struct))) + return -1; +#endif return 1; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/traps.c linux.ac/arch/i386/kernel/traps.c --- linux.vanilla/arch/i386/kernel/traps.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/i386/kernel/traps.c Tue May 30 16:47:56 2000 @@ -2,12 +2,14 @@ * linux/arch/i386/traps.c * * Copyright (C) 1991, 1992 Linus Torvalds - * FXSAVE/FXRSTOR support by Ingo Molnar, OS exception support by Goutham Rao + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 */ /* * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'asm.s'. + * state in 'entry.S'. */ #include #include @@ -136,8 +138,6 @@ unlock_kernel(); \ } -void page_exception(void); - asmlinkage void divide_error(void); asmlinkage void debug(void); asmlinkage void nmi(void); @@ -154,10 +154,12 @@ asmlinkage void general_protection(void); asmlinkage void page_fault(void); asmlinkage void coprocessor_error(void); +#ifdef CONFIG_X86_XMM +asmlinkage void simd_coprocessor_error(void); +#endif asmlinkage void reserved(void); asmlinkage void alignment_check(void); asmlinkage void spurious_interrupt_bug(void); -asmlinkage void xmm_fault(void); int kstack_depth_to_print = 24; @@ -320,7 +322,6 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, current, BUS_ADRALN, get_cr2()) DO_ERROR(18, SIGSEGV, "reserved", reserved, current) -DO_VM86_ERROR(19, SIGFPE, "XMM fault", xmm_fault, current) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { @@ -588,11 +589,10 @@ siginfo_t info; /* - * Save the info for the exception handler - * (this will also clear the error) + * Save the info for the exception handler and clear the error */ task = current; - save_fpu(task); + save_init_fpu(task); task->thread.trap_no = 16; task->thread.error_code = 0; info.si_signo = SIGFPE; @@ -643,6 +643,63 @@ math_error((void *)regs->eip); } +#ifdef CONFIG_X86_XMM +void simd_math_error(void *eip) +{ + struct task_struct * task; + siginfo_t info; + + /* + * Save the info for the exception handler and clear the error + */ + task = current; + save_init_fpu(task); + set_fpu_mxcsr(XMM_DEFAULT_MXCSR); + task->thread.trap_no = 19; + task->thread.error_code = 0; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_code = __SI_FAULT; + info.si_addr = eip; + /* + * The SIMD FPU exceptions are handled a little differently, as there + * is only a single status/control register. Thus, to determine which + * unmasked exception was caught we must mask the exception mask bits + * at 0x1f80, and then use these to mask the exception bits at 0x3f. + */ + switch (~((task->thread.i387.hard.mxcsr & 0x1f80) >> 7) & + (task->thread.i387.hard.mxcsr & 0x3f)) { + case 0x000: + default: + break; + case 0x001: /* Invalid Op */ + info.si_code = FPE_FLTINV; + break; + case 0x002: /* Denormalize */ + case 0x010: /* Underflow */ + info.si_code = FPE_FLTUND; + break; + case 0x004: /* Zero Divide */ + info.si_code = FPE_FLTDIV; + break; + case 0x008: /* Overflow */ + info.si_code = FPE_FLTOVF; + break; + case 0x020: /* Precision */ + info.si_code = FPE_FLTRES; + break; + } + force_sig_info(SIGFPE, &info, task); +} + +asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs, + long error_code) +{ + ignore_irq13 = 1; + simd_math_error((void *)regs->eip); +} +#endif /* CONFIG_X86_XMM */ + asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, long error_code) { @@ -661,19 +718,18 @@ */ asmlinkage void math_state_restore(struct pt_regs regs) { - __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ + __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ - if(current->used_math) - i387_restore_hard(current->thread.i387); - else - { + if (current->used_math) { + restore_fpu(current); + } else { /* * Our first FPU usage, clean the chip. */ __asm__("fninit"); current->used_math = 1; } - current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */ + current->flags |= PF_USEDFPU; /* So we fnsave on switch_to() */ } #ifndef CONFIG_MATH_EMULATION @@ -907,8 +963,10 @@ set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(16,&coprocessor_error); set_trap_gate(17,&alignment_check); - set_trap_gate(19,&xmm_fault); - +#ifdef CONFIG_X86_XMM + if (cpu_has_xmm) + set_trap_gate(19,&simd_coprocessor_error); +#endif set_system_gate(SYSCALL_VECTOR,&system_call); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/math-emu/get_address.c linux.ac/arch/i386/math-emu/get_address.c --- linux.vanilla/arch/i386/math-emu/get_address.c Thu May 25 17:38:23 2000 +++ linux.ac/arch/i386/math-emu/get_address.c Tue May 30 14:36:16 2000 @@ -155,6 +155,7 @@ { struct desc_struct descriptor; unsigned long base_address, limit, address, seg_top; + unsigned short selector; segment--; @@ -174,12 +175,15 @@ case PREFIX_FS_-1: /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register in the assembler statement. */ - __asm__("mov %%fs,%0":"=r" ((unsigned short)addr->selector)); + + __asm__("mov %%fs,%0":"=r" (selector)); + addr->selector = selector; break; case PREFIX_GS_-1: /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register in the assembler statement. */ - __asm__("mov %%gs,%0":"=r" ((unsigned short)addr->selector)); + __asm__("mov %%gs,%0":"=r" (selector)); + addr->selector = selector; break; default: addr->selector = PM_REG_(segment); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ia64/defconfig linux.ac/arch/ia64/defconfig --- linux.vanilla/arch/ia64/defconfig Thu May 25 17:38:35 2000 +++ linux.ac/arch/ia64/defconfig Mon May 29 19:25:14 2000 @@ -59,10 +59,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/m68k/defconfig linux.ac/arch/m68k/defconfig --- linux.vanilla/arch/m68k/defconfig Thu May 25 17:38:33 2000 +++ linux.ac/arch/m68k/defconfig Mon May 29 19:25:14 2000 @@ -67,10 +67,6 @@ # CONFIG_AMIGA_Z2RAM is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips/defconfig linux.ac/arch/mips/defconfig --- linux.vanilla/arch/mips/defconfig Thu May 25 17:38:28 2000 +++ linux.ac/arch/mips/defconfig Mon May 29 19:25:14 2000 @@ -72,10 +72,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips/defconfig-decstation linux.ac/arch/mips/defconfig-decstation --- linux.vanilla/arch/mips/defconfig-decstation Thu May 25 17:38:29 2000 +++ linux.ac/arch/mips/defconfig-decstation Mon May 29 19:25:14 2000 @@ -70,10 +70,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips/defconfig-ip22 linux.ac/arch/mips/defconfig-ip22 --- linux.vanilla/arch/mips/defconfig-ip22 Thu May 25 17:38:29 2000 +++ linux.ac/arch/mips/defconfig-ip22 Mon May 29 19:25:15 2000 @@ -72,10 +72,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips64/defconfig linux.ac/arch/mips64/defconfig --- linux.vanilla/arch/mips64/defconfig Thu May 25 17:38:35 2000 +++ linux.ac/arch/mips64/defconfig Mon May 29 19:25:15 2000 @@ -66,10 +66,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips64/defconfig-ip22 linux.ac/arch/mips64/defconfig-ip22 --- linux.vanilla/arch/mips64/defconfig-ip22 Thu May 25 17:38:35 2000 +++ linux.ac/arch/mips64/defconfig-ip22 Mon May 29 19:25:15 2000 @@ -57,10 +57,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/mips64/defconfig-ip27 linux.ac/arch/mips64/defconfig-ip27 --- linux.vanilla/arch/mips64/defconfig-ip27 Thu May 25 17:38:35 2000 +++ linux.ac/arch/mips64/defconfig-ip27 Mon May 29 19:25:15 2000 @@ -66,10 +66,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/8xx_io/Config.in linux.ac/arch/ppc/8xx_io/Config.in --- linux.vanilla/arch/ppc/8xx_io/Config.in Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/8xx_io/Config.in Sun Jun 4 21:10:56 2000 @@ -12,5 +12,7 @@ fi fi bool '860T FEC Ethernet' CONFIG_FEC_ENET + bool 'Use SMC2 for UART' CONFIG_8xxSMC2 + bool 'Enable SCC2 and SCC3 for UART' CONFIG_8xxSCC endmenu fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/8xx_io/commproc.c linux.ac/arch/ppc/8xx_io/commproc.c --- linux.vanilla/arch/ppc/8xx_io/commproc.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/8xx_io/commproc.c Sun Jun 4 21:10:56 2000 @@ -94,9 +94,9 @@ */ host_buffer = host_page_addr; /* Host virtual page address */ host_end = host_page_addr + PAGE_SIZE; - pte = find_pte(&init_mm, host_page_addr); + pte = va_to_pte(&init_mm, host_page_addr); pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(current->mm->mmap, host_buffer); + flush_tlb_page(init_mm.mmap, host_buffer); /* Tell everyone where the comm processor resides. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/8xx_io/enet.c linux.ac/arch/ppc/8xx_io/enet.c --- linux.vanilla/arch/ppc/8xx_io/enet.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/8xx_io/enet.c Sun Jun 4 21:10:56 2000 @@ -402,6 +402,7 @@ * full. */ if (cep->tx_full) { + cep->tx_full = 0; if (netif_queue_stopped(dev)) netif_wake_queue(dev); } @@ -835,7 +836,7 @@ /* Make it uncached. */ - pte = find_pte(&init_mm, mem_addr); + pte = va_to_pte(&init_mm, mem_addr); pte_val(*pte) |= _PAGE_NO_CACHE; flush_tlb_page(init_mm.mmap, mem_addr); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/8xx_io/fec.c linux.ac/arch/ppc/8xx_io/fec.c --- linux.vanilla/arch/ppc/8xx_io/fec.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/8xx_io/fec.c Sat Jun 10 21:59:27 2000 @@ -1,5 +1,5 @@ /* - * Fast Ethernet Controller (FECC) driver for Motorola MPC8xx. + * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx. * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) * * This version of the driver is specific to the FADS implementation, @@ -15,7 +15,17 @@ * will be much more memory efficient and will easily handle lots of * small packets. * + * Much better multiple PHY support by Magnus Damm. + * Copyright (c) 2000 Ericsson Radio Systems AB. + * */ + +/* List of PHYs we wish to support. +*/ +#define CONFIG_FEC_LXT970 +#define CONFIG_FEC_LXT971 +#define CONFIG_FEC_QS6612 + #include #include #include @@ -31,6 +41,10 @@ #include #include #include +#include +#ifdef CONFIG_FEC_PACKETHOOK +#include +#endif #include #include @@ -40,6 +54,24 @@ #include #include "commproc.h" +/* Forward declarations of some structures to support different PHYs +*/ + +typedef struct { + uint mii_data; + void (*funct)(uint mii_reg, struct net_device *dev); +} phy_cmd_t; + +typedef struct { + uint id; + char *name; + + const phy_cmd_t *config; + const phy_cmd_t *startup; + const phy_cmd_t *ack_int; + const phy_cmd_t *shutdown; +} phy_info_t; + /* The number of Tx and Rx buffers. These are allocated from the page * pool. The code may assume these are power of two, so it it best * to keep them that size. @@ -103,20 +135,51 @@ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ scc_t *sccp; struct net_device_stats stats; - char tx_full; - unsigned long lock; + uint tx_full; + spinlock_t lock; + + uint phy_id; + uint phy_id_done; + uint phy_status; + uint phy_speed; + phy_info_t *phy; + struct tq_struct phy_task; + + uint sequence_done; + + uint phy_addr; + + int link; + int old_link; + int full_duplex; + +#ifdef CONFIG_FEC_PACKETHOOK + unsigned long ph_lock; + fec_ph_func *ph_rxhandler; + fec_ph_func *ph_txhandler; + __u16 ph_proto; + volatile __u32 *ph_regaddr; + void *ph_priv; +#endif }; static int fec_enet_open(struct net_device *dev); static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int fec_enet_rx(struct net_device *dev); static void fec_enet_mii(struct net_device *dev); -static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); +static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); +#ifdef CONFIG_FEC_PACKETHOOK +static void fec_enet_tx(struct net_device *dev, __u32 regval); +static void fec_enet_rx(struct net_device *dev, __u32 regval); +#else +static void fec_enet_tx(struct net_device *dev); +static void fec_enet_rx(struct net_device *dev); +#endif static int fec_enet_close(struct net_device *dev); static struct net_device_stats *fec_enet_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); - -static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 }; +static void fec_restart(struct net_device *dev, int duplex); +static void fec_stop(struct net_device *dev); +static ushort my_enet_addr[3]; /* MII processing. We keep this as simple as possible. Requests are * placed on the list (if there is room). When the request is finished @@ -124,91 +187,133 @@ */ typedef struct mii_list { uint mii_regval; - void (*mii_func)(int val); + void (*mii_func)(uint val, struct net_device *dev); struct mii_list *mii_next; } mii_list_t; -#define NMII 10 +#define NMII 20 mii_list_t mii_cmds[NMII]; mii_list_t *mii_free; mii_list_t *mii_head; mii_list_t *mii_tail; -static int mii_queue(int request, void (*func)(int)); +static int mii_queue(struct net_device *dev, int request, + void (*func)(uint, struct net_device *)); /* Make MII read/write commands for the FEC. */ #define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) #define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ (VAL & 0xffff)) +#define mk_mii_end 0 -static int -fec_enet_open(struct net_device *dev) +/* Transmitter timeout. +*/ +#define TX_TIMEOUT (2*HZ) + +/* Register definitions for the PHY. +*/ + +#define MII_REG_CR 0 /* Control Register */ +#define MII_REG_SR 1 /* Status Register */ +#define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */ +#define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */ +#define MII_REG_ANAR 4 /* A-N Advertisement Register */ +#define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */ +#define MII_REG_ANER 6 /* A-N Expansion Register */ +#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */ +#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */ + +/* values for phy_status */ + +#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */ +#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */ +#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */ +#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */ +#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */ +#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */ +#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ + +#define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */ +#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */ +#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */ +#define PHY_STAT_SPMASK 0xf000 /* mask for speed */ +#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */ +#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */ +#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */ +#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ + +#ifdef CONFIG_FEC_PACKETHOOK +int +fec_register_ph(struct net_device *dev, fec_ph_func *rxfun, fec_ph_func *txfun, + __u16 proto, volatile __u32 *regaddr, void *priv) { + struct fec_enet_private *fep; + int retval = 0; - /* I should reset the ring buffers here, but I don't yet know - * a simple way to do that. - */ + fep = dev->priv; + + if (test_and_set_bit(0, (void*)&fep->ph_lock) != 0) { + /* Someone is messing with the packet hook */ + return -EAGAIN; + } + if (fep->ph_rxhandler != NULL || fep->ph_txhandler != NULL) { + retval = -EBUSY; + goto out; + } + fep->ph_rxhandler = rxfun; + fep->ph_txhandler = txfun; + fep->ph_proto = proto; + fep->ph_regaddr = regaddr; + fep->ph_priv = priv; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + out: + fep->ph_lock = 0; - return 0; /* Always succeed */ + return retval; } -static int -fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; - volatile cbd_t *bdp; - unsigned long flags; - /* Transmitter timeout, serious problems. */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 20) - return 1; - printk("%s: transmit timed out.\n", dev->name); - fep->stats.tx_errors++; -#ifndef final_version - { - int i; - cbd_t *bdp; - printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n", - fep->cur_tx, fep->tx_full ? " (full)" : "", - fep->cur_rx); - bdp = fep->tx_bd_base; - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%04x %04x %08x\n", - bdp->cbd_sc, - bdp->cbd_datlen, - bdp->cbd_bufaddr); - bdp = fep->rx_bd_base; - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%04x %04x %08x\n", - bdp->cbd_sc, - bdp->cbd_datlen, - bdp->cbd_bufaddr); - } -#endif +int +fec_unregister_ph(struct net_device *dev) +{ + struct fec_enet_private *fep; + int retval = 0; - dev->tbusy=0; - dev->trans_start = jiffies; + fep = dev->priv; - return 0; + if (test_and_set_bit(0, (void*)&fep->ph_lock) != 0) { + /* Someone is messing with the packet hook */ + return -EAGAIN; } - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } + fep->ph_rxhandler = fep->ph_txhandler = NULL; + fep->ph_proto = 0; + fep->ph_regaddr = NULL; + fep->ph_priv = NULL; + + fep->ph_lock = 0; + + return retval; +} + +EXPORT_SYMBOL(fec_register_ph); +EXPORT_SYMBOL(fec_unregister_ph); + +#endif /* CONFIG_FEC_PACKETHOOK */ + +static int +fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *fecp; + volatile cbd_t *bdp; - if (test_and_set_bit(0, (void*)&fep->lock) != 0) { - printk("%s: tx queue lock!.\n", dev->name); - /* don't clear dev->tbusy flag. */ + fep = dev->priv; + fecp = (volatile fec_t*)dev->base_addr; + + if (!fep->link) { + /* Link is down or autonegotiation is in progress. */ return 1; } @@ -221,7 +326,6 @@ * This should not happen, since dev->tbusy should be set. */ printk("%s: tx queue full!.\n", dev->name); - fep->lock = 0; return 1; } #endif @@ -245,38 +349,85 @@ /* Push the data cache so the CPM does not get stale memory * data. */ - flush_dcache_range(skb->data, skb->data + skb->len); + flush_dcache_range((unsigned long)skb->data, + (unsigned long)skb->data + skb->len); + + spin_lock_irq(&fep->lock); - /* Send it on its way. Tell CPM its ready, interrupt when done, + /* Send it on its way. Tell FEC its ready, interrupt when done, * its the last BD of the frame, and to put the CRC on the end. */ - save_flags(flags); - cli(); - bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); + bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR + | BD_ENET_TX_LAST | BD_ENET_TX_TC); dev->trans_start = jiffies; - (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_x_des_active = 0x01000000; + + /* Trigger transmission start */ + fecp->fec_x_des_active = 0x01000000; /* If this was the last BD in the ring, start at the beginning again. */ - if (bdp->cbd_sc & BD_ENET_TX_WRAP) + if (bdp->cbd_sc & BD_ENET_TX_WRAP) { bdp = fep->tx_bd_base; - else + } else { bdp++; + } - fep->lock = 0; if (bdp->cbd_sc & BD_ENET_TX_READY) - fep->tx_full = 1; - else - dev->tbusy=0; - restore_flags(flags); + netif_stop_queue(dev); fep->cur_tx = (cbd_t *)bdp; + spin_unlock_irq(&fep->lock); + return 0; } +static void +fec_timeout(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + printk("%s: transmit timed out.\n", dev->name); + fep->stats.tx_errors++; +#ifndef final_version + { + int i; + cbd_t *bdp; + + printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", + (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", + (unsigned long)fep->dirty_tx, + (unsigned long)fep->cur_rx); + + bdp = fep->tx_bd_base; + printk(" tx: %u buffers\n", TX_RING_SIZE); + for (i = 0 ; i < TX_RING_SIZE; i++) { + printk(" %08x: %04x %04x %08x\n", + (uint) bdp, + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + bdp++; + } + + bdp = fep->rx_bd_base; + printk(" rx: %lu buffers\n", RX_RING_SIZE); + for (i = 0 ; i < RX_RING_SIZE; i++) { + printk(" %08x: %04x %04x %08x\n", + (uint) bdp, + bdp->cbd_sc, + bdp->cbd_datlen, + bdp->cbd_bufaddr); + bdp++; + } + } +#endif + if (!fep->tx_full) + netif_wake_queue(dev); +} + /* The interrupt handler. * This is called from the MPC core interrupt. */ @@ -284,136 +435,177 @@ fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; - struct fec_enet_private *fep; - volatile cbd_t *bdp; - volatile fec_t *ep; + volatile fec_t *fecp; uint int_events; - int c=0; +#ifdef CONFIG_FEC_PACKETHOOK + struct fec_enet_private *fep = dev->priv; + __u32 regval; - fep = (struct fec_enet_private *)dev->priv; - ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); - if (dev->interrupt) - printk("%s: Re-entering the interrupt handler.\n", dev->name); - dev->interrupt = 1; + if (fep->ph_regaddr) regval = *fep->ph_regaddr; +#endif + + fecp = (volatile fec_t*)dev->base_addr; /* Get the interrupt events that caused us to be here. */ - while ((int_events = ep->fec_ievent) != 0) { - ep->fec_ievent = int_events; - if ((int_events & - (FEC_ENET_HBERR | FEC_ENET_BABR | - FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) - printk("FEC ERROR %x\n", int_events); - - /* Handle receive event in its own function. - */ - if (int_events & (FEC_ENET_RXF | FEC_ENET_RXB)) - fec_enet_rx(dev_id); - - /* Transmit OK, or non-fatal error. Update the buffer descriptors. - * FEC handles all errors, we just discover them as part of the - * transmit process. - */ - if (int_events & (FEC_ENET_TXF | FEC_ENET_TXB)) { - bdp = fep->dirty_tx; - while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) { -#if 1 - if (bdp==fep->cur_tx) - break; + while ((int_events = fecp->fec_ievent) != 0) { + fecp->fec_ievent = int_events; + if ((int_events & (FEC_ENET_HBERR | FEC_ENET_BABR | + FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) { + printk("FEC ERROR %x\n", int_events); + } + + /* Handle receive event in its own function. + */ + if (int_events & FEC_ENET_RXF) { +#ifdef CONFIG_FEC_PACKETHOOK + fec_enet_rx(dev, regval); +#else + fec_enet_rx(dev); +#endif + } + + /* Transmit OK, or non-fatal error. Update the buffer + descriptors. FEC handles all errors, we just discover + them as part of the transmit process. + */ + if (int_events & FEC_ENET_TXF) { +#ifdef CONFIG_FEC_PACKETHOOK + fec_enet_tx(dev, regval); +#else + fec_enet_tx(dev); #endif - if (++c>1) {/*we go here when an it has been lost*/}; + } + if (int_events & FEC_ENET_MII) { + fec_enet_mii(dev); + } + + } +} - if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ - fep->stats.tx_heartbeat_errors++; - if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ - fep->stats.tx_window_errors++; - if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ - fep->stats.tx_aborted_errors++; - if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ - fep->stats.tx_fifo_errors++; - if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ - fep->stats.tx_carrier_errors++; - fep->stats.tx_errors++; - - fep->stats.tx_packets++; - +static void +#ifdef CONFIG_FEC_PACKETHOOK +fec_enet_tx(struct net_device *dev, __u32 regval) +#else +fec_enet_tx(struct net_device *dev) +#endif +{ + struct fec_enet_private *fep; + volatile cbd_t *bdp; + struct sk_buff *skb; + + fep = dev->priv; + spin_lock(&fep->lock); + bdp = fep->dirty_tx; + + while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) { + if (bdp == fep->cur_tx && fep->tx_full == 0) break; + + skb = fep->tx_skbuff[fep->skb_dirty]; + /* Check for errors. */ + if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | + BD_ENET_TX_RL | BD_ENET_TX_UN | + BD_ENET_TX_CSL)) { + fep->stats.tx_errors++; + if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ + fep->stats.tx_heartbeat_errors++; + if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ + fep->stats.tx_window_errors++; + if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ + fep->stats.tx_aborted_errors++; + if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ + fep->stats.tx_fifo_errors++; + if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ + fep->stats.tx_carrier_errors++; + } else { +#ifdef CONFIG_FEC_PACKETHOOK + /* Packet hook ... */ + if (fep->ph_txhandler && + ((struct ethhdr *)skb->data)->h_proto + == fep->ph_proto) { + fep->ph_txhandler((__u8*)skb->data, skb->len, + regval, fep->ph_priv); + } +#endif + fep->stats.tx_packets++; + } + #ifndef final_version if (bdp->cbd_sc & BD_ENET_TX_READY) - printk("HEY! Enet xmit interrupt and TX_READY.\n"); + printk("HEY! Enet xmit interrupt and TX_READY.\n"); #endif /* Deferred means some collisions occurred during transmit, * but we eventually sent the packet OK. */ if (bdp->cbd_sc & BD_ENET_TX_DEF) - fep->stats.collisions++; + fep->stats.collisions++; /* Free the sk buffer associated with this last transmit. */ - dev_kfree_skb(fep->tx_skbuff[fep->skb_dirty]/*, FREE_WRITE*/); +#if 0 +printk("TXI: %x %x %x\n", bdp, skb, fep->skb_dirty); +#endif + dev_kfree_skb(skb/*, FREE_WRITE*/); + fep->tx_skbuff[fep->skb_dirty] = NULL; fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; /* Update pointer to next buffer descriptor to be transmitted. */ if (bdp->cbd_sc & BD_ENET_TX_WRAP) - bdp = fep->tx_bd_base; + bdp = fep->tx_bd_base; else - bdp++; + bdp++; /* Since we have freed up a buffer, the ring is no longer * full. */ - if (fep->tx_full && dev->tbusy) { - fep->tx_full = 0; - dev->tbusy = 0; - mark_bh(NET_BH); + if (fep->tx_full) { + fep->tx_full = 0; + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); } - - fep->dirty_tx = (cbd_t *)bdp; -#if 0 - if (bdp==fep->cur_tx) - break; +#ifdef CONFIG_FEC_PACKETHOOK + /* Re-read register. Not exactly guaranteed to be correct, + but... */ + if (fep->ph_regaddr) regval = *fep->ph_regaddr; #endif - }/*while (bdp->cbd_sc&BD_ENET_TX_READY)==0*/ - } /* if tx events */ - - if (int_events & FEC_ENET_MII) - fec_enet_mii(dev_id); - - } /* while any events */ - - dev->interrupt = 0; - - return; + } + fep->dirty_tx = (cbd_t *)bdp; + spin_unlock(&fep->lock); } + /* During a receive, the cur_rx points to the current incoming buffer. * When we update through the ring, if the next incoming buffer has * not been given to the system, we just set the empty indicator, * effectively tossing the packet. */ -static int +static void +#ifdef CONFIG_FEC_PACKETHOOK +fec_enet_rx(struct net_device *dev, __u32 regval) +#else fec_enet_rx(struct net_device *dev) +#endif { struct fec_enet_private *fep; + volatile fec_t *fecp; volatile cbd_t *bdp; struct sk_buff *skb; ushort pkt_len; - volatile fec_t *ep; + __u8 *data; - fep = (struct fec_enet_private *)dev->priv; - ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + fep = dev->priv; + fecp = (volatile fec_t*)dev->base_addr; /* First, grab all of the stats for the incoming packet. * These get messed up if we get called due to a busy condition. */ bdp = fep->cur_rx; -for (;;) { - if (bdp->cbd_sc & BD_ENET_RX_EMPTY) - break; - +while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { + #ifndef final_version /* Since we have allocated space to hold a complete frame, * the last indicator should be set. @@ -422,50 +614,77 @@ printk("FEC ENET: rcv is not +last\n"); #endif - /* Frame too long or too short. - */ - if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) - fep->stats.rx_length_errors++; - if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ - fep->stats.rx_frame_errors++; - if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ - fep->stats.rx_crc_errors++; - if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ - fep->stats.rx_crc_errors++; + /* Check for errors. */ + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | + BD_ENET_RX_CR | BD_ENET_RX_OV)) { + fep->stats.rx_errors++; + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { + /* Frame too long or too short. */ + fep->stats.rx_length_errors++; + } + if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ + fep->stats.rx_frame_errors++; + if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ + fep->stats.rx_crc_errors++; + if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ + fep->stats.rx_crc_errors++; + } /* Report late collisions as a frame error. * On this error, the BD is closed, but we don't know what we * have in the buffer. So, just drop this frame on the floor. */ if (bdp->cbd_sc & BD_ENET_RX_CL) { + fep->stats.rx_errors++; fep->stats.rx_frame_errors++; + goto rx_processing_done; } - else { - /* Process the incoming frame. - */ - fep->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; - fep->stats.rx_bytes += pkt_len; + /* Process the incoming frame. + */ + fep->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + fep->stats.rx_bytes += pkt_len; + data = (__u8*)__va(bdp->cbd_bufaddr); + +#ifdef CONFIG_FEC_PACKETHOOK + /* Packet hook ... */ + if (fep->ph_rxhandler) { + if (((struct ethhdr *)data)->h_proto == fep->ph_proto) { + switch (fep->ph_rxhandler(data, pkt_len, regval, + fep->ph_priv)) { + case 1: + goto rx_processing_done; + break; + case 0: + break; + default: + fep->stats.rx_errors++; + goto rx_processing_done; + } + } + } - /* This does 16 byte alignment, exactly what we need. - */ - skb = dev_alloc_skb(pkt_len); + /* If it wasn't filtered - copy it to an sk buffer. */ +#endif - if (skb == NULL) { - printk("%s: Memory squeeze, dropping packet.\n", dev->name); - fep->stats.rx_dropped++; - } - else { - skb->dev = dev; - skb_put(skb,pkt_len); /* Make room */ - eth_copy_and_sum(skb, - (unsigned char *)__va(bdp->cbd_bufaddr), - pkt_len, 0); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - } + /* This does 16 byte alignment, exactly what we need. + */ + skb = dev_alloc_skb(pkt_len); + + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + fep->stats.rx_dropped++; + } else { + skb->dev = dev; + skb_put(skb,pkt_len); /* Make room */ + eth_copy_and_sum(skb, + (unsigned char *)__va(bdp->cbd_bufaddr), + pkt_len, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); } + rx_processing_done: /* Clear the status flags for this buffer. */ @@ -487,9 +706,14 @@ * incoming frames. On a heavily loaded network, we should be * able to keep up at the expense of system resources. */ - ep->fec_r_des_active = 0x01000000; + fecp->fec_r_des_active = 0x01000000; #endif - } +#ifdef CONFIG_FEC_PACKETHOOK + /* Re-read register. Not exactly guaranteed to be correct, + but... */ + if (fep->ph_regaddr) regval = *fep->ph_regaddr; +#endif + } /* while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) */ fep->cur_rx = (cbd_t *)bdp; #if 0 @@ -500,12 +724,11 @@ * our way back to the interrupt return only to come right back * here. */ - ep->fec_r_des_active = 0x01000000; + fecp->fec_r_des_active = 0x01000000; #endif - - return 0; } + static void fec_enet_mii(struct net_device *dev) { @@ -524,7 +747,7 @@ } if (mip->mii_func != NULL) - (*(mip->mii_func))(mii_reg); + (*(mip->mii_func))(mii_reg, dev); mii_head = mip->mii_next; mip->mii_next = mii_free; @@ -535,12 +758,18 @@ } static int -mii_queue(int regval, void (*func)(int)) +mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *)) { + struct fec_enet_private *fep; unsigned long flags; mii_list_t *mip; int retval; + /* Add PHY address to register command. + */ + fep = dev->priv; + regval |= fep->phy_addr << 23; + retval = 0; save_flags(flags); @@ -569,199 +798,580 @@ return(retval); } -static void -mii_status(uint mii_reg) +static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c) { - if (((mii_reg >> 18) & 0x1f) == 1) { - /* status register. - */ - printk("fec: "); - if (mii_reg & 0x0004) - printk("link up"); - else - printk("link down"); + int k; - if (mii_reg & 0x0010) - printk(",remote fault"); - if (mii_reg & 0x0020) - printk(",auto complete"); - printk("\n"); - } - if (((mii_reg >> 18) & 0x1f) == 0x14) { - /* Extended chip status register. - */ - printk("fec: "); - if (mii_reg & 0x0800) - printk("100 Mbps"); - else - printk("10 Mbps"); + if(!c) + return; - if (mii_reg & 0x1000) - printk(", Full-Duplex\n"); - else - printk(", Half-Duplex\n"); - } - if (((mii_reg >> 18) & 0x1f) == 0x1f) { - printk("fec: %x\n", mii_reg); - } + for(k = 0; (c+k)->mii_data != mk_mii_end; k++) + mii_queue(dev, (c+k)->mii_data, (c+k)->funct); } -static void -mii_startup_cmds(void) +static void mii_parse_sr(uint mii_reg, struct net_device *dev) { + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); - /* Read status registers to clear any pending interrupt. - */ - mii_queue(mk_mii_read(1), mii_status); -#ifndef CONFIG_RPXCLASSIC - mii_queue(mk_mii_read(18), mii_status); + *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); - /* Read extended chip status register. - */ - mii_queue(mk_mii_read(0x14), mii_status); + if (mii_reg & 0x0004) + *s |= PHY_STAT_LINK; + if (mii_reg & 0x0010) + *s |= PHY_STAT_FAULT; + if (mii_reg & 0x0020) + *s |= PHY_STAT_ANC; +} - /* Enable Link status change interrupts. - */ - mii_queue(mk_mii_write(0x11, 0x0002), NULL); +static void mii_parse_cr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); -#ifdef CONFIG_FADS - /* FADS uses the TRSTE in the BCSR, which is kind of weird. - * This really controls the startup default configuration. - * Changing the state of TRSTE once powered up doesn't do - * anything, you have to whack the control register. - * This of course screws up any autoconfig that was done....... - */ - mii_queue(mk_mii_write(0, 0x1000), NULL); -#endif -#else - /* Experimenting with the QS6612 PHY....not done yet. - */ - mii_queue(mk_mii_read(31), mii_status); -#endif + *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP); + + if (mii_reg & 0x1000) + *s |= PHY_CONF_ANE; + if (mii_reg & 0x4000) + *s |= PHY_CONF_LOOP; } -/* This supports the mii_link interrupt below. - * We should get called three times. Once for register 1, once for - * register 18, and once for register 20. - */ -static uint mii_saved_reg1; +static void mii_parse_anar(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); -static void -mii_relink(uint mii_reg) + *s &= ~(PHY_CONF_SPMASK); + + if (mii_reg & 0x0020) + *s |= PHY_CONF_10HDX; + if (mii_reg & 0x0040) + *s |= PHY_CONF_10FDX; + if (mii_reg & 0x0080) + *s |= PHY_CONF_100HDX; + if (mii_reg & 0x00100) + *s |= PHY_CONF_100FDX; +} +#if 0 +static void mii_disp_reg(uint mii_reg, struct net_device *dev) { - if (((mii_reg >> 18) & 0x1f) == 1) { - /* Just save the status register and get out. - */ - mii_saved_reg1 = mii_reg; - return; - } - if (((mii_reg >> 18) & 0x1f) == 18) { - /* Not much here, but has to be read to clear the - * interrupt condition. - */ - if ((mii_reg & 0x8000) == 0) - printk("fec: re-link and no IRQ?\n"); - if ((mii_reg & 0x4000) == 0) - printk("fec: no PHY power?\n"); - } - if (((mii_reg >> 18) & 0x1f) == 20) { - /* Extended chip status register. - * OK, now we have it all, so figure out what is going on. - */ - printk("fec: "); - if (mii_saved_reg1 & 0x0004) - printk("link up"); - else - printk("link down"); + printk("reg %u = 0x%04x\n", (mii_reg >> 18) & 0x1f, mii_reg & 0xffff); +} +#endif - if (mii_saved_reg1 & 0x0010) - printk(", remote fault"); - if (mii_saved_reg1 & 0x0020) - printk(", auto complete"); +/* ------------------------------------------------------------------------- */ +/* The Level one LXT970 is used by many boards */ - if (mii_reg & 0x0800) - printk(", 100 Mbps"); - else - printk(", 10 Mbps"); +#ifdef CONFIG_FEC_LXT970 + +#define MII_LXT970_MIRROR 16 /* Mirror register */ +#define MII_LXT970_IER 17 /* Interrupt Enable Register */ +#define MII_LXT970_ISR 18 /* Interrupt Status Register */ +#define MII_LXT970_CONFIG 19 /* Configuration Register */ +#define MII_LXT970_CSR 20 /* Chip Status Register */ + +static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + *s &= ~(PHY_STAT_SPMASK); + + if (mii_reg & 0x0800) { + if (mii_reg & 0x1000) + *s |= PHY_STAT_100FDX; + else + *s |= PHY_STAT_100HDX; + } + else { if (mii_reg & 0x1000) - printk(", Full-Duplex\n"); + *s |= PHY_STAT_10FDX; else - printk(", Half-Duplex\n"); + *s |= PHY_STAT_10HDX; } } -/* This interrupt occurs when the LTX970 detects a link change. -*/ -static void -mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - struct fec_enet_private *fep; - volatile fec_t *ep; - - fep = (struct fec_enet_private *)dev->priv; - ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); +static phy_info_t phy_info_lxt970 = { + 0x07810000, + "LXT970", - /* We need to sequentially read registers 1 and 18 to clear - * the interrupt. We don't need to do that here because this - * is an edge triggered interrupt that has already been acknowledged - * by the top level handler. We also read the extended status - * register 20. We just queue the commands and let them happen - * as part of the "normal" processing. - */ - mii_queue(mk_mii_read(1), mii_relink); -#ifndef CONFIG_RPXCLASSIC - - /* Unique to LevelOne PHY. - */ - mii_queue(mk_mii_read(18), mii_relink); - mii_queue(mk_mii_read(20), mii_relink); -#else + (const phy_cmd_t []) { /* config */ +#if 0 +// { mk_mii_write(MII_REG_ANAR, 0x0021), NULL }, - /* Unique to QS6612 PHY. - */ - mii_queue(mk_mii_read(6), mii_relink); - mii_queue(mk_mii_read(31), mii_relink); + /* Set default operation of 100-TX....for some reason + * some of these bits are set on power up, which is wrong. + */ + { mk_mii_write(MII_LXT970_CONFIG, 0), NULL }, #endif -} + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* read SR and ISR to acknowledge */ + + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_LXT970_ISR), NULL }, -static int -fec_enet_close(struct net_device *dev) -{ - /* Don't know what to do yet. - */ + /* find out the current status */ + + { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +#endif /* CONFIG_FEC_LXT970 */ - return 0; -} +/* ------------------------------------------------------------------------- */ +/* The Level one LXT971 is used on some of my custom boards */ -static struct net_device_stats *fec_enet_get_stats(struct net_device *dev) -{ - struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; +#ifdef CONFIG_FEC_LXT971 - return &fep->stats; -} +/* register definitions for the 971 */ -/* Set or clear the multicast filter for this adaptor. - * Skeleton taken from sunlance driver. - * The CPM Ethernet implementation allows Multicast as well as individual - * MAC address filtering. Some of the drivers check to make sure it is - * a group multicast address, and discard those that are not. I guess I - * will do the same for now, but just remove the test if you want - * individual filtering as well (do the upper net layers want or support - * this kind of feature?). +#define MII_LXT971_PCR 16 /* Port Control Register */ +#define MII_LXT971_SR2 17 /* Status Register 2 */ +#define MII_LXT971_IER 18 /* Interrupt Enable Register */ +#define MII_LXT971_ISR 19 /* Interrupt Status Register */ +#define MII_LXT971_LCR 20 /* LED Control Register */ +#define MII_LXT971_TCR 30 /* Transmit Control Register */ + +/* + * I had some nice ideas of running the MDIO faster... + * The 971 should support 8MHz and I tried it, but things acted really + * wierd, so 2.5 MHz ought to be enough for anyone... */ -static void set_multicast_list(struct net_device *dev) +static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev) { - struct fec_enet_private *fep; - struct dev_mc_list *dmi; - u_char *mcptr, *tdptr; - volatile fec_t *ep; - int i, j; + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); - fep = (struct fec_enet_private *)dev->priv; - ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + *s &= ~(PHY_STAT_SPMASK); + + if (mii_reg & 0x4000) { + if (mii_reg & 0x0200) + *s |= PHY_STAT_100FDX; + else + *s |= PHY_STAT_100HDX; + } + else { + if (mii_reg & 0x0200) + *s |= PHY_STAT_10FDX; + else + *s |= PHY_STAT_10HDX; + } + if (mii_reg & 0x0008) + *s |= PHY_STAT_FAULT; +} + +static phy_info_t phy_info_lxt971 = { + 0x0001378e, + "LXT971", + + (const phy_cmd_t []) { /* config */ + /* limit to 10MBit because my protorype board + * doesn't work with 100. */ + + { mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10 MBit */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + + /* Somehow does the 971 tell me that the link is down + * the first read after power-up. + * read here to get a valid value in ack_int */ + + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* find out the current status */ + + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, + + /* we only need to read ISR to acknowledge */ + + { mk_mii_read(MII_LXT971_ISR), NULL }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +#endif /* CONFIG_FEC_LXT970 */ + + +/* ------------------------------------------------------------------------- */ +/* The Quality Semiconductor QS6612 is used on the RPX CLLF */ + +#ifdef CONFIG_FEC_QS6612 + +/* register definitions */ + +#define MII_QS6612_MCR 17 /* Mode Control Register */ +#define MII_QS6612_FTR 27 /* Factory Test Register */ +#define MII_QS6612_MCO 28 /* Misc. Control Register */ +#define MII_QS6612_ISR 29 /* Interrupt Source Register */ +#define MII_QS6612_IMR 30 /* Interrupt Mask Register */ +#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */ + +static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK); + + switch((mii_reg >> 2) & 7) { + case 1: *s |= PHY_STAT_10HDX; break; + case 2: *s |= PHY_STAT_100HDX; break; + case 5: *s |= PHY_STAT_10FDX; break; + case 6: *s |= PHY_STAT_100FDX; break; + } +} + +static phy_info_t phy_info_qs6612 = { + 0x00181440, + "QS6612", + + (const phy_cmd_t []) { /* config */ +// { mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10 MBit */ + + /* The PHY powers up isolated on the RPX, + * so send a command to allow operation. + */ + + { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL }, + + /* parse cr and anar to get some info */ + + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + + /* we need to read ISR, SR and ANER to acknowledge */ + + { mk_mii_read(MII_QS6612_ISR), NULL }, + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_REG_ANER), NULL }, + + /* read pcr to get info */ + + { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + + +#endif /* CONFIG_FEC_QS6612 */ + + +static phy_info_t *phy_info[] = { + +#ifdef CONFIG_FEC_LXT970 + &phy_info_lxt970, +#endif /* CONFIG_FEC_LXT970 */ + +#ifdef CONFIG_FEC_LXT971 + &phy_info_lxt971, +#endif /* CONFIG_FEC_LXT971 */ + +#ifdef CONFIG_FEC_QS6612 + &phy_info_qs6612, +#endif /* CONFIG_FEC_LXT971 */ + + NULL +}; + +static void mii_display_status(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + if (!fep->link && !fep->old_link) { + /* Link is still down - don't print anything */ + return; + } + + printk("%s: status: ", dev->name); + + if (!fep->link) { + printk("link down"); + } else { + printk("link up"); + + switch(*s & PHY_STAT_SPMASK) { + case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break; + case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break; + case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break; + case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break; + default: + printk(", Unknown speed/duplex"); + } + + if (*s & PHY_STAT_ANC) + printk(", auto-negotiation complete"); + } + + if (*s & PHY_STAT_FAULT) + printk(", remote fault"); + + printk(".\n"); +} + +static void mii_display_config(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + printk("%s: config: auto-negotiation ", dev->name); + + if (*s & PHY_CONF_ANE) + printk("on"); + else + printk("off"); + + if (*s & PHY_CONF_100FDX) + printk(", 100FDX"); + if (*s & PHY_CONF_100HDX) + printk(", 100HDX"); + if (*s & PHY_CONF_10FDX) + printk(", 10FDX"); + if (*s & PHY_CONF_10HDX) + printk(", 10HDX"); + if (!(*s & PHY_CONF_SPMASK)) + printk(", No speed/duplex selected?"); + + if (*s & PHY_CONF_LOOP) + printk(", loopback enabled"); + + printk(".\n"); + + fep->sequence_done = 1; +} + +static void mii_relink(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + int duplex; + + fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; + mii_display_status(dev); + fep->old_link = fep->link; + + if (fep->link) { + duplex = 0; + if (fep->phy_status + & (PHY_STAT_100FDX | PHY_STAT_10FDX)) + duplex = 1; + fec_restart(dev, duplex); + } + else + fec_stop(dev); + +#if 0 + enable_irq(fep->mii_irq); +#endif + +} + +static void mii_queue_relink(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + fep->phy_task.routine = (void *)mii_relink; + fep->phy_task.data = dev; + queue_task(&fep->phy_task, &tq_scheduler); +} + +static void mii_queue_config(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + fep->phy_task.routine = (void *)mii_display_config; + fep->phy_task.data = dev; + queue_task(&fep->phy_task, &tq_scheduler); +} + + + +phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink }, + { mk_mii_end, } }; +phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config }, + { mk_mii_end, } }; + + + +/* Read remainder of PHY ID. +*/ +static void +mii_discover_phy3(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep; + int i; + + fep = dev->priv; + fep->phy_id |= (mii_reg & 0xffff); + printk("fec: Phy @ 0x%x, type 0x%08x\n", fep->phy_addr, fep->phy_id); + + for(i = 0; phy_info[i]; i++) + if(phy_info[i]->id == (fep->phy_id >> 4)) + break; + + if(!phy_info[i]) + panic("%s: PHY id 0x%08x is not supported!\n", + dev->name, fep->phy_id); + + fep->phy = phy_info[i]; + fep->phy_id_done = 1; +} + +/* Scan all of the MII PHY addresses looking for someone to respond + * with a valid ID. This usually happens quickly. + */ +static void +mii_discover_phy(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep; + uint phytype; + + fep = dev->priv; + + if (fep->phy_addr < 32) { + if ((phytype = (mii_reg & 0xffff)) != 0xffff) { + + /* Got first part of ID, now get remainder. + */ + fep->phy_id = phytype << 16; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), + mii_discover_phy3); + } + else { + fep->phy_addr++; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), + mii_discover_phy); + } + } + else { + printk("FEC: No PHY device found.\n"); + } +} + +/* This interrupt occurs when the PHY detects a link change. +*/ +static void +#ifdef CONFIG_RPXCLASSIC +mii_link_interrupt(void *dev_id) +#else +mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) +#endif +{ + struct net_device *dev = dev_id; + struct fec_enet_private *fep = dev->priv; + +#if 0 + disable_irq(fep->mii_irq); /* disable now, enable later */ +#endif + + mii_do_cmd(dev, fep->phy->ack_int); + mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ + +} + +static int +fec_enet_open(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. + */ + + fep->sequence_done = 0; + fep->link = 0; + + if (fep->phy) { + mii_do_cmd(dev, fep->phy->ack_int); + mii_do_cmd(dev, fep->phy->config); + mii_do_cmd(dev, phy_cmd_config); /* display configuration */ + + while(!fep->sequence_done) + schedule(); + + mii_do_cmd(dev, fep->phy->startup); + netif_start_queue(dev); + return 0; /* Success */ + } + + return -ENODEV; /* No PHY we understand */ + +} + +static int +fec_enet_close(struct net_device *dev) +{ + /* Don't know what to do yet. + */ + netif_stop_queue(dev); + fec_stop(dev); + + return 0; +} + +static struct net_device_stats *fec_enet_get_stats(struct net_device *dev) +{ + struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; + + return &fep->stats; +} + +/* Set or clear the multicast filter for this adaptor. + * Skeleton taken from sunlance driver. + * The CPM Ethernet implementation allows Multicast as well as individual + * MAC address filtering. Some of the drivers check to make sure it is + * a group multicast address, and discard those that are not. I guess I + * will do the same for now, but just remove the test if you want + * individual filtering as well (do the upper net layers want or support + * this kind of feature?). + */ + +static void set_multicast_list(struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *ep; + + fep = (struct fec_enet_private *)dev->priv; + ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); if (dev->flags&IFF_PROMISC) { @@ -826,20 +1436,23 @@ struct net_device *dev; struct fec_enet_private *fep; int i, j; - unsigned char *eap; + unsigned char *eap, *iap; unsigned long mem_addr; pte_t *pte; volatile cbd_t *bdp; cbd_t *cbd_base; volatile immap_t *immap; volatile fec_t *fecp; - unsigned char *iap; bd_t *bd; - - bd = (bd_t *)__res; + extern uint _get_IMMR(void); +#ifdef CONFIG_RPXCLASSIC + unsigned char tmpaddr[6]; +#endif immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + bd = (bd_t *)__res; + /* Allocate some private information. */ fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL); @@ -856,47 +1469,27 @@ fecp->fec_ecntrl = 1; udelay(10); - /* Enable interrupts we wish to service. - */ - fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | - FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); - - /* Clear any outstanding interrupt. - */ - fecp->fec_ievent = 0xffc0; - - fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; - - /* Right now, all of the boards supply the ethernet address in - * the board descriptor. If someone doesn't we can just use - * the hard coded address in this driver for testing (this is - * a Motorola address for a board I have, so it is unlikely to - * be used elsewhere). + /* Set the Ethernet address. If using multiple Enets on the 8xx, + * this needs some work to get unique addresses. */ - eap = (unsigned char *)&my_enet_addr[0]; -#if 1 + eap = (unsigned char *)my_enet_addr; iap = bd->bi_enetaddr; + +#ifdef CONFIG_RPXCLASSIC + /* The Embedded Planet boards have only one MAC address in + * the EEPROM, but can have two Ethernet ports. For the + * FEC port, we create another address by setting one of + * the address bits above something that would have (up to + * now) been allocated. + */ for (i=0; i<6; i++) - dev->dev_addr[i] = *eap++ = *iap++; -#else - for (i=0; i<6; i++) - dev->dev_addr[i] = *eap++; + tmpaddr[i] = *iap++; + tmpaddr[3] |= 0x80; + iap = tmpaddr; #endif - /* Set station address. - */ - fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; - fecp->fec_addr_high = my_enet_addr[2]; - - /* Reset all multicast. - */ - fecp->fec_hash_table_high = 0; - fecp->fec_hash_table_low = 0; - - /* Set maximum receive buffer size. - */ - fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; - fecp->fec_r_hash = PKT_MAXBUF_SIZE; + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++ = *iap++; /* Allocate memory for buffer descriptors. */ @@ -910,15 +1503,13 @@ /* Make it uncached. */ - pte = find_pte(&init_mm, (int)mem_addr); + pte = va_to_pte(&init_mm, mem_addr); pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(current->mm->mmap, mem_addr); + flush_tlb_page(init_mm.mmap, mem_addr); /* Set receive and transmit descriptor base. */ - fecp->fec_r_des_start = __pa(mem_addr); fep->rx_bd_base = cbd_base; - fecp->fec_x_des_start = __pa((unsigned long)(cbd_base + RX_RING_SIZE)); fep->tx_bd_base = cbd_base + RX_RING_SIZE; fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; @@ -937,9 +1528,9 @@ /* Make it uncached. */ - pte = find_pte(&init_mm, mem_addr); + pte = va_to_pte(&init_mm, mem_addr); pte_val(*pte) |= _PAGE_NO_CACHE; - flush_tlb_page(current->mm->mmap, mem_addr); + flush_tlb_page(init_mm.mmap, mem_addr); /* Initialize the BD for every fragment in the page. */ @@ -956,6 +1547,172 @@ bdp--; bdp->cbd_sc |= BD_SC_WRAP; +#ifdef CONFIG_FEC_PACKETHOOK + fep->ph_lock = 0; + fep->ph_rxhandler = fep->ph_txhandler = NULL; + fep->ph_proto = 0; + fep->ph_regaddr = NULL; + fep->ph_priv = NULL; +#endif + + /* Install our interrupt handler. + */ + if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) + panic("Could not allocate FEC IRQ!"); +#ifdef CONFIG_RPXCLASSIC + /* Make Port C, bit 15 an input that causes interrupts. + */ + immap->im_ioport.iop_pcpar &= ~0x0001; + immap->im_ioport.iop_pcdir &= ~0x0001; + immap->im_ioport.iop_pcso &= ~0x0001; + immap->im_ioport.iop_pcint |= 0x0001; + cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev); + + /* Make LEDS reflect Link status. + */ + *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE; +#endif +#ifdef CONFIG_FADS + if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0) + panic("Could not allocate MII IRQ!"); +#endif + + dev->base_addr = (unsigned long)fecp; + dev->priv = fep; + + /* The FEC Ethernet specific entries in the device structure. */ + dev->open = fec_enet_open; + dev->hard_start_xmit = fec_enet_start_xmit; + dev->tx_timeout = fec_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + dev->stop = fec_enet_close; + dev->get_stats = fec_enet_get_stats; + dev->set_multicast_list = set_multicast_list; + + for (i=0; iim_ioport.iop_pdpar = 0x1fff; + + /* Bits moved from Rev. D onward. + */ + if ((_get_IMMR() & 0xffff) < 0x0501) + immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ + else + immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ + + /* Set MII speed to 2.5 MHz + */ + fecp->fec_mii_speed = fep->phy_speed = + ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; + + printk("%s: FEC ENET Version 0.2, ", dev->name); + for (i=0; i<5; i++) + printk("%02x:", dev->dev_addr[i]); + printk("%02x\n", dev->dev_addr[5]); + + /* Queue up command to detect the PHY and initialize the + * remainder of the interface. + */ + fep->phy_id_done = 0; + fep->phy_addr = 0; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); + + return 0; +} + +/* This function is called to start or restart the FEC during a link + * change. This only happens when switching between half and full + * duplex. + */ +static void +fec_restart(struct net_device *dev, int duplex) +{ + struct fec_enet_private *fep; + int i; + unsigned char *eap; + volatile cbd_t *bdp; + volatile immap_t *immap; + volatile fec_t *fecp; + + immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + + fecp = &(immap->im_cpm.cp_fec); + + fep = dev->priv; + + /* Whack a reset. We should wait for this. + */ + fecp->fec_ecntrl = 1; + udelay(10); + + /* Enable interrupts we wish to service. + */ + fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | + FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); + + /* Clear any outstanding interrupt. + */ + fecp->fec_ievent = 0xffc0; + + fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; + + /* Set station address. + */ + fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; + fecp->fec_addr_high = my_enet_addr[2]; + + eap = (unsigned char *)&my_enet_addr[0]; + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++; + + /* Reset all multicast. + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + fecp->fec_r_hash = PKT_MAXBUF_SIZE; + + /* Set receive and transmit descriptor base. + */ + fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); + fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->cur_rx = fep->rx_bd_base; + + /* Reset SKB transmit buffers. + */ + fep->skb_cur = fep->skb_dirty = 0; + for (i=0; i<=TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i] != NULL) { + dev_kfree_skb(fep->tx_skbuff[i]); + fep->tx_skbuff[i] = NULL; + } + } + + /* Initialize the receive buffer descriptors. + */ + bdp = fep->rx_bd_base; + for (i=0; icbd_sc = BD_ENET_RX_EMPTY; + bdp++; + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + /* ...and the same for transmmit. */ bdp = fep->tx_bd_base; @@ -973,59 +1730,65 @@ bdp--; bdp->cbd_sc |= BD_SC_WRAP; - /* Enable MII mode, half-duplex until we know better.. + /* Enable MII mode. */ - fecp->fec_r_cntrl = 0x0c; - fecp->fec_x_cntrl = 0x00; + if (duplex) { + fecp->fec_r_cntrl = 0x04; /* MII enable */ + fecp->fec_x_cntrl = 0x04; /* FD enable */ + } + else { + fecp->fec_r_cntrl = 0x06; /* MII enable|No Rcv on Xmit */ + fecp->fec_x_cntrl = 0x00; + } + fep->full_duplex = duplex; /* Enable big endian and don't care about SDMA FC. */ fecp->fec_fun_code = 0x78000000; - /* Set MII speed (50 MHz core). + /* Set MII speed. */ - fecp->fec_mii_speed = 0x14; + fecp->fec_mii_speed = fep->phy_speed; - /* Configure all of port D for MII. + /* And last, enable the transmit and receive processing. */ - immap->im_ioport.iop_pdpar = 0x1fff; - immap->im_ioport.iop_pddir = 0x1c58; + fecp->fec_ecntrl = 6; + fecp->fec_r_des_active = 0x01000000; +} - /* Install our interrupt handlers. The 860T FADS board uses - * IRQ2 for the MII interrupt. - */ - if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) - panic("Could not allocate FEC IRQ!"); - if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0) - panic("Could not allocate MII IRQ!"); +static void +fec_stop(struct net_device *dev) +{ + volatile immap_t *immap; + volatile fec_t *fecp; + struct fec_enet_private *fep; - dev->base_addr = (unsigned long)fecp; - dev->priv = fep; - dev->name = "fec"; + immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + + fecp = &(immap->im_cpm.cp_fec); + + fep = dev->priv; - /* The FEC Ethernet specific entries in the device structure. */ - dev->open = fec_enet_open; - dev->hard_start_xmit = fec_enet_start_xmit; - dev->stop = fec_enet_close; - dev->get_stats = fec_enet_get_stats; - dev->set_multicast_list = set_multicast_list; - /* And last, enable the transmit and receive processing. - */ - fecp->fec_ecntrl = 2; - fecp->fec_r_des_active = 0x01000000; + fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ - printk("FEC ENET Version 0.1, "); - for (i=0; i<5; i++) - printk("%02x:", dev->dev_addr[i]); - printk("%02x\n", dev->dev_addr[5]); + while(!(fecp->fec_ievent & 0x10000000)); - for (i=0; ifec_ecntrl = 1; + udelay(10); + + /* Clear outstanding MII command interrupts. + */ + fecp->fec_ievent = FEC_ENET_MII; - mii_startup_cmds(); + /* Enable MII command finihed interrupt + */ + fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; + fecp->fec_imask = FEC_ENET_MII; - return 0; + /* Set MII speed. + */ + fecp->fec_mii_speed = fep->phy_speed; } - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/8xx_io/uart.c linux.ac/arch/ppc/8xx_io/uart.c --- linux.vanilla/arch/ppc/8xx_io/uart.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/8xx_io/uart.c Sun Jun 4 21:10:56 2000 @@ -101,11 +101,15 @@ */ #define smc_scc_num hub6 +#ifdef CONFIG_8xxSMC2 /* SMC2 is sometimes used for low performance TDM interfaces. Define * this as 1 if you want SMC2 as a serial port UART managed by this driver. * Define this as 0 if you wish to use SMC2 for something else. */ #define USE_SMC2 1 +#else +#define USE_SMC2 0 +#endif /* Define SCC to ttySx mapping. */ @@ -130,7 +134,7 @@ #if USE_SMC2 { 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, 1 }, /* SMC2 ttyS1 */ #endif -#if defined(CONFIG_MPC860) || defined(CONFIG_MPC860T) +#ifdef CONFIG_8xxSCC { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, SCC_NUM_BASE}, /* SCC2 ttyS2 */ { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, SCC_NUM_BASE + 1}, /* SCC3 ttyS3 */ #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/Makefile linux.ac/arch/ppc/Makefile --- linux.vanilla/arch/ppc/Makefile Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/Makefile Sat Jun 10 21:48:23 2000 @@ -34,8 +34,8 @@ CFLAGS := $(CFLAGS) -mcpu=860 -I../8xx_io endif -ifdef CONFIG_PPC64 -CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-mpowerpc64 +ifdef CONFIG_PPC64BRIDGE +CFLAGS := $(CFLAGS) -Wa,-mppc64bridge endif ifdef CONFIG_4xx @@ -128,7 +128,7 @@ endif endif -ifdef CONFIG_PPC64 +ifdef CONFIG_PPC64BRIDGE $(BOOT_TARGETS): $(CHECKS) vmlinux @$(MAKECOFFBOOT) $@ @$(MAKEBOOT) $@ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/boot/Makefile linux.ac/arch/ppc/boot/Makefile --- linux.vanilla/arch/ppc/boot/Makefile Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/boot/Makefile Sat Jun 10 21:48:23 2000 @@ -41,7 +41,7 @@ TFTPSIMAGE=/tftpboot/sImage endif -ifeq ($(CONFIG_PPC64),y) +ifeq ($(CONFIG_PPC64BRIDGE),y) MSIZE=.64 else MSIZE= diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/chrpboot/Makefile linux.ac/arch/ppc/chrpboot/Makefile --- linux.vanilla/arch/ppc/chrpboot/Makefile Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/chrpboot/Makefile Sat Jun 10 21:48:23 2000 @@ -5,29 +5,24 @@ # # Based on coffboot by Paul Mackerras -.c.s: - $(CC) $(CFLAGS) -S -o $*.s $< -.s.o: - $(AS) -o $*.o $< +ifeq ($(CONFIG_PPC64BRIDGE),y) +MSIZE=.64 +AFLAGS += -Wa,-mppc64bridge +else +MSIZE= +endif + .c.o: $(CC) $(CFLAGS) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $< -.S.s: - $(CPP) $(AFLAGS) -traditional -o $*.o $< .S.o: $(CC) $(AFLAGS) -traditional -c -o $*.o $< CFLAGS = $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS LD_ARGS = -Ttext 0x00400000 -OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o sysmap.o +OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o LIBS = $(TOPDIR)/lib/lib.a -ifeq ($(CONFIG_PPC64),y) -MSIZE=.64 -else -MSIZE= -endif - ifeq ($(CONFIG_ALL_PPC),y) # yes, we want to build chrp stuff CONFIG_CHRP = y @@ -58,8 +53,8 @@ piggyback: piggyback.c $(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c -mknote: mknote.c - $(HOSTCC) $(HOSTCFLAGS) -o mknote mknote.c +addnote: addnote.c + $(HOSTCC) $(HOSTCFLAGS) -o addnote addnote.c image.o: piggyback ../coffboot/vmlinux.gz ./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o @@ -70,13 +65,13 @@ initrd.o: ramdisk.image.gz piggyback ./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o -zImage: $(OBJS) no_initrd.o mknote +zImage: $(OBJS) no_initrd.o addnote $(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS) - ./mknote > note - $(OBJCOPY) $@ $@ --add-section=.note=note -R .comment + ./addnote $@ -zImage.initrd: $(OBJS) initrd.o +zImage.initrd: $(OBJS) initrd.o addnote $(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS) + ./addnote $@ else znetboot: @@ -98,7 +93,7 @@ clean: - rm -f piggyback note mknote $(OBJS) zImage + rm -f piggyback note addnote $(OBJS) zImage fastdep: $(TOPDIR)/scripts/mkdep *.[Sch] > .depend diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/chrpboot/addnote.c linux.ac/arch/ppc/chrpboot/addnote.c --- linux.vanilla/arch/ppc/chrpboot/addnote.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/chrpboot/addnote.c Sat Jun 10 21:48:23 2000 @@ -0,0 +1,163 @@ +/* + * Program to hack in a PT_NOTE program header entry in an ELF file. + * This is needed for OF on RS/6000s to load an image correctly. + * Note that OF needs a program header entry for the note, not an + * ELF section. + * + * Copyright 2000 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. + * + * Usage: addnote zImage + */ +#include +#include +#include +#include + +char arch[] = "PowerPC"; + +#define N_DESCR 6 +unsigned int descr[N_DESCR] = { + 0xffffffff, /* real-mode = true */ + 0x00c00000, /* real-base, i.e. where we expect OF to be */ + 0xffffffff, /* real-size */ + 0xffffffff, /* virt-base */ + 0xffffffff, /* virt-size */ + 0x4000, /* load-base */ +}; + +unsigned char buf[512]; + +#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) +#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2)) + +#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \ + buf[(off) + 1] = (v) & 0xff) +#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \ + PUT_16BE((off) + 2, (v))) + +/* Structure of an ELF file */ +#define E_IDENT 0 /* ELF header */ +#define E_PHOFF 28 +#define E_PHENTSIZE 42 +#define E_PHNUM 44 +#define E_HSIZE 52 /* size of ELF header */ + +#define EI_MAGIC 0 /* offsets in E_IDENT area */ +#define EI_CLASS 4 +#define EI_DATA 5 + +#define PH_TYPE 0 /* ELF program header */ +#define PH_OFFSET 4 +#define PH_FILESZ 16 +#define PH_HSIZE 32 /* size of program header */ + +#define PT_NOTE 4 /* Program header type = note */ + +#define ELFCLASS32 1 +#define ELFDATA2MSB 2 + +unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; + +main(int ac, char **av) +{ + int fd, n, i; + int ph, ps, np; + int nnote, ns; + + if (ac != 2) { + fprintf(stderr, "Usage: %s elf-file\n", av[0]); + exit(1); + } + fd = open(av[1], O_RDWR); + if (fd < 0) { + perror(av[1]); + exit(1); + } + + nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; + + n = read(fd, buf, sizeof(buf)); + if (n < 0) { + perror("read"); + exit(1); + } + + if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0) + goto notelf; + + if (buf[E_IDENT+EI_CLASS] != ELFCLASS32 + || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) { + fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", + av[1]); + exit(1); + } + + ph = GET_32BE(E_PHOFF); + ps = GET_16BE(E_PHENTSIZE); + np = GET_16BE(E_PHNUM); + if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) + goto notelf; + if (ph + (np + 1) * ps + nnote > n) + goto nospace; + + for (i = 0; i < np; ++i) { + if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { + fprintf(stderr, "%s already has a note entry\n", + av[1]); + exit(0); + } + ph += ps; + } + + /* XXX check that the area we want to use is all zeroes */ + for (i = 0; i < ps + nnote; ++i) + if (buf[ph + i] != 0) + goto nospace; + + /* fill in the program header entry */ + ns = ph + ps; + PUT_32BE(ph + PH_TYPE, PT_NOTE); + PUT_32BE(ph + PH_OFFSET, ns); + PUT_32BE(ph + PH_FILESZ, nnote); + + /* fill in the note area we point to */ + /* XXX we should probably make this a proper section */ + PUT_32BE(ns, strlen(arch) + 1); + PUT_32BE(ns + 4, N_DESCR * 4); + PUT_32BE(ns + 8, 0x1275); + strcpy(&buf[ns + 12], arch); + ns += 12 + strlen(arch) + 1; + for (i = 0; i < N_DESCR; ++i) + PUT_32BE(ns + i * 4, descr[i]); + + /* Update the number of program headers */ + PUT_16BE(E_PHNUM, np + 1); + + /* write back */ + lseek(fd, (long) 0, SEEK_SET); + i = write(fd, buf, n); + if (i < 0) { + perror("write"); + exit(1); + } + if (i < n) { + fprintf(stderr, "%s: write truncated\n", av[1]); + exit(1); + } + + exit(0); + + notelf: + fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]); + exit(1); + + nospace: + fprintf(stderr, "sorry, I can't find space in %s to put the note\n", + av[0]); + exit(1); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/chrpboot/main.c linux.ac/arch/ppc/chrpboot/main.c --- linux.vanilla/arch/ppc/chrpboot/main.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/chrpboot/main.c Sat Jun 10 21:48:23 2000 @@ -16,11 +16,11 @@ extern int getprop(void *, const char *, void *, int); void gunzip(void *, int, unsigned char *, int *); -#define get_16be(x) (*(unsigned short *)(x)) -#define get_32be(x) (*(unsigned *)(x)) - #define RAM_START 0x00000000 -#define RAM_END (8<<20) +#define RAM_END (64<<20) + +#define BOOT_START ((unsigned long)_start) +#define BOOT_END ((unsigned long)(_end + 0xFFF) & ~0xFFF) #define RAM_FREE ((unsigned long)(_end+0x1000)&~0xFFF) #define PROG_START 0x00010000 @@ -36,6 +36,7 @@ extern char sysmap_data[]; extern int sysmap_len; +static char scratch[1024<<10]; /* 1MB of scratch space for gunzip */ chrpboot(int a1, int a2, void *prom) { @@ -48,13 +49,25 @@ printf("chrpboot starting: loaded at 0x%x\n\r", &_start); - end_avail = (char *) RAM_END; + if (initrd_len) { + initrd_size = initrd_len; + initrd_start = (RAM_END - initrd_size) & ~0xFFF; + a1 = initrd_start; + a2 = initrd_size; + claim(initrd_start, RAM_END - initrd_start, 0); + printf("initial ramdisk moving 0x%x <- 0x%x (%x bytes)\n\r", + initrd_start, initrd_data, initrd_size); + memcpy((char *)initrd_start, initrd_data, initrd_size); + } im = image_data; len = image_len; + /* claim 4MB starting at PROG_START */ + claim(PROG_START, (4<<20) - PROG_START, 0); dst = (void *) PROG_START; if (im[0] == 0x1f && im[1] == 0x8b) { - avail_ram = (char *)RAM_FREE; + avail_ram = scratch; + end_avail = scratch + sizeof(scratch); printf("gunzipping (0x%x <- 0x%x:0x%0x)...", dst, im, im+len); gunzip(dst, 0x400000, im, &len); printf("done %u bytes\n\r", len); @@ -86,17 +99,18 @@ rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); - +#if 0 rec->tag = BI_SYSMAP; rec->data[0] = (unsigned long)sysmap_data; rec->data[1] = sysmap_len; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); +#endif rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } - (*(void (*)())sa)(0, 0, prom, a1, a2); + (*(void (*)())sa)(a1, a2, prom); printf("returned?\n\r"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/chrpboot/start.c linux.ac/arch/ppc/chrpboot/start.c --- linux.vanilla/arch/ppc/chrpboot/start.c Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/chrpboot/start.c Sat Jun 10 21:48:23 2000 @@ -131,6 +131,29 @@ return args.phandle; } +void * +claim(unsigned int virt, unsigned int size, unsigned int align) +{ + struct prom_args { + char *service; + int nargs; + int nret; + unsigned int virt; + unsigned int size; + unsigned int align; + void *ret; + } args; + + args.service = "claim"; + args.nargs = 3; + args.nret = 1; + args.virt = virt; + args.size = size; + args.align = align; + (*prom)(&args); + return args.ret; +} + int getprop(void *phandle, const char *name, void *buf, int buflen) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/coffboot/Makefile linux.ac/arch/ppc/coffboot/Makefile --- linux.vanilla/arch/ppc/coffboot/Makefile Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/coffboot/Makefile Sat Jun 10 21:48:23 2000 @@ -14,7 +14,7 @@ CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o LIBS = $(TOPDIR)/lib/lib.a -ifeq ($(CONFIG_PPC64),y) +ifeq ($(CONFIG_PPC64BRIDGE),y) MSIZE=.64 else MSIZE= @@ -54,7 +54,7 @@ miboot.image: dummy.o vmlinux.gz $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz dummy.o $@ -miboot.image.initrd: dummy.o vmlinux.gz +miboot.image.initrd: miboot.image ramdisk.image.gz $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz miboot.image $@ coffboot: $(COFFOBJS) no_initrd.o ld.script diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/config.in linux.ac/arch/ppc/config.in --- linux.vanilla/arch/ppc/config.in Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/config.in Sat Jun 10 21:48:23 2000 @@ -17,10 +17,14 @@ choice 'Processor Type' \ "6xx/7xx/7400 CONFIG_6xx \ 4xx CONFIG_4xx \ - 630/Power3(64-Bit) CONFIG_PPC64 \ + POWER3/POWER4(64-Bit) CONFIG_PPC64BRIDGE \ 8260 CONFIG_8260 \ 8xx CONFIG_8xx" 6xx +if [ "$CONFIG_PPC64BRIDGE" = "y" ]; then + bool 'Power 4 support' CONFIG_POWER4 +fi + if [ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_6xx y define_bool CONFIG_SERIAL_CONSOLE y @@ -35,14 +39,6 @@ if [ "$CONFIG_8xx" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y - choice 'Processor Model' \ - "821 CONFIG_MPC821 \ - 823 CONFIG_MPC823 \ - 850 CONFIG_MPC850 \ - 855 CONFIG_MPC855 \ - 860 CONFIG_MPC860 \ - 860T CONFIG_MPC860T" 860 - choice 'Machine Type' \ "RPX-Lite CONFIG_RPXLITE \ RPX-Classic CONFIG_RPXCLASSIC \ @@ -58,7 +54,7 @@ APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP fi -if [ "$CONFIG_PPC64" = "y" ]; then +if [ "$CONFIG_PPC64BRIDGE" = "y" ]; then define_bool CONFIG_ALL_PPC y fi @@ -99,7 +95,7 @@ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_PCI n else - if [ "$CONFIG_6xx" = "y" -o "$CONFIG_PPC64" = "y" ]; then + if [ "$CONFIG_6xx" = "y" -o "$CONFIG_PPC64BRIDGE" = "y" ]; then define_bool CONFIG_PCI y else # CONFIG_8xx @@ -161,7 +157,7 @@ if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL y if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then - string 'Initial kernel command string' CONFIG_CMDLINE console=ttyS0,9600 console=tty0 root=/dev/sda2 + string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2" fi fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/configs/apus_defconfig linux.ac/arch/ppc/configs/apus_defconfig --- linux.vanilla/arch/ppc/configs/apus_defconfig Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/configs/apus_defconfig Mon May 29 19:25:15 2000 @@ -78,10 +78,6 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PMAC_AUTO=y # CONFIG_IDE_CHIPSETS is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/configs/common_defconfig linux.ac/arch/ppc/configs/common_defconfig --- linux.vanilla/arch/ppc/configs/common_defconfig Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/configs/common_defconfig Sat Jun 10 21:48:23 2000 @@ -14,7 +14,7 @@ CONFIG_PPC=y CONFIG_6xx=y # CONFIG_4xx is not set -# CONFIG_PPC64 is not set +# CONFIG_PPC64BRIDGE is not set # CONFIG_8260 is not set # CONFIG_8xx is not set CONFIG_ALL_PPC=y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/configs/gemini_defconfig linux.ac/arch/ppc/configs/gemini_defconfig --- linux.vanilla/arch/ppc/configs/gemini_defconfig Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/configs/gemini_defconfig Sat Jun 10 21:48:23 2000 @@ -14,7 +14,7 @@ CONFIG_PPC=y CONFIG_6xx=y # CONFIG_4xx is not set -# CONFIG_PPC64 is not set +# CONFIG_PPC64BRIDGE is not set # CONFIG_82xx is not set # CONFIG_8xx is not set # CONFIG_PMAC is not set @@ -77,10 +77,6 @@ # # CONFIG_BLK_DEV_HD_ONLY is not set # CONFIG_BLK_CPQ_DA is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/configs/oak_defconfig linux.ac/arch/ppc/configs/oak_defconfig --- linux.vanilla/arch/ppc/configs/oak_defconfig Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/configs/oak_defconfig Sat Jun 10 21:48:23 2000 @@ -13,7 +13,7 @@ CONFIG_PPC=y # CONFIG_6xx is not set CONFIG_4xx=y -# CONFIG_PPC64 is not set +# CONFIG_PPC64BRIDGE is not set # CONFIG_82xx is not set # CONFIG_8xx is not set CONFIG_OAK=y @@ -69,10 +69,6 @@ # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/configs/walnut_defconfig linux.ac/arch/ppc/configs/walnut_defconfig --- linux.vanilla/arch/ppc/configs/walnut_defconfig Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/configs/walnut_defconfig Sat Jun 10 21:48:23 2000 @@ -13,7 +13,7 @@ CONFIG_PPC=y # CONFIG_6xx is not set CONFIG_4xx=y -# CONFIG_PPC64 is not set +# CONFIG_PPC64BRIDGE is not set # CONFIG_82xx is not set # CONFIG_8xx is not set # CONFIG_OAK is not set @@ -69,10 +69,6 @@ # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set - -# -# Additional Block Devices -# CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/defconfig linux.ac/arch/ppc/defconfig --- linux.vanilla/arch/ppc/defconfig Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/defconfig Sat Jun 10 21:48:23 2000 @@ -14,7 +14,7 @@ CONFIG_PPC=y CONFIG_6xx=y # CONFIG_4xx is not set -# CONFIG_PPC64 is not set +# CONFIG_PPC64BRIDGE is not set # CONFIG_8260 is not set # CONFIG_8xx is not set CONFIG_ALL_PPC=y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/Makefile linux.ac/arch/ppc/kernel/Makefile --- linux.vanilla/arch/ppc/kernel/Makefile Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/Makefile Sat Jun 10 21:48:23 2000 @@ -7,8 +7,13 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... +ifdef CONFIG_PPC64BRIDGE +.S.o: + $(CC) $(CFLAGS) -D__ASSEMBLY__ -mppc64bridge -c $< -o $*.o +else .S.o: $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o +endif O_TARGET := kernel.o OX_OBJS := ppc_ksyms.o setup.o @@ -32,6 +37,10 @@ O_OBJS := entry.o traps.o irq.o idle.o time.o process.o signal.o syscalls.o \ misc.o ptrace.o align.o ppc_htab.o semaphore.o bitops.o + +ifdef CONFIG_POWER4 +O_OBJS += xics.o +endif ifndef CONFIG_8xx O_OBJS += hashtable.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/align.c linux.ac/arch/ppc/kernel/align.c --- linux.vanilla/arch/ppc/kernel/align.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/align.c Sat Jun 10 21:48:23 2000 @@ -21,7 +21,7 @@ unsigned char flags; }; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) #define OPCD(inst) (((inst) & 0xFC000000) >> 26) #define RS(inst) (((inst) & 0x03E00000) >> 21) #define RA(inst) (((inst) & 0x001F0000) >> 16) @@ -184,7 +184,7 @@ fix_alignment(struct pt_regs *regs) { int instr, nb, flags; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) int opcode, f1, f2, f3; #endif int i, t; @@ -197,9 +197,11 @@ unsigned char v[8]; } data; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) /* The 4xx-family processors have no DSISR register, * so we emulate it. + * The POWER4 has a DSISR register but doesn't set it on + * an alignment fault. -- paulus */ instr = *((unsigned int *)regs->nip); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/bitops.c linux.ac/arch/ppc/kernel/bitops.c --- linux.vanilla/arch/ppc/kernel/bitops.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/bitops.c Sat Jun 10 21:48:23 2000 @@ -6,60 +6,58 @@ #include /* - * I left these here since the problems with "cc" make it difficult to keep - * them in bitops.h -- Cort + * If the bitops are not inlined in bitops.h, they are defined here. + * -- paulus */ -void set_bit(int nr, volatile void *addr) +#if !__INLINE_BITOPS +void set_bit(int nr, volatile void * addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - if ((unsigned long)addr & 3) - printk(KERN_ERR "set_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - or %0,%0,%1 - stwcx. %0,0,%2 + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + or %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) - : "cc"); + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc" ); } void clear_bit(int nr, volatile void *addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "clear_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - andc %0,%0,%1 - stwcx. %0,0,%2 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + andc %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); } void change_bit(int nr, volatile void *addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "change_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - xor %0,%0,%1 - stwcx. %0,0,%2 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + xor %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); } @@ -69,15 +67,14 @@ unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_set_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - or %1,%0,%2 - stwcx. %1,0,%3 - bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + or %1,%0,%3 + stwcx. %1,0,%4 + bne 1b" + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; @@ -89,15 +86,14 @@ unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_clear_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - andc %1,%0,%2 - stwcx. %1,0,%3 - bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + andc %1,%0,%3 + stwcx. %1,0,%4 + bne 1b" + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; @@ -109,93 +105,16 @@ unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_change_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - xor %1,%0,%2 - stwcx. %1,0,%3 - bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + xor %1,%0,%3 + stwcx. %1,0,%4 + bne 1b" + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; } - -/* I put it in bitops.h -- Cort */ -#if 0 -int ffz(unsigned int x) -{ - int n; - - x = ~x & (x+1); /* set LS zero to 1, other bits to 0 */ - __asm__ ("cntlzw %0,%1" : "=r" (n) : "r" (x)); - return 31 - n; -} - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ - -int find_first_zero_bit(void * addr, int size) -{ - unsigned int * p = ((unsigned int *) addr); - unsigned int result = 0; - unsigned int tmp; - - if (size == 0) - return 0; - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} - -/* - * Find next zero bit in a bitmap reasonably efficiently.. - */ -int find_next_zero_bit(void * addr, int size, int offset) -{ - unsigned int * p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (~tmp) - goto found_middle; - size -= 32; - result += 32; - } - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; -found_first: - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} -#endif +#endif /* !__INLINE_BITOPS */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/chrp_pci.c linux.ac/arch/ppc/kernel/chrp_pci.c --- linux.vanilla/arch/ppc/kernel/chrp_pci.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/chrp_pci.c Sat Jun 10 21:48:23 2000 @@ -21,6 +21,10 @@ #include "pci.h" +#ifdef CONFIG_POWER4 +static unsigned long pci_address_offset(int, unsigned int); +#endif /* CONFIG_POWER4 */ + /* LongTrail */ #define pci_config_addr(bus, dev, offset) \ (GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset)) @@ -172,8 +176,11 @@ unsigned char offset, unsigned char *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 1 ) != 0 ) + unsigned long ret; + + if (call_rtas( "read-pci-config", 2, 2, &ret, addr, 1) != 0) return PCIBIOS_DEVICE_NOT_FOUND; + *val = ret; return PCIBIOS_SUCCESSFUL; } @@ -181,8 +188,11 @@ unsigned char offset, unsigned short *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 2 ) != 0 ) + unsigned long ret; + + if (call_rtas("read-pci-config", 2, 2, &ret, addr, 2) != 0) return PCIBIOS_DEVICE_NOT_FOUND; + *val = ret; return PCIBIOS_SUCCESSFUL; } @@ -191,8 +201,11 @@ unsigned char offset, unsigned int *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); - if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 4 ) != 0 ) + unsigned long ret; + + if (call_rtas("read-pci-config", 2, 2, &ret, addr, 4) != 0) return PCIBIOS_DEVICE_NOT_FOUND; + *val = ret; return PCIBIOS_SUCCESSFUL; } @@ -275,14 +288,33 @@ { struct pci_dev *dev; int i; + int *brp; + struct device_node *np; extern struct pci_ops generic_pci_ops; - /* Some IBM's with the python have >1 bus, this finds them */ - for ( i = 0; i < python_busnr ; i++ ) - pci_scan_bus(i+1, &generic_pci_ops, NULL); +#ifndef CONFIG_POWER4 + np = find_devices("device-tree"); + if (np != 0) { + for (np = np->child; np != NULL; np = np->sibling) { + if (np->type == NULL || strcmp(np->type, "pci") != 0) + continue; + if ((brp = (int *) get_property(np, "bus-range", NULL)) == 0) + continue; + if (brp[0] != 0) /* bus 0 is already done */ + pci_scan_bus(brp[0], &generic_pci_ops, NULL); + } + } +#else + /* XXX kludge for now because we can't properly handle + physical addresses > 4GB. -- paulus */ + pci_scan_bus(0x1e, &generic_pci_ops, NULL); +#endif /* CONFIG_POWER4 */ /* PCI interrupts are controlled by the OpenPIC */ pci_for_each_dev(dev) { + np = find_pci_device_OFnode(dev->bus->number, dev->devfn); + if ( (np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0)) + dev->irq = np->intrs[0].line; if ( dev->irq ) dev->irq = openpic_to_irq( dev->irq ); /* these need to be absolute addrs for OF and Matrox FB -- Cort */ @@ -301,10 +333,30 @@ pcibios_write_config_word(dev->bus->number, dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); } - if ( (dev->bus->number > 0) && - ((dev->vendor == PCI_VENDOR_ID_NCR) || - (dev->vendor == PCI_VENDOR_ID_AMD))) - dev->resource[0].start += (dev->bus->number*0x08000000); +#ifdef CONFIG_POWER4 + for (i = 0; i < 6; ++i) { + unsigned long offset; + if (dev->resource[i].start == 0) + continue; + offset = pci_address_offset(dev->bus->number, + dev->resource[i].flags); + if (offset) { + dev->resource[i].start += offset; + dev->resource[i].end += offset; + printk("device %x.%x[%d] now [%lx..%lx]\n", + dev->bus->number, dev->devfn, i, + dev->resource[i].start, + dev->resource[i].end); + } + /* zap the 2nd function of the winbond chip */ + if (dev->resource[i].flags & IORESOURCE_IO + && dev->bus->number == 0 && dev->devfn == 0x81) + dev->resource[i].flags &= ~IORESOURCE_IO; + } +#else + if (dev->bus->number > 0 && python_busnr > 0) + dev->resource[0].start += dev->bus->number*0x01000000; +#endif } } @@ -316,7 +368,11 @@ chrp_setup_pci_ptrs(void) { struct device_node *py; - + +#ifdef CONFIG_POWER4 + set_config_access_method(rtas); + pci_dram_offset = 0; +#else /* CONFIG_POWER4 */ if ( !strncmp("MOT", get_property(find_path_device("/"), "model", NULL),3) ) { @@ -327,23 +383,27 @@ } else { - if ( (py = find_compatible_devices( "pci", "IBM,python" )) ) + if ((py = find_compatible_devices("pci", "IBM,python")) != 0 + || (py = find_compatible_devices("pci", "IBM,python3.0")) != 0) { + char *name = get_property(find_path_device("/"), "name", NULL); + /* find out how many pythons */ while ( (py = py->next) ) python_busnr++; set_config_access_method(python); + /* * We base these values on the machine type but should * try to read them from the python controller itself. * -- Cort */ - if ( !strncmp("IBM,7025-F50", get_property(find_path_device("/"), "name", NULL),12) ) + if ( !strncmp("IBM,7025-F50", name, 12) ) { pci_dram_offset = 0x80000000; isa_mem_base = 0xa0000000; isa_io_base = 0x88000000; - } else if ( !strncmp("IBM,7043-260", - get_property(find_path_device("/"), "name", NULL),12) ) + } else if ( !strncmp("IBM,7043-260", name, 12) + || !strncmp("IBM,7044-270", name, 12)) { pci_dram_offset = 0x0; isa_mem_base = 0xc0000000; @@ -372,6 +432,66 @@ } } } +#endif /* CONFIG_POWER4 */ ppc_md.pcibios_fixup = chrp_pcibios_fixup; } + +#ifdef CONFIG_PPC64BRIDGE +/* + * Hack alert!!! + * 64-bit machines like POWER3 and POWER4 have > 32 bit + * physical addresses. For now we remap particular parts + * of the 32-bit physical address space that the Linux + * page table gives us into parts of the physical address + * space above 4GB so we can access the I/O devices. + */ + +#ifdef CONFIG_POWER4 +static unsigned long pci_address_offset(int busnr, unsigned int flags) +{ + unsigned long offset = 0; + + if (busnr >= 0x1e) { + if (flags & IORESOURCE_IO) + offset = -0x100000; + else if (flags & IORESOURCE_MEM) + offset = 0x38000000; + } else if (busnr <= 0xf) { + if (flags & IORESOURCE_MEM) + offset = -0x40000000; + else + } + return offset; +} + +unsigned long phys_to_bus(unsigned long pa) +{ + if (pa >= 0xf8000000) + pa -= 0x38000000; + else if (pa >= 0x80000000 && pa < 0xc0000000) + pa += 0x40000000; + return pa; +} + +unsigned long bus_to_phys(unsigned int ba, int busnr) +{ + return ba + pci_address_offset(busnr, IORESOURCE_MEM); +} + +#else /* CONFIG_POWER4 */ +/* + * For now assume I/O addresses are < 4GB and PCI bridges don't + * remap addresses on POWER3 machines. + */ +unsigned long phys_to_bus(unsigned long pa) +{ + return pa; +} + +unsigned long bus_to_phys(unsigned int ba, int busnr) +{ + return ba; +} +#endif /* CONFIG_POWER4 */ +#endif /* CONFIG_PPC64BRIDGE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/chrp_setup.c linux.ac/arch/ppc/kernel/chrp_setup.c --- linux.vanilla/arch/ppc/kernel/chrp_setup.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/chrp_setup.c Sat Jun 10 21:48:23 2000 @@ -55,6 +55,7 @@ #include "local_irq.h" #include "i8259.h" #include "open_pic.h" +#include "xics.h" extern volatile unsigned char *chrp_int_ack_special; @@ -259,6 +260,7 @@ request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); +#ifndef CONFIG_PPC64BRIDGE /* PCI bridge config space access area - * appears to be not in devtree on longtrail. */ ioremap(GG2_PCI_CONFIG_BASE, 0x80000); @@ -267,14 +269,23 @@ * -- Geert */ hydra_init(); /* Mac I/O */ +#endif /* CONFIG_PPC64BRIDGE */ +#ifndef CONFIG_POWER4 /* Some IBM machines don't have the hydra -- Cort */ if ( !OpenPIC ) { - OpenPIC = (struct OpenPIC *)*(unsigned long *)get_property( - find_path_device("/"), "platform-open-pic", NULL); - OpenPIC = ioremap((unsigned long)OpenPIC, sizeof(struct OpenPIC)); + unsigned long *opprop; + + opprop = (unsigned long *)get_property(find_path_device("/"), + "platform-open-pic", NULL); + if (opprop != 0) { + printk("OpenPIC addrs: %lx %lx %lx\n", + opprop[0], opprop[1], opprop[2]); + OpenPIC = ioremap(opprop[0], sizeof(struct OpenPIC)); + } } +#endif /* * Fix the Super I/O configuration @@ -283,7 +294,10 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif + +#ifndef CONFIG_PPC64BRIDGE pmac_find_bridges(); +#endif /* CONFIG_PPC64BRIDGE */ /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort @@ -402,15 +416,15 @@ { struct device_node *np; int i; + unsigned long *addrp; - if ( !(np = find_devices("pci") ) ) + if (!(np = find_devices("pci")) + || !(addrp = (unsigned long *) + get_property(np, "8259-interrupt-acknowledge", NULL))) printk("Cannot find pci to get ack address\n"); else - { chrp_int_ack_special = (volatile unsigned char *) - (*(unsigned long *)get_property(np, - "8259-interrupt-acknowledge", NULL)); - } + ioremap(*addrp, 1); open_pic_irq_offset = 16; for ( i = 16 ; i < NR_IRQS ; i++ ) irq_desc[i].handler = &open_pic; @@ -435,6 +449,8 @@ #ifdef CONFIG_NVRAM pmac_nvram_init(); #endif + if (ppc_md.progress) + ppc_md.progress(" Have fun! ", 0x7777); } #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) @@ -560,10 +576,16 @@ ppc_md.setup_residual = NULL; ppc_md.get_cpuinfo = chrp_get_cpuinfo; ppc_md.irq_cannonicalize = chrp_irq_cannonicalize; +#ifndef CONFIG_POWER4 ppc_md.init_IRQ = chrp_init_IRQ; ppc_md.get_irq = chrp_get_irq; ppc_md.post_irq = chrp_post_irq; - +#else + ppc_md.init_IRQ = xics_init_IRQ; + ppc_md.get_irq = xics_get_irq; + ppc_md.post_irq = NULL; +#endif /* CONFIG_POWER4 */ + ppc_md.init = chrp_init2; ppc_md.restart = chrp_restart; @@ -652,6 +674,7 @@ if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) ) { /* assume no display-character RTAS method - use hex display */ + call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex); return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/entry.S linux.ac/arch/ppc/kernel/entry.S --- linux.vanilla/arch/ppc/kernel/entry.S Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/entry.S Sat Jun 10 21:48:23 2000 @@ -31,8 +31,8 @@ #include #include -#define SHOW_SYSCALLS -#define SHOW_SYSCALLS_TASK +#undef SHOW_SYSCALLS +#undef SHOW_SYSCALLS_TASK #ifdef SHOW_SYSCALLS_TASK .data @@ -227,12 +227,15 @@ stw r1,KSP(r3) /* Set old stack pointer */ sync tophys(r0,r4) + CLR_TOP32(r0) mtspr SPRG3,r0 /* Update current THREAD phys addr */ #ifdef CONFIG_8xx /* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */ lwz r9,PGDIR(r4) /* cache the page table root */ tophys(r9,r9) /* convert to phys addr */ mtspr M_TWB,r9 /* Update MMU base address */ + tlbia + SYNC #endif /* CONFIG_8xx */ lwz r1,KSP(r4) /* Load new stack pointer */ /* save the old current 'last' for return value */ @@ -244,6 +247,7 @@ 8: addi r4,r1,INT_FRAME_SIZE /* size of frame */ stw r4,THREAD+KSP(r2) /* save kernel stack pointer */ tophys(r9,r1) + CLR_TOP32(r9) mtspr SPRG2,r9 /* phys exception stack pointer */ 10: lwz r2,_CTR(r1) lwz r0,_LINK(r1) @@ -270,12 +274,13 @@ lwz r0,_MSR(r1) mtspr SRR0,r2 + FIX_SRR1(r0,r2) mtspr SRR1,r0 lwz r0,GPR0(r1) lwz r2,GPR2(r1) lwz r1,GPR1(r1) SYNC - rfi + RFI #ifdef CONFIG_SMP .globl ret_from_smpfork @@ -311,11 +316,7 @@ #ifdef CONFIG_SMP /* get processor # */ lwz r3,PROCESSOR(r2) -#ifndef CONFIG_PPC64 slwi r3,r3,5 -#else -#error not 64-bit ready -#endif add r4,r4,r3 #endif /* CONFIG_SMP */ lwz r5,0(r4) @@ -365,14 +366,17 @@ /* if returning to user mode, set new sprg2 and save kernel SP */ lwz r0,_MSR(r1) - mtspr SRR1,r0 andi. r0,r0,MSR_PR beq+ 1f addi r0,r1,INT_FRAME_SIZE /* size of frame */ stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ tophys(r2,r1) + CLR_TOP32(r2) mtspr SPRG2,r2 /* phys exception stack pointer */ -1: +1: + lwz r0,_MSR(r1) + FIX_SRR1(r0,r2) + mtspr SRR1,r0 lwz r2,_CCR(r1) mtcrf 0xFF,r2 lwz r2,_NIP(r1) @@ -381,7 +385,7 @@ lwz r2,GPR2(r1) lwz r1,GPR1(r1) SYNC - rfi + RFI /* * Fake an interrupt from kernel mode. @@ -423,7 +427,6 @@ stw r0,20(r1) lis r4,rtas_data@ha lwz r4,rtas_data@l(r4) - addis r4,r4,-KERNELBASE@h lis r6,1f@ha /* physical return address for rtas */ addi r6,r6,1f@l addis r6,r6,-KERNELBASE@h @@ -436,20 +439,23 @@ li r0,0 ori r0,r0,MSR_EE|MSR_SE|MSR_BE andc r0,r9,r0 - andi. r9,r9,MSR_ME|MSR_RI + li r10,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP + andc r9,r0,r10 sync /* disable interrupts so SRR0/1 */ mtmsr r0 /* don't get trashed */ mtlr r6 + CLR_TOP32(r7) mtspr SPRG2,r7 mtspr SRR0,r8 mtspr SRR1,r9 - rfi + RFI 1: addis r9,r1,-KERNELBASE@h lwz r8,20(r9) /* get return address */ lwz r9,8(r9) /* original msr value */ + FIX_SRR1(r9,r0) li r0,0 mtspr SPRG2,r0 mtspr SRR0,r8 mtspr SRR1,r9 - rfi /* return to caller */ + RFI /* return to caller */ #endif /* CONFIG_ALL_PPC */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/hashtable.S linux.ac/arch/ppc/kernel/hashtable.S --- linux.vanilla/arch/ppc/kernel/hashtable.S Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/hashtable.S Sat Jun 10 21:48:24 2000 @@ -52,6 +52,13 @@ .globl hash_page hash_page: +#ifdef CONFIG_PPC64BRIDGE + mfmsr r0 + clrldi r0,r0,1 /* make sure it's in 32-bit mode */ + sync + MTMSRD(r0) + isync +#endif #ifdef CONFIG_SMP SAVE_2GPRS(7,r21) eieio @@ -120,28 +127,183 @@ ori r4,r4,0xe04 /* clear out reserved bits */ andc r6,r6,r4 /* PP=2 or 0, when _PAGE_HWWRITE */ +#ifdef CONFIG_POWER4 + /* + * XXX hack hack hack - translate 32-bit "physical" addresses + * in the linux page tables to 42-bit real addresses in such + * a fashion that we can get at the I/O we need to access. + * -- paulus + */ + cmpwi 0,r6,0 + rlwinm r4,r6,16,16,30 + bge 57f + cmplwi 0,r4,0xfe00 + li r5,0x3fd + bne 56f + li r5,0x3ff +56: sldi r5,r5,32 + or r6,r6,r5 +57: +#endif + +#ifdef CONFIG_PPC64BRIDGE /* Construct the high word of the PPC-style PTE */ mfsrin r5,r3 /* get segment reg for segment */ -#ifdef CONFIG_PPC64 + rlwinm r5,r5,0,5,31 sldi r5,r5,12 -#else /* CONFIG_PPC64 */ - rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */ -#endif /* CONFIG_PPC64 */ #ifndef CONFIG_SMP /* do this later for SMP */ -#ifdef CONFIG_PPC64 ori r5,r5,1 /* set V (valid) bit */ -#else /* CONFIG_PPC64 */ +#endif + + rlwimi r5,r3,16,20,24 /* put in API (abbrev page index) */ + /* Get the address of the primary PTE group in the hash table */ + .globl hash_page_patch_A +hash_page_patch_A: + lis r4,Hash_base@h /* base address of hash table */ + rlwimi r4,r5,32-5,25-Hash_bits,24 /* (VSID & hash_mask) << 7 */ + rlwinm r0,r3,32-5,25-Hash_bits,24 /* (PI & hash_mask) << 7 */ + xor r4,r4,r0 /* make primary hash */ + + /* See whether it was a PTE not found exception or a + protection violation. */ + andis. r0,r20,0x4000 + li r2,8 /* PTEs/group */ + bne 10f /* no PTE: go look for an empty slot */ + tlbie r3 /* invalidate TLB entry */ + + /* Search the primary PTEG for a PTE whose 1st dword matches r5 */ + mtctr r2 + addi r3,r4,-16 +1: ldu r0,16(r3) /* get next PTE */ + cmpd 0,r0,r5 + bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ + beq+ found_slot + + /* Search the secondary PTEG for a matching PTE */ + ori r5,r5,0x2 /* set H (secondary hash) bit */ + .globl hash_page_patch_B +hash_page_patch_B: + xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ + xori r3,r3,0xff80 + addi r3,r3,-16 + mtctr r2 +2: ldu r0,16(r3) + cmpd 0,r0,r5 + bdnzf 2,2b + beq+ found_slot + xori r5,r5,0x2 /* clear H bit again */ + + /* Search the primary PTEG for an empty slot */ +10: mtctr r2 + addi r3,r4,-16 /* search primary PTEG */ +1: ldu r0,16(r3) /* get next PTE */ + andi. r0,r0,1 + bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ + beq+ found_empty + + /* Search the secondary PTEG for an empty slot */ + ori r5,r5,0x2 /* set H (secondary hash) bit */ + .globl hash_page_patch_C +hash_page_patch_C: + xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ + xori r3,r3,0xff80 + addi r3,r3,-16 + mtctr r2 +2: ldu r0,16(r3) + andi. r0,r0,1 + bdnzf 2,2b + beq+ found_empty + + /* + * Choose an arbitrary slot in the primary PTEG to overwrite. + * Since both the primary and secondary PTEGs are full, and we + * have no information that the PTEs in the primary PTEG are + * more important or useful than those in the secondary PTEG, + * and we know there is a definite (although small) speed + * advantage to putting the PTE in the primary PTEG, we always + * put the PTE in the primary PTEG. + */ + xori r5,r5,0x2 /* clear H bit again */ + lis r3,next_slot@ha + tophys(r3,r3) + lwz r2,next_slot@l(r3) + addi r2,r2,16 + andi. r2,r2,0x70 +#ifdef CONFIG_POWER4 + /* + * Since we don't have BATs on POWER4, we rely on always having + * PTEs in the hash table to map the hash table and the code + * that manipulates it in virtual mode, namely flush_hash_page and + * flush_hash_segments. Otherwise we can get a DSI inside those + * routines which leads to a deadlock on the hash_table_lock on + * SMP machines. We avoid this by never overwriting the first + * PTE of each PTEG if it is already valid. + * -- paulus. + */ + bne 102f + li r2,0x10 +102: +#endif /* CONFIG_POWER4 */ + stw r2,next_slot@l(r3) + add r3,r4,r2 +11: + /* update counter of evicted pages */ + lis r2,htab_evicts@ha + tophys(r2,r2) + lwz r4,htab_evicts@l(r2) + addi r4,r4,1 + stw r4,htab_evicts@l(r2) + +#ifndef CONFIG_SMP + /* Store PTE in PTEG */ +found_empty: + std r5,0(r3) +found_slot: + std r6,8(r3) + sync + +#else /* CONFIG_SMP */ +/* + * Between the tlbie above and updating the hash table entry below, + * another CPU could read the hash table entry and put it in its TLB. + * There are 3 cases: + * 1. using an empty slot + * 2. updating an earlier entry to change permissions (i.e. enable write) + * 3. taking over the PTE for an unrelated address + * + * In each case it doesn't really matter if the other CPUs have the old + * PTE in their TLB. So we don't need to bother with another tlbie here, + * which is convenient as we've overwritten the register that had the + * address. :-) The tlbie above is mainly to make sure that this CPU comes + * and gets the new PTE from the hash table. + * + * We do however have to make sure that the PTE is never in an invalid + * state with the V bit set. + */ +found_empty: +found_slot: + std r5,0(r3) /* clear V (valid) bit in PTE */ + sync + tlbsync + sync + std r6,8(r3) /* put in correct RPN, WIMG, PP bits */ + sync + ori r5,r5,1 + std r5,0(r3) /* finally set V bit in PTE */ +#endif /* CONFIG_SMP */ + +#else /* CONFIG_PPC64BRIDGE */ + + /* Construct the high word of the PPC-style PTE */ + mfsrin r5,r3 /* get segment reg for segment */ + rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */ + +#ifndef CONFIG_SMP /* do this later for SMP */ oris r5,r5,0x8000 /* set V (valid) bit */ -#endif /* CONFIG_PPC64 */ #endif -#ifdef CONFIG_PPC64 -/* XXX: does this insert the api correctly? -- Cort */ - rlwimi r5,r3,17,21,25 /* put in API (abbrev page index) */ -#else /* CONFIG_PPC64 */ rlwimi r5,r3,10,26,31 /* put in API (abbrev page index) */ -#endif /* CONFIG_PPC64 */ /* Get the address of the primary PTE group in the hash table */ .globl hash_page_patch_A hash_page_patch_A: @@ -160,89 +322,44 @@ /* Search the primary PTEG for a PTE whose 1st word matches r5 */ mtctr r2 addi r3,r4,-8 -1: -#ifdef CONFIG_PPC64 - lwzu r0,16(r3) /* get next PTE */ -#else - lwzu r0,8(r3) /* get next PTE */ -#endif +1: lwzu r0,8(r3) /* get next PTE */ cmp 0,r0,r5 bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ beq+ found_slot /* Search the secondary PTEG for a matching PTE */ -#ifdef CONFIG_PPC64 - ori r5,r5,0x2 /* set H (secondary hash) bit */ -#else ori r5,r5,0x40 /* set H (secondary hash) bit */ -#endif .globl hash_page_patch_B hash_page_patch_B: xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ xori r3,r3,0xffc0 -#ifdef CONFIG_PPC64 - addi r3,r3,-16 -#else addi r3,r3,-8 -#endif mtctr r2 -2: -#ifdef CONFIG_PPC64 - lwzu r0,16(r3) -#else - lwzu r0,8(r3) -#endif +2: lwzu r0,8(r3) cmp 0,r0,r5 bdnzf 2,2b beq+ found_slot -#ifdef CONFIG_PPC64 - xori r5,r5,0x2 /* clear H bit again */ -#else xori r5,r5,0x40 /* clear H bit again */ -#endif /* Search the primary PTEG for an empty slot */ 10: mtctr r2 -#ifdef CONFIG_PPC64 - addi r3,r4,-16 /* search primary PTEG */ -#else addi r3,r4,-8 /* search primary PTEG */ -#endif -1: -#ifdef CONFIG_PPC64 - lwzu r0,16(r3) /* get next PTE */ - andi. r0,r0,1 -#else - lwzu r0,8(r3) /* get next PTE */ +1: lwzu r0,8(r3) /* get next PTE */ rlwinm. r0,r0,0,0,0 /* only want to check valid bit */ -#endif bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */ beq+ found_empty /* Search the secondary PTEG for an empty slot */ -#ifdef CONFIG_PPC64 - ori r5,r5,0x2 /* set H (secondary hash) bit */ -#else ori r5,r5,0x40 /* set H (secondary hash) bit */ -#endif .globl hash_page_patch_C hash_page_patch_C: xoris r3,r4,Hash_msk>>16 /* compute secondary hash */ xori r3,r3,0xffc0 -#ifdef CONFIG_PPC64 - addi r3,r3,-16 -#else addi r3,r3,-8 -#endif mtctr r2 2: -#ifdef CONFIG_PPC64 - lwzu r0,16(r3) - andi. r0,r0,1 -#else lwzu r0,8(r3) rlwinm. r0,r0,0,0,0 /* only want to check valid bit */ -#endif bdnzf 2,2b beq+ found_empty @@ -255,21 +372,12 @@ * advantage to putting the PTE in the primary PTEG, we always * put the PTE in the primary PTEG. */ -#ifdef CONFIG_PPC64 - xori r5,r5,0x2 /* clear H bit again */ -#else xori r5,r5,0x40 /* clear H bit again */ -#endif lis r3,next_slot@ha tophys(r3,r3) lwz r2,next_slot@l(r3) -#ifdef CONFIG_PPC64 - addi r2,r2,16 - andi. r2,r2,0x78 -#else addi r2,r2,8 andi. r2,r2,0x38 -#endif stw r2,next_slot@l(r3) add r3,r4,r2 11: @@ -283,17 +391,9 @@ #ifndef CONFIG_SMP /* Store PTE in PTEG */ found_empty: -#ifdef CONFIG_PPC64 - std r5,0(r3) -#else stw r5,0(r3) -#endif found_slot: -#ifdef CONFIG_PPC64 - std r6,8(r3) -#else stw r6,4(r3) -#endif sync #else /* CONFIG_SMP */ @@ -325,6 +425,7 @@ oris r5,r5,0x8000 stw r5,0(r3) /* finally set V bit in PTE */ #endif /* CONFIG_SMP */ +#endif /* CONFIG_PPC64BRIDGE */ /* * Update the hash table miss count. We only want misses here @@ -371,7 +472,7 @@ lwz r22,GPR22(r21) lwz r23,GPR23(r21) lwz r21,GPR21(r21) - rfi + RFI #ifdef CONFIG_SMP hash_page_out: @@ -410,7 +511,7 @@ #endif blr 99: -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) /* Note - we had better not do anything which could generate a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ @@ -419,6 +520,8 @@ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC +#endif +#ifdef CONFIG_SMP lis r9,hash_table_lock@h ori r9,r9,hash_table_lock@l lwz r8,PROCESSOR(r2) @@ -430,6 +533,7 @@ bne- 10b eieio #endif +#ifndef CONFIG_PPC64BRIDGE rlwinm r3,r3,7,1,24 /* put VSID lower limit in position */ oris r3,r3,0x8000 /* set V bit */ rlwinm r4,r4,7,1,24 /* put VSID upper limit in position */ @@ -448,6 +552,26 @@ blt 2f /* branch if out of range */ stw r0,0(r5) /* invalidate entry */ 2: bdnz 1b /* continue with loop */ +#else /* CONFIG_PPC64BRIDGE */ + rldic r3,r3,12,20 /* put VSID lower limit in position */ + ori r3,r3,1 /* set V bit */ + rldic r4,r4,12,20 /* put VSID upper limit in position */ + ori r4,r4,0xfff /* set V bit, API etc. */ + lis r6,Hash_size@ha + lwz r6,Hash_size@l(r6) /* size in bytes */ + srwi r6,r6,4 /* # PTEs */ + mtctr r6 + addi r5,r5,-16 + li r0,0 +1: ldu r6,16(r5) /* get next tag word */ + cmpld 0,r6,r3 + cmpld 1,r6,r4 + cror 0,0,5 /* set cr0.lt if out of range */ + blt 2f /* branch if out of range */ + std r0,0(r5) /* invalidate entry */ +2: bdnz 1b /* continue with loop */ +#endif /* CONFIG_PPC64BRIDGE */ + sync tlbia sync @@ -456,6 +580,8 @@ sync lis r3,hash_table_lock@ha stw r0,hash_table_lock@l(r3) +#endif +#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) mtmsr r10 SYNC #endif @@ -479,7 +605,7 @@ #endif blr 99: -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) /* Note - we had better not do anything which could generate a hash table miss while we have the hash table locked, or we'll get a deadlock. -paulus */ @@ -488,6 +614,8 @@ rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ mtmsr r0 SYNC +#endif +#ifdef CONFIG_SMP lis r9,hash_table_lock@h ori r9,r9,hash_table_lock@l lwz r8,PROCESSOR(r2) @@ -499,6 +627,7 @@ bne- 10b eieio #endif +#ifndef CONFIG_PPC64BRIDGE rlwinm r3,r3,11,1,20 /* put context into vsid */ rlwimi r3,r4,11,21,24 /* put top 4 bits of va into vsid */ oris r3,r3,0x8000 /* set V (valid) bit */ @@ -528,6 +657,37 @@ bne 4f /* if we didn't find it */ 3: li r0,0 stw r0,0(r7) /* invalidate entry */ +#else /* CONFIG_PPC64BRIDGE */ + rldic r3,r3,16,16 /* put context into vsid (<< 12) */ + rlwimi r3,r4,16,16,24 /* top 4 bits of va and API */ + ori r3,r3,1 /* set V (valid) bit */ + rlwinm r7,r4,32-5,9,24 /* get page index << 7 */ + srdi r5,r3,5 /* vsid << 7 */ + rlwinm r5,r5,0,1,24 /* vsid << 7 (limited to 24 bits) */ + xor r7,r7,r5 /* primary hash << 7 */ + lis r5,Hash_mask@ha + lwz r5,Hash_mask@l(r5) /* hash mask */ + slwi r5,r5,7 /* << 7 */ + and r7,r7,r5 + add r6,r6,r7 /* address of primary PTEG */ + li r8,8 + mtctr r8 + addi r7,r6,-16 +1: ldu r0,16(r7) /* get next PTE */ + cmpd 0,r0,r3 /* see if tag matches */ + bdnzf 2,1b /* while --ctr != 0 && !cr0.eq */ + beq 3f /* if we found it */ + ori r3,r3,2 /* set H (alt. hash) bit */ + xor r6,r6,r5 /* address of secondary PTEG */ + mtctr r8 + addi r7,r6,-16 +2: ldu r0,16(r7) /* get next PTE */ + cmpd 0,r0,r3 /* see if tag matches */ + bdnzf 2,2b /* while --ctr != 0 && !cr0.eq */ + bne 4f /* if we didn't find it */ +3: li r0,0 + std r0,0(r7) /* invalidate entry */ +#endif /* CONFIG_PPC64BRIDGE */ 4: sync tlbie r4 /* in hw tlb too */ sync @@ -536,6 +696,8 @@ sync li r0,0 stw r0,0(r9) /* clear hash_table_lock */ +#endif +#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE) mtmsr r10 SYNC #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/head.S linux.ac/arch/ppc/kernel/head.S --- linux.vanilla/arch/ppc/kernel/head.S Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/head.S Sat Jun 10 21:48:24 2000 @@ -36,7 +36,19 @@ #include #endif -#ifdef CONFIG_PPC64 +#ifndef CONFIG_PPC64BRIDGE +CACHELINE_BYTES = 32 +LG_CACHELINE_BYTES = 5 +CACHELINE_MASK = 0x1f +CACHELINE_WORDS = 8 +#else +CACHELINE_BYTES = 128 +LG_CACHELINE_BYTES = 7 +CACHELINE_MASK = 0x7f +CACHELINE_WORDS = 32 +#endif /* CONFIG_PPC64BRIDGE */ + +#ifdef CONFIG_PPC64BRIDGE #define LOAD_BAT(n, reg, RA, RB) \ ld RA,(n*32)+0(reg); \ ld RB,(n*32)+8(reg); \ @@ -47,7 +59,7 @@ mtspr DBAT##n##U,RA; \ mtspr DBAT##n##L,RB; \ -#else /* CONFIG_PPC64 */ +#else /* CONFIG_PPC64BRIDGE */ /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ #define LOAD_BAT(n, reg, RA, RB) \ @@ -65,7 +77,7 @@ mtspr DBAT##n##U,RA; \ mtspr DBAT##n##L,RB; \ 1: -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ .text .globl _stext @@ -125,16 +137,6 @@ .globl __start __start: -#ifdef CONFIG_PPC64 -/* - * Go into 32-bit mode to boot. OF should do this for - * us already but just in case... - * -- Cort - */ - mfmsr r10 - clrldi r10,r10,3 - mtmsr r10 -#endif /* * We have to do any OF calls before we map ourselves to KERNELBASE, * because OF may have I/O devices mapped into that area @@ -166,67 +168,23 @@ bl flush_tlbs #endif +#ifndef CONFIG_POWER4 + /* POWER4 doesn't have BATs */ + bl initial_bats +#else /* CONFIG_POWER4 */ /* - * Use the first pair of BAT registers to map the 1st 16MB - * of RAM to KERNELBASE. From this point on we can't safely - * call OF any more. + * Load up the SDR1 and segment register values now + * since we don't have the BATs. */ - lis r11,KERNELBASE@h -#ifndef CONFIG_PPC64 - mfspr r9,PVR - rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ - cmpi 0,r9,1 - bne 4f - ori r11,r11,4 /* set up BAT registers for 601 */ - li r8,0x7f /* valid, block length = 8MB */ - oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ - oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ - mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */ - mtspr IBAT0L,r8 /* lower BAT register */ - mtspr IBAT1U,r9 - mtspr IBAT1L,r10 - b 5f -#endif /* CONFIG_PPC64 */ - -4: tophys(r8,r11) -#ifdef CONFIG_SMP - ori r8,r8,0x12 /* R/W access, M=1 */ -#else - ori r8,r8,2 /* R/W access */ -#endif /* CONFIG_SMP */ -#ifdef CONFIG_APUS - ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ -#else - ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ -#endif /* CONFIG_APUS */ - -#ifdef CONFIG_PPC64 - /* clear out the high 32 bits in the BAT */ - clrldi r11,r11,32 - clrldi r8,r8,32 - /* turn off the pagetable mappings just in case */ - clrldi r16,r16,63 - mtsdr1 r16 -#else /* CONFIG_PPC64 */ - /* - * If the MMU is off clear the bats. See clear_bat() -- Cort - */ - mfmsr r20 - andi. r20,r20,MSR_DR - bne 100f - bl clear_bats -100: -#endif /* CONFIG_PPC64 */ - mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ - mtspr DBAT0U,r11 /* bit in upper BAT register */ - mtspr IBAT0L,r8 - mtspr IBAT0U,r11 -#if 0 /* Useful debug code, please leave in for now so I don't have to - * look at docs when I need to setup a BAT ... - */ - bl setup_screen_bat -#endif -5: isync + bl reloc_offset + addis r4,r3,_SDR1@ha /* get the value from _SDR1 */ + lwz r4,_SDR1@l(r4) /* assume hash table below 4GB */ + mtspr SDR1,r4 + slbia + lis r5,0x2000 /* set pseudo-segment reg 12 */ + ori r5,r5,12 + mtsr 12,r5 +#endif /* CONFIG_POWER4 */ #ifndef CONFIG_APUS /* @@ -267,7 +225,21 @@ ori r0,r0,start_here@l mtspr SRR0,r0 SYNC - rfi /* enables MMU */ + RFI /* enables MMU */ + +#ifdef CONFIG_SMP + .globl __secondary_hold +__secondary_hold: + /* tell the master we're here */ + stw r3,4(0) +100: lwz r4,0(0) + /* wait until we're told to start */ + cmpw 0,r4,r3 + bne 100b + /* our cpu # was at addr 0 - go */ + mr r24,r3 /* cpu # */ + b __secondary_start +#endif /* * Exception entry code. This code runs with address translation @@ -284,7 +256,8 @@ bne 1f; \ tophys(r21,r1); /* use tophys(kernel sp) otherwise */ \ subi r21,r21,INT_FRAME_SIZE; /* alloc exc. frame */\ -1: stw r20,_CCR(r21); /* save registers */ \ +1: CLR_TOP32(r21); \ + stw r20,_CCR(r21); /* save registers */ \ stw r22,GPR22(r21); \ stw r23,GPR23(r21); \ mfspr r20,SPRG0; \ @@ -341,8 +314,13 @@ /* Data access exception. */ . = 0x300 +#ifdef CONFIG_PPC64BRIDGE + b DataAccess +DataAccessCont: +#else DataAccess: EXCEPTION_PROLOG +#endif /* CONFIG_PPC64BRIDGE */ mfspr r20,DSISR andis. r0,r20,0xa470 /* weird error? */ bne 1f /* if not, try to put a PTE */ @@ -361,10 +339,30 @@ .long do_page_fault .long ret_from_except +#ifdef CONFIG_PPC64BRIDGE +/* SLB fault on data access. */ + . = 0x380 + b DataSegment +DataSegmentCont: + mfspr r4,DAR + stw r4,_DAR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + bl transfer_to_handler + .long UnknownException + .long ret_from_except +#endif /* CONFIG_PPC64BRIDGE */ + /* Instruction access exception. */ . = 0x400 +#ifdef CONFIG_PPC64BRIDGE + b InstructionAccess +InstructionAccessCont: +#else InstructionAccess: EXCEPTION_PROLOG +#endif /* CONFIG_PPC64BRIDGE */ andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ mr r3,r22 /* into the hash table */ @@ -380,6 +378,19 @@ .long do_page_fault .long ret_from_except +#ifdef CONFIG_PPC64BRIDGE +/* SLB fault on instruction access. */ + . = 0x480 + b InstructionSegment +InstructionSegmentCont: + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + bl transfer_to_handler + .long UnknownException + .long ret_from_except +#endif /* CONFIG_PPC64BRIDGE */ + /* External interrupt */ . = 0x500; HardwareInterrupt: @@ -526,7 +537,7 @@ tlbli r3 mfspr r3,SRR1 /* Need to restore CR0 */ mtcrf 0x80,r3 - rfi + rfi InstructionAddressInvalid: mfspr r3,SRR1 rlwinm r1,r3,9,6,6 /* Get load/store bit */ @@ -593,7 +604,7 @@ tlbld r3 mfspr r3,SRR1 /* Need to restore CR0 */ mtcrf 0x80,r3 - rfi + rfi DataAddressInvalid: mfspr r3,SRR1 rlwinm r1,r3,9,6,6 /* Get load/store bit */ @@ -658,7 +669,7 @@ tlbld r3 mfspr r3,SRR1 /* Need to restore CR0 */ mtcrf 0x80,r3 - rfi + rfi STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint) STD_EXCEPTION(0x1400, SMI, SMIException) @@ -706,7 +717,22 @@ EXCEPTION_PROLOG b trap_0f_cont #endif /* CONFIG_ALTIVEC */ - + +#ifdef CONFIG_PPC64BRIDGE +DataAccess: + EXCEPTION_PROLOG + b DataAccessCont +InstructionAccess: + EXCEPTION_PROLOG + b InstructionAccessCont +DataSegment: + EXCEPTION_PROLOG + b DataSegmentCont +InstructionSegment: + EXCEPTION_PROLOG + b InstructionSegmentCont +#endif /* CONFIG_PPC64BRIDGE */ + /* * This code finishes saving the registers to the exception frame * and jumps to the appropriate handler for the exception, turning @@ -741,11 +767,12 @@ bgt- stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */ lwz r24,0(r23) /* virtual address of handler */ lwz r23,4(r23) /* where to go when done */ + FIX_SRR1(r20,r22) mtspr SRR0,r24 mtspr SRR1,r20 mtlr r23 SYNC - rfi /* jump to handler, enable MMU */ + RFI /* jump to handler, enable MMU */ /* * On kernel stack overflow, load up an initial stack pointer @@ -759,10 +786,11 @@ lis r24,StackOverflow@ha addi r24,r24,StackOverflow@l li r20,MSR_KERNEL + FIX_SRR1(r20,r22) mtspr SRR0,r24 mtspr SRR1,r20 SYNC - rfi + RFI /* * Disable FP for the task which had the FPU previously, @@ -774,8 +802,11 @@ load_up_fpu: mfmsr r5 ori r5,r5,MSR_FP +#ifdef CONFIG_PPC64BRIDGE + clrldi r5,r5,1 /* turn off 64-bit mode */ +#endif /* CONFIG_PPC64BRIDGE */ SYNC - mtmsr r5 /* enable use of fpu now */ + MTMSRD(r5) /* enable use of fpu now */ SYNC /* * For SMP, we don't do lazy FPU switching because it just gets too @@ -827,7 +858,7 @@ REST_2GPRS(22, r21) lwz r21,GPR21(r21) SYNC - rfi + RFI /* * FP unavailable trap from kernel - print a message, but let @@ -919,7 +950,7 @@ REST_2GPRS(22, r21) lwz r21,GPR21(r21) SYNC - rfi + RFI /* * AltiVec unavailable trap from kernel - print a message, but let @@ -1046,7 +1077,7 @@ copy_and_flush: addi r5,r5,-4 addi r6,r6,-4 -4: li r0,8 +4: li r0,CACHELINE_WORDS mtctr r0 3: addi r6,r6,4 /* copy a cache line */ lwzx r0,r6,r4 @@ -1195,27 +1226,6 @@ #endif /* CONFIG_APUS */ #ifdef CONFIG_SMP - .globl __secondary_hold -__secondary_hold: - /* tell the master we're here */ - lis r5,0x4@h - ori r5,r5,0x4@l - stw r3,0(r5) - dcbf 0,r5 -100: - lis r5,0 - dcbi 0,r5 - lwz r4,0(r5) - /* wait until we're told to start */ - cmp 0,r4,r3 - bne 100b - /* our cpu # was at addr 0 - go */ - lis r5,__secondary_start@h - ori r5,r5,__secondary_start@l - tophys(r5,r5) - mtlr r5 - mr r24,r3 /* cpu # */ - blr #ifdef CONFIG_GEMINI .globl __secondary_start_gemini __secondary_start_gemini: @@ -1243,7 +1253,15 @@ .globl __secondary_start __secondary_start: +#ifdef CONFIG_PPC64BRIDGE + mfmsr r0 + clrldi r0,r0,1 /* make sure it's in 32-bit mode */ + sync + MTMSRD(r0) + isync +#else bl enable_caches +#endif /* get current */ lis r2,current_set@h @@ -1264,6 +1282,7 @@ /* ptr to phys current thread */ tophys(r4,r2) addi r4,r4,THREAD /* phys address of our thread_struct */ + CLR_TOP32(r4) mtspr SPRG3,r4 li r3,0 mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ @@ -1275,7 +1294,7 @@ mtspr SRR0,r3 mtspr SRR1,r4 SYNC - rfi + RFI #endif /* CONFIG_SMP */ /* @@ -1333,14 +1352,11 @@ tophys(r6,r6) lwz r6,_SDR1@l(r6) mtspr SDR1,r6 -#ifdef CONFIG_PPC64 - /* clear the v bit in the ASR so we can - * behave as if we have segment registers - * -- Cort - */ - clrldi r6,r6,63 +#ifdef CONFIG_PPC64BRIDGE + /* clear the ASR so we only use the pseudo-segment registers. */ + li r6,0 mtasr r6 -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ li r0,16 /* load up segment register values */ mtctr r0 /* for context 0 */ lis r3,0x2000 /* Ku = 1, VSID = 0 */ @@ -1349,6 +1365,7 @@ addi r3,r3,1 /* increment VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b +#ifndef CONFIG_POWER4 /* Load the BAT registers with the values set up by MMU_init. MMU_init takes care of whether we're on a 601 or not. */ mfpvr r3 @@ -1361,17 +1378,29 @@ LOAD_BAT(1,r3,r4,r5) LOAD_BAT(2,r3,r4,r5) LOAD_BAT(3,r3,r4,r5) +#endif /* CONFIG_POWER4 */ blr /* * This is where the main kernel code starts. */ start_here: +#ifndef CONFIG_PPC64BRIDGE bl enable_caches +#endif /* ptr to current */ lis r2,init_task_union@h ori r2,r2,init_task_union@l + /* Set up for using our exception vectors */ + /* ptr to phys current thread */ + tophys(r4,r2) + addi r4,r4,THREAD /* init task's THREAD */ + CLR_TOP32(r4) + mtspr SPRG3,r4 + li r3,0 + mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ + /* Clear out the BSS */ lis r11,_end@ha addi r11,r11,_end@l @@ -1424,10 +1453,11 @@ ori r4,r4,2f@l tophys(r4,r4) li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR) + FIX_SRR1(r3,r5) mtspr SRR0,r4 mtspr SRR1,r3 SYNC - rfi + RFI /* Load up the kernel context */ 2: SYNC /* Force all PTE updates to finish */ @@ -1439,34 +1469,30 @@ #endif bl load_up_mmu - -/* Set up for using our exception vectors */ - /* ptr to phys current thread */ - tophys(r4,r2) - addi r4,r4,THREAD /* init task's THREAD */ - mtspr SPRG3,r4 - li r3,0 - mtspr SPRG2,r3 /* 0 => r1 has kernel sp */ /* Now turn on the MMU for real! */ li r4,MSR_KERNEL + FIX_SRR1(r4,r5) lis r3,start_kernel@h ori r3,r3,start_kernel@l mtspr SRR0,r3 mtspr SRR1,r4 SYNC - rfi /* enable MMU and jump to start_kernel */ + RFI /* * Set up the segment registers for a new context. */ - .globl set_context -set_context: +_GLOBAL(set_context) rlwinm r3,r3,4,8,27 /* VSID = context << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ mtctr r0 li r4,0 -3: mtsrin r3,r4 +3: +#ifdef CONFIG_PPC64BRIDGE + slbie r4 +#endif /* CONFIG_PPC64BRIDGE */ + mtsrin r3,r4 addi r3,r3,1 /* next VSID */ addis r4,r4,0x1000 /* address of next segment */ bdnz 3b @@ -1511,7 +1537,7 @@ #ifndef CONFIG_GEMINI flush_tlbs: - lis r20, 0x1000 + lis r20, 0x40 1: addic. r20, r20, -0x1000 tlbie r20 blt 1b @@ -1522,30 +1548,79 @@ addi r4, r3, __after_prom_start - _start mfmsr r3 andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */ - beq 1f + beqlr ori r3,r3,MSR_DR|MSR_IR xori r3,r3,MSR_DR|MSR_IR mtspr SRR0,r4 mtspr SRR1,r3 sync - rfi -1: blr + RFI #endif -#if 0 /* That's useful debug stuff */ +#ifndef CONFIG_POWER4 +/* + * Use the first pair of BAT registers to map the 1st 16MB + * of RAM to KERNELBASE. From this point on we can't safely + * call OF any more. + */ +initial_bats: + lis r11,KERNELBASE@h +#ifndef CONFIG_PPC64BRIDGE + mfspr r9,PVR + rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ + cmpi 0,r9,1 + bne 4f + ori r11,r11,4 /* set up BAT registers for 601 */ + li r8,0x7f /* valid, block length = 8MB */ + oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ + oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ + mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */ + mtspr IBAT0L,r8 /* lower BAT register */ + mtspr IBAT1U,r9 + mtspr IBAT1L,r10 + isync + blr +#endif /* CONFIG_PPC64BRIDGE */ + +4: tophys(r8,r11) +#ifdef CONFIG_SMP + ori r8,r8,0x12 /* R/W access, M=1 */ +#else + ori r8,r8,2 /* R/W access */ +#endif /* CONFIG_SMP */ +#ifdef CONFIG_APUS + ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ +#else + ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ +#endif /* CONFIG_APUS */ + +#ifdef CONFIG_PPC64BRIDGE + /* clear out the high 32 bits in the BAT */ + clrldi r11,r11,32 + clrldi r8,r8,32 +#endif /* CONFIG_PPC64BRIDGE */ + mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ + mtspr DBAT0U,r11 /* bit in upper BAT register */ + mtspr IBAT0L,r8 + mtspr IBAT0U,r11 +#if 0 /* Useful debug code, please leave in for now so I don't have to + * look at docs when I need to setup a BAT ... + */ setup_screen_bat: li r3,0 mtspr DBAT1U,r3 - mtspr IBAT1U,r3 - lis r3, 0x8200 - ori r4,r3,0x2a + lis r3,0xfa00 + CLR_TOP32(r3) + lis r4,0xfa00 + CLR_TOP32(r4) + ori r4,r4,0x2a mtspr DBAT1L,r4 - mtspr IBAT1L,r4 ori r3,r3,(BL_16M<<2)|0x2 /* set up BAT registers for 604 */ mtspr DBAT1U,r3 - mtspr IBAT1U,r3 - blr #endif + isync + blr +#endif /* CONFIG_POWER4 */ #ifdef CONFIG_8260 /* Jump into the system reset for the rom. @@ -1568,7 +1643,7 @@ mtlr r4 blr #endif - + /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the data segment, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/head_8xx.S linux.ac/arch/ppc/kernel/head_8xx.S --- linux.vanilla/arch/ppc/kernel/head_8xx.S Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/head_8xx.S Sat Jun 10 21:48:24 2000 @@ -31,6 +31,13 @@ #include #include +/* XXX need definitions here for 16 byte cachelines on some/all 8xx + -- paulus */ +CACHELINE_BYTES = 32 +LG_CACHELINE_BYTES = 5 +CACHELINE_MASK = 0x1f +CACHELINE_WORDS = 8 + .text .globl _stext _stext: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/i8259.c linux.ac/arch/ppc/kernel/i8259.c --- linux.vanilla/arch/ppc/kernel/i8259.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/i8259.c Sat Jun 10 21:48:24 2000 @@ -104,11 +104,6 @@ 0 }; -static void -no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ -} - void __init i8259_init(void) { /* init master interrupt controller */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/irq.c linux.ac/arch/ppc/kernel/irq.c --- linux.vanilla/arch/ppc/kernel/irq.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/irq.c Sat Jun 10 21:48:24 2000 @@ -286,10 +286,18 @@ action = action->next; } while ( action ); __cli(); - unmask_irq(irq); + if (irq_desc[irq].handler) { + if (irq_desc[irq].handler->end) + irq_desc[irq].handler->end(irq); + else if (irq_desc[irq].handler->enable) + irq_desc[irq].handler->enable(irq); + } } else { ppc_spurious_interrupts++; - disable_irq( irq ); + printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq); + disable_irq(irq); + if (irq_desc[irq].handler->end) + irq_desc[irq].handler->end(irq); } } @@ -301,6 +309,7 @@ /* every arch is required to have a get_irq -- Cort */ irq = ppc_md.get_irq( regs ); + if ( irq < 0 ) { /* -2 means ignore, already handled */ @@ -313,7 +322,7 @@ goto out; } ppc_irq_dispatch_handler( regs, irq ); - if ( ppc_md.post_irq ) + if (ppc_md.post_irq) ppc_md.post_irq( regs, irq ); out: @@ -769,4 +778,8 @@ continue; register_irq_proc(i); } +} + +void no_action(int irq, void *dev, struct pt_regs *regs) +{ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/m8260_setup.c linux.ac/arch/ppc/kernel/m8260_setup.c --- linux.vanilla/arch/ppc/kernel/m8260_setup.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/m8260_setup.c Sun Jun 4 21:10:56 2000 @@ -167,9 +167,11 @@ bp = (bd_t *)__res; - len += sprintf(len+buffer,"clock\t\t: %dMHz\n" - "bus clock\t: %dMHz\n", + len += sprintf(len+buffer,"core clock\t: %d MHz\n" + "CPM clock\t: %d MHz\n" + "bus clock\t: %d MHz\n", bp->bi_intfreq /*/ 1000000*/, + bp->bi_cpmfreq /*/ 1000000*/, bp->bi_busfreq /*/ 1000000*/); return len; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/misc.S linux.ac/arch/ppc/kernel/misc.S --- linux.vanilla/arch/ppc/kernel/misc.S Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/misc.S Sat Jun 10 21:48:24 2000 @@ -22,11 +22,14 @@ #include "ppc_asm.h" #if defined(CONFIG_4xx) || defined(CONFIG_8xx) -CACHE_LINE_SIZE = 16 -LG_CACHE_LINE_SIZE = 4 +#define CACHE_LINE_SIZE 16 +#define LG_CACHE_LINE_SIZE 4 +#elif !defined(CONFIG_PPC64BRIDGE) +#define CACHE_LINE_SIZE 32 +#define LG_CACHE_LINE_SIZE 5 #else -CACHE_LINE_SIZE = 32 -LG_CACHE_LINE_SIZE = 5 +#define CACHE_LINE_SIZE 128 +#define LG_CACHE_LINE_SIZE 7 #endif /* CONFIG_4xx || CONFIG_8xx */ .text @@ -140,12 +143,33 @@ * Flush MMU TLB */ _GLOBAL(_tlbia) +#if defined(CONFIG_SMP) + mfmsr r10 + sync + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + mtmsr r0 + SYNC + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,10 +10: lwarx r7,0,r9 + cmpi 0,r7,0 + bne- 10b + stwcx. r8,0,r9 + bne- 10b + eieio +#endif /* CONFIG_SMP */ sync tlbia sync #ifdef CONFIG_SMP tlbsync sync + li r0,0 + stw r0,0(r9) /* clear hash_table_lock */ + mtmsr r10 + SYNC #endif blr @@ -153,11 +177,32 @@ * Flush MMU TLB for a particular address */ _GLOBAL(_tlbie) +#if defined(CONFIG_SMP) + mfmsr r10 + sync + rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */ + mtmsr r0 + SYNC + lis r9,hash_table_lock@h + ori r9,r9,hash_table_lock@l + lwz r8,PROCESSOR(r2) + oris r8,r8,11 +10: lwarx r7,0,r9 + cmpi 0,r7,0 + bne- 10b + stwcx. r8,0,r9 + bne- 10b + eieio +#endif /* CONFIG_SMP */ tlbie r3 sync #ifdef CONFIG_SMP tlbsync sync + li r0,0 + stw r0,0(r9) /* clear hash_table_lock */ + mtmsr r10 + SYNC #endif blr @@ -305,6 +350,16 @@ * the destination into cache). This requires that the destination * is cacheable. */ +#define COPY_16_BYTES \ + lwz r6,4(r4); \ + lwz r7,8(r4); \ + lwz r8,12(r4); \ + lwzu r9,16(r4); \ + stw r6,4(r3); \ + stw r7,8(r3); \ + stw r8,12(r3); \ + stwu r9,16(r3) + _GLOBAL(copy_page) li r0,4096/CACHE_LINE_SIZE mtctr r0 @@ -312,22 +367,20 @@ addi r4,r4,-4 li r5,4 1: dcbz r5,r3 - lwz r6,4(r4) - lwz r7,8(r4) - lwz r8,12(r4) - lwzu r9,16(r4) - stw r6,4(r3) - stw r7,8(r3) - stw r8,12(r3) - stwu r9,16(r3) - lwz r6,4(r4) - lwz r7,8(r4) - lwz r8,12(r4) - lwzu r9,16(r4) - stw r6,4(r3) - stw r7,8(r3) - stw r8,12(r3) - stwu r9,16(r3) + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 32 + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 64 + COPY_16_BYTES + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 128 + COPY_16_BYTES + COPY_16_BYTES + COPY_16_BYTES + COPY_16_BYTES +#endif +#endif +#endif bdnz 1b blr @@ -464,7 +517,7 @@ * The *_ns versions don't do byte-swapping. */ _GLOBAL(_insb) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,1 blelr- @@ -475,7 +528,7 @@ blr _GLOBAL(_outsb) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,1 blelr- @@ -486,7 +539,7 @@ blr _GLOBAL(_insw) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr- @@ -497,7 +550,7 @@ blr _GLOBAL(_outsw) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr- @@ -508,7 +561,7 @@ blr _GLOBAL(_insl) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr- @@ -519,7 +572,7 @@ blr _GLOBAL(_outsl) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr- @@ -531,7 +584,7 @@ _GLOBAL(ide_insw) _GLOBAL(_insw_ns) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr- @@ -543,7 +596,7 @@ _GLOBAL(ide_outsw) _GLOBAL(_outsw_ns) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr- @@ -554,7 +607,7 @@ blr _GLOBAL(_insl_ns) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr- @@ -565,7 +618,7 @@ blr _GLOBAL(_outsl_ns) - cmpw 0,r5,0 + cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr- @@ -650,6 +703,12 @@ _GLOBAL(_get_PVR) mfspr r3,PVR blr + +#ifdef CONFIG_8xx +_GLOBAL(_get_IMMR) + mfspr r3, 638 + blr +#endif _GLOBAL(_get_HID0) mfspr r3,HID0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/open_pic.c linux.ac/arch/ppc/kernel/open_pic.c --- linux.vanilla/arch/ppc/kernel/open_pic.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/open_pic.c Sat Jun 10 21:48:24 2000 @@ -97,10 +97,6 @@ #define check_arg_cpu(cpu) do {} while (0) #endif -void no_action(int ir1, void *dev, struct pt_regs *regs) -{ -} - #ifdef CONFIG_SMP void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) { @@ -293,7 +289,7 @@ void find_ISUs(void) { -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE /* hardcode this for now since the IBM 260 is the only thing with * a distributed openpic right now. -- Cort */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/pmac_time.c linux.ac/arch/ppc/kernel/pmac_time.c --- linux.vanilla/arch/ppc/kernel/pmac_time.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/pmac_time.c Sun Jun 4 21:10:56 2000 @@ -28,6 +28,8 @@ #include "time.h" +extern rwlock_t xtime_lock; + /* Apparently the RTC stores seconds since 1 Jan 1904 */ #define RTC_OFFSET 2082844800 @@ -151,16 +153,21 @@ static int time_sleep_notify(struct pmu_sleep_notifier *self, int when) { static unsigned long time_diff; + unsigned long flags; switch (when) { case PBOOK_SLEEP_NOW: + read_lock_irqsave(&xtime_lock, flags); time_diff = xtime.tv_sec - pmac_get_rtc_time(); + read_unlock_irqrestore(&xtime_lock, flags); break; case PBOOK_WAKE: + write_lock_irqsave(&xtime_lock, flags); xtime.tv_sec = pmac_get_rtc_time() + time_diff; xtime.tv_usec = 0; set_dec(decrementer_count); last_rtc_update = xtime.tv_sec; + write_unlock_irqrestore(&xtime_lock, flags); break; } return PBOOK_SLEEP_OK; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/ppc_asm.h linux.ac/arch/ppc/kernel/ppc_asm.h --- linux.vanilla/arch/ppc/kernel/ppc_asm.h Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/ppc_asm.h Sat Jun 10 21:48:24 2000 @@ -73,11 +73,13 @@ /* * This instruction is not implemented on the PPC 603 or 601; however, on * the 403GCX and 405GP tlbia IS defined and tlbie is not. + * All of these instructions exist in the 8xx, they have magical powers, + * and they must be used. */ -#if !defined(CONFIG_4xx) +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) #define tlbia \ - li r4,128; \ + li r4,1024; \ mtctr r4; \ lis r4,KERNELBASE@h; \ 0: tlbie r4; \ @@ -102,3 +104,25 @@ .align 1; \ .long 0b; \ .previous + +/* + * On 64-bit cpus, we use the rfid instruction instead of rfi, but + * we then have to make sure we preserve the top 32 bits except for + * the 64-bit mode bit, which we clear. + */ +#ifdef CONFIG_PPC64BRIDGE +#define FIX_SRR1(ra, rb) \ + mr rb,ra; \ + mfmsr ra; \ + clrldi ra,ra,1; /* turn off 64-bit mode */ \ + rldimi ra,rb,0,32 +#define RFI .long 0x4c000024 /* rfid instruction */ +#define MTMSRD(r) .long (0x7c000164 + ((r) << 21)) /* mtmsrd */ +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ + +#else +#define FIX_SRR1(ra, rb) +#define RFI rfi +#define MTMSRD(r) mtmsr r +#define CLR_TOP32(r) +#endif /* CONFIG_PPC64BRIDGE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/ppc_htab.c linux.ac/arch/ppc/kernel/ppc_htab.c --- linux.vanilla/arch/ppc/kernel/ppc_htab.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/ppc_htab.c Sat Jun 10 21:48:24 2000 @@ -165,7 +165,7 @@ valid = 0; for_each_task(p) { - if ( (ptr->vsid >> 4) == p->mm->context ) + if (p->mm && (ptr->vsid >> 4) == p->mm->context) { valid = 1; break; @@ -565,17 +565,22 @@ if (!first) *p++ = '\t'; val = _get_L2CR(); - p += sprintf(p, "%08x: ", val); - p += sprintf(p, " %s", - (val&0x80000000)?"enabled":"disabled"); - p += sprintf(p,",%sparity",(val&0x40000000)?"":"no "); - p += sprintf(p, ",%s", sizestrings[(val >> 28) & 3]); - p += sprintf(p, ",%s", clockstrings[(val >> 25) & 7]); - p += sprintf(p, ",%s", typestrings[(val >> 23) & 0x2]); - p += sprintf(p,"%s",(val>>22)&1?"":",data only"); - p += sprintf(p,"%s",(val>>20)&1?",ZZ enabled":""); - p += sprintf(p,",%s",(val>>19)&1?"write-through":"copy-back"); - p += sprintf(p,",%sns hold", holdstrings[(val>>16)&3]); + p += sprintf(p, "0x%08x: ", val); + p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" : + "disabled"); + p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no "); + p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]); + p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]); + p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]); + p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : ""); + p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": ""); + p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" : + "copy-back"); + p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : ""); + p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]); + p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : ""); + p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :""); + p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :""); p += sprintf(p,"\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/ppc_ksyms.c linux.ac/arch/ppc/kernel/ppc_ksyms.c --- linux.vanilla/arch/ppc/kernel/ppc_ksyms.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/ppc_ksyms.c Sat Jun 10 21:48:24 2000 @@ -97,12 +97,14 @@ #endif #endif +#if !__INLINE_BITOPS EXPORT_SYMBOL(set_bit); EXPORT_SYMBOL(clear_bit); EXPORT_SYMBOL(change_bit); EXPORT_SYMBOL(test_and_set_bit); EXPORT_SYMBOL(test_and_clear_bit); EXPORT_SYMBOL(test_and_change_bit); +#endif /* __INLINE_BITOPS */ EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); @@ -267,11 +269,13 @@ EXPORT_SYMBOL(decrementer_count); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); +EXPORT_SYMBOL(console_lock); #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); #endif EXPORT_SYMBOL(down_read_failed); +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) extern void (*debugger)(struct pt_regs *regs); extern int (*debugger_bpt)(struct pt_regs *regs); extern int (*debugger_sstep)(struct pt_regs *regs); @@ -285,5 +289,7 @@ EXPORT_SYMBOL(debugger_iabr_match); EXPORT_SYMBOL(debugger_dabr_match); EXPORT_SYMBOL(debugger_fault_handler); +#endif EXPORT_SYMBOL(ret_to_user_hook); +EXPORT_SYMBOL(do_softirq); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/prom.c linux.ac/arch/ppc/kernel/prom.c --- linux.vanilla/arch/ppc/kernel/prom.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/prom.c Sat Jun 10 21:48:24 2000 @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_FB #include @@ -80,7 +83,8 @@ unsigned intr; }; -typedef unsigned long interpret_func(struct device_node *, unsigned long); +typedef unsigned long interpret_func(struct device_node *, unsigned long, + int, int); static interpret_func interpret_pci_props; static interpret_func interpret_dbdma_props; static interpret_func interpret_isa_props; @@ -101,7 +105,7 @@ char *bootpath = 0; char *bootdevice = 0; -unsigned int rtas_data = 0; /* virtual pointer */ +unsigned int rtas_data = 0; /* physical pointer */ unsigned int rtas_entry = 0; /* physical pointer */ unsigned int rtas_size = 0; unsigned int old_rtas = 0; @@ -145,7 +149,7 @@ static unsigned long inspect_node(phandle, struct device_node *, unsigned long, unsigned long, struct device_node ***); static unsigned long finish_node(struct device_node *, unsigned long, - interpret_func *); + interpret_func *, int, int); static unsigned long finish_node_interrupts(struct device_node *, unsigned long); static unsigned long check_display(unsigned long); static int prom_next_node(phandle *); @@ -158,6 +162,7 @@ extern void enter_rtas(void *); extern unsigned long reloc_offset(void); +void phys_call_rtas(int, int, int, ...); extern char cmd_line[512]; /* XXX */ boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */ @@ -279,7 +284,267 @@ } } -unsigned long smp_chrp_cpu_nr __initdata = 1; +void +prom_print_hex(unsigned int v) +{ + char buf[16]; + int i, c; + + for (i = 0; i < 8; ++i) { + c = (v >> ((7-i)*4)) & 0xf; + c += (c >= 10)? ('a' - 10): '0'; + buf[i] = c; + } + buf[i] = ' '; + buf[i+1] = 0; + prom_print(buf); +} + +void +prom_print_nl(void) +{ + unsigned long offset = reloc_offset(); + prom_print(RELOC("\n")); +} + +unsigned long smp_chrp_cpu_nr __initdata = 0; + +#ifdef CONFIG_SMP +/* + * With CHRP SMP we need to use the OF to start the other + * processors so we can't wait until smp_boot_cpus (the OF is + * trashed by then) so we have to put the processors into + * a holding pattern controlled by the kernel (not OF) before + * we destroy the OF. + * + * This uses a chunk of high memory, puts some holding pattern + * code there and sends the other processors off to there until + * smp_boot_cpus tells them to do something. We do that by using + * physical address 0x0. The holding pattern checks that address + * until its cpu # is there, when it is that cpu jumps to + * __secondary_start(). smp_boot_cpus() takes care of setting those + * values. + * + * We also use physical address 0x4 here to tell when a cpu + * is in its holding pattern code. + * + * -- Cort + */ +static void +prom_hold_cpus(unsigned long mem) +{ + extern void __secondary_hold(void); + unsigned long i; + int cpu; + phandle node; + unsigned long offset = reloc_offset(); + char type[16], *path; + unsigned int reg; + + /* + * XXX: hack to make sure we're chrp, assume that if we're + * chrp we have a device_type property -- Cort + */ + node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); + if ( (int)call_prom(RELOC("getprop"), 4, 1, node, + RELOC("device_type"),type, sizeof(type)) <= 0) + return; + + /* copy the holding pattern code to someplace safe (0) */ + /* the holding pattern is now within the first 0x100 + bytes of the kernel image -- paulus */ + memcpy((void *)0, KERNELBASE + offset, 0x100); + flush_icache_range(0, 0x100); + + /* look for cpus */ + *(unsigned long *)(0x0) = 0; + asm volatile("dcbf 0,%0": : "r" (0) : "memory"); + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), + type, sizeof(type)); + if (strcmp(type, RELOC("cpu")) != 0) + continue; + path = (char *) mem; + memset(path, 0, 256); + if ((int) call_prom(RELOC("package-to-path"), 3, 1, + node, path, 255) < 0) + continue; + reg = -1; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), + ®, sizeof(reg)); + cpu = RELOC(smp_chrp_cpu_nr)++; + RELOC(smp_hw_index)[cpu] = reg; + /* XXX: hack - don't start cpu 0, this cpu -- Cort */ + if (cpu == 0) + continue; + prom_print(RELOC("starting cpu ")); + prom_print(path); + *(ulong *)(0x4) = 0; + call_prom(RELOC("start-cpu"), 3, 0, node, + __pa(__secondary_hold), cpu); + prom_print(RELOC("...")); + for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ ) + ; + if (*(ulong *)(0x4) == cpu) + prom_print(RELOC("ok\n")); + else { + prom_print(RELOC("failed: ")); + prom_print_hex(*(ulong *)0x4); + prom_print_nl(); + } + } +} +#endif /* CONFIG_SMP */ + +void +bootx_init(unsigned long r4, unsigned long phys) +{ + boot_infos_t *bi = (boot_infos_t *) r4; + unsigned long space; + unsigned long ptr, x; + char *model; + unsigned long offset = reloc_offset(); + + RELOC(boot_infos) = PTRUNRELOC(bi); + if (!BOOT_INFO_IS_V2_COMPATIBLE(bi)) + bi->logicalDisplayBase = 0; + +#ifdef CONFIG_BOOTX_TEXT + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; + RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; + RELOC(disp_bi) = PTRUNRELOC(bi); + + clearscreen(); + + /* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since + there is nothing much we can do with an incompatible version, except display + a message and eventually hang the processor... + + I'll try to keep enough of boot-info compatible in the future to always allow + display of this message; + */ + if (!BOOT_INFO_IS_COMPATIBLE(bi)) + prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); + + prom_welcome(bi, phys); + flushscreen(); +#endif /* CONFIG_BOOTX_TEXT */ + + /* New BootX enters kernel with MMU off, i/os are not allowed + here. This hack will have been done by the boostrap anyway. + */ + if (bi->version < 4) { + /* + * XXX If this is an iMac, turn off the USB controller. + */ + model = (char *) early_get_property + (r4 + bi->deviceTreeOffset, 4, RELOC("model")); + if (model + && (strcmp(model, RELOC("iMac,1")) == 0 + || strcmp(model, RELOC("PowerMac1,1")) == 0)) { + out_le32((unsigned *)0x80880008, 1); /* XXX */ + } + } + + /* Move klimit to enclose device tree, args, ramdisk, etc... */ + if (bi->version < 5) { + space = bi->deviceTreeOffset + bi->deviceTreeSize; + if (bi->ramDisk) + space = bi->ramDisk + bi->ramDiskSize; + } else + space = bi->totalParamsSize; + RELOC(klimit) = PTRUNRELOC((char *) bi + space); + + /* New BootX will have flushed all TLBs and enters kernel with + MMU switched OFF, so this should not be useful anymore. + */ + if (bi->version < 4) { + /* + * Touch each page to make sure the PTEs for them + * are in the hash table - the aim is to try to avoid + * getting DSI exceptions while copying the kernel image. + */ + for (ptr = (KERNELBASE + offset) & PAGE_MASK; + ptr < (unsigned long)bi + space; ptr += PAGE_SIZE) + x = *(volatile unsigned long *)ptr; + } + +#ifdef CONFIG_BOOTX_TEXT + prom_drawstring(RELOC("booting...\n")); + flushscreen(); + RELOC(bootx_text_mapped) = 0; +#endif +} + +#ifdef CONFIG_PPC64BRIDGE +/* + * Set up a hash table with a set of entries in it to map the + * first 64MB of RAM. This is used on 64-bit machines since + * some of them don't have BATs. + * We assume the PTE will fit in the primary PTEG. + */ + +static inline void make_pte(unsigned long htab, unsigned int hsize, + unsigned int va, unsigned int pa, int mode) +{ + unsigned int *pteg; + unsigned int hash, i; + + hash = ((va >> 5) ^ (va >> 21)) & 0x7fff80; + pteg = (unsigned int *)(htab + (hash & (hsize - 1))); + for (i = 0; i < 8; ++i, pteg += 4) { + if ((pteg[1] & 1) == 0) { + pteg[1] = ((va >> 16) & 0xff80) | 1; + pteg[3] = pa | mode; + break; + } + } +} + +extern unsigned long _SDR1; +extern PTE *Hash; +extern unsigned long Hash_size; + +void +prom_alloc_htab(void) +{ + unsigned int hsize; + unsigned long htab; + unsigned int addr; + unsigned long offset = reloc_offset(); + + /* + * Because of OF bugs we can't use the "claim" client + * interface to allocate memory for the hash table. + * This code is only used on 64-bit PPCs, and the only + * 64-bit PPCs at the moment are RS/6000s, and their + * OF is based at 0xc00000 (the 12M point), so we just + * arbitrarily use the 0x800000 - 0xc00000 region for the + * hash table. + * -- paulus. + */ +#ifdef CONFIG_POWER4 + hsize = 4 << 20; /* POWER4 has no BATs */ +#else + hsize = 2 << 20; +#endif /* CONFIG_POWER4 */ + htab = (8 << 20); + RELOC(Hash) = (void *)(htab + KERNELBASE); + RELOC(Hash_size) = hsize; + RELOC(_SDR1) = htab + __ilog2(hsize) - 18; + + /* + * Put in PTEs for the first 64MB of RAM + */ + cacheable_memzero((void *)htab, hsize); + for (addr = 0; addr < 0x4000000; addr += 0x1000) + make_pte(htab, hsize, addr + KERNELBASE, addr, + _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX); +} +#endif /* CONFIG_PPC64BRIDGE */ /* * We enter here early on, when the Open Firmware prom is still @@ -289,11 +554,6 @@ unsigned long prom_init(int r3, int r4, prom_entry pp) { -#ifdef CONFIG_SMP - int i; - phandle node; - char type[16], *path; -#endif int chrp = 0; unsigned long mem; ihandle prom_rtas, prom_mmu, prom_op; @@ -313,82 +573,7 @@ /* If we came here from BootX, clear the screen, * set up some pointers and return. */ if (r3 == 0x426f6f58 && pp == NULL) { - boot_infos_t *bi = (boot_infos_t *) r4; - unsigned long space; - unsigned long ptr, x; - char *model; - - RELOC(boot_infos) = PTRUNRELOC(bi); - if (!BOOT_INFO_IS_V2_COMPATIBLE(bi)) - bi->logicalDisplayBase = 0; - -#ifdef CONFIG_BOOTX_TEXT - RELOC(g_loc_X) = 0; - RELOC(g_loc_Y) = 0; - RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8; - RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16; - RELOC(disp_bi) = PTRUNRELOC(bi); - - clearscreen(); - - /* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since - there is nothing much we can do with an incompatible version, except display - a message and eventually hang the processor... - - I'll try to keep enough of boot-info compatible in the future to always allow - display of this message; - */ - if (!BOOT_INFO_IS_COMPATIBLE(bi)) - prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n")); - - prom_welcome(bi, phys); - flushscreen(); -#endif /* CONFIG_BOOTX_TEXT */ - - /* New BootX enters kernel with MMU off, i/os are not allowed - here. This hack will have been done by the boostrap anyway. - */ - if (bi->version < 4) { - /* - * XXX If this is an iMac, turn off the USB controller. - */ - model = (char *) early_get_property - (r4 + bi->deviceTreeOffset, 4, RELOC("model")); - if (model - && (strcmp(model, RELOC("iMac,1")) == 0 - || strcmp(model, RELOC("PowerMac1,1")) == 0)) { - out_le32((unsigned *)0x80880008, 1); /* XXX */ - } - } - - /* Move klimit to enclose device tree, args, ramdisk, etc... */ - if (bi->version < 5) { - space = bi->deviceTreeOffset + bi->deviceTreeSize; - if (bi->ramDisk) - space = bi->ramDisk + bi->ramDiskSize; - } else - space = bi->totalParamsSize; - RELOC(klimit) = PTRUNRELOC((char *) bi + space); - - /* New BootX will have flushed all TLBs and enters kernel with - MMU switched OFF, so this should not be useful anymore. - */ - if (bi->version < 4) { - /* - * Touch each page to make sure the PTEs for them - * are in the hash table - the aim is to try to avoid - * getting DSI exceptions while copying the kernel image. - */ - for (ptr = (KERNELBASE + offset) & PAGE_MASK; - ptr < (unsigned long)bi + space; ptr += PAGE_SIZE) - x = *(volatile unsigned long *)ptr; - } - -#ifdef CONFIG_BOOTX_TEXT - prom_print(RELOC("booting...\n")); - flushscreen(); - RELOC(bootx_text_mapped) = 0; -#endif + bootx_init(r4, phys); return phys; } @@ -421,7 +606,8 @@ if (prom_op != (void*)-1) { char model[64]; int sz; - sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, RELOC("model"), model, 64); + sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, + RELOC("model"), model, 64); if (sz > 0) { char *c; /* hack to skip the ibm chrp firmware # */ @@ -454,62 +640,68 @@ mem = ALIGN(mem + strlen(d) + 1); } - mem = check_display(mem); - - prom_print(RELOC("copying OF device tree...")); - mem = copy_device_tree(mem, mem + (1<<20)); - prom_print(RELOC("done\n")); - - - RELOC(klimit) = (char *) (mem - offset); - prom_rtas = call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas")); if (prom_rtas != (void *) -1) { + int i, nargs; + struct prom_args prom_args; + RELOC(rtas_size) = 0; call_prom(RELOC("getprop"), 4, 1, prom_rtas, RELOC("rtas-size"), &RELOC(rtas_size), sizeof(rtas_size)); - prom_print(RELOC("instantiating rtas...")); + prom_print(RELOC("instantiating rtas")); if (RELOC(rtas_size) == 0) { RELOC(rtas_data) = 0; } else { /* - * We do _not_ want the rtas_data inside the klimit - * boundry since it'll be squashed when we do the - * relocate of the kernel on chrp right after prom_init() - * in head.S. So, we just pick a spot in memory. - * -- Cort + * Ask OF for some space for RTAS. + * Actually OF has bugs so we just arbitrarily + * use memory at the 6MB point. */ -#if 0 - mem = (mem + 4095) & -4096; - RELOC(rtas_data) = mem + KERNELBASE; - mem += RELOC(rtas_size); -#endif - RELOC(rtas_data) = (6<<20) + KERNELBASE; + RELOC(rtas_data) = 6 << 20; + prom_print(RELOC(" at ")); + prom_print_hex(RELOC(rtas_data)); } prom_rtas = call_prom(RELOC("open"), 1, 1, RELOC("/rtas")); - { - int i, nargs; - struct prom_args prom_args; - nargs = 3; - prom_args.service = RELOC("call-method"); - prom_args.nargs = nargs; - prom_args.nret = 2; - prom_args.args[0] = RELOC("instantiate-rtas"); - prom_args.args[1] = prom_rtas; - prom_args.args[2] = ((void *)(RELOC(rtas_data)-KERNELBASE)); - RELOC(prom)(&prom_args); - if (prom_args.args[nargs] != 0) - i = 0; - else - i = (int)prom_args.args[nargs+1]; - RELOC(rtas_entry) = i; - } + prom_print(RELOC("...")); + nargs = 3; + prom_args.service = RELOC("call-method"); + prom_args.nargs = nargs; + prom_args.nret = 2; + prom_args.args[0] = RELOC("instantiate-rtas"); + prom_args.args[1] = prom_rtas; + prom_args.args[2] = (void *) RELOC(rtas_data); + RELOC(prom)(&prom_args); + if (prom_args.args[nargs] != 0) + i = 0; + else + i = (int)prom_args.args[nargs+1]; + RELOC(rtas_entry) = i; if ((RELOC(rtas_entry) == -1) || (RELOC(rtas_entry) == 0)) prom_print(RELOC(" failed\n")); else prom_print(RELOC(" done\n")); } +#ifdef CONFIG_PPC64BRIDGE + /* + * Find out how much memory we have and allocate a + * suitably-sized hash table. + */ + prom_alloc_htab(); +#endif + +#ifdef CONFIG_SMP + prom_hold_cpus(mem); +#endif + + mem = check_display(mem); + + prom_print(RELOC("copying OF device tree...")); + mem = copy_device_tree(mem, mem + (1<<20)); + prom_print(RELOC("done\n")); + + RELOC(klimit) = (char *) (mem - offset); + /* If we are already running at 0xc0000000, we assume we were loaded by * an OF bootloader which did set a BAT for us. This breaks OF translate * so we force phys to be 0 @@ -542,85 +734,10 @@ } #ifdef CONFIG_BOOTX_TEXT - if (!chrp && RELOC(prom_disp_node) != 0) + if (RELOC(prom_disp_node) != 0) setup_disp_fake_bi(RELOC(prom_disp_node)); #endif -#ifdef CONFIG_SMP - /* - * With CHRP SMP we need to use the OF to start the other - * processors so we can't wait until smp_boot_cpus (the OF is - * trashed by then) so we have to put the processors into - * a holding pattern controlled by the kernel (not OF) before - * we destroy the OF. - * - * This uses a chunk of high memory, puts some holding pattern - * code there and sends the other processors off to there until - * smp_boot_cpus tells them to do something. We do that by using - * physical address 0x0. The holding pattern checks that address - * until its cpu # is there, when it is that cpu jumps to - * __secondary_start(). smp_boot_cpus() takes care of setting those - * values. - * - * We also use physical address 0x4 here to tell when a cpu - * is in its holding pattern code. - * - * -- Cort - */ - { - extern void __secondary_hold(void); - unsigned long i; - char type[16]; - - - /* - * XXX: hack to make sure we're chrp, assume that if we're - * chrp we have a device_type property -- Cort - */ - node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); - if ( (int)call_prom(RELOC("getprop"), 4, 1, node, - RELOC("device_type"),type, sizeof(type)) <= 0) - return phys; - - /* copy the holding pattern code to someplace safe (8M) */ - memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x100 ); - for (i = 8<<20; i < ((8<<20)+0x100); i += 32) - { - asm volatile("dcbf 0,%0" : : "r" (i) : "memory"); - asm volatile("icbi 0,%0" : : "r" (i) : "memory"); - } - } - - /* look for cpus */ - for (node = 0; prom_next_node(&node);) - { - type[0] = 0; - call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), - type, sizeof(type)); - if (strcmp(type, RELOC("cpu")) != 0) - continue; - path = (char *) mem; - memset(path, 0, 256); - if ((int) call_prom(RELOC("package-to-path"), 3, 1, - node, path, 255) < 0) - continue; - /* XXX: hack - don't start cpu 0, this cpu -- Cort */ - if ( smp_chrp_cpu_nr++ == 0 ) - continue; - prom_print(RELOC("starting cpu ")); - prom_print(path); - *(unsigned long *)(0x4) = 0; - asm volatile("dcbf 0,%0": : "r" (0x4) : "memory"); - call_prom(RELOC("start-cpu"), 3, 0, node, 8<<20, smp_chrp_cpu_nr-1); - for ( i = 0 ; (i < 10000) && - (*(ulong *)(0x4) == (ulong)0); i++ ) - ; - if (*(ulong *)(0x4) == (ulong)smp_chrp_cpu_nr-1 ) - prom_print(RELOC("...ok\n")); - else - prom_print(RELOC("...failed\n")); - } -#endif /* If OpenFirmware version >= 3, then use quiesce call */ if (prom_version >= 3) { prom_print(RELOC("Calling quiesce ...\n")); @@ -631,17 +748,41 @@ #ifdef CONFIG_BOOTX_TEXT if (!chrp && RELOC(disp_bi)) { - RELOC(prom_stdout) = 0; clearscreen(); prom_welcome(PTRRELOC(RELOC(disp_bi)), phys); - prom_print(RELOC("booting...\n")); + prom_drawstring(RELOC("booting...\n")); } RELOC(bootx_text_mapped) = 0; #endif + prom_print(RELOC("returning from prom_init\n")); + RELOC(prom_stdout) = 0; return phys; } +void phys_call_rtas(int service, int nargs, int nret, ...) +{ + va_list list; + union { + unsigned long words[16]; + double align; + } u; + unsigned long offset = reloc_offset(); + void (*rtas)(void *, unsigned long); + int i; + + u.words[0] = service; + u.words[1] = nargs; + u.words[2] = nret; + va_start(list, nret); + for (i = 0; i < nargs; ++i) + u.words[i+3] = va_arg(list, unsigned long); + va_end(list); + + rtas = (void (*)(void *, unsigned long)) RELOC(rtas_entry); + rtas(&u, RELOC(rtas_data)); +} + #ifdef CONFIG_BOOTX_TEXT __init static void prom_welcome(boot_infos_t* bi, unsigned long phys) @@ -650,34 +791,34 @@ unsigned long flags; unsigned long pvr; - prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); - prom_print(RELOC("\nstarted at : 0x")); + prom_drawstring(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); + prom_drawstring(RELOC("\nstarted at : 0x")); prom_drawhex(phys); - prom_print(RELOC("\nlinked at : 0x")); + prom_drawstring(RELOC("\nlinked at : 0x")); prom_drawhex(KERNELBASE); - prom_print(RELOC("\nframe buffer at : 0x")); + prom_drawstring(RELOC("\nframe buffer at : 0x")); prom_drawhex((unsigned long)bi->dispDeviceBase); - prom_print(RELOC(" (phys), 0x")); + prom_drawstring(RELOC(" (phys), 0x")); prom_drawhex((unsigned long)bi->logicalDisplayBase); - prom_print(RELOC(" (log)")); - prom_print(RELOC("\nklimit : 0x")); - prom_drawhex(RELOC(klimit)); - prom_print(RELOC("\nMSR : 0x")); + prom_drawstring(RELOC(" (log)")); + prom_drawstring(RELOC("\nklimit : 0x")); + prom_drawhex((unsigned long)RELOC(klimit)); + prom_drawstring(RELOC("\nMSR : 0x")); __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); prom_drawhex(flags); __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); pvr >>= 16; if (pvr > 1) { - prom_print(RELOC("\nHID0 : 0x")); + prom_drawstring(RELOC("\nHID0 : 0x")); __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); prom_drawhex(flags); } if (pvr == 8 || pvr == 12) { - prom_print(RELOC("\nICTC : 0x")); + prom_drawstring(RELOC("\nICTC : 0x")); __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); prom_drawhex(flags); } - prom_print(RELOC("\n\n")); + prom_drawstring(RELOC("\n\n")); } #endif @@ -822,6 +963,10 @@ call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &pitch, sizeof(pitch)); address = 0; + if (pitch == 1) { + address = 0xfa000000; + pitch = 0x1000; /* for strange IBM display */ + } call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &address, sizeof(address)); if (address == 0) { @@ -987,6 +1132,7 @@ /* All newworld machines now use the interrupt tree */ struct device_node *np = allnodes; + while(np) { if (get_property(np, "interrupt-parent", 0)) { pmac_newworld = 1; @@ -997,7 +1143,7 @@ if (boot_infos == 0 && pmac_newworld) use_of_interrupt_tree = 1; - mem = finish_node(allnodes, mem, NULL); + mem = finish_node(allnodes, mem, NULL, 0, 0); dev_tree_size = mem - (unsigned long) allnodes; klimit = (char *) mem; } @@ -1025,21 +1171,30 @@ __init static unsigned long finish_node(struct device_node *np, unsigned long mem_start, - interpret_func *ifunc) + interpret_func *ifunc, int naddrc, int nsizec) { struct device_node *child; + int *ip; np->name = get_property(np, "name", 0); np->type = get_property(np, "device_type", 0); /* get the device addresses and interrupts */ if (ifunc != NULL) { - mem_start = ifunc(np, mem_start); + mem_start = ifunc(np, mem_start, naddrc, nsizec); } if (use_of_interrupt_tree) { mem_start = finish_node_interrupts(np, mem_start); } + /* Look for #address-cells and #size-cells properties. */ + ip = (int *) get_property(np, "#address-cells", 0); + if (ip != NULL) + naddrc = *ip; + ip = (int *) get_property(np, "#size-cells", 0); + if (ip != NULL) + nsizec = *ip; + /* the f50 sets the name to 'display' and 'compatible' to what we * expect for the name -- Cort */ @@ -1080,7 +1235,8 @@ } for (child = np->child; child != NULL; child = child->sibling) - mem_start = finish_node(child, mem_start, ifunc); + mem_start = finish_node(child, mem_start, ifunc, + naddrc, nsizec); return mem_start; } @@ -1246,7 +1402,8 @@ __init static unsigned long -interpret_pci_props(struct device_node *np, unsigned long mem_start) +interpret_pci_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) { struct address_range *adr; struct pci_reg_property *pci_addrs; @@ -1329,7 +1486,8 @@ __init static unsigned long -interpret_dbdma_props(struct device_node *np, unsigned long mem_start) +interpret_dbdma_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) { struct reg_property *rp; struct address_range *adr; @@ -1381,7 +1539,8 @@ __init static unsigned long -interpret_macio_props(struct device_node *np, unsigned long mem_start) +interpret_macio_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) { struct reg_property *rp; struct address_range *adr; @@ -1450,7 +1609,8 @@ __init static unsigned long -interpret_isa_props(struct device_node *np, unsigned long mem_start) +interpret_isa_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) { struct isa_reg_property *rp; struct address_range *adr; @@ -1491,21 +1651,24 @@ __init static unsigned long -interpret_root_props(struct device_node *np, unsigned long mem_start) +interpret_root_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) { - struct reg_property *rp; struct address_range *adr; int i, l, *ip; + unsigned int *rp; + int rpsize = (naddrc + nsizec) * sizeof(unsigned int); - rp = (struct reg_property *) get_property(np, "reg", &l); - if (rp != 0 && l >= sizeof(struct reg_property)) { + rp = (unsigned int *) get_property(np, "reg", &l); + if (rp != 0 && l >= rpsize) { i = 0; adr = (struct address_range *) mem_start; - while ((l -= sizeof(struct reg_property)) >= 0) { + while ((l -= rpsize) >= 0) { adr[i].space = 0; - adr[i].address = rp[i].address; - adr[i].size = rp[i].size; + adr[i].address = rp[naddrc - 1]; + adr[i].size = rp[naddrc + nsizec - 1]; ++i; + rp += naddrc + nsizec; } np->addrs = adr; np->n_addrs = i; @@ -1583,9 +1746,8 @@ int l; for (np = allnodes; np != 0; np = np->allnext) { - char *pname = np->parent ? - (char *)get_property(np->parent, "name", &l) : 0; - if (pname && strcmp(pname, "mac-io") == 0) + if (np->parent == NULL || np->parent->type == NULL + || strcmp(np->parent->type, "pci") != 0) continue; reg = (unsigned int *) get_property(np, "reg", &l); if (reg == 0 || l < sizeof(struct reg_property)) @@ -1781,6 +1943,8 @@ } #endif +spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED; + /* this can be called after setup -- Cort */ __openfirmware int @@ -1813,11 +1977,10 @@ u.words[i+3] = va_arg(list, unsigned long); va_end(list); - save_flags(s); - cli(); - + spin_lock_irqsave(&rtas_lock, s); enter_rtas((void *)__pa(&u)); - restore_flags(s); + spin_unlock_irqrestore(&rtas_lock, s); + if (nret > 1 && outputs != NULL) for (i = 0; i < nret-1; ++i) outputs[i] = u.words[i+nargs+4]; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/setup.c linux.ac/arch/ppc/kernel/setup.c --- linux.vanilla/arch/ppc/kernel/setup.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/setup.c Sat Jun 10 21:48:24 2000 @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef CONFIG_8xx #include #include @@ -130,6 +131,14 @@ }; /* + * These are used in binfmt_elf.c to put aux entries on the stack + * for each elf executable being started. + */ +int dcache_bsize; +int icache_bsize; +int ucache_bsize; + +/* * I really need to add multiple-console support... -- Cort */ int __init pmac_display_supported(char *name) @@ -288,6 +297,15 @@ break; } break; + case 0x0035: + len += sprintf(len+buffer, "POWER4\n"); + break; + case 0x0040: + len += sprintf(len+buffer, "POWER3 (630)\n"); + break; + case 0x0041: + len += sprintf(len+buffer, "POWER3 (630+)\n"); + break; case 0x0050: len += sprintf(len+buffer, "8xx\n"); break; @@ -458,7 +476,6 @@ intuit_machine_type(); #endif /* CONFIG_MACH_SPECIFIC */ finish_device_tree(); - /* * If we were booted via quik, r3 points to the physical * address of the command-line parameters. @@ -494,6 +511,8 @@ #ifdef CONFIG_BLK_DEV_INITRD if (r3 && r4 && r4 != 0xdeadbeef) { + if (r3 < KERNELBASE) + r3 += KERNELBASE; initrd_start = r3; initrd_end = r3 + r4; ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); @@ -574,7 +593,7 @@ } __max_memory = maxmem; } - + /* this is for modules since _machine can be a define -- Cort */ ppc_md.ppc_machine = _machine; @@ -684,6 +703,24 @@ breakpoint(); #endif + /* + * Set cache line size based on type of cpu as a default. + * Systems with OF can look in the properties on the cpu node(s) + * for a possibly more accurate value. + */ + dcache_bsize = icache_bsize = 32; /* most common value */ + switch (_get_PVR() >> 16) { + case 1: /* 601, with unified cache */ + ucache_bsize = 32; + break; + /* XXX need definitions in here for 8xx etc. */ + case 0x40: + case 0x41: + case 0x35: /* 64-bit POWER3, POWER3+, POWER4 */ + dcache_bsize = icache_bsize = 128; + break; + } + /* reboot on panic */ panic_timeout = 180; @@ -779,7 +816,7 @@ for (i = 0; i < 26; i++) id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); id->word156 = __le16_to_cpu(id->word156); - for (i = 0; i < 4; i++) + for (i = 0; i < 3; i++) id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); for (i = 0; i < 96; i++) id->words160_255[i] = __le16_to_cpu(id->words160_255[i]); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/smp.c linux.ac/arch/ppc/kernel/smp.c --- linux.vanilla/arch/ppc/kernel/smp.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/smp.c Sat Jun 10 21:48:24 2000 @@ -53,6 +53,9 @@ unsigned int prof_counter[NR_CPUS]; cycles_t cacheflush_time; +/* this has to go in the data section because it is accessed from prom_init */ +int smp_hw_index[NR_CPUS] = {0}; + /* all cpu mappings are 1-1 -- Cort */ volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; @@ -238,6 +241,7 @@ case _MACH_chrp: case _MACH_prep: case _MACH_gemini: +#ifndef CONFIG_POWER4 /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ) break; @@ -254,6 +258,18 @@ openpic_cause_IPI(smp_processor_id(), msg, 1<mm->mmap->vm_page_prot = PAGE_SHARED; - current->mm->mmap->vm_start = PAGE_OFFSET; - current->mm->mmap->vm_end = init_mm.mmap->vm_end; -#endif cpu_callin_map[current->processor] = 1; + +#ifndef CONFIG_POWER4 /* * Each processor has to do this and this is the best * place to stick it for now. * -- Cort */ - if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) ) + if (OpenPIC && _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep)) do_openpic_setup_cpu(); +#else + xics_setup_cpu(); +#endif /* CONFIG_POWER4 */ #ifdef CONFIG_GEMINI if ( _machine == _MACH_gemini ) gemini_init_l2(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/time.c linux.ac/arch/ppc/kernel/time.c --- linux.vanilla/arch/ppc/kernel/time.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/kernel/time.c Sun Jun 4 21:10:56 2000 @@ -50,6 +50,7 @@ /* keep track of when we need to update the rtc */ time_t last_rtc_update = 0; +extern rwlock_t xtime_lock; /* The decrementer counts down by 128 every 128ns on a 601. */ #define DECREMENTER_COUNT_601 (1000000000 / HZ) @@ -69,6 +70,7 @@ int timer_interrupt(struct pt_regs * regs) { int dval, d; + unsigned long flags; unsigned long cpu = smp_processor_id(); hardirq_enter(cpu); @@ -102,7 +104,6 @@ while ((d = get_dec()) == dval) ; asm volatile("mftb %0" : "=r" (last_tb) ); - /* * Don't play catchup between the call to time_init() * and sti() in init/main.c. @@ -122,6 +123,7 @@ /* * update the rtc when needed */ + read_lock_irqsave(&xtime_lock, flags); if ( (time_status & STA_UNSYNC) && ((xtime.tv_sec > last_rtc_update + 60) || (xtime.tv_sec < last_rtc_update)) ) @@ -132,6 +134,7 @@ /* do it again in 60 s */ last_rtc_update = xtime.tv_sec; } + read_unlock_irqrestore(&xtime_lock, flags); } #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); @@ -153,17 +156,18 @@ save_flags(flags); cli(); + read_lock_irqsave(&xtime_lock, flags); *tv = xtime; + read_unlock_irqrestore(&xtime_lock, flags); /* XXX we don't seem to have the decrementers synced properly yet */ #ifndef CONFIG_SMP asm volatile("mftb %0" : "=r" (diff) ); diff -= last_tb; - tv->tv_usec += diff * count_period_num / count_period_den; tv->tv_sec += tv->tv_usec / 1000000; tv->tv_usec = tv->tv_usec % 1000000; #endif - + restore_flags(flags); } @@ -177,8 +181,10 @@ frac_tick = tv->tv_usec % (1000000 / HZ); save_flags(flags); cli(); + write_lock_irqsave(&xtime_lock, flags); xtime.tv_sec = tv->tv_sec; xtime.tv_usec = tv->tv_usec - frac_tick; + write_unlock_irqrestore(&xtime_lock, flags); set_dec(frac_tick * count_period_den / count_period_num); time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; @@ -191,6 +197,7 @@ void __init time_init(void) { + unsigned long flags; if (ppc_md.time_init != NULL) { ppc_md.time_init(); @@ -205,8 +212,10 @@ ppc_md.calibrate_decr(); } - xtime.tv_sec = ppc_md.get_rtc_time(); - xtime.tv_usec = 0; + write_lock_irqsave(&xtime_lock, flags); + xtime.tv_sec = ppc_md.get_rtc_time(); + xtime.tv_usec = 0; + write_unlock_irqrestore(&xtime_lock, flags); set_dec(decrementer_count); /* allow setting the time right away */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/xics.c linux.ac/arch/ppc/kernel/xics.c --- linux.vanilla/arch/ppc/kernel/xics.c Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/xics.c Sat Jun 10 21:48:24 2000 @@ -0,0 +1,214 @@ +/* + * arch/ppc/kernel/xics.c + * + * Copyright 2000 IBM Corporation. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include "i8259.h" +#include "xics.h" + +void xics_enable_irq(u_int irq); +void xics_disable_irq(u_int irq); +void xics_mask_and_ack_irq(u_int irq); +void xics_end_irq(u_int irq); + +struct hw_interrupt_type xics_pic = { + " XICS ", + NULL, + NULL, + xics_enable_irq, + xics_disable_irq, + xics_mask_and_ack_irq, + xics_end_irq +}; + +struct hw_interrupt_type xics_8259_pic = { + " XICS/8259", + NULL, + NULL, + NULL, + NULL, + xics_mask_and_ack_irq, + NULL +}; + +#define XICS_IPI 2 +#define XICS_IRQ_8259_CASCADE 0x2c +#define XICS_IRQ_OFFSET 16 +#define XICS_IRQ_SPURIOUS 0 + +#define DEFAULT_SERVER 0 +#define DEFAULT_PRIORITY 0 + +struct xics_ipl { + union { + u32 word; + u8 bytes[4]; + } xirr_poll; + union { + u32 word; + u8 bytes[4]; + } xirr; + u32 dummy; + union { + u32 word; + u8 bytes[4]; + } qirr; +}; + +struct xics_info { + volatile struct xics_ipl * per_cpu[NR_CPUS]; +}; + +struct xics_info xics_info; + +#define xirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.word) +#define cppr_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr.bytes[0]) +#define poll_info(n_cpu) (xics_info.per_cpu[n_cpu]->xirr_poll.word) +#define qirr_info(n_cpu) (xics_info.per_cpu[n_cpu]->qirr.bytes[0]) + +void +xics_enable_irq( + u_int irq + ) +{ + int status; + int call_status; + + irq -= XICS_IRQ_OFFSET; + if (irq == XICS_IPI) + return; + call_status = call_rtas("ibm,set-xive", 3, 1, (ulong*)&status, + irq, DEFAULT_SERVER, DEFAULT_PRIORITY); + if( call_status != 0 ) { + printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%x, status=%x\n", + irq, call_status, status); + return; + } +} + +void +xics_disable_irq( + u_int irq + ) +{ + int status; + int call_status; + + irq -= XICS_IRQ_OFFSET; + call_status = call_rtas("ibm,int-off", 1, 1, (ulong*)&status, irq); + if( call_status != 0 ) { + printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%x\n", + irq, call_status); + return; + } +} + +void +xics_end_irq( + u_int irq + ) +{ + int cpu = smp_processor_id(); + + cppr_info(cpu) = 0; /* actually the value overwritten by ack */ + xirr_info(cpu) = (0xff<<24) | (irq-XICS_IRQ_OFFSET); +} + +void +xics_mask_and_ack_irq( + u_int irq + ) +{ + int cpu = smp_processor_id(); + + if( irq < XICS_IRQ_OFFSET ) { + i8259_pic.ack(irq); + xirr_info(cpu) = (0xff<<24) | XICS_IRQ_8259_CASCADE; + } + else { + cppr_info(cpu) = 0xff; + } +} + +int +xics_get_irq(struct pt_regs *regs) +{ + u_int cpu = smp_processor_id(); + u_int vec; + int irq; + + vec = xirr_info(cpu); + /* (vec >> 24) == old priority */ + vec &= 0x00ffffff; + /* for sanity, this had better be < NR_IRQS - 16 */ + if( vec == XICS_IRQ_8259_CASCADE ) + irq = i8259_irq(cpu); + else if( vec == XICS_IRQ_SPURIOUS ) + irq = -1; + else + irq = vec + XICS_IRQ_OFFSET; + return irq; +} + +#ifdef CONFIG_SMP +void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +{ + qirr_info(smp_processor_id()) = 0xff; + smp_message_recv(MSG_RESCHEDULE); +} + +void xics_cause_IPI(int cpu) +{ + qirr_info(cpu) = 0; +} + +void xics_setup_cpu(void) +{ + int cpu = smp_processor_id(); + + cppr_info(cpu) = 0xff; +} +#endif /* CONFIG_SMP */ + +void +xics_init_IRQ( void ) +{ + int i; + extern unsigned long smp_chrp_cpu_nr; + +#ifdef CONFIG_SMP + for (i = 0; i < smp_chrp_cpu_nr; ++i) + xics_info.per_cpu[i] = + ioremap(0xfe000000 + smp_hw_index[i] * 0x1000, 0x20); +#else + xics_info.per_cpu[0] = ioremap(0xfe000000, 0x20); +#endif /* CONFIG_SMP */ + xics_8259_pic.enable = i8259_pic.enable; + xics_8259_pic.disable = i8259_pic.disable; + for (i = 0; i < 16; ++i) + irq_desc[i].handler = &xics_8259_pic; + for (; i < NR_IRQS; ++i) + irq_desc[i].handler = &xics_pic; + + cppr_info(0) = 0xff; + if (request_irq(XICS_IRQ_8259_CASCADE + XICS_IRQ_OFFSET, no_action, + 0, "8259 cascade", 0)) + printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); + i8259_init(); + +#ifdef CONFIG_SMP + request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0); +#endif +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/xics.h linux.ac/arch/ppc/kernel/xics.h --- linux.vanilla/arch/ppc/kernel/xics.h Thu Jan 1 01:00:00 1970 +++ linux.ac/arch/ppc/kernel/xics.h Sat Jun 10 21:48:24 2000 @@ -0,0 +1,23 @@ +/* + * arch/ppc/kernel/xics.h + * + * Copyright 2000 IBM Corporation. + * + * 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. + */ + +#ifndef _PPC_KERNEL_XICS_H +#define _PPC_KERNEL_XICS_H + +#include "local_irq.h" + +extern struct hw_interrupt_type xics_pic; +extern struct hw_interrupt_type xics_8259_pic; + +void xics_init_IRQ(void); +int xics_get_irq(struct pt_regs *); + +#endif /* _PPC_KERNEL_XICS_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mbxboot/Makefile linux.ac/arch/ppc/mbxboot/Makefile --- linux.vanilla/arch/ppc/mbxboot/Makefile Thu May 25 17:38:31 2000 +++ linux.ac/arch/ppc/mbxboot/Makefile Sun Jun 4 21:10:57 2000 @@ -28,14 +28,14 @@ TFTPIMAGE=/tftpboot/zImage.embedded ifdef CONFIG_8xx -ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00180000 -OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o gzimage.o rdimage.o +ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000 +OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx endif ifdef CONFIG_8260 -ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00400000 -OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o gzimage.o rdimage.o +ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000 +OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260 endif @@ -61,32 +61,21 @@ all: zImage zvmlinux.initrd: zvmlinux -# -# Build the boot loader images -# - $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=.gzimage=../coffboot/vmlinux.gz \ - --set-section-flags=.gzimage=alloc,load,readonly,data \ - gzimage.o - $(OBJCOPY) $(OBJCOPY_ARGS) -R .rdimage rdimage.o + $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS) $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=.rdimage=ramdisk.image.gz \ - --set-section-flags=.rdimage=alloc,load,readonly,data \ - rdimage.o - $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) -# -# Compute the sizes/offsets for the final image, and rebuild with these values. -# - $(CC) $(CFLAGS) \ - -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .rdimage` \ - -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .rdimage` \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .gzimage` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .gzimage` \ + --add-section=initrd=ramdisk.image.gz \ + --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.initrd.tmp1 zvmlinux.initrd1 + $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \ + -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \ -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@ - $(OBJDUMP) -h $@ + $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=initrd=ramdisk.image.gz \ + --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.initrd.tmp $@ zImage: zvmlinux ln -sf zvmlinux zImage @@ -96,27 +85,23 @@ zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz # -# Build the boot loader images -# -# - $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=.gzimage=../coffboot/vmlinux.gz \ - --set-section-flags=.gzimage=alloc,load,readonly,data \ - gzimage.o - $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) -# -# Compute the sizes/offsets for the final image, and rebuild with these values. +# build the boot loader image and then compute the offset into it +# for the kernel image # - $(CC) $(CFLAGS) \ - -DINITRD_OFFSET=0 \ - -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux .gzimage` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux .gzimage` \ + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.tmp $@ +# +# then with the offset rebuild the bootloader so we know where the kernel is +# + $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \ -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@ - $(OBJDUMP) -h $@ + $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ + zvmlinux.tmp $@ + rm zvmlinux.tmp znetboot : zImage cp zImage $(TFTPIMAGE) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mbxboot/embed_config.c linux.ac/arch/ppc/mbxboot/embed_config.c --- linux.vanilla/arch/ppc/mbxboot/embed_config.c Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/mbxboot/embed_config.c Sat Jun 10 21:59:27 2000 @@ -231,17 +231,17 @@ u_char *cp; int i; -#if 1 +#if 0 /* This is actually provided by my boot rom. I have it * here for those people that may load the kernel with * a JTAG/COP tool and not the rom monitor. */ - bd->bi_baudrate = 19200; - bd->bi_intfreq = 165; - bd->bi_busfreq = 33; - bd->bi_cpmfreq = 132; - bd->bi_brgfreq = bd->bi_cpmfreq / 2; /* BRGCLK = (CPM*2/4) */ - bd->bi_memsize = 16 * 1024 * 1024; + bd->bi_baudrate = 115200; + bd->bi_intfreq = 200; + bd->bi_busfreq = 66; + bd->bi_cpmfreq = 66; + bd->bi_brgfreq = 33; + bd->bi_memsize = 16 * 1024 * 1024; #endif cp = (u_char *)def_enet_addr; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mbxboot/head_8260.S linux.ac/arch/ppc/mbxboot/head_8260.S --- linux.vanilla/arch/ppc/mbxboot/head_8260.S Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/mbxboot/head_8260.S Sun Jun 4 21:10:57 2000 @@ -101,6 +101,11 @@ subi r1,r1,256 li r2,0x000F /* Mask pointer to 16-byte boundary */ andc r1,r1,r2 + + /* Speed us up a little. + */ + bl flush_instruction_cache + /* Run loader */ mr r3,r8 /* Load point */ mr r4,r7 /* Program length */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mbxboot/m8260_tty.c linux.ac/arch/ppc/mbxboot/m8260_tty.c --- linux.vanilla/arch/ppc/mbxboot/m8260_tty.c Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/mbxboot/m8260_tty.c Sun Jun 4 21:10:57 2000 @@ -72,8 +72,8 @@ */ up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + up->smc_rfcr = CPMFCR_EB; + up->smc_tfcr = CPMFCR_EB; up->smc_brklen = 0; up->smc_brkec = 0; up->smc_brkcr = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mbxboot/mbxtty.c linux.ac/arch/ppc/mbxboot/mbxtty.c --- linux.vanilla/arch/ppc/mbxboot/mbxtty.c Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/mbxboot/mbxtty.c Thu Jan 1 01:00:00 1970 @@ -1,201 +0,0 @@ - - -/* Minimal serial functions needed to send messages out the serial - * port on the MBX console. - * - * The MBX uxes SMC1 for the serial port. We reset the port and use - * only the first BD that EPPC-Bug set up as a character FIFO. - * - * Later versions (at least 1.4, maybe earlier) of the MBX EPPC-Bug - * use COM1 instead of SMC1 as the console port. This kinda sucks - * for the rest of the kernel, so here we force the use of SMC1 again. - * I f**ked around for a day trying to figure out how to make EPPC-Bug - * use SMC1, but gave up and decided to fix it here. - */ -#include -#include -#ifdef CONFIG_MBX -#include -#endif -#ifdef CONFIG_FADS -#include -#endif -#include "../8xx_io/commproc.h" - -#ifdef CONFIG_MBX -#define MBX_CSR1 ((volatile u_char *)0xfa100000) -#define CSR1_COMEN (u_char)0x02 -#endif - -static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); - -void -serial_init(bd_t *bd) -{ - volatile smc_t *sp; - volatile smc_uart_t *up; - volatile cbd_t *tbdf, *rbdf; - volatile cpm8xx_t *cp; - uint dpaddr, memaddr; - - cp = cpmp; - sp = (smc_t*)&(cp->cp_smc[0]); - up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC1]; - - /* Disable transmitter/receiver. - */ - sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); - -#ifdef CONFIG_MBX - if (*MBX_CSR1 & CSR1_COMEN) { - /* COM1 is enabled. Initialize SMC1 and use it for - * the console port. - */ - - /* Enable SDMA. - */ - ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; - - /* Use Port B for SMCs instead of other functions. - */ - cp->cp_pbpar |= 0x00000cc0; - cp->cp_pbdir &= ~0x00000cc0; - cp->cp_pbodr &= ~0x00000cc0; - - /* Allocate space for two buffer descriptors in the DP ram. - * For now, this address seems OK, but it may have to - * change with newer versions of the firmware. - */ - dpaddr = 0x0800; - - /* Grab a few bytes from the top of memory. EPPC-Bug isn't - * running any more, so we can do this. - */ - memaddr = (bd->bi_memsize - 32) & ~15; - - /* Set the physical address of the host memory buffers in - * the buffer descriptors. - */ - rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; - rbdf->cbd_bufaddr = memaddr; - rbdf->cbd_sc = 0; - tbdf = rbdf + 1; - tbdf->cbd_bufaddr = memaddr+4; - tbdf->cbd_sc = 0; - - /* Set up the uart parameters in the parameter ram. - */ - up->smc_rbase = dpaddr; - up->smc_tbase = dpaddr+sizeof(cbd_t); - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; - - /* Set UART mode, 8 bit, no parity, one stop. - * Enable receive and transmit. - */ - sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; - - /* Mask all interrupts and remove anything pending. - */ - sp->smc_smcm = 0; - sp->smc_smce = 0xff; - - /* Set up the baud rate generator. - * See 8xx_io/commproc.c for details. - */ - cp->cp_simode = 0x10000000; - cp->cp_brgc1 = - ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN; - - /* Enable SMC1 for console output. - */ - *MBX_CSR1 &= ~CSR1_COMEN; - } - else { -#endif - /* SMC1 is used as console port. - */ - tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; - rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase]; - - /* Issue a stop transmit, and wait for it. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, - CPM_CR_STOP_TX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); -#ifdef CONFIG_MBX - } -#endif - - /* Make the first buffer the only buffer. - */ - tbdf->cbd_sc |= BD_SC_WRAP; - rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; - - /* Single character receive. - */ - up->smc_mrblr = 1; - up->smc_maxidl = 0; - - /* Initialize Tx/Rx parameters. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - /* Enable transmitter/receiver. - */ - sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; -} - -void -serial_putchar(const char c) -{ - volatile cbd_t *tbdf; - volatile char *buf; - volatile smc_uart_t *up; - - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; - tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; - - /* Wait for last character to go. - */ - buf = (char *)tbdf->cbd_bufaddr; - while (tbdf->cbd_sc & BD_SC_READY); - - *buf = c; - tbdf->cbd_datlen = 1; - tbdf->cbd_sc |= BD_SC_READY; -} - -char -serial_getc() -{ - volatile cbd_t *rbdf; - volatile char *buf; - volatile smc_uart_t *up; - char c; - - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; - rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; - - /* Wait for character to show up. - */ - buf = (char *)rbdf->cbd_bufaddr; - while (rbdf->cbd_sc & BD_SC_EMPTY); - c = *buf; - rbdf->cbd_sc |= BD_SC_EMPTY; - - return(c); -} - -int -serial_tstc() -{ - volatile cbd_t *rbdf; - volatile smc_uart_t *up; - - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; - rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; - - return(!(rbdf->cbd_sc & BD_SC_EMPTY)); -} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mm/fault.c linux.ac/arch/ppc/mm/fault.c --- linux.vanilla/arch/ppc/mm/fault.c Thu May 25 17:38:29 2000 +++ linux.ac/arch/ppc/mm/fault.c Sun Jun 4 21:10:57 2000 @@ -238,7 +238,7 @@ /* The pgtable.h claims some functions generically exist, but I * can't find them...... */ -pte_t *find_pte(struct mm_struct *mm, unsigned long address) +pte_t *va_to_pte(struct mm_struct *mm, unsigned long address) { pgd_t *dir; pmd_t *pmd; @@ -267,7 +267,7 @@ { pte_t *pte; - pte = find_pte(current->mm, address); + pte = va_to_pte(current->mm, address); if (pte) return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK-1))); return (0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mm/init.c linux.ac/arch/ppc/mm/init.c --- linux.vanilla/arch/ppc/mm/init.c Thu May 25 17:38:29 2000 +++ linux.ac/arch/ppc/mm/init.c Sat Jun 10 21:48:24 2000 @@ -94,6 +94,7 @@ extern int num_memory; extern struct mem_info memory[]; extern boot_infos_t *boot_infos; +extern unsigned int rtas_data, rtas_size; #ifndef CONFIG_SMP struct pgtable_cache_struct quicklists; #endif @@ -116,21 +117,26 @@ #endif /* CONFIG_8260 */ static void mapin_ram(void); void map_page(unsigned long va, unsigned long pa, int flags); +void set_phys_avail(struct mem_pieces *mp); extern void die_if_kernel(char *,struct pt_regs *,long); -struct mem_pieces phys_mem; - +extern char _start[], _end[]; +extern char _stext[], etext[]; extern struct task_struct *current_set[NR_CPUS]; -PTE *Hash, *Hash_end; -unsigned long Hash_size, Hash_mask; +struct mem_pieces phys_mem; +char *klimit = _end; +struct mem_pieces phys_avail; + +PTE *Hash=0, *Hash_end; +unsigned long Hash_size=0, Hash_mask; #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) -unsigned long _SDR1; +unsigned long _SDR1=0; static void hash_init(void); union ubat { /* BAT register values to be loaded */ BAT bat; -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE u64 word[2]; #else u32 word[2]; @@ -479,7 +485,8 @@ if (pmd_none(oldpd) && mem_init_done) set_pgdir(va, *(pgd_t *)pd); set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags))); - flush_hash_page(0, va); + if (mem_init_done) + flush_hash_page(0, va); } #ifndef CONFIG_8xx @@ -503,11 +510,16 @@ void local_flush_tlb_all(void) { +#ifdef CONFIG_PPC64BRIDGE + /* XXX this assumes that the vmalloc arena starts no lower than + * 0xd0000000 on 64-bit machines. */ + flush_hash_segments(0xd, 0xffffff); +#else __clear_user(Hash, Hash_size); - _tlbia(); #ifdef CONFIG_SMP smp_send_tlb_invalidate(0); -#endif +#endif /* CONFIG_SMP */ +#endif /* CONFIG_PPC64BRIDGE */ } /* @@ -690,7 +702,7 @@ int i; unsigned long v, p, s, f; -#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) if (!__map_without_bats) { unsigned long tot, mem_base, bl, done; unsigned long max_size = (256<<20); @@ -725,7 +737,7 @@ RAM_PAGE); } } -#endif /* !CONFIG_4xx && !CONFIG_8xx */ +#endif /* !CONFIG_4xx && !CONFIG_8xx && !CONFIG_POWER4 */ for (i = 0; i < phys_mem.n_regions; ++i) { v = (ulong)__va(phys_mem.regions[i].address); @@ -940,9 +952,7 @@ if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300); hash_init(); -#ifdef CONFIG_PPC64 - _SDR1 = __pa(Hash) | (ffz(~Hash_size) - 7)-11; -#else +#ifndef CONFIG_PPC64BRIDGE _SDR1 = __pa(Hash) | (Hash_mask >> 10); #endif @@ -952,6 +962,11 @@ /* Map in all of RAM starting at KERNELBASE */ mapin_ram(); +#ifdef CONFIG_POWER4 + ioremap_base = ioremap_bot = 0xfffff000; + isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000; + +#else /* CONFIG_POWER4 */ /* * Setup the bat mappings we're going to load that cover * the io areas. RAM was mapped by mapin_ram(). @@ -966,26 +981,15 @@ break; case _MACH_chrp: setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE); -#ifdef CONFIG_PPC64 - /* temporary hack to get working until page tables are stable -- Cort*/ -/* setbat(1, 0x80000000, 0xc0000000, 0x10000000, IO_PAGE);*/ - setbat(3, 0xd0000000, 0xd0000000, 0x10000000, IO_PAGE); +#ifdef CONFIG_PPC64BRIDGE + setbat(1, 0x80000000, 0xc0000000, 0x10000000, IO_PAGE); #else setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE); setbat(3, 0x90000000, 0x90000000, 0x10000000, IO_PAGE); -#endif +#endif break; case _MACH_Pmac: -#if 0 - { - unsigned long base = 0xf3000000; - struct device_node *macio = find_devices("mac-io"); - if (macio && macio->n_addrs) - base = macio->addrs[0].address; - setbat(0, base, base, 0x100000, IO_PAGE); - } -#endif - ioremap_base = 0xf0000000; + ioremap_base = 0xf8000000; break; case _MACH_apus: /* Map PPC exception vectors. */ @@ -1009,6 +1013,7 @@ break; } ioremap_bot = ioremap_base; +#endif /* CONFIG_POWER4 */ #else /* CONFIG_8xx */ end_of_DRAM = m8xx_find_end_of_memory(); @@ -1080,6 +1085,7 @@ /* remove the bootmem bitmap from the available memory */ mem_pieces_remove(&phys_avail, start, boot_mapsize, 1); + /* add everything in phys_avail into the bootmem map */ for (i = 0; i < phys_avail.n_regions; ++i) free_bootmem(phys_avail.regions[i].address, @@ -1159,9 +1165,6 @@ int codepages = 0; int datapages = 0; int initpages = 0; -#if defined(CONFIG_ALL_PPC) - extern unsigned int rtas_data, rtas_size; -#endif /* defined(CONFIG_ALL_PPC) */ max_mapnr = max_low_pfn; high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); num_physpages = max_mapnr; /* RAM is assumed contiguous */ @@ -1223,13 +1226,7 @@ unsigned long __init *pmac_find_end_of_memory(void) { unsigned long a, total; - unsigned long ram_limit = 0xf0000000 - KERNELBASE; - /* allow 0x08000000 for IO space */ - if ( _machine & (_MACH_prep|_MACH_Pmac) ) - ram_limit = 0xd8000000 - KERNELBASE; -#ifdef CONFIG_PPC64 - ram_limit = 64<<20; -#endif + unsigned long ram_limit = 0xe0000000 - KERNELBASE; memory_node = find_devices("memory"); if (memory_node == NULL) { @@ -1422,27 +1419,42 @@ */ static void __init hash_init(void) { - int Hash_bits; - unsigned long h, ramsize; + int Hash_bits, mb, mb2; + unsigned int hmask, ramsize, h; extern unsigned int hash_page_patch_A[], hash_page_patch_B[], hash_page_patch_C[], hash_page[]; + ramsize = (ulong)end_of_DRAM - KERNELBASE; +#ifdef CONFIG_PPC64BRIDGE + /* The hash table has already been allocated and initialized + in prom.c */ + Hash_mask = (Hash_size >> 7) - 1; + hmask = Hash_mask >> 9; + Hash_bits = __ilog2(Hash_size) - 7; + mb = 25 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 25 - Hash_bits; + +#else /* CONFIG_PPC64BRIDGE */ + if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105); /* * Allow 64k of hash table for every 16MB of memory, * up to a maximum of 2MB. */ - ramsize = (ulong)end_of_DRAM - KERNELBASE; - for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2) + for (h = 64<<10; h < ramsize / 256 && h < (2<<20); h *= 2) ; Hash_size = h; -#ifdef CONFIG_PPC64 - Hash_mask = (h >> 7) - 1; -#else Hash_mask = (h >> 6) - 1; -#endif - + hmask = Hash_mask >> 10; + Hash_bits = __ilog2(h) - 6; + mb = 26 - Hash_bits; + if (Hash_bits > 16) + Hash_bits = 16; + mb2 = 26 - Hash_bits; + /* shrink the htab since we don't use it on 603's -- Cort */ switch (_get_PVR()>>16) { case 3: /* 603 */ @@ -1459,50 +1471,36 @@ if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); /* Find some memory for the hash table. */ - if ( Hash_size ) + if ( Hash_size ) { Hash = mem_pieces_find(Hash_size, Hash_size); - else + /*__clear_user(Hash, Hash_size);*/ + } else Hash = 0; +#endif /* CONFIG_PPC64BRIDGE */ - printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", + printk("Total memory = %dMB; using %ldkB for hash table (at %p)\n", ramsize >> 20, Hash_size >> 10, Hash); if ( Hash_size ) { if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345); Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); - /*__clear_user(Hash, Hash_size);*/ /* * Patch up the instructions in head.S:hash_page */ -#ifdef CONFIG_PPC64 - Hash_bits = ffz(~Hash_size) - 7; -#else - Hash_bits = ffz(~Hash_size) - 6; -#endif hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff) | (__pa(Hash) >> 16); hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) - | ((26 - Hash_bits) << 6); - if (Hash_bits > 16) - Hash_bits = 16; + | (mb << 6); hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) - | ((26 - Hash_bits) << 6); + | (mb2 << 6); hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) -#ifdef CONFIG_PPC64 - | (Hash_mask >> 11); -#else - | (Hash_mask >> 10); -#endif + | hmask; hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) -#ifdef CONFIG_PPC64 - | (Hash_mask >> 11); -#else - | (Hash_mask >> 10); -#endif + | hmask; #if 0 /* see hash_page in head.S, note also patch_C ref below */ hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff) - | (Hash_mask >> 10); + | hmask; #endif /* * Ensure that the locations we've patched have been written @@ -1579,3 +1577,48 @@ return (ret); } #endif + +/* + * Set phys_avail to phys_mem less the kernel text/data/bss. + */ +void __init +set_phys_avail(struct mem_pieces *mp) +{ + unsigned long kstart, ksize; + + /* + * Initially, available phyiscal memory is equivalent to all + * physical memory. + */ + + phys_avail = *mp; + + /* + * Map out the kernel text/data/bss from the available physical + * memory. + */ + + kstart = __pa(_stext); /* should be 0 */ + ksize = PAGE_ALIGN(klimit - _stext); + + mem_pieces_remove(&phys_avail, kstart, ksize, 0); + mem_pieces_remove(&phys_avail, 0, 0x4000, 0); + +#if defined(CONFIG_BLK_DEV_INITRD) + /* Remove the init RAM disk from the available memory. */ + if (initrd_start) { + mem_pieces_remove(&phys_avail, __pa(initrd_start), + initrd_end - initrd_start, 1); + } +#endif /* CONFIG_BLK_DEV_INITRD */ +#ifdef CONFIG_ALL_PPC + /* remove the RTAS pages from the available memory */ + if (rtas_data) + mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); +#endif /* CONFIG_ALL_PPC */ +#ifdef CONFIG_PPC64BRIDGE + /* Remove the hash table from the available memory */ + if (Hash) + mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1); +#endif /* CONFIG_PPC64BRIDGE */ +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mm/mem_pieces.c linux.ac/arch/ppc/mm/mem_pieces.c --- linux.vanilla/arch/ppc/mm/mem_pieces.c Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/mm/mem_pieces.c Sat Jun 10 21:48:24 2000 @@ -18,18 +18,11 @@ #include #include #include - -#include -#include +#include #include "mem_pieces.h" -extern char _start[], _end[]; -extern char _stext[], etext[]; - -char *klimit = _end; - -struct mem_pieces phys_avail; +extern struct mem_pieces phys_avail; static void mem_pieces_print(struct mem_pieces *); @@ -142,7 +135,7 @@ rp->address = start; rp->size = size; } -#endif +#endif /* CONFIG_APUS || CONFIG_ALL_PPC */ void __init mem_pieces_sort(struct mem_pieces *mp) @@ -184,39 +177,4 @@ ++d; } mp->n_regions = d; -} - -/* - * Set phys_avail to phys_mem less the kernel text/data/bss. - */ -void __init -set_phys_avail(struct mem_pieces *mp) -{ - unsigned long kstart, ksize; - - /* - * Initially, available phyiscal memory is equivalent to all - * physical memory. - */ - - phys_avail = *mp; - - /* - * Map out the kernel text/data/bss from the available physical - * memory. - */ - - kstart = __pa(_stext); /* should be 0 */ - ksize = PAGE_ALIGN(klimit - _stext); - - mem_pieces_remove(&phys_avail, kstart, ksize, 0); - mem_pieces_remove(&phys_avail, 0, 0x4000, 0); - -#if defined(CONFIG_BLK_DEV_INITRD) - /* Remove the init RAM disk from the available memory. */ - if (initrd_start) { - mem_pieces_remove(&phys_avail, __pa(initrd_start), - initrd_end - initrd_start, 1); - } -#endif /* CONFIG_BLK_DEV_INITRD */ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/mm/mem_pieces.h linux.ac/arch/ppc/mm/mem_pieces.h --- linux.vanilla/arch/ppc/mm/mem_pieces.h Thu May 25 17:38:30 2000 +++ linux.ac/arch/ppc/mm/mem_pieces.h Sat Jun 10 21:48:24 2000 @@ -17,8 +17,7 @@ #ifndef __MEM_PIECES_H__ #define __MEM_PIECES_H__ -#include - +#include #ifdef __cplusplus extern "C" { @@ -34,13 +33,6 @@ struct reg_property regions[MEM_PIECES_MAX]; }; - -/* Global Variables */ - -extern char *klimit; -extern struct mem_pieces phys_avail; - - /* Function Prototypes */ extern void *mem_pieces_find(unsigned int size, unsigned int align); @@ -50,9 +42,6 @@ unsigned int size); extern void mem_pieces_coalesce(struct mem_pieces *mp); extern void mem_pieces_sort(struct mem_pieces *mp); - -extern void set_phys_avail(struct mem_pieces *mp); - #ifdef __cplusplus } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/xmon/start.c linux.ac/arch/ppc/xmon/start.c --- linux.vanilla/arch/ppc/xmon/start.c Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/xmon/start.c Sat Jun 10 21:48:24 2000 @@ -272,7 +272,7 @@ if ( _machine == _MACH_chrp ) { sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */ - sccd[0] = 3; eieio(); /* DLL = 38400 baud */ + sccd[0] = 12; eieio(); /* DLL = 9600 baud */ sccd[1] = 0; eieio(); sccd[2] = 0; eieio(); /* FCR = 0 */ sccd[3] = 3; eieio(); /* LCR = 8N1 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/xmon/xmon.c linux.ac/arch/ppc/xmon/xmon.c --- linux.vanilla/arch/ppc/xmon/xmon.c Thu May 25 17:38:32 2000 +++ linux.ac/arch/ppc/xmon/xmon.c Sat Jun 10 21:48:24 2000 @@ -19,6 +19,7 @@ static int size = 1; static unsigned ndump = 64; static unsigned nidump = 16; +static unsigned ncsum = 4096; static int termch; static u_int bus_error_jmp[100]; @@ -85,6 +86,7 @@ static void cacheflush(void); static char *pretty_print_addr(unsigned long addr); static char *lookup_name(unsigned long addr); +static void csum(void); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned); extern void printf(const char *fmt, ...); @@ -261,7 +263,7 @@ bp->enabled = 0; } } -#ifndef CONFIG_8xx +#if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) if (dabr.enabled) set_dabr(dabr.address); if (iabr.enabled) @@ -276,7 +278,7 @@ struct bpt *bp; unsigned instr; -#ifndef CONFIG_8xx +#if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) set_dabr(0); set_iabr(0); #endif @@ -379,10 +381,70 @@ case 'b': bpt_cmds(); break; + case 'c': + csum(); + break; } } } +static unsigned short fcstab[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 +}; + +#define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) + +static void +csum(void) +{ + unsigned int i; + unsigned short fcs; + unsigned char v; + + scanhex(&adrs); + scanhex(&ncsum); + fcs = 0xffff; + for (i = 0; i < ncsum; ++i) { + if (mread(adrs+i, &v, 1) == 0) { + printf("csum stopped at %x\n", adrs+i); + break; + } + fcs = FCS(fcs, v); + } + printf("%x\n", fcs); +} + static void bpt_cmds(void) { @@ -393,7 +455,7 @@ cmd = inchar(); switch (cmd) { -#ifndef CONFIG_8xx +#if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4) case 'd': mode = 7; cmd = inchar(); @@ -695,6 +757,7 @@ } #endif +#ifndef CONFIG_PPC64BRIDGE static void dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) { @@ -752,6 +815,67 @@ if (last_found) printf(" ... %x\n", last_va); } + +#else /* CONFIG_PPC64BRIDGE */ +static void +dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) +{ + extern void *Hash; + extern unsigned long Hash_size; + unsigned *htab = Hash; + unsigned hsize = Hash_size; + unsigned v, hmask, va, last_va; + int found, last_found, i; + unsigned *hg, w1, last_w2, last_va0; + + last_found = 0; + hmask = hsize / 128 - 1; + va = start; + start = (start >> 12) & 0xffff; + end = (end >> 12) & 0xffff; + for (v = start; v < end; ++v) { + found = 0; + hg = htab + (((v ^ seg) & hmask) * 32); + w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4); + for (i = 0; i < 8; ++i, hg += 4) { + if (hg[1] == w1) { + found = 1; + break; + } + } + if (!found) { + w1 ^= 2; + hg = htab + ((~(v ^ seg) & hmask) * 32); + for (i = 0; i < 8; ++i, hg += 4) { + if (hg[1] == w1) { + found = 1; + break; + } + } + } + if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) { + if (last_found) { + if (last_va != last_va0) + printf(" ... %x", last_va); + printf("\n"); + } + if (found) { + printf("%x to %x", va, hg[3]); + last_va0 = va; + } + last_found = found; + } + if (found) { + last_w2 = hg[3] & ~0x180; + last_va = va; + } + va += 4096; + } + if (last_found) + printf(" ... %x\n", last_va); +} +#endif /* CONFIG_PPC64BRIDGE */ + static unsigned hash_ctx; static unsigned hash_start; static unsigned hash_end; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/s390/config.in linux.ac/arch/s390/config.in --- linux.vanilla/arch/s390/config.in Thu May 25 17:38:35 2000 +++ linux.ac/arch/s390/config.in Tue May 30 14:52:16 2000 @@ -63,10 +63,6 @@ comment 'Kernel hacking' #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -bool 'Kernel profiling support' CONFIG_PROFILE -if [ "$CONFIG_PROFILE" = "y" ]; then - int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 -fi if [ "$CONFIG_CTC" = "y" ]; then bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/s390/defconfig linux.ac/arch/s390/defconfig --- linux.vanilla/arch/s390/defconfig Thu May 25 17:38:35 2000 +++ linux.ac/arch/s390/defconfig Tue May 30 14:52:23 2000 @@ -174,5 +174,4 @@ # # Kernel hacking # -# CONFIG_PROFILE is not set # CONFIG_REMOTE_DEBUG is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/s390/kernel/traps.c linux.ac/arch/s390/kernel/traps.c --- linux.vanilla/arch/s390/kernel/traps.c Thu May 25 17:38:35 2000 +++ linux.ac/arch/s390/kernel/traps.c Tue May 30 14:41:10 2000 @@ -62,9 +62,6 @@ force_sig(signr, tsk); \ } - -void page_exception(void); - /* TODO: define these as 'pgm_check_handler_t xxx;' asmlinkage void divide_error(void); asmlinkage void debug(void); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sh/defconfig linux.ac/arch/sh/defconfig --- linux.vanilla/arch/sh/defconfig Thu May 25 17:38:34 2000 +++ linux.ac/arch/sh/defconfig Mon May 29 19:25:15 2000 @@ -59,10 +59,6 @@ # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_DEV_DAC960 is not set - -# -# Additional Block Devices -# # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_LVM is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/config.in linux.ac/arch/sparc/config.in --- linux.vanilla/arch/sparc/config.in Thu May 25 17:38:24 2000 +++ linux.ac/arch/sparc/config.in Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.93 2000/05/22 08:12:19 davem Exp $ +# $Id: config.in,v 1.94 2000/06/04 22:23:10 anton Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -12,6 +12,15 @@ endmenu mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment comment 'General setup' define_bool CONFIG_VT y @@ -56,15 +65,6 @@ bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL source drivers/parport/Config.in dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT -endmenu - -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi endmenu mainmenu_option next_comment diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/kernel/entry.S linux.ac/arch/sparc/kernel/entry.S --- linux.vanilla/arch/sparc/kernel/entry.S Thu May 25 17:38:24 2000 +++ linux.ac/arch/sparc/kernel/entry.S Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.164 2000/05/09 17:40:13 davem Exp $ +/* $Id: entry.S,v 1.165 2000/06/05 06:08:45 anton Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -945,7 +945,7 @@ and %l5, %l4, %l5 /* Test for NULL pte_t * in vmalloc area. */ - sethi %hi(SUN4C_VMALLOC_START), %l4 + sethi %hi(VMALLOC_START), %l4 cmp %l5, %l4 blu,a C_LABEL(invalid_segment_patch1) lduXa [%l5] ASI_SEGMAP, %l4 @@ -1072,7 +1072,7 @@ andn %l4, 0x1ff, %l5 1: - sethi %hi(SUN4C_VMALLOC_START), %l4 + sethi %hi(VMALLOC_START), %l4 cmp %l5, %l4 bgeu 1f diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/kernel/ioport.c linux.ac/arch/sparc/kernel/ioport.c --- linux.vanilla/arch/sparc/kernel/ioport.c Thu May 25 17:38:25 2000 +++ linux.ac/arch/sparc/kernel/ioport.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.37 2000/03/28 06:38:19 davem Exp $ +/* $Id: ioport.c,v 1.38 2000/06/04 06:23:52 anton Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -52,11 +52,11 @@ /* This points to the next to use virtual memory for DVMA mappings */ static struct resource _sparc_dvma = { - "sparc_dvma", DVMA_VADDR, DVMA_VADDR + DVMA_LEN - 1 + "sparc_dvma", DVMA_VADDR, DVMA_END - 1 }; /* This points to the start of I/O mappings, cluable from outside. */ /*ext*/ struct resource sparc_iomap = { - "sparc_iomap", IOBASE_VADDR, IOBASE_END-1 + "sparc_iomap", IOBASE_VADDR, IOBASE_END - 1 }; /* @@ -453,7 +453,11 @@ panic("sbus_dma_sync_single: 0x%x\n", ba); va = (unsigned long) phys_to_virt(mmu_translate_dvma(ba)); - mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); + /* + * XXX This bogosity will be fixed with the iommu rewrite coming soon + * to a kernel near you. - Anton + */ + /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ } void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/kernel/signal.c linux.ac/arch/sparc/kernel/signal.c --- linux.vanilla/arch/sparc/kernel/signal.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc/kernel/signal.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.103 2000/05/09 17:40:13 davem Exp $ +/* $Id: signal.c,v 1.104 2000/05/27 00:49:35 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/kernel/traps.c linux.ac/arch/sparc/kernel/traps.c --- linux.vanilla/arch/sparc/kernel/traps.c Thu May 25 17:38:25 2000 +++ linux.ac/arch/sparc/kernel/traps.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.62 2000/05/09 17:40:13 davem Exp $ +/* $Id: traps.c,v 1.63 2000/06/04 06:23:52 anton Exp $ * arch/sparc/kernel/traps.c * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) @@ -498,8 +498,6 @@ */ extern void sparc_cpu_startup(void); - -extern ctxd_t *srmmu_ctx_table_phys; int linux_smp_still_initting; unsigned int thiscpus_tbr; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/hypersparc.S linux.ac/arch/sparc/mm/hypersparc.S --- linux.vanilla/arch/sparc/mm/hypersparc.S Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/hypersparc.S Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: hypersparc.S,v 1.15 2000/05/09 17:40:13 davem Exp $ +/* $Id: hypersparc.S,v 1.16 2000/06/04 06:23:52 anton Exp $ * hypersparc.S: High speed Hypersparc mmu/cache operations. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -28,7 +28,7 @@ .globl hypersparc_flush_cache_all, hypersparc_flush_cache_mm .globl hypersparc_flush_cache_range, hypersparc_flush_cache_page - .globl hypersparc_flush_page_to_ram, hypersparc_flush_chunk + .globl hypersparc_flush_page_to_ram .globl hypersparc_flush_page_for_dma, hypersparc_flush_sig_insns .globl hypersparc_flush_tlb_all, hypersparc_flush_tlb_mm .globl hypersparc_flush_tlb_range, hypersparc_flush_tlb_page @@ -229,7 +229,6 @@ /* HyperSparc is copy-back. */ hypersparc_flush_page_to_ram: -hypersparc_flush_chunk: sethi %hi(vac_line_size), %g1 ld [%g1 + %lo(vac_line_size)], %o4 andn %o0, (PAGE_SIZE - 1), %o0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/init.c linux.ac/arch/sparc/mm/init.c --- linux.vanilla/arch/sparc/mm/init.c Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/init.c Sat Jun 10 21:50:42 2000 @@ -1,10 +1,10 @@ -/* $Id: init.c,v 1.85 2000/05/09 17:40:13 davem Exp $ +/* $Id: init.c,v 1.86 2000/06/04 06:23:52 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 2000 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) */ #include @@ -125,9 +125,13 @@ unsigned long bootmap_pfn; int i; - /* Limit maximum memory until we implement highmem for sparc */ - if (!cmdline_memory_size || cmdline_memory_size > 0x0d000000) - cmdline_memory_size = 0x0d000000; + /* + * XXX Limit maximum memory until we implement highmem for sparc. + * The nocache region has taken up some room but I'll rearrange + * the virtual address regions soon - Anton + */ + if (!cmdline_memory_size || cmdline_memory_size > 0x0c000000) + cmdline_memory_size = 0x0c000000; /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/srmmu.c linux.ac/arch/sparc/mm/srmmu.c --- linux.vanilla/arch/sparc/mm/srmmu.c Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/srmmu.c Sat Jun 10 21:50:42 2000 @@ -1,11 +1,11 @@ -/* $Id: srmmu.c,v 1.209 2000/05/09 17:40:13 davem Exp $ +/* $Id: srmmu.c,v 1.211 2000/06/04 06:23:52 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Pete Zaitcev * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1999 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1999,2000 Anton Blanchard (anton@linuxcare.com) */ #include @@ -57,6 +57,8 @@ extern unsigned long last_valid_pfn; +pgd_t *srmmu_swapper_pg_dir; + #ifdef CONFIG_SMP #define FLUSH_BEGIN(mm) #define FLUSH_END @@ -65,40 +67,29 @@ #define FLUSH_END } #endif -BTFIXUPDEF_CALL(void, ctxd_set, ctxd_t *, pgd_t *) BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *) - -#define ctxd_set(ctxp,pgdp) BTFIXUP_CALL(ctxd_set)(ctxp,pgdp) #define pmd_set(pmdp,ptep) BTFIXUP_CALL(pmd_set)(pmdp,ptep) BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long) -BTFIXUPDEF_CALL(void, flush_chunk, unsigned long) - #define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page) + int flush_page_for_dma_global = 1; -#define flush_chunk(chunk) BTFIXUP_CALL(flush_chunk)(chunk) + #ifdef CONFIG_SMP BTFIXUPDEF_CALL(void, local_flush_page_for_dma, unsigned long) - #define local_flush_page_for_dma(page) BTFIXUP_CALL(local_flush_page_for_dma)(page) #endif -static struct srmmu_stats { - int invall; - int invpg; - int invrnge; - int invmm; -} module_stats; - char *srmmu_name; ctxd_t *srmmu_ctx_table_phys; ctxd_t *srmmu_context_table; int viking_mxcc_present = 0; -static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; +spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; -/* In general all page table modifications should use the V8 atomic +/* + * In general all page table modifications should use the V8 atomic * swap instruction. This insures the mmu and the cpu are in sync * with respect to ref/mod bits in the page tables. */ @@ -117,31 +108,55 @@ return ((x & 0xF0000000) != 0); } +int srmmu_cache_pagetables; + +/* XXX Make this dynamic based on ram size - Anton */ +#define SRMMU_NOCACHE_NPAGES 256 +#define SRMMU_NOCACHE_VADDR 0xfc000000 +#define SRMMU_NOCACHE_SIZE (SRMMU_NOCACHE_NPAGES*PAGE_SIZE) +#define SRMMU_NOCACHE_END (SRMMU_NOCACHE_VADDR + SRMMU_NOCACHE_SIZE) +#define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16) +#define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4) + +void *srmmu_nocache_pool; +void *srmmu_nocache_bitmap; +int srmmu_nocache_low; +int srmmu_nocache_used; + +/* This makes sense. Honest it does - Anton */ +#define __nocache_pa(VADDR) (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool)) +#define __nocache_va(PADDR) (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR) +#define __nocache_fix(VADDR) __va(__nocache_pa(VADDR)) + static unsigned long srmmu_pgd_page(pgd_t pgd) -{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } +{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__nocache_va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } static unsigned long srmmu_pmd_page(pmd_t pmd) -{ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } +{ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__nocache_va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } static unsigned long srmmu_pte_pagenr(pte_t pte) { return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); } static inline int srmmu_pte_none(pte_t pte) { return !(pte_val(pte) & 0xFFFFFFF); } + static inline int srmmu_pte_present(pte_t pte) { return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); } -static inline void srmmu_pte_clear(pte_t *ptep) { set_pte(ptep, __pte(0)); } +static inline void srmmu_pte_clear(pte_t *ptep) +{ set_pte(ptep, __pte(0)); } static inline int srmmu_pmd_none(pmd_t pmd) { return !(pmd_val(pmd) & 0xFFFFFFF); } + static inline int srmmu_pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; } static inline int srmmu_pmd_present(pmd_t pmd) { return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); } -static inline void srmmu_pmd_clear(pmd_t *pmdp) { set_pte((pte_t *)pmdp, __pte(0)); } +static inline void srmmu_pmd_clear(pmd_t *pmdp) +{ set_pte((pte_t *)pmdp, __pte(0)); } static inline int srmmu_pgd_none(pgd_t pgd) { return !(pgd_val(pgd) & 0xFFFFFFF); } @@ -152,18 +167,35 @@ static inline int srmmu_pgd_present(pgd_t pgd) { return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); } -static inline void srmmu_pgd_clear(pgd_t * pgdp) { set_pte((pte_t *)pgdp, __pte(0)); } +static inline void srmmu_pgd_clear(pgd_t * pgdp) +{ set_pte((pte_t *)pgdp, __pte(0)); } + +static inline int srmmu_pte_write(pte_t pte) +{ return pte_val(pte) & SRMMU_WRITE; } + +static inline int srmmu_pte_dirty(pte_t pte) +{ return pte_val(pte) & SRMMU_DIRTY; } + +static inline int srmmu_pte_young(pte_t pte) +{ return pte_val(pte) & SRMMU_REF; } + +static inline pte_t srmmu_pte_wrprotect(pte_t pte) +{ return __pte(pte_val(pte) & ~SRMMU_WRITE);} + +static inline pte_t srmmu_pte_mkclean(pte_t pte) +{ return __pte(pte_val(pte) & ~SRMMU_DIRTY);} + +static inline pte_t srmmu_pte_mkold(pte_t pte) +{ return __pte(pte_val(pte) & ~SRMMU_REF);} -static inline int srmmu_pte_write(pte_t pte) { return pte_val(pte) & SRMMU_WRITE; } -static inline int srmmu_pte_dirty(pte_t pte) { return pte_val(pte) & SRMMU_DIRTY; } -static inline int srmmu_pte_young(pte_t pte) { return pte_val(pte) & SRMMU_REF; } - -static inline pte_t srmmu_pte_wrprotect(pte_t pte) { return __pte(pte_val(pte) & ~SRMMU_WRITE);} -static inline pte_t srmmu_pte_mkclean(pte_t pte) { return __pte(pte_val(pte) & ~SRMMU_DIRTY);} -static inline pte_t srmmu_pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~SRMMU_REF);} -static inline pte_t srmmu_pte_mkwrite(pte_t pte) { return __pte(pte_val(pte) | SRMMU_WRITE);} -static inline pte_t srmmu_pte_mkdirty(pte_t pte) { return __pte(pte_val(pte) | SRMMU_DIRTY);} -static inline pte_t srmmu_pte_mkyoung(pte_t pte) { return __pte(pte_val(pte) | SRMMU_REF);} +static inline pte_t srmmu_pte_mkwrite(pte_t pte) +{ return __pte(pte_val(pte) | SRMMU_WRITE);} + +static inline pte_t srmmu_pte_mkdirty(pte_t pte) +{ return __pte(pte_val(pte) | SRMMU_DIRTY);} + +static inline pte_t srmmu_pte_mkyoung(pte_t pte) +{ return __pte(pte_val(pte) | SRMMU_REF);} /* * Conversion functions: convert a page and protection to a page entry, @@ -176,265 +208,233 @@ { return __pte(((page) >> 4) | pgprot_val(pgprot)); } static pte_t srmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space) -{ - return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot)); -} +{ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot)); } +/* XXX should we hyper_flush_whole_icache here - Anton */ static void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) -{ - set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4))); -} +{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); } static void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ - set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__pa((unsigned long) pmdp) >> 4))); -} +{ set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pmdp) >> 4))); } static void srmmu_pmd_set(pmd_t * pmdp, pte_t * ptep) -{ - set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (__pa((unsigned long) ptep) >> 4))); -} +{ set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) ptep) >> 4))); } static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot) -{ - return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); -} +{ return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); } /* to find an entry in a top-level page table... */ extern inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address) -{ - return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); -} +{ return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); } /* Find an entry in the second-level page table.. */ static inline pmd_t *srmmu_pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) srmmu_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); -} +{ return (pmd_t *) pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); } /* Find an entry in the third-level page table.. */ static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) srmmu_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); -} +{ return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); } -static inline pte_t *srmmu_get_pte_fast(void) +/* XXX Make this SMP safe - Anton */ +unsigned long __srmmu_get_nocache(int size, int align) { - struct page *ret; - - spin_lock(&pte_spinlock); - if ((ret = (struct page *)pte_quicklist) != NULL) { - unsigned int mask = (unsigned int)ret->pprev_hash; - unsigned int tmp, off; - - if (mask & 0xff) - for (tmp = 0x001, off = 0; (mask & tmp) == 0; tmp <<= 1, off += 256); - else - for (tmp = 0x100, off = 2048; (mask & tmp) == 0; tmp <<= 1, off += 256); - (unsigned int)ret->pprev_hash = mask & ~tmp; - if (!(mask & ~tmp)) - pte_quicklist = (unsigned long *)ret->next_hash; - ret = (struct page *)(page_address(ret) + off); - pgtable_cache_size--; + int offset = srmmu_nocache_low; + int i; + unsigned long va_tmp, phys_tmp; + int lowest_failed = 0; + + size = size >> SRMMU_NOCACHE_BITMAP_SHIFT; + +repeat: + offset = find_next_zero_bit(srmmu_nocache_bitmap, SRMMU_NOCACHE_BITMAP_SIZE, offset); + + /* we align on physical address */ + if (align) { + va_tmp = (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT)); + phys_tmp = (__nocache_pa(va_tmp) + align - 1) & ~(align - 1); + va_tmp = (unsigned long)__nocache_va(phys_tmp); + offset = (va_tmp - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT; + } + + if ((SRMMU_NOCACHE_BITMAP_SIZE - offset) < size) { + printk("Run out of nocached RAM!\n"); + return 0; } - spin_unlock(&pte_spinlock); - return (pte_t *)ret; + + i = 0; + while(i < size) { + if (test_bit(offset + i, srmmu_nocache_bitmap)) { + lowest_failed = 1; + offset = offset + i + 1; + goto repeat; + } + i++; + } + + i = 0; + while(i < size) { + set_bit(offset + i, srmmu_nocache_bitmap); + i++; + srmmu_nocache_used++; + } + + if (!lowest_failed && offset > srmmu_nocache_low) + srmmu_nocache_low = offset; + + return (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT)); } -static inline pte_t *srmmu_get_pte_slow(void) +unsigned long srmmu_get_nocache(int size, int align) { - pte_t *ret; - struct page *page; - - ret = (pte_t *)get_free_page(GFP_KERNEL); - if (ret) { - page = mem_map + MAP_NR(ret); - flush_chunk((unsigned long)ret); - (unsigned int)page->pprev_hash = 0xfffe; - spin_lock(&pte_spinlock); - (unsigned long *)page->next_hash = pte_quicklist; - pte_quicklist = (unsigned long *)page; - pgtable_cache_size += 15; - } - return ret; -} - -static inline pgd_t *srmmu_get_pgd_fast(void) -{ - struct page *ret; - - spin_lock(&pgd_spinlock); - if ((ret = (struct page *)pgd_quicklist) != NULL) { - unsigned int mask = (unsigned int)ret->pprev_hash; - unsigned int tmp, off; - - for (tmp = 0x001, off = 0; (mask & tmp) == 0; tmp <<= 1, off += 1024); - (unsigned int)ret->pprev_hash = mask & ~tmp; - if (!(mask & ~tmp)) - pgd_quicklist = (unsigned long *)ret->next_hash; - ret = (struct page *)(page_address(ret) + off); - pgd_cache_size--; - } - spin_unlock(&pgd_spinlock); - return (pgd_t *)ret; + unsigned long tmp; + + tmp = __srmmu_get_nocache(size, align); + + memset((void *)tmp, 0, size); + + return tmp; } -static inline pgd_t *srmmu_get_pgd_slow(void) +/* XXX Make this SMP safe - Anton */ +void srmmu_free_nocache(unsigned long vaddr, int size) { - pgd_t *ret; - struct page *page; - - ret = (pgd_t *)__get_free_page(GFP_KERNEL); - if (ret) { - pgd_t *init = pgd_offset(&init_mm, 0); - memset(ret + (0 * PTRS_PER_PGD), 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(ret + (0 * PTRS_PER_PGD) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - memset(ret + (1 * PTRS_PER_PGD), 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(ret + (1 * PTRS_PER_PGD) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - memset(ret + (2 * PTRS_PER_PGD), 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(ret + (2 * PTRS_PER_PGD) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - memset(ret + (3 * PTRS_PER_PGD), 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); - memcpy(ret + (3 * PTRS_PER_PGD) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - page = mem_map + MAP_NR(ret); - flush_chunk((unsigned long)ret); - (unsigned int)page->pprev_hash = 0xe; - spin_lock(&pgd_spinlock); - (unsigned long *)page->next_hash = pgd_quicklist; - pgd_quicklist = (unsigned long *)page; - pgd_cache_size += 3; - spin_unlock(&pgd_spinlock); + int offset = (vaddr - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT; + + size = size >> SRMMU_NOCACHE_BITMAP_SHIFT; + + while(size--) { + clear_bit(offset + size, srmmu_nocache_bitmap); + srmmu_nocache_used--; } - return ret; + + if (offset < srmmu_nocache_low) + srmmu_nocache_low = offset; } -static void srmmu_free_pte_slow(pte_t *pte) +void srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end); + +void srmmu_nocache_init(void) { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long paddr, vaddr; + unsigned long pteval; + + srmmu_nocache_pool = __alloc_bootmem(SRMMU_NOCACHE_SIZE, PAGE_SIZE, 0UL); + memset(srmmu_nocache_pool, 0, SRMMU_NOCACHE_SIZE); + + srmmu_nocache_bitmap = __alloc_bootmem(SRMMU_NOCACHE_BITMAP_SIZE, SMP_CACHE_BYTES, 0UL); + memset(srmmu_nocache_bitmap, 0, SRMMU_NOCACHE_BITMAP_SIZE); + + srmmu_swapper_pg_dir = (pgd_t *)__srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE); + memset(__nocache_fix(srmmu_swapper_pg_dir), 0, SRMMU_PGD_TABLE_SIZE); + init_mm.pgd = srmmu_swapper_pg_dir; + + srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, SRMMU_NOCACHE_END); + + paddr = __pa((unsigned long)srmmu_nocache_pool); + vaddr = SRMMU_NOCACHE_VADDR; + + while (vaddr < SRMMU_NOCACHE_END) { + pgd = pgd_offset_k(vaddr); + pmd = pmd_offset(__nocache_fix(pgd), vaddr); + pte = pte_offset(__nocache_fix(pmd), vaddr); + + pteval = ((paddr >> 4) | SRMMU_ET_PTE | SRMMU_PRIV); + + if (srmmu_cache_pagetables) + pteval |= SRMMU_CACHE; + + set_pte(__nocache_fix(pte), pteval); + + vaddr += PAGE_SIZE; + paddr += PAGE_SIZE; + } + + flush_cache_all(); + flush_tlb_all(); } -static void srmmu_free_pgd_slow(pgd_t *pgd) +static inline pgd_t *srmmu_pgd_alloc(void) { + pgd_t *pgd = NULL; + + pgd = (pgd_t *)__srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE); + if (pgd) { + pgd_t *init = pgd_offset_k(0); + memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); + memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + } + + return pgd; } -static inline void srmmu_pte_free(pte_t *pte) +static void srmmu_pgd_free(pgd_t *pgd) { - struct page *page = mem_map + MAP_NR(pte); - - spin_lock(&pte_spinlock); - if (!page->pprev_hash) { - (unsigned long *)page->next_hash = pte_quicklist; - pte_quicklist = (unsigned long *)page; - } - (unsigned int)page->pprev_hash |= (1 << ((((unsigned long)pte) >> 8) & 15)); - pgtable_cache_size++; - spin_unlock(&pte_spinlock); + srmmu_free_nocache((unsigned long)pgd, SRMMU_PGD_TABLE_SIZE); } static pte_t *srmmu_pte_alloc(pmd_t * pmd, unsigned long address) { address = (address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1); if(srmmu_pmd_none(*pmd)) { - pte_t *page = srmmu_get_pte_fast(); - - if (page) { + pte_t *page = (pte_t *)srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE); + if(page) { + spin_unlock(&pte_spinlock); pmd_set(pmd, page); return page + address; } - page = srmmu_get_pte_slow(); - if(srmmu_pmd_none(*pmd)) { - if(page) { - spin_unlock(&pte_spinlock); - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - if (page) { - (unsigned int)(((struct page *)pte_quicklist)->pprev_hash) = 0xffff; - pgtable_cache_size++; - spin_unlock(&pte_spinlock); - } + /* XXX fix this - Anton */ + pmd_set(pmd, BAD_PAGETABLE); + return NULL; } if(srmmu_pmd_bad(*pmd)) { printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + /* XXX fix this - Anton */ pmd_set(pmd, BAD_PAGETABLE); return NULL; } return ((pte_t *) pmd_page(*pmd)) + address; } -/* Real three-level page tables on SRMMU. */ -static void srmmu_pmd_free(pmd_t * pmd) +static inline void srmmu_pte_free(pte_t *pte) { - return srmmu_pte_free((pte_t *)pmd); + srmmu_free_nocache((unsigned long)pte, SRMMU_PTE_TABLE_SIZE); } static pmd_t *srmmu_pmd_alloc(pgd_t * pgd, unsigned long address) { address = (address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1); if(srmmu_pgd_none(*pgd)) { - pmd_t *page = (pmd_t *)srmmu_get_pte_fast(); - - if (page) { + pmd_t *page = (pmd_t *)srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); + if(page) { + spin_unlock(&pte_spinlock); pgd_set(pgd, page); return page + address; } - page = (pmd_t *)srmmu_get_pte_slow(); - if(srmmu_pgd_none(*pgd)) { - if(page) { - spin_unlock(&pte_spinlock); - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); - return NULL; - } - if (page) { - (unsigned int)(((struct page *)pte_quicklist)->pprev_hash) = 0xffff; - pgtable_cache_size++; - spin_unlock(&pte_spinlock); - } + /* XXX fix this - Anton */ + pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); + return NULL; } if(srmmu_pgd_bad(*pgd)) { printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + /* XXX fix this - Anton */ pgd_set(pgd, (pmd_t *) BAD_PAGETABLE); return NULL; } return (pmd_t *) pgd_page(*pgd) + address; } -static void srmmu_pgd_free(pgd_t *pgd) -{ - struct page *page = mem_map + MAP_NR(pgd); - - spin_lock(&pgd_spinlock); - if (!page->pprev_hash) { - (unsigned long *)page->next_hash = pgd_quicklist; - pgd_quicklist = (unsigned long *)page; - } - (unsigned int)page->pprev_hash |= (1 << ((((unsigned long)pgd) >> 10) & 3)); - pgd_cache_size++; - spin_unlock(&pgd_spinlock); -} - -static pgd_t *srmmu_pgd_alloc(void) +static void srmmu_pmd_free(pmd_t * pmd) { - pgd_t *ret; - - ret = srmmu_get_pgd_fast(); - if (ret) return ret; - return srmmu_get_pgd_slow(); + srmmu_free_nocache((unsigned long)pmd, SRMMU_PMD_TABLE_SIZE); } - static void srmmu_set_pgdir(unsigned long address, pgd_t entry) { struct task_struct * p; - struct page *page; read_lock(&tasklist_lock); for_each_task(p) { @@ -443,24 +443,6 @@ *pgd_offset(p->mm,address) = entry; } read_unlock(&tasklist_lock); - spin_lock(&pgd_spinlock); - address >>= SRMMU_PGDIR_SHIFT; - for (page = (struct page *)pgd_quicklist; page; page = page->next_hash) { - pgd_t *pgd = (pgd_t *)page_address(page); - unsigned int mask = (unsigned int)page->pprev_hash; - - if (mask & 1) - pgd[address + 0 * SRMMU_PTRS_PER_PGD] = entry; - if (mask & 2) - pgd[address + 1 * SRMMU_PTRS_PER_PGD] = entry; - if (mask & 4) - pgd[address + 2 * SRMMU_PTRS_PER_PGD] = entry; - if (mask & 8) - pgd[address + 3 * SRMMU_PTRS_PER_PGD] = entry; - if (mask) - flush_chunk((unsigned long)pgd); - } - spin_unlock(&pgd_spinlock); } static void srmmu_set_pte_cacheable(pte_t *ptep, pte_t pteval) @@ -468,62 +450,6 @@ srmmu_set_entry(ptep, pte_val(pteval)); } -static void srmmu_set_pte_nocache_cypress(pte_t *ptep, pte_t pteval) -{ - register unsigned long a, b, c, d, e, f, g; - unsigned long line, page; - - srmmu_set_entry(ptep, pte_val(pteval)); - page = ((unsigned long)ptep) & PAGE_MASK; - line = (page + PAGE_SIZE) - 0x100; - a = 0x20; b = 0x40; c = 0x60; d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0; - goto inside; - do { - line -= 0x100; - inside: - __asm__ __volatile__("sta %%g0, [%0] %1\n\t" - "sta %%g0, [%0 + %2] %1\n\t" - "sta %%g0, [%0 + %3] %1\n\t" - "sta %%g0, [%0 + %4] %1\n\t" - "sta %%g0, [%0 + %5] %1\n\t" - "sta %%g0, [%0 + %6] %1\n\t" - "sta %%g0, [%0 + %7] %1\n\t" - "sta %%g0, [%0 + %8] %1\n\t" : : - "r" (line), - "i" (ASI_M_FLUSH_PAGE), - "r" (a), "r" (b), "r" (c), "r" (d), - "r" (e), "r" (f), "r" (g)); - } while(line != page); -} - -static void srmmu_set_pte_nocache_viking(pte_t *ptep, pte_t pteval) -{ - unsigned long vaddr; - int set; - int i; - - set = ((unsigned long)ptep >> 5) & 0x7f; - vaddr = (KERNBASE + PAGE_SIZE) | (set << 5); - srmmu_set_entry(ptep, pte_val(pteval)); - for (i = 0; i < 8; i++) { - __asm__ __volatile__ ("ld [%0], %%g0" : : "r" (vaddr)); - vaddr += PAGE_SIZE; - } -} - -static void srmmu_quick_kernel_fault(unsigned long address) -{ -#ifdef CONFIG_SMP - printk("CPU[%d]: Kernel faults at addr=0x%08lx\n", - smp_processor_id(), address); - while (1) ; -#else - printk("Kernel faults at addr=0x%08lx\n", address); - printk("PTE=%08lx\n", srmmu_hwprobe((address & PAGE_MASK))); - die_if_kernel("SRMMU bolixed...", current->thread.kregs); -#endif -} - static inline void alloc_context(struct mm_struct *old_mm, struct mm_struct *mm) { struct ctx_list *ctxp; @@ -567,8 +493,9 @@ spin_lock(&srmmu_context_spinlock); alloc_context(old_mm, mm); spin_unlock(&srmmu_context_spinlock); - ctxd_set(&srmmu_context_table[mm->context], mm->pgd); + srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd); } + /* XXX should we hyper_flush_whole_icache() here - Anton */ srmmu_set_context(mm->context); } @@ -581,12 +508,13 @@ unsigned long tmp; physaddr &= PAGE_MASK; - pgdp = srmmu_pgd_offset(&init_mm, virt_addr); + pgdp = pgd_offset_k(virt_addr); pmdp = pmd_offset(pgdp, virt_addr); ptep = pte_offset(pmdp, virt_addr); tmp = (physaddr >> 4) | SRMMU_ET_PTE; - /* I need to test whether this is consistent over all + /* + * I need to test whether this is consistent over all * sun4m's. The bus_type represents the upper 4 bits of * 36-bit physical address on the I/O space lines... */ @@ -606,7 +534,7 @@ pmd_t *pmdp; pte_t *ptep; - pgdp = srmmu_pgd_offset(&init_mm, virt_addr); + pgdp = pgd_offset_k(virt_addr); pmdp = pmd_offset(pgdp, virt_addr); ptep = pte_offset(pmdp, virt_addr); @@ -615,7 +543,8 @@ flush_tlb_all(); } -/* On the SRMMU we do not have the problems with limited tlb entries +/* + * On the SRMMU we do not have the problems with limited tlb entries * for mapping kernel pages, so we just take things from the free page * pool. As a side effect we are putting a little too much pressure * on the gfp() subsystem. This setup also makes the logic of the @@ -646,14 +575,14 @@ extern void tsunami_flush_page_to_ram(unsigned long page); extern void tsunami_flush_page_for_dma(unsigned long page); extern void tsunami_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); -extern void tsunami_flush_chunk(unsigned long chunk); extern void tsunami_flush_tlb_all(void); extern void tsunami_flush_tlb_mm(struct mm_struct *mm); extern void tsunami_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end); extern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); extern void tsunami_setup_blockops(void); -/* Workaround, until we find what's going on with Swift. When low on memory, +/* + * Workaround, until we find what's going on with Swift. When low on memory, * it sometimes loops in fault/handle_mm_fault incl. flush_tlb_page to find * out it is already in page tables/ fault again on the same instruction. * I really don't understand it, have checked it and contexts @@ -693,7 +622,6 @@ extern void swift_flush_page_to_ram(unsigned long page); extern void swift_flush_page_for_dma(unsigned long page); extern void swift_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); -extern void swift_flush_chunk(unsigned long chunk); extern void swift_flush_tlb_all(void); extern void swift_flush_tlb_mm(struct mm_struct *mm); extern void swift_flush_tlb_range(struct mm_struct *mm, @@ -727,11 +655,11 @@ /* same as above: srmmu_flush_tlb_page() */ } } - module_stats.invpg++; } #endif -/* The following are all MBUS based SRMMU modules, and therefore could +/* + * The following are all MBUS based SRMMU modules, and therefore could * be found in a multiprocessor configuration. On the whole, these * chips seems to be much more touchy about DVMA and page tables * with respect to cache coherency. @@ -900,11 +828,6 @@ } while(line != page); } -static void cypress_flush_chunk(unsigned long chunk) -{ - cypress_flush_page_to_ram(chunk); -} - /* Cypress is also IO cache coherent. */ static void cypress_flush_page_for_dma(unsigned long page) { @@ -921,7 +844,6 @@ static void cypress_flush_tlb_all(void) { srmmu_flush_whole_tlb(); - module_stats.invall++; } static void cypress_flush_tlb_mm(struct mm_struct *mm) @@ -936,7 +858,6 @@ : "r" (SRMMU_CTX_REG), "r" (0x300), "r" (mm->context), "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE) : "g5"); - module_stats.invmm++; FLUSH_END } @@ -959,7 +880,6 @@ "r" (size), "r" (SRMMU_PGDIR_SIZE), "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE) : "g5", "cc"); - module_stats.invrnge++; FLUSH_END } @@ -977,7 +897,6 @@ : "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (page & PAGE_MASK), "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE) : "g5"); - module_stats.invpg++; FLUSH_END } @@ -993,8 +912,6 @@ extern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr); extern void viking_flush_page(unsigned long page); extern void viking_mxcc_flush_page(unsigned long page); -extern void viking_flush_chunk(unsigned long chunk); -extern void viking_mxcc_flush_chunk(unsigned long chunk); extern void viking_flush_tlb_all(void); extern void viking_flush_tlb_mm(struct mm_struct *mm); extern void viking_flush_tlb_range(struct mm_struct *mm, unsigned long start, @@ -1014,7 +931,6 @@ extern void hypersparc_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end); extern void hypersparc_flush_cache_page(struct vm_area_struct *vma, unsigned long page); extern void hypersparc_flush_page_to_ram(unsigned long page); -extern void hypersparc_flush_chunk(unsigned long chunk); extern void hypersparc_flush_page_for_dma(unsigned long page); extern void hypersparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr); extern void hypersparc_flush_tlb_all(void); @@ -1023,39 +939,8 @@ extern void hypersparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); extern void hypersparc_setup_blockops(void); -static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) -{ - unsigned long page = ((unsigned long)ptep) & PAGE_MASK; - - srmmu_set_entry(ptep, pte_val(pteval)); - hypersparc_flush_page_to_ram(page); -} - -static void hypersparc_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) -{ - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4)))); - hypersparc_flush_page_to_ram((unsigned long)ctxp); - hyper_flush_whole_icache(); -} - -static void hypersparc_switch_mm(struct mm_struct *old_mm, - struct mm_struct *mm, struct task_struct *tsk, int cpu) -{ - if(mm->context == NO_CONTEXT) { - ctxd_t *ctxp; - - spin_lock(&srmmu_context_spinlock); - alloc_context(old_mm, mm); - spin_unlock(&srmmu_context_spinlock); - ctxp = &srmmu_context_table[mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) mm->pgd) >> 4)))); - hypersparc_flush_page_to_ram((unsigned long)ctxp); - } - hyper_flush_whole_icache(); - srmmu_set_context(mm->context); -} - -/* NOTE: All of this startup code assumes the low 16mb (approx.) of +/* + * NOTE: All of this startup code assumes the low 16mb (approx.) of * kernel mappings are done with one single contiguous chunk of * ram. On small ram machines (classics mainly) we only get * around 8mb mapped for us. @@ -1067,35 +952,62 @@ prom_halt(); } -static inline void srmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end) +void __init srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end) +{ + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + while(start < end) { + pgdp = pgd_offset_k(start); + if(pgd_none(*(pgd_t *)__nocache_fix(pgdp))) { + pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); + if (pmdp == NULL) + early_pgtable_allocfail("pmd"); + memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE); + pgd_set(__nocache_fix(pgdp), pmdp); + } + pmdp = pmd_offset(__nocache_fix(pgdp), start); + if(pmd_none(*(pmd_t *)__nocache_fix(pmdp))) { + ptep = (pte_t *)__srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE); + if (ptep == NULL) + early_pgtable_allocfail("pte"); + memset(__nocache_fix(ptep), 0, SRMMU_PTE_TABLE_SIZE); + pmd_set(__nocache_fix(pmdp), ptep); + } + start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK; + } +} + +void __init srmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end) { pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; while(start < end) { - pgdp = srmmu_pgd_offset(&init_mm, start); - if(srmmu_pgd_none(*pgdp)) { - pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE, - SRMMU_PMD_TABLE_SIZE, 0UL); + pgdp = pgd_offset_k(start); + if(pgd_none(*pgdp)) { + pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); if (pmdp == NULL) early_pgtable_allocfail("pmd"); memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE); - srmmu_pgd_set(pgdp, pmdp); + pgd_set(pgdp, pmdp); } - pmdp = srmmu_pmd_offset(pgdp, start); - if(srmmu_pmd_none(*pmdp)) { - ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL); + pmdp = pmd_offset(pgdp, start); + if(pmd_none(*pmdp)) { + ptep = (pte_t *)__srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE); if (ptep == NULL) early_pgtable_allocfail("pte"); memset(ptep, 0, SRMMU_PTE_TABLE_SIZE); - srmmu_pmd_set(pmdp, ptep); + pmd_set(pmdp, ptep); } start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK; } } -/* This is much cleaner than poking around physical address space +/* + * This is much cleaner than poking around physical address space * looking at the prom's page table directly which is what most * other OS's do. Yuck... this is much better. */ @@ -1131,35 +1043,34 @@ what = 2; } - pgdp = srmmu_pgd_offset(&init_mm, start); + pgdp = pgd_offset_k(start); if(what == 2) { - *pgdp = __pgd(prompte); + *(pgd_t *)__nocache_fix(pgdp) = __pgd(prompte); start += SRMMU_PGDIR_SIZE; continue; } - if(srmmu_pgd_none(*pgdp)) { - pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE, - SRMMU_PMD_TABLE_SIZE, 0UL); + if(srmmu_pgd_none(*(pgd_t *)__nocache_fix(pgdp))) { + pmdp = (pmd_t *)__srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE, SRMMU_PMD_TABLE_SIZE); if (pmdp == NULL) early_pgtable_allocfail("pmd"); - memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE); - srmmu_pgd_set(pgdp, pmdp); + memset(__nocache_fix(pmdp), 0, SRMMU_PMD_TABLE_SIZE); + pgd_set(__nocache_fix(pgdp), pmdp); } - pmdp = srmmu_pmd_offset(pgdp, start); + pmdp = srmmu_pmd_offset(__nocache_fix(pgdp), start); if(what == 1) { - *pmdp = __pmd(prompte); + *(pmd_t *)__nocache_fix(pmdp) = __pmd(prompte); start += SRMMU_PMD_SIZE; continue; } - if(srmmu_pmd_none(*pmdp)) { - ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL); + if(srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) { + ptep = (pte_t *)__srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE); if (ptep == NULL) early_pgtable_allocfail("pte"); - memset(ptep, 0, SRMMU_PTE_TABLE_SIZE); - srmmu_pmd_set(pmdp, ptep); + memset(__nocache_fix(ptep), 0, SRMMU_PTE_TABLE_SIZE); + pmd_set(__nocache_fix(pmdp), ptep); } - ptep = srmmu_pte_offset(pmdp, start); - *ptep = __pte(prompte); + ptep = srmmu_pte_offset(__nocache_fix(pmdp), start); + *(pte_t *)__nocache_fix(ptep) = __pte(prompte); start += PAGE_SIZE; } } @@ -1171,15 +1082,14 @@ /* Create a third-level SRMMU 16MB page mapping. */ static void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base) { - pgd_t *pgdp = srmmu_pgd_offset(&init_mm, vaddr); + pgd_t *pgdp = pgd_offset_k(vaddr); unsigned long big_pte; big_pte = KERNEL_PTE(phys_base >> 4); - *pgdp = __pgd(big_pte); + *(pgd_t *)__nocache_fix(pgdp) = __pgd(big_pte); } -/* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. - */ +/* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. */ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry) { unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK); @@ -1254,53 +1164,40 @@ prom_printf("Something wrong, can't find cpu node in paging_init.\n"); prom_halt(); } - - memset(swapper_pg_dir, 0, PAGE_SIZE); last_valid_pfn = end_pfn = bootmem_init(); - srmmu_allocate_ptable_skeleton(KERNBASE, (unsigned long)__va(end_of_phys_memory)); -#if CONFIG_SUN_IO - srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); - srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); -#endif - - /* This does not logically belong here, but we need to - * call it at the moment we are able to use the bootmem - * allocator. - */ - sun_serial_setup(); - + srmmu_nocache_init(); srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); map_kernel(); -#define BOOTMEM_BROKEN -#ifdef BOOTMEM_BROKEN - srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t)*2, SMP_CACHE_BYTES, 0UL); - (unsigned long)srmmu_context_table += num_contexts*sizeof(ctxd_t); - (unsigned long)srmmu_context_table &= ~(num_contexts*sizeof(ctxd_t)-1); -#else - srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t), num_contexts*sizeof(ctxd_t), 0UL); -#endif + /* ctx table has to be physically aligned to its size */ + srmmu_context_table = (ctxd_t *)__srmmu_get_nocache(num_contexts*sizeof(ctxd_t), num_contexts*sizeof(ctxd_t)); + srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa((unsigned long)srmmu_context_table); - srmmu_ctx_table_phys = (ctxd_t *) __pa((unsigned long) srmmu_context_table); for(i = 0; i < num_contexts; i++) - ctxd_set(&srmmu_context_table[i], swapper_pg_dir); + srmmu_ctxd_set((ctxd_t *)__nocache_fix(&srmmu_context_table[i]), srmmu_swapper_pg_dir); flush_cache_all(); - if(BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page) { - unsigned long start = (unsigned long)srmmu_context_table; - unsigned long end = PAGE_ALIGN((unsigned long)srmmu_context_table + num_contexts*sizeof(ctxd_t)); - - while(start < end) { - viking_flush_page(start); - start += PAGE_SIZE; - } - } - srmmu_set_ctable_ptr((unsigned long) srmmu_ctx_table_phys); + srmmu_set_ctable_ptr((unsigned long)srmmu_ctx_table_phys); flush_tlb_all(); poke_srmmu(); +#if CONFIG_SUN_IO + srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); + srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); +#endif + + flush_cache_all(); + flush_tlb_all(); + + /* + * This does not logically belong here, but we need to + * call it at the moment we are able to use the bootmem + * allocator. + */ + sun_serial_setup(); + sparc_context_init(num_contexts); { @@ -1309,36 +1206,19 @@ zones_size[ZONE_DMA] = end_pfn; free_area_init(zones_size); } - -#ifdef CONFIG_BLK_DEV_INITRD - /* If initial ramdisk was specified with physical address, - translate it here, as the p2v translation in srmmu - is not straightforward. */ - if (initrd_start && initrd_start < KERNBASE) { - initrd_start = __va(initrd_start); - initrd_end = __va(initrd_end); - if (initrd_end <= initrd_start) - initrd_start = 0; - } -#endif - } static int srmmu_mmu_info(char *buf) { return sprintf(buf, "MMU type\t: %s\n" - "invall\t\t: %d\n" - "invmm\t\t: %d\n" - "invrnge\t\t: %d\n" - "invpg\t\t: %d\n" "contexts\t: %d\n" + "nocache total\t: %d\n" + "nocache used\t: %d\n" , srmmu_name, - module_stats.invall, - module_stats.invmm, - module_stats.invrnge, - module_stats.invpg, - num_contexts + num_contexts, + SRMMU_NOCACHE_SIZE, + (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT) ); } @@ -1351,7 +1231,7 @@ if(mm->context != NO_CONTEXT) { flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir); + srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir); flush_tlb_mm(mm); spin_lock(&srmmu_context_spinlock); free_context(mm->context); @@ -1429,30 +1309,6 @@ } } -static void hypersparc_destroy_context(struct mm_struct *mm) -{ - if(mm->context != NO_CONTEXT) { - ctxd_t *ctxp; - - /* HyperSparc is copy-back, any data for this - * process in a modified cache line is stale - * and must be written back to main memory now - * else we eat shit later big time. - */ - flush_cache_mm(mm); - - ctxp = &srmmu_context_table[mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) swapper_pg_dir) >> 4)))); - hypersparc_flush_page_to_ram((unsigned long)ctxp); - - flush_tlb_mm(mm); - spin_lock(&srmmu_context_spinlock); - free_context(mm->context); - spin_unlock(&srmmu_context_spinlock); - mm->context = NO_CONTEXT; - } -} - /* Init various srmmu chip types. */ static void __init srmmu_is_bad(void) { @@ -1527,7 +1383,7 @@ srmmu_set_mmureg(mreg); -#if 0 /* I think this is bad news... -DaveM */ +#if 0 /* XXX I think this is bad news... -DaveM */ hyper_clear_all_tags(); #endif @@ -1543,7 +1399,6 @@ init_vac_layout(); - BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_hyper, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM); @@ -1561,11 +1416,7 @@ BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(flush_chunk, hypersparc_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ - BTFIXUPSET_CALL(ctxd_set, hypersparc_ctxd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(switch_mm, hypersparc_switch_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(destroy_context, hypersparc_destroy_context, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM); poke_srmmu = poke_hypersparc; @@ -1615,7 +1466,6 @@ { init_vac_layout(); - BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_cypress, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM); @@ -1629,7 +1479,6 @@ BTFIXUPSET_CALL(flush_tlb_page, cypress_flush_tlb_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, cypress_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, cypress_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP); @@ -1673,7 +1522,8 @@ /* Enable I & D caches */ mreg = srmmu_get_mmureg(); mreg |= (SWIFT_IE | SWIFT_DE); - /* The Swift branch folding logic is completely broken. At + /* + * The Swift branch folding logic is completely broken. At * trap time, if things are just right, if can mistakenly * think that a trap is coming from kernel mode when in fact * it is coming from user mode (it mis-executes the branch in @@ -1702,7 +1552,8 @@ case 0x30: srmmu_modtype = Swift_lots_o_bugs; hwbug_bitmask |= (HWBUG_KERN_ACCBROKEN | HWBUG_KERN_CBITBROKEN); - /* Gee george, I wonder why Sun is so hush hush about + /* + * Gee george, I wonder why Sun is so hush hush about * this hardware bug... really braindamage stuff going * on here. However I think we can find a way to avoid * all of the workaround overhead under Linux. Basically, @@ -1723,7 +1574,8 @@ case 0x31: srmmu_modtype = Swift_bad_c; hwbug_bitmask |= HWBUG_KERN_CBITBROKEN; - /* You see Sun allude to this hardware bug but never + /* + * You see Sun allude to this hardware bug but never * admit things directly, they'll say things like, * "the Swift chip cache problems" or similar. */ @@ -1738,7 +1590,6 @@ BTFIXUPSET_CALL(flush_cache_page, swift_flush_cache_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, swift_flush_cache_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, swift_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ BTFIXUPSET_CALL(flush_tlb_all, swift_flush_tlb_all, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_mm, swift_flush_tlb_mm, BTFIXUPCALL_NORM); @@ -1753,7 +1604,8 @@ flush_page_for_dma_global = 0; - /* Are you now convinced that the Swift is one of the + /* + * Are you now convinced that the Swift is one of the * biggest VLSI abortions of all time? Bravo Fujitsu! * Fujitsu, the !#?!%$'d up processor people. I bet if * you examined the microcode of the Swift you'd find @@ -1815,21 +1667,15 @@ turbosparc_flush_dcache(); } -static void turbosparc_flush_chunk(unsigned long chunk) -{ -} - static void turbosparc_flush_tlb_all(void) { srmmu_flush_whole_tlb(); - module_stats.invall++; } static void turbosparc_flush_tlb_mm(struct mm_struct *mm) { FLUSH_BEGIN(mm) srmmu_flush_whole_tlb(); - module_stats.invmm++; FLUSH_END } @@ -1837,7 +1683,6 @@ { FLUSH_BEGIN(mm) srmmu_flush_whole_tlb(); - module_stats.invrnge++; FLUSH_END } @@ -1845,7 +1690,6 @@ { FLUSH_BEGIN(vma->vm_mm) srmmu_flush_whole_tlb(); - module_stats.invpg++; FLUSH_END } @@ -1906,7 +1750,6 @@ BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM); @@ -1927,7 +1770,8 @@ static void __init init_tsunami(void) { - /* Tsunami's pretty sane, Sun and TI actually got it + /* + * Tsunami's pretty sane, Sun and TI actually got it * somewhat right this time. Fujitsu should have * taken some lessons from them. */ @@ -1940,7 +1784,6 @@ BTFIXUPSET_CALL(flush_cache_page, tsunami_flush_cache_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, tsunami_flush_cache_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, tsunami_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ BTFIXUPSET_CALL(flush_tlb_all, tsunami_flush_tlb_all, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_mm, tsunami_flush_tlb_mm, BTFIXUPCALL_NORM); @@ -1968,7 +1811,8 @@ mxcc_control &= ~(MXCC_CTL_RRC); mxcc_set_creg(mxcc_control); - /* We don't need memory parity checks. + /* + * We don't need memory parity checks. * XXX This is a mess, have to dig out later. ecd. viking_mxcc_turn_off_parity(&mreg, &mxcc_control); */ @@ -1980,9 +1824,7 @@ mreg &= ~(VIKING_TCENABLE); if(smp_catch++) { - /* Must disable mixed-cmd mode here for - * other cpu's. - */ + /* Must disable mixed-cmd mode here for other cpu's. */ bpreg = viking_get_bpreg(); bpreg &= ~(VIKING_ACTION_MIX); viking_set_bpreg(bpreg); @@ -2021,14 +1863,12 @@ viking_mxcc_present = 0; msi_set_sync(); - BTFIXUPSET_CALL(set_pte, srmmu_set_pte_nocache_viking, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_chunk, viking_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ - - /* We need this to make sure old viking takes no hits + /* + * We need this to make sure old viking takes no hits * on it's cache for dma snoops to workaround the * "load from non-cacheable memory" interrupt bug. * This is only necessary because of the new way in @@ -2041,7 +1881,7 @@ srmmu_name = "TI Viking/MXCC"; viking_mxcc_present = 1; - BTFIXUPSET_CALL(flush_chunk, viking_mxcc_flush_chunk, BTFIXUPCALL_NOP); /* local flush _only_ */ + srmmu_cache_pagetables = 1; /* MXCC vikings lack the DMA snooping bug. */ BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page_for_dma, BTFIXUPCALL_NOP); @@ -2118,8 +1958,10 @@ return; } - /* Now Fujitsu TurboSparc. It might happen that it is - in Swift emulation mode, so we will check later... */ + /* + * Now Fujitsu TurboSparc. It might happen that it is + * in Swift emulation mode, so we will check later... + */ if (psr_typ == 0 && psr_vers == 5) { init_turbosparc(); return; @@ -2166,74 +2008,10 @@ srmmu_is_bad(); } +/* dont laugh, static pagetables */ static int srmmu_check_pgt_cache(int low, int high) { - struct page *page, *page2; - int freed = 0; - - if (pgtable_cache_size > high) { - spin_lock(&pte_spinlock); - for (page2 = NULL, page = (struct page *)pte_quicklist; page;) { - if ((unsigned int)page->pprev_hash == 0xffff) { - if (page2) - page2->next_hash = page->next_hash; - else - (struct page *)pte_quicklist = page->next_hash; - page->next_hash = NULL; - page->pprev_hash = NULL; - pgtable_cache_size -= 16; - __free_page(page); - freed++; - if (page2) - page = page2->next_hash; - else - page = (struct page *)pte_quicklist; - if (pgtable_cache_size <= low) - break; - continue; - } - page2 = page; - page = page->next_hash; - } - spin_unlock(&pte_spinlock); - } - if (pgd_cache_size > high / 4) { - spin_lock(&pgd_spinlock); - for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) { - if ((unsigned int)page->pprev_hash == 0xf) { - if (page2) - page2->next_hash = page->next_hash; - else - (struct page *)pgd_quicklist = page->next_hash; - page->next_hash = NULL; - page->pprev_hash = NULL; - pgd_cache_size -= 4; - __free_page(page); - freed++; - if (page2) - page = page2->next_hash; - else - page = (struct page *)pgd_quicklist; - if (pgd_cache_size <= low / 4) - break; - continue; - } - page2 = page; - page = page->next_hash; - } - spin_unlock(&pgd_spinlock); - } - return freed; -} - -static void srmmu_flush_dma_area(unsigned long addr, int len) -{ - /* XXX Later */ -} - -static void srmmu_inval_dma_area(unsigned long addr, int len) -{ - /* XXX Later */ + return 0; } extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme, @@ -2302,10 +2080,6 @@ #ifndef CONFIG_SMP BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2); #endif - BTFIXUPSET_CALL(get_pte_fast, srmmu_get_pte_fast, BTFIXUPCALL_RETINT(0)); - BTFIXUPSET_CALL(get_pgd_fast, srmmu_get_pgd_fast, BTFIXUPCALL_RETINT(0)); - BTFIXUPSET_CALL(free_pte_slow, srmmu_free_pte_slow, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(free_pgd_slow, srmmu_free_pgd_slow, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(do_check_pgt_cache, srmmu_check_pgt_cache, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_pgdir, srmmu_set_pgdir, BTFIXUPCALL_NORM); @@ -2317,7 +2091,7 @@ BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_SETHI(none_mask, 0xF0000000); /* P3: is it used? */ + BTFIXUPSET_SETHI(none_mask, 0xF0000000); /* XXX P3: is it used? */ BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0); @@ -2369,16 +2143,8 @@ BTFIXUPSET_CALL(free_task_struct, srmmu_free_task_struct, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(get_task_struct, srmmu_get_task_struct, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(quick_kernel_fault, srmmu_quick_kernel_fault, BTFIXUPCALL_NORM); - /* SRMMU specific. */ - BTFIXUPSET_CALL(ctxd_set, srmmu_ctxd_set, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_set, srmmu_pmd_set, BTFIXUPCALL_NORM); - -/* hmm isn't flush_dma_area the same thing as flush_page_for_dma? */ -/* It is, except flush_page_for_dma was local to srmmu.c */ - BTFIXUPSET_CALL(mmu_flush_dma_area, srmmu_flush_dma_area, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_inval_dma_area, srmmu_inval_dma_area, BTFIXUPCALL_NORM); get_srmmu_type(); patch_window_trap_handlers(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/sun4c.c linux.ac/arch/sparc/mm/sun4c.c --- linux.vanilla/arch/sparc/mm/sun4c.c Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/sun4c.c Sat Jun 10 21:50:42 2000 @@ -1,10 +1,10 @@ -/* $Id: sun4c.c,v 1.192 2000/05/09 17:40:13 davem Exp $ +/* $Id: sun4c.c,v 1.194 2000/06/05 06:08:45 anton Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au) - * Copyright (C) 1997,99 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1997-2000 Anton Blanchard (anton@linuxcare.com) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ @@ -597,14 +597,6 @@ /* XXX Implement this */ } -static void sun4c_inval_dma_area(unsigned long virt, int len) -{ -} - -static void sun4c_flush_dma_area(unsigned long virt, int len) -{ -} - /* TLB management. */ /* Don't change this struct without changing entry.S. This is used @@ -1011,13 +1003,6 @@ } } -/* This is now a fast in-window trap handler to avoid any and all races. */ -static void sun4c_quick_kernel_fault(unsigned long address) -{ - printk("Kernel faults at addr 0x%08lx\n", address); - panic("sun4c kernel fault handler bolixed..."); -} - /* 2 page buckets for task struct and kernel stack allocation. * * TASK_STACK_BEGIN @@ -2280,22 +2265,6 @@ return (pgd_t *)ret; } -static int sun4c_check_pgt_cache(int low, int high) -{ - int freed = 0; - if (pgtable_cache_size > high) { - do { - if (pgd_quicklist) - free_pgd_slow(get_pgd_fast()), freed++; - if (pmd_quicklist) - free_pmd_slow(get_pmd_fast()), freed++; - if (pte_quicklist) - free_pte_slow(get_pte_fast()), freed++; - } while (pgtable_cache_size > low); - } - return freed; -} - static void sun4c_set_pgdir(unsigned long address, pgd_t entry) { /* Nothing to do */ @@ -2361,11 +2330,6 @@ return (pte_t *) sun4c_pmd_page(*pmd) + address; } -static pte_t *sun4c_pte_get(void) -{ - return sun4c_get_pte_fast(); -} - /* * allocating and freeing a pmd is trivial: the 1-entry pmd is * inside the pgd, so has no extra memory associated with it. @@ -2389,6 +2353,22 @@ return sun4c_get_pgd_fast(); } +static int sun4c_check_pgt_cache(int low, int high) +{ + int freed = 0; + if (pgtable_cache_size > high) { + do { + if (pgd_quicklist) + sun4c_free_pgd_slow(sun4c_get_pgd_fast()), freed++; + if (pmd_quicklist) + sun4c_free_pmd_slow(sun4c_get_pmd_fast()), freed++; + if (pte_quicklist) + sun4c_free_pte_slow(sun4c_get_pte_fast()), freed++; + } while (pgtable_cache_size > low); + } + return freed; +} + /* There are really two cases of aliases to watch out for, and these * are: * @@ -2568,7 +2548,7 @@ memset(pg3, 0, PAGE_SIZE); /* Save work later. */ - vaddr = SUN4C_VMALLOC_START; + vaddr = VMALLOC_START; swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg0); vaddr += SUN4C_PGDIR_SIZE; swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg1); @@ -2628,10 +2608,6 @@ #ifndef CONFIG_SMP BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM); #endif - BTFIXUPSET_CALL(get_pte_fast, sun4c_pte_get, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(get_pgd_fast, sun4c_pgd_alloc, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(free_pte_slow, sun4c_free_pte_slow, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(free_pgd_slow, sun4c_free_pgd_slow, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_pgdir, sun4c_set_pgdir, BTFIXUPCALL_NOP); @@ -2727,14 +2703,11 @@ BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_translate_dvma, sun4c_translate_dvma, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM); /* Task struct and kernel stack allocating/freeing. */ BTFIXUPSET_CALL(alloc_task_struct, sun4c_alloc_task_struct, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(get_task_struct, sun4c_get_task_struct, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(quick_kernel_fault, sun4c_quick_kernel_fault, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM); /* These should _never_ get called with two level tables. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/swift.S linux.ac/arch/sparc/mm/swift.S --- linux.vanilla/arch/sparc/mm/swift.S Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/swift.S Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: swift.S,v 1.5 2000/05/09 17:40:13 davem Exp $ +/* $Id: swift.S,v 1.6 2000/06/04 06:23:53 anton Exp $ * swift.S: MicroSparc-II mmu/cache operations. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -30,7 +30,7 @@ */ .globl swift_flush_cache_all, swift_flush_cache_mm .globl swift_flush_cache_range, swift_flush_cache_page - .globl swift_flush_page_for_dma, swift_flush_chunk + .globl swift_flush_page_for_dma .globl swift_flush_page_to_ram swift_flush_cache_all: @@ -38,7 +38,6 @@ swift_flush_cache_range: swift_flush_cache_page: swift_flush_page_for_dma: -swift_flush_chunk: swift_flush_page_to_ram: sethi %hi(0x2000), %o0 1: subcc %o0, 0x10, %o0 @@ -190,10 +189,8 @@ * caches which are virtually indexed and tagged. */ .globl swift_flush_page_for_dma - .globl swift_flush_chunk .globl swift_flush_page_to_ram swift_flush_page_for_dma: -swift_flush_chunk: swift_flush_page_to_ram: andn %o0, (PAGE_SIZE - 1), %o1 #if 1 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/tsunami.S linux.ac/arch/sparc/mm/tsunami.S --- linux.vanilla/arch/sparc/mm/tsunami.S Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/tsunami.S Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: tsunami.S,v 1.4 2000/05/09 17:40:13 davem Exp $ +/* $Id: tsunami.S,v 1.5 2000/06/04 06:23:53 anton Exp $ * tsunami.S: High speed MicroSparc-I mmu/cache operations. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -28,7 +28,7 @@ .globl tsunami_flush_cache_all, tsunami_flush_cache_mm .globl tsunami_flush_cache_range, tsunami_flush_cache_page .globl tsunami_flush_page_to_ram, tsunami_flush_page_for_dma - .globl tsunami_flush_sig_insns, tsunami_flush_chunk + .globl tsunami_flush_sig_insns .globl tsunami_flush_tlb_all, tsunami_flush_tlb_mm .globl tsunami_flush_tlb_range, tsunami_flush_tlb_page @@ -46,7 +46,6 @@ WINDOW_FLUSH(%g4, %g5) tsunami_flush_page_for_dma: sta %g0, [%g0] ASI_M_IC_FLCLEAR -tsunami_flush_chunk: sta %g0, [%g0] ASI_M_DC_FLCLEAR tsunami_flush_cache_out: tsunami_flush_page_to_ram: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc/mm/viking.S linux.ac/arch/sparc/mm/viking.S --- linux.vanilla/arch/sparc/mm/viking.S Thu May 25 17:38:26 2000 +++ linux.ac/arch/sparc/mm/viking.S Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: viking.S,v 1.16 2000/05/09 17:40:13 davem Exp $ +/* $Id: viking.S,v 1.17 2000/06/04 06:23:53 anton Exp $ * viking.S: High speed Viking cache/mmu operations * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -31,12 +31,10 @@ .globl viking_flush_cache_range, viking_flush_cache_page .globl viking_flush_page, viking_mxcc_flush_page .globl viking_flush_page_for_dma, viking_flush_page_to_ram - .globl viking_flush_chunk, viking_mxcc_flush_chunk .globl viking_flush_sig_insns .globl viking_flush_tlb_all, viking_flush_tlb_mm .globl viking_flush_tlb_range, viking_flush_tlb_page -viking_flush_chunk: viking_flush_page: sethi %hi(PAGE_OFFSET), %g2 sub %o0, %g2, %g3 @@ -107,10 +105,6 @@ sub %g3, MXCC_STREAM_SIZE, %g3 9: retl - nop - -viking_mxcc_flush_chunk: - retl nop #define WINDOW_FLUSH(tmp1, tmp2) \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/config.in linux.ac/arch/sparc64/config.in --- linux.vanilla/arch/sparc64/config.in Thu May 25 17:38:33 2000 +++ linux.ac/arch/sparc64/config.in Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.112 2000/05/22 08:12:19 davem Exp $ +# $Id: config.in,v 1.114 2000/06/04 22:23:10 anton Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -10,6 +10,15 @@ endmenu mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment comment 'General setup' define_bool CONFIG_VT y @@ -61,15 +70,6 @@ endmenu mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - -mainmenu_option next_comment comment 'Console drivers' bool 'PROM console' CONFIG_PROM_CONSOLE bool 'Support Frame buffer devices' CONFIG_FB @@ -294,7 +294,7 @@ mainmenu_option next_comment comment 'XFree86 DRI support' bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM -# dep_tristate ' Creator/Creator3D/Elite3D' CONFIG_DRM_FFB $CONFIG_DRM +dep_tristate ' Creator/Creator3D' CONFIG_DRM_FFB $CONFIG_DRM endmenu source fs/Config.in diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/defconfig linux.ac/arch/sparc64/defconfig --- linux.vanilla/arch/sparc64/defconfig Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/defconfig Sat Jun 10 21:50:42 2000 @@ -8,6 +8,13 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # General setup # CONFIG_VT=y @@ -59,13 +66,6 @@ CONFIG_ENVCTRL=m # -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# # Console drivers # CONFIG_PROM_CONSOLE=y @@ -170,9 +170,9 @@ CONFIG_DECNET=m CONFIG_DECNET_SIOCGIFCONF=y # CONFIG_DECNET_ROUTER is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -208,6 +208,8 @@ # CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set # CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set # CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m @@ -227,7 +229,6 @@ # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_IDEDMA_PCI_AUTO=y CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set # CONFIG_BLK_DEV_AEC62XX is not set @@ -256,6 +257,8 @@ # CONFIG_VIA82CXXX_TUNING is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set CONFIG_BLK_DEV_IDE_MODES=y # @@ -296,7 +299,7 @@ CONFIG_SCSI_SYM53C8XX=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=10 +CONFIG_SCSI_NCR53C8XX_SYNC=40 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set # CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set @@ -379,6 +382,7 @@ # XFree86 DRI support # CONFIG_DRM=y +CONFIG_DRM_FFB=m # # File systems @@ -429,6 +433,7 @@ # CONFIG_ROOT_NFS is not set CONFIG_NFSD=m CONFIG_NFSD_V3=y +# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/Makefile linux.ac/arch/sparc64/kernel/Makefile --- linux.vanilla/arch/sparc64/kernel/Makefile Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/kernel/Makefile Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $ +# $Id: Makefile,v 1.55 2000/05/27 00:49:35 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/ioctl32.c linux.ac/arch/sparc64/kernel/ioctl32.c --- linux.vanilla/arch/sparc64/kernel/ioctl32.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/kernel/ioctl32.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.91 2000/05/23 05:25:44 davem Exp $ +/* $Id: ioctl32.c,v 1.92 2000/05/26 22:44:11 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2442,8 +2442,8 @@ } typedef struct drm32_unique { - size_t unique_len; /* Length of unique */ - u32 unique; /* Unique name for driver instantiation */ + int unique_len; /* Length of unique */ + u32 unique; /* Unique name for driver instantiation */ } drm32_unique_t; #define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) #define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) @@ -2487,13 +2487,15 @@ if (!ret) { if (cmd == DRM32_IOCTL_GET_UNIQUE && + uptr != NULL && copy_to_user(uptr, karg.unique, karg.unique_len)) ret = -EFAULT; if (put_user(karg.unique_len, &uarg->unique_len)) ret = -EFAULT; } - kfree(karg.unique); + if (karg.unique != NULL) + kfree(karg.unique); return ret; } @@ -2836,7 +2838,7 @@ int count; u32 contexts; /* (drm_ctx_t *) */ } drm32_ctx_res_t; -#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t) +#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/iommu_common.c linux.ac/arch/sparc64/kernel/iommu_common.c --- linux.vanilla/arch/sparc64/kernel/iommu_common.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/sparc64/kernel/iommu_common.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: iommu_common.c,v 1.3 2000/01/28 13:41:59 jj Exp $ +/* $Id: iommu_common.c,v 1.4 2000/06/04 21:50:23 anton Exp $ * iommu_common.c: UltraSparc SBUS/PCI common iommu code. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -45,7 +45,7 @@ } if (pgcount != npages) { - printk("verify_langths: Error, page count wrong, " + printk("verify_lengths: Error, page count wrong, " "npages[%d] pgcount[%d]\n", npages, pgcount); return -1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/signal.c linux.ac/arch/sparc64/kernel/signal.c --- linux.vanilla/arch/sparc64/kernel/signal.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/kernel/signal.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.49 2000/04/08 02:11:46 davem Exp $ +/* $Id: signal.c,v 1.50 2000/05/27 00:49:35 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/signal32.c linux.ac/arch/sparc64/kernel/signal32.c --- linux.vanilla/arch/sparc64/kernel/signal32.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/kernel/signal32.c Sat Jun 10 21:50:42 2000 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.62 2000/04/12 08:10:19 davem Exp $ +/* $Id: signal32.c,v 1.63 2000/05/27 00:49:35 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/kernel/sys_sparc32.c linux.ac/arch/sparc64/kernel/sys_sparc32.c --- linux.vanilla/arch/sparc64/kernel/sys_sparc32.c Thu May 25 17:46:15 2000 +++ linux.ac/arch/sparc64/kernel/sys_sparc32.c Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.147 2000/05/22 07:29:40 davem Exp $ +/* $Id: sys_sparc32.c,v 1.148 2000/05/27 00:49:35 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/sparc64/solaris/timod.c linux.ac/arch/sparc64/solaris/timod.c --- linux.vanilla/arch/sparc64/solaris/timod.c Thu May 25 17:38:34 2000 +++ linux.ac/arch/sparc64/solaris/timod.c Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.6 2000/03/25 03:23:21 davem Exp $ +/* $Id: timod.c,v 1.7 2000/06/09 07:35:30 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -18,6 +18,8 @@ #include #include +#include + #include #include @@ -151,8 +153,10 @@ SOLD("wakeing socket"); sock = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i; wake_up_interruptible(&sock->wait); + read_lock(&sock->sk->callback_lock); if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - kill_fasync(sock->fasync_list, SIGIO, POLL_IN); + __kill_fasync(sock->fasync_list, SIGIO, POLL_IN); + read_unlock(&sock->sk->callback_lock); SOLD("done"); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/acorn/char/Makefile linux.ac/drivers/acorn/char/Makefile --- linux.vanilla/drivers/acorn/char/Makefile Thu May 25 17:38:12 2000 +++ linux.ac/drivers/acorn/char/Makefile Sun Jun 4 21:15:50 2000 @@ -18,7 +18,7 @@ # Object file lists. -obj-y := i2c.o pcf8583.o +obj-y := obj-m := obj-n := obj- := @@ -34,7 +34,8 @@ obj-$(CONFIG_ATOMWIDE_SERIAL) += serial-atomwide.o obj-$(CONFIG_DUALSP_SERIAL) += serial-dualsp.o -obj-y += $(obj-$(MACHINE)) +# Do the i2c and rtc last +obj-y += $(obj-$(MACHINE)) i2c.o pcf8583.o O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/Config.in linux.ac/drivers/atm/Config.in --- linux.vanilla/drivers/atm/Config.in Thu May 25 17:38:18 2000 +++ linux.ac/drivers/atm/Config.in Fri May 26 15:25:23 2000 @@ -59,7 +59,7 @@ if [ "$CONFIG_ATM_FORE200E_PCA" = "y" ]; then bool ' Use default PCA-200E firmware (normally enabled)' CONFIG_ATM_FORE200E_PCA_DEFAULT_FW if [ "$CONFIG_ATM_FORE200E_PCA_DEFAULT_FW" = "n" ]; then - string ' Pathname of user-supplied binary firmware' CONFIG_ATM_FORE200E_PCA_FW + string ' Pathname of user-supplied binary firmware' CONFIG_ATM_FORE200E_PCA_FW "" fi fi fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/Makefile linux.ac/drivers/atm/Makefile --- linux.vanilla/drivers/atm/Makefile Thu May 25 17:38:18 2000 +++ linux.ac/drivers/atm/Makefile Sat May 27 15:45:07 2000 @@ -45,7 +45,7 @@ NEED_SUNI_MX = suni.o endif ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y) - NEED_SUNI_MX = idt77105.o + NEED_IDT77105_MX = idt77105.o endif endif endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/ambassador.c linux.ac/drivers/atm/ambassador.c --- linux.vanilla/drivers/atm/ambassador.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/atm/ambassador.c Tue Jun 6 12:42:46 2000 @@ -290,10 +290,12 @@ /********** microcode **********/ #ifdef AMB_NEW_MICROCODE -#define UCODE(x) "atmsar12" "." #x +#define UCODE(x) UCODE1(atmsar12.,x) #else -#define UCODE(x) "atmsar11" "." #x +#define UCODE(x) UCODE1(atmsar11.,x) #endif +#define UCODE2(x) #x +#define UCODE1(x,y) UCODE2(x ## y) static const u32 __initdata ucode_start = #include UCODE(start) @@ -326,45 +328,43 @@ /********** access to adapter **********/ -static inline void wr_plain (const amb_dev * dev, const u32 * addr, u32 data) { - PRINTD (DBG_FLOW|DBG_REGS, "wr: %p <- %08x", addr, data); +static inline void wr_plain (const amb_dev * dev, size_t addr, u32 data) { + PRINTD (DBG_FLOW|DBG_REGS, "wr: %08x <- %08x", addr, data); #ifdef AMB_MMIO - dev->membase[addr - (u32 *) 0] = data; + dev->membase[addr / sizeof(u32)] = data; #else - outl (data, dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); + outl (data, dev->iobase + addr); #endif } -static inline u32 rd_plain (const amb_dev * dev, const u32 * addr) { +static inline u32 rd_plain (const amb_dev * dev, size_t addr) { #ifdef AMB_MMIO - u32 data = dev->membase[addr - (u32 *) 0]; + u32 data = dev->membase[addr / sizeof(u32)]; #else - u32 data = inl (dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); + u32 data = inl (dev->iobase + addr); #endif - PRINTD (DBG_FLOW|DBG_REGS, "rd: %p -> %08x", addr, data); + PRINTD (DBG_FLOW|DBG_REGS, "rd: %08x -> %08x", addr, data); return data; } -static const amb_mem * const mem = 0; - -static inline void wr_mem (const amb_dev * dev, const u32 * addr, u32 data) { +static inline void wr_mem (const amb_dev * dev, size_t addr, u32 data) { u32 be = cpu_to_be32 (data); - PRINTD (DBG_FLOW|DBG_REGS, "wr: %p <- %08x b[%08x]", addr, data, be); + PRINTD (DBG_FLOW|DBG_REGS, "wr: %08x <- %08x b[%08x]", addr, data, be); #ifdef AMB_MMIO - dev->membase[addr - (u32 *) 0] = be; + dev->membase[addr / sizeof(u32)] = be; #else - outl (be, dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); + outl (be, dev->iobase + addr); #endif } -static inline u32 rd_mem (const amb_dev * dev, const u32 * addr) { +static inline u32 rd_mem (const amb_dev * dev, size_t addr) { #ifdef AMB_MMIO - u32 be = dev->membase[addr - (u32 *) 0]; + u32 be = dev->membase[addr / sizeof(u32)]; #else - u32 be = inl (dev->iobase + (addr - (u32 *) 0) * sizeof(u32)); + u32 be = inl (dev->iobase + addr); #endif u32 data = be32_to_cpu (be); - PRINTD (DBG_FLOW|DBG_REGS, "rd: %p -> %08x b[%08x]", addr, data, be); + PRINTD (DBG_FLOW|DBG_REGS, "rd: %08x -> %08x b[%08x]", addr, data, be); return data; } @@ -600,7 +600,7 @@ ptrs->in = NEXTQ (ptrs->in, ptrs->start, ptrs->limit); // mail the command - wr_mem (dev, &mem->mb.adapter.cmd_address, virt_to_bus (ptrs->in)); + wr_mem (dev, offsetof(amb_mem, mb.adapter.cmd_address), virt_to_bus (ptrs->in)); // prepare to wait for cq->pending milliseconds // effectively one centisecond on i386 @@ -667,8 +667,8 @@ txq->pending++; txq->in.ptr = NEXTQ (txq->in.ptr, txq->in.start, txq->in.limit); // hand over the TX and ring the bell - wr_mem (dev, &mem->mb.adapter.tx_address, virt_to_bus (txq->in.ptr)); - wr_mem (dev, &mem->doorbell, TX_FRAME); + wr_mem (dev, offsetof(amb_mem, mb.adapter.tx_address), virt_to_bus (txq->in.ptr)); + wr_mem (dev, offsetof(amb_mem, doorbell), TX_FRAME); if (txq->pending > txq->high) txq->high = txq->pending; @@ -724,7 +724,7 @@ rxq->pending++; rxq->in.ptr = NEXTQ (rxq->in.ptr, rxq->in.start, rxq->in.limit); // hand over the RX buffer - wr_mem (dev, &mem->mb.adapter.rx_address[pool], virt_to_bus (rxq->in.ptr)); + wr_mem (dev, offsetof(amb_mem, mb.adapter.rx_address[pool]), virt_to_bus (rxq->in.ptr)); spin_unlock_irqrestore (&rxq->lock, flags); return 0; @@ -855,16 +855,16 @@ /********** enable host interrupts **********/ static inline void interrupts_on (amb_dev * dev) { - wr_plain (dev, &mem->interrupt_control, - rd_plain (dev, &mem->interrupt_control) + wr_plain (dev, offsetof(amb_mem, interrupt_control), + rd_plain (dev, offsetof(amb_mem, interrupt_control)) | AMB_INTERRUPT_BITS); } /********** disable host interrupts **********/ static inline void interrupts_off (amb_dev * dev) { - wr_plain (dev, &mem->interrupt_control, - rd_plain (dev, &mem->interrupt_control) + wr_plain (dev, offsetof(amb_mem, interrupt_control), + rd_plain (dev, offsetof(amb_mem, interrupt_control)) &~ AMB_INTERRUPT_BITS); } @@ -900,7 +900,7 @@ } { - u32 interrupt = rd_plain (dev, &mem->interrupt); + u32 interrupt = rd_plain (dev, offsetof(amb_mem, interrupt)); // for us or someone else sharing the same interrupt if (!interrupt) { @@ -910,7 +910,7 @@ // definitely for us PRINTD (DBG_IRQ, "FYI: interrupt was %08x", interrupt); - wr_plain (dev, &mem->interrupt, -1); + wr_plain (dev, offsetof(amb_mem, interrupt), -1); } { @@ -959,8 +959,8 @@ cli(); PRINTK (KERN_INFO, "don't panic - putting adapter into reset"); - wr_plain (dev, &mem->reset_control, - rd_plain (dev, &mem->reset_control) | AMB_RESET_BITS); + wr_plain (dev, offsetof(amb_mem, reset_control), + rd_plain (dev, offsetof(amb_mem, reset_control)) | AMB_RESET_BITS); PRINTK (KERN_INFO, "marking all commands complete"); for (cmd = ptrs->start; cmd < ptrs->limit; ++cmd) @@ -1985,7 +1985,7 @@ lb->valid = cpu_to_be32 (DMA_VALID); // dump_registers (dev); // dump_loader_block (lb); - wr_mem (dev, &mem->doorbell, virt_to_bus (lb) & ~onegigmask); + wr_mem (dev, offsetof(amb_mem, doorbell), virt_to_bus (lb) & ~onegigmask); timeout = command_timeouts[cmd] * HZ/100; @@ -2002,7 +2002,7 @@ if (cmd == adapter_start) { // wait for start command to acknowledge... timeout = HZ/10; - while (rd_plain (dev, &mem->doorbell)) + while (rd_plain (dev, offsetof(amb_mem, doorbell))) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -2095,21 +2095,21 @@ PRINTD (DBG_FLOW|DBG_LOAD, "amb_reset"); - word = rd_plain (dev, &mem->reset_control); + word = rd_plain (dev, offsetof(amb_mem, reset_control)); // put card into reset state - wr_plain (dev, &mem->reset_control, word | AMB_RESET_BITS); + wr_plain (dev, offsetof(amb_mem, reset_control), word | AMB_RESET_BITS); // wait a short while udelay (10); #if 1 // put card into known good state - wr_plain (dev, &mem->interrupt_control, AMB_DOORBELL_BITS); + wr_plain (dev, offsetof(amb_mem, interrupt_control), AMB_DOORBELL_BITS); // clear all interrupts just in case - wr_plain (dev, &mem->interrupt, -1); + wr_plain (dev, offsetof(amb_mem, interrupt), -1); #endif // clear self-test done flag - wr_plain (dev, &mem->mb.loader.ready, 0); + wr_plain (dev, offsetof(amb_mem, mb.loader.ready), 0); // take card out of reset state - wr_plain (dev, &mem->reset_control, word &~ AMB_RESET_BITS); + wr_plain (dev, offsetof(amb_mem, reset_control), word &~ AMB_RESET_BITS); if (diags) { unsigned long timeout; @@ -2119,7 +2119,7 @@ timeout = schedule_timeout (timeout); // half second time-out timeout = HZ/2; - while (!rd_plain (dev, &mem->mb.loader.ready)) + while (!rd_plain (dev, offsetof(amb_mem, mb.loader.ready))) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -2129,7 +2129,7 @@ // get results of self-test // XXX double check byte-order - word = rd_mem (dev, &mem->mb.loader.result); + word = rd_mem (dev, offsetof(amb_mem, mb.loader.result)); if (word & SELF_TEST_FAILURE) { void sf (const char * msg) { PRINTK (KERN_ERR, "self-test failed: %s", msg); @@ -2235,7 +2235,7 @@ #endif // pass the structure - wr_mem (dev, &mem->doorbell, virt_to_bus (&a)); + wr_mem (dev, offsetof(amb_mem, doorbell), virt_to_bus (&a)); // 2.2 second wait (must not touch doorbell during 2 second DMA test) timeout = HZ*22/10; @@ -2243,7 +2243,7 @@ timeout = schedule_timeout (timeout); // give the adapter another half second? timeout = HZ/2; - while (rd_plain (dev, &mem->doorbell)) + while (rd_plain (dev, offsetof(amb_mem, doorbell))) if (timeout) { timeout = schedule_timeout (timeout); } else { @@ -2318,10 +2318,10 @@ u32 mapreg; blb = virt_to_bus (&lb); // the kernel stack had better not ever cross a 1Gb boundary! - mapreg = rd_plain (dev, &mem->stuff[10]); + mapreg = rd_plain (dev, offsetof(amb_mem, stuff[10])); mapreg &= ~onegigmask; mapreg |= blb & onegigmask; - wr_plain (dev, &mem->stuff[10], mapreg); + wr_plain (dev, offsetof(amb_mem, stuff[10]), mapreg); return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/atmtcp.c linux.ac/drivers/atm/atmtcp.c --- linux.vanilla/drivers/atm/atmtcp.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/atm/atmtcp.c Sat May 27 15:49:40 2000 @@ -330,14 +330,20 @@ struct atmtcp_dev_data *dev_data; struct atm_dev *dev; + MOD_INC_USE_COUNT; + dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL); - if (!dev_data) return -ENOMEM; + if (!dev_data) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL); if (!dev) { kfree(dev_data); + MOD_DEC_USE_COUNT; return itf == -1 ? -ENOMEM : -EBUSY; } - MOD_INC_USE_COUNT; dev->ci_range.vpi_bits = MAX_VPI_BITS; dev->ci_range.vci_bits = MAX_VCI_BITS; PRIV(dev) = dev_data; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/eni.c linux.ac/drivers/atm/eni.c --- linux.vanilla/drivers/atm/eni.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/atm/eni.c Tue May 30 15:17:17 2000 @@ -1711,7 +1711,7 @@ dev->link_rate = ATM_OC3_PCR; eni_dev = ENI_DEV(dev); pci_dev = eni_dev->pci_dev; - real_base = pci_dev->resource[0].start; + real_base = pci_resource_start(pci_dev, 0); eni_dev->irq = pci_dev->irq; error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision); if (error) { @@ -2246,8 +2246,16 @@ int error = -ENOMEM; DPRINTK("eni_init_one\n"); + + MOD_INC_USE_COUNT; /* @@@ we don't support unloading yet */ + + if (pci_enable_device(pci_dev)) { + error = -EIO; + goto out0; + } + eni_dev = (struct eni_dev *) kmalloc(sizeof(struct eni_dev),GFP_KERNEL); - if (!eni_dev) return -ENOMEM; + if (!eni_dev) goto out0; if (!cpu_zeroes) { cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE, &zeroes); @@ -2265,7 +2273,6 @@ if (error) goto out3; eni_dev->more = eni_boards; eni_boards = dev; - MOD_INC_USE_COUNT; /* @@@ we don't support unloading yet */ return 0; out3: atm_dev_deregister(dev); @@ -2274,6 +2281,8 @@ cpu_zeroes = NULL; out1: kfree(eni_dev); +out0: + MOD_DEC_USE_COUNT; /* @@@ we don't support unloading yet */ return error; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/fore200e.c linux.ac/drivers/atm/fore200e.c --- linux.vanilla/drivers/atm/fore200e.c Thu May 25 17:38:19 2000 +++ linux.ac/drivers/atm/fore200e.c Sat May 27 15:49:23 2000 @@ -1409,6 +1409,8 @@ struct fore200e* fore200e = FORE200E_DEV(vcc->dev); struct fore200e_vcc* fore200e_vcc; + MOD_INC_USE_COUNT; + /* find a free VPI/VCI */ fore200e_walk_vccs(vcc, &vpi, &vci); @@ -1416,8 +1418,10 @@ vcc->vci = vci; /* ressource checking only? */ - if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) { + MOD_DEC_USE_COUNT; return 0; + } set_bit(ATM_VF_ADDR, &vcc->flags); vcc->itf = vcc->dev->number; @@ -1435,6 +1439,7 @@ down(&fore200e->rate_sf); if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) { up(&fore200e->rate_sf); + MOD_DEC_USE_COUNT; return -EAGAIN; } /* reserving the pseudo-CBR bandwidth at this point grants us @@ -1451,6 +1456,7 @@ down(&fore200e->rate_sf); fore200e->available_cell_rate += vcc->qos.txtp.max_pcr; up(&fore200e->rate_sf); + MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -1461,13 +1467,10 @@ down(&fore200e->rate_sf); fore200e->available_cell_rate += vcc->qos.txtp.max_pcr; up(&fore200e->rate_sf); + MOD_DEC_USE_COUNT; return -EBUSY; } -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - /* compute rate control parameters */ if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) { @@ -2598,6 +2601,10 @@ printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n"); +#if 0 /* XXX uncomment this to forbid module unloading */ + MOD_INC_USE_COUNT; +#endif + /* for each configured bus interface */ for (link = 0, bus = fore200e_bus; bus->model_name; bus++) { @@ -2624,10 +2631,8 @@ } #if 0 /* XXX uncomment this to forbid module unloading */ -#ifdef MODULE - if (link > 0) - MOD_INC_USE_COUNT; -#endif + if (link <= 0) + MOD_DEC_USE_COUNT; #endif return link; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/idt77105.c linux.ac/drivers/atm/idt77105.c --- linux.vanilla/drivers/atm/idt77105.c Thu May 25 17:38:19 2000 +++ linux.ac/drivers/atm/idt77105.c Sat May 27 15:34:04 2000 @@ -334,9 +334,7 @@ int __init idt77105_init(struct atm_dev *dev) { -#ifdef MODULE MOD_INC_USE_COUNT; -#endif /* MODULE */ dev->phy = &idt77105_ops; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/nicstar.c linux.ac/drivers/atm/nicstar.c --- linux.vanilla/drivers/atm/nicstar.c Thu May 25 17:38:19 2000 +++ linux.ac/drivers/atm/nicstar.c Tue May 30 15:17:17 2000 @@ -472,7 +472,7 @@ card->index = i; card->atmdev = NULL; card->pcidev = pcidev; - card->membase = pcidev->resource[1].start; + card->membase = pci_resource_start(pcidev, 1); #ifdef __powerpc__ /* Compensate for different memory map between host CPU and PCI bus. Shouldn't we use a macro for this? */ @@ -893,10 +893,9 @@ #ifdef CONFIG_ATM_NICSTAR_USE_SUNI if (card->max_pcr == ATM_OC3_PCR) { suni_init(card->atmdev); -#ifdef MODULE + MOD_INC_USE_COUNT; /* Can't remove the nicstar driver or the suni driver would oops */ -#endif /* MODULE */ } #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/atm/zatm.c linux.ac/drivers/atm/zatm.c --- linux.vanilla/drivers/atm/zatm.c Thu May 25 17:38:19 2000 +++ linux.ac/drivers/atm/zatm.c Tue May 30 15:17:17 2000 @@ -1385,7 +1385,7 @@ DPRINTK(">zatm_init\n"); zatm_dev = ZATM_DEV(dev); pci_dev = zatm_dev->pci_dev; - zatm_dev->base = pci_dev->resource[0].start; + zatm_dev->base = pci_resource_start(pci_dev, 0); zatm_dev->irq = pci_dev->irq; if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) || (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/Config.in linux.ac/drivers/block/Config.in --- linux.vanilla/drivers/block/Config.in Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/Config.in Sat May 27 15:47:31 2000 @@ -36,8 +36,6 @@ dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI -comment 'Additional Block Devices' - tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/ll_rw_blk.c linux.ac/drivers/block/ll_rw_blk.c --- linux.vanilla/drivers/block/ll_rw_blk.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/block/ll_rw_blk.c Wed May 31 11:45:14 2000 @@ -411,6 +411,7 @@ drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1); + elevator_account_request(&q->elevator, req); if (list_empty(head)) { req->elevator_sequence = elevator_sequence(&q->elevator, latency); list_add(&req->queue, &q->queue_head); @@ -748,7 +749,6 @@ req->bhtail = bh; req->q = q; add_request(q, req, head, orig_latency); - elevator_account_request(elevator, req); spin_unlock_irqrestore(&io_request_lock, flags); return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/loop.c linux.ac/drivers/block/loop.c --- linux.vanilla/drivers/block/loop.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/loop.c Fri Jun 9 20:52:55 2000 @@ -238,7 +238,8 @@ kaddr = (char*)kmap(page); if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) { size = 0; - printk(KERN_ERR "loop: transfer error block %ld\n",page->index); + printk(KERN_ERR "loop: transfer error block %ld\n", + page->index); desc->error = -EINVAL; } kunmap(page); @@ -345,9 +346,11 @@ } } - if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset, - dest_addr, size, block)) { - printk(KERN_ERR "loop: transfer error block %d\n", block); + if ((lo->transfer)(lo, current_request->cmd, + bh->b_data + offset, + dest_addr, size, block)) { + printk(KERN_ERR "loop: transfer error block %d\n", + block); brelse(bh); goto error_out_lock; } @@ -539,8 +542,10 @@ lo->lo_dentry = NULL; if (lo->lo_backing_file != NULL) { - put_write_access(lo->lo_backing_file->f_dentry->d_inode); - fput(lo->lo_backing_file); + struct file *filp = lo->lo_backing_file; + if ((filp->f_mode & FMODE_WRITE) == 0) + put_write_access(filp->f_dentry->d_inode); + fput(filp); lo->lo_backing_file = NULL; } else { dput(dentry); @@ -636,7 +641,8 @@ if (!inode) return -EINVAL; if (MAJOR(inode->i_rdev) != MAJOR_NR) { - printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n", MAJOR_NR); + printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n", + MAJOR_NR); return -ENODEV; } dev = MINOR(inode->i_rdev); @@ -698,7 +704,8 @@ if (!inode) return 0; if (MAJOR(inode->i_rdev) != MAJOR_NR) { - printk(KERN_WARNING "lo_release: pseudo-major != %d\n", MAJOR_NR); + printk(KERN_WARNING "lo_release: pseudo-major != %d\n", + MAJOR_NR); return 0; } dev = MINOR(inode->i_rdev); @@ -706,7 +713,8 @@ return 0; lo = &loop_dev[dev]; if (lo->lo_refcnt <= 0) - printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt); + printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", + lo->lo_refcnt); else { int type = lo->lo_encrypt_type; --lo->lo_refcnt; @@ -761,6 +769,10 @@ EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); +static void no_plug_device(request_queue_t *q, kdev_t device) +{ +} + int __init loop_init(void) { int i; @@ -806,6 +818,7 @@ } blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), no_plug_device); blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); for (i=0; i < max_loop; i++) { memset(&loop_dev[i], 0, sizeof(struct loop_device)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/md.c linux.ac/drivers/block/md.c --- linux.vanilla/drivers/block/md.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/block/md.c Fri Jun 9 16:05:43 2000 @@ -43,7 +43,7 @@ #include extern asmlinkage int sys_sched_yield(void); -extern asmlinkage int sys_setsid(void); +extern asmlinkage long sys_setsid(void); #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -327,11 +327,13 @@ * ok, add this new device name to the list */ hd = find_gendisk (dev); - - if (!hd) - sprintf (dname->name, "[dev %s]", kdevname(dev)); - else - disk_name (hd, MINOR(dev), dname->name); + dname->name = NULL; + if (hd) + dname->name = disk_name (hd, MINOR(dev), dname->namebuf); + if (!dname->name) { + sprintf (dname->namebuf, "[dev %s]", kdevname(dev)); + dname->name = dname->namebuf; + } dname->dev = dev; MD_INIT_LIST_HEAD(&dname->list); @@ -1010,7 +1012,7 @@ skip: return 0; } -#undef GETBLK_FAILED KERN_ERR +#undef GETBLK_FAILED static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev) { @@ -1838,9 +1840,9 @@ * Free resources if final stop */ if (!ro) { + printk (KERN_INFO "md%d stopped.\n", mdidx(mddev)); free_mddev(mddev); - printk (KERN_INFO "md%d stopped.\n", mdidx(mddev)); } else printk (KERN_INFO "md%d switched to read-only mode.\n", mdidx(mddev)); @@ -3359,7 +3361,6 @@ } else current->priority = 40; } - wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); fsync_dev(read_disk); printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); err = 0; @@ -3367,6 +3368,7 @@ * this also signals 'finished resyncing' to md_stop */ out: + wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); up(&mddev->resync_sem); out_nolock: mddev->curr_resync = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/nbd.c linux.ac/drivers/block/nbd.c --- linux.vanilla/drivers/block/nbd.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/nbd.c Mon May 29 19:35:38 2000 @@ -38,6 +38,8 @@ #include #include +#include + #include #include #include @@ -53,6 +55,7 @@ static u64 nbd_bytesizes[MAX_NBD]; static struct nbd_device nbd_dev[MAX_NBD]; +static devfs_handle_t devfs_handle = NULL; #define DEBUG( s ) /* #define DEBUG( s ) printk( s ) @@ -514,12 +517,20 @@ register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops, nbd_bytesizes[i]>>9); } + devfs_handle = devfs_mk_dir (NULL, "nbd", 0, NULL); + devfs_register_series (devfs_handle, "%u", MAX_NBD, + DEVFS_FL_DEFAULT, MAJOR_NR, 0, + S_IFBLK | S_IRUSR | S_IWUSR, 0, 0, + &nbd_fops, NULL); + return 0; } #ifdef MODULE void cleanup_module(void) { + devfs_unregister (devfs_handle); + if (unregister_blkdev(MAJOR_NR, "nbd") != 0) printk("nbd: cleanup_module failed\n"); else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/paride/paride.c linux.ac/drivers/block/paride/paride.c --- linux.vanilla/drivers/block/paride/paride.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/paride/paride.c Tue Jun 6 12:32:06 2000 @@ -120,8 +120,8 @@ pi->claimed = 1; #ifdef CONFIG_PARPORT if (pi->pardev) - while (parport_claim((struct pardevice *)(pi->pardev))) - sleep_on(&(pi->parq)); + wait_event (pi->parq, + !parport_claim ((struct pardevice *)pi->pardev)); #endif } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/paride/pd.c linux.ac/drivers/block/paride/pd.c --- linux.vanilla/drivers/block/paride/pd.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/paride/pd.c Tue Jun 6 12:32:06 2000 @@ -487,7 +487,7 @@ MOD_INC_USE_COUNT; - while (!pd_valid) sleep_on(&pd_wait_open); + wait_event (pd_wait_open, pd_valid); PD.access++; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/raid1.c linux.ac/drivers/block/raid1.c --- linux.vanilla/drivers/block/raid1.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/raid1.c Fri Jun 9 15:49:35 2000 @@ -908,6 +908,7 @@ if (mbh) { q = blk_get_queue(mbh->b_rdev); generic_make_request(q, WRITE, mbh); + drive_stat_acct(mbh->b_rdev, WRITE, -bh->b_size/512, 0); } } } else { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/raid5.c linux.ac/drivers/block/raid5.c --- linux.vanilla/drivers/block/raid5.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/raid5.c Thu Jun 8 16:42:24 2000 @@ -15,7 +15,7 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include #include #include #include @@ -41,8 +41,13 @@ */ #define RAID5_DEBUG 0 #define RAID5_PARANOIA 1 -#define CHECK_DEVLOCK() if (!spin_is_locked(&conf->device_lock)) BUG() -#define CHECK_SHLOCK(sh) if (!stripe_locked(sh)) BUG() +#if defined(CONFIG_SMP) || defined(DEBUG_SPINLOCKS) +# define CHECK_DEVLOCK() if (!spin_is_locked(&conf->device_lock)) BUG() +# define CHECK_SHLOCK(sh) if (!stripe_locked(sh)) BUG() +#else +# define CHECK_DEVLOCK() 0 +# define CHECK_SHLOCK(sh) 0 +#endif #if RAID5_DEBUG #define PRINTK(x...) printk(x) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/rd.c linux.ac/drivers/block/rd.c --- linux.vanilla/drivers/block/rd.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/block/rd.c Thu Jun 8 14:53:41 2000 @@ -107,7 +107,11 @@ * architecture-specific setup routine (from the stored boot sector * information). */ +#if defined(CONFIG_ARCH_S390) +int rd_size = 8192; /* Size of the RAM disks */ +#else int rd_size = 4096; /* Size of the RAM disks */ +#endif /* * It would be very desiderable to have a soft-blocksize (that in the case * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because @@ -693,6 +697,9 @@ iput(inode); } +#ifdef CONFIG_MAC_FLOPPY +int swim3_fd_eject(int devnum); +#endif static void __init rd_load_disk(int n) { @@ -713,6 +720,12 @@ if (rd_prompt) { #ifdef CONFIG_BLK_DEV_FD floppy_eject(); +#endif +#ifdef CONFIG_MAC_FLOPPY + if(MAJOR(ROOT_DEV) == FLOPPY_MAJOR) + swim3_fd_eject(MINOR(ROOT_DEV)); + else if(MAJOR(real_root_dev) == FLOPPY_MAJOR) + swim3_fd_eject(MINOR(real_root_dev)); #endif printk(KERN_NOTICE "VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/swim3.c linux.ac/drivers/block/swim3.c --- linux.vanilla/drivers/block/swim3.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/swim3.c Thu Jun 8 14:53:41 2000 @@ -801,6 +801,16 @@ return err; } +int swim3_fd_eject(int devnum) +{ + if (devnum >= floppy_count) + return -ENODEV; + /* Do not check this - this function should ONLY be called early + * in the boot process! */ + /* if (floppy_states[devnum].ref_count != 1) return -EBUSY; */ + return fd_eject(&floppy_states[devnum]); +} + static struct floppy_struct floppy_type = { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/xd.c linux.ac/drivers/block/xd.c --- linux.vanilla/drivers/block/xd.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/xd.c Sat May 27 15:51:09 2000 @@ -258,20 +258,19 @@ { int dev = DEVICE_NR(inode->i_rdev); + MOD_INC_USE_COUNT; + if (dev < xd_drives) { while (!xd_valid[dev]) sleep_on(&xd_wait_open); -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif /* MODULE */ - xd_access[dev]++; return (0); } - else - return -ENXIO; + + MOD_DEC_USE_COUNT; + return -ENXIO; } /* do_xd_request: handle an incoming request */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/xor.c linux.ac/drivers/block/xor.c --- linux.vanilla/drivers/block/xor.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/xor.c Thu Jun 8 16:56:56 2000 @@ -1814,7 +1814,7 @@ fastest = f; } #ifdef CONFIG_X86_XMM - if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + if (cpu_has_xmm) { fastest = &t_xor_block_pIII_kni; } #endif @@ -1849,7 +1849,7 @@ #endif #ifdef CONFIG_X86_XMM - if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + if (cpu_has_xmm) { printk(KERN_INFO "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); /* we force the use of the KNI xor block because it diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/z2ram.c linux.ac/drivers/block/z2ram.c --- linux.vanilla/drivers/block/z2ram.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/block/z2ram.c Sat May 27 15:51:06 2000 @@ -165,12 +165,16 @@ sizeof( z2ram_map[0] ); int max_chip_map = ( amiga_chip_size / Z2RAM_CHUNKSIZE ) * sizeof( z2ram_map[0] ); + int rc = -ENOMEM; + + MOD_INC_USE_COUNT; device = DEVICE_NR( inode->i_rdev ); if ( current_device != -1 && current_device != device ) { - return -EBUSY; + rc = -EBUSY; + goto err_out; } if ( current_device == -1 ) @@ -188,7 +192,7 @@ if (index >= m68k_realnum_memory) { printk( KERN_ERR DEVICE_NAME ": no such entry in z2ram_map\n" ); - return -ENOMEM; + goto err_out; } paddr = m68k_memory[index].addr; @@ -215,7 +219,7 @@ { printk( KERN_ERR DEVICE_NAME ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; + goto err_out; } while (size) { @@ -240,7 +244,7 @@ { printk( KERN_ERR DEVICE_NAME ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; + goto err_out; } get_z2ram(); @@ -261,7 +265,7 @@ { printk( KERN_ERR DEVICE_NAME ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; + goto err_out; } get_z2ram(); @@ -279,7 +283,7 @@ { printk( KERN_ERR DEVICE_NAME ": cannot get mem for z2ram_map\n" ); - return -ENOMEM; + goto err_out; } get_chipram(); @@ -292,15 +296,17 @@ break; default: - return -ENODEV; + rc = -ENODEV; + goto err_out; + + break; } if ( z2ram_size == 0 ) { - kfree( z2ram_map ); printk( KERN_NOTICE DEVICE_NAME ": no unused ZII/Chip RAM found\n" ); - return -ENOMEM; + goto err_out_kfree; } current_device = device; @@ -309,9 +315,13 @@ blk_size[ MAJOR_NR ] = z2_sizes; } - MOD_INC_USE_COUNT; - return 0; + +err_out_kfree: + kfree( z2ram_map ); +err_out: + MOD_DEC_USE_COUNT; + return rc; } static int diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/aztcd.c linux.ac/drivers/cdrom/aztcd.c --- linux.vanilla/drivers/cdrom/aztcd.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/cdrom/aztcd.c Sat May 27 15:49:55 2000 @@ -1543,14 +1543,17 @@ #ifdef AZT_DEBUG printk("aztcd: starting aztcd_open\n"); #endif + if (aztPresent == 0) return -ENXIO; /* no hardware */ + MOD_INC_USE_COUNT; + if (!azt_open_count && azt_state == AZT_S_IDLE) { azt_invalidate_buffers(); st = getAztStatus(); /* check drive status */ - if (st == -1) return -EIO; /* drive doesn't respond */ + if (st == -1) goto err_out; /* drive doesn't respond */ if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */ @@ -1563,18 +1566,20 @@ { printk("aztcd: Disk Changed or No Disk in Drive?\n"); aztTocUpToDate=0; } - if (aztUpdateToc()) return -EIO; + if (aztUpdateToc()) goto err_out; } ++azt_open_count; - MOD_INC_USE_COUNT; aztLockDoor(); - #ifdef AZT_DEBUG printk("aztcd: exiting aztcd_open\n"); #endif return 0; + +err_out: + MOD_DEC_USE_COUNT; + return -EIO; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/cdrom.c linux.ac/drivers/cdrom/cdrom.c --- linux.vanilla/drivers/cdrom/cdrom.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/cdrom/cdrom.c Thu May 25 20:32:58 2000 @@ -211,10 +211,15 @@ dvd_do_auth passed uninitialized data to drive because init_cdrom_command did not clear a 0 sized buffer. + 3.09 May 12, 2000 - Jens Axboe + -- Fix Video-CD on SCSI drives that don't support READ_CD command. In + that case switch block size and issue plain READ_10 again, then switch + back. + -------------------------------------------------------------------------*/ -#define REVISION "Revision: 3.08" -#define VERSION "Id: cdrom.c 3.08 2000/05/01" +#define REVISION "Revision: 3.09" +#define VERSION "Id: cdrom.c 3.09 2000/05/12" /* 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: */ @@ -465,7 +470,7 @@ if ((cdi = cdrom_find_device(dev)) == NULL) return -ENODEV; - if (fp->f_mode & FMODE_WRITE) + if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM)) return -EROFS; /* if this was a O_NONBLOCK open and we should honor the flags, @@ -1371,6 +1376,28 @@ return 0; } +/* + * Specific READ_10 interface + */ +static int cdrom_read_cd(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc, int lba, + int blocksize, int nblocks) +{ + struct cdrom_device_ops *cdo = cdi->ops; + + memset(&cgc->cmd, 0, sizeof(cgc->cmd)); + cgc->cmd[0] = GPCMD_READ_10; + cgc->cmd[2] = (lba >> 24) & 0xff; + cgc->cmd[3] = (lba >> 16) & 0xff; + cgc->cmd[4] = (lba >> 8) & 0xff; + cgc->cmd[5] = lba & 0xff; + cgc->cmd[6] = (nblocks >> 16) & 0xff; + cgc->cmd[7] = (nblocks >> 8) & 0xff; + cgc->cmd[8] = nblocks & 0xff; + cgc->buflen = blocksize * nblocks; + return cdo->generic_packet(cdi, cgc); +} + /* very generic interface for reading the various types of blocks */ static int cdrom_read_block(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc, @@ -1787,6 +1814,43 @@ return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; } +/* + * Required when we need to use READ_10 to issue other than 2048 block + * reads + */ +static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) +{ + struct cdrom_device_ops *cdo = cdi->ops; + struct cdrom_generic_command cgc; + struct modesel_head mh; + int ret; + + memset(&mh, 0, sizeof(mh)); + mh.block_desc_length = 0x08; + mh.block_length_med = (size >> 8) & 0xff; + mh.block_length_lo = size & 0xff; + + memset(&cgc, 0, sizeof(cgc)); + cgc.cmd[0] = 0x15; + cgc.cmd[1] = 1 << 4; + cgc.cmd[4] = 12; + cgc.buflen = sizeof(mh); + cgc.buffer = (char *) &mh; + cgc.data_direction = CGC_DATA_WRITE; + mh.block_desc_length = 0x08; + mh.block_length_med = (size >> 8) & 0xff; + mh.block_length_lo = size & 0xff; + + ret = cdo->generic_packet(cdi, &cgc); + if (ret) { + printk("switch_blocksize failed, ret %x ", ret); + if (cgc.sense) + printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); + printk("\n"); + } + return ret; +} + static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { @@ -1829,8 +1893,27 @@ return -ENOMEM; cgc.data_direction = CGC_DATA_READ; ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize); - if (!ret) - if (copy_to_user((char *)arg, cgc.buffer, blocksize)) + if (ret) { + /* + * SCSI-II devices are not required to support + * READ_CD, so let's try switching block size + */ + /* FIXME: switch back again... */ + if ((ret = cdrom_switch_blocksize(cdi, blocksize))) { + kfree(cgc.buffer); + return ret; + } + cgc.sense = NULL; + ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); + if (ret) { + printk("read_cd failed, ret %x ", ret); + if (cgc.sense) + printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); + printk("\n"); + } + ret |= cdrom_switch_blocksize(cdi, blocksize); + } + if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize)) ret = -EFAULT; kfree(cgc.buffer); return ret; @@ -1867,8 +1950,7 @@ } cgc.data_direction = CGC_DATA_READ; while (ra.nframes > 0) { - ret = cdrom_read_block(cdi, &cgc, lba, frames, 1, - CD_FRAMESIZE_RAW); + ret = cdrom_read_block(cdi, &cgc, lba, frames, 1, CD_FRAMESIZE_RAW); if (ret) break; __copy_to_user(ra.buf, cgc.buffer, CD_FRAMESIZE_RAW * frames); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/cm206.c linux.ac/drivers/cdrom/cm206.c --- linux.vanilla/drivers/cdrom/cm206.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/cdrom/cm206.c Sat May 27 15:50:10 2000 @@ -736,13 +736,14 @@ static int cm206_open(struct cdrom_device_info * cdi, int purpose) { + MOD_INC_USE_COUNT; if (!cd->openfiles) { /* reset only first time */ cd->background=0; reset_cm260(); cd->adapter_last = -1; /* invalidate adapter memory */ cd->sector_last = -1; } - ++cd->openfiles; MOD_INC_USE_COUNT; + ++cd->openfiles; stats(open); return 0; } @@ -757,7 +758,8 @@ cd->sector_last = -1; /* Make our internal buffer invalid */ FIRST_TRACK = 0; /* No valid disc status */ } - --cd->openfiles; MOD_DEC_USE_COUNT; + --cd->openfiles; + MOD_DEC_USE_COUNT; } /* Empty buffer empties $sectors$ sectors of the adapter card buffer, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/mcd.c linux.ac/drivers/cdrom/mcd.c --- linux.vanilla/drivers/cdrom/mcd.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/cdrom/mcd.c Sat May 27 15:50:27 2000 @@ -1110,12 +1110,16 @@ if (mcdPresent == 0) return -ENXIO; /* no hardware */ - if (!mcd_open_count && mcd_state == MCD_S_IDLE) { + MOD_INC_USE_COUNT; + + if (mcd_open_count || mcd_state != MCD_S_IDLE) + goto bump_count; + mcd_invalidate_buffers(); do { st = statusCmd(); /* check drive status */ if (st == -1) - return -EIO; /* drive doesn't respond */ + goto err_out; /* drive doesn't respond */ if ((st & MST_READY) == 0) { /* no disk? wait a sec... */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ); @@ -1123,11 +1127,15 @@ } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS); if (updateToc() < 0) - return -EIO; - } + goto err_out; + +bump_count: ++mcd_open_count; - MOD_INC_USE_COUNT; return 0; + +err_out: + MOD_DEC_USE_COUNT; + return -EIO; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/optcd.c linux.ac/drivers/cdrom/optcd.c --- linux.vanilla/drivers/cdrom/optcd.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/cdrom/optcd.c Sat May 27 15:50:42 2000 @@ -1871,6 +1871,8 @@ { DEBUG((DEBUG_VFS, "starting opt_open")); + MOD_INC_USE_COUNT; + if (!open_count && state == S_IDLE) { int status; @@ -1885,12 +1887,12 @@ status = drive_status(); if (status < 0) { DEBUG((DEBUG_VFS, "drive_status: %02x", -status)); - return -EIO; + goto err_out; } DEBUG((DEBUG_VFS, "status: %02x", status)); if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) { printk(KERN_INFO "optcd: no disk or door open\n"); - return -EIO; + goto err_out; } status = exec_cmd(COMLOCK); /* Lock door */ if (status < 0) { @@ -1904,15 +1906,18 @@ DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status)); } - return -EIO; + goto err_out; } open_count++; } - MOD_INC_USE_COUNT; DEBUG((DEBUG_VFS, "exiting opt_open")); return 0; + +err_out: + MOD_DEC_USE_COUNT; + return -EIO; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/cdrom/sjcd.c linux.ac/drivers/cdrom/sjcd.c --- linux.vanilla/drivers/cdrom/sjcd.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/cdrom/sjcd.c Sat May 27 22:04:47 2000 @@ -58,10 +58,7 @@ #define SJCD_VERSION_MAJOR 1 #define SJCD_VERSION_MINOR 7 -#ifdef MODULE #include -#endif /* MODULE */ - #include #include #include @@ -1339,6 +1336,8 @@ */ if( fp->f_mode & 2 ) return( -EROFS ); + MOD_INC_USE_COUNT; + if( sjcd_open_count == 0 ){ int s, sjcd_open_tries; /* We don't know that, do we? */ @@ -1360,7 +1359,7 @@ #if defined( SJCD_DIAGNOSTIC ) printk( "SJCD: open: timed out when check status.\n" ); #endif - return( -EIO ); + goto err_out; } else if( !sjcd_media_is_available ){ #if defined( SJCD_DIAGNOSTIC ) printk("SJCD: open: no disk in drive\n"); @@ -1375,10 +1374,10 @@ #if defined( SJCD_DIAGNOSTIC ) printk("SJCD: open: tray close attempt failed\n"); #endif - return( -EIO ); + goto err_out; } continue; - } else return( -EIO ); + } else goto err_out; } break; } @@ -1387,17 +1386,19 @@ #if defined( SJCD_DIAGNOSTIC ) printk("SJCD: open: tray lock attempt failed\n"); #endif - return( -EIO ); + goto err_out; } #if defined( SJCD_TRACE ) printk( "SJCD: open: done\n" ); #endif } -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif + ++sjcd_open_count; return( 0 ); + +err_out: + MOD_DEC_USE_COUNT; + return( -EIO ); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/Config.in linux.ac/drivers/char/Config.in --- linux.vanilla/drivers/char/Config.in Thu May 25 17:46:15 2000 +++ linux.ac/drivers/char/Config.in Sun Jun 4 21:51:40 2000 @@ -206,7 +206,7 @@ fi comment 'Video Adapters' if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then - dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT $CONFIG_SOUND + dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT fi dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_ALL_PPC" = "y" ]; then diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/Makefile linux.ac/drivers/char/Makefile --- linux.vanilla/drivers/char/Makefile Thu May 25 17:37:59 2000 +++ linux.ac/drivers/char/Makefile Sun Jun 4 21:51:40 2000 @@ -134,40 +134,22 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_SPECIALIX) += specialix.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o -obj-$(CONFIG_SX) += sx.o -# If either SX or RIO is in the kernel, generic_serial goes in the -# kernel, and the module is no longer required. The "in kernel" case -# is last to be able to override the module case.... This is an -# example of the new "makefile automatically figures out the -# dependencies".... -- REW - -GS=n -ifeq ($(CONFIG_RIO),m) - M_OBJS += generic_serial.o - MOD_SUB_DIRS += rio - GS = m -endif - -ifeq ($(CONFIG_SX),m) - GS = m - M_OBJS += sx.o -endif +# After much ado, we found that an object can safely be declared as +# both a module and into the kernel. Below that is filtered out. +# So this should simply provide the wanted functionality! +obj-$(CONFIG_SX) += sx.o generic_serial.o +obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o + ifeq ($(CONFIG_RIO),y) - L_OBJS += rio/rio.o generic_serial.o SUB_DIRS += rio - MOD_SUB_DIRS += rio - GS = y -endif - -ifeq ($(CONFIG_SX),y) - L_OBJS += sx.o - GS = y +else + ifeq ($(CONFIG_RIO),m) + MOD_SUB_DIRS += rio + endif endif -obj-$(GS) += generic_serial.o - obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o obj-$(CONFIG_PRINTER) += lp.o @@ -238,6 +220,7 @@ L_TUNERS=m endif endif +obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o ifeq ($(CONFIG_VIDEO_ZR36120),y) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/adbmouse.c linux.ac/drivers/char/adbmouse.c --- linux.vanilla/drivers/char/adbmouse.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/adbmouse.c Sun Mar 19 18:23:12 2000 @@ -132,6 +132,10 @@ static int release_mouse(struct inode *inode, struct file *file) { adb_mouse_interrupt_hook = NULL; + /* + * FIXME?: adb_mouse_interrupt_hook may still be executing + * on another CPU. + */ MOD_DEC_USE_COUNT; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/agp/agp.h linux.ac/drivers/char/agp/agp.h --- linux.vanilla/drivers/char/agp/agp.h Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/agp/agp.h Sat Jun 10 21:54:29 2000 @@ -31,6 +31,7 @@ U8_APER_SIZE, U16_APER_SIZE, U32_APER_SIZE, + LVL2_APER_SIZE, FIXED_APER_SIZE }; @@ -63,6 +64,12 @@ u32 size_value; } aper_size_info_32; +typedef struct _aper_size_info_lvl2 { + int size; + int num_entries; + u32 size_value; +} aper_size_info_lvl2; + typedef struct _aper_size_info_fixed { int size; int num_entries; @@ -124,10 +131,12 @@ #define A_SIZE_8(x) ((aper_size_info_8 *) x) #define A_SIZE_16(x) ((aper_size_info_16 *) x) #define A_SIZE_32(x) ((aper_size_info_32 *) x) +#define A_SIZE_LVL2(x) ((aper_size_info_lvl2 *) x) #define A_SIZE_FIX(x) ((aper_size_info_fixed *) x) #define A_IDX8() (A_SIZE_8(agp_bridge.aperture_sizes) + i) #define A_IDX16() (A_SIZE_16(agp_bridge.aperture_sizes) + i) #define A_IDX32() (A_SIZE_32(agp_bridge.aperture_sizes) + i) +#define A_IDXLVL2() (A_SIZE_LVL2(agp_bridge.aperture_sizes) + i) #define A_IDXFIX() (A_SIZE_FIX(agp_bridge.aperture_sizes) + i) #define MAXKEY (4096 * 32) @@ -151,6 +160,9 @@ #ifndef PCI_DEVICE_ID_INTEL_810_0 #define PCI_DEVICE_ID_INTEL_810_0 0x7120 #endif +#ifndef PCI_DEVICE_ID_INTEL_840_0 +#define PCI_DEVICE_ID_INTEL_840_0 0x1a21 +#endif #ifndef PCI_DEVICE_ID_INTEL_810_DC100_0 #define PCI_DEVICE_ID_INTEL_810_DC100_0 0x7122 #endif @@ -189,6 +201,10 @@ #define INTEL_AGPCTRL 0xb0 #define INTEL_NBXCFG 0x50 #define INTEL_ERRSTS 0x91 + +/* intel i840 registers */ +#define INTEL_I840_MCHCFG 0x50 +#define INTEL_I840_ERRSTS 0xc8 /* intel i810 registers */ #define I810_GMADDR 0x10 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/agp/agpgart_be.c linux.ac/drivers/char/agp/agpgart_be.c --- linux.vanilla/drivers/char/agp/agpgart_be.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/agp/agpgart_be.c Sat Jun 10 21:54:29 2000 @@ -315,6 +315,9 @@ case U32_APER_SIZE: current_size = A_SIZE_32(temp)->size; break; + case LVL2_APER_SIZE: + current_size = A_SIZE_LVL2(temp)->size; + break; case FIXED_APER_SIZE: current_size = A_SIZE_FIX(temp)->size; break; @@ -539,6 +542,11 @@ int i; void *temp; + /* The generic routines can't handle 2 level gatt's */ + if (agp_bridge.size_type == LVL2_APER_SIZE) { + return -EINVAL; + } + table = NULL; i = agp_bridge.aperture_size_idx; temp = agp_bridge.current_size; @@ -566,6 +574,7 @@ break; /* This case will never really happen. */ case FIXED_APER_SIZE: + case LVL2_APER_SIZE: default: size = page_order = num_entries = 0; break; @@ -590,6 +599,7 @@ * happen. */ case FIXED_APER_SIZE: + case LVL2_APER_SIZE: default: agp_bridge.current_size = agp_bridge.current_size; @@ -663,6 +673,10 @@ case FIXED_APER_SIZE: page_order = A_SIZE_FIX(temp)->page_order; break; + case LVL2_APER_SIZE: + /* The generic routines can't deal with 2 level gatt's */ + return -EINVAL; + break; default: page_order = 0; break; @@ -706,6 +720,10 @@ case FIXED_APER_SIZE: num_entries = A_SIZE_FIX(temp)->num_entries; break; + case LVL2_APER_SIZE: + /* The generic routines can't deal with 2 level gatt's */ + return -EINVAL; + break; default: num_entries = 0; break; @@ -1126,6 +1144,38 @@ return 0; } +static int intel_840_configure(void) +{ + u32 temp; + u16 temp2; + aper_size_info_16 *current_size; + + current_size = A_SIZE_16(agp_bridge.current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE, + (char)current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp); + agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* attbase - aperture base */ + pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE, + agp_bridge.gatt_bus_addr); + + /* agpctrl */ + pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000); + + /* mcgcfg */ + pci_read_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, &temp2); + pci_write_config_word(agp_bridge.dev, INTEL_I840_MCHCFG, + temp2 | (1 << 9)); + /* clear any possible error conditions */ + pci_write_config_word(agp_bridge.dev, INTEL_I840_ERRSTS, 0xc000); + return 0; +} + static unsigned long intel_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ @@ -1179,6 +1229,34 @@ (void) pdev; /* unused */ } +static int __init intel_840_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = intel_generic_masks; + agp_bridge.num_of_masks = 1; + agp_bridge.aperture_sizes = (void *) intel_generic_sizes; + agp_bridge.size_type = U16_APER_SIZE; + agp_bridge.num_aperture_sizes = 7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = intel_840_configure; + agp_bridge.fetch_size = intel_fetch_size; + agp_bridge.cleanup = intel_cleanup; + agp_bridge.tlb_flush = intel_tlbflush; + agp_bridge.mask_memory = intel_mask_memory; + agp_bridge.agp_enable = agp_generic_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = agp_generic_create_gatt_table; + agp_bridge.free_gatt_table = agp_generic_free_gatt_table; + agp_bridge.insert_memory = agp_generic_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + + return 0; + + (void) pdev; /* unused */ +} + #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_VIA @@ -1403,19 +1481,180 @@ #ifdef CONFIG_AGP_AMD +typedef struct _amd_page_map { + unsigned long *real; + unsigned long *remapped; +} amd_page_map; + static struct _amd_irongate_private { volatile u8 *registers; + amd_page_map **gatt_pages; + int num_tables; } amd_irongate_private; +static int amd_create_page_map(amd_page_map *page_map) +{ + int i; + + page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); + if (page_map->real == NULL) { + return -ENOMEM; + } + set_bit(PG_reserved, &mem_map[MAP_NR(page_map->real)].flags); + CACHE_FLUSH(); + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL) { + clear_bit(PG_reserved, + &mem_map[MAP_NR(page_map->real)].flags); + free_page((unsigned long) page_map->real); + page_map->real = NULL; + return -ENOMEM; + } + CACHE_FLUSH(); + + for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + page_map->remapped[i] = agp_bridge.scratch_page; + } + + return 0; +} + +static void amd_free_page_map(amd_page_map *page_map) +{ + iounmap(page_map->remapped); + clear_bit(PG_reserved, + &mem_map[MAP_NR(page_map->real)].flags); + free_page((unsigned long) page_map->real); +} + +static void amd_free_gatt_pages(void) +{ + int i; + amd_page_map **tables; + amd_page_map *entry; + + tables = amd_irongate_private.gatt_pages; + for(i = 0; i < amd_irongate_private.num_tables; i++) { + entry = tables[i]; + if (entry != NULL) { + if (entry->real != NULL) { + amd_free_page_map(entry); + } + kfree(entry); + } + } + kfree(tables); +} + +static int amd_create_gatt_pages(int nr_tables) +{ + amd_page_map **tables; + amd_page_map *entry; + int retval = 0; + int i; + + tables = kmalloc((nr_tables + 1) * sizeof(amd_page_map *), + GFP_KERNEL); + if (tables == NULL) { + return -ENOMEM; + } + memset(tables, 0, sizeof(amd_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { + entry = kmalloc(sizeof(amd_page_map), GFP_KERNEL); + if (entry == NULL) { + retval = -ENOMEM; + break; + } + memset(entry, 0, sizeof(amd_page_map)); + tables[i] = entry; + retval = amd_create_page_map(entry); + if (retval != 0) break; + } + amd_irongate_private.num_tables = nr_tables; + amd_irongate_private.gatt_pages = tables; + + if (retval != 0) amd_free_gatt_pages(); + + return retval; +} + +/* Since we don't need contigious memory we just try + * to get the gatt table once + */ + +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge.gart_bus_addr)) +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +static int amd_create_gatt_table(void) +{ + aper_size_info_lvl2 *value; + amd_page_map page_dir; + unsigned long addr; + int retval; + u32 temp; + int i; + + value = A_SIZE_LVL2(agp_bridge.current_size); + retval = amd_create_page_map(&page_dir); + if (retval != 0) { + return retval; + } + + retval = amd_create_gatt_pages(value->num_entries / 1024); + if (retval != 0) { + amd_free_page_map(&page_dir); + return retval; + } + + agp_bridge.gatt_table_real = page_dir.real; + agp_bridge.gatt_table = page_dir.remapped; + agp_bridge.gatt_bus_addr = virt_to_bus(page_dir.real); + + /* Get the address for the gart region. + * This is a bus address even on the alpha, b/c its + * used to program the agp master not the cpu + */ + + pci_read_config_dword(agp_bridge.dev, AMD_APBASE, &temp); + addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + agp_bridge.gart_bus_addr = addr; + + /* Calculate the agp offset */ + for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = + virt_to_bus(amd_irongate_private.gatt_pages[i]->real); + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + } + + return 0; +} + +static int amd_free_gatt_table(void) +{ + amd_page_map page_dir; + + page_dir.real = agp_bridge.gatt_table_real; + page_dir.remapped = agp_bridge.gatt_table; + + amd_free_gatt_pages(); + amd_free_page_map(&page_dir); + return 0; +} + static int amd_irongate_fetch_size(void) { int i; u32 temp; - aper_size_info_32 *values; + aper_size_info_lvl2 *values; pci_read_config_dword(agp_bridge.dev, AMD_APSIZE, &temp); temp = (temp & 0x0000000e); - values = A_SIZE_32(agp_bridge.aperture_sizes); + values = A_SIZE_LVL2(agp_bridge.aperture_sizes); for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge.previous_size = @@ -1431,12 +1670,11 @@ static int amd_irongate_configure(void) { - aper_size_info_32 *current_size; - unsigned long addr; + aper_size_info_lvl2 *current_size; u32 temp; u16 enable_reg; - current_size = A_SIZE_32(agp_bridge.current_size); + current_size = A_SIZE_LVL2(agp_bridge.current_size); /* Get the memory mapped registers */ pci_read_config_dword(agp_bridge.dev, AMD_MMBASE, &temp); @@ -1451,7 +1689,7 @@ pci_write_config_byte(agp_bridge.dev, AMD_MODECNTL, 0x80); /* Set indexing mode */ - pci_write_config_byte(agp_bridge.dev, AMD_MODECNTL2, 0x02); + pci_write_config_byte(agp_bridge.dev, AMD_MODECNTL2, 0x00); /* Write the enable register */ enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); @@ -1467,28 +1705,16 @@ /* Flush the tlb */ OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); - /* Get the address for the gart region */ - pci_read_config_dword(agp_bridge.dev, AMD_APBASE, &temp); - addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); -#ifdef __alpha__ - /* ??? Presumably what is wanted is the bus address as seen - from the CPU side, since it appears that this value is - exported to userland via an ioctl. The terminology below - is confused, mixing `physical address' with `bus address', - as x86 folk are wont to do. */ - addr = virt_to_phys(ioremap(addr, 0)); -#endif - agp_bridge.gart_bus_addr = addr; return 0; } static void amd_irongate_cleanup(void) { - aper_size_info_32 *previous_size; + aper_size_info_lvl2 *previous_size; u32 temp; u16 enable_reg; - previous_size = A_SIZE_32(agp_bridge.previous_size); + previous_size = A_SIZE_LVL2(agp_bridge.previous_size); enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); enable_reg = (enable_reg & ~(0x0004)); @@ -1521,15 +1747,76 @@ return addr | agp_bridge.masks[0].mask; } -static aper_size_info_32 amd_irongate_sizes[7] = +static int amd_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + unsigned long *cur_gatt; + unsigned long addr; + + num_entries = A_SIZE_LVL2(agp_bridge.current_size)->num_entries; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + if ((pg_start + mem->page_count) > num_entries) { + return -EINVAL; + } + + j = pg_start; + while (j < (pg_start + mem->page_count)) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i]; + } + agp_bridge.tlb_flush(mem); + return 0; +} + +static int amd_remove_memory(agp_memory * mem, off_t pg_start, + int type) { - {2048, 524288, 9, 0x0000000c}, - {1024, 262144, 8, 0x0000000a}, - {512, 131072, 7, 0x00000008}, - {256, 65536, 6, 0x00000006}, - {128, 32768, 5, 0x00000004}, - {64, 16384, 4, 0x00000002}, - {32, 8192, 3, 0x00000000} + int i; + unsigned long *cur_gatt; + unsigned long addr; + + if (type != 0 || mem->type != 0) { + return -EINVAL; + } + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + addr = (i * PAGE_SIZE) + agp_bridge.gart_bus_addr; + cur_gatt = GET_GATT(addr); + cur_gatt[GET_GATT_OFF(addr)] = + (unsigned long) agp_bridge.scratch_page; + } + + agp_bridge.tlb_flush(mem); + return 0; +} + +static aper_size_info_lvl2 amd_irongate_sizes[7] = +{ + {2048, 524288, 0x0000000c}, + {1024, 262144, 0x0000000a}, + {512, 131072, 0x00000008}, + {256, 65536, 0x00000006}, + {128, 32768, 0x00000004}, + {64, 16384, 0x00000002}, + {32, 8192, 0x00000000} }; static gatt_mask amd_irongate_masks[] = @@ -1542,7 +1829,7 @@ agp_bridge.masks = amd_irongate_masks; agp_bridge.num_of_masks = 1; agp_bridge.aperture_sizes = (void *) amd_irongate_sizes; - agp_bridge.size_type = U32_APER_SIZE; + agp_bridge.size_type = LVL2_APER_SIZE; agp_bridge.num_aperture_sizes = 7; agp_bridge.dev_private_data = (void *) &amd_irongate_private; agp_bridge.needs_scratch_page = FALSE; @@ -1553,10 +1840,10 @@ agp_bridge.mask_memory = amd_irongate_mask_memory; agp_bridge.agp_enable = agp_generic_agp_enable; agp_bridge.cache_flush = global_cache_flush; - agp_bridge.create_gatt_table = agp_generic_create_gatt_table; - agp_bridge.free_gatt_table = agp_generic_free_gatt_table; - agp_bridge.insert_memory = agp_generic_insert_memory; - agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.create_gatt_table = amd_create_gatt_table; + agp_bridge.free_gatt_table = amd_free_gatt_table; + agp_bridge.insert_memory = amd_insert_memory; + agp_bridge.remove_memory = amd_remove_memory; agp_bridge.alloc_by_type = agp_generic_alloc_by_type; agp_bridge.free_by_type = agp_generic_free_by_type; @@ -1755,6 +2042,12 @@ "Intel", "440GX", intel_generic_setup }, + { PCI_DEVICE_ID_INTEL_840_0, + PCI_VENDOR_ID_INTEL, + INTEL_I840, + "Intel", + "i840", + intel_840_setup }, { 0, PCI_VENDOR_ID_INTEL, INTEL_GENERIC, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/agp/agpgart_fe.c linux.ac/drivers/char/agp/agpgart_fe.c --- linux.vanilla/drivers/char/agp/agpgart_fe.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/agp/agpgart_fe.c Sat May 27 15:49:10 2000 @@ -697,19 +697,18 @@ int minor = MINOR(inode->i_rdev); agp_file_private *priv; agp_client *client; + int rc = -ENXIO; AGP_LOCK(); + MOD_INC_USE_COUNT; + + if (minor != AGPGART_MINOR) + goto err_out; - if (minor != AGPGART_MINOR) { - AGP_UNLOCK(); - return -ENXIO; - } priv = kmalloc(sizeof(agp_file_private), GFP_KERNEL); + if (priv == NULL) + goto err_out_nomem; - if (priv == NULL) { - AGP_UNLOCK(); - return -ENOMEM; - } memset(priv, 0, sizeof(agp_file_private)); set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); priv->my_pid = current->pid; @@ -726,9 +725,15 @@ } file->private_data = (void *) priv; agp_insert_file_private(priv); - MOD_INC_USE_COUNT; AGP_UNLOCK(); return 0; + +err_out_nomem: + rc = -ENOMEM; +err_out: + MOD_DEC_USE_COUNT; + AGP_UNLOCK(); + return rc; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/amikeyb.c linux.ac/drivers/char/amikeyb.c --- linux.vanilla/drivers/char/amikeyb.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/amikeyb.c Sun Jun 4 22:01:47 2000 @@ -186,8 +186,8 @@ kbd_pt_regs = NULL; + init_timer(&amikeyb_rep_timer); amikeyb_rep_timer.expires = jiffies + key_repeat_rate; - amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; add_timer(&amikeyb_rep_timer); handle_scancode(rep_scancode, 1); @@ -254,8 +254,8 @@ } else { del_timer(&amikeyb_rep_timer); rep_scancode = keycode; + init_timer(&amikeyb_rep_timer); amikeyb_rep_timer.expires = jiffies + key_repeat_delay; - amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; add_timer(&amikeyb_rep_timer); } handle_scancode(keycode, !break_flag); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/atarimouse.c linux.ac/drivers/char/atarimouse.c --- linux.vanilla/drivers/char/atarimouse.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/atarimouse.c Tue Mar 21 21:35:30 2000 @@ -39,37 +39,36 @@ static void atari_mouse_interrupt(char *buf) { - int buttons; + int buttons; -/* ikbd_mouse_disable(); */ +/* ikbd_mouse_disable(); */ - buttons = ((buf[0] & 1) + buttons = ((buf[0] & 1) | ((buf[0] & 2) << 1) | (atari_mouse_buttons & 2)); - atari_mouse_buttons = buttons; + atari_mouse_buttons = buttons; - busmouse_add_movementbuttons(msedev, buf[1], -buf[2], buttons ^ 7); -/* ikbd_mouse_rel_pos(); */ + busmouse_add_movementbuttons(msedev, buf[1], -buf[2], buttons ^ 7); +/* ikbd_mouse_rel_pos(); */ } static int release_mouse(struct inode *inode, struct file *file) { - ikbd_mouse_disable(); - - atari_mouse_interrupt_hook = NULL; - MOD_DEC_USE_COUNT; - return 0; + ikbd_mouse_disable(); + atari_mouse_interrupt_hook = NULL; + MOD_DEC_USE_COUNT; + return 0; } static int open_mouse(struct inode *inode, struct file *file) { - atari_mouse_buttons = 0; - ikbd_mouse_y0_top (); - ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]); - ikbd_mouse_rel_pos(); - MOD_INC_USE_COUNT; - atari_mouse_interrupt_hook = atari_mouse_interrupt; - return 0; + atari_mouse_buttons = 0; + ikbd_mouse_y0_top (); + ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]); + ikbd_mouse_rel_pos(); + MOD_INC_USE_COUNT; + atari_mouse_interrupt_hook = atari_mouse_interrupt; + return 0; } static struct busmouse atarimouse = { @@ -78,14 +77,14 @@ static int __init atari_mouse_init(void) { - 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; + 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; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/bttv.c linux.ac/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/char/bttv.c Sun Jun 4 21:51:40 2000 @@ -64,7 +64,6 @@ /* insmod args */ MODULE_PARM(triton1,"i"); -MODULE_PARM(remap,"1-4i"); MODULE_PARM(radio,"1-4i"); MODULE_PARM(card,"1-4i"); MODULE_PARM(pll,"1-4i"); @@ -76,6 +75,7 @@ MODULE_PARM(gbuffers,"i"); MODULE_PARM(gbufsize,"i"); +EXPORT_SYMBOL(bttv_get_cardinfo); EXPORT_SYMBOL(bttv_get_id); EXPORT_SYMBOL(bttv_gpio_enable); EXPORT_SYMBOL(bttv_read_gpio); @@ -91,7 +91,6 @@ static unsigned int bigendian=0; #endif static int triton1=0; -static unsigned long remap[BTTV_MAX]; static unsigned int radio[BTTV_MAX]; static unsigned int card[BTTV_MAX] = { 0, 0, 0, 0 }; static unsigned int pll[BTTV_MAX] = { -1, -1, -1, -1}; @@ -123,8 +122,19 @@ /* gpio ports (IR for example) */ /* see bttv.h for comments */ +int bttv_get_cardinfo(unsigned int card, int *type, int *cardid) +{ + if (card >= bttv_num) { + return -1; + } + *type = bttvs[card].type; + *cardid = bttvs[card].cardid; + return 0; +} + int bttv_get_id(unsigned int card) { + printk("bttv_get_id is obsolete, use bttv_get_cardinfo instead\n"); if (card >= bttv_num) { return -1; } @@ -180,7 +190,7 @@ return 0; } -WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card) +wait_queue_head_t* bttv_get_gpio_queue(unsigned int card) { struct bttv *btv; @@ -276,7 +286,7 @@ void * mem; unsigned long adr, page; - mem=vmalloc_32(size); + mem=vmalloc(size); if (mem) { memset(mem, 0, size); /* Clear the ram out, no junk to the user */ @@ -467,7 +477,7 @@ NULL }; -static int __init init_bttv_i2c(struct bttv *btv) +static int __devinit init_bttv_i2c(struct bttv *btv) { /* i2c bit_adapter */ memcpy(&btv->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); @@ -489,7 +499,7 @@ } /* read I2C */ -static int __init I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { unsigned char buffer = 0; @@ -514,7 +524,7 @@ } /* write I2C */ -static int __init I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, +static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both) { unsigned char buffer[2]; @@ -531,7 +541,7 @@ } /* read EEPROM */ -static void __init readee(struct bttv *btv, unsigned char *eedata, int addr) +static void __devinit readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; @@ -558,7 +568,7 @@ int id; char *name; } -hauppauge_tuner[] __initdata = +hauppauge_tuner[] __devinitdata = { { TUNER_ABSENT, "" }, { TUNER_ABSENT, "External" }, @@ -606,7 +616,7 @@ { TUNER_ABSENT, "Temic 4046FM5" }, }; -static void __init hauppauge_eeprom(struct bttv *btv) +static void __devinit hauppauge_eeprom(struct bttv *btv) { if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { @@ -615,11 +625,9 @@ printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); } - - return; } -static void __init hauppauge_boot_msp34xx(struct bttv *btv) +static void __devinit hauppauge_boot_msp34xx(struct bttv *btv) { int i; @@ -655,7 +663,7 @@ /* This is basically the same procedure as * used by Alessandro Rubini in his pxc200 * driver, but using BTTV functions */ -static void __init init_PXC200(struct bttv *btv) +static void __devinit init_PXC200(struct bttv *btv) { static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, @@ -705,7 +713,7 @@ unsigned id; int cardnr; char *name; -} cards[] __initdata = { +} cards[] __devinitdata = { { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, @@ -813,7 +821,7 @@ /* 0x10 */ { "Pixelview PlayTV (bt878)", - 3, 1, 0, 2, 0x01fe00, { 2, 0, 1, 1}, + 3, 1, 0, 2, 0x01fe00, { 2, 3, 1, 1}, { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0, 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Leadtek WinView 601", @@ -910,10 +918,18 @@ { "ProVideo PV951", /* pic16c54 */ 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, 0,0,0,0,0,0,0,0, PLL_28, 1 }, + { "Little OnAir TV", + 3, 1, 0, 2, 0xe00b, {2, 3, 1, 1}, + {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},0, + 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, + + { "Sigma TVII-FM", + 2, 1, 0, -1, 3, {2, 3, 1, 1}, {1, 1, 0, 2, 3},0, + 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) -static void __init dump_eeprom(struct bttv *btv,int addr) +static void __devinit dump_eeprom(struct bttv *btv,int addr) { int i; @@ -930,7 +946,7 @@ } } -static int __init idcard_eeprom(struct bttv *btv) +static int __devinit idcard_eeprom(struct bttv *btv) { unsigned id; int i,n; @@ -943,6 +959,7 @@ return -1; /* look for the card */ + btv->cardid = id; for (n = -1, i = 0; cards[i].id != 0; i++) if (cards[i].id == id) n = i; @@ -1203,7 +1220,7 @@ unsigned int *po=(unsigned int *) btv->vbi_odd; unsigned int *pe=(unsigned int *) btv->vbi_even; - if (debug) + if (debug > 1) printk("bttv%d: vbi1: po=%08lx pe=%08lx\n", btv->nr,virt_to_bus(po), virt_to_bus(pe)); @@ -1225,7 +1242,7 @@ *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); *(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); - if (debug) + if (debug > 1) printk("bttv%d: vbi2: po=%08lx pe=%08lx\n", btv->nr,virt_to_bus(po), virt_to_bus(pe)); } @@ -1302,7 +1319,7 @@ unsigned long vadr=(unsigned long) vbuf; int shift, csize; - if (debug) + if (debug > 1) printk("bttv%d: prisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); @@ -1399,7 +1416,7 @@ *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); - if (debug) + if (debug > 1) printk("bttv%d: prisc2: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); @@ -1424,7 +1441,7 @@ if (palette>=VIDEO_PALETTE_PLANAR) return make_prisctab(btv, ro, re, vbuf, width, height, palette); - if (debug) + if (debug > 1) printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); @@ -1476,7 +1493,7 @@ *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); - if (debug) + if (debug > 1) printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); @@ -1494,7 +1511,7 @@ int W, l, r; int i; - if (debug) + if (debug > 1) printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y); /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ @@ -1559,7 +1576,7 @@ inter=(btv->win.interlace&1)^1; width=btv->win.width; height=btv->win.height; - if (debug) + if (debug > 1) printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n", btv->nr,btv->picture.palette,width,height,bpl,bpp); if(width > 1023) @@ -1668,7 +1685,7 @@ *(re++)=cpu_to_le32(BT848_RISC_JUMP); *(re++)=cpu_to_le32(btv->bus_vbi_odd); - if (debug) + if (debug > 1) printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n", btv->nr,btv->picture.palette,width,height,bpl,bpp); } @@ -1734,9 +1751,6 @@ u16 ewidth, eheight, owidth, oheight; u16 format, bswap; struct tvnorm *tvn; - unsigned long flags; - - spin_lock_irqsave(&btv->s_lock, flags); tvn=&tvnorms[btv->win.norm]; @@ -1789,8 +1803,6 @@ btwrite(format, BT848_COLOR_FMT); btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); - - spin_unlock_irqrestore(&btv->s_lock, flags); } @@ -1847,7 +1859,6 @@ /* * Grab into virtual memory. - * Currently only does double buffering. Do we need more? */ static int vgrab(struct bttv *btv, struct video_mmap *mp) @@ -1904,16 +1915,16 @@ btv->gbuf[mp->frame].ro = 0; #endif - if (btv->gq_in == btv->gq_out) { + if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) { btv->gq_start = 1; btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } btv->gqueue[btv->gq_in++] = mp->frame; btv->gq_in = btv->gq_in % MAX_GBUFFERS; - spin_unlock_irqrestore(&btv->s_lock, flags); btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); + spin_unlock_irqrestore(&btv->s_lock, flags); return 0; } @@ -1927,39 +1938,43 @@ { struct bttv *btv= (struct bttv *)v; int q,todo; + DECLARE_WAITQUEUE(wait, current); /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */ todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { - unsigned long flags; - if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) return -EFAULT; todo-=q; buf+=q; - spin_lock_irqsave(&btv->s_lock, flags); + add_wait_queue(&btv->vbiq, &wait); + current->state = TASK_INTERRUPTIBLE; if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - spin_unlock_irqrestore(&btv->s_lock, flags); + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; if(count==todo) return -EWOULDBLOCK; return count-todo; } - spin_unlock_irqrestore(&btv->s_lock, flags); - interruptible_sleep_on(&btv->vbiq); + schedule(); if(signal_pending(current)) { + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; + if(todo==count) return -EINTR; else return count-todo; } - } else - spin_unlock_irqrestore(&btv->s_lock, flags); + } + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; } if (todo) { @@ -1980,9 +1995,11 @@ static void bt848_restart(struct bttv *btv) { + unsigned long irq_flags; + if (verbose) printk("bttv%d: resetting chip\n",btv->nr); - btwrite(~0x0UL, BT848_INT_STAT); + btwrite(0xfffffUL, BT848_INT_STAT); btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_SRESET); btwrite(virt_to_bus(btv->risc_jmp+2), @@ -1994,8 +2011,10 @@ btv->errors = 0; btv->needs_restart = 0; + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_geo(btv,0); bt848_set_risc_jmps(btv,-1); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } /* @@ -2042,13 +2061,16 @@ static void bttv_close(struct video_device *dev) { struct bttv *btv=(struct bttv *)dev; + unsigned long irq_flags; down(&btv->lock); btv->user--; + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->scr_on = 0; btv->risc_cap_odd = 0; btv->risc_cap_even = 0; bt848_set_risc_jmps(btv,-1); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); /* * A word of warning. At this point the chip @@ -2133,9 +2155,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct bttv *btv=(struct bttv *)dev; + unsigned long irq_flags; int i,ret = 0; - if (debug) printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd); + if (debug > 1) + printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd); switch (cmd) { case VIDIOCGCAP: @@ -2206,7 +2230,9 @@ if (btv->win.norm != v.norm) { btv->win.norm = v.norm; make_vbitab(btv); + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_winsize(btv); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } up(&btv->lock); return 0; @@ -2248,7 +2274,9 @@ down(&btv->lock); set_pll(btv); make_vbitab(btv); + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_winsize(btv); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); up(&btv->lock); } return 0; @@ -2289,12 +2317,13 @@ if(copy_from_user(&vw,arg,sizeof(vw))) return -EFAULT; + down(&btv->lock); if(vw.flags || vw.width < 16 || vw.height < 16) { - down(&btv->lock); + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->scr_on = 0; bt848_set_risc_jmps(btv,-1); - up(&btv->lock); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); return -EINVAL; } if (btv->win.bpp < 4) @@ -2302,18 +2331,17 @@ vw.x = (vw.x + 3) & ~3; vw.width &= ~3; } - down(&btv->lock); if (btv->needs_restart) bt848_restart(btv); btv->win.x=vw.x; btv->win.y=vw.y; btv->win.width=vw.width; btv->win.height=vw.height; - + + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_risc_jmps(btv,0); - bt848_set_winsize(btv); - up(&btv->lock); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); /* * Do any clips. @@ -2337,11 +2365,12 @@ return -EFAULT; } } - down(&btv->lock); make_clip_tab(btv, vcp, vw.clipcount); if (vw.clipcount != 0) vfree(vcp); + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_risc_jmps(btv,-1); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); up(&btv->lock); return 0; } @@ -2370,13 +2399,13 @@ return -EINVAL; if (btv->win.width==0 || btv->win.height==0) return -EINVAL; - down(&btv->lock); + spin_lock_irqsave(&btv->s_lock, irq_flags); if (v == 1 && btv->win.vidadr != 0) btv->scr_on = 1; if (v == 0) btv->scr_on = 0; bt848_set_risc_jmps(btv,-1); - up(&btv->lock); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); return 0; } case VIDIOCGFBUF: @@ -2500,9 +2529,7 @@ if(!(v.flags&VIDEO_AUDIO_MUTE)) audio(btv, AUDIO_UNMUTE, 1); - up(&btv->lock); call_i2c_clients(btv,cmd,&v); - down(&btv->lock); if (btv->type == BTTV_TERRATV) { unsigned int con = 0; @@ -2554,6 +2581,9 @@ } case VIDIOCSYNC: + { + DECLARE_WAITQUEUE(wait, current); + if(copy_from_user((void *)&i,arg,sizeof(int))) return -EFAULT; if (i < 0 || i >= gbuffers) @@ -2563,13 +2593,20 @@ ret = -EINVAL; break; case GBUFFER_GRABBING: + add_wait_queue(&btv->capq, &wait); + current->state = TASK_INTERRUPTIBLE; while(btv->gbuf[i].stat==GBUFFER_GRABBING) { if (debug) printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); - interruptible_sleep_on(&btv->capq); - if(signal_pending(current)) + schedule(); + if(signal_pending(current)) { + remove_wait_queue(&btv->capq, &wait); + current->state = TASK_RUNNING; return -EINTR; + } } + remove_wait_queue(&btv->capq, &wait); + current->state = TASK_RUNNING; /* fall throuth */ case GBUFFER_DONE: case GBUFFER_ERROR: @@ -2584,6 +2621,7 @@ up(&btv->lock); } return ret; + } case BTTV_FIELDNR: if(copy_to_user((void *) arg, (void *) &btv->last_field, @@ -2602,7 +2640,6 @@ btv->pll.pll_ofreq = p.pll_ofreq; btv->pll.pll_crystal = p.pll_crystal; up(&btv->lock); - break; } @@ -2749,12 +2786,11 @@ { struct bttv *btv=(struct bttv *)(v-2); int q,todo; + DECLARE_WAITQUEUE(wait, current); todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { - unsigned long flags; - if (btv->needs_restart) { down(&btv->lock); bt848_restart(btv); @@ -2765,27 +2801,31 @@ todo-=q; buf+=q; - spin_lock_irqsave(&btv->s_lock, flags); + add_wait_queue(&btv->vbiq, &wait); + current->state = TASK_INTERRUPTIBLE; if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - spin_unlock_irqrestore(&btv->s_lock, flags); + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; if(count==todo) return -EWOULDBLOCK; return count-todo; } - spin_unlock_irqrestore(&btv->s_lock, flags); - interruptible_sleep_on(&btv->vbiq); + schedule(); if(signal_pending(current)) { + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; if(todo==count) return -EINTR; else return count-todo; } - } else - spin_unlock_irqrestore(&btv->s_lock, flags); + } + remove_wait_queue(&btv->vbiq, &wait); + current->state = TASK_RUNNING; } if (todo) { @@ -2813,15 +2853,18 @@ static int vbi_open(struct video_device *dev, int flags) { struct bttv *btv=(struct bttv *)(dev-2); + unsigned long irq_flags; MOD_INC_USE_COUNT; - down(&btv->lock); if (btv->needs_restart) bt848_restart(btv); + set_pll(btv); btv->vbip=VBIBUF_SIZE; + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->vbi_on = 1; bt848_set_risc_jmps(btv,-1); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); up(&btv->lock); return 0; @@ -2830,12 +2873,12 @@ static void vbi_close(struct video_device *dev) { struct bttv *btv=(struct bttv *)(dev-2); + unsigned long irq_flags; - down(&btv->lock); + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->vbi_on = 0; bt848_set_risc_jmps(btv,-1); - up(&btv->lock); - + spin_unlock_irqrestore(&btv->s_lock, irq_flags); MOD_DEC_USE_COUNT; } @@ -3018,7 +3061,7 @@ #define TRITON_PEER_CONCURRENCY (1<<3) -static void __init handle_chipset(void) +static void __devinit handle_chipset(void) { struct pci_dev *dev = NULL; @@ -3050,7 +3093,7 @@ /* can tda9855.c handle this too maybe? */ -static void __init init_tda9840(struct bttv *btv) +static void __devinit init_tda9840(struct bttv *btv) { /* Horrible Hack */ I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */ @@ -3066,12 +3109,11 @@ /* Figure out card and tuner type */ -static void __init idcard(struct bttv *btv) +static void __devinit idcard(struct bttv *btv) { int type,eeprom = 0; btwrite(0, BT848_GPIO_OUT_EN); - DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", btv->nr, btread(BT848_GPIO_DATA))); /* Default the card to the user-selected one. */ if (card[btv->nr] >= 0 && card[btv->nr] < TVCARDS) @@ -3114,7 +3156,6 @@ (btv->id==848 && btv->revision==0x12) ? "A" : "", tvcards[btv->type].name); printk(KERN_INFO "bttv%d: model: %s\n",btv->nr,btv->video_dev.name); - /* board specific initialisations */ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { @@ -3228,10 +3269,6 @@ static void bt848_set_risc_jmps(struct bttv *btv, int flags) { - unsigned long irq_flags; - - spin_lock_irqsave(&btv->s_lock, irq_flags); - if (-1 == flags) { /* defaults */ flags = 0; @@ -3241,8 +3278,9 @@ flags |= 0x0c; } - if (debug) printk("bttv%d: set_risc_jmp %08lx:", - btv->nr,virt_to_bus(btv->risc_jmp)); + if (debug > 1) + printk("bttv%d: set_risc_jmp %08lx:", + btv->nr,virt_to_bus(btv->risc_jmp)); /* Sync to start of odd field */ btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC @@ -3252,24 +3290,29 @@ /* Jump to odd vbi sub */ btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20)); if (flags&8) { - if (debug) printk(" ev=%08lx",virt_to_bus(btv->vbi_odd)); + if (debug > 1) + printk(" ev=%08lx",virt_to_bus(btv->vbi_odd)); btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd)); } else { - if (debug) printk(" -----------"); + if (debug > 1) + printk(" -----------"); btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); } /* Jump to odd sub */ btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20)); if (0 != btv->risc_cap_odd) { - if (debug) printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd); + if (debug > 1) + printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd); flags |= 3; btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd); } else if (flags&2) { - if (debug) printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd)); + if (debug > 1) + printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd)); btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd)); } else { - if (debug) printk(" -----------"); + if (debug > 1) + printk(" -----------"); btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6)); } @@ -3282,24 +3325,29 @@ /* Jump to even vbi sub */ btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP); if (flags&4) { - if (debug) printk(" ov=%08lx",virt_to_bus(btv->vbi_even)); + if (debug > 1) + printk(" ov=%08lx",virt_to_bus(btv->vbi_even)); btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even)); } else { - if (debug) printk(" -----------"); + if (debug > 1) + printk(" -----------"); btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); } /* Jump to even sub */ btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20)); if (0 != btv->risc_cap_even) { - if (debug) printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even); + if (debug > 1) + printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even); flags |= 3; btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even); } else if (flags&1) { - if (debug) printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even)); + if (debug > 1) + printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even)); btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even)); } else { - if (debug) printk(" -----------"); + if (debug > 1) + printk(" -----------"); btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); } @@ -3311,18 +3359,17 @@ btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp)); /* enable cpaturing and DMA */ - if (debug) printk(" flags=0x%x dma=%s\n", - flags,(flags&0x0f) ? "on" : "off"); + if (debug > 1) + printk(" flags=0x%x dma=%s\n", + flags,(flags&0x0f) ? "on" : "off"); btaor(flags, ~0x0f, BT848_CAP_CTL); if (flags&0x0f) bt848_dma(btv, 3); else bt848_dma(btv, 0); - - spin_unlock_irqrestore(&btv->s_lock, irq_flags); } -static int __init init_video_dev(struct bttv *btv) +static int __devinit init_video_dev(struct bttv *btv) { memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); @@ -3349,9 +3396,10 @@ return 1; } -static int __init init_bt848(struct bttv *btv) +static int __devinit init_bt848(struct bttv *btv) { int j; + unsigned long irq_flags; btv->user=0; init_MUTEX(&btv->lock); @@ -3412,7 +3460,6 @@ return -1; if (!(btv->risc_jmp =(unsigned int *) kmalloc(2048, GFP_KERNEL))) return -1; - DEBUG(printk(KERN_DEBUG "risc_jmp: %p\n",btv->risc_jmp)); btv->vbi_odd=btv->risc_jmp+16; btv->vbi_even=btv->vbi_odd+256; btv->bus_vbi_odd=virt_to_bus(btv->risc_jmp+12); @@ -3475,7 +3522,7 @@ btwrite(0x00, BT848_O_SCLOOP); /* clear interrupt status */ - btwrite(~0x0UL, BT848_INT_STAT); + btwrite(0xfffffUL, BT848_INT_STAT); /* set interrupt mask */ btwrite(btv->triton1| @@ -3489,8 +3536,10 @@ BT848_INT_MASK); make_vbitab(btv); + spin_lock_irqsave(&btv->s_lock, irq_flags); bt848_set_risc_jmps(btv,-1); - + spin_unlock_irqrestore(&btv->s_lock, irq_flags); + /* * Now add the template and register the device unit. */ @@ -3505,7 +3554,8 @@ u32 dstat; int count,i; struct bttv *btv; - + unsigned long irq_flags; + btv=(struct bttv *)dev_id; count=0; while (1) @@ -3515,6 +3565,7 @@ astat=stat&btread(BT848_INT_MASK); if (!astat) return; + btwrite(astat,BT848_INT_STAT); IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat)); IDEBUG(printk ("bttv%d: stat=%08x\n", btv->nr, stat)); @@ -3550,15 +3601,18 @@ btread(BT848_RISC_COUNT)); btv->errors++; if (btv->errors < BTTV_ERRORS) { + spin_lock_irqsave(&btv->s_lock, irq_flags); btand(~15, BT848_GPIO_DMA_CTL); btwrite(virt_to_bus(btv->risc_jmp+2), BT848_RISC_STRT_ADD); bt848_set_geo(btv,0); bt848_set_risc_jmps(btv,-1); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } else { if (verbose) printk("bttv%d: aiee: error loops\n",btv->nr); /* cancel all outstanding grab requests */ + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->gq_in = 0; btv->gq_out = 0; btv->gq_grab = -1; @@ -3569,8 +3623,9 @@ btv->risc_cap_odd = 0; btv->risc_cap_even = 0; bt848_set_risc_jmps(btv,0); - btv->needs_restart = 1; + spin_unlock_irqrestore(&btv->s_lock, irq_flags); + wake_up_interruptible(&btv->vbiq); wake_up_interruptible(&btv->capq); } @@ -3596,6 +3651,7 @@ if (debug) printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); do_gettimeofday(&btv->gbuf[btv->gq_grab].tv); + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; btv->gq_grab = -1; if (btv->gq_in != btv->gq_out) @@ -3618,22 +3674,25 @@ btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); } + spin_unlock_irqrestore(&btv->s_lock, irq_flags); wake_up_interruptible(&btv->capq); break; } if (stat&(8<<28)) { + spin_lock_irqsave(&btv->s_lock, irq_flags); btv->gq_start = 0; btv->gq_grab = btv->gqueue[btv->gq_out++]; btv->gq_out = btv->gq_out % MAX_GBUFFERS; if (debug) - printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab); + printk("bttv%d: cap irq: capture %d [start]\n",btv->nr,btv->gq_grab); btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; bt848_set_risc_jmps(btv,-1); bt848_set_geo(btv,0); btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } } if (astat&BT848_INT_OCERR) @@ -3676,9 +3735,6 @@ { IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr)); } - - btwrite(astat,BT848_INT_STAT); - count++; if (count > 10) printk (KERN_WARNING "bttv%d: irq loop %d\n", @@ -3698,11 +3754,11 @@ * Scan for a Bt848 card, request the irq and map the io memory */ -static void __init bttv_remove(struct pci_dev *pci_dev) +static void __devinit bttv_remove(struct pci_dev *pci_dev) { u8 command; int j; - struct bttv *btv = pci_dev->driver_data; + struct bttv *btv = PCI_GET_DRIVER_DATA(pci_dev); /* unregister i2c_bus */ i2c_bit_del_bus(&btv->i2c_adap); @@ -3767,7 +3823,7 @@ } -static int __init bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) +static int __devinit bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int result; unsigned char command; @@ -3788,20 +3844,17 @@ btv->vbi_even=NULL; init_waitqueue_head(&btv->vbiq); init_waitqueue_head(&btv->capq); - init_waitqueue_head(&btv->capqo); - init_waitqueue_head(&btv->capqe); btv->vbip=VBIBUF_SIZE; - - init_waitqueue_head(&btv->gpioq); btv->s_lock = SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&btv->gpioq); btv->shutdown=0; btv->id=dev->device; btv->irq=dev->irq; - btv->bt848_adr=pci_resource_start(dev, 0); + btv->bt848_adr=pci_resource_start(dev,0); if (pci_enable_device(dev)) return -EIO; - if (!request_mem_region(btv->bt848_adr, + if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), "bttv")) { return -EBUSY; @@ -3871,24 +3924,23 @@ } } - dev->driver_data = btv; + PCI_SET_DRIVER_DATA(dev,btv); if(init_bt848(btv) < 0) { bttv_remove(dev); return -EIO; } - bttv_num++; return 0; fail: - release_mem_region(btv->bt848_adr, + release_mem_region(pci_resource_start(btv->dev,0), pci_resource_len(btv->dev,0)); return result; } -static struct pci_device_id bttv_pci_tbl[] __initdata = { +static struct pci_device_id bttv_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, @@ -3903,13 +3955,13 @@ MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); static struct pci_driver bttv_pci_driver = { - name:"bttv", - id_table:bttv_pci_tbl, - probe:bttv_probe, - remove:bttv_remove, + name: "bttv", + id_table: bttv_pci_tbl, + probe: bttv_probe, + remove: bttv_remove, }; -static int __init bttv_init_module(void) +int bttv_init_module(void) { bttv_num = 0; @@ -3930,10 +3982,10 @@ return pci_module_init(&bttv_pci_driver); } -static void __exit bttv_cleanup_module(void) +void bttv_cleanup_module(void) { pci_unregister_driver(&bttv_pci_driver); - return; + return; } module_init(bttv_init_module); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/bttv.h linux.ac/drivers/char/bttv.h --- linux.vanilla/drivers/char/bttv.h Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/bttv.h Sat Jun 10 22:40:33 2000 @@ -21,7 +21,12 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,28) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,31) + +#ifndef PCI_GET_DRIVER_DATA +# define PCI_GET_DRIVER_DATA(pdev) ((pdev)->driver_data) +# define PCI_SET_DRIVER_DATA(pdev,data) (((pdev)->driver_data) = (data)) +#endif /* PCI_GET_DRIVER_DATA */ #include #include @@ -32,12 +37,13 @@ #include "audiochip.h" #include "bt848.h" -#define WAIT_QUEUE wait_queue_head_t - -/* returns card type, +/* returns card type + card ID (for bt878-based ones) for possible values see lines below beginning with #define BTTV_UNKNOWN returns negative value if error ocurred */ +extern int bttv_get_cardinfo(unsigned int card, int *type, int *cardid); + +/* obsolete, use bttv_get_cardinfo instead */ extern int bttv_get_id(unsigned int card); /* sets GPOE register (BT848_GPIO_OUT_EN) to new value: @@ -68,7 +74,7 @@ WARNING: because there is no buffer for GPIO data, one MUST process data ASAP */ -extern WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card); +extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); #ifndef O_NONCAP @@ -130,6 +136,7 @@ struct video_picture picture; /* Current picture params */ struct video_audio audio_dev; /* Current audio params */ + spinlock_t s_lock; struct semaphore lock; int user; int capuser; @@ -143,8 +150,6 @@ int tuner_type; int channel; - - spinlock_t s_lock; unsigned int nr; unsigned short id; @@ -160,6 +165,7 @@ struct bttv_window win; int fb_color_ctl; int type; /* card type */ + int cardid; int audio; /* audio mode */ int audio_chip; /* set to one of the chips supported by bttv.c */ int radio; @@ -169,10 +175,8 @@ u32 *vbi_even; u32 bus_vbi_even; u32 bus_vbi_odd; - WAIT_QUEUE vbiq; - WAIT_QUEUE capq; - WAIT_QUEUE capqo; - WAIT_QUEUE capqe; + wait_queue_head_t vbiq; + wait_queue_head_t capq; int vbip; u32 *risc_scr_odd; @@ -198,7 +202,7 @@ int errors; int needs_restart; - WAIT_QUEUE gpioq; + wait_queue_head_t gpioq; int shutdown; }; #endif @@ -277,6 +281,8 @@ #define BTTV_STB2 0x28 #define BTTV_AVPHONE98 0x29 #define BTTV_PV951 0x2a +#define BTTV_ONAIR_TV 0x2b +#define BTTV_SIGMA_TVII_FM 0x2c #define PLL_NONE 0 #define PLL_28 1 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/busmouse.c linux.ac/drivers/char/busmouse.c --- linux.vanilla/drivers/char/busmouse.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/busmouse.c Sun Jun 4 21:23:03 2000 @@ -110,8 +110,7 @@ if (changed) { wake_up(&mse->wait); - if (mse->fasyncptr) - kill_fasync(mse->fasyncptr, SIGIO, POLL_IN); + kill_fasync(&mse->fasyncptr, SIGIO, POLL_IN); } } @@ -193,6 +192,8 @@ if (mousedev >= NR_MICE) return -EINVAL; + MOD_INC_USE_COUNT; + down(&mouse_sem); mse = busmouse_data[mousedev]; if (!mse) @@ -211,8 +212,6 @@ if (mse->active++) goto end; - MOD_INC_USE_COUNT; - spin_lock_irq(&mse->lock); mse->ready = 0; @@ -226,6 +225,9 @@ spin_unlock_irq(&mse->lock); end: up(&mouse_sem); + + if (ret) + MOD_DEC_USE_COUNT; return ret; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/c-qcam.c linux.ac/drivers/char/c-qcam.c --- linux.vanilla/drivers/char/c-qcam.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/c-qcam.c Mon May 29 19:42:50 2000 @@ -12,9 +12,15 @@ * probe=1 -- use IEEE-1284 autoprobe data only (default) * probe=2 -- probe aggressively for cameras * + * force_rgb=1 -- force data format to RGB (default is BGR) + * * The parport parameter controls which parports will be scanned. * Scanning all parports causes some printers to print a garbage page. * -- March 14, 1999 Billy Donahue + * + * Fixed data format to BGR, added force_rgb parameter. Added missing + * parport_unregister_driver() on module removal. + * -- May 28, 2000 Claudio Matsuoka */ #include @@ -62,6 +68,7 @@ static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int probe = 2; +static int force_rgb = 0; static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) { @@ -278,6 +285,7 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) { unsigned int bytes = 0; + qcam_set_ack(q, 0); if (q->bidirectional) { @@ -285,6 +293,8 @@ while (bytes < nbytes) { unsigned int lo1, hi1, lo2, hi2; + unsigned char r, g, b; + if (qcam_await_ready2(q, 1)) return bytes; lo1 = parport_read_data(q->pport) >> 1; hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; @@ -293,17 +303,30 @@ lo2 = parport_read_data(q->pport) >> 1; hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; qcam_set_ack(q, 0); - buf[bytes++] = (lo1 | ((hi1 & 1)<<7)); - buf[bytes++] = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1); - buf[bytes++] = (lo2 | ((hi2 & 1)<<7)); + r = (lo1 | ((hi1 & 1)<<7)); + g = ((hi1 & 0x1e)<<3) | ((hi2 & 0x1e)>>1); + b = (lo2 | ((hi2 & 1)<<7)); + if (force_rgb) { + buf[bytes++] = r; + buf[bytes++] = g; + buf[bytes++] = b; + } else { + buf[bytes++] = b; + buf[bytes++] = g; + buf[bytes++] = r; + } } } else { /* It's a unidirectional port */ + int i = 0, n = bytes; + unsigned char rgb[3]; + while (bytes < nbytes) { unsigned int hi, lo; + if (qcam_await_ready1(q, 1)) return bytes; hi = (parport_read_status(q->pport) & 0xf0); qcam_set_ack(q, 1); @@ -311,7 +334,23 @@ lo = (parport_read_status(q->pport) & 0xf0); qcam_set_ack(q, 0); /* flip some bits */ - buf[bytes++] = (hi | (lo >> 4)) ^ 0x88; + rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; + if (i >= 2) { +get_fragment: + if (force_rgb) { + buf[n++] = rgb[0]; + buf[n++] = rgb[1]; + buf[n++] = rgb[2]; + } else { + buf[n++] = rgb[2]; + buf[n++] = rgb[1]; + buf[n++] = rgb[0]; + } + } + } + if (i) { + i = 0; + goto get_fragment; } } return bytes; @@ -408,8 +447,13 @@ if (current->need_resched) schedule(); } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); + if (force_rgb) { + if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) + printk("qcam: bad EOF\n"); + } else { + if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) + printk("qcam: bad EOF\n"); + } qcam_set_ack(q, 0); if (qcam_await_ready1(q, 1)) { @@ -437,8 +481,13 @@ schedule(); } while (l && tmpbuf[0] == 0x7e); l = qcam_read_bytes(q, tmpbuf+1, 2); - if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) - printk("qcam: bad EOF\n"); + if (force_rgb) { + if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) + printk("qcam: bad EOF\n"); + } else { + if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) + printk("qcam: bad EOF\n"); + } } qcam_write_data(q, 0); @@ -829,19 +878,24 @@ return parport_register_driver(&cqcam_driver); } -MODULE_AUTHOR("Philip Blundell "); -MODULE_DESCRIPTION(BANNER); -MODULE_PARM_DESC(parport ,"parport= for port detection method \n\ -probe=<0|1|2> # for camera detection method"); -MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i"); -MODULE_PARM(probe, "i"); - static void __exit cqcam_cleanup (void) { unsigned int i; + for (i = 0; i < num_cams; i++) close_cqcam(qcams[i]); + + parport_unregister_driver(&cqcam_driver); } + +MODULE_AUTHOR("Philip Blundell "); +MODULE_DESCRIPTION(BANNER); +MODULE_PARM_DESC(parport ,"parport= for port detection method\n\ +probe=<0|1|2> for camera detection method\n\ +force_rgb=<0|1> for RGB data format (default BGR)"); +MODULE_PARM(parport, "1-" __MODULE_STRING(MAX_CAMS) "i"); +MODULE_PARM(probe, "i"); +MODULE_PARM(force_rgb, "i"); module_init(cqcam_init); module_exit(cqcam_cleanup); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/console.c linux.ac/drivers/char/console.c --- linux.vanilla/drivers/char/console.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/char/console.c Sun Jun 4 21:34:21 2000 @@ -2290,10 +2290,13 @@ static void con_flush_chars(struct tty_struct *tty) { + unsigned long flags; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; pm_access(pm_con); + spin_lock_irqsave(&console_lock, flags); set_cursor(vt->vc_num); + spin_unlock_irqrestore(&console_lock, flags); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/cyclades.c linux.ac/drivers/char/cyclades.c --- linux.vanilla/drivers/char/cyclades.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/cyclades.c Sun Jun 4 22:15:37 2000 @@ -1,7 +1,8 @@ #undef BLOCKMOVE #define Z_WAKE +#undef Z_EXT_CHARS_IN_BUFFER static char rcsid[] = -"$Revision: 2.3.2.6 $$Date: 2000/05/05 13:56:05 $"; +"$Revision: 2.3.2.7 $$Date: 2000/06/01 18:26:34 $"; /* * linux/drivers/char/cyclades.c @@ -24,6 +25,12 @@ * This version supports shared IRQ's (only for PCI boards). * * $Log: cyclades.c,v $ + * Revision 2.3.2.7 2000/06/01 18:26:34 ivan + * Request PLX I/O region, although driver doesn't use it, to avoid + * problems with other drivers accessing it. + * Removed count for on-board buffer characters in cy_chars_in_buffer + * (Cyclades-Z only). + * * Revision 2.3.2.6 2000/05/05 13:56:05 ivan * Driver now reports physical instead of virtual memory addresses. * Masks were added to some Cyclades-Z read accesses. @@ -636,6 +643,7 @@ #include #include #include +#include #include #include #include @@ -882,9 +890,8 @@ static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; -static struct timer_list -cyz_timerlist = { - NULL, NULL, 0, 0, cyz_poll +static struct timer_list cyz_timerlist = { + function: cyz_poll }; #else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); @@ -3122,12 +3129,15 @@ card = info->card; channel = (info->line) - (cy_card[card].first_line); +#ifdef Z_EXT_CHARS_IN_BUFFER if (!IS_CYC_Z(cy_card[card])) { +#endif /* Z_EXT_CHARS_IN_BUFFER */ #ifdef CY_DEBUG_IO printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ #endif return info->xmit_cnt; +#ifdef Z_EXT_CHARS_IN_BUFFER } else { static volatile struct FIRM_ID *firm_id; static volatile struct ZFW_CTRL *zfw_ctrl; @@ -3156,6 +3166,7 @@ #endif return (info->xmit_cnt + char_count); } +#endif /* Z_EXT_CHARS_IN_BUFFER */ } /* cy_chars_in_buffer */ @@ -4856,7 +4867,7 @@ struct pci_dev *pdev = NULL; unsigned char cyy_rev_id; unsigned char cy_pci_irq = 0; - uclong cy_pci_phys0, cy_pci_phys2; + uclong cy_pci_phys0, cy_pci_phys1, cy_pci_phys2; uclong cy_pci_addr0, cy_pci_addr2; unsigned short i,j,cy_pci_nchan, plx_ver; unsigned short device_id,dev_index = 0; @@ -4885,6 +4896,7 @@ /* read PCI configuration area */ cy_pci_irq = pdev->irq; cy_pci_phys0 = pci_resource_start(pdev, 0); + cy_pci_phys1 = pci_resource_start(pdev, 1); cy_pci_phys2 = pci_resource_start(pdev, 2); pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); @@ -4907,6 +4919,11 @@ pdev->resource[2].flags &= ~IORESOURCE_IO; } + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + request_region(cy_pci_phys1, CyPCI_Yctl, "Cyclom-Y"); + #if defined(__alpha__) if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", @@ -5054,6 +5071,12 @@ "Ignoring it...\n"); pdev->resource[2].flags &= ~IORESOURCE_IO; } + + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + request_region(cy_pci_phys1, CyPCI_Zctl, "Cyclades-Z"); + if (mailbox == ZE_V1) { #if !defined(__alpha__) cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/dn_keyb.c linux.ac/drivers/char/dn_keyb.c --- linux.vanilla/drivers/char/dn_keyb.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/dn_keyb.c Sat May 27 22:00:30 2000 @@ -357,17 +357,14 @@ mouse_dy+=mouse_packet[2] == 0xff ? 0 : (signed char)mouse_packet[2]; wake_up_interruptible(&mouse_wait); 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, POLL_IN); + 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; + kill_fasync(&mouse_fasyncptr, SIGIO, POLL_IN); } mouse_byte_count=0; /* printk("mouse: %d, %d, %x\n",mouse_x,mouse_y,buttons); */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/Makefile linux.ac/drivers/char/drm/Makefile --- linux.vanilla/drivers/char/drm/Makefile Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/drm/Makefile Sat Jun 10 21:50:43 2000 @@ -39,6 +39,17 @@ endif endif +ifeq ($(CONFIG_DRM_FFB),y) + OX_OBJS += ffb_drv.o + O_OBJS += ffb_context.o +else + ifeq ($(CONFIG_DRM_FFB),m) + MIX_OBJC += ffb_drv.o + MI_OBJS += ffb_context.o + M_OBJS += ffb.o + endif +endif + O_OBJS += $(L_OBJS) include $(TOPDIR)/Rules.make @@ -48,3 +59,6 @@ tdfx.o: tdfx_drv.o tdfx_context.o $(L_OBJS) $(LD) $(LD_RFLAG) -r -o $@ tdfx_drv.o tdfx_context.o $(L_OBJS) + +ffb.o: ffb_drv.o ffb_context.o $(L_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ ffb_drv.o ffb_context.o $(L_OBJS) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/bufs.c linux.ac/drivers/char/drm/bufs.c --- linux.vanilla/drivers/char/drm/bufs.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/drm/bufs.c Sat Jun 10 21:50:43 2000 @@ -72,11 +72,13 @@ switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: +#ifndef __sparc__ if (map->offset + map->size < map->offset || map->offset < virt_to_phys(high_memory)) { drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } +#endif #ifdef CONFIG_MTRR if (map->type == _DRM_FRAME_BUFFER || (map->flags & _DRM_WRITE_COMBINING)) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/drmP.h linux.ac/drivers/char/drm/drmP.h --- linux.vanilla/drivers/char/drm/drmP.h Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/drm/drmP.h Sat Jun 10 22:25:31 2000 @@ -433,9 +433,9 @@ /* Context support */ int irq; /* Interrupt used by board */ - __volatile__ int context_flag; /* Context swapping flag */ - __volatile__ int interrupt_flag;/* Interruption handler flag */ - __volatile__ int dma_flag; /* DMA dispatch flag */ + __volatile__ long context_flag; /* Context swapping flag */ + __volatile__ long interrupt_flag;/* Interruption handler flag */ + __volatile__ long dma_flag; /* DMA dispatch flag */ struct timer_list timer; /* Timer for delaying ctx switch */ wait_queue_head_t context_wait; /* Processes waiting on ctx switch */ int last_checked; /* Last context checked for DMA */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/ffb_context.c linux.ac/drivers/char/drm/ffb_context.c --- linux.vanilla/drivers/char/drm/ffb_context.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/drm/ffb_context.c Sat Jun 10 21:50:43 2000 @@ -0,0 +1,530 @@ +/* $Id: ffb_context.c,v 1.3 2000/06/09 03:46:53 davem Exp $ + * ffb_context.c: Creator/Creator3D DRI/DRM context switching. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + * + * Almost entirely stolen from tdfx_context.c, see there + * for authors. + */ + +#include +#include + +#include "drmP.h" + +#include "ffb_drv.h" + +static int ffb_alloc_queue(drm_device_t *dev, int is_2d_only) +{ + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + int i; + + for (i = 0; i < FFB_MAX_CTXS; i++) { + if (fpriv->hw_state[i] == NULL) + break; + } + if (i == FFB_MAX_CTXS) + return -1; + + fpriv->hw_state[i] = kmalloc(sizeof(struct ffb_hw_context), GFP_KERNEL); + if (fpriv->hw_state[i] == NULL) + return -1; + + fpriv->hw_state[i]->is_2d_only = is_2d_only; + + /* Plus one because 0 is the special DRM_KERNEL_CONTEXT. */ + return i + 1; +} + +static void ffb_save_context(ffb_dev_priv_t *fpriv, int idx) +{ + ffb_fbcPtr ffb = fpriv->regs; + struct ffb_hw_context *ctx; + int i; + + ctx = fpriv->hw_state[idx - 1]; + if (idx == 0 || ctx == NULL) + return; + + if (ctx->is_2d_only) { + /* 2D applications only care about certain pieces + * of state. + */ + ctx->drawop = upa_readl(&ffb->drawop); + ctx->ppc = upa_readl(&ffb->ppc); + ctx->wid = upa_readl(&ffb->wid); + ctx->fg = upa_readl(&ffb->fg); + ctx->bg = upa_readl(&ffb->bg); + ctx->xclip = upa_readl(&ffb->xclip); + ctx->fbc = upa_readl(&ffb->fbc); + ctx->rop = upa_readl(&ffb->rop); + ctx->cmp = upa_readl(&ffb->cmp); + ctx->matchab = upa_readl(&ffb->matchab); + ctx->magnab = upa_readl(&ffb->magnab); + ctx->pmask = upa_readl(&ffb->pmask); + ctx->xpmask = upa_readl(&ffb->xpmask); + ctx->lpat = upa_readl(&ffb->lpat); + ctx->fontxy = upa_readl(&ffb->fontxy); + ctx->fontw = upa_readl(&ffb->fontw); + ctx->fontinc = upa_readl(&ffb->fontinc); + + /* stencil/stencilctl only exists on FFB2+ and later + * due to the introduction of 3DRAM-III. + */ + if (fpriv->ffb_type == ffb2_vertical_plus || + fpriv->ffb_type == ffb2_horizontal_plus) { + ctx->stencil = upa_readl(&ffb->stencil); + ctx->stencilctl = upa_readl(&ffb->stencilctl); + } + + for (i = 0; i < 32; i++) + ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); + ctx->ucsr = upa_readl(&ffb->ucsr); + return; + } + + /* Fetch drawop. */ + ctx->drawop = upa_readl(&ffb->drawop); + + /* If we were saving the vertex registers, this is where + * we would do it. We would save 32 32-bit words starting + * at ffb->suvtx. + */ + + /* Capture rendering attributes. */ + + ctx->ppc = upa_readl(&ffb->ppc); /* Pixel Processor Control */ + ctx->wid = upa_readl(&ffb->wid); /* Current WID */ + ctx->fg = upa_readl(&ffb->fg); /* Constant FG color */ + ctx->bg = upa_readl(&ffb->bg); /* Constant BG color */ + ctx->consty = upa_readl(&ffb->consty); /* Constant Y */ + ctx->constz = upa_readl(&ffb->constz); /* Constant Z */ + ctx->xclip = upa_readl(&ffb->xclip); /* X plane clip */ + ctx->dcss = upa_readl(&ffb->dcss); /* Depth Cue Scale Slope */ + ctx->vclipmin = upa_readl(&ffb->vclipmin); /* Primary XY clip, minimum */ + ctx->vclipmax = upa_readl(&ffb->vclipmax); /* Primary XY clip, maximum */ + ctx->vclipzmin = upa_readl(&ffb->vclipzmin); /* Primary Z clip, minimum */ + ctx->vclipzmax = upa_readl(&ffb->vclipzmax); /* Primary Z clip, maximum */ + ctx->dcsf = upa_readl(&ffb->dcsf); /* Depth Cue Scale Front Bound */ + ctx->dcsb = upa_readl(&ffb->dcsb); /* Depth Cue Scale Back Bound */ + ctx->dczf = upa_readl(&ffb->dczf); /* Depth Cue Scale Z Front */ + ctx->dczb = upa_readl(&ffb->dczb); /* Depth Cue Scale Z Back */ + ctx->blendc = upa_readl(&ffb->blendc); /* Alpha Blend Control */ + ctx->blendc1 = upa_readl(&ffb->blendc1); /* Alpha Blend Color 1 */ + ctx->blendc2 = upa_readl(&ffb->blendc2); /* Alpha Blend Color 2 */ + ctx->fbc = upa_readl(&ffb->fbc); /* Frame Buffer Control */ + ctx->rop = upa_readl(&ffb->rop); /* Raster Operation */ + ctx->cmp = upa_readl(&ffb->cmp); /* Compare Controls */ + ctx->matchab = upa_readl(&ffb->matchab); /* Buffer A/B Match Ops */ + ctx->matchc = upa_readl(&ffb->matchc); /* Buffer C Match Ops */ + ctx->magnab = upa_readl(&ffb->magnab); /* Buffer A/B Magnitude Ops */ + ctx->magnc = upa_readl(&ffb->magnc); /* Buffer C Magnitude Ops */ + ctx->pmask = upa_readl(&ffb->pmask); /* RGB Plane Mask */ + ctx->xpmask = upa_readl(&ffb->xpmask); /* X Plane Mask */ + ctx->ypmask = upa_readl(&ffb->ypmask); /* Y Plane Mask */ + ctx->zpmask = upa_readl(&ffb->zpmask); /* Z Plane Mask */ + + /* Auxiliary Clips. */ + ctx->auxclip0min = upa_readl(&ffb->auxclip[0].min); + ctx->auxclip0max = upa_readl(&ffb->auxclip[0].max); + ctx->auxclip1min = upa_readl(&ffb->auxclip[1].min); + ctx->auxclip1max = upa_readl(&ffb->auxclip[1].max); + ctx->auxclip2min = upa_readl(&ffb->auxclip[2].min); + ctx->auxclip2max = upa_readl(&ffb->auxclip[2].max); + ctx->auxclip3min = upa_readl(&ffb->auxclip[3].min); + ctx->auxclip3max = upa_readl(&ffb->auxclip[3].max); + + ctx->lpat = upa_readl(&ffb->lpat); /* Line Pattern */ + ctx->fontxy = upa_readl(&ffb->fontxy); /* XY Font Coordinate */ + ctx->fontw = upa_readl(&ffb->fontw); /* Font Width */ + ctx->fontinc = upa_readl(&ffb->fontinc); /* Font X/Y Increment */ + + /* These registers/features only exist on FFB2 and later chips. */ + if (fpriv->ffb_type >= ffb2_prototype) { + ctx->dcss1 = upa_readl(&ffb->dcss1); /* Depth Cue Scale Slope 1 */ + ctx->dcss2 = upa_readl(&ffb->dcss2); /* Depth Cue Scale Slope 2 */ + ctx->dcss2 = upa_readl(&ffb->dcss3); /* Depth Cue Scale Slope 3 */ + ctx->dcs2 = upa_readl(&ffb->dcs2); /* Depth Cue Scale 2 */ + ctx->dcs3 = upa_readl(&ffb->dcs3); /* Depth Cue Scale 3 */ + ctx->dcs4 = upa_readl(&ffb->dcs4); /* Depth Cue Scale 4 */ + ctx->dcd2 = upa_readl(&ffb->dcd2); /* Depth Cue Depth 2 */ + ctx->dcd3 = upa_readl(&ffb->dcd3); /* Depth Cue Depth 3 */ + ctx->dcd4 = upa_readl(&ffb->dcd4); /* Depth Cue Depth 4 */ + + /* And stencil/stencilctl only exists on FFB2+ and later + * due to the introduction of 3DRAM-III. + */ + if (fpriv->ffb_type == ffb2_vertical_plus || + fpriv->ffb_type == ffb2_horizontal_plus) { + ctx->stencil = upa_readl(&ffb->stencil); + ctx->stencilctl = upa_readl(&ffb->stencilctl); + } + } + + /* Save the 32x32 area pattern. */ + for (i = 0; i < 32; i++) + ctx->area_pattern[i] = upa_readl(&ffb->pattern[i]); + + /* Finally, stash away the User Constol/Status Register. */ + ctx->ucsr = upa_readl(&ffb->ucsr); +} + +static void ffb_restore_context(ffb_dev_priv_t *fpriv, int old, int idx) +{ + ffb_fbcPtr ffb = fpriv->regs; + struct ffb_hw_context *ctx; + int i; + + ctx = fpriv->hw_state[idx - 1]; + if (idx == 0 || ctx == NULL) + return; + + if (ctx->is_2d_only) { + /* 2D applications only care about certain pieces + * of state. + */ + upa_writel(ctx->drawop, &ffb->drawop); + + /* If we were restoring the vertex registers, this is where + * we would do it. We would restore 32 32-bit words starting + * at ffb->suvtx. + */ + + upa_writel(ctx->ppc, &ffb->ppc); + upa_writel(ctx->wid, &ffb->wid); + upa_writel(ctx->fg, &ffb->fg); + upa_writel(ctx->bg, &ffb->bg); + upa_writel(ctx->xclip, &ffb->xclip); + upa_writel(ctx->fbc, &ffb->fbc); + upa_writel(ctx->rop, &ffb->rop); + upa_writel(ctx->cmp, &ffb->cmp); + upa_writel(ctx->matchab, &ffb->matchab); + upa_writel(ctx->magnab, &ffb->magnab); + upa_writel(ctx->pmask, &ffb->pmask); + upa_writel(ctx->xpmask, &ffb->xpmask); + upa_writel(ctx->lpat, &ffb->lpat); + upa_writel(ctx->fontxy, &ffb->fontxy); + upa_writel(ctx->fontw, &ffb->fontw); + upa_writel(ctx->fontinc, &ffb->fontinc); + + /* stencil/stencilctl only exists on FFB2+ and later + * due to the introduction of 3DRAM-III. + */ + if (fpriv->ffb_type == ffb2_vertical_plus || + fpriv->ffb_type == ffb2_horizontal_plus) { + upa_writel(ctx->stencil, &ffb->stencil); + upa_writel(ctx->stencilctl, &ffb->stencilctl); + upa_writel(0x80000000, &ffb->fbc); + upa_writel((ctx->stencilctl | 0x80000), + &ffb->rawstencilctl); + upa_writel(ctx->fbc, &ffb->fbc); + } + + for (i = 0; i < 32; i++) + upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); + upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); + return; + } + + /* Restore drawop. */ + upa_writel(ctx->drawop, &ffb->drawop); + + /* If we were restoring the vertex registers, this is where + * we would do it. We would restore 32 32-bit words starting + * at ffb->suvtx. + */ + + /* Restore rendering attributes. */ + + upa_writel(ctx->ppc, &ffb->ppc); /* Pixel Processor Control */ + upa_writel(ctx->wid, &ffb->wid); /* Current WID */ + upa_writel(ctx->fg, &ffb->fg); /* Constant FG color */ + upa_writel(ctx->bg, &ffb->bg); /* Constant BG color */ + upa_writel(ctx->consty, &ffb->consty); /* Constant Y */ + upa_writel(ctx->constz, &ffb->constz); /* Constant Z */ + upa_writel(ctx->xclip, &ffb->xclip); /* X plane clip */ + upa_writel(ctx->dcss, &ffb->dcss); /* Depth Cue Scale Slope */ + upa_writel(ctx->vclipmin, &ffb->vclipmin); /* Primary XY clip, minimum */ + upa_writel(ctx->vclipmax, &ffb->vclipmax); /* Primary XY clip, maximum */ + upa_writel(ctx->vclipzmin, &ffb->vclipzmin); /* Primary Z clip, minimum */ + upa_writel(ctx->vclipzmax, &ffb->vclipzmax); /* Primary Z clip, maximum */ + upa_writel(ctx->dcsf, &ffb->dcsf); /* Depth Cue Scale Front Bound */ + upa_writel(ctx->dcsb, &ffb->dcsb); /* Depth Cue Scale Back Bound */ + upa_writel(ctx->dczf, &ffb->dczf); /* Depth Cue Scale Z Front */ + upa_writel(ctx->dczb, &ffb->dczb); /* Depth Cue Scale Z Back */ + upa_writel(ctx->blendc, &ffb->blendc); /* Alpha Blend Control */ + upa_writel(ctx->blendc1, &ffb->blendc1); /* Alpha Blend Color 1 */ + upa_writel(ctx->blendc2, &ffb->blendc2); /* Alpha Blend Color 2 */ + upa_writel(ctx->fbc, &ffb->fbc); /* Frame Buffer Control */ + upa_writel(ctx->rop, &ffb->rop); /* Raster Operation */ + upa_writel(ctx->cmp, &ffb->cmp); /* Compare Controls */ + upa_writel(ctx->matchab, &ffb->matchab); /* Buffer A/B Match Ops */ + upa_writel(ctx->matchc, &ffb->matchc); /* Buffer C Match Ops */ + upa_writel(ctx->magnab, &ffb->magnab); /* Buffer A/B Magnitude Ops */ + upa_writel(ctx->magnc, &ffb->magnc); /* Buffer C Magnitude Ops */ + upa_writel(ctx->pmask, &ffb->pmask); /* RGB Plane Mask */ + upa_writel(ctx->xpmask, &ffb->xpmask); /* X Plane Mask */ + upa_writel(ctx->ypmask, &ffb->ypmask); /* Y Plane Mask */ + upa_writel(ctx->zpmask, &ffb->zpmask); /* Z Plane Mask */ + + /* Auxiliary Clips. */ + upa_writel(ctx->auxclip0min, &ffb->auxclip[0].min); + upa_writel(ctx->auxclip0max, &ffb->auxclip[0].max); + upa_writel(ctx->auxclip1min, &ffb->auxclip[1].min); + upa_writel(ctx->auxclip1max, &ffb->auxclip[1].max); + upa_writel(ctx->auxclip2min, &ffb->auxclip[2].min); + upa_writel(ctx->auxclip2max, &ffb->auxclip[2].max); + upa_writel(ctx->auxclip3min, &ffb->auxclip[3].min); + upa_writel(ctx->auxclip3max, &ffb->auxclip[3].max); + + upa_writel(ctx->lpat, &ffb->lpat); /* Line Pattern */ + upa_writel(ctx->fontxy, &ffb->fontxy); /* XY Font Coordinate */ + upa_writel(ctx->fontw, &ffb->fontw); /* Font Width */ + upa_writel(ctx->fontinc, &ffb->fontinc); /* Font X/Y Increment */ + + /* These registers/features only exist on FFB2 and later chips. */ + if (fpriv->ffb_type >= ffb2_prototype) { + upa_writel(ctx->dcss1, &ffb->dcss1); /* Depth Cue Scale Slope 1 */ + upa_writel(ctx->dcss2, &ffb->dcss2); /* Depth Cue Scale Slope 2 */ + upa_writel(ctx->dcss3, &ffb->dcss2); /* Depth Cue Scale Slope 3 */ + upa_writel(ctx->dcs2, &ffb->dcs2); /* Depth Cue Scale 2 */ + upa_writel(ctx->dcs3, &ffb->dcs3); /* Depth Cue Scale 3 */ + upa_writel(ctx->dcs4, &ffb->dcs4); /* Depth Cue Scale 4 */ + upa_writel(ctx->dcd2, &ffb->dcd2); /* Depth Cue Depth 2 */ + upa_writel(ctx->dcd3, &ffb->dcd3); /* Depth Cue Depth 3 */ + upa_writel(ctx->dcd4, &ffb->dcd4); /* Depth Cue Depth 4 */ + + /* And stencil/stencilctl only exists on FFB2+ and later + * due to the introduction of 3DRAM-III. + */ + if (fpriv->ffb_type == ffb2_vertical_plus || + fpriv->ffb_type == ffb2_horizontal_plus) { + /* Unfortunately, there is a hardware bug on + * the FFB2+ chips which prevents a normal write + * to the stencil control register from working + * as it should. + * + * The state controlled by the FFB stencilctl register + * really gets transferred to the per-buffer instances + * of the stencilctl register in the 3DRAM chips. + * + * The bug is that FFB does not update buffer C correctly, + * so we have to do it by hand for them. + */ + + /* This will update buffers A and B. */ + upa_writel(ctx->stencil, &ffb->stencil); + upa_writel(ctx->stencilctl, &ffb->stencilctl); + + /* Force FFB to use buffer C 3dram regs. */ + upa_writel(0x80000000, &ffb->fbc); + upa_writel((ctx->stencilctl | 0x80000), + &ffb->rawstencilctl); + + /* Now restore the correct FBC controls. */ + upa_writel(ctx->fbc, &ffb->fbc); + } + } + + /* Restore the 32x32 area pattern. */ + for (i = 0; i < 32; i++) + upa_writel(ctx->area_pattern[i], &ffb->pattern[i]); + + /* Finally, stash away the User Constol/Status Register. + * The only state we really preserve here is the picking + * control. + */ + upa_writel((ctx->ucsr & 0xf0000), &ffb->ucsr); +} + +#define FFB_UCSR_FB_BUSY 0x01000000 +#define FFB_UCSR_RP_BUSY 0x02000000 +#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) + +static void FFBWait(ffb_fbcPtr ffb) +{ + int limit = 100000; + + do { + u32 regval = upa_readl(&ffb->ucsr); + + if ((regval & FFB_UCSR_ALL_BUSY) == 0) + break; + } while (--limit); +} + +int ffb_context_switch(drm_device_t *dev, int old, int new) +{ + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + + atomic_inc(&dev->total_ctx); + +#if DRM_DMA_HISTOGRAM + dev->ctx_start = get_cycles(); +#endif + + DRM_DEBUG("Context switch from %d to %d\n", old, new); + + if (new == dev->last_context || + dev->last_context == 0) { + dev->last_context = new; + return 0; + } + + FFBWait(fpriv->regs); + ffb_save_context(fpriv, old); + ffb_restore_context(fpriv, old, new); + FFBWait(fpriv->regs); + + dev->last_context = new; + + return 0; +} + +int ffb_resctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_res_t res; + drm_ctx_t ctx; + int i; + + DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS); + copy_from_user_ret(&res, (drm_ctx_res_t *)arg, sizeof(res), -EFAULT); + if (res.count >= DRM_RESERVED_CONTEXTS) { + memset(&ctx, 0, sizeof(ctx)); + for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { + ctx.handle = i; + copy_to_user_ret(&res.contexts[i], + &i, + sizeof(i), + -EFAULT); + } + } + res.count = DRM_RESERVED_CONTEXTS; + copy_to_user_ret((drm_ctx_res_t *)arg, &res, sizeof(res), -EFAULT); + return 0; +} + + +int ffb_addctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + int idx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + idx = ffb_alloc_queue(dev, (ctx.flags & _DRM_CONTEXT_2DONLY)); + if (idx < 0) + return -ENFILE; + + DRM_DEBUG("%d\n", ctx.handle); + ctx.handle = idx; + copy_to_user_ret((drm_ctx_t *)arg, &ctx, sizeof(ctx), -EFAULT); + return 0; +} + +int ffb_modctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + struct ffb_hw_context *hwctx; + drm_ctx_t ctx; + int idx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + + idx = ctx.handle; + if (idx <= 0 || idx >= FFB_MAX_CTXS) + return -EINVAL; + + hwctx = fpriv->hw_state[idx - 1]; + if (hwctx == NULL) + return -EINVAL; + + if ((ctx.flags & _DRM_CONTEXT_2DONLY) == 0) + hwctx->is_2d_only = 0; + else + hwctx->is_2d_only = 1; + + return 0; +} + +int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + struct ffb_hw_context *hwctx; + drm_ctx_t ctx; + int idx; + + copy_from_user_ret(&ctx, (drm_ctx_t*)arg, sizeof(ctx), -EFAULT); + + idx = ctx.handle; + if (idx <= 0 || idx >= FFB_MAX_CTXS) + return -EINVAL; + + hwctx = fpriv->hw_state[idx - 1]; + if (hwctx == NULL) + return -EINVAL; + + if (hwctx->is_2d_only != 0) + ctx.flags = _DRM_CONTEXT_2DONLY; + else + ctx.flags = 0; + + copy_to_user_ret((drm_ctx_t*)arg, &ctx, sizeof(ctx), -EFAULT); + + return 0; +} + +int ffb_switchctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + return ffb_context_switch(dev, dev->last_context, ctx.handle); +} + +int ffb_newctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + + return 0; +} + +int ffb_rmctx(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_ctx_t ctx; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + int idx; + + copy_from_user_ret(&ctx, (drm_ctx_t *)arg, sizeof(ctx), -EFAULT); + DRM_DEBUG("%d\n", ctx.handle); + + idx = ctx.handle - 1; + if (idx < 0 || idx >= FFB_MAX_CTXS) + return -EINVAL; + + if (fpriv->hw_state[idx] != NULL) { + kfree(fpriv->hw_state[idx]); + fpriv->hw_state[idx] = NULL; + } + return 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/ffb_drv.c linux.ac/drivers/char/drm/ffb_drv.c --- linux.vanilla/drivers/char/drm/ffb_drv.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/drm/ffb_drv.c Sat Jun 10 21:50:43 2000 @@ -0,0 +1,842 @@ +/* $Id: ffb_drv.c,v 1.3 2000/06/01 04:24:39 davem Exp $ + * ffb_drv.c: Creator/Creator3D direct rendering driver. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + */ + +#include "drmP.h" + +#include +#include + +#include "ffb_drv.h" + +#define FFB_NAME "ffb" +#define FFB_DESC "Creator/Creator3D" +#define FFB_DATE "20000517" +#define FFB_MAJOR 0 +#define FFB_MINOR 0 +#define FFB_PATCHLEVEL 1 + +/* Forward declarations. */ +int ffb_init(void); +void ffb_cleanup(void); +static int ffb_version(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int ffb_open(struct inode *inode, struct file *filp); +static int ffb_release(struct inode *inode, struct file *filp); +static int ffb_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int ffb_lock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int ffb_unlock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static int ffb_mmap(struct file *filp, struct vm_area_struct *vma); + +/* From ffb_context.c */ +extern int ffb_resctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_addctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_modctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_getctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_switchctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_newctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_rmctx(struct inode *, struct file *, unsigned int, unsigned long); +extern int ffb_context_switch(drm_device_t *, int, int); + +static struct file_operations ffb_fops = { + open: ffb_open, + flush: drm_flush, + release: ffb_release, + ioctl: ffb_ioctl, + mmap: ffb_mmap, + read: drm_read, + fasync: drm_fasync, + poll: drm_poll, +}; + +/* This is just a template, we make a new copy for each FFB + * we discover at init time so that each one gets a unique + * misc device minor number. + */ +static struct miscdevice ffb_misc = { + minor: MISC_DYNAMIC_MINOR, + name: FFB_NAME, + fops: &ffb_fops, +}; + +static drm_ioctl_desc_t ffb_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { ffb_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, /* XXX */ + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + + /* The implementation is currently a nop just like on tdfx. + * Later we can do something more clever. -DaveM + */ + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { ffb_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { ffb_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { ffb_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { ffb_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { ffb_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { ffb_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { ffb_resctx, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { ffb_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { ffb_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, +}; +#define FFB_IOCTL_COUNT DRM_ARRAY_SIZE(ffb_ioctls) + +#ifdef MODULE +static char *ffb = NULL; +#endif + +MODULE_AUTHOR("David S. Miller (davem@redhat.com)"); +MODULE_DESCRIPTION("Sun Creator/Creator3D DRI"); + +static int ffb_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + down(&dev->struct_sem); + del_timer(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: + drm_ioremapfree(map->handle, map->size); + break; + + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + }; + + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wake_up_interruptible(&dev->lock.lock_queue); + } + up(&dev->struct_sem); + + return 0; +} + +drm_device_t **ffb_dev_table; +static int ffb_dev_table_size; + +static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance) +{ + volatile unsigned char *strap_bits; + unsigned char val; + + strap_bits = (volatile unsigned char *) + (ffb_priv->card_phys_base + 0x00200000UL); + + /* Don't ask, you have to read the value twice for whatever + * reason to get correct contents. + */ + val = upa_readb(strap_bits); + val = upa_readb(strap_bits); + switch (val & 0x78) { + case (0x0 << 5) | (0x0 << 3): + ffb_priv->ffb_type = ffb1_prototype; + printk("ffb%d: Detected FFB1 pre-FCS prototype\n", instance); + break; + case (0x0 << 5) | (0x1 << 3): + ffb_priv->ffb_type = ffb1_standard; + printk("ffb%d: Detected FFB1\n", instance); + break; + case (0x0 << 5) | (0x3 << 3): + ffb_priv->ffb_type = ffb1_speedsort; + printk("ffb%d: Detected FFB1-SpeedSort\n", instance); + break; + case (0x1 << 5) | (0x0 << 3): + ffb_priv->ffb_type = ffb2_prototype; + printk("ffb%d: Detected FFB2/vertical pre-FCS prototype\n", instance); + break; + case (0x1 << 5) | (0x1 << 3): + ffb_priv->ffb_type = ffb2_vertical; + printk("ffb%d: Detected FFB2/vertical\n", instance); + break; + case (0x1 << 5) | (0x2 << 3): + ffb_priv->ffb_type = ffb2_vertical_plus; + printk("ffb%d: Detected FFB2+/vertical\n", instance); + break; + case (0x2 << 5) | (0x0 << 3): + ffb_priv->ffb_type = ffb2_horizontal; + printk("ffb%d: Detected FFB2/horizontal\n", instance); + break; + case (0x2 << 5) | (0x2 << 3): + ffb_priv->ffb_type = ffb2_horizontal; + printk("ffb%d: Detected FFB2+/horizontal\n", instance); + break; + default: + ffb_priv->ffb_type = ffb2_vertical; + printk("ffb%d: Unknown boardID[%08x], assuming FFB2\n", instance, val); + break; + }; +} + +static int ffb_init_one(int prom_node, int instance) +{ + struct linux_prom64_registers regs[2*PROMREG_MAX]; + drm_device_t *dev; + ffb_dev_priv_t *ffb_priv; + int ret, i; + + dev = kmalloc(sizeof(drm_device_t) + sizeof(ffb_dev_priv_t), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + memset(dev, 0, sizeof(*dev)); + spin_lock_init(&dev->count_lock); + sema_init(&dev->struct_sem, 1); + + ffb_priv = (ffb_dev_priv_t *) (dev + 1); + ffb_priv->prom_node = prom_node; + if (prom_getproperty(ffb_priv->prom_node, "reg", + (void *)regs, sizeof(regs)) <= 0) { + kfree(dev); + return -EINVAL; + } + ffb_priv->card_phys_base = regs[0].phys_addr; + ffb_priv->regs = (ffb_fbcPtr) + (regs[0].phys_addr + 0x00600000UL); + get_ffb_type(ffb_priv, instance); + for (i = 0; i < FFB_MAX_CTXS; i++) + ffb_priv->hw_state[i] = NULL; + + ffb_dev_table[instance] = dev; + +#ifdef MODULE + drm_parse_options(ffb); +#endif + + memcpy(&ffb_priv->miscdev, &ffb_misc, sizeof(ffb_misc)); + ret = misc_register(&ffb_priv->miscdev); + if (ret) { + ffb_dev_table[instance] = NULL; + kfree(dev); + return ret; + } + + dev->device = MKDEV(MISC_MAJOR, ffb_priv->miscdev.minor); + dev->name = FFB_NAME; + + drm_mem_init(); + drm_proc_init(dev); + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d at %016lx\n", + FFB_NAME, + FFB_MAJOR, + FFB_MINOR, + FFB_PATCHLEVEL, + FFB_DATE, + ffb_priv->miscdev.minor, + ffb_priv->card_phys_base); + + return 0; +} + +static int ffb_init_dev_table(void) +{ + int root, node; + int total = 0; + + root = prom_getchild(prom_root_node); + for (node = prom_searchsiblings(root, "SUNW,ffb"); node; + node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) + total++; + + ffb_dev_table = kmalloc(sizeof(drm_device_t *) * total, GFP_KERNEL); + if (!ffb_dev_table) + return -ENOMEM; + + ffb_dev_table_size = total; + + return 0; +} + +int ffb_init(void) +{ + int root, node, instance, ret; + + ret = ffb_init_dev_table(); + if (ret) + return ret; + + instance = 0; + root = prom_getchild(prom_root_node); + for (node = prom_searchsiblings(root, "SUNW,ffb"); node; + node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) { + ret = ffb_init_one(node, instance); + if (ret) + return ret; + instance++; + } + + return 0; +} + +void ffb_cleanup(void) +{ + int instance; + + DRM_DEBUG("\n"); + + drm_proc_cleanup(); + for (instance = 0; instance < ffb_dev_table_size; instance++) { + drm_device_t *dev = ffb_dev_table[instance]; + ffb_dev_priv_t *ffb_priv; + + if (!dev) + continue; + + ffb_priv = (ffb_dev_priv_t *) (dev + 1); + if (misc_deregister(&ffb_priv->miscdev)) { + DRM_ERROR("Cannot unload module\n"); + } else { + DRM_INFO("Module unloaded\n"); + } + ffb_takedown(dev); + kfree(dev); + ffb_dev_table[instance] = NULL; + } + kfree(ffb_dev_table); + ffb_dev_table = NULL; + ffb_dev_table_size = 0; +} + +static int ffb_version(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + drm_version_t version; + int len, ret; + + ret = copy_from_user(&version, (drm_version_t *)arg, sizeof(version)); + if (ret) + return -EFAULT; + + version.version_major = FFB_MAJOR; + version.version_minor = FFB_MINOR; + version.version_patchlevel = FFB_PATCHLEVEL; + + len = strlen(FFB_NAME); + if (len > version.name_len) + len = version.name_len; + version.name_len = len; + if (len && version.name) { + ret = copy_to_user(version.name, FFB_NAME, len); + if (ret) + return -EFAULT; + } + + len = strlen(FFB_DATE); + if (len > version.date_len) + len = version.date_len; + version.date_len = len; + if (len && version.date) { + ret = copy_to_user(version.date, FFB_DATE, len); + if (ret) + return -EFAULT; + } + + len = strlen(FFB_DESC); + if (len > version.desc_len) + len = version.desc_len; + version.desc_len = len; + if (len && version.desc) { + ret = copy_to_user(version.desc, FFB_DESC, len); + if (ret) + return -EFAULT; + } + + ret = copy_to_user((drm_version_t *) arg, &version, sizeof(version)); + if (ret) + ret = -EFAULT; + + return ret; +} + +static int ffb_setup(drm_device_t *dev) +{ + int i; + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + init_waitqueue_head(&dev->lock.lock_queue); + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + init_timer(&dev->timer); + init_waitqueue_head(&dev->context_wait); + + dev->ctx_start = 0; + dev->lck_start = 0; + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + dev->buf_async = NULL; + init_waitqueue_head(&dev->buf_readers); + init_waitqueue_head(&dev->buf_writers); + + return 0; +} + +static int ffb_open(struct inode *inode, struct file *filp) +{ + drm_device_t *dev; + int minor, i; + int ret = 0; + + minor = MINOR(inode->i_rdev); + for (i = 0; i < ffb_dev_table_size; i++) { + ffb_dev_priv_t *ffb_priv; + + ffb_priv = (ffb_dev_priv_t *) (ffb_dev_table[i] + 1); + + if (ffb_priv->miscdev.minor == minor) + break; + } + + if (i >= ffb_dev_table_size) + return -EINVAL; + + dev = ffb_dev_table[i]; + if (!dev) + return -EINVAL; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + ret = drm_open_helper(inode, filp, dev); + if (!ret) { + MOD_INC_USE_COUNT; + atomic_inc(&dev->total_open); + spin_lock(&dev->count_lock); + if (!dev->open_count++) { + spin_unlock(&dev->count_lock); + return ffb_setup(dev); + } + spin_unlock(&dev->count_lock); + } + + return ret; +} + +static int ffb_release(struct inode *inode, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int ret = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (dev->lock.hw_lock != NULL + && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) + && dev->lock.pid == current->pid) { + ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1); + int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock); + int idx; + + /* We have to free up the rogue hw context state + * holding error or else we will leak it. + */ + idx = context - 1; + if (fpriv->hw_state[idx] != NULL) { + kfree(fpriv->hw_state[idx]); + fpriv->hw_state[idx] = NULL; + } + } + + ret = drm_release(inode, filp); + + if (!ret) { + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + spin_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return ffb_takedown(dev); + } + spin_unlock(&dev->count_lock); + } + + return ret; +} + +static int ffb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_ioctl_desc_t *ioctl; + drm_ioctl_t *func; + int ret; + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", + current->pid, cmd, nr, dev->device, priv->authenticated); + + if (nr >= FFB_IOCTL_COUNT) { + ret = -EINVAL; + } else { + ioctl = &ffb_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + ret = -EINVAL; + } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) + || (ioctl->auth_needed && !priv->authenticated)) { + ret = -EACCES; + } else { + ret = (func)(inode, filp, cmd, arg); + } + } + + atomic_dec(&dev->ioctl_count); + + return ret; +} + +static int ffb_lock(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + DECLARE_WAITQUEUE(entry, current); + int ret = 0; + drm_lock_t lock; + + ret = copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)); + if (ret) + return -EFAULT; + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, current->pid, dev->lock.hw_lock->lock, + lock.flags); + + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = current->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; + current->policy |= SCHED_YIELD; + schedule(); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + + if (!ret && + (dev->last_context != lock.context)) + ffb_context_switch(dev, dev->last_context, lock.context); + + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + + return ret; +} + +int ffb_unlock(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_lock_t lock; + unsigned int old, new, prev, ctx; + int ret; + + ret = copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)); + if (ret) + return -EFAULT; + + if ((ctx = lock.context) == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lock.context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + + /* We no longer really hold it, but if we are the next + * agent to request it then we should just be able to + * take it immediately and not eat the ioctl. + */ + dev->lock.pid = 0; + { + __volatile__ unsigned int *plock = &dev->lock.hw_lock->lock; + + do { + old = *plock; + new = ctx; + prev = cmpxchg(plock, old, new); + } while (prev != old); + } + + wake_up_interruptible(&dev->lock.lock_queue); + + return 0; +} + +static void align_fb_mapping(struct vm_area_struct *vma) +{ + unsigned long j, alignment; + + j = vma->vm_end - vma->vm_start; + for (alignment = (4 * 1024 * 1024); alignment > PAGE_SIZE; alignment >>= 3) + if (j >= alignment) + break; + if (alignment > PAGE_SIZE) { + j = alignment; + alignment = j - (vma->vm_start & (j - 1)); + if (alignment != j) { + struct vm_area_struct *vmm = find_vma(current->mm,vma->vm_start); + + if (!vmm || vmm->vm_start >= vma->vm_end + alignment) { + vma->vm_start += alignment; + vma->vm_end += alignment; + } + } + } +} + +/* The problem here is, due to virtual cache aliasing, + * we must make sure the shared memory area lands in the + * same dcache line for both the kernel and all drm clients. + */ +static void align_shm_mapping(struct vm_area_struct *vma, unsigned long kvirt) +{ + kvirt &= PAGE_SIZE; + if ((vma->vm_start & PAGE_SIZE) != kvirt) { + struct vm_area_struct *vmm = find_vma(current->mm, vma->vm_start); + + if (!vmm || vmm->vm_start >= vma->vm_end + PAGE_SIZE) { + vma->vm_start += PAGE_SIZE; + vma->vm_end += PAGE_SIZE; + } + } +} + +extern struct vm_operations_struct drm_vm_ops; +extern struct vm_operations_struct drm_vm_shm_ops; + +static int ffb_mmap(struct file *filp, struct vm_area_struct *vma) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_map_t *map = NULL; + ffb_dev_priv_t *ffb_priv; + int i, minor; + + DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", + vma->vm_start, vma->vm_end, VM_OFFSET(vma)); + + minor = MINOR(filp->f_dentry->d_inode->i_rdev); + ffb_priv = NULL; + for (i = 0; i < ffb_dev_table_size; i++) { + ffb_priv = (ffb_dev_priv_t *) (ffb_dev_table[i] + 1); + if (ffb_priv->miscdev.minor == minor) + break; + } + if (i >= ffb_dev_table_size) + return -EINVAL; + + /* We don't support/need dma mappings, so... */ + if (!VM_OFFSET(vma)) + return -EINVAL; + + for (i = 0; i < dev->map_count; i++) { + unsigned long off; + + map = dev->maplist[i]; + + /* Ok, a little hack to make 32-bit apps work. */ + off = (map->offset & 0xffffffff); + if (off == VM_OFFSET(vma)) + break; + } + + if (i >= dev->map_count) + return -EINVAL; + + if (!map || + ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) + return -EPERM; + + if (map->size != (vma->vm_end - vma->vm_start)) + return -EINVAL; + + /* Set read-only attribute before mappings are created + * so it works for fb/reg maps too. + */ + if (map->flags & _DRM_READ_ONLY) + vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect( + __pte(pgprot_val(vma->vm_page_prot))))); + + switch (map->type) { + case _DRM_FRAME_BUFFER: + align_fb_mapping(vma); + /* FALLTHROUGH */ + + case _DRM_REGISTERS: + /* In order to handle 32-bit drm apps/xserver we + * play a trick. The mappings only really specify + * the 32-bit offset from the cards 64-bit base + * address, and we just add in the base here. + */ + vma->vm_flags |= VM_IO; + if (io_remap_page_range(vma->vm_start, + ffb_priv->card_phys_base + VM_OFFSET(vma), + vma->vm_end - vma->vm_start, + vma->vm_page_prot, 0)) + return -EAGAIN; + + vma->vm_ops = &drm_vm_ops; + break; + case _DRM_SHM: + align_shm_mapping(vma, (unsigned long)dev->lock.hw_lock); + vma->vm_ops = &drm_vm_shm_ops; + + /* Don't let this area swap. Change when + * DRM_KERNEL advisory is supported. + */ + vma->vm_flags |= VM_LOCKED; + break; + default: + return -EINVAL; /* This should never happen. */ + }; + + vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ + + vma->vm_file = filp; /* Needed for drm_vm_open() */ + drm_vm_open(vma); + return 0; +} + +module_init(ffb_init); +module_exit(ffb_cleanup); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/ffb_drv.h linux.ac/drivers/char/drm/ffb_drv.h --- linux.vanilla/drivers/char/drm/ffb_drv.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/drm/ffb_drv.h Sat Jun 10 21:50:43 2000 @@ -0,0 +1,276 @@ +/* $Id: ffb_drv.h,v 1.1 2000/06/01 04:24:39 davem Exp $ + * ffb_drv.h: Creator/Creator3D direct rendering driver. + * + * Copyright (C) 2000 David S. Miller (davem@redhat.com) + */ + +/* Auxilliary clips. */ +typedef struct { + volatile unsigned int min; + volatile unsigned int max; +} ffb_auxclip, *ffb_auxclipPtr; + +/* FFB register set. */ +typedef struct _ffb_fbc { + /* Next vertex registers, on the right we list which drawops + * use said register and the logical name the register has in + * that context. + */ /* DESCRIPTION DRAWOP(NAME) */ +/*0x00*/unsigned int pad1[3]; /* Reserved */ +/*0x0c*/volatile unsigned int alpha; /* ALPHA Transparency */ +/*0x10*/volatile unsigned int red; /* RED */ +/*0x14*/volatile unsigned int green; /* GREEN */ +/*0x18*/volatile unsigned int blue; /* BLUE */ +/*0x1c*/volatile unsigned int z; /* DEPTH */ +/*0x20*/volatile unsigned int y; /* Y triangle(DOYF) */ + /* aadot(DYF) */ + /* ddline(DYF) */ + /* aaline(DYF) */ +/*0x24*/volatile unsigned int x; /* X triangle(DOXF) */ + /* aadot(DXF) */ + /* ddline(DXF) */ + /* aaline(DXF) */ +/*0x28*/unsigned int pad2[2]; /* Reserved */ +/*0x30*/volatile unsigned int ryf; /* Y (alias to DOYF) ddline(RYF) */ + /* aaline(RYF) */ + /* triangle(RYF) */ +/*0x34*/volatile unsigned int rxf; /* X ddline(RXF) */ + /* aaline(RXF) */ + /* triangle(RXF) */ +/*0x38*/unsigned int pad3[2]; /* Reserved */ +/*0x40*/volatile unsigned int dmyf; /* Y (alias to DOYF) triangle(DMYF) */ +/*0x44*/volatile unsigned int dmxf; /* X triangle(DMXF) */ +/*0x48*/unsigned int pad4[2]; /* Reserved */ +/*0x50*/volatile unsigned int ebyi; /* Y (alias to RYI) polygon(EBYI) */ +/*0x54*/volatile unsigned int ebxi; /* X polygon(EBXI) */ +/*0x58*/unsigned int pad5[2]; /* Reserved */ +/*0x60*/volatile unsigned int by; /* Y brline(RYI) */ + /* fastfill(OP) */ + /* polygon(YI) */ + /* rectangle(YI) */ + /* bcopy(SRCY) */ + /* vscroll(SRCY) */ +/*0x64*/volatile unsigned int bx; /* X brline(RXI) */ + /* polygon(XI) */ + /* rectangle(XI) */ + /* bcopy(SRCX) */ + /* vscroll(SRCX) */ + /* fastfill(GO) */ +/*0x68*/volatile unsigned int dy; /* destination Y fastfill(DSTY) */ + /* bcopy(DSRY) */ + /* vscroll(DSRY) */ +/*0x6c*/volatile unsigned int dx; /* destination X fastfill(DSTX) */ + /* bcopy(DSTX) */ + /* vscroll(DSTX) */ +/*0x70*/volatile unsigned int bh; /* Y (alias to RYI) brline(DYI) */ + /* dot(DYI) */ + /* polygon(ETYI) */ + /* Height fastfill(H) */ + /* bcopy(H) */ + /* vscroll(H) */ + /* Y count fastfill(NY) */ +/*0x74*/volatile unsigned int bw; /* X dot(DXI) */ + /* brline(DXI) */ + /* polygon(ETXI) */ + /* fastfill(W) */ + /* bcopy(W) */ + /* vscroll(W) */ + /* fastfill(NX) */ +/*0x78*/unsigned int pad6[2]; /* Reserved */ +/*0x80*/unsigned int pad7[32]; /* Reserved */ + + /* Setup Unit's vertex state register */ +/*100*/ volatile unsigned int suvtx; +/*104*/ unsigned int pad8[63]; /* Reserved */ + + /* Frame Buffer Control Registers */ +/*200*/ volatile unsigned int ppc; /* Pixel Processor Control */ +/*204*/ volatile unsigned int wid; /* Current WID */ +/*208*/ volatile unsigned int fg; /* FG data */ +/*20c*/ volatile unsigned int bg; /* BG data */ +/*210*/ volatile unsigned int consty; /* Constant Y */ +/*214*/ volatile unsigned int constz; /* Constant Z */ +/*218*/ volatile unsigned int xclip; /* X Clip */ +/*21c*/ volatile unsigned int dcss; /* Depth Cue Scale Slope */ +/*220*/ volatile unsigned int vclipmin; /* Viewclip XY Min Bounds */ +/*224*/ volatile unsigned int vclipmax; /* Viewclip XY Max Bounds */ +/*228*/ volatile unsigned int vclipzmin; /* Viewclip Z Min Bounds */ +/*22c*/ volatile unsigned int vclipzmax; /* Viewclip Z Max Bounds */ +/*230*/ volatile unsigned int dcsf; /* Depth Cue Scale Front Bound */ +/*234*/ volatile unsigned int dcsb; /* Depth Cue Scale Back Bound */ +/*238*/ volatile unsigned int dczf; /* Depth Cue Z Front */ +/*23c*/ volatile unsigned int dczb; /* Depth Cue Z Back */ +/*240*/ unsigned int pad9; /* Reserved */ +/*244*/ volatile unsigned int blendc; /* Alpha Blend Control */ +/*248*/ volatile unsigned int blendc1; /* Alpha Blend Color 1 */ +/*24c*/ volatile unsigned int blendc2; /* Alpha Blend Color 2 */ +/*250*/ volatile unsigned int fbramitc; /* FB RAM Interleave Test Control */ +/*254*/ volatile unsigned int fbc; /* Frame Buffer Control */ +/*258*/ volatile unsigned int rop; /* Raster OPeration */ +/*25c*/ volatile unsigned int cmp; /* Frame Buffer Compare */ +/*260*/ volatile unsigned int matchab; /* Buffer AB Match Mask */ +/*264*/ volatile unsigned int matchc; /* Buffer C(YZ) Match Mask */ +/*268*/ volatile unsigned int magnab; /* Buffer AB Magnitude Mask */ +/*26c*/ volatile unsigned int magnc; /* Buffer C(YZ) Magnitude Mask */ +/*270*/ volatile unsigned int fbcfg0; /* Frame Buffer Config 0 */ +/*274*/ volatile unsigned int fbcfg1; /* Frame Buffer Config 1 */ +/*278*/ volatile unsigned int fbcfg2; /* Frame Buffer Config 2 */ +/*27c*/ volatile unsigned int fbcfg3; /* Frame Buffer Config 3 */ +/*280*/ volatile unsigned int ppcfg; /* Pixel Processor Config */ +/*284*/ volatile unsigned int pick; /* Picking Control */ +/*288*/ volatile unsigned int fillmode; /* FillMode */ +/*28c*/ volatile unsigned int fbramwac; /* FB RAM Write Address Control */ +/*290*/ volatile unsigned int pmask; /* RGB PlaneMask */ +/*294*/ volatile unsigned int xpmask; /* X PlaneMask */ +/*298*/ volatile unsigned int ypmask; /* Y PlaneMask */ +/*29c*/ volatile unsigned int zpmask; /* Z PlaneMask */ +/*2a0*/ ffb_auxclip auxclip[4]; /* Auxilliary Viewport Clip */ + + /* New 3dRAM III support regs */ +/*2c0*/ volatile unsigned int rawblend2; +/*2c4*/ volatile unsigned int rawpreblend; +/*2c8*/ volatile unsigned int rawstencil; +/*2cc*/ volatile unsigned int rawstencilctl; +/*2d0*/ volatile unsigned int threedram1; +/*2d4*/ volatile unsigned int threedram2; +/*2d8*/ volatile unsigned int passin; +/*2dc*/ volatile unsigned int rawclrdepth; +/*2e0*/ volatile unsigned int rawpmask; +/*2e4*/ volatile unsigned int rawcsrc; +/*2e8*/ volatile unsigned int rawmatch; +/*2ec*/ volatile unsigned int rawmagn; +/*2f0*/ volatile unsigned int rawropblend; +/*2f4*/ volatile unsigned int rawcmp; +/*2f8*/ volatile unsigned int rawwac; +/*2fc*/ volatile unsigned int fbramid; + +/*300*/ volatile unsigned int drawop; /* Draw OPeration */ +/*304*/ unsigned int pad10[2]; /* Reserved */ +/*30c*/ volatile unsigned int lpat; /* Line Pattern control */ +/*310*/ unsigned int pad11; /* Reserved */ +/*314*/ volatile unsigned int fontxy; /* XY Font coordinate */ +/*318*/ volatile unsigned int fontw; /* Font Width */ +/*31c*/ volatile unsigned int fontinc; /* Font Increment */ +/*320*/ volatile unsigned int font; /* Font bits */ +/*324*/ unsigned int pad12[3]; /* Reserved */ +/*330*/ volatile unsigned int blend2; +/*334*/ volatile unsigned int preblend; +/*338*/ volatile unsigned int stencil; +/*33c*/ volatile unsigned int stencilctl; + +/*340*/ unsigned int pad13[4]; /* Reserved */ +/*350*/ volatile unsigned int dcss1; /* Depth Cue Scale Slope 1 */ +/*354*/ volatile unsigned int dcss2; /* Depth Cue Scale Slope 2 */ +/*358*/ volatile unsigned int dcss3; /* Depth Cue Scale Slope 3 */ +/*35c*/ volatile unsigned int widpmask; +/*360*/ volatile unsigned int dcs2; +/*364*/ volatile unsigned int dcs3; +/*368*/ volatile unsigned int dcs4; +/*36c*/ unsigned int pad14; /* Reserved */ +/*370*/ volatile unsigned int dcd2; +/*374*/ volatile unsigned int dcd3; +/*378*/ volatile unsigned int dcd4; +/*37c*/ unsigned int pad15; /* Reserved */ +/*380*/ volatile unsigned int pattern[32]; /* area Pattern */ +/*400*/ unsigned int pad16[8]; /* Reserved */ +/*420*/ volatile unsigned int reset; /* chip RESET */ +/*424*/ unsigned int pad17[247]; /* Reserved */ +/*800*/ volatile unsigned int devid; /* Device ID */ +/*804*/ unsigned int pad18[63]; /* Reserved */ +/*900*/ volatile unsigned int ucsr; /* User Control & Status Register */ +/*904*/ unsigned int pad19[31]; /* Reserved */ +/*980*/ volatile unsigned int mer; /* Mode Enable Register */ +/*984*/ unsigned int pad20[1439]; /* Reserved */ +} ffb_fbc, *ffb_fbcPtr; + +struct ffb_hw_context { + int is_2d_only; + + unsigned int ppc; + unsigned int wid; + unsigned int fg; + unsigned int bg; + unsigned int consty; + unsigned int constz; + unsigned int xclip; + unsigned int dcss; + unsigned int vclipmin; + unsigned int vclipmax; + unsigned int vclipzmin; + unsigned int vclipzmax; + unsigned int dcsf; + unsigned int dcsb; + unsigned int dczf; + unsigned int dczb; + unsigned int blendc; + unsigned int blendc1; + unsigned int blendc2; + unsigned int fbc; + unsigned int rop; + unsigned int cmp; + unsigned int matchab; + unsigned int matchc; + unsigned int magnab; + unsigned int magnc; + unsigned int pmask; + unsigned int xpmask; + unsigned int ypmask; + unsigned int zpmask; + unsigned int auxclip0min; + unsigned int auxclip0max; + unsigned int auxclip1min; + unsigned int auxclip1max; + unsigned int auxclip2min; + unsigned int auxclip2max; + unsigned int auxclip3min; + unsigned int auxclip3max; + unsigned int drawop; + unsigned int lpat; + unsigned int fontxy; + unsigned int fontw; + unsigned int fontinc; + unsigned int area_pattern[32]; + unsigned int ucsr; + unsigned int stencil; + unsigned int stencilctl; + unsigned int dcss1; + unsigned int dcss2; + unsigned int dcss3; + unsigned int dcs2; + unsigned int dcs3; + unsigned int dcs4; + unsigned int dcd2; + unsigned int dcd3; + unsigned int dcd4; + unsigned int mer; +}; + +#define FFB_MAX_CTXS 32 + +enum ffb_chip_type { + ffb1_prototype = 0, /* Early pre-FCS FFB */ + ffb1_standard, /* First FCS FFB, 100Mhz UPA, 66MHz gclk */ + ffb1_speedsort, /* Second FCS FFB, 100Mhz UPA, 75MHz gclk */ + ffb2_prototype, /* Early pre-FCS vertical FFB2 */ + ffb2_vertical, /* First FCS FFB2/vertical, 100Mhz UPA, 100MHZ gclk, + 75(SingleBuffer)/83(DoubleBuffer) MHz fclk */ + ffb2_vertical_plus, /* Second FCS FFB2/vertical, same timings */ + ffb2_horizontal, /* First FCS FFB2/horizontal, same timings as FFB2/vert */ + ffb2_horizontal_plus, /* Second FCS FFB2/horizontal, same timings */ + afb_m3, /* FCS Elite3D, 3 float chips */ + afb_m6 /* FCS Elite3D, 6 float chips */ +}; + +typedef struct ffb_dev_priv { + /* Misc software state. */ + int prom_node; + enum ffb_chip_type ffb_type; + u64 card_phys_base; + struct miscdevice miscdev; + + /* Controller registers. */ + ffb_fbcPtr regs; + + /* Context table. */ + struct ffb_hw_context *hw_state[FFB_MAX_CTXS]; +} ffb_dev_priv_t; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/fops.c linux.ac/drivers/char/drm/fops.c --- linux.vanilla/drivers/char/drm/fops.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/drm/fops.c Sat Jun 10 21:50:43 2000 @@ -92,7 +92,8 @@ DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n", current->pid, dev->device, dev->open_count); - if (_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) + if (dev->lock.hw_lock != NULL + && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && dev->lock.pid == current->pid) { DRM_ERROR("Process %d dead, freeing lock for context %d\n", current->pid, @@ -216,7 +217,7 @@ if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO); #else /* Parameter added in 2.3.21 */ - if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN); + kill_fasync(&dev->buf_async, SIGIO, POLL_IN); #endif DRM_DEBUG("waking\n"); wake_up_interruptible(&dev->buf_readers); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/drm/init.c linux.ac/drivers/char/drm/init.c --- linux.vanilla/drivers/char/drm/init.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/drm/init.c Sat Jun 10 21:50:43 2000 @@ -104,5 +104,9 @@ #if defined(__i386__) if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */ #endif +#if defined(__sparc__) && !defined(__sparc_v9__) + if (1) + return 0; /* No cmpxchg before v9 sparc. */ +#endif return 1; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/epca.c linux.ac/drivers/char/epca.c --- linux.vanilla/drivers/char/epca.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/epca.c Sat May 27 15:29:11 2000 @@ -4007,6 +4007,9 @@ int board_idx, info_idx = ent->driver_data; unsigned long addr; + if (pci_enable_device(pdev)) + return -EIO; + board_num++; board_idx = board_num + num_cards; if (board_idx >= MAXBOARDS) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/joystick/joy-pci.c linux.ac/drivers/char/joystick/joy-pci.c --- linux.vanilla/drivers/char/joystick/joy-pci.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/joystick/joy-pci.c Sat May 27 15:27:29 2000 @@ -243,7 +243,8 @@ for (i = 0; js_pci_data[i].vendor; i++) for (j = 0; (pci_p = pci_find_device(js_pci_data[i].vendor, js_pci_data[i].model, pci_p)); j++) - js_pci_port = js_pci_probe(js_pci_port, i, j, pci_p, js_pci_data + i); + if (pci_enable_device(pci_p) == 0) + js_pci_port = js_pci_probe(js_pci_port, i, j, pci_p, js_pci_data + i); if (!js_pci_port) { #ifdef MODULE diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/msp3400.c linux.ac/drivers/char/msp3400.c --- linux.vanilla/drivers/char/msp3400.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/msp3400.c Sun Jun 4 21:51:40 2000 @@ -1,7 +1,7 @@ /* * programming the msp34* sound processor family * - * (c) 1997,1998 Gerd Knorr + * (c) 1997-2000 Gerd Knorr * * what works and what doesn't: * @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef CONFIG_SMP #include @@ -57,16 +58,14 @@ #include "audiochip.h" -#define WAIT_QUEUE wait_queue_head_t - /* sound mixer stuff */ -#if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE) +#if 0 /* defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE) */ # define REGISTER_MIXER 1 #endif /* Addresses to scan */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {0x40,0x44,I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {0x40,0x40,I2C_CLIENT_END}; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; @@ -102,7 +101,7 @@ /* thread */ struct task_struct *thread; - WAIT_QUEUE wq; + wait_queue_head_t wq; struct semaphore *notify; int active,restart,rmmod; @@ -1370,7 +1369,7 @@ if (simple == -1) { /* default mode */ - msp->simple = 0; + msp->simple = (((rev2>>8)&0xff) == 0) ? 0 : 1; } else { /* use insmod option */ msp->simple = simple; @@ -1632,22 +1631,19 @@ /* ----------------------------------------------------------------------- */ -#ifdef MODULE -int init_module(void) -#else -int msp3400c_init(void) -#endif +int msp3400_init_module(void) { i2c_add_driver(&driver); return 0; } -#ifdef MODULE -void cleanup_module(void) +void msp3400_cleanup_module(void) { i2c_del_driver(&driver); } -#endif + +module_init(msp3400_init_module); +module_exit(msp3400_cleanup_module); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/mxser.c linux.ac/drivers/char/mxser.c --- linux.vanilla/drivers/char/mxser.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/mxser.c Sat May 27 15:26:52 2000 @@ -618,6 +618,8 @@ mxser_pcibrds[b].device_id, pdev); if (!pdev) break; + if (pci_enable_device(pdev)) + continue; b++; hwconf.pdev = pdev; printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/n_hdlc.c linux.ac/drivers/char/n_hdlc.c --- linux.vanilla/drivers/char/n_hdlc.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/n_hdlc.c Sat May 27 22:00:30 2000 @@ -663,7 +663,7 @@ #if LINUX_VERSION_CODE < VERSION(2,3,0) kill_fasync (n_hdlc->tty->fasync, SIGIO); #else - kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN); + kill_fasync(&n_hdlc->tty->fasync, SIGIO, POLL_IN); #endif } /* end of n_hdlc_tty_receive() */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/n_tty.c linux.ac/drivers/char/n_tty.c --- linux.vanilla/drivers/char/n_tty.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/n_tty.c Sat May 27 22:00:30 2000 @@ -630,8 +630,7 @@ put_tty_queue(c, tty); tty->canon_head = tty->read_head; tty->canon_data++; - if (tty->fasync) - kill_fasync(tty->fasync, SIGIO, POLL_IN); + kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); return; @@ -735,8 +734,7 @@ } if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { - if (tty->fasync) - kill_fasync(tty->fasync, SIGIO, POLL_IN); + kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/pc110pad.c linux.ac/drivers/char/pc110pad.c --- linux.vanilla/drivers/char/pc110pad.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/pc110pad.c Sat May 27 22:00:30 2000 @@ -83,8 +83,7 @@ static void wake_readers(void) { wake_up_interruptible(&queue); - if(asyncptr) - kill_fasync(asyncptr, SIGIO, POLL_IN); + kill_fasync(&asyncptr, SIGIO, POLL_IN); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/pc_keyb.c linux.ac/drivers/char/pc_keyb.c --- linux.vanilla/drivers/char/pc_keyb.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/pc_keyb.c Sat May 27 22:00:30 2000 @@ -415,8 +415,7 @@ head = (head + 1) & (AUX_BUF_SIZE-1); if (head != queue->tail) { queue->head = head; - if (queue->fasync) - kill_fasync(queue->fasync, SIGIO, POLL_IN); + kill_fasync(&queue->fasync, SIGIO, POLL_IN); wake_up_interruptible(&queue->proc_list); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/pcmcia/serial_cb.c linux.ac/drivers/char/pcmcia/serial_cb.c --- linux.vanilla/drivers/char/pcmcia/serial_cb.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/pcmcia/serial_cb.c Sat May 27 15:25:59 2000 @@ -92,6 +92,7 @@ if (loc->bus != LOC_PCI) goto err_out; pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn); if (!pdev) goto err_out; + if (pci_enable_device(pdev)) goto err_out; printk(KERN_INFO "serial_attach(bus %d, fn %d)\n", pdev->bus->number, pdev->devfn); io = pci_resource_start (pdev, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/ppdev.c linux.ac/drivers/char/ppdev.c --- linux.vanilla/drivers/char/ppdev.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/ppdev.c Tue Jun 6 13:38:42 2000 @@ -83,6 +83,63 @@ /* ROUND_UP macro from fs/select.c */ #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) +struct pp_port_list_struct { + struct parport *port; + struct pp_port_list_struct *next; +}; +static struct pp_port_list_struct *pp_port_list; +static DECLARE_MUTEX(pp_port_list_lock); + +/* pp_attach and pp_detach are for keeping a list of currently + * available ports, held under a mutex. We do this rather than + * using parport_enumerate because it stops a load of races. + */ + +static void pp_attach (struct parport *port) +{ + struct pp_port_list_struct *add; + + add = kmalloc (sizeof (struct pp_port_list_struct), GFP_KERNEL); + if (!add) { + printk (KERN_WARNING CHRDEV ": memory squeeze\n"); + return; + } + + add->next = pp_port_list; + down (&pp_port_list_lock); + pp_port_list = add; + up (&pp_port_list_lock); +} + +static void pp_detach (struct parport *port) +{ + struct pp_port_list_struct *del; + + down (&pp_port_list_lock); + del = pp_port_list; + if (del->port == port) + pp_port_list = del->next; + else { + struct pp_port_list_struct *prev; + do { + prev = del; + del = del->next; + } while (del && del->port != port); + if (del) + prev->next = del->next; + } + up (&pp_port_list_lock); + + if (del) + kfree (del); +} + +static struct parport_driver ppdev_driver = { + name: CHRDEV, + attach: pp_attach, + detach: pp_detach +}; + static inline void pp_enable_irq (struct pp_struct *pp) { struct parport *port = pp->pdev->port; @@ -216,7 +273,7 @@ static int register_device (int minor, struct pp_struct *pp) { - struct parport * port; + struct pp_port_list_struct *ports; struct pardevice * pdev = NULL; char *name; int fl; @@ -226,20 +283,24 @@ return -ENOMEM; sprintf (name, CHRDEV "%x", minor); - port = parport_enumerate (); /* FIXME: use attach/detach */ - while (port && port->number != minor) - port = port->next; + down (&pp_port_list_lock); + ports = pp_port_list; + while (ports && ports->port->number != minor) + ports = ports->next; + if (ports->port) { + fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + pdev = parport_register_device (ports->port, name, NULL, + NULL, pp_irq, fl, pp); + } + up (&pp_port_list_lock); - if (!port) { + if (!ports->port) { printk (KERN_WARNING "%s: no associated port!\n", name); kfree (name); return -ENXIO; } - fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device (port, name, NULL, NULL, pp_irq, fl, - pp); if (!pdev) { printk (KERN_WARNING "%s: failed to register device!\n", name); @@ -596,6 +657,10 @@ static int __init ppdev_init (void) { + if (parport_register_driver (&ppdev_driver)) { + printk (KERN_WARNING CHRDEV ": unable to register driver\n"); + return -EIO; + } if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { printk (KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); @@ -616,6 +681,7 @@ /* Clean up all parport stuff */ devfs_unregister (devfs_handle); devfs_unregister_chrdev (PP_MAJOR, CHRDEV); + parport_unregister_driver (&ppdev_driver); } module_init(ppdev_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/qpmouse.c linux.ac/drivers/char/qpmouse.c --- linux.vanilla/drivers/char/qpmouse.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/qpmouse.c Sat May 27 22:00:30 2000 @@ -133,8 +133,7 @@ head &= QP_BUF_SIZE-1; } queue->head = head; - if (queue->fasync) - kill_fasync(queue->fasync, SIGIO, POLL_IN); + kill_fasync(&queue->fasync, SIGIO, POLL_IN); wake_up_interruptible(&queue->proc_list); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/radio-aimslab.c linux.ac/drivers/char/radio-aimslab.c --- linux.vanilla/drivers/char/radio-aimslab.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/radio-aimslab.c Tue Jun 6 12:41:05 2000 @@ -355,7 +355,7 @@ return -EINVAL; request_region(io, 2, "rtrack"); - printk(KERN_INFO "AIMSlab Radiotrack/radioreveal card driver.\n"); + printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/rio/rio_linux.c linux.ac/drivers/char/rio/rio_linux.c --- linux.vanilla/drivers/char/rio/rio_linux.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/rio/rio_linux.c Sat May 27 15:31:06 2000 @@ -1149,6 +1149,7 @@ while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { + if (pci_enable_device(pdev)) continue; #else for (i=0;i< RIO_NBOARDS;i++) { if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, @@ -1234,6 +1235,7 @@ while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { + if (pci_enable_device(pdev)) continue; #else for (i=0;i< RIO_NBOARDS;i++) { if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/rocket.c linux.ac/drivers/char/rocket.c --- linux.vanilla/drivers/char/rocket.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/rocket.c Sat May 27 15:26:22 2000 @@ -1957,7 +1957,10 @@ if (!dev) return 0; - rcktpt_io_addr[i] = dev->resource[0].start; + if (pci_enable_device(dev)) + return 0; + + rcktpt_io_addr[i] = pci_resource_start (dev, 0); switch(dev->device) { case PCI_DEVICE_ID_RP4QUAD: str = "Quadcable"; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/rtc.c linux.ac/drivers/char/rtc.c --- linux.vanilla/drivers/char/rtc.c Thu May 25 17:38:01 2000 +++ linux.ac/drivers/char/rtc.c Sat May 27 22:00:30 2000 @@ -179,8 +179,7 @@ /* Now do the rest of the actions */ wake_up_interruptible(&rtc_wait); - if (rtc_async_queue) - kill_fasync (rtc_async_queue, SIGIO, POLL_IN); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); } #endif @@ -781,8 +780,7 @@ /* Now we have new data */ wake_up_interruptible(&rtc_wait); - if (rtc_async_queue) - kill_fasync (rtc_async_queue, SIGIO, POLL_IN); + kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); } #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/serial.c linux.ac/drivers/char/serial.c --- linux.vanilla/drivers/char/serial.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/serial.c Sat Jun 10 22:06:45 2000 @@ -43,13 +43,16 @@ * few races on freeing buffers too. * Alan Modra * + * 5/00: Support for the RSA-DV II/S card added. + * Kiyokazu SUTO + * * This module exports the following rs232 io functions: * * int rs_init(void); */ -static char *serial_version = "4.93"; -static char *serial_revdate = "2000-03-20"; +static char *serial_version = "5.01"; +static char *serial_revdate = "2000-05-29"; /* * Serial driver configuration section. Here are the various options: @@ -134,6 +137,8 @@ #endif #endif +#define CONFIG_SERIAL_RSA + #define RS_STROBE_TIME (10*HZ) #define RS_ISR_PASS_LIMIT 256 @@ -277,9 +282,20 @@ UART_STARTECH }, { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, + { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, { 0, 0} }; +#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) + +#define PORT_RSA_MAX 4 +static int probe_rsa[PORT_RSA_MAX]; +static int force_rsa[PORT_RSA_MAX]; + +MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +#endif /* CONFIG_SERIAL_RSA */ + static struct serial_state rs_table[RS_TABLE_SIZE] = { SERIAL_PORT_DFNS /* Defined in serial.h */ }; @@ -293,11 +309,8 @@ static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; static int serial_pci_board_idx = 0; #endif -#ifndef PCI_BASE_ADDRESS -#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start) -#define PCI_BASE_REGION_SIZE(dev, r) ((dev)->resource[r].end - \ - (dev)->resource[r].start) -#define IS_PCI_REGION_IOPORT(dev, r) ((dev)->resource[r].flags & \ +#ifndef IS_PCI_REGION_IOPORT +#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ IORESOURCE_IO) #endif #ifndef PCI_IRQ_RESOURCE @@ -314,7 +327,8 @@ #define ACTIVATE_FUNC(dev) (dev->activate) #define DEACTIVATE_FUNC(dev) (dev->deactivate) #endif - + +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) static struct tty_struct *serial_table[NR_PORTS]; static struct termios *serial_termios[NR_PORTS]; @@ -996,6 +1010,9 @@ tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); wake_up_interruptible(&tty->write_wait); +#ifdef SERIAL_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif } } @@ -1090,6 +1107,50 @@ IRQ_timeout[irq] = timeout ? timeout : 1; } +#ifdef CONFIG_SERIAL_RSA +/* Attempts to turn on the RSA FIFO. Returns zero on failure */ +static int enable_rsa(struct async_struct *info) +{ + unsigned char mode; + int result; + unsigned long flags; + + save_flags(flags); cli(); + mode = serial_inp(info, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + + if (!result) { + serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_inp(info, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + } + + restore_flags(flags); + return result; +} + +/* Attempts to turn off the RSA FIFO. Returns zero on failure */ +static int disable_rsa(struct async_struct *info) +{ + unsigned char mode; + int result; + unsigned long flags; + + save_flags(flags); cli(); + mode = serial_inp(info, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + + if (!result) { + serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_inp(info, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + } + + restore_flags(flags); + return result; +} +#endif /* CONFIG_SERIAL_RSA */ + static int startup(struct async_struct * info) { unsigned long flags; @@ -1127,7 +1188,7 @@ printk("starting up ttys%d (irq %d)...", info->line, state->irq); #endif - if (uart_config[info->state->type].flags & UART_STARTECH) { + if (uart_config[state->type].flags & UART_STARTECH) { /* Wake up UART */ serial_outp(info, UART_LCR, 0xBF); serial_outp(info, UART_EFR, UART_EFR_ECB); @@ -1145,7 +1206,7 @@ /* * For a XR16C850, we need to set the trigger levels */ - if (info->state->type == PORT_16850) { + if (state->type == PORT_16850) { serial_outp(info, UART_FCTR, UART_FCTR_TRGD | UART_FCTR_RX); serial_outp(info, UART_TRG, UART_TRG_96); @@ -1156,12 +1217,12 @@ serial_outp(info, UART_LCR, 0); } - if (info->state->type == PORT_16750) { + if (state->type == PORT_16750) { /* Wake up UART */ serial_outp(info, UART_IER, 0); } - if (info->state->type == PORT_16C950) { + if (state->type == PORT_16C950) { /* Wake up and initialize UART */ info->ACR = 0; serial_outp(info, UART_LCR, 0xBF); @@ -1174,6 +1235,20 @@ serial_outp(info, UART_LCR, 0); } +#ifdef CONFIG_SERIAL_RSA + /* + * If this is an RSA port, see if we can kick it up to the + * higher speed clock. + */ + if (state->type == PORT_RSA) { + if (state->baud_base != SERIAL_RSA_BAUD_BASE && + enable_rsa(info)) + state->baud_base = SERIAL_RSA_BAUD_BASE; + if (state->baud_base == SERIAL_RSA_BAUD_BASE) + serial_outp(info, UART_RSA_FRR, 0); + } +#endif + /* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) @@ -1199,7 +1274,8 @@ * if it is, then bail out, because there's likely no UART * here. */ - if (serial_inp(info, UART_LSR) == 0xff) { + if (!(info->flags & ASYNC_BUGGY_UART) && + (serial_inp(info, UART_LSR) == 0xff)) { printk("LSR safety check engaged!\n"); if (capable(CAP_SYS_ADMIN)) { if (info->tty) @@ -1425,6 +1501,17 @@ UART_FCR_CLEAR_XMIT)); serial_outp(info, UART_FCR, 0); +#ifdef CONFIG_SERIAL_RSA + /* + * Reset the RSA board back to 115kbps compat mode. + */ + if ((state->type == PORT_RSA) && + (state->baud_base == SERIAL_RSA_BAUD_BASE && + disable_rsa(info))) + state->baud_base = SERIAL_RSA_BAUD_BASE_LO; +#endif + + (void)serial_in(info, UART_RX); /* read data port to reset things */ if (info->tty) @@ -1522,6 +1609,12 @@ baud = tty_get_baud_rate(info->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ +#ifdef CONFIG_SERIAL_RSA + if ((info->state->type == PORT_RSA) && + (info->state->baud_base != SERIAL_RSA_BAUD_BASE) && + enable_rsa(info)) + info->state->baud_base = SERIAL_RSA_BAUD_BASE; +#endif baud_base = info->state->baud_base; if (info->state->type == PORT_16C950) { if (baud <= baud_base) @@ -1583,6 +1676,10 @@ if (uart_config[info->state->type].flags & UART_USE_FIFO) { if ((info->state->baud_base / quot) < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; +#ifdef CONFIG_SERIAL_RSA + else if (info->state->type == PORT_RSA) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; +#endif else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; } @@ -1810,6 +1907,9 @@ info->xmit.head = info->xmit.tail = 0; restore_flags(flags); wake_up_interruptible(&tty->write_wait); +#ifdef SERIAL_HAVE_POLL_WAIT + wake_up_interruptible(&tty->poll_wait); +#endif if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); @@ -1912,6 +2012,10 @@ tmp.type = state->type; tmp.line = state->line; tmp.port = state->port; + if (HIGH_BITS_OFFSET) + tmp.port_high = state->port >> HIGH_BITS_OFFSET; + else + tmp.port_high = 0; tmp.irq = state->irq; tmp.flags = state->flags; tmp.xmit_fifo_size = state->xmit_fifo_size; @@ -1933,14 +2037,19 @@ struct serial_state old_state, *state; unsigned int i,change_irq,change_port; int retval = 0; + unsigned long new_port; if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; state = info->state; old_state = *state; - + + new_port = new_serial.port; + if (HIGH_BITS_OFFSET) + new_port += new_serial.port_high << HIGH_BITS_OFFSET; + change_irq = new_serial.irq != state->irq; - change_port = (new_serial.port != state->port) || + change_port = (new_port != ((int) state->port)) || (new_serial.hub6 != state->hub6); if (!capable(CAP_SYS_ADMIN)) { @@ -1978,7 +2087,7 @@ if (new_serial.type) { for (i = 0 ; i < NR_PORTS; i++) if ((state != &rs_table[i]) && - (rs_table[i].port == new_serial.port) && + (rs_table[i].port == new_port) && rs_table[i].type) return -EADDRINUSE; } @@ -2005,8 +2114,14 @@ info->xmit_fifo_size = state->xmit_fifo_size = new_serial.xmit_fifo_size; - if ((state->type != PORT_UNKNOWN) && state->port) + if ((state->type != PORT_UNKNOWN) && state->port) { +#ifdef CONFIG_SERIAL_RSA + if (old_state.type == PORT_RSA) + release_region(state->port + UART_RSA_BASE, 16); + else +#endif release_region(state->port,8); + } state->type = new_serial.type; if (change_port || change_irq) { /* @@ -2015,15 +2130,22 @@ */ shutdown(info); state->irq = new_serial.irq; - info->port = state->port = new_serial.port; + info->port = state->port = new_port; info->hub6 = state->hub6 = new_serial.hub6; if (info->hub6) info->io_type = state->io_type = SERIAL_IO_HUB6; else if (info->io_type == SERIAL_IO_HUB6) info->io_type = state->io_type = SERIAL_IO_PORT; } - if ((state->type != PORT_UNKNOWN) && state->port) - request_region(state->port,8,"serial(set)"); + if ((state->type != PORT_UNKNOWN) && state->port) { +#ifdef CONFIG_SERIAL_RSA + if (state->type == PORT_RSA) + request_region(state->port + UART_RSA_BASE, + 16, "serial_rsa(set)"); + else +#endif + request_region(state->port,8,"serial(set)"); + } check_and_exit: @@ -2462,6 +2584,9 @@ /* note the counters on entry */ cprev = info->state->icount; restore_flags(flags); + /* Force modem status interrupts on */ + info->IER |= UART_IER_MSI; + serial_out(info, UART_IER, info->IER); while (1) { interruptible_sleep_on(&info->delta_msr_wait); /* see if a signal did it */ @@ -3348,6 +3473,16 @@ * LSR register (which serial_icr_read does) */ if (state->type == PORT_16550A) { + /* + * EFR [4] must be set else this test fails + * + * This shouldn't be necessary, but Mike Hudson + * (Exoray@isys.ca) claims that it's needed for 952 + * dual UART's (which are not recommended for new designs). + */ + serial_out(info, UART_LCR, 0xBF); + serial_out(info, UART_EFR, 0x10); + serial_out(info, UART_LCR, 0x00); /* Check for Oxford Semiconductor 16C950 */ scratch = serial_icr_read(info, UART_ID1); scratch2 = serial_icr_read(info, UART_ID2); @@ -3434,7 +3569,8 @@ save_flags(flags); cli(); - if (!state->iomem_base) { + if (!(state->flags & ASYNC_BUGGY_UART) && + !state->iomem_base) { /* * Do a simple existence test first; if we fail this, * there's no point trying anything else. @@ -3459,8 +3595,9 @@ serial_outp(info, UART_IER, scratch); if (scratch2 || scratch3 != 0x0F) { #ifdef SERIAL_DEBUG_AUTOCONF - printk("serial: ttyS%d: simple autoconfig failed\n", - state->line); + printk("serial: ttyS%d: simple autoconfig failed " + "(%02x, %02x)\n", state->line, + scratch2, scratch3); #endif restore_flags(flags); return; /* We failed; there's nothing here */ @@ -3545,6 +3682,25 @@ } serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); } +#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) + if (state->type == PORT_16550A) { + int i; + + for (i = 0 ; i < PORT_RSA_MAX ; ++i) { + if (!probe_rsa[i] && !force_rsa[i]) + break; + if (((probe_rsa[i] != state->port) || + check_region(state->port + UART_RSA_BASE, 16)) && + (force_rsa[i] != state->port)) + continue; + if (!enable_rsa(info)) + continue; + state->type = PORT_RSA; + state->baud_base = SERIAL_RSA_BAUD_BASE; + break; + } + } +#endif serial_outp(info, UART_LCR, save_lcr); if (state->type == PORT_16450) { scratch = serial_in(info, UART_SCR); @@ -3564,12 +3720,23 @@ return; } - if (info->port) - request_region(info->port,8,"serial(auto)"); + if (info->port) { +#ifdef CONFIG_SERIAL_RSA + if (state->type == PORT_RSA) + request_region(info->port + UART_RSA_BASE, 16, + "serial_rsa(auto)"); + else +#endif + request_region(info->port,8,"serial(auto)"); + } /* * Reset the UART. */ +#ifdef CONFIG_SERIAL_RSA + if (state->type == PORT_RSA) + serial_outp(info, UART_RSA_FRR, 0); +#endif serial_outp(info, UART_MCR, save_mcr); serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | @@ -3614,7 +3781,7 @@ static _INLINE_ int get_pci_port(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *state, + struct serial_struct *req, int idx) { unsigned long port; @@ -3626,24 +3793,28 @@ base_idx += idx; if (board->flags & SPCI_FL_REGION_SZ_CAP) { - max_port = PCI_BASE_REGION_SIZE(dev, base_idx) / 8; + max_port = pci_resource_len(dev, base_idx) / 8; if (idx >= max_port) return 1; } - port = PCI_BASE_ADDRESS(dev, base_idx) + board->first_uart_offset; + port = pci_resource_start(dev, base_idx) + board->first_uart_offset; if ((board->flags & SPCI_FL_BASE_TABLE) == 0) port += idx * (board->uart_offset ? board->uart_offset : 8); if (IS_PCI_REGION_IOPORT(dev, base_idx)) { - state->port = port; + req->port = port; + if (HIGH_BITS_OFFSET) + req->port_high = port >> HIGH_BITS_OFFSET; + else + req->port_high = 0; return 0; } - state->io_type = SERIAL_IO_MEM; - state->iomem_base = ioremap(port, board->uart_offset); - state->iomem_reg_shift = board->reg_shift; - state->port = 0; + req->io_type = SERIAL_IO_MEM; + req->iomem_base = ioremap(port, board->uart_offset); + req->iomem_reg_shift = board->reg_shift; + req->port = 0; return 0; } @@ -3670,23 +3841,28 @@ struct pci_board *board) { int k, line; - struct serial_struct fake_state; + struct serial_struct serial_req; int base_baud; if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { - printk("SERIAL: PNP device '"); + printk("serial: PNP device '"); printk_pnp_dev_id(board->vendor, board->device); printk("' prepare failed\n"); return; } if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { - printk("SERIAL: PNP device '"); + printk("serial: PNP device '"); printk_pnp_dev_id(board->vendor, board->device); printk("' activate failed\n"); return; } + if (!(board->flags & SPCI_FL_ISPNP) && pci_enable_device(dev)) { + printk("serial: PCI device enable failed\n"); + return; + } + /* * Run the initialization function, if any */ @@ -3710,18 +3886,18 @@ base_baud = board->base_baud; if (!base_baud) base_baud = BASE_BAUD; - memset(&fake_state, 0, sizeof(fake_state)); + memset(&serial_req, 0, sizeof(serial_req)); for (k=0; k < board->num_ports; k++) { - fake_state.irq = get_pci_irq(dev, board, k); - if (get_pci_port(dev, board, &fake_state, k)) + serial_req.irq = get_pci_irq(dev, board, k); + if (get_pci_port(dev, board, &serial_req, k)) break; - fake_state.flags = ASYNC_SKIP_TEST; + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; #ifdef SERIAL_DEBUG_PCI printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", - fake_state.port, fake_state.irq, fake_state.io_type); + serial_req.port, serial_req.irq, serial_req.io_type); #endif - line = register_serial(&fake_state); + line = register_serial(&serial_req); if (line < 0) break; rs_table[line].baud_base = base_baud; @@ -3742,28 +3918,45 @@ #endif pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) { - u8 data, *p, scratch; + u8 data, *p, irq_config; + int pci_config; + irq_config = 0x41; + pci_config = PCI_COMMAND_MEMORY; + if (dev->vendor == PCI_VENDOR_ID_PANACOM) + irq_config = 0x43; + if ((dev->vendor == PCI_VENDOR_ID_PLX) && + (dev->device == PCI_VENDOR_ID_PLX_ROMULUS)) { + /* + * As the megawolf cards have the int pins active + * high, and have 2 UART chips, both ints must be + * enabled on the 9050. Also, the UARTS are set in + * 16450 mode by default, so we have to enable the + * 16C950 'enhanced' mode so that we can use the deep + * FIFOs + */ + irq_config = 0x5b; + pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + } + pci_read_config_byte(dev, PCI_COMMAND, &data); if (enable) pci_write_config_byte(dev, PCI_COMMAND, - data | PCI_COMMAND_MEMORY); + data | pci_config); /* enable/disable interrupts */ - p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80); - scratch = 0x41; - if (dev->vendor == PCI_VENDOR_ID_PANACOM) - scratch = 0x43; - writel(enable ? scratch : 0x00, (unsigned long)p + 0x4c); + p = ioremap(pci_resource_start(dev, 0), 0x80); + writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c); iounmap(p); if (!enable) pci_write_config_byte(dev, PCI_COMMAND, - data & ~PCI_COMMAND_MEMORY); + data & ~pci_config); return 0; } + /* * SIIG serial cards have an PCI interface chip which also controls * the UART clocking frequency. Each UART can be clocked independently @@ -3796,7 +3989,7 @@ if (!enable) return 0; - p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); switch (dev->device & 0xfff8) { case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ @@ -3841,6 +4034,36 @@ return 0; } +/* Added for EKF Intel i960 serial boards */ +static int +#ifndef MODULE +__init +#endif +pci_inteli960ni_fn(struct pci_dev *dev, + struct pci_board *board, + int enable) +{ + unsigned long oldval; + + if (!(board->subdevice & 0x1000)) + return(-1); + + if (!enable) /* is there something to deinit? */ + return(0); + +#ifdef SERIAL_DEBUG_PCI + printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n", + (unsigned long) board->subdevice); +#endif + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, (void*) &oldval); + if (oldval == 0x00001000L) { /* RESET value */ + printk(KERN_DEBUG "Local i960 firmware missing"); + return(-1); + } + return(0); +} + /* * This is the configuration table for all of the PCI serial boards @@ -3851,8 +4074,9 @@ * Vendor ID, Device ID, * Subvendor ID, Subdevice ID, * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, - * Offset to get to next UART's registers - * Register shift to use for memory-mapped I/O + * Offset to get to next UART's registers, + * Register shift to use for memory-mapped I/O, + * Initialization function, first UART offset */ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, PCI_SUBVENDOR_ID_CONNECT_TECH, @@ -3942,6 +4166,10 @@ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, + /* VScom SPCOM800, from sl@s.pl */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE2, 8, 921600 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_KEYSPAN, PCI_SUBDEVICE_ID_KEYSPAN_SX2, @@ -3979,6 +4207,12 @@ PCI_SUBVENDOR_ID_CHASE_PCIRAS, PCI_SUBDEVICE_ID_CHASE_PCIRAS8, SPCI_FL_BASE2, 8, 460800 }, + /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ + /* (Exoray@isys.ca) */ + { PCI_VENDOR_ID_PLX, PCI_VENDOR_ID_PLX_ROMULUS, + 0x10b5, 0x106a, + SPCI_FL_BASE2, 4, 921600, + 0x20, 2, pci_plx9050_fn, 0x03 }, { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE1, 4, 115200 }, @@ -4164,7 +4398,7 @@ PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, 0, 0, pci_siig20x_fn }, - /* Computone devices submitted by Doug McNash dougm@computone.com */ + /* Computone devices submitted by Doug McNash dmcnash@computone.com */ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, SPCI_FL_BASE0, 4, 921600, /* IOMEM */ @@ -4198,6 +4432,15 @@ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, PCI_ANY_ID, PCI_ANY_ID, SPCI_FL_BASE0, 4, 921600 }, + /* EKF addition for i960 Boards form EKF with serial port */ + { PCI_VENDOR_ID_INTEL, 0x1960, + 0xE4BF, PCI_ANY_ID, + SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ + 8<<2, 2, pci_inteli960ni_fn, 0x10000}, + /* RAStel 2 port modem, gerg@moreton.com.au */ + { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* * Untested PCI modems, sent in from various folks... */ @@ -4221,12 +4464,12 @@ }; /* - * Given a complete unknown PCI device, try to use some hueristics to + * Given a complete unknown PCI device, try to use some heuristics to * guess what the configuration might be, based on the pitiful PCI * serial specs. Returns 0 on success, 1 on failure. */ -static int _INLINE_ serial_guess_board(struct pci_dev *dev, - struct pci_board *board) +static int _INLINE_ serial_pci_guess_board(struct pci_dev *dev, + struct pci_board *board) { int num_iomem = 0, num_port = 0, first_port = -1; int i; @@ -4281,13 +4524,6 @@ printk(KERN_DEBUG "Entered probe_serial_pci()\n"); #endif - if (!pcibios_present()) { -#ifdef SERIAL_DEBUG_PCI - printk(KERN_DEBUG "Leaving probe_serial_pci() (no pcibios)\n"); -#endif - return; - } - pci_for_each_dev(dev) { for (board = pci_boards; board->vendor; board++) { if (board->vendor != (unsigned short) PCI_ANY_ID && @@ -4305,7 +4541,7 @@ break; } - if (board->vendor == 0 && serial_guess_board(dev, board)) + if (board->vendor == 0 && serial_pci_guess_board(dev, board)) continue; start_pci_pnp_board(dev, board); @@ -4321,58 +4557,280 @@ #ifdef ENABLE_SERIAL_PNP -static struct pci_board pnp_devices[] __initdata = { - /* Motorola VoiceSURFR 56K Modem */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, +struct pnp_board { + unsigned short vendor; + unsigned short device; +}; + +static struct pnp_board pnp_devices[] __initdata = { + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, + /* Anchor Datacomm BV */ + /* SXPro 144 External Data Fax Modem Plug & Play */ + { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) }, + /* SXPro 288 External Data Fax Modem Plug & Play */ + { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) }, /* Rockwell 56K ACF II Fax+Data+Voice Modem */ - { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_NO_SHIRQ | SPCI_FL_PNPDEFAULT, - 1, 115200 }, + { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) }, /* AZT3005 PnP SOUND DEVICE */ - { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) }, /* Best Data Products Inc. Smart One 336F PnP Modem */ - { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, + /* Boca Research */ + /* Boca Complete Ofc Communicator 14.4 Data-FAX */ + { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, /* Boca Research 33,600 ACF Modem */ - { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) }, + /* Boca 33.6 Kbps Internal FD34FSVD */ + { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) }, + /* Boca 33.6 Kbps Internal FD34FSVD */ + { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, + /* Best Data Products Inc. Smart One 336F PnP Modem */ + { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, + /* Computer Peripherals Inc */ + /* EuroViVa CommCenter-33.6 SP PnP */ + { ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) }, + /* Creative Labs */ + /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ + { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) }, + /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ + { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) }, + /* Creative */ /* Creative Modem Blaster Flash56 DI5601-1 */ - { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) }, /* Creative Modem Blaster V.90 DI5660 */ - { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) }, + /* FUJITSU */ + /* Fujitsu 33600 PnP-I2 R Plug & Play */ + { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) }, + /* Fujitsu FMV-FX431 Plug & Play */ + { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) }, + /* Fujitsu 33600 PnP-I4 R Plug & Play */ + { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) }, + /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */ + { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) }, + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) }, + /* Hayes */ + /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) }, + /* Hayes Optima 336 V.34 + FAX + Voice PnP */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) }, + /* Hayes Optima 336B V.34 + FAX + Voice PnP */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) }, + /* Hayes Accura 56K Ext Fax Modem PnP */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) }, + /* Hayes Accura 56K Ext Fax Modem PnP */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) }, + /* Hayes Accura 56K Fax Modem PnP */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) }, + /* Hayes 288, V.34 + FAX */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) }, + /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */ + { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) }, + /* IBM */ + /* IBM Thinkpad 701 Internal Modem Voice */ + { ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) }, + /* Intertex */ + /* Intertex 28k8 33k6 Voice EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) }, + /* Intertex 33k6 56k Voice EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) }, + /* Intertex 28k8 33k6 Voice SP EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) }, + /* Intertex 33k6 56k Voice SP EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) }, + /* Intertex 28k8 33k6 Voice SP INT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) }, + /* Intertex 28k8 33k6 Voice SP EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) }, + /* Intertex 33k6 56k Voice SP EXT PnP */ + { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) }, + /* Kortex International */ + /* KORTEX 28800 Externe PnP */ + { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) }, + /* KXPro 33.6 Vocal ASVD PnP */ + { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) }, + /* Lasat */ + /* LASAT Internet 33600 PnP */ + { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) }, + /* Lasat Safire 560 PnP */ + { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) }, + /* Lasat Safire 336 PnP */ + { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) }, + /* Microcom, Inc. */ + /* Microcom TravelPorte FAST V.34 Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) }, + /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) }, + /* Microcom DeskPorte FAST EP 28.8 Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) }, + /* Microcom DeskPorte 28.8P Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) }, + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, + /* Microcom DeskPorte 28.8S Internal Plug & Play */ + { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) }, + /* Motorola */ + /* Motorola BitSURFR Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) }, + /* Motorola TA210 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) }, + /* Motorola HMTA 200 (ISDN) Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) }, + /* Motorola BitSURFR Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) }, + /* Motorola Lifestyle 28.8 Internal */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) }, + /* Motorola V.3400 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) }, + /* Motorola Lifestyle 28.8 V.34 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) }, + /* Motorola Power 28.8 V.34 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) }, + /* Motorola ModemSURFR External 28.8 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) }, + /* Motorola Premier 33.6 Desktop Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) }, + /* Motorola VoiceSURFR 56K External PnP */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) }, + /* Motorola ModemSURFR 56K External PnP */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) }, + /* Motorola ModemSURFR 56K Internal PnP */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) }, + /* Motorola ModemSURFR Internal 28.8 Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) }, + /* Motorola Premier 33.6 Internal Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) }, + /* Motorola OnlineSURFR 28.8 Internal Plug & Play */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) }, + /* Motorola VoiceSURFR 56K Internal PnP */ + { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) }, + /* Com 1 */ + /* Deskline K56 Phone System PnP */ + { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) }, + /* PC Rider K56 Phone System PnP */ + { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) }, /* Pace 56 Voice Internal Plug & Play Modem */ - { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* SupraExpress 28.8 Data/Fax PnP modem */ - { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* US Robotics Sporster 33600 Modem */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* U.S. Robotics 56K FAX INT */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* Viking 56K FAX INT */ - { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - - /* These ID's are taken from M$ documentation */ - /* Compaq 14400 Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - /* Compaq 2400/9600 Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) }, + /* Generic */ /* Generic standard PC COM port */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, /* Generic 16550A-compatible COM port */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501), 0, 0, - SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, + /* Compaq 14400 Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) }, + /* Compaq 2400/9600 Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) }, + /* Dial-Up Networking Serial Cable between 2 PCs */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) }, + /* Dial-Up Networking Parallel Cable between 2 PCs */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) }, + /* Standard 9600 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) }, + /* Standard 14400 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) }, + /* Standard 28800 bps Modem*/ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) }, + /* Standard Modem*/ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) }, + /* Standard 9600 bps Modem*/ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) }, + /* Standard 14400 bps Modem*/ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) }, + /* Standard 28800 bps Modem*/ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) }, + /* Standard Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) }, + /* Standard 9600 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) }, + /* Standard 14400 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) }, + /* Standard 28800 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) }, + /* Standard Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) }, + /* Standard 9600 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) }, + /* Standard 14400 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) }, + /* Standard 28800 bps Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) }, + /* Standard Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) }, + /* Standard PCMCIA Card Modem */ + { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) }, + /* Rockwell */ + /* Modular Technology */ + /* Rockwell 33.6 DPF Internal PnP */ + /* Modular Technology 33.6 Internal PnP */ + { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) }, + /* Kortex International */ + /* KORTEX 14400 Externe PnP */ + { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) }, + /* Viking Components, Inc */ + /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */ + { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) }, + /* Rockwell */ + /* British Telecom */ + /* Modular Technology */ + /* Rockwell 33.6 DPF External PnP */ + /* BT Prologue 33.6 External PnP */ + /* Modular Technology 33.6 External PnP */ + { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) }, + /* Viking 56K FAX INT */ + { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) }, + /* SupraExpress 28.8 Data/Fax PnP modem */ + { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) }, + /* Phoebe Micro */ + /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ + { ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) }, + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, + /* 3Com Corp. */ + /* Gateway Telepath IIvi 33.6 */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) }, + /* Sportster Vi 14.4 PnP FAX Voicemail */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) }, + /* U.S. Robotics 33.6K Voice INT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) }, + /* U.S. Robotics 33.6K Voice EXT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) }, + /* U.S. Robotics 33.6K Voice INT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) }, + /* U.S. Robotics 56K Voice INT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) }, + /* U.S. Robotics 56K Voice EXT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) }, + /* U.S. Robotics 56K FAX INT */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) }, + /* U.S. Robotics 56K Voice INT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) }, + /* U.S. Robotics 56K Voice EXT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) }, + /* U.S. Robotics 56K Voice INT PnP */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) }, + /* U.S. Robotics 56K Message */ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) }, + /* U.S. Robotics 56K FAX EXT PnP*/ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) }, + /* U.S. Robotics 56K FAX INT PnP*/ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) }, + /* U.S. Robotics 56K Voice EXT PnP*/ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) }, + /* U.S. Robotics 56K Voice INT PnP*/ + { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) }, { 0, } }; @@ -4394,10 +4852,80 @@ irq->map = map; } +static char *modem_names[] __initdata = { + "MODEM", "Modem", "modem", "FAX", "Fax", "fax", + "56K", "56k", "K56", "33.6", "28.8", "14.4", + "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", + "33600", "28800", "14400", "V.90", "V.34", "V.32", 0 +}; + +static int __init check_name(char *name) +{ + char **tmp = modem_names; + + while (*tmp) { + if (strstr(name, *tmp)) + return 1; + tmp++; + } + return 0; +} + +static int inline check_compatible_id(struct pci_dev *dev) +{ + int i; + for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++) + if ((dev->vendor_compatible[i] == + ISAPNP_VENDOR('P', 'N', 'P')) && + (swab16(dev->device_compatible[i]) >= 0xc000) && + (swab16(dev->device_compatible[i]) <= 0xdfff)) + return 0; + return 1; +} + +/* + * Given a complete unknown ISA PnP device, try to use some heuristics to + * detect modems. Currently use such heuristic set: + * - dev->name or dev->bus->name must contain "modem" substring; + * - device must have only one IO region (8 byte long) with base adress + * 0x2e8, 0x3e8, 0x2f8 or 0x3f8. + * + * Such detection looks very ugly, but can detect at least some of numerous + * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] + * table. + */ +static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev, + struct pci_board *board) +{ + struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; + struct isapnp_resources *resa; + + if (!(check_name(dev->name) || check_name(dev->bus->name)) && + !(check_compatible_id(dev))) + return 1; + + if (!res || res->next) + return 1; + + for (resa = res->alt; resa; resa = resa->alt) { + struct isapnp_port *port; + for (port = res->port; port; port = port->next) + if ((port->size == 8) && + ((port->min == 0x2f8) || + (port->min == 0x3f8) || + (port->min == 0x2e8) || + (port->min == 0x3e8))) + return 0; + } + + return 1; +} + static void __init probe_serial_pnp(void) { struct pci_dev *dev = NULL; - struct pci_board *board; + struct pnp_board *pnp_board; + struct pci_board board; #ifdef SERIAL_DEBUG_PNP printk("Entered probe_serial_pnp()\n"); @@ -4409,13 +4937,35 @@ return; } - for (board = pnp_devices; board->vendor; board++) { - while ((dev = isapnp_find_dev(NULL, board->vendor, - board->device, dev))) { - if (board->flags & SPCI_FL_NO_SHIRQ) - avoid_irq_share(dev); - start_pci_pnp_board(dev, board); - } + isapnp_for_each_dev(dev) { + if (dev->active) + continue; + + memset(&board, 0, sizeof(board)); + board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT; + board.num_ports = 1; + board.base_baud = 115200; + + for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++) + if ((dev->vendor == pnp_board->vendor) && + (dev->device == pnp_board->device)) + break; + + if (pnp_board->vendor) { + board.vendor = pnp_board->vendor; + board.device = pnp_board->device; + /* Special case that's more efficient to hardcode */ + if ((board.vendor == ISAPNP_VENDOR('A', 'K', 'Y') && + board.device == ISAPNP_DEVICE(0x1021))) + board.flags |= SPCI_FL_NO_SHIRQ; + } else { + if (serial_pnp_guess_board(dev, &board)) + continue; + } + + if (board.flags & SPCI_FL_NO_SHIRQ) + avoid_irq_share(dev); + start_pci_pnp_board(dev, &board); } #ifdef SERIAL_DEBUG_PNP @@ -4477,7 +5027,7 @@ #if (LINUX_VERSION_CODE > 0x20100) serial_driver.driver_name = "serial"; #endif -#ifdef CONFIG_DEVFS_FS +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) serial_driver.name = "tts/%d"; #else serial_driver.name = "ttyS"; @@ -4525,7 +5075,7 @@ * major number and the subtype code. */ callout_driver = serial_driver; -#ifdef CONFIG_DEVFS_FS +#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) callout_driver.name = "cua/%d"; #else callout_driver.name = "cua"; @@ -4615,14 +5165,25 @@ unsigned long flags; struct serial_state *state; struct async_struct *info; + unsigned long port; + + port = req->port; + if (HIGH_BITS_OFFSET) + port += req->port_high << HIGH_BITS_OFFSET; save_flags(flags); cli(); for (i = 0; i < NR_PORTS; i++) { - if ((rs_table[i].port == req->port) && + if ((rs_table[i].port == port) && (rs_table[i].iomem_base == req->iomem_base)) break; } if (i == NR_PORTS) { + for (i = 4; i < NR_PORTS; i++) + if ((rs_table[i].type == PORT_UNKNOWN) && + (rs_table[i].count == 0)) + break; + } + if (i == NR_PORTS) { for (i = 0; i < NR_PORTS; i++) if ((rs_table[i].type == PORT_UNKNOWN) && (rs_table[i].count == 0)) @@ -4636,11 +5197,11 @@ if (rs_table[i].count) { restore_flags(flags); printk("Couldn't configure serial #%d (port=%ld,irq=%d): " - "device already open\n", i, req->port, req->irq); + "device already open\n", i, port, req->irq); return -1; } state->irq = req->irq; - state->port = req->port; + state->port = port; state->flags = req->flags; state->io_type = req->io_type; state->iomem_base = req->iomem_base; @@ -4648,7 +5209,7 @@ if (req->baud_base) state->baud_base = req->baud_base; if ((info = state->info) != NULL) { - info->port = req->port; + info->port = port; info->flags = req->flags; info->io_type = req->io_type; info->iomem_base = req->iomem_base; @@ -4721,10 +5282,10 @@ timer_table[RS_TIMER].expires = 0; remove_bh(SERIAL_BH); if ((e1 = tty_unregister_driver(&serial_driver))) - printk("SERIAL: failed to unregister serial driver (%d)\n", + printk("serial: failed to unregister serial driver (%d)\n", e1); if ((e2 = tty_unregister_driver(&callout_driver))) - printk("SERIAL: failed to unregister callout driver (%d)\n", + printk("serial: failed to unregister callout driver (%d)\n", e2); restore_flags(flags); @@ -4733,8 +5294,15 @@ rs_table[i].info = NULL; kfree_s(info, sizeof(struct async_struct)); } - if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) - release_region(rs_table[i].port, 8); + if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { +#ifdef CONFIG_SERIAL_RSA + if (rs_table[i].type == PORT_RSA) + release_region(rs_table[i].port + + UART_RSA_BASE, 16); + else +#endif + release_region(rs_table[i].port, 8); + } #if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) if (rs_table[i].iomem_base) iounmap(rs_table[i].iomem_base); @@ -4881,9 +5449,6 @@ int cflag = CREAD | HUPCL | CLOCAL; int quot = 0; char *s; -#if defined(CONFIG_KDB) - extern int kdb_port; -#endif if (options) { baud = simple_strtoul(options, NULL, 10); @@ -4987,14 +5552,6 @@ if (serial_in(info, UART_LSR) == 0xff) return -1; -#if defined(CONFIG_KDB) - /* - * Remember I/O port for kdb - */ - if (kdb_port == 0 ) - kdb_port = ser->port; -#endif /* CONFIG_KDB */ - return 0; } @@ -5023,6 +5580,6 @@ /* Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" + compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" End: */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/stallion.c linux.ac/drivers/char/stallion.c --- linux.vanilla/drivers/char/stallion.c Thu May 25 17:38:00 2000 +++ linux.ac/drivers/char/stallion.c Sun Jun 4 22:02:49 2000 @@ -2795,8 +2795,8 @@ */ #if DEBUG printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__, - devp->resource[0].start, devp->resource[1].start, - devp->resource[2].start, devp->resource[3].start, devp->irq); + pci_resource_start(devp, 0), pci_resource_start(devp, 1), + pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq); #endif /* @@ -2805,22 +2805,16 @@ */ switch (brdtype) { case BRD_ECHPCI: - brdp->ioaddr2 = (devp->resource[0].start & - PCI_BASE_ADDRESS_IO_MASK); - brdp->ioaddr1 = (devp->resource[1].start & - PCI_BASE_ADDRESS_IO_MASK); + brdp->ioaddr2 = pci_resource_start(devp, 0); + brdp->ioaddr1 = pci_resource_start(devp, 1); break; case BRD_ECH64PCI: - brdp->ioaddr2 = (devp->resource[2].start & - PCI_BASE_ADDRESS_IO_MASK); - brdp->ioaddr1 = (devp->resource[1].start & - PCI_BASE_ADDRESS_IO_MASK); + brdp->ioaddr2 = pci_resource_start(devp, 2); + brdp->ioaddr1 = pci_resource_start(devp, 1); break; case BRD_EASYIOPCI: - brdp->ioaddr1 = (devp->resource[2].start & - PCI_BASE_ADDRESS_IO_MASK); - brdp->ioaddr2 = (devp->resource[1].start & - PCI_BASE_ADDRESS_IO_MASK); + brdp->ioaddr1 = pci_resource_start(devp, 2); + brdp->ioaddr2 = pci_resource_start(devp, 1); break; default: printk("STALLION: unknown PCI board type=%d\n", brdtype); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/stradis.c linux.ac/drivers/char/stradis.c --- linux.vanilla/drivers/char/stradis.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/stradis.c Sun Jun 4 21:54:58 2000 @@ -2055,10 +2055,13 @@ saa->id = dev->device; saa->irq = dev->irq; saa->video_dev.minor = -1; - saa->saa7146_adr = dev->resource[0].start; + saa->saa7146_adr = pci_resource_start(dev, 0); pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision); - saa->saa7146_mem = ioremap(((saa->saa7146_adr) & - PCI_BASE_ADDRESS_MEM_MASK), 0x200); + + saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200); + if (!saa->saa7146_mem) + return -EIO; + memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus)); memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); sprintf(saa->i2c.name, "stradis%d", num); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/tty_io.c linux.ac/drivers/char/tty_io.c --- linux.vanilla/drivers/char/tty_io.c Thu May 25 17:37:59 2000 +++ linux.ac/drivers/char/tty_io.c Sat May 27 22:00:30 2000 @@ -1427,49 +1427,6 @@ return 0; } -/* - * fasync_helper() is used by some character device drivers (mainly mice) - * to set up the fasync queue. It returns negative on error, 0 if it did - * no changes and positive if it added/deleted the entry. - */ -int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) -{ - struct fasync_struct *fa, **fp; - unsigned long flags; - - for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { - if (fa->fa_file == filp) - break; - } - - if (on) { - if (fa) { - fa->fa_fd = fd; - return 0; - } - fa = (struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); - if (!fa) - return -ENOMEM; - fa->magic = FASYNC_MAGIC; - fa->fa_file = filp; - fa->fa_fd = fd; - save_flags(flags); - cli(); - fa->fa_next = *fapp; - *fapp = fa; - restore_flags(flags); - return 1; - } - if (!fa) - return 0; - save_flags(flags); - cli(); - *fp = fa->fa_next; - restore_flags(flags); - kfree(fa); - return 1; -} - static int tty_fasync(int fd, struct file * filp, int on) { struct tty_struct * tty; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/tuner.c linux.ac/drivers/char/tuner.c --- linux.vanilla/drivers/char/tuner.c Thu May 25 17:38:02 2000 +++ linux.ac/drivers/char/tuner.c Mon Jun 5 20:23:28 2000 @@ -10,6 +10,7 @@ #include #include #include +#include #include "tuner.h" #include "audiochip.h" @@ -428,22 +429,19 @@ EXPORT_NO_SYMBOLS; -#ifdef MODULE -int init_module(void) -#else -int i2c_tuner_init(void) -#endif +int tuner_init_module(void) { i2c_add_driver(&driver); return 0; } -#ifdef MODULE -void cleanup_module(void) +void tuner_cleanup_module(void) { i2c_del_driver(&driver); } -#endif + +module_init(tuner_init_module); +module_exit(tuner_cleanup_module); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/tvmixer.c linux.ac/drivers/char/tvmixer.c --- linux.vanilla/drivers/char/tvmixer.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/char/tvmixer.c Mon Jun 5 19:54:47 2000 @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "audiochip.h" + +#define DEV_MAX 4 + +static int debug = 0; +static int devnr = -1; + +MODULE_PARM(debug,"i"); +MODULE_PARM(devnr,"i"); + +/* ----------------------------------------------------------------------- */ + +struct TVMIXER { + struct i2c_client *dev; + int minor; + int count; +}; + +static struct TVMIXER devices[DEV_MAX]; + +static int tvmixer_adapters(struct i2c_adapter *adap); +static int tvmixer_clients(struct i2c_client *client); + +static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int tvmixer_open(struct inode *inode, struct file *file); +static int tvmixer_release(struct inode *inode, struct file *file); +static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin); + + +static struct i2c_driver driver = { + "tv card mixer driver", + 42 /* I2C_DRIVERID_FIXME */, + I2C_DF_DUMMY, + tvmixer_adapters, + tvmixer_clients, +}; + +static struct file_operations tvmixer_fops = { + llseek: tvmixer_llseek, + ioctl: tvmixer_ioctl, + open: tvmixer_open, + release: tvmixer_release, +}; + +/* ----------------------------------------------------------------------- */ + +static int mix_to_v4l(int i) +{ + int r; + + r = ((i & 0xff) * 65536 + 50) / 100; + if (r > 65535) r = 65535; + if (r < 0) r = 0; + return r; +} + +static int v4l_to_mix(int i) +{ + int r; + + r = (i * 100 + 32768) / 65536; + if (r > 100) r = 100; + if (r < 0) r = 0; + return r | (r << 8); +} + +static int v4l_to_mix2(int l, int r) +{ + r = (r * 100 + 32768) / 65536; + if (r > 100) r = 100; + if (r < 0) r = 0; + l = (l * 100 + 32768) / 65536; + if (l > 100) l = 100; + if (l < 0) l = 0; + return (r << 8) | l; +} + +static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct video_audio va; + int left,right,ret,val = 0; + struct TVMIXER *mix = file->private_data; + struct i2c_client *client = mix->dev; + + if (NULL == client) + return -ENODEV; + + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strncpy(info.id, "tv card", sizeof(info.id)); + strncpy(info.name, client->name, sizeof(info.name)); + info.modify_counter = 42 /* FIXME */; + 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, "tv card", sizeof(info.id)); + strncpy(info.name, client->name, 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 (_SIOC_DIR(cmd) & _SIOC_WRITE) + if (get_user(val, (int *)arg)) + return -EFAULT; + + /* read state */ + memset(&va,0,sizeof(va)); + client->driver->command(client,VIDIOCGAUDIO,&va); + + switch (cmd) { + case MIXER_READ(SOUND_MIXER_RECMASK): + case MIXER_READ(SOUND_MIXER_CAPS): + case MIXER_READ(SOUND_MIXER_RECSRC): + case MIXER_WRITE(SOUND_MIXER_RECSRC): + ret = 0; + break; + + case MIXER_READ(SOUND_MIXER_STEREODEVS): + ret = SOUND_MASK_VOLUME; + break; + case MIXER_READ(SOUND_MIXER_DEVMASK): + ret = SOUND_MASK_VOLUME; + if (va.flags & VIDEO_AUDIO_BASS) + ret |= SOUND_MASK_BASS; + if (va.flags & VIDEO_AUDIO_TREBLE) + ret |= SOUND_MASK_TREBLE; + break; + + case MIXER_WRITE(SOUND_MIXER_VOLUME): + left = mix_to_v4l(val); + right = mix_to_v4l(val >> 8); + va.volume = MAX(left,right); + va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1); + va.balance = (leftdriver->command(client,VIDIOCSAUDIO,&va); + client->driver->command(client,VIDIOCGAUDIO,&va); + /* fall throuth */ + case MIXER_READ(SOUND_MIXER_VOLUME): + left = (MIN(65536 - va.balance,32768) * + va.volume) / 32768; + right = (MIN(va.balance,32768) * + va.volume) / 32768; + ret = v4l_to_mix2(left,right); + break; + + case MIXER_WRITE(SOUND_MIXER_BASS): + va.bass = mix_to_v4l(val); + client->driver->command(client,VIDIOCSAUDIO,&va); + client->driver->command(client,VIDIOCGAUDIO,&va); + /* fall throuth */ + case MIXER_READ(SOUND_MIXER_BASS): + ret = v4l_to_mix(va.bass); + break; + + case MIXER_WRITE(SOUND_MIXER_TREBLE): + va.treble = mix_to_v4l(val); + client->driver->command(client,VIDIOCSAUDIO,&va); + client->driver->command(client,VIDIOCGAUDIO,&va); + /* fall throuth */ + case MIXER_READ(SOUND_MIXER_TREBLE): + ret = v4l_to_mix(va.treble); + break; + + default: + return -EINVAL; + } + if (put_user(ret, (int *)arg)) + return -EFAULT; + return 0; +} + +static int tvmixer_open(struct inode *inode, struct file *file) +{ + int i, minor = MINOR(inode->i_rdev); + struct TVMIXER *mix = NULL; + struct i2c_client *client = NULL; + + for (i = 0; i < DEV_MAX; i++) { + if (devices[i].minor == minor) { + mix = devices+i; + client = mix->dev; + break; + } + } + + if (NULL == client) + return -ENODEV; + + /* lock bttv in memory while the mixer is in use */ + file->private_data = mix; + if (client->adapter->inc_use) + client->adapter->inc_use(client->adapter); + MOD_INC_USE_COUNT; + return 0; +} + +static int tvmixer_release(struct inode *inode, struct file *file) +{ + struct TVMIXER *mix = file->private_data; + struct i2c_client *client = mix->dev; + + if (NULL == client) + return -ENODEV; + + if (client->adapter->dec_use) + client->adapter->dec_use(client->adapter); + MOD_DEC_USE_COUNT; + return 0; +} + +static loff_t tvmixer_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +/* ----------------------------------------------------------------------- */ + +static int tvmixer_adapters(struct i2c_adapter *adap) +{ + return 0; +} + +static int tvmixer_clients(struct i2c_client *client) +{ + struct video_audio va; + int i,minor; + + /* TV card ??? */ + if (client->adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) { + if (debug) + printk("tvmixer: %s is not a tv card\n", + client->adapter->name); + return -1; + } + printk("tvmixer: debug: %s\n",client->name); + + /* unregister ?? */ + for (i = 0; i < DEV_MAX; i++) { + if (devices[i].dev == client) { + /* unregister */ + unregister_sound_mixer(devices[i].minor); + devices[i].dev = NULL; + devices[i].minor = -1; + printk("tvmixer: %s unregistered (#1)\n",client->name); + return 0; + } + } + + /* look for a free slot */ + for (i = 0; i < DEV_MAX; i++) + if (NULL == devices[i].dev) + break; + if (i == DEV_MAX) { + printk(KERN_WARNING "tvmixer: DEV_MAX too small\n"); + return -1; + } + + /* audio chip with mixer ??? */ + if (NULL == client->driver->command) { + if (debug) + printk("tvmixer: %s: driver->command is NULL\n", + client->driver->name); + return -1; + } + memset(&va,0,sizeof(va)); + if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) { + if (debug) + printk("tvmixer: %s: VIDIOCGAUDIO failed\n", + client->name); + return -1; + } + if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) { + if (debug) + printk("tvmixer: %s: has no volume control\n", + client->name); + return -1; + } + + /* everything is fine, register */ + if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) { + printk(KERN_ERR "tvmixer: cannot allocate mixer device\n"); + return -1; + } + + devices[i].minor = minor; + devices[i].count = 0; + devices[i].dev = client; + printk("tvmixer: %s (%s) registered with minor %d\n", + client->name,client->adapter->name,minor); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +int tvmixer_init_module(void) +{ + int i; + + for (i = 0; i < DEV_MAX; i++) + devices[i].minor = -1; + i2c_add_driver(&driver); + return 0; +} + +void tvmixer_cleanup_module(void) +{ + int i; + + i2c_del_driver(&driver); + for (i = 0; i < DEV_MAX; i++) { + if (devices[i].minor != -1) { + unregister_sound_mixer(devices[i].minor); + printk("tvmixer: %s unregistered (#2)\n", + devices[i].dev->name); + } + } +} + +module_init(tvmixer_init_module); +module_exit(tvmixer_cleanup_module); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/videodev.c linux.ac/drivers/char/videodev.c --- linux.vanilla/drivers/char/videodev.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/char/videodev.c Thu Jun 8 16:59:52 2000 @@ -63,7 +63,7 @@ #ifdef CONFIG_VIDEO_BT848 -extern int i2c_tuner_init(struct video_init *); +extern int tuner_init_module(struct video_init *); #endif #ifdef CONFIG_VIDEO_BWQCAM extern int init_bw_qcams(struct video_init *); @@ -80,7 +80,7 @@ static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_BT848 - {"i2c-tuner", i2c_tuner_init}, + {"i2c-tuner", tuner_init_module}, #endif #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/wdt_pci.c linux.ac/drivers/char/wdt_pci.c --- linux.vanilla/drivers/char/wdt_pci.c Thu May 25 17:38:03 2000 +++ linux.ac/drivers/char/wdt_pci.c Fri May 26 14:31:59 2000 @@ -28,6 +28,7 @@ * Parameterized timeout * JP Nollmann : Added support for PCI wdt501p * Alan Cox : Split ISA and PCI cards into two drivers + * Jeff Garzik : PCI cleanups */ #include @@ -53,6 +54,8 @@ #include +#define PFX "wdt_pci: " + /* * Until Access I/O gets their application for a PCI vendor ID approved, * I don't think that it's appropriate to move these constants into the @@ -487,12 +490,86 @@ 0 }; -#ifdef MODULE -#define wdtpci_init init_module +static int __init wdtpci_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + static int dev_count = 0; + + dev_count++; + if (dev_count > 1) { + printk (KERN_ERR PFX + "this driver only supports 1 device\n"); + return -ENODEV; + } + + irq = dev->irq; + io = pci_resource_start (dev, 2); + printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " + "(Interrupt %d)\n", io, irq); + + if (pci_enable_device (dev)) + goto err_out; + + if (request_region (io, 16, "wdt-pci") == NULL) { + printk (KERN_ERR PFX "I/O %d is not free.\n", io); + goto err_out; + } + + if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ, + "wdt-pci", &wdtpci_miscdev)) { + printk (KERN_ERR PFX "IRQ %d is not free.\n", irq); + goto err_out_free_res; + } + + misc_register (&wdtpci_miscdev); + +#ifdef CONFIG_WDT_501 + misc_register (&temp_miscdev); +#endif + + register_reboot_notifier (&wdtpci_notifier); + + return 0; + +err_out_free_res: + release_region (io, 16); +err_out: + return -EIO; +} + + +static void __exit wdtpci_remove_one (struct pci_dev *pdev) +{ + /* here we assume only one device will ever have + * been picked up and registered by probe function */ + unregister_reboot_notifier(&wdtpci_notifier); +#ifdef CONFIG_WDT_501_PCI + misc_deregister(&temp_miscdev); +#endif + misc_deregister(&wdtpci_miscdev); + free_irq(irq, &wdtpci_miscdev); + release_region(io, 16); +} + + +static struct pci_device_id wdtpci_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_ACCESSIO, PCI_DEVICE_ID_WDG_CSM, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); + + +static struct pci_driver wdtpci_driver = { + name: "wdt-pci", + id_table: wdtpci_pci_tbl, + probe: wdtpci_init_one, + remove: wdtpci_remove_one, +}; + /** - * cleanup_module: + * wdtpci_cleanup: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload @@ -501,18 +578,11 @@ * module in 60 seconds or reboot. */ -void cleanup_module(void) +static void __exit wdtpci_cleanup(void) { - misc_deregister(&wdtpci_miscdev); -#ifdef CONFIG_WDT_501_PCI - misc_deregister(&temp_miscdev); -#endif - unregister_reboot_notifier(&wdtpci_notifier); - release_region(io,16); - free_irq(irq, &wdtpci_miscdev); + pci_unregister_driver (&wdtpci_driver); } -#endif /** * wdtpci_init: @@ -522,37 +592,16 @@ * The open() function will actually kick the board off. */ -int __init wdtpci_init(void) +static int __init wdtpci_init(void) { - struct pci_dev *dev = NULL; - - if (pci_present()) - { - while ((dev = pci_find_device(PCI_VENDOR_ID_ACCESSIO, - PCI_DEVICE_ID_WDG_CSM, dev))) { - /* See if we can do this device */ - irq = dev->irq; - io = dev->resource[2].start; - printk("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " - "(Interrupt %d)\n", io, irq); - } - } - if(request_region(io, 16, "wdt-pci")==NULL) - { - printk(KERN_ERR "I/O %d is not free.\n", io); - return -EIO; - } - if(request_irq(irq, wdtpci_interrupt, SA_INTERRUPT|SA_SHIRQ, "wdt-pci", &wdtpci_miscdev)) - { - printk(KERN_ERR "IRQ %d is not free.\n", irq); - release_region(io, 16); - return -EIO; - } - misc_register(&wdtpci_miscdev); -#ifdef CONFIG_WDT_501 - misc_register(&temp_miscdev); -#endif - register_reboot_notifier(&wdtpci_notifier); + int rc = pci_register_driver (&wdtpci_driver); + + if (rc < 1) + return -ENODEV; + return 0; } + +module_init(wdtpci_init); +module_exit(wdtpci_cleanup); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/README linux.ac/drivers/i2o/README --- linux.vanilla/drivers/i2o/README Thu May 25 17:38:17 2000 +++ linux.ac/drivers/i2o/README Fri May 26 14:21:11 2000 @@ -92,7 +92,6 @@ Lan: o Performance tuning o Test Fibre Channel code -o Fix lan_set_mc_list() Tape: o Anyone seen anything implementing this ? diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_config.c linux.ac/drivers/i2o/i2o_config.c --- linux.vanilla/drivers/i2o/i2o_config.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/i2o/i2o_config.c Sat May 27 22:00:30 2000 @@ -161,8 +161,7 @@ // printk(KERN_INFO "File %p w/id %d has %d events\n", // inf->fp, inf->q_id, inf->q_len); - if(inf->fasync) - kill_fasync(inf->fasync, SIGIO, POLL_IN); + kill_fasync(&inf->fasync, SIGIO, POLL_IN); } return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_core.c linux.ac/drivers/i2o/i2o_core.c --- linux.vanilla/drivers/i2o/i2o_core.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/i2o/i2o_core.c Sat Jun 10 22:20:22 2000 @@ -189,7 +189,8 @@ * I2O configuration spinlock. This isnt a big deal for contention * so we have one only */ -static struct semaphore i2o_configuration_lock; + +static DECLARE_MUTEX(i2o_configuration_lock); /* * Event spinlock. Used to keep event queue sane and from @@ -883,11 +884,11 @@ switch(msg[4]) { case I2O_EVT_IND_EXEC_RESOURCE_LIMITS: - printk(KERN_ERR "iop%d: Out of resources\n", c->unit); + printk(KERN_ERR "%s: Out of resources\n", c->name); break; case I2O_EVT_IND_EXEC_POWER_FAIL: - printk(KERN_ERR "iop%d: Power failure\n", c->unit); + printk(KERN_ERR "%s: Power failure\n", c->name); break; case I2O_EVT_IND_EXEC_HW_FAIL: @@ -1027,12 +1028,12 @@ entries -= 3; entries /= 9; - dprintk(KERN_INFO "I2O: Dynamic LCT Update\n"); - dprintk(KERN_INFO "I2O: Dynamic LCT contains %d entries\n", entries); + dprintk(KERN_INFO "%s: Dynamic LCT Update\n",c->name); + dprintk(KERN_INFO "%s: Dynamic LCT contains %d entries\n", c->name, entries); if(!entries) { - printk(KERN_INFO "iop%d: Empty LCT???\n", c->unit); + printk(KERN_INFO "%s: Empty LCT???\n", c->name); continue; } @@ -1059,7 +1060,7 @@ } if(!found) { - dprintk(KERN_INFO "Deleted device!\n"); + dprintk(KERN_INFO "i2o_core: Deleted device!\n"); spin_lock(&i2o_dev_lock); i2o_delete_device(d); spin_unlock(&i2o_dev_lock); @@ -1111,7 +1112,6 @@ struct i2o_message *m; u32 mv; u32 *msg; - int count = 0; /* * Old 960 steppings had a bug in the I2O unit that caused @@ -1126,8 +1126,6 @@ m=(struct i2o_message *)bus_to_virt(mv); msg=(u32*)m; - count++; - /* * Temporary Debugging */ @@ -1148,7 +1146,6 @@ /* That 960 bug again... */ if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF) mv=I2O_REPLY_READ32(c); - } } @@ -1281,7 +1278,6 @@ } if((ret=i2o_query_scalar(c, unit, 0xF100, 4, buf, 16))>=0) { - buf[16]=0; printk(KERN_INFO " Device: %s\n", buf); } @@ -1657,7 +1653,8 @@ * time, we assume the IOP could not reboot properly. */ - dprintk(KERN_INFO "Reset in progress, waiting for reboot\n"); + dprintk(KERN_INFO "%s: Reset in progress, waiting for reboot...\n", + c->name); time = jiffies; m = I2O_POST_READ32(c); @@ -1733,8 +1730,7 @@ m=i2o_wait_message(c, "StatusGet"); if(m==0xFFFFFFFF) - return -ETIMEDOUT; - + return -ETIMEDOUT; msg=(u32 *)(c->mem_offset+m); msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0; @@ -1897,12 +1893,12 @@ { struct i2o_controller *iop, *niop = NULL; - printk(KERN_INFO "Activating I2O controllers\n"); + printk(KERN_INFO "Activating I2O controllers...\n"); printk(KERN_INFO "This may take a few minutes if there are many devices\n"); /* In INIT state, Activate IOPs */ for (iop = i2o_controller_chain; iop; iop = niop) { - dprintk(KERN_INFO "Calling i2o_activate_controller for %s\n", + dprintk(KERN_INFO "Calling i2o_activate_controller for %s...\n", iop->name); niop = iop->next; if (i2o_activate_controller(iop) < 0) @@ -1919,7 +1915,7 @@ * If build_sys_table fails, we kill everything and bail * as we can't init the IOPs w/o a system table */ - dprintk(KERN_INFO "calling i2o_build_sys_table\n"); + dprintk(KERN_INFO "i2o_core: Calling i2o_build_sys_table...\n"); if (i2o_build_sys_table() < 0) { i2o_sys_shutdown(); return; @@ -1928,7 +1924,7 @@ /* If IOP don't get online, we need to rebuild the System table */ for (iop = i2o_controller_chain; iop; iop = niop) { niop = iop->next; - dprintk(KERN_INFO "Calling i2o_online_controller for %s\n", iop->name); + dprintk(KERN_INFO "Calling i2o_online_controller for %s...\n", iop->name); if (i2o_online_controller(iop) < 0) { i2o_delete_controller(iop); goto rebuild_sys_tab; @@ -1992,7 +1988,8 @@ /* In READY state, Get status */ if (i2o_status_get(iop) < 0) { - printk(KERN_INFO "Unable to obtain status of IOP, attempting a reset.\n"); + printk(KERN_INFO "Unable to obtain status of %s, " + "attempting a reset.\n", iop->name); if (i2o_reset_controller(iop) < 0) return -1; } @@ -2002,18 +1999,19 @@ return -1; } + if (iop->status_block->i2o_version > I2OVER15) { + printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O Specification.\n", + iop->name); + return -1; + } + if (iop->status_block->iop_state == ADAPTER_STATE_READY || iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || iop->status_block->iop_state == ADAPTER_STATE_HOLD || iop->status_block->iop_state == ADAPTER_STATE_FAILED) { - u32 m[MSG_FRAME_SIZE]; - dprintk(KERN_INFO "%s: Already running, trying to reset\n", + dprintk(KERN_INFO "%s: Already running, trying to reset...\n", iop->name); - - i2o_init_outbound_q(iop); - I2O_REPLY_WRITE32(iop,virt_to_bus(m)); - if (i2o_reset_controller(iop) < 0) return -1; } @@ -2048,7 +2046,7 @@ u32 *msg; u32 time; - dprintk(KERN_INFO "%s: Initializing Outbound Queue\n", c->name); + dprintk(KERN_INFO "%s: Initializing Outbound Queue...\n", c->name); m=i2o_wait_message(c, "OutboundInit"); if(m==0xFFFFFFFF) return -ETIMEDOUT; @@ -2217,13 +2215,13 @@ /* In READY state */ - dprintk(KERN_INFO "Attempting to enable iop%d\n", iop->unit); + dprintk(KERN_INFO "%s: Attempting to enable...\n", iop->name); if (i2o_enable_controller(iop) < 0) return -1; /* In OPERATIONAL state */ - dprintk(KERN_INFO "Attempting to get/parse lct iop%d\n", iop->unit); + dprintk(KERN_INFO "%s: Attempting to get/parse lct...\n", iop->name); if (i2o_lct_get(iop) < 0) return -1; @@ -2275,7 +2273,7 @@ */ if(i2o_status_get(iop)) { printk(KERN_ERR "%s: Deleting b/c could not get status while" - "attempting to build system table", iop->name); + "attempting to build system table\n", iop->name); i2o_delete_controller(iop); sys_tbl->num_entries--; continue; // try the next one @@ -2338,7 +2336,6 @@ } while(m==0xFFFFFFFF && (jiffies-t)= 0xA0 && cmd <= 0xEF)) - i2o_report_common_dsc(detailed_status); - - if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F) + i2o_report_common_dsc(detailed_status); + else if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F) i2o_report_lan_dsc(detailed_status); else printk(" / DetailedStatus = %0#4x.\n", detailed_status); @@ -3189,7 +3185,7 @@ return 0; } else - printk(KERN_INFO "event thread created as pid %d\n", evt_pid); + printk(KERN_INFO "I2O: Event thread created as pid %d\n", evt_pid); if(i2o_num_controllers) i2o_sys_init(); @@ -3247,8 +3243,6 @@ { printk(KERN_INFO "Loading I2O Core - (c) Copyright 1999 Red Hat Software\n"); - init_MUTEX(&i2o_configuration_lock); - if (i2o_install_handler(&i2o_core_handler) < 0) { printk(KERN_ERR @@ -3285,9 +3279,6 @@ i2o_config_init(); #ifdef CONFIG_I2O_BLOCK i2o_block_init(); -#endif -#ifdef CONFIG_I2O_SCSI - i2o_scsi_init(); #endif #ifdef CONFIG_I2O_LAN i2o_lan_init(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_lan.c linux.ac/drivers/i2o/i2o_lan.c --- linux.vanilla/drivers/i2o/i2o_lan.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/i2o/i2o_lan.c Fri May 26 14:21:11 2000 @@ -1,7 +1,7 @@ /* * drivers/i2o/i2o_lan.c * - * I2O LAN CLASS OSM May 4th 2000 + * I2O LAN CLASS OSM May 26th 2000 * * (C) Copyright 1999, 2000 University of Helsinki, * Department of Computer Science @@ -68,9 +68,7 @@ static struct net_device *i2o_landevs[MAX_LAN_CARDS+1]; static int unit = -1; /* device unit number */ -extern rwlock_t dev_mc_lock; - -static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m); +static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m); static void i2o_lan_send_post_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m); static int i2o_lan_receive_post(struct net_device *dev); static void i2o_lan_receive_post_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m); @@ -86,7 +84,7 @@ NULL, NULL, NULL, - "I2O Lan OSM send", + "I2O LAN OSM send", -1, I2O_CLASS_LAN }; @@ -97,7 +95,7 @@ NULL, NULL, NULL, - "I2O Lan OSM receive", + "I2O LAN OSM receive", -1, I2O_CLASS_LAN }; @@ -108,7 +106,7 @@ NULL, NULL, NULL, - "I2O Lan OSM", + "I2O LAN OSM", -1, I2O_CLASS_LAN }; @@ -133,7 +131,6 @@ struct i2o_controller *iop = i2o_dev->controller; u32 *preserved_msg = (u32*)(iop->mem_offset + msg[7]); - // FIXME on 64-bit host u32 *sgl_elem = &preserved_msg[4]; struct sk_buff *skb = NULL; u8 le_flag; @@ -259,11 +256,13 @@ i2o_report_status(KERN_INFO, dev->name, msg); #endif - /* DDM has handled transmit request(s), free sk_buffs */ - + /* DDM has handled transmit request(s), free sk_buffs. + * We get similar single transaction reply also in error cases + * (except if msg failure or transaction error). + */ while (trl_count) { dev_kfree_skb_irq((struct sk_buff *)msg[4 + trl_count]); - dprintk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n", + dprintk(KERN_INFO "%s: tx skb freed (trl_count=%d).\n", dev->name, trl_count); atomic_dec(&priv->tx_out); trl_count--; @@ -296,15 +295,8 @@ if (i2o_lan_handle_status(dev, msg)) return; - /* Getting unused buckets back? */ - - if (msg[4] & I2O_LAN_DSC_CANCELED || - msg[4] & I2O_LAN_DSC_RECEIVE_ABORTED) { - i2o_lan_release_buckets(dev, msg); - return; - } - - /* If other DetailedStatusCodes need special code, add it here */ + i2o_lan_release_buckets(dev, msg); + return; } #ifdef DRIVERDEBUG @@ -410,26 +402,43 @@ if (i2o_lan_handle_status(dev, msg)) return; - /* This should NOT be reached */ + /* In other error cases just report and continue */ + + i2o_report_status(KERN_INFO, dev->name, msg); } #ifdef DRIVERDEBUG i2o_report_status(KERN_INFO, dev->name, msg); #endif - switch (msg[1] >> 24) { - case LAN_RESET: - case LAN_SUSPEND: - /* default reply without payload */ + case LAN_RESET: + case LAN_SUSPEND: + /* default reply without payload */ break; - case I2O_CMD_UTIL_EVT_REGISTER: - case I2O_CMD_UTIL_EVT_ACK: - i2o_lan_handle_event(dev, msg); + + case I2O_CMD_UTIL_EVT_REGISTER: + case I2O_CMD_UTIL_EVT_ACK: + i2o_lan_handle_event(dev, msg); break; - default: - printk(KERN_ERR "%s: No handler for the reply.\n", - dev->name); - i2o_report_status(KERN_INFO, dev->name, msg); + + case I2O_CMD_UTIL_PARAMS_SET: + /* default reply, results in ReplyPayload (not examined) */ + switch (msg[3] >> 16) { + case 1: dprintk(KERN_INFO "%s: Reply to set MAC filter mask.\n", + dev->name); + break; + case 2: dprintk(KERN_INFO "%s: Reply to set MAC table.\n", + dev->name); + break; + default: printk(KERN_WARNING "%s: Bad group 0x%04X\n", + dev->name,msg[3] >> 16); + } + break; + + default: + printk(KERN_ERR "%s: No handler for the reply.\n", + dev->name); + i2o_report_status(KERN_INFO, dev->name, msg); } } @@ -446,7 +455,7 @@ u32 *pskb = &msg[6]; while (trl_count--) { - dprintk(KERN_DEBUG "%s: Releasing unused sk_buff %p (trl_count=%d).\n", + dprintk(KERN_DEBUG "%s: Releasing unused rx skb %p (trl_count=%d).\n", dev->name, (struct sk_buff*)(*pskb),trl_count+1); dev_kfree_skb_irq((struct sk_buff *)(*pskb)); pskb += 1 + trl_elem_size; @@ -464,22 +473,15 @@ struct i2o_controller *iop = i2o_dev->controller; u32 max_evt_data_size =iop->status_block->inbound_frame_size-5; struct i2o_reply { - u8 version_offset; - u8 msg_flags; - u16 msg_size; - u32 tid:12; - u32 initiator:12; - u32 function:8; - u32 initiator_context; - u32 transaction_context; + u32 header[4]; u32 evt_indicator; - u32 data[max_evt_data_size]; /* max */ + u32 data[max_evt_data_size]; } *evt = (struct i2o_reply *)msg; - int evt_data_len = (evt->msg_size - 5) * 4; /* real */ + int evt_data_len = ((msg[0]>>16) - 5) * 4; /* real size*/ printk(KERN_INFO "%s: I2O event - ", dev->name); - if (evt->function == I2O_CMD_UTIL_EVT_ACK) { + if (msg[1]>>24 == I2O_CMD_UTIL_EVT_ACK) { printk("Event acknowledgement reply.\n"); return; } @@ -505,17 +507,19 @@ break; } - case I2O_EVT_IND_GENERAL_WARNING: - printk("General warning 0x%04x.\n", evt->data[0]); - break; - - case I2O_EVT_IND_CONFIGURATION_FLAG: - printk("Configuration requested.\n"); + case I2O_EVT_IND_FIELD_MODIFIED: { + u16 *work16 = (u16 *)evt->data; + printk("Group 0x%04x, field %d changed.\n", work16[0], work16[1]); break; + } - case I2O_EVT_IND_CAPABILITY_CHANGE: - printk("Capability change 0x%04x.\n", evt->data[0]); + case I2O_EVT_IND_VENDOR_EVT: { + int i; + printk("Vendor event:\n"); + for (i = 0; i < evt_data_len / 4; i++) + printk(" 0x%08x\n", evt->data[i]); break; + } case I2O_EVT_IND_DEVICE_RESET: /* Spec 2.0 p. 6-121: @@ -526,48 +530,43 @@ printk("%s: Event Acknowledge timeout.\n", dev->name); break; +#if 0 case I2O_EVT_IND_EVT_MASK_MODIFIED: printk("Event mask modified, 0x%08x.\n", evt->data[0]); break; - case I2O_EVT_IND_FIELD_MODIFIED: { - u16 *work16 = (u16 *)evt->data; - printk("Group 0x%04x, field %d changed.\n", work16[0], work16[1]); + case I2O_EVT_IND_GENERAL_WARNING: + printk("General warning 0x%04x.\n", evt->data[0]); + break; + case I2O_EVT_IND_CONFIGURATION_FLAG: + printk("Configuration requested.\n"); break; - } - case I2O_EVT_IND_VENDOR_EVT: { - int i; - printk("Vendor event:\n"); - for (i = 0; i < evt_data_len / 4; i++) - printk(" 0x%08x\n", evt->data[i]); + case I2O_EVT_IND_CAPABILITY_CHANGE: + printk("Capability change 0x%04x.\n", evt->data[0]); break; - } case I2O_EVT_IND_DEVICE_STATE: printk("Device state changed 0x%08x.\n", evt->data[0]); break; - +#endif case I2O_LAN_EVT_LINK_DOWN: + netif_carrier_off(dev); printk("Link to the physical device is lost.\n"); break; case I2O_LAN_EVT_LINK_UP: + netif_carrier_on(dev); printk("Link to the physical device is (re)established.\n"); break; case I2O_LAN_EVT_MEDIA_CHANGE: printk("Media change.\n"); break; - default: printk("0x%08x. No handler.\n", evt->evt_indicator); } - - /* Note: EventAck necessary only for events that cause the device to - * syncronize with the user. - */ } /* @@ -722,7 +721,7 @@ printk(KERN_WARNING "%s: Unable to set RxMaxPacketsBucket.\n", dev->name); else - dprintk(KERN_INFO "%s: RxMaxPacketsBucket set to &d.\n", + dprintk(KERN_INFO "%s: RxMaxPacketsBucket set to %d.\n", dev->name, val); return; } @@ -739,6 +738,7 @@ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; + u32 mc_addr_group[64]; MOD_INC_USE_COUNT; @@ -756,6 +756,18 @@ i2o_lan_reset(dev); + /* Get the max number of multicast addresses */ + + if (i2o_query_scalar(iop, i2o_dev->lct_data.tid, 0x0001, -1, + &mc_addr_group, sizeof(mc_addr_group)) < 0 ) { + printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } + priv->max_size_mc_table = mc_addr_group[8]; + + /* Malloc space for free bucket list to resuse reveive post buckets */ + priv->i2o_fbl = kmalloc(priv->max_buckets_out * sizeof(struct sk_buff *), GFP_KERNEL); if (priv->i2o_fbl == NULL) { @@ -819,9 +831,6 @@ /* * i2o_lan_batch_send(): Send packets in batch. * Both i2o_lan_sdu_send and i2o_lan_packet_send use this. - * - * This is a coarse first approximation for the tx_batching. - * If you come up with something better, please tell me. -taneli */ static void i2o_lan_batch_send(struct net_device *dev) { @@ -864,7 +873,7 @@ * If tx_batch_mode = 0x01 forced to batch mode * If tx_batch_mode = 0x10 switch automatically, current mode immediate * If tx_batch_mode = 0x11 switch automatically, current mode batch - * If gap between two packets is > 2 ticks, switch to immediate + * If gap between two packets is > 0 ticks, switch to immediate */ if (priv->tx_batch_mode >> 1) // switch automatically priv->tx_batch_mode = tickssofar ? 0x02 : 0x03; @@ -996,7 +1005,7 @@ if (!(priv->tx_batch_mode & 0x01) || priv->tx_count == priv->sgl_max) { dev->trans_start = jiffies; i2o_post_message(iop, priv->m); - dprintk(KERN_DEBUG"%s: %d packets sent.\n", dev->name, priv->tx_count); + dprintk(KERN_DEBUG "%s: %d packets sent.\n", dev->name, priv->tx_count); priv->tx_count = 0; } @@ -1134,100 +1143,90 @@ return (struct net_device_stats *)&priv->stats; } -/* - * i2o_lan_set_mc_list(): Enable a network device to receive packets - * not send to the protocol address. +/* + * i2o_lan_set_mc_filter(): Post a request to set multicast filter. */ - -static void i2o_lan_set_mc_list(struct net_device *dev) +int i2o_lan_set_mc_filter(struct net_device *dev, u32 filter_mask) { - struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; + struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; struct i2o_controller *iop = i2o_dev->controller; - u32 filter_mask; - u32 max_size_mc_table; - u32 mc_addr_group[64]; + u32 msg[10]; -// This isn't safe yet in SMP. Needs to be async. -// Seems to work in uniprocessor environment. + msg[0] = TEN_WORD_MSG_SIZE | SGL_OFFSET_5; + msg[1] = I2O_CMD_UTIL_PARAMS_SET << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid; + msg[2] = priv->unit << 16 | lan_context; + msg[3] = 0x0001 << 16 | 3 ; // TransactionContext: group&field + msg[4] = 0; + msg[5] = 0xCC000000 | 16; // Immediate data SGL + msg[6] = 1; // OperationCount + msg[7] = 0x0001<<16 | I2O_PARAMS_FIELD_SET; // Group, Operation + msg[8] = 3 << 16 | 1; // FieldIndex, FieldCount + msg[9] = filter_mask; // Value -return; - -// read_lock_bh(&dev_mc_lock); - spin_lock(&dev->xmit_lock); - dev->xmit_lock_owner = smp_processor_id(); + return i2o_post_this(iop, msg, sizeof(msg)); +} - if (i2o_query_scalar(iop, i2o_dev->lct_data.tid, 0x0001, -1, - &mc_addr_group, sizeof(mc_addr_group)) < 0 ) { - printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name); - return; +/* + * i2o_lan_set_mc_table(): Post a request to set LAN_MULTICAST_MAC_ADDRESS table. + */ +int i2o_lan_set_mc_table(struct net_device *dev) +{ + struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; + struct i2o_device *i2o_dev = priv->i2o_dev; + struct i2o_controller *iop = i2o_dev->controller; + struct dev_mc_list *mc; + u32 msg[10 + 2 * dev->mc_count]; + u8 *work8 = (u8 *)(msg + 10); + + msg[0] = I2O_MESSAGE_SIZE(10 + 2 * dev->mc_count) | SGL_OFFSET_5; + msg[1] = I2O_CMD_UTIL_PARAMS_SET << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid; + msg[2] = priv->unit << 16 | lan_context; // InitiatorContext + msg[3] = 0x0002 << 16 | (u16)-1; // TransactionContext + msg[4] = 0; // OperationFlags + msg[5] = 0xCC000000 | (16 + 8 * dev->mc_count); // Immediate data SGL + msg[6] = 2; // OperationCount + msg[7] = 0x0002 << 16 | I2O_PARAMS_TABLE_CLEAR; // Group, Operation + msg[8] = 0x0002 << 16 | I2O_PARAMS_ROW_ADD; // Group, Operation + msg[9] = dev->mc_count << 16 | (u16)-1; // RowCount, FieldCount + + for (mc = dev->mc_list; mc ; mc = mc->next, work8 += 8) { + memset(work8, 0, 8); + memcpy(work8, mc->dmi_addr, mc->dmi_addrlen); // Values } - max_size_mc_table = mc_addr_group[8]; + return i2o_post_this(iop, msg, sizeof(msg)); +} + +/* + * i2o_lan_set_multicast_list(): Enable a network device to receive packets + * not send to the protocol address. + */ +static void i2o_lan_set_multicast_list(struct net_device *dev) +{ + struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; + u32 filter_mask; if (dev->flags & IFF_PROMISC) { filter_mask = 0x00000002; - printk(KERN_INFO "%s: Enabling promiscuous mode...\n", dev->name); - } else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > max_size_mc_table) { + dprintk(KERN_INFO "%s: Enabling promiscuous mode...\n", dev->name); + } else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > priv->max_size_mc_table) { filter_mask = 0x00000004; - printk(KERN_INFO "%s: Enabling all multicast mode...\n", dev->name); + dprintk(KERN_INFO "%s: Enabling all multicast mode...\n", dev->name); } else if (dev->mc_count) { - struct dev_mc_list *mc; - u8 mc_table[2 + 8 * dev->mc_count]; // RowCount, Addresses - u64 *work64 = (u64 *)(mc_table + 2); - filter_mask = 0x00000000; - printk(KERN_INFO "%s: Enabling multicast mode...\n", dev->name); - - /* Fill multicast addr table */ - - memset(mc_table, 0, sizeof(mc_table)); - memcpy(mc_table, &dev->mc_count, 2); - for (mc = dev->mc_list; mc ; mc = mc->next, work64++ ) - memcpy(work64, mc->dmi_addr, mc->dmi_addrlen); - - /* Clear old mc table, copy new table to */ - - if (i2o_clear_table(iop, i2o_dev->lct_data.tid, 0x0002) < 0) - printk(KERN_INFO "%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n", dev->name); - - if ((i2o_row_add_table(iop, i2o_dev->lct_data.tid, 0x0002, -1, - mc_table, sizeof(mc_table))) < 0) - printk(KERN_INFO "%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n", dev->name); + dprintk(KERN_INFO "%s: Enabling multicast mode...\n", dev->name); + if (i2o_lan_set_mc_table(dev) < 0) + printk(KERN_WARNING "%s: Unable to send MAC table.\n", dev->name); } else { filter_mask = 0x00000300; // Broadcast, Multicast disabled - printk(KERN_INFO "%s: Enabling unicast mode...\n", dev->name); + dprintk(KERN_INFO "%s: Enabling unicast mode...\n", dev->name); } - /* Finally copy new FilterMask to */ - - if (i2o_set_scalar(iop, i2o_dev->lct_data.tid, 0x0001, 3, - &filter_mask, sizeof(filter_mask)) <0) - printk(KERN_WARNING "%s: Unable to set MAC FilterMask.\n", dev->name); - - dev->xmit_lock_owner = -1; - spin_unlock(&dev->xmit_lock); -// read_unlock_bh(&dev_mc_lock); - - return; -} - -static struct tq_struct i2o_lan_set_mc_list_task = { - 0, 0, (void (*)(void *))i2o_lan_set_mc_list, (void *) 0 -}; + /* Finally copy new FilterMask to DDM */ -/* - * i2o_lan_set_multicast_list(): - * Queue routine i2o_lan_set_mc_list() to be called later. - * Needs to be async. - */ -static void i2o_lan_set_multicast_list(struct net_device *dev) -{ - if (in_interrupt()) { - i2o_lan_set_mc_list_task.data = (void *)dev; - queue_task(&i2o_lan_set_mc_list_task, &tq_scheduler); - } else - i2o_lan_set_mc_list(dev); + if (i2o_lan_set_mc_filter(dev, filter_mask) < 0) + printk(KERN_WARNING "%s: Unable to send MAC FilterMask.\n", dev->name); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_lan.h linux.ac/drivers/i2o/i2o_lan.h --- linux.vanilla/drivers/i2o/i2o_lan.h Thu May 25 17:38:18 2000 +++ linux.ac/drivers/i2o/i2o_lan.h Sat Jun 10 22:26:21 2000 @@ -1,7 +1,7 @@ /* * i2o_lan.h I2O LAN Class definitions * - * I2O LAN CLASS OSM April 3rd 2000 + * I2O LAN CLASS OSM May 26th 2000 * * (C) Copyright 1999, 2000 University of Helsinki, * Department of Computer Science @@ -23,7 +23,7 @@ #define I2O_LAN_RX_COPYBREAK 200 #define I2O_LAN_TX_TIMEOUT (1*HZ) #define I2O_LAN_TX_BATCH_MODE 2 /* 2=automatic, 1=on, 0=off */ -#define I2O_LAN_EVENT_MASK 0; /* 0=None, 0xFFC00002=All */ +#define I2O_LAN_EVENT_MASK 0 /* 0=None, 0xFFC00002=All */ /* LAN types */ #define I2O_LAN_ETHERNET 0x0030 @@ -100,7 +100,7 @@ #define I2O_LAN_DSC_DEST_ADDRESS_DETECTED 0x0E #define I2O_LAN_DSC_DEST_ADDRESS_OMITTED 0x0F #define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x10 -#define I2O_LAN_DSC_TEMP_SUSPENDED_STATE 0x11 +#define I2O_LAN_DSC_SUSPENDED 0x11 struct i2o_packet_info { u32 offset : 24; @@ -143,6 +143,8 @@ spinlock_t fbl_lock; spinlock_t tx_lock; + + u32 max_size_mc_table; /* max number of multicast addresses */ /* LAN OSM configurable parameters are here: */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_pci.c linux.ac/drivers/i2o/i2o_pci.c --- linux.vanilla/drivers/i2o/i2o_pci.c Thu May 25 17:38:18 2000 +++ linux.ac/drivers/i2o/i2o_pci.c Sat May 27 15:28:44 2000 @@ -132,9 +132,9 @@ for(i=0; i<6; i++) { /* Skip I/O spaces */ - if(!(dev->resource[i].flags&PCI_BASE_ADDRESS_SPACE)) + if(!(pci_resource_flags(dev, i) & IORESOURCE_IO)) { - memptr=dev->resource[i].start; + memptr = pci_resource_start(dev, i); break; } } @@ -256,6 +256,8 @@ printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n"); continue; } + if (pci_enable_device(dev)) + continue; printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n", dev->bus->number, dev->devfn); pci_set_master(dev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/i2o/i2o_scsi.h linux.ac/drivers/i2o/i2o_scsi.h --- linux.vanilla/drivers/i2o/i2o_scsi.h Thu May 25 17:38:18 2000 +++ linux.ac/drivers/i2o/i2o_scsi.h Sat Jun 10 22:29:15 2000 @@ -22,6 +22,7 @@ extern int i2o_scsi_reset(Scsi_Cmnd *, unsigned int); extern int i2o_scsi_bios_param(Disk *, kdev_t, int *); extern void i2o_scsi_setup(char *str, int *ints); +extern int i2o_scsi_release(struct Scsi_Host *host); #define I2OSCSI { \ next: NULL, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/Config.in linux.ac/drivers/ide/Config.in --- linux.vanilla/drivers/ide/Config.in Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/Config.in Sat Jun 10 22:00:33 2000 @@ -1,6 +1,8 @@ # # IDE ATA ATAPI Block device driver configuration # +# Andre Hedrick +# mainmenu_option next_comment comment 'IDE, ATA and ATAPI Block devices' @@ -21,6 +23,9 @@ dep_mbool ' Seagate Vendor Specific' CONFIG_BLK_DEV_IDEDISK_SEAGATE $CONFIG_BLK_DEV_IDEDISK_VENDOR dep_mbool ' Western Digital Vendor Specific' CONFIG_BLK_DEV_IDEDISK_WD $CONFIG_BLK_DEV_IDEDISK_VENDOR + define_bool CONFIG_BLK_DEV_COMMERIAL n + dep_mbool ' TiVo Commerial Application Specific' CONFIG_BLK_DEV_TIVO $CONFIG_BLK_DEV_COMMERIAL + dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE @@ -44,32 +49,28 @@ dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' AEC62XX Tuning support (WIP)' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX $CONFIG_IDEDMA_PCI_WIP + dep_mbool ' AEC62XX Tuning support' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3 dep_bool ' AMD Viper support' CONFIG_BLK_DEV_AMD7409 $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' AMD Viper ATA-66 Override (WIP)' CONFIG_AMD7409_OVERRIDE $CONFIG_BLK_DEV_AMD7409 $CONFIG_IDEDMA_PCI_WIP dep_bool ' CMD64X chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI - dep_mbool ' CMD64X chipset RAID (WIP)' CONFIG_CMD64X_RAID $CONFIG_BLK_DEV_CMD64X $CONFIG_IDEDMA_PCI_WIP - dep_bool ' CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI + dep_bool ' CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' HPT34X AUTODMA support (WIP)' CONFIG_HPT34X_AUTODMA $CONFIG_BLK_DEV_HPT34X $CONFIG_IDEDMA_PCI_WIP dep_bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' HPT366 Fast Interrupts (WIP)' CONFIG_HPT366_FIP $CONFIG_BLK_DEV_HPT366 $CONFIG_IDEDMA_PCI_WIP - dep_mbool ' HPT366 mode Three (WIP)' CONFIG_HPT366_MODE3 $CONFIG_BLK_DEV_HPT366 $CONFIG_IDEDMA_PCI_WIP if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then dep_mbool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' PIIXn Tuning support' CONFIG_PIIX_TUNING $CONFIG_BLK_DEV_PIIX $CONFIG_IDEDMA_PCI_AUTO fi dep_bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL - dep_bool ' PROMISE PDC20246/PDC20262 support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_bool ' PROMISE PDC20246/PDC20262/PDC20267 support' CONFIG_BLK_DEV_PDC202XX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX - dep_mbool ' Special Mode Feature (WIP)' CONFIG_PDC202XX_MASTER $CONFIG_BLK_DEV_PDC202XX $CONFIG_IDEDMA_PCI_WIP dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI + dep_bool ' VIA82CXXX chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI dep_mbool ' VIA82CXXX Tuning support (WIP)' CONFIG_VIA82CXXX_TUNING $CONFIG_BLK_DEV_VIA82CXXX $CONFIG_IDEDMA_PCI_WIP fi if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then @@ -81,14 +82,12 @@ dep_bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC - define_bool CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_BLK_DEV_IDEDMA_PMAC fi if [ "$CONFIG_ARCH_ACORN" = "y" ]; then dep_bool ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_ARCH_ACORN dep_bool ' ICS DMA support' CONFIG_BLK_DEV_IDEDMA_ICS $CONFIG_BLK_DEV_IDE_ICSIDE dep_bool ' Use ICS DMA by default' CONFIG_IDEDMA_ICS_AUTO $CONFIG_BLK_DEV_IDEDMA_ICS define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_ICS - define_bool CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_BLK_DEV_IDEDMA_ICS dep_bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE $CONFIG_ARCH_ACORN fi if [ "$CONFIG_AMIGA" = "y" ]; then @@ -132,6 +131,17 @@ define_bool CONFIG_IDEDMA_AUTO n fi +if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \ + "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ + "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then + bool ' IGNORE word93 Validation BITS' CONFIG_IDEDMA_IVB +fi + +if [ "$CONFIG_BLK_DEV_TIVO" = "y" ]; then + define_bool CONFIG_DMA_NONPCI y +else + define_bool CONFIG_DMA_NONPCI n +fi if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \ "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/Makefile linux.ac/drivers/ide/Makefile --- linux.vanilla/drivers/ide/Makefile Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/Makefile Mon Jun 5 19:35:17 2000 @@ -18,11 +18,11 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -L_TARGET := ide.a -L_OBJS := ide-geometry.o +O_TARGET := idedriver.o +O_OBJS := ide-geometry.o M_OBJS := MOD_LIST_NAME := IDE_MODULES -LX_OBJS := +OX_OBJS := MX_OBJS := ifeq ($(CONFIG_BLK_DEV_AEC62XX),y) @@ -78,7 +78,7 @@ endif ifeq ($(CONFIG_BLK_DEV_HD),y) -L_OBJS += hd.o +O_OBJS += hd.o endif ifeq ($(CONFIG_BLK_DEV_HPT34X),y) @@ -97,7 +97,7 @@ IDE_OBJS += icside.o endif -ifeq ($(CONFIG_BLK_DEV_IDEDMA_PCI),y) +ifeq ($(CONFIG_BLK_DEV_IDEDMA),y) IDE_OBJS += ide-dma.o endif @@ -178,8 +178,8 @@ ###Collect ifeq ($(CONFIG_BLK_DEV_IDE),y) - LX_OBJS += ide.o ide-features.o - L_OBJS += ide-probe.o $(IDE_OBJS) + OX_OBJS += ide.o ide-features.o + O_OBJS += ide-probe.o $(IDE_OBJS) else ifeq ($(CONFIG_BLK_DEV_IDE),m) MIX_OBJS += ide.o ide-features.o $(IDE_OBJS) @@ -190,7 +190,7 @@ ############ ifeq ($(CONFIG_BLK_DEV_IDECS),y) -L_OBJS += ide-cs.o +O_OBJS += ide-cs.o else ifeq ($(CONFIG_BLK_DEV_IDECS),m) M_OBJS += ide-cs.o @@ -198,7 +198,7 @@ endif ifeq ($(CONFIG_BLK_DEV_IDEDISK),y) -L_OBJS += ide-disk.o +O_OBJS += ide-disk.o else ifeq ($(CONFIG_BLK_DEV_IDEDISK),m) M_OBJS += ide-disk.o @@ -206,7 +206,7 @@ endif ifeq ($(CONFIG_BLK_DEV_IDECD),y) -L_OBJS += ide-cd.o +O_OBJS += ide-cd.o else ifeq ($(CONFIG_BLK_DEV_IDECD),m) M_OBJS += ide-cd.o @@ -214,7 +214,7 @@ endif ifeq ($(CONFIG_BLK_DEV_IDETAPE),y) -L_OBJS += ide-tape.o +O_OBJS += ide-tape.o else ifeq ($(CONFIG_BLK_DEV_IDETAPE),m) M_OBJS += ide-tape.o @@ -222,7 +222,7 @@ endif ifeq ($(CONFIG_BLK_DEV_IDEFLOPPY),y) -L_OBJS += ide-floppy.o +O_OBJS += ide-floppy.o else ifeq ($(CONFIG_BLK_DEV_IDEFLOPPY),m) M_OBJS += ide-floppy.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/aec62xx.c linux.ac/drivers/ide/aec62xx.c --- linux.vanilla/drivers/ide/aec62xx.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/aec62xx.c Sat Jun 10 22:00:33 2000 @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/aec62xx.c Version 0.08 Mar. 28, 2000 + * linux/drivers/ide/aec62xx.c Version 0.09 June. 9, 2000 * - * Copyright (C) 2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1999-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License * */ @@ -55,7 +55,7 @@ { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; u8 art = 0, uart = 0; @@ -358,7 +358,7 @@ byte unit = (drive->select.b.unit & 0x01); unsigned long dma_base = hwif->dma_base; byte speed = -1; - byte ultra66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; + byte ultra66 = eighty_ninty_three(drive); if (drive->media != ide_disk) return ((int) ide_dma_off_quietly); @@ -497,6 +497,23 @@ switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); + case ide_dma_lostirq: + case ide_dma_timeout: + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: +// { +// int i = 0; +// byte reg49h = 0; +// pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); +// for (i=0;i<256;i++) +// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); +// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); +// } +// return 0; + default: + break; + } default: break; } @@ -529,9 +546,6 @@ byte ata66 = 0; pci_read_config_byte(hwif->pci_dev, 0x49, &ata66); -#if 1 - printk("AEC6260: reg49h=0x%02x ATA-%s Cable Port%d\n", ata66, (ata66 & mask) ? "33" : "66", hwif->channel); -#endif return ((ata66 & mask) ? 0 : 1); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/alim15x3.c linux.ac/drivers/ide/alim15x3.c --- linux.vanilla/drivers/ide/alim15x3.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/alim15x3.c Sat Jun 10 22:00:33 2000 @@ -1,17 +1,15 @@ /* - * linux/drivers/ide/alim15x3.c Version 0.09 Mar. 18, 2000 + * linux/drivers/ide/alim15x3.c Version 0.10 Jun. 9, 2000 * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer + * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License * * (U)DMA capable version of ali 1533/1543(C), 1535(D) * - * version: 1.0 beta2 (Sep. 2, 1999) - * e-mail your problems to cjtsai@ali.com.tw - * ********************************************************************** * 9/7/99 --Parts from the above author are included and need to be * converted into standard interface, once I finish the thought. @@ -237,7 +235,6 @@ static byte m5229_revision = 0; static byte chip_is_1543c_e = 0; -static byte cable_80_pin[2] = { 0, 0 }; byte ali_proc = 0; static struct pci_dev *isa_dev; @@ -346,7 +343,7 @@ /* * enable ultra dma and set timing */ - tmpbyte |= ((0x08 | (4-speed)) << (unit << 2)); + tmpbyte |= ((0x08 | ((4-speed)&0x07)) << (unit << 2)); pci_write_config_byte(dev, m5229_udma, tmpbyte); if (speed >= XFER_UDMA_3) { pci_read_config_byte(dev, 0x4b, &tmpbyte); @@ -370,12 +367,14 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33) { struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); byte speed = 0x00; - byte ultra66 = ((hwif->udma_four) && (id->hw_config & 0x2000)) ? 1 : 0; + byte ultra66 = eighty_ninty_three(drive); + byte ultra100 = (m5229_revision>=0xc4) ? 1 : 0; int rval; - if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) { + if ((id->dma_ultra & 0x0020) && (ultra100) && (ultra66) && (ultra33)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) { speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (ultra66) && (ultra33)) { speed = XFER_UDMA_3; @@ -454,7 +453,7 @@ } dma_func = ide_dma_off_quietly; if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, can_ultra_dma); if ((id->field_valid & 2) && @@ -508,13 +507,13 @@ unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) { - unsigned long fixdma_base = dev->resource[4].start; + unsigned long fixdma_base = pci_resource_start(dev, 4); pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); - if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { + if (!fixdma_base) { /* * */ @@ -539,11 +538,16 @@ return 0; } +/* + * This checks if the controller and the cable are capable + * of UDMA66 transfers. It doesn't check the drives. + * But see note 2 below! + */ unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; - byte ata66mask = hwif->channel ? 0x02 : 0x01; unsigned int ata66 = 0; + byte cable_80_pin[2] = { 0, 0 }; unsigned long flags; byte tmpbyte; @@ -575,7 +579,7 @@ * 1543C-B0 (m1533, 0x79, bit 2) */ pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); - } else if (m5229_revision == 0xC3) { + } else if (m5229_revision >= 0xC3) { /* * 1553/1535 (m1533, 0x79, bit 1) */ @@ -596,6 +600,10 @@ * has 80-pin (from host view) */ if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1; + /* + * Allow ata66 if cable of current channel has 80 pins + */ + ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0]; } else { /* * revision 0x20 (1543-E, 1543-F) @@ -625,18 +633,6 @@ pci_write_config_byte(dev, 0x53, tmpbyte); - /* - * Ultra66 cable detection (from Host View) - * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin - * - * 0x4a, bit0 is 0 => primary channel - * has 80-pin (from host view) - * - * 0x4a, bit1 is 0 => secondary channel - * has 80-pin (from host view) - */ - pci_read_config_byte(dev, 0x4a, &tmpbyte); - ata66 = (!(tmpbyte & ata66mask)) ? 1 : 0; __restore_flags(flags); return(ata66); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/amd7409.c linux.ac/drivers/ide/amd7409.c --- linux.vanilla/drivers/ide/amd7409.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/amd7409.c Sat Jun 10 22:00:33 2000 @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/amd7409.c Version 0.04 Mar. 18, 2000 + * linux/drivers/ide/amd7409.c Version 0.05 June 9, 2000 * - * Copyright (C) 2000 Andre Hedrick + * Copyright (C) 1999-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * */ @@ -40,7 +40,7 @@ static int amd7409_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* @@ -71,6 +71,20 @@ extern char *ide_xfer_verbose (byte xfer_rate); +static unsigned int amd7409_swdma_check (struct pci_dev *dev) +{ + unsigned int class_rev; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + return ((int) (class_rev >= 7) ? 1 : 0); +} + +static int amd7409_swdma_error(ide_drive_t *drive) +{ + printk("%s: single-word DMA not support (revision < C4)\n", drive->name); + return 0; +} + /* * Here is where all the hard work goes to program the chipset. * @@ -122,64 +136,68 @@ case XFER_UDMA_4: ultra_timing |= 0x45; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_3: ultra_timing |= 0x44; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_2: ultra_timing |= 0x40; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_1: ultra_timing |= 0x41; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_0: ultra_timing |= 0x42; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_2: dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_1: dma_pio_timing |= 0x21; - pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_0: dma_pio_timing |= 0x77; - pio_timing |= (0x03 << drive->dn); + break; + case XFER_SW_DMA_2: + if (!amd7409_swdma_check(dev)) + return amd7409_swdma_error(drive); + dma_pio_timing |= 0x42; + break; + case XFER_SW_DMA_1: + if (!amd7409_swdma_check(dev)) + return amd7409_swdma_error(drive); + dma_pio_timing |= 0x65; + break; + case XFER_SW_DMA_0: + if (!amd7409_swdma_check(dev)) + return amd7409_swdma_error(drive); + dma_pio_timing |= 0xA8; break; #endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_3: dma_pio_timing |= 0x22; - pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_2: dma_pio_timing |= 0x42; - pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_1: dma_pio_timing |= 0x65; - pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_0: default: dma_pio_timing |= 0xA8; - pio_timing |= (0x03 << drive->dn); break; } + pio_timing |= (0x03 << drive->dn); + if (!drive->init_speed) drive->init_speed = speed; @@ -268,12 +286,14 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - byte udma_66 = ((id->hw_config & 0x2000) && - (HWIF(drive)->udma_four)) ? 1 : 0; + byte udma_66 = eighty_ninty_three(drive); + byte udma_100 = 0; byte speed = 0x00; int rval; - if ((id->dma_ultra & 0x0010) && (udma_66)) { + if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && (udma_66)) { speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (udma_66)) { speed = XFER_UDMA_3; @@ -318,7 +338,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -327,12 +347,15 @@ } } else if (id->field_valid & 2) { try_dma_modes: - if (id->dma_mword & 0x0007) { + if ((id->dma_mword & 0x0007) || + ((id->dma_1word & 0x007) && + (amd7409_swdma_check(HWIF(drive)->pci_dev)))) { /* 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; @@ -372,9 +395,14 @@ unsigned int __init pci_init_amd7409 (struct pci_dev *dev, const char *name) { - unsigned long fixdma_base = dev->resource[4].start; + unsigned long fixdma_base = pci_resource_start(dev, 4); + +#ifdef CONFIG_BLK_DEV_IDEDMA + if (!amd7409_swdma_check(dev)) + printk("%s: disabling single-word DMA support (revision < C4)\n", name); +#endif /* CONFIG_BLK_DEV_IDEDMA */ - if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { + if (!fixdma_base) { /* * */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/cmd64x.c linux.ac/drivers/ide/cmd64x.c --- linux.vanilla/drivers/ide/cmd64x.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/cmd64x.c Sat Jun 10 22:00:33 2000 @@ -1,6 +1,6 @@ /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 * - * linux/drivers/ide/cmd64x.c Version 1.21 Mar. 18, 2000 + * linux/drivers/ide/cmd64x.c Version 1.22 June 9, 2000 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because @@ -10,7 +10,7 @@ * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1999-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1999-2000 Andre Hedrick */ #include @@ -93,6 +93,9 @@ u8 hi_byte = 0, lo_byte = 0; switch(bmide_dev->device) { + case PCI_DEVICE_ID_CMD_649: + p += sprintf(p, "\n CMD649 Chipset.\n"); + break; case PCI_DEVICE_ID_CMD_648: p += sprintf(p, "\n CMD648 Chipset.\n"); break; @@ -128,19 +131,23 @@ (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", (reg72&0x20)?( ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): - ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"):"X"):"?", + ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):"X"):"?", (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", (reg72&0x40)?( ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): - ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"):"X"):"?", + ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):"X"):"?", (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", (reg7a&0x20)?( ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): - ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"):"X"):"?", + ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):"X"):"?", (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", (reg7a&0x40)?( ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): - ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"):"X"):"?" ); + ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" ); p += sprintf(p, "PIO Mode: %s %s %s %s\n", "?", "?", "?", "?"); @@ -349,9 +356,9 @@ #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); int err = 0; + byte unit = (drive->select.b.unit & 0x01); u8 pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; u8 pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; u8 regU = 0; @@ -369,6 +376,7 @@ (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); switch(speed) { + case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; case XFER_UDMA_2: regU |= (unit ? 0x42 : 0x11); break; @@ -383,7 +391,7 @@ #else int err = 0; - switch(speed) { + switch(speed) { #endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; @@ -394,6 +402,7 @@ default: return 1; } + #ifdef CONFIG_BLK_DEV_IDEDMA (void) pci_write_config_byte(dev, pciU, regU); #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -420,10 +429,12 @@ byte speed = 0x00; byte set_pio = 0x00; byte udma_33 = ((rev >= 0x05) || (ultra_66)) ? 1 : 0; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; + byte udma_66 = eighty_ninty_three(drive); + byte udma_100 = 0; int rval; switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: udma_100 = 1; break; case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_646: case PCI_DEVICE_ID_CMD_643: @@ -446,7 +457,9 @@ * in the 646U2. * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. */ - if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { + if ((id->dma_ultra & 0x0020) && (udma_100) && (udma_66) && (udma_33)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { speed = XFER_UDMA_3; @@ -483,7 +496,7 @@ if (cmd64x_tune_chipset(drive, speed)) return ((int) ide_dma_off); - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 11) & 7) ? 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 : @@ -500,12 +513,15 @@ unsigned int class_rev = 0; byte can_ultra_33 = 0; byte can_ultra_66 = 0; + byte can_ultra_100 = 0; ide_dma_action_t dma_func = ide_dma_on; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: + can_ultra_100 = 1; case PCI_DEVICE_ID_CMD_648: can_ultra_66 = 1; case PCI_DEVICE_ID_CMD_643: @@ -514,6 +530,7 @@ case PCI_DEVICE_ID_CMD_646: can_ultra_33 = (class_rev >= 0x05) ? 1 : 0; can_ultra_66 = 0; + can_ultra_100 = 0; break; default: return hwif->dmaproc(ide_dma_off, drive); @@ -528,7 +545,7 @@ } dma_func = ide_dma_off_quietly; if ((id->field_valid & 4) && (can_ultra_33)) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66); if ((id->field_valid & 2) && @@ -636,6 +653,7 @@ printk("\n"); break; case PCI_DEVICE_ID_CMD_648: + case PCI_DEVICE_ID_CMD_649: break; default: break; @@ -714,6 +732,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_643: hwif->dmaproc = &cmd64x_dmaproc; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/cs5530.c linux.ac/drivers/ide/cs5530.c --- linux.vanilla/drivers/ide/cs5530.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/cs5530.c Sat Jun 10 22:00:33 2000 @@ -1,7 +1,7 @@ /* * linux/drivers/ide/cs5530.c Version 0.6 Mar. 18, 2000 * - * Copyright (C) 2000 Andre Hedrick + * Copyright (C) 2000 Andre Hedrick * Ditto of GNU General Public License. * * Copyright (C) 2000 Mark Lord @@ -43,7 +43,7 @@ static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/cy82c693.c linux.ac/drivers/ide/cy82c693.c --- linux.vanilla/drivers/ide/cy82c693.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/cy82c693.c Sat Jun 10 22:00:33 2000 @@ -1,8 +1,8 @@ /* * linux/drivers/ide/cy82c693.c Version 0.34 Dec. 13, 1999 * - * Copyright (C) 1998-99 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998-99 Andre Hedrick, Integrater + * Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer + * Copyright (C) 1998-2000 Andre Hedrick , Integrater * * CYPRESS CY82C693 chipset IDE controller * diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/hpt34x.c linux.ac/drivers/ide/hpt34x.c --- linux.vanilla/drivers/ide/hpt34x.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/hpt34x.c Sat Jun 10 22:00:34 2000 @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/hpt34x.c Version 0.30 Mar. 18, 2000 + * linux/drivers/ide/hpt34x.c Version 0.31 June. 9, 2000 * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1998-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * @@ -62,7 +62,7 @@ static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u8 c0 = 0, c1 = 0; /* @@ -360,7 +360,7 @@ unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) { int i = 0; - unsigned long hpt34xIoBase = dev->resource[4].start; + unsigned long hpt34xIoBase = pci_resource_start(dev, 4); unsigned short cmd; unsigned long flags; @@ -371,7 +371,7 @@ pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & PCI_COMMAND_MEMORY) { - if (dev->resource[PCI_ROM_RESOURCE].start) { + if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/hpt366.c linux.ac/drivers/ide/hpt366.c --- linux.vanilla/drivers/ide/hpt366.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/hpt366.c Sat Jun 10 22:00:34 2000 @@ -1,13 +1,16 @@ /* - * linux/drivers/ide/hpt366.c Version 0.17 Mar. 18, 2000 + * linux/drivers/ide/hpt366.c Version 0.18 June. 9, 2000 * - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1999-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his * donation of an ABit BP6 mainboard, processor, and memory acellerated * development and support. + * + * Note that final HPT370 support was done by force extraction of GPL. + * */ #include @@ -30,13 +33,26 @@ #include "ide_modes.h" -#undef DISPLAY_HPT366_TIMINGS +#define DISPLAY_HPT366_TIMINGS #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) #include #include #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ +extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); + +const char *quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP LM20.5", + NULL +}; + +const char *bad_ata100_5[] = { + NULL +}; + const char *bad_ata66_4[] = { "WDC AC310200R", NULL @@ -60,70 +76,92 @@ struct chipset_bus_clock_list_entry { byte xfer_speed; - unsigned int chipset_settings; + unsigned int chipset_settings_write; + unsigned int chipset_settings_read; }; 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 } + { XFER_UDMA_4, 0x900fd943, 0x900fd943 }, + { XFER_UDMA_3, 0x900ad943, 0x900ad943 }, + { XFER_UDMA_2, 0x900bd943, 0x900bd943 }, + { XFER_UDMA_1, 0x9008d943, 0x9008d943 }, + { XFER_UDMA_0, 0x9008d943, 0x9008d943 }, + + { XFER_MW_DMA_2, 0xa008d943, 0xa008d943 }, + { XFER_MW_DMA_1, 0xa010d955, 0xa010d955 }, + { XFER_MW_DMA_0, 0xa010d9fc, 0xa010d9fc }, + + { XFER_PIO_4, 0xc008d963, 0xc008d963 }, + { XFER_PIO_3, 0xc010d974, 0xc010d974 }, + { XFER_PIO_2, 0xc010d997, 0xc010d997 }, + { XFER_PIO_1, 0xc010d9c7, 0xc010d9c7 }, + { XFER_PIO_0, 0xc018d9d9, 0xc018d9d9 }, + { 0, 0x0120d9d9, 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 } + { XFER_UDMA_4, 0x90c9a731, 0x90c9a731 }, + { XFER_UDMA_3, 0x90cfa731, 0x90cfa731 }, + { XFER_UDMA_2, 0x90caa731, 0x90caa731 }, + { XFER_UDMA_1, 0x90cba731, 0x90cba731 }, + { XFER_UDMA_0, 0x90c8a731, 0x90c8a731 }, + + { XFER_MW_DMA_2, 0xa0c8a731, 0xa0c8a731 }, + { XFER_MW_DMA_1, 0xa0c8a732, 0xa0c8a732 }, /* 0xa0c8a733 */ + { XFER_MW_DMA_0, 0xa0c8a797, 0xa0c8a797 }, + + { XFER_PIO_4, 0xc0c8a731, 0xc0c8a731 }, + { XFER_PIO_3, 0xc0c8a742, 0xc0c8a742 }, + { XFER_PIO_2, 0xc0d0a753, 0xc0d0a753 }, + { XFER_PIO_1, 0xc0d0a7a3, 0xc0d0a7a3 }, /* 0xc0d0a793 */ + { XFER_PIO_0, 0xc0d0a7aa, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ + { 0, 0x0120a7a7, 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 } + { XFER_UDMA_4, 0x90c98521, 0x90c98521 }, + { XFER_UDMA_3, 0x90cf8521, 0x90cf8521 }, + { XFER_UDMA_2, 0x90cf8521, 0x90cf8521 }, + { XFER_UDMA_1, 0x90cb8521, 0x90cb8521 }, + { XFER_UDMA_0, 0x90cb8521, 0x90cb8521 }, + + { XFER_MW_DMA_2, 0xa0ca8521, 0xa0ca8521 }, + { XFER_MW_DMA_1, 0xa0ca8532, 0xa0ca8532 }, + { XFER_MW_DMA_0, 0xa0ca8575, 0xa0ca8575 }, + + { XFER_PIO_4, 0xc0ca8521, 0xc0ca8521 }, + { XFER_PIO_3, 0xc0ca8532, 0xc0ca8532 }, + { XFER_PIO_2, 0xc0ca8542, 0xc0ca8542 }, + { XFER_PIO_1, 0xc0d08572, 0xc0d08572 }, + { XFER_PIO_0, 0xc0d08585, 0xc0d08585 }, + { 0, 0x01208585, 0x01208585 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { + { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, + { XFER_UDMA_4, 0x16454e31, 0x16454e31 }, + { XFER_UDMA_3, 0x166d4e31, 0x166d4e31 }, + { XFER_UDMA_2, 0x16494e31, 0x16494e31 }, + { XFER_UDMA_1, 0x164d4e31, 0x164d4e31 }, + { XFER_UDMA_0, 0x16514e31, 0x16514e31 }, + + { XFER_MW_DMA_2, 0x26514e21, 0x26514e21 }, + { XFER_MW_DMA_1, 0x26514e33, 0x26514e33 }, + { XFER_MW_DMA_0, 0x26514e97, 0x26514e97 }, + + { XFER_PIO_4, 0x06514e21, 0x06514e21 }, + { XFER_PIO_3, 0x06514e22, 0x06514e22 }, + { XFER_PIO_2, 0x06514e33, 0x06514e33 }, + { XFER_PIO_1, 0x06914e43, 0x06914e43 }, + { XFER_PIO_0, 0x06914e57, 0x06914e57 }, + { 0, 0x06514e57, 0x06514e57 } }; #define HPT366_DEBUG_DRIVE_INFO 0 +#define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 @@ -139,7 +177,12 @@ char *p = buffer; u32 bibma = bmide_dev->resource[4].start; u32 bibma2 = bmide2_dev->resource[4].start; + char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A"}; u8 c0 = 0, c1 = 0; + u32 class_rev; + + pci_read_config_dword(bmide_dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; /* * at that point bibma+0x2 et bibma+0xa are byte registers @@ -149,7 +192,7 @@ if (bmide2_dev) c1 = inb_p((unsigned short)bibma2 + 0x02); - p += sprintf(p, "\n HPT366 Chipset.\n"); + p += sprintf(p, "\n %s Chipset.\n", chipset_names[class_rev]); p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); p += sprintf(p, " %sabled %sabled\n", (c0&0x80) ? "dis" : " en", @@ -173,74 +216,70 @@ byte hpt363_shared_irq = 0; byte hpt363_shared_pin = 0; -static unsigned int pci_rev_check_hpt366 (struct pci_dev *dev) +static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev) { unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - return ((int) (class_rev == 0x03) ? 1 : 0); + return ((int) (class_rev > 0x02) ? 1 : 0); } static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; -#if HPT366_DEBUG_DRIVE_INFO - printk("check_in_drive_lists(%s, %p)\n", drive->name, list); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - 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; + if (quirk_drives == list) { + while (*list) { + if (strstr(id->model, *list++)) { + return 1; + } + } + } else { + while (*list) { + if (!strcmp(*list++,id->model)) { + return 1; + } } } return 0; } -static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) +static unsigned int pci_bus_clock_list (byte speed, int direction, struct chipset_bus_clock_list_entry * chipset_table) { -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list(speed=0x%02x, table=%p)\n", speed, chipset_table); -#endif /* HPT366_DEBUG_DRIVE_INFO */ for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list: found match: 0x%08x\n", chipset_table->chipset_settings); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return chipset_table->chipset_settings; + return (direction) ? chipset_table->chipset_settings_write : chipset_table->chipset_settings_read; } -#if HPT366_DEBUG_DRIVE_INFO - printk("pci_bus_clock_list: using default: 0x%08x\n", 0x01208585); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - return 0x01208585; + return (direction) ? chipset_table->chipset_settings_write : chipset_table->chipset_settings_read; } -static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) +static void hpt366_tune_chipset (ide_drive_t *drive, byte speed, int direction) { - int err; byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; + byte regfast = (HWIF(drive)->channel) ? 0x52 : 0x51; unsigned int reg1 = 0; unsigned int reg2 = 0; + byte drive_fast = 0; -#if HPT366_DEBUG_DRIVE_INFO - printk("hpt366_tune_chipset(%s, speed=0x%02x)\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast); + if (drive_fast & 0x02) + pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20); pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); /* detect bus speed by looking at control reg timing: */ switch((reg1 >> 8) & 7) { case 5: - reg2 = pci_bus_clock_list(speed, forty_base); + reg2 = pci_bus_clock_list(speed, direction, forty_base); break; case 9: - reg2 = pci_bus_clock_list(speed, twenty_five_base); + reg2 = pci_bus_clock_list(speed, direction, twenty_five_base); break; default: - printk("hpt366: assuming 33Mhz PCI bus\n"); case 7: - reg2 = pci_bus_clock_list(speed, thirty_three_base); + reg2 = pci_bus_clock_list(speed, direction, thirty_three_base); break; } /* @@ -254,18 +293,56 @@ reg2 &= ~0x80000000; pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); - err = ide_config_drive_speed(drive, speed); +} + +static void hpt370_tune_chipset (ide_drive_t *drive, byte speed, int direction) +{ + byte regfast = (HWIF(drive)->channel) ? 0x52 : 0x51; + byte reg5bh = (direction) ? 0x20 : 0x22; + unsigned int list_conf = pci_bus_clock_list(speed, direction, thirty_three_base_hpt370); + unsigned int drive_conf = 0; + unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + byte drive_pci = 0; + byte drive_fast = 0; + + switch (drive->dn) { + case 0: drive_pci = 0x40; break; + case 1: drive_pci = 0x44; break; + case 2: drive_pci = 0x48; break; + case 3: drive_pci = 0x4c; break; + default: return; + } + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x80); + + pci_read_config_dword(HWIF(drive)->pci_dev, drive_pci, &drive_conf); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x5b, reg5bh); + + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + /* + * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) + */ + list_conf &= ~0x80000000; + pci_write_config_dword(HWIF(drive)->pci_dev, drive_pci, list_conf); +} + +static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) +{ if (!drive->init_speed) drive->init_speed = speed; -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n", - drive->name, speed, ide_xfer_verbose(speed), - drive->dn, reg1, reg2, err); -#endif /* HPT366_DEBUG_DRIVE_INFO */ + if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + hpt370_tune_chipset(drive, speed, 0); + } else { + hpt366_tune_chipset(drive, speed, 0); + } drive->current_speed = speed; - return(err); + return ((int) ide_config_drive_speed(drive, speed)); } static void config_chipset_for_pio (ide_drive_t *drive) @@ -274,9 +351,6 @@ unsigned short xfer_pio = drive->id->eide_pio_modes; byte timing, speed, pio; -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_pio\n", drive->name); -#endif /* HPT366_DEBUG_DRIVE_INFO */ pio = ide_get_best_pio_mode(drive, 255, 5, NULL); if (xfer_pio> 4) @@ -306,13 +380,10 @@ speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; } -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_pio: speed=0x%04x\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - (void) hpt366_tune_chipset(drive, speed); + (void) hpt3xx_tune_chipset(drive, speed); } -static void hpt366_tune_drive (ide_drive_t *drive, byte pio) +static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio) { byte speed; switch(pio) { @@ -322,7 +393,7 @@ case 1: speed = XFER_PIO_1;break; default: speed = XFER_PIO_0;break; } - (void) hpt366_tune_chipset(drive, speed); + (void) hpt3xx_tune_chipset(drive, speed); } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -341,18 +412,24 @@ { struct hd_driveid *id = drive->id; byte speed = 0x00; - byte reg51h = 0; + byte ultra66 = eighty_ninty_three(drive); int rval; - 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 & 0x0020) && + (!check_in_drive_lists(drive, bad_ata100_5)) && + (HPT370_ALLOW_ATA100_5) && + (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) && + (ultra66)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && + (!check_in_drive_lists(drive, bad_ata66_4)) && + (HPT366_ALLOW_ATA66_4) && + (ultra66)) { 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)) { + (ultra66)) { speed = XFER_UDMA_3; } else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) { if (id->dma_ultra & 0x0004) { @@ -368,52 +445,56 @@ speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: returning 'ide_dma_off_quietly'\n", drive->name); -#endif /* HPT366_DEBUG_DRIVE_INFO */ + } else { return ((int) ide_dma_off_quietly); } - pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); - -#ifdef CONFIG_HPT366_FIP - /* - * Some drives prefer/allow for the method of handling interrupts. - */ - if (!(reg51h & 0x80)) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80); -#else /* ! CONFIG_HPT366_FIP */ - /* - * Disable the "fast interrupt" prediction. - * Instead, always wait for the real interrupt from the drive! - */ - if (reg51h & 0x80) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); -#endif /* CONFIG_HPT366_FIP */ -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: speed=0x%04x\n", drive->name, speed); -#endif /* HPT366_DEBUG_DRIVE_INFO */ - (void) hpt366_tune_chipset(drive, speed); + (void) hpt3xx_tune_chipset(drive, speed); - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 11) & 7) ? 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); - -#if HPT366_DEBUG_DRIVE_INFO - printk("%s: config_chipset_for_dma: returning %d (%s)\n", drive->name, rval, rval == ide_dma_on ? "dma_on" : "dma_off"); -#endif /* HPT366_DEBUG_DRIVE_INFO */ return rval; } +int hpt3xx_quirkproc (ide_drive_t *drive) +{ + return ((int) check_in_drive_lists(drive, quirk_drives)); +} + +void hpt3xx_intrproc (ide_drive_t *drive) +{ +} + +void hpt3xx_maskproc (ide_drive_t *drive, int mask) +{ + if (drive->quirk_list) { + if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + byte reg5a = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5a); + if (((reg5a & 0x10) >> 4) != mask) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + } else { + if (mask) { + disable_irq(HWIF(drive)->irq); + } else { + enable_irq(HWIF(drive)->irq); + } + } + } else { + if (IDE_CONTROL_REG) + OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); + } +} + +void hpt370_rw_proc (ide_drive_t *drive, ide_dma_action_t func) +{ + if ((func != ide_dma_write) || (func != ide_dma_read)) + return; + hpt370_tune_chipset(drive, drive->current_speed, (func == ide_dma_write)); +} + static int config_drive_xfer_rate (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -427,7 +508,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -436,8 +517,7 @@ } } else if (id->field_valid & 2) { try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { + if (id->dma_mword & 0x0007) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) @@ -472,24 +552,39 @@ */ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { - byte reg50h = 0; + byte reg50h = 0, reg52h = 0, reg5ah = 0; switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_lostirq: -#if 0 - pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03); pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - /* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */ -#endif + pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); + pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5ah); + printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", + drive->name, + ide_dmafunc_verbose(func), + reg50h, reg52h, reg5ah); + if (reg5ah & 0x10) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10); + break; case ide_dma_timeout: default: break; } return ide_dmaproc(func, drive); /* use standard DMA stuff */ } + +int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} #endif /* CONFIG_BLK_DEV_IDEDMA */ unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) @@ -519,7 +614,7 @@ if (!hpt366_proc) { hpt366_proc = 1; bmide_dev = dev; - if (pci_rev_check_hpt366(dev)) + if (pci_rev_check_hpt3xx(dev)) bmide2_dev = dev; hpt366_display_info = &hpt366_get_info; } @@ -546,14 +641,24 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif) { - if (pci_rev_check_hpt366(hwif->pci_dev)) return; - - hwif->tuneproc = &hpt366_tune_drive; - hwif->speedproc = &hpt366_tune_chipset; + hwif->tuneproc = &hpt3xx_tune_drive; + hwif->speedproc = &hpt3xx_tune_chipset; + hwif->quirkproc = &hpt3xx_quirkproc; + hwif->intrproc = &hpt3xx_intrproc; + hwif->maskproc = &hpt3xx_maskproc; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { - hwif->dmaproc = &hpt366_dmaproc; + if (pci_rev_check_hpt3xx(hwif->pci_dev)) { + byte reg5ah = 0; + pci_read_config_byte(hwif->pci_dev, 0x5a, ®5ah); + if (reg5ah & 0x10) /* interrupt force enable */ + pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10); + hwif->dmaproc = &hpt370_dmaproc; + hwif->rwproc = &hpt370_rw_proc; + } else { + hwif->dmaproc = &hpt366_dmaproc; + } hwif->autodma = 1; } else { hwif->autodma = 0; @@ -571,19 +676,16 @@ { byte masterdma = 0, slavedma = 0; byte dma_new = 0, dma_old = inb(dmabase+2); + byte primary = hwif->channel ? 0x4b : 0x43; + byte secondary = hwif->channel ? 0x4f : 0x47; unsigned long flags; - if (pci_rev_check_hpt366(hwif->pci_dev)) { - ide_setup_dma(hwif, dmabase, 8); - return; - } - __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ dma_new = dma_old; - pci_read_config_byte(hwif->pci_dev, 0x43, &masterdma); - pci_read_config_byte(hwif->pci_dev, 0x47, &slavedma); + pci_read_config_byte(hwif->pci_dev, primary, &masterdma); + pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); if (masterdma & 0x30) dma_new |= 0x20; if (slavedma & 0x30) dma_new |= 0x40; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-cd.c linux.ac/drivers/ide/ide-cd.c --- linux.vanilla/drivers/ide/ide-cd.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ide-cd.c Sat May 27 15:37:02 2000 @@ -1524,7 +1524,7 @@ memset(&pc, 0, sizeof(pc)); pc.sense = sense; pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; - pc.c[4] = lockflag ? 3 : 0; + pc.c[4] = lockflag ? 1 : 0; stat = cdrom_queue_packet_command (drive, &pc); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-disk.c linux.ac/drivers/ide/ide-disk.c --- linux.vanilla/drivers/ide/ide-disk.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ide-disk.c Sat Jun 10 22:00:34 2000 @@ -1,14 +1,13 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.09 April 23, 1999 + * linux/drivers/ide/ide-disk.c Version 1.10 June 9, 2000 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ /* * Mostly written by Mark Lord - * and Gadi Oxman - * - * See linux/MAINTAINERS for address of current maintainer. + * and Gadi Oxman + * and Andre Hedrick * * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c. * @@ -27,9 +26,10 @@ * the entire disk. * Version 1.09 added increment of rq->sector in ide_multwrite * added UDMA 3/4 reporting + * Version 1.10 request queue changes, Ultra DMA 100 */ -#define IDEDISK_VERSION "1.09" +#define IDEDISK_VERSION "1.10" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -140,11 +140,8 @@ int i; unsigned int msect, nsect; struct request *rq; -#if 0 - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, "read_intr", stat); - } -#else /* new way for dealing with premature shared PCI interrupts */ + + /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { return ide_error(drive, "read_intr", stat); @@ -153,7 +150,6 @@ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } -#endif msect = drive->mult_count; read_next: @@ -688,7 +684,6 @@ { if (ide_spin_wait_hwgroup(drive)) return -EBUSY; - drive->nowerr = arg; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; spin_unlock_irq(&io_request_lock); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-dma.c linux.ac/drivers/ide/ide-dma.c --- linux.vanilla/drivers/ide/ide-dma.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ide-dma.c Sat Jun 10 22:00:34 2000 @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/ide-dma.c Version 4.09 April 23, 1999 + * linux/drivers/ide/ide-dma.c Version 4.10 June 9, 2000 * - * Copyright (c) 1999 Andre Hedrick + * Copyright (c) 1999-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License */ @@ -70,12 +70,11 @@ * * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports. * - * ACARD ATP850UF Chipset "Modified SCSI Class" with other names - * AEC6210 U/UF - * SIIG's UltraIDE Pro CN-2449 - * TTI HPT343 Chipset "Modified SCSI Class" but reports as an - * unknown storage device. - * NEW check_drive_lists(ide_drive_t *drive, int good_bad) + * check_drive_lists(ide_drive_t *drive, int good_bad) + * + * ATA-66/100 and recovery functions, I forgot the rest...... + * SELECT_READ_WRITE(hwif,drive,func) for active tuning based on IO direction. + * */ #include @@ -358,10 +357,11 @@ { struct hd_driveid *id = drive->id; - if ((id->field_valid & 4) && (id->hw_config & 0x2000) && - (HWIF(drive)->udma_four) && - (id->dma_ultra & (id->dma_ultra >> 11) & 3)) { - if ((id->dma_ultra >> 12) & 1) { + if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && + (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { + if ((id->dma_ultra >> 13) & 1) { + printk(", UDMA(100)"); /* UDMA BIOS-enabled! */ + } else if ((id->dma_ultra >> 12) & 1) { printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ } else { printk(", UDMA(44)"); /* UDMA BIOS-enabled! */ @@ -393,9 +393,9 @@ if (ide_dmaproc(ide_dma_bad_drive, drive)) return hwif->dmaproc(ide_dma_off, drive); - /* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */ - if ((id->field_valid & 4) && (hwif->udma_four) && (id->hw_config & 0x2000)) - if ((id->dma_ultra & (id->dma_ultra >> 11) & 3)) + /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */ + if ((id->field_valid & 4) && (eighty_ninty_three(drive))) + if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) return hwif->dmaproc(ide_dma_on, drive); /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */ if (id->field_valid & 4) /* UltraDMA */ @@ -413,6 +413,22 @@ } /* + * 1 dmaing, 2 error, 4 intr + */ +static int dma_timer_expiry (ide_drive_t *drive) +{ + byte dma_stat = inb(HWIF(drive)->dma_base+2); + +#ifdef DEBUG + printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); +#endif /* DEBUG */ + + if (dma_stat & 1) /* DMAing */ + return WAIT_CMD; + return 0; +} + +/* * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. * * The caller is assumed to have selected the drive and programmed the drive's @@ -451,6 +467,7 @@ case ide_dma_read: reading = 1 << 3; case ide_dma_write: + SELECT_READ_WRITE(hwif,drive,func); if (!(count = ide_build_dmatable(drive, func))) return 1; /* try PIO instead of DMA */ outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ @@ -459,7 +476,7 @@ drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); case ide_dma_begin: /* Note that this is done *after* the cmd has @@ -570,8 +587,8 @@ if (hwif->mate && hwif->mate->dma_base) { dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); } else { - dma_base = dev->resource[4].start; - if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) { + dma_base = pci_resource_start(dev, 4); + if (!dma_base) { printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base); dma_base = 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-features.c linux.ac/drivers/ide/ide-features.c --- linux.vanilla/drivers/ide/ide-features.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/ide-features.c Sat Jun 10 22:00:34 2000 @@ -1,14 +1,16 @@ /* - * linux/drivers/block/ide-features.c Version 0.03 Feb. 10, 2000 + * linux/drivers/block/ide-features.c Version 0.04 June 9, 2000 * * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) * - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1999-2000 Andre Hedrick * * Extracts if ide.c to address the evolving transfer rate code for * the SETFEATURES_XFER callouts. Various parts of any given function * are credited to previous ATA-IDE maintainers. * + * Auto-CRC downgrade for Ultra DMA(ing) + * * May be copied or modified under the terms of the GNU General Public License */ @@ -115,6 +117,10 @@ */ byte ide_auto_reduce_xfer (ide_drive_t *drive) { + if (!drive->crc_count) + return drive->current_speed; + drive->crc_count = 0; + switch(drive->current_speed) { case XFER_UDMA_7: return XFER_UDMA_6; case XFER_UDMA_6: return XFER_UDMA_5; @@ -164,6 +170,7 @@ probe_irq_off(probe_irq_on()); irqs = probe_irq_on(); + SELECT_MASK(HWIF(drive), drive, 1); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); ide_delay_50ms(); @@ -173,17 +180,20 @@ if (0 < (signed long)(jiffies - timeout)) { if (irqs) (void) probe_irq_off(irqs); + SELECT_MASK(HWIF(drive), drive, 0); return 0; /* drive timed-out */ } ide_delay_50ms(); /* give drive a breather */ } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + SELECT_MASK(HWIF(drive), drive, 0); printk("%s: CHECK for good STATUS\n", drive->name); return 0; } __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only; some systems need this */ + SELECT_MASK(HWIF(drive), drive, 0); id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); ide_input_data(drive, id, SECTOR_WORDS); (void) GET_STAT(); /* clear drive IRQ */ @@ -214,11 +224,15 @@ (nsect > XFER_UDMA_2) && (feature == SETFEATURES_XFER)) { if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name); + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name); return 1; } +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ if ((drive->id->hw_config & 0x2000) == 0) { - printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name); +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); return 1; } } @@ -244,6 +258,18 @@ } /* + * All hosts that use the 80c ribbon mus use! + */ +byte eighty_ninty_three (ide_drive_t *drive) +{ + return ((byte) ((HWIF(drive)->udma_four) && +#ifndef CONFIG_IDEDMA_IVB + (drive->id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x2000)) ? 1 : 0); +} + +/* * Similar to ide_wait_stat(), except it never calls ide_error internally. * This is a kludge to handle the new ide_config_drive_speed() function, * and should not otherwise be used anywhere. Eventually, the tuneproc's @@ -260,10 +286,11 @@ int i, error = 1; byte stat; -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) byte unit = (drive->select.b.unit & 0x01); outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -276,6 +303,7 @@ disable_irq(hwif->irq); /* disable_irq_nosync ?? */ udelay(1); SELECT_DRIVE(HWIF(drive), drive); + SELECT_MASK(HWIF(drive), drive, 0); udelay(1); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); @@ -315,6 +343,8 @@ } } + SELECT_MASK(HWIF(drive), drive, 0); + enable_irq(hwif->irq); if (error) { @@ -326,13 +356,13 @@ drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) if (speed > XFER_PIO_4) { outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); } else { outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); } -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ switch(speed) { case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; @@ -358,5 +388,5 @@ EXPORT_SYMBOL(ide_driveid_update); EXPORT_SYMBOL(ide_ata66_check); EXPORT_SYMBOL(set_transfer); +EXPORT_SYMBOL(eighty_ninty_three); EXPORT_SYMBOL(ide_config_drive_speed); - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-geometry.c linux.ac/drivers/ide/ide-geometry.c --- linux.vanilla/drivers/ide/ide-geometry.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/ide-geometry.c Wed May 31 11:20:21 2000 @@ -3,7 +3,7 @@ */ #include -#if defined(CONFIG_IDE) && !defined(CONFIG_BLK_DEV_HD) +#if defined(CONFIG_IDE) && !defined(CONFIG_BLK_DEV_HD_ONLY) #include #include @@ -211,4 +211,4 @@ drive->bios_cyl, drive->bios_head, drive->bios_sect); return ret; } -#endif /* (CONFIG_IDE) && !(CONFIG_BLK_DEV_HD) */ +#endif /* (CONFIG_IDE) && !(CONFIG_BLK_DEV_HD_ONLY) */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-pci.c linux.ac/drivers/ide/ide-pci.c --- linux.vanilla/drivers/ide/ide-pci.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ide-pci.c Sat Jun 10 22:00:34 2000 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-pci.c Version 1.04 July 27, 1999 + * linux/drivers/ide/ide-pci.c Version 1.05 June 9, 2000 * * Copyright (c) 1998-2000 Andre Hedrick * @@ -33,10 +33,13 @@ #define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) #define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) #define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) +#define DEVID_PIIX4NX ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX}) +#define DEVID_PIIX4U3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_5}) #define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) +#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267}) #define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) #define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001}) #define DEVID_SAMURAI ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE}) @@ -44,6 +47,7 @@ #define DEVID_CMD643 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643}) #define DEVID_CMD646 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646}) #define DEVID_CMD648 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648}) +#define DEVID_CMD649 ((ide_pci_devid_t){PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649}) #define DEVID_SIS5513 ((ide_pci_devid_t){PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513}) #define DEVID_OPTI621 ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621}) #define DEVID_OPTI621V ((ide_pci_devid_t){PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558}) @@ -65,6 +69,7 @@ #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}) #define DEVID_CS5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) +#define DEVID_AMD7403 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7403}) #define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409}) #define IDE_IGNORE ((void *)-1) @@ -288,7 +293,7 @@ typedef struct ide_pci_device_s { ide_pci_devid_t devid; - const char *name; + char *name; unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); unsigned int (*ata66_check)(ide_hwif_t *hwif); void (*init_hwif)(ide_hwif_t *hwif); @@ -307,10 +312,13 @@ {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U3, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, @@ -320,6 +328,7 @@ {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, @@ -338,6 +347,7 @@ {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AMD7403, "AMD7403", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_AMD7409, "AMD7409", PCI_AMD7409, ATA66_AMD7409, INIT_AMD7409, DMA_AMD7409, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; @@ -352,6 +362,7 @@ case PCI_DEVICE_ID_TTI_HPT366: case PCI_DEVICE_ID_PROMISE_20246: case PCI_DEVICE_ID_PROMISE_20262: + case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_ARTOP_ATP850UF: case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: @@ -510,6 +521,14 @@ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; + + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { + /* see comments in hpt34x.c on why..... */ + char *chipset_names[] = {"HPT343", "HPT345"}; + strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY)]); + d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; + } + printk("%s: chipset revision %d\n", d->name, class_rev); /* @@ -541,10 +560,7 @@ printk("%s: 100%% native mode on irq %d\n", d->name, pciirq); #endif } - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } + /* * Set up the IDE ports */ @@ -553,14 +569,14 @@ 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) && (class_rev != 0x03)) + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) return; if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { ctl = dev->resource[(2*port)+1].start; base = dev->resource[2*port].start; if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); + printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); #if 0 /* FIXME! This really should check that it really gets the IO/MEM part right! */ continue; @@ -603,19 +619,21 @@ goto bypass_umc_dma; } if (hwif->udma_four) { - printk("%s: ATA-66 forced bit set (WARNING)!!\n", d->name); + printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); } else { hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; } #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) autodma = 0; if (autodma) hwif->autodma = 1; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || @@ -625,6 +643,7 @@ IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) || ((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); if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) { @@ -665,6 +684,7 @@ ide_pci_device_t *d2; unsigned char pin1 = 0, pin2 = 0; unsigned int class_rev; + char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A"}; if (PCI_FUNC(dev->devfn) & 1) return; @@ -672,8 +692,13 @@ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; + strcpy(d->name, chipset_names[class_rev]); + switch(class_rev) { - case 3: return; + case 4: + case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + return; default: break; } @@ -700,15 +725,6 @@ return; d2 = d; printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - if (hpt363_shared_pin && !hpt363_shared_irq) { - printk("%s: IDE controller run unsupported mode three!!!\n", d2->name); -#ifndef CONFIG_HPT366_MODE3 - printk("%s: IDE controller report to \n", d->name); - return; -#else /* CONFIG_HPT366_MODE3 */ - printk("%s: OVERRIDE IDE controller not advisable this mode!!!\n", d2->name); -#endif /* CONFIG_HPT366_MODE3 */ - } ide_setup_pci_device(dev2, d2); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-pmac.c linux.ac/drivers/ide/ide-pmac.c --- linux.vanilla/drivers/ide/ide-pmac.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ide-pmac.c Fri Jun 9 15:55:20 2000 @@ -813,12 +813,6 @@ return 0; } -static int -pmac_ide_tune_chipset(ide_drive_t *drive, byte speed) -{ - return 0; -} - int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide-probe.c linux.ac/drivers/ide/ide-probe.c --- linux.vanilla/drivers/ide/ide-probe.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/ide-probe.c Sat Jun 10 22:00:34 2000 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-probe.c Version 1.05 July 3, 1999 + * linux/drivers/ide/ide-probe.c Version 1.06 June 9, 2000 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -7,6 +7,7 @@ /* * Mostly written by Mark Lord * and Gadi Oxman + * and Andre Hedrick * * See linux/MAINTAINERS for address of current maintainer. * @@ -23,6 +24,7 @@ * added ide6/7/8/9 * allowed for secondary flash card to be detectable * with new flag : drive->ata_flash : 1; + * Version 1.06 stream line request queue and prep for cascade project. */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -41,6 +43,7 @@ #include #include #include +#include #include #include @@ -167,6 +170,7 @@ } drive->media = ide_disk; printk("ATA DISK drive\n"); + QUIRK_LIST(HWIF(drive),drive); return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ide.c linux.ac/drivers/ide/ide.c --- linux.vanilla/drivers/ide/ide.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/ide.c Sat Jun 10 22:00:34 2000 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide.c Version 6.30 Dec 28, 1999 + * linux/drivers/ide/ide.c Version 6.31 June 9, 2000 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -7,6 +7,7 @@ /* * Mostly written by Mark Lord * and Gadi Oxman + * and Andre Hedrick * * See linux/MAINTAINERS for address of current maintainer. * @@ -109,6 +110,9 @@ * Version 6.21 Fixing/Fixed SMP spinlock issue with insight from an old * hat that clarified original low level driver design. * Version 6.30 Added SMP support; fixed multmode issues. -ml + * Version 6.31 Debug Share INTR's and request queue streaming + * Native ATA-100 support + * Prep for Cascades Project * * Some additional driver compile-time options are in ./include/linux/ide.h * @@ -117,8 +121,8 @@ * */ -#define REVISION "Revision: 6.30" -#define VERSION "Id: ide.c 6.30 1999/12/28" +#define REVISION "Revision: 6.31" +#define VERSION "Id: ide.c 6.31 2000/06/09" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -482,7 +486,8 @@ #if 0 udelay(1); /* need to guarantee 400ns since last command was issued */ #endif - if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */ +// if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */ + if (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT) return 0; /* drive busy: definitely not interrupting */ return 1; /* drive ready: *might* be interrupting */ } @@ -651,6 +656,19 @@ return ide_stopped; } +static void check_dma_crc (ide_drive_t *drive) +{ + if (drive->crc_count) { + (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive); + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); + if (drive->current_speed >= XFER_SW_DMA_0) + (void) HWIF(drive)->dmaproc(ide_dma_on, drive); + } else { + (void) HWIF(drive)->dmaproc(ide_dma_off, drive); + } +} + static void pre_reset (ide_drive_t *drive) { if (drive->driver != NULL) @@ -658,12 +676,15 @@ if (!drive->keep_settings) { if (drive->using_dma) { - (void) HWIF(drive)->dmaproc(ide_dma_off, drive); + check_dma_crc(drive); } else { drive->unmask = 0; drive->io_32bit = 0; } + return; } + if (drive->using_dma) + check_dma_crc(drive); } /* @@ -902,9 +923,9 @@ if (err == ABRT_ERR) { if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) return ide_stopped; /* some newer drives don't support WIN_SPECIFY */ - } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) - ; /* UDMA crc error -- just retry the operation */ - else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ + } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { + drive->crc_count++; /* UDMA crc error -- just retry the operation */ + } else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */ rq->errors = ERROR_MAX; else if (err & TRK0_ERR) /* help it find track zero */ rq->errors |= ERROR_RECAL; @@ -941,6 +962,7 @@ ide_set_handler (drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive),drive,0); OUT_BYTE(nsect,IDE_NSECTOR_REG); OUT_BYTE(cmd,IDE_COMMAND_REG); } @@ -1298,7 +1320,7 @@ hwif = HWIF(drive); if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) { /* set nIEN for previous hwif */ - OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]); + SELECT_INTERRUPT(hwif, drive); } hwgroup->hwif = hwif; hwgroup->drive = drive; @@ -1316,13 +1338,13 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (hwif->irq != masked_irq) + if (masked_irq && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&io_request_lock); ide__sti(); /* allow other IRQs while we start this request */ startstop = start_request(drive); spin_lock_irq(&io_request_lock); - if (hwif->irq != masked_irq) + if (masked_irq && hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_stopped) hwgroup->busy = 0; @@ -1404,7 +1426,11 @@ */ spin_unlock(&io_request_lock); hwif = HWIF(drive); +#if DISABLE_IRQ_NOSYNC + disable_irq_nosync(hwif->irq); +#else disable_irq(hwif->irq); /* disable_irq_nosync ?? */ +#endif /* DISABLE_IRQ_NOSYNC */ __cli(); /* local CPU only, as if we were handling an interrupt */ if (hwgroup->poll_timeout != 0) { startstop = handler(drive); @@ -2008,12 +2034,12 @@ else hwgroup->hwif = HWIF(hwgroup->drive); -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) if (hwif->dma_base) { (void) ide_release_dma(hwif); hwif->dma_base = 0; } -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ /* * Remove us from the kernel's knowledge @@ -2048,6 +2074,10 @@ hwif->speedproc = old_hwif.speedproc; hwif->selectproc = old_hwif.selectproc; hwif->resetproc = old_hwif.resetproc; + hwif->intrproc = old_hwif.intrproc; + hwif->maskproc = old_hwif.maskproc; + hwif->quirkproc = old_hwif.quirkproc; + hwif->rwproc = old_hwif.rwproc; hwif->dmaproc = old_hwif.dmaproc; hwif->dma_base = old_hwif.dma_base; hwif->dma_extra = old_hwif.dma_extra; @@ -2275,17 +2305,18 @@ unsigned long timeout = jiffies + (3 * HZ); spin_lock_irq(&io_request_lock); + while (hwgroup->busy) { - unsigned long flags; + unsigned long lflags; spin_unlock_irq(&io_request_lock); - __save_flags(flags); /* local CPU only */ + __save_flags(lflags); /* local CPU only */ __sti(); /* local CPU only; needed for jiffies */ if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); + __restore_flags(lflags); /* local CPU only */ printk("%s: channel busy\n", drive->name); return -EBUSY; } - __restore_flags(flags); /* local CPU only */ + __restore_flags(lflags); /* local CPU only */ spin_lock_irq(&io_request_lock); } return 0; @@ -2422,13 +2453,13 @@ */ void ide_delay_50ms (void) { -#if 0 +#ifndef CONFIG_BLK_DEV_IDECS unsigned long timeout = jiffies + ((HZ + 19)/20) + 1; while (0 < (signed long)(timeout - jiffies)); #else __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/20); -#endif +#endif /* CONFIG_BLK_DEV_IDECS */ } int system_bus_clock (void) @@ -2576,7 +2607,6 @@ err = -EFAULT; return err; } - case HDIO_SCAN_HWIF: { int args[3]; @@ -3266,6 +3296,7 @@ if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) { ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */ disable_irq(ide_hwifs[0].irq); /* disable_irq_nosync ?? */ +// disable_irq_nosync(ide_hwifs[0].irq); } #endif /* __mc68000__ || CONFIG_APUS */ @@ -3619,10 +3650,10 @@ for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ } #ifdef CONFIG_PROC_FS diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/ns87415.c linux.ac/drivers/ide/ns87415.c --- linux.vanilla/drivers/ide/ns87415.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/ns87415.c Sat Jun 10 22:00:34 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 1998 Eddie C. Dost - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1999-2000 Andre Hedrick * * Inspired by an earlier effort from David S. Miller */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/pdc202xx.c linux.ac/drivers/ide/pdc202xx.c --- linux.vanilla/drivers/ide/pdc202xx.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/pdc202xx.c Sat Jun 10 22:00:34 2000 @@ -1,7 +1,7 @@ /* * linux/drivers/ide/pdc202xx.c Version 0.30 Mar. 18, 2000 * - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1998-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this @@ -12,6 +12,8 @@ * Promise Ultra66 cards with BIOS v1.11 this * compiled into the kernel if you have more than one card installed. * + * Promise Ultra100 cards. + * * The latest chipset code will support the following :: * Three Ultra33 controllers and 12 drives. * 8 are UDMA supported and 4 are limited to DMA mode 2 multi-word. @@ -51,6 +53,10 @@ #define DISPLAY_PDC202XX_TIMINGS +#ifndef SPLIT_BYTE +#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) +#endif + #if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -99,10 +105,25 @@ { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0; u16 reg50h = 0, pmask = (1<<10), smask = (1<<11); - u8 c0 = 0, c1 = 0; + u8 hi = 0, lo = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + u8 c0 = inb_p((unsigned short)bibma + 0x02); + u8 c1 = inb_p((unsigned short)bibma + 0x0a); + + u8 sc11 = inb_p((unsigned short)bibma + 0x11); + u8 sc1a = inb_p((unsigned short)bibma + 0x1a); + u8 sc1b = inb_p((unsigned short)bibma + 0x1b); + u8 sc1c = inb_p((unsigned short)bibma + 0x1c); + u8 sc1d = inb_p((unsigned short)bibma + 0x1d); + u8 sc1e = inb_p((unsigned short)bibma + 0x1e); + u8 sc1f = inb_p((unsigned short)bibma + 0x1f); pci_read_config_word(bmide_dev, 0x50, ®50h); pci_read_config_dword(bmide_dev, 0x60, ®60h); @@ -110,14 +131,10 @@ pci_read_config_dword(bmide_dev, 0x68, ®68h); pci_read_config_dword(bmide_dev, 0x6c, ®6ch); - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - switch(bmide_dev->device) { + switch(bmide_dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + p += sprintf(p, "\n PDC20267 Chipset.\n"); + break; case PCI_DEVICE_ID_PROMISE_20262: p += sprintf(p, "\n PDC20262 Chipset.\n"); break; @@ -130,9 +147,40 @@ break; } + p += sprintf(p, "------------------------------- General Status ---------------------------------\n"); + p += sprintf(p, "Burst Mode : %sabled\n", (sc1f & 0x01) ? "en" : "dis"); + p += sprintf(p, "Host Mode : %s\n", (sc1f & 0x08) ? "Tri-Stated" : "Normal"); + p += sprintf(p, "Bus Clocking : %s\n", + ((sc1f & 0xC0) == 0xC0) ? "100 External" : + ((sc1f & 0x80) == 0x80) ? "66 External" : + ((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal"); + p += sprintf(p, "IO pad select : %s mA\n", + ((sc1c & 0x03) == 0x03) ? "10" : + ((sc1c & 0x02) == 0x02) ? "8" : + ((sc1c & 0x01) == 0x01) ? "6" : + ((sc1c & 0x00) == 0x00) ? "4" : "??"); + SPLIT_BYTE(sc1e, hi, lo); + p += sprintf(p, "Status Polling Period : %d\n", hi); + p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo); p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80)?"dis":" en",(c1&0x80)?"dis":" en"); + p += sprintf(p, " %s %s\n", + (c0&0x80)?"disabled":"enabled ", + (c1&0x80)?"disabled":"enabled "); + p += sprintf(p, "66 Clocking %s %s\n", + (sc11&0x02)?"enabled ":"disabled", + (sc11&0x08)?"enabled ":"disabled"); + p += sprintf(p, " Mode %s Mode %s\n", + (sc1a & 0x01) ? "MASTER" : "PCI ", + (sc1b & 0x01) ? "MASTER" : "PCI "); + p += sprintf(p, " %s %s\n", + (sc1d & 0x08) ? "Error " : + (sc1d & 0x04) ? "Interrupting" : + (sc1d & 0x02) ? "FIFO Full " : + (sc1d & 0x01) ? "FIFO Empty " : "????????????", + (sc1d & 0x80) ? "Error " : + (sc1d & 0x40) ? "Interrupting" : + (sc1d & 0x20) ? "FIFO Full " : + (sc1d & 0x10) ? "FIFO Empty " : "????????????"); p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); p += sprintf(p, "DMA enabled: %s %s %s %s\n", (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); @@ -141,9 +189,13 @@ pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)), pdc202xx_ultra_verbose(reg68h, (reg50h & smask)), pdc202xx_ultra_verbose(reg6ch, (reg50h & smask))); - p += sprintf(p, " PIO Mode: %s %s %s %s\n", + p += sprintf(p, "PIO Mode: %s %s %s %s\n", pdc202xx_pio_verbose(reg60h),pdc202xx_pio_verbose(reg64h), pdc202xx_pio_verbose(reg68h),pdc202xx_pio_verbose(reg6ch)); +#if 0 + p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n"); +#endif + return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ @@ -324,6 +376,7 @@ switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; /* speed 8 == UDMA mode 4 */ case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; /* speed 7 == UDMA mode 3 */ case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; /* speed 6 == UDMA mode 2 */ @@ -408,7 +461,7 @@ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; + unsigned long high_16 = pci_resource_start(dev, 4); unsigned long dma_base = hwif->dma_base; byte unit = (drive->select.b.unit & 0x01); @@ -418,8 +471,9 @@ byte AP; unsigned short EP; byte CLKSPD = IN_BYTE(high_16 + 0x11); - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0; + byte udma_66 = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0; + byte udma_100 = ((dev->device == PCI_DEVICE_ID_PROMISE_20267) && udma_66) ? 1 : 0; /* * Set the control register to use the 66Mhz system @@ -436,11 +490,15 @@ byte mask = hwif->channel ? 0x08 : 0x02; unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); - byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; + byte ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + byte ultra_100 = ((id->dma_ultra & 0x0020) || + (id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; pci_read_config_word(dev, 0x50, &EP); - if ((ultra_66) && (EP & c_mask)) { + if (((ultra_66) || (ultra_100)) && (EP & c_mask)) { #ifdef DEBUG printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary", "Primary"); printk(" Switching to Ultra33 mode.\n"); @@ -449,13 +507,14 @@ /* Secondary : zero out fourth bit */ OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); } else { - if (ultra_66) { + if ((ultra_66) || (ultra_100)) { /* * check to make sure drive on same channel * is u66 capable */ if (hwif->drives[!(drive->dn%2)].id) { - if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || + if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0020) || + (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) { OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); } else { @@ -517,17 +576,18 @@ if (drive->media == ide_disk) /* PREFETCH_EN */ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) speed = XFER_UDMA_4; - else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) speed = XFER_UDMA_3; - else if ((id->dma_ultra & 0x0004) && (udma_33)) speed = XFER_UDMA_2; - else if ((id->dma_ultra & 0x0002) && (udma_33)) speed = XFER_UDMA_1; - else if ((id->dma_ultra & 0x0001) && (udma_33)) speed = XFER_UDMA_0; - else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; - else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; - else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; - else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2; - else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1; - else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0; + if ((id->dma_ultra & 0x0020) && (udma_100)) speed = XFER_UDMA_5; + else if ((id->dma_ultra & 0x0010) && (udma_66)) speed = XFER_UDMA_4; + else if ((id->dma_ultra & 0x0008) && (udma_66)) speed = XFER_UDMA_3; + else if ((id->dma_ultra & 0x0004) && (udma_33)) speed = XFER_UDMA_2; + else if ((id->dma_ultra & 0x0002) && (udma_33)) speed = XFER_UDMA_1; + else if ((id->dma_ultra & 0x0001) && (udma_33)) speed = XFER_UDMA_0; + else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; + else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; + else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; + else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2; + else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1; + else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0; else { /* restore original pci-config space */ pci_write_config_dword(dev, drive_pci, drive_conf); @@ -537,7 +597,7 @@ outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); (void) pdc202xx_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 7) ? 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 : @@ -558,7 +618,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, 1); if ((id->field_valid & 2) && @@ -603,6 +663,10 @@ switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); + case ide_dma_lostirq: + case ide_dma_timeout: + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); default: break; } @@ -610,14 +674,29 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ +void pdc202xx_reset (ide_drive_t *drive) +{ + unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); + byte udma_speed_flag = inb(high_16 + 0x001f); + int i = 0; + + OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); + ide_delay_50ms(); + ide_delay_50ms(); + OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); + for (i = 0; i < 40; i++) + ide_delay_50ms(); +} + unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) { - unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; + unsigned long high_16 = pci_resource_start(dev, 4); byte udma_speed_flag = inb(high_16 + 0x001f); byte primary_mode = inb(high_16 + 0x001a); byte secondary_mode = inb(high_16 + 0x001b); - if (dev->device == PCI_DEVICE_ID_PROMISE_20262) { + if ((dev->device == PCI_DEVICE_ID_PROMISE_20262) || + (dev->device == PCI_DEVICE_ID_PROMISE_20267)) { int i = 0; /* * software reset - this is required because the bios @@ -646,7 +725,7 @@ byte irq = 0, irq2 = 0; pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */ - if (irq != irq2) { + if ((irq != irq2) && (dev->device != PCI_DEVICE_ID_PROMISE_20267)) { pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */ printk("%s: pci-config space interrupt mirror fixed.\n", name); } @@ -705,8 +784,12 @@ void __init ide_init_pdc202xx (ide_hwif_t *hwif) { - hwif->tuneproc = &pdc202xx_tune_drive; - hwif->speedproc = &pdc202xx_tune_chipset; + hwif->tuneproc = &pdc202xx_tune_drive; + hwif->speedproc = &pdc202xx_tune_chipset; + + if ((hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20262) || + (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267)) + hwif->resetproc = &pdc202xx_reset; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/piix.c linux.ac/drivers/ide/piix.c --- linux.vanilla/drivers/ide/piix.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/piix.c Sat Jun 10 22:00:34 2000 @@ -1,8 +1,8 @@ /* - * linux/drivers/ide/piix.c Version 0.31 Mar. 18, 2000 + * linux/drivers/ide/piix.c Version 0.32 June 9, 2000 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1998-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * PIO mode setting function for Intel chipsets. @@ -83,7 +83,7 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = bmide_dev->resource[4].start; + u32 bibma = pci_resource_start(bmide_dev, 4); u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; u8 c0 = 0, c1 = 0; u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; @@ -108,10 +108,14 @@ c1 = inb_p((unsigned short)bibma + 0x0a); switch(bmide_dev->device) { + case PCI_DEVICE_ID_INTEL_82820FW_5: + p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n"); + break; case PCI_DEVICE_ID_INTEL_82372FB_1: case PCI_DEVICE_ID_INTEL_82801AA_1: p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n"); break; + case PCI_DEVICE_ID_INTEL_82451NX: case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82371AB: @@ -142,21 +146,25 @@ (reg48&0x04) ? "yes" : "no ", (reg48&0x08) ? "yes" : "no " ); p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + ((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" : ((reg54&0x11) && (reg4a&0x02)) ? "4" : ((reg54&0x11) && (reg4a&0x01)) ? "3" : (reg4a&0x02) ? "2" : (reg4a&0x01) ? "1" : (reg4a&0x00) ? "0" : "X", + ((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" : ((reg54&0x22) && (reg4a&0x20)) ? "4" : ((reg54&0x22) && (reg4a&0x10)) ? "3" : (reg4a&0x20) ? "2" : (reg4a&0x10) ? "1" : (reg4a&0x00) ? "0" : "X", + ((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" : ((reg54&0x44) && (reg4b&0x02)) ? "4" : ((reg54&0x44) && (reg4b&0x01)) ? "3" : (reg4b&0x02) ? "2" : (reg4b&0x01) ? "1" : (reg4b&0x00) ? "0" : "X", + ((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" : ((reg54&0x88) && (reg4b&0x20)) ? "4" : ((reg54&0x88) && (reg4b&0x10)) ? "3" : (reg4b&0x20) ? "2" : @@ -188,6 +196,7 @@ */ static byte piix_dma_2_pio (byte xfer_rate) { switch(xfer_rate) { + case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: @@ -286,6 +295,7 @@ switch(speed) { case XFER_UDMA_4: case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: case XFER_UDMA_3: case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; @@ -298,7 +308,11 @@ if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); - pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); + if (speed == XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); + } if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_write_config_word(dev, 0x4a, reg4a|u_speed); @@ -341,15 +355,20 @@ struct pci_dev *dev = hwif->pci_dev; byte speed; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || + byte udma_66 = eighty_ninty_three(drive); + int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82820FW_5)) ? 1 : 0; + int ultra66 = ((ultra100) || + (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; int ultra = ((ultra66) || (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) || + (dev->device == PCI_DEVICE_ID_INTEL_82451NX) || (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; - if ((id->dma_ultra & 0x0010) && (ultra)) { + if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && (ultra)) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; } else if ((id->dma_ultra & 0x0008) && (ultra)) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; @@ -371,7 +390,7 @@ (void) piix_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 7) ? 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 : diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/qd6580.c linux.ac/drivers/ide/qd6580.c --- linux.vanilla/drivers/ide/qd6580.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/qd6580.c Sat Jun 10 22:00:34 2000 @@ -1,16 +1,19 @@ /* - * linux/drivers/ide/qd6580.c Version 0.03 May 13, 2000 + * linux/drivers/ide/qd6580.c Version 0.04 June 4, 2000 * * Copyright (C) 1996-2000 Linus Torvalds & author (see below) */ /* * Version 0.03 Cleaned auto-tune, added probe - * + * Version 0.04 Added second channel tuning + * * QDI QD6580 EIDE controller fast support - * + * * To activate controller support use kernel parameter "ide0=qd6580" * To enable tuning use kernel parameter "ide0=autotune" + * To enable tuning second channel (not really tested), + * use parameter "ide1=autotune" */ /* @@ -36,146 +39,254 @@ #include "ide_modes.h" /* - * I/O ports are 0xb0 0xb1 0xb2 and 0xb3 - * or 0x30 0x31 0x32 and 0x33 + * I/O ports are 0xb0-0xb3 + * or 0x30-0x33 * -- this is a dual IDE interface with I/O chips * * More research on qd6580 being done by willmore@cig.mot.com (David) + * More Information given by Petr Sourcek (petr@ryston.cz) + * http://www.ryston.cz/petr/vlb */ -/* +/* * 0xb0: Timer1 * - * - * 0xb1: Status * - * && 0xf0 is either 0b1010000 or 0b01010000, or else it isn't a qd6580 - * bit 3 & 2: unknown (useless ?) I have 0 & 1, respectively - * bit 1: 1 if qd6580 baseport is 0xb0 - * 0 if qd6580 baseport is 0x30 - * bit 0: 1 if ide baseport is 0x1f0 - * 0 if ide baseport is 0x170 + * 0xb1: Config + * + * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 * (? Strange: the Dos driver uses it, and then forces baseport to 0x1f0 ?) - * - * + * bit 1: qd baseport: 1 = 0xb0 ; 0 = 0x30 + * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz + * bit 3: 1 for qd6580 + * upper nibble is either 1010 or 0101, or else it isn't a qd6580 + * + * * 0xb2: Timer2 * - * + * * 0xb3: Control * - * bits 0-3 are always set 1 - * bit 6 : if 1, must be set 1 - * bit 1 : if 1, bit 7 must be set 1 - * bit 0 : if 1, drives are independant, we can have two different timers for - * the two drives. - * if 0, we have to take the slowest drive into account, - * but we may tune the second hwif ? + * bits 0-3 must always be set 1 + * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock + * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb + * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb + * channel 1 for hdc & hdd + * bit 1 : 1 = only disks on primary port + * 0 = disks & ATAPI devices on primary port + * bit 2-4 : always 0 + * bit 5 : status, but of what ? + * bit 6 : always set 1 by dos driver + * bit 7 : set 1 for non-ATAPI devices (read-ahead and post-write buffer ?) */ +/* truncates a in [b,c] */ +#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) + typedef struct ide_hd_timings_s { int active_time; /* Active pulse (ns) minimum */ int recovery_time; /* Recovery pulse (ns) minimum */ } ide_hd_timings_t; static int basePort; /* base port address (0x30 or 0xb0) */ -static byte status; /* status register of qd6580 */ +static byte config; /* config register of qd6580 */ static byte control; /* control register of qd6580 */ -/* truncates a in [b,c] */ -#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) - static int bus_clock; /* Vesa local bus clock (ns) */ static int tuned=0; /* to remember whether we've already been tuned */ +static int snd_tuned=0; /* to remember whether we've already been tuned */ +static int nb_disks_prim=0; /* number of disk drives on primary port */ + +/* + * write_reg + * + * writes the specified byte on the specified register + */ + +static void write_reg ( byte content, byte reg ) +{ + unsigned long flags; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + outb_p(content,reg); + inb(0x3f6); + restore_flags(flags); /* all CPUs */ +} /* * tune_drive * - * Finds timings for the specified drive, returns it in struc t + * Finds timings for the specified drive, returns it in struct t */ -static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t) +static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t ) { ide_pio_data_t d; - t->active_time = 0xaf; - t->recovery_time = 0x19f; /* worst cases values from the dos driver */ + t->active_time = 175; + t->recovery_time = 415; /* worst cases values from the dos driver */ - if (drive->present == 0) { /* not present : free to give any timing */ - t->active_time = 0x0; - t->recovery_time = 0x0; + if (!drive->present) { /* not present : free to give any timing */ + t->active_time = 0; + t->recovery_time = 0; return; } - - pio = ide_get_best_pio_mode(drive, pio, 4, &d); - if (pio) { - - switch (pio) { - case 0: break; - case 3: t->active_time = 0x56; - t->recovery_time = d.cycle_time-0x66; - break; - case 4: t->active_time = 0x46; - t->recovery_time = d.cycle_time-0x3d; - break; - default: if (d.cycle_time >= 0xb4) { - t->active_time = 0x6e; - t->recovery_time = d.cycle_time - 0x78; - } else { - t->active_time = ide_pio_timings[pio].active_time; - t->recovery_time = d.cycle_time - -t->active_time - -ide_pio_timings[pio].setup_time; - } - } - } + pio = ide_get_best_pio_mode(drive, pio, 255, &d); + pio = IDE_MIN(pio,4); + + switch (pio) { + case 0: break; + case 3: + if (d.cycle_time >= 110) { + t->active_time = 86; + t->recovery_time = d.cycle_time-102; + } else { + printk("%s: Strange recovery time !\n",drive->name); + return; + } + break; + case 4: + if (d.cycle_time >= 69) { + t->active_time = 70; + t->recovery_time = d.cycle_time-61; + } else { + printk("%s: Strange recovery time !\n",drive->name); + return; + } + break; + default: + if (d.cycle_time >= 180) { + t->active_time = 110; + t->recovery_time = d.cycle_time - 120; + } else { + t->active_time = ide_pio_timings[pio].active_time; + t->recovery_time = d.cycle_time + -t->active_time; + } + } printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time); + + if (drive->media == ide_disk) + nb_disks_prim++; + else { +/* need to disable read-ahead FIFO and post-write buffer for ATAPI drives*/ + write_reg(0x5f,basePort+0x03); + printk("%s: Warning: please try to connect this drive to secondary IDE port\nto improve data transfer rate on primary IDE port.\n",drive->name); + } } -/* +/* + * tune_snd_drive + * + * Finds timings for the specified drive, using second channel rules + */ + +static void tune_snd_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t ) +{ + ide_pio_data_t d; + + t->active_time = 175; + t->recovery_time = 415; + + if (!drive->present) { /* not present : free to give any timing */ + t->active_time = 0; + t->recovery_time = 0; + return; + } + + pio = ide_get_best_pio_mode(drive, pio, 255, &d); + + if ((pio) && (d.cycle_time >= 180)) { + t->active_time = 115; + t->recovery_time = d.cycle_time - 115; + } + printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time); + + if ((drive->media == ide_disk) && (nb_disks_prim<2)) { +/* a disk drive on secondary port while there's room on primary, which is the + * only one that has read-ahead fifo and post-write buffer ? What a waste !*/ + printk("%s: Warning: please try to connect this drive to primary IDE port\nto improve data transfer rate.\n",drive->name); + } +} + +/* + * compute_timing + * + * computes the timing value where + * lower nibble is active time, in count of VLB clocks, 17-(from 2 to 17) + * upper nibble is recovery time, in count of VLB clocks, 15-(from 2 to 15) + */ + +static byte compute_timing ( char name[6], ide_hd_timings_t *t ) +{ + byte active_cycle; + byte recovery_cycle; + byte parameter; + + active_cycle = 17-IDE_IN(t->active_time / bus_clock + 1, 2, 17); + recovery_cycle = 15-IDE_IN(t->recovery_time / bus_clock + 1, 2, 15); + + parameter = active_cycle | (recovery_cycle<<4); + + printk("%s: tim1=%dns tim2=%dns => %#x\n", name, t[0].active_time, t[0].recovery_time, parameter); + return(parameter); +} + +/* * tune_ide * - * Tunes the whole ide, ie tunes each drives, and takes the worst timings - * to tune qd6580 + * Tunes the whole hwif, ie tunes each drives, and in case we have to share, + * takes the worse timings to tune qd6580 */ static void tune_ide ( ide_hwif_t *hwif, byte pio ) { unsigned long flags; ide_hd_timings_t t[2]={{0,0},{0,0}}; - - byte active_cycle; - byte recovery_cycle; - byte parameter; int bus_speed = ide_system_bus_speed (); - + bus_clock = 1000 / bus_speed; - + save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ outb( (bus_clock<30) ? 0x0 : 0x0a, basePort + 0x02); outb( 0x40 | ((control & 0x02) ? 0x9f:0x1f), basePort+0x03); - restore_flags(flags); + restore_flags(flags); tune_drive (&hwif->drives[0], pio, &t[0]); tune_drive (&hwif->drives[1], pio, &t[1]); + if (control & 0x01) { /* only primary port enabled, can tune separately */ + write_reg(compute_timing (hwif->drives[0].name, &t[0]),basePort); + write_reg(compute_timing (hwif->drives[1].name, &t[1]),basePort+0x02); + } else { /* both ports enabled, we have to share */ + + t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time); + t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time); + write_reg(compute_timing (hwif->name, &t[0]),basePort); + } +} + +/* + * tune_snd_ide + * + * Tunes the whole secondary hwif, ie tunes each drives, and takes the worse + * timings to tune qd6580 + */ + +static void tune_snd_ide ( ide_hwif_t *hwif, byte pio ) +{ + ide_hd_timings_t t[2]={{0,0},{0,0}}; + + tune_snd_drive (&hwif->drives[0], pio, &t[0]); + tune_snd_drive (&hwif->drives[1], pio, &t[1]); + t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time); t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time); - - active_cycle = 17-IDE_IN(t[0].active_time / bus_clock + 1, 2, 17); - recovery_cycle = 15-IDE_IN(t[0].recovery_time / bus_clock + 1, 2, 15); - - parameter=active_cycle | (recovery_cycle<<4); - - printk("%s: tim1=%dns tim2=%dns => %#x\n", hwif->name, t[0].active_time, t[0].recovery_time, parameter); - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb_p(parameter,0xb0); - inb(0x3f6); - restore_flags(flags); /* all CPUs */ - + + write_reg(compute_timing (hwif->name, &t[0]),basePort+0x02); } /* @@ -193,6 +304,20 @@ } /* + * tune_snd_qd6580 + * + * tunes the second hwif if not tuned + */ + +static void tune_snd_qd6580 (ide_drive_t *drive, byte pio) +{ + if (! snd_tuned) { + tune_snd_ide(HWIF(drive), pio); + snd_tuned = 1; + } +} + +/* * testreg * * tests if the given port is a register @@ -203,7 +328,7 @@ byte savereg; byte readreg; unsigned long flags; - + save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ savereg = inb(port); @@ -214,14 +339,15 @@ if (savereg == 0x15) { printk("Outch ! the probe for qd6580 isn't reliable !\n"); - printk("Please contact samuel.thibault@fnac.net to tell about your hardware\n"); - printk("Assuming qd6580 is present"); + printk("Please contact maintainers to tell about your hardware\n"); + printk("Assuming qd6580 is not present.\n"); + return 0; } return (readreg == 0x15); } -/* +/* * trybase: * * tries to find a qd6580 at the given base and save it if found @@ -233,20 +359,20 @@ save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ - status = inb(base+0x01); + config = inb(base+0x01); control = inb(base+0x03); restore_flags(flags); /* all CPUs */ - if (((status & 0xf0) != 0x50) && ((status & 0xf0) != 0xa0)) return(0); - if (! ( ((status & 0x02) == 0x0) == (base == 0x30) ) ) return (0); + if (((config & 0xf0) != 0x50) && ((config & 0xf0) != 0xa0)) return(0); + if (! ( ((config & 0x02) == 0x0) == (base == 0x30) ) ) return (0); /* Seems to be OK, let's use it */ - + basePort = base; return(testreg(base)); } -/* +/* * probe: * * probes qd6580 at 0xb0 (the default) or 0x30 @@ -257,6 +383,11 @@ return (trybase(0xb0) ? 1 : trybase(0x30)); } +/* + * init_qd6580: + * + * called at the very beginning of initialization ; should just probe and link + */ void __init init_qd6580 (void) { @@ -264,13 +395,16 @@ printk("qd6580: not found\n"); return; } - - printk("qd6580: base=%#x, status=%#x, control=%#x\n", basePort, status, control); - + + printk("qd6580: base=%#x, config=%#x, control=%#x\n", basePort, config, control); + ide_hwifs[0].chipset = ide_qd6580; - ide_hwifs[1].chipset = ide_qd6580; ide_hwifs[0].tuneproc = &tune_qd6580; - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; + if (!(control & 0x01)) { + ide_hwifs[1].chipset = ide_qd6580; + ide_hwifs[1].tuneproc = &tune_snd_qd6580; + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].channel = 1; + } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/sis5513.c linux.ac/drivers/ide/sis5513.c --- linux.vanilla/drivers/ide/sis5513.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/sis5513.c Sat Jun 10 22:00:34 2000 @@ -1,7 +1,7 @@ /* - * linux/drivers/ide/sis5513.c Version 0.10 Mar. 18, 2000 + * linux/drivers/ide/sis5513.c Version 0.11 June 9, 2000 * - * Copyright (C) 1999-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1999-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * Thanks to SIS Taiwan for direct support and hardware. @@ -111,12 +111,12 @@ extern int (*sis_display_info)(char *, char **, off_t, int); /* ide-proc.c */ static struct pci_dev *bmide_dev; -static char *cable_type[] __initdata = { +static char *cable_type[] = { "80 pins", "40 pins" }; -static char *recovery_time [] __initdata ={ +static char *recovery_time [] ={ "12 PCICLK", "1 PCICLK", "2 PCICLK", "3 PCICLK", "4 PCICLK", "5 PCICLCK", @@ -127,14 +127,14 @@ "15 PCICLK", "15 PCICLK" }; -static char * cycle_time [] __initdata = { +static char * cycle_time [] = { "Undefined", "2 CLCK", "3 CLK", "4 CLK", "5 CLK", "6 CLK", "7 CLK", "8 CLK" }; -static char * active_time [] __initdata = { +static char * active_time [] = { "8 PCICLK", "1 PCICLCK", "2 PCICLK", "2 PCICLK", "4 PCICLK", "5 PCICLK", @@ -185,7 +185,7 @@ p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", - active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + active_time[(reg & 0x07)], active_time[(reg1 &0x07)] ); rc = pci_read_config_byte(bmide_dev, 0x40, ®); rc = pci_read_config_byte(bmide_dev, 0x44, ®1); @@ -209,7 +209,7 @@ p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", - active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + active_time[(reg & 0x07)], active_time[(reg1 &0x07)] ); rc = pci_read_config_byte(bmide_dev, 0x42, ®); rc = pci_read_config_byte(bmide_dev, 0x46, ®1); @@ -335,7 +335,7 @@ #ifdef CONFIG_BLK_DEV_IDEDMA /* - * ((id->hw_config & 0x2000) && (HWIF(drive)->udma_four)) + * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) { @@ -349,7 +349,7 @@ unsigned long dma_base = hwif->dma_base; byte unit = (drive->select.b.unit & 0x01); byte speed = 0x00, unmask = 0xE0, four_two = 0x00; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; + byte udma_66 = eighty_ninty_three(drive); if (host_dev) { switch(host_dev->device) { @@ -536,7 +536,7 @@ pci_read_config_byte(dev, 0x52, ®52h); if (!(reg52h & 0x04)) { - /* set IDE controller to operate in Compabitility mode obly */ + /* set IDE controller to operate in Compabitility mode only */ pci_write_config_byte(dev, 0x52, reg52h|0x04); } #if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/trm290.c linux.ac/drivers/ide/trm290.c --- linux.vanilla/drivers/ide/trm290.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/ide/trm290.c Tue May 30 15:17:17 2000 @@ -224,10 +224,10 @@ struct pci_dev *dev = hwif->pci_dev; hwif->chipset = ide_trm290; - cfgbase = dev->resource[4].start; + cfgbase = pci_resource_start(dev, 4); if ((dev->class & 5) && cfgbase) { - hwif->config_data = cfgbase & PCI_BASE_ADDRESS_IO_MASK; + hwif->config_data = cfgbase; printk("TRM290: chip config base at 0x%04lx\n", hwif->config_data); } else { hwif->config_data = 0x3df0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ide/via82cxxx.c linux.ac/drivers/ide/via82cxxx.c --- linux.vanilla/drivers/ide/via82cxxx.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/ide/via82cxxx.c Sat Jun 10 22:10:57 2000 @@ -1,10 +1,10 @@ /* - * linux/drivers/ide/via82cxxx.c Version 0.09 Apr. 02, 2000 + * linux/drivers/ide/via82cxxx.c Version 0.10 June 9, 2000 * * Copyright (C) 1998-99 Michel Aubry, Maintainer * Copyright (C) 1999 Jeff Garzik, MVP4 Support * (jgarzik@mandrakesoft.com) - * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com) + * Copyright (C) 1998-2000 Andre Hedrick * May be copied or modified under the terms of the GNU General Public License * * The VIA MVP-4 is reported OK with UDMA. @@ -101,19 +101,19 @@ struct chipset_bus_clock_list_entry { byte xfer_speed; - byte chipset_settings_25; byte ultra_settings_25; - byte chipset_settings_33; + byte chipset_settings_25; byte ultra_settings_33; - byte chipset_settings_37; + byte chipset_settings_33; byte ultra_settings_37; - byte chipset_settings_41; + byte chipset_settings_37; byte ultra_settings_41; + byte chipset_settings_41; }; static struct chipset_bus_clock_list_entry * via82cxxx_table = NULL; -struct chipset_bus_clock_list_entry via82cxxx_type_one [] = { +static struct chipset_bus_clock_list_entry via82cxxx_type_one [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ #ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -134,7 +134,7 @@ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA9, 0x00, 0x00 } }; -struct chipset_bus_clock_list_entry via82cxxx_type_two [] = { +static struct chipset_bus_clock_list_entry via82cxxx_type_two [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ #ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -155,7 +155,7 @@ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE } }; -struct chipset_bus_clock_list_entry via82cxxx_type_three [] = { +static struct chipset_bus_clock_list_entry via82cxxx_type_three [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ #ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -176,7 +176,7 @@ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE } }; -struct chipset_bus_clock_list_entry via82cxxx_type_four [] = { +static struct chipset_bus_clock_list_entry via82cxxx_type_four [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ #ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0xE0, 0x20, 0xE1, 0x31, 0x00, 0x00 }, @@ -243,20 +243,20 @@ #define arraysize(x) (sizeof(x)/sizeof(*(x))) -#undef DISPLAY_VIA_TIMINGS +#define DISPLAY_VIA_TIMINGS #if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) #include #include -static char *FIFO_str[] __initdata = { +static char *FIFO_str[] = { " 1 ", "3/4", "1/2", "1/4" }; -static char *control3_str[] __initdata = { +static char *control3_str[] = { "No limitation", "64", "128", @@ -760,11 +760,15 @@ { struct hd_driveid *id = drive->id; byte speed = 0x00; + byte ultra66 = eighty_ninty_three(drive); + byte ultra100 = 0; int rval; - if ((id->dma_ultra & 0x0010) && (HWIF(drive)->udma_four)) { + if ((id->dma_ultra & 0x0020) && (ultra66) && (ultra100)) { + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0010) && (ultra66)) { speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (HWIF(drive)->udma_four)) { + } else if ((id->dma_ultra & 0x0008) && (ultra66)) { speed = XFER_UDMA_3; } else if (id->dma_ultra & 0x0004) { speed = XFER_UDMA_2; @@ -778,12 +782,6 @@ speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; } else { return ((int) ide_dma_off_quietly); } @@ -793,7 +791,6 @@ rval = (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); return rval; } @@ -811,7 +808,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -820,8 +817,7 @@ } } else if (id->field_valid & 2) { try_dma_modes: - if ((id->dma_mword & 0x0007) || - (id->dma_1word & 0x0007)) { + if (id->dma_mword & 0x0007) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) @@ -870,7 +866,7 @@ byte revision = 0; for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { - host = pci_find_device (PCI_VENDOR_ID_VIA, + host = pci_find_device (ApolloHostChipInfo[i].vendor_id, ApolloHostChipInfo[i].host_id, NULL); if (!host) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/Makefile linux.ac/drivers/ieee1394/Makefile --- linux.vanilla/drivers/ieee1394/Makefile Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/Makefile Sun Jun 4 21:50:42 2000 @@ -25,15 +25,13 @@ OX_OBJS := ifeq ($(CONFIG_IEEE1394),y) -L_OBJS += ieee1394.o hosts.o highlevel.o csr.o -O_TARGET = ieee1394.o -O_OBJS += ieee1394_core.o ieee1394_transactions.o -OX_OBJS += ieee1394_syms.o +L_OBJS += ieee1394_core.o ieee1394_transactions.o hosts.o highlevel.o csr.o guid.o +LX_OBJS += ieee1394_syms.o else ifeq ($(CONFIG_IEEE1394),m) M_OBJS += ieee1394.o O_TARGET = ieee1394.o - O_OBJS += ieee1394_core.o ieee1394_transactions.o hosts.o highlevel.o csr.o + O_OBJS += ieee1394_core.o ieee1394_transactions.o hosts.o highlevel.o csr.o guid.o OX_OBJS += ieee1394_syms.o endif endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/aic5800.c linux.ac/drivers/ieee1394/aic5800.c --- linux.vanilla/drivers/ieee1394/aic5800.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/aic5800.c Sat Jun 10 21:42:15 2000 @@ -723,14 +723,17 @@ static int add_card(struct pci_dev *dev) { -#define FAIL(fmt, args...) \ +#define FAIL(fmt, args...) do {\ PRINT_G(KERN_ERR, fmt , ## args); \ num_of_cards--; \ remove_card(aic); \ - return 1; + return 1; } while (0) struct aic5800 *aic; /* shortcut to currently handled device */ unsigned long page; + + if (pci_enable_device(dev)) + return 1; if (num_of_cards == MAX_AIC5800_CARDS) { PRINT_G(KERN_WARNING, "cannot handle more than %d cards. " diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/guid.c linux.ac/drivers/ieee1394/guid.c --- linux.vanilla/drivers/ieee1394/guid.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/ieee1394/guid.c Sun Jun 4 21:50:42 2000 @@ -0,0 +1,226 @@ +/* + * IEEE 1394 for Linux + * + * GUID collection and management + * + * Copyright (C) 2000 Andreas E. Bombe + */ + +#include +#include +#include +#include +#include + +#include "ieee1394_types.h" +#include "ieee1394.h" +#include "hosts.h" +#include "ieee1394_transactions.h" +#include "highlevel.h" +#include "csr.h" + + +static atomic_t outstanding_requests; + +static LIST_HEAD(guid_list); +rwlock_t guid_lock = RW_LOCK_UNLOCKED; + +struct guid_entry { + struct list_head list; + atomic_t refcount; + + u64 guid; + + struct hpsb_host *host; + nodeid_t node_id; + + atomic_t generation; +}; + +struct guid_req { + struct hpsb_packet *pkt; + struct tq_struct tq; +}; + + +static struct guid_entry *create_guid_entry(void) +{ + struct guid_entry *ge; + unsigned long flags; + + ge = kmalloc(sizeof(struct guid_entry), SLAB_ATOMIC); + if (!ge) return NULL; + + INIT_LIST_HEAD(&ge->list); + atomic_set(&ge->refcount, 0); + ge->guid = (u64) -1; + ge->host = NULL; + ge->node_id = 0; + atomic_set(&ge->generation, -1); + + write_lock_irqsave(&guid_lock, flags); + list_add_tail(&ge->list, &guid_list); + write_unlock_irqrestore(&guid_lock, flags); + + return ge; +} + +static struct guid_entry *find_entry(u64 guid) +{ + struct list_head *lh; + struct guid_entry *ge; + + lh = guid_list.next; + while (lh != &guid_list) { + ge = list_entry(lh, struct guid_entry, list); + if (ge->guid == guid) return ge; + lh = lh->next; + } + + return NULL; +} + +static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid) +{ + struct guid_entry *ge; + unsigned long flags; + + HPSB_DEBUG("node %d on host 0x%p has GUID 0x%08x%08x", + nodeid & NODE_MASK, host, (unsigned int)(guid >> 32), + (unsigned int)(guid & 0xffffffff)); + + read_lock_irqsave(&guid_lock, flags); + ge = find_entry(guid); + read_unlock_irqrestore(&guid_lock, flags); + + if (!ge) ge = create_guid_entry(); + if (!ge) return; + + ge->host = host; + ge->node_id = nodeid; + ge->guid = guid; + + atomic_set(&ge->generation, get_hpsb_generation()); +} + +static void pkt_complete(struct guid_req *req) +{ + struct hpsb_packet *pkt = req->pkt; + int rcode = (pkt->header[1] >> 12) & 0xf; + + if (pkt->ack_code == ACK_PENDING && rcode == RCODE_COMPLETE) { + if (*(char *)pkt->data > 1) { + associate_guid(pkt->host, pkt->node_id, + ((u64)be32_to_cpu(pkt->data[3]) << 32) + | be32_to_cpu(pkt->data[4])); + } else { + HPSB_DEBUG("minimal ROM on node %d", + pkt->node_id & NODE_MASK); + } + } else { + HPSB_DEBUG("guid transaction error: ack %d, rcode %d", + pkt->ack_code, rcode); + } + + free_tlabel(pkt->host, pkt->node_id, pkt->tlabel); + free_hpsb_packet(pkt); + kfree(req); + + if (atomic_dec_and_test(&outstanding_requests)) { + /* FIXME: free unreferenced and inactive GUID entries. */ + } +} + + +static void host_reset(struct hpsb_host *host) +{ + struct guid_req *greq; + struct hpsb_packet *pkt; + struct selfid *sid = (struct selfid *)host->topology_map; + int nodecount = host->node_count; + nodeid_t nodeid = LOCAL_BUS; + + for (; nodecount; nodecount--, nodeid++, sid++) { + while (sid->extended) sid++; + if (!sid->link_active) continue; + if (nodeid == host->node_id) continue; + + greq = kmalloc(sizeof(struct guid_req), SLAB_ATOMIC); + if (!greq) { + HPSB_ERR("out of memory in GUID processing"); + return; + } + + pkt = hpsb_make_readbpacket(host, nodeid, + CSR_REGISTER_BASE + CSR_CONFIG_ROM, + 20); + if (!pkt) { + kfree(greq); + HPSB_ERR("out of memory in GUID processing"); + return; + } + + greq->tq.next = NULL; + greq->tq.sync = 0; + greq->tq.routine = (void (*)(void*))pkt_complete; + greq->tq.data = greq; + greq->pkt = pkt; + + queue_task(&greq->tq, &pkt->complete_tq); + + if (!hpsb_send_packet(pkt)) { + free_tlabel(pkt->host, pkt->node_id, pkt->tlabel); + free_hpsb_packet(pkt); + kfree(greq); + HPSB_NOTICE("failed to send packet in GUID processing"); + } + + HPSB_INFO("GUID request sent to node %d", nodeid & NODE_MASK); + atomic_inc(&outstanding_requests); + } +} + + +struct guid_entry *hpsb_guid_get_handle(u64 guid) +{ + unsigned long flags; + struct guid_entry *ge; + + read_lock_irqsave(&guid_lock, flags); + ge = find_entry(guid); + if (ge) atomic_inc(&ge->refcount); + read_unlock_irqrestore(&guid_lock, flags); + + return ge; +} + +struct hpsb_host *hpsb_guid_localhost(struct guid_entry *ge) +{ + if (atomic_read(&ge->generation) != get_hpsb_generation()) return NULL; + if (ge->node_id == ge->host->node_id) return ge->host; + return NULL; +} + +int hpsb_guid_fill_packet(struct guid_entry *ge, struct hpsb_packet *pkt) +{ + if (atomic_read(&ge->generation) != get_hpsb_generation()) return 0; + + pkt->host = ge->host; + pkt->node_id = ge->node_id; + pkt->generation = atomic_read(&ge->generation); + return 1; +} + + +static struct hpsb_highlevel_ops guid_ops = { + host_reset: host_reset, +}; + +void init_ieee1394_guid(void) +{ + atomic_set(&outstanding_requests, 0); + + if (!hpsb_register_highlevel("GUID manager", &guid_ops)) { + HPSB_ERR("out of memory during ieee1394 initialization"); + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/guid.h linux.ac/drivers/ieee1394/guid.h --- linux.vanilla/drivers/ieee1394/guid.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/ieee1394/guid.h Sun Jun 4 21:50:42 2000 @@ -0,0 +1,54 @@ + +#ifndef _IEEE1394_GUID_H +#define _IEEE1394_GUID_H + + +/* + * General information: Finding out which GUID belongs to which node is done by + * sending packets and therefore waiting for the answers. Wherever it is + * mentioned that a node is inaccessible this could just as well mean that we + * just don't know yet (usually, bus reset handlers can't rely on GUIDs being + * associated with current nodes). + */ + +struct guid_entry; +typedef struct guid_entry *hpsb_guid_t; + + +/* + * Returns a guid handle (which has its reference count incremented) or NULL if + * there is the GUID in question is not known of. Getting a valid handle does + * not mean that the node with this GUID is currently accessible (might not be + * plugged in or powered down). + */ +hpsb_guid_t hpsb_guid_get_handle(u64 guid); + +/* + * If the handle refers to a local host, this function will return the pointer + * to the hpsb_host structure. It will return NULL otherwise. Once you have + * established it is a local host, you can use that knowledge from then on (the + * GUID won't wander to an external node). + * + * Note that the local GUID currently isn't collected, so this will always + * return NULL. + */ +struct hpsb_host *hpsb_guid_localhost(hpsb_guid_t handle); + +/* + * This will fill in the given, pre-initialised hpsb_packet with the current + * information from the GUID handle (host, node ID, generation number). It will + * return false if the node owning the GUID is not accessible (and not modify the + * hpsb_packet) and return true otherwise. + * + * Note that packet sending may still fail in hpsb_send_packet if a bus reset + * happens while you are trying to set up the packet (due to obsolete generation + * number). It will at least reliably fail so that you don't accidentally and + * unknowingly send your packet to the wrong node. + */ +int hpsb_guid_fill_packet(hpsb_guid_t handle, struct hpsb_packet *pkt); + + +void init_ieee1394_guid(void); + + +#endif /* _IEEE1394_GUID_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ieee1394_core.c linux.ac/drivers/ieee1394/ieee1394_core.c --- linux.vanilla/drivers/ieee1394/ieee1394_core.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ieee1394_core.c Sun Jun 4 21:50:42 2000 @@ -25,6 +25,7 @@ #include "highlevel.h" #include "ieee1394_transactions.h" #include "csr.h" +#include "guid.h" atomic_t hpsb_generation = ATOMIC_INIT(0); @@ -45,6 +46,26 @@ } +/** + * alloc_hpsb_packet - allocate new packet structure + * @data_size: size of the data block to be allocated + * + * This function allocates, initializes and returns a new &struct hpsb_packet. + * It can be used in interrupt context. A header block is always included, its + * size is big enough to contain all possible 1394 headers. The data block is + * only allocated when @data_size is not zero. + * + * For packets for which responses will be received the @data_size has to be big + * enough to contain the response's data block since no further allocation + * occurs at response matching time. + * + * The packet's generation value will be set to the current generation number + * for ease of use. Remember to overwrite it with your own recorded generation + * number if you can not be sure that your code will not race with a bus reset. + * + * Return value: A pointer to a &struct hpsb_packet or NULL on allocation + * failure. + */ struct hpsb_packet *alloc_hpsb_packet(size_t data_size) { struct hpsb_packet *packet = NULL; @@ -83,6 +104,14 @@ return packet; } + +/** + * free_hpsb_packet - free packet and data associated with it + * @packet: packet to free (is NULL safe) + * + * This function will free packet->data, packet->header and finally the packet + * itself. + */ void free_hpsb_packet(struct hpsb_packet *packet) { if (packet == NULL) { @@ -336,6 +365,20 @@ queue_task(&host->timeout_tq, &tq_timer); } +/** + * hpsb_send_packet - transmit a packet on the bus + * @packet: packet to send + * + * The packet is sent through the host specified in the packet->host field. + * Before sending, the packet's transmit speed is automatically determined using + * the local speed map. + * + * Possibilities for failure are that host is either not initialized, in bus + * reset, the packet's generation number doesn't match the current generation + * number or the host reports a transmit error. + * + * Return value: False (0) on failure, true (1) otherwise. + */ int hpsb_send_packet(struct hpsb_packet *packet) { struct hpsb_host *host = packet->host; @@ -721,47 +764,6 @@ } -#if 0 -int hpsb_host_thread(void *hostPointer) -{ - struct hpsb_host *host = (struct hpsb_host *)hostPointer; - - /* I don't understand why, but I just want to be on the safe side. */ - lock_kernel(); - - HPSB_INFO(__FUNCTION__ " starting for one %s adapter", - host->template->name); - - exit_mm(current); - exit_files(current); - exit_fs(current); - - strcpy(current->comm, "ieee1394 thread"); - - /* ... but then again, I think the following is safe. */ - unlock_kernel(); - - for (;;) { - siginfo_t info; - unsigned long signr; - - if (signal_pending(current)) { - spin_lock_irq(¤t->sigmask_lock); - signr = dequeue_signal(¤t->blocked, &info); - spin_unlock_irq(¤t->sigmask_lock); - - break; - } - - abort_timedouts(host); - } - - HPSB_INFO(__FUNCTION__ " exiting"); - return 0; -} -#endif - - #ifndef MODULE void __init ieee1394_init(void) @@ -769,6 +771,7 @@ register_builtin_lowlevels(); init_hpsb_highlevel(); init_csr(); + init_ieee1394_guid(); } #else @@ -777,6 +780,8 @@ { init_hpsb_highlevel(); init_csr(); + init_ieee1394_guid(); + return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ieee1394_syms.c linux.ac/drivers/ieee1394/ieee1394_syms.c --- linux.vanilla/drivers/ieee1394/ieee1394_syms.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ieee1394_syms.c Sun Jun 4 21:50:42 2000 @@ -8,6 +8,7 @@ #include #include +#include #include "ieee1394_types.h" #include "hosts.h" @@ -15,6 +16,7 @@ #include "ieee1394_transactions.h" /* #include "events.h" */ #include "highlevel.h" +#include "guid.h" EXPORT_SYMBOL(hpsb_register_lowlevel); EXPORT_SYMBOL(hpsb_unregister_lowlevel); @@ -52,3 +54,7 @@ EXPORT_SYMBOL(highlevel_write); EXPORT_SYMBOL(highlevel_lock); EXPORT_SYMBOL(highlevel_lock64); + +EXPORT_SYMBOL(hpsb_guid_get_handle); +EXPORT_SYMBOL(hpsb_guid_localhost); +EXPORT_SYMBOL(hpsb_guid_fill_packet); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ieee1394_transactions.c linux.ac/drivers/ieee1394/ieee1394_transactions.c --- linux.vanilla/drivers/ieee1394/ieee1394_transactions.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ieee1394_transactions.c Sun Jun 4 21:50:42 2000 @@ -132,6 +132,26 @@ } +/** + * get_tlabel - allocate a transaction label + * @host: host to be used for transmission + * @nodeid: the node ID of the transmission target + * @wait: whether to sleep if no tlabel is available + * + * Every asynchronous transaction on the 1394 bus needs a transaction label to + * match the response to the request. This label has to be different from any + * other transaction label in an outstanding request to the same node to make + * matching possible without ambiguity. + * + * There are 64 different tlabels, so an allocated tlabel has to be freed with + * free_tlabel() after the transaction is complete (unless it's reused again for + * the same target node). + * + * @wait must not be set to true if you are calling from interrupt context. + * + * Return value: The allocated transaction label or -1 if there was no free + * tlabel and @wait is false. + */ int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait) { unsigned long flags; @@ -166,6 +186,18 @@ } } +/** + * free_tlabel - free an allocated transaction label + * @host: host to be used for transmission + * @nodeid: the node ID of the transmission target + * @tlabel: the transaction label to free + * + * Frees the transaction label allocated with get_tlabel(). The tlabel has to + * be freed after the transaction is complete (i.e. response was received for a + * split transaction or packet was sent for a unified transaction). + * + * A tlabel must not be freed twice. + */ void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel) { unsigned long flags; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ieee1394_types.h linux.ac/drivers/ieee1394/ieee1394_types.h --- linux.vanilla/drivers/ieee1394/ieee1394_types.h Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ieee1394_types.h Sat Jun 10 22:52:26 2000 @@ -27,7 +27,19 @@ #define __constant_cpu_to_be32(x) __constant_htonl((x)) -#endif +#define set_current_state(state_value) \ + do { current->state = (state_value); } while (0) + +#include +inline static int pci_enable_device(struct pci_dev *dev) +{ + u16 cmd; + pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY); + return 0; +} + +#endif /* Linux version < 2.3 */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) #include @@ -39,6 +51,9 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif typedef __u32 quadlet_t; typedef __u64 octlet_t; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ohci1394.c linux.ac/drivers/ieee1394/ohci1394.c --- linux.vanilla/drivers/ieee1394/ohci1394.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ohci1394.c Sun Jun 4 21:50:42 2000 @@ -38,15 +38,25 @@ * . Self-id are sometimes not received properly * if card is initialized with no other nodes * on the bus + * . SONY CXD3222 chip is not working properly + * . Apple PowerBook detected but not working yet */ /* * Acknowledgments: * * Emilie Chung - * .Tip on Async Request Filter + * . Tip on Async Request Filter * Pascal Drolet - * .Various tips for optimization and functionnalities + * . Various tips for optimization and functionnalities + * Robert Ficklin + * . Loop in irq_handler + * James Goodwin + * . Various tips on initialization, self-id reception, etc. + * Albrecht Dress + * . Apple PowerBook detection + * Daniel Kobras + * . Reset the board properly before leaving */ #include @@ -65,6 +75,7 @@ #include #include #include +#include #include #include @@ -118,6 +129,7 @@ { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72862 }, { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72870 }, { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72871 }, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW }, { -1, -1 } }; @@ -128,7 +140,618 @@ static void remove_card(struct ti_ohci *ohci); static int init_driver(void); static void dma_trm_bh(void *data); +static void dma_rcv_bh(void *data); static void dma_trm_reset(struct dma_trm_ctx *d); +static void stop_context(struct ti_ohci *ohci, int reg, char *msg); + +#ifdef _VIDEO_1394_H + +/* Taken from bttv.c */ +/*******************************/ +/* Memory management functions */ +/*******************************/ + +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +/* [DaveM] I've recoded most of this so that: + * 1) It's easier to tell what is happening + * 2) It's more portable, especially for translating things + * out of vmalloc mapped areas in the kernel. + * 3) Less unnecessary translations happen. + * + * The code used to assume that the kernel vmalloc mappings + * existed in the page tables of every process, this is simply + * not guarenteed. We now use pgd_offset_k which is the + * defined way to get at the kernel page tables. + */ + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if(pte_present(pte)) + ret = (pte_page(pte)|(adr&(PAGE_SIZE-1))); + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long uvirt_to_bus(unsigned long adr) +{ + unsigned long kva, ret; + + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long kvirt_to_bus(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; +} + +static void * rvmalloc(unsigned long size) +{ + void * mem; + unsigned long adr, page; + + mem=vmalloc(size); + if (mem) + { + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_reserve(MAP_NR(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + } + return mem; +} + +static void rvfree(void * mem, unsigned long size) +{ + unsigned long adr, page; + + if (mem) + { + adr=(unsigned long) mem; + while (size > 0) + { + page = kvirt_to_pa(adr); + mem_map_unreserve(MAP_NR(__va(page))); + adr+=PAGE_SIZE; + size-=PAGE_SIZE; + } + vfree(mem); + } +} + +static int free_dma_fbuf_ctx(struct dma_fbuf_ctx **d) +{ + int i; + struct ti_ohci *ohci; + + if ((*d)==NULL) return -1; + + ohci = (struct ti_ohci *)(*d)->ohci; + + DBGMSG(ohci->id, "Freeing dma_fbuf_ctx %d", (*d)->ctx); + + stop_context(ohci, (*d)->ctrlClear, NULL); + + if ((*d)->buf) rvfree((void *)(*d)->buf, + (*d)->num_desc * (*d)->buf_size); + + if ((*d)->prg) { + for (i=0;i<(*d)->num_desc;i++) + if ((*d)->prg[i]) kfree((*d)->prg[i]); + kfree((*d)->prg); + } + + if ((*d)->buffer_status) + kfree((*d)->buffer_status); + + kfree(*d); + *d = NULL; + + return 0; +} + +static struct dma_fbuf_ctx * +alloc_dma_fbuf_ctx(struct ti_ohci *ohci, int ctx, int num_desc, + int buf_size, int channel) +{ + struct dma_fbuf_ctx *d=NULL; + int i; + + d = (struct dma_fbuf_ctx *)kmalloc(sizeof(struct dma_fbuf_ctx), + GFP_KERNEL); + + if (d==NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma_fbuf_ctx"); + return NULL; + } + + d->ohci = (void *)ohci; + d->ctx = ctx; + d->channel = channel; + d->num_desc = num_desc; + d->frame_size = buf_size; + if (buf_size%PAGE_SIZE) + d->buf_size = buf_size + PAGE_SIZE - (buf_size%PAGE_SIZE); + else + d->buf_size = buf_size; + d->ctrlSet = OHCI1394_IrRcvContextControlSet+32*d->ctx; + d->ctrlClear = OHCI1394_IrRcvContextControlClear+32*d->ctx; + d->cmdPtr = OHCI1394_IrRcvCommandPtr+32*d->ctx; + d->ctxMatch = OHCI1394_IrRcvContextMatch+32*d->ctx; + d->nb_cmd = d->buf_size / PAGE_SIZE + 1; + d->last_buffer = 0; + d->buf = NULL; + d->prg = NULL; + init_waitqueue_head(&d->waitq); + + d->buf = rvmalloc(d->num_desc * d->buf_size); + + if (d->buf == NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuffer"); + free_dma_fbuf_ctx(&d); + return NULL; + } + memset(d->buf, 0, d->num_desc * d->buf_size); + + d->prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *), + GFP_KERNEL); + + if (d->prg == NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg"); + free_dma_fbuf_ctx(&d); + return NULL; + } + memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd *)); + + for (i=0;inum_desc;i++) { + d->prg[i] = kmalloc(d->nb_cmd * sizeof(struct dma_cmd), + GFP_KERNEL); + if (d->prg[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "failed to allocate dma fbuf prg"); + free_dma_fbuf_ctx(&d); + return NULL; + } + } + + d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int), + GFP_KERNEL); + + if (d->buffer_status == NULL) { + PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg"); + free_dma_fbuf_ctx(&d); + return NULL; + } + memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int)); + + PRINT(KERN_INFO, ohci->id, "Iso DMA to User's Space: %d buffers " + "of size %d allocated for a frame size %d, each with %d prgs", + d->num_desc, d->buf_size, d->frame_size, d->nb_cmd); + + return d; +} + +static void initialize_dma_fbuf_prg(struct dma_cmd *prg, int n, + int frame_size, unsigned long buf) +{ + int i; + int leftsize = (frame_size%PAGE_SIZE) ? + frame_size%PAGE_SIZE : PAGE_SIZE; + + /* the first descriptor will sync and read only 4 bytes */ + prg[0].control = (0x280F << 16) | 4; + prg[0].address = kvirt_to_bus(buf); + prg[0].branchAddress = (virt_to_bus(&(prg[1].control)) + & 0xfffffff0) | 0x1; + prg[0].status = 0; + + /* the second descriptor will read PAGE_SIZE-4 bytes */ + prg[1].control = (0x280C << 16) | (PAGE_SIZE-4); + prg[1].address = kvirt_to_bus(buf+4); + prg[1].branchAddress = (virt_to_bus(&(prg[2].control)) + & 0xfffffff0) | 0x1; + prg[1].status = 0; + + for (i=2;iohci; + int i; + + stop_context(ohci, d->ctrlClear, NULL); + + for (i=0;inum_desc;i++) { + initialize_dma_fbuf_prg(d->prg[i], d->nb_cmd, d->frame_size, + (unsigned long)d->buf+i*d->buf_size); + } + + /* Set bufferFill, no header */ + reg_write(ohci, d->ctrlSet, 0x80000000); + + /* Set the context match register to match on all tags, + sync for sync tag, and listen to d->channel */ + reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel); + + /* Set up isoRecvIntMask to generate interrupts */ + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<ctx); +} + +/* find which context is listening to this channel */ +int fbuf_ctx_listening(struct ti_ohci *ohci, int channel) +{ + int i; + for (i=0;inb_iso_ctx-1;i++) + if (ohci->fbuf_context[i]) { + if (ohci->fbuf_context[i]->channel==channel) + return i; + } + + PRINT(KERN_ERR, ohci->id, + "no iso context is listening to channel %d", + channel); + return -1; +} + +static int ohci_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; + + switch(cmd) + { + case VIDEO1394_LISTEN_CHANNEL: + { + struct video1394_mmap v; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { + PRINT(KERN_ERR, ohci->id, + "iso channel %d out of bound", v.channel); + return -EFAULT; + } + if (test_and_set_bit(v.channel, &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is already taken", v.channel); + return -EFAULT; + } + + /* find a free iso context */ + for (i=0;inb_iso_ctx-1;i++) + if (ohci->fbuf_context[i]==NULL) break; + + if (i==(ohci->nb_iso_ctx-1)) { + PRINT(KERN_ERR, ohci->id, "no iso context available"); + return -EFAULT; + } + + if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { + PRINT(KERN_ERR, ohci->id, + "%d buffers of size %d bytes is too big", + v.nb_buffers, v.buf_size); + return -EFAULT; + } + + ohci->fbuf_context[i] = + alloc_dma_fbuf_ctx(ohci, i+1, v.nb_buffers, + v.buf_size, v.channel); + + if (ohci->fbuf_context[i] == NULL) { + PRINT(KERN_ERR, ohci->id, + "Couldn't allocate fbuf context"); + return -EFAULT; + } + initialize_dma_fbuf_ctx(ohci->fbuf_context[i], v.sync_tag); + + ohci->current_fbuf_ctx = ohci->fbuf_context[i]; + + v.buf_size = ohci->fbuf_context[i]->buf_size; + + PRINT(KERN_INFO, ohci->id, + "iso context %d listen on channel %d", i+1, + v.channel); + + if(copy_to_user((void *)arg, &v, sizeof(v))) + return -EFAULT; + + return 0; + } + case VIDEO1394_UNLISTEN_CHANNEL: + { + int channel; + int i; + + if(copy_from_user(&channel, (void *)arg, sizeof(int))) + return -EFAULT; + + if (!test_and_clear_bit(channel, &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is not being used", channel); + return -EFAULT; + } + + i = fbuf_ctx_listening(ohci, channel); + if (i<0) return -EFAULT; + + free_dma_fbuf_ctx(&ohci->fbuf_context[i]); + + PRINT(KERN_INFO, ohci->id, + "iso context %d stop listening on channel %d", + i+1, channel); + + return 0; + } + case VIDEO1394_QUEUE_BUFFER: + { + struct video1394_wait v; + struct dma_fbuf_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = fbuf_ctx_listening(ohci, v.channel); + if (i<0) return -EFAULT; + d = ohci->fbuf_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { + PRINT(KERN_ERR, ohci->id, + "buffer %d is already used",v.buffer); + return -EFAULT; + } + + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; + + d->prg[d->last_buffer][d->nb_cmd-1].branchAddress = + (virt_to_bus(&(d->prg[v.buffer][0].control)) + & 0xfffffff0) | 0x1; + + d->last_buffer = v.buffer; + + if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) + { + DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); + + /* Tell the controller where the first program is */ + reg_write(ohci, d->cmdPtr, + virt_to_bus(&(d->prg[v.buffer][0])) | 0x1 ); + + /* Run IR context */ + reg_write(ohci, d->ctrlSet, 0x8000); + } + else { + /* Wake up dma context if necessary */ + if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { + PRINT(KERN_INFO, ohci->id, + "Waking up iso dma ctx=%d", d->ctx); + reg_write(ohci, d->ctrlSet, 0x1000); + } + } + return 0; + + } + case VIDEO1394_WAIT_BUFFER: + { + struct video1394_wait v; + struct dma_fbuf_ctx *d; + int i; + + if(copy_from_user(&v, (void *)arg, sizeof(v))) + return -EFAULT; + + i = fbuf_ctx_listening(ohci, v.channel); + if (i<0) return -EFAULT; + d = ohci->fbuf_context[i]; + + if ((v.buffer<0) || (v.buffer>d->num_desc)) { + PRINT(KERN_ERR, ohci->id, + "buffer %d out of range",v.buffer); + return -EFAULT; + } + + switch(d->buffer_status[v.buffer]) { + case VIDEO1394_BUFFER_READY: + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + case VIDEO1394_BUFFER_QUEUED: + while(d->buffer_status[v.buffer]!= + VIDEO1394_BUFFER_READY) { + interruptible_sleep_on(&d->waitq); + if(signal_pending(current)) return -EINTR; + } + d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; + return 0; + default: + PRINT(KERN_ERR, ohci->id, + "buffer %d is not queued",v.buffer); + return -EFAULT; + } + } + default: + return -EINVAL; + } +} + +/* + * This maps the vmalloced and reserved fbuffer to user space. + * + * FIXME: + * - PAGE_READONLY should suffice!? + * - remap_page_range is kind of inefficient for page by page remapping. + * But e.g. pte_alloc() does not work in modules ... :-( + */ + +static int do_fbuf_mmap(struct ti_ohci *ohci, struct dma_fbuf_ctx *d, + const char *adr, unsigned long size) +{ + unsigned long start=(unsigned long) adr; + unsigned long page,pos; + + if (size>d->num_desc * d->buf_size) { + PRINT(KERN_ERR, ohci->id, + "fbuf context %d buf size is different from mmap size", + d->ctx); + return -EINVAL; + } + if (!d->buf) { + PRINT(KERN_ERR, ohci->id, + "fbuf context %d is not allocated", d->ctx); + return -EINVAL; + } + + pos=(unsigned long) d->buf; + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + start+=PAGE_SIZE; + pos+=PAGE_SIZE; + size-=PAGE_SIZE; + } + return 0; +} + +int ohci_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ti_ohci *ohci=&cards[MINOR(file->f_dentry->d_inode->i_rdev)]; + PRINT(KERN_INFO, ohci->id, "mmap"); + if (ohci->current_fbuf_ctx == NULL) { + PRINT(KERN_ERR, ohci->id, "current fbuf context not set"); + return -EINVAL; + } + + return do_fbuf_mmap(ohci, ohci->current_fbuf_ctx, + (char *)vma->vm_start, + (unsigned long)(vma->vm_end-vma->vm_start)); + return 0; +} + +static int ohci_open(struct inode *inode, struct file *file) +{ + struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; + PRINT(KERN_INFO, ohci->id, "open"); + return 0; +} + +static int ohci_release(struct inode *inode, struct file *file) +{ + struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)]; + int i; + + PRINT(KERN_INFO, ohci->id, "release"); + for (i=0;inb_iso_ctx-1;i++) + if (ohci->fbuf_context[i]) { + if (!test_and_clear_bit(ohci->fbuf_context[i]->channel, + &ohci->IR_channel_usage)) { + PRINT(KERN_ERR, ohci->id, + "channel %d is not being used", + ohci->fbuf_context[i]->channel); + } + PRINT(KERN_INFO, ohci->id, + "iso context %d stop listening on channel %d", + i+1, ohci->fbuf_context[i]->channel); + free_dma_fbuf_ctx(&ohci->fbuf_context[i]); + } + return 0; +} + +static struct file_operations ohci_fops= +{ + ioctl: ohci_ioctl, + mmap: ohci_mmap, + open: ohci_open, + release: ohci_release +}; + +int wakeup_dma_fbuf_ctx(struct ti_ohci *ohci, struct dma_fbuf_ctx *d) +{ + int i; + + if (d==NULL) { + PRINT(KERN_ERR, ohci->id, "Iso receive event received but " + "context not allocated"); + return -EFAULT; + } + + for (i=0;inum_desc;i++) { + if (d->prg[i][d->nb_cmd-1].status) { + d->prg[i][d->nb_cmd-1].status=0; + d->buffer_status[i] = VIDEO1394_BUFFER_READY; + } + } + if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); + return 0; +} + +#endif + + /*********************************** * IEEE-1394 functionality section * @@ -220,6 +843,22 @@ "Error in reception of self-id packets" "Self-id count: %08x q[0]: %08x", self_id_count, q[0]); + + /* + * Tip by James Goodwin : + * We had an error, generate another bus reset in response. + * TODO. Actually read the current value in the phy before + * generating a bus reset (read modify write). This way + * we don't stomp any current gap count settings, etc. + */ + if (ohci->self_id_errorsself_id_errors++; + } + else { + PRINT(KERN_ERR, ohci->id, + "Timeout on self-id error reception"); + } return -1; } @@ -411,15 +1050,34 @@ spin_lock_init(&ohci->phy_reg_lock); + /* + * Tip by James Goodwin : + * We need to add delays after the soft reset, setting LPS, and + * enabling our link. This might fixes the self-id reception + * problem at initialization. + */ + /* Soft reset */ if ((retval=ohci_soft_reset(ohci))<0) return retval; - - /* Set the bus number */ - reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); + /* + *Delay aftger soft reset to make sure everything has settled + * down (sanity) + */ + mdelay(100); + /* Set Link Power Status (LPS) */ reg_write(ohci, OHCI1394_HCControlSet, 0x00080000); + /* + * Delay after setting LPS in order to make sure link/phy + * communication is established + */ + mdelay(100); + + /* Set the bus number */ + reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); + /* Enable posted writes */ reg_write(ohci, OHCI1394_HCControlSet, 0x00040000); @@ -464,9 +1122,6 @@ /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); - /* Enable link */ - reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); - /* Initialize IR dma */ ohci->nb_iso_ctx = get_nb_iso_ctx(ohci); PRINT(KERN_INFO, ohci->id, "%d iso contexts available", @@ -477,7 +1132,18 @@ reg_write(ohci, OHCI1394_IrRcvContextMatch+32*i, 0); reg_write(ohci, OHCI1394_IrRcvCommandPtr+32*i, 0); } - +#ifdef _VIDEO_1394_H + ohci->fbuf_context = (struct dma_fbuf_ctx **) + kmalloc((ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *), + GFP_KERNEL); + if (ohci->fbuf_context) + memset(ohci->fbuf_context, 0, + (ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *)); + else { + PRINT(KERN_ERR, ohci->id, "Cannot allocate fbuf_context"); + return -1; + } +#endif /* Set bufferFill, isochHeader, multichannel for IR context */ reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000); @@ -495,16 +1161,6 @@ (thanks to Michael Greger for seeing that I forgot this) */ reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001); - initialize_dma_rcv_ctx(ohci->ir_context); - - /* Initialize AR dma */ - initialize_dma_rcv_ctx(ohci->ar_req_context); - initialize_dma_rcv_ctx(ohci->ar_resp_context); - - /* Initialize AT dma */ - initialize_dma_trm_ctx(ohci->at_req_context); - initialize_dma_trm_ctx(ohci->at_resp_context); - /* * Accept AT requests from all nodes. This probably * will have to be controlled from the subsystem @@ -539,6 +1195,20 @@ OHCI1394_isochRx ); + /* Enable link */ + reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); + + /* Initialize AR dma */ + initialize_dma_rcv_ctx(ohci->ar_req_context); + initialize_dma_rcv_ctx(ohci->ar_resp_context); + + /* Initialize AT dma */ + initialize_dma_trm_ctx(ohci->at_req_context); + initialize_dma_trm_ctx(ohci->at_resp_context); + + /* Initialize IR dma */ + initialize_dma_rcv_ctx(ohci->ir_context); + return 1; } @@ -619,7 +1289,7 @@ struct ti_ohci *ohci = host->hostdata; struct dma_trm_ctx *d; unsigned char tcode; - int i=50; + int timeout=50; if (packet->data_size >= ohci->max_packet_size) { PRINT(KERN_ERR, ohci->id, @@ -642,8 +1312,9 @@ } while (d->free_prgs<1) { spin_unlock(&d->lock); - schedule(); - if (i-- <0) { + interruptible_sleep_on(&d->waitq); + if(signal_pending(current)) return -EINTR; + if (timeout--<0) { stop_context(ohci, d->ctrlClear, "AT DMA runaway loop... bailing out"); return 0; @@ -687,7 +1358,7 @@ switch (cmd) { case RESET_BUS: - host->attempt_root=1; + host->attempt_root=1; PRINT(KERN_INFO, ohci->id, "resetting bus on request%s", (host->attempt_root ? " and attempting to become root" : "")); @@ -743,6 +1414,11 @@ spin_lock_irqsave(&ohci->IR_channel_lock, flags); +#if 0 + PRINT(KERN_INFO, ohci->id, "!!! try listen on channel %d !!!", + arg); +#endif + if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) { PRINT(KERN_INFO, ohci->id, "listening enabled on channel %d", arg); @@ -845,137 +1521,179 @@ struct ti_ohci *ohci = (struct ti_ohci *)dev_id; struct hpsb_host *host = ohci->host; int phyid = -1, isroot = 0; + int timeout = 255; - /* read the interrupt event register */ - event=reg_read(ohci, OHCI1394_IntEventSet); - -#if 0 - /* - * clear the interrupt event register, except for the - * bus reset event interrupt (if any). This is an - * attempt to comply with ohci spec 7.2.3.2 - */ - reg_write(ohci, OHCI1394_IntEventClear, event & (~OHCI1394_busReset)); + do { + /* read the interrupt event register */ + event=reg_read(ohci, OHCI1394_IntEventClear); + + DBGMSG(ohci->id, "IntEvent: %08x",event); + + if (!event) return; + + /* clear the interrupt event register */ + reg_write(ohci, OHCI1394_IntEventClear, event); + + if (event & OHCI1394_busReset) { + if (!host->in_bus_reset) { + PRINT(KERN_INFO, ohci->id, "Bus reset"); + + /* Wait for the AT fifo to be flushed */ + dma_trm_reset(ohci->at_req_context); + dma_trm_reset(ohci->at_resp_context); + + /* Subsystem call */ + hpsb_bus_reset(ohci->host); + + ohci->NumBusResets++; + } + } + /* + * Problem: How can I ensure that the AT bottom half will be + * executed before the AR bottom half (both events may have + * occured within a single irq event) + * Quick hack: just launch it within the IRQ handler + */ + if (event & OHCI1394_reqTxComplete) { + struct dma_trm_ctx *d = ohci->at_req_context; + DBGMSG(ohci->id, "Got reqTxComplete interrupt " + "status=0x%08X", reg_read(ohci, d->ctrlSet)); + if (reg_read(ohci, d->ctrlSet) & 0x800) + stop_context(ohci, d->ctrlClear, + "reqTxComplete"); + else + dma_trm_bh((void *)d); + } + if (event & OHCI1394_respTxComplete) { + struct dma_trm_ctx *d = ohci->at_resp_context; + DBGMSG(ohci->id, "Got respTxComplete interrupt " + "status=0x%08X", reg_read(ohci, d->ctrlSet)); + if (reg_read(ohci, d->ctrlSet) & 0x800) + stop_context(ohci, d->ctrlClear, + "respTxComplete"); + else + dma_trm_bh((void *)d); + } + if (event & OHCI1394_RQPkt) { + struct dma_rcv_ctx *d = ohci->ar_req_context; + DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X", + reg_read(ohci, d->ctrlSet)); + if (reg_read(ohci, d->ctrlSet) & 0x800) + stop_context(ohci, d->ctrlClear, "RQPkt"); + else { +#if 1 + queue_task(&d->task, &tq_immediate); + mark_bh(IMMEDIATE_BH); #else - /* The above attempt doesn't work */ - reg_write(ohci, OHCI1394_IntEventClear, event); + dma_rcv_bh((void *)d); #endif - if (event & OHCI1394_busReset) { - if (!host->in_bus_reset) { - PRINT(KERN_INFO, ohci->id, "Bus reset"); - - /* Wait for the AT fifo to be flushed */ - dma_trm_reset(ohci->at_req_context); - dma_trm_reset(ohci->at_resp_context); - -#if 0 - /* clear the bus reset event */ - reg_write(ohci, OHCI1394_IntEventClear, - OHCI1394_busReset); -#endif - /* Subsystem call */ - hpsb_bus_reset(ohci->host); - - ohci->NumBusResets++; + } } - } - /* - * Problem: How can I ensure that the AT bottom half will be - * executed before the AR bottom half (both events may have - * occured within a single irq event) - * Quick hack: just launch it within the IRQ handler - */ - if (event & OHCI1394_reqTxComplete) { - struct dma_trm_ctx *d = ohci->at_req_context; - DBGMSG(ohci->id, "Got reqTxComplete interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "reqTxComplete"); - else - dma_trm_bh((void *)d); - } - if (event & OHCI1394_respTxComplete) { - struct dma_trm_ctx *d = ohci->at_resp_context; - DBGMSG(ohci->id, "Got respTxComplete interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "respTxComplete"); - else - dma_trm_bh((void *)d); - } - if (event & OHCI1394_RQPkt) { - struct dma_rcv_ctx *d = ohci->ar_req_context; - DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "RQPkt"); - else { - queue_task(&d->task, &tq_immediate); - mark_bh(IMMEDIATE_BH); + if (event & OHCI1394_RSPkt) { + struct dma_rcv_ctx *d = ohci->ar_resp_context; + DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X", + reg_read(ohci, d->ctrlSet)); + if (reg_read(ohci, d->ctrlSet) & 0x800) + stop_context(ohci, d->ctrlClear, "RSPkt"); + else { +#if 1 + queue_task(&d->task, &tq_immediate); + mark_bh(IMMEDIATE_BH); +#else + dma_rcv_bh((void *)d); +#endif + } } - } - if (event & OHCI1394_RSPkt) { - struct dma_rcv_ctx *d = ohci->ar_resp_context; - DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "RSPkt"); - else { - queue_task(&d->task, &tq_immediate); - mark_bh(IMMEDIATE_BH); + if (event & OHCI1394_isochRx) { + quadlet_t isoRecvIntEvent; + struct dma_rcv_ctx *d = ohci->ir_context; +#ifdef _VIDEO_1394_H + int i; +#endif + isoRecvIntEvent = + reg_read(ohci, OHCI1394_IsoRecvIntEventSet); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, + isoRecvIntEvent); + DBGMSG(ohci->id, "Got isochRx interrupt " + "status=0x%08X isoRecvIntEvent=%08x", + reg_read(ohci, d->ctrlSet), isoRecvIntEvent); + if (isoRecvIntEvent & 0x1) { + if (reg_read(ohci, d->ctrlSet) & 0x800) + stop_context(ohci, d->ctrlClear, + "isochRx"); + else { +#if 1 + queue_task(&d->task, &tq_immediate); + mark_bh(IMMEDIATE_BH); +#else + dma_rcv_bh((void *)d); +#endif + } + } +#ifdef _VIDEO_1394_H + for (i=0;inb_iso_ctx-1;i++) + if (isoRecvIntEvent & (1<<(i+1))) + wakeup_dma_fbuf_ctx( + ohci,ohci->fbuf_context[i]); +#endif } - } - if (event & OHCI1394_isochRx) { - quadlet_t isoRecvIntEvent; - struct dma_rcv_ctx *d = ohci->ir_context; - isoRecvIntEvent = reg_read(ohci, OHCI1394_IsoRecvIntEventSet); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, - isoRecvIntEvent); - DBGMSG(ohci->id, "Got reqTxComplete interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - stop_context(ohci, d->ctrlClear, "isochRx"); - else { - queue_task(&d->task, &tq_immediate); - mark_bh(IMMEDIATE_BH); + if (event & OHCI1394_selfIDComplete) { + if (host->in_bus_reset) { + node_id = reg_read(ohci, OHCI1394_NodeID); + if (node_id & 0x80000000) { /* NodeID valid */ + phyid = node_id & 0x0000003f; + isroot = (node_id & 0x40000000) != 0; + + PRINT(KERN_INFO, ohci->id, + "SelfID process finished " + "(phyid %d, %s)", phyid, + (isroot ? "root" : "not root")); + + handle_selfid(ohci, host, + phyid, isroot); + } + else + PRINT(KERN_ERR, ohci->id, + "SelfID process finished but " + "NodeID not valid: %08X", + node_id); + + /* Accept Physical requests from all nodes. */ + reg_write(ohci,OHCI1394_AsReqFilterHiSet, + 0xffffffff); + reg_write(ohci,OHCI1394_AsReqFilterLoSet, + 0xffffffff); + /* + * Tip by James Goodwin + * Turn on phys dma reception. We should + * probably manage the filtering somehow, + * instead of blindly turning it on. + */ + reg_write(ohci,OHCI1394_PhyReqFilterHiSet, + 0xffffffff); + reg_write(ohci,OHCI1394_PhyReqFilterLoSet, + 0xffffffff); + reg_write(ohci,OHCI1394_PhyUpperBound, + 0xffff0000); + } + else PRINT(KERN_ERR, ohci->id, + "self-id received outside of bus reset" + "sequence"); } - } - if (event & OHCI1394_selfIDComplete) { - if (host->in_bus_reset) { - node_id = reg_read(ohci, OHCI1394_NodeID); - if (node_id & 0x80000000) { /* NodeID valid */ - phyid = node_id & 0x0000003f; - isroot = (node_id & 0x40000000) != 0; - - PRINT(KERN_INFO, ohci->id, - "SelfID process finished (phyid %d, %s)", - phyid, (isroot ? "root" : "not root")); - - handle_selfid(ohci, host, phyid, isroot); + if (event & OHCI1394_phyRegRcvd) { +#if 1 + if (host->in_bus_reset) { + PRINT(KERN_INFO, ohci->id, "PhyControl: %08X", + reg_read(ohci, OHCI1394_PhyControl)); } - else - PRINT(KERN_ERR, ohci->id, - "SelfID process finished but NodeID" - " not valid: %08X",node_id); - - /* Accept Physical requests from all nodes. */ - reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff); - reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff); - } - else PRINT(KERN_INFO, ohci->id, - "phy reg received without reset\n"); - } - if (event & OHCI1394_phyRegRcvd) { -#if 0 - if (host->in_bus_reset) { - PRINT(KERN_INFO, ohci->id, "PhyControl: %08X", - reg_read(ohci, OHCI1394_PhyControl)); - } else - PRINT(KERN_ERR, ohci->id, - "phy reg received without reset"); + else PRINT(KERN_ERR, ohci->id, + "phy reg received outside of bus reset" + "sequence"); #endif - } + } + } while (--timeout); + PRINT(KERN_ERR, ohci->id, "irq_handler timeout event=0x%08x", event); } /* Put the buffer back into the dma context */ @@ -1119,6 +1837,17 @@ buf_ptr += offset/4; } + /* + * Tip by James Goodwin + * We need to handle write requests that are received + * to our middle address space (posted writes). + * In this case, the hardware generates an + * ack_complete... but, if we pass the packet up to + * the subsystem, it will try and send a response + * (which it shouldn't), because it assumes we + * returned ack_pending. + */ + /* * We get one phy packet for each bus reset. * we know that from now on the bus topology may @@ -1132,6 +1861,20 @@ (d->spb[length/4-1]>>16)&0x1f, (d->spb[length/4-1]>>21)&0x3, tcode, length, d->spb[3], d->ctx); + + /* + * Tip by James Goodwin + * Handle case of posted writes. If we receive + * an ack_complete, we should not send a + * response. Fake out upper layers by turning + * the packet into a broadcast packet... we + * should really modify the core stack to + * accept an ack received argument and figure + * out whether to reply. + */ + if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) { + d->spb[0] |= (ALL_NODES<<16); + } hpsb_packet_received(ohci->host, d->spb, length); } @@ -1154,6 +1897,20 @@ (buf_ptr[length/4-1]>>16)&0x1f, (buf_ptr[length/4-1]>>21)&0x3, tcode, length, buf_ptr[3], d->ctx); + + /* + * Tip by James Goodwin + * Handle case of posted writes. If we receive + * an ack_complete, we should not send a + * response. Fake out upper layers by turning + * the packet into a broadcast packet... we + * should really modify the core stack to + * accept an ack received argument and figure + * out whether to reply. + */ + if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) { + buf_ptr[0] |= (ALL_NODES<<16); + } hpsb_packet_received(ohci->host, buf_ptr, length); } @@ -1207,32 +1964,42 @@ d->sent_ind = (d->sent_ind+1)%d->num_desc; d->free_prgs++; spin_unlock(&d->lock); - + + if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq); + DBGMSG(ohci->id, "Packet sent to node %d ack=0x%X spd=%d ctx=%d", (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, d->ctx); hpsb_packet_sent(ohci->host, packet, ack&0xf); } -static int free_dma_rcv_ctx(struct dma_rcv_ctx *d) +static int free_dma_rcv_ctx(struct dma_rcv_ctx **d) { int i; + struct ti_ohci *ohci; - if (d==NULL) return -1; + if (*d==NULL) return -1; - if (d->buf) { - for (i=0; inum_desc; i++) - if (d->buf[i]) kfree(d->buf[i]); - kfree(d->buf); - } - if (d->prg) { - for (i=0; inum_desc; i++) - if (d->prg[i]) kfree(d->prg[i]); - kfree(d->prg); - } - if (d->spb) kfree(d->spb); + ohci = (struct ti_ohci *)(*d)->ohci; + + DBGMSG(ohci->id, "Freeing dma_rcv_ctx %d",(*d)->ctx); - kfree(d); + stop_context(ohci, (*d)->ctrlClear, NULL); + + if ((*d)->buf) { + for (i=0; i<(*d)->num_desc; i++) + if ((*d)->buf[i]) kfree((*d)->buf[i]); + kfree((*d)->buf); + } + if ((*d)->prg) { + for (i=0; i<(*d)->num_desc; i++) + if ((*d)->prg[i]) kfree((*d)->prg[i]); + kfree((*d)->prg); + } + if ((*d)->spb) kfree((*d)->spb); + kfree(*d); + *d = NULL; + return 0; } @@ -1270,7 +2037,7 @@ if (d->buf == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); - free_dma_rcv_ctx(d); + free_dma_rcv_ctx(&d); return NULL; } memset(d->buf, 0, d->num_desc * sizeof(quadlet_t*)); @@ -1279,7 +2046,7 @@ if (d->prg == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); - free_dma_rcv_ctx(d); + free_dma_rcv_ctx(&d); return NULL; } memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd*)); @@ -1288,7 +2055,7 @@ if (d->spb == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate split buffer"); - free_dma_rcv_ctx(d); + free_dma_rcv_ctx(&d); return NULL; } @@ -1300,7 +2067,7 @@ } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer"); - free_dma_rcv_ctx(d); + free_dma_rcv_ctx(&d); return NULL; } @@ -1311,7 +2078,7 @@ } else { PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg"); - free_dma_rcv_ctx(d); + free_dma_rcv_ctx(&d); return NULL; } } @@ -1319,17 +2086,29 @@ spin_lock_init(&d->lock); /* initialize bottom handler */ + d->task.sync = 0; + d->task.next = NULL; d->task.routine = dma_rcv_bh; d->task.data = (void*)d; return d; } -static int free_dma_trm_ctx(struct dma_trm_ctx *d) +static int free_dma_trm_ctx(struct dma_trm_ctx **d) { - if (d==NULL) return -1; - if (d->prg) kfree(d->prg); - kfree(d); + struct ti_ohci *ohci; + + if (*d==NULL) return -1; + + ohci = (struct ti_ohci *)(*d)->ohci; + + DBGMSG(ohci->id, "Freeing dma_trm_ctx %d",(*d)->ctx); + + stop_context(ohci, (*d)->ctrlClear, NULL); + + if ((*d)->prg) kfree((*d)->prg); + kfree(*d); + *d = NULL; return 0; } @@ -1359,7 +2138,7 @@ if (d->prg == NULL) { PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg"); - free_dma_trm_ctx(d); + free_dma_trm_ctx(&d); return NULL; } memset(d->prg, 0, d->num_desc * sizeof(struct at_dma_prg)); @@ -1370,6 +2149,8 @@ d->task.routine = dma_trm_bh; d->task.data = (void*)d; + init_waitqueue_head(&d->waitq); + return d; } @@ -1385,10 +2166,12 @@ return 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - /* XXX check return value */ - pci_enable_device(dev); -#endif + if (pci_enable_device(dev)) { + PRINT_G(KERN_NOTICE, "failed to enable OHCI hardware %d", + num_of_cards); + return 1; + } + pci_set_master(dev); ohci = &cards[num_of_cards++]; @@ -1397,13 +2180,6 @@ ohci->state = 0; - if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, - OHCI1394_DRIVER_NAME, ohci)) { - PRINT(KERN_INFO, ohci->id, "allocated interrupt %d", dev->irq); - } else { - FAIL("failed to allocate shared interrupt %d", dev->irq); - } - /* csr_config rom allocation */ ohci->csr_config_rom = kmalloc(1024, GFP_KERNEL); if (ohci->csr_config_rom == NULL) { @@ -1437,7 +2213,9 @@ OHCI1394_AsRspRcvContextControlClear, OHCI1394_AsRspRcvCommandPtr); - if (ohci->ar_resp_context == NULL) return 1; + if (ohci->ar_resp_context == NULL) { + FAIL("failed to allocate AR Resp context"); + } ohci->at_req_context = alloc_dma_trm_ctx(ohci, 0, AT_REQ_NUM_DESC, @@ -1445,7 +2223,9 @@ OHCI1394_AsReqTrContextControlClear, OHCI1394_AsReqTrCommandPtr); - if (ohci->at_req_context == NULL) return 1; + if (ohci->at_req_context == NULL) { + FAIL("failed to allocate AT Req context"); + } ohci->at_resp_context = alloc_dma_trm_ctx(ohci, 1, AT_RESP_NUM_DESC, @@ -1453,7 +2233,9 @@ OHCI1394_AsRspTrContextControlClear, OHCI1394_AsRspTrCommandPtr); - if (ohci->at_resp_context == NULL) return 1; + if (ohci->at_resp_context == NULL) { + FAIL("failed to allocate AT Resp context"); + } ohci->ir_context = alloc_dma_rcv_ctx(ohci, 2, IR_NUM_DESC, @@ -1462,7 +2244,9 @@ OHCI1394_IrRcvContextControlClear, OHCI1394_IrRcvCommandPtr); - if (ohci->ir_context == NULL) return 1; + if (ohci->ir_context == NULL) { + FAIL("failed to allocate IR context"); + } ohci->IR_channel_usage= 0x0000000000000000; spin_lock_init(&ohci->IR_channel_lock); @@ -1482,6 +2266,13 @@ PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p", ohci->registers); + if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ, + OHCI1394_DRIVER_NAME, ohci)) { + PRINT(KERN_INFO, ohci->id, "allocated interrupt %d", dev->irq); + } else { + FAIL("failed to allocate shared interrupt %d", dev->irq); + } + return 0; #undef FAIL } @@ -1507,6 +2298,10 @@ int i; struct dma_rcv_ctx *d=NULL; struct dma_trm_ctx *dt=NULL; +#ifdef _VIDEO_1394_H + int j; + struct dma_fbuf_ctx *f=ohci->fbuf_context[0]; +#endif p += sprintf(p,"IEEE-1394 OHCI Driver status report:\n"); p += sprintf(p," bus number: 0x%x Node ID: 0x%x\n", @@ -1535,6 +2330,27 @@ host->is_busmgr ? "bus_mgr" : ""); p += sprintf(p,"\n---Iso Receive DMA---\n"); + +#ifdef _VIDEO_1394_H + +#if 0 + if (f!=NULL) { + for (i=0; inum_desc; i++) { + for (j=0;jnb_cmd;j++) { + p += sprintf(p, + "prg[%d][%d]: %p %08x %08x %08x %08x\n", + i,j,virt_to_bus(&(f->prg[i][j])), + f->prg[i][j].control, + f->prg[i][j].address, + f->prg[i][j].branchAddress, + f->prg[i][j].status); + } + } + } +#endif + +#else + d = ohci->ir_context; #if 0 for (i=0; inum_desc; i++) { @@ -1621,7 +2437,8 @@ dt->branchAddrPtr); p += sprintf(p, "AT resp queue: first: %p last: %p\n", dt->first, dt->last); - +#endif + /* ----- Register Dump ----- */ p += sprintf(p,"\n### HC Register dump ###\n"); SR("Version : %08x GUID_ROM : %08x ATRetries : %08x\n", @@ -1736,19 +2553,34 @@ static void remove_card(struct ti_ohci *ohci) { - if (ohci->registers) - iounmap(ohci->registers); +#ifdef _VIDEO_1394_H + int i; +#endif /* Free AR dma */ - free_dma_rcv_ctx(ohci->ar_req_context); - free_dma_rcv_ctx(ohci->ar_resp_context); + free_dma_rcv_ctx(&ohci->ar_req_context); + free_dma_rcv_ctx(&ohci->ar_resp_context); /* Free AT dma */ - free_dma_trm_ctx(ohci->at_req_context); - free_dma_trm_ctx(ohci->at_resp_context); + free_dma_trm_ctx(&ohci->at_req_context); + free_dma_trm_ctx(&ohci->at_resp_context); /* Free IR dma */ - free_dma_rcv_ctx(ohci->ir_context); + free_dma_rcv_ctx(&ohci->ir_context); + +#ifdef _VIDEO_1394_H + /* Free the frame buffer context */ + if (ohci->fbuf_context) + for (i=0;inb_iso_ctx-1;i++) { + free_dma_fbuf_ctx(&ohci->fbuf_context[i]); + } +#endif + + /* + * Reset the board properly before leaving + * Daniel Kobras + */ + ohci_soft_reset(ohci); /* Free self-id buffer */ if (ohci->self_id_buffer) @@ -1761,6 +2593,9 @@ /* Free the IRQ */ free_irq(ohci->dev->irq, ohci); + if (ohci->registers) + iounmap(ohci->registers); + ohci->state = 0; } @@ -1858,16 +2693,30 @@ proc_unregister(&proc_root, ohci_proc_entry.low_ino); #endif #endif + +#ifdef _VIDEO_1394_H + unregister_chrdev(OHCI1394_MAJOR, "ohci1394"); +#endif + PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n"); } int init_module(void) { - + memset(cards, 0, MAX_OHCI1394_CARDS * sizeof (struct ti_ohci)); + if (hpsb_register_lowlevel(get_ohci_template())) { PRINT_G(KERN_ERR, "registering failed\n"); return -ENXIO; } else { +#ifdef _VIDEO_1394_H + if (register_chrdev(OHCI1394_MAJOR, "ohci1394", &ohci_fops)) + { + printk("ohci1394: unable to get major %d\n", + OHCI1394_MAJOR); + return -EIO; + } +#endif return 0; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/ohci1394.h linux.ac/drivers/ieee1394/ohci1394.h --- linux.vanilla/drivers/ieee1394/ohci1394.h Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/ohci1394.h Sat Jun 10 22:52:33 2000 @@ -1,8 +1,29 @@ +/* + * ohci1394.h - driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * Gord Peters + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #ifndef _OHCI1394_H #define _OHCI1394_H #include "ieee1394_types.h" +/* include this for the video frame grabber */ +/* #include "video1394.h" */ #define OHCI1394_DRIVER_NAME "ohci1394" @@ -46,11 +67,16 @@ #define PCI_DEVICE_ID_NEC_UPD72871 0x00ce #endif +#ifndef PCI_DEVICE_ID_APPLE_UNI_N_FW +#define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018 +#endif + #define MAX_OHCI1394_CARDS 4 #define OHCI1394_MAX_AT_REQ_RETRIES 0x2 #define OHCI1394_MAX_AT_RESP_RETRIES 0x2 #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 +#define OHCI1394_MAX_SELF_ID_ERRORS 16 #define AR_REQ_NUM_DESC 4 /* number of AR req descriptors */ #define AR_REQ_BUF_SIZE 4096 /* size of AR req buffers */ @@ -116,8 +142,34 @@ int ctrlClear; int ctrlSet; int cmdPtr; + wait_queue_head_t waitq; }; +#ifdef _VIDEO_1394_H + +#define OHCI1394_MAJOR 172 +#define ISO_CHANNELS 64 + +struct dma_fbuf_ctx { + void *ohci; + int ctx; + int channel; + int last_buffer; + unsigned int num_desc; + unsigned int buf_size; + unsigned int frame_size; + unsigned int nb_cmd; + unsigned char *buf; + struct dma_cmd **prg; + unsigned int *buffer_status; + int ctrlClear; + int ctrlSet; + int cmdPtr; + int ctxMatch; + wait_queue_head_t waitq; +}; +#endif + struct ti_ohci { int id; /* sequential card number */ @@ -147,6 +199,12 @@ spinlock_t IR_channel_lock; int nb_iso_ctx; +#ifdef _VIDEO_1394_H + /* frame buffer context */ + struct dma_fbuf_ctx **fbuf_context; + struct dma_fbuf_ctx *current_fbuf_ctx; +#endif + /* IEEE-1394 part follows */ struct hpsb_host *host; @@ -154,6 +212,7 @@ spinlock_t phy_reg_lock; + int self_id_errors; int NumBusResets; }; @@ -328,8 +387,8 @@ #define OHCI1394_RSPkt 0x00000020 #define OHCI1394_isochTx 0x00000040 #define OHCI1394_isochRx 0x00000080 -#define OHCI1394_postedWriteErr 0x00001000 -#define OHCI1394_lockRespErr 0x00002000 +#define OHCI1394_postedWriteErr 0x00000100 +#define OHCI1394_lockRespErr 0x00000200 #define OHCI1394_selfIDComplete 0x00010000 #define OHCI1394_busReset 0x00020000 #define OHCI1394_phy 0x00080000 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/pcilynx.c linux.ac/drivers/ieee1394/pcilynx.c --- linux.vanilla/drivers/ieee1394/pcilynx.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/pcilynx.c Thu Jun 8 16:41:23 2000 @@ -99,6 +99,8 @@ return -1; } + +#if 0 static void free_pcl(struct ti_lynx *lynx, pcl_t pclid) { int off, bit; @@ -145,6 +147,7 @@ get_pcl(lynx, pclid, &pcl); pretty_print_pcl(&pcl); } +#endif static int add_card(struct pci_dev *dev); @@ -486,7 +489,8 @@ put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl); /* 85 bytes for each FIFO - FIXME - optimize or make configurable */ - reg_write(lynx, FIFO_SIZES, 0x00555555); + /* reg_write(lynx, FIFO_SIZES, 0x00555555); */ + reg_write(lynx, FIFO_SIZES, 0x002020c0); /* 20 byte threshold before triggering PCI transfer */ reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24); /* 69 byte threshold on both send FIFOs before transmitting */ @@ -597,15 +601,16 @@ } else { arg = 1 << 6; } - + + retval = get_phy_reg(lynx, 1); + arg |= (retval == -1 ? 63 : retval); + retval = 0; + PRINT(KERN_INFO, lynx->id, "resetting bus on request%s", (host->attempt_root ? " and attempting to become root" : "")); - spin_lock_irqsave(&lynx->phy_reg_lock, flags); - reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(1) - | LINK_PHY_WDATA(arg)); - spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); + set_phy_reg(lynx, 1, arg); break; case GET_CYCLE_COUNTER: @@ -717,61 +722,10 @@ static void aux_setup_pcls(struct ti_lynx *lynx) { struct ti_pcl pcl; - unsigned long membufbus = virt_to_bus(lynx->mem_dma_buffer); - int i; - /* This pcl is used to start any aux transfers, the pointer to next - points to itself to avoid a dummy pcl (the PCL engine only executes - the next pcl on startup. The real chain is done by branch */ - pcl.next = pcl_bus(lynx, lynx->mem_pcl.start); - pcl.buffer[0].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_SET; - pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.max); - pcl.buffer[1].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_CLEAR; - pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd); - put_pcl(lynx, lynx->mem_pcl.start, &pcl); - - /* let maxpcl transfer exactly 32kB */ - pcl.next = PCL_NEXT_INVALID; - for (i=0; i<8; i++) { - pcl.buffer[i].control = 4000; - pcl.buffer[i].pointer = membufbus + i * 4000; - } - pcl.buffer[0].control |= PCL_CMD_LBUS_TO_PCI /*| PCL_GEN_INTR*/; - pcl.buffer[8].control = 768 | PCL_LAST_BUFF; - pcl.buffer[8].pointer = membufbus + 8 * 4000; - put_pcl(lynx, lynx->mem_pcl.max, &pcl); - - - /* magic stuff - self and modpcl modifying pcl */ - pcl.next = pcl_bus(lynx, lynx->mem_pcl.mod); - pcl.user_data = 4000; - pcl.buffer[0].control = PCL_CMD_LOAD; - pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(user_data); - pcl.buffer[1].control = PCL_CMD_STOREQ; - pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.mod) - + pcloffs(buffer[1].control); - pcl.buffer[2].control = PCL_CMD_LOAD; - pcl.buffer[2].pointer = membufbus; - pcl.buffer[3].control = PCL_CMD_STOREQ; - pcl.buffer[3].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(buffer[1].pointer); - pcl.buffer[4].control = PCL_CMD_STOREQ; - pcl.buffer[4].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) - + pcloffs(buffer[6].pointer); - pcl.buffer[5].control = PCL_CMD_LOAD; - pcl.buffer[5].pointer = membufbus + 4; - pcl.buffer[6].control = PCL_CMD_STOREQ | PCL_LAST_CMD; - put_pcl(lynx, lynx->mem_pcl.cmd, &pcl); - - /* modified by cmdpcl when actual transfer occurs */ pcl.next = PCL_NEXT_INVALID; - pcl.buffer[0].control = PCL_CMD_LBUS_TO_PCI; /* null transfer */ - for (i=1; i<13; i++) { - pcl.buffer[i].control = 4000; - pcl.buffer[i].pointer = membufbus + (i-1) * 4000; - } - put_pcl(lynx, lynx->mem_pcl.mod, &pcl); + pcl.user_data = pcl_bus(lynx, lynx->dmem_pcl); + put_pcl(lynx, lynx->dmem_pcl, &pcl); } static int mem_open(struct inode *inode, struct file *file) @@ -828,7 +782,8 @@ md->type = ram; break; case aux: - md->aux_intr_last_seen = atomic_read(&cards[cid].aux_intr_seen); + atomic_set(&md->aux_intr_last_seen, + atomic_read(&cards[cid].aux_intr_seen)); md->type = aux; break; } @@ -862,11 +817,9 @@ poll_wait(file, &cards[cid].aux_intr_wait, pt); intr_seen = atomic_read(&cards[cid].aux_intr_seen); - if (md->aux_intr_last_seen != intr_seen) { + if (atomic_read(&md->aux_intr_last_seen) != intr_seen) { mask |= POLLPRI; - /* md->aux_intr_last_seen = intr_seen; */ - md->aux_intr_last_seen++; /* don't miss interrupts */ - /* FIXME - make ioctl for configuring this */ + atomic_inc(&md->aux_intr_last_seen); } } @@ -882,38 +835,104 @@ short mem_mindma = 2400; MODULE_PARM(mem_mindma, "h"); +static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count, + int offset) +{ + pcltmp_t pcltmp; + struct ti_pcl *pcl; + size_t retval; + int i; + DECLARE_WAITQUEUE(wait, current); + + //printk("buf 0x%08x %x count %d offset %d\n", physbuf, physbuf % 3, count, offset); + + count &= ~3; + count = MIN(count, 53196); + retval = count; + + if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!"); + } + + switch (md->type) { + case rom: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | offset); + break; + case ram: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | offset); + break; + case aux: + reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | offset); + break; + } + + pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp); + pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | MIN(count, 4092); + pcl->buffer[0].pointer = physbuf; + count -= 4092; + + i = 0; + while (count > 0) { + i++; + pcl->buffer[i].control = MIN(count, 4092); + pcl->buffer[i].pointer = physbuf + i * 4092; + count -= 4092; + } + pcl->buffer[i].control |= PCL_LAST_BUFF; + commit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); + run_sub_pcl(md->lynx, md->lynx->dmem_pcl, 2, CHANNEL_LOCALBUS); + + schedule(); + while (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + if (signal_pending(current)) { + retval = -EINTR; + break; + } + schedule(); + } + + reg_write(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS), 0); + remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); + + if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS)) + & DMA_CHAN_CTRL_BUSY) { + PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!"); + } + + return retval; +} + static ssize_t mem_read(struct file *file, char *buffer, size_t count, loff_t *offset) { struct memdata *md = (struct memdata *)file->private_data; - size_t bcount; + ssize_t bcount; size_t alignfix; int off = (int)*offset; /* avoid useless 64bit-arithmetic */ + ssize_t retval; void *membase; - DECLARE_WAITQUEUE(wait, current); - - if ((off + count) > PCILYNX_MAX_MEMORY+1) { - count = PCILYNX_MAX_MEMORY+1 - off; + if ((off + count) > PCILYNX_MAX_MEMORY + 1) { + count = PCILYNX_MAX_MEMORY + 1 - off; } if (count <= 0) { return 0; } - down(&md->lynx->mem_dma_mutex); - switch (md->type) { case rom: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | off); membase = md->lynx->local_rom; break; case ram: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | off); membase = md->lynx->local_ram; break; case aux: - reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | off); membase = md->lynx->aux_port; break; default: @@ -921,89 +940,49 @@ md->lynx->id, md->type); } + down(&md->lynx->mem_dma_mutex); + if (count < mem_mindma) { memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, count); - copy_to_user(buffer, md->lynx->mem_dma_buffer, count); - bcount = 0; - goto done; + goto out; } - + bcount = count; alignfix = 4 - (off % 4); if (alignfix != 4) { if (bcount < alignfix) { alignfix = bcount; } - memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, alignfix); - copy_to_user(buffer, md->lynx->mem_dma_buffer, alignfix); + memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, + alignfix); if (bcount == alignfix) { - goto done; + goto out; } bcount -= alignfix; - buffer += alignfix; off += alignfix; } - if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!"); - } - - add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); - - if (bcount > 32768) { - current->state = TASK_INTERRUPTIBLE; - - reg_write(md->lynx, DMA0_READY, 1); /* select maxpcl */ - run_pcl(md->lynx, md->lynx->mem_pcl.start, 0); - - while (reg_read(md->lynx, DMA0_CHAN_CTRL) - & DMA_CHAN_CTRL_BUSY) { - if (signal_pending(current)) { - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - goto rmwait_done; - } - schedule(); - } - - copy_to_user(buffer, md->lynx->mem_dma_buffer, 32768); - buffer += 32768; - bcount -= 32768; - } - - *(u32 *)(md->lynx->mem_dma_buffer) = - pcl_bus(md->lynx, md->lynx->mem_pcl.mod) - + pcloffs(buffer[bcount/4000+1].control); - *(u32 *)(md->lynx->mem_dma_buffer+4) = PCL_LAST_BUFF | (bcount % 4000); - - current->state = TASK_INTERRUPTIBLE; + while (bcount >= 4) { + retval = mem_dmaread(md, virt_to_phys(md->lynx->mem_dma_buffer) + + count - bcount, bcount, off); + if (retval < 0) return retval; - reg_write(md->lynx, DMA0_READY, 0); - run_pcl(md->lynx, md->lynx->mem_pcl.start, 0); - - while (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - if (signal_pending(current)) { - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - goto rmwait_done; - } - schedule(); + bcount -= retval; + off += retval; } - copy_to_user(buffer, md->lynx->mem_dma_buffer, bcount); - bcount = 0; - - if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) { - PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!"); + if (bcount) { + memcpy_fromio(md->lynx->mem_dma_buffer + count - bcount, + membase+off, bcount); } - rmwait_done: - reg_write(md->lynx, DMA0_CHAN_CTRL, 0); - remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait); - done: + out: + retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count); up(&md->lynx->mem_dma_mutex); - count -= bcount; + if (retval < 0) return retval; *offset += count; - return (count ? count : -EINTR); + return count; } @@ -1200,6 +1179,12 @@ data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE] + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE; + if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) { + PRINT(KERN_ERR, lynx->id, + "iso length mismatch 0x%08x/0x%08x", *data, + lynx->iso_rcv.stat[idx]); + } + if (lynx->iso_rcv.stat[idx] & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) { PRINT(KERN_INFO, lynx->id, @@ -1224,11 +1209,12 @@ static int add_card(struct pci_dev *dev) { -#define FAIL(fmt, args...) \ +#define FAIL(fmt, args...) do { \ PRINT_G(KERN_ERR, fmt , ## args); \ num_of_cards--; \ remove_card(lynx); \ - return 1 + return 1; \ + } while (0) struct ti_lynx *lynx; /* shortcut to currently handled device */ unsigned long page; @@ -1246,6 +1232,9 @@ lynx->id = num_of_cards-1; lynx->dev = dev; + if (pci_enable_device(dev)) { + FAIL("failed to enable PCILynx hardware %d", lynx->id); + } pci_set_master(dev); if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ, @@ -1271,7 +1260,7 @@ } #endif - lynx->mem_dma_buffer = kmalloc(32768, GFP_KERNEL); + lynx->mem_dma_buffer = kmalloc(65536, GFP_KERNEL); if (lynx->mem_dma_buffer != NULL) { lynx->state = have_aux_buf; } else { @@ -1301,15 +1290,15 @@ lynx->local_ram = ioremap(dev->base_address[1], PCILYNX_MAX_MEMORY); lynx->aux_port = ioremap(dev->base_address[2], PCILYNX_MAX_MEMORY); #else - lynx->registers = ioremap_nocache(dev->resource[0].start, + lynx->registers = ioremap_nocache(pci_resource_start(dev,0), PCILYNX_MAX_REGISTER); - lynx->local_ram = ioremap(dev->resource[1].start, PCILYNX_MAX_MEMORY); - lynx->aux_port = ioremap(dev->resource[2].start, PCILYNX_MAX_MEMORY); + lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY); + lynx->aux_port = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,15) lynx->local_rom = ioremap(dev->rom_address, PCILYNX_MAX_MEMORY); #else - lynx->local_rom = ioremap(dev->resource[PCI_ROM_RESOURCE].start, + lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE), PCILYNX_MAX_MEMORY); #endif lynx->state = have_iomappings; @@ -1328,12 +1317,8 @@ /* alloc_pcl return values are not checked, it is expected that the * provided PCL space is sufficient for the initial allocations */ if (lynx->aux_port != NULL) { - lynx->mem_pcl.start = alloc_pcl(lynx); - lynx->mem_pcl.cmd = alloc_pcl(lynx); - lynx->mem_pcl.mod = alloc_pcl(lynx); - lynx->mem_pcl.max = alloc_pcl(lynx); + lynx->dmem_pcl = alloc_pcl(lynx); aux_setup_pcls(lynx); - sema_init(&lynx->mem_dma_mutex, 1); } lynx->rcv_pcl = alloc_pcl(lynx); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/pcilynx.h linux.ac/drivers/ieee1394/pcilynx.h --- linux.vanilla/drivers/ieee1394/pcilynx.h Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/pcilynx.h Sun Jun 4 21:50:42 2000 @@ -19,7 +19,7 @@ #define ISORCV_PER_PAGE (PAGE_SIZE / MAX_ISORCV_SIZE) #define ISORCV_PAGES (NUM_ISORCV_PCL / ISORCV_PER_PAGE) -/* only iso rcv uses these definitions so far */ +/* only iso rcv and localbus use these definitions so far */ #define CHANNEL_LOCALBUS 0 #define CHANNEL_ASYNC_RCV 1 #define CHANNEL_ISO_RCV 2 @@ -70,9 +70,7 @@ #endif /* PCLs for local mem / aux transfers */ - struct { - pcl_t start, cmd, mod, max; - } mem_pcl; + pcl_t dmem_pcl; /* IEEE-1394 part follows */ struct hpsb_host *host; @@ -105,7 +103,7 @@ struct memdata { struct ti_lynx *lynx; int cid; - int aux_intr_last_seen; + atomic_t aux_intr_last_seen; enum { rom, aux, ram } type; }; @@ -415,6 +413,38 @@ #endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */ +#if defined (CONFIG_IEEE1394_PCILYNX_LOCALRAM) || defined (__BIG_ENDIAN) +typedef struct ti_pcl pcltmp_t; + +inline static struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid, + pcltmp_t *tmp) +{ + get_pcl(lynx, pclid, tmp); + return tmp; +} + +inline static void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid, + pcltmp_t *tmp) +{ + put_pcl(lynx, pclid, tmp); +} + +#else +typedef int pcltmp_t; /* just a dummy */ + +inline static struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid, + pcltmp_t *tmp) +{ + return lynx->pcl_mem + pclid * sizeof(struct ti_pcl); +} + +inline static void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid, + pcltmp_t *tmp) +{ +} +#endif + + inline static void run_sub_pcl(const struct ti_lynx *lynx, pcl_t pclid, int idx, int dmachan) { @@ -464,73 +494,73 @@ #define _(x) (__constant_cpu_to_be32(x)) -quadlet_t lynx_csr_rom[] = { - /* bus info block */ - _(0x04040000), /* info/CRC length, CRC */ - _(0x31333934), /* 1394 magic number */ - _(0xf064a000), /* misc. settings */ - _(0x08002850), /* vendor ID, chip ID high */ - _(0x0000ffff), /* chip ID low */ - /* root directory */ - _(0x00090000), /* CRC length, CRC */ - _(0x03080028), /* vendor ID (Texas Instr.) */ - _(0x81000009), /* offset to textual ID */ - _(0x0c000200), /* node capabilities */ - _(0x8d00000e), /* offset to unique ID */ - _(0xc7000010), /* offset to module independent info */ - _(0x04000000), /* module hardware version */ - _(0x81000026), /* offset to textual ID */ - _(0x09000000), /* node hardware version */ - _(0x81000026), /* offset to textual ID */ - /* module vendor ID textual */ - _(0x00080000), /* CRC length, CRC */ - _(0x00000000), - _(0x00000000), - _(0x54455841), /* "Texas Instruments" */ - _(0x5320494e), - _(0x53545255), - _(0x4d454e54), - _(0x53000000), - /* node unique ID leaf */ - _(0x00020000), /* CRC length, CRC */ - _(0x08002850), /* vendor ID, chip ID high */ - _(0x0000ffff), /* chip ID low */ - /* module dependent info */ - _(0x00060000), /* CRC length, CRC */ - _(0xb8000006), /* offset to module textual ID */ - _(0x81000004), /* ??? textual descriptor */ - _(0x39010000), /* SRAM size */ - _(0x3a010000), /* AUXRAM size */ - _(0x3b000000), /* AUX device */ - /* module textual ID */ - _(0x00050000), /* CRC length, CRC */ - _(0x00000000), - _(0x00000000), - _(0x54534231), /* "TSB12LV21" */ - _(0x324c5632), - _(0x31000000), - /* part number */ - _(0x00060000), /* CRC length, CRC */ - _(0x00000000), - _(0x00000000), - _(0x39383036), /* "9806000-0001" */ - _(0x3030342d), - _(0x30303431), - _(0x20000001), - /* module hardware version textual */ - _(0x00050000), /* CRC length, CRC */ - _(0x00000000), - _(0x00000000), - _(0x5453424b), /* "TSBKPCITST" */ - _(0x50434954), - _(0x53540000), - /* node hardware version textual */ - _(0x00050000), /* CRC length, CRC */ - _(0x00000000), - _(0x00000000), - _(0x54534232), /* "TSB21LV03" */ - _(0x313c5630), - _(0x33000000) +static quadlet_t lynx_csr_rom[] = { +/* bus info block offset (hex) */ + _(0x04040000), /* info/CRC length, CRC 400 */ + _(0x31333934), /* 1394 magic number 404 */ + _(0xf064a000), /* misc. settings 408 */ + _(0x08002850), /* vendor ID, chip ID high 40c */ + _(0x0000ffff), /* chip ID low 410 */ +/* root directory */ + _(0x00090000), /* directory length, CRC 414 */ + _(0x03080028), /* vendor ID (Texas Instr.) 418 */ + _(0x81000008), /* offset to textual ID 41c */ + _(0x0c000200), /* node capabilities 420 */ + _(0x8d00000e), /* offset to unique ID 424 */ + _(0xc7000010), /* offset to module independent info 428 */ + _(0x04000000), /* module hardware version 42c */ + _(0x81000014), /* offset to textual ID 430 */ + _(0x09000000), /* node hardware version 434 */ + _(0x81000018), /* offset to textual ID 438 */ + /* module vendor ID textual */ + _(0x00070000), /* CRC length, CRC 43c */ + _(0x00000000), /* 440 */ + _(0x00000000), /* 444 */ + _(0x54455841), /* "Texas Instruments" 448 */ + _(0x5320494e), /* 44c */ + _(0x53545255), /* 450 */ + _(0x4d454e54), /* 454 */ + _(0x53000000), /* 458 */ +/* node unique ID leaf */ + _(0x00020000), /* CRC length, CRC 45c */ + _(0x08002850), /* vendor ID, chip ID high 460 */ + _(0x0000ffff), /* chip ID low 464 */ +/* module dependent info */ + _(0x00050000), /* CRC length, CRC 468 */ + _(0x81000012), /* offset to module textual ID 46c */ + _(0x81000017), /* textual descriptor 470 */ + _(0x39010000), /* SRAM size 474 */ + _(0x3a010000), /* AUXRAM size 478 */ + _(0x3b000000), /* AUX device 47c */ +/* module textual ID */ + _(0x00050000), /* CRC length, CRC 480 */ + _(0x00000000), /* 484 */ + _(0x00000000), /* 488 */ + _(0x54534231), /* "TSB12LV21" 48c */ + _(0x324c5632), /* 490 */ + _(0x31000000), /* 494 */ +/* part number */ + _(0x00060000), /* CRC length, CRC 498 */ + _(0x00000000), /* 49c */ + _(0x00000000), /* 4a0 */ + _(0x39383036), /* "9806000-0001" 4a4 */ + _(0x3030302d), /* 4a8 */ + _(0x30303031), /* 4ac */ + _(0x20000001), /* 4b0 */ +/* module hardware version textual */ + _(0x00050000), /* CRC length, CRC 4b4 */ + _(0x00000000), /* 4b8 */ + _(0x00000000), /* 4bc */ + _(0x5453424b), /* "TSBKPCITST" 4c0 */ + _(0x50434954), /* 4c4 */ + _(0x53540000), /* 4c8 */ +/* node hardware version textual */ + _(0x00050000), /* CRC length, CRC 4d0 */ + _(0x00000000), /* 4d4 */ + _(0x00000000), /* 4d8 */ + _(0x54534232), /* "TSB21LV03" 4dc */ + _(0x314c5630), /* 4e0 */ + _(0x33000000) /* 4e4 */ }; #undef _ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/raw1394.c linux.ac/drivers/ieee1394/raw1394.c --- linux.vanilla/drivers/ieee1394/raw1394.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/ieee1394/raw1394.c Sun Jun 4 21:50:42 2000 @@ -575,8 +575,8 @@ break; case RAW1394_REQ_LOCK: - if ((req->req.misc != EXTCODE_FETCH_ADD) - && (req->req.misc != EXTCODE_LITTLE_ADD)) { + if ((req->req.misc == EXTCODE_FETCH_ADD) + || (req->req.misc == EXTCODE_LITTLE_ADD)) { if (req->req.length != 4) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; @@ -667,8 +667,8 @@ break; case RAW1394_REQ_LOCK: - if ((req->req.misc != EXTCODE_FETCH_ADD) - && (req->req.misc != EXTCODE_LITTLE_ADD)) { + if ((req->req.misc == EXTCODE_FETCH_ADD) + || (req->req.misc == EXTCODE_LITTLE_ADD)) { if (req->req.length != 4) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; @@ -690,6 +690,7 @@ break; } + req->data = packet->data; req->req.length = 4; break; @@ -716,6 +717,7 @@ if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; req->req.length = 0; + free_tlabel(packet->host, packet->node_id, packet->tlabel); queue_complete_req(req); } return sizeof(struct raw1394_request); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/ieee1394/video1394.h linux.ac/drivers/ieee1394/video1394.h --- linux.vanilla/drivers/ieee1394/video1394.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/ieee1394/video1394.h Sun Jun 4 21:50:42 2000 @@ -0,0 +1,50 @@ +/* + * video1394.h - driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _VIDEO_1394_H +#define _VIDEO_1394_H + +#define VIDEO1394_MAX_SIZE 0x400000 + +enum { + VIDEO1394_BUFFER_FREE = 0, + VIDEO1394_BUFFER_QUEUED, + VIDEO1394_BUFFER_READY +}; + +enum { + VIDEO1394_LISTEN_CHANNEL = 0, + VIDEO1394_UNLISTEN_CHANNEL, + VIDEO1394_QUEUE_BUFFER, + VIDEO1394_WAIT_BUFFER +}; + +struct video1394_mmap { + int channel; + int sync_tag; + int nb_buffers; + int buf_size; +}; + +struct video1394_wait { + int channel; + int buffer; +}; + +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/avmb1/b1pci.c linux.ac/drivers/isdn/avmb1/b1pci.c --- linux.vanilla/drivers/isdn/avmb1/b1pci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/avmb1/b1pci.c Thu Jun 8 15:08:19 2000 @@ -466,12 +466,15 @@ struct capicardparams param; int retval; - if (dev->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */ + if (pci_enable_device(dev)) + return 0; /* return failure */ + + if (pci_resource_flags(dev, 2) & IORESOURCE_IO) { /* B1 PCI V4 */ #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 driver = &b1pciv4_driver; #endif - param.membase = dev->resource[ 0].start & PCI_BASE_ADDRESS_MEM_MASK; - param.port = dev->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK; + param.membase = pci_resource_start (dev, 0); + param.port = pci_resource_start (dev, 2); param.irq = dev->irq; printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", @@ -488,7 +491,7 @@ } } else { param.membase = 0; - param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; + param.port = pci_resource_start (dev, 1); param.irq = dev->irq; printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/avmb1/c4.c linux.ac/drivers/isdn/avmb1/c4.c --- linux.vanilla/drivers/isdn/avmb1/c4.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/avmb1/c4.c Sun Jun 4 21:58:22 2000 @@ -1333,9 +1333,12 @@ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) { struct capicardparams param; - param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; + if (pci_enable_device(dev)) + continue; + + param.port = pci_resource_start (dev, 1); param.irq = dev->irq; - param.membase = dev->resource[ 0].start & PCI_BASE_ADDRESS_MEM_MASK; + param.membase = pci_resource_start (dev, 0); printk(KERN_INFO "%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/avmb1/capifs.c linux.ac/drivers/isdn/avmb1/capifs.c --- linux.vanilla/drivers/isdn/avmb1/capifs.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/avmb1/capifs.c Sat Jun 10 22:18:33 2000 @@ -209,7 +209,7 @@ dentry->d_inode = np->inode; if ( dentry->d_inode ) - dentry->d_inode->i_count++; + atomic_inc(&dentry->d_inode->i_count); d_add(dentry, dentry->d_inode); @@ -228,9 +228,9 @@ for ( i = 0 ; i < sbi->max_ncci ; i++ ) { if ( (inode = sbi->nccis[i].inode) ) { - if ( inode->i_count != 1 ) + if ( atomic_read(&inode->i_count) != 1 ) printk("capifs_put_super: badness: entry %d count %d\n", - i, inode->i_count); + i, atomic_read(&inode->i_count)); inode->i_nlink--; iput(inode); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/avmb1/kcapi.c linux.ac/drivers/isdn/avmb1/kcapi.c --- linux.vanilla/drivers/isdn/avmb1/kcapi.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/avmb1/kcapi.c Thu May 25 00:15:35 2000 @@ -281,7 +281,7 @@ *eof = 1; if (off >= len+begin) return 0; - *start = page + (off-begin); + *start = page + (begin-off); return ((count < begin+len-off) ? count : begin+len-off); } @@ -320,7 +320,7 @@ *eof = 1; if (off >= len+begin) return 0; - *start = page + (off-begin); + *start = page + (begin-off); return ((count < begin+len-off) ? count : begin+len-off); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/avmb1/t1pci.c linux.ac/drivers/isdn/avmb1/t1pci.c --- linux.vanilla/drivers/isdn/avmb1/t1pci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/avmb1/t1pci.c Sun Jun 4 21:59:02 2000 @@ -305,11 +305,12 @@ while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) { struct capicardparams param; + if (pci_enable_device(dev)) + continue; + param.port = pci_resource_start (dev, 1); param.irq = dev->irq; param.membase = pci_resource_start (dev, 0); - - pci_enable_device (dev); /* XXX check return */ printk(KERN_INFO "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/eicon/eicon_pci.c linux.ac/drivers/isdn/eicon/eicon_pci.c --- linux.vanilla/drivers/isdn/eicon/eicon_pci.c Thu May 25 17:38:10 2000 +++ linux.ac/drivers/isdn/eicon/eicon_pci.c Thu Jun 8 15:07:23 2000 @@ -148,6 +148,8 @@ } } + pci_enable_device(pdev); /* XXX handle error return */ + pci_akt = 0; switch(pci_type) { @@ -156,8 +158,8 @@ aparms->type = EICON_CTYPE_MAESTRA; aparms->irq = pdev->irq; - preg = pdev->resource[ 2].start & 0xfffffffc; - pcfg = pdev->resource[ 1].start & 0xffffff80; + preg = pci_resource_start(pdev, 2); + pcfg = pci_resource_start(pdev, 1); #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); @@ -178,9 +180,9 @@ printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n"); aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/ aparms->irq = pdev->irq; - pram = pdev->resource[ 0].start & 0xfffff000; - preg = pdev->resource[ 2].start & 0xfffff000; - pcfg = pdev->resource[ 4].start & 0xfffff000; + pram = pci_resource_start(pdev, 0); + preg = pci_resource_start(pdev, 2); + pcfg = pci_resource_start(pdev, 4); #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/avm_pci.c linux.ac/drivers/isdn/hisax/avm_pci.c --- linux.vanilla/drivers/isdn/hisax/avm_pci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/avm_pci.c Thu Jun 8 15:06:45 2000 @@ -820,11 +820,12 @@ PCI_FRITZPCI_ID, dev_avm))) { cs->irq = dev_avm->irq; if (!cs->irq) { - printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n"); + printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); return(0); } - cs->hw.avm.cfg_reg = dev_avm->resource[ 1].start & - PCI_BASE_ADDRESS_IO_MASK; + if (pci_enable_device(dev_avm)) + return(0); + cs->hw.avm.cfg_reg = pci_resource_start (dev_avm, 1); if (!cs->hw.avm.cfg_reg) { printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); return(0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/bkm_a4t.c linux.ac/drivers/isdn/hisax/bkm_a4t.c --- linux.vanilla/drivers/isdn/hisax/bkm_a4t.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/bkm_a4t.c Thu Jun 8 15:08:23 2000 @@ -319,11 +319,13 @@ if ((dev_a4t = pci_find_device(I20_VENDOR_ID, I20_DEVICE_ID, dev_a4t))) { u_int sub_sys_id = 0; + if (pci_enable_device(dev_a4t)) + return (0); pci_read_config_dword(dev_a4t, PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { found = 1; - pci_memaddr = dev_a4t->resource[ 0].start; + pci_memaddr = pci_resource_start (dev_a4t, 0); cs->irq = dev_a4t->irq; } } @@ -339,7 +341,6 @@ printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); return (0); } - pci_memaddr &= PCI_BASE_ADDRESS_MEM_MASK; cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096); /* Check suspecious address */ pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/diva.c linux.ac/drivers/isdn/hisax/diva.c --- linux.vanilla/drivers/isdn/hisax/diva.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/diva.c Thu Jun 8 15:07:54 2000 @@ -936,26 +936,28 @@ cs->subtyp = 0; if ((dev_diva = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_ID, dev_diva))) { + if (pci_enable_device(dev_diva)) + return (0); cs->subtyp = DIVA_PCI; cs->irq = dev_diva->irq; - cs->hw.diva.cfg_reg = dev_diva->resource[ 2].start - & PCI_BASE_ADDRESS_IO_MASK; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_U_ID, dev_diva_u))) { + if (pci_enable_device(dev_diva_u)) + return (0); cs->subtyp = DIVA_PCI; cs->irq = dev_diva_u->irq; - cs->hw.diva.cfg_reg = dev_diva_u->resource[ 2].start - & PCI_BASE_ADDRESS_IO_MASK; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA_201, dev_diva201))) { + if (pci_enable_device(dev_diva201)) + return (0); cs->subtyp = DIVA_IPAC_PCI; cs->irq = dev_diva201->irq; cs->hw.diva.pci_cfg = - (ulong) ioremap((dev_diva201->resource[ 0].start - & PCI_BASE_ADDRESS_IO_MASK), 4096); + (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); cs->hw.diva.cfg_reg = - (ulong) ioremap((dev_diva201->resource[ 1].start - & PCI_BASE_ADDRESS_IO_MASK), 4096); + (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); } else { printk(KERN_WARNING "Diva: No PCI card found\n"); return(0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/elsa.c linux.ac/drivers/isdn/hisax/elsa.c --- linux.vanilla/drivers/isdn/hisax/elsa.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/elsa.c Sat Jun 10 21:45:19 2000 @@ -1058,20 +1058,20 @@ cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS1000_ID, dev_qs1000))) { - cs->subtyp = ELSA_QS1000PCI; + if (pci_enable_device(dev_qs1000)) + return (0); + cs->subtyp = ELSA_QS1000PCI; cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = dev_qs1000->resource[ 1].start & - PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = dev_qs1000->resource[ 3].start & - PCI_BASE_ADDRESS_IO_MASK; + cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS3000_ID, dev_qs3000))) { + if (pci_enable_device(dev_qs1000)) + return (0); cs->subtyp = ELSA_QS3000PCI; cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = dev_qs3000->resource[ 1].start & - PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = dev_qs3000->resource[ 3].start & - PCI_BASE_ADDRESS_IO_MASK; + cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); return(0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/gazel.c linux.ac/drivers/isdn/hisax/gazel.c --- linux.vanilla/drivers/isdn/hisax/gazel.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/gazel.c Thu Jun 8 15:07:38 2000 @@ -589,7 +589,8 @@ seekcard = GAZEL_R685; for (nbseek = 0; nbseek < 3; nbseek++) { if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) { - + if (pci_enable_device(dev_tel)) + return 1; pci_irq = dev_tel->irq; pci_ioaddr0 = dev_tel->resource[ 1].start; pci_ioaddr1 = dev_tel->resource[ 2].start; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/hfc_pci.c linux.ac/drivers/isdn/hisax/hfc_pci.c --- linux.vanilla/drivers/isdn/hisax/hfc_pci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/hfc_pci.c Sat Jun 10 21:45:11 2000 @@ -1738,7 +1738,9 @@ dev_hfcpci); i++; if (tmp_hfcpci) { - if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + if (pci_enable_device(tmp_hfcpci)) + continue; + if ((card->para[0]) && (card->para[0] != pci_resource_start(tmp_hfcpci, 0))) continue; else break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/netjet.c linux.ac/drivers/isdn/hisax/netjet.c --- linux.vanilla/drivers/isdn/hisax/netjet.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/netjet.c Sat Jun 10 21:45:04 2000 @@ -1130,13 +1130,14 @@ } if ((dev_netjet = pci_find_device(PCI_VENDOR_TRAVERSE_TECH, PCI_NETJET_ID, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return (0); cs->irq = dev_netjet->irq; if (!cs->irq) { printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); return(0); } - cs->hw.njet.base = dev_netjet->resource[ 0].start - & PCI_BASE_ADDRESS_IO_MASK; + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); if (!cs->hw.njet.base) { printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); return(0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/niccy.c linux.ac/drivers/isdn/hisax/niccy.c --- linux.vanilla/drivers/isdn/hisax/niccy.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/niccy.c Sat Jun 10 21:44:58 2000 @@ -313,6 +313,8 @@ cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS, PCI_NICCY_ID, niccy_dev))) { + if (pci_enable_device(niccy_dev)) + return (0); /* get IRQ */ if (!niccy_dev->irq) { printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); @@ -323,12 +325,12 @@ printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); return(0); } - cs->hw.niccy.cfg_reg = niccy_dev->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; + cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0); if (!niccy_dev->resource[ 1].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr = niccy_dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = pci_resource_start(niccy_dev, 1); cs->subtyp = NICCY_PCI; } else { printk(KERN_WARNING "Niccy: No PCI card found\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/sedlbauer.c linux.ac/drivers/isdn/hisax/sedlbauer.c --- linux.vanilla/drivers/isdn/hisax/sedlbauer.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/sedlbauer.c Sat Jun 10 21:44:46 2000 @@ -641,23 +641,22 @@ } if ((dev_sedl = pci_find_device(PCI_VENDOR_SEDLBAUER, PCI_SPEEDPCI_ID, dev_sedl))) { + if (pci_enable_device(dev_sedl)) + return (0); cs->irq = dev_sedl->irq; if (!cs->irq) { printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); return(0); } - cs->hw.sedl.cfg_reg = dev_sedl->resource[ 0].start & - PCI_BASE_ADDRESS_IO_MASK; + cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); } else { printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); return(0); } cs->irq_flags |= SA_SHIRQ; cs->hw.sedl.bus = SEDL_BUS_PCI; - pci_read_config_word(dev_sedl, PCI_SUBSYSTEM_VENDOR_ID, - &sub_vendor_id); - pci_read_config_word(dev_sedl, PCI_SUBSYSTEM_ID, - &sub_id); + sub_vendor_id = dev_sedl->subsystem_vendor; + sub_id = dev_sedl->subsystem_device; printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", sub_vendor_id, sub_id); printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/telespci.c linux.ac/drivers/isdn/hisax/telespci.c --- linux.vanilla/drivers/isdn/hisax/telespci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/telespci.c Sun Jun 4 21:59:41 2000 @@ -325,6 +325,8 @@ return(0); } if ((dev_tel = pci_find_device (0x11DE, 0x6120, dev_tel))) { + if (pci_enable_device(dev_tel)) + return (0); cs->irq = dev_tel->irq; if (!cs->irq) { printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hisax/w6692.c linux.ac/drivers/isdn/hisax/w6692.c --- linux.vanilla/drivers/isdn/hisax/w6692.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/hisax/w6692.c Sun Jun 4 22:00:27 2000 @@ -1009,8 +1009,11 @@ dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); - if (dev_w6692) + if (dev_w6692) { + if (pci_enable_device(dev_w6692)) + continue; break; + } id_idx++; } if (dev_w6692) { @@ -1018,7 +1021,7 @@ pci_irq = dev_w6692->irq; /* I think address 0 is allways the configuration area */ /* and address 1 is the real IO space KKe 03.09.99 */ - pci_ioaddr = dev_w6692->resource[ 1].start; + pci_ioaddr = pci_resource_start(dev_w6692, 1); } if (!found) { printk(KERN_WARNING "W6692: No PCI card found\n"); @@ -1029,7 +1032,6 @@ printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); return (0); } - pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; if (!pci_ioaddr) { printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); return (0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/hysdn/hysdn_init.c linux.ac/drivers/isdn/hysdn/hysdn_init.c --- linux.vanilla/drivers/isdn/hysdn/hysdn_init.c Thu May 25 17:38:10 2000 +++ linux.ac/drivers/isdn/hysdn/hysdn_init.c Sat Jun 10 21:44:17 2000 @@ -84,7 +84,8 @@ card_last = NULL; while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_PLX, akt_pcidev)) != NULL) { - + if (pci_enable_device(akt_pcidev)) + continue; if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) { printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); return; @@ -93,12 +94,11 @@ card->myid = cardmax; /* set own id */ card->bus = akt_pcidev->bus->number; card->devfn = akt_pcidev->devfn; /* slot + function */ - pcibios_read_config_word(card->bus, card->devfn, PCI_SUBSYSTEM_ID, &card->subsysid); - pcibios_read_config_byte(card->bus, card->devfn, PCI_INTERRUPT_LINE, &irq); - card->irq = irq; - card->iobase = akt_pcidev->resource[ PCI_REG_PLX_IO_BASE].start & PCI_BASE_ADDRESS_IO_MASK; - card->plxbase = akt_pcidev->resource[ PCI_REG_PLX_MEM_BASE].start; - card->membase = akt_pcidev->resource[ PCI_REG_MEMORY_BASE].start; + card->subsysid = akt_pcidev->subsystem_device; + card->irq = akt_pcidev->irq; + card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE); + card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE); + card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE); card->brdtype = BD_NONE; /* unknown */ card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ card->faxchans = 0; /* default no fax channels */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/isdn/isdn_tty.c linux.ac/drivers/isdn/isdn_tty.c --- linux.vanilla/drivers/isdn/isdn_tty.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/isdn/isdn_tty.c Mon May 29 19:21:40 2000 @@ -381,8 +381,14 @@ #define MODEM_PARANOIA_CHECK #define MODEM_DO_RESTART +#ifdef CONFIG_DEVFS_FS +static char *isdn_ttyname_ttyI = "isdn/ttyI%d"; +static char *isdn_ttyname_cui = "isdn/cui%d"; +#else static char *isdn_ttyname_ttyI = "ttyI"; static char *isdn_ttyname_cui = "cui"; +#endif + static int bit2si[8] = {1, 5, 7, 7, 7, 7, 7, 7}; static int si2bit[8] = diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/macintosh/mac_keyb.c linux.ac/drivers/macintosh/mac_keyb.c --- linux.vanilla/drivers/macintosh/mac_keyb.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/macintosh/mac_keyb.c Sat Jun 10 21:46:58 2000 @@ -225,7 +225,7 @@ static void kbd_repeat(unsigned long); -static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat }; +static struct timer_list repeat_timer = { function: kbd_repeat }; static int last_keycode; static void mackeyb_probe(void); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/3c503.c linux.ac/drivers/net/3c503.c --- linux.vanilla/drivers/net/3c503.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/3c503.c Thu Jun 8 15:05:21 2000 @@ -99,7 +99,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return el2_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (addr = addrs; *addr; addr++) { int i; @@ -118,7 +118,7 @@ #if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST) return el2_pio_probe(dev); #else - return ENODEV; + return -ENODEV; #endif } @@ -134,7 +134,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return el2_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; @@ -144,7 +144,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -161,7 +161,7 @@ /* Reset and/or avoid any lurking NE2000 */ if (inb(ioaddr + 0x408) == 0xff) { mdelay(1); - return ENODEV; + return -ENODEV; } /* We verify that it's a 3C503 board by checking the first three octets @@ -171,7 +171,7 @@ /* ASIC location registers should be 0 or have only a single bit set. */ if ( (iobase_reg & (iobase_reg - 1)) || (membase_reg & (membase_reg - 1))) { - return ENODEV; + return -ENODEV; } saved_406 = inb_p(ioaddr + 0x406); outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ @@ -183,12 +183,9 @@ if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) { /* Restore the register we frobbed. */ outb(saved_406, ioaddr + 0x406); - return ENODEV; + return -ENODEV; } - if (load_8390_module("3c503.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk("3c503.c: Passed a NULL device.\n"); @@ -645,6 +642,9 @@ { int this_dev, found = 0; + if (load_8390_module("3c503.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { struct net_device *dev = &dev_el2[this_dev]; dev->irq = irq[this_dev]; @@ -658,14 +658,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -684,7 +683,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/3c507.c linux.ac/drivers/net/3c507.c --- linux.vanilla/drivers/net/3c507.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/3c507.c Sun Jun 4 21:52:47 2000 @@ -315,7 +315,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return el16_probe1(dev, base_addr); else if (base_addr != 0) - return ENXIO; /* Don't probe at all. */ + return -ENXIO; /* Don't probe at all. */ for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; @@ -325,7 +325,7 @@ return 0; } - return ENODEV; + return -ENODEV; } static int __init el16_probe1(struct net_device *dev, int ioaddr) @@ -351,7 +351,7 @@ && inb(ioaddr+2) == 'C' && inb(ioaddr+3) == 'O') ; else - return ENODEV; + return -ENODEV; /* Allocate a new 'dev' if needed. */ if (dev == NULL) @@ -370,7 +370,7 @@ irqval = request_irq(irq, &el16_interrupt, 0, "3c507", dev); if (irqval) { printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); - return EAGAIN; + return -EAGAIN; } /* We've committed to using the board, and can start filling in *dev. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/3c515.c linux.ac/drivers/net/3c515.c --- linux.vanilla/drivers/net/3c515.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/3c515.c Tue Jun 6 17:43:20 2000 @@ -448,7 +448,7 @@ goto no_pnp; for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) { struct pci_dev *idev = NULL; - int irq, j; + int irq; while((idev = isapnp_find_dev(NULL, corkscrew_isapnp_adapters[i].vendor, corkscrew_isapnp_adapters[i].function, @@ -1427,7 +1427,7 @@ entry = (++vp->cur_rx) % RX_RING_SIZE; } /* Refill the Rx ring buffers. */ - for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) { + for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) { struct sk_buff *skb; entry = vp->dirty_rx % RX_RING_SIZE; if (vp->rx_skbuff[entry] == NULL) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/3c523.c linux.ac/drivers/net/3c523.c --- linux.vanilla/drivers/net/3c523.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/3c523.c Sun Jun 4 21:53:30 2000 @@ -417,7 +417,7 @@ unsigned int size = 0; if (MCA_bus == 0) { - return ENODEV; + return -ENODEV; } /* search through the slots for the 3c523. */ slot = mca_find_adapter(ELMC_MCA_ID, 0); @@ -519,7 +519,7 @@ printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); release_region(dev->base_addr, ELMC_IO_EXTENT); - return ENODEV; + return -ENODEV; } dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/3c59x.c linux.ac/drivers/net/3c59x.c --- linux.vanilla/drivers/net/3c59x.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/3c59x.c Thu Jun 8 14:51:54 2000 @@ -9,7 +9,7 @@ Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597 and the EtherLink XL 3c900 and 3c905 cards. - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + The author may be reached as becker@scyld.com, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 @@ -53,7 +53,7 @@ - Increased the loop counter in wait_for_completion from 2,000 to 4,000. LK1.1.5 28 April 2000, andrewm - - Added powerpc defines + - Added powerpc defines (John Daniel said these work...) - Some extra diagnostics - In vortex_error(), reset the Tx on maxCollisions. Otherwise most chips usually get a Tx timeout. @@ -63,6 +63,20 @@ - In vortex_up(), don't make Wn3_config initialisation dependent upon has_nway (this came across from 3c575_cb). + LK1.1.6 06 Jun 2000, andrewm + - Backed out the PPC defines. + - Use del_timer_sync(), mod_timer(). + - Fix wrapped ulong comparison in boomerang_rx() + - Add IS_TORNADO, use it to suppress 3c905C checksum error msg + (Donald Becker, I Lee Hetherington ) + - Replace union wn3_config with BFINS/BFEXT manipulation for + sparc64 (Pete Zaitcev, Peter Jones) + - In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex): + do a netif_wake_queue() to better recover from errors. (Anders Pedersen, + Donald Becker) + - Print a warning on out-of-memory (rate limited to 1 per 10 secs) + - Added two more Cardbus 575 NICs: 5b57 and 6564 (Paul Wagland) + - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. */ @@ -75,6 +89,12 @@ * elimination of all the tests and reduced cache footprint. */ +/* A few values that may be tweaked. */ +/* Keep the ring sizes a power of two for efficiency. */ +#define TX_RING_SIZE 16 +#define RX_RING_SIZE 32 +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ + /* "Knobs" that adjust features and parameters. */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1512 effectively disables this feature. */ @@ -85,6 +105,8 @@ static int max_interrupt_work = 32; /* Give the NIC an extra reset at the end of vortex_up() */ static int extra_reset = 0; +/* Tx timeout interval (millisecs) */ +static int watchdog = 400; /* Allow aggregation of Tx interrupts. Saves CPU load at the cost * of possible Tx stalls if the system is blocking interrupts @@ -92,6 +114,7 @@ * AKPM 26 April 2000: enabling this still gets vestigial Tx timeouts * in a heavily loaded (collision-prone) 10BaseT LAN. Should be OK with * switched Ethernet. + * AKPM 24May00: vestigial timeouts have been removed by later fixes. */ #define tx_interrupt_mitigation 1 @@ -107,15 +130,6 @@ debugging. */ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; -/* A few values that may be tweaked. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT ((400*HZ)/1000) - -/* Keep the ring sizes a power of two for efficiency. */ -#define TX_RING_SIZE 16 -#define RX_RING_SIZE 32 -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ - #ifndef __OPTIMIZE__ #error You must compile this file with the correct options! #error See the last lines of the source file. @@ -141,12 +155,6 @@ #include #include -/* John Daniel said these work... */ -#ifdef __powerpc__ -#define outsl outsl_ns -#define insl insl_ns -#endif - /* Kernel compatibility defines, some common to David Hinds' PCMCIA package. This is only in the support-all-kernels source code. */ @@ -155,9 +163,9 @@ #include static char version[] __devinitdata = -"3c59x.c:v0.99L+LK1.1.5 30 Apr 2000 Donald Becker and others http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html " "$Revision: 1.78 $\n"; +"3c59x.c:v0.99L+LK1.1.6 28 May 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.97 $\n"; -MODULE_AUTHOR("Donald Becker "); +MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver"); MODULE_PARM(debug, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); @@ -168,6 +176,7 @@ MODULE_PARM(compaq_ioaddr, "i"); MODULE_PARM(compaq_irq, "i"); MODULE_PARM(compaq_device_id, "i"); +MODULE_PARM(watchdog, "i"); /* Operational parameter that usually are not changed. */ @@ -271,9 +280,9 @@ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; -enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, - EEPROM_230=8, /* AKPM: Uses 0x230 as the base bitmpas for EEPROM reads */ - HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, }; +enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8, + EEPROM_230=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ + HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, }; enum vortex_chips { @@ -284,31 +293,33 @@ CH_3C595_2, CH_3C595_3, - CH_VORTEX, CH_3C900_1, CH_3C900_2, CH_3C900_3, - CH_3C900_4, + CH_3C900_5, CH_3C900B_FL, CH_3C905_1, CH_3C905_2, - CH_3C905B_1, + CH_3C905B_2, CH_3C905B_FX, CH_3C905C, CH_3C980, + CH_3C9805, CH_3CSOHO100_TX, CH_3C555, + CH_3C575, CH_3C575_1, CH_3CCFE575, - CH_3CCFE575CT, + CH_3CCFE575CT, CH_3CCFE656, CH_3CCFEM656, + CH_3CCFEM656_1, CH_3C450, }; @@ -323,6 +334,7 @@ int drv_flags; int io_size; } vortex_info_tbl[] __devinitdata = { +#define EISA_TBL_OFFSET 0 /* Offset of this entry for vortex_eisa_init */ {"3c590 Vortex 10Mbps", PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, {"3c592 EISA 10mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */ @@ -336,18 +348,15 @@ {"3c595 Vortex 100base-MII", PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, }, -#define EISA_TBL_OFFSET 6 /* Offset of this entry for vortex_eisa_init */ - {"3Com Vortex", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, {"3c900 Boomerang 10baseT", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, {"3c900 Boomerang 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, {"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, - {"3c900 Cyclone 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, + {"3c900 Cyclone 10Mbps TPC", /* AKPM: from Don's 0.99M */ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3c900B-FL Cyclone 10base-FL", @@ -356,35 +365,42 @@ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, }, {"3c905 Boomerang 100baseT4", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, }, - {"3c905B Cyclone 100baseTx", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, + {"3c905B Cyclone 10/100/BNC", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, {"3c905B-FX Cyclone 100baseFx", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3c905C Tornado", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, }, {"3c980 Cyclone", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, + {"3c980 10/100 Base-TX NIC(Python-T)", + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3cSOHO100-TX Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3c555 Laptop Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, + {"3c575 [Megahertz] 10/100 LAN CardBus", + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, }, {"3c575 Boomerang CardBus", - PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 64, }, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, }, {"3CCFE575 Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, }, + {"3CCFE575CT Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, }, - {"3CCFE656 Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, }, {"3CCFEM656 Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, }, - {"3c450 Cyclone/unknown", /* AKPM: from Don's 0.99N */ - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, + {"3CCFEM656 Cyclone CardBus(0x6564)", /* From pcmcia-cs-3.1.5 */ + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, }, + {"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */ + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, }, + {0,}, /* 0 terminated list. */ }; @@ -397,32 +413,35 @@ { 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 }, { 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 }, - { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VORTEX }, { 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 }, { 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 }, { 0x10B7, 0x9004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 }, - { 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_4 }, + { 0x10B7, 0x9006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_5 }, { 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL }, { 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 }, { 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 }, - { 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 }, + { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 }, { 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX }, { 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C }, { 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 }, + { 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 }, { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX }, { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 }, + { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 }, { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 }, - { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT }, + { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT }, { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 }, { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 }, + { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 }, + {0,} /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); @@ -501,15 +520,21 @@ enum Window3 { /* Window 3: MAC/config bits. */ Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, }; -union wn3_config { - int i; - struct w3_config_fields { - unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; - int pad8:8; - unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1; - int pad24:7; - } u; -}; + +#define BFEXT(value, offset, bitcount) \ + ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1)) + +#define BFINS(lhs, rhs, offset, bitcount) \ + (((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \ + (((rhs) & ((1 << (bitcount)) - 1)) << (offset))) + +#define RAM_SIZE(v) BFEXT(v, 0, 3) +#define RAM_WIDTH(v) BFEXT(v, 3, 1) +#define RAM_SPEED(v) BFEXT(v, 4, 2) +#define ROM_SIZE(v) BFEXT(v, 6, 2) +#define RAM_SPLIT(v) BFEXT(v, 16, 2) +#define XCVR(v) BFEXT(v, 20, 4) +#define AUTOSELECT(v) BFEXT(v, 24, 1) enum Window4 { /* Window 4: Xcvr/media bits. */ Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10, @@ -532,7 +557,8 @@ /* The Rx and Tx descriptor lists. Caution Alpha hackers: these types are 32 bits! Note also the 8 byte alignment contraint on tx_ring[] and rx_ring[]. */ -#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */ +#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */ +#define DN_COMPLETE 0x00010000 /* This packet has been downloaded */ struct boom_rx_desc { u32 next; /* Last entry points to 0. */ s32 status; @@ -785,6 +811,7 @@ struct net_device *dev; static int printed_version = 0; int retval; + struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx]; if (!printed_version) { printk (KERN_INFO "%s", version); @@ -801,7 +828,7 @@ printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ", dev->name, pdev ? "PCI" : "EISA", - vortex_info_tbl[chip_idx].name, + vci->name, ioaddr); /* private struct aligned and zeroed by init_etherdev */ @@ -809,8 +836,8 @@ dev->base_addr = ioaddr; dev->irq = irq; dev->mtu = mtu; - vp->has_nway = (vortex_info_tbl[chip_idx].drv_flags & HAS_NWAY) ? 1 : 0; - vp->io_size = vortex_info_tbl[chip_idx].io_size; + vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0; + vp->io_size = vci->io_size; /* module list only for EISA devices */ if (pdev == NULL) { @@ -821,10 +848,9 @@ /* PCI-only startup logic */ if (pdev) { /* EISA resources already marked, so only PCI needs to do this here */ - if (!request_region (ioaddr, vortex_info_tbl[chip_idx].io_size, - dev->name)) { + if (!request_region (ioaddr, vci->io_size, dev->name)) { printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", - dev->name, vortex_info_tbl[chip_idx].io_size, ioaddr); + dev->name, vci->io_size, ioaddr); retval = -EBUSY; goto free_dev; } @@ -836,7 +862,7 @@ } /* enable bus-mastering if necessary */ - if (vortex_info_tbl[chip_idx].flags & PCI_USES_MASTER) + if (vci->flags & PCI_USES_MASTER) pci_set_master (pdev); } @@ -891,7 +917,7 @@ /* Read the station address from the EEPROM. */ EL3WINDOW(0); { - int base = (vortex_info_tbl[chip_idx].drv_flags & EEPROM_230) ? 0x230 : EEPROM_Read; + int base = (vci->drv_flags & EEPROM_230) ? 0x230 : EEPROM_Read; for (i = 0; i < 0x40; i++) { int timer; outw(base + i, ioaddr + Wn0EepromCmd); @@ -912,7 +938,7 @@ checksum ^= eeprom[i++]; checksum = (checksum ^ (checksum >> 8)) & 0xff; } - if (checksum != 0x00) + if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO)) printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); @@ -932,7 +958,7 @@ dev->irq); #endif - if (pdev && vortex_info_tbl[chip_idx].drv_flags & HAS_CB_FNS) { + if (pdev && vci->drv_flags & HAS_CB_FNS) { u32 fn_st_addr; /* Cardbus function status space */ fn_st_addr = pci_resource_start (pdev, 2); if (fn_st_addr) @@ -960,24 +986,24 @@ { static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; - union wn3_config config; + unsigned int config; EL3WINDOW(3); vp->available_media = inw(ioaddr + Wn3_Options); if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ vp->available_media = 0x40; - config.i = inl(ioaddr + Wn3_Config); + config = inl(ioaddr + Wn3_Config); if (vortex_debug > 1) printk(KERN_DEBUG " Internal config register is %4.4x, " - "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options)); + "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options)); printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", - 8 << config.u.ram_size, - config.u.ram_width ? "word" : "byte", - ram_split[config.u.ram_split], - config.u.autoselect ? "autoselect/" : "", - config.u.xcvr > XCVR_ExtMII ? "" : - media_tbl[config.u.xcvr].name); - vp->default_media = config.u.xcvr; - vp->autoselect = config.u.autoselect; + 8 << RAM_SIZE(config), + RAM_WIDTH(config) ? "word" : "byte", + ram_split[RAM_SPLIT(config)], + AUTOSELECT(config) ? "autoselect/" : "", + XCVR(config) > XCVR_ExtMII ? "" : + media_tbl[XCVR(config)].name); + vp->default_media = XCVR(config); + vp->autoselect = AUTOSELECT(config); } if (vp->media_override != 7) { @@ -1037,12 +1063,12 @@ dev->do_ioctl = &vortex_ioctl; dev->set_multicast_list = &set_rx_mode; dev->tx_timeout = &vortex_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; + dev->watchdog_timeo = (watchdog * HZ) / 1000; return 0; free_region: - release_region (ioaddr, vortex_info_tbl[chip_idx].io_size); + release_region (ioaddr, vci->io_size); free_dev: unregister_netdev(dev); kfree (dev); @@ -1070,7 +1096,7 @@ { long ioaddr = dev->base_addr; struct vortex_private *vp = (struct vortex_private *)dev->priv; - union wn3_config config; + unsigned int config; int i, device_id; if (vp->pdev) @@ -1080,7 +1106,7 @@ /* Before initializing select the active media port. */ EL3WINDOW(3); - config.i = inl(ioaddr + Wn3_Config); + config = inl(ioaddr + Wn3_Config); if (vp->media_override != 7) { if (vortex_debug > 1) @@ -1118,13 +1144,13 @@ dev->name, media_tbl[dev->if_port].name); vp->full_duplex = vp->force_fd; - config.u.xcvr = dev->if_port; + config = BFINS(config, dev->if_port, 20, 4); //AKPM if (!vp->has_nway) { if (vortex_debug > 6) printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", - config.i); - outl(config.i, ioaddr + Wn3_Config); + config); + outl(config, ioaddr + Wn3_Config); } if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { @@ -1151,7 +1177,7 @@ if (vortex_debug > 1) { printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n", - dev->name, config.i); + dev->name, config); } wait_for_completion(dev, TxReset); @@ -1233,8 +1259,6 @@ set_rx_mode(dev); outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - netif_start_queue (dev); - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ @@ -1264,6 +1288,7 @@ } outw(TxEnable, ioaddr + EL3_CMD); } + netif_start_queue (dev); } static int @@ -1321,9 +1346,11 @@ int ok = 0; int media_status, mii_status, old_window; - if (vortex_debug > 1) + if (vortex_debug > 1) { printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", dev->name, media_tbl[dev->if_port].name); + printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo); + } disable_irq(dev->irq); old_window = inw(ioaddr + EL3_CMD) >> 13; @@ -1383,7 +1410,7 @@ ok = 1; } if ( ! ok) { - union wn3_config config; + unsigned int config; do { dev->if_port = media_tbl[dev->if_port].next; @@ -1405,14 +1432,14 @@ media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); EL3WINDOW(3); - config.i = inl(ioaddr + Wn3_Config); - config.u.xcvr = dev->if_port; - outl(config.i, ioaddr + Wn3_Config); + config = inl(ioaddr + Wn3_Config); + config = BFINS(config, dev->if_port, 20, 4); + outl(config, ioaddr + Wn3_Config); outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, ioaddr + EL3_CMD); if (vortex_debug > 1) - printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config.i); + printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config); /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */ } EL3WINDOW(old_window); @@ -1422,10 +1449,10 @@ printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n", dev->name, media_tbl[dev->if_port].name); - vp->timer.expires = RUN_AT(next_tick); - add_timer(&vp->timer); + mod_timer(&vp->timer, RUN_AT(next_tick)); if (vp->deferred) outw(FakeIntr, ioaddr + EL3_CMD); + timer_exit(&vp->timer); return; } @@ -1437,6 +1464,7 @@ printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", dev->name, inb(ioaddr + TxStatus), inw(ioaddr + EL3_STATUS)); + /* Slight code bloat to be user friendly. */ if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) printk(KERN_ERR "%s: Transmitter encountered 16 collisions --" @@ -1460,7 +1488,7 @@ } } - if (vortex_debug > 1) + if (vortex_debug > 0) dump_tx_ring(dev); wait_for_completion(dev, TxReset); @@ -1481,8 +1509,10 @@ netif_stop_queue (dev); outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); outw(DownUnstall, ioaddr + EL3_CMD); - } else + } else { vp->stats.tx_dropped++; + netif_wake_queue(dev); + } /* Issue Tx Enable */ outw(TxEnable, ioaddr + EL3_CMD); @@ -1607,6 +1637,7 @@ } else { wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); + netif_wake_queue(dev); } } } @@ -1875,9 +1906,15 @@ outw(AckIntr | DownComplete, ioaddr + EL3_CMD); while (vp->cur_tx - dirty_tx > 0) { int entry = dirty_tx % TX_RING_SIZE; +#if 1 /* AKPM: the latter is faster, but cyclone-only */ if (inl(ioaddr + DownListPtr) == vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc)) break; /* It still hasn't been processed. */ +#else + if ((vp->tx_ring[entry].status & DN_COMPLETE) == 0) + break; /* It still hasn't been processed. */ +#endif + if (vp->tx_skbuff[entry]) { struct sk_buff *skb = vp->tx_skbuff[entry]; @@ -1899,8 +1936,6 @@ netif_wake_queue (dev); } } - if (vp->tx_full) - netif_stop_queue (dev); /* Check for all uncommon interrupts at once. */ if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) @@ -1925,7 +1960,7 @@ if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ writel(0x8000, vp->cb_fn_base + 4); - } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); + } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch); if (vortex_debug > 4) printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", @@ -2041,8 +2076,7 @@ /* Check if the packet is long enough to just accept without copying to a properly sized skbuff. */ - if (pkt_len < rx_copybreak - && (skb = dev_alloc_skb(pkt_len + 2)) != 0) { + if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != 0) { skb->dev = dev; skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); @@ -2076,13 +2110,19 @@ entry = (++vp->cur_rx) % RX_RING_SIZE; } /* Refill the Rx ring buffers. */ - for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) { + for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) { struct sk_buff *skb; entry = vp->dirty_rx % RX_RING_SIZE; if (vp->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(PKT_BUF_SZ); - if (skb == NULL) + if (skb == NULL) { + static unsigned long last_jif; + if ((jiffies - last_jif) > 10 * HZ) { + printk(KERN_WARNING "%s: memory shortage\n", dev->name); + last_jif = jiffies; + } break; /* Bad news! */ + } skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE)); @@ -2102,7 +2142,7 @@ netif_stop_queue (dev); - del_timer(&vp->timer); + del_timer_sync(&vp->timer); /* Turn off statistics ASAP. We update vp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); @@ -2184,16 +2224,16 @@ int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */ wait_for_completion(dev, DownStall); - printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d(%d) " + printk(KERN_ERR " Flags; bus-master %d, full %d; dirty %d(%d) " "current %d(%d).\n", vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE, vp->cur_tx, vp->cur_tx % TX_RING_SIZE); - printk(KERN_DEBUG " Transmit list %8.8x vs. %p.\n", + printk(KERN_ERR " Transmit list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]); for (i = 0; i < TX_RING_SIZE; i++) { - printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i, + printk(KERN_ERR " %d: @%p length %8.8x status %8.8x\n", i, &vp->tx_ring[i], le32_to_cpu(vp->tx_ring[i].length), le32_to_cpu(vp->tx_ring[i].status)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/8139too.c linux.ac/drivers/net/8139too.c --- linux.vanilla/drivers/net/8139too.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/8139too.c Wed May 31 11:25:23 2000 @@ -97,7 +97,7 @@ #include -#define RTL8139_VERSION "0.9.5" +#define RTL8139_VERSION "0.9.6" #define RTL8139_MODULE_NAME "8139too" #define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION #define PFX RTL8139_MODULE_NAME ": " @@ -232,6 +232,7 @@ IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, + ChipVersion = 0x43, RxConfig = 0x44, Timer = 0x48, /* A general-purpose counter. */ RxMissed = 0x4C, /* 24 bits valid, write clears. */ @@ -392,8 +393,8 @@ typedef enum { CH_8139 = 0, + CH_8139_K, CH_8139A, - CH_8139A_G, CH_8139B, CH_8130, CH_8139C, @@ -403,36 +404,36 @@ /* directly indexed by chip_t, above */ const static struct { const char *name; - u32 version; /* from RTL8139C docs */ + u8 version; /* from RTL8139C docs */ u32 RxConfigMask; /* should clear the bits supported by this chip */ } rtl_chip_info[] = { { "RTL-8139", - 0x60000000, + 0x40, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, - { "RTL-8139A", - 0x70000000, - 0xf0fe0040, + { "RTL-8139 rev K", + 0x60, + 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, - { "RTL-8139A rev. G", - 0x70800000, + { "RTL-8139A", + 0x70, 0xf0fe0040, }, { "RTL-8139B", - 0x78000000, + 0x78, 0xf0fc0040 }, { "RTL-8130", - 0x7C000000, + 0x7C, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139C", - 0x74000000, + 0x74, 0xf0fc0040, /* XXX copied from RTL8139B, verify */ }, @@ -672,7 +673,7 @@ } /* identify chip attached to board */ - tmp = RTL_R32 (TxConfig) & TxVersionMask; + tmp = RTL_R8 (ChipVersion); for (i = arraysize (rtl_chip_info) - 1; i >= 0; i--) if (tmp == rtl_chip_info[i].version) { tp->chipset = i; @@ -686,10 +687,8 @@ tp->chipset = 0; match: - DPRINTK ("chipset id (%d/%d/%d) == %d, '%s'\n", - CH_8139, - CH_8139A, - CH_8139B, + DPRINTK ("chipset id (%d) == index %d, '%s'\n", + tmp, tp->chipset, rtl_chip_info[tp->chipset].name); @@ -1703,8 +1702,8 @@ } else { eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], - rx_size, 0); - skb_put (skb, rx_size); + rx_size - 4, 0); + skb_put (skb, rx_size - 4); } skb->protocol = eth_type_trans (skb, dev); netif_rx (skb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/8390.c linux.ac/drivers/net/8390.c --- linux.vanilla/drivers/net/8390.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/8390.c Mon Jun 5 19:20:11 2000 @@ -1152,17 +1152,13 @@ EXPORT_SYMBOL(ethdev_init); EXPORT_SYMBOL(NS8390_init); -struct module *NS8390_module = NULL; - int init_module(void) { - NS8390_module = &__this_module; return 0; } void cleanup_module(void) { - NS8390_module = NULL; } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/8390.h linux.ac/drivers/net/8390.h --- linux.vanilla/drivers/net/8390.h Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/8390.h Sat Jun 10 22:43:12 2000 @@ -53,24 +53,49 @@ #if defined(LOAD_8390_BY_KMOD) && defined(MODULE) && !defined(NS8390_CORE) /* Function pointers to be mapped onto the 8390 core support */ -static int (*S_ethdev_init)(struct net_device *dev); -static void (*S_NS8390_init)(struct net_device *dev, int startp); -static int (*S_ei_open)(struct net_device *dev); -static int (*S_ei_close)(struct net_device *dev); -static void (*S_ei_interrupt)(int irq, void *dev_id, struct pt_regs *regs); +static int (*S_ethdev_init)(struct net_device *dev) = NULL; +static void (*S_NS8390_init)(struct net_device *dev, int startp) = NULL; +static int (*S_ei_open)(struct net_device *dev) = NULL; +static int (*S_ei_close)(struct net_device *dev) = NULL; +static void (*S_ei_interrupt)(int irq, void *dev_id, struct pt_regs *regs) = NULL; - -#define NS8390_KSYSMS_PRESENT ( \ - get_module_symbol(NULL, "ethdev_init") != 0 && \ - get_module_symbol(NULL, "NS8390_init") != 0 && \ - get_module_symbol(NULL, "ei_open") != 0 && \ - get_module_symbol(NULL, "ei_close") != 0 && \ - get_module_symbol(NULL, "ei_interrupt") != 0) +extern __inline__ void unload_8390_module(void) +{ + if (S_ethdev_init) { + put_module_symbol((unsigned long)S_ethdev_init); + S_ethdev_init = NULL; + } + if (S_NS8390_init) { + put_module_symbol((unsigned long)S_NS8390_init); + S_NS8390_init = NULL; + } + if (S_ei_open) { + put_module_symbol((unsigned long)S_ei_open); + S_ei_open = NULL; + } + if (S_ei_close) { + put_module_symbol((unsigned long)S_ei_close); + S_ei_close = NULL; + } + if (S_ei_interrupt) { + put_module_symbol((unsigned long)S_ei_interrupt); + S_ei_interrupt = NULL; + } +} extern __inline__ int load_8390_module(const char *driver) { + /* Do we actually need to handle this case? */ + if (S_ethdev_init) { + printk(KERN_DEBUG "%s: load_8390_module called when pointers already present\n", driver); + return 0; + } + + /* Attempt to get the first symbol */ + S_ethdev_init = (void *)get_module_symbol(NULL, "ethdev_init"); - if (! NS8390_KSYSMS_PRESENT) { + if (!S_ethdev_init) { + /* It failed. See if we have request_module() */ int (*request_mod)(const char *module_name); if (get_module_symbol("", "request_module") == 0) { @@ -80,52 +105,34 @@ return -ENOSYS; } + /* OK - we have request_module() - try it */ request_mod = (void*)get_module_symbol("", "request_module"); if (request_mod("8390")) { printk("%s: request to load the 8390 module failed.\n", driver); return -ENOSYS; } - /* Check if module really loaded and is valid */ - if (! NS8390_KSYSMS_PRESENT) { - printk("%s: 8390.o not found/invalid or failed to load.\n", driver); - return -ENOSYS; - } - printk(KERN_INFO "%s: auto-loaded 8390 module.\n", driver); + + /* Retry getting ethdev_init */ + S_ethdev_init = (void *)get_module_symbol(NULL, "ethdev_init"); } - /* Map the functions into place */ - S_ethdev_init = (void*)get_module_symbol(0, "ethdev_init"); + /* Get addresses for the other functions */ S_NS8390_init = (void*)get_module_symbol(0, "NS8390_init"); S_ei_open = (void*)get_module_symbol(0, "ei_open"); S_ei_close = (void*)get_module_symbol(0, "ei_close"); S_ei_interrupt = (void*)get_module_symbol(0, "ei_interrupt"); - return 0; -} - -/* - * Since a kmod aware driver won't explicitly show a dependence on the - * exported 8390 functions (due to the mapping above), the 8390 module - * (if present, and not in-kernel) needs to be protected from garbage - * collection. NS8390_module is only defined for a modular 8390 core. - */ - -extern __inline__ void lock_8390_module(void) -{ - struct module **mod = (struct module**)get_module_symbol(0, "NS8390_module"); - - if (mod != NULL && *mod != NULL) - __MOD_INC_USE_COUNT(*mod); + /* Check if module really loaded and is valid */ + if (!S_ethdev_init || !S_NS8390_init || !S_ei_open || !S_ei_close + || !S_ei_interrupt) { + unload_8390_module(); + printk("%s: 8390.o not found/invalid or failed to load.\n", driver); + return -ENOSYS; } -extern __inline__ void unlock_8390_module(void) -{ - struct module **mod = (struct module**)get_module_symbol(0, "NS8390_module"); - - if (mod != NULL && *mod != NULL) - __MOD_DEC_USE_COUNT(*mod); + return 0; } /* @@ -141,8 +148,7 @@ #else /* not a module or kmod support not wanted */ #define load_8390_module(driver) 0 -#define lock_8390_module() do { } while (0) -#define unlock_8390_module() do { } while (0) +#define unload_8390_module() do { } while (0) extern int ethdev_init(struct net_device *dev); extern void NS8390_init(struct net_device *dev, int startp); extern int ei_open(struct net_device *dev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/Config.in linux.ac/drivers/net/Config.in --- linux.vanilla/drivers/net/Config.in Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/Config.in Mon Jun 5 19:39:44 2000 @@ -49,7 +49,7 @@ tristate ' MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC fi if [ "$CONFIG_SGI_IP27" = "y" ]; then - bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH + bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH fi if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then tristate ' National DP83902AV support' CONFIG_STNIC @@ -60,14 +60,14 @@ tristate ' 3c503 "EtherLink II" support' CONFIG_EL2 tristate ' 3c505 "EtherLink Plus" support' CONFIG_ELPLUS if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' 3c507 support (EXPERIMENTAL)' CONFIG_EL16 + tristate ' 3c507 "EtherLink 16" support (EXPERIMENTAL)' CONFIG_EL16 fi tristate ' 3c509/3c529 (MCA)/3c579 "EtherLink III" support' CONFIG_EL3 - tristate ' 3c515 ISA Fast EtherLink' CONFIG_3C515 + tristate ' 3c515 ISA "Fast EtherLink"' CONFIG_3C515 if [ "$CONFIG_MCA" = "y" ]; then - tristate ' 3c523 EtherLinkMC support' CONFIG_ELMC + tristate ' 3c523 "EtherLink/MC" support' CONFIG_ELMC if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' 3c527 EtherLink/MC 32 support (EXPERIMENTAL)' CONFIG_ELMC_II + tristate ' 3c527 "EtherLink/MC 32" support (EXPERIMENTAL)' CONFIG_ELMC_II fi fi tristate ' 3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX @@ -104,7 +104,7 @@ tristate ' EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3 fi tristate ' EtherExpress 16 support' CONFIG_EEXPRESS - tristate ' EtherExpressPro support' CONFIG_EEXPRESS_PRO + tristate ' EtherExpressPro support/EtherExpress 10 (i82595) support' CONFIG_EEXPRESS_PRO if [ "$CONFIG_OBSOLETE" = "y" ]; then tristate ' FMV-181/182/183/184 support' CONFIG_FMV18X fi @@ -121,6 +121,7 @@ if [ "$CONFIG_MCA" = "y" ]; then tristate ' SKnet MCA support' CONFIG_SKMC tristate ' NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA + tristate ' IBM LAN Adapter/A support' CONFIG_IBMLANA fi bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI if [ "$CONFIG_NET_PCI" = "y" ]; then @@ -182,15 +183,16 @@ mainmenu_option next_comment comment 'Ethernet (1000 Mbit)' - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - # tristate 'Packet Engines Hamachi GNIC-II support (EXPERIMENTAL)' CONFIG_HAMACHI - tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN - fi - tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC - if [ "$CONFIG_ACENIC" != "n" ]; then - bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I - fi - tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + # tristate 'Packet Engines Hamachi GNIC-II support (EXPERIMENTAL)' CONFIG_HAMACHI + tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN +fi +tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC +if [ "$CONFIG_ACENIC" != "n" ]; then + bool ' Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I +fi +tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN + endmenu bool 'FDDI driver support' CONFIG_FDDI @@ -223,7 +225,7 @@ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP + dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP fi fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/Makefile linux.ac/drivers/net/Makefile --- linux.vanilla/drivers/net/Makefile Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/Makefile Mon Jun 5 19:39:44 2000 @@ -83,16 +83,8 @@ endif endif -ifeq ($(CONFIG_ISDN),y) - ifeq ($(CONFIG_ISDN_PPP),y) - obj-y += slhc.o ppp_deflate.o - endif -else - ifeq ($(CONFIG_ISDN),m) - ifeq ($(CONFIG_ISDN_PPP),y) - obj-m += slhc.o ppp_deflate.o - endif - endif +ifeq ($(CONFIG_ISDN_PPP),y) + obj-$(CONFIG_ISDN) += slhc.o endif ifeq ($(CONFIG_ARCNET),y) @@ -240,6 +232,7 @@ obj-$(CONFIG_EL16) += 3c507.o obj-$(CONFIG_ELMC) += 3c523.o obj-$(CONFIG_SKMC) += sk_mca.o +obj-$(CONFIG_IBMLANA) += ibmlana.o obj-$(CONFIG_ELMC_II) += 3c527.o obj-$(CONFIG_EL3) += 3c509.o obj-$(CONFIG_3C515) += 3c515.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ac3200.c linux.ac/drivers/net/ac3200.c --- linux.vanilla/drivers/net/ac3200.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/ac3200.c Thu Jun 8 15:05:57 2000 @@ -102,10 +102,10 @@ if (ioaddr > 0x1ff) /* Check a single specified location. */ return ac_probe1(ioaddr, dev); else if (ioaddr > 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; if ( ! EISA_bus) - return ENXIO; + return -ENXIO; for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { if (check_region(ioaddr, AC_IO_EXTENT)) @@ -114,7 +114,7 @@ return 0; } - return ENODEV; + return -ENODEV; } static int __init ac_probe1(int ioaddr, struct net_device *dev) @@ -151,7 +151,7 @@ || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1 || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) { printk(", not found (invalid prefix).\n"); - return ENODEV; + return -ENODEV; } #endif @@ -174,7 +174,7 @@ printk (" nothing! Unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]); @@ -213,7 +213,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EINVAL; + return -EINVAL; } dev->mem_start = (unsigned long)ioremap(dev->mem_start, AC_STOP_PG*0x100); if (dev->mem_start == 0) { @@ -223,7 +223,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } ei_status.reg0 = 1; /* Use as remap flag */ printk("ac3200.c: remapped %dkB card memory to virtual address %#lx\n", @@ -365,6 +365,9 @@ { int this_dev, found = 0; + if (load_8390_module("ac3200.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { struct net_device *dev = &dev_ac32[this_dev]; dev->irq = irq[this_dev]; @@ -376,14 +379,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -405,7 +407,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/aironet4500_card.c linux.ac/drivers/net/aironet4500_card.c --- linux.vanilla/drivers/net/aironet4500_card.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/aironet4500_card.c Fri May 26 14:36:50 2000 @@ -98,6 +98,8 @@ pdev = pci_find_slot(awc_pci_bus, awc_pci_dev); if (!pdev) continue; + if (pci_enable_device(pdev)) + continue; vendor = pdev->vendor; device = pdev->device; pci_irq_line = pdev->irq; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/am79c961a.c linux.ac/drivers/net/am79c961a.c --- linux.vanilla/drivers/net/am79c961a.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/am79c961a.c Sun Jun 4 21:17:02 2000 @@ -466,8 +466,15 @@ dev->trans_start = jiffies; restore_flags (flags); - if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN)) + /* + * If the next packet is owned by the ethernet device, + * then the tx ring is full and we can't add another + * packet. + */ + if (am_readword(dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN) { + printk(KERN_DEBUG"tx ring full, stopping queue\n"); netif_stop_queue(dev); + } dev_kfree_skb(skb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/apne.c linux.ac/drivers/net/apne.c --- linux.vanilla/drivers/net/apne.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/apne.c Mon Jun 5 19:20:11 2000 @@ -178,9 +178,6 @@ 8, 9+GAYLE_ODD, 0xa, 0xb+GAYLE_ODD, 0xc, 0xd+GAYLE_ODD, 0xe, 0xf+GAYLE_ODD }; - if (load_8390_module("apne.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk(KERN_ERR "apne.c: Passed a NULL device.\n"); @@ -271,7 +268,7 @@ stop_page = (wordlength == 2) ? 0x40 : 0x20; } else { printk(" not found.\n"); - return ENXIO; + return -ENXIO; } @@ -572,12 +569,16 @@ int init_module(void) { int err; + + if (load_8390_module("apne.c")) + return -ENOSYS; + if ((err = register_netdev(&apne_dev))) { if (err == -EIO) printk("No PCMCIA NEx000 ethernet card found.\n"); + unload_8390_module(); return (err); } - lock_8390_module(); return (0); } @@ -591,7 +592,7 @@ pcmcia_reset(); - unlock_8390_module(); + unload_8390_module(); apne_owned = 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ariadne2.c linux.ac/drivers/net/ariadne2.c --- linux.vanilla/drivers/net/ariadne2.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/ariadne2.c Mon Jun 5 19:20:11 2000 @@ -113,9 +113,6 @@ }; unsigned long ioaddr = board+ARIADNE2_BASE*2; - if (load_8390_module("ariadne2.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk(KERN_ERR "ariadne2.c: Passed a NULL device.\n"); @@ -405,12 +402,16 @@ int init_module(void) { int err; + + if (load_8390_module("ariadne2.c")) + return -ENOSYS; + if ((err = register_netdev(&ariadne2_dev))) { if (err == -EIO) printk("No AriadNE2 ethernet card found.\n"); + unload_8390_module(); return err; } - lock_8390_module(); return 0; } @@ -419,7 +420,7 @@ free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev); release_mem_region(ZTWO_PADDR(ariadne2_dev.base_addr), NE_IO_EXTENT*2); unregister_netdev(&ariadne2_dev); - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/arlan.c linux.ac/drivers/net/arlan.c --- linux.vanilla/drivers/net/arlan.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/arlan.c Sun Jun 4 21:56:12 2000 @@ -1091,14 +1091,14 @@ { if (lastFoundAt == 0xbe000) printk(KERN_ERR "arlan: No Arlan devices found \n"); - return ENODEV; + return -ENODEV; } else return 0; ARLAN_DEBUG_EXIT("arlan_probe_everywhere"); - return ENODEV; + return -ENODEV; } int __init arlan_find_devices(void) @@ -1975,7 +1975,7 @@ printk("Arlan driver %s\n", arlan_version); if (arlan_probe_everywhere(dev)) - return ENODEV; + return -ENODEV; arlans_found++; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/at1700.c linux.ac/drivers/net/at1700.c --- linux.vanilla/drivers/net/at1700.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/at1700.c Sat Jun 10 21:41:18 2000 @@ -206,7 +206,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return at1700_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; at1700_probe_list[i]; i++) { int ioaddr = at1700_probe_list[i]; @@ -215,7 +215,7 @@ if (at1700_probe1(dev, ioaddr) == 0) return 0; } - return ENODEV; + return -ENODEV; } #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/atari_bionet.c linux.ac/drivers/net/atari_bionet.c --- linux.vanilla/drivers/net/atari_bionet.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/atari_bionet.c Sat Jun 10 21:41:18 2000 @@ -332,7 +332,7 @@ int i; if (!MACH_IS_ATARI || no_more_found) - return ENODEV; + return -ENODEV; printk("Probing for BioNet 100 Adapter...\n"); @@ -350,12 +350,12 @@ || station_addr[2] != 'O' ) { no_more_found = 1; printk( "No BioNet 100 found.\n" ); - return ENODEV; + return -ENODEV; } if (dev == NULL) - return ENODEV; + return -ENODEV; if (bionet_debug > 0 && version_printed++ == 0) printk(version); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/atari_pamsnet.c linux.ac/drivers/net/atari_pamsnet.c --- linux.vanilla/drivers/net/atari_pamsnet.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/atari_pamsnet.c Sat Jun 10 21:41:18 2000 @@ -574,7 +574,7 @@ static int no_more_found = 0; if (no_more_found) - return ENODEV; + return -ENODEV; no_more_found = 1; @@ -619,7 +619,7 @@ printk("No PAM's Net/GK found.\n"); if ((dev == NULL) || (lance_target < 0)) - return ENODEV; + return -ENODEV; if (pamsnet_debug > 0 && version_printed++ == 0) printk(version); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/atp.c linux.ac/drivers/net/atp.c --- linux.vanilla/drivers/net/atp.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/atp.c Sat Jun 10 21:41:18 2000 @@ -162,7 +162,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return atp_probe1(dev, base_addr); else if (base_addr == 1) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (port = ports; *port; port++) { int ioaddr = *port; @@ -173,7 +173,7 @@ return 0; } - return ENODEV; + return -ENODEV; } static int __init atp_probe1(struct net_device *dev, short ioaddr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/bonding.c linux.ac/drivers/net/bonding.c --- linux.vanilla/drivers/net/bonding.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/bonding.c Mon Jun 5 20:00:31 2000 @@ -85,35 +85,49 @@ return 0; } -static int bond_close(struct net_device *master) +static void release_one_slave(struct net_device *master, slave_t *slave) { bonding_t *bond = master->priv; - slave_t *slave; - while ((slave = bond->next) != (slave_t*)bond) { + spin_lock_bh(&master->xmit_lock); + if (bond->current_slave == slave) + bond->current_slave = slave->next; + slave->next->prev = slave->prev; + slave->prev->next = slave->next; + spin_unlock_bh(&master->xmit_lock); - spin_lock_bh(&master->xmit_lock); - slave->next->prev = slave->prev; - slave->prev->next = slave->next; - bond->current_slave = (slave_t*)bond; - spin_unlock_bh(&master->xmit_lock); + netdev_set_master(slave->dev, NULL); - netdev_set_master(slave->dev, NULL); + dev_put(slave->dev); + kfree(slave); + MOD_DEC_USE_COUNT; +} - kfree(slave); - } +static int bond_close(struct net_device *master) +{ + bonding_t *bond = master->priv; + slave_t *slave; + + while ((slave = bond->next) != (slave_t*)bond) + release_one_slave(master, slave); MOD_DEC_USE_COUNT; return 0; } -/* Fake multicast ability. - - NB. It is possible and necessary to make it true one, otherwise - the device is not functional. - */ -static void bond_set_multicast_list(struct net_device *dev) +static void bond_set_multicast_list(struct net_device *master) { + bonding_t *bond = master->priv; + slave_t *slave; + + for (slave = bond->next; slave != (slave_t*)bond; slave = slave->next) { + slave->dev->mc_list = master->mc_list; + slave->dev->mc_count = master->mc_count; + slave->dev->flags = master->flags; + slave->dev->set_multicast_list(slave->dev); + } + + return 0; } static int bond_enslave(struct net_device *master, struct net_device *dev) @@ -161,20 +175,9 @@ if (dev->master != master) return -EINVAL; - netdev_set_master(dev, NULL); - for (slave = bond->next; slave != (slave_t*)bond; slave = slave->next) { if (slave->dev == dev) { - spin_lock_bh(&master->xmit_lock); - if (bond->current_slave == slave) - bond->current_slave = slave->next; - slave->next->prev = slave->prev; - slave->prev->next = slave->next; - spin_unlock_bh(&master->xmit_lock); - - kfree(slave); - dev_put(dev); - MOD_DEC_USE_COUNT; + release_one_slave(master, slave); break; } } @@ -281,7 +284,7 @@ if (slave == (slave_t*)bond) continue; - if (netif_running(slave->dev) && netif_carrier_ok(dev)) { + if (netif_running(slave->dev) && netif_carrier_ok(slave->dev)) { bond->current_slave = slave->next; skb->dev = slave->dev; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/cs89x0.c linux.ac/drivers/net/cs89x0.c --- linux.vanilla/drivers/net/cs89x0.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/cs89x0.c Sat Jun 10 21:41:18 2000 @@ -238,7 +238,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return cs89x0_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; @@ -248,7 +248,7 @@ return 0; } printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n"); - return ENODEV; + return -ENODEV; } extern int inline @@ -366,7 +366,7 @@ if (ioaddr & 1) { ioaddr &= ~1; if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG) - return ENODEV; + return -ENODEV; outw(PP_ChipID, ioaddr + ADD_PORT); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/daynaport.c linux.ac/drivers/net/daynaport.c --- linux.vanilla/drivers/net/daynaport.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/daynaport.c Sun Jun 4 21:57:44 2000 @@ -633,6 +633,7 @@ static int ns8390_open(struct net_device *dev) { + MOD_INC_USE_COUNT; ei_open(dev); /* At least on my card (a Focus Enhancements PDS card) I start */ @@ -644,10 +645,9 @@ if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) { printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return EAGAIN; + MOD_DEC_USE_COUNT; + return -EAGAIN; } - - MOD_INC_USE_COUNT; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/de4x5.c linux.ac/drivers/net/de4x5.c --- linux.vanilla/drivers/net/de4x5.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/de4x5.c Tue May 30 15:28:39 2000 @@ -2229,7 +2229,7 @@ lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ - iobase = pdev->resource[0].start; + iobase = pci_resource_start(pdev, 0); /* Fetch the IRQ to be used */ irq = pdev->irq; @@ -2318,7 +2318,7 @@ lp->chipset = device; /* Get the board I/O address (64 bits on sparc64) */ - iobase = this_dev->resource[0].start; + iobase = pci_resource_start(this_dev, 0); /* Fetch the IRQ to be used */ irq = this_dev->irq; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/de600.c linux.ac/drivers/net/de600.c --- linux.vanilla/drivers/net/de600.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/de600.c Sat Jun 10 21:41:18 2000 @@ -650,7 +650,7 @@ de600_put_command(STOP_RESET); if (de600_read_status(dev) & 0xf0) { printk(": not at I/O %#3x.\n", DATA_PORT); - return ENODEV; + return -ENODEV; } /* @@ -675,13 +675,13 @@ dev->dev_addr[3] |= 0x70; } else { printk(" not identified in the printer port\n"); - return ENODEV; + return -ENODEV; } #if 0 /* Not yet */ if (check_region(DE600_IO, 3)) { printk(", port 0x%x busy\n", DE600_IO); - return EBUSY; + return -EBUSY; } #endif request_region(DE600_IO, 3, "de600"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/de620.c linux.ac/drivers/net/de620.c --- linux.vanilla/drivers/net/de620.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/de620.c Thu Jun 8 15:04:10 2000 @@ -834,13 +834,13 @@ if ((checkbyte != 0xa5) || (read_eeprom(dev) != 0)) { printk(" not identified in the printer port\n"); - return ENODEV; + return -ENODEV; } #if 0 /* Not yet */ if (check_region(dev->base_addr, 3)) { printk(", port 0x%x busy\n", dev->base_addr); - return EBUSY; + return -EBUSY; } #endif request_region(dev->base_addr, 3, "de620"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/defxx.c linux.ac/drivers/net/defxx.c --- linux.vanilla/drivers/net/defxx.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/defxx.c Fri May 26 14:36:50 2000 @@ -500,6 +500,9 @@ printk(version); /* we only display this string ONCE */ } + if (pci_enable_device(pdev)) + continue; + /* Verify that I/O enable bit is set (PCI slot is enabled) */ pci_read_config_word(pdev, PCI_COMMAND, &command); @@ -515,7 +518,7 @@ /* Get I/O base address from PCI Configuration Space */ - port = pdev->resource[1].start; + port = pci_resource_start (pdev, 1); /* Verify port address range is not already being used */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/dgrs.c linux.ac/drivers/net/dgrs.c --- linux.vanilla/drivers/net/dgrs.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/net/dgrs.c Tue Jun 6 17:24:12 2000 @@ -4,7 +4,7 @@ * The RightSwitch is a 4 (EISA) or 6 (PCI) port etherswitch and * a NIC on an internal board. * - * Author: Rick Richardson, rick@dgii.com, rick_richardson@dgii.com + * Author: Rick Richardson, rick@remotepoint.com * Derived from the SVR4.2 (UnixWare) driver for the same card. * * Copyright 1995-1996 Digi International Inc. @@ -73,7 +73,7 @@ * */ -static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $"; +static char *version = "$Id: dgrs.c,v 1.13 2000/06/06 04:07:00 rick Exp $"; #include #include @@ -206,7 +206,7 @@ I596_RFD *rfdp; /* Current RFD list */ I596_RBD *rbdp; /* Current RBD list */ - int intrcnt; /* Count of interrupts */ + volatile int intrcnt; /* Count of interrupts */ /* * SE-4 (EISA) board variables @@ -1184,7 +1184,7 @@ */ if (priv->plxreg) OUTL(dev->base_addr + PLX_LCL2PCI_DOORBELL, 1); - rc = request_irq(dev->irq, &dgrs_intr, 0, "RightSwitch", dev); + rc = request_irq(dev->irq, &dgrs_intr, SA_SHIRQ, "RightSwitch", dev); if (rc) return (rc); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/dmfe.c linux.ac/drivers/net/dmfe.c --- linux.vanilla/drivers/net/dmfe.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/dmfe.c Fri May 26 14:36:50 2000 @@ -359,15 +359,16 @@ if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC) continue; - if ((pci_id != PCI_DM9102_ID) && (pci_id != PCI_DM9132_ID)) + if ((net_dev->device != PCI_DM9102_ID) && (net_dev->device != PCI_DM9132_ID)) continue; - pci_iobase = net_dev->resource[0].start; + pci_iobase = pci_resource_start (net_dev, 0); pci_irqline = net_dev->irq; /* Enable Master/IO access, Disable memory access */ - pci_enable_device (net_dev); /* XXX check return val */ + if (pci_enable_device(net_dev)) + continue; pci_set_master(net_dev); /* Set Latency Timer 80h */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/e2100.c linux.ac/drivers/net/e2100.c --- linux.vanilla/drivers/net/e2100.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/e2100.c Thu Jun 8 15:03:31 2000 @@ -125,7 +125,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return e21_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (port = e21_probe_list; *port; port++) { if (check_region(*port, E21_IO_EXTENT)) @@ -134,7 +134,7 @@ return 0; } - return ENODEV; + return -ENODEV; } int __init e21_probe1(struct net_device *dev, int ioaddr) @@ -147,14 +147,14 @@ if (inb(ioaddr + E21_SAPROM + 0) != 0x00 || inb(ioaddr + E21_SAPROM + 1) != 0x00 || inb(ioaddr + E21_SAPROM + 2) != 0x1d) - return ENODEV; + return -ENODEV; /* Verify by making certain that there is a 8390 at there. */ outb(E8390_NODMA + E8390_STOP, ioaddr); udelay(1); /* we want to delay one I/O cycle - which is 2MHz */ status = inb(ioaddr); if (status != 0x21 && status != 0x23) - return ENODEV; + return -ENODEV; /* Read the station address PROM. */ for (i = 0; i < 6; i++) @@ -163,9 +163,6 @@ inb(ioaddr + E21_MEDIA); /* Point to media selection. */ outb(0, ioaddr + E21_ASIC); /* and disable the secondary interface. */ - if (load_8390_module("e2100.c")) - return -ENOSYS; - if (ei_debug && version_printed++ == 0) printk(version); @@ -194,7 +191,7 @@ } if (i >= 8) { printk(" unable to get IRQ %d.\n", dev->irq); - return EAGAIN; + return -EAGAIN; } } else if (dev->irq == 2) /* Fixup luser bogosity: IRQ2 is really IRQ9 */ dev->irq = 9; @@ -259,7 +256,7 @@ short ioaddr = dev->base_addr; if (request_irq(dev->irq, ei_interrupt, 0, "e2100", dev)) { - return EBUSY; + return -EBUSY; } /* Set the interrupt line and memory base on the hardware. */ @@ -410,6 +407,9 @@ { int this_dev, found = 0; + if (load_8390_module("e2100.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) { struct net_device *dev = &dev_e21[this_dev]; dev->irq = irq[this_dev]; @@ -424,14 +424,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -450,7 +449,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eepro.c linux.ac/drivers/net/eepro.c --- linux.vanilla/drivers/net/eepro.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/eepro.c Sat Jun 10 21:41:18 2000 @@ -23,6 +23,8 @@ This is a compatibility hardware problem. Versions: + 0.12a port of version 0.12a of 2.2.x kernels to 2.3.x + (aris (aris@conectiva.com.br), 05/19/2000) 0.11e some tweaks about multiple cards support (PdP, jul/aug 1999) 0.11d added __initdata, __init stuff; call spin_lock_init in eepro_probe1. Replaced "eepro" by dev->name. Augmented @@ -93,7 +95,7 @@ */ static const char *version = - "eepro.c: v0.11d 08/12/1998 dupuis@lei.ucl.ac.be\n"; + "eepro.c: v0.12a 04/26/2000 aris@conectiva.com.br\n"; #include @@ -174,6 +176,7 @@ #define LAN595 0 #define LAN595TX 1 #define LAN595FX 2 +#define LAN595FX_10ISA 3 /* Information that need to be kept for each board. */ struct eepro_local { @@ -293,7 +296,7 @@ static void set_multicast_list(struct net_device *dev); static void eepro_tx_timeout (struct net_device *dev); -static int read_eeprom(int ioaddr, int location); +static int read_eeprom(int ioaddr, int location, struct net_device *dev); static void hardware_send_packet(struct net_device *dev, void *buf, short length); static int eepro_grab_irq(struct net_device *dev); @@ -327,18 +330,32 @@ buffer (transmit-buffer = 32K - receive-buffer). */ -#define RAM_SIZE 0x8000 -#define RCV_HEADER 8 -#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */ -#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */ -/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */ -#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8) -/* #define XMT_RAM (RAM_SIZE - RCV_RAM) */ /* 8KB for XMT buffer */ -#define XMT_RAM (RAM_SIZE - (rcv_ram)) /* 8KB for XMT buffer */ -/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */ /* 0x6000 */ -#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) -#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */ -#define XMT_HEADER 8 +/* now this section could be used by both boards: the oldies and the ee10: + * ee10 uses tx buffer before of rx buffer and the oldies the inverse. + * (aris) + */ +#define RAM_SIZE 0x8000 + +#define RCV_HEADER 8 +#define RCV_DEFAULT_RAM 0x6000 +#define RCV_RAM rcv_ram + +static unsigned rcv_ram = RCV_DEFAULT_RAM; + +#define XMT_HEADER 8 +#define XMT_RAM (RAM_SIZE - RCV_RAM) + +#define XMT_START ((rcv_start + RCV_RAM) % RAM_SIZE) + +#define RCV_LOWER_LIMIT (rcv_start >> 8) +#define RCV_UPPER_LIMIT (((rcv_start + RCV_RAM) - 2) >> 8) +#define XMT_LOWER_LIMIT (XMT_START >> 8) +#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8) + +#define RCV_START_PRO 0x00 +#define RCV_START_10 XMT_RAM + /* by default the old driver */ +static unsigned rcv_start = RCV_START_PRO; #define RCV_DONE 0x0008 #define RX_OK 0x2000 @@ -384,7 +401,11 @@ #define IO_32_BIT 0x10 #define RCV_BAR 0x04 /* The following are word (16-bit) registers */ #define RCV_STOP 0x06 -#define XMT_BAR 0x0a + +#define XMT_BAR_PRO 0x0a +#define XMT_BAR_10 0x0b +static unsigned xmt_bar = XMT_BAR_PRO; + #define HOST_ADDRESS_REG 0x0c #define IO_PORT 0x0e #define IO_PORT_32_BIT 0x0c @@ -396,8 +417,13 @@ #define INT_NO_REG 0x02 #define RCV_LOWER_LIMIT_REG 0x08 #define RCV_UPPER_LIMIT_REG 0x09 -#define XMT_LOWER_LIMIT_REG 0x0a -#define XMT_UPPER_LIMIT_REG 0x0b + +#define XMT_LOWER_LIMIT_REG_PRO 0x0a +#define XMT_UPPER_LIMIT_REG_PRO 0x0b +#define XMT_LOWER_LIMIT_REG_10 0x0b +#define XMT_UPPER_LIMIT_REG_10 0x0a +static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; +static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; /* Bank 2 registers */ #define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */ @@ -420,12 +446,68 @@ #define I_ADD_REG4 0x08 #define I_ADD_REG5 0x09 -#define EEPROM_REG 0x0a +#define EEPROM_REG_PRO 0x0a +#define EEPROM_REG_10 0x0b +static unsigned eeprom_reg = EEPROM_REG_PRO; + #define EESK 0x01 #define EECS 0x02 #define EEDI 0x04 #define EEDO 0x08 +/* do a full reset */ +#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr) + +/* do a nice reset */ +#define eepro_sel_reset(ioaddr) { \ + outb(SEL_RESET_CMD, ioaddr); \ + SLOW_DOWN; \ + SLOW_DOWN; \ + } + +/* disable all interrupts */ +#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG) + +/* clear all interrupts */ +#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG) + +/* enable tx/rx */ +#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \ + ioaddr + INT_MASK_REG) + +/* enable exec event interrupt */ +#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG) + +/* enable rx */ +#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr) + +/* disable rx */ +#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr) + +/* switch bank */ +#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr) +#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr) +#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr) + +/* enable interrupt line */ +#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\ + ioaddr + REG1) + +/* disable interrupt line */ +#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \ + ioaddr + REG1); + +/* set diagnose flag */ +#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr) + +/* ack for rx/tx int */ +#define eepro_ack_rxtx(ioaddr) outb (RX_INT | TX_INT, ioaddr + STATUS_REG) + +/* ack for rx int */ +#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG) + +/* ack for tx int */ +#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG) /* Check for a network adaptor of this type, and return '0' if one exists. If dev->base_addr == 0, probe all likely locations. @@ -478,7 +560,7 @@ return eepro_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; eepro_portlist[i]; i++) { @@ -490,20 +572,20 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif -void printEEPROMInfo(short ioaddr) +void printEEPROMInfo(short ioaddr, struct net_device *dev) { unsigned short Word; int i,j; for (i=0, j=ee_Checksum; i>ee_IO0)<<4); if (net_debug>4) { - Word=read_eeprom(ioaddr, 1); + Word=read_eeprom(ioaddr, 1, dev); printk(KERN_DEBUG "Word1:\n"); printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask); printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI)); @@ -522,7 +604,7 @@ printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex)); } - Word=read_eeprom(ioaddr, 5); + Word=read_eeprom(ioaddr, 5, dev); printk(KERN_DEBUG "Word5:\n"); printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE)); printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn)); @@ -532,12 +614,12 @@ if (GetBit(Word,ee_PortAUI)) printk("AUI "); printk("port(s) \n"); - Word=read_eeprom(ioaddr, 6); + Word=read_eeprom(ioaddr, 6, dev); printk(KERN_DEBUG "Word6:\n"); printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask); printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID); - Word=read_eeprom(ioaddr, 7); + Word=read_eeprom(ioaddr, 7, dev); printk(KERN_DEBUG "Word7:\n"); printk(KERN_DEBUG " INT to IRQ:\n"); @@ -557,7 +639,8 @@ { unsigned short station_addr[6], id, counter; int i,j, irqMask; - int eepro; + int eepro = 0; + struct eepro_local *lp; const char *ifmap[] = {"AUI", "10Base2", "10BaseT"}; enum iftype { AUI=0, BNC=1, TPE=2 }; @@ -566,9 +649,6 @@ id=inb(ioaddr + ID_REG); - printk(KERN_DEBUG " id: %#x ",id); - printk(" io: %#x ",ioaddr); - if (((id) & ID_REG_MASK) == ID_REG_SIG) { /* We seem to have the 82595 signature, let's @@ -580,19 +660,45 @@ (counter + 0x40)) { /* Yes, the 82595 has been found */ + printk(KERN_DEBUG " id: %#x ",id); + printk(" io: %#x ",ioaddr); + + /* Initialize the device structure */ + dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct eepro_local)); + + lp = (struct eepro_local *)dev->priv; /* Now, get the ethernet hardware address from the EEPROM */ - station_addr[0] = read_eeprom(ioaddr, 2); - station_addr[1] = read_eeprom(ioaddr, 3); - station_addr[2] = read_eeprom(ioaddr, 4); + station_addr[0] = read_eeprom(ioaddr, 2, dev); - /* Check the station address for the manufacturer's code */ - if (net_debug>3) - printEEPROMInfo(ioaddr); - - if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */ + /* FIXME - find another way to know that we've found + * an Etherexpress 10 + */ + if (station_addr[0] == 0x0000 || + station_addr[0] == 0xffff) { + eepro = 3; + lp->eepro = LAN595FX_10ISA; + eeprom_reg = EEPROM_REG_10; + rcv_start = RCV_START_10; + xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; + xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; + + station_addr[0] = read_eeprom(ioaddr, 2, dev); + } + + station_addr[1] = read_eeprom(ioaddr, 3, dev); + station_addr[2] = read_eeprom(ioaddr, 4, dev); + + if (eepro) { + printk("%s: Intel EtherExpress 10 ISA\n at %#x,", + dev->name, ioaddr); + } else if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) { + /* int to IRQ Mask */ eepro = 2; printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", dev->name, ioaddr); @@ -615,13 +721,21 @@ dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); } + + dev->mem_start = (RCV_LOWER_LIMIT << 8); if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */ (dev->mem_end & 0x3f) > 29) /* and less than 29K */ - dev->mem_end = RCV_RAM; /* or it will be set to 24K */ - else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */ + dev->mem_end = (RCV_UPPER_LIMIT << 8); + else { + dev->mem_end = (dev->mem_end * 1024) + + (RCV_LOWER_LIMIT << 8); + rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8); + } - /* From now on, dev->mem_end contains the actual size of rx buffer */ + /* From now on, dev->mem_end - dev->mem_start contains + * the actual size of rx buffer + */ if (net_debug > 3) printk(", %dK RCV buffer", (int)(dev->mem_end)/1024); @@ -629,7 +743,7 @@ /* ............... */ - if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE)) + if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE)) dev->if_port = BNC; else dev->if_port = TPE; @@ -637,8 +751,8 @@ if ((dev->irq < 2) && (eepro!=0)) { - i = read_eeprom(ioaddr, 1); - irqMask = read_eeprom(ioaddr, 7); + i = read_eeprom(ioaddr, 1, dev); + irqMask = read_eeprom(ioaddr, 7, dev); i &= 0x07; /* Mask off INT number */ for (j=0; ((j<16) && (i>=0)); j++) { @@ -650,15 +764,13 @@ i--; /* count bits set in irqMask */ } } - if (dev -> irq<2) { + if (dev->irq < 2) { printk(" Duh! illegal interrupt vector stored in EEPROM.\n"); - return ENODEV; + return -ENODEV; } else - if (dev->irq==2) dev->irq = 9; - - else if (dev->irq == 2) - dev->irq = 9; + if (dev->irq==2) + dev->irq = 9; } if (dev->irq > 2) { @@ -671,7 +783,7 @@ net_debug = dev->mem_start & 7; /* still useful or not */ if (net_debug > 3) { - i = read_eeprom(ioaddr, 5); + i = read_eeprom(ioaddr, 5, dev); if (i & 0x2000) /* bit 13 of EEPROM word 5 */ printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n", dev->name); @@ -683,12 +795,6 @@ /* Grab the region so we can find another board if autoIRQ fails. */ request_region(ioaddr, EEPRO_IO_EXTENT, dev->name); - /* Initialize the device structure */ - dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct eepro_local)); - ((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED; dev->open = eepro_open; @@ -704,15 +810,20 @@ ether_setup(dev); - outb(RESET_CMD, ioaddr); /* RESET the 82595 */ + /* Check the station address for the manufacturer's code */ + if (net_debug>3) + printEEPROMInfo(ioaddr, dev); + + /* RESET the 82595 */ + eepro_reset(ioaddr); return 0; } - else return ENODEV; + else return -ENODEV; } else if (net_debug > 3) printk ("EtherExpress Pro probed failed!\n"); - return ENODEV; + return -ENODEV; } /* Open/initialize the board. This is called (in the current kernel) @@ -730,55 +841,54 @@ int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 }; int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr; - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ + eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ /* Enable the interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); + eepro_en_intline(ioaddr); + + /* be CAREFUL, BANK 0 now */ + eepro_sw2bank0(ioaddr); - outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ - /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + eepro_clear_int(ioaddr); /* Let EXEC event to interrupt */ - outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); + eepro_en_intexec(ioaddr); do { - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ + eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ temp_reg = inb(ioaddr + INT_NO_REG); outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ + eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) { /* Twinkle the interrupt, and check if it's seen */ autoirq_setup(0); - outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ + eepro_diag(ioaddr); /* RESET the 82595 */ if (*irqp == autoirq_report(2)) /* It's a good IRQ line */ break; /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + eepro_clear_int(ioaddr); } } while (*++irqp); - outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ + eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */ /* Disable the physical interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); + eepro_dis_intline(ioaddr); - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ + eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + eepro_dis_int(ioaddr); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + eepro_clear_int(ioaddr); return dev->irq; } @@ -787,13 +897,18 @@ { unsigned short temp_reg, old8, old9; int irqMask; - int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end; + int i, ioaddr = dev->base_addr; struct eepro_local *lp = (struct eepro_local *)dev->priv; if (net_debug > 3) printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name); - if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */ + irqMask = read_eeprom(ioaddr,7,dev); + + if (lp->eepro == LAN595FX_10ISA) { + if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n"); + } + else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */ { lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); @@ -831,8 +946,8 @@ /* Initialize the 82595. */ - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ - temp_reg = inb(ioaddr + EEPROM_REG); + eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ + temp_reg = inb(ioaddr + eeprom_reg); lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ @@ -840,7 +955,7 @@ printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping); if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ - outb(temp_reg & 0xef, ioaddr + EEPROM_REG); + outb(temp_reg & 0xef, ioaddr + eeprom_reg); for (i=0; i < 6; i++) outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); @@ -855,17 +970,17 @@ outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */ /* Set the receiving mode */ - outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ + eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ /* Set the interrupt vector */ temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == 2) + if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA) outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == 2) + if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA) outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); @@ -876,20 +991,20 @@ /* Initialize the RCV and XMT upper and lower limits */ outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); - outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); - outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); + outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg); + outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg); /* Enable the interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); + eepro_en_intline(ioaddr); - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ + /* Switch back to Bank 0 */ + eepro_sw2bank0(ioaddr); /* Let RX and TX events to interrupt */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + eepro_en_int(ioaddr); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + eepro_clear_int(ioaddr); /* Initialize RCV */ outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); @@ -897,7 +1012,7 @@ outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); /* Initialize XMT */ - outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); + outw(XMT_LOWER_LIMIT << 8, ioaddr + xmt_bar); /* Check for the i82595TX and i82595FX */ old8 = inb(ioaddr + 8); @@ -927,12 +1042,12 @@ if (dev->if_port != TPE) { /* Hopefully, this will fix the problem of using Pentiums and pro/10 w/ BNC. */ - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ + eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ temp_reg = inb(ioaddr + REG13); /* disable the full duplex mode since it is not applicable with the 10Base2 cable. */ outb(temp_reg & ~(FDX | A_N_ENABLE), REG13); - outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ + eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */ } } else if (net_debug > 3) { @@ -941,13 +1056,9 @@ } } - outb(SEL_RESET_CMD, ioaddr); + eepro_sel_reset(ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - SLOW_DOWN; - SLOW_DOWN; - - lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */ + lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; lp->tx_last = 0; netif_start_queue(dev); @@ -955,7 +1066,8 @@ if (net_debug > 3) printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name); - outb(RCV_ENABLE_CMD, ioaddr); + /* enabling rx */ + eepro_en_rx(ioaddr); MOD_INC_USE_COUNT; return 0; @@ -965,7 +1077,6 @@ { struct eepro_local *lp = (struct eepro_local *) dev->priv; int ioaddr = dev->base_addr; - int rcv_ram = dev->mem_end; /* if (net_debug > 1) */ printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name, @@ -977,19 +1088,20 @@ lp->stats.tx_errors++; /* Try to restart the adaptor. */ - outb (SEL_RESET_CMD, ioaddr); - /* We are supposed to wait for 2 us after a SEL_RESET */ - SLOW_DOWN; - SLOW_DOWN; - + eepro_sel_reset(ioaddr); + /* Do I also need to flush the transmit buffers here? YES? */ - lp->tx_start = lp->tx_end = rcv_ram; + lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT; lp->tx_last = 0; dev->trans_start = jiffies; netif_wake_queue (dev); - outb (RCV_ENABLE_CMD, ioaddr); + /* enabling interrupts */ + eepro_en_int(ioaddr); + + /* enabling rx */ + eepro_en_rx(ioaddr); } @@ -1012,6 +1124,7 @@ lp->stats.tx_bytes+=skb->len; hardware_send_packet(dev, buf, length); + dev->trans_start = jiffies; } @@ -1053,31 +1166,34 @@ ioaddr = dev->base_addr; - do { - status = inb(ioaddr + STATUS_REG); - + while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--)) + { + switch (status & (RX_INT | TX_INT)) { + case (RX_INT | TX_INT): + eepro_ack_rxtx(ioaddr); + break; + case RX_INT: + eepro_ack_rx(ioaddr); + break; + case TX_INT: + eepro_ack_tx(ioaddr); + break; + } if (status & RX_INT) { if (net_debug > 4) - printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name); + printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name); - /* Acknowledge the RX_INT */ - outb(RX_INT, ioaddr + STATUS_REG); /* Get the received packets */ eepro_rx(dev); } - - else if (status & TX_INT) { + if (status & TX_INT) { if (net_debug > 4) - printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name); - - /* Acknowledge the TX_INT */ - outb(TX_INT, ioaddr + STATUS_REG); + printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name); /* Process the status of transmitted packets */ eepro_transmit_interrupt(dev); } - - } while ((boguscount-- > 0) && (status & 0x06)); + } if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name); @@ -1090,32 +1206,31 @@ { struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; - int rcv_ram = dev->mem_end; short temp_reg; netif_stop_queue(dev); - outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ + eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg & 0x7f, ioaddr + REG1); - outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ + eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ /* Flush the Tx and disable Rx. */ outb(STOP_RCV_CMD, ioaddr); - lp->tx_start = lp->tx_end = rcv_ram ; + lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8); lp->tx_last = 0; /* Mask all the interrupts. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + eepro_dis_int(ioaddr); /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + eepro_clear_int(ioaddr); /* Reset the 82595 */ - outb(RESET_CMD, ioaddr); + eepro_reset(ioaddr); /* release the interrupt */ free_irq(dev->irq, dev); @@ -1126,10 +1241,6 @@ /* Update the statistics here. What statistics? */ - /* We are supposed to wait for 200 us after a RESET */ - SLOW_DOWN; - SLOW_DOWN; /* May not be enough? */ - MOD_DEC_USE_COUNT; return 0; } @@ -1164,23 +1275,23 @@ */ dev->flags|=IFF_PROMISC; - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ + eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode | PRMSC_Mode, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ + eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ printk("%s: promiscuous mode enabled.\n", dev->name); } else if (dev->mc_count==0 ) { - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ + eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */ mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ + eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ } else @@ -1191,14 +1302,14 @@ /* Disable RX and TX interrupts. Necessary to avoid corruption of the HOST_ADDRESS_REG by interrupt service routines. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + eepro_dis_int(ioaddr); - outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ + eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode | Multi_IA, ioaddr + REG2); mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ + eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG); outw(MC_SETUP, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); @@ -1218,7 +1329,7 @@ outw(eaddrs[0], ioaddr + IO_PORT); outw(eaddrs[1], ioaddr + IO_PORT); outw(eaddrs[2], ioaddr + IO_PORT); - outw(lp->tx_end, ioaddr + XMT_BAR); + outw(lp->tx_end, ioaddr + xmt_bar); outb(MC_SETUP, ioaddr); /* Update the transmit queue */ @@ -1262,10 +1373,9 @@ } while (++boguscount < 100); /* Re-enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); - + eepro_en_int(ioaddr); } - outb(RCV_ENABLE_CMD, ioaddr); + eepro_en_rx(ioaddr); } /* The horrible routine to read a word from the serial EEPROM. */ @@ -1276,15 +1386,25 @@ #define EE_READ_CMD (6 << 6) int -read_eeprom(int ioaddr, int location) +read_eeprom(int ioaddr, int location, struct net_device *dev) { int i; unsigned short retval = 0; - short ee_addr = ioaddr + EEPROM_REG; + short ee_addr = ioaddr + eeprom_reg; + struct eepro_local *lp = (struct eepro_local *)dev->priv; int read_cmd = location | EE_READ_CMD; short ctrl_val = EECS ; + + /* XXXX - this is not the final version. We must test this on other + * boards other than eepro10. I think that it won't let other + * boards to fail. (aris) + */ + if (lp->eepro == LAN595FX_10ISA) { + eepro_sw2bank1(ioaddr); + outb(0x00, ioaddr + STATUS_REG); + } - outb(BANK2_SELECT, ioaddr); + eepro_sw2bank2(ioaddr); outb(ctrl_val, ee_addr); /* Shift the read command bits out. */ @@ -1311,7 +1431,7 @@ eeprom_delay(); outb(ctrl_val, ee_addr); eeprom_delay(); - outb(BANK0_SELECT, ioaddr); + eepro_sw2bank0(ioaddr); return retval; } @@ -1320,7 +1440,6 @@ { struct eepro_local *lp = (struct eepro_local *)dev->priv; short ioaddr = dev->base_addr; - int rcv_ram = dev->mem_end; unsigned status, tx_available, last, end, boguscount = 100; if (net_debug > 5) @@ -1331,7 +1450,7 @@ /* Disable RX and TX interrupts. Necessary to avoid corruption of the HOST_ADDRESS_REG by interrupt service routines. */ - outb(ALL_MASK, ioaddr + INT_MASK_REG); + eepro_dis_int(ioaddr); /* determine how much of the transmit buffer space is available */ if (lp->tx_end > lp->tx_start) @@ -1346,26 +1465,24 @@ eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */ /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + eepro_en_int(ioaddr); continue; } last = lp->tx_end; end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */ - - if ((RAM_SIZE - last) <= XMT_HEADER) { + if (end >= (XMT_UPPER_LIMIT << 8)) { /* the transmit buffer is wrapped around */ + if (((XMT_UPPER_LIMIT << 8) - last) <= XMT_HEADER) { /* Arrrr!!!, must keep the xmt header together, several days were lost to chase this one down. */ - last = rcv_ram; + last = (XMT_LOWER_LIMIT << 8); end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; } - else end = rcv_ram + (end - RAM_SIZE); + else end = (XMT_LOWER_LIMIT << 8) + (end - XMT_RAM); } - outw(last, ioaddr + HOST_ADDRESS_REG); outw(XMT_CMD, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); @@ -1385,7 +1502,7 @@ status = inw(ioaddr + IO_PORT); if (lp->tx_start == lp->tx_end) { - outw(last, ioaddr + XMT_BAR); + outw(last, ioaddr + xmt_bar); outb(XMT_CMD, ioaddr); lp->tx_start = last; /* I don't like to change tx_start here */ } @@ -1411,15 +1528,22 @@ if (netif_queue_stopped(dev)) netif_wake_queue(dev); + + /* now we are serializing tx. queue won't come back until + * the tx interrupt + */ + if (lp->eepro == LAN595FX_10ISA) + netif_stop_queue(dev); /* Enable RX and TX interrupts */ - outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); + eepro_en_int(ioaddr); if (net_debug > 5) printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); return; } - + eepro_en_int(ioaddr); + netif_stop_queue(dev); if (net_debug > 5) printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); @@ -1429,13 +1553,16 @@ eepro_rx(struct net_device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr, rcv_ram = dev->mem_end; + short ioaddr = dev->base_addr; short boguscount = 20; - short rcv_car = lp->rx_start; + unsigned rcv_car = lp->rx_start; unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size; if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name); + + /* clear all interrupts */ + eepro_clear_int(ioaddr); /* Set the read pointer to the start of the RCV */ outw(rcv_car, ioaddr + HOST_ADDRESS_REG); @@ -1515,6 +1642,9 @@ if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name); + + /* enable tx/rx interrupts */ + eepro_en_int(ioaddr); } static void @@ -1523,7 +1653,7 @@ struct eepro_local *lp = (struct eepro_local *)dev->priv; short ioaddr = dev->base_addr; short boguscount = 20; - short xmt_status; + unsigned xmt_status; /* if (dev->tbusy == 0) { @@ -1533,31 +1663,67 @@ dev->name); } */ + while (lp->tx_start != lp->tx_end && boguscount) { - while (lp->tx_start != lp->tx_end) { - outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); xmt_status = inw(ioaddr+IO_PORT); - if ((xmt_status & TX_DONE_BIT) == 0) break; + if ((xmt_status & TX_DONE_BIT) == 0) { + udelay(40); + boguscount--; + continue; + } xmt_status = inw(ioaddr+IO_PORT); lp->tx_start = inw(ioaddr+IO_PORT); + if (lp->eepro == LAN595FX_10ISA) { + lp->tx_start = (XMT_LOWER_LIMIT << 8); + lp->tx_end = lp->tx_start; + + /* yeah, black magic :( */ + eepro_sw2bank0(ioaddr); + eepro_en_int(ioaddr); + + /* disabling rx */ + eepro_dis_rx(ioaddr); + + /* enabling rx */ + eepro_en_rx(ioaddr); + } + netif_wake_queue (dev); if (xmt_status & 0x2000) lp->stats.tx_packets++; else { lp->stats.tx_errors++; - if (xmt_status & 0x0400) + if (xmt_status & 0x0400) { lp->stats.tx_carrier_errors++; - printk("%s: XMT status = %#x\n", - dev->name, xmt_status); - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); + printk(KERN_DEBUG "%s: carrier error\n", + dev->name); + printk(KERN_DEBUG "%s: XMT status = %#x\n", + dev->name, xmt_status); + } + else { + printk(KERN_DEBUG "%s: XMT status = %#x\n", + dev->name, xmt_status); + printk(KERN_DEBUG "%s: XMT status = %#x\n", + dev->name, xmt_status); + } + if (lp->eepro == LAN595FX_10ISA) { + /* Try to restart the adaptor. */ + /* We are supposed to wait for 2 us after a SEL_RESET */ + eepro_sel_reset(ioaddr); + + /* first enable interrupts */ + eepro_sw2bank0(ioaddr); + outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + STATUS_REG); + + /* enabling rx */ + eepro_en_rx(ioaddr); + } } - if (xmt_status & 0x000f) { lp->stats.collisions += (xmt_status & 0x000f); } @@ -1566,25 +1732,19 @@ lp->stats.tx_heartbeat_errors++; } - if (--boguscount == 0) - break; + boguscount--; } } #define MAX_EEPRO 8 static struct net_device dev_eepro[MAX_EEPRO]; -static int io[MAX_EEPRO] = { -#ifdef PnPWakeup - 0x210, /*: default for PnP enabled FX chips */ -#else - 0x200, /* Why? */ -#endif - [1 ... MAX_EEPRO - 1] = -1 }; +static int io[MAX_EEPRO]; static int irq[MAX_EEPRO] = { [0 ... MAX_EEPRO-1] = 0 }; static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */ - [0 ... MAX_EEPRO-1] = RCV_RAM/1024 + [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024 }; +static int autodetect; static int n_eepro = 0; /* For linux 2.1.xx */ @@ -1594,19 +1754,30 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i"); MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i"); +MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i"); #ifdef MODULE int init_module(void) { - if (io[0] == 0) - printk("eepro_init_module: You should not use auto-probing with insmod!\n"); + int i; + if (io[0] == 0 && autodetect == 0) { + printk("eepro_init_module: Probe is very dangerous in ISA boards!\n"); + printk("eepro_init_module: Please add \"autodetect=1\" to force probe\n"); + return 1; + } + else if (autodetect) { + /* if autodetect is set then we must force detection */ + io[0] = 0; + + printk("eepro_init_module: Auto-detecting boards (May God protect us...)\n"); + } - while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) { + for (i = 0; i < MAX_EEPRO; i++) { struct net_device *d = &dev_eepro[n_eepro]; d->mem_end = mem[n_eepro]; - d->base_addr = io[n_eepro]; + d->base_addr = io[0]; d->irq = irq[n_eepro]; d->init = eepro_probe; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eepro100.c linux.ac/drivers/net/eepro100.c --- linux.vanilla/drivers/net/eepro100.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/eepro100.c Wed May 31 11:18:46 2000 @@ -4,27 +4,17 @@ May not compile for kernels 2.3.43-47. Written 1996-1999 by Donald Becker. + The driver also contains updates by different kernel developers + (see incomplete list below). + Current maintainer is Andrey V. Savochkin . + Please use this email address and linux-kernel mailing list for bug reports. + 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 Pro100 (Speedo3) design. It should work with all i82557/558/559 boards. - The author may be reached as becker@CESDIS.usra.edu, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 - For updates see - http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html - 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 - - The driver also contains updates by different kernel developers - (see incomplete list below). - This driver clone is maintained by Andrey V. Savochkin . - Please use this email address and linux-kernel mailing list for bug reports. - Version history: 1998 Apr - 2000 Feb Andrey V. Savochkin Serious fixes for multicast filter list setting, TX timeout routine; @@ -33,12 +23,11 @@ Convert to new PCI driver interface 2000 Mar 24 Dragan Stancevic Disabled FC and ER, to avoid lockups when when we get FCP interrupts. - Dragan Stancevic March 24th, 2000. */ static const char *version = "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" -"eepro100.c: $Revision: 1.29 $ 2000/03/30 Modified by Andrey V. Savochkin and others\n"; +"eepro100.c: $Revision: 1.33 $ 2000/05/24 Modified by Andrey V. Savochkin and others\n"; /* A few user-configurable values that apply to all boards. First set is undocumented and spelled per Intel recommendations. */ @@ -218,9 +207,13 @@ } #endif -/* The total I/O port extent of the board. - The registers beyond 0x18 only exist on the i82558. */ -#define SPEEDO3_TOTAL_SIZE 0x20 +#ifndef PCI_DEVICE_ID_INTEL_ID1029 +#define PCI_DEVICE_ID_INTEL_ID1029 0x1029 +#endif +#ifndef PCI_DEVICE_ID_INTEL_ID1030 +#define PCI_DEVICE_ID_INTEL_ID1030 0x1030 +#endif + int speedo_debug = 1; @@ -338,21 +331,22 @@ */ -static int speedo_found1(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt, int acpi_idle_state); - -#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 +static int speedo_found1(struct pci_dev *pdev, long ioaddr, int fnd_cnt, int acpi_idle_state); 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, }; +static inline unsigned int io_inw(unsigned long port) +{ + return inw(port); +} +static inline void io_outw(unsigned int val, unsigned long port) +{ + outw(val, port); +} + #ifndef USE_IO /* Currently alpha headers define in/out macros. Undefine them. 2000/03/30 SAW */ @@ -377,6 +371,10 @@ int wait = 1000; do ; while(inb(cmd_ioaddr) && --wait >= 0); +#ifndef final_version + if (wait < 0) + printk(KERN_ALERT "eepro100: wait_for_cmd_done timeout!\n"); +#endif } /* Offsets to the various registers. @@ -412,15 +410,15 @@ #endif 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, + 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 { @@ -656,7 +654,7 @@ pci_set_master(pdev); - if (speedo_found1(pdev, ioaddr, irq, 0, cards_found, acpi_idle_state) == 0) + if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0) cards_found++; else goto err_out_iounmap; @@ -676,7 +674,7 @@ } static int speedo_found1(struct pci_dev *pdev, - long ioaddr, int irq, int chip_idx, int card_idx, int acpi_idle_state) + long ioaddr, int card_idx, int acpi_idle_state) { struct net_device *dev; struct speedo_private *sp; @@ -712,11 +710,15 @@ The size test is for 6 bit vs. 8 bit address serial EEPROMs. */ { - u16 sum = 0; - int j; + unsigned long iobase; int read_cmd, ee_size; + u16 sum; + int j; - if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000) + /* Use IO only to avoid postponed writes and satisfy EEPROM timing + requirements. */ + iobase = pci_resource_start(pdev, 1); + if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000) == 0xffe0000) { ee_size = 0x100; read_cmd = EE_READ_CMD << 24; @@ -725,8 +727,8 @@ 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); + for (j = 0, i = 0, sum = 0; i < ee_size; i++) { + u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27); eeprom[i] = value; sum += value; if (i < 3) { @@ -739,7 +741,8 @@ "check settings before activating this device!\n", dev->name, sum); /* Don't unregister_netdev(dev); as the EEPro may actually be - usable, especially if the MAC address is set later. */ + usable, especially if the MAC address is set later. + On the other hand, it may be unusable if MDI data is corrupted. */ } /* Reset the chip: stop Tx and Rx processes and clear counters. @@ -760,7 +763,7 @@ #ifdef USE_IO printk("I/O at %#3lx, ", ioaddr); #endif - printk("IRQ %d.\n", irq); + printk("IRQ %d.\n", pdev->irq); #if 1 || defined(kernel_bloat) /* OK, this is pure kernel bloat. I don't like it when other drivers @@ -839,7 +842,7 @@ pdev->driver_data = dev; dev->base_addr = ioaddr; - dev->irq = irq; + dev->irq = pdev->irq; sp = dev->priv; sp->pdev = pdev; @@ -887,30 +890,32 @@ #define EE_WRITE_1 0x4806 #define EE_OFFSET SCBeeprom -/* Delay between EEPROM clock transitions. - The code works with no delay on 33Mhz PCI. */ -#define eeprom_delay() inw(ee_addr) - +/* The fixes for the code were kindly provided by Dragan Stancevic + to strictly follow Intel specifications of EEPROM + access timing. + The publicly available sheet 64486302 (sec. 3.1) specifies 1us access + interval for serial EEPROM. However, it looks like that there is an + additional requirement dictating larger udelay's in the code below. + 2000/05/24 SAW */ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len) { unsigned retval = 0; long ee_addr = ioaddr + SCBeeprom; - outw(EE_ENB | EE_SHIFT_CLK, ee_addr); + io_outw(EE_ENB, ee_addr); udelay(2); + io_outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2); /* 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); + io_outw(dataval, ee_addr); udelay(2); + io_outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2); + retval = (retval << 1) | ((io_inw(ee_addr) & EE_DATA_READ) ? 1 : 0); } while (--cmd_len >= 0); - outw(EE_ENB, ee_addr); + io_outw(EE_ENB, ee_addr); udelay(2); /* Terminate the EEPROM access. */ - outw(EE_ENB & ~EE_CS, ee_addr); + io_outw(EE_ENB & ~EE_CS, ee_addr); udelay(4); return retval; } @@ -1104,8 +1109,11 @@ int partner = mdio_read(ioaddr, phy_num, 5); if (partner != sp->partner) { int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0; - if (speedo_debug > 2) + if (speedo_debug > 2) { printk(KERN_DEBUG "%s: Link status change.\n", dev->name); + printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n", + dev->name, sp->partner, partner, sp->advertising); + } sp->partner = partner; if (flow_ctrl != sp->flow_ctrl) { sp->flow_ctrl = flow_ctrl; @@ -1137,6 +1145,9 @@ /* We must continue to monitor the media. */ sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */ add_timer(&sp->timer); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43) + timer_exit(&sp->timer); +#endif /* LINUX_VERSION_CODE */ } static void speedo_show_state(struct net_device *dev) @@ -1169,12 +1180,14 @@ i, (sp->rx_ringp[i] != NULL) ? (unsigned)sp->rx_ringp[i]->status : 0); +#if 0 for (i = 0; i < 16; i++) { /* FIXME: what does it mean? --SAW */ if (i == 6) i = 21; printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n", dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i)); } +#endif } @@ -1247,6 +1260,29 @@ netif_wake_queue(dev); } +static void reset_mii(struct net_device *dev) +{ + struct speedo_private *sp = (struct speedo_private *)dev->priv; + long ioaddr = dev->base_addr; + /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */ + if ((sp->phy[0] & 0x8000) == 0) { + int phy_addr = sp->phy[0] & 0x1f; + int advertising = mdio_read(ioaddr, phy_addr, 4); + int mii_bmcr = mdio_read(ioaddr, phy_addr, 0); + mdio_write(ioaddr, phy_addr, 0, 0x0400); + mdio_write(ioaddr, phy_addr, 1, 0x0000); + mdio_write(ioaddr, phy_addr, 4, 0x0000); + mdio_write(ioaddr, phy_addr, 0, 0x8000); +#ifdef honor_default_port + mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]); +#else + mdio_read(ioaddr, phy_addr, 0); + mdio_write(ioaddr, phy_addr, 0, mii_bmcr); + mdio_write(ioaddr, phy_addr, 4, advertising); +#endif + } +} + static void speedo_tx_timeout(struct net_device *dev) { struct speedo_private *sp = (struct speedo_private *)dev->priv; @@ -1273,6 +1309,7 @@ outl(cpu_to_le32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE])), ioaddr + SCBPointer); outw(CUStart, ioaddr + SCBCmd); + reset_mii(dev); } else { #else { @@ -1283,11 +1320,7 @@ del_timer(&sp->timer); end_bh_atomic(); #else /* LINUX_VERSION_CODE */ -#ifdef CONFIG_SMP del_timer_sync(&sp->timer); -#else /* SMP */ - del_timer(&sp->timer); -#endif /* SMP */ #endif /* LINUX_VERSION_CODE */ /* Reset the Tx and Rx units. */ outl(PortReset, ioaddr + SCBPort); @@ -1310,26 +1343,12 @@ dev->trans_start = jiffies; spin_unlock_irqrestore(&sp->lock, flags); set_rx_mode(dev); /* it takes the spinlock itself --SAW */ + /* Reset MII transceiver. Do it before starting the timer to serialize + mdio_xxx operations. Yes, it's a paranoya :-) 2000/05/09 SAW */ + reset_mii(dev); sp->timer.expires = RUN_AT(2*HZ); add_timer(&sp->timer); } - /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */ - if ((sp->phy[0] & 0x8000) == 0) { - int phy_addr = sp->phy[0] & 0x1f; - int advertising = mdio_read(ioaddr, phy_addr, 4); - int mii_bmcr = mdio_read(ioaddr, phy_addr, 0); - mdio_write(ioaddr, phy_addr, 0, 0x0400); - mdio_write(ioaddr, phy_addr, 1, 0x0000); - mdio_write(ioaddr, phy_addr, 4, 0x0000); - mdio_write(ioaddr, phy_addr, 0, 0x8000); -#ifdef honor_default_port - mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]); -#else - mdio_read(ioaddr, phy_addr, 0); - mdio_write(ioaddr, phy_addr, 0, mii_bmcr); - mdio_write(ioaddr, phy_addr, 4, advertising); -#endif - } return; } @@ -1384,8 +1403,7 @@ sp->tx_ring[entry].link = cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); sp->tx_ring[entry].tx_desc_addr = - cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE) + - TX_DESCR_BUF_OFFSET); + cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET); /* 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 = @@ -1913,7 +1931,7 @@ if (netif_running(dev)) { unsigned long flags; /* Take a spinlock to make wait_for_cmd_done and sending the - * command atomic. --SAW */ + command atomic. --SAW */ spin_lock_irqsave(&sp->lock, flags); wait_for_cmd_done(ioaddr + SCBCmd); outb(CUDumpStats, ioaddr + SCBCmd); @@ -1935,17 +1953,35 @@ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = phy; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - /* FIXME: these operations probably need to be serialized with MDIO - access from the timer routine and timeout handler. 2000/03/08 SAW */ + /* FIXME: these operations need to be serialized with MDIO + access from the timeout handler. + They are currently serialized only with MDIO access from the + timer routine. 2000/05/09 SAW */ saved_acpi = pci_set_power_state(sp->pdev, 0); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) + start_bh_atomic(); + data[3] = mdio_read(ioaddr, data[0], data[1]); + end_bh_atomic(); +#else /* LINUX_VERSION_CODE */ + del_timer_sync(&sp->timer); data[3] = mdio_read(ioaddr, data[0], data[1]); + add_timer(&sp->timer); /* may be set to the past --SAW */ +#endif /* LINUX_VERSION_CODE */ pci_set_power_state(sp->pdev, saved_acpi); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; saved_acpi = pci_set_power_state(sp->pdev, 0); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) + start_bh_atomic(); + mdio_write(ioaddr, data[0], data[1], data[2]); + end_bh_atomic(); +#else /* LINUX_VERSION_CODE */ + del_timer_sync(&sp->timer); mdio_write(ioaddr, data[0], data[1], data[2]); + add_timer(&sp->timer); /* may be set to the past --SAW */ +#endif /* LINUX_VERSION_CODE */ pci_set_power_state(sp->pdev, saved_acpi); return 0; default: @@ -2205,6 +2241,10 @@ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1029, + PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eexpress.c linux.ac/drivers/net/eexpress.c --- linux.vanilla/drivers/net/eexpress.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/eexpress.c Sat Jun 10 21:41:18 2000 @@ -396,7 +396,7 @@ if (ioaddr&0xfe00) return eexp_hw_probe(dev,ioaddr); else if (ioaddr) - return ENXIO; + return -ENXIO; for (port=&ports[0] ; *port ; port++ ) { @@ -1081,7 +1081,7 @@ dev->priv = lp = kmalloc(sizeof(struct net_local), GFP_KERNEL); if (!dev->priv) - return ENOMEM; + return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_local)); @@ -1127,7 +1127,7 @@ default: printk(") bad memory size (%dk).\n", memory_size); kfree(dev->priv); - return ENODEV; + return -ENODEV; break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/epic100.c linux.ac/drivers/net/epic100.c --- linux.vanilla/drivers/net/epic100.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/epic100.c Sat Jun 10 23:12:32 2000 @@ -384,6 +384,8 @@ duplex = full_duplex[card_idx]; } + pdev->driver_data = dev; + dev->base_addr = ioaddr; dev->irq = pdev->irq; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", @@ -1054,7 +1056,7 @@ printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); /* If we own the next entry, it's a new packet. Send it up. */ - while ( ! le32_to_cpu(ep->rx_ring[entry].rxstatus) & DescOwn) { + while (!(le32_to_cpu(ep->rx_ring[entry].rxstatus) & DescOwn)) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); if (debug > 4) @@ -1295,9 +1297,6 @@ { struct net_device *dev = pdev->driver_data; - if (!dev) - BUG(); - unregister_netdev(dev); #ifndef USE_IO_OPS iounmap ((void*) dev->base_addr); @@ -1315,9 +1314,6 @@ struct net_device *dev = pdev->driver_data; long ioaddr = dev->base_addr; - if (!dev) - BUG(); - epic_pause(dev); /* Put the chip into low-power mode. */ outl(0x0008, ioaddr + GENCTL); @@ -1327,9 +1323,6 @@ static void epic_resume (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; - - if (!dev) - BUG(); epic_restart (dev); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/es3210.c linux.ac/drivers/net/es3210.c --- linux.vanilla/drivers/net/es3210.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/es3210.c Mon Jun 5 19:20:11 2000 @@ -181,9 +181,6 @@ return ENODEV; } - if (load_8390_module("es3210.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk("es3210.c: Passed a NULL device.\n"); @@ -404,6 +401,9 @@ { int this_dev, found = 0; + if (load_8390_module("es3210.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) { struct net_device *dev = &dev_es3210[this_dev]; dev->irq = irq[this_dev]; @@ -415,14 +415,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -441,6 +440,6 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eth16i.c linux.ac/drivers/net/eth16i.c --- linux.vanilla/drivers/net/eth16i.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/eth16i.c Sat Jun 10 22:05:32 2000 @@ -448,7 +448,7 @@ if(base_addr > 0x1ff) /* Check only single location */ return eth16i_probe1(dev, base_addr); else if(base_addr != 0) /* Don't probe at all */ - return ENXIO; + return -ENXIO; /* Seek card from the ISA io address space */ for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) { @@ -466,7 +466,7 @@ return 0; } - return ENODEV; + return -ENODEV; } static int __init eth16i_probe1(struct net_device *dev, int ioaddr) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/fc/iph5526.c linux.ac/drivers/net/fc/iph5526.c --- linux.vanilla/drivers/net/fc/iph5526.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/fc/iph5526.c Tue May 30 15:27:09 2000 @@ -3771,7 +3771,9 @@ for (i = 0; i < clone_list[i].vendor_id != 0; i++) while ((pdev = pci_find_device(clone_list[i].vendor_id, clone_list[i].device_id, pdev))) { - unsigned short pci_command; + unsigned short pci_command; + if (pci_enable_device(pdev)) + continue; if (count < MAX_FC_CARDS) { fc[count] = kmalloc(sizeof(struct fc_info), GFP_ATOMIC); if (fc[count] == NULL) { @@ -3800,8 +3802,8 @@ host->hostt->use_new_eh_code = 1; host->this_id = tmpt->this_id; - pci_maddr = pdev->resource[0].start; - if ( (pdev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + pci_maddr = pci_resource_start(pdev, 0); + if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { printk("iph5526.c : Cannot find proper PCI device base address.\n"); scsi_unregister(host); kfree(fc[count]); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/fmv18x.c linux.ac/drivers/net/fmv18x.c --- linux.vanilla/drivers/net/fmv18x.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/fmv18x.c Sat Jun 10 22:05:32 2000 @@ -137,7 +137,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return fmv18x_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; fmv18x_probe_list[i]; i++) { int ioaddr = fmv18x_probe_list[i]; @@ -147,7 +147,7 @@ return 0; } - return ENODEV; + return -ENODEV; } /* The Fujitsu datasheet suggests that the NIC be probed for by checking its @@ -194,7 +194,7 @@ if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) { printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); - return EAGAIN; + return -EAGAIN; } /* Allocate a new 'dev' if needed. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/pi2.c linux.ac/drivers/net/hamradio/pi2.c --- linux.vanilla/drivers/net/hamradio/pi2.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/hamradio/pi2.c Sat Jun 10 22:05:32 2000 @@ -1378,7 +1378,7 @@ if (irqval) { printk(KERN_ERR "PI: unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); - return EAGAIN; + return -EAGAIN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hamradio/pt.c linux.ac/drivers/net/hamradio/pt.c --- linux.vanilla/drivers/net/hamradio/pt.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/hamradio/pt.c Sat Jun 10 22:05:32 2000 @@ -833,7 +833,7 @@ if (irqval) { printk(KERN_ERR "PT: ERROR: Unable to get IRQ %d (irqval = %d).\n", dev->irq, irqval); - return EAGAIN; + return -EAGAIN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hp-plus.c linux.ac/drivers/net/hp-plus.c --- linux.vanilla/drivers/net/hp-plus.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/hp-plus.c Sat Jun 10 22:05:32 2000 @@ -131,7 +131,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return hpp_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; hpplus_portlist[i]; i++) { int ioaddr = hpplus_portlist[i]; @@ -141,7 +141,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -157,10 +157,7 @@ /* Check for the HP+ signature, 50 48 0x 53. */ if (inw(ioaddr + HP_ID) != 0x4850 || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) - return ENODEV; - - if (load_8390_module("hp-plus.c")) - return -ENOSYS; + return -ENODEV; /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { @@ -186,7 +183,7 @@ if (checksum != 0xff) { printk(" bad checksum %2.2x.\n", checksum); - return ENODEV; + return -ENODEV; } else { /* Point at the Software Configuration Flags. */ outw(ID_Page, ioaddr + HP_PAGING); @@ -436,6 +433,9 @@ { int this_dev, found = 0; + if (load_8390_module("hp-plus.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) { struct net_device *dev = &dev_hpp[this_dev]; dev->irq = irq[this_dev]; @@ -448,14 +448,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -475,7 +474,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hp.c linux.ac/drivers/net/hp.c --- linux.vanilla/drivers/net/hp.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/hp.c Thu Jun 8 15:04:28 2000 @@ -92,7 +92,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return hp_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; hppclan_portlist[i]; i++) { int ioaddr = hppclan_portlist[i]; @@ -102,7 +102,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -119,7 +119,7 @@ || inb(ioaddr+1) != 0x00 || inb(ioaddr+2) != 0x09 || inb(ioaddr+14) == 0x57) - return ENODEV; + return -ENODEV; /* Set up the parameters based on the board ID. If you have additional mappings, please mail them to me -djb. */ @@ -131,9 +131,6 @@ wordmode = 0; } - if (load_8390_module("hp.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk("hp.c: Passed a NULL device.\n"); @@ -178,7 +175,7 @@ printk(" no free IRQ lines.\n"); kfree(dev->priv); dev->priv = NULL; - return EBUSY; + return -EBUSY; } } else { if (dev->irq == 2) @@ -187,7 +184,7 @@ printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return EBUSY; + return -EBUSY; } } @@ -407,6 +404,9 @@ { int this_dev, found = 0; + if (load_8390_module("hp.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) { struct net_device *dev = &dev_hp[this_dev]; dev->irq = irq[this_dev]; @@ -419,14 +419,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -446,7 +445,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hp100.c linux.ac/drivers/net/hp100.c --- linux.vanilla/drivers/net/hp100.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/hp100.c Sun Jun 4 22:14:21 2000 @@ -8,7 +8,7 @@ ** Extended for new busmaster capable chipsets by ** Siegfried "Frieder" Loeffler (dg1sek) ** -** Maintained by: Jaroslav Kysela +** Maintained by: Jaroslav Kysela ** ** This driver has only been tested with ** -- HP J2585B 10/100 Mbit/s PCI Busmaster @@ -109,16 +109,9 @@ #include #include -#if LINUX_VERSION_CODE >= 0x020100 #define LINUX_2_1 typedef struct net_device_stats hp100_stats_t; EXPORT_NO_SYMBOLS; -#else -#include -#define ioremap vremap -#define iounmap vfree -typedef struct enet_statistics hp100_stats_t; -#endif #include "hp100.h" @@ -187,12 +180,7 @@ u_short priority_tx; /* != 0 - priority tx */ u_short mode; /* PIO, Shared Mem or Busmaster */ u_char bus; -#ifndef LINUX_2_1 - u_char pci_bus; - u_char pci_device_fn; -#else struct pci_dev *pci_dev; -#endif short mem_mapped; /* memory mapped access */ void *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */ unsigned long mem_ptr_phys; /* physical memory mapped area */ @@ -287,21 +275,15 @@ static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; static int hp100_mode = 1; -#ifdef LINUX_2_1 MODULE_PARM( hp100_rx_ratio, "1i" ); MODULE_PARM( hp100_priority_tx, "1i" ); MODULE_PARM( hp100_mode, "1i" ); -#endif /* * prototypes */ -#ifdef LINUX_2_1 static int hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev ); -#else -static int hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ); -#endif static int hp100_open( struct net_device *dev ); static int hp100_close( struct net_device *dev ); static int hp100_start_xmit( struct sk_buff *skb, struct net_device *dev ); @@ -361,25 +343,12 @@ { if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL; if ( base_addr < 0x400 ) -#ifdef LINUX_2_1 return hp100_probe1( dev, base_addr, HP100_BUS_ISA, NULL ); -#else - return hp100_probe1( dev, base_addr, HP100_BUS_ISA, 0, 0 ); -#endif if ( EISA_bus && base_addr >= 0x1c38 && ( (base_addr - 0x1c38) & 0x3ff ) == 0 ) -#ifdef LINUX_2_1 return hp100_probe1( dev, base_addr, HP100_BUS_EISA, NULL ); -#else - return hp100_probe1( dev, base_addr, HP100_BUS_EISA, 0, 0 ); -#endif #ifdef CONFIG_PCI -#ifdef LINUX_2_1 printk( "hp100: %s: You must specify card # in i/o address parameter for PCI bus...", dev->name ); #else - printk( "hp100: %s: You may specify card # in i/o address parameter for PCI bus...", dev->name ); - return hp100_probe1( dev, base_addr, HP100_BUS_PCI, 0, 0 ); -#endif -#else return -ENODEV; #endif } @@ -397,16 +366,13 @@ if ( pcibios_present() ) { int pci_index; -#ifdef LINUX_2_1 struct pci_dev *pci_dev = NULL; int pci_id_index; u_short pci_command; -#endif #ifdef HP100_DEBUG_PCI printk( "hp100: %s: PCI BIOS is present, checking for devices..\n", dev->name ); #endif -#ifdef LINUX_2_1 pci_index = 0; for ( pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; pci_id_index++ ) { while ( (pci_dev = pci_find_device( hp100_pci_ids[ pci_id_index ].vendor, @@ -416,8 +382,10 @@ pci_index++; continue; } + if (pci_enable_device(pci_dev)) + continue; /* found... */ - ioaddr = pci_dev ->resource[ 0 ].start; + ioaddr = pci_resource_start (pci_dev, 0); if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; pci_read_config_word( pci_dev, PCI_COMMAND, &pci_command ); if ( !( pci_command & PCI_COMMAND_IO ) ) { @@ -441,55 +409,6 @@ return 0; } } -#else /* old PCI interface */ - for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ ) - { - u_char pci_bus, pci_device_fn; - u_short pci_command; - int pci_id_index; - - for ( pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; pci_id_index++ ) - if ( pcibios_find_device( hp100_pci_ids[ pci_id_index ].vendor, - hp100_pci_ids[ pci_id_index ].device, - pci_index, &pci_bus, - &pci_device_fn ) == 0 ) goto __pci_found; - break; - - __pci_found: - pcibios_read_config_dword( pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &ioaddr ); - - ioaddr &= ~3; /* remove I/O space marker in bit 0. */ - - if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; - - pcibios_read_config_word( pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command ); - if ( !( pci_command & PCI_COMMAND_IO ) ) - { -#ifdef HP100_DEBUG - printk( "hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name ); -#endif - pci_command |= PCI_COMMAND_IO; - pcibios_write_config_word( pci_bus, pci_device_fn, - PCI_COMMAND, pci_command ); - } - if ( !( pci_command & PCI_COMMAND_MASTER ) ) - { -#ifdef HP100_DEBUG - printk( "hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name ); -#endif - pci_command |= PCI_COMMAND_MASTER; - pcibios_write_config_word( pci_bus, pci_device_fn, - PCI_COMMAND, pci_command ); - } -#ifdef HP100_DEBUG - printk( "hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr ); -#endif - if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI, pci_bus, pci_device_fn ) == 0 ) - return 0; - } -#endif } if ( pci_start_index > 0 ) return -ENODEV; #endif /* CONFIG_PCI */ @@ -498,33 +417,21 @@ for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 ) { if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; -#ifdef LINUX_2_1 if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA, NULL ) == 0 ) return 0; -#else - if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA, 0, 0 ) == 0 ) return 0; -#endif } /* Third Probe all ISA possible port regions */ for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 ) { if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue; -#ifdef LINUX_2_1 if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA, NULL ) == 0 ) return 0; -#else - if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA, 0, 0 ) == 0 ) return 0; -#endif } return -ENODEV; } -#ifdef LINUX_2_1 static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev ) -#else -static int __init hp100_probe1( struct net_device *dev, int ioaddr, u_char bus, u_char pci_bus, u_char pci_device_fn ) -#endif { int i; @@ -549,7 +456,7 @@ #ifdef HP100_DEBUG printk( "hp100_probe1: %s: dev == NULL ?\n", dev->name ); #endif - return EIO; + return -EIO; } if ( hp100_inw( HW_ID ) != HP100_HW_ID_CASCADE ) @@ -799,12 +706,7 @@ lp->chip = chip; lp->mode = local_mode; lp->bus = bus; -#ifdef LINUX_2_1 lp->pci_dev = pci_dev; -#else - lp->pci_bus = pci_bus; - lp->pci_device_fn = pci_device_fn; -#endif lp->priority_tx = hp100_priority_tx; lp->rx_ratio = hp100_rx_ratio; lp->mem_ptr_phys = mem_ptr_phys; @@ -836,18 +738,14 @@ dev->set_multicast_list = &hp100_set_multicast_list; /* Ask the card for which IRQ line it is configured */ -#ifdef LINUX_2_1 if ( bus == HP100_BUS_PCI ) { dev->irq = pci_dev->irq; } else { -#endif hp100_page( HW_MAP ); dev->irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQMASK; if ( dev->irq == 2 ) dev->irq = 9; -#ifdef LINUX_2_1 } -#endif if(lp->mode==1) /* busmaster */ dev->dma=4; @@ -1648,9 +1546,6 @@ if ( skb==NULL ) { -#ifndef LINUX_2_1 - dev_tint( dev ); -#endif return 0; } @@ -1754,9 +1649,7 @@ /* Update statistics */ lp->stats.tx_packets++; -#ifdef LINUX_2_1 lp->stats.tx_bytes += skb->len; -#endif dev->trans_start = jiffies; return 0; @@ -1799,11 +1692,7 @@ hp100_inb(TX_PDL), donecount); #endif -#ifdef LINUX_2_1 dev_kfree_skb_any( lp->txrhead->skb ); -#else - dev_kfree_skb_any( lp->txrhead->skb, FREE_WRITE ); -#endif lp->txrhead->skb=(void *)NULL; lp->txrhead=lp->txrhead->next; lp->txrcommit--; @@ -1826,9 +1715,6 @@ if ( skb==NULL ) { -#ifndef LINUX_2_1 - dev_tint( dev ); -#endif return 0; } @@ -1953,17 +1839,11 @@ hp100_outb( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */ lp->stats.tx_packets++; -#ifdef LINUX_2_1 lp->stats.tx_bytes += skb->len; -#endif dev->trans_start=jiffies; hp100_ints_on(); -#ifdef LINUX_2_1 dev_kfree_skb_any( skb ); -#else - dev_kfree_skb_any( skb, FREE_WRITE ); -#endif #ifdef HP100_DEBUG_TX printk( "hp100: %s: start_xmit: end\n", dev->name ); @@ -2071,9 +1951,7 @@ netif_rx( skb ); lp->stats.rx_packets++; -#ifdef LINUX_2_1 lp->stats.rx_bytes += skb->len; -#endif #ifdef HP100_DEBUG_RX printk( "hp100: %s: rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", @@ -2180,9 +2058,7 @@ netif_rx( ptr->skb ); /* Up and away... */ lp->stats.rx_packets++; -#ifdef LINUX_2_1 lp->stats.rx_bytes += ptr->skb->len; -#endif } switch ( header & 0x00070000 ) { @@ -2197,11 +2073,7 @@ printk("hp100: %s: rx_bm: Received bad packet (length=%d)\n",dev->name,pkt_len); #endif if(ptr->skb!=NULL) -#ifdef LINUX_2_1 dev_kfree_skb_any( ptr->skb ); -#else - dev_kfree_skb_any( ptr->skb, FREE_READ ); -#endif lp->stats.rx_errors++; } @@ -3119,16 +2991,12 @@ /* Parameters set by insmod */ int hp100_port[5] = { 0, -1, -1, -1, -1 }; -#ifdef LINUX_2_1 MODULE_PARM(hp100_port, "1-5i"); -#endif /* Allocate 5 string of length IFNAMSIZ, one string for each device */ char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" }; -#ifdef LINUX_2_1 /* Allow insmod to write those 5 strings individually */ MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ)); -#endif /* List of devices */ static struct net_device *hp100_devlist[5] = { NULL, NULL, NULL, NULL, NULL }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/hplance.c linux.ac/drivers/net/hplance.c --- linux.vanilla/drivers/net/hplance.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/hplance.c Sat Jun 10 22:05:32 2000 @@ -93,7 +93,7 @@ } /* OK, return success, or ENODEV if we didn't find any cards */ if (!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ibmlana.c linux.ac/drivers/net/ibmlana.c --- linux.vanilla/drivers/net/ibmlana.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/ibmlana.c Tue Jun 6 12:37:13 2000 @@ -0,0 +1,1260 @@ +/* +net-3-driver for the IBM LAN Adapter/A + +This is an extension to the Linux operating system, and is covered by the +same Gnu Public License that covers that work. + +Copyright 1999 by Alfred Arnold (alfred@ccac.rwth-aachen.de, aarnold@elsa.de) + +This driver is based both on the SK_MCA driver, which is itself based on the +SK_G16 and 3C523 driver. + +paper sources: + 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by + Hans-Peter Messmer for the basic Microchannel stuff + + 'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer + for help on Ethernet driver programming + + 'DP83934CVUL-20/25 MHz SONIC-T Ethernet Controller Datasheet' by National + Semiconductor for info on the MAC chip + + 'LAN Technical Reference Ethernet Adapter Interface Version 1 Release 1.0 + Document Number SC30-3661-00' by IBM for info on the adapter itself + + Also see http://www.natsemi.com/ + +special acknowledgements to: + - Bob Eager for helping me out with documentation from IBM + - Jim Shorney for his endless patience with me while I was using + him as a beta tester to trace down the address filter bug ;-) + + Missing things: + + -> set debug level via ioctl instead of compile-time switches + -> I didn't follow the development of the 2.1.x kernels, so my + assumptions about which things changed with which kernel version + are probably nonsense + +History: + Nov 6th, 1999 + startup from SK_MCA driver + Dec 6th, 1999 + finally got docs about the card. A big thank you to Bob Eager! + Dec 12th, 1999 + first packet received + Dec 13th, 1999 + recv queue done, tcpdump works + Dec 15th, 1999 + transmission part works + Dec 28th, 1999 + added usage of the isa_functions for Linux 2.3 . Things should + still work with 2.0.x.... + Jan 28th, 2000 + in Linux 2.2.13, the version.h file mysteriously didn't get + included. Added a workaround for this. Futhermore, it now + not only compiles as a modules ;-) + Jan 30th, 2000 + newer kernels automatically probe more than one board, so the + 'startslot' as a variable is also needed here + Apr 12th, 2000 + the interrupt mask register is not set 'hard' instead of individually + setting registers, since this seems to set bits that shouldn't be + set + May 21st, 2000 + reset interrupt status immediately after CAM load + add a recovery delay after releasing the chip's reset line + May 24th, 2000 + finally found the bug in the address filter setup - damned signed + chars! + June 1st, 2000 + corrected version codes, added support for the latest 2.3 changes + + *************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MODULE +#include +#endif + +#include +#include +#include + +#define _IBM_LANA_DRIVER_ +#include "ibmlana.h" + +#undef DEBUG + +/* ------------------------------------------------------------------------ + * global static data - not more since we can handle multiple boards and + * have to pack all state info into the device struct! + * ------------------------------------------------------------------------ */ + +static char *MediaNames[Media_Count] = + { "10BaseT", "10Base5", "Unknown", "10Base2" }; + +/* ------------------------------------------------------------------------ + * private subfunctions + * ------------------------------------------------------------------------ */ + +#ifdef DEBUG + /* dump all registers */ + +static void dumpregs(struct IBMLANA_NETDEV *dev) +{ + int z; + + for (z = 0; z < 160; z += 2) { + if (!(z & 15)) + printk("REGS: %04x:", z); + printk(" %04x", inw(dev->base_addr + z)); + if ((z & 15) == 14) + printk("\n"); + } +} + +/* dump parts of shared memory - only needed during debugging */ + +static void dumpmem(struct IBMLANA_NETDEV *dev, u32 start, u32 len) +{ + int z; + + printk("Address %04x:\n", start); + for (z = 0; z < len; z++) { + if ((z & 15) == 0) + printk("%04x:", z); + printk(" %02x", IBMLANA_READB(dev->mem_start + start + z)); + if ((z & 15) == 15) + printk("\n"); + } + if ((z & 15) != 0) + printk("\n"); +} + +/* print exact time - ditto */ + +static void PrTime(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + printk("%9d:%06d: ", (int) tv.tv_sec, (int) tv.tv_usec); +} +#endif /* DEBUG */ + +/* deduce resources out of POS registers */ + +static void getaddrs(int slot, int *base, int *memlen, int *iobase, + int *irq, ibmlana_medium * medium) +{ + u_char pos0, pos1; + + pos0 = mca_read_stored_pos(slot, 2); + pos1 = mca_read_stored_pos(slot, 3); + + *base = 0xc0000 + ((pos1 & 0xf0) << 9); + *memlen = (pos1 & 0x01) ? 0x8000 : 0x4000; + *iobase = (pos0 & 0xe0) << 7; + switch (pos0 & 0x06) { + case 0: + *irq = 5; + break; + case 2: + *irq = 15; + break; + case 4: + *irq = 10; + break; + case 6: + *irq = 11; + break; + } + *medium = (pos0 & 0x18) >> 3; +} + +/* wait on register value with mask and timeout */ + +static int wait_timeout(struct IBMLANA_NETDEV *dev, int regoffs, u16 mask, + u16 value, int timeout) +{ + unsigned long fin = jiffies + timeout; + + while (jiffies != fin) + if ((inw(dev->base_addr + regoffs) & mask) == value) + return 1; + + return 0; +} + + +/* reset the whole board */ + +static void ResetBoard(struct IBMLANA_NETDEV *dev) +{ + unsigned char bcmval; + + /* read original board control value */ + + bcmval = inb(dev->base_addr + BCMREG); + + /* set reset bit for a while */ + + bcmval |= BCMREG_RESET; + outb(bcmval, dev->base_addr + BCMREG); + udelay(10); + bcmval &= ~BCMREG_RESET; + outb(bcmval, dev->base_addr + BCMREG); + + /* switch over to RAM again */ + + bcmval |= BCMREG_RAMEN | BCMREG_RAMWIN; + outb(bcmval, dev->base_addr + BCMREG); +} + +/* calculate RAM layout & set up descriptors in RAM */ + +static void InitDscrs(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + u32 addr, baddr, raddr; + int z; + tda_t tda; + rda_t rda; + rra_t rra; + + /* initialize RAM */ + + IBMLANA_SETIO(dev->mem_start, 0xaa, + dev->mem_start - dev->mem_start); + + /* setup n TX descriptors - independent of RAM size */ + + priv->tdastart = addr = 0; + priv->txbufstart = baddr = sizeof(tda_t) * TXBUFCNT; + for (z = 0; z < TXBUFCNT; z++) { + tda.status = 0; + tda.config = 0; + tda.length = 0; + tda.fragcount = 1; + tda.startlo = baddr; + tda.starthi = 0; + tda.fraglength = 0; + if (z == TXBUFCNT - 1) + tda.link = priv->tdastart; + else + tda.link = addr + sizeof(tda_t); + tda.link |= 1; + IBMLANA_TOIO(dev->mem_start + addr, &tda, sizeof(tda_t)); + addr += sizeof(tda_t); + baddr += PKTSIZE; + } + + /* calculate how many receive buffers fit into remaining memory */ + + priv->rxbufcnt = (dev->mem_end - dev->mem_start - baddr) / + (sizeof(rra_t) + sizeof(rda_t) + PKTSIZE); + + /* calculate receive addresses */ + + priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE); + priv->rdastart = addr = + priv->rrastart + (priv->rxbufcnt * sizeof(rra_t)); + priv->rxbufstart = baddr = + priv->rdastart + (priv->rxbufcnt * sizeof(rda_t)); + for (z = 0; z < priv->rxbufcnt; z++) { + rra.startlo = baddr; + rra.starthi = 0; + rra.cntlo = PKTSIZE >> 1; + rra.cnthi = 0; + IBMLANA_TOIO(dev->mem_start + raddr, &rra, sizeof(rra_t)); + + rda.status = 0; + rda.length = 0; + rda.startlo = 0; + rda.starthi = 0; + rda.seqno = 0; + if (z < priv->rxbufcnt - 1) + rda.link = addr + sizeof(rda_t); + else + rda.link = 1; + rda.inuse = 1; + IBMLANA_TOIO(dev->mem_start + addr, &rda, sizeof(rda_t)); + + baddr += PKTSIZE; + raddr += sizeof(rra_t); + addr += sizeof(rda_t); + } + + /* initialize current pointers */ + + priv->nextrxdescr = 0; + priv->lastrxdescr = priv->rxbufcnt - 1; + priv->nexttxdescr = 0; + priv->currtxdescr = 0; + priv->txusedcnt = 0; + memset(priv->txused, 0, sizeof(priv->txused)); +} + +/* set up Rx + Tx descriptors in SONIC */ + +static int InitSONIC(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + + /* set up start & end of resource area */ + + outw(0, SONIC_URRA); + outw(priv->rrastart, dev->base_addr + SONIC_RSA); + outw(priv->rrastart + (priv->rxbufcnt * sizeof(rra_t)), + dev->base_addr + SONIC_REA); + outw(priv->rrastart, dev->base_addr + SONIC_RRP); + outw(priv->rrastart, dev->base_addr + SONIC_RWP); + + /* set EOBC so that only one packet goes into one buffer */ + + outw((PKTSIZE - 4) >> 1, dev->base_addr + SONIC_EOBC); + + /* let SONIC read the first RRA descriptor */ + + outw(CMDREG_RRRA, dev->base_addr + SONIC_CMDREG); + if (!wait_timeout(dev, SONIC_CMDREG, CMDREG_RRRA, 0, 2)) { + printk + ("%s: SONIC did not respond on RRRA command - giving up.", + dev->name); + return 0; + } + + /* point SONIC to the first RDA */ + + outw(0, dev->base_addr + SONIC_URDA); + outw(priv->rdastart, dev->base_addr + SONIC_CRDA); + + /* set upper half of TDA address */ + + outw(0, dev->base_addr + SONIC_UTDA); + + return 1; +} + +/* stop SONIC so we can reinitialize it */ + +static void StopSONIC(struct IBMLANA_NETDEV *dev) +{ + /* disable interrupts */ + + outb(inb(dev->base_addr + BCMREG) & (~BCMREG_IEN), + dev->base_addr + BCMREG); + outb(0, dev->base_addr + SONIC_IMREG); + + /* reset the SONIC */ + + outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG); + udelay(10); + outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG); +} + +/* initialize card and SONIC for proper operation */ + +static void putcam(camentry_t * cams, int *camcnt, char *addr) +{ + camentry_t *pcam = cams + (*camcnt); + u8 *uaddr = (u8 *) addr; + + pcam->index = *camcnt; + pcam->addr0 = (((u16) uaddr[1]) << 8) | uaddr[0]; + pcam->addr1 = (((u16) uaddr[3]) << 8) | uaddr[2]; + pcam->addr2 = (((u16) uaddr[5]) << 8) | uaddr[4]; + (*camcnt)++; +} + +static void InitBoard(struct IBMLANA_NETDEV *dev) +{ + int camcnt; + camentry_t cams[16]; + u32 cammask; + struct dev_mc_list *mcptr; + u16 rcrval; + + /* reset the SONIC */ + + outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG); + udelay(10); + + /* clear all spurious interrupts */ + + outw(inw(dev->base_addr + SONIC_ISREG), + dev->base_addr + SONIC_ISREG); + + /* set up the SONIC's bus interface - constant for this adapter - + must be done while the SONIC is in reset */ + + outw(DCREG_USR1 | DCREG_USR0 | DCREG_WC1 | DCREG_DW32, + dev->base_addr + SONIC_DCREG); + outw(0, dev->base_addr + SONIC_DCREG2); + + /* remove reset form the SONIC */ + + outw(0, dev->base_addr + SONIC_CMDREG); + udelay(10); + + /* data sheet requires URRA to be programmed before setting up the CAM contents */ + + outw(0, dev->base_addr + SONIC_URRA); + + /* program the CAM entry 0 to the device address */ + + camcnt = 0; + putcam(cams, &camcnt, dev->dev_addr); + + /* start putting the multicast addresses into the CAM list. Stop if + it is full. */ + + for (mcptr = dev->mc_list; mcptr != NULL; mcptr = mcptr->next) { + putcam(cams, &camcnt, mcptr->dmi_addr); + if (camcnt == 16) + break; + } + + /* calculate CAM mask */ + + cammask = (1 << camcnt) - 1; + + /* feed CDA into SONIC, initialize RCR value (always get broadcasts) */ + + IBMLANA_TOIO(dev->mem_start, cams, sizeof(camentry_t) * camcnt); + IBMLANA_TOIO(dev->mem_start + (sizeof(camentry_t) * camcnt), + &cammask, sizeof(cammask)); + +#ifdef DEBUG + printk("CAM setup:\n"); + dumpmem(dev, 0, sizeof(camentry_t) * camcnt + sizeof(cammask)); +#endif + + outw(0, dev->base_addr + SONIC_CAMPTR); + outw(camcnt, dev->base_addr + SONIC_CAMCNT); + outw(CMDREG_LCAM, dev->base_addr + SONIC_CMDREG); + if (!wait_timeout(dev, SONIC_CMDREG, CMDREG_LCAM, 0, 2)) { + printk + ("%s:SONIC did not respond on LCAM command - giving up.", + dev->name); + return; + } else { + /* clear interrupt condition */ + + outw(ISREG_LCD, dev->base_addr + SONIC_ISREG); + +#ifdef DEBUG + printk("Loading CAM done, address pointers %04x:%04x\n", + inw(dev->base_addr + SONIC_URRA), + inw(dev->base_addr + SONIC_CAMPTR)); + { + int z; + + printk("\n-->CAM: PTR %04x CNT %04x\n", + inw(dev->base_addr + SONIC_CAMPTR), + inw(dev->base_addr + SONIC_CAMCNT)); + outw(CMDREG_RST, dev->base_addr + SONIC_CMDREG); + for (z = 0; z < camcnt; z++) { + outw(z, dev->base_addr + SONIC_CAMEPTR); + printk("Entry %d: %04x %04x %04x\n", z, + inw(dev->base_addr + + SONIC_CAMADDR0), + inw(dev->base_addr + + SONIC_CAMADDR1), + inw(dev->base_addr + + SONIC_CAMADDR2)); + } + outw(0, dev->base_addr + SONIC_CMDREG); + } +#endif + } + + rcrval = RCREG_BRD | RCREG_LB_NONE; + + /* if still multicast addresses left or ALLMULTI is set, set the multicast + enable bit */ + + if ((dev->flags & IFF_ALLMULTI) || (mcptr != NULL)) + rcrval |= RCREG_AMC; + + /* promiscous mode ? */ + + if (dev->flags & IFF_PROMISC) + rcrval |= RCREG_PRO; + + /* program receive mode */ + + outw(rcrval, dev->base_addr + SONIC_RCREG); +#ifdef DEBUG + printk("\nRCRVAL: %04x\n", rcrval); +#endif + + /* set up descriptors in shared memory + feed them into SONIC registers */ + + InitDscrs(dev); + if (!InitSONIC(dev)) + return; + + /* reset all pending interrupts */ + + outw(0xffff, dev->base_addr + SONIC_ISREG); + + /* enable transmitter + receiver interrupts */ + + outw(CMDREG_RXEN, dev->base_addr + SONIC_CMDREG); + outw(IMREG_PRXEN | IMREG_RBEEN | IMREG_PTXEN | IMREG_TXEREN, + dev->base_addr + SONIC_IMREG); + + /* turn on card interrupts */ + + outb(inb(dev->base_addr + BCMREG) | BCMREG_IEN, + dev->base_addr + BCMREG); + +#ifdef DEBUG + printk("Register dump after initialization:\n"); + dumpregs(dev); +#endif +} + +/* start transmission of a descriptor */ + +static void StartTx(struct IBMLANA_NETDEV *dev, int descr) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + int addr; + + addr = priv->tdastart + (descr * sizeof(tda_t)); + + /* put descriptor address into SONIC */ + + outw(addr, dev->base_addr + SONIC_CTDA); + + /* trigger transmitter */ + + priv->currtxdescr = descr; + outw(CMDREG_TXP, dev->base_addr + SONIC_CMDREG); +} + +/* ------------------------------------------------------------------------ + * interrupt handler(s) + * ------------------------------------------------------------------------ */ + +/* receive buffer area exhausted */ + +static void irqrbe_handler(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + + /* point the SONIC back to the RRA start */ + + outw(priv->rrastart, dev->base_addr + SONIC_RRP); + outw(priv->rrastart, dev->base_addr + SONIC_RWP); +} + +/* receive interrupt */ + +static void irqrx_handler(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + rda_t rda; + u32 rdaaddr, lrdaaddr; + + /* loop until ... */ + + while (1) { + /* read descriptor that was next to be filled by SONIC */ + + rdaaddr = + priv->rdastart + (priv->nextrxdescr * sizeof(rda_t)); + lrdaaddr = + priv->rdastart + (priv->lastrxdescr * sizeof(rda_t)); + IBMLANA_FROMIO(&rda, dev->mem_start + rdaaddr, + sizeof(rda_t)); + + /* iron out upper word halves of fields we use - SONIC will duplicate + bits 0..15 to 16..31 */ + + rda.status &= 0xffff; + rda.length &= 0xffff; + rda.startlo &= 0xffff; + + /* stop if the SONIC still owns it, i.e. there is no data for us */ + + if (rda.inuse) + break; + + /* good packet? */ + + else if (rda.status & RCREG_PRX) { + struct sk_buff *skb; + + /* fetch buffer */ + + skb = dev_alloc_skb(rda.length + 2); + if (skb == NULL) + priv->stat.rx_dropped++; + else { + /* copy out data */ + + IBMLANA_FROMIO(skb_put(skb, rda.length), + dev->mem_start + + rda.startlo, rda.length); + + /* set up skb fields */ + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_NONE; + + /* bookkeeping */ + + priv->stat.rx_packets++; +#if (LINUX_VERSION_CODE >= 0x20119) /* byte counters for kernel >= 2.1.25 */ + priv->stat.rx_bytes += rda.length; +#endif + + /* pass to the upper layers */ + + netif_rx(skb); + } + } + + /* otherwise check error status bits and increase statistics */ + + else { + priv->stat.rx_errors++; + + if (rda.status & RCREG_FAER) + priv->stat.rx_frame_errors++; + + if (rda.status & RCREG_CRCR) + priv->stat.rx_crc_errors++; + } + + /* descriptor processed, will become new last descriptor in queue */ + + rda.link = 1; + rda.inuse = 1; + IBMLANA_TOIO(dev->mem_start + rdaaddr, &rda, + sizeof(rda_t)); + + /* set up link and EOL = 0 in currently last descriptor. Only write + the link field since the SONIC may currently already access the + other fields. */ + + IBMLANA_TOIO(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4); + + /* advance indices */ + + priv->lastrxdescr = priv->nextrxdescr; + if ((++priv->nextrxdescr) >= priv->rxbufcnt) + priv->nextrxdescr = 0; + } +} + +/* transmit interrupt */ + +static void irqtx_handler(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + tda_t tda; + + /* fetch descriptor (we forgot the size ;-) */ + + IBMLANA_FROMIO(&tda, + dev->mem_start + priv->tdastart + + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t)); + + /* update statistics */ + + priv->stat.tx_packets++; +#if (LINUX_VERSION_CODE >= 0x020119) + priv->stat.tx_bytes += tda.length; +#endif + + /* update our pointers */ + + priv->txused[priv->currtxdescr] = 0; + priv->txusedcnt--; + + /* if there are more descriptors present in RAM, start them */ + + if (priv->txusedcnt > 0) + StartTx(dev, (priv->currtxdescr + 1) % TXBUFCNT); + + /* tell the upper layer we can go on transmitting */ + +#if LINUX_VERSION_CODE >= 0x02032a + netif_wake_queue(dev); +#else + dev->tbusy = 0; + mark_bh(NET_BH); +#endif +} + +static void irqtxerr_handler(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + tda_t tda; + + /* fetch descriptor to check status */ + + IBMLANA_FROMIO(&tda, + dev->mem_start + priv->tdastart + + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t)); + + /* update statistics */ + + priv->stat.tx_errors++; + if (tda.status & (TCREG_NCRS | TCREG_CRSL)) + priv->stat.tx_carrier_errors++; + if (tda.status & TCREG_EXC) + priv->stat.tx_aborted_errors++; + if (tda.status & TCREG_OWC) + priv->stat.tx_window_errors++; + if (tda.status & TCREG_FU) + priv->stat.tx_fifo_errors++; + + /* update our pointers */ + + priv->txused[priv->currtxdescr] = 0; + priv->txusedcnt--; + + /* if there are more descriptors present in RAM, start them */ + + if (priv->txusedcnt > 0) + StartTx(dev, (priv->currtxdescr + 1) % TXBUFCNT); + + /* tell the upper layer we can go on transmitting */ + +#if LINUX_VERSION_CODE >= 0x02032a + netif_wake_queue(dev); +#else + dev->tbusy = 0; + mark_bh(NET_BH); +#endif +} + +/* general interrupt entry */ + +static void irq_handler(int irq, void *device, struct pt_regs *regs) +{ + struct IBMLANA_NETDEV *dev = (struct IBMLANA_NETDEV *) device; + u16 ival; + + /* in case we're not meant... */ + + if (!(inb(dev->base_addr + BCMREG) & BCMREG_IPEND)) + return; + +#if (LINUX_VERSION_CODE >= 0x02032a) +#if 0 + set_bit(LINK_STATE_RXSEM, &dev->state); +#endif +#else + dev->interrupt = 1; +#endif + + /* loop through the interrupt bits until everything is clear */ + + while (1) { + ival = inw(dev->base_addr + SONIC_ISREG); + + if (ival & ISREG_RBE) { + irqrbe_handler(dev); + outw(ISREG_RBE, dev->base_addr + SONIC_ISREG); + } + + if (ival & ISREG_PKTRX) { + irqrx_handler(dev); + outw(ISREG_PKTRX, dev->base_addr + SONIC_ISREG); + } + + if (ival & ISREG_TXDN) { + irqtx_handler(dev); + outw(ISREG_TXDN, dev->base_addr + SONIC_ISREG); + } + + if (ival & ISREG_TXER) { + irqtxerr_handler(dev); + outw(ISREG_TXER, dev->base_addr + SONIC_ISREG); + } + + break; + } + +#if (LINUX_VERSION_CODE >= 0x02032a) +#if 0 + clear_bit(LINK_STATE_RXSEM, &dev->state); +#endif +#else + dev->interrupt = 0; +#endif +} + +/* ------------------------------------------------------------------------ + * driver methods + * ------------------------------------------------------------------------ */ + +/* MCA info */ + +static int ibmlana_getinfo(char *buf, int slot, void *d) +{ + int len = 0, i; + struct IBMLANA_NETDEV *dev = (struct IBMLANA_NETDEV *) d; + ibmlana_priv *priv; + + /* can't say anything about an uninitialized device... */ + + if (dev == NULL) + return len; + if (dev->priv == NULL) + return len; + priv = (ibmlana_priv *) dev->priv; + + /* print info */ + + len += sprintf(buf + len, "IRQ: %d\n", priv->realirq); + len += sprintf(buf + len, "I/O: %#lx\n", dev->base_addr); + len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, + dev->mem_end - 1); + len += + sprintf(buf + len, "Transceiver: %s\n", + MediaNames[priv->medium]); + len += sprintf(buf + len, "Device: %s\n", dev->name); + len += sprintf(buf + len, "MAC address:"); + for (i = 0; i < 6; i++) + len += sprintf(buf + len, " %02x", dev->dev_addr[i]); + buf[len++] = '\n'; + buf[len] = 0; + + return len; +} + +/* open driver. Means also initialization and start of LANCE */ + +static int ibmlana_open(struct IBMLANA_NETDEV *dev) +{ + int result; + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + + /* register resources - only necessary for IRQ */ + + result = + request_irq(priv->realirq, irq_handler, + SA_SHIRQ | SA_SAMPLE_RANDOM, "ibm_lana", dev); + if (result != 0) { + printk("%s: failed to register irq %d\n", dev->name, + dev->irq); + return result; + } + dev->irq = priv->realirq; + + /* set up the card and SONIC */ + + InitBoard(dev); + + /* initialize operational flags */ + +#if (LINUX_VERSION_CODE >= 0x02032a) + netif_start_queue(dev); +#else + dev->interrupt = 0; + dev->tbusy = 0; + dev->start = 1; +#endif + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +/* close driver. Shut down board and free allocated resources */ + +static int ibmlana_close(struct IBMLANA_NETDEV *dev) +{ + /* turn off board */ + + /* release resources */ + if (dev->irq != 0) + free_irq(dev->irq, dev); + dev->irq = 0; + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + return 0; +} + +/* transmit a block. */ + +static int ibmlana_tx(struct sk_buff *skb, struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + int retval = 0, tmplen, addr; + unsigned long flags; + tda_t tda; + int baddr; + + /* if we get called with a NULL descriptor, the Ethernet layer thinks + our card is stuck an we should reset it. We'll do this completely: */ + + if (skb == NULL) { + printk("%s: Resetting SONIC\n", dev->name); + StopSONIC(dev); + InitBoard(dev); + return 0; /* don't try to free the block here ;-) */ + } + + /* find out if there are free slots for a frame to transmit. If not, + the upper layer is in deep desperation and we simply ignore the frame. */ + + if (priv->txusedcnt >= TXBUFCNT) { + retval = -EIO; + priv->stat.tx_dropped++; + goto tx_done; + } + + /* copy the frame data into the next free transmit buffer - fillup missing */ + + tmplen = skb->len; + if (tmplen < 60) + tmplen = 60; + baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE); + IBMLANA_TOIO(dev->mem_start + baddr, skb->data, skb->len); + + /* copy filler into RAM - in case we're filling up... + we're filling a bit more than necessary, but that doesn't harm + since the buffer is far larger... + Sorry Linus for the filler string but I couldn't resist ;-) */ + + if (tmplen > skb->len) { + char *fill = "NetBSD is a nice OS too! "; + unsigned int destoffs = skb->len, l = strlen(fill); + + while (destoffs < tmplen) { + IBMLANA_TOIO(dev->mem_start + baddr + destoffs, + fill, l); + destoffs += l; + } + } + + /* set up the new frame descriptor */ + + addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t)); + IBMLANA_FROMIO(&tda, dev->mem_start + addr, sizeof(tda_t)); + tda.length = tda.fraglength = tmplen; + IBMLANA_TOIO(dev->mem_start + addr, &tda, sizeof(tda_t)); + + /* if there were no active descriptors, trigger the SONIC */ + + save_flags(flags); + cli(); + + priv->txusedcnt++; + priv->txused[priv->nexttxdescr] = 1; + + /* are all transmission slots used up ? */ + + if (priv->txusedcnt >= TXBUFCNT) +#if (LINUX_VERSION_CODE >= 0x02032a) + netif_stop_queue(dev); +#else + dev->tbusy = 1; +#endif + + if (priv->txusedcnt == 1) + StartTx(dev, priv->nexttxdescr); + priv->nexttxdescr = (priv->nexttxdescr + 1) % TXBUFCNT; + + restore_flags(flags); + + tx_done: + + /* When did that change exactly ? */ + +#if (LINUX_VERSION_CODE >= 0x20200) + dev_kfree_skb(skb); +#else + dev_kfree_skb(skb, FREE_WRITE); +#endif + return retval; +} + +/* return pointer to Ethernet statistics */ + +static struct enet_statistics *ibmlana_stats(struct IBMLANA_NETDEV *dev) +{ + ibmlana_priv *priv = (ibmlana_priv *) dev->priv; + + return &(priv->stat); +} + +/* we don't support runtime reconfiguration, since am MCA card can + be unambigously identified by its POS registers. */ + +static int ibmlana_config(struct IBMLANA_NETDEV *dev, struct ifmap *map) +{ + return 0; +} + +/* switch receiver mode. */ + +static void ibmlana_set_multicast_list(struct IBMLANA_NETDEV *dev) +{ + /* first stop the SONIC... */ + + StopSONIC(dev); + + /* ...then reinit it with the new flags */ + + InitBoard(dev); +} + +/* ------------------------------------------------------------------------ + * hardware check + * ------------------------------------------------------------------------ */ + +static int startslot; /* counts through slots when probing multiple devices */ + +int ibmlana_probe(struct IBMLANA_NETDEV *dev) +{ + int force_detect = 0; + int slot, z; + int base = 0, irq = 0, iobase = 0, memlen = 0; + ibmlana_priv *priv; + ibmlana_medium medium; + + /* can't work without an MCA bus ;-) */ + + if (MCA_bus == 0) + return ENODEV; + + /* start address of 1 --> forced detection */ + + if (dev->mem_start == 1) + force_detect = 1; + + /* search through slots */ + + if (dev != NULL) { + base = dev->mem_start; + irq = dev->irq; + } + slot = mca_find_adapter(IBM_LANA_ID, startslot); + + while (slot != -1) { + /* deduce card addresses */ + + getaddrs(slot, &base, &memlen, &iobase, &irq, &medium); + +#if (LINUX_VERSION_CODE >= 0x20300) + /* slot already in use ? */ + + if (mca_is_adapter_used(slot)) { + slot = mca_find_adapter(IBM_LANA_ID, slot + 1); + continue; + } +#endif + + /* were we looking for something different ? */ + + if ((dev->irq != 0) || (dev->mem_start != 0)) { + if ((dev->irq != 0) && (dev->irq != irq)) { + slot = + mca_find_adapter(IBM_LANA_ID, + slot + 1); + continue; + } + if ((dev->mem_start != 0) + && (dev->mem_start != base)) { + slot = + mca_find_adapter(IBM_LANA_ID, + slot + 1); + continue; + } + } + + /* found something that matches */ + + break; + } + + /* nothing found ? */ + + if (slot == -1) + return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV; + + /* announce success */ + printk("%s: IBM LAN Adapter/A found in slot %d\n", dev->name, + slot + 1); + + /* try to obtain I/O range */ + if (check_region(iobase, IBM_LANA_IORANGE) < 0) { + printk("cannot allocate I/O range at %#x!\n", iobase); + startslot = slot + 1; + return 0; + } + request_region(iobase, IBM_LANA_IORANGE, "ibm_lana"); + + /* make procfs entries */ + + mca_set_adapter_name(slot, "IBM LAN Adapter/A"); + mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev); + +#if (LINUX_VERSION_CODE >= 0x20200) + mca_mark_as_used(slot); +#endif + + /* allocate structure */ + + priv = dev->priv = + (ibmlana_priv *) kmalloc(sizeof(ibmlana_priv), GFP_KERNEL); + priv->slot = slot; + priv->realirq = irq; + priv->medium = medium; + memset(&(priv->stat), 0, sizeof(struct enet_statistics)); + + /* set base + irq for this device (irq not allocated so far) */ + + dev->irq = 0; + dev->mem_start = base; + dev->mem_end = base + memlen; + dev->base_addr = iobase; + + /* set methods */ + + dev->open = ibmlana_open; + dev->stop = ibmlana_close; + dev->set_config = ibmlana_config; + dev->hard_start_xmit = ibmlana_tx; + dev->do_ioctl = NULL; + dev->get_stats = ibmlana_stats; + dev->set_multicast_list = ibmlana_set_multicast_list; + dev->flags |= IFF_MULTICAST; + + /* generic setup */ + + ether_setup(dev); + + /* copy out MAC address */ + + for (z = 0; z < sizeof(dev->dev_addr); z++) + dev->dev_addr[z] = inb(dev->base_addr + MACADDRPROM + z); + + /* print config */ + + printk("%s: IRQ %d, I/O %#lx, memory %#lx-%#lx, " + "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n", + dev->name, priv->realirq, dev->base_addr, + dev->mem_start, dev->mem_end - 1, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]); + + /* reset board */ + + ResetBoard(dev); + + /* next probe will start at next slot */ + + startslot = slot + 1; + + return 0; +} + +/* ------------------------------------------------------------------------ + * modularization support + * ------------------------------------------------------------------------ */ + +#ifdef MODULE + +#define DEVMAX 5 + +#if (LINUX_VERSION_CODE >= 0x020363) +static struct IBMLANA_NETDEV moddevs[DEVMAX] = + { {" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe} +}; +#else +static char NameSpace[8 * DEVMAX]; +static struct IBMLANA_NETDEV moddevs[DEVMAX] = + { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, +{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe} +}; +#endif + +int irq = 0; +int io = 0; + +int init_module(void) +{ + int z, res; + + startslot = 0; + for (z = 0; z < DEVMAX; z++) { + strcpy(moddevs[z].name, " "); + res = register_netdev(moddevs + z); + if (res != 0) + return (z > 0) ? 0 : -EIO; + } + + return 0; +} + +void cleanup_module(void) +{ + struct IBMLANA_NETDEV *dev; + ibmlana_priv *priv; + int z; + + if (MOD_IN_USE) { + printk("cannot unload, module in use\n"); + return; + } + + for (z = 0; z < DEVMAX; z++) { + dev = moddevs + z; + if (dev->priv != NULL) { + priv = (ibmlana_priv *) dev->priv; + /*DeinitBoard(dev); */ + if (dev->irq != 0) + free_irq(dev->irq, dev); + dev->irq = 0; + release_region(dev->base_addr, IBM_LANA_IORANGE); + unregister_netdev(dev); +#if (LINUX_VERSION_CODE >= 0x20200) + mca_mark_as_unused(priv->slot); +#endif + mca_set_adapter_name(priv->slot, ""); + mca_set_adapter_procfn(priv->slot, NULL, NULL); + kfree_s(dev->priv, sizeof(ibmlana_priv)); + dev->priv = NULL; + } + } +} +#endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ibmlana.h linux.ac/drivers/net/ibmlana.h --- linux.vanilla/drivers/net/ibmlana.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/net/ibmlana.h Mon Jun 5 19:42:16 2000 @@ -0,0 +1,295 @@ +#ifndef _IBM_LANA_INCLUDE_ +#define _IBM_LANA_INCLUDE_ + +#ifdef _IBM_LANA_DRIVER_ + +/* version-dependent functions/structures */ + +#if LINUX_VERSION_CODE >= 0x020318 +#define IBMLANA_READB(addr) isa_readb(addr) +#define IBMLANA_TOIO(dest, src, len) isa_memcpy_toio(dest, src, len) +#define IBMLANA_FROMIO(dest, src, len) isa_memcpy_fromio(dest, src, len) +#define IBMLANA_SETIO(dest, val, len) isa_memset_io(dest, val, len) +#define IBMLANA_NETDEV net_device +#else +#define IBMLANA_READB(addr) readb(addr) +#define IBMLANA_TOIO(dest, src, len) memcpy_toio(dest, src, len) +#define IBMLANA_FROMIO(dest, src, len) memcpy_fromio(dest, src, len) +#define IBMLANA_SETIO(dest, val, len) memset_io(dest, val, len) +#define IBMLANA_NETDEV device +#endif + +/* maximum packet size */ + +#define PKTSIZE 1524 + +/* number of transmit buffers */ + +#define TXBUFCNT 4 + +/* Adapter ID's */ +#define IBM_LANA_ID 0xffe0 + +/* media enumeration - defined in a way that it fits onto the LAN/A's + POS registers... */ + +typedef enum { Media_10BaseT, Media_10Base5, + Media_Unknown, Media_10Base2, Media_Count +} ibmlana_medium; + +/* private structure */ + +typedef struct { + unsigned int slot; /* MCA-Slot-# */ + struct enet_statistics stat; /* packet statistics */ + int realirq; /* memorizes actual IRQ, even when + currently not allocated */ + ibmlana_medium medium; /* physical cannector */ + u32 tdastart, txbufstart, /* addresses */ + rrastart, rxbufstart, rdastart, rxbufcnt, txusedcnt; + int nextrxdescr, /* next rx descriptor to be used */ + lastrxdescr, /* last free rx descriptor */ + nexttxdescr, /* last tx descriptor to be used */ + currtxdescr, /* tx descriptor currently tx'ed */ + txused[TXBUFCNT]; /* busy flags */ +} ibmlana_priv; + +/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes + a full 64K I/O range... */ + +#define IBM_LANA_IORANGE 0xa0 + +/* Command Register: */ + +#define SONIC_CMDREG 0x00 +#define CMDREG_HTX 0x0001 /* halt transmission */ +#define CMDREG_TXP 0x0002 /* start transmission */ +#define CMDREG_RXDIS 0x0004 /* disable receiver */ +#define CMDREG_RXEN 0x0008 /* enable receiver */ +#define CMDREG_STP 0x0010 /* stop timer */ +#define CMDREG_ST 0x0020 /* start timer */ +#define CMDREG_RST 0x0080 /* software reset */ +#define CMDREG_RRRA 0x0100 /* force SONIC to read first RRA */ +#define CMDREG_LCAM 0x0200 /* force SONIC to read CAM descrs */ + +/* Data Configuration Register */ + +#define SONIC_DCREG 0x02 +#define DCREG_EXBUS 0x8000 /* Extended Bus Mode */ +#define DCREG_LBR 0x2000 /* Latched Bus Retry */ +#define DCREG_PO1 0x1000 /* Programmable Outputs */ +#define DCREG_PO0 0x0800 +#define DCREG_SBUS 0x0400 /* Synchronous Bus Mode */ +#define DCREG_USR1 0x0200 /* User Definable Pins */ +#define DCREG_USR0 0x0100 +#define DCREG_WC0 0x0000 /* 0..3 Wait States */ +#define DCREG_WC1 0x0040 +#define DCREG_WC2 0x0080 +#define DCREG_WC3 0x00c0 +#define DCREG_DW16 0x0000 /* 16 bit Bus Mode */ +#define DCREG_DW32 0x0020 /* 32 bit Bus Mode */ +#define DCREG_BMS 0x0010 /* Block Mode Select */ +#define DCREG_RFT4 0x0000 /* 4/8/16/24 bytes RX Threshold */ +#define DCREG_RFT8 0x0004 +#define DCREG_RFT16 0x0008 +#define DCREG_RFT24 0x000c +#define DCREG_TFT8 0x0000 /* 8/16/24/28 bytes TX Threshold */ +#define DCREG_TFT16 0x0001 +#define DCREG_TFT24 0x0002 +#define DCREG_TFT28 0x0003 + +/* Receive Control Register */ + +#define SONIC_RCREG 0x04 +#define RCREG_ERR 0x8000 /* accept damaged and collided pkts */ +#define RCREG_RNT 0x4000 /* accept packets that are < 64 */ +#define RCREG_BRD 0x2000 /* accept broadcasts */ +#define RCREG_PRO 0x1000 /* promiscous mode */ +#define RCREG_AMC 0x0800 /* accept all multicasts */ +#define RCREG_LB_NONE 0x0000 /* no loopback */ +#define RCREG_LB_MAC 0x0200 /* MAC loopback */ +#define RCREG_LB_ENDEC 0x0400 /* ENDEC loopback */ +#define RCREG_LB_XVR 0x0600 /* Transceiver loopback */ +#define RCREG_MC 0x0100 /* Multicast received */ +#define RCREG_BC 0x0080 /* Broadcast received */ +#define RCREG_LPKT 0x0040 /* last packet in RBA */ +#define RCREG_CRS 0x0020 /* carrier sense present */ +#define RCREG_COL 0x0010 /* recv'd packet with collision */ +#define RCREG_CRCR 0x0008 /* recv'd packet with CRC error */ +#define RCREG_FAER 0x0004 /* recv'd packet with inv. framing */ +#define RCREG_LBK 0x0002 /* recv'd loopback packet */ +#define RCREG_PRX 0x0001 /* recv'd packet is OK */ + +/* Transmit Control Register */ + +#define SONIC_TCREG 0x06 +#define TCREG_PINT 0x8000 /* generate interrupt after TDA read */ +#define TCREG_POWC 0x4000 /* timer start out of window detect */ +#define TCREG_CRCI 0x2000 /* inhibit CRC generation */ +#define TCREG_EXDIS 0x1000 /* disable excessive deferral timer */ +#define TCREG_EXD 0x0400 /* excessive deferral occured */ +#define TCREG_DEF 0x0200 /* single deferral occured */ +#define TCREG_NCRS 0x0100 /* no carrier detected */ +#define TCREG_CRSL 0x0080 /* carrier lost */ +#define TCREG_EXC 0x0040 /* excessive collisions occured */ +#define TCREG_OWC 0x0020 /* out of window collision occured */ +#define TCREG_PMB 0x0008 /* packet monitored bad */ +#define TCREG_FU 0x0004 /* FIFO underrun */ +#define TCREG_BCM 0x0002 /* byte count mismatch of fragments */ +#define TCREG_PTX 0x0001 /* packet transmitted OK */ + +/* Interrupt Mask Register */ + +#define SONIC_IMREG 0x08 +#define IMREG_BREN 0x4000 /* interrupt when bus retry occured */ +#define IMREG_HBLEN 0x2000 /* interrupt when heartbeat lost */ +#define IMREG_LCDEN 0x1000 /* interrupt when CAM loaded */ +#define IMREG_PINTEN 0x0800 /* interrupt when PINT in TDA set */ +#define IMREG_PRXEN 0x0400 /* interrupt when packet received */ +#define IMREG_PTXEN 0x0200 /* interrupt when packet was sent */ +#define IMREG_TXEREN 0x0100 /* interrupt when send failed */ +#define IMREG_TCEN 0x0080 /* interrupt when timer completed */ +#define IMREG_RDEEN 0x0040 /* interrupt when RDA exhausted */ +#define IMREG_RBEEN 0x0020 /* interrupt when RBA exhausted */ +#define IMREG_RBAEEN 0x0010 /* interrupt when RBA too short */ +#define IMREG_CRCEN 0x0008 /* interrupt when CRC counter rolls */ +#define IMREG_FAEEN 0x0004 /* interrupt when FAE counter rolls */ +#define IMREG_MPEN 0x0002 /* interrupt when MP counter rolls */ +#define IMREG_RFOEN 0x0001 /* interrupt when Rx FIFO overflows */ + +/* Interrupt Status Register */ + +#define SONIC_ISREG 0x0a +#define ISREG_BR 0x4000 /* bus retry occured */ +#define ISREG_HBL 0x2000 /* heartbeat lost */ +#define ISREG_LCD 0x1000 /* CAM loaded */ +#define ISREG_PINT 0x0800 /* PINT in TDA set */ +#define ISREG_PKTRX 0x0400 /* packet received */ +#define ISREG_TXDN 0x0200 /* packet was sent */ +#define ISREG_TXER 0x0100 /* send failed */ +#define ISREG_TC 0x0080 /* timer completed */ +#define ISREG_RDE 0x0040 /* RDA exhausted */ +#define ISREG_RBE 0x0020 /* RBA exhausted */ +#define ISREG_RBAE 0x0010 /* RBA too short for received frame */ +#define ISREG_CRC 0x0008 /* CRC counter rolls over */ +#define ISREG_FAE 0x0004 /* FAE counter rolls over */ +#define ISREG_MP 0x0002 /* MP counter rolls over */ +#define ISREG_RFO 0x0001 /* Rx FIFO overflows */ + +#define SONIC_UTDA 0x0c /* current transmit descr address */ +#define SONIC_CTDA 0x0e + +#define SONIC_URDA 0x1a /* current receive descr address */ +#define SONIC_CRDA 0x1c + +#define SONIC_CRBA0 0x1e /* current receive buffer address */ +#define SONIC_CRBA1 0x20 + +#define SONIC_RBWC0 0x22 /* word count in receive buffer */ +#define SONIC_RBWC1 0x24 + +#define SONIC_EOBC 0x26 /* minimum space to be free in RBA */ + +#define SONIC_URRA 0x28 /* upper address of CDA & Recv Area */ + +#define SONIC_RSA 0x2a /* start of receive resource area */ + +#define SONIC_REA 0x2c /* end of receive resource area */ + +#define SONIC_RRP 0x2e /* resource read pointer */ + +#define SONIC_RWP 0x30 /* resource write pointer */ + +#define SONIC_CAMEPTR 0x42 /* CAM entry pointer */ + +#define SONIC_CAMADDR2 0x44 /* CAM address ports */ +#define SONIC_CAMADDR1 0x46 +#define SONIC_CAMADDR0 0x48 + +#define SONIC_CAMPTR 0x4c /* lower address of CDA */ + +#define SONIC_CAMCNT 0x4e /* # of CAM descriptors to load */ + +/* Data Configuration Register 2 */ + +#define SONIC_DCREG2 0x7e +#define DCREG2_EXPO3 0x8000 /* extended programmable outputs */ +#define DCREG2_EXPO2 0x4000 +#define DCREG2_EXPO1 0x2000 +#define DCREG2_EXPO0 0x1000 +#define DCREG2_HD 0x0800 /* heartbeat disable */ +#define DCREG2_JD 0x0200 /* jabber timer disable */ +#define DCREG2_AUTO 0x0100 /* enable AUI/TP auto selection */ +#define DCREG2_XWRAP 0x0040 /* TP transceiver loopback */ +#define DCREG2_PH 0x0010 /* HOLD request timing */ +#define DCREG2_PCM 0x0004 /* packet compress when matched */ +#define DCREG2_PCNM 0x0002 /* packet compress when not matched */ +#define DCREG2_RJCM 0x0001 /* inverse packet match via CAM */ + +/* Board Control Register: Enable RAM, Interrupts... */ + +#define BCMREG 0x80 +#define BCMREG_RAMEN 0x80 /* switch over to RAM */ +#define BCMREG_IPEND 0x40 /* interrupt pending ? */ +#define BCMREG_RESET 0x08 /* reset board */ +#define BCMREG_16BIT 0x04 /* adapter in 16-bit slot */ +#define BCMREG_RAMWIN 0x02 /* enable RAM window */ +#define BCMREG_IEN 0x01 /* interrupt enable */ + +/* MAC Address PROM */ + +#define MACADDRPROM 0x92 + +/* structure of a CAM entry */ + +typedef struct { + u32 index; /* pointer into CAM area */ + u32 addr0; /* address part (bits 0..15 used) */ + u32 addr1; + u32 addr2; +} camentry_t; + +/* structure of a receive resource */ + +typedef struct { + u32 startlo; /* start address (bits 0..15 used) */ + u32 starthi; + u32 cntlo; /* size in 16-bit quantities */ + u32 cnthi; +} rra_t; + +/* structure of a receive descriptor */ + +typedef struct { + u32 status; /* packet status */ + u32 length; /* length in bytes */ + u32 startlo; /* start address */ + u32 starthi; + u32 seqno; /* frame sequence */ + u32 link; /* pointer to next descriptor */ + /* bit 0 = EOL */ + u32 inuse; /* !=0 --> free for SONIC to write */ +} rda_t; + +/* structure of a transmit descriptor */ + +typedef struct { + u32 status; /* transmit status */ + u32 config; /* value for TCR */ + u32 length; /* total length */ + u32 fragcount; /* number of fragments */ + u32 startlo; /* start address of fragment */ + u32 starthi; + u32 fraglength; /* length of this fragment */ + /* more address/length triplets may */ + /* follow here */ + u32 link; /* pointer to next descriptor */ + /* bit 0 = EOL */ +} tda_t; + +#endif /* _IBM_LANA_DRIVER_ */ + +extern int ibmlana_probe(struct IBMLANA_NETDEV *); + + +#endif /* _IBM_LANA_INCLUDE_ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ioc3-eth.c linux.ac/drivers/net/ioc3-eth.c --- linux.vanilla/drivers/net/ioc3-eth.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/ioc3-eth.c Mon May 29 19:29:10 2000 @@ -38,7 +38,6 @@ * - Free rings and buffers when closing or before re-initializing rings. * - Handle allocation failures in ioc3_alloc_skb() more gracefully. * - Handle allocation failures in ioc3_init_rings(). - * - Maybe implement private_ioctl(). * - Use prefetching for large packets. What is a good lower limit for * prefetching? * - We're probably allocating a bit too much memory. @@ -75,6 +74,17 @@ /* 32 RX buffers. This is tunable in the range of 16 <= x < 512. */ #define RX_BUFFS 32 +/* Private ioctls that de facto are well known and used for examply + by mii-tool. */ +#define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Read from current PHY */ +#define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read any PHY register */ +#define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write any PHY register */ + +/* These exist in other drivers; we don't use them at this time. */ +#define SIOCGPARAMS (SIOCDEVPRIVATE+3) /* Read operational parameters */ +#define SIOCSPARAMS (SIOCDEVPRIVATE+4) /* Set operational parameters */ + +static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void ioc3_set_multicast_list(struct net_device *dev); static int ioc3_open(struct net_device *dev); static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -97,6 +107,7 @@ int rx_pi; /* RX producer index */ int tx_ci; /* TX consumer index */ int tx_pi; /* TX producer index */ + int txqlen; spinlock_t ioc3_lock; }; @@ -124,17 +135,6 @@ #define BARRIER() \ __asm__("sync" ::: "memory") -/* This El Cheapo implementatin of TX_BUFFS_AVAIL may leave on entry unused. - Since the TX ring has 128 entries which is fairly large we don't care and - use this, more efficient implementation. */ -#define TX_BUFFS_AVAIL(ip) \ -({ \ - struct ioc3_private *_ip = (ip); \ - ((512 + _ip->tx_ci + 1) - _ip->tx_pi) & 511; \ -}) -//#undef TX_BUFFS_AVAIL -//#define TX_BUFFS_AVAIL(ip) (1) - #define IOC3_SIZE 0x100000 @@ -276,6 +276,8 @@ printk(".\n"); } +/* Caller must hold the ioc3_lock ever for MII readers. This is also + used to protect the transmitter side but it's low contention. */ static u16 mii_read(struct ioc3 *ioc3, int phy, int reg) { while (ioc3->micr & MICR_BUSY); @@ -385,8 +387,9 @@ } static inline void -ioc3_tx(struct ioc3_private *ip, struct ioc3 *ioc3) +ioc3_tx(struct net_device *dev, struct ioc3_private *ip, struct ioc3 *ioc3) { + unsigned long packets, bytes; int tx_entry, o_entry; struct sk_buff *skb; u32 etcir; @@ -395,14 +398,16 @@ etcir = ioc3->etcir; tx_entry = (etcir >> 7) & 127; o_entry = ip->tx_ci; + packets = 0; + bytes = 0; while (o_entry != tx_entry) { ioc3->eisr = EISR_TXEXPLICIT; /* Ack */ ioc3->eisr; /* Flush */ + packets++; + bytes += skb->len; skb = ip->tx_skbs[o_entry]; - ip->stats.tx_packets++; - ip->stats.tx_bytes += skb->len; dev_kfree_skb_irq(skb); ip->tx_skbs[o_entry] = NULL; @@ -411,6 +416,14 @@ etcir = ioc3->etcir; /* More pkts sent? */ tx_entry = (etcir >> 7) & 127; } + + ip->stats.tx_packets += packets; + ip->stats.tx_bytes += bytes; + ip->txqlen -= packets; + + if (ip->txqlen < 128) + netif_wake_queue(dev); + ip->tx_ci = o_entry; spin_unlock(&ip->ioc3_lock); } @@ -454,24 +467,20 @@ ioc3_rx(dev, ip, ioc3); } if (eisr & EISR_TXEXPLICIT) { - ioc3_tx(ip, ioc3); + ioc3_tx(dev, ip, ioc3); } if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) { ioc3_error(dev, ip, ioc3, eisr); } - if ((TX_BUFFS_AVAIL(ip) >= 0) && netif_queue_stopped(dev)) { - netif_wake_queue(dev); - } - __cli(); ioc3->eier = eier; return; } -int -ioc3_eth_init(struct net_device *dev, struct ioc3_private *p, struct ioc3 *ioc3) +int ioc3_eth_init(struct net_device *dev, struct ioc3_private *ip, + struct ioc3 *ioc3) { u16 word, mii0, mii_status, mii2, mii3, mii4; u32 vendor, model, rev; @@ -482,6 +491,7 @@ udelay(4); /* Give it time ... */ ioc3->emcr = 0; + spin_lock_irq(&ip->ioc3_lock); phy = -1; for (i = 0; i < 32; i++) { word = mii_read(ioc3, i, 2); @@ -491,10 +501,11 @@ } } if (phy == -1) { + spin_unlock_irq(&ip->ioc3_lock); printk("Didn't find a PHY, goodbye.\n"); return -ENODEV; } - p->phy = phy; + ip->phy = phy; mii0 = mii_read(ioc3, phy, 0); mii_status = mii_read(ioc3, phy, 1); @@ -512,8 +523,13 @@ /* Autonegotiate 100mbit and fullduplex. */ mii_write(ioc3, phy, 0, mii0 | 0x3100); - mdelay(1000); + + spin_unlock_irq(&ip->ioc3_lock); + mdelay(1000); /* XXX Yikes XXX */ + spin_lock_irq(&ip->ioc3_lock); + mii_status = mii_read(ioc3, phy, 1); + spin_unlock_irq(&ip->ioc3_lock); return 0; /* XXX */ } @@ -629,6 +645,7 @@ ioc3_init_rings(dev, ip, ioc3); spin_lock_init(&ip->ioc3_lock); + ip->txqlen = 0; /* Misc registers */ ioc3->erbar = 0; @@ -644,13 +661,14 @@ //ioc3->erpir = ERPIR_ARM; /* The IOC3-specific entries in the device structure. */ - dev->open = &ioc3_open; - dev->hard_start_xmit = &ioc3_start_xmit; + dev->open = ioc3_open; + dev->hard_start_xmit = ioc3_start_xmit; dev->tx_timeout = ioc3_timeout; dev->watchdog_timeo = (400 * HZ) / 1000; - dev->stop = &ioc3_close; - dev->get_stats = &ioc3_get_stats; - dev->set_multicast_list = &ioc3_set_multicast_list; + dev->stop = ioc3_close; + dev->get_stats = ioc3_get_stats; + dev->do_ioctl = ioc3_ioctl; + dev->set_multicast_list = ioc3_set_multicast_list; } int @@ -664,7 +682,11 @@ return 0; initialized++; - nid = get_nasid(); +#if 0 + nid = get_nasid(); /* Never assume we are on master cpu */ +#else + nid = 0; +#endif ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; ioc3_probe1(dev, ioc3); @@ -693,7 +715,7 @@ ioc3->eier = EISR_RXTIMERINT | EISR_TXEXPLICIT | /* Interrupts ... */ EISR_RXMEMERR | EISR_TXMEMERR; - netif_wake_queue(dev); + netif_start_queue(dev); restore_flags(flags); MOD_INC_USE_COUNT; @@ -711,11 +733,8 @@ struct ioc3_etxd *desc; int produce; - if (!TX_BUFFS_AVAIL(ip)) { - return 1; - } - spin_lock_irq(&ip->ioc3_lock); + data = (unsigned long) skb->data; len = skb->len; @@ -759,8 +778,11 @@ ip->tx_pi = produce; ioc3->etpir = produce << 7; /* Fire ... */ - if (TX_BUFFS_AVAIL(ip)) - netif_wake_queue(dev); + ip->txqlen++; + + if (ip->txqlen > 127) + netif_stop_queue(dev); + spin_unlock_irq(&ip->ioc3_lock); return 0; @@ -853,6 +875,40 @@ return temp; } +/* Provide ioctl() calls to examine the MII xcvr state. */ +static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct ioc3_private *ip = (struct ioc3_private *) dev->priv; + u16 *data = (u16 *)&rq->ifr_data; + struct ioc3 *ioc3 = ip->regs; + int phy = ip->phy; + + switch (cmd) { + case SIOCGMIIPHY: /* Get the address of the PHY in use. */ + if (phy == -1) + return -ENODEV; + data[0] = phy; + return 0; + + case SIOCGMIIREG: /* Read any PHY register. */ + spin_lock_irq(&ip->ioc3_lock); + data[3] = mii_read(ioc3, data[0], data[1]); + spin_unlock_irq(&ip->ioc3_lock); + return 0; + + case SIOCSMIIREG: /* Write any PHY register. */ + spin_lock_irq(&ip->ioc3_lock); + mii_write(ioc3, data[0], data[1], data[2]); + spin_unlock_irq(&ip->ioc3_lock); + return 0; + + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} + static void ioc3_set_multicast_list(struct net_device *dev) { struct dev_mc_list *dmi = dev->mc_list; @@ -905,6 +961,8 @@ struct pci_dev *dev = NULL; while ((dev = pci_find_device(PCI_VENDOR_ID_SGI, 0x0003, dev))) { + if (pci_enable_device(dev)) + continue; ioc3_init(&p, dev); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/irda/Makefile linux.ac/drivers/net/irda/Makefile --- linux.vanilla/drivers/net/irda/Makefile Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/irda/Makefile Sat May 27 15:29:39 2000 @@ -52,22 +52,6 @@ endif endif -ifeq ($(CONFIG_TOSHIBA_FIR),y) -L_OBJS += toshoboe.o -else - ifeq ($(CONFIG_TOSHIBA_FIR),m) - M_OBJS += toshoboe.o - endif -endif - -ifeq ($(CONFIG_TOSHIBA_FIR),y) -L_OBJS += toshoboe.o -else - ifeq ($(CONFIG_TOSHIBA_FIR),m) - M_OBJS += toshoboe.o - endif -endif - ifeq ($(CONFIG_SMC_IRCC_FIR),y) L_OBJS += smc-ircc.o LX_OBJS += irport.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/irda/toshoboe.c linux.ac/drivers/net/irda/toshoboe.c --- linux.vanilla/drivers/net/irda/toshoboe.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/irda/toshoboe.c Fri May 26 14:36:51 2000 @@ -717,7 +717,7 @@ self->open = 0; self->stopped = 0; self->pdev = pci_dev; - self->base = pci_dev->resource[0].start; + self->base = pci_resource_start (pci_dev, 0); self->io.sir_base = self->base; self->io.irq = pci_dev->irq; @@ -900,7 +900,6 @@ static void toshoboe_wakeup (struct toshoboe_cb *self) { - struct net_device *dev = self->netdev; unsigned long flags; if (!self->stopped) @@ -952,36 +951,26 @@ struct pci_dev *pci_dev = NULL; int found = 0; - do - { - pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA, - PCI_DEVICE_ID_FIR701, pci_dev); - if (pci_dev) - { + while ((pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA, + PCI_DEVICE_ID_FIR701, pci_dev)) != NULL) { + if (pci_enable_device(pci_dev)) + continue; printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n", - pci_dev->resource[0].start, + pci_resource_start (pci_dev, 0), pci_dev->irq); if (!toshoboe_open (pci_dev)) found++; - } - - } - while (pci_dev); - + } if (found) - { return 0; - } return -ENODEV; } -#ifdef MODULE -static void -toshoboe_cleanup (void) +static void __exit toshoboe_cleanup (void) { int i; @@ -997,19 +986,8 @@ } - -int -init_module (void) -{ - return toshoboe_init (); -} - - -void -cleanup_module (void) -{ - toshoboe_cleanup (); -} - - +#ifdef MODULE +module_init(toshoboe_init); #endif +module_exit(toshoboe_cleanup); + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/lance.c linux.ac/drivers/net/lance.c --- linux.vanilla/drivers/net/lance.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/lance.c Fri May 26 14:36:51 2000 @@ -361,7 +361,6 @@ lance_need_isa_bounce_buffers = 0; #if defined(CONFIG_PCI) - if (pci_present()) { struct pci_dev *pdev = NULL; if (lance_debug > 1) @@ -369,20 +368,12 @@ while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) { unsigned int pci_ioaddr; - unsigned short pci_command; + if (pci_enable_device(pdev)) + continue; + pci_set_master(pdev); pci_irq_line = pdev->irq; - 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 ) - */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - if ( ! (pci_command & PCI_COMMAND_MASTER)) { - printk("PCI Master Bit has not been set. Setting...\n"); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - } + pci_ioaddr = pci_resource_start (pdev, 0); printk("Found PCnet/PCI at %#x, irq %d.\n", pci_ioaddr, pci_irq_line); result = lance_probe1(dev, pci_ioaddr, pci_irq_line, 0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/lne390.c linux.ac/drivers/net/lne390.c --- linux.vanilla/drivers/net/lne390.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/lne390.c Thu Jun 8 15:02:12 2000 @@ -107,13 +107,13 @@ if (ioaddr > 0x1ff) /* Check a single specified location. */ return lne390_probe1(dev, ioaddr); else if (ioaddr > 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; if (!EISA_bus) { #if LNE390_DEBUG & LNE390_D_PROBE printk("lne390-debug: Not an EISA bus. Not probing high ports.\n"); #endif - return ENXIO; + return -ENXIO; } /* EISA spec allows for up to 16 slots, but 8 is typical. */ @@ -124,7 +124,7 @@ return 0; } - return ENODEV; + return -ENODEV; } int __init lne390_probe1(struct net_device *dev, int ioaddr) @@ -144,7 +144,7 @@ /* Check the EISA ID of the card. */ eisa_id = inl(ioaddr + LNE390_ID_PORT); if ((eisa_id != LNE390_ID0) && (eisa_id != LNE390_ID1)) { - return ENODEV; + return -ENODEV; } revision = (eisa_id >> 24) & 0x01; /* 0 = rev A, 1 rev B */ @@ -158,13 +158,10 @@ for(i = 0; i < ETHER_ADDR_LEN; i++) printk(" %02x", inb(ioaddr + LNE390_SA_PROM + i)); printk(" (invalid prefix).\n"); - return ENODEV; + return -ENODEV; } #endif - if (load_8390_module("lne390.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk("lne390.c: Passed a NULL device.\n"); @@ -198,7 +195,7 @@ printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } if (dev->mem_start == 0) { @@ -231,7 +228,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EINVAL; + return -EINVAL; } dev->mem_start = (unsigned long)ioremap(dev->mem_start, LNE390_STOP_PG*0x100); if (dev->mem_start == 0) { @@ -241,7 +238,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } ei_status.reg0 = 1; /* Use as remap flag */ printk("lne390.c: remapped %dkB card memory to virtual address %#lx\n", @@ -393,6 +390,9 @@ { int this_dev, found = 0; + if (load_8390_module("lne390.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) { struct net_device *dev = &dev_lne[this_dev]; dev->irq = irq[this_dev]; @@ -404,14 +404,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -431,7 +430,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/mac89x0.c linux.ac/drivers/net/mac89x0.c --- linux.vanilla/drivers/net/mac89x0.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/mac89x0.c Sat Jun 10 22:05:32 2000 @@ -180,14 +180,14 @@ unsigned short sig; if (once_is_enough) - return ENODEV; + return -ENODEV; once_is_enough = 1; /* We might have to parameterize this later */ slot = 0xE; /* Get out now if there's a real NuBus card in slot E */ if (nubus_find_slot(slot, NULL) != NULL) - return ENODEV; + return -ENODEV; /* The pseudo-ISA bits always live at offset 0x300 (gee, wonder why...) */ @@ -204,13 +204,13 @@ restore_flags(flags); if (!card_present) - return ENODEV; + return -ENODEV; } writew(0, ioaddr + ADD_PORT); sig = readw(ioaddr + DATA_PORT); if (sig != swab16(CHIP_EISA_ID_SIG)) - return ENODEV; + return -ENODEV; /* Initialize the net_device structure. */ if (dev->priv == NULL) { @@ -254,7 +254,7 @@ /* Try to read the MAC address */ if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) { printk("\nmac89x0: No EEPROM, giving up now.\n"); - return ENODEV; + return -ENODEV; } else { for (i = 0; i < ETH_ALEN; i += 2) { /* Big-endian (why??!) */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/myri_sbus.c linux.ac/drivers/net/myri_sbus.c --- linux.vanilla/drivers/net/myri_sbus.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/myri_sbus.c Sat Jun 10 22:05:32 2000 @@ -982,7 +982,7 @@ mp->reg_size, "MyriCOM Regs"); if (!mp->regs) { printk("MyriCOM: Cannot map MyriCOM registers.\n"); - return ENODEV; + return -ENODEV; } mp->lanai = (unsigned short *) (mp->regs + (256 * 1024)); mp->lanai3 = (unsigned int *) mp->lanai; @@ -1059,7 +1059,7 @@ if (request_irq(dev->irq, &myri_interrupt, SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) { printk("MyriCOM: Cannot register interrupt handler.\n"); - return ENODEV; + return -ENODEV; } DET(("ether_setup()\n")); @@ -1109,7 +1109,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; for_each_sbus(bus) { @@ -1125,7 +1125,7 @@ } } if (!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ne.c linux.ac/drivers/net/ne.c --- linux.vanilla/drivers/net/ne.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/ne.c Mon Jun 5 19:20:11 2000 @@ -195,7 +195,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return ne_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; #ifdef CONFIG_PCI /* Then look for any installed PCI clones */ @@ -218,7 +218,7 @@ } #endif - return ENODEV; + return -ENODEV; } #endif @@ -232,7 +232,9 @@ unsigned int pci_ioaddr; while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) { - pci_ioaddr = pdev->resource[0].start; + if (pci_enable_device(pdev)) + continue; + pci_ioaddr = pci_resource_start (pdev, 0); /* Avoid already found cards from previous calls */ if (check_region(pci_ioaddr, NE_IO_EXTENT)) continue; @@ -309,7 +311,7 @@ static unsigned version_printed = 0; if (reg0 == 0xFF) - return ENODEV; + return -ENODEV; /* Do a preliminary verification that we have a 8390. */ { @@ -322,13 +324,10 @@ if (inb_p(ioaddr + EN0_COUNTER0) != 0) { outb_p(reg0, ioaddr); outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */ - return ENODEV; + return -ENODEV; } } - if (load_8390_module("ne.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { @@ -364,7 +363,7 @@ break; } else { printk(" not found (no reset ack).\n"); - return ENODEV; + return -ENODEV; } } @@ -466,11 +465,11 @@ { printk(" not found (invalid signature %2.2x %2.2x).\n", SA_prom[14], SA_prom[15]); - return ENXIO; + return -ENXIO; } #else printk(" not found.\n"); - return ENXIO; + return -ENXIO; #endif } @@ -496,7 +495,7 @@ if (! dev->irq) { printk(" failed to detect IRQ line.\n"); - return EAGAIN; + return -EAGAIN; } /* Allocate dev->priv and fill in 8390 specific dev fields. */ @@ -516,7 +515,7 @@ printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } } dev->base_addr = ioaddr; @@ -837,6 +836,9 @@ { int this_dev, found = 0; + if (load_8390_module("ne.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { struct net_device *dev = &dev_ne[this_dev]; dev->irq = irq[this_dev]; @@ -848,16 +850,15 @@ continue; } if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } if (io[this_dev] != 0) printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); else printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for ISA cards.\n"); + unload_8390_module(); return -ENXIO; } - lock_8390_module(); return 0; } @@ -878,7 +879,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ne2.c linux.ac/drivers/net/ne2.c --- linux.vanilla/drivers/net/ne2.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/ne2.c Thu Jun 8 15:02:56 2000 @@ -171,7 +171,7 @@ return ne2_probe1(dev, current_mca_slot); } } - return ENODEV; + return -ENODEV; } @@ -222,7 +222,7 @@ POS = mca_read_stored_pos(slot, 2); if(!(POS % 2)) { printk(" disabled.\n"); - return ENODEV; + return -ENODEV; } i = (POS & 0xE)>>1; @@ -245,7 +245,7 @@ outb(0x21, base_addr + NE_CMD); if (inb(base_addr + NE_CMD) != 0x21) { printk("NE/2 adapter not responding\n"); - return ENODEV; + return -ENODEV; } /* In the crynwr sources they do a RAM-test here. I skip it. I suppose @@ -266,7 +266,7 @@ while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2*HZ/100) { printk(" not found (no reset ack).\n"); - return ENODEV; + return -ENODEV; } outb_p(0xff, base_addr + EN0_ISR); /* Ack all intr. */ @@ -321,7 +321,7 @@ if (irqval) { printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, +irqval); - return EAGAIN; + return -EAGAIN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ne2k-pci.c linux.ac/drivers/net/ne2k-pci.c --- linux.vanilla/drivers/net/ne2k-pci.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/ne2k-pci.c Mon Jun 5 19:20:11 2000 @@ -242,11 +242,6 @@ outb(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ } - if (load_8390_module("ne2k-pci.c")) { - printk (KERN_ERR "ne2k-pci: cannot load 8390 module\n"); - goto err_out_free_netdev; - } - /* Read the 16 bytes of station address PROM. We must first initialize registers, similar to NS8390_init(eifdev, 0). We can't reliably read the SAPROM address without this. @@ -565,13 +560,18 @@ { int rc; - lock_8390_module(); + if (load_8390_module("ne2k-pci.c")) + return -ENOSYS; rc = pci_module_init (&ne2k_driver); /* XXX should this test CONFIG_HOTPLUG like pci_module_init? */ + + /* YYY No. If we're returning non-zero, we're being unloaded + * immediately. dwmw2 + */ if (rc <= 0) - unlock_8390_module(); + unload_8390_module(); return rc; } @@ -580,7 +580,7 @@ static void __exit ne2k_pci_cleanup(void) { pci_unregister_driver (&ne2k_driver); - unlock_8390_module(); + unload_8390_module(); } module_init(ne2k_pci_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ne3210.c linux.ac/drivers/net/ne3210.c --- linux.vanilla/drivers/net/ne3210.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/ne3210.c Thu Jun 8 16:39:27 2000 @@ -102,13 +102,13 @@ if (ioaddr > 0x1ff) /* Check a single specified location. */ return ne3210_probe1(dev, ioaddr); else if (ioaddr > 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; if (!EISA_bus) { #if NE3210_DEBUG & NE3210_D_PROBE printk("ne3210-debug: Not an EISA bus. Not probing high ports.\n"); #endif - return ENXIO; + return -ENXIO; } /* EISA spec allows for up to 16 slots, but 8 is typical. */ @@ -119,7 +119,7 @@ return 0; } - return ENODEV; + return -ENODEV; } int __init ne3210_probe1(struct net_device *dev, int ioaddr) @@ -140,7 +140,7 @@ /* Check the EISA ID of the card. */ eisa_id = inl(ioaddr + NE3210_ID_PORT); if (eisa_id != NE3210_ID) { - return ENODEV; + return -ENODEV; } @@ -153,13 +153,10 @@ for(i = 0; i < ETHER_ADDR_LEN; i++) printk(" %02x", inb(ioaddr + NE3210_SA_PROM + i)); printk(" (invalid prefix).\n"); - return ENODEV; + return -ENODEV; } #endif - if (load_8390_module("ne3210.c")) - return -ENOSYS; - /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { printk("ne3210.c: Passed a NULL device.\n"); @@ -194,7 +191,7 @@ printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } if (dev->mem_start == 0) { @@ -223,7 +220,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EINVAL; + return -EINVAL; } dev->mem_start = (unsigned long)ioremap(dev->mem_start, NE3210_STOP_PG*0x100); if (dev->mem_start == 0) { @@ -233,7 +230,7 @@ free_irq(dev->irq, dev); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } ei_status.reg0 = 1; /* Use as remap flag */ printk("ne3210.c: remapped %dkB card memory to virtual address %#lx\n", @@ -384,6 +381,9 @@ { int this_dev, found = 0; + if (load_8390_module("ne3210.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) { struct net_device *dev = &dev_ne3210[this_dev]; dev->irq = irq[this_dev]; @@ -395,14 +395,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "ne3210.c: No NE3210 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -422,7 +421,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/net_init.c linux.ac/drivers/net/net_init.c --- linux.vanilla/drivers/net/net_init.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/net_init.c Thu May 25 20:28:46 2000 @@ -115,14 +115,17 @@ * Allocate a name */ - if (dev->name[0] == '\0' || dev->name[0] == ' ') - { - if(dev_alloc_name(dev, mask)<0) - { - if(new_device) - kfree(dev); - return NULL; + if (dev->name[0] == '\0' || dev->name[0] == ' ') { + strcpy(dev->name, mask); + if (!netdev_boot_setup_check(dev)) { + if (dev_alloc_name(dev, mask)<0) { + if (new_device) + kfree(dev); + return NULL; + } } + } else { + netdev_boot_setup_check(dev); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ni52.c linux.ac/drivers/net/ni52.c --- linux.vanilla/drivers/net/ni52.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/ni52.c Thu Jun 8 15:03:58 2000 @@ -367,7 +367,7 @@ (inb(base_addr+NI52_MAGIC2) == NI52_MAGICVAL2)) return ni52_probe1(dev, base_addr); } else if (base_addr > 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; #ifdef MODULE printk("%s: no autoprobing allowed for modules.\n",dev->name); @@ -402,7 +402,7 @@ #endif dev->base_addr = base_addr; - return ENODEV; + return -ENODEV; } static int __init ni52_probe1(struct net_device *dev,int ioaddr) @@ -414,7 +414,7 @@ if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 || dev->dev_addr[2] != NI52_ADDR2) - return ENODEV; + return -ENODEV; printk("%s: NI5210 found at %#3lx, ",dev->name,dev->base_addr); @@ -428,12 +428,12 @@ if(size != 0x2000 && size != 0x4000) { printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n",dev->name,size); - return ENODEV; + return -ENODEV; } if(!check586(dev,(char *) dev->mem_start,size)) { printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size); - return ENODEV; + return -ENODEV; } #else if(dev->mem_start != 0) /* no auto-mem-probe */ @@ -443,7 +443,7 @@ size = 0x2000; /* check for 8K mem */ if(!check586(dev,(char *) dev->mem_start,size)) { printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start); - return ENODEV; + return -ENODEV; } } } @@ -455,7 +455,7 @@ { if(!memaddrs[i]) { printk("?memprobe, Can't find io-memory!\n"); - return ENODEV; + return -ENODEV; } dev->mem_start = memaddrs[i]; size = 0x2000; /* check for 8K mem */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/oaknet.c linux.ac/drivers/net/oaknet.c --- linux.vanilla/drivers/net/oaknet.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/oaknet.c Mon Jun 5 19:20:11 2000 @@ -144,16 +144,6 @@ } /* - * We're dependent on the 8390 generic driver module, make - * sure its symbols are loaded. - */ - - if (load_8390_module("oaknet.c")) { - release_region(dev->base_addr, OAKNET_IO_SIZE); - return (-ENOSYS); - } - - /* * We're not using the old-style probing API, so we have to allocate * our own device structure. */ @@ -676,13 +666,21 @@ { int status; + /* + * We're dependent on the 8390 generic driver module, make + * sure its symbols are loaded. + */ + + if (load_8390_module("oaknet.c")) + return (-ENOSYS); + if (oaknet_devs != NULL) return (-EBUSY); status = oaknet_init() - if (status == 0) - lock_8390_module(); + if (status != 0) + unload_8390_module(); return (status); } @@ -706,7 +704,7 @@ oaknet_devs = NULL; - unlock_8390_module(); + unload_8390_module(); } module_init(oaknet_init_module); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/pcmcia/Config.in linux.ac/drivers/net/pcmcia/Config.in --- linux.vanilla/drivers/net/pcmcia/Config.in Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/pcmcia/Config.in Sat May 27 22:03:39 2000 @@ -21,12 +21,12 @@ tristate ' Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP fi - bool 'Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO + bool ' Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO if [ "$CONFIG_NET_PCMCIA_RADIO" = "y" ]; then - dep_tristate ' Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA - dep_tristate ' Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA - dep_tristate ' AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA - dep_tristate ' Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA + dep_tristate ' Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA + dep_tristate ' Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA + dep_tristate ' AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA + dep_tristate ' Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA fi fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/pcnet32.c linux.ac/drivers/net/pcnet32.c --- linux.vanilla/drivers/net/pcnet32.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/pcnet32.c Fri May 26 14:36:51 2000 @@ -311,21 +311,6 @@ int (*probe1) (unsigned long, unsigned char, int, int, struct pci_dev *); }; -static struct pcnet32_pci_id_info pcnet32_tbl[] = { - { "AMD PCnetPCI series", - PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0, 0, - PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, - pcnet32_probe1}, - { "AMD PCnetPCI series (IBM)", - PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, - PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, - pcnet32_probe1}, - { "AMD PCnetHome series", - PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PCNETHOME, 0, 0, - PCI_USES_IO|PCI_USES_MASTER, PCNET32_TOTAL_SIZE, - pcnet32_probe1}, - {0,} -}; /* * PCI device identifiers for "new style" Linux PCI Device Drivers @@ -751,7 +736,7 @@ } if (pcnet32_debug > 0) - printk(KERN_INFO, version); + printk(KERN_INFO "%s", version); /* The PCNET32-specific entries in the device structure. */ dev->open = &pcnet32_open; @@ -1257,8 +1242,7 @@ lp->stats.rx_errors++; } else { int rx_in_place = 0; - dma_addr_t rx_dma_addr = lp->rx_dma_addr[entry]; - + if (pkt_len > rx_copybreak) { struct sk_buff *newskb; @@ -1524,7 +1508,7 @@ /* find the PCI devices */ #define USE_PCI_REGISTER_DRIVER #ifdef USE_PCI_REGISTER_DRIVER - if (err = pci_module_init(&pcnet32_driver) < 0 ) + if ((err = pci_module_init(&pcnet32_driver)) < 0 ) return err; #else { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/plip.c linux.ac/drivers/net/plip.c --- linux.vanilla/drivers/net/plip.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/plip.c Thu Jun 8 16:36:58 2000 @@ -1301,10 +1301,67 @@ static struct net_device *dev_plip[PLIP_MAX] = { NULL, }; +static int inline +plip_searchfor(int list[], int a) +{ + int i; + for (i = 0; i < PLIP_MAX && list[i] != -1; i++) { + if (list[i] == a) return 1; + } + return 0; +} + +/* plip_attach() is called (by the parport code) when a port is + * available to use. */ +static void plip_attach (struct parport *port) +{ + static int i = 0; + + if ((parport[0] == -1 && (!timid || !port->devices)) || + plip_searchfor(parport, port->number)) { + if (i == PLIP_MAX) { + printk(KERN_ERR "plip: too many devices\n"); + return; + } + dev_plip[i] = kmalloc(sizeof(struct net_device), + GFP_KERNEL); + if (!dev_plip[i]) { + printk(KERN_ERR "plip: memory squeeze\n"); + return; + } + memset(dev_plip[i], 0, sizeof(struct net_device)); + sprintf(dev_plip[i]->name, "plip%d", i); + dev_plip[i]->priv = port; + if (plip_init_dev(dev_plip[i],port) || + register_netdev(dev_plip[i])) { + kfree(dev_plip[i]->name); + kfree(dev_plip[i]); + dev_plip[i] = NULL; + } else { + i++; + } + } +} + +/* plip_detach() is called (by the parport code) when a port is + * no longer available to use. */ +static void plip_detach (struct parport *port) +{ + /* Nothing to do */ +} + +static struct parport_driver plip_driver = { + name: "plip", + attach: plip_attach, + detach: plip_detach +}; + static void __exit plip_cleanup_module (void) { int i; + parport_unregister_driver (&plip_driver); + for (i=0; i < PLIP_MAX; i++) { if (dev_plip[i]) { struct net_local *nl = @@ -1357,21 +1414,8 @@ #endif /* !MODULE */ -static int inline -plip_searchfor(int list[], int a) -{ - int i; - for (i = 0; i < PLIP_MAX && list[i] != -1; i++) { - if (list[i] == a) return 1; - } - return 0; -} - static int __init plip_init (void) { - struct parport *pb = parport_enumerate(); - int i=0; - if (parport[0] == -2) return 0; @@ -1380,38 +1424,11 @@ timid = 0; } - /* If the user feeds parameters, use them */ - while (pb) { - if ((parport[0] == -1 && (!timid || !pb->devices)) || - plip_searchfor(parport, pb->number)) { - if (i == PLIP_MAX) { - printk(KERN_ERR "plip: too many devices\n"); - break; - } - dev_plip[i] = kmalloc(sizeof(struct net_device), - GFP_KERNEL); - if (!dev_plip[i]) { - printk(KERN_ERR "plip: memory squeeze\n"); - break; - } - memset(dev_plip[i], 0, sizeof(struct net_device)); - sprintf(dev_plip[i]->name, "plip%d", i); - dev_plip[i]->priv = pb; - if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) { - kfree(dev_plip[i]->name); - kfree(dev_plip[i]); - dev_plip[i] = NULL; - } else { - i++; - } - } - pb = pb->next; - } - - if (i == 0) { - printk(KERN_INFO "plip: no devices registered\n"); - return -EIO; + if (parport_register_driver (&plip_driver)) { + printk (KERN_WARNING "plip: couldn't register driver\n"); + return 1; } + return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/ptifddi.c linux.ac/drivers/net/ptifddi.c --- linux.vanilla/drivers/net/ptifddi.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/ptifddi.c Sat Jun 10 22:05:32 2000 @@ -165,7 +165,7 @@ &sdep->resource[0], 0, sizeof(sturct dfddi_ram), "PTI FDDI DPRAM"); if(!pp->dpram) { printk("ptiFDDI: Cannot map DPRAM I/O area.\n"); - return ENODEV; + return -ENODEV; } /* Next, register 1 contains reset byte. */ @@ -173,7 +173,7 @@ &sdep->resource[1], 0, 1, "PTI FDDI RESET Byte"); if(!pp->reset) { printk("ptiFDDI: Cannot map RESET byte.\n"); - return ENODEV; + return -ENODEV; } /* Register 2 contains unreset byte. */ @@ -181,7 +181,7 @@ &sdep->resource[2], 0, 1, "PTI FDDI UNRESET Byte"); if(!pp->unreset) { printk("ptiFDDI: Cannot map UNRESET byte.\n"); - return ENODEV; + return -ENODEV; } /* Reset the card. */ @@ -191,7 +191,7 @@ i = pti_card_test(pp); if(i) { printk("ptiFDDI: Bootup card test fails.\n"); - return ENODEV; + return -ENODEV; } /* Clear DPRAM, start afresh. */ @@ -212,7 +212,7 @@ int cards = 0, v; if(called) - return ENODEV; + return -ENODEV; called++; for_each_sbus(bus) { @@ -228,7 +228,7 @@ } } if(!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/rcpci45.c linux.ac/drivers/net/rcpci45.c --- linux.vanilla/drivers/net/rcpci45.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/rcpci45.c Fri May 26 14:36:51 2000 @@ -205,7 +205,7 @@ !((pdev = pci_find_slot(pci_bus, pci_device_fn)))) break; pci_irq_line = pdev->irq; - pci_ioaddr = pdev->resource[0].start; + pci_ioaddr = pci_resource_start (pdev, 0); #ifdef RCDEBUG printk("rc: Found RedCreek PCI adapter\n"); @@ -214,6 +214,8 @@ printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr); #endif + if (pci_enable_device(pdev)) + break; pci_set_master(pdev); if (!RCfound_device(pci_ioaddr, pci_irq_line, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/rrunner.c linux.ac/drivers/net/rrunner.c --- linux.vanilla/drivers/net/rrunner.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/rrunner.c Fri May 26 14:36:51 2000 @@ -146,6 +146,9 @@ PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, pdev))) { + if (pci_enable_device(pdev)) + continue; + if (pdev == opdev) return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/rtl8129.c linux.ac/drivers/net/rtl8129.c --- linux.vanilla/drivers/net/rtl8129.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/rtl8129.c Tue May 30 15:27:15 2000 @@ -353,8 +353,12 @@ continue; pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->resource[0].start; + + ioaddr = pci_resource_start(pdev, 0); irq = pdev->irq; + + if (pci_enable_device(pdev)) + continue; if ((pci_tbl[chip_idx].flags & PCI_USES_IO) && check_region(ioaddr, pci_tbl[chip_idx].io_size)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/seeq8005.c linux.ac/drivers/net/seeq8005.c --- linux.vanilla/drivers/net/seeq8005.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/seeq8005.c Sat Jun 10 22:05:32 2000 @@ -119,7 +119,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return seeq8005_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; seeq8005_portlist[i]; i++) { int ioaddr = seeq8005_portlist[i]; @@ -129,7 +129,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -153,27 +153,27 @@ old_stat = inw(SEEQ_STATUS); /* read status register */ if (old_stat == 0xffff) - return ENODEV; /* assume that 0xffff == no device */ + return -ENODEV; /* assume that 0xffff == no device */ if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */ if (net_debug>1) { printk("seeq8005: reserved stat bits != 0x1800\n"); printk(" == 0x%04x\n",old_stat); } - return ENODEV; + return -ENODEV; } old_rear = inw(SEEQ_REA); if (old_rear == 0xffff) { outw(0,SEEQ_REA); if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */ - return ENODEV; + return -ENODEV; } } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */ if (net_debug>1) { printk("seeq8005: unused rear bits != 0xff00\n"); printk(" == 0x%04x\n",old_rear); } - return ENODEV; + return -ENODEV; } old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */ @@ -207,7 +207,7 @@ outw( old_stat, SEEQ_STATUS); outw( old_dmaar, SEEQ_DMAAR); outw( old_cfg1, SEEQ_CFG1); - return ENODEV; + return -ENODEV; } #endif @@ -309,7 +309,7 @@ if (irqval) { printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); - return EAGAIN; + return -EAGAIN; } } #endif @@ -356,7 +356,7 @@ if (irqval) { printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); - return EAGAIN; + return -EAGAIN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sis900.c linux.ac/drivers/net/sis900.c --- linux.vanilla/drivers/net/sis900.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/sis900.c Fri May 26 14:17:27 2000 @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.06.04 Feb 11 2000 + Revision: 1.07 Mar. 07 2000 Modified from the driver which is originally written by Donald Becker. @@ -18,6 +18,7 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Rev 1.07 Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring Rev 1.06.04 Feb. 11 2000 Jeff Garzik softnet and init for kernel 2.4 Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed @@ -69,17 +70,17 @@ char *card_name); enum { SIS_900 = 0, - SIS_7018 + SIS_7016 }; static char * card_names[] = { "SiS 900 PCI Fast Ethernet", "SiS 7016 PCI Fast Ethernet" }; -static struct pci_device_id sis900_pci_tbl [] __initdata = { +static struct pci_device_id sis900_pci_tbl [] __devinitdata = { {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7016}, {0,} }; MODULE_DEVICE_TABLE (pci, sis900_pci_tbl); @@ -123,6 +124,7 @@ unsigned int cur_phy; struct timer_list timer; /* Link status detection timer. */ + unsigned int cur_rx, dirty_rx; unsigned int cur_tx, dirty_tx; @@ -131,8 +133,8 @@ struct sk_buff *rx_skbuff[NUM_RX_DESC]; BufferDesc tx_ring[NUM_TX_DESC]; BufferDesc rx_ring[NUM_RX_DESC]; - unsigned int tx_full; /* The Tx queue is full. */ + unsigned int tx_full; /* The Tx queue is full. */ int LinkOn; }; @@ -175,7 +177,7 @@ return -ENODEV; } - pci_io_base = pci_dev->resource[0].start; + pci_io_base = pci_resource_start(pci_dev, 0); if (check_region(pci_io_base, SIS900_TOTAL_SIZE)) { printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%08x\n", pci_io_base); @@ -189,7 +191,7 @@ /* do the real low level jobs */ if (sis900_mac_probe(pci_dev, card_names[pci_id->driver_data]) == NULL) - return -1; + return -ENODEV; return 0; } @@ -197,7 +199,7 @@ static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name) { struct sis900_private *sis_priv; - long ioaddr = pci_dev->resource[0].start; + long ioaddr = pci_resource_start(pci_dev, 0); struct net_device *net_dev = NULL; int irq = pci_dev->irq; u16 signature; @@ -472,15 +474,16 @@ struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; long ioaddr = net_dev->base_addr; + MOD_INC_USE_COUNT; + /* Soft reset the chip. */ sis900_reset(net_dev); if (request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev)) { + MOD_DEC_USE_COUNT; return -EAGAIN; } - MOD_INC_USE_COUNT; - sis900_init_rxfilter(net_dev); sis900_init_tx_ring(net_dev); @@ -1256,8 +1259,7 @@ struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; unregister_netdev(net_dev); - release_region(net_dev->base_addr, - SIS900_TOTAL_SIZE); + release_region(net_dev->base_addr, SIS900_TOTAL_SIZE); kfree(sis_priv); kfree(net_dev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sk98lin/skge.c linux.ac/drivers/net/sk98lin/skge.c --- linux.vanilla/drivers/net/sk98lin/skge.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/sk98lin/skge.c Fri May 26 14:36:51 2000 @@ -369,24 +369,18 @@ if (!pci_present()) /* is PCI support present? */ return -ENODEV; - while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) - { - dev = NULL; - - if (pdev->vendor != PCI_VENDOR_ID_SYSKONNECT || - pdev->device != PCI_DEVICE_ID_SYSKONNECT_GE) { + while((pdev = pci_find_device(PCI_VENDOR_ID_SYSKONNECT, + PCI_DEVICE_ID_SYSKONNECT_GE, pdev)) != NULL) { + if (pci_enable_device(pdev)) continue; - } dev = init_etherdev(dev, sizeof(SK_AC)); - if (dev == NULL || dev->priv == NULL){ + if (dev == NULL) { printk(KERN_ERR "Unable to allocate etherdev " "structure!\n"); break; } - memset(dev->priv, 0, sizeof(SK_AC)); - pAC = dev->priv; pAC->PciDev = *pdev; pAC->PciDevId = pdev->device; @@ -412,7 +406,7 @@ pci_set_master(pdev); - base_address = pdev->resource[0].start; + base_address = pci_resource_start (pdev, 0); #ifdef SK_BIG_ENDIAN /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sk_g16.c linux.ac/drivers/net/sk_g16.c --- linux.vanilla/drivers/net/sk_g16.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/sk_g16.c Sat Jun 10 21:40:34 2000 @@ -556,11 +556,11 @@ return SK_probe(dev, base_addr); } - return ENODEV; /* Sorry, but on specified address NO SK_G16 */ + return -ENODEV; /* Sorry, but on specified address NO SK_G16 */ } else if (base_addr > 0) /* Don't probe at all */ { - return ENXIO; + return -ENXIO; } /* Autoprobe base_addr */ @@ -594,7 +594,7 @@ dev->base_addr = base_addr; /* Write back original base_addr */ - return ENODEV; /* Failed to find or init driver */ + return -ENODEV; /* Failed to find or init driver */ } /* End of SK_init */ @@ -752,7 +752,7 @@ { PRINTK(("## %s: We did not find SK_G16 at RAM location.\n", SK_NAME)); - return ENODEV; /* NO SK_G16 found */ + return -ENODEV; /* NO SK_G16 found */ } printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sk_mca.c linux.ac/drivers/net/sk_mca.c --- linux.vanilla/drivers/net/sk_mca.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/sk_mca.c Sat Jun 10 21:40:34 2000 @@ -62,14 +62,25 @@ implemented LANCE multicast filter Jun 6th, 1999 additions for Linux 2.2 - Aug 2nd, 1999 - small fixes (David Weinehall) + Dec 25th, 1999 + unfortunately there seem to be newer MC2+ boards that react + on IRQ 3/5/9/10 instead of 3/5/10/11, so we have to autoprobe + in questionable cases... + Dec 28th, 1999 + integrated patches from David Weinehall & Bill Wendling for 2.3 + kernels (isa_...functions). Things are defined in a way that + it still works with 2.0.x 8-) + Dec 30th, 1999 + added handling of the remaining interrupt conditions. That + should cure the spurious hangs. + Jan 30th, 2000 + newer kernels automatically probe more than one board, so the + 'startslot' as a variable is also needed here + June 1st, 2000 + added changes for recent 2.3 kernels *************************************************************************/ -#include -#include - #include #include #include @@ -84,6 +95,11 @@ #include #include +#ifdef MODULE +#include +#include +#endif + #include #include #include @@ -96,11 +112,11 @@ * have to pack all state info into the device struct! * ------------------------------------------------------------------------ */ -static char *MediaNames[Media_Count] = { - "10Base2", "10BaseT", "10Base5", "Unknown" }; +static char *MediaNames[Media_Count] = + { "10Base2", "10BaseT", "10Base5", "Unknown" }; -static unsigned char poly[] = { - 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, +static unsigned char poly[] = + { 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 }; @@ -111,14 +127,14 @@ /* dump parts of shared memory - only needed during debugging */ #ifdef DEBUG -static void dumpmem(struct net_device *dev, u32 start, u32 len) +static void dumpmem(struct SKMCA_NETDEV *dev, u32 start, u32 len) { int z; for (z = 0; z < len; z++) { if ((z & 15) == 0) printk("%04x:", z); - printk(" %02x", readb(dev->mem_start + start + z)); + printk(" %02x", SKMCA_READB(dev->mem_start + start + z)); if ((z & 15) == 15) printk("\n"); } @@ -133,7 +149,6 @@ do_gettimeofday(&tv); printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec); } - #endif /* deduce resources out of POS registers */ @@ -169,10 +184,10 @@ *irq = 5; break; case 8: - *irq = 10; + *irq = -10; break; case 12: - *irq = 11; + *irq = -11; break; } *medium = (pos2 >> 6) & 3; @@ -205,18 +220,37 @@ /* reset the whole board */ -static void ResetBoard(struct net_device *dev) +static void ResetBoard(struct SKMCA_NETDEV *dev) { skmca_priv *priv = (skmca_priv *) dev->priv; - writeb(CTRL_RESET_ON, priv->ctrladdr); + SKMCA_WRITEB(CTRL_RESET_ON, priv->ctrladdr); udelay(10); - writeb(CTRL_RESET_OFF, priv->ctrladdr); + SKMCA_WRITEB(CTRL_RESET_OFF, priv->ctrladdr); +} + +/* wait for LANCE interface to become not busy */ + +static int WaitLANCE(struct SKMCA_NETDEV *dev) +{ + skmca_priv *priv = (skmca_priv *) dev->priv; + int t = 0; + + while ((SKMCA_READB(priv->ctrladdr) & STAT_IO_BUSY) == + STAT_IO_BUSY) { + udelay(1); + if (++t > 1000) { + printk("%s: LANCE access timeout", dev->name); + return 0; + } + } + + return 1; } /* set LANCE register - must be atomic */ -static void SetLANCE(struct net_device *dev, u16 addr, u16 value) +static void SetLANCE(struct SKMCA_NETDEV *dev, u16 addr, u16 value) { skmca_priv *priv = (skmca_priv *) dev->priv; unsigned long flags; @@ -228,25 +262,25 @@ /* wait until no transfer is pending */ - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); + WaitLANCE(dev); /* transfer register address to RAP */ - writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, - priv->ctrladdr); - writew(addr, priv->ioregaddr); - writeb(IOCMD_GO, priv->cmdaddr); + SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, + priv->ctrladdr); + SKMCA_WRITEW(addr, priv->ioregaddr); + SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr); udelay(1); - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); + WaitLANCE(dev); /* transfer data to register */ - writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, - priv->ctrladdr); - writew(value, priv->ioregaddr); - writeb(IOCMD_GO, priv->cmdaddr); + SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, + priv->ctrladdr); + SKMCA_WRITEW(value, priv->ioregaddr); + SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr); udelay(1); - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); + WaitLANCE(dev); /* reenable interrupts */ @@ -255,7 +289,7 @@ /* get LANCE register */ -static u16 GetLANCE(struct net_device *dev, u16 addr) +static u16 GetLANCE(struct SKMCA_NETDEV *dev, u16 addr) { skmca_priv *priv = (skmca_priv *) dev->priv; unsigned long flags; @@ -268,25 +302,25 @@ /* wait until no transfer is pending */ - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); + WaitLANCE(dev); /* transfer register address to RAP */ - writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, - priv->ctrladdr); - writew(addr, priv->ioregaddr); - writeb(IOCMD_GO, priv->cmdaddr); + SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, + priv->ctrladdr); + SKMCA_WRITEW(addr, priv->ioregaddr); + SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr); udelay(1); - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); + WaitLANCE(dev); /* transfer data from register */ - writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, - priv->ctrladdr); - writeb(IOCMD_GO, priv->cmdaddr); + SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, + priv->ctrladdr); + SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr); udelay(1); - while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY); - res = readw(priv->ioregaddr); + WaitLANCE(dev); + res = SKMCA_READW(priv->ioregaddr); /* reenable interrupts */ @@ -297,7 +331,7 @@ /* build up descriptors in shared RAM */ -static void InitDscrs(struct net_device *dev) +static void InitDscrs(struct SKMCA_NETDEV *dev) { u32 bufaddr; @@ -314,11 +348,11 @@ descr.Flags = 0; descr.Len = 0xf000; descr.Status = 0; - isa_memcpy_toio(dev->mem_start + RAM_TXBASE + - (z * sizeof(LANCE_TxDescr)), - &descr, sizeof(LANCE_TxDescr)); - memset_io(dev->mem_start + bufaddr, 0, - RAM_BUFSIZE); + SKMCA_TOIO(dev->mem_start + RAM_TXBASE + + (z * sizeof(LANCE_TxDescr)), &descr, + sizeof(LANCE_TxDescr)); + SKMCA_SETIO(dev->mem_start + bufaddr, 0, + RAM_BUFSIZE); bufaddr += RAM_BUFSIZE; } } @@ -334,11 +368,11 @@ descr.Flags = RXDSCR_FLAGS_OWN; descr.MaxLen = -RAM_BUFSIZE; descr.Len = 0; - isa_memcpy_toio(dev->mem_start + RAM_RXBASE + - (z * sizeof(LANCE_RxDescr)), - &descr, sizeof(LANCE_RxDescr)); - isa_memset_io(dev->mem_start + bufaddr, 0, - RAM_BUFSIZE); + SKMCA_TOIO(dev->mem_start + RAM_RXBASE + + (z * sizeof(LANCE_RxDescr)), &descr, + sizeof(LANCE_RxDescr)); + SKMCA_SETIO(dev->mem_start + bufaddr, 0, + RAM_BUFSIZE); bufaddr += RAM_BUFSIZE; } } @@ -393,7 +427,7 @@ /* feed ready-built initialization block into LANCE */ -static void InitLANCE(struct net_device *dev) +static void InitLANCE(struct SKMCA_NETDEV *dev) { skmca_priv *priv = (skmca_priv *) dev->priv; @@ -423,8 +457,12 @@ /* we don't get ready until the LANCE has read the init block */ +#if (LINUX_VERSION_CODE >= 0x02032a) netif_stop_queue(dev); - +#else + dev->tbusy = 1; +#endif + /* let LANCE read the initialization block. LANCE is ready when we receive the corresponding interrupt. */ @@ -433,12 +471,16 @@ /* stop the LANCE so we can reinitialize it */ -static void StopLANCE(struct net_device *dev) +static void StopLANCE(struct SKMCA_NETDEV *dev) { /* can't take frames any more */ +#if (LINUX_VERSION_CODE >= 0x02032a) netif_stop_queue(dev); - +#else + dev->tbusy = 1; +#endif + /* disable interrupts, stop it */ SetLANCE(dev, LANCE_CSR0, CSR0_STOP); @@ -446,7 +488,7 @@ /* initialize card and LANCE for proper operation */ -static void InitBoard(struct net_device *dev) +static void InitBoard(struct SKMCA_NETDEV *dev) { LANCE_InitBlock block; @@ -462,8 +504,7 @@ block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29); block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29); - isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, - sizeof(block)); + SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block)); /* initialize LANCE. Implicitly sets up other structures in RAM. */ @@ -472,7 +513,7 @@ /* deinitialize card and LANCE */ -static void DeinitBoard(struct net_device *dev) +static void DeinitBoard(struct SKMCA_NETDEV *dev) { /* stop LANCE */ @@ -483,44 +524,97 @@ ResetBoard(dev); } +/* probe for device's irq */ + +static int ProbeIRQ(struct SKMCA_NETDEV *dev) +{ + unsigned long imaskval, njiffies, irq; + u16 csr0val; + + /* enable all interrupts */ + + imaskval = probe_irq_on(); + + /* initialize the board. Wait for interrupt 'Initialization done'. */ + + ResetBoard(dev); + InitBoard(dev); + + njiffies = jiffies + 100; + do { + csr0val = GetLANCE(dev, LANCE_CSR0); + } + while (((csr0val & CSR0_IDON) == 0) && (jiffies != njiffies)); + + /* turn of interrupts again */ + + irq = probe_irq_off(imaskval); + + /* if we found something, ack the interrupt */ + + if (irq) + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_IDON); + + /* back to idle state */ + + DeinitBoard(dev); + + return irq; +} + /* ------------------------------------------------------------------------ * interrupt handler(s) * ------------------------------------------------------------------------ */ -/* LANCE has read initializazion block -> start it */ +/* LANCE has read initialization block -> start it */ -static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0) +static u16 irqstart_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0) { /* now we're ready to transmit */ +#if (LINUX_VERSION_CODE >= 0x02032a) netif_wake_queue(dev); - +#else + dev->tbusy = 0; +#endif + /* reset IDON bit, start LANCE */ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT); return GetLANCE(dev, LANCE_CSR0); } +/* did we loose blocks due to a FIFO overrun ? */ + +static u16 irqmiss_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0) +{ + skmca_priv *priv = (skmca_priv *) dev->priv; + + /* update statistics */ + + priv->stat.rx_fifo_errors++; + + /* reset MISS bit */ + + SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_MISS); + return GetLANCE(dev, LANCE_CSR0); +} + /* receive interrupt */ -static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0) +static u16 irqrx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0) { skmca_priv *priv = (skmca_priv *) dev->priv; LANCE_RxDescr descr; unsigned int descraddr; - /* did we loose blocks due to a FIFO overrun ? */ - - if (oldcsr0 & CSR0_MISS) - priv->stat.rx_fifo_errors++; - /* run through queue until we reach a descriptor we do not own */ descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr)); while (1) { /* read descriptor */ - isa_memcpy_fromio(&descr, dev->mem_start + descraddr, - sizeof(LANCE_RxDescr)); + SKMCA_FROMIO(&descr, dev->mem_start + descraddr, + sizeof(LANCE_RxDescr)); /* if we reach a descriptor we do not own, we're done */ if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0) @@ -551,10 +645,9 @@ if (skb == NULL) priv->stat.rx_dropped++; else { - isa_memcpy_fromio(skb_put(skb, descr.Len), - dev->mem_start + - descr.LowAddr, - descr.Len); + SKMCA_FROMIO(skb_put(skb, descr.Len), + dev->mem_start + + descr.LowAddr, descr.Len); skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; @@ -571,8 +664,8 @@ descr.Flags |= RXDSCR_FLAGS_OWN; /* update descriptor in shared RAM */ - isa_memcpy_toio(dev->mem_start + descraddr, &descr, - sizeof(LANCE_RxDescr)); + SKMCA_TOIO(dev->mem_start + descraddr, &descr, + sizeof(LANCE_RxDescr)); /* go to next descriptor */ priv->nextrx++; @@ -591,7 +684,7 @@ /* transmit interrupt */ -static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0) +static u16 irqtx_handler(struct SKMCA_NETDEV *dev, u16 oldcsr0) { skmca_priv *priv = (skmca_priv *) dev->priv; LANCE_TxDescr descr; @@ -603,8 +696,8 @@ RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr)); while (priv->txbusy > 0) { /* read descriptor */ - isa_memcpy_fromio(&descr, dev->mem_start + descraddr, - sizeof(LANCE_TxDescr)); + SKMCA_FROMIO(&descr, dev->mem_start + descraddr, + sizeof(LANCE_TxDescr)); /* if the LANCE still owns this one, we've worked out all sent packets */ if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0) @@ -653,9 +746,15 @@ /* at least one descriptor is freed. Therefore we can accept a new one */ + /* inform upper layers we're in business again */ +#if (LINUX_VERSION_CODE >= 0x02032a) netif_wake_queue(dev); - +#else + dev->tbusy = 0; + mark_bh(NET_BH); +#endif + return oldcsr0; } @@ -663,7 +762,7 @@ static void irq_handler(int irq, void *device, struct pt_regs *regs) { - struct net_device *dev = (struct net_device *) device; + struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) device; u16 csr0val; /* read CSR0 to get interrupt cause */ @@ -675,6 +774,14 @@ if ((csr0val & CSR0_INTR) == 0) return; +#if (LINUX_VERSION_CODE >= 0x02032a) +#if 0 + set_bit(LINK_STATE_RXSEM, &dev->state); +#endif +#else + dev->interrupt = 1; +#endif + /* loop through the interrupt bits until everything is clear */ do { @@ -682,10 +789,28 @@ csr0val = irqstart_handler(dev, csr0val); if ((csr0val & CSR0_RINT) != 0) csr0val = irqrx_handler(dev, csr0val); + if ((csr0val & CSR0_MISS) != 0) + csr0val = irqmiss_handler(dev, csr0val); if ((csr0val & CSR0_TINT) != 0) csr0val = irqtx_handler(dev, csr0val); + if ((csr0val & CSR0_MERR) != 0) { + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_MERR); + csr0val = GetLANCE(dev, LANCE_CSR0); + } + if ((csr0val & CSR0_BABL) != 0) { + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_BABL); + csr0val = GetLANCE(dev, LANCE_CSR0); + } } while ((csr0val & CSR0_INTR) != 0); + +#if (LINUX_VERSION_CODE >= 0x02032a) +#if 0 + clear_bit(LINK_STATE_RXSEM, &dev->state); +#endif +#else + dev->interrupt = 0; +#endif } /* ------------------------------------------------------------------------ @@ -697,7 +822,7 @@ static int skmca_getinfo(char *buf, int slot, void *d) { int len = 0, i; - struct net_device *dev = (struct net_device *) d; + struct SKMCA_NETDEV *dev = (struct SKMCA_NETDEV *) d; skmca_priv *priv; /* can't say anything about an uninitialized device... */ @@ -728,7 +853,7 @@ /* open driver. Means also initialization and start of LANCE */ -static int skmca_open(struct net_device *dev) +static int skmca_open(struct SKMCA_NETDEV *dev) { int result; skmca_priv *priv = (skmca_priv *) dev->priv; @@ -745,8 +870,19 @@ dev->irq = priv->realirq; /* set up the card and LANCE */ + InitBoard(dev); + /* set up flags */ + +#if (LINUX_VERSION_CODE >= 0x02032a) + netif_start_queue(dev); +#else + dev->interrupt = 0; + dev->tbusy = 0; + dev->start = 0; +#endif + #ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -756,7 +892,7 @@ /* close driver. Shut down board and free allocated resources */ -static int skmca_close(struct net_device *dev) +static int skmca_close(struct SKMCA_NETDEV *dev) { /* turn off board */ DeinitBoard(dev); @@ -775,7 +911,7 @@ /* transmit a block. */ -static int skmca_tx(struct sk_buff *skb, struct net_device *dev) +static int skmca_tx(struct sk_buff *skb, struct SKMCA_NETDEV *dev) { skmca_priv *priv = (skmca_priv *) dev->priv; LANCE_TxDescr descr; @@ -783,8 +919,15 @@ int tmplen, retval = 0; unsigned long flags; - netif_stop_queue(dev); - + /* if we get called with a NULL descriptor, the Ethernet layer thinks + our card is stuck an we should reset it. We'll do this completely: */ + + if (skb == NULL) { + DeinitBoard(dev); + InitBoard(dev); + return 0; /* don't try to free the block here ;-) */ + } + /* is there space in the Tx queue ? If no, the upper layer gave us a packet in spite of us not being ready and is really in trouble. We'll do the dropping for him: */ @@ -796,8 +939,8 @@ /* get TX descriptor */ address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr)); - isa_memcpy_fromio(&descr, dev->mem_start + address, - sizeof(LANCE_TxDescr)); + SKMCA_FROMIO(&descr, dev->mem_start + address, + sizeof(LANCE_TxDescr)); /* enter packet length as 2s complement - assure minimum length */ tmplen = skb->len; @@ -813,15 +956,14 @@ unsigned int destoffs = 0, l = strlen(fill); while (destoffs < tmplen) { - isa_memcpy_toio(dev->mem_start + descr.LowAddr + - destoffs, fill, l); + SKMCA_TOIO(dev->mem_start + descr.LowAddr + + destoffs, fill, l); destoffs += l; } } /* do the real data copying */ - isa_memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, - skb->len); + SKMCA_TOIO(dev->mem_start + descr.LowAddr, skb->data, skb->len); /* hand descriptor over to LANCE - this is the first and last chunk */ descr.Flags = @@ -840,12 +982,19 @@ if (priv->nexttxput >= TXCOUNT) priv->nexttxput = 0; priv->txbusy++; - if (priv->txbusy < TXCOUNT) - netif_wake_queue(dev); + + /* are we saturated ? */ + + if (priv->txbusy >= TXCOUNT) +#if (LINUX_VERSION_CODE >= 0x02032a) + netif_stop_queue(dev); +#else + dev->tbusy = 1; +#endif /* write descriptor back to RAM */ - isa_memcpy_toio(dev->mem_start + address, &descr, - sizeof(LANCE_TxDescr)); + SKMCA_TOIO(dev->mem_start + address, &descr, + sizeof(LANCE_TxDescr)); /* if no descriptors were active, give the LANCE a hint to read it immediately */ @@ -855,24 +1004,31 @@ restore_flags(flags); -tx_done: + tx_done: + /* When did that change exactly ? */ + +#if LINUX_VERSION_CODE >= 0x020200 dev_kfree_skb(skb); +#else + dev_kfree_skb(skb, FREE_WRITE); +#endif return retval; } /* return pointer to Ethernet statistics */ -static struct enet_statistics *skmca_stats(struct net_device *dev) +static struct enet_statistics *skmca_stats(struct SKMCA_NETDEV *dev) { skmca_priv *priv = (skmca_priv *) dev->priv; + return &(priv->stat); } /* we don't support runtime reconfiguration, since an MCA card can be unambigously identified by its POS registers. */ -static int skmca_config(struct net_device *dev, struct ifmap *map) +static int skmca_config(struct SKMCA_NETDEV *dev, struct ifmap *map) { return 0; } @@ -880,7 +1036,7 @@ /* switch receiver mode. We use the LANCE's multicast filter to prefilter multicast addresses. */ -static void skmca_set_multicast_list(struct net_device *dev) +static void skmca_set_multicast_list(struct SKMCA_NETDEV *dev) { LANCE_InitBlock block; @@ -888,8 +1044,7 @@ StopLANCE(dev); /* ...then modify the initialization block... */ - isa_memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, - sizeof(block)); + SKMCA_FROMIO(&block, dev->mem_start + RAM_INITBASE, sizeof(block)); if (dev->flags & IFF_PROMISC) block.Mode |= LANCE_INIT_PROM; else @@ -909,8 +1064,7 @@ } } - isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, - sizeof(block)); + SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block)); /* ...then reinit LANCE with the correct flags */ InitLANCE(dev); @@ -920,13 +1074,9 @@ * hardware check * ------------------------------------------------------------------------ */ -#ifdef MODULE static int startslot; /* counts through slots when probing multiple devices */ -#else -#define startslot 0 /* otherwise a dummy, since there is only eth0 in-kern */ -#endif -int skmca_probe(struct net_device *dev) +int skmca_probe(struct SKMCA_NETDEV *dev) { int force_detect = 0; int junior, slot, i; @@ -937,7 +1087,7 @@ /* can't work without an MCA bus ;-) */ if (MCA_bus == 0) - return ENODEV; + return -ENODEV; /* start address of 1 --> forced detection */ @@ -957,7 +1107,7 @@ getaddrs(slot, junior, &base, &irq, &medium); -#if LINUX_VERSION_CODE >= 0x020200 +#if LINUX_VERSION_CODE >= 0x020300 /* slot already in use ? */ if (mca_is_adapter_used(slot)) { @@ -1015,7 +1165,6 @@ priv->ioregaddr = base + 0x3ff0; priv->ctrladdr = base + 0x3ff2; priv->cmdaddr = base + 0x3ff3; - priv->realirq = irq; priv->medium = medium; memset(&(priv->stat), 0, sizeof(struct enet_statistics)); @@ -1024,6 +1173,22 @@ dev->mem_start = base; dev->mem_end = base + 0x4000; + /* autoprobe ? */ + if (irq < 0) { + int nirq; + + printk + ("%s: ambigous POS bit combination, must probe for IRQ...\n", + dev->name); + nirq = ProbeIRQ(dev); + if (nirq <= 0) + printk("%s: IRQ probe failed, assuming IRQ %d", + dev->name, priv->realirq = -irq); + else + priv->realirq = nirq; + } else + priv->realirq = irq; + /* set methods */ dev->open = skmca_open; dev->stop = skmca_close; @@ -1039,7 +1204,7 @@ /* copy out MAC address */ for (i = 0; i < 6; i++) - dev->dev_addr[i] = readb(priv->macbase + (i << 1)); + dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1)); /* print config */ printk("%s: IRQ %d, memory %#lx-%#lx, " @@ -1053,9 +1218,7 @@ ResetBoard(dev); -#ifdef MODULE startslot = slot + 1; -#endif return 0; } @@ -1068,13 +1231,24 @@ #define DEVMAX 5 -static struct net_device moddevs[DEVMAX] = - { {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, -{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, -{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, -{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, -{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe} +#if (LINUX_VERSION_CODE >= 0x020369) +static struct SKMCA_NETDEV moddevs[DEVMAX] = + { {" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe} }; +#else +static char NameSpace[8 * DEVMAX]; +static struct SKMCA_NETDEV moddevs[DEVMAX] = + { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}, +{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe} +}; +#endif int irq = 0; int io = 0; @@ -1096,7 +1270,7 @@ void cleanup_module(void) { - struct net_device *dev; + struct SKMCA_NETDEV *dev; skmca_priv *priv; int z; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sk_mca.h linux.ac/drivers/net/sk_mca.h --- linux.vanilla/drivers/net/sk_mca.h Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/sk_mca.h Mon Jun 5 19:42:34 2000 @@ -3,172 +3,191 @@ #ifdef _SK_MCA_DRIVER_ +/* version-dependent functions/structures */ + +#if LINUX_VERSION_CODE >= 0x020318 +#define SKMCA_READB(addr) isa_readb(addr) +#define SKMCA_READW(addr) isa_readw(addr) +#define SKMCA_WRITEB(data, addr) isa_writeb(data, addr) +#define SKMCA_WRITEW(data, addr) isa_writew(data, addr) +#define SKMCA_TOIO(dest, src, len) isa_memcpy_toio(dest, src, len) +#define SKMCA_FROMIO(dest, src, len) isa_memcpy_fromio(dest, src, len) +#define SKMCA_SETIO(dest, val, len) isa_memset_io(dest, val, len) +#define SKMCA_NETDEV net_device +#else +#define SKMCA_READB(addr) readb(addr) +#define SKMCA_READW(addr) readw(addr) +#define SKMCA_WRITEB(data, addr) writeb(data, addr) +#define SKMCA_WRITEW(data, addr) writew(data, addr) +#define SKMCA_TOIO(dest, src, len) memcpy_toio(dest, src, len) +#define SKMCA_FROMIO(dest, src, len) memcpy_fromio(dest, src, len) +#define SKMCA_SETIO(dest, val, len) memset_io(dest, val, len) +#define SKMCA_NETDEV device +#endif + /* Adapter ID's */ #define SKNET_MCA_ID 0x6afd #define SKNET_JUNIOR_MCA_ID 0x6be9 /* media enumeration - defined in a way that it fits onto the MC2+'s POS registers... */ - -typedef enum {Media_10Base2, Media_10BaseT, - Media_10Base5, Media_Unknown, Media_Count} skmca_medium; + +typedef enum { Media_10Base2, Media_10BaseT, + Media_10Base5, Media_Unknown, Media_Count +} skmca_medium; /* private structure */ -typedef struct - { - unsigned int slot; /* MCA-Slot-# */ - unsigned int macbase; /* base address of MAC address PROM */ - unsigned int ioregaddr; /* address of I/O-register (Lo) */ - unsigned int ctrladdr; /* address of control/stat register */ - unsigned int cmdaddr; /* address of I/O-command register */ - int nextrx; /* index of next RX descriptor to - be read */ - int nexttxput; /* index of next free TX descriptor */ - int nexttxdone; /* index of next TX descriptor to - be finished */ - int txbusy; /* # of busy TX descriptors */ - struct enet_statistics stat; /* packet statistics */ - int realirq; /* memorizes actual IRQ, even when - currently not allocated */ - skmca_medium medium; /* physical cannector */ - } skmca_priv; +typedef struct { + unsigned int slot; /* MCA-Slot-# */ + unsigned int macbase; /* base address of MAC address PROM */ + unsigned int ioregaddr; /* address of I/O-register (Lo) */ + unsigned int ctrladdr; /* address of control/stat register */ + unsigned int cmdaddr; /* address of I/O-command register */ + int nextrx; /* index of next RX descriptor to + be read */ + int nexttxput; /* index of next free TX descriptor */ + int nexttxdone; /* index of next TX descriptor to + be finished */ + int txbusy; /* # of busy TX descriptors */ + struct enet_statistics stat; /* packet statistics */ + int realirq; /* memorizes actual IRQ, even when + currently not allocated */ + skmca_medium medium; /* physical cannector */ +} skmca_priv; /* card registers: control/status register bits */ -#define CTRL_ADR_DATA 0 /* Bit 0 = 0 ->access data register */ -#define CTRL_ADR_RAP 1 /* Bit 0 = 1 ->access RAP register */ -#define CTRL_RW_WRITE 0 /* Bit 1 = 0 ->write register */ -#define CTRL_RW_READ 2 /* Bit 1 = 1 ->read register */ -#define CTRL_RESET_ON 0 /* Bit 3 = 0 ->reset board */ -#define CTRL_RESET_OFF 8 /* Bit 3 = 1 ->no reset of board */ +#define CTRL_ADR_DATA 0 /* Bit 0 = 0 ->access data register */ +#define CTRL_ADR_RAP 1 /* Bit 0 = 1 ->access RAP register */ +#define CTRL_RW_WRITE 0 /* Bit 1 = 0 ->write register */ +#define CTRL_RW_READ 2 /* Bit 1 = 1 ->read register */ +#define CTRL_RESET_ON 0 /* Bit 3 = 0 ->reset board */ +#define CTRL_RESET_OFF 8 /* Bit 3 = 1 ->no reset of board */ -#define STAT_ADR_DATA 0 /* Bit 0 of ctrl register read back */ +#define STAT_ADR_DATA 0 /* Bit 0 of ctrl register read back */ #define STAT_ADR_RAP 1 -#define STAT_RW_WRITE 0 /* Bit 1 of ctrl register read back */ +#define STAT_RW_WRITE 0 /* Bit 1 of ctrl register read back */ #define STAT_RW_READ 2 -#define STAT_RESET_ON 0 /* Bit 3 of ctrl register read back */ +#define STAT_RESET_ON 0 /* Bit 3 of ctrl register read back */ #define STAT_RESET_OFF 8 -#define STAT_IRQ_ACT 0 /* interrupt pending */ -#define STAT_IRQ_NOACT 16 /* no interrupt pending */ -#define STAT_IO_NOBUSY 0 /* no transfer busy */ -#define STAT_IO_BUSY 32 /* transfer busy */ +#define STAT_IRQ_ACT 0 /* interrupt pending */ +#define STAT_IRQ_NOACT 16 /* no interrupt pending */ +#define STAT_IO_NOBUSY 0 /* no transfer busy */ +#define STAT_IO_BUSY 32 /* transfer busy */ /* I/O command register bits */ -#define IOCMD_GO 128 /* Bit 7 = 1 -> start register xfer */ +#define IOCMD_GO 128 /* Bit 7 = 1 -> start register xfer */ /* LANCE registers */ -#define LANCE_CSR0 0 /* Status/Control */ +#define LANCE_CSR0 0 /* Status/Control */ -#define CSR0_ERR 0x8000 /* general error flag */ -#define CSR0_BABL 0x4000 /* transmitter timeout */ -#define CSR0_CERR 0x2000 /* collision error */ -#define CSR0_MISS 0x1000 /* lost Rx block */ -#define CSR0_MERR 0x0800 /* memory access error */ -#define CSR0_RINT 0x0400 /* receiver interrupt */ -#define CSR0_TINT 0x0200 /* transmitter interrupt */ -#define CSR0_IDON 0x0100 /* initialization done */ -#define CSR0_INTR 0x0080 /* general interrupt flag */ -#define CSR0_INEA 0x0040 /* interrupt enable */ -#define CSR0_RXON 0x0020 /* receiver enabled */ -#define CSR0_TXON 0x0010 /* transmitter enabled */ -#define CSR0_TDMD 0x0008 /* force transmission now */ -#define CSR0_STOP 0x0004 /* stop LANCE */ -#define CSR0_STRT 0x0002 /* start LANCE */ -#define CSR0_INIT 0x0001 /* read initialization block */ - -#define LANCE_CSR1 1 /* addr bit 0..15 of initialization */ -#define LANCE_CSR2 2 /* 16..23 block */ - -#define LANCE_CSR3 3 /* Bus control */ -#define CSR3_BCON_HOLD 0 /* Bit 0 = 0 -> BM1,BM0,HOLD */ -#define CSR3_BCON_BUSRQ 1 /* Bit 0 = 1 -> BUSAK0,BYTE,BUSRQ */ -#define CSR3_ALE_HIGH 0 /* Bit 1 = 0 -> ALE asserted high */ -#define CSR3_ALE_LOW 2 /* Bit 1 = 1 -> ALE asserted low */ -#define CSR3_BSWAP_OFF 0 /* Bit 2 = 0 -> no byte swap */ -#define CSR3_BSWAP_ON 0 /* Bit 2 = 1 -> byte swap */ +#define CSR0_ERR 0x8000 /* general error flag */ +#define CSR0_BABL 0x4000 /* transmitter timeout */ +#define CSR0_CERR 0x2000 /* collision error */ +#define CSR0_MISS 0x1000 /* lost Rx block */ +#define CSR0_MERR 0x0800 /* memory access error */ +#define CSR0_RINT 0x0400 /* receiver interrupt */ +#define CSR0_TINT 0x0200 /* transmitter interrupt */ +#define CSR0_IDON 0x0100 /* initialization done */ +#define CSR0_INTR 0x0080 /* general interrupt flag */ +#define CSR0_INEA 0x0040 /* interrupt enable */ +#define CSR0_RXON 0x0020 /* receiver enabled */ +#define CSR0_TXON 0x0010 /* transmitter enabled */ +#define CSR0_TDMD 0x0008 /* force transmission now */ +#define CSR0_STOP 0x0004 /* stop LANCE */ +#define CSR0_STRT 0x0002 /* start LANCE */ +#define CSR0_INIT 0x0001 /* read initialization block */ + +#define LANCE_CSR1 1 /* addr bit 0..15 of initialization */ +#define LANCE_CSR2 2 /* 16..23 block */ + +#define LANCE_CSR3 3 /* Bus control */ +#define CSR3_BCON_HOLD 0 /* Bit 0 = 0 -> BM1,BM0,HOLD */ +#define CSR3_BCON_BUSRQ 1 /* Bit 0 = 1 -> BUSAK0,BYTE,BUSRQ */ +#define CSR3_ALE_HIGH 0 /* Bit 1 = 0 -> ALE asserted high */ +#define CSR3_ALE_LOW 2 /* Bit 1 = 1 -> ALE asserted low */ +#define CSR3_BSWAP_OFF 0 /* Bit 2 = 0 -> no byte swap */ +#define CSR3_BSWAP_ON 0 /* Bit 2 = 1 -> byte swap */ /* LANCE structures */ -typedef struct /* LANCE initialization block */ - { - u16 Mode; /* mode flags */ - u8 PAdr[6]; /* MAC address */ - u8 LAdrF[8]; /* Multicast filter */ - u32 RdrP; /* Receive descriptor */ - u32 TdrP; /* Transmit descriptor */ - } LANCE_InitBlock; - +typedef struct { /* LANCE initialization block */ + u16 Mode; /* mode flags */ + u8 PAdr[6]; /* MAC address */ + u8 LAdrF[8]; /* Multicast filter */ + u32 RdrP; /* Receive descriptor */ + u32 TdrP; /* Transmit descriptor */ +} LANCE_InitBlock; + /* Mode flags init block */ -#define LANCE_INIT_PROM 0x8000 /* enable promiscous mode */ -#define LANCE_INIT_INTL 0x0040 /* internal loopback */ -#define LANCE_INIT_DRTY 0x0020 /* disable retry */ -#define LANCE_INIT_COLL 0x0010 /* force collision */ -#define LANCE_INIT_DTCR 0x0008 /* disable transmit CRC */ -#define LANCE_INIT_LOOP 0x0004 /* loopback */ -#define LANCE_INIT_DTX 0x0002 /* disable transmitter */ -#define LANCE_INIT_DRX 0x0001 /* disable receiver */ - -typedef struct /* LANCE Tx descriptor */ - { - u16 LowAddr; /* bit 0..15 of address */ - u16 Flags; /* bit 16..23 of address + Flags */ - u16 Len; /* 2s complement of packet length */ - u16 Status; /* Result of transmission */ - } LANCE_TxDescr; - -#define TXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ -#define TXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ -#define TXDSCR_FLAGS_MORE 0x1000 /* more than one retry needed? */ -#define TXDSCR_FLAGS_ONE 0x0800 /* one retry? */ -#define TXDSCR_FLAGS_DEF 0x0400 /* transmission deferred? */ -#define TXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ -#define TXDSCR_FLAGS_ENP 0x0100 /* last packet in chain? */ - -#define TXDSCR_STATUS_BUFF 0x8000 /* buffer error? */ -#define TXDSCR_STATUS_UFLO 0x4000 /* silo underflow during transmit? */ -#define TXDSCR_STATUS_LCOL 0x1000 /* late collision? */ -#define TXDSCR_STATUS_LCAR 0x0800 /* loss of carrier? */ -#define TXDSCR_STATUS_RTRY 0x0400 /* retry error? */ - -typedef struct /* LANCE Rx descriptor */ - { - u16 LowAddr; /* bit 0..15 of address */ - u16 Flags; /* bit 16..23 of address + Flags */ - u16 MaxLen; /* 2s complement of buffer length */ - u16 Len; /* packet length */ - } LANCE_RxDescr; - -#define RXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ -#define RXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ -#define RXDSCR_FLAGS_FRAM 0x2000 /* framing error flag */ -#define RXDSCR_FLAGS_OFLO 0x1000 /* FIFO overflow? */ -#define RXDSCR_FLAGS_CRC 0x0800 /* CRC error? */ -#define RXDSCR_FLAGS_BUFF 0x0400 /* buffer error? */ -#define RXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ -#define RXDCSR_FLAGS_ENP 0x0100 /* last packet in chain? */ +#define LANCE_INIT_PROM 0x8000 /* enable promiscous mode */ +#define LANCE_INIT_INTL 0x0040 /* internal loopback */ +#define LANCE_INIT_DRTY 0x0020 /* disable retry */ +#define LANCE_INIT_COLL 0x0010 /* force collision */ +#define LANCE_INIT_DTCR 0x0008 /* disable transmit CRC */ +#define LANCE_INIT_LOOP 0x0004 /* loopback */ +#define LANCE_INIT_DTX 0x0002 /* disable transmitter */ +#define LANCE_INIT_DRX 0x0001 /* disable receiver */ + +typedef struct { /* LANCE Tx descriptor */ + u16 LowAddr; /* bit 0..15 of address */ + u16 Flags; /* bit 16..23 of address + Flags */ + u16 Len; /* 2s complement of packet length */ + u16 Status; /* Result of transmission */ +} LANCE_TxDescr; + +#define TXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ +#define TXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ +#define TXDSCR_FLAGS_MORE 0x1000 /* more than one retry needed? */ +#define TXDSCR_FLAGS_ONE 0x0800 /* one retry? */ +#define TXDSCR_FLAGS_DEF 0x0400 /* transmission deferred? */ +#define TXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ +#define TXDSCR_FLAGS_ENP 0x0100 /* last packet in chain? */ + +#define TXDSCR_STATUS_BUFF 0x8000 /* buffer error? */ +#define TXDSCR_STATUS_UFLO 0x4000 /* silo underflow during transmit? */ +#define TXDSCR_STATUS_LCOL 0x1000 /* late collision? */ +#define TXDSCR_STATUS_LCAR 0x0800 /* loss of carrier? */ +#define TXDSCR_STATUS_RTRY 0x0400 /* retry error? */ + +typedef struct { /* LANCE Rx descriptor */ + u16 LowAddr; /* bit 0..15 of address */ + u16 Flags; /* bit 16..23 of address + Flags */ + u16 MaxLen; /* 2s complement of buffer length */ + u16 Len; /* packet length */ +} LANCE_RxDescr; + +#define RXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ +#define RXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ +#define RXDSCR_FLAGS_FRAM 0x2000 /* framing error flag */ +#define RXDSCR_FLAGS_OFLO 0x1000 /* FIFO overflow? */ +#define RXDSCR_FLAGS_CRC 0x0800 /* CRC error? */ +#define RXDSCR_FLAGS_BUFF 0x0400 /* buffer error? */ +#define RXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ +#define RXDCSR_FLAGS_ENP 0x0100 /* last packet in chain? */ /* RAM layout */ -#define TXCOUNT 4 /* length of TX descriptor queue */ -#define LTXCOUNT 2 /* log2 of it */ -#define RXCOUNT 4 /* length of RX descriptor queue */ -#define LRXCOUNT 2 /* log2 of it */ +#define TXCOUNT 4 /* length of TX descriptor queue */ +#define LTXCOUNT 2 /* log2 of it */ +#define RXCOUNT 4 /* length of RX descriptor queue */ +#define LRXCOUNT 2 /* log2 of it */ -#define RAM_INITBASE 0 /* LANCE init block */ -#define RAM_TXBASE 24 /* Start of TX descriptor queue */ +#define RAM_INITBASE 0 /* LANCE init block */ +#define RAM_TXBASE 24 /* Start of TX descriptor queue */ #define RAM_RXBASE \ -(RAM_TXBASE + (TXCOUNT * 8)) /* Start of RX descriptor queue */ +(RAM_TXBASE + (TXCOUNT * 8)) /* Start of RX descriptor queue */ #define RAM_DATABASE \ -(RAM_RXBASE + (RXCOUNT * 8)) /* Start of data area for frames */ -#define RAM_BUFSIZE 1580 /* max. frame size - should never be - reached */ +(RAM_RXBASE + (RXCOUNT * 8)) /* Start of data area for frames */ +#define RAM_BUFSIZE 1580 /* max. frame size - should never be + reached */ -#endif /* _SK_MCA_DRIVER_ */ +#endif /* _SK_MCA_DRIVER_ */ -extern int skmca_probe(struct net_device *); +extern int skmca_probe(struct SKMCA_NETDEV *); -#endif /* _SK_MCA_INCLUDE_ */ \ No newline at end of file +#endif /* _SK_MCA_INCLUDE_ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/skfp/skfddi.c linux.ac/drivers/net/skfp/skfddi.c --- linux.vanilla/drivers/net/skfp/skfddi.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/skfp/skfddi.c Tue May 30 15:27:47 2000 @@ -305,6 +305,8 @@ pdev)) == 0) { break; } + if (pci_enable_device(pdev)) + continue; #ifndef MEM_MAPPED_IO /* Verify that I/O enable bit is set (PCI slot is enabled) */ @@ -352,7 +354,7 @@ command &= ~PCI_COMMAND_IO; pci_write_config_word(pdev, PCI_COMMAND, command); - port = pdev->resource[0].start; + port = pci_resource_start(pdev, 0); port = (unsigned long)ioremap(port, 0x4000); if (!port){ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/smc-mca.c linux.ac/drivers/net/smc-mca.c --- linux.vanilla/drivers/net/smc-mca.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/smc-mca.c Sat Jun 10 21:40:34 2000 @@ -118,7 +118,7 @@ int irq = dev ? dev->irq : 0; if (!MCA_bus) { - return ENODEV; + return -ENODEV; } if (base_addr || irq) { @@ -252,9 +252,6 @@ reg4 = inb(ioaddr + 4) & 0x7f; outb(reg4, ioaddr + 4); - if (load_8390_module("wd.c")) - return -ENOSYS; - printk(KERN_INFO "%s: Parameters: %#3x,", dev->name, ioaddr); for (i = 0; i < 6; i++) @@ -458,6 +455,9 @@ { int this_dev, found = 0; + if (load_8390_module("wd.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -466,15 +466,14 @@ if (register_netdev(dev) != 0) { if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); printk(KERN_NOTICE "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -494,7 +493,7 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/smc-ultra.c linux.ac/drivers/net/smc-ultra.c --- linux.vanilla/drivers/net/smc-ultra.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/smc-ultra.c Sat Jun 10 21:40:34 2000 @@ -114,7 +114,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return ultra_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; ultra_portlist[i]; i++) { int ioaddr = ultra_portlist[i]; @@ -124,7 +124,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -143,7 +143,7 @@ /* Check the ID nibble. */ if ((idreg & 0xF0) != 0x20 /* SMC Ultra */ && (idreg & 0xF0) != 0x40) /* SMC EtherEZ */ - return ENODEV; + return -ENODEV; /* Select the station address register set. */ outb(reg4, ioaddr + 4); @@ -151,10 +151,7 @@ for (i = 0; i < 8; i++) checksum += inb(ioaddr + 8 + i); if ((checksum & 0xff) != 0xFF) - return ENODEV; - - if (load_8390_module("smc-ultra.c")) - return -ENOSYS; + return -ENODEV; if (dev == NULL) dev = init_etherdev(0, 0); @@ -448,6 +445,9 @@ { int this_dev, found = 0; + if (load_8390_module("smc-ultra.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -460,6 +460,7 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) return 0; /* Got at least one. */ + unload_8390_module(); return -ENXIO; } found++; @@ -483,7 +484,7 @@ kfree(dev->priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/smc-ultra32.c linux.ac/drivers/net/smc-ultra32.c --- linux.vanilla/drivers/net/smc-ultra32.c Thu May 25 17:37:55 2000 +++ linux.ac/drivers/net/smc-ultra32.c Sat Jun 10 21:40:34 2000 @@ -108,7 +108,7 @@ const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; int ioaddr, edge, media; - if (!EISA_bus) return ENODEV; + if (!EISA_bus) return -ENODEV; /* EISA spec allows for up to 16 slots, but 8 is typical. */ for (ioaddr = 0x1000 + ULTRA32_BASE; ioaddr < 0x9000; ioaddr += 0x1000) @@ -123,7 +123,7 @@ if (ultra32_probe1(dev, ioaddr) == 0) return 0; } - return ENODEV; + return -ENODEV; } int __init ultra32_probe1(struct net_device *dev, int ioaddr) @@ -138,7 +138,7 @@ /* Check the ID nibble. */ if ((idreg & 0xf0) != 0x20) /* SMC Ultra */ - return ENODEV; + return -ENODEV; /* Select the station address register set. */ outb(reg4, ioaddr + 4); @@ -146,10 +146,7 @@ for (i = 0; i < 8; i++) checksum += inb(ioaddr + 8 + i); if ((checksum & 0xff) != 0xff) - return ENODEV; - - if (load_8390_module("smc-ultra32.c")) - return -ENOSYS; + return -ENODEV; /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { @@ -184,7 +181,7 @@ if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) { printk("\nsmc-ultra32: Card RAM is disabled! " "Run EISA config utility.\n"); - return ENODEV; + return -ENODEV; } if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0) printk("\nsmc-ultra32: Ignoring Bus-Master enable bit. " @@ -381,20 +378,22 @@ { int this_dev, found = 0; + if (load_8390_module("smc-ultra32.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->init = ultra32_probe; if (register_netdev(dev) != 0) { if (found > 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n"); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -413,6 +412,6 @@ kfree(priv); } } - unlock_8390_module(); + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/smc9194.c linux.ac/drivers/net/smc9194.c --- linux.vanilla/drivers/net/smc9194.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/smc9194.c Tue Jun 6 17:43:20 2000 @@ -45,10 +45,12 @@ . Fixed bug reported by Gardner Buchanan in . smc_enable, with outw instead of outb . 03/06/96 Erik Stahlman Added hardware multicast from Peter Cammaert + . 04/14/00 Heiko Pruessing (SMA Regelsysteme) Fixed bug in chip memory + . allocation ----------------------------------------------------------------------------*/ static const char *version = - "smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n"; + "smc9194.c:v0.13 04/14/00 by Erik Stahlman (erik@vt.edu)\n"; #include #include @@ -517,11 +519,15 @@ length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + /* - . the MMU wants the number of pages to be the number of 256 bytes - . 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + ** The MMU wants the number of pages to be the number of 256 bytes + ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) ) + ** + ** Pkt size for allocating is data length +6 (for additional status words, + ** length and ctl!) If odd size last byte is included in this header. */ - numPages = length / 256; + numPages = ((length & 0xfffe) + 6) / 256; if (numPages > 7 ) { printk(CARDNAME": Far too big packet error. \n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sonic.c linux.ac/drivers/net/sonic.c --- linux.vanilla/drivers/net/sonic.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/sonic.c Sat Jun 10 21:40:34 2000 @@ -44,7 +44,7 @@ // if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) { if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) { printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq); - return EAGAIN; + return -EAGAIN; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/stnic.c linux.ac/drivers/net/stnic.c --- linux.vanilla/drivers/net/stnic.c Thu May 25 17:37:58 2000 +++ linux.ac/drivers/net/stnic.c Mon Jun 5 19:20:11 2000 @@ -300,3 +300,6 @@ } module_init(stnic_probe); +/* No cleanup routine - if there were one, it should do a: + unload_8390_module() +*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/strip.c linux.ac/drivers/net/strip.c --- linux.vanilla/drivers/net/strip.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/strip.c Sat Jun 10 21:40:34 2000 @@ -2870,7 +2870,7 @@ /* Return "not found", so that dev_init() will unlink * the placeholder device entry for us. */ - return ENODEV; + return -ENODEV; #endif } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sunbmac.c linux.ac/drivers/net/sunbmac.c --- linux.vanilla/drivers/net/sunbmac.c Thu May 25 17:37:56 2000 +++ linux.ac/drivers/net/sunbmac.c Sat Jun 10 21:40:34 2000 @@ -1262,7 +1262,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; for_each_sbus(sbus) { @@ -1278,7 +1278,7 @@ } } if (!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sunhme.c linux.ac/drivers/net/sunhme.c --- linux.vanilla/drivers/net/sunhme.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/sunhme.c Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: sunhme.c,v 1.95 2000/03/25 05:18:15 davem Exp $ +/* $Id: sunhme.c,v 1.96 2000/06/09 07:35:27 davem Exp $ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. @@ -2519,12 +2519,12 @@ if (is_qfe) { qp = quattro_sbus_find(sdev); if (qp == NULL) - return ENODEV; + return -ENODEV; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) if (qp->happy_meals[qfe_slot] == NULL) break; if (qfe_slot == 4) - return ENODEV; + return -ENODEV; } if (dev == NULL) { dev = init_etherdev(0, sizeof(struct happy_meal)); @@ -2564,7 +2564,7 @@ printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", sdev->num_registers); printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); - return ENODEV; + return -ENODEV; } if (qp != NULL) { @@ -2578,35 +2578,35 @@ GREG_REG_SIZE, "HME Global Regs"); if (!hp->gregs) { printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); - return ENODEV; + return -ENODEV; } hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, ETX_REG_SIZE, "HME TX Regs"); if (!hp->etxregs) { printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); - return ENODEV; + return -ENODEV; } hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, ERX_REG_SIZE, "HME RX Regs"); if (!hp->erxregs) { printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n"); - return ENODEV; + return -ENODEV; } hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, BMAC_REG_SIZE, "HME BIGMAC Regs"); if (!hp->bigmacregs) { printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n"); - return ENODEV; + return -ENODEV; } hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, TCVR_REG_SIZE, "HME Tranceiver Regs"); if (!hp->tcvregs) { printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n"); - return ENODEV; + return -ENODEV; } hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); @@ -2695,7 +2695,7 @@ pcp = pdev->sysdata; if (pcp == NULL || pcp->prom_node == -1) { printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); - return ENODEV; + return -ENODEV; } node = pcp->prom_node; @@ -2703,12 +2703,12 @@ if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { qp = quattro_pci_find(pdev); if (qp == NULL) - return ENODEV; + return -ENODEV; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) if (qp->happy_meals[qfe_slot] == NULL) break; if (qfe_slot == 4) - return ENODEV; + return -ENODEV; } if (dev == NULL) { dev = init_etherdev(0, sizeof(struct happy_meal)); @@ -2758,12 +2758,11 @@ qp->happy_meals[qfe_slot] = dev; } - hpreg_base = pdev->resource[0].start; + hpreg_base = pci_resource_start(pdev, 0); if ((pdev->resource[0].flags & IORESOURCE_IO) != 0) { printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n"); - return ENODEV; + return -ENODEV; } - hpreg_base &= PCI_BASE_ADDRESS_MEM_MASK; hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000); if (qfe_slot != -1 && prom_getproplen(node, "local-mac-address") == 6) @@ -2806,7 +2805,7 @@ if (!hp->happy_block) { printk(KERN_ERR "happymeal(PCI): Cannot get hme init block.\n"); - return ENODEV; + return -ENODEV; } hp->linkcheck = 0; @@ -2920,7 +2919,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; cards = 0; @@ -2933,7 +2932,7 @@ cards += happy_meal_pci_probe(dev); #endif if (!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sunlance.c linux.ac/drivers/net/sunlance.c --- linux.vanilla/drivers/net/sunlance.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/sunlance.c Sat Jun 10 21:40:34 2000 @@ -1502,7 +1502,7 @@ fail: if (lp != NULL) lance_free_hwresources(lp); - return ENODEV; + return -ENODEV; } /* On 4m, find the associated dma for the lance chip */ @@ -1532,7 +1532,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || @@ -1542,7 +1542,7 @@ sdev.irqs[0] = 6; return sparc_lance_init(NULL, &sdev, 0, 0); } - return ENODEV; + return -ENODEV; } #else /* !CONFIG_SUN4 */ @@ -1562,7 +1562,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; for_each_sbus (bus) { @@ -1593,7 +1593,7 @@ } /* for each sbusdev */ } /* for each sbus */ if (!cards) - return ENODEV; + return -ENODEV; return 0; } #endif /* !CONFIG_SUN4 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/sunqe.c linux.ac/drivers/net/sunqe.c --- linux.vanilla/drivers/net/sunqe.c Thu May 25 17:37:54 2000 +++ linux.ac/drivers/net/sunqe.c Sat Jun 10 21:40:34 2000 @@ -999,7 +999,7 @@ #endif if (called) - return ENODEV; + return -ENODEV; called++; for_each_sbus(bus) { @@ -1015,7 +1015,7 @@ } } if (!cards) - return ENODEV; + return -ENODEV; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tlan.c linux.ac/drivers/net/tlan.c --- linux.vanilla/drivers/net/tlan.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/tlan.c Mon May 29 19:34:42 2000 @@ -72,6 +72,31 @@ * - TODO: Port completely to new PCI/DMA API * Auto-Neg fallback. * + * v1.6 April 04, 2000 - Fixed driver support for kernel-parameters. Haven't + * tested it though, as the kernel support is currently + * broken (2.3.99p4p3). + * - Updated tlan.txt accordingly. + * - Adjusted minimum/maximum frame length. + * - There is now a TLAN website up at + * http://tlan.kernel.dk + * + * v1.7 April 07, 2000 - Started to implement custom ioctls. Driver now + * reports PHY information when used with Donald + * Beckers userspace MII diagnostics utility. + * + * v1.8 April 23, 2000 - Fixed support for forced speed/duplex settings. + * - Added link information to Auto-Neg and forced + * modes. When NIC operates with auto-neg the driver + * will report Link speed & duplex modes as well as + * link partner abilities. When forced link is used, + * the driver will report status of the established + * link. + * Please read tlan.txt for additional information. + * - Removed call to check_region(), and used + * return value of request_region() instead. + * + * v1.8a May 28, 2000 - Minor updates. + * *******************************************************************************/ @@ -99,6 +124,8 @@ static int duplex = 0; static int speed = 0; +MODULE_AUTHOR("Maintainer: Torben Mathiasen "); +MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters"); MODULE_PARM(aui, "i"); MODULE_PARM(duplex, "i"); MODULE_PARM(speed, "i"); @@ -111,9 +138,14 @@ static int bbuf = 0; static u8 *TLanPadBuffer; static char TLanSignature[] = "TLAN"; -static int TLanVersionMajor = 1; -static int TLanVersionMinor = 5; +static const char *tlan_banner = "ThunderLAN driver v1.8a\n"; +const char *media[] = { + "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ", + "100baseTx-FD", "100baseT4", 0 +}; + +int media_map[] = { 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,}; static TLanAdapterEntry TLanAdapterList[] __initdata = { { PCI_VENDOR_ID_COMPAQ, @@ -211,6 +243,7 @@ static int TLan_Close(struct net_device *); static struct net_device_stats *TLan_GetStats( struct net_device * ); static void TLan_SetMulticastList( struct net_device * ); +static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static u32 TLan_HandleInvalid( struct net_device *, u16 ); static u32 TLan_HandleTxEOF( struct net_device *, u16 ); @@ -371,9 +404,7 @@ u32 io_base, index; int found; - printk(KERN_INFO "ThunderLAN driver v%d.%d\n", - TLanVersionMajor, - TLanVersionMinor); + printk(KERN_INFO "%s", tlan_banner); TLanPadBuffer = (u8 *) kmalloc(TLAN_MIN_FRAME_SIZE, (GFP_KERNEL | GFP_DMA)); @@ -404,17 +435,36 @@ dev->irq = irq; priv->adapter = &TLanAdapterList[index]; priv->adapterRev = rev; - priv->aui = aui; - if ( ( duplex != 1 ) && ( duplex != 2 ) ) - duplex = 0; - priv->duplex = duplex; + + /* Kernel parameters */ + if (dev->mem_start) { + priv->aui = dev->mem_start & 0x01; + priv->duplex = ((dev->mem_start & 0x06) == 0x06) ? 0 : (dev->mem_start & 0x06) >> 1; + priv->speed = ((dev->mem_start & 0x18) == 0x18) ? 0 : (dev->mem_start & 0x18) >> 3; + + if (priv->speed == 0x1) { + priv->speed = TLAN_SPEED_10; + } else if (priv->speed == 0x2) { + priv->speed = TLAN_SPEED_100; + } + debug = priv->debug = dev->mem_end; + } else { - if ( ( speed != 10 ) && ( speed != 100 ) ) - speed = 0; + if ( ( duplex != 1 ) && ( duplex != 2 ) ) + duplex = 0; + + priv->duplex = duplex; - priv->speed = speed; - priv->debug = debug; + if ( ( speed != 10 ) && ( speed != 100 ) ) + speed = 0; + + priv->aui = aui; + priv->speed = speed; + priv->debug = debug; + + } + spin_lock_init(&priv->lock); if (TLan_Init(dev)) { @@ -495,8 +545,11 @@ TLanAdapterList[dl_index].deviceId ); + if (pci_enable_device(pdev)) + continue; + *pci_irq = pdev->irq; - *pci_io_base = pdev->resource[0].start; + *pci_io_base = pci_resource_start (pdev, 0); *pci_dfn = pdev->devfn; pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev); pci_read_config_word ( pdev, PCI_COMMAND, &pci_command); @@ -554,13 +607,13 @@ static int TLan_Init( struct net_device *dev ) { int dma_size; - int err; + int err; int i; TLanPrivateInfo *priv; priv = (TLanPrivateInfo *) dev->priv; - err = check_region( dev->base_addr, 0x10 ); - if ( err ) { + + if (!request_region( dev->base_addr, 0x10, TLanSignature )) { printk(KERN_ERR "TLAN: %s: Io port region 0x%lx size 0x%x in use.\n", dev->name, dev->base_addr, @@ -568,7 +621,6 @@ return -EIO; } - request_region( dev->base_addr, 0x10, TLanSignature ); if ( bbuf ) { dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) @@ -611,7 +663,7 @@ dev->stop = &TLan_Close; dev->get_stats = &TLan_GetStats; dev->set_multicast_list = &TLan_SetMulticastList; - + dev->do_ioctl = &TLan_ioctl; return 0; @@ -669,6 +721,49 @@ + /************************************************************** + * TLan_ioctl + * + * Returns: + * 0 on success, error code otherwise + * Params: + * dev structure of device to receive ioctl. + * + * rq ifreq structure to hold userspace data. + * + * cmd ioctl command. + * + * + *************************************************************/ + +static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u16 *data = (u16 *)&rq->ifr_data; + u32 phy = priv->phy[priv->phyNum]; + + if (!priv->phyOnline) + return -EAGAIN; + + switch(cmd) { + case SIOCDEVPRIVATE: + data[0] = phy; + + case SIOCDEVPRIVATE+1: /* Read MII register */ + TLan_MiiReadReg(dev, data[0], data[1], &data[3]); + return 0; + + case SIOCDEVPRIVATE+2: /* Write MII register */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + TLan_MiiWriteReg(dev, data[0], data[1], data[2]); + return 0; + default: + return -EOPNOTSUPP; + } +} /* tlan_ioctl */ + + /*************************************************************** * TLan_StartTx @@ -1898,7 +1993,10 @@ u32 phy; u8 sio; u16 status; + u16 partner; u16 tlphy_ctl; + u16 tlphy_par; + int i; phy = priv->phy[priv->phyNum]; @@ -1922,7 +2020,26 @@ udelay( 1000 ); TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); if ( status & MII_GS_LINK ) { - printk( "TLAN: %s: Link active.\n", dev->name ); + TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner ); + TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par ); + + printk( "TLAN: %s: Link active with ", dev->name ); + if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) { + printk( "forced 10%sMbps %s-Duplex\n", + tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0", + tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half"); + } else { + printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n", + tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0", + tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half"); + + printk("TLAN: Partner capability: "); + for (i = 5; i <= 10; i++) + if (partner & (1<base_addr, TLAN_LED_REG, TLAN_LED_LINK ); } } @@ -1946,7 +2063,7 @@ outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM ); outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); } else { - printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n", dev->name ); + printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n", dev->name ); TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET ); return; } @@ -2149,10 +2266,10 @@ TLan_MiiSync( dev->base_addr ); value = MII_GC_LOOPBK; TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value ); - + TLan_MiiSync(dev->base_addr); /* Wait for 500 ms and reset the * tranceiver. The TLAN docs say both 50 ms and - * 500 ms, so do the longer, just in case + * 500 ms, so do the longer, just in case. */ TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_RESET ); @@ -2177,12 +2294,12 @@ while ( value & MII_GC_RESET ) { TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value ); } - TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 ); /* Wait for 500 ms and initialize. * I don't remember why I wait this long. + * I've changed this to 50ms, as it seems long enough. */ - TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_START_LINK ); + TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); } /* TLan_PhyReset */ @@ -2200,52 +2317,56 @@ u16 tctl; phy = priv->phy[priv->phyNum]; - TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name ); TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); + TLan_MiiReadReg( dev, phy, MII_GEN_STS, &ability ); if ( ( status & MII_GS_AUTONEG ) && - ( priv->duplex == TLAN_DUPLEX_DEFAULT ) && - ( priv->speed == TLAN_SPEED_DEFAULT ) && ( ! priv->aui ) ) { - ability = status >> 11; - - if ( priv->speed == TLAN_SPEED_10 ) { - ability &= 0x0003; - } else if ( priv->speed == TLAN_SPEED_100 ) { - ability &= 0x001C; - } - - if ( priv->duplex == TLAN_DUPLEX_FULL ) { - ability &= 0x000A; - } else if ( priv->duplex == TLAN_DUPLEX_HALF ) { - ability &= 0x0005; - } - - TLan_MiiWriteReg( dev, phy, MII_AN_ADV, ( ability << 5 ) | 1 ); - TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 ); - TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 ); - - /* Wait for 4 sec for autonegotiation - * to complete. The max spec time is less than this - * but the card need additional time to start AN. - * .5 sec should be plenty extra. - */ - printk( "TLAN: %s: Starting autonegotiation.\n", dev->name ); - TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN ); - return; - } + ability = status >> 11; + if ( priv->speed == TLAN_SPEED_10 && + priv->duplex == TLAN_DUPLEX_HALF) { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000); + } else if ( priv->speed == TLAN_SPEED_10 && + priv->duplex == TLAN_DUPLEX_FULL) { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100); + } else if ( priv->speed == TLAN_SPEED_100 && + priv->duplex == TLAN_DUPLEX_HALF) { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000); + } else if ( priv->speed == TLAN_SPEED_100 && + priv->duplex == TLAN_DUPLEX_FULL) { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100); + } else { + + /* Set Auto-Neg advertisement */ + TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1); + /* Enablee Auto-Neg */ + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 ); + /* Restart Auto-Neg */ + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 ); + /* Wait for 4 sec for autonegotiation + * to complete. The max spec time is less than this + * but the card need additional time to start AN. + * .5 sec should be plenty extra. + */ + printk( "TLAN: %s: Starting autonegotiation.\n", dev->name ); + TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN ); + return; + } + + } + if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) { priv->phyNum = 0; data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data ); - TLan_SetTimer( dev, (4*(HZ/1000)), TLAN_TIMER_PHY_PDOWN ); + TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); return; - } else if ( priv->phyNum == 0 ) { + } else if ( priv->phyNum == 0 ) { TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl ); if ( priv->aui ) { tctl |= TLAN_TC_AUISEL; - } else { + } else { tctl &= ~TLAN_TC_AUISEL; control = 0; if ( priv->duplex == TLAN_DUPLEX_FULL ) { @@ -2260,10 +2381,10 @@ TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl ); } - /* Wait for 1 sec to give the tranceiver time + /* Wait for 2 sec to give the tranceiver time * to establish link. */ - TLan_SetTimer( dev, HZ, TLAN_TIMER_FINISH_RESET ); + TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_FINISH_RESET ); } /* TLan_PhyStartLink */ @@ -2306,14 +2427,14 @@ priv->phyNum = 0; data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data ); - TLan_SetTimer( dev, (400*(HZ/1000)), TLAN_TIMER_PHY_PDOWN ); + TLan_SetTimer( dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); return; } if ( priv->phyNum == 0 ) { if ( ( priv->duplex == TLAN_DUPLEX_FULL ) || ( an_adv & an_lpa & 0x0040 ) ) { TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB | MII_GC_DUPLEX ); - printk( "TLAN: Starting internal PHY with DUPLEX\n" ); + printk( "TLAN: Starting internal PHY with FULL-DUPLEX\n" ); } else { TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB ); printk( "TLAN: Starting internal PHY with HALF-DUPLEX\n" ); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tlan.h linux.ac/drivers/net/tlan.h --- linux.vanilla/drivers/net/tlan.h Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/tlan.h Sat Jun 10 22:45:01 2000 @@ -36,8 +36,8 @@ #define FALSE 0 #define TRUE 1 -#define TLAN_MIN_FRAME_SIZE 64 -#define TLAN_MAX_FRAME_SIZE 1600 +#define TLAN_MIN_FRAME_SIZE 60 +#define TLAN_MAX_FRAME_SIZE 1536 #define TLAN_NUM_RX_LISTS 4 #define TLAN_NUM_TX_LISTS 8 @@ -404,7 +404,11 @@ #define TLAN_TS_POLOK 0x2000 #define TLAN_TS_TPENERGY 0x1000 #define TLAN_TS_RESERVED 0x0FFF - +#define TLAN_TLPHY_PAR 0x19 +#define TLAN_PHY_CIM_STAT 0x0020 +#define TLAN_PHY_SPEED_100 0x0040 +#define TLAN_PHY_DUPLEX_FULL 0x0080 +#define TLAN_PHY_AN_EN_STAT 0x0400 #define CIRC_INC( a, b ) if ( ++a >= b ) a = 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tokenring/ibmtr.c linux.ac/drivers/net/tokenring/ibmtr.c --- linux.vanilla/drivers/net/tokenring/ibmtr.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/tokenring/ibmtr.c Fri Jun 9 16:58:03 2000 @@ -781,6 +781,9 @@ { struct tok_info *ti=(struct tok_info *)dev->priv; + /* init the spinlock */ + spin_lock_init(&ti->lock); + SET_PAGE(ti->srb_page); ti->open_status = CLOSED; @@ -845,9 +848,6 @@ static int tok_open(struct net_device *dev) { struct tok_info *ti=(struct tok_info *)dev->priv; - - /* init the spinlock */ - spin_lock_init(&ti->lock); if (ti->open_status==CLOSED) tok_init_card(dev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tokenring/lanstreamer.c linux.ac/drivers/net/tokenring/lanstreamer.c --- linux.vanilla/drivers/net/tokenring/lanstreamer.c Thu May 25 17:37:53 2000 +++ linux.ac/drivers/net/tokenring/lanstreamer.c Tue May 30 15:18:35 2000 @@ -207,12 +207,14 @@ { while ((pci_device = pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR, pci_device))) { + if (pci_enable_device(pci_device)) + continue; pci_set_master(pci_device); /* Check to see if io has been allocated, if so, we've already done this card, so continue on the card discovery loop */ - if (check_region(pci_device->resource[0].start & (~3), STREAMER_IO_SPACE)) + if (check_region(pci_resource_start(pci_device,0), STREAMER_IO_SPACE)) { card_no++; continue; @@ -242,10 +244,11 @@ pci_device, dev, dev->priv); #endif dev->irq = pci_device->irq; - dev->base_addr = pci_device->resource[0].start & (~3); + dev->base_addr = pci_resource_start(pci_device, 0); dev->init = &streamer_init; streamer_priv->streamer_card_name = (char *)pci_device->resource[0].name; - streamer_priv->streamer_mmio = ioremap(pci_device->resource[1].start, 256); + streamer_priv->streamer_mmio = + ioremap(pci_resource_start(pci_device, 1), 256); if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000)) streamer_priv->pkt_buf_sz = PKT_BUF_SZ; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tokenring/olympic.c linux.ac/drivers/net/tokenring/olympic.c --- linux.vanilla/drivers/net/tokenring/olympic.c Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/tokenring/olympic.c Tue May 30 21:07:58 2000 @@ -29,6 +29,16 @@ * 2/23/00 - Updated to dev_kfree_irq * 3/10/00 - Fixed FDX enable which triggered other bugs also * squashed. + * 5/20/00 - Changes to handle Olympic on LinuxPPC. Endian changes. + * The odd thing about the changes is that the fix for + * endian issues with the big-endian data in the arb, asb... + * was to always swab() the bytes, no matter what CPU. + * That's because the read[wl]() functions always swap the + * bytes on the way in on PPC. + * Fixing the hardware descriptors was another matter, + * because they weren't going through read[wl](), there all + * the results had to be in memory in le32 values. kdaaker + * * * To Do: * @@ -169,13 +179,25 @@ if (pci_present()) { while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) { + __u16 pci_command ; + + if (pci_enable_device(pci_device)) + continue; + /* These lines are needed by the PowerPC, it appears +that these flags + * are not being set properly for the PPC, this may +well be fixed with + * the new PCI code */ + pci_read_config_word(pci_device, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + pci_write_config_word(pci_device, PCI_COMMAND,pci_command); pci_set_master(pci_device); /* Check to see if io has been allocated, if so, we've already done this card, so continue on the card discovery loop */ - if (check_region(pci_device->resource[0].start, OLYMPIC_IO_SPACE)) { + if (check_region(pci_resource_start(pci_device, 0), OLYMPIC_IO_SPACE)) { card_no++ ; continue ; } @@ -192,11 +214,13 @@ printk("pci_device: %p, dev:%p, dev->priv: %p\n", pci_device, dev, dev->priv); #endif dev->irq=pci_device->irq; - dev->base_addr=pci_device->resource[0].start; + dev->base_addr=pci_resource_start(pci_device, 0); dev->init=&olympic_init; olympic_priv->olympic_card_name = (char *)pci_device->resource[0].name ; - olympic_priv->olympic_mmio=ioremap(pci_device->resource[1].start,256); - olympic_priv->olympic_lap=ioremap(pci_device->resource[2].start,2048); + olympic_priv->olympic_mmio = + ioremap(pci_resource_start(pci_device,1),256); + olympic_priv->olympic_lap = + ioremap(pci_resource_start(pci_device,2),2048); if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) ) olympic_priv->pkt_buf_sz = PKT_BUF_SZ ; @@ -329,7 +353,7 @@ } } - uaa_addr=ntohs(readw(init_srb+8)); + uaa_addr=swab16(readw(init_srb+8)); #if OLYMPIC_DEBUG printk("UAA resides at %x\n",uaa_addr); @@ -346,8 +370,8 @@ memcpy_fromio(&dev->dev_addr[0], adapter_addr,6); - olympic_priv->olympic_addr_table_addr = ntohs(readw(init_srb + 12)) ; - olympic_priv->olympic_parms_addr = ntohs(readw(init_srb + 14)) ; + olympic_priv->olympic_addr_table_addr = swab16(readw(init_srb + 12)); + olympic_priv->olympic_parms_addr = swab16(readw(init_srb + 14)); return 0; @@ -409,9 +433,9 @@ /* If Network Monitor, instruct card to copy MAC frames through the ARB */ #if OLYMPIC_NETWORK_MONITOR - writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8); + writew(swab16(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), init_srb+8); #else - writew(ntohs(OPEN_ADAPTER_ENABLE_FDX),init_srb+8); + writew(swab16(OPEN_ADAPTER_ENABLE_FDX), init_srb+8); #endif if (olympic_priv->olympic_laa[0]) { @@ -445,7 +469,7 @@ #if OLYMPIC_DEBUG printk("init_srb(%p): ",init_srb); for(i=0;i<20;i++) - printk("%x ",readb(init_srb+i)); + printk("%02x ",readb(init_srb+i)); printk("\n"); #endif @@ -504,10 +528,10 @@ if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed); - olympic_priv->asb=ntohs(readw(init_srb+8)); - olympic_priv->srb=ntohs(readw(init_srb+10)); - olympic_priv->arb=ntohs(readw(init_srb+12)); - olympic_priv->trb=ntohs(readw(init_srb+16)); + olympic_priv->asb = swab16(readw(init_srb+8)); + olympic_priv->srb = swab16(readw(init_srb+10)); + olympic_priv->arb = swab16(readw(init_srb+12)); + olympic_priv->trb = swab16(readw(init_srb+16)); olympic_priv->olympic_receive_options = 0x01 ; olympic_priv->olympic_copy_all_options = 0 ; @@ -528,8 +552,8 @@ skb->dev = dev; - olympic_priv->olympic_rx_ring[i].buffer=virt_to_bus(skb->data); - olympic_priv->olympic_rx_ring[i].res_length = olympic_priv->pkt_buf_sz ; + olympic_priv->olympic_rx_ring[i].buffer = cpu_to_le32(virt_to_bus(skb->data)); + olympic_priv->olympic_rx_ring[i].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz); olympic_priv->rx_ring_skb[i]=skb; } @@ -539,17 +563,17 @@ return -EIO; } - writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXDESCQ); - writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXCDA); - writew(i,olympic_mmio+RXDESCQCNT); + writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]), olympic_mmio+RXDESCQ); + writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]), olympic_mmio+RXCDA); + writew(i, olympic_mmio+RXDESCQCNT); - writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXSTATQ); - writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXCSA); + writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]), olympic_mmio+RXSTATQ); + writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]), olympic_mmio+RXCSA); - olympic_priv->rx_ring_last_received=OLYMPIC_RX_RING_SIZE-1; /* last processed rx status */ - olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE-1; + olympic_priv->rx_ring_last_received = OLYMPIC_RX_RING_SIZE - 1; /* last processed rx status */ + olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE - 1; - writew(i,olympic_mmio+RXSTATQCNT); + writew(i, olympic_mmio+RXSTATQCNT); #if OLYMPIC_DEBUG printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ)); @@ -578,9 +602,9 @@ olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef; olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE; - writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXDESCQ_1); - writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXCDA_1); - writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXDESCQCNT_1); + writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]), olympic_mmio+TXDESCQ_1); + writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]), olympic_mmio+TXCDA_1); + writew(OLYMPIC_TX_RING_SIZE, olympic_mmio+TXDESCQCNT_1); writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXSTATQ_1); writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXCSA_1); @@ -654,34 +678,35 @@ rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ; while (rx_status->status_buffercnt) { + __u32 l_status_buffercnt; olympic_priv->rx_status_last_received++ ; olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1); #if OLYMPIC_DEBUG printk(" stat_ring addr: %x \n", &(olympic_priv->olympic_rx_status_ring[olympic_priv->rx_status_last_received]) ); - printk("rx status: %x rx len: %x \n",rx_status->status_buffercnt,rx_status->fragmentcnt_framelen); + printk("rx status: %x rx len: %x \n", le32_to_cpu(rx_status->status_buffercnt), le32_to_cpu(rx_status->fragmentcnt_framelen)); #endif - length=rx_status->fragmentcnt_framelen & 0xffff; - buffer_cnt = rx_status->status_buffercnt & 0xffff ; + length = le32_to_cpu(rx_status->fragmentcnt_framelen) & 0xffff; + buffer_cnt = le32_to_cpu(rx_status->status_buffercnt) & 0xffff; i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */ - frag_len = rx_status->fragmentcnt_framelen >> 16 ; + frag_len = le32_to_cpu(rx_status->fragmentcnt_framelen) >> 16; #if OLYMPIC_DEBUG - printk("length: %x, frag_len: %x, buffer_cnt: %x\n",length,frag_len,buffer_cnt); + printk("length: %x, frag_len: %x, buffer_cnt: %x\n", length, frag_len, buffer_cnt); #endif - - if(rx_status->status_buffercnt & 0xC0000000) { - if (rx_status->status_buffercnt & 0x3B000000) { + l_status_buffercnt = le32_to_cpu(rx_status->status_buffercnt); + if(l_status_buffercnt & 0xC0000000) { + if (l_status_buffercnt & 0x3B000000) { if (olympic_priv->olympic_message_level) { - if (rx_status->status_buffercnt & (1<<29)) /* Rx Frame Truncated */ + if (l_status_buffercnt & (1<<29)) /* Rx Frame Truncated */ printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name); - if (rx_status->status_buffercnt & (1<<28)) /*Rx receive overrun */ + if (l_status_buffercnt & (1<<28)) /*Rx receive overrun */ printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name); - if (rx_status->status_buffercnt & (1<<27)) /* No receive buffers */ + if (l_status_buffercnt & (1<<27)) /* No receive buffers */ printk(KERN_WARNING "%s: No receive buffers \n",dev->name); - if (rx_status->status_buffercnt & (1<<25)) /* Receive frame error detect */ + if (l_status_buffercnt & (1<<25)) /* Receive frame error detect */ printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name); - if (rx_status->status_buffercnt & (1<<24)) /* Received Error Detect */ + if (l_status_buffercnt & (1<<24)) /* Received Error Detect */ printk(KERN_WARNING "%s: Received Error Detect \n",dev->name); } olympic_priv->rx_ring_last_received += i ; @@ -717,8 +742,8 @@ skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; skb_put(skb2,length); skb2->protocol = tr_type_trans(skb2,dev); - olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer=virt_to_bus(skb->data); - olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = olympic_priv->pkt_buf_sz ; + olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer = cpu_to_le32(virt_to_bus(skb->data)); + olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz); olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; netif_rx(skb2) ; } else { @@ -727,8 +752,8 @@ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1); rx_ring_last_received = olympic_priv->rx_ring_last_received ; rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]); - cpy_length = (i == 1 ? frag_len : rx_desc->res_length); - memcpy(skb_put(skb, cpy_length), bus_to_virt(rx_desc->buffer), cpy_length) ; + cpy_length = (i == 1 ? frag_len : le32_to_cpu(rx_desc->res_length)); + memcpy(skb_put(skb, cpy_length), bus_to_virt(le32_to_cpu(rx_desc->buffer)), cpy_length) ; } while (--i) ; skb->protocol = tr_type_trans(skb,dev); @@ -849,8 +874,8 @@ netif_stop_queue(dev); if(olympic_priv->free_tx_ring_entries) { - olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data); - olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000); + olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer = cpu_to_le32(virt_to_bus(skb->data)); + olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length = cpu_to_le32(skb->len | (0x80000000)); olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb; olympic_priv->free_tx_ring_entries--; @@ -1205,9 +1230,9 @@ if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */ - frame_len = ntohs(readw(arb_block + 10)) ; + frame_len = swab16(readw(arb_block + 10)) ; - buff_off = ntohs(readw(arb_block + 6)) ; + buff_off = swab16(readw(arb_block + 6)) ; buf_ptr = olympic_priv->olympic_lap + buff_off ; @@ -1229,7 +1254,7 @@ do { frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; - buffer_len = ntohs(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); + buffer_len = swab16(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ; next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next)); @@ -1271,7 +1296,7 @@ return ; } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */ - lan_status = ntohs(readw(arb_block+6)); + lan_status = swab16(readw(arb_block+6)); fdx_prot_error = readb(arb_block+8) ; /* Issue ARB Free */ @@ -1535,9 +1560,9 @@ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, att_code)))); + swab16(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code)))); size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name) ; @@ -1550,20 +1575,20 @@ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, major_vector))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, lan_status))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, local_ring))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, mon_error))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, frame_correl)))); + swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, lan_status))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, local_ring))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, mon_error))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, frame_correl)))); size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n", dev->name) ; size += sprintf(buffer+size, "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n", dev->name, - ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))), - ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))), + swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tokenring/olympic.h linux.ac/drivers/net/tokenring/olympic.h --- linux.vanilla/drivers/net/tokenring/olympic.h Thu May 25 17:37:52 2000 +++ linux.ac/drivers/net/tokenring/olympic.h Tue May 30 17:11:34 2000 @@ -207,6 +207,8 @@ /* Olympic data structures */ +/* xxxx These structures are all little endian in hardware. */ + struct olympic_tx_desc { __u32 buffer; __u32 status_length; @@ -218,13 +220,15 @@ struct olympic_rx_desc { __u32 buffer; - __u32 res_length ; + __u32 res_length; }; struct olympic_rx_status { __u32 fragmentcnt_framelen; __u32 status_buffercnt; }; +/* xxxx END These structures are all little endian in hardware. */ +/* xxxx There may be more, but I'm pretty sure about these */ struct mac_receive_buffer { __u16 next ; @@ -236,10 +240,10 @@ struct olympic_private { - __u16 srb; - __u16 trb; - __u16 arb; - __u16 asb; + __u16 srb; /* be16 */ + __u16 trb; /* be16 */ + __u16 arb; /* be16 */ + __u16 asb; /* be16 */ __u8 *olympic_mmio; __u8 *olympic_lap; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/21142.c linux.ac/drivers/net/tulip/21142.c --- linux.vanilla/drivers/net/tulip/21142.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/21142.c Fri Jun 9 19:17:49 2000 @@ -14,14 +14,15 @@ */ #include "tulip.h" +#include +#include static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; -u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; +u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; - /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list of available transceivers. */ void t21142_timer(unsigned long data) @@ -82,8 +83,7 @@ tp->csr6 &= 0x00D5; tp->csr6 |= new_csr6; outl(0x0301, ioaddr + CSR12); - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); } next_tick = 3*HZ; } @@ -102,19 +102,22 @@ int csr14 = ((tp->to_advertise & 0x0780) << 9) | ((tp->to_advertise&0x0020)<<1) | 0xffbf; + DPRINTK("ENTER\n"); + dev->if_port = 0; tp->nway = tp->mediasense = 1; tp->nwayset = tp->lpar = 0; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, %8.8x.\n", + printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%8.8x.\n", dev->name, csr14); outl(0x0001, ioaddr + CSR13); + udelay(100); outl(csr14, ioaddr + CSR14); if (tp->chip_id == PNIC2) tp->csr6 = 0x01a80000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); else tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); - tulip_outl_CSR6(tp, tp->csr6); + tulip_outl_csr(tp, tp->csr6, CSR6); if (tp->mtable && tp->mtable->csr15dir) { outl(tp->mtable->csr15dir, ioaddr + CSR15); outl(tp->mtable->csr15val, ioaddr + CSR15); @@ -180,12 +183,12 @@ outl(1, ioaddr + CSR13); } #if 0 /* Restart shouldn't be needed. */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0000); + tulip_outl_csr(tp, tp->csr6 | csr6_sr, CSR6); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", dev->name, inl(ioaddr + CSR5)); #endif - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n", dev->name, tp->csr6, inl(ioaddr + CSR6), @@ -231,8 +234,7 @@ tp->csr6 = 0x83860000; outl(0x0003FF7F, ioaddr + CSR14); outl(0x0301, ioaddr + CSR12); - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/eeprom.c linux.ac/drivers/net/tulip/eeprom.c --- linux.vanilla/drivers/net/tulip/eeprom.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/eeprom.c Thu Jun 8 15:13:13 2000 @@ -162,6 +162,13 @@ if (tp->flags & CSR12_IN_SROM) csr12dir = *p++; count = *p++; + + /* there is no phy information, don't even try to build mtable */ + if (count == 0) { + DPRINTK("no phy info, aborting mtable build\n"); + return; + } + mtable = (struct mediatable *) kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf), GFP_KERNEL); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/interrupt.c linux.ac/drivers/net/tulip/interrupt.c --- linux.vanilla/drivers/net/tulip/interrupt.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/interrupt.c Tue May 30 21:05:51 2000 @@ -178,7 +178,7 @@ int maxtx = TX_RING_SIZE; int maxoi = TX_RING_SIZE; int work_count = tulip_max_interrupt_work; - + tp->nir++; do { @@ -236,13 +236,7 @@ if (status & 0x0002) tp->stats.tx_fifo_errors++; if ((status & 0x0080) && tp->full_duplex == 0) tp->stats.tx_heartbeat_errors++; -#ifdef ETHER_STATS - if (status & 0x0100) tp->stats.collisions16++; -#endif } else { -#ifdef ETHER_STATS - if (status & 0x0001) tp->stats.tx_deferred++; -#endif tp->stats.tx_bytes += tp->tx_buffers[entry].skb->len; tp->stats.collisions += (status >> 3) & 15; @@ -280,8 +274,7 @@ printk(KERN_WARNING "%s: The transmitter stopped." " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); } spin_unlock(&tp->lock); } @@ -297,14 +290,13 @@ else tp->csr6 |= 0x00200000; /* Store-n-forward. */ /* Restart the transmit process. */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); outl(0, ioaddr + CSR1); } if (csr5 & RxDied) { /* Missed a Rx frame. */ tp->stats.rx_errors++; tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); } if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/media.c linux.ac/drivers/net/tulip/media.c --- linux.vanilla/drivers/net/tulip/media.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/media.c Tue May 30 21:05:51 2000 @@ -388,8 +388,7 @@ tp->csr6 &= ~0x00400000; if (tp->full_duplex) tp->csr6 |= 0x0200; else tp->csr6 &= ~0x0200; - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); if (tulip_debug > 0) printk(KERN_INFO "%s: Setting %s-duplex based on MII" "#%d link partner capability of %4.4x.\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/pnic.c linux.ac/drivers/net/tulip/pnic.c --- linux.vanilla/drivers/net/tulip/pnic.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/pnic.c Tue May 30 21:05:51 2000 @@ -44,8 +44,7 @@ if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); dev->trans_start = jiffies; } } @@ -65,7 +64,7 @@ outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); - tulip_outl_CSR6(tp, tp->csr6); + tulip_outl_csr(tp, tp->csr6, CSR6); outl(0x30, ioaddr + CSR12); outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ dev->trans_start = jiffies; @@ -128,8 +127,7 @@ if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); dev->trans_start = jiffies; if (tulip_debug > 1) printk(KERN_INFO "%s: Changing PNIC configuration to %s " diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/timer.c linux.ac/drivers/net/tulip/timer.c --- linux.vanilla/drivers/net/tulip/timer.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/timer.c Tue May 30 21:05:51 2000 @@ -154,8 +154,7 @@ medianame[tp->mtable->mleaf[tp->cur_index].media]); tulip_select_media(dev, 0); /* Restart the transmit process. */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); next_tick = (24*HZ)/10; break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/tulip.h linux.ac/drivers/net/tulip/tulip.h --- linux.vanilla/drivers/net/tulip/tulip.h Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/tulip.h Sat Jun 10 22:45:09 2000 @@ -169,31 +169,54 @@ csr6_ra = (1<<30), csr6_ign_dest_msb = (1<<26), csr6_mbo = (1<<25), - csr6_scr = (1<<24), - csr6_pcs = (1<<23), - csr6_ttm = (1<<22), - csr6_sf = (1<<21), - csr6_hbd = (1<<19), - csr6_ps = (1<<18), - csr6_ca = (1<<17), - csr6_st = (1<<13), - csr6_fc = (1<<12), - csr6_om_int_loop = (1<<10), - csr6_om_ext_loop = (1<<11), - csr6_fd = (1<<9), - csr6_pm = (1<<7), - csr6_pr = (1<<6), - csr6_sb = (1<<5), - csr6_if = (1<<4), - csr6_pb = (1<<3), - csr6_ho = (1<<2), - csr6_sr = (1<<1), - csr6_hp = (1<<0), + csr6_scr = (1<<24), /* scramble mode flag: can't be set */ + csr6_pcs = (1<<23), /* Enables PCS functions (symbol mode requires csr6_ps be set) default is set */ + csr6_ttm = (1<<22), /* Transmit Threshold Mode, set for 10baseT, 0 for 100BaseTX */ + csr6_sf = (1<<21), /* Store and forward. If set ignores TR bits */ + csr6_hbd = (1<<19), /* Heart beat disable. Disables SQE function in 10baseT */ + csr6_ps = (1<<18), /* Port Select. 0 (defualt) = 10baseT, 1 = 100baseTX: can't be set */ + csr6_ca = (1<<17), /* Collision Offset Enable. If set uses special algorithm in low collision situations */ + csr6_trh = (1<<15), /* Transmit Threshold high bit */ + csr6_trl = (1<<14), /* Transmit Threshold low bit */ + + /*************************************************************** + * This table shows transmit threshold values based on media * + * and these two registers (from PNIC1 & 2 docs) Note: this is * + * all meaningless if sf is set. * + ***************************************************************/ + + /*********************************** + * (trh,trl) * 100BaseTX * 10BaseT * + *********************************** + * (0,0) * 128 * 72 * + * (0,1) * 256 * 96 * + * (1,0) * 512 * 128 * + * (1,1) * 1024 * 160 * + ***********************************/ + + csr6_st = (1<<13), /* Transmit conrol: 1 = transmit, 0 = stop */ + csr6_fc = (1<<12), /* Forces a collision in next transmission (for testing in loopback mode) */ + csr6_om_int_loop = (1<<10), /* internal (FIFO) loopback flag */ + csr6_om_ext_loop = (1<<11), /* external (PMD) loopback flag */ + /* set both and you get (PHY) loopback */ + csr6_fd = (1<<9), /* Full duplex mode, disables hearbeat, no loopback */ + csr6_pm = (1<<7), /* Pass All Multicast */ + csr6_pr = (1<<6), /* Promiscuous mode */ + csr6_sb = (1<<5), /* Start(1)/Stop(0) backoff counter */ + csr6_if = (1<<4), /* Inverse Filtering, rejects only addresses in address table: can't be set */ + csr6_pb = (1<<3), /* Pass Bad Frames, (1) causes even bad frames to be passed on */ + csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ + csr6_sr = (1<<1), /* Start(1)/Stop(0) Receive */ + csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ csr6_mask_capture = (csr6_sc | csr6_ca), csr6_mask_defstate = (csr6_mask_capture | csr6_mbo), - csr6_mask_fullcap = (csr6_mask_defstate | csr6_hbd | - csr6_ps | (3<<14) | csr6_fd), + csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps), + csr6_mask_hdcaptt = (csr6_mask_hdcap | csr6_trh | csr6_trl), + csr6_mask_fullcap = (csr6_mask_hdcaptt | csr6_fd), + csr6_mask_fullpromisc = (csr6_pr | csr6_pm), + csr6_mask_filters = (csr6_hp | csr6_ho | csr6_if), + csr6_mask_100bt = (csr6_scr | csr6_pcs | csr6_hbd), }; @@ -397,11 +420,20 @@ extern u16 t21041_csr15[]; -extern inline void tulip_outl_CSR6 (struct tulip_private *tp, u32 newcsr6) +static inline void tulip_outl_csr (struct tulip_private *tp, u32 newValue, enum tulip_offsets offset) { - long ioaddr = tp->base_addr; + outl (newValue, tp->base_addr + offset); +} - outl (newcsr6, ioaddr + CSR6); +static inline void tulip_stop_rxtx(struct tulip_private *tp, u32 csr6mask) +{ + tulip_outl_csr(tp, csr6mask & ~(csr6_st | csr6_sr), CSR6); +} + +static inline void tulip_restart_rxtx(struct tulip_private *tp, u32 csr6mask) +{ + tulip_outl_csr(tp, csr6mask | csr6_sr, CSR6); + tulip_outl_csr(tp, csr6mask | csr6_st | csr6_sr, CSR6); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/tulip/tulip_core.c linux.ac/drivers/net/tulip/tulip_core.c --- linux.vanilla/drivers/net/tulip/tulip_core.c Thu May 25 17:37:57 2000 +++ linux.ac/drivers/net/tulip/tulip_core.c Thu Jun 8 15:13:13 2000 @@ -19,7 +19,7 @@ */ -static const char version[] = "Linux Tulip driver version 0.9.4.3 (Apr 14, 2000)\n"; +static const char version[] = "Linux Tulip driver version 0.9.6 (May 31, 2000)\n"; #include #include "tulip.h" @@ -50,7 +50,8 @@ }; /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ -#if defined(__alpha__) || defined(__arm__) || defined(__sparc__) +#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ + || defined(__sparc_) static int rx_copybreak = 1518; #else static int rx_copybreak = 100; @@ -71,7 +72,7 @@ #if defined(__alpha__) static int csr0 = 0x01A00000 | 0xE000; -#elif defined(__i386__) || defined(__powerpc__) +#elif defined(__i386__) || defined(__powerpc__) || defined(__hppa__) static int csr0 = 0x01A00000 | 0x8000; #elif defined(__sparc__) /* The UltraSparc PCI controllers will disconnect at every 64-byte @@ -210,13 +211,15 @@ int next_tick = 3*HZ; int i; + DPRINTK("ENTER\n"); + /* Wake the chip from sleep/snooze mode. */ if (tp->flags & HAS_ACPI) pci_write_config_dword(tp->pdev, 0x40, 0); /* On some chip revs we must set the MII/SYM port before the reset!? */ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) - tulip_outl_CSR6 (tp, 0x00040000); + tulip_outl_csr (tp, 0x00040000, CSR6); /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ outl(0x00000001, ioaddr + CSR0); @@ -311,9 +314,9 @@ tp->csr6 = 0; tp->cur_index = i; tp->nwayset = 0; - if (dev->if_port == 0 && tp->chip_id == DC21041) { + if (dev->if_port == 0 && tp->chip_id == DC21041) tp->nway = 1; - } + if (dev->if_port == 0 && tp->chip_id == DC21142) { if (tp->mii_cnt) { tulip_select_media(dev, 1); @@ -321,8 +324,8 @@ printk(KERN_INFO "%s: Using MII transceiver %d, status " "%4.4x.\n", dev->name, tp->phys[0], tulip_mdio_read(dev, tp->phys[0], 1)); - tulip_outl_CSR6(tp, 0x82020000); - tp->csr6 = 0x820E0000; + tulip_outl_csr(tp, csr6_mask_defstate, CSR6); + tp->csr6 = csr6_mask_hdcap; dev->if_port = 11; outl(0x0000, ioaddr + CSR13); outl(0x0000, ioaddr + CSR14); @@ -371,13 +374,13 @@ tulip_select_media(dev, 1); /* Start the chip's Tx to process setup frame. */ - tulip_outl_CSR6(tp, tp->csr6); - tulip_outl_CSR6(tp, tp->csr6 | 0x2000); + tulip_outl_csr(tp, tp->csr6, CSR6); + tulip_outl_csr(tp, tp->csr6 | csr6_st, CSR6); /* Enable interrupts by setting the interrupt mask. */ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_outl_csr(tp, tp->csr6 | csr6_st | csr6_sr, CSR6); outl(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { @@ -421,6 +424,8 @@ long ioaddr = dev->base_addr; unsigned long flags; + DPRINTK("ENTER\n"); + spin_lock_irqsave (&tp->lock, flags); if (tulip_media_cap[dev->if_port] & MediaIsMII) { @@ -510,8 +515,7 @@ #endif /* Stop and restart the chip's Tx processes . */ - tulip_outl_CSR6(tp, tp->csr6 | 0x0002); - tulip_outl_CSR6(tp, tp->csr6 | 0x2002); + tulip_restart_rxtx(tp, tp->csr6); /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); @@ -529,6 +533,8 @@ struct tulip_private *tp = (struct tulip_private *)dev->priv; int i; + DPRINTK("ENTER\n"); + tp->tx_full = 0; tp->cur_rx = tp->cur_tx = 0; tp->dirty_rx = tp->dirty_tx = 0; @@ -584,12 +590,11 @@ int entry; u32 flag; dma_addr_t mapping; - unsigned long cpuflags; /* Caution: the write order is important here, set the field with the ownership bits last. */ - spin_lock_irqsave(&tp->lock, cpuflags); + spin_lock_irq(&tp->lock); /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % TX_RING_SIZE; @@ -621,7 +626,7 @@ /* Trigger an immediate transmit demand. */ outl(0, dev->base_addr + CSR1); - spin_unlock_irqrestore(&tp->lock, cpuflags); + spin_unlock_irq(&tp->lock); dev->trans_start = jiffies; @@ -642,7 +647,7 @@ outl (0x00000000, ioaddr + CSR7); /* Stop the Tx and Rx processes. */ - tulip_outl_CSR6 (tp, inl (ioaddr + CSR6) & ~0x2002); + tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); /* 21040 -- Leave the card in 10baseT state. */ if (tp->chip_id == DC21040) @@ -839,7 +844,14 @@ { struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; - int csr6 = inl(ioaddr + CSR6) & ~0x00D5; + int csr6, need_lock = 0; + unsigned long flags; + + DPRINTK("ENTER\n"); + + spin_lock_irqsave(&tp->lock, flags); + csr6 = inl(ioaddr + CSR6) & ~0x00D5; + spin_unlock_irqrestore(&tp->lock, flags); tp->csr6 &= ~0x00D5; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ @@ -847,10 +859,14 @@ csr6 |= 0x00C0; /* Unconditionally log net taps. */ printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); + + need_lock = 1; } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well -- accept all multicasts. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; + + need_lock = 1; } else if (tp->flags & MC_HASH_ONLY) { /* Some work-alikes have only a 64-entry hash filter table. */ /* Should verify correctness on big-endian/__powerpc__ */ @@ -860,27 +876,35 @@ if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; + need_lock = 1; } else { mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); + if (tp->chip_id == AX88140) { + spin_lock_irqsave(&tp->lock, flags); outl(2, ioaddr + CSR13); outl(mc_filter[0], ioaddr + CSR14); outl(3, ioaddr + CSR13); outl(mc_filter[1], ioaddr + CSR14); + /* need_lock = 0; */ } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ + spin_lock_irqsave(&tp->lock, flags); outl(mc_filter[0], ioaddr + 0xAC); outl(mc_filter[1], ioaddr + 0xB0); + /* need_lock = 0; */ + } else { + need_lock = 1; } } + } else { u16 *eaddrs, *setup_frm = tp->setup_frame; struct dev_mc_list *mclist; u32 tx_flags = 0x08000000 | 192; int i; - unsigned long flags; /* Note that only the low-address shortword of setup_frame is valid! The values are doubled for big-endian architectures. */ @@ -923,7 +947,7 @@ if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { /* Same setup recently queued, we need not add it. */ } else { - unsigned int entry; + unsigned int entry, dummy = -1; /* Now add this frame to the Tx list. */ @@ -936,7 +960,8 @@ tp->tx_ring[entry].length = (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0; tp->tx_ring[entry].buffer1 = 0; - tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + /* Must set DescOwned later to avoid race with chip */ + dummy = entry; entry = tp->cur_tx++ % TX_RING_SIZE; } @@ -952,6 +977,8 @@ tp->tx_ring[entry].buffer1 = cpu_to_le32(tp->tx_buffers[entry].mapping); tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + if (dummy >= 0) + tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) { netif_stop_queue(dev); tp->tx_full = 1; @@ -961,10 +988,15 @@ outl(0, ioaddr + CSR1); } - - spin_unlock_irqrestore(&tp->lock, flags); } - tulip_outl_CSR6(tp, csr6 | 0x0000); + + if (need_lock) + spin_lock_irqsave(&tp->lock, flags); + + /* Can someone explain to me what the OR here is supposed to accomplish???? */ + tulip_outl_csr(tp, csr6 | 0x0000, CSR6); + + spin_unlock_irqrestore(&tp->lock, flags); } @@ -999,29 +1031,33 @@ ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; - /* init_etherdev ensures qword aligned structures */ + /* init_etherdev ensures aligned and zeroed private structures */ dev = init_etherdev (NULL, sizeof (*tp)); if (!dev) { printk (KERN_ERR PFX "ether device alloc failed, aborting\n"); return -ENOMEM; } - /* We do a request_region() only to register /proc/ioports info. */ - /* Note that proper size is tulip_tbl[chip_idx].chip_name, but... */ - if (!request_region (ioaddr, tulip_tbl[chip_idx].io_size, dev->name)) { + /* grab all resources from both PIO and MMIO regions, as we + * don't want anyone else messing around with our hardware */ + if (!request_region (pci_resource_start (pdev, 0), + pci_resource_len (pdev, 0), + dev->name)) { printk (KERN_ERR PFX "I/O ports (0x%x@0x%lx) unavailable, " "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); goto err_out_free_netdev; } - - if (pci_enable_device(pdev)) { - printk (KERN_ERR PFX "cannot enable PCI device (id %04x:%04x, " - "bus %d, devfn %d), aborting\n", - pdev->vendor, pdev->device, - pdev->bus->number, pdev->devfn); - goto err_out_free_netdev; + if (!request_mem_region (pci_resource_start (pdev, 1), + pci_resource_len (pdev, 1), + dev->name)) { + printk (KERN_ERR PFX "MMIO resource (0x%x@0x%lx) unavailable, " + "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); + goto err_out_free_pio_res; } + if (pci_enable_device(pdev)) + goto err_out_free_mmio_res; + pci_set_master(pdev); pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev); @@ -1044,8 +1080,13 @@ tp->pdev = pdev; tp->base_addr = ioaddr; tp->revision = chip_rev; + tp->csr0 = csr0; spin_lock_init(&tp->lock); + dev->base_addr = ioaddr; + dev->irq = irq; + pdev->driver_data = dev; + #ifdef TULIP_FULL_DUPLEX tp->full_duplex = 1; tp->full_duplex_lock = 1; @@ -1060,8 +1101,17 @@ printk(KERN_INFO "%s: %s rev %d at %#3lx,", dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); + /* bugfix: the ASIX must have a burst limit or horrible things happen. */ + if (chip_idx == AX88140) { + if ((tp->csr0 & 0x3f00) == 0) + tp->csr0 |= 0x2000; + } + else if (chip_idx == DC21143 && chip_rev == 65) + tp->csr0 &= ~0x01000000; + /* Stop the chip's Tx and Rx processes. */ - tulip_outl_CSR6(tp, inl(ioaddr + CSR6) & ~0x2002); + tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); + /* Clear the missed-packet counter. */ (volatile int)inl(ioaddr + CSR8); @@ -1158,20 +1208,6 @@ printk(", IRQ %d.\n", irq); last_irq = irq; - pdev->driver_data = dev; - dev->base_addr = ioaddr; - dev->irq = irq; - tp->csr0 = csr0; - - /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. - And the ASIX must have a burst limit or horrible things happen. */ - if (chip_idx == DC21143 && chip_rev == 65) - tp->csr0 &= ~0x01000000; - else if (chip_idx == AX88140) { - if ((tp->csr0 & 0x3f00) == 0) - tp->csr0 |= 0x2000; - } - /* The lower four bits are the media type. */ if (board_idx >= 0 && board_idx < MAX_UNITS) { tp->default_port = options[board_idx] & 15; @@ -1198,7 +1234,7 @@ else tp->to_advertise = 0x01e1; - /* This is logically part of probe1(), but too complex to write inline. */ + /* This is logically part of _init_one(), but too complex to write inline. */ if (tp->flags & HAS_MEDIA_TABLE) { memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom)); tulip_parse_eeprom(dev); @@ -1280,7 +1316,7 @@ outl(0x00000000, ioaddr + CSR13); outl(0xFFFFFFFF, ioaddr + CSR14); outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ - tulip_outl_CSR6(tp, inl(ioaddr + CSR6) | 0x0200); + tulip_outl_csr(tp, inl(ioaddr + CSR6) | csr6_fd, CSR6); outl(0x0000EF05, ioaddr + CSR13); break; case DC21040: @@ -1295,10 +1331,10 @@ case DC21142: case PNIC2: if (tp->mii_cnt || tulip_media_cap[dev->if_port] & MediaIsMII) { - tulip_outl_CSR6(tp, 0x82020000); + tulip_outl_csr(tp, csr6_mask_defstate, CSR6); outl(0x0000, ioaddr + CSR13); outl(0x0000, ioaddr + CSR14); - tulip_outl_CSR6(tp, 0x820E0000); + tulip_outl_csr(tp, csr6_mask_hdcap, CSR6); } else t21142_start_nway(dev); break; @@ -1306,19 +1342,21 @@ if ( ! tp->mii_cnt) { tp->nway = 1; tp->nwayset = 0; - tulip_outl_CSR6(tp, 0x00420000); + tulip_outl_csr(tp, csr6_ttm | csr6_ca, CSR6); outl(0x30, ioaddr + CSR12); - tulip_outl_CSR6(tp, 0x0001F078); - tulip_outl_CSR6(tp, 0x0201F078); /* Turn on autonegotiation. */ + tulip_outl_csr(tp, 0x0001F078, CSR6); + tulip_outl_csr(tp, 0x0201F078, CSR6); /* Turn on autonegotiation. */ } break; - case MX98713: case COMPEX9881: - tulip_outl_CSR6(tp, 0x00000000); + case MX98713: + case COMPEX9881: + tulip_outl_csr(tp, 0x00000000, CSR6); outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ outl(0x00000001, ioaddr + CSR13); break; - case MX98715: case MX98725: - tulip_outl_CSR6(tp, 0x01a80000); + case MX98715: + case MX98725: + tulip_outl_csr(tp, 0x01a80000, CSR6); outl(0xFFFFFFFF, ioaddr + CSR14); outl(0x00001000, ioaddr + CSR12); break; @@ -1333,6 +1371,12 @@ return 0; +err_out_free_mmio_res: + release_mem_region (pci_resource_start (pdev, 1), + pci_resource_len (pdev, 1)); +err_out_free_pio_res: + release_region (pci_resource_start (pdev, 0), + pci_resource_len (pdev, 0)); err_out_free_netdev: unregister_netdev (dev); kfree (dev); @@ -1376,8 +1420,10 @@ tp->rx_ring, tp->rx_ring_dma); unregister_netdev(dev); - release_region(dev->base_addr, - tulip_tbl[tp->chip_id].io_size); + release_mem_region (pci_resource_start (pdev, 1), + pci_resource_len (pdev, 1)); + release_region (pci_resource_start (pdev, 0), + pci_resource_len (pdev, 0)); kfree(dev); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wan/comx.c linux.ac/drivers/net/wan/comx.c --- linux.vanilla/drivers/net/wan/comx.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wan/comx.c Thu May 25 20:47:55 2000 @@ -81,6 +81,10 @@ static struct comx_hardware *comx_channels = NULL; static struct comx_protocol *comx_lines = NULL; +static int comx_mkdir(struct inode *, struct dentry *, int); +static int comx_rmdir(struct inode *, struct dentry *); +static struct dentry *comx_lookup(struct inode *, struct dentry *); + static struct inode_operations comx_root_inode_ops = { lookup: comx_lookup, mkdir: comx_mkdir, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wan/cycx_main.c linux.ac/drivers/net/wan/cycx_main.c --- linux.vanilla/drivers/net/wan/cycx_main.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wan/cycx_main.c Fri Jun 9 15:53:02 2000 @@ -13,6 +13,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ +* 2000/07/06 acme __exit at cyclomx_cleanup * 2000/04/02 acme dprintk and cycx_debug * module_init/module_exit * 2000/01/21 acme rename cyclomx_open to cyclomx_mod_inc_use_count @@ -59,7 +60,7 @@ /* Defines & Macros */ #define DRV_VERSION 0 /* version number */ -#define DRV_RELEASE 7 /* release (minor version) number */ +#define DRV_RELEASE 8 /* release (minor version) number */ #define MAX_CARDS 1 /* max number of adapters */ #ifndef CONFIG_CYCLOMX_CARDS /* configurable option */ @@ -102,7 +103,7 @@ * < 0 error. * Context: process */ -int __init cyclomx_init (void) +static int __init cyclomx_init (void) { int cnt, err = 0; @@ -156,7 +157,7 @@ * o unregister all adapters from the WAN router * o release all remaining system resources */ -void cyclomx_cleanup (void) +static void __exit cyclomx_cleanup (void) { int i = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wan/sbni.c linux.ac/drivers/net/wan/sbni.c --- linux.vanilla/drivers/net/wan/sbni.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wan/sbni.c Sat Jun 10 21:39:44 2000 @@ -334,7 +334,7 @@ if(base_addr > 0x1ff) /* Check a single specified location. */ return sbni_probe1(dev, base_addr); else if(base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for(i = 0; (base_addr = netcard_portlist[i]); i++) { if(!check_region(base_addr, SBNI_IO_EXTENT) && base_addr != 1) @@ -345,7 +345,7 @@ return 0; } } - return ENODEV; + return -ENODEV; } #endif /* have devlist*/ @@ -408,7 +408,7 @@ } if(bad_card) - return ENODEV; + return -ENODEV; else outb(0, ioaddr + CSR0); if(dev->irq < 2) @@ -422,7 +422,7 @@ if(autoirq == 0) { printk("sbni probe at %#x failed to detect IRQ line\n", ioaddr); - return EAGAIN; + return -EAGAIN; } } /* clear FIFO buffer */ @@ -436,7 +436,7 @@ if (irqval) { printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); - return EAGAIN; + return -EAGAIN; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wan/sdladrv.c linux.ac/drivers/net/wan/sdladrv.c --- linux.vanilla/drivers/net/wan/sdladrv.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wan/sdladrv.c Fri May 26 14:36:51 2000 @@ -1983,8 +1983,9 @@ while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) != NULL) { - pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD, - &PCI_subsys_vendor); + if (pci_enable_device(pci_dev)) + continue; + PCI_subsys_vendor = pci_dev->subsystem_vendor; if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) continue; hw->pci_dev = pci_dev; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wavelan.c linux.ac/drivers/net/wavelan.c --- linux.vanilla/drivers/net/wavelan.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wavelan.c Sat Jun 10 21:39:44 2000 @@ -3623,7 +3623,7 @@ /* Check if the base address if available. */ if (check_region(ioaddr, sizeof(ha_t))) - return EADDRINUSE; /* ioaddr already used */ + return -EADDRINUSE; /* ioaddr already used */ /* Reset host interface */ wv_hacr_reset(ioaddr); @@ -3649,7 +3649,7 @@ "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n", ioaddr, mac[0], mac[1], mac[2]); #endif - return ENODEV; + return -ENODEV; } /************************ INTERRUPT HANDLING ************************/ @@ -4002,7 +4002,7 @@ "%s: wavelan_config(): could not wavelan_map_irq(%d).\n", dev->name, irq_mask); #endif - return EAGAIN; + return -EAGAIN; } dev->irq = irq; @@ -4095,7 +4095,7 @@ printk(KERN_WARNING "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n", dev->name, wv_struct_check()); - return ENODEV; + return -ENODEV; } #endif /* STRUCT_CHECK */ @@ -4109,7 +4109,7 @@ "%s: wavelan_probe(): invalid base address\n", dev->name); #endif - return ENXIO; + return -ENXIO; } /* Check a single specified location. */ @@ -4157,7 +4157,7 @@ dev->name); #endif - return ENODEV; + return -ENODEV; } /****************************** MODULE ******************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/wd.c linux.ac/drivers/net/wd.c --- linux.vanilla/drivers/net/wd.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/wd.c Sat Jun 10 21:39:44 2000 @@ -94,7 +94,7 @@ if (base_addr > 0x1ff) /* Check a single specified location. */ return wd_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; wd_portlist[i]; i++) { int ioaddr = wd_portlist[i]; @@ -104,7 +104,7 @@ return 0; } - return ENODEV; + return -ENODEV; } #endif @@ -122,11 +122,7 @@ if (inb(ioaddr + 8) == 0xff /* Extra check to avoid soundcard. */ || inb(ioaddr + 9) == 0xff || (checksum & 0xff) != 0xFF) - return ENODEV; - - /* Looks like we have a card. Make sure 8390 support is available. */ - if (load_8390_module("wd.c")) - return -ENOSYS; + return -ENODEV; /* We should have a "dev" from Space.c or the static module table. */ if (dev == NULL) { @@ -268,7 +264,7 @@ printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return EAGAIN; + return -EAGAIN; } /* OK, were are certain this is going to work. Setup the device. */ @@ -468,6 +464,9 @@ { int this_dev, found = 0; + if (load_8390_module("wd.c")) + return -ENOSYS; + for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { struct net_device *dev = &dev_wd[this_dev]; dev->irq = irq[this_dev]; @@ -482,14 +481,13 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) { /* Got at least one. */ - lock_8390_module(); return 0; } + unload_8390_module(); return -ENXIO; } found++; } - lock_8390_module(); return 0; } @@ -507,9 +505,9 @@ release_region(ioaddr, WD_IO_EXTENT); unregister_netdev(dev); kfree(priv); - unlock_8390_module(); } } + unload_8390_module(); } #endif /* MODULE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/znet.c linux.ac/drivers/net/znet.c --- linux.vanilla/drivers/net/znet.c Thu May 25 17:37:50 2000 +++ linux.ac/drivers/net/znet.c Sat Jun 10 21:39:44 2000 @@ -218,7 +218,7 @@ if (p >= (char *)phys_to_virt(0x100000)) { if (znet_debug > 1) printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); - return ENODEV; + return -ENODEV; } netinfo = (struct netidblk *)p; dev->base_addr = netinfo->iobase1; @@ -256,7 +256,7 @@ || request_dma(zn.rx_dma,"ZNet rx") || request_dma(zn.tx_dma,"ZNet tx")) { printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name); - return EBUSY; + return -EBUSY; } /* Allocate buffer memory. We can cross a 128K boundary, so we diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/BUGS-parport linux.ac/drivers/parport/BUGS-parport --- linux.vanilla/drivers/parport/BUGS-parport Thu May 25 17:38:20 2000 +++ linux.ac/drivers/parport/BUGS-parport Mon May 29 19:31:42 2000 @@ -1,5 +1,6 @@ Currently known (or at least suspected) bugs in parport: -o lp doesn't allow you to read status while printing is in progress. +o lp doesn't allow you to read status while printing is in progress (is + this still true?). -See . +See . diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/ChangeLog linux.ac/drivers/parport/ChangeLog --- linux.vanilla/drivers/parport/ChangeLog Thu May 25 17:38:22 2000 +++ linux.ac/drivers/parport/ChangeLog Sun Jun 4 22:21:48 2000 @@ -1,3 +1,23 @@ +2000-05-28 Gunther Mayer + + * Fix PCI ID printk for non-superio PCI cards. + +2000-05-28 Tim Waugh + + * share.c (call_driver_chain): Get the driverlist_lock. + (parport_register_device): Make sure that port->devices always + looks consistent. + (parport_register_driver): Ensure that parport drivers are given + parameters that are valid for the duration of the callback by + locking the portlist against changes. + (parport_unregister_driver): Likewise. + (parport_claim): Don't overwrite flags. + +2000-05-28 Tim Waugh + + * daisy.c (assign_addrs): Avoid double-probing daisy-chain devices + if the first probe succeeds. + 2000-05-16 Tim Waugh * share.c (parport_claim): Fix SMP race. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/TODO-parport linux.ac/drivers/parport/TODO-parport --- linux.vanilla/drivers/parport/TODO-parport Thu May 25 17:38:20 2000 +++ linux.ac/drivers/parport/TODO-parport Mon May 29 19:32:05 2000 @@ -17,4 +17,4 @@ 4. A better PLIP (make use of bidirectional/ECP/EPP ports). -See . +See . diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/daisy.c linux.ac/drivers/parport/daisy.c --- linux.vanilla/drivers/parport/daisy.c Thu May 25 17:38:22 2000 +++ linux.ac/drivers/parport/daisy.c Mon May 29 19:33:02 2000 @@ -428,6 +428,7 @@ unsigned char s, last_dev; unsigned char daisy; int thisdev = numdevs; + int detected; char *deviceid; parport_data_forward (port); @@ -484,8 +485,9 @@ } parport_write_data (port, 0xff); udelay (2); + detected = numdevs - thisdev; DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name, - numdevs - thisdev); + detected); /* Ask the new devices to introduce themselves. */ deviceid = kmalloc (1000, GFP_KERNEL); @@ -495,7 +497,7 @@ parport_device_id (thisdev, deviceid, 1000); kfree (deviceid); - return numdevs - thisdev; + return detected; } /* Find a device with a particular manufacturer and model string, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/parport_pc.c linux.ac/drivers/parport/parport_pc.c --- linux.vanilla/drivers/parport/parport_pc.c Thu May 25 17:38:22 2000 +++ linux.ac/drivers/parport/parport_pc.c Mon May 29 19:34:15 2000 @@ -2430,8 +2430,9 @@ def.) */ /* TODO: test if sharing interrupts works */ printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " - "I/O at %#lx(%#lx)\n", parport_pc_pci_tbl[i].vendor, - parport_pc_pci_tbl[i].device, io_lo, io_hi); + "I/O at %#lx(%#lx)\n", + parport_pc_pci_tbl[i + last_sio].vendor, + parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi); if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, dev)) count++; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/parport/share.c linux.ac/drivers/parport/share.c --- linux.vanilla/drivers/parport/share.c Thu May 25 17:38:22 2000 +++ linux.ac/drivers/parport/share.c Mon May 29 19:38:55 2000 @@ -87,12 +87,14 @@ { struct parport_driver *drv; + spin_lock (&driverlist_lock); for (drv = driver_chain; drv; drv = drv->next) { if (attach) drv->attach (port); else drv->detach (port); } + spin_unlock (&driverlist_lock); } /* Ask kmod for some lowlevel drivers. */ @@ -126,8 +128,12 @@ driver_chain = drv; spin_unlock (&driverlist_lock); + /* We have to take the portlist lock for this to be sure + * that port is valid for the duration of the callback. */ + spin_lock (&parportlist_lock); for (port = portlist; port; port = port->next) drv->attach (port); + spin_unlock (&parportlist_lock); if (!portlist) get_lowlevel_driver (); @@ -171,8 +177,10 @@ /* Call the driver's detach routine for each * port to clean up any resources that the * attach routine acquired. */ + spin_lock (&parportlist_lock); for (port = portlist; port; port = port->next) drv->detach (port); + spin_unlock (&parportlist_lock); return; } @@ -195,6 +203,8 @@ struct parport *parport_enumerate(void) { + /* Don't use this: use parport_register_driver instead. */ + if (!portlist) get_lowlevel_driver (); @@ -297,7 +307,18 @@ * This function must not run from an irq handler so we don' t need * to clear irq on the local CPU. -arca */ + spin_lock(&parportlist_lock); + + /* We are locked against anyone else performing alterations, but + * because of parport_enumerate people can still _read_ the list + * while we are changing it; so be careful.. + * + * It's okay to have portlist_tail a little bit out of sync + * since it's only used for changing the list, not for reading + * from it. + */ + if (portlist_tail) portlist_tail->next = tmp; portlist_tail = tmp; @@ -403,6 +424,10 @@ #endif spin_lock(&parportlist_lock); + + /* We are protected from other people changing the list, but + * they can see see it (using parport_enumerate). So be + * careful about the order of writes.. */ if (portlist == port) { if ((portlist = port->next) == NULL) portlist_tail = NULL; @@ -418,6 +443,7 @@ } spin_unlock(&parportlist_lock); + /* Yes, parport_enumerate _is_ unsafe. Don't use it. */ if (!port->devices) free_port (port); } @@ -565,6 +591,9 @@ } tmp->next = port->physport->devices; + wmb(); /* Make sure that tmp->next is written before it's + added to the list; see comments marked 'no locking + required' */ if (port->physport->devices) port->physport->devices->prev = tmp; port->physport->devices = tmp; @@ -647,6 +676,11 @@ * free up the resources. */ if (port->ops == &dead_ops && !port->devices) free_port (port); + + /* Yes, that's right, someone _could_ still have a pointer to + * port, if they used parport_enumerate. That's why they + * shouldn't use it (and use parport_register_driver instead).. + */ } /** @@ -702,7 +736,7 @@ dev->waiting = 0; /* Take ourselves out of the wait list again. */ - spin_lock_irqsave (&port->waitlist_lock, flags); + spin_lock_irq (&port->waitlist_lock); if (dev->waitprev) dev->waitprev->waitnext = dev->waitnext; else @@ -711,7 +745,7 @@ dev->waitnext->waitprev = dev->waitprev; else port->waittail = dev->waitprev; - spin_unlock_irqrestore (&port->waitlist_lock, flags); + spin_unlock_irq (&port->waitlist_lock); dev->waitprev = dev->waitnext = NULL; } @@ -878,7 +912,7 @@ } /* Nobody was waiting, so walk the list to see if anyone is - interested in being woken up. */ + interested in being woken up. (Note: no locking required) */ for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) { if (pd->wakeup && pd != dev) pd->wakeup(pd->private); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/pci/pci.c linux.ac/drivers/pci/pci.c --- linux.vanilla/drivers/pci/pci.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/pci/pci.c Sat May 27 15:40:24 2000 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/pci/pci.ids linux.ac/drivers/pci/pci.ids --- linux.vanilla/drivers/pci/pci.ids Thu May 25 17:46:15 2000 +++ linux.ac/drivers/pci/pci.ids Tue Jun 6 17:43:20 2000 @@ -238,11 +238,12 @@ 100a Phoenix Technologies 100b National Semiconductor Corporation 0001 DP83810 - 0002 87415 + 0002 87415/87560 IDE + 000e 87560 Legacy I/O 000f OHCI Compliant FireWire Controller 0011 National PCI System I/O 0012 USB Controller - d001 87410 + d001 87410 IDE 100c Tseng Labs Inc 3202 ET4000/W32p rev A 3205 ET4000/W32p rev B @@ -976,6 +977,7 @@ 1058 Electronics & Telecommunications RSH 1059 Teknor Industrial Computers Inc 105a Promise Technology, Inc. + 4d30 20267 4d33 20246 4d38 20262 5300 DC5300 @@ -1228,6 +1230,7 @@ 0646 PCI0646 0647 PCI0647 0648 PCI0648 + 0649 PCI0649 0650 PBC0650A 0670 USB0670 0673 USB0673 @@ -1458,6 +1461,8 @@ 5055 3c555 Laptop Hurricane 5057 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card + 5b57 3c575 [Megahertz] 10/100 LAN CardBus + 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus 5157 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card 5257 3CCFE575CT Cyclone CardBus @@ -1469,6 +1474,7 @@ 5970 3c597 EISA Fast Demon/Vortex 6560 3CCFE656 Cyclone CardBus 6562 3CCFEM656 Cyclone CardBus + 6564 3CCFEM656 Cyclone CardBus (0x6564) 7646 3cSOHO100-TX Hurricane 8811 Token ring 9000 3c900 10BaseT [Boomerang] @@ -1509,6 +1515,8 @@ 10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC 9800 3c980-TX [Fast Etherlink XL Server Adapter] 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter + 9805 3c980-TX [10/100 Base-TX NIC(Python-T)] + 10b7 9805 3c980 10/100 Base-TX NIC(Python-T) 10b8 Standard Microsystems Corp [SMC] 0005 83C170QF 1055 e000 LANEPIC @@ -4517,6 +4525,13 @@ 11d4 0048 SoundMAX Integrated Digital Audio 2426 82801AB 82810 AC'97 Modem 2428 82801AB 82810 PCI Bridge + 2440 82820 820 (Camino 2) Chipset ISA Bridge (ICH2) + 2442 82820 820 (Camino 2) Chipset USB (Hub A) + 2443 82820 820 (Camino 2) Chipset SMBus + 2444 82820 820 (Camino 2) Chipset USB (Hub B) + 2449 82820 820 (Camino 2) Chipset Ethernet + 244b 82820 820 (Camino 2) Chipset IDE U100 + 244e 82820 820 (Camino 2) Chipset PCI 2500 82820 820 (Camino) Chipset Host Bridge (MCH) 1043 801c P3C-2000 system chipset 2501 82820 820 (Camino) Chipset Host Bridge (MCH) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/pci/quirks.c linux.ac/drivers/pci/quirks.c --- linux.vanilla/drivers/pci/quirks.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/pci/quirks.c Wed May 31 11:21:50 2000 @@ -138,7 +138,7 @@ * 0xE0 (64 bytes of ACPI registers) * 0xE2 (32 bytes of SMB registers) */ -static void __init quirk_ali7101(struct pci_dev *dev) +static void __init quirk_ali7101_acpi(struct pci_dev *dev) { u16 region; @@ -153,7 +153,7 @@ * 0x40 (64 bytes of ACPI registers) * 0x90 (32 bytes of SMB registers) */ -static void __init quirk_piix4acpi(struct pci_dev *dev) +static void __init quirk_piix4_acpi(struct pci_dev *dev) { u32 region; @@ -181,6 +181,26 @@ } /* + * PIIX3 USB: We have to disable USB interrupts that are + * hardwired to PIRQD# and may be shared with an + * external device. + * + * Legacy Support Register (LEGSUP): + * bit13: USB PIRQ Enable (USBPIRQDEN), + * bit4: Trap/SMI ON IRQ Enable (USBSMIEN). + * + * We mask out all r/wc bits, too. + */ +static void __init quirk_piix3usb(struct pci_dev *dev) +{ + u16 legsup; + + pci_read_config_word(dev, 0xc0, &legsup); + legsup &= 0x50ef; + pci_write_config_word(dev, 0xc0, legsup); +} + +/* * The main table of quirks. */ @@ -209,10 +229,11 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4acpi }, - { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3usb }, { 0 } }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/pcmcia/yenta.c linux.ac/drivers/pcmcia/yenta.c --- linux.vanilla/drivers/pcmcia/yenta.c Thu May 25 17:38:23 2000 +++ linux.ac/drivers/pcmcia/yenta.c Tue May 30 15:19:04 2000 @@ -788,7 +788,7 @@ */ if (pci_enable_device(dev)) return -1; - if (!dev->resource[0].start) { + if (!pci_resource_start(dev, 0)) { printk("No cardbus resource!\n"); return -1; } @@ -797,7 +797,7 @@ * Ok, start setup.. Map the cardbus registers, * and request the IRQ. */ - socket->base = ioremap(dev->resource[0].start, 0x1000); + socket->base = ioremap(pci_resource_start(dev, 0), 0x1000); if (!socket->base) return -1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/pcikbd.c linux.ac/drivers/sbus/char/pcikbd.c --- linux.vanilla/drivers/sbus/char/pcikbd.c Thu May 25 17:38:10 2000 +++ linux.ac/drivers/sbus/char/pcikbd.c Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.46 2000/05/03 06:37:05 davem Exp $ +/* $Id: pcikbd.c,v 1.47 2000/06/09 07:35:40 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -737,8 +737,7 @@ spin_unlock_irqrestore(&pcikbd_lock, flags); - if (queue->fasync) - kill_fasync(queue->fasync, SIGIO, POLL_IN); + kill_fasync(&queue->fasync, SIGIO, POLL_IN); wake_up_interruptible(&queue->proc_list); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/sunkbd.c linux.ac/drivers/sbus/char/sunkbd.c --- linux.vanilla/drivers/sbus/char/sunkbd.c Thu May 25 17:38:10 2000 +++ linux.ac/drivers/sbus/char/sunkbd.c Sat May 27 22:00:30 2000 @@ -1310,8 +1310,7 @@ } spin_unlock_irqrestore(&kbd_queue_lock, flags); - if (kb_fasync) - kill_fasync (kb_fasync, SIGIO, POLL_IN); + kill_fasync (&kb_fasync, SIGIO, POLL_IN); wake_up_interruptible (&kbd_wait); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sbus/char/sunmouse.c linux.ac/drivers/sbus/char/sunmouse.c --- linux.vanilla/drivers/sbus/char/sunmouse.c Thu May 25 17:38:10 2000 +++ linux.ac/drivers/sbus/char/sunmouse.c Sat May 27 22:00:30 2000 @@ -147,8 +147,7 @@ spin_unlock_irqrestore(&sunmouse.lock, flags); - if (sunmouse.fasync) - kill_fasync (sunmouse.fasync, SIGIO, POLL_IN); + kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN); wake_up_interruptible (&sunmouse.proc_list); } @@ -382,8 +381,7 @@ /* We just completed a transaction, wake up whoever is awaiting * this event. */ - if (sunmouse.fasync) - kill_fasync (sunmouse.fasync, SIGIO, POLL_IN); + kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN); wake_up_interruptible(&sunmouse.proc_list); } return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.c linux.ac/drivers/scsi/3w-xxxx.c --- linux.vanilla/drivers/scsi/3w-xxxx.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/3w-xxxx.c Tue May 30 15:21:26 2000 @@ -565,6 +565,8 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n"); while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, TW_DEVICE_ID, tw_pci_dev))) { + if (pci_enable_device(tw_pci_dev)) + continue; /* Prepare temporary device extension */ tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC); if (tw_dev == NULL) { @@ -582,11 +584,11 @@ } /* Calculate the cards register addresses */ - tw_dev->registers.base_addr = tw_pci_dev->resource[0].start; - tw_dev->registers.control_reg_addr = (tw_pci_dev->resource[0].start & ~15); - tw_dev->registers.status_reg_addr = ((tw_pci_dev->resource[0].start & ~15) + 0x4); - tw_dev->registers.command_que_addr = ((tw_pci_dev->resource[0].start & ~15) + 0x8); - tw_dev->registers.response_que_addr = ((tw_pci_dev->resource[0].start & ~15) + 0xC); + tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0); + tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0); + tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4; + tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8; + tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC; /* Save pci_dev struct to device extension */ tw_dev->tw_pci_dev = tw_pci_dev; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/53c7,8xx.c linux.ac/drivers/scsi/53c7,8xx.c --- linux.vanilla/drivers/scsi/53c7,8xx.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/53c7,8xx.c Tue May 30 15:21:26 2000 @@ -1412,8 +1412,10 @@ " perhaps you specified an incorrect PCI bus, device, or function.\n", error); return -1; } - io_port = pdev->resource[0].start; - base = pdev->resource[1].start; + if (pci_enable_device(pdev)) + return -1; + io_port = pci_resource_start(pdev, 0); + base = pci_resource_start(pdev, 1); irq = pdev->irq; /* If any one ever clones the NCR chips, this will have to change */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/AM53C974.c linux.ac/drivers/scsi/AM53C974.c --- linux.vanilla/drivers/scsi/AM53C974.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/AM53C974.c Tue May 30 15:21:26 2000 @@ -616,27 +616,23 @@ * * Returns : number of host adapters detected **************************************************************************/ -static __inline__ int AM53C974_pci_detect(Scsi_Host_Template * tpnt) +static inline int AM53C974_pci_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ struct pci_dev *pdev = NULL; unsigned short command; while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI, pdev))) { + if (pci_enable_device(pdev)) + continue; pci_read_config_word(pdev, PCI_COMMAND, &command); /* check whether device is I/O mapped -- should be */ if (!(command & PCI_COMMAND_IO)) continue; - /* PCI Spec 2.1 states that it is either the driver's or the PCI card's responsibility - to set the PCI Master Enable Bit if needed. - (from Mark Stockton ) */ - if (!(command & PCI_COMMAND_MASTER)) { - command |= PCI_COMMAND_MASTER; - printk("PCI Master Bit has not been set. Setting...\n"); - pci_write_config_word(pdev, PCI_COMMAND, command); - } + pci_set_master (pdev); + /* everything seems OK now, so initialize */ if (AM53C974_init(tpnt, pdev)) count++; @@ -696,7 +692,7 @@ instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata)); hostdata = (struct AM53C974_hostdata *) instance->hostdata; instance->base = 0; - instance->io_port = pdev->resource[0].start; + instance->io_port = pci_resource_start(pdev, 0); instance->irq = pdev->irq; instance->dma_channel = -1; AM53C974_setio(instance); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/BusLogic.c linux.ac/drivers/scsi/BusLogic.c --- linux.vanilla/drivers/scsi/BusLogic.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/BusLogic.c Tue May 30 15:21:26 2000 @@ -771,12 +771,15 @@ 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->resource[0].start; - unsigned long BaseAddress1 = PCI_Device->resource[1].start; + unsigned long BaseAddress0 = pci_resource_start(PCI_Device, 0); + unsigned long BaseAddress1 = pci_resource_start(PCI_Device, 1); BusLogic_IO_Address_T IO_Address = BaseAddress0; BusLogic_PCI_Address_T PCI_Address = BaseAddress1; + + if (pci_enable_device(PCI_Device)) + continue; - if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO)) + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0); @@ -784,7 +787,7 @@ NULL, Bus, Device, IO_Address); continue; } - if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO) { BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1); @@ -973,7 +976,10 @@ unsigned char Bus = PCI_Device->bus->number; unsigned char Device = PCI_Device->devfn >> 3; unsigned int IRQ_Channel = PCI_Device->irq; - BusLogic_IO_Address_T IO_Address = PCI_Device->resource[0].start; + BusLogic_IO_Address_T IO_Address = pci_resource_start(PCI_Device, 0); + + if (pci_enable_device(PCI_Device)) + continue; if (IO_Address == 0 || IRQ_Channel == 0) continue; for (i = 0; i < BusLogic_ProbeInfoCount; i++) @@ -1017,12 +1023,16 @@ 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->resource[0].start; - unsigned long BaseAddress1 = PCI_Device->resource[1].start; + unsigned long BaseAddress0 = pci_resource_start(PCI_Device, 0); + unsigned long BaseAddress1 = pci_resource_start(PCI_Device, 1); BusLogic_IO_Address_T IO_Address = BaseAddress0; BusLogic_PCI_Address_T PCI_Address = BaseAddress1; + + if (pci_enable_device(PCI_Device)) + continue; + #ifndef CONFIG_SCSI_OMIT_FLASHPOINT - if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO)) + if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) { BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0); @@ -1030,7 +1040,7 @@ NULL, Bus, Device, IO_Address); continue; } - if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) { BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ChangeLog.ncr53c8xx linux.ac/drivers/scsi/ChangeLog.ncr53c8xx --- linux.vanilla/drivers/scsi/ChangeLog.ncr53c8xx Thu May 25 17:38:05 2000 +++ linux.ac/drivers/scsi/ChangeLog.ncr53c8xx Mon Jun 5 19:48:04 2000 @@ -1,3 +1,6 @@ +Thu May 11 12:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.3b + Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2i - Return value 1 (instead of 0) from the driver setup routine. @@ -14,6 +17,11 @@ that supply SCSI_DATA_NONE direction (this avoids some BUG() statement in the PCI code when a data buffer is also supplied). +Thu Mar 16 9:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.3b-3 + - Added exclusion for the 53C1010 and 53C1010_66 chips + to the driver (change to sym53c8xx_comm.h). + Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2g - Add the file sym53c8xx_comm.h that collects code that should @@ -31,6 +39,40 @@ - Get data transfer direction from the scsi command structure (Scsi_Cmnd) when this information is available. +Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 3.2g + - Add the file sym53c8xx_comm.h that collects code that should + be shared by sym53c8xx and ncr53c8xx drivers. For now, it is + a header file that is only included by the ncr53c8xx driver, + but things will be cleaned up later. This code addresses + notably: + * Chip detection and PCI related initialisations + * NVRAM detection and reading + * DMA mapping + * Boot setup command + * And some other ... + - Add support for the new dynamic dma mapping kernel interface. + Requires Linux-2.3.47 (tested with pre-2.3.47-6). + - Get data transfer direction from the scsi command structure + (Scsi_Cmnd) when this information is available. + +Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * revision pre-3.3b-1 + - Merge parallel driver series 3.31 and 3.2e + +Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.31 + - Added support for mounting disks on wide-narrow-wide + scsi configurations. + - Built off of version 3.30 + +Mon Jan 10 13:30 2000 Pam Delaney (pam.delaney@lsil.com) + * revision 3.30 + - Added capability to use the integrity checking code + in the kernel (optional). + - Disabled support for the 53C1010. + - Built off of version 3.2c + Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2e - Add year 2000 copyright. @@ -94,7 +136,7 @@ * revision 3.2 (8xx-896 driver bundle) - Only define the host template in ncr53c8xx.h and include the sym53c8xx_defs.h file. - - Declare static all symbols that donnot need to be visible from + - Declare static all symbols that do not need to be visible from outside the driver code. - Add 'excl' boot command option that allows to pass to the driver io address of devices not to attach. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ChangeLog.sym53c8xx linux.ac/drivers/scsi/ChangeLog.sym53c8xx --- linux.vanilla/drivers/scsi/ChangeLog.sym53c8xx Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/ChangeLog.sym53c8xx Mon Jun 5 19:48:23 2000 @@ -1,9 +1,20 @@ +Thu May 11 12:40 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.6b + - Merged version. + Mon Apr 24 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5m - Return value 1 (instead of 0) from the driver setup routine. - - Donnot enable PCI DAC cycles. This just broke support for + - Do not enable PCI DAC cycles. This just broke support for SYM534C896 on sparc64. Problem fixed by David S. Miller. +Fri Apr 14 9:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.6b-9 + - Added 53C1010_66 support. + - Small fix to integrity checking code. + - Removed requirement for integrity checking if want to run + at ultra 3. + Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5l - Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that @@ -12,6 +23,16 @@ that supply SCSI_DATA_NONE direction (this avoids some BUG() statement in the PCI code when a data buffer is also supplied). +Sat Mar 11 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * version sym53c8xx-1.6b-5 + - Test against expected data transfer direction from SCRIPTS. + - Add support for the new dynamic dma mapping kernel interface. + Requires Linux-2.3.47 (tested with pre-2.3.47-6). + Many thanks to David S. Miller for his preliminary changes + that have been useful guidelines. + - Get data transfer direction from the scsi command structure + (Scsi_Cmnd) with kernels that provide this information. + Mon Mar 6 23:30 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5k - Test against expected data transfer direction from SCRIPTS. @@ -21,6 +42,16 @@ - Miscellaneous (minor) fixes in the code added in driver version 1.5j. +Mon Feb 14 4:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-pre-1.6b-2. + - Updated the SCRIPTS error handling of the SWIDE + condition - to remove any reads of the sbdl + register. Changes needed because the 896 and 1010 + chips will check parity in some special circumstances. + This will cause a parity error interrupt if not in + data phase. Changes based on those made in the + FreeBSD driver version 1.3.2. + Sun Feb 20 11:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5j - Add support for the new dynamic dma mapping kernel interface. @@ -35,6 +66,26 @@ - Fix an old bug that only affected 896 rev. 1 when driver profile support option was set in kernel configuration. +Fri Jan 14 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-pre-1.6b-1. + - Merge parallel driver series 1.61 and 1.5e + +Tue Jan 11 14:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.61 + - Added support for mounting disks on wide-narrow-wide + scsi configurations. + - Modified offset to be a maximum of 31 in ST mode, + 62 in DT mode. + - Based off of 1.60 + +Mon Jan 10 10:00 2000 Pam Delaney (pam.delaney@lsil.com) + * version sym53c8xx-1.60 + - Added capability to use the integrity checking code + in the kernel (optional). + - Added PPR negotiation. + - Added support for 53C1010 Ultra 3 part. + - Based off of 1.5f + Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5h - Add year 2000 copyright. @@ -118,7 +169,7 @@ Sat Jun 5 11:00 1999 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5c - - Donnot negotiate on auto-sense if we are currently using 8 bit + - Do not negotiate on auto-sense if we are currently using 8 bit async transfer for the target. - Only check for SISL/RAID on i386 platforms. (A problem has been reported on PPC with that code). @@ -179,7 +230,7 @@ - Do some work in SCRIPTS after the SELECT instruction and prior to testing for a PHASE. SYMBIOS say this feature is working fine. (Btw, only problems with Toshiba 3401B had been reported). - - Measure the PCI clock speed and donnot attach controllers if + - Measure the PCI clock speed and do not attach controllers if result is greater than 37 MHz. Since the precision of the algorithm (from Stefan Esser) is better than 2%, this should be fine. @@ -353,7 +404,7 @@ transactions since those early chip revisions may use such on LOAD/STORE instructions (work-around). - Remove some useless and bloat code from the pci init stuff. - - Donnot use the readX()/writeX() kernel functions for __i386__, + - Do not use the readX()/writeX() kernel functions for __i386__, since they perform useless masking operations in order to deal with broken driver in 2.1.X kernel. @@ -379,7 +430,7 @@ * version pre-sym53c8xx-0.12 - Damned! I just broke the driver for Alpha by leaving a stale instruction in the source code. Hopefully fixed. - - Donnot set PFEN when it is useless. Doing so we are sure that BOF + - Do not set PFEN when it is useless. Doing so we are sure that BOF will be active, since the manual appears to be very unclear on what feature is actually used by the chip when both PFEN and BOF are set. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/NCR53C9x.c linux.ac/drivers/scsi/NCR53C9x.c --- linux.vanilla/drivers/scsi/NCR53C9x.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/NCR53C9x.c Sat May 27 16:02:11 2000 @@ -3578,7 +3578,7 @@ } #else /* For SMP we only service one ESP on the list list at our IRQ level! */ -static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) +void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct NCR_ESP *esp; unsigned long flags; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/README.ncr53c8xx linux.ac/drivers/scsi/README.ncr53c8xx --- linux.vanilla/drivers/scsi/README.ncr53c8xx Thu May 25 17:38:05 2000 +++ linux.ac/drivers/scsi/README.ncr53c8xx Mon Jun 5 19:47:42 2000 @@ -168,6 +168,12 @@ 895 Y Y FAST40 80 MB/s Y Y 895A Y Y FAST40 80 MB/s Y Y 896 Y Y FAST40 80 MB/s Y Y +897 Y Y FAST40 80 MB/s Y Y +1510D Y Y FAST40 80 MB/s Y Y +1010 Y Y FAST80 160 MB/s N Y +1010_66* Y Y FAST80 160 MB/s N Y + +* Chip supports 33MHz and 66MHz PCI buses. Summary of other supported features: @@ -686,11 +692,12 @@ Invalidate. 10.2.5 Ultra SCSI support - Only apply to 860, 875 and 895 controllers. + Only apply to 860, 875, 895, 895a, 896, 1010 and 1010_66 controllers. Have no effect with other ones. + ultra:n All ultra speeds enabled ultra:2 Ultra2 enabled ultra:1 Ultra enabled - ultra:n disabled + ultra:0 Ultra speeds disabled 10.2.6 Default number of tagged commands tags:0 (or tags:1 ) tagged command queuing disabled @@ -822,6 +829,7 @@ 0x0: No check. 0x1: Check and donnot attach the controller on error. 0x2: Check and just warn on error. + 0x4: Disable SCSI bus integrity checking. 10.2.20 Exclude a host from being attached excl= diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/advansys.c linux.ac/drivers/scsi/advansys.c --- linux.vanilla/drivers/scsi/advansys.c Thu May 25 17:38:03 2000 +++ linux.ac/drivers/scsi/advansys.c Tue May 30 15:21:26 2000 @@ -4699,7 +4699,8 @@ NULL) { pci_device_id_cnt++; } else { - pci_devicep[pci_card_cnt_max++] = pci_devp; + if (pci_enable_device(pci_devp) == 0) + pci_devicep[pci_card_cnt_max++] = pci_devp; } } @@ -4739,7 +4740,7 @@ #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13) iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; #else /* version >= v2.3.13 */ - iop = pci_devp->resource[0].start & PCI_IOADDRESS_MASK; + iop = pci_resource_start(pci_devp, 0); #endif /* version >= v2.3.13 */ ASC_DBG2(1, "advansys_detect: vendorID %X, deviceID %X\n", @@ -4900,7 +4901,7 @@ #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,13) pci_memory_address = pci_devp->base_address[1]; #else /* version >= v2.3.13 */ - pci_memory_address = pci_devp->resource[1].start; + pci_memory_address = pci_resource_start(pci_devp, 1); #endif /* version >= v2.3.13 */ ASC_DBG1(1, "advansys_detect: pci_memory_address: %x\n", pci_memory_address); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/aic7xxx.c linux.ac/drivers/scsi/aic7xxx.c --- linux.vanilla/drivers/scsi/aic7xxx.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/aic7xxx.c Tue May 30 15:22:21 2000 @@ -9551,14 +9551,15 @@ pdev = NULL; while ((pdev = pci_find_device(aic_pdevs[i].vendor_id, aic_pdevs[i].device_id, - pdev))) + pdev))) { + if (pci_enable_device(pdev)) + continue; #else index = 0; while (!(pcibios_find_device(aic_pdevs[i].vendor_id, aic_pdevs[i].device_id, - index++, &pci_bus, &pci_devfn)) ) + index++, &pci_bus, &pci_devfn)) ) { #endif - { if ( i == 0 ) /* We found one, but it's the 7810 RAID cont. */ { if (aic7xxx_verbose & (VERBOSE_PROBE|VERBOSE_PROBE2)) @@ -9587,8 +9588,8 @@ temp_p->pdev = pdev; temp_p->pci_bus = pdev->bus->number; temp_p->pci_device_fn = pdev->devfn; - temp_p->base = pdev->resource[0].start; - temp_p->mbase = pdev->resource[1].start; + temp_p->base = pci_resource_start(pdev, 0); + temp_p->mbase = pci_resource_start(pdev, 1); current_p = list_p; while(current_p && temp_p) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/atp870u.c linux.ac/drivers/scsi/atp870u.c --- linux.vanilla/drivers/scsi/atp870u.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/atp870u.c Tue May 30 15:22:21 2000 @@ -1615,7 +1615,7 @@ h = 0; while (devid[h] != 0) { pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]); - if (pdev[2] == NULL) { + if (pdev[2] == NULL || pci_enable_device(pdev[2])) { h++; index = 0; continue; @@ -1650,7 +1650,7 @@ } /* Found an atp870u/w. */ - base_io = pdev[h]->resource[0].start; + base_io = pci_resource_start(pdev[h], 0); irq = pdev[h]->irq; error = pci_read_config_byte(pdev[h],0x49,&host_id); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/dmx3191d.c linux.ac/drivers/scsi/dmx3191d.c --- linux.vanilla/drivers/scsi/dmx3191d.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/dmx3191d.c Fri May 26 14:34:11 2000 @@ -68,11 +68,10 @@ while ((pdev = pci_find_device(PCI_VENDOR_ID_DOMEX, PCI_DEVICE_ID_DOMEX_DMX3191D, pdev))) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - unsigned long port = pdev->base_address[0] & PCI_IOADDRESS_MASK; -#else - unsigned long port = pdev->resource[0].start; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) */ + unsigned long port = pci_resource_start (pdev, 0); + + if (pci_enable_device(pdev)) + continue; if (check_region(port, DMX3191D_REGION)) { dmx3191d_printk("region 0x%lx-0x%lx already reserved\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/eata.c linux.ac/drivers/scsi/eata.c --- linux.vanilla/drivers/scsi/eata.c Thu May 25 17:38:03 2000 +++ linux.ac/drivers/scsi/eata.c Fri May 26 14:34:11 2000 @@ -829,7 +829,9 @@ if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; - if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue; + addr = pci_resource_start (dev, 0); + + pci_enable_device (dev); /* XXX handle error */ #if defined(DEBUG_PCI_DETECT) printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/eata_dma.c linux.ac/drivers/scsi/eata_dma.c --- linux.vanilla/drivers/scsi/eata_dma.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/eata_dma.c Tue May 30 15:22:21 2000 @@ -1388,20 +1388,22 @@ #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - struct pci_dev *dev; + struct pci_dev *dev = NULL; u32 base, x; u8 pal1, pal2, pal3; - for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { + while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { DBG(DBG_PROBE && DBG_PCI, printk("eata_dma: find_PCI, HBA at %s\n", dev->name)); + if (pci_enable_device(dev)) + continue; pci_set_master(dev); - base = dev->resource[0].flags; - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + base = pci_resource_flags(dev, 0); + if (base & IORESOURCE_MEM) { printk("eata_dma: invalid base address of device %s\n", dev->name); continue; } - base = dev->resource[0].start; + base = pci_resource_start(dev, 0); /* EISA tag there ? */ pal1 = inb(base); pal2 = inb(base + 1); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/eata_pio.c linux.ac/drivers/scsi/eata_pio.c --- linux.vanilla/drivers/scsi/eata_pio.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/eata_pio.c Tue May 30 15:22:21 2000 @@ -878,19 +878,21 @@ #ifndef CONFIG_PCI printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - struct pci_dev *dev; + struct pci_dev *dev = NULL; u32 base, x; - for(dev=NULL; dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev);) { + while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); + if (pci_enable_device(dev)) + continue; pci_set_master(dev); - base = dev->resource[0].flags; - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) { + base = pci_resource_flags(dev, 0); + if (base & IORESOURCE_MEM) { printk("eata_pio: invalid base address of device %s\n", dev->name); continue; } - base = dev->resource[0].start; + base = pci_resource_start(dev, 0); /* EISA tag there ? */ if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) continue; /* Jep, it's forced, so move on */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/fdomain.c linux.ac/drivers/scsi/fdomain.c --- linux.vanilla/drivers/scsi/fdomain.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/fdomain.c Tue May 30 15:22:33 2000 @@ -828,6 +828,7 @@ PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) return 0; + if (pci_enable_device(pdev)) return 0; #if DEBUG_DETECT printk( "scsi: TMC-3260 detect:" @@ -840,7 +841,7 @@ /* 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->resource[0].start; + pci_base = pci_resource_start(pdev, 0); pci_irq = pdev->irq; /* Now we have the I/O base address and interrupt from the PCI diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/gdth.c linux.ac/drivers/scsi/gdth.c --- linux.vanilla/drivers/scsi/gdth.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/gdth.c Fri May 26 14:34:11 2000 @@ -533,6 +533,8 @@ pdev = NULL; while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) != NULL) { + if (pci_enable_device(pdev)) + continue; if (cnt >= MAXHA) return cnt; /* GDT PCI controller found, resources are already in pdev */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/hosts.c linux.ac/drivers/scsi/hosts.c --- linux.vanilla/drivers/scsi/hosts.c Thu May 25 17:38:03 2000 +++ linux.ac/drivers/scsi/hosts.c Sat Jun 10 22:21:47 2000 @@ -345,6 +345,14 @@ #include "../acorn/scsi/powertec.h" #endif +#ifdef CONFIG_SCSI_ARXESCSI +#include "../acorn/scsi/arxescsi.h" +#endif + +#ifdef CONFIG_I2O_SCSI +#include "../i2o/i2o_scsi.h" +#endif + #ifdef CONFIG_JAZZ_ESP #include "jazz_esp.h" #endif @@ -636,6 +644,9 @@ #ifdef CONFIG_SCSI_CUMANA_2 CUMANA_FAS216, #endif +#ifdef CONFIG_SCSI_ARXESCSI + ARXEScsi, +#endif #ifdef CONFIG_SCSI_ECOSCSI ECOSCSI_NCR5380, #endif @@ -655,6 +666,10 @@ #ifdef CONFIG_BLK_DEV_3W_XXXX_RAID TWXXXX, #endif +/* Put I2O last so that host specific controllers always win */ +#ifdef CONFIG_I2O_SCSI + I2OSCSI +#endif /* "Removable host adapters" below this line (Parallel Port/USB/other) */ #ifdef CONFIG_SCSI_PPA PPA, @@ -732,38 +747,41 @@ */ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ - struct Scsi_Host * retval, *shpnt; + struct Scsi_Host * retval, *shpnt, *o_shp; Scsi_Host_Name *shn, *shn2; - int new = 1; + int flag_new = 1; + const char * hname; + size_t hname_len; retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j, - (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC); + (tpnt->unchecked_isa_dma && j ? + GFP_DMA : 0) | GFP_ATOMIC); memset(retval, 0, sizeof(struct Scsi_Host) + j); /* trying to find a reserved entry (host_no) */ - for (shn = scsi_host_no_list;shn;shn = shn->next) - if (!(shn->host_registered) && shn->loaded_as_module && tpnt->proc_dir && - tpnt->proc_dir->name && !strncmp(tpnt->proc_dir->name, shn->name, strlen(tpnt->proc_dir->name))) { - new = 0; + hname = (tpnt->proc_name) ? tpnt->proc_name : ""; + hname_len = strlen(hname); + for (shn = scsi_host_no_list;shn;shn = shn->next) { + if (!(shn->host_registered) && shn->loaded_as_module && + (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) { + flag_new = 0; retval->host_no = shn->host_no; shn->host_registered = 1; shn->loaded_as_module = scsi_loadable_module_flag; break; } + } atomic_set(&retval->host_active,0); retval->host_busy = 0; retval->host_failed = 0; if(j > 0xffff) panic("Too many extra bytes requested\n"); retval->extra_bytes = j; retval->loaded_as_module = scsi_loadable_module_flag; - if (new) { - int len = 0; + if (flag_new) { shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC); - if (tpnt->proc_dir) - len = strlen(tpnt->proc_dir->name); - shn->name = kmalloc(len+1, GFP_ATOMIC); - if (tpnt->proc_dir) - strncpy(shn->name, tpnt->proc_dir->name, len); - shn->name[len] = 0; + shn->name = kmalloc(hname_len + 1, GFP_ATOMIC); + if (hname_len > 0) + strncpy(shn->name, hname, hname_len); + shn->name[hname_len] = 0; shn->host_no = max_scsi_hosts++; shn->host_registered = 1; shn->loaded_as_module = scsi_loadable_module_flag; @@ -827,11 +845,26 @@ if(!scsi_hostlist) scsi_hostlist = retval; - else - { + else { shpnt = scsi_hostlist; - while(shpnt->next) shpnt = shpnt->next; - shpnt->next = retval; + if (retval->host_no < shpnt->host_no) { + retval->next = shpnt; + wmb(); /* want all to see these writes in this order */ + scsi_hostlist = retval; + } + else { + for (o_shp = shpnt, shpnt = shpnt->next; shpnt; + o_shp = shpnt, shpnt = shpnt->next) { + if (retval->host_no < shpnt->host_no) { + retval->next = shpnt; + wmb(); + o_shp->next = retval; + break; + } + } + if (! shpnt) + o_shp->next = retval; + } } return retval; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ini9100u.c linux.ac/drivers/scsi/ini9100u.c --- linux.vanilla/drivers/scsi/ini9100u.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/ini9100u.c Fri May 26 14:34:11 2000 @@ -290,6 +290,8 @@ for (i = 0; i < TULSZ(i91u_pci_devices); i++) { while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { + if (pci_enable_device(pDev)) + continue; pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); wBIOS = (UWORD) (dRegValue & 0xFF); if (((dRegValue & 0xFF00) >> 8) == 0xFF) @@ -377,8 +379,6 @@ pHCB->pSRB_head = NULL; /* Initial SRB save queue */ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ - request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */ - get_tulipPCIConfig(pHCB, i); dBiosAdr = pHCB->HCS_BIOS; @@ -387,6 +387,8 @@ pbBiosAdr = phys_to_virt(dBiosAdr); init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); + request_region(pHCB->HCS_Base, 256, "i91u"); /* Register */ + pHCB->HCS_Index = i; /* 7/29/98 */ hreg = scsi_register(tpnt, sizeof(HCS)); hreg->io_port = pHCB->HCS_Base; @@ -812,4 +814,14 @@ { printk("\ni91u_panic: %s\n", msg); panic("i91u panic"); +} + +/* + * Release ressources + */ +int i91u_release(struct Scsi_Host *hreg) +{ + free_irq(hreg->irq, hreg); + release_region(hreg->io_port, 256); + return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ini9100u.h linux.ac/drivers/scsi/ini9100u.h --- linux.vanilla/drivers/scsi/ini9100u.h Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/ini9100u.h Sat Jun 10 22:26:47 2000 @@ -78,6 +78,7 @@ #include "sd.h" extern int i91u_detect(Scsi_Host_Template *); +extern int i91u_release(struct Scsi_Host *); extern int i91u_command(Scsi_Cmnd *); extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); @@ -93,7 +94,7 @@ proc_info: NULL, \ name: i91u_REVID, \ detect: i91u_detect, \ - release: NULL, \ + release: i91u_release, \ info: NULL, \ command: i91u_command, \ queuecommand: i91u_queue, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/inia100.c linux.ac/drivers/scsi/inia100.c --- linux.vanilla/drivers/scsi/inia100.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/inia100.c Fri May 26 14:34:11 2000 @@ -247,6 +247,8 @@ inia100_pci_devices[i].device_id, pdev))) { + if (pci_enable_device(pdev)) + continue; if (iAdapters >= MAX_SUPPORTED_ADAPTERS) break; /* Never greater than maximum */ @@ -261,24 +263,23 @@ */ bPCIBusNum = pdev->bus->number; bPCIDeviceNum = pdev->devfn; - dRegValue = pdev->resource[0].start; + dRegValue = pci_resource_start(pdev, 0); if (dRegValue == -1) { /* Check return code */ printk("\n\rinia100: orchid read configuration error.\n"); return (0); /* Read configuration space error */ } + /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ wBASE = (WORD) dRegValue; - /* Now read the interrupt line */ + /* Now read the interrupt line value */ dRegValue = pdev->irq; - bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ - pci_read_config_word(pdev, PCI_COMMAND, &command); - pci_write_config_word(pdev, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + bInterrupt = dRegValue; /* Assign interrupt line */ - wBASE &= PCI_BASE_ADDRESS_IO_MASK; wBIOS = ORC_RDWORD(wBASE, 0x50); + pci_set_master(pdev); + #ifdef MMAPIO base = wBASE & PAGE_MASK; page_offset = wBASE - base; @@ -370,7 +371,6 @@ memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz); pHCB->HCS_physEscbArray = (U32) VIRT_TO_BUS(pHCB->HCS_virEscbArray); - request_region(pHCB->HCS_Base, 0x100, "inia100"); /* Register */ get_orcPCIConfig(pHCB, i); dBiosAdr = pHCB->HCS_BIOS; @@ -382,6 +382,8 @@ printk("inia100: initial orchid fail!!\n"); return (0); } + request_region(pHCB->HCS_Base, 256, "inia100"); /* Register */ + hreg = scsi_register(tpnt, sizeof(ORC_HCS)); if (hreg == NULL) { printk("Invalid scsi_register pointer.\n"); @@ -411,28 +413,28 @@ /* Initial orc chip */ switch (i) { case 0: - ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 1: - ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr1, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 2: - ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr2, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 3: - ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr3, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 4: - ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr4, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 5: - ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr5, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 6: - ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr6, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; case 7: - ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); + ok = request_irq(pHCB->HCS_Intr, inia100_intr7, SA_INTERRUPT | SA_SHIRQ, "inia100", hreg); break; default: inia100_panic("inia100: Too many host adapters\n"); @@ -784,5 +786,15 @@ printk("\ninia100_panic: %s\n", msg); panic("inia100 panic"); } + +/* + * Release ressources + */ +int inia100_release(struct Scsi_Host *hreg) +{ + free_irq(hreg->irq, hreg); + release_region(hreg->io_port, 256); + return 0; +} /*#include "inia100scsi.c" */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/inia100.h linux.ac/drivers/scsi/inia100.h --- linux.vanilla/drivers/scsi/inia100.h Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/inia100.h Sat Jun 10 22:26:47 2000 @@ -71,6 +71,7 @@ #include "sd.h" extern int inia100_detect(Scsi_Host_Template *); +extern int inia100_release(struct Scsi_Host *); extern int inia100_command(Scsi_Cmnd *); extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int inia100_abort(Scsi_Cmnd *); @@ -87,7 +88,7 @@ proc_info: NULL, \ name: inia100_REVID, \ detect: inia100_detect, \ - release: NULL, \ + release: inia100_release, \ info: NULL, \ command: inia100_command, \ queuecommand: inia100_queue, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ips.c linux.ac/drivers/scsi/ips.c --- linux.vanilla/drivers/scsi/ips.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/ips.c Tue May 30 15:23:02 2000 @@ -325,12 +325,13 @@ if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev))) break; - + if (pci_enable_device(dev)) + break; /* stuff that we get in dev */ irq = dev->irq; bus = dev->bus->number; func = dev->devfn; - io_addr = dev->resource[0].start; + io_addr = pci_resource_start(dev, 0); /* get planer status */ if (pci_read_config_word(dev, 0x04, &planer)) { @@ -341,7 +342,7 @@ } /* check I/O address */ - if ((dev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) continue; /* check to see if an onboard planer controller is disabled */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/megaraid.c linux.ac/drivers/scsi/megaraid.c --- linux.vanilla/drivers/scsi/megaraid.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/megaraid.c Fri May 26 14:34:11 2000 @@ -1478,6 +1478,8 @@ struct pci_dev *pdev = NULL; while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { + if (pci_enable_device(pdev)) + continue; if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { u16 magic; pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); @@ -1505,18 +1507,13 @@ } /* Read the base port and IRQ from PCI */ - megaBase = pdev->resource[0].start; + megaBase = pci_resource_start (pdev, 0); megaIrq = pdev->irq; - if (flag & BOARD_QUARTZ) { - - megaBase &= PCI_BASE_ADDRESS_MEM_MASK; + if (flag & BOARD_QUARTZ) megaBase = (long) ioremap (megaBase, 128); - } - else { - megaBase &= PCI_BASE_ADDRESS_IO_MASK; + else megaBase += 0x10; - } /* Initialize SCSI Host structure */ host = scsi_register (pHostTmpl, sizeof (mega_host_config)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/ncr53c8xx.c linux.ac/drivers/scsi/ncr53c8xx.c --- linux.vanilla/drivers/scsi/ncr53c8xx.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/ncr53c8xx.c Mon Jun 5 19:47:43 2000 @@ -73,7 +73,7 @@ */ /* -** April 24 2000, version 3.2i +** May 11 2000, version 3.3b ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -93,6 +93,7 @@ ** 53C895 (Wide, Fast 40, on board rom BIOS) ** 53C895A (Wide, Fast 40, on board rom BIOS) ** 53C896 (Wide, Fast 40, on board rom BIOS) +** 53C897 (Wide, Fast 40, on board rom BIOS) ** 53C1510D (Wide, Fast 40, on board rom BIOS) ** ** Other features: @@ -104,7 +105,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2i" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.3b" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -187,6 +188,14 @@ typedef u_long vm_offset_t; #include "ncr53c8xx.h" +/* +** Donnot compile integrity checking code for Linux-2.3.0 +** and above since SCSI data structures are not ready yet. +*/ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,0) +#define SCSI_NCR_INTEGRITY_CHECKING +#endif + #define NAME53C "ncr53c" #define NAME53C8XX "ncr53c8xx" #define DRIVER_SMP_LOCK ncr53c8xx_lock @@ -472,8 +481,10 @@ **========================================================== */ +#define NS_NOCHANGE (0) #define NS_SYNC (1) #define NS_WIDE (2) +#define NS_PPR (4) /*========================================================== ** @@ -666,6 +677,13 @@ /*2*/ u_char widedone; /*3*/ u_char wval; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + u_char ic_min_sync; + u_char ic_max_width; + u_char ic_maximums_set; + u_char ic_done; +#endif + /*---------------------------------------------------------------- ** User settable limits and options. ** These limits are read from the NVRAM if present. @@ -1204,6 +1222,17 @@ struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ u_char release_stage; /* Synchronisation stage on release */ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + /*---------------------------------------------------------------- + ** Fields that are used for integrity check + **---------------------------------------------------------------- + */ + unsigned char check_integrity; /* Enable midlayer integ.check on + * bus scan. */ + unsigned char check_integ_par; /* Set if par or Init. Det. error + * used only during integ check */ +#endif }; #define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) @@ -1382,6 +1411,10 @@ static void ncr_int_sto (ncb_p np); static u_long ncr_lookup (char* id); static void ncr_negotiate (struct ncb* np, struct tcb* tp); +static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr); +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr); +#endif #ifdef SCSI_NCR_PROFILE_SUPPORT static void ncb_profile (ncb_p np, ccb_p cp); @@ -1396,6 +1429,7 @@ static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); static int ncr_show_msg (u_char * msg); +static void ncr_print_msg (ccb_p cp, char *label, u_char *msg); static int ncr_snooptest (ncb_p np); static void ncr_timeout (ncb_p np); static void ncr_wakeup (ncb_p np, u_long code); @@ -3792,6 +3826,17 @@ instance->can_queue = (MAX_START-4); instance->select_queue_depths = ncr53c8xx_select_queue_depths; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + np->check_integrity = 0; + instance->check_integrity = 0; + +#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK + if ( !(driver_setup.bus_check & 0x04) ) { + np->check_integrity = 1; + instance->check_integrity = 1; + } +#endif +#endif /* ** Patch script to physical addresses */ @@ -4020,6 +4065,270 @@ } } +/*========================================================== +** +** +** Prepare the next negotiation message for integrity check, +** if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** +**========================================================== +*/ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + u_char no_increase; + + if (tp->inq_done) { + + if (!tp->ic_maximums_set) { + tp->ic_maximums_set = 1; + + /* check target and host adapter capabilities */ + if ( (tp->inq_byte7 & INQ7_WIDE16) && + np->maxwide && tp->usrwide ) + tp->ic_max_width = 1; + else + tp->ic_max_width = 0; + + if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) { + tp->ic_min_sync = (tp->minsync < np->minsync) ? + np->minsync : tp->minsync; + } + else + tp->ic_min_sync = 255; + + tp->period = 1; + tp->widedone = 1; + } + + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", + ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); + } + + /* First command from integrity check routine will request + * a PPR message. Disable. + */ + if ((cmd->ic_nego & NS_PPR) == NS_PPR) + cmd->ic_nego &= ~NS_PPR; + /* Previous command recorded a parity or an initiator + * detected error condition. Force bus to narrow for this + * target. Clear flag. Negotation on request sense. + * Note: kernel forces 2 bus resets :o( but clears itself out. + * Minor bug? in scsi_obsolete.c (ugly) + */ + if (np->check_integ_par) { + printk("%s: Parity Error. Target set to narrow.\n", + ncr_name(np)); + tp->ic_max_width = 0; + tp->widedone = tp->period = 0; + } + + /* In case of a bus reset, ncr_negotiate will reset + * the flags tp->widedone and tp->period to 0, forcing + * a new negotiation. + */ + no_increase = 0; + if (tp->widedone == 0) { + cmd->ic_nego = NS_WIDE; + tp->widedone = 1; + no_increase = 1; + } + else if (tp->period == 0) { + cmd->ic_nego = NS_SYNC; + tp->period = 1; + no_increase = 1; + } + + switch (cmd->ic_nego) { + case NS_WIDE: + /* + ** negotiate wide transfers ? + ** Do NOT negotiate if device only supports + ** narrow. + */ + if (tp->ic_max_width | np->check_integ_par) { + nego = NS_WIDE; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = cmd->ic_nego_width & tp->ic_max_width; + } + else + cmd->ic_nego_width &= tp->ic_max_width; + + break; + + case NS_SYNC: + /* + ** negotiate synchronous transfers? + ** Target must support sync transfers. + ** + ** If period becomes longer than max, reset to async + */ + + if (tp->inq_byte7 & INQ7_SYNC) { + + nego = NS_SYNC; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + + switch (cmd->ic_nego_sync) { + case 2: /* increase the period */ + if (!no_increase) { + if (tp->ic_min_sync <= 0x0A) + tp->ic_min_sync = 0x0C; + else if (tp->ic_min_sync <= 0x0C) + tp->ic_min_sync = 0x19; + else if (tp->ic_min_sync <= 0x19) + tp->ic_min_sync *= 2; + else { + tp->ic_min_sync = 255; + cmd->ic_nego_sync = 0; + tp->maxoffs = 0; + } + } + msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; + msgptr[msglen++] = tp->maxoffs; + break; + + case 1: /* nego. to maximum */ + msgptr[msglen++] = tp->maxoffs?tp->ic_min_sync:0; + msgptr[msglen++] = tp->maxoffs; + break; + + case 0: /* nego to async */ + default: + msgptr[msglen++] = 0; + msgptr[msglen++] = 0; + break; + }; + } + else + cmd->ic_nego_sync = 0; + break; + + case NS_NOCHANGE: + default: + break; + }; + }; + + cp->nego_status = nego; + np->check_integ_par = 0; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide/narrow msgout": "sync/async msgout", msgptr); + }; + }; + + return msglen; +} +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + +/*========================================================== +** +** +** Prepare the next negotiation message if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** +**========================================================== +*/ + + +static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + + if (tp->inq_done) { + + /* + ** negotiate wide transfers ? + */ + + if (!tp->widedone) { + if (tp->inq_byte7 & INQ7_WIDE16) { + nego = NS_WIDE; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (tp->ic_done) + tp->usrwide &= tp->ic_max_width; +#endif + } else + tp->widedone=1; + + }; + + /* + ** negotiate synchronous transfers? + */ + + if (!nego && !tp->period) { + if (tp->inq_byte7 & INQ7_SYNC) { + nego = NS_SYNC; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((tp->ic_done) && + (tp->minsync < tp->ic_min_sync)) + tp->minsync = tp->ic_min_sync; +#endif + } else { + tp->period =0xffff; + PRINT_TARGET(np, cp->target); + printk ("target did not report SYNC.\n"); + }; + }; + }; + + switch (nego) { + case NS_SYNC: + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; + msgptr[msglen++] = tp->maxoffs; + break; + case NS_WIDE: + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = tp->usrwide; + break; + }; + + cp->nego_status = nego; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide msgout":"sync_msgout", msgptr); + }; + }; + + return msglen; +} + + /*========================================================== ** @@ -4038,7 +4347,7 @@ ccb_p cp; int segments; - u_char nego, idmsg, *msgptr; + u_char idmsg, *msgptr; u_int msglen; int direction; u_int32 lastp, goalp; @@ -4120,51 +4429,6 @@ cp->phys.header.stamp.start = jiffies; #endif - /*--------------------------------------------------- - ** - ** negotiation required? - ** - **--------------------------------------------------- - */ - - nego = 0; - - if ((!tp->widedone || !tp->period) && !tp->nego_cp && tp->inq_done && lp) { - - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inq_byte7 & INQ7_WIDE16) { - nego = NS_WIDE; - } else - tp->widedone=1; - }; - - /* - ** negotiate synchronous transfers? - */ - - if (!nego && !tp->period) { - if (tp->inq_byte7 & INQ7_SYNC) { - nego = NS_SYNC; - } else { - tp->period =0xffff; - PRINT_TARGET(np, cmd->target); - printk ("device did not report SYNC.\n"); - }; - }; - - /* - ** remember nego is pending for the target. - ** Avoid to start a nego for all queued commands - ** when tagged command queuing is enabled. - */ - - if (nego) - tp->nego_cp = cp; - }; /*---------------------------------------------------- ** @@ -4225,34 +4489,6 @@ msgptr[msglen++] = (cp->tag << 1) + 1; } - switch (nego) { - case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("sync msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printk (".\n"); - }; - break; - case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->cmd); - printk ("wide msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-4]); - printk (".\n"); - }; - break; - }; - /*---------------------------------------------------- ** ** Build the data descriptors @@ -4273,6 +4509,84 @@ segments = 0; } + /*--------------------------------------------------- + ** + ** negotiation required? + ** + ** (nego_status is filled by ncr_prepare_nego()) + ** + **--------------------------------------------------- + */ + + cp->nego_status = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } + } + else if (np->check_integrity && (cmd->ic_in_progress)) { + msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); + } + else if (np->check_integrity && cmd->ic_complete) { + /* + * Midlayer signal to the driver that all of the scsi commands + * for the integrity check have completed. Save the negotiated + * parameters (extracted from sval and wval). + */ + + { + u_char idiv; + idiv = (tp->wval>>4) & 0x07; + if ((tp->sval&0x1f) && idiv ) + tp->period = (((tp->sval>>5)+4) + *div_10M[idiv-1])/np->clock_khz; + else + tp->period = 0xffff; + } + /* + * tp->period contains 10 times the transfer period, + * which itself is 4 * the requested negotiation rate. + */ + if (tp->period <= 250) tp->ic_min_sync = 10; + else if (tp->period <= 303) tp->ic_min_sync = 11; + else if (tp->period <= 500) tp->ic_min_sync = 12; + else + tp->ic_min_sync = (tp->period + 40 - 1) / 40; + + + /* + * Negotiation for this target it complete. + */ + tp->ic_max_width = (tp->wval & EWS) ? 1: 0; + tp->ic_done = 1; + tp->widedone = 1; + + printk("%s: Integrity Check Complete: \n", ncr_name(np)); + + printk("%s: %s %s SCSI", ncr_name(np), + (tp->sval&0x1f)?"SYNC":"ASYNC", + tp->ic_max_width?"WIDE":"NARROW"); + + if (tp->sval&0x1f) { + u_long mbs = 10000 * (tp->ic_max_width + 1); + + printk(" %d.%d MB/s", + (int) (mbs / tp->period), (int) (mbs % tp->period)); + + printk(" (%d ns, %d offset)\n", + tp->period/10, tp->sval&0x1f); + } + else + printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); + } +#else + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + /*---------------------------------------------------- ** ** Determine xfer direction. @@ -4376,12 +4690,11 @@ ** status */ cp->actualquirks = tp->quirks; - cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; + cp->host_status = cp->nego_status ? HS_NEGOTIATE : HS_BUSY; cp->scsi_status = S_ILLEGAL; cp->parity_status = 0; cp->xerr_status = XE_OK; - cp->nego_status = nego; #if 0 cp->sync_status = tp->sval; cp->wide_status = tp->wval; @@ -5041,7 +5354,13 @@ for (i=0; i<14; i++) printk (" %x", *p++); printk (".\n"); } - + } else if ((cp->host_status == HS_COMPLETE) + && (cp->scsi_status == S_CONFLICT)) { + /* + ** Reservation Conflict condition code + */ + cmd->result = ScsiResult(DID_OK, S_CONFLICT); + } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_BUSY || cp->scsi_status == S_QUEUE_FULL)) { @@ -6398,6 +6717,14 @@ else msg = M_ID_ERROR; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + /* + ** Save error message. For integrity check use only. + */ + if (np->check_integrity) + np->check_integ_par = msg; +#endif + /* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a * script that will ignore all data in bytes until phase @@ -6908,6 +7235,16 @@ return (1); } +static void ncr_print_msg ( ccb_p cp, char *label, u_char *msg) +{ + if (cp) + PRINT_ADDR(cp->cmd); + if (label) + printk("%s: ", label); + + (void) ncr_show_msg (msg); + printk(".\n"); +} void ncr_int_sir (ncb_p np) { @@ -8275,6 +8612,7 @@ static unsigned __init ncrgetfreq (ncb_p np, int gen) { unsigned ms = 0; + char count = 0; /* * Measure GEN timer delay in order @@ -8299,8 +8637,10 @@ OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ OUTB (nc_stime1, 0); /* disable general purpose timer */ OUTB (nc_stime1, gen); /* set to nominal delay of 1<basePort = pdev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; + padapter->basePort = pci_resource_start (pdev, 1); 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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/pci2220i.c linux.ac/drivers/scsi/pci2220i.c --- linux.vanilla/drivers/scsi/pci2220i.c Thu May 25 17:38:05 2000 +++ linux.ac/drivers/scsi/pci2220i.c Fri May 26 14:34:11 2000 @@ -2386,8 +2386,8 @@ memset (&DaleSetup, 0, sizeof (DaleSetup)); memset (DiskMirror, 0, sizeof (DiskMirror)); - zr = pcidev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK; - zl = pcidev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK; + zr = pci_resource_start (pcidev, 1); + zl = pci_resource_start (pcidev, 2); padapter->basePort = zr; padapter->regRemap = zr + RTR_LOCAL_REMAP; // 32 bit local space remap @@ -2542,6 +2542,8 @@ while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL ) { + if (pci_enable_device(pcidev)) + continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2220I)); padapter = HOSTDATA(pshost); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/qla1280.c linux.ac/drivers/scsi/qla1280.c --- linux.vanilla/drivers/scsi/qla1280.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/qla1280.c Fri May 26 14:34:12 2000 @@ -801,13 +801,13 @@ for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) while ((pdev = pci_find_device(QLA1280_VENDOR_ID, - bdp->device_id, pdev ) )) + bdp->device_id, pdev ) )) { + if (pci_enable_device(pdev)) continue; #else while (!(pcibios_find_device(QLA1280_VENDOR_ID, bdp->device_id, - index++, &pci_bus, &pci_devfn)) ) + index++, &pci_bus, &pci_devfn)) ) { #endif - { /* found a adapter */ host = scsi_register(template, sizeof(scsi_qla_host_t)); ha = (scsi_qla_host_t *) host->hostdata; @@ -817,9 +817,7 @@ /* Sanitize the information from PCI BIOS. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) host->irq = pdev->irq; -/* this depends on release 2.3.18 */ - host->io_port = pdev->resource[0].start; -/* MRS host->io_port = (unsigned int) pdev->base_address[0]; */ + host->io_port = pci_resource_start(pdev, 0); ha->pci_bus = pdev->bus->number; ha->pci_device_fn = pdev->devfn; ha->pdev = pdev; @@ -828,14 +826,13 @@ pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase); host->irq = pci_irq; host->io_port = (unsigned int) piobase; + host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->pci_bus = pci_bus; ha->pci_device_fn = pci_devfn; #endif ha->device_id = bdp->device_id; - host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->devnum = i; - host->io_port &= PCI_BASE_ADDRESS_IO_MASK; if( qla1280_mem_alloc(ha) ) { printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n"); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/qlogicfc.c linux.ac/drivers/scsi/qlogicfc.c --- linux.vanilla/drivers/scsi/qlogicfc.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/qlogicfc.c Tue May 30 15:23:41 2000 @@ -746,6 +746,8 @@ for (i=0; i<2; i++){ while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) { + if (pci_enable_device(pdev)) + continue; host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); host->max_id = QLOGICFC_MAX_ID + 1; @@ -2004,7 +2006,7 @@ printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id); return 1; } - io_base = pdev->resource[0].start; + io_base = pci_resource_start(pdev, 0); irq = pdev->irq; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/qlogicisp.c linux.ac/drivers/scsi/qlogicisp.c --- linux.vanilla/drivers/scsi/qlogicisp.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/qlogicisp.c Tue May 30 15:23:41 2000 @@ -678,6 +678,9 @@ while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, pdev))) { + if (pci_enable_device(pdev)) + continue; + host = scsi_register(tmpt, sizeof(struct isp1020_hostdata)); hostdata = (struct isp1020_hostdata *) host->hostdata; @@ -1371,10 +1374,10 @@ return 1; } - io_base = pdev->resource[0].start; - mem_base = pdev->resource[1].start; - io_flags = pdev->resource[0].flags; - mem_flags = pdev->resource[1].flags; + io_base = pci_resource_start(pdev, 0); + mem_base = pci_resource_start(pdev, 1); + io_flags = pci_resource_flags(pdev, 0); + mem_flags = pci_resource_flags(pdev, 1); irq = pdev->irq; if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/scsi_scan.c linux.ac/drivers/scsi/scsi_scan.c --- linux.vanilla/drivers/scsi/scsi_scan.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/scsi_scan.c Thu Jun 8 15:09:14 2000 @@ -38,7 +38,6 @@ #define BLIST_MAX5LUN 0x080 #define BLIST_ISDISK 0x100 #define BLIST_ISROM 0x200 -#define BLIST_GHOST 0x400 static void print_inquiry(unsigned char *data); static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev, @@ -137,13 +136,7 @@ {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, - {"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST}, - {"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST}, - {"AOpen", "PD-2 DVD-520S", "*", BLIST_GHOST}, - {"HITACHI", "GF-1050","*", BLIST_GHOST}, /* Hitachi SCSI DVD-RAM */ {"TOSHIBA","CDROM","*", BLIST_ISROM}, - {"TOSHIBA","DVD-RAM SD-W1101","*", BLIST_GHOST}, - {"TOSHIBA","DVD-RAM SD-W1111","*", BLIST_GHOST}, {"MegaRAID", "LD", "*", BLIST_FORCELUN}, /* @@ -468,8 +461,6 @@ Scsi_Device *SDtail, *SDpnt = *SDpnt2; Scsi_Request * SRpnt; int bflags, type = -1; - static int ghost_channel=-1, ghost_dev=-1; - int org_lun = lun; extern devfs_handle_t scsi_devfs_handle; SDpnt->host = shpnt; @@ -480,13 +471,6 @@ scsi_build_commandblocks(SDpnt); - if ((channel == ghost_channel) && (dev == ghost_dev) && (lun == 1)) { - SDpnt->lun = 0; - } else { - ghost_channel = ghost_dev = -1; - } - - /* Some low level driver could use device->type (DB) */ SDpnt->type = -1; @@ -499,39 +483,14 @@ SDpnt->expecting_cc_ua = 0; SDpnt->starved = 0; - scsi_cmd[0] = TEST_UNIT_READY; - scsi_cmd[1] = lun << 5; - scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0; - SRpnt = scsi_allocate_request(SDpnt); - SRpnt->sr_data_direction = SCSI_DATA_NONE; - - scsi_wait_req (SRpnt, (void *) scsi_cmd, - (void *) NULL, - 0, SCSI_TIMEOUT + 4 * HZ, 5); - - SCSI_LOG_SCAN_BUS(3, printk("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n", - dev, lun, SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, print_driverbyte(SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, print_hostbyte(SRpnt->sr_result)); - SCSI_LOG_SCAN_BUS(3, printk("\n")); + /* + * We used to do a TEST_UNIT_READY before the INQUIRY but that was + * not really necessary. Spec recommends using INQUIRY to scan for + * devices (and TEST_UNIT_READY to poll for media change). - Paul G. + */ - if (SRpnt->sr_result) { - if (((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) || - (status_byte(SRpnt->sr_result) & CHECK_CONDITION)) && - ((SRpnt->sr_sense_buffer[0] & 0x70) >> 4) == 7) { - if (((SRpnt->sr_sense_buffer[2] & 0xf) != NOT_READY) && - ((SRpnt->sr_sense_buffer[2] & 0xf) != UNIT_ATTENTION) && - ((SRpnt->sr_sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0)) { - scsi_release_request(SRpnt); - return 1; - } - } else { - scsi_release_request(SRpnt); - return 0; - } - } SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n")); /* * Build an INQUIRY command block. @@ -547,7 +506,7 @@ scsi_wait_req (SRpnt, (void *) scsi_cmd, (void *) scsi_result, - 256, SCSI_TIMEOUT, 3); + 256, SCSI_TIMEOUT+4*HZ, 3); SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n", SRpnt->sr_result ? "failed" : "successful", SRpnt->sr_result)); @@ -588,18 +547,6 @@ scsi_result[1] |= 0x80; /* removable */ } - if (bflags & BLIST_GHOST) { - if ((ghost_channel == channel) && (ghost_dev == dev) && (org_lun == 1)) { - lun=1; - } else { - ghost_channel = channel; - ghost_dev = dev; - scsi_result[0] = TYPE_MOD; - scsi_result[1] |= 0x80; /* removable */ - } - } - - memcpy(SDpnt->vendor, scsi_result + 8, 8); memcpy(SDpnt->model, scsi_result + 16, 16); memcpy(SDpnt->rev, scsi_result + 32, 4); @@ -808,19 +755,9 @@ } /* - * If this device is Ghosted, scan upto two luns. (It physically only - * has one). -- REW - */ - if (bflags & BLIST_GHOST) { - *max_dev_lun = 2; - return 1; - } - - - /* - * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI - * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1 - * (ANSI SCSI Revision 1) and Response Data Format 0 + * We assume the device can't handle lun!=0 if: - it reports scsi-0 + * (ANSI SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it + * reports scsi-1 (ANSI SCSI Revision 1) and Response Data Format 0 */ if (((scsi_result[2] & 0x07) == 0) || diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sg.c linux.ac/drivers/scsi/sg.c --- linux.vanilla/drivers/scsi/sg.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/sg.c Thu Jun 8 16:38:27 2000 @@ -17,8 +17,8 @@ * any later version. * */ - static char * sg_version_str = "Version: 3.1.13 (20000323)"; - static int sg_version_num = 30113; /* 2 digits for each component */ + static char * sg_version_str = "Version: 3.1.15 (20000528)"; + static int sg_version_num = 30115; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -113,7 +113,8 @@ static Scsi_Cmnd * dummy_cmdp = 0; /* only used for sizeof */ -static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; +static rwlock_t sg_dev_arr_lock = RW_LOCK_UNLOCKED; /* Also used to lock + file descriptor list for device */ struct Scsi_Device_Template sg_template = { @@ -155,7 +156,7 @@ char res_used; /* 1 -> using reserve buffer, 0 -> not ... */ char orphan; /* 1 -> drop on sight, 0 -> normal */ char sg_io_owned; /* 1 -> packet belongs to SG_IO */ - char done; /* 1 -> bh handler done, 0 -> prior to bh */ + char done; /* 0->before bh, 1->before read, 2->read */ } Sg_request; /* 168 bytes long on i386 */ typedef struct sg_fd /* holds the state of a file descriptor */ @@ -163,6 +164,7 @@ struct sg_fd * nextfp; /* NULL when last opened fd on this device */ struct sg_device * parentdp; /* owning device */ wait_queue_head_t read_wait; /* queue read until command done */ + rwlock_t rq_list_lock; /* protect access to list in req_arr */ int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ Sg_scatter_hold reserve; /* buffer held for this file descriptor */ unsigned save_scat_len; /* original length of trunc. scat. element */ @@ -176,7 +178,7 @@ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ -} Sg_fd; /* 2760 bytes long on i386 */ +} Sg_fd; /* 2768 bytes long on i386 */ typedef struct sg_device /* holds the state of each scsi generic device */ { @@ -189,7 +191,7 @@ char exclude; /* opened for exclusive access */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ char detached; /* 0->attached, 1->detached pending removal */ -} Sg_device; /* 40 bytes long on i386 */ +} Sg_device; /* 44 bytes long on i386 */ static int sg_fasync(int fd, struct file * filp, int mode); @@ -222,11 +224,11 @@ static void sg_low_free(char * buff, int size, int mem_src); static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev); static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp); -static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id); +static Sg_request * sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request * sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); -static int sg_res_in_use(const Sg_fd * sfp); -static int sg_dio_in_use(const Sg_fd * sfp); +static int sg_res_in_use(Sg_fd * sfp); +static int sg_dio_in_use(Sg_fd * sfp); static void sg_clr_scpnt(Scsi_Cmnd * SCpnt); static void sg_shorten_timeout(Scsi_Cmnd * scpnt); static int sg_ms_to_jif(unsigned int msecs); @@ -364,7 +366,7 @@ else req_pack_id = old_hdr.pack_id; } - srp = sg_get_request(sfp, req_pack_id); + srp = sg_get_rq_mark(sfp, req_pack_id); if (! srp) { /* now wait on packet to arrive */ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -372,7 +374,7 @@ int dio = sg_dio_in_use(sfp); res = 0; /* following is a macro that beats race condition */ __wait_event_interruptible(sfp->read_wait, - (srp = sg_get_request(sfp, req_pack_id)), + (srp = sg_get_rq_mark(sfp, req_pack_id)), res); if (0 == res) break; @@ -550,7 +552,7 @@ hp->cmd_len = (unsigned char)cmd_size; hp->iovec_count = 0; hp->mx_sb_len = 0; -#if 1 +#if 0 hp->dxfer_direction = SG_DXFER_UNKNOWN; #else if (input_size > 0) @@ -686,7 +688,7 @@ srp->data.sglist_len = 0; srp->data.bufflen = 0; srp->data.buffer = NULL; - hp->duration = jiffies; + hp->duration = jiffies; /* unit jiffies now, millisecs after done */ /* Now send everything of to mid-level. The next time we hear about this packet is when sg_cmd_done_bh() is called (i.e. a callback). */ scsi_do_cmd(SCpnt, (void *)cmnd, @@ -703,6 +705,7 @@ Sg_device * sdp; Sg_fd * sfp; Sg_request * srp; + unsigned long iflags; if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) return -ENXIO; @@ -740,6 +743,7 @@ return result; /* -ERESTARTSYS because signal hit process */ } } + srp->done = 2; result = sg_new_read(sfp, (char *)arg, size_sg_io_hdr, srp); return (result < 0) ? result : 0; } @@ -794,24 +798,24 @@ case SG_GET_PACK_ID: result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); if (result) return result; - srp = sfp->headrp; - while (srp) { - if (srp->done && (! srp->sg_io_owned)) { + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + if ((1 == srp->done) && (! srp->sg_io_owned)) { + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __put_user(srp->header.pack_id, (int *)arg); return 0; } - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __put_user(-1, (int *)arg); return 0; case SG_GET_NUM_WAITING: - srp = sfp->headrp; - val = 0; - while (srp) { - if (srp->done && (! srp->sg_io_owned)) + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) { + if ((1 == srp->done) && (! srp->sg_io_owned)) ++val; - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); return put_user(val, (int *)arg); case SG_GET_SG_TABLESIZE: return put_user(sdp->sg_tablesize, (int *)arg); @@ -855,16 +859,17 @@ if (result) return result; else { sg_req_info_t rinfo[SG_MAX_QUEUE]; - Sg_request * srp = sfp->headrp; - for (val = 0; val < SG_MAX_QUEUE; + Sg_request * srp; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE; ++val, srp = srp ? srp->nextrp : srp) { memset(&rinfo[val], 0, size_sg_req_info); if (srp) { - rinfo[val].req_state = srp->done ? 2 : 1; + rinfo[val].req_state = srp->done + 1; rinfo[val].problem = srp->header.masked_status & srp->header.host_status & srp->header.driver_status; rinfo[val].duration = srp->done ? - sg_jif_to_ms(srp->header.duration) : + srp->header.duration : sg_jif_to_ms(jiffies - srp->header.duration); rinfo[val].orphan = srp->orphan; rinfo[val].sg_io_owned = srp->sg_io_owned; @@ -872,6 +877,7 @@ rinfo[val].usr_ptr = srp->header.usr_ptr; } } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); __copy_to_user((void *)arg, rinfo, size_sg_req_info * SG_MAX_QUEUE); return 0; } @@ -882,8 +888,29 @@ return -EBUSY; result = get_user(val, (int *)arg); if (result) return result; - /* Don't do anything till scsi mid level visibility */ - return 0; + if (SG_SCSI_RESET_NOTHING == val) + return 0; +#ifdef SCSI_TRY_RESET_DEVICE + switch (val) + { + case SG_SCSI_RESET_DEVICE: + val = SCSI_TRY_RESET_DEVICE; + break; + case SG_SCSI_RESET_BUS: + val = SCSI_TRY_RESET_BUS; + break; + case SG_SCSI_RESET_HOST: + val = SCSI_TRY_RESET_HOST; + break; + default: + return -EINVAL; + } + if(! capable(CAP_SYS_ADMIN)) return -EACCES; + return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO; +#else + SCSI_LOG_TIMEOUT(1, printk("sg_ioctl: SG_RESET_SCSI not supported\n")); + result = -EINVAL; +#endif case SCSI_IOCTL_SEND_COMMAND: if (read_only) { unsigned char opcode = WRITE_6; @@ -918,17 +945,19 @@ Sg_fd * sfp; Sg_request * srp; int count = 0; + unsigned long iflags; if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) return POLLERR; poll_wait(filp, &sfp->read_wait, wait); - srp = sfp->headrp; - while (srp) { /* if any read waiting, flag it */ - if ((0 == res) && srp->done && (! srp->sg_io_owned)) + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + /* if any read waiting, flag it */ + if ((0 == res) && (1 == srp->done) && (! srp->sg_io_owned)) res = POLLIN | POLLRDNORM; ++count; - srp = srp->nextrp; } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); if (! sfp->cmd_q) { if (0 == count) res |= POLLOUT | POLLWRNORM; @@ -960,11 +989,17 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) { int dev = MINOR(SCpnt->request.rq_dev); - Sg_device * sdp; + Sg_device * sdp = NULL; Sg_fd * sfp; Sg_request * srp = NULL; - if (NULL == (sdp = sg_get_dev(dev))) { + read_lock(&sg_dev_arr_lock); + if (sg_dev_arr && (dev >= 0)) { + if (dev < sg_template.dev_max) + sdp = sg_dev_arr[dev]; + } + if (NULL == sdp) { + read_unlock(&sg_dev_arr_lock); SCSI_LOG_TIMEOUT(1, printk("sg...bh: bad args dev=%d\n", dev)); scsi_release_command(SCpnt); SCpnt = NULL; @@ -972,16 +1007,17 @@ } sfp = sdp->headfp; while (sfp) { - srp = sfp->headrp; - while (srp) { + read_lock(&sfp->rq_list_lock); + for (srp = sfp->headrp; srp; srp = srp->nextrp) { if (SCpnt == srp->my_cmdp) break; - srp = srp->nextrp; } + read_unlock(&sfp->rq_list_lock); if (srp) break; sfp = sfp->nextfp; } + read_unlock(&sg_dev_arr_lock); if (! srp) { SCSI_LOG_TIMEOUT(1, printk("sg...bh: req missing, dev=%d\n", dev)); scsi_release_command(SCpnt); @@ -1001,6 +1037,7 @@ dev, srp->header.pack_id, (int)SCpnt->result)); srp->header.resid = SCpnt->resid; /* sg_unmap_and(&srp->data, 0); */ /* unmap locked pages a.s.a.p. */ + /* N.B. unit of duration changes here from jiffies to millisecs */ srp->header.duration = sg_jif_to_ms(jiffies - (int)srp->header.duration); if (0 != SCpnt->result) { memcpy(srp->sense_b, SCpnt->sense_buffer, sizeof(srp->sense_b)); @@ -1052,8 +1089,7 @@ if (sfp && srp) { /* Now wake up any sg_read() that is waiting for this packet. */ wake_up_interruptible(&sfp->read_wait); - if (sfp->async_qp) - kill_fasync(sfp->async_qp, SIGPOLL, POLL_IN); + kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); } } @@ -1091,18 +1127,18 @@ static int sg_init() { static int sg_registered = 0; - unsigned long flags = 0; + unsigned long iflags; if ((sg_template.dev_noticed == 0) || sg_dev_arr) return 0; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); if(!sg_registered) { if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) { printk("Unable to get major %d for generic SCSI device\n", SCSI_GENERIC_MAJOR); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; } sg_registered++; @@ -1114,11 +1150,11 @@ sizeof(Sg_device *), GFP_ATOMIC); if (NULL == sg_dev_arr) { printk("sg_init: no space for sg_dev_arr\n"); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; } memset(sg_dev_arr, 0, sg_template.dev_max * sizeof(Sg_device *)); - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); #ifdef CONFIG_PROC_FS sg_proc_init(); #endif /* CONFIG_PROC_FS */ @@ -1149,10 +1185,10 @@ static int sg_attach(Scsi_Device * scsidp) { Sg_device * sdp; - unsigned long flags = 0; + unsigned long iflags; int k; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); if (sg_template.nr_dev >= sg_template.dev_max) { /* try to resize */ Sg_device ** tmp_da; int tmp_dev_max = sg_template.nr_dev + SG_DEV_ARR_LUMP; @@ -1161,7 +1197,7 @@ sizeof(Sg_device *), GFP_ATOMIC); if (NULL == tmp_da) { scsidp->attached--; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); printk("sg_attach: device array cannot be resized\n"); return 1; } @@ -1180,7 +1216,7 @@ sdp = NULL; if (NULL == sdp) { scsidp->attached--; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); printk("sg_attach: Sg_device cannot be allocated\n"); return 1; } @@ -1200,7 +1236,7 @@ &sg_fops, NULL); sg_template.nr_dev++; sg_dev_arr[k] = sdp; - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 0; } @@ -1214,37 +1250,36 @@ static void sg_detach(Scsi_Device * scsidp) { Sg_device * sdp; - unsigned long flags = 0; + unsigned long iflags; Sg_fd * sfp; Sg_request * srp; int k; if (NULL == sg_dev_arr) return; - write_lock_irqsave(&sg_dev_arr_lock, flags); -/* Need to stop sg_cmd_done_bh() playing with this list during this loop */ + write_lock_irqsave(&sg_dev_arr_lock, iflags); for (k = 0; k < sg_template.dev_max; k++) { sdp = sg_dev_arr[k]; if ((NULL == sdp) || (sdp->device != scsidp)) continue; /* dirty but lowers nesting */ if (sdp->headfp) { - sfp = sdp->headfp; - while (sfp) { - srp = sfp->headrp; - while (srp) { - if (! srp->done) + for (sfp = sdp->headfp; sfp; sfp = sfp->nextfp) { + /* no lock on request list here */ + for (srp = sfp->headrp; srp; srp = srp->nextrp) { + if (! srp->done) { + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); sg_shorten_timeout(srp->my_cmdp); - srp = srp->nextrp; + write_lock_irqsave(&sg_dev_arr_lock, iflags); } - sfp = sfp->nextfp; } - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty, sleep(3)\n", k)); scsi_sleep(3); /* sleep 3 jiffies, hoping for timeout to go off */ devfs_unregister (sdp->de); sdp->de = NULL; sdp->detached = 1; - write_lock_irqsave(&sg_dev_arr_lock, flags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); } else { SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); @@ -1259,7 +1294,7 @@ sg_template.dev_noticed--; break; } - write_unlock_irqrestore(&sg_dev_arr_lock, flags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return; } @@ -1277,12 +1312,11 @@ void cleanup_module( void) { - scsi_unregister_module(MODULE_SCSI_DEV, &sg_template); - devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); - #ifdef CONFIG_PROC_FS sg_proc_cleanup(); #endif /* CONFIG_PROC_FS */ + scsi_unregister_module(MODULE_SCSI_DEV, &sg_template); + devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg"); if(sg_dev_arr != NULL) { /* Really worrying situation of writes still pending and get here */ /* Strategy: shorten timeout on release + wait on detach ... */ @@ -1301,7 +1335,7 @@ /* Can't see clean way to abort a command so shorten timeout to 1 jiffy */ static void sg_shorten_timeout(Scsi_Cmnd * scpnt) -{ /* assumed to be called with sg_dev_arr_lock held */ +{ #if 0 /* scsi_syms.c is very miserly about exported functions */ scsi_delete_timer(scpnt); if (! scpnt) @@ -1313,11 +1347,7 @@ scsi_add_timer(scpnt, scpnt->timeout_per_command, scsi_old_times_out); #else - unsigned long flags = 0; - - write_unlock_irqrestore(&sg_dev_arr_lock, flags); scsi_sleep(HZ); /* just sleep 1 second and hope ... */ - write_lock_irqsave(&sg_dev_arr_lock, flags); #endif } @@ -1859,6 +1889,8 @@ Sg_scatter_hold * rsv_schp = &sfp->reserve; SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); + /* round request up to next highest SG_SECTOR_SZ byte boundary */ + size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK); if (rsv_schp->k_use_sg > 0) { int k, num; int rem = size; @@ -1921,17 +1953,35 @@ srp->res_used = 0; } -static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id) +static Sg_request * sg_get_rq_mark(Sg_fd * sfp, int pack_id) { - Sg_request * resp = NULL; + Sg_request * resp; + unsigned long iflags; - resp = sfp->headrp; - while (resp) { /* look for requests that are ready + not SG_IO owned */ - if (resp->done && (! resp->sg_io_owned) && - ((-1 == pack_id) || (resp->header.pack_id == pack_id))) - return resp; - resp = resp->nextrp; + write_lock_irqsave(&sfp->rq_list_lock, iflags); + for (resp = sfp->headrp; resp; resp = resp->nextrp) { + /* look for requests that are ready + not SG_IO owned */ + if ((1 == resp->done) && (! resp->sg_io_owned) && + ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { + resp->done = 2; /* guard against other readers */ + break; + } } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return resp; +} + +static Sg_request * sg_get_nth_request(Sg_fd * sfp, int nth) +{ + Sg_request * resp; + unsigned long iflags; + int k; + + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (k = 0, resp = sfp->headrp; resp && (k < nth); + ++k, resp = resp->nextrp) + ; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); return resp; } @@ -1939,46 +1989,45 @@ static Sg_request * sg_add_request(Sg_fd * sfp) { int k; - Sg_request * resp = NULL; - Sg_request * rp; + unsigned long iflags; + Sg_request * resp; + Sg_request * rp = sfp->req_arr; + write_lock_irqsave(&sfp->rq_list_lock, iflags); resp = sfp->headrp; - rp = sfp->req_arr; if (! resp) { - resp = rp; - sfp->headrp = resp; + memset(rp, 0, sizeof(Sg_request)); + rp->parentfp = sfp; + resp = rp; + sfp->headrp = resp; } else { if (0 == sfp->cmd_q) resp = NULL; /* command queuing disallowed */ else { - for (k = 0, rp; k < SG_MAX_QUEUE; ++k, ++rp) { + for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { if (! rp->parentfp) break; } if (k < SG_MAX_QUEUE) { - while (resp->nextrp) resp = resp->nextrp; - resp->nextrp = rp; - resp = rp; + memset(rp, 0, sizeof(Sg_request)); + rp->parentfp = sfp; + while (resp->nextrp) + resp = resp->nextrp; + resp->nextrp = rp; + resp = rp; } else resp = NULL; } } if (resp) { - resp->parentfp = sfp; resp->nextrp = NULL; - resp->res_used = 0; - resp->orphan = 0; - resp->sg_io_owned = 0; - resp->done = 0; - memset(&resp->data, 0, sizeof(Sg_scatter_hold)); - memset(&resp->header, 0, size_sg_io_hdr); resp->header.duration = jiffies; resp->my_cmdp = NULL; resp->data.kiobp = NULL; - resp->data.mapped = 0; } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); return resp; } @@ -1987,29 +2036,51 @@ { Sg_request * prev_rp; Sg_request * rp; + unsigned long iflags; + int res = 0; if ((! sfp) || (! srp) || (! sfp->headrp)) - return 0; + return res; + write_lock_irqsave(&sfp->rq_list_lock, iflags); prev_rp = sfp->headrp; if (srp == prev_rp) { - prev_rp->parentfp = NULL; sfp->headrp = prev_rp->nextrp; - return 1; + prev_rp->parentfp = NULL; + res = 1; } - while ((rp = prev_rp->nextrp)) { - if (srp == rp) { - rp->parentfp = NULL; - prev_rp->nextrp = rp->nextrp; - return 1; - } - prev_rp = rp; + else { + while ((rp = prev_rp->nextrp)) { + if (srp == rp) { + prev_rp->nextrp = rp->nextrp; + rp->parentfp = NULL; + res = 1; + break; + } + prev_rp = rp; + } } - return 0; + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return res; +} + +static Sg_fd * sg_get_nth_sfp(Sg_device * sdp, int nth) +{ + Sg_fd * resp; + unsigned long iflags; + int k; + + read_lock_irqsave(&sg_dev_arr_lock, iflags); + for (k = 0, resp = sdp->headfp; resp && (k < nth); + ++k, resp = resp->nextfp) + ; + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + return resp; } static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) { Sg_fd * sfp; + unsigned long iflags; sfp = (Sg_fd *)sg_low_malloc(sizeof(Sg_fd), 0, SG_HEAP_KMAL, 0); if (! sfp) @@ -2017,6 +2088,7 @@ memset(sfp, 0, sizeof(Sg_fd)); sfp->fd_mem_src = SG_HEAP_KMAL; init_waitqueue_head(&sfp->read_wait); + sfp->rq_list_lock = RW_LOCK_UNLOCKED; sfp->timeout = SG_DEFAULT_TIMEOUT; sfp->force_packid = SG_DEF_FORCE_PACK_ID; @@ -2025,14 +2097,16 @@ sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; + write_lock_irqsave(&sg_dev_arr_lock, iflags); if (! sdp->headfp) sdp->headfp = sfp; else { /* add to tail of existing list */ - Sg_fd * pfp = sdp->headfp; - while (pfp->nextfp) - pfp = pfp->nextfp; - pfp->nextfp = sfp; + Sg_fd * pfp = sdp->headfp; + while (pfp->nextfp) + pfp = pfp->nextfp; + pfp->nextfp = sfp; } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n", sfp, (int)sfp->fd_mem_src)); sg_build_reserve(sfp, sg_big_buff); @@ -2048,36 +2122,41 @@ int dirty = 0; int res = 0; + /* no lock since not expecting any parallel action on this fd */ srp = sfp->headrp; if (srp) { - while (srp) { - tsrp = srp->nextrp; + while (srp) { + tsrp = srp->nextrp; if (srp->done) sg_finish_rem_req(srp); - else - ++dirty; - srp = tsrp; - } + else + ++dirty; + srp = tsrp; + } } if (0 == dirty) { - Sg_fd * fp; - Sg_fd * prev_fp = sdp->headfp; - - if (sfp == prev_fp) - sdp->headfp = prev_fp->nextfp; - else { - while ((fp = prev_fp->nextfp)) { - if (sfp == fp) { - prev_fp->nextfp = fp->nextfp; - break; - } - prev_fp = fp; - } - } - if (sfp->reserve.bufflen > 0) { + Sg_fd * fp; + Sg_fd * prev_fp; + unsigned long iflags; + + write_lock_irqsave(&sg_dev_arr_lock, iflags); + prev_fp = sdp->headfp; + if (sfp == prev_fp) + sdp->headfp = prev_fp->nextfp; + else { + while ((fp = prev_fp->nextfp)) { + if (sfp == fp) { + prev_fp->nextfp = fp->nextfp; + break; + } + prev_fp = fp; + } + } + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + if (sfp->reserve.bufflen > 0) { SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int)sfp->reserve.bufflen, (int)sfp->reserve.k_use_sg)); - sg_remove_scat(&sfp->reserve); + sg_remove_scat(&sfp->reserve); } sfp->parentdp = NULL; SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%p\n", sfp)); @@ -2104,28 +2183,28 @@ return res; } -static int sg_res_in_use(const Sg_fd * sfp) +static int sg_res_in_use(Sg_fd * sfp) { - const Sg_request * srp = sfp->headrp; + const Sg_request * srp; + unsigned long iflags; - while (srp) { - if (srp->res_used) - return 1; - srp = srp->nextrp; - } - return 0; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) + if (srp->res_used) break; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return srp ? 1 : 0; } -static int sg_dio_in_use(const Sg_fd * sfp) +static int sg_dio_in_use(Sg_fd * sfp) { - const Sg_request * srp = sfp->headrp; + const Sg_request * srp; + unsigned long iflags; - while (srp) { - if ((! srp->done) && srp->data.kiobp) - return 1; - srp = srp->nextrp; - } - return 0; + read_lock_irqsave(&sfp->rq_list_lock, iflags); + for (srp = sfp->headrp; srp; srp = srp->nextrp) + if ((! srp->done) && srp->data.kiobp) break; + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); + return srp ? 1 : 0; } /* If retSzp==NULL want exact size or fail */ @@ -2314,7 +2393,8 @@ } static unsigned char allow_ops[] = {TEST_UNIT_READY, INQUIRY, -READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12}; +READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12, +MODE_SENSE, MODE_SENSE_10}; static int sg_allow_access(unsigned char opcode, char dev_type) { @@ -2331,28 +2411,29 @@ static int sg_last_dev() -{ /* assumed to be called with sg_dev_arr_lock held */ +{ int k; + unsigned long iflags; - for (k = sg_template.dev_max - 1; k >= 0; --k) { - if (sg_dev_arr[k] && sg_dev_arr[k]->device) - return k + 1; - } - return 0; /* origin 1 */ + read_lock_irqsave(&sg_dev_arr_lock, iflags); + for (k = sg_template.dev_max - 1; k >= 0; --k) + if (sg_dev_arr[k] && sg_dev_arr[k]->device) break; + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + return k + 1; /* origin 1 */ } static Sg_device * sg_get_dev(int dev) { - Sg_device * sdp; + Sg_device * sdp = NULL; + unsigned long iflags; - if ((NULL == sg_dev_arr) || (dev < 0)) - return NULL; - read_lock(&sg_dev_arr_lock); + if (sg_dev_arr && (dev >= 0)) + { + read_lock_irqsave(&sg_dev_arr_lock, iflags); if (dev < sg_template.dev_max) sdp = sg_dev_arr[dev]; - else - sdp = NULL; - read_unlock(&sg_dev_arr_lock); + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + } return sdp; } @@ -2429,8 +2510,7 @@ *eof = infofp(buffer, &len, &begin, offset, size); \ if (offset >= (begin + len)) \ return 0; \ - *start = buffer + ((begin > offset) ? \ - (begin - offset) : (offset - begin)); \ + *start = buffer + offset - begin; \ return (size < (begin + len - offset)) ? \ size : begin + len - offset; \ } while(0) @@ -2520,7 +2600,6 @@ PRINT_PROC("sg_dev_arr NULL, driver not initialized\n"); return 1; } - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n", sg_template.dev_max, max_dev); @@ -2528,11 +2607,11 @@ "def_reserved_size=%d\n", scsi_dma_free_sectors, sg_pool_secs_avail, sg_big_buff); for (j = 0; j < max_dev; ++j) { - if ((sdp = sg_dev_arr[j])) { + if ((sdp = sg_get_dev(j))) { Sg_fd * fp; Sg_request * srp; struct scsi_device * scsidp; - int dev, k, blen, usg; + int dev, k, m, blen, usg; if (! (scsidp = sdp->device)) { PRINT_PROC("device %d detached ??\n", j); @@ -2540,48 +2619,45 @@ } dev = MINOR(sdp->i_rdev); - if ((fp = sdp->headfp)) { - PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev); + if (sg_get_nth_sfp(sdp, 0)) { + PRINT_PROC(" >>> device=sg%d ", dev); PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d" " excl=%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, scsidp->host->hostt->emulated, sdp->sg_tablesize, sdp->exclude); } - for (k = 1; fp; fp = fp->nextfp, ++k) { - PRINT_PROC(" FD(%d): timeout=%d bufflen=%d " - "(res)sgat=%d low_dma=%d\n", - k, fp->timeout, fp->reserve.bufflen, + for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) { + PRINT_PROC(" FD(%d): timeout=%dms bufflen=%d " + "(res)sgat=%d low_dma=%d\n", k + 1, + sg_jif_to_ms(fp->timeout), fp->reserve.bufflen, (int)fp->reserve.k_use_sg, (int)fp->low_dma); PRINT_PROC(" cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n", (int)fp->cmd_q, (int)fp->force_packid, (int)fp->keep_orphan, (int)fp->closed); - srp = fp->headrp; - if (NULL == srp) - PRINT_PROC(" No requests active\n"); - while (srp) { + for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) { hp = &srp->header; /* stop indenting so far ... */ PRINT_PROC(srp->res_used ? " rb>> " : ((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " ")); blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen; usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg; - PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" : - "prior: id=%d"), srp->header.pack_id); - PRINT_PROC(" blen=%d", blen); + PRINT_PROC(srp->done ? ((1 == srp->done) ? "rcv:" : "fin:") + : (srp->my_cmdp ? "act:" : "prior:")); + PRINT_PROC(" id=%d blen=%d", srp->header.pack_id, blen); if (srp->done) - PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration)); + PRINT_PROC(" dur=%d", hp->duration); else PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ? sg_jif_to_ms(fp->timeout) : hp->timeout), sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0)); - PRINT_PROC(" sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode); - srp = srp->nextrp; + PRINT_PROC("ms sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode); /* reset indenting */ } + if (0 == m) + PRINT_PROC(" No requests active\n"); } } } - read_unlock(&sg_dev_arr_lock); return 1; } @@ -2596,19 +2672,17 @@ int j, max_dev; struct scsi_device * scsidp; - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); for (j = 0; j < max_dev; ++j) { - sdp = sg_dev_arr[j]; + sdp = sg_get_dev(j); if (sdp && (scsidp = sdp->device)) PRINT_PROC("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, (int)scsidp->type, (int)scsidp->disconnect, - (int)scsidp->queue_depth, (int)scsidp->tagged_queue); + scsidp->lun, (int)scsidp->type, (int)scsidp->access_count, + (int)scsidp->queue_depth, (int)scsidp->device_busy); else PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); } - read_unlock(&sg_dev_arr_lock); return 1; } @@ -2619,7 +2693,7 @@ static int sg_proc_devhdr_info(char * buffer, int * len, off_t * begin, off_t offset, int size) { - PRINT_PROC("host\tchan\tid\tlun\ttype\tdiscon\tqdepth\ttq\n"); + PRINT_PROC("host\tchan\tid\tlun\ttype\tbopens\tqdepth\tbusy\n"); return 1; } @@ -2634,17 +2708,15 @@ int j, max_dev; struct scsi_device * scsidp; - read_lock(&sg_dev_arr_lock); max_dev = sg_last_dev(); for (j = 0; j < max_dev; ++j) { - sdp = sg_dev_arr[j]; + sdp = sg_get_dev(j); if (sdp && (scsidp = sdp->device)) PRINT_PROC("%8.8s\t%16.16s\t%4.4s\n", scsidp->vendor, scsidp->model, scsidp->rev); else PRINT_PROC("\n"); } - read_unlock(&sg_dev_arr_lock); return 1; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sr.c linux.ac/drivers/scsi/sr.c --- linux.vanilla/drivers/scsi/sr.c Thu May 25 17:38:04 2000 +++ linux.ac/drivers/scsi/sr.c Tue May 30 21:44:19 2000 @@ -25,6 +25,9 @@ * * Modified by Richard Gooch to support devfs * + * Modified by Jens Axboe - support DVD-RAM + * transparently and loose the GHOST hack + * */ #include @@ -297,9 +300,10 @@ else printk("sr: can't switch blocksize: in interrupt\n"); } - if (SCpnt->request.cmd == WRITE) { + + if ((SCpnt->request.cmd == WRITE) && !scsi_CDs[dev].device->writeable) return 0; - } + if (scsi_CDs[dev].device->sector_size == 1024) { if ((block & 1) || (SCpnt->request.nr_sectors & 1)) { printk("sr.c:Bad 1K block number requested (%d %ld)", @@ -322,9 +326,6 @@ } switch (SCpnt->request.cmd) { case WRITE: - if (!scsi_CDs[dev].device->writeable) { - return 0; - } SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = SCSI_DATA_WRITE; break; @@ -587,10 +588,11 @@ 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, + printk("sr%i: scsi3-mmc drive: %dx/%dx %s%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 + 3] & 0x20 ? "dvd-ram " : "", 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 */ @@ -601,9 +603,12 @@ if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ scsi_CDs[i].cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) + if ((buffer[n + 3] & 0x20) == 0) { /* can't write DVD-RAM media */ scsi_CDs[i].cdi.mask |= CDC_DVD_RAM; + } else { + scsi_CDs[i].device->writeable = 1; + } if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ scsi_CDs[i].cdi.mask |= CDC_DVD_R; @@ -626,7 +631,6 @@ scsi_CDs[i].cdi.mask |= CDC_SELECT_DISC; /*else I don't think it can close its tray scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */ - scsi_free(buffer, 512); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sym53c8xx.c linux.ac/drivers/scsi/sym53c8xx.c --- linux.vanilla/drivers/scsi/sym53c8xx.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/sym53c8xx.c Mon Jun 5 19:47:43 2000 @@ -55,7 +55,7 @@ */ /* -** April 24 2000, sym53c8xx 1.5m +** May 11 2000, sym53c8xx 1.6b ** ** Supported SCSI features: ** Synchronous data transfers @@ -73,7 +73,10 @@ ** 53C895 (Wide, Fast 40, on-board rom BIOS) ** 53C895A (Wide, Fast 40, on-board rom BIOS) ** 53C896 (Wide, Fast 40 Dual, on-board rom BIOS) +** 53C897 (Wide, Fast 40 Dual, on-board rom BIOS) ** 53C1510D (Wide, Fast 40 Dual, on-board rom BIOS) +** 53C1010 (Wide, Fast 80 Dual, on-board rom BIOS) +** 53C1010_66(Wide, Fast 80 Dual, on-board rom BIOS, 33/66MHz PCI) ** ** Other features: ** Memory mapped IO @@ -84,7 +87,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5m" +#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.6b" /* #define DEBUG_896R1 */ #define SCSI_NCR_OPTIMIZE_896 @@ -174,6 +177,14 @@ #include "sym53c8xx.h" +/* +** Donnot compile integrity checking code for Linux-2.3.0 +** and above since SCSI data structures are not ready yet. +*/ +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,0) +#define SCSI_NCR_INTEGRITY_CHECKING +#endif + #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -606,6 +617,7 @@ #define DEBUG_TIMING (0x0100) #define DEBUG_NEGO (0x0200) #define DEBUG_TAGS (0x0400) +#define DEBUG_IC (0x0800) /* ** Enable/Disable debug messages. @@ -1654,6 +1666,8 @@ #define XE_EXTRA_DATA (1) /* unexpected data phase */ #define XE_BAD_PHASE (2) /* illegal phase (4/5) */ #define XE_PARITY_ERR (4) /* unrecovered SCSI parity error */ +#define XE_SODL_UNRUN (1<<3) +#define XE_SWIDE_OVRUN (1<<4) /*========================================================== ** @@ -1663,8 +1677,10 @@ **========================================================== */ +#define NS_NOCHANGE (0) #define NS_SYNC (1) #define NS_WIDE (2) +#define NS_PPR (4) /*========================================================== ** @@ -1819,7 +1835,7 @@ /*---------------------------------------------------------------- ** negotiation of wide and synch transfer and device quirks. - ** sval and wval are read from SCRIPTS and so have alignment + ** sval, wval and uval are read from SCRIPTS and so have alignment ** constraints. **---------------------------------------------------------------- */ @@ -1830,6 +1846,15 @@ /*1*/ u_char quirks; /*2*/ u_char widedone; /*3*/ u_char wval; +/*0*/ u_char uval; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + u_char ic_min_sync; + u_char ic_max_width; + u_char ic_done; +#endif + u_char ic_maximums_set; + u_char ppr_negotiation; /*---------------------------------------------------------------- ** User settable limits and options. @@ -1838,8 +1863,8 @@ */ u_char usrsync; u_char usrwide; - u_char usrflag; u_short usrtags; + u_char usrflag; }; /*======================================================================== @@ -2049,6 +2074,7 @@ #define HF_AUTO_SENSE (1u<<4) #define HF_DATA_IN (1u<<5) #define HF_PM_TO_C (1u<<6) +#define HF_EXT_ERR (1u<<7) #ifdef SCSI_NCR_IARB_SUPPORT #define HF_HINT_IARB (1u<<7) @@ -2106,6 +2132,7 @@ struct scr_tblmove smsg_ext ; struct scr_tblmove cmd ; struct scr_tblmove sense ; + struct scr_tblmove wresid; struct scr_tblmove data [MAX_SCATTER]; /* @@ -2269,7 +2296,7 @@ **---------------------------------------------------------------- */ u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest3, sv_ctest4, - sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_stest1; + sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4, sv_stest1, sv_scntl4; /*---------------------------------------------------------------- ** Actual initial value of IO register bits used by the @@ -2278,7 +2305,7 @@ **---------------------------------------------------------------- */ u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest3, rv_ctest4, - rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1; + rv_ctest5, rv_stest2, rv_ccntl0, rv_ccntl1, rv_scntl4; /*---------------------------------------------------------------- ** Target data. @@ -2393,8 +2420,8 @@ ** written with a script command. **---------------------------------------------------------------- */ - u_char msgout[8]; /* Buffer for MESSAGE OUT */ - u_char msgin [8]; /* Buffer for MESSAGE IN */ + u_char msgout[12]; /* Buffer for MESSAGE OUT */ + u_char msgin [12]; /* Buffer for MESSAGE IN */ u_int32 lastmsg; /* Last SCSI message sent */ u_char scratch; /* Scratch for SCSI receive */ @@ -2466,6 +2493,17 @@ */ struct usrcmd user; /* Command from user */ u_char release_stage; /* Synchronisation stage on release */ + + /*---------------------------------------------------------------- + ** Fields that are used (primarily) for integrity check + **---------------------------------------------------------------- + */ + unsigned char check_integrity; /* Enable midlayer integ. check on + * bus scan. */ +#ifdef SCSI_NCR_INTEGRITY_CHECKING + unsigned char check_integ_par; /* Set if par or Init. Det. error + * used only during integ check */ +#endif }; #define NCB_PHYS(np, lbl) (np->p_ncb + offsetof(struct ncb, lbl)) @@ -2511,20 +2549,20 @@ ncrcmd select2 [ 2]; #endif ncrcmd command [ 2]; - ncrcmd dispatch [ 28]; + ncrcmd dispatch [ 30]; ncrcmd sel_no_cmd [ 10]; ncrcmd init [ 6]; ncrcmd clrack [ 4]; - ncrcmd disp_msg_in [ 2]; ncrcmd disp_status [ 4]; - ncrcmd datai_done [ 16]; - ncrcmd datao_done [ 10]; + ncrcmd datai_done [ 26]; + ncrcmd datao_done [ 12]; ncrcmd ign_i_w_r_msg [ 4]; #ifdef SCSI_NCR_PROFILE_SUPPORT - ncrcmd dataphase [ 4]; + ncrcmd datai_phase [ 4]; #else - ncrcmd dataphase [ 2]; + ncrcmd datai_phase [ 2]; #endif + ncrcmd datao_phase [ 4]; ncrcmd msg_in [ 2]; ncrcmd msg_in2 [ 10]; #ifdef SCSI_NCR_IARB_SUPPORT @@ -2562,16 +2600,17 @@ ncrcmd ungetjob [ 4]; #endif ncrcmd reselect [ 4]; - ncrcmd reselected [ 48]; + ncrcmd reselected [ 20]; + ncrcmd resel_scntl4 [ 30]; #if MAX_TASKS*4 > 512 - ncrcmd resel_tag [ 16]; + ncrcmd resel_tag [ 18]; #elif MAX_TASKS*4 > 256 - ncrcmd resel_tag [ 10]; + ncrcmd resel_tag [ 12]; #else - ncrcmd resel_tag [ 6]; + ncrcmd resel_tag [ 8]; #endif ncrcmd resel_go [ 6]; - ncrcmd resel_notag [ 4]; + ncrcmd resel_notag [ 2]; ncrcmd resel_dsa [ 8]; ncrcmd data_in [MAX_SCATTER * SCR_SG_SIZE]; ncrcmd data_in2 [ 4]; @@ -2591,6 +2630,7 @@ */ struct scripth { ncrcmd start64 [ 2]; + ncrcmd no_data [ 2]; ncrcmd sel_for_abort [ 18]; ncrcmd sel_for_abort_1 [ 2]; ncrcmd select_no_atn [ 8]; @@ -2608,11 +2648,13 @@ ncrcmd send_wdtr [ 4]; ncrcmd sdtr_resp [ 6]; ncrcmd send_sdtr [ 4]; + ncrcmd ppr_resp [ 6]; + ncrcmd send_ppr [ 4]; ncrcmd nego_bad_phase [ 4]; - ncrcmd msg_out_abort [ 12]; - ncrcmd msg_out [ 6]; + ncrcmd msg_out [ 4]; ncrcmd msg_out_done [ 4]; - ncrcmd no_data [ 28]; + ncrcmd data_ovrun [ 18]; + ncrcmd data_ovrun1 [ 20]; ncrcmd abort_resel [ 16]; ncrcmd resend_ident [ 4]; ncrcmd ident_break [ 4]; @@ -2621,7 +2663,7 @@ ncrcmd data_io [ 2]; ncrcmd data_io_com [ 8]; ncrcmd data_io_out [ 12]; - ncrcmd bad_identify [ 12]; + ncrcmd resel_bad_lun [ 4]; ncrcmd bad_i_t_l [ 4]; ncrcmd bad_i_t_l_q [ 4]; ncrcmd bad_status [ 6]; @@ -2632,14 +2674,13 @@ ncrcmd pm0_save [ 14]; ncrcmd pm1_save [ 14]; - /* SWIDE handling */ - ncrcmd swide_ma_32 [ 4]; - ncrcmd swide_ma_64 [ 6]; - ncrcmd swide_scr_64 [ 26]; - ncrcmd swide_scr_64_1 [ 12]; - ncrcmd swide_com_64 [ 6]; - ncrcmd swide_common [ 10]; - ncrcmd swide_fin_32 [ 24]; + /* WSR handling */ +#ifdef SYM_DEBUG_PM_WITH_WSR + ncrcmd pm_wsr_handle [ 44]; +#else + ncrcmd pm_wsr_handle [ 42]; +#endif + ncrcmd wsr_ma_helper [ 4]; /* Data area */ ncrcmd zero [ 1]; @@ -2697,6 +2738,9 @@ static void ncr_int_udc (ncb_p np); static void ncr_negotiate (ncb_p np, tcb_p tp); static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr); +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr); +#endif #ifdef SCSI_NCR_PROFILE_SUPPORT static void ncb_profile (ncb_p np, ccb_p cp); #endif @@ -2706,9 +2750,12 @@ static int ncr_scatter_896R1 (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd); static int ncr_scatter (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd); static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p); -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer); +static void ncr_get_xfer_info(ncb_p np, tcb_p tp, u_char *factor, u_char *offset, u_char *width); +static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, u_char scntl4); +static void ncr_set_sync_wide_status (ncb_p np, u_char target); static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln); static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); +static void ncr_setsyncwide (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, u_char scntl4, u_char wide); static int ncr_show_msg (u_char * msg); static void ncr_print_msg (ccb_p cp, char *label, u_char * msg); static int ncr_snooptest (ncb_p np); @@ -2978,9 +3025,9 @@ SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), PADDR (msg_in), SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)), - PADDR (dataphase), + PADDR (datao_phase), SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)), - PADDR (dataphase), + PADDR (datai_phase), SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), PADDR (status), SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), @@ -2988,6 +3035,12 @@ SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), PADDRH (msg_out), /* + * Set the extended error flag. + */ + SCR_REG_REG (HF_REG, SCR_OR, HF_EXT_ERR), + 0, + + /* ** Discard one illegal phase byte, if required. */ SCR_LOAD_REL (scratcha, 1), @@ -3056,17 +3109,6 @@ SCR_JUMP, PADDR (dispatch), -}/*-------------------------< DISP_MSG_IN >----------------------*/,{ - /* - ** Anticipate MSG_IN phase then STATUS phase. - ** - ** May spare 2 SCRIPTS instructions when we have - ** completed the OUTPUT of the data and the device - ** goes directly to STATUS phase. - */ - SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)), - PADDR (msg_in), - }/*-------------------------< DISP_STATUS >----------------------*/,{ /* ** Anticipate STATUS phase. @@ -3081,6 +3123,12 @@ }/*-------------------------< DATAI_DONE >-------------------*/,{ /* + * If the device wants us to send more data, + * we must count the extra bytes. + */ + SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)), + PADDRH (data_ovrun), + /* ** If the SWIDE is not full, jump to dispatcher. ** We anticipate a STATUS phase. ** If we get later an IGNORE WIDE RESIDUE, we @@ -3097,36 +3145,56 @@ SCR_REG_REG (scntl2, SCR_OR, WSR), 0, /* - ** Since the device is required to send any - ** IGNORE WIDE RESIDUE message prior to any - ** other information, we just snoop the SCSI - ** BUS to check for such a message. + * We are expecting an IGNORE RESIDUE message + * from the device, otherwise we are in data + * overrun condition. Check against MSG_IN phase. */ + SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), + SIR_SWIDE_OVERRUN, SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), PADDR (disp_status), - SCR_FROM_REG (sbdl), - 0, + /* + * We are in MSG_IN phase, + * Read the first byte of the message. + * If it is not an IGNORE RESIDUE message, + * signal overrun and jump to message + * processing. + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin[0]), + SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)), + SIR_SWIDE_OVERRUN, SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), - PADDR (disp_status), + PADDR (msg_in2), + /* - ** We have been ODD at the end of the transfer, - ** but the device hasn't be so. - ** Signal a DATA OVERRUN condition to the C code. - */ - SCR_INT, - SIR_SWIDE_OVERRUN, + * We got the message we expected. + * Read the 2nd byte, and jump to dispatcher. + */ + SCR_CLR (SCR_ACK), + 0, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin[1]), + SCR_CLR (SCR_ACK), + 0, SCR_JUMP, - PADDR (dispatch), + PADDR (disp_status), }/*-------------------------< DATAO_DONE >-------------------*/,{ /* + * If the device wants us to send more data, + * we must count the extra bytes. + */ + SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)), + PADDRH (data_ovrun), + /* ** If the SODL is not full jump to dispatcher. ** We anticipate a MSG IN phase or a STATUS phase. */ SCR_FROM_REG (scntl2), 0, SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)), - PADDR (disp_msg_in), + PADDR (disp_status), /* ** The SODL is full, clear this condition. */ @@ -3157,13 +3225,25 @@ SCR_JUMP, PADDR (clrack), -}/*-------------------------< DATAPHASE >------------------*/,{ +}/*-------------------------< DATAI_PHASE >------------------*/,{ #ifdef SCSI_NCR_PROFILE_SUPPORT SCR_REG_REG (QU_REG, SCR_OR, HF_DATA_ST), 0, #endif SCR_RETURN, 0, +}/*-------------------------< DATAO_PHASE >------------------*/,{ + /* + ** Patch for 53c1010_66 only - to allow A0 part + ** to operate properly in a 33MHz PCI bus. + ** + ** SCR_REG_REG(scntl4, SCR_OR, 0x0c), + ** 0, + */ + SCR_NO_OP, + 0, + SCR_RETURN, + 0, }/*-------------------------< MSG_IN >--------------------*/,{ /* ** Get the first byte of the message. @@ -3524,31 +3604,42 @@ offsetof(struct tcb, wval), SCR_LOAD_REL (sxfer, 1), offsetof(struct tcb, sval), +}/*-------------------------< RESEL_SCNTL4 >------------------*/,{ /* - ** If MESSAGE IN phase as expected, - ** read the data directly from the BUS DATA lines. - ** This helps to support very old SCSI devices that - ** may reselect without sending an IDENTIFY. + ** Write with uval value. Patch if device + ** does not support Ultra3. + ** + ** SCR_LOAD_REL (scntl4, 1), + ** offsetof(struct tcb, uval), */ + + SCR_NO_OP, + 0, + /* + * We expect MESSAGE IN phase. + * If not, get help from the C code. + */ SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)), SIR_RESEL_NO_MSG_IN, - SCR_FROM_REG (sbdl), - 0, + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + /* - ** If message phase but not an IDENTIFY, - ** get some help from the C code. - ** Old SCSI device may behave so. - */ + * If IDENTIFY LUN #0, use a faster path + * to find the LCB structure. + */ + SCR_JUMPR ^ IFTRUE (MASK (0x80, 0xbf)), + 56, + /* + * If message isn't an IDENTIFY, + * tell the C code about. + */ SCR_INT ^ IFFALSE (MASK (0x80, 0x80)), SIR_RESEL_NO_IDENTIFY, /* - ** It is an IDENTIFY message, - ** Load the LUN control block address. - ** If LUN 0, avoid a PCI BUS ownership by loading - ** directly 'b_lun0' from the TCB. - */ - SCR_JUMPR ^ IFTRUE (MASK (0x0, 0x3f)), - 48, + * It is an IDENTIFY message, + * Load the LUN control block address. + */ SCR_LOAD_REL (dsa, 4), offsetof(struct tcb, b_luntbl), SCR_SFBR_REG (dsa, SCR_SHL, 0), @@ -3578,15 +3669,20 @@ offsetof(struct lcb, b_tasktbl), SCR_RETURN, 0, - }/*-------------------------< RESEL_TAG >-------------------*/,{ /* + ** ACK the IDENTIFY or TAG previously received + */ + + SCR_CLR (SCR_ACK), + 0, + /* ** Read IDENTIFY + SIMPLE + TAG using a single MOVE. ** Agressive optimization, is'nt it? ** No need to test the SIMPLE TAG message, since the ** driver only supports conformant devices for tags. ;-) */ - SCR_MOVE_ABS (3) ^ SCR_MSG_IN, + SCR_MOVE_ABS (2) ^ SCR_MSG_IN, NADDR (msgin), /* ** Read the TAG from the SIDL. @@ -3627,14 +3723,9 @@ offsetof(struct ccb, phys.header.go.restart), SCR_RETURN, 0, + /* In normal situations we branch to RESEL_DSA */ }/*-------------------------< RESEL_NOTAG >-------------------*/,{ /* - ** No tag expected. - ** Read an throw away the IDENTIFY. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - /* ** JUMP indirectly to the restart point of the CCB. */ SCR_JUMP, @@ -3681,7 +3772,7 @@ SCR_CALL, PADDR (datai_done), SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< DATA_OUT >--------------------*/,{ /* ** Because the size depends on the @@ -3700,7 +3791,7 @@ SCR_CALL, PADDR (datao_done), SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< PM0_DATA >--------------------*/,{ /* @@ -3719,7 +3810,7 @@ ** Check against expected direction. */ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM0 DATA mini-script. @@ -3739,7 +3830,7 @@ ** Check against expected direction. */ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM0 DATA mini-script. @@ -3784,7 +3875,7 @@ ** Check against expected direction. */ SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM1 DATA mini-script. @@ -3804,7 +3895,7 @@ ** Check against expected direction. */ SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)), - PADDRH (no_data), + PADDRH (data_ovrun), /* ** Keep track we are moving data from the ** PM1 DATA mini-script. @@ -3835,6 +3926,7 @@ }/*---------------------------------------------------------*/ }; + static struct scripth scripth0 __initdata = { /*------------------------< START64 >-----------------------*/{ /* @@ -3844,7 +3936,9 @@ */ SCR_JUMP, PADDR (init), - +}/*-------------------------< NO_DATA >-------------------*/,{ + SCR_JUMP, + PADDRH (data_ovrun), }/*-----------------------< SEL_FOR_ABORT >------------------*/,{ /* ** We are jumped here by the C code, if we have @@ -4078,33 +4172,31 @@ SCR_JUMP, PADDRH (msg_out_done), -}/*-------------------------< NEGO_BAD_PHASE >------------*/,{ - SCR_INT, - SIR_NEGO_PROTO, - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ +}/*-------------------------< PPR_RESP >-------------*/,{ /* - ** After ABORT message, - ** - ** expect an immediate disconnect, ... + ** let the target fetch our answer. */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK|SCR_ATN), + SCR_SET (SCR_ATN), 0, - SCR_WAIT_DISC, + SCR_CLR (SCR_ACK), 0, - SCR_INT, - SIR_MSG_OUT_DONE, + SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)), + PADDRH (nego_bad_phase), + +}/*-------------------------< SEND_PPR >-------------*/,{ /* - ** ... and set the status to "ABORTED" + ** Send the M_X_PPR_REQ */ - SCR_LOAD_REG (HS_REG, HS_ABORTED), - 0, + SCR_MOVE_ABS (8) ^ SCR_MSG_OUT, + NADDR (msgout), + SCR_JUMP, + PADDRH (msg_out_done), + +}/*-------------------------< NEGO_BAD_PHASE >------------*/,{ + SCR_INT, + SIR_NEGO_PROTO, SCR_JUMP, - PADDR (complete2), + PADDR (dispatch), }/*-------------------------< MSG_OUT >-------------------*/,{ /* @@ -4113,11 +4205,6 @@ SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, NADDR (msgout), /* - ** If it was no ABORT message ... - */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), - PADDRH (msg_out_abort), - /* ** ... wait for the next phase ** if it's a message out, send it again, ... */ @@ -4135,34 +4222,56 @@ SCR_JUMP, PADDR (dispatch), -}/*-------------------------< NO_DATA >--------------------*/,{ +}/*-------------------------< DATA_OVRUN >--------------------*/,{ /* - ** The target wants to tranfer too much data - ** or in the wrong direction. - ** Remember that in extended error. - */ + * The target may want to transfer too much data. + * + * If phase is DATA OUT write 1 byte and count it. + */ + SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), + 16, + SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT, + NADDR (scratch), + SCR_JUMP, + PADDRH (data_ovrun1), + /* + * If WSR is set, clear this condition, and + * count this byte. + */ + SCR_FROM_REG (scntl2), + 0, + SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), + 16, + SCR_REG_REG (scntl2, SCR_OR, WSR), + 0, + SCR_JUMP, + PADDRH (data_ovrun1), + /* + * Finally check against DATA IN phase. + * Jump to dispatcher if not so. + * Read 1 byte otherwise and count it. + */ + SCR_JUMP ^ IFFALSE (IF (SCR_DATA_IN)), + PADDR (dispatch), + SCR_CHMOV_ABS (1) ^ SCR_DATA_IN, + NADDR (scratch), +}/*-------------------------< DATA_OVRUN1 >--------------------*/,{ + /* + * Set the extended error flag. + */ + SCR_REG_REG (HF_REG, SCR_OR, HF_EXT_ERR), + 0, SCR_LOAD_REL (scratcha, 1), offsetof (struct ccb, xerr_status), - SCR_REG_REG (scratcha, SCR_OR, XE_EXTRA_DATA), + SCR_REG_REG (scratcha, SCR_OR, XE_EXTRA_DATA), 0, SCR_STORE_REL (scratcha, 1), offsetof (struct ccb, xerr_status), /* - ** Discard one data byte, if required. - */ - SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_IN, - NADDR (scratch), - /* - ** Count this byte. - ** This will allow to return a positive - ** residual to user. - */ + * Count this byte. + * This will allow to return a negative + * residual to user. + */ SCR_LOAD_REL (scratcha, 4), offsetof (struct ccb, phys.extra_bytes), SCR_REG_REG (scratcha, SCR_ADD, 0x01), @@ -4174,12 +4283,10 @@ SCR_STORE_REL (scratcha, 4), offsetof (struct ccb, phys.extra_bytes), /* - ** .. and repeat as required. - */ - SCR_CALL, - PADDR (dispatch), + * .. and repeat as required. + */ SCR_JUMP, - PADDRH (no_data), + PADDRH (data_ovrun), }/*-------------------------< ABORT_RESEL >----------------*/,{ SCR_SET (SCR_ATN), @@ -4227,10 +4334,9 @@ SCR_CHMOV_TBL ^ SCR_DATA_IN, offsetof (struct dsb, sense), SCR_CALL, - PADDR (dispatch), + PADDR (datai_done), SCR_JUMP, - PADDRH (no_data), - + PADDRH (data_ovrun), }/*-------------------------< DATA_IO >--------------------*/,{ /* ** We jump here if the data direction was unknown at the @@ -4280,29 +4386,14 @@ SCR_JUMP, PADDRH(data_io_com), -}/*-------------------------< BAD_IDENTIFY >---------------*/,{ - /* - ** If message phase but not an IDENTIFY, - ** get some help from the C code. - ** Old SCSI device may behave so. - */ - SCR_JUMPR ^ IFTRUE (MASK (0x80, 0x80)), - 16, - SCR_INT, - SIR_RESEL_NO_IDENTIFY, - SCR_JUMP, - PADDRH (abort_resel), +}/*-------------------------< RESEL_BAD_LUN >---------------*/,{ /* ** Message is an IDENTIFY, but lun is unknown. - ** Read the message, since we got it directly - ** from the SCSI BUS data lines. ** Signal problem to C code for logging the event. ** Send a M_ABORT to clear all pending tasks. */ SCR_INT, SIR_RESEL_BAD_LUN, - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), SCR_JUMP, PADDRH (abort_resel), }/*-------------------------< BAD_I_T_L >------------------*/,{ @@ -4441,7 +4532,7 @@ SCR_FROM_REG (scntl2), 0, SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), - PADDRH (swide_scr_64), + PADDRH (pm_wsr_handle), /* ** Save the remaining byte count, the updated ** address and the return address. @@ -4468,7 +4559,7 @@ SCR_FROM_REG (scntl2), 0, SCR_CALL ^ IFTRUE (MASK (WSR, WSR)), - PADDRH (swide_scr_64), + PADDRH (pm_wsr_handle), /* ** Save the remaining byte count, the updated ** address and the return address. @@ -4484,101 +4575,32 @@ PADDRH (pm1_data_addr), SCR_JUMP, PADDR (dispatch), - -}/*--------------------------< SWIDE_MA_32 >-----------------------*/,{ - /* - ** Handling of the SWIDE for 32 bit chips. - ** - ** We jump here from the C code with SCRATCHA - ** containing the address to write the SWIDE. - ** - Save 32 bit address in . - */ - SCR_STORE_ABS (scratcha, 4), - PADDRH (scratch), - SCR_JUMP, - PADDRH (swide_common), -}/*--------------------------< SWIDE_MA_64 >-----------------------*/,{ - /* - ** Handling of the SWIDE for 64 bit chips when the - ** hardware handling of phase mismatch is disabled. - ** - ** We jump here from the C code with SCRATCHA - ** containing the address to write the SWIDE and - ** SBR containing bit 32..39 of this address. - ** - Save 32 bit address in . - ** - Move address bit 32..39 to SFBR. - */ - SCR_STORE_ABS (scratcha, 4), - PADDRH (scratch), - SCR_FROM_REG (sbr), - 0, - SCR_JUMP, - PADDRH (swide_com_64), -}/*--------------------------< SWIDE_SCR_64 >-----------------------*/,{ - /* - ** Handling of the SWIDE for 64 bit chips when - ** hardware phase mismatch is enabled. - ** We are entered with a SCR_CALL from PMO_SAVE - ** and PM1_SAVE sub-scripts. - ** - ** Snoop the SCSI BUS in case of the device - ** willing to ignore this residue. - ** If it does, we must only increment the RBC, - ** since this register does reflect all bytes - ** received from the SCSI BUS including the SWIDE. - */ - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDRH (swide_scr_64_1), - SCR_FROM_REG (sbdl), - 0, - SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)), - PADDRH (swide_scr_64_1), - SCR_REG_REG (rbc, SCR_ADD, 1), - 0, - SCR_REG_REG (rbc1, SCR_ADDC, 0), - 0, - SCR_REG_REG (rbc2, SCR_ADDC, 0), - 0, +}/*--------------------------< PM_WSR_HANDLE >-----------------------*/,{ /* - ** Save UA and RBC, since the PM0/1_SAVE - ** sub-scripts haven't moved them to the - ** context yet and the below MOV may just - ** change their value. - */ - SCR_STORE_ABS (ua, 4), - PADDRH (scratch), - SCR_STORE_ABS (rbc, 4), - PADDRH (scratch1), + * Phase mismatch handling from SCRIPT with WSR set. + * Such a condition can occur if the chip wants to + * execute a CHMOV(size > 1) when the WSR bit is + * set and the target changes PHASE. + */ +#ifdef SYM_DEBUG_PM_WITH_WSR /* - ** Throw away the IGNORE WIDE RESIDUE message. - ** since we just did take care of it. - */ - SCR_MOVE_ABS (2) ^ SCR_MSG_IN, - NADDR (scratch), - SCR_CLR (SCR_ACK), - 0, + * Some debugging may still be needed.:) + */ + SCR_INT, + SIR_PM_WITH_WSR, +#endif /* - ** Restore UA and RBC registers and return. - */ - SCR_LOAD_ABS (ua, 4), - PADDRH (scratch), - SCR_LOAD_ABS (rbc, 4), - PADDRH (scratch1), - SCR_RETURN, - 0, -}/*--------------------------< SWIDE_SCR_64_1 >---------------------*/,{ + * We must move the residual byte to memory. + * + * UA contains bit 0..31 of the address to + * move the residual byte. + * Move it to the table indirect. + */ + SCR_STORE_REL (ua, 4), + offsetof (struct ccb, phys.wresid.addr), /* - ** We must grab the SWIDE and move it to - ** memory. - ** - ** - Save UA (32 bit address) in . - ** - Move address bit 32..39 to SFBR. - ** - Increment UA (updated address). - */ - SCR_STORE_ABS (ua, 4), - PADDRH (scratch), - SCR_FROM_REG (rbc3), - 0, + * Increment UA (move address to next position). + */ SCR_REG_REG (ua, SCR_ADD, 1), 0, SCR_REG_REG (ua1, SCR_ADDC, 0), @@ -4587,70 +4609,45 @@ 0, SCR_REG_REG (ua3, SCR_ADDC, 0), 0, -}/*--------------------------< SWIDE_COM_64 >-----------------------*/,{ /* - ** - Save DRS. - ** - Load DRS with address bit 32..39 of the - ** location to write the SWIDE. - ** SFBR has been loaded with these bits. - ** (Look above). - */ - SCR_STORE_ABS (drs, 4), - PADDRH (saved_drs), - SCR_LOAD_ABS (drs, 4), + * Compute SCRATCHA as: + * - size to transfer = 1 byte. + * - bit 24..31 = high address bit [32...39]. + */ + SCR_LOAD_ABS (scratcha, 4), PADDRH (zero), - SCR_TO_REG (drs), + SCR_REG_REG (scratcha, SCR_OR, 1), 0, -}/*--------------------------< SWIDE_COMMON >-----------------------*/,{ - /* - ** - Save current DSA - ** - Load DSA with bit 0..31 of the memory - ** location to write the SWIDE. - */ - SCR_STORE_ABS (dsa, 4), - PADDRH (saved_dsa), - SCR_LOAD_ABS (dsa, 4), - PADDRH (scratch), - /* - ** Move the SWIDE to memory. - ** Clear the WSR bit. - */ - SCR_STORE_REL (swide, 1), + SCR_FROM_REG (rbc3), 0, - SCR_REG_REG (scntl2, SCR_OR, WSR), + SCR_TO_REG (scratcha3), 0, /* - ** Restore the original DSA. - */ - SCR_LOAD_ABS (dsa, 4), - PADDRH (saved_dsa), -}/*--------------------------< SWIDE_FIN_32 >-----------------------*/,{ - /* - ** For 32 bit chip, the following SCRIPTS - ** instruction is patched with a JUMP to dispatcher. - ** (Look into the C code). - */ - SCR_LOAD_ABS (drs, 4), - PADDRH (saved_drs), + * Move this value to the table indirect. + */ + SCR_STORE_REL (scratcha, 4), + offsetof (struct ccb, phys.wresid.size), /* - ** 64 bit chip only. - ** If PM handling from SCRIPTS, we are just - ** a helper for the C code, so jump to - ** dispatcher now. - */ - SCR_FROM_REG (ccntl0), + * Wait for a valid phase. + * While testing with bogus QUANTUM drives, the C1010 + * sometimes raised a spurious phase mismatch with + * WSR and the CHMOV(1) triggered another PM. + * Waiting explicitely for the PHASE seemed to avoid + * the nested phase mismatch. Btw, this didn't happen + * using my IBM drives. + */ + SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)), 0, - SCR_JUMP ^ IFFALSE (MASK (ENPMJ, ENPMJ)), - PADDR (dispatch), /* - ** 64 bit chip with hardware PM handling enabled. - ** - ** Since we are paranoid:), we donnot want - ** a SWIDE followed by a CHMOV(1) to lead to - ** a CHMOV(0) in our PM context. - ** We check against such a condition. - ** Also does the C code. - */ + * Perform the move of the residual byte. + */ + SCR_CHMOV_TBL ^ SCR_DATA_IN, + offsetof (struct ccb, phys.wresid), + /* + * We can now handle the phase mismatch with UA fixed. + * RBC[0..23]=0 is a special case that does not require + * a PM context. The C code also checks against this. + */ SCR_FROM_REG (rbc), 0, SCR_RETURN ^ IFFALSE (DATA (0)), @@ -4664,19 +4661,29 @@ SCR_RETURN ^ IFFALSE (DATA (0)), 0, /* - ** If we are there, RBC(0..23) is zero, - ** and we just have to load the current - ** DATA SCRIPTS address (register TEMP) - ** with the IA and go to dispatch. - ** No PM context is needed. - */ + * RBC[0..23]=0. + * Not only we donnot need a PM context, but this would + * lead to a bogus CHMOV(0). This condition means that + * the residual was the last byte to move from this CHMOV. + * So, we just have to move the current data script pointer + * (i.e. TEMP) to the SCRIPTS address following the + * interrupted CHMOV and jump to dispatcher. + */ SCR_STORE_ABS (ia, 4), PADDRH (scratch), SCR_LOAD_ABS (temp, 4), PADDRH (scratch), SCR_JUMP, PADDR (dispatch), - +}/*--------------------------< WSR_MA_HELPER >-----------------------*/,{ + /* + * Helper for the C code when WSR bit is set. + * Perform the move of the residual byte. + */ + SCR_CHMOV_TBL ^ SCR_DATA_IN, + offsetof (struct ccb, phys.wresid), + SCR_JUMP, + PADDR (dispatch), }/*-------------------------< ZERO >------------------------*/,{ SCR_DATA_ZERO, }/*-------------------------< SCRATCH >---------------------*/,{ @@ -4792,6 +4799,7 @@ assert ((u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in)); p = scr->data_out; + for (i=0; i SCRIPT_KVAR_LAST)) panic("ncr KVAR out of range"); @@ -5152,16 +5161,30 @@ static void __init ncr_save_initial_setting(ncb_p np) { np->sv_scntl0 = INB(nc_scntl0) & 0x0a; - np->sv_scntl3 = INB(nc_scntl3) & 0x07; np->sv_dmode = INB(nc_dmode) & 0xce; np->sv_dcntl = INB(nc_dcntl) & 0xa8; np->sv_ctest3 = INB(nc_ctest3) & 0x01; np->sv_ctest4 = INB(nc_ctest4) & 0x80; - np->sv_ctest5 = INB(nc_ctest5) & 0x24; np->sv_gpcntl = INB(nc_gpcntl); np->sv_stest2 = INB(nc_stest2) & 0x20; np->sv_stest4 = INB(nc_stest4); np->sv_stest1 = INB(nc_stest1); + + np->sv_scntl3 = INB(nc_scntl3) & 0x07; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66) ){ + /* + ** C1010 always uses large fifo, bit 5 rsvd + ** scntl4 used ONLY with C1010 + */ + np->sv_ctest5 = INB(nc_ctest5) & 0x04 ; + np->sv_scntl4 = INB(nc_scntl4); + } + else { + np->sv_ctest5 = INB(nc_ctest5) & 0x24 ; + np->sv_scntl4 = 0; + } } /* @@ -5200,15 +5223,35 @@ /* * Divisor to be used for async (timer pre-scaler). + * + * Note: For C1010 the async divisor is 2(8) if he + * quadrupler is disabled (enabled). */ - i = np->clock_divn - 1; - while (--i >= 0) { - if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { - ++i; - break; + + if ( (np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + + np->rv_scntl3 = 0; + } + else + { + i = np->clock_divn - 1; + while (--i >= 0) { + if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz + > div_10M[i]) { + ++i; + break; + } } + np->rv_scntl3 = i+1; } - np->rv_scntl3 = i+1; + + + /* + * Save the ultra3 register for the C1010/C1010_66 + */ + + np->rv_scntl4 = np->sv_scntl4; /* * Minimum synchronous period factor supported by the chip. @@ -5222,13 +5265,28 @@ else np->minsync = (period + 40 - 1) / 40; /* + * Fix up. If sync. factor is 10 (160000Khz clock) and chip + * supports ultra3, then min. sync. period 12.5ns and the factor is 9 + */ + + if ((np->minsync == 10) && (np->features & FE_ULTRA3)) + np->minsync = 9; + + /* * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). + * + * Transfer period minimums: SCSI-1 200 (50); Fast 100 (25) + * Ultra 50 (12); Ultra2 (6); Ultra3 (3) */ - if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) + if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2|FE_ULTRA3))) np->minsync = 25; - else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) + else if (np->minsync < 12 && (np->features & FE_ULTRA)) np->minsync = 12; + else if (np->minsync < 10 && (np->features & FE_ULTRA2)) + np->minsync = 10; + else if (np->minsync < 9 && (np->features & FE_ULTRA3)) + np->minsync = 9; /* * Maximum synchronous period factor supported by the chip. @@ -5248,7 +5306,7 @@ #endif /* - ** Phase mismatch handled by SCRIPTS (53C895A or 53C896) ? + ** Phase mismatch handled by SCRIPTS (53C895A, 53C896 or C1010) ? */ if (np->features & FE_NOPM) np->rv_ccntl0 |= (ENPMJ); @@ -5292,6 +5350,14 @@ np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP); /* + ** DEL ? - 53C1010 Rev 1 - Part Number 609-0393638 + ** 64-bit Slave Cycles must be disabled. + */ + if ( ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) && (np->revision_id < 0x02) ) + || (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 ) ) + np->rv_ccntl1 |= 0x10; + + /* ** Select all supported special features. ** If we are using on-board RAM for scripts, prefetch (PFEN) ** does not help, but burst op fetch (BOF) does. @@ -5313,8 +5379,13 @@ np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ if (np->features & FE_WRIE) np->rv_ctest3 |= WRIE; /* Write and Invalidate */ - if (np->features & FE_DFS) + + + if ( (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && + (np->features & FE_DFS)) np->rv_ctest5 |= DFS; /* Dma Fifo Size */ + /* C1010/C1010_66 always large fifo */ /* ** Select some other @@ -5362,14 +5433,15 @@ /* ** Set SCSI BUS mode. ** - ** - ULTRA2 chips (895/895A/896) report the current + ** - ULTRA2 chips (895/895A/896) + ** and ULTRA 3 chips (1010) report the current ** BUS mode through the STEST4 IO register. ** - For previous generation chips (825/825A/875), ** user has to tell us how to check against HVD, ** since a 100% safe algorithm is not possible. */ np->scsi_mode = SMODE_SE; - if (np->features & FE_ULTRA2) + if (np->features & (FE_ULTRA2 | FE_ULTRA3)) np->scsi_mode = (np->sv_stest4 & SMODE); else if (np->features & FE_DIFF) { switch(driver_setup.diff_support) { @@ -5471,7 +5543,8 @@ i == SCSI_NCR_SYMBIOS_NVRAM ? "Symbios format NVRAM, " : (i == SCSI_NCR_TEKRAM_NVRAM ? "Tekram format NVRAM, " : ""), np->myaddr, - np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10), + np->minsync < 10 ? 80 : + (np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10) ), (np->rv_scntl0 & 0xa) ? ", Parity Checking" : ", NO Parity", (np->rv_stest2 & 0x20) ? ", Differential" : ""); @@ -5864,14 +5937,6 @@ ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); /* - ** If not 64 bit chip, patch some places in SCRIPTS. - */ - if (!(np->features & FE_64BIT)) { - np->scripth0->swide_fin_32[0] = cpu_to_scr(SCR_JUMP); - np->scripth0->swide_fin_32[1] = - cpu_to_scr(NCB_SCRIPT_PHYS(np, dispatch)); - } - /* ** Patch some variables in SCRIPTS */ np->scripth0->pm0_data_addr[0] = @@ -5879,6 +5944,15 @@ np->scripth0->pm1_data_addr[0] = cpu_to_scr(NCB_SCRIPT_PHYS(np, pm1_data)); + /* + ** Patch if not Ultra 3 - Do not write to scntl4 + */ + if (np->features & FE_ULTRA3) { + np->script0->resel_scntl4[0] = cpu_to_scr(SCR_LOAD_REL (scntl4, 1)); + np->script0->resel_scntl4[1] = cpu_to_scr(offsetof(struct tcb, uval)); + } + + #ifdef SCSI_NCR_PCI_MEM_NOT_SUPPORTED np->scripth0->script0_ba[0] = cpu_to_scr(vtobus(np->script0)); np->scripth0->script0_ba64[0] = cpu_to_scr(vtobus(np->script0)); @@ -5912,7 +5986,7 @@ goto attach_error; assert (offsetof(struct lcb, resel_task) == 0); - np->resel_badlun = cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_identify)); + np->resel_badlun = cpu_to_scr(NCB_SCRIPTH_PHYS(np, resel_bad_lun)); for (i = 0 ; i < 64 ; i++) np->badluntbl[i] = cpu_to_scr(NCB_PHYS(np, resel_badlun)); @@ -5940,6 +6014,15 @@ cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe)); } + /* + ** Patch the script to provide an extra clock cycle on + ** data out phase - 53C1010_66MHz part only. + */ + if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66){ + np->script0->datao_phase[0] = + cpu_to_scr(SCR_REG_REG(scntl4, SCR_OR, 0x0c)); + } + #ifdef SCSI_NCR_IARB_SUPPORT /* ** If user does not want to use IMMEDIATE ARBITRATION @@ -5968,8 +6051,11 @@ #else #define XXX 2 #endif - np->script0->dataphase[XXX] = cpu_to_scr(SCR_JUMP); - np->script0->dataphase[XXX+1] = + np->script0->datai_phase[XXX] = cpu_to_scr(SCR_JUMP); + np->script0->datai_phase[XXX+1] = + cpu_to_scr(NCB_SCRIPTH_PHYS (np, tweak_pmj)); + np->script0->datao_phase[0] = cpu_to_scr(SCR_JUMP); + np->script0->datao_phase[1] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tweak_pmj)); #undef XXX } @@ -5985,6 +6071,9 @@ ** We should use ncr_soft_reset(), but we donnot want to do ** so, since we may not be safe if ABRT interrupt occurs due ** to the BIOS or previous O/S having enable this interrupt. + ** + ** For C1010 need to set ABRT bit prior to SRST if SCRIPTs + ** are running. Not true in this case. */ ncr_chip_reset(np); @@ -6089,6 +6178,19 @@ instance->dma_channel = 0; instance->cmd_per_lun = MAX_TAGS; instance->can_queue = (MAX_START-4); + + np->check_integrity = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + instance->check_integrity = 0; + +#ifdef SCSI_NCR_ENABLE_INTEGRITY_CHECK + if ( !(driver_setup.bus_check & 0x04) ) { + np->check_integrity = 1; + instance->check_integrity = 1; + } +#endif +#endif instance->select_queue_depths = sym53c8xx_select_queue_depths; @@ -6214,6 +6316,299 @@ /*========================================================== ** ** +** Prepare the next negotiation message for integrity check, +** if needed. +** +** Fill in the part of message buffer that contains the +** negotiation and the nego_status field of the CCB. +** Returns the size of the message in bytes. +** +** If tp->ppr_negotiation is 1 and a M_REJECT occurs, then +** we disable ppr_negotiation. If the first ppr_negotiation is +** successful, set this flag to 2. +** +**========================================================== +*/ +#ifdef SCSI_NCR_INTEGRITY_CHECKING +static int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr) +{ + tcb_p tp = &np->target[cp->target]; + int msglen = 0; + int nego = 0; + u_char new_width, new_offset, new_period; + u_char no_increase; + + if (tp->ppr_negotiation == 1) /* PPR message successful */ + tp->ppr_negotiation = 2; + + if (tp->inq_done) { + + if (!tp->ic_maximums_set) { + tp->ic_maximums_set = 1; + + /* + * Check against target, host and user limits + */ + if ( (tp->inq_byte7 & INQ7_WIDE16) && + np->maxwide && tp->usrwide) + tp->ic_max_width = 1; + else + tp->ic_max_width = 0; + + + if ((tp->inq_byte7 & INQ7_SYNC) && tp->maxoffs) + tp->ic_min_sync = (tp->minsync < np->minsync) ? + np->minsync : tp->minsync; + else + tp->ic_min_sync = 255; + + tp->period = 1; + tp->widedone = 1; + + /* + * Enable PPR negotiation - only if Ultra3 support + * is accessible. + */ + +#if 0 + if (tp->ic_max_width && (tp->ic_min_sync != 255 )) + tp->ppr_negotiation = 1; +#endif + tp->ppr_negotiation = 0; + if (np->features & FE_ULTRA3) { + if (tp->ic_max_width && (tp->ic_min_sync == 0x09)) + tp->ppr_negotiation = 1; + } + + if (!tp->ppr_negotiation) + cmd->ic_nego &= ~NS_PPR; + } + + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: cmd->ic_nego %d, 1st byte 0x%2X\n", + ncr_name(np), cmd->ic_nego, cmd->cmnd[0]); + } + + /* Previous command recorded a parity or an initiator + * detected error condition. Force bus to narrow for this + * target. Clear flag. Negotation on request sense. + * Note: kernel forces 2 bus resets :o( but clears itself out. + * Minor bug? in scsi_obsolete.c (ugly) + */ + if (np->check_integ_par) { + printk("%s: Parity Error. Target set to narrow.\n", + ncr_name(np)); + tp->ic_max_width = 0; + tp->widedone = tp->period = 0; + } + + /* Initializing: + * If ic_nego == NS_PPR, we are in the initial test for + * PPR messaging support. If driver flag is clear, then + * either we don't support PPR nego (narrow or async device) + * or this is the second TUR and we have had a M. REJECT + * or unexpected disconnect on the first PPR negotiation. + * Do not negotiate, reset nego flags (in case a reset has + * occurred), clear ic_nego and return. + * General case: Kernel will clear flag on a fallback. + * Do only SDTR or WDTR in the future. + */ + if (!tp->ppr_negotiation && (cmd->ic_nego == NS_PPR )) { + tp->ppr_negotiation = 0; + cmd->ic_nego &= ~NS_PPR; + tp->widedone = tp->period = 1; + return msglen; + } + else if (( tp->ppr_negotiation && !(cmd->ic_nego & NS_PPR )) || + (!tp->ppr_negotiation && (cmd->ic_nego & NS_PPR )) ) { + tp->ppr_negotiation = 0; + cmd->ic_nego &= ~NS_PPR; + } + + /* + * Always check the PPR nego. flag bit if ppr_negotiation + * is set. If the ic_nego PPR bit is clear, + * there must have been a fallback. Do only + * WDTR / SDTR in the future. + */ + if ((tp->ppr_negotiation) && (!(cmd->ic_nego & NS_PPR))) + tp->ppr_negotiation = 0; + + /* In case of a bus reset, ncr_negotiate will reset + * the flags tp->widedone and tp->period to 0, forcing + * a new negotiation. Do WDTR then SDTR. If PPR, do both. + * Do NOT increase the period. It is possible for the Scsi_Cmnd + * flags to be set to increase the period when a bus reset + * occurs - we don't want to change anything. + */ + + no_increase = 0; + + if (tp->ppr_negotiation && (!tp->widedone) && (!tp->period) ) { + cmd->ic_nego = NS_PPR; + tp->widedone = tp->period = 1; + no_increase = 1; + } + else if (!tp->widedone) { + cmd->ic_nego = NS_WIDE; + tp->widedone = 1; + no_increase = 1; + } + else if (!tp->period) { + cmd->ic_nego = NS_SYNC; + tp->period = 1; + no_increase = 1; + } + + new_width = cmd->ic_nego_width & tp->ic_max_width; + + switch (cmd->ic_nego_sync) { + case 2: /* increase the period */ + if (!no_increase) { + if (tp->ic_min_sync <= 0x09) + tp->ic_min_sync = 0x0A; + else if (tp->ic_min_sync <= 0x0A) + tp->ic_min_sync = 0x0C; + else if (tp->ic_min_sync <= 0x0C) + tp->ic_min_sync = 0x19; + else if (tp->ic_min_sync <= 0x19) + tp->ic_min_sync *= 2; + else { + tp->ic_min_sync = 255; + cmd->ic_nego_sync = 0; + tp->maxoffs = 0; + } + } + new_period = tp->maxoffs?tp->ic_min_sync:0; + new_offset = tp->maxoffs; + break; + + case 1: /* nego. to maximum */ + new_period = tp->maxoffs?tp->ic_min_sync:0; + new_offset = tp->maxoffs; + break; + + case 0: /* nego to async */ + default: + new_period = 0; + new_offset = 0; + break; + }; + + + nego = NS_NOCHANGE; + if (tp->ppr_negotiation) { + u_char options_byte = 0; + + /* + ** Must make sure data is consistent. + ** If period is 9 and sync, must be wide and DT bit set. + ** else period must be larger. If the width is 0, + ** reset bus to wide but increase the period to 0x0A. + ** Note: The strange else clause is due to the integrity check. + ** If fails at 0x09, wide, the I.C. code will redo at the same + ** speed but a narrow bus. The driver must take care of slowing + ** the bus speed down. + ** + ** The maximum offset in ST mode is 31, in DT mode 62 (1010/1010_66 only) + */ + if ( (new_period==0x09) && new_offset) { + if (new_width) + options_byte = 0x02; + else { + tp->ic_min_sync = 0x0A; + new_period = 0x0A; + cmd->ic_nego_width = 1; + new_width = 1; + new_offset &= 0x1f; + } + } + else if (new_period > 0x09) + new_offset &= 0x1f; + + nego = NS_PPR; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 6; + msgptr[msglen++] = M_X_PPR_REQ; + msgptr[msglen++] = new_period; + msgptr[msglen++] = 0; + msgptr[msglen++] = new_offset; + msgptr[msglen++] = new_width; + msgptr[msglen++] = options_byte; + + } + else { + switch (cmd->ic_nego & ~NS_PPR) { + case NS_WIDE: + /* + ** WDTR negotiation on if device supports + ** wide or if wide device forced narrow + ** due to a parity error. + */ + + cmd->ic_nego_width &= tp->ic_max_width; + + if (tp->ic_max_width | np->check_integ_par) { + nego = NS_WIDE; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = new_width; + } + break; + + case NS_SYNC: + /* + ** negotiate synchronous transfers + ** Target must support sync transfers. + ** Min. period = 0x0A, maximum offset of 31=0x1f. + */ + + if (tp->inq_byte7 & INQ7_SYNC) { + + if (new_offset && (new_period < 0x0A)) { + tp->ic_min_sync = 0x0A; + new_period = 0x0A; + } + nego = NS_SYNC; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = new_period; + msgptr[msglen++] = new_offset & 0x1f; + } + else + cmd->ic_nego_sync = 0; + break; + + case NS_NOCHANGE: + break; + } + } + + }; + + cp->nego_status = nego; + np->check_integ_par = 0; + + if (nego) { + tp->nego_cp = cp; + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, nego == NS_WIDE ? + "wide/narrow msgout": + (nego == NS_SYNC ? "sync/async msgout" : "ppr msgout"), + msgptr); + }; + }; + + return msglen; +} +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + +/*========================================================== +** +** ** Prepare the next negotiation message if needed. ** ** Fill in the part of message buffer that contains the @@ -6224,13 +6619,42 @@ **========================================================== */ + static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr) { tcb_p tp = &np->target[cp->target]; int msglen = 0; int nego = 0; + u_char width, offset, factor, last_byte; + + if (!np->check_integrity) { + /* If integrity checking disabled, enable PPR messaging + * if device supports wide, sync and ultra 3 + */ + if (tp->ppr_negotiation == 1) /* PPR message successful */ + tp->ppr_negotiation = 2; + + if ((tp->inq_done) && (!tp->ic_maximums_set)) { + tp->ic_maximums_set = 1; + + /* + * Issue PPR only if board is capable + * and set-up for Ultra3 transfers. + */ + tp->ppr_negotiation = 0; + if ( (np->features & FE_ULTRA3) && + (tp->usrwide) && (tp->maxoffs) && + (tp->minsync == 0x09) ) + tp->ppr_negotiation = 1; + } + } if (tp->inq_done) { + /* + * Get the current width, offset and period + */ + ncr_get_xfer_info( np, tp, &factor, + &offset, &width); /* ** negotiate wide transfers ? @@ -6238,19 +6662,50 @@ if (!tp->widedone) { if (tp->inq_byte7 & INQ7_WIDE16) { - nego = NS_WIDE; + if (tp->ppr_negotiation) + nego = NS_PPR; + else + nego = NS_WIDE; + + width = tp->usrwide; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (tp->ic_done) + width &= tp->ic_max_width; +#endif } else tp->widedone=1; + }; /* ** negotiate synchronous transfers? */ - if (!nego && !tp->period) { + if ((nego != NS_WIDE) && !tp->period) { if (tp->inq_byte7 & INQ7_SYNC) { - nego = NS_SYNC; + if (tp->ppr_negotiation) + nego = NS_PPR; + else + nego = NS_SYNC; + + /* Check for async flag */ + if (tp->maxoffs == 0) { + offset = 0; + factor = 0; + } + else { + offset = tp->maxoffs; + factor = tp->minsync; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((tp->ic_done) && + (factor < tp->ic_min_sync)) + factor = tp->ic_min_sync; +#endif + } + } else { + offset = 0; + factor = 0; tp->period =0xffff; PRINT_TARGET(np, cp->target); printk ("target did not report SYNC.\n"); @@ -6259,18 +6714,54 @@ }; switch (nego) { + case NS_PPR: + /* + ** Must make sure data is consistent. + ** If period is 9 and sync, must be wide and DT bit set + ** else period must be larger. + ** Maximum offset is 31=0x1f is ST mode, 62 if DT mode + */ + last_byte = 0; + if ( (factor==9) && offset) { + if (!width) { + factor = 0x0A; + offset &= 0x1f; + } + else + last_byte = 0x02; + } + else if (factor > 0x09) + offset &= 0x1f; + + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 6; + msgptr[msglen++] = M_X_PPR_REQ; + msgptr[msglen++] = factor; + msgptr[msglen++] = 0; + msgptr[msglen++] = offset; + msgptr[msglen++] = width; + msgptr[msglen++] = last_byte; + break; case NS_SYNC: + /* + ** Never negotiate faster than Ultra 2 (25ns periods) + */ + if (offset && (factor < 0x0A)) { + factor = 0x0A; + tp->minsync = 0x0A; + } + msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 3; msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; - msgptr[msglen++] = tp->maxoffs; + msgptr[msglen++] = factor; + msgptr[msglen++] = offset & 0x1f; break; case NS_WIDE: msgptr[msglen++] = M_EXTENDED; msgptr[msglen++] = 2; msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; + msgptr[msglen++] = width; break; }; @@ -6280,7 +6771,9 @@ tp->nego_cp = cp; if (DEBUG_FLAGS & DEBUG_NEGO) { ncr_print_msg(cp, nego == NS_WIDE ? - "wide msgout":"sync_msgout", msgptr); + "wide msgout": + (nego == NS_SYNC ? "sync msgout" : "ppr msgout"), + msgptr); }; }; @@ -6464,6 +6957,73 @@ cp->segments = 0; } + /*--------------------------------------------------- + ** + ** negotiation required? + ** + ** (nego_status is filled by ncr_prepare_nego()) + ** + **--------------------------------------------------- + */ + + cp->nego_status = 0; + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if ((np->check_integrity && tp->ic_done) || !np->check_integrity) { + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } + } + else if (np->check_integrity && (cmd->ic_in_progress)) { + msglen += ncr_ic_nego (np, cp, cmd, msgptr + msglen); + } + else if (np->check_integrity && cmd->ic_complete) { + u_long current_period; + u_char current_offset, current_width, current_factor; + + ncr_get_xfer_info (np, tp, ¤t_factor, + ¤t_offset, ¤t_width); + + tp->ic_max_width = current_width; + tp->ic_min_sync = current_factor; + + if (current_factor == 9) current_period = 125; + else if (current_factor == 10) current_period = 250; + else if (current_factor == 11) current_period = 303; + else if (current_factor == 12) current_period = 500; + else current_period = current_factor * 40; + + /* + * Negotiation for this target is complete. Update flags. + */ + tp->period = current_period; + tp->widedone = 1; + tp->ic_done = 1; + + printk("%s: Integrity Check Complete: \n", ncr_name(np)); + + printk("%s: %s %s SCSI", ncr_name(np), + current_offset?"SYNC":"ASYNC", + tp->ic_max_width?"WIDE":"NARROW"); + if (current_offset) { + u_long mbs = 10000 * (tp->ic_max_width + 1); + + printk(" %d.%d MB/s", + (int) (mbs / current_period), (int) (mbs % current_period)); + + printk(" (%d ns, %d offset)\n", + (int) current_period/10, current_offset); + } + else + printk(" %d MB/s. \n ", (tp->ic_max_width+1)*5); + } +#else + if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) { + msglen += ncr_prepare_nego (np, cp, msgptr + msglen); + } +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ + + /*---------------------------------------------------- ** ** Determine xfer direction. @@ -6524,19 +7084,6 @@ cp->startp = cp->phys.header.savep; cp->lastp0 = cp->phys.header.lastp; - /*--------------------------------------------------- - ** - ** negotiation required? - ** - ** (nego_status is filled by ncr_prepare_nego()) - ** - **--------------------------------------------------- - */ - - cp->nego_status = 0; - if ((!tp->widedone || !tp->period) && !tp->nego_cp && lp) - msglen += ncr_prepare_nego (np, cp, msgptr + msglen); - /*---------------------------------------------------- ** ** fill in ccb @@ -6559,6 +7106,7 @@ cp->phys.select.sel_id = cp->target; cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; + cp->phys.select.sel_scntl4 = tp->uval; /* ** message */ @@ -7091,6 +7639,14 @@ PRINT_ADDR(cmd); printk ("illegal scsi phase (4/5).\n"); } + if (cp->xerr_status & XE_SODL_UNRUN) { + PRINT_ADDR(cmd); + printk ("ODD transfer in DATA OUT phase.\n"); + } + if (cp->xerr_status & XE_SWIDE_OVRUN){ + PRINT_ADDR(cmd); + printk ("ODD transfer in DATA IN phase.\n"); + } if (cp->host_status==HS_COMPLETE) cp->host_status = HS_FAIL; @@ -7167,6 +7723,12 @@ PRINT_ADDR(cmd); ncr_printl_hex("sense data:", cmd->sense_buffer, 14); } + } else if ((cp->host_status == HS_COMPLETE) + && (cp->scsi_status == S_CONFLICT)) { + /* + ** Reservation Conflict condition code + */ + SetScsiResult(cmd, DID_OK, S_CONFLICT); } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_BUSY || @@ -7418,7 +7980,11 @@ OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */ OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */ - OUTB (nc_stest2, EXT|np->rv_stest2); /* Extended Sreq/Sack filtering */ + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)){ + OUTB (nc_stest2, EXT|np->rv_stest2); + /* Extended Sreq/Sack filtering, not supported in C1010/C1010_66 */ + } OUTB (nc_stest3, TE); /* TolerANT enable */ OUTB (nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */ @@ -7427,14 +7993,24 @@ ** Disable overlapped arbitration for all dual-function ** devices, regardless revision id. ** We may consider it is a post-chip-design feature. ;-) + ** + ** Errata applies to all 896 and 1010 parts. */ if (np->device_id == PCI_DEVICE_ID_NCR_53C875) OUTB (nc_ctest0, (1<<5)); - else if (np->device_id == PCI_DEVICE_ID_NCR_53C896) + else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 || + np->device_id == PCI_DEVICE_ID_LSI_53C1010 || + np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 ) np->rv_ccntl0 |= DPR; /* - ** If 64 bit (895A/896/1010) write the CCNTL1 register to + ** C1010_66MHz rev 0 part requies AIPCNTL1 bit 3 to be set. + */ + if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66) + OUTB(nc_aipcntl1, (1<<3)); + + /* + ** If 64 bit (895A/896/1010/1010_66) write the CCNTL1 register to ** enable 40 bit address table indirect addressing for MOVE. ** Also write CCNTL0 if 64 bit chip, since this register seems ** to only be used by 64 bit cores. @@ -7445,8 +8021,8 @@ } /* - ** If phase mismatch handled by scripts (53C895A or 53C896), - ** set PM jump addresses. + ** If phase mismatch handled by scripts (53C895A or 53C896 + ** or 53C1010 or 53C1010_66), set PM jump addresses. */ if (np->features & FE_NOPM) { @@ -7475,9 +8051,10 @@ OUTB (nc_dien , MDPE|BF|SSI|SIR|IID); /* - ** For 895/6 enable SBMC interrupt and save current SCSI bus mode. + ** For 895/895A/896/c1010 + ** Enable SBMC interrupt and save current SCSI bus mode. */ - if (np->features & FE_ULTRA2) { + if ( (np->features & FE_ULTRA2) || (np->features & FE_ULTRA3) ) { OUTONW (nc_sien, SBMC); np->scsi_mode = INB (nc_stest4) & SMODE; } @@ -7496,6 +8073,7 @@ tp->sval = 0; tp->wval = np->rv_scntl3; + tp->uval = np->rv_scntl4; if (tp->usrsync != 255) { if (tp->usrsync <= np->maxsync) { @@ -7626,6 +8204,10 @@ /* ** Compute the synchronous period in tenths of nano-seconds + ** from sfac. + ** + ** Note, if sfac == 9, DT is being used. Double the period of 125 + ** to 250. */ if (sfac <= 10) per = 250; else if (sfac == 11) per = 303; @@ -7673,7 +8255,76 @@ ** Compute and return sync parameters for the ncr */ *fakp = fak - 4; - *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); + + /* + ** If sfac < 25, and 8xx parts, desire that the chip operate at + ** least at Ultra speeds. Must set bit 7 of scntl3. + ** For C1010, do not set this bit. If operating at Ultra3 speeds, + ** set the U3EN bit instead. + */ + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + *scntl3p = (div+1) << 4; + *fakp = 0; + } + else { + *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); + *fakp = fak - 4; + } +} + +/*========================================================== +** +** Utility routine to return the current bus width +** synchronous period and offset. +** Utilizes target sval, wval and uval +** +**========================================================== +*/ +static void ncr_get_xfer_info(ncb_p np, tcb_p tp, u_char *factor, + u_char *offset, u_char *width) +{ + + u_char idiv; + u_long period; + + *width = (tp->wval & EWS) ? 1 : 0; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + *offset = (tp->sval & 0x3f); + else + *offset = (tp->sval & 0x1f); + + /* + * Midlayer signal to the driver that all of the scsi commands + * for the integrity check have completed. Save the negotiated + * parameters (extracted from sval, wval and uval). + * See ncr_setsync for alg. details. + */ + + idiv = (tp->wval>>4) & 0x07; + + if ( *offset && idiv ) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + if (tp->uval & 0x80) + period = (2*div_10M[idiv-1])/np->clock_khz; + else + period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + period = (((tp->sval>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } + else + period = 0xffff; + + if (period <= 125) *factor = 9; + else if (period <= 250) *factor = 10; + else if (period <= 303) *factor = 11; + else if (period <= 500) *factor = 12; + else *factor = (period + 40 - 1) / 40; + } @@ -7687,14 +8338,20 @@ static void ncr_set_sync_wide_status (ncb_p np, u_char target) { - ccb_p cp; + ccb_p cp = np->ccbc; tcb_p tp = &np->target[target]; /* ** set actual value and sync_status + ** + ** TEMP register contains current scripts address + ** which is data type/direction/dependent. */ OUTB (nc_sxfer, tp->sval); OUTB (nc_scntl3, tp->wval); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + OUTB (nc_scntl4, tp->uval); /* ** patch ALL ccbs of this target. @@ -7706,6 +8363,9 @@ continue; cp->phys.select.sel_scntl3 = tp->wval; cp->phys.select.sel_sxfer = tp->sval; + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + cp->phys.select.sel_scntl4 = tp->uval; }; } @@ -7716,11 +8376,13 @@ **========================================================== */ -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) +static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, + u_char scntl4) { tcb_p tp; u_char target = INB (nc_sdid) & 0x0f; u_char idiv; + u_char offset; assert (cp); if (!cp) return; @@ -7729,9 +8391,21 @@ tp = &np->target[target]; - if (!scntl3 || !(sxfer & 0x1f)) - scntl3 = np->rv_scntl3; - scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | (np->rv_scntl3 & 0x07); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + offset = sxfer & 0x3f; /* bits 5-0 */ + scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS); + scntl4 = (scntl4 & 0x80); + } + else { + offset = sxfer & 0x1f; /* bits 4-0 */ + if (!scntl3 || !offset) + scntl3 = np->rv_scntl3; + + scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | + (np->rv_scntl3 & 0x07); + } + /* ** Deduce the value of controller sync period from scntl3. @@ -7739,27 +8413,42 @@ */ idiv = ((scntl3 >> 4) & 0x7); - if ((sxfer & 0x1f) && idiv) - tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + if ( offset && idiv) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + /* Note: If extra data hold clocks are used, + * the formulas below must be modified. + * When scntl4 == 0, ST mode. + */ + if (scntl4 & 0x80) + tp->period = (2*div_10M[idiv-1])/np->clock_khz; + else + tp->period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } else tp->period = 0xffff; + /* ** Stop there if sync parameters are unchanged */ - if (tp->sval == sxfer && tp->wval == scntl3) return; + if (tp->sval == sxfer && tp->wval == scntl3 && tp->uval == scntl4) return; tp->sval = sxfer; tp->wval = scntl3; + tp->uval = scntl4; /* ** Bells and whistles ;-) ** Donnot announce negotiations due to auto-sense, ** unless user really want us to be verbose. :) */ - if (bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) + if ( bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) goto next; PRINT_TARGET(np, target); - if (sxfer & 0x01f) { + if (offset) { unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); unsigned mb10 = (f10 + tp->period/2) / tp->period; char *scsi; @@ -7767,19 +8456,23 @@ /* ** Disable extended Sreq/Sack filtering */ - if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT); + if ((tp->period <= 2000) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + OUTOFFB (nc_stest2, EXT); /* ** Bells and whistles ;-) */ - if (tp->period < 500) scsi = "FAST-40"; + if (tp->period < 250) scsi = "FAST-80"; + else if (tp->period < 500) scsi = "FAST-40"; else if (tp->period < 1000) scsi = "FAST-20"; else if (tp->period < 2000) scsi = "FAST-10"; else scsi = "FAST-5"; printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, tp->widedone > 1 ? "WIDE " : "", - mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); + mb10 / 10, mb10 % 10, tp->period / 10, offset); } else printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); next: @@ -7790,6 +8483,7 @@ ncr_set_sync_wide_status(np, target); } + /*========================================================== ** ** Switch wide mode for current job and it's target @@ -7843,6 +8537,126 @@ ncr_set_sync_wide_status(np, target); } + +/*========================================================== +** +** Switch sync/wide mode for current job and it's target +** PPR negotiations only +** +**========================================================== +*/ + +static void ncr_setsyncwide (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer, + u_char scntl4, u_char wide) +{ + tcb_p tp; + u_char target = INB (nc_sdid) & 0x0f; + u_char idiv; + u_char offset; + + assert (cp); + if (!cp) return; + + assert (target == (cp->target & 0xf)); + + tp = &np->target[target]; + tp->widedone = wide+1; + + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + offset = sxfer & 0x3f; /* bits 5-0 */ + scntl3 = (scntl3 & 0xf0) | (wide ? EWS : 0); + scntl4 = (scntl4 & 0x80); + } + else { + offset = sxfer & 0x1f; /* bits 4-0 */ + if (!scntl3 || !offset) + scntl3 = np->rv_scntl3; + + scntl3 = (scntl3 & 0xf0) | (wide ? EWS : 0) | + (np->rv_scntl3 & 0x07); + } + + + /* + ** Deduce the value of controller sync period from scntl3. + ** period is in tenths of nano-seconds. + */ + + idiv = ((scntl3 >> 4) & 0x7); + if ( offset && idiv) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + /* Note: If extra data hold clocks are used, + * the formulas below must be modified. + * When scntl4 == 0, ST mode. + */ + if (scntl4 & 0x80) + tp->period = (2*div_10M[idiv-1])/np->clock_khz; + else + tp->period = (4*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; + } + else + tp->period = 0xffff; + + + /* + ** Stop there if sync parameters are unchanged + */ + if (tp->sval == sxfer && tp->wval == scntl3 && tp->uval == scntl4) return; + tp->sval = sxfer; + tp->wval = scntl3; + tp->uval = scntl4; + + /* + ** Bells and whistles ;-) + ** Donnot announce negotiations due to auto-sense, + ** unless user really want us to be verbose. :) + */ + if ( bootverbose < 2 && (cp->host_flags & HF_AUTO_SENSE)) + goto next; + PRINT_TARGET(np, target); + if (offset) { + unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); + unsigned mb10 = (f10 + tp->period/2) / tp->period; + char *scsi; + + /* + ** Disable extended Sreq/Sack filtering + */ + if ((tp->period <= 2000) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + OUTOFFB (nc_stest2, EXT); + + /* + ** Bells and whistles ;-) + */ + if (tp->period < 250) scsi = "FAST-80"; + else if (tp->period < 500) scsi = "FAST-40"; + else if (tp->period < 1000) scsi = "FAST-20"; + else if (tp->period < 2000) scsi = "FAST-10"; + else scsi = "FAST-5"; + + printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, + tp->widedone > 1 ? "WIDE " : "", + mb10 / 10, mb10 % 10, tp->period / 10, offset); + } else + printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); +next: + /* + ** set actual value and sync_status + ** patch ALL ccbs of this target. + */ + ncr_set_sync_wide_status(np, target); +} + + + + /*========================================================== ** ** Switch tagged mode for a target. @@ -8452,6 +9266,28 @@ ncr_log_hard_error(np, sist, dstat); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + u_char ctest4_o, ctest4_m; + u_char shadow; + + /* + * Get shadow register data + * Write 1 to ctest4 + */ + ctest4_o = INB(nc_ctest4); + + OUTB(nc_ctest4, ctest4_o | 0x10); + + ctest4_m = INB(nc_ctest4); + shadow = INW_OFF(0x42); + + OUTB(nc_ctest4, ctest4_o); + + printk("%s: ctest4/sist original 0x%x/0x%X mod: 0x%X/0x%x\n", + ncr_name(np), ctest4_o, sist, ctest4_m, shadow); + } + if ((sist & (GEN|HTH|SGE)) || (dstat & (MDPE|BF|ABRT|IID))) { ncr_start_reset(np); @@ -8577,6 +9413,20 @@ */ void ncr_int_udc (ncb_p np) { + u_int32 dsa = INL (nc_dsa); + ccb_p cp = ncr_ccb_from_dsa(np, dsa); + tcb_p tp = &np->target[cp->target]; + + /* + * Fix Up. Some disks respond to a PPR negotation with + * a bus free instead of a message reject. + * Disable ppr negotiation if this is first time + * tried ppr negotiation. + */ + + if (tp->ppr_negotiation == 1) + tp->ppr_negotiation = 0; + printk ("%s: unexpected disconnect\n", ncr_name(np)); ncr_recover_scsi_int(np, HS_UNEXPECTED); } @@ -8688,6 +9538,7 @@ /* ** Keep track of the parity error. */ + OUTONB (HF_PRT, HF_EXT_ERR); cp->xerr_status |= XE_PARITY_ERR; /* @@ -8695,14 +9546,22 @@ */ np->msgout[0] = (phase == 7) ? M_PARITY : M_ID_ERROR; +#ifdef SCSI_NCR_INTEGRITY_CHECKING + /* + ** Save error message. For integrity check use only. + */ + if (np->check_integrity) + np->check_integ_par = np->msgout[0]; +#endif + /* - ** If the old phase was DATA IN phase, we have to deal with - ** the 3 situations described above. + ** If the old phase was DATA IN or DT DATA IN phase, + ** we have to deal with the 3 situations described above. ** For other input phases (MSG IN and STATUS), the device ** must resend the whole thing that failed parity checking ** or signal error. So, jumping to dispatcher should be OK. */ - if (phase == 1) { + if ((phase == 1) || (phase == 5)) { /* Phase mismatch handled by SCRIPTS */ if (dsp == NCB_SCRIPTH_PHYS (np, pm_handle)) OUTL (nc_dsp, dsp); @@ -8772,45 +9631,64 @@ */ cp = ncr_ccb_from_dsa(np, dsa); + if (DEBUG_FLAGS & DEBUG_PHASE) + printk("CCB = %2x %2x %2x %2x %2x %2x\n", + cp->cmd->cmnd[0], cp->cmd->cmnd[1], cp->cmd->cmnd[2], + cp->cmd->cmnd[3], cp->cmd->cmnd[4], cp->cmd->cmnd[5]); + /* ** Donnot take into account dma fifo and various buffers in ** INPUT phase since the chip flushes everything before ** raising the MA interrupt for interrupted INPUT phases. ** For DATA IN phase, we will check for the SWIDE later. */ - if ((cmd & 7) != 1) { + if ( !(((cmd & 7) == 1) || ((cmd & 7) == 5) ) ) { u_int32 dfifo; u_char ss0, ss2; /* - ** Read DFIFO, CTEST[4-6] using 1 PCI bus ownership. + ** If C1010, DFBC contains number of bytes in DMA fifo. + ** else read DFIFO, CTEST[4-6] using 1 PCI bus ownership. */ - dfifo = INL(nc_dfifo); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + delta = INL(nc_dfbc) & 0xffff; + else { + dfifo = INL(nc_dfifo); - /* - ** Calculate remaining bytes in DMA fifo. - ** (CTEST5 = dfifo >> 16) - */ - if (dfifo & (DFS << 16)) - delta = ((((dfifo >> 8) & 0x300) | - (dfifo & 0xff)) - rest) & 0x3ff; - else - delta = ((dfifo & 0xff) - rest) & 0x7f; + /* + ** Calculate remaining bytes in DMA fifo. + ** C1010 - always large fifo, value in dfbc + ** Otherwise, (CTEST5 = dfifo >> 16) + */ + if (dfifo & (DFS << 16)) + delta = ((((dfifo >> 8) & 0x300) | + (dfifo & 0xff)) - rest) & 0x3ff; + else + delta = ((dfifo & 0xff) - rest) & 0x7f; - /* - ** The data in the dma fifo has not been transfered to - ** the target -> add the amount to the rest - ** and clear the data. - ** Check the sstat2 register in case of wide transfer. - */ + /* + ** The data in the dma fifo has not been + ** transferred to the target -> add the amount + ** to the rest and clear the data. + ** Check the sstat2 register in case of wide + ** transfer. + */ + + } + rest += delta; ss0 = INB (nc_sstat0); if (ss0 & OLF) rest++; - if (ss0 & ORF) rest++; + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && (ss0 & ORF)) + rest++; if (cp && (cp->phys.select.sel_scntl3 & EWS)) { ss2 = INB (nc_sstat2); if (ss2 & OLF1) rest++; - if (ss2 & ORF1) rest++; + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && (ss2 & ORF)) + rest++; }; /* @@ -8902,9 +9780,10 @@ /* ** if old phase not dataphase, leave here. + ** C/D line is low if data. */ - if (cmd & 0x06) { + if (cmd & 0x02) { PRINT_ADDR(cp->cmd); printk ("phase change %x-%x %d@%08x resid=%d.\n", cmd&7, INB(nc_sbcl)&7, (unsigned)olen, @@ -8962,45 +9841,42 @@ ** - move current data pointer context by one byte. */ nxtdsp = NCB_SCRIPT_PHYS (np, dispatch); - if ((cmd & 7) == 1 && cp && (cp->phys.select.sel_scntl3 & EWS) && + if ( ((cmd & 7) == 1 || (cmd & 7) == 5) + && cp && (cp->phys.select.sel_scntl3 & EWS) && (INB (nc_scntl2) & WSR)) { - /* - ** Hmmm... The device may want to also ignore - ** this residue but it must send immediately the - ** appropriate message. We snoop the SCSI BUS - ** and will just throw away this message from - ** SCRIPTS if the SWIDE is to be ignored. - */ - if ((INB (nc_sbcl) & 7) == 7 && - INB (nc_sbdl) == M_IGN_RESIDUE) { - nxtdsp = NCB_SCRIPT_PHYS (np, ign_i_w_r_msg); - } - /* - ** We must grab the SWIDE. - ** We will use some complex SCRIPTS for that. - */ - else { - OUTL (nc_scratcha, pm->sg.addr); - nxtdsp = NCB_SCRIPTH_PHYS (np, swide_ma_32); - if (np->features & FE_64BIT) { - OUTB (nc_sbr, (pm->sg.size >> 24)); - nxtdsp = NCB_SCRIPTH_PHYS (np, swide_ma_64); - } - /* - ** Adjust our data pointer context. - */ - ++pm->sg.addr; - --pm->sg.size; - /* - ** Hmmm... Could it be possible that a SWIDE that - ** is followed by a 1 byte CHMOV would lead to - ** a CHMOV(0). Anyway, we handle it by just - ** skipping context that would attempt a CHMOV(0). - */ - if (!pm->sg.size) - newcmd = pm->ret; - } - } + u32 tmp; + +#ifdef SYM_DEBUG_PM_WITH_WSR + PRINT_ADDR(cp); + printf ("MA interrupt with WSR set - " + "pm->sg.addr=%x - pm->sg.size=%d\n", + pm->sg.addr, pm->sg.size); +#endif + /* + * Set up the table indirect for the MOVE + * of the residual byte and adjust the data + * pointer context. + */ + tmp = scr_to_cpu(pm->sg.addr); + cp->phys.wresid.addr = cpu_to_scr(tmp); + pm->sg.addr = cpu_to_scr(tmp + 1); + tmp = scr_to_cpu(pm->sg.size); + cp->phys.wresid.size = cpu_to_scr((tmp&0xff000000) | 1); + pm->sg.size = cpu_to_scr(tmp - 1); + + /* + * If only the residual byte is to be moved, + * no PM context is needed. + */ + if ((tmp&0xffffff) == 1) + newcmd = pm->ret; + + /* + * Prepare the address of SCRIPTS that will + * move the residual byte to memory. + */ + nxtdsp = NCB_SCRIPTH_PHYS (np, wsr_ma_helper); + } if (DEBUG_FLAGS & DEBUG_PHASE) { PRINT_ADDR(cp->cmd); @@ -9076,7 +9952,8 @@ nxtdsp = NCB_SCRIPTH_PHYS (np, ident_break); } else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) || - dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) { + dsp == NCB_SCRIPTH_PHYS (np, send_sdtr) || + dsp == NCB_SCRIPTH_PHYS (np, send_ppr)) { nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase); } break; @@ -9277,12 +10154,56 @@ ** to be stuck with WIDE and/or SYNC data transfer. ** ** cp->nego_status is filled by ncr_prepare_nego(). + ** + ** Do NOT negotiate if performing integrity check + ** or if integrity check has completed, all check + ** conditions will have been cleared. + */ + +#ifdef SCSI_NCR_INTEGRITY_CHECKING + if (DEBUG_FLAGS & DEBUG_IC) { + printk("%s: ncr_sir_to_redo: ic_done %2X, in_progress %2X\n", + ncr_name(np), tp->ic_done, cp->cmd->ic_in_progress); + } + + /* + ** If parity error during integrity check, + ** set the target width to narrow. Otherwise, + ** do not negotiate on a request sense. */ + if ( np->check_integ_par && np->check_integrity + && cp->cmd->ic_in_progress ) { + cp->nego_status = 0; + msglen += + ncr_ic_nego (np, cp, cmd ,&cp->scsi_smsg2[msglen]); + } + + if (!np->check_integrity || + (np->check_integrity && + (!cp->cmd->ic_in_progress && !tp->ic_done)) ) { + ncr_negotiate(np, tp); + cp->nego_status = 0; + { + u_char sync_offset; + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) + sync_offset = tp->sval & 0x3f; + else + sync_offset = tp->sval & 0x1f; + + if ((tp->wval & EWS) || sync_offset) + msglen += + ncr_prepare_nego (np, cp, &cp->scsi_smsg2[msglen]); + } + + } +#else ncr_negotiate(np, tp); cp->nego_status = 0; if ((tp->wval & EWS) || (tp->sval & 0x1f)) msglen += ncr_prepare_nego (np, cp, &cp->scsi_smsg2[msglen]); +#endif /* SCSI_NCR_INTEGRITY_CHECKING */ /* ** Message table indirect structure. @@ -9489,6 +10410,7 @@ np->abrt_sel.sel_id = target; np->abrt_sel.sel_scntl3 = tp->wval; np->abrt_sel.sel_sxfer = tp->sval; + np->abrt_sel.sel_scntl4 = tp->uval; OUTL(nc_dsa, np->p_ncb); OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, sel_for_abort)); return; @@ -9696,6 +10618,7 @@ if (np->abrt_msg[0] == M_RESET) { tp->sval = 0; tp->wval = np->rv_scntl3; + tp->uval = np->rv_scntl4; ncr_set_sync_wide_status(np, target); ncr_negotiate(np, tp); } @@ -10014,11 +10937,30 @@ static int ncr_compute_residual(ncb_p np, ccb_p cp) { - int dp_sg, dp_sgmin, resid, tmp; + int dp_sg, dp_sgmin, tmp; + int resid=0; int dp_ofs = 0; /* - ** Should have been checked by the caller. + * Check for some data lost or just thrown away. + * We are not required to be quite accurate in this + * situation. Btw, if we are odd for output and the + * device claims some more data, it may well happen + * than our residual be zero. :-) + */ + if (cp->xerr_status & (XE_EXTRA_DATA|XE_SODL_UNRUN|XE_SWIDE_OVRUN)) { + if (cp->xerr_status & XE_EXTRA_DATA) + resid -= scr_to_cpu(cp->phys.extra_bytes); + if (cp->xerr_status & XE_SODL_UNRUN) + ++resid; + if (cp->xerr_status & XE_SWIDE_OVRUN) + --resid; + } + + + /* + ** If all data has been transferred, + ** there is no residual. */ if (cp->phys.header.lastp == cp->phys.header.goalp) return 0; @@ -10159,7 +11101,7 @@ */ static void ncr_sync_nego(ncb_p np, tcb_p tp, ccb_p cp) { - u_char scntl3; + u_char scntl3, scntl4; u_char chg, ofs, per, fak; /* @@ -10203,6 +11145,7 @@ */ fak = 7; scntl3 = 0; + scntl4 = 0; if (ofs != 0) { ncr_getsync(np, per, &fak, &scntl3); if (fak > 7) { @@ -10214,13 +11157,14 @@ fak = 7; per = 0; scntl3 = 0; + scntl4 = 0; tp->minsync = 0; } if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->cmd); - printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", - per, scntl3, ofs, fak, chg); + printk ("sync: per=%d scntl3=0x%x scntl4=0x%x ofs=%d fak=%d chg=%d.\n", + per, scntl3, scntl4, ofs, fak, chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -10234,13 +11178,18 @@ /* ** Answer wasn't acceptable. */ - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsync (np, cp, scntl3, (fak<<5)|ofs,0); + else + ncr_setsync (np, cp, scntl3, ofs, scntl4); + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); }; return; @@ -10256,7 +11205,11 @@ ** prepare an answer message */ - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsync (np, cp, scntl3, (fak<<5)|ofs,0); + else + ncr_setsync (np, cp, scntl3, ofs, scntl4); np->msgout[0] = M_EXTENDED; np->msgout[1] = 3; @@ -10350,7 +11303,7 @@ return; case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); break; }; }; @@ -10377,6 +11330,205 @@ OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, wdtr_resp)); } +/*========================================================== +** +** ncr chip handler for PARALLEL PROTOCOL REQUEST +** (PPR) message. +** +**========================================================== +** +** Read comments above. +** +**---------------------------------------------------------- +*/ +static void ncr_ppr_nego(ncb_p np, tcb_p tp, ccb_p cp) +{ + u_char scntl3, scntl4; + u_char chg, ofs, per, fak, wth, dt; + + /* + ** PPR message received. + */ + + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, "ppr msg in", np->msgin); + }; + + /* + ** get requested values. + */ + + chg = 0; + per = np->msgin[3]; + ofs = np->msgin[5]; + wth = np->msgin[6]; + dt = np->msgin[7]; + if (ofs==0) per=255; + + /* + ** if target sends sync (wide), + ** it CAN transfer synch (wide). + */ + + if (ofs) + tp->inq_byte7 |= INQ7_SYNC; + + if (wth) + tp->inq_byte7 |= INQ7_WIDE16; + + /* + ** check values against driver limits. + */ + + if (wth > tp->usrwide) + {chg = 1; wth = tp->usrwide;} + if (per < np->minsync) + {chg = 1; per = np->minsync;} + if (per < tp->minsync) + {chg = 1; per = tp->minsync;} + if (ofs > tp->maxoffs) + {chg = 1; ofs = tp->maxoffs;} + + /* + ** Check against controller limits. + */ + fak = 7; + scntl3 = 0; + scntl4 = 0; + if (ofs != 0) { + scntl4 = dt ? 0x80 : 0; + ncr_getsync(np, per, &fak, &scntl3); + if (fak > 7) { + chg = 1; + ofs = 0; + } + } + if (ofs == 0) { + fak = 7; + per = 0; + scntl3 = 0; + scntl4 = 0; + tp->minsync = 0; + } + + /* + ** If target responds with Ultra 3 speed + ** but narrow or not DT, reject. + ** If target responds with DT request + ** but not Ultra3 speeds, reject message, + ** reset min sync for target to 0x0A and + ** set flags to re-negotiate. + */ + + if ((per == 0x09) && ofs && (!wth || !dt)) + chg = 1; + else if (( (per > 0x09) && dt) ) + chg = 2; + + + if (DEBUG_FLAGS & DEBUG_NEGO) { + PRINT_ADDR(cp->cmd); + printk ("ppr: wth=%d per=%d scntl3=0x%x scntl4=0x%x ofs=%d fak=%d chg=%d.\n", + wth, per, scntl3, scntl4, ofs, fak, chg); + } + + if (INB (HS_PRT) == HS_NEGOTIATE) { + OUTB (HS_PRT, HS_BUSY); + switch (cp->nego_status) { + case NS_PPR: + /* + ** This was an answer message + */ + if (chg) { + /* + ** Answer wasn't acceptable. + */ + if (chg == 2) { + /* Send message reject and reset flags for + ** host to re-negotiate with min period 0x0A. + */ + tp->minsync = 0x0A; + tp->period = 0; + tp->widedone = 0; + } + ncr_setsyncwide (np, cp, 0, 0xe0, 0, 0); + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); + } else { + /* + ** Answer is ok. + */ + + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsyncwide (np, cp, scntl3, (fak<<5)|ofs,0, wth); + else + ncr_setsyncwide (np, cp, scntl3, ofs, scntl4, wth); + + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); + + }; + return; + + case NS_SYNC: + ncr_setsync (np, cp, 0, 0xe0, 0); + break; + + case NS_WIDE: + ncr_setwide (np, cp, 0, 0); + break; + }; + }; + + /* + ** It was a request. Set value and + ** prepare an answer message + ** + ** If narrow or not DT and requesting Ultra3 + ** slow the bus down and force ST. If not + ** requesting Ultra3, force ST. + ** Max offset is 31=0x1f if ST mode. + */ + + if ((per == 0x09) && ofs && (!wth || !dt)) { + per = 0x0A; + dt = 0; + ofs &= 0x1f; + } + else if ( (per > 0x09) && dt) { + dt = 0; + ofs &= 0x1f; + } + + if ((np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66)) + ncr_setsyncwide (np, cp, scntl3, (fak<<5)|ofs,0, wth); + else + ncr_setsyncwide (np, cp, scntl3, ofs, scntl4, wth); + + np->msgout[0] = M_EXTENDED; + np->msgout[1] = 6; + np->msgout[2] = M_X_PPR_REQ; + np->msgout[3] = per; + np->msgout[4] = 0; + np->msgout[5] = ofs; + np->msgout[6] = wth; + np->msgout[7] = dt; + + cp->nego_status = NS_PPR; + + if (DEBUG_FLAGS & DEBUG_NEGO) { + ncr_print_msg(cp, "ppr msgout", np->msgout); + } + + np->msgin [0] = M_NOOP; + + if (!ofs) + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, msg_bad)); + else + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, ppr_resp)); +} + + /* ** Reset SYNC or WIDE to default settings. @@ -10392,13 +11544,45 @@ switch (cp->nego_status) { case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0); + ncr_setsync (np, cp, 0, 0xe0, 0); break; case NS_WIDE: ncr_setwide (np, cp, 0, 0); break; + case NS_PPR: + /* + * ppr_negotiation is set to 1 on the first ppr nego command. + * If ppr is successful, it is reset to 2. + * If unsuccessful it is reset to 0. + */ + if (DEBUG_FLAGS & DEBUG_NEGO) { + tcb_p tp=&np->target[cp->target]; + u_char factor, offset, width; + + ncr_get_xfer_info ( np, tp, &factor, &offset, &width); + + printk("Current factor %d offset %d width %d\n", + factor, offset, width); + } + if (tp->ppr_negotiation == 2) + ncr_setsyncwide (np, cp, 0, 0xe0, 0, 0); + else if (tp->ppr_negotiation == 1) { + + /* First ppr command has received a M REJECT. + * Do not change the existing wide/sync parameter + * values (asyn/narrow if this as the first nego; + * may be different if target initiates nego.). + */ + tp->ppr_negotiation = 0; + } + else + { + tp->ppr_negotiation = 0; + ncr_setwide (np, cp, 0, 0); + } + break; }; np->msgin [0] = M_NOOP; np->msgout[0] = M_NOOP; @@ -10410,6 +11594,9 @@ ** ncr chip handler for MESSAGE REJECT received for ** a WIDE or SYNCHRONOUS negotiation. ** +** clear the PPR negotiation flag, all future nego. +** will be SDTR and WDTR +** **========================================================== ** ** Read comments above. @@ -10451,6 +11638,7 @@ case SIR_DUMMY_INTERRUPT: goto out; #endif + /* ** The C code is currently trying to recover from something. ** Typically, user want to abort some command. @@ -10529,8 +11717,11 @@ np->msgout[0] = M_NOOP; /* Should we really care of that */ if (np->lastmsg == M_PARITY || np->lastmsg == M_ID_ERROR) { - if (cp) + if (cp) { cp->xerr_status &= ~XE_PARITY_ERR; + if (!cp->xerr_status) + OUTOFFB (HF_PRT, HF_EXT_ERR); + } } goto out; /* @@ -10558,8 +11749,10 @@ ** It is a data overrun condition. */ case SIR_SWIDE_OVERRUN: - if (cp) - cp->xerr_status |= XE_EXTRA_DATA; + if (cp) { + OUTONB (HF_PRT, HF_EXT_ERR); + cp->xerr_status |= XE_SWIDE_OVRUN; + } goto out; /* ** We have been ODD at the end of a DATA OUT @@ -10567,8 +11760,10 @@ ** It is a data underrun condition. */ case SIR_SODL_UNDERRUN: - if (cp) - cp->xerr_status |= XE_EXTRA_DATA; + if (cp) { + OUTONB (HF_PRT, HF_EXT_ERR); + cp->xerr_status |= XE_SODL_UNRUN; + } goto out; /* ** We received a message. @@ -10597,6 +11792,9 @@ case M_X_WIDE_REQ: ncr_wide_nego(np, tp, cp); return; + case M_X_PPR_REQ: + ncr_ppr_nego(np, tp, cp); + return; default: goto out_reject; } @@ -10910,6 +12108,11 @@ offsetof(struct tcb , sval )) &3) == 0); assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ offsetof(struct tcb , wval )) &3) == 0); + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + assert (( (offsetof(struct ncr_reg, nc_scntl4) ^ + offsetof(struct tcb , uval )) &3) == 0); + } } /*------------------------------------------------------------------------ @@ -11446,7 +12649,8 @@ ** do not have a clock doubler and so are provided with a ** 80 MHz clock. All other fast20 boards incorporate a doubler ** and so should be delivered with a 40 MHz clock. -** The recent fast40 chips (895/896/895A) use a 40 Mhz base clock +** The recent fast40 chips (895/896/895A) and the +** fast80 chip (C1010) use a 40 Mhz base clock ** and provide a clock quadrupler (160 Mhz). The code below ** tries to deal as cleverly as possible with all this stuff. ** @@ -11467,14 +12671,20 @@ printk ("%s: enabling clock multiplier\n", ncr_name(np)); OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ - if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ - int i = 20; + + if ( (np->device_id != PCI_DEVICE_ID_LSI_53C1010) && + (np->device_id != PCI_DEVICE_ID_LSI_53C1010_66) && + (np->multiplier > 2)) { + int i = 20; /* Poll bit 5 of stest4 for quadrupler */ while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) UDELAY (20); if (!i) - printk("%s: the chip cannot lock the frequency\n", ncr_name(np)); - } else /* Wait 20 micro-seconds for doubler */ - UDELAY (20); + printk("%s: the chip cannot lock the frequency\n", + ncr_name(np)); + + } else /* Wait 120 micro-seconds for multiplier*/ + UDELAY (120); + OUTB(nc_stest3, HSC); /* Halt the scsi clock */ OUTB(nc_scntl3, scntl3); OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ @@ -11489,6 +12699,7 @@ { unsigned int ms = 0; unsigned int f; + int count; /* * Measure GEN timer delay in order @@ -11505,15 +12716,21 @@ * performed trust the higher delay * (lower frequency returned). */ - OUTW (nc_sien , 0); /* mask all scsi interrupts */ + OUTW (nc_sien , 0x0);/* mask all scsi interrupts */ + /* enable general purpose timer */ (void) INW (nc_sist); /* clear pending scsi interrupt */ OUTB (nc_dien , 0); /* mask all dma interrupts */ (void) INW (nc_sist); /* another one, just to be sure :) */ OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ OUTB (nc_stime1, 0); /* disable general purpose timer */ OUTB (nc_stime1, gen); /* set to nominal delay of 1<device_id == PCI_DEVICE_ID_LSI_53C1010) + f = ms ? ((1 << gen) * 2866 ) / ms : 0; + else +#endif f = ms ? ((1 << gen) * 4340) / ms : 0; if (bootverbose >= 2) @@ -11568,11 +12792,19 @@ } /* + ** If multiplier not found but a C1010, assume a mult of 4. ** If multiplier not found or scntl3 not 7,5,3, ** reset chip and get frequency from general purpose timer. ** Otherwise trust scntl3 BIOS setting. */ - if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { + if ((np->device_id == PCI_DEVICE_ID_LSI_53C1010) || + (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)) { + f1=40000; + np->multiplier = mult; + if (bootverbose >= 2) + printk ("%s: clock multiplier assumed\n", ncr_name(np)); + } + else if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { OUTB (nc_stest1, 0); /* make sure doubler is OFF */ f1 = ncr_getfreq (np); @@ -11587,8 +12819,14 @@ ** to make sure our frequency calculation algorithm ** is not too biased. */ - np->pciclock_min = (33000*55+80-1)/80; - np->pciclock_max = (33000*55)/40; + if (np->features & FE_66MHZ) { + np->pciclock_min = (66000*55+80-1)/80; + np->pciclock_max = (66000*55)/40; + } + else { + np->pciclock_min = (33000*55+80-1)/80; + np->pciclock_max = (33000*55)/40; + } if (f1 == 40000 && mult > 1) { if (bootverbose >= 2) @@ -11728,7 +12966,8 @@ #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT char *cur = str; char *pc, *pv; - int i, val, c; + unsigned long val; + int i, c; int xi = 0; while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { @@ -12165,7 +13404,7 @@ static int __init sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) { - u_short vendor_id, device_id, command; + u_short vendor_id, device_id, command, status_reg; u_char cache_line_size, latency_timer; u_char suggested_cache_line_size = 0; u_char pci_fix_up = driver_setup.pci_fix_up; @@ -12205,6 +13444,7 @@ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer); + pci_read_config_word(pdev, PCI_STATUS, &status_reg); #ifdef SCSI_NCR_PQS_PDS_SUPPORT /* @@ -12402,14 +13642,51 @@ if (driver_setup.special_features & 4) chip->features &= ~FE_NOPM; } + + /* + ** Work around for errant bit in 895A. The 66Mhz + ** capable bit is set erroneously. Clear this bit. + ** (Item 1 DEL 533) + ** + ** Make sure Config space and Features agree. + ** + ** Recall: writes are not normal to status register - + ** write a 1 to clear and a 0 to leave unchanged. + ** Can only reset bits. + */ + if (chip->features & FE_66MHZ) { + if (!(status_reg & PCI_STATUS_66MHZ)) + chip->features &= ~FE_66MHZ; + } + else { + if (status_reg & PCI_STATUS_66MHZ) { + status_reg = PCI_STATUS_66MHZ; + pci_write_config_word(pdev, PCI_STATUS, status_reg); + pci_read_config_word(pdev, PCI_STATUS, &status_reg); + } + } + + if (driver_setup.ultra_scsi < 3 && (chip->features & FE_ULTRA3)) { + chip->features |= FE_ULTRA2; + chip->features &= ~FE_ULTRA3; + } if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2)) { chip->features |= FE_ULTRA; chip->features &= ~FE_ULTRA2; } if (driver_setup.ultra_scsi < 1) chip->features &= ~FE_ULTRA; + if (!driver_setup.max_wide) chip->features &= ~FE_WIDE; + + /* + * C1010 Ultra3 support requires 16 bit data transfers. + */ + if (!driver_setup.max_wide && (chip->features & FE_ULTRA3)) { + chip->features |= FE_ULTRA2; + chip->features |= ~FE_ULTRA3; + } /* ** Some features are required to be enabled in order to diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sym53c8xx_comm.h linux.ac/drivers/scsi/sym53c8xx_comm.h --- linux.vanilla/drivers/scsi/sym53c8xx_comm.h Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/sym53c8xx_comm.h Mon Jun 5 19:47:43 2000 @@ -155,6 +155,7 @@ #define DEBUG_NEGO (0x0200) #define DEBUG_TAGS (0x0400) #define DEBUG_SCATTER (0x0800) +#define DEBUG_IC (0x1000) /* ** Enable/Disable debug messages. @@ -2414,6 +2415,11 @@ /* ** Check if the chip is supported */ + if ((device_id == PCI_DEVICE_ID_LSI_53C1010) || + (device_id == PCI_DEVICE_ID_LSI_53C1010_66)){ + printk(NAME53C8XX ": not initializing, device not supported\n"); + return -1; + } chip = 0; for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { if (device_id != ncr_chip_table[i].device_id) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sym53c8xx_defs.h linux.ac/drivers/scsi/sym53c8xx_defs.h --- linux.vanilla/drivers/scsi/sym53c8xx_defs.h Thu May 25 17:38:07 2000 +++ linux.ac/drivers/scsi/sym53c8xx_defs.h Sat Jun 10 22:26:47 2000 @@ -102,6 +102,14 @@ # define SCSI_NCR_USER_INFO_SUPPORT #endif +/* +** To disable integrity checking, do not define the +** following option. +*/ +#ifdef CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK +# define SCSI_NCR_ENABLE_INTEGRITY_CHECK +#endif + /*========================================================== ** ** nvram settings - #define SCSI_NCR_NVRAM_SUPPORT to enable @@ -121,10 +129,9 @@ */ /* - * For Ultra2 SCSI support option, use special features and allow 40Mhz - * synchronous data transfers. + * For Ultra2 and Ultra3 SCSI support option, use special features. * - * Value 5 (default) means: + * Value (default) means: * bit 0 : all features enabled, except: * bit 1 : PCI Write And Invalidate. * bit 2 : Data Phase Mismatch handling from SCRIPTS. @@ -133,8 +140,20 @@ * enabled by the driver. */ #define SCSI_NCR_SETUP_SPECIAL_FEATURES (3) -#define SCSI_NCR_SETUP_ULTRA_SCSI (2) -#define SCSI_NCR_MAX_SYNC (40) + +/* + * For Ultra2 and Ultra3 SCSI support allow 80Mhz synchronous data transfers. + * Value means: + * 0 - Ultra speeds disabled + * 1 - Ultra enabled (Maximum 20Mtrans/sec) + * 2 - Ultra2 enabled (Maximum 40Mtrans/sec) + * 3 - Ultra3 enabled (Maximum 80Mtrans/sec) + * + * Use boot options sym53c8xx=ultra:3 to enable Ultra3 support. + */ + +#define SCSI_NCR_SETUP_ULTRA_SCSI (3) +#define SCSI_NCR_MAX_SYNC (80) /* * Allow tags from 2 to 256, default 8 @@ -190,7 +209,7 @@ /* * Sync transfer frequency at startup. - * Allow from 5Mhz to 40Mhz default 20 Mhz. + * Allow from 5Mhz to 80Mhz default 20 Mhz. */ #ifndef CONFIG_SCSI_NCR53C8XX_SYNC #define CONFIG_SCSI_NCR53C8XX_SYNC (20) @@ -207,8 +226,10 @@ #define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC)) #elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33 #define SCSI_NCR_SETUP_DEFAULT_SYNC (11) -#else +#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 40 #define SCSI_NCR_SETUP_DEFAULT_SYNC (10) +#else +#define SCSI_NCR_SETUP_DEFAULT_SYNC (9) #endif /* @@ -469,6 +490,15 @@ #define PCI_DEVICE_ID_NCR_53C1510D 0xa #endif +#ifndef PCI_DEVICE_ID_LSI_53C1010 +#define PCI_DEVICE_ID_LSI_53C1010 0x20 +#endif + +#ifndef PCI_DEVICE_ID_LSI_53C1010_66 +#define PCI_DEVICE_ID_LSI_53C1010_66 0x21 +#endif + + /* ** NCR53C8XX devices features table. */ @@ -502,6 +532,8 @@ #define FE_NOPM (1<<19) /* Scripts handles phase mismatch */ #define FE_LEDC (1<<20) /* Hardware control of LED */ #define FE_DIFF (1<<21) /* Support Differential SCSI */ +#define FE_ULTRA3 (1<<22) /* Ultra-3 80Mtrans/sec */ +#define FE_66MHZ (1<<23) /* 66MHz PCI Support */ #define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) #define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) @@ -586,7 +618,15 @@ , \ {PCI_DEVICE_ID_NCR_53C1510D, 0xff, "1510D", 7, 31, 7, \ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ - FE_RAM|FE_IO256}\ + FE_RAM|FE_IO256} \ + , \ + {PCI_DEVICE_ID_LSI_53C1010, 0xff, "1010", 6, 62, 7, \ + FE_WIDE|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ + FE_RAM|FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC|FE_ULTRA3} \ + , \ + {PCI_DEVICE_ID_LSI_53C1010_66, 0xff, "1010_66", 6, 62, 7, \ + FE_WIDE|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN| \ + FE_RAM|FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM|FE_LEDC|FE_ULTRA3|FE_66MHZ} \ } /* @@ -605,7 +645,9 @@ PCI_DEVICE_ID_NCR_53C895, \ PCI_DEVICE_ID_NCR_53C896, \ PCI_DEVICE_ID_NCR_53C895A, \ - PCI_DEVICE_ID_NCR_53C1510D \ + PCI_DEVICE_ID_NCR_53C1510D, \ + PCI_DEVICE_ID_LSI_53C1010, \ + PCI_DEVICE_ID_LSI_53C1010_66 \ } /* @@ -640,7 +682,7 @@ u_char recovery; u_char host_id; u_short iarb; - u_int excludes[SCSI_NCR_MAX_EXCLUDES]; + u_long excludes[SCSI_NCR_MAX_EXCLUDES]; char tag_ctrl[100]; }; @@ -662,7 +704,7 @@ 1, \ SCSI_NCR_SETUP_DEFAULT_TAGS, \ SCSI_NCR_SETUP_DEFAULT_SYNC, \ - 0x00, \ + 0x0200, \ 7, \ SCSI_NCR_SETUP_LED_PIN, \ 1, \ @@ -864,12 +906,14 @@ /*03*/ u_char nc_scntl3; /* cnf system clock dependent */ #define EWS 0x08 /* cmd: enable wide scsi [W]*/ #define ULTRA 0x80 /* cmd: ULTRA enable */ + /* bits 0-2, 7 rsvd for C1010 */ /*04*/ u_char nc_scid; /* cnf host adapter scsi address */ #define RRE 0x40 /* r/w:e enable response to resel. */ #define SRE 0x20 /* r/w:e enable response to select */ /*05*/ u_char nc_sxfer; /* ### Sync speed and count */ + /* bits 6-7 rsvd for C1010 */ /*06*/ u_char nc_sdid; /* ### Destination-ID */ @@ -944,12 +988,14 @@ /*1a*/ u_char nc_ctest2; #define CSIGP 0x40 + /* bits 0-2,7 rsvd for C1010 */ /*1b*/ u_char nc_ctest3; #define FLF 0x08 /* cmd: flush dma fifo */ #define CLF 0x04 /* cmd: clear dma fifo */ #define FM 0x02 /* mod: fetch pin mode */ #define WRIE 0x01 /* mod: write and invalidate enable */ + /* bits 4-7 rsvd for C1010 */ /*1c*/ u_int32 nc_temp; /* ### Temporary stack */ @@ -960,6 +1006,7 @@ /*22*/ u_char nc_ctest5; #define DFS 0x20 /* mod: dma fifo size */ + /* bits 0-1, 3-7 rsvd for C1010 */ /*23*/ u_char nc_ctest6; /*24*/ u_int32 nc_dbc; /* ### Byte count and command */ @@ -991,6 +1038,7 @@ #define STD 0x04 /* cmd: start dma mode */ #define IRQD 0x02 /* mod: irq disable */ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */ + /* bits 0-1 rsvd for C1010 */ /*3c*/ u_int32 nc_adder; @@ -1041,6 +1089,7 @@ #define SMODE_SE 0x80 /* Single Ended */ #define SMODE_LVD 0xc0 /* Low Voltage Differential */ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */ + /* bits 0-5 rsvd for C1010 */ /*53*/ u_char nc_53_; /*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */ @@ -1054,6 +1103,7 @@ /*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */ #define ZMOD 0x80 /* High Impedance Mode */ + #define DIC 0x10 /* Disable Internal Cycles */ #define DDAC 0x08 /* Disable Dual Address Cycle */ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */ @@ -1075,7 +1125,16 @@ /*b0*/ u_int32 nc_sbms; /* Static Block Move Selector */ /*b4*/ u_int32 nc_dbms; /* Dynamic Block Move Selector */ /*b8*/ u_int32 nc_dnad64; /* DMA Next Address 64 */ -/*bc*/ u_int32 nc_bc_; +/*bc*/ u_short nc_scntl4; /* C1010 only */ + #define U3EN 0x80 /* Enable Ultra 3 */ + #define AIPEN 0x40 /* Allow check upper byte lanes */ + #define XCLKH_DT 0x08 /* Extra clock of data hold on DT + transfer edge */ + #define XCLKH_ST 0x04 /* Extra clock of data hold on ST + transfer edge */ + +/*be*/ u_char nc_aipcntl0; /* Epat Control 1 C1010 only */ +/*bf*/ u_char nc_aipcntl1; /* AIP Control C1010_66 Only */ /*c0*/ u_int32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */ /*c4*/ u_int32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */ @@ -1095,6 +1154,17 @@ /*d7*/ u_char nc_ia3; /*d8*/ u_int32 nc_sbc; /* SCSI Byte Count (3 bytes only) */ /*dc*/ u_int32 nc_csbc; /* Cumulative SCSI Byte Count */ + + /* Following for C1010 only */ +/*e0*/ u_short nc_crcpad; /* CRC Value */ +/*e2*/ u_char nc_crccntl0; /* CRC control register */ + #define SNDCRC 0x10 /* Send CRC Request */ +/*e3*/ u_char nc_crccntl1; /* CRC control register */ +/*e4*/ u_int32 nc_crcdata; /* CRC data register */ +/*e8*/ u_int32 nc_e8_; /* rsvd */ +/*ec*/ u_int32 nc_ec_; /* rsvd */ +/*f0*/ u_short nc_dfbc; /* DMA FIFO byte count */ + }; /*----------------------------------------------------------- @@ -1113,6 +1183,8 @@ ** ** SCSI phases ** +** DT phases illegal for ncr driver. +** **----------------------------------------------------------- */ @@ -1120,11 +1192,14 @@ #define SCR_DATA_IN 0x01000000 #define SCR_COMMAND 0x02000000 #define SCR_STATUS 0x03000000 -#define SCR_ILG_OUT 0x04000000 -#define SCR_ILG_IN 0x05000000 +#define SCR_DT_DATA_OUT 0x04000000 +#define SCR_DT_DATA_IN 0x05000000 #define SCR_MSG_OUT 0x06000000 #define SCR_MSG_IN 0x07000000 +#define SCR_ILG_OUT 0x04000000 +#define SCR_ILG_IN 0x05000000 + /*----------------------------------------------------------- ** ** Data transfer via SCSI. @@ -1179,7 +1254,7 @@ #define SCR_SEL_TBL_ATN 0x43000000 struct scr_tblsel { - u_char sel_0; + u_char sel_scntl4; u_char sel_sxfer; u_char sel_id; u_char sel_scntl3; @@ -1463,6 +1538,7 @@ #define M_X_MODIFY_DP (0x00) #define M_X_SYNC_REQ (0x01) #define M_X_WIDE_REQ (0x03) +#define M_X_PPR_REQ (0x04) /* ** Status diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/tmscsim.c linux.ac/drivers/scsi/tmscsim.c --- linux.vanilla/drivers/scsi/tmscsim.c Thu May 25 17:38:05 2000 +++ linux.ac/drivers/scsi/tmscsim.c Tue May 30 15:23:41 2000 @@ -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->resource[0].start; irq = pdev->irq +# define PCI_GET_IO_AND_IRQ io_port = pci_resource_start(pdev, 0); irq = pdev->irq; #else # include # define PDEV pbus, pdevfn @@ -2002,6 +2002,8 @@ if ( PCI_PRESENT ) while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974)) { + if (pci_enable_device(pdev)) + continue; DC390_LOCK_IO; /* Remove this when going to new eh */ PCI_GET_IO_AND_IRQ; DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sgi/char/shmiq.c linux.ac/drivers/sgi/char/shmiq.c --- linux.vanilla/drivers/sgi/char/shmiq.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/sgi/char/shmiq.c Sat May 27 22:00:30 2000 @@ -118,8 +118,7 @@ e->data.device, e->data.which, e->data.type, e->data.flags); s->tail = tail_next; shmiqs [device].tail = tail_next; - if (shmiqs [device].fasync) - kill_fasync (shmiqs [device].fasync, SIGIO, POLL_IN); + kill_fasync (&shmiqs [device].fasync, SIGIO, POLL_IN); wake_up_interruptible (&shmiqs [device].proc_list); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/724hwmcode.h linux.ac/drivers/sound/724hwmcode.h --- linux.vanilla/drivers/sound/724hwmcode.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/724hwmcode.h Wed May 31 11:15:34 2000 @@ -0,0 +1,1575 @@ +//============================================================================= +// Copyright (c) 1997-1999 Yamaha Corporation. All Rights Reserved. +// +// Title: +// hwmcode.c +// Desc: +// micro-code for CTRL & DSP +//============================================================================= +#ifndef _HWMCODE_ +#define _HWMCODE_ + +static unsigned long int DspInst[] = { + 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, + 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, + 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, + 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static unsigned long int CntrlInst[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x001A82, 0x032D0D, 0x000810, 0x10043A, + 0x02D38D, 0x000810, 0x18043A, 0x00010D, + 0x020015, 0x0000FD, 0x000020, 0x038860, + 0x039060, 0x038060, 0x038040, 0x038040, + 0x038040, 0x018040, 0x000A7D, 0x038040, + 0x038040, 0x018040, 0x200402, 0x000882, + 0x08001A, 0x000904, 0x015986, 0x000007, + 0x260007, 0x000007, 0x000007, 0x018A06, + 0x000007, 0x030C8D, 0x000810, 0x18043A, + 0x260007, 0x00087D, 0x018042, 0x00160A, + 0x04A206, 0x000007, 0x00218D, 0x000810, + 0x08043A, 0x21C206, 0x000007, 0x0007FD, + 0x018042, 0x08000A, 0x000904, 0x029386, + 0x000195, 0x090D04, 0x000007, 0x000820, + 0x0000F5, 0x000B7D, 0x01F060, 0x0000FD, + 0x032206, 0x018040, 0x000A7D, 0x038042, + 0x13804A, 0x18000A, 0x001820, 0x059060, + 0x058860, 0x018040, 0x0000FD, 0x018042, + 0x70000A, 0x000115, 0x071144, 0x032386, + 0x030000, 0x007020, 0x034A06, 0x018040, + 0x00348D, 0x000810, 0x08043A, 0x21EA06, + 0x000007, 0x02D38D, 0x000810, 0x18043A, + 0x018206, 0x000007, 0x240007, 0x000F8D, + 0x000810, 0x00163A, 0x002402, 0x005C02, + 0x0028FD, 0x000020, 0x018040, 0x08000D, + 0x000815, 0x510984, 0x000007, 0x00004D, + 0x000E5D, 0x000E02, 0x00418D, 0x000810, + 0x08043A, 0x2C8A06, 0x000007, 0x00008D, + 0x000924, 0x000F02, 0x00458D, 0x000810, + 0x08043A, 0x2C8A06, 0x000007, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x018386, 0x000007, 0x01AA06, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x218086, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x055A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x034986, 0x000007, 0x002104, 0x034986, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x06C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00688D, 0x000810, 0x08043A, 0x288A06, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x060206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x215886, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x212086, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x07DA86, 0x00057D, 0x002820, + 0x03B060, 0x07F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x07FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x008D8D, 0x000810, + 0x08043A, 0x288A06, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x095186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x007FBD, 0x383DC4, + 0x000007, 0x001A7D, 0x001375, 0x018042, + 0x09004A, 0x10000A, 0x0B8D04, 0x139504, + 0x000007, 0x000820, 0x019060, 0x001104, + 0x212086, 0x010040, 0x0017FD, 0x018042, + 0x08000A, 0x000904, 0x212286, 0x000007, + 0x00197D, 0x038042, 0x09804A, 0x10000A, + 0x000924, 0x001664, 0x0011FD, 0x038042, + 0x2B804A, 0x19804A, 0x00008D, 0x218944, + 0x000007, 0x002244, 0x0AE186, 0x000007, + 0x001A64, 0x002A24, 0x00197D, 0x080102, + 0x100122, 0x000820, 0x039060, 0x018040, + 0x003DFD, 0x00008D, 0x000820, 0x018040, + 0x001375, 0x001A7D, 0x010042, 0x09804A, + 0x10000A, 0x00021D, 0x0189E4, 0x2992E4, + 0x309144, 0x000007, 0x00060D, 0x000A15, + 0x000C1D, 0x001025, 0x00A9E4, 0x012BE4, + 0x000464, 0x01B3E4, 0x0232E4, 0x000464, + 0x000464, 0x000464, 0x000464, 0x00040D, + 0x08B1C4, 0x000007, 0x000820, 0x000BF5, + 0x030040, 0x00197D, 0x038042, 0x09804A, + 0x000A24, 0x08000A, 0x080E64, 0x000007, + 0x100122, 0x000820, 0x031060, 0x010040, + 0x0064AC, 0x00027D, 0x000020, 0x018040, + 0x00107D, 0x018042, 0x0011FD, 0x3B804A, + 0x09804A, 0x20000A, 0x000095, 0x1A1144, + 0x00A144, 0x0D2086, 0x00040D, 0x00B984, + 0x0D2186, 0x0018FD, 0x018042, 0x0010FD, + 0x09804A, 0x28000A, 0x000095, 0x010924, + 0x002A64, 0x0D1186, 0x000007, 0x002904, + 0x0D2286, 0x000007, 0x0D2A06, 0x080002, + 0x00008D, 0x00387D, 0x000820, 0x018040, + 0x00127D, 0x018042, 0x10000A, 0x003904, + 0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984, + 0x0DA186, 0x000025, 0x0E7A06, 0x00002D, + 0x000015, 0x00082D, 0x02C78D, 0x000820, + 0x0EC206, 0x00000D, 0x7F8035, 0x00B984, + 0x0E7186, 0x400025, 0x00008D, 0x110944, + 0x000007, 0x00018D, 0x109504, 0x000007, + 0x009164, 0x000424, 0x000424, 0x000424, + 0x100102, 0x280002, 0x02C68D, 0x000820, + 0x0EC206, 0x00018D, 0x00042D, 0x00008D, + 0x109504, 0x000007, 0x00020D, 0x109184, + 0x000007, 0x02C70D, 0x000820, 0x00008D, + 0x0038FD, 0x018040, 0x003BFD, 0x001020, + 0x03A860, 0x000815, 0x313184, 0x212184, + 0x000007, 0x03B060, 0x03A060, 0x018040, + 0x0022FD, 0x000095, 0x010924, 0x000424, + 0x000424, 0x001264, 0x100102, 0x000820, + 0x039060, 0x018040, 0x001924, 0x00FB8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x000424, + 0x000424, 0x00117D, 0x018042, 0x08000A, + 0x000A24, 0x280502, 0x280C02, 0x09800D, + 0x000820, 0x0002FD, 0x018040, 0x200007, + 0x0022FD, 0x018042, 0x08000A, 0x000095, + 0x280DC4, 0x011924, 0x00197D, 0x018042, + 0x0011FD, 0x09804A, 0x10000A, 0x0000B5, + 0x113144, 0x0A8D04, 0x000007, 0x080A44, + 0x129504, 0x000007, 0x0023FD, 0x001020, + 0x038040, 0x101244, 0x000007, 0x000820, + 0x039060, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x10FA86, 0x000007, + 0x003BFD, 0x000100, 0x000A10, 0x0B807A, + 0x13804A, 0x090984, 0x000007, 0x000095, + 0x013D04, 0x118086, 0x10000A, 0x100002, + 0x090984, 0x000007, 0x038042, 0x11804A, + 0x090D04, 0x000007, 0x10000A, 0x090D84, + 0x000007, 0x00257D, 0x000820, 0x018040, + 0x00010D, 0x000810, 0x28143A, 0x00127D, + 0x018042, 0x20000A, 0x00197D, 0x018042, + 0x00117D, 0x31804A, 0x10000A, 0x003124, + 0x01280D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x300102, 0x003124, 0x000424, 0x000424, + 0x001224, 0x280502, 0x001A4C, 0x130186, + 0x700002, 0x00002D, 0x030000, 0x00387D, + 0x018042, 0x10000A, 0x132A06, 0x002124, + 0x0000AD, 0x100002, 0x00010D, 0x000924, + 0x006B24, 0x01368D, 0x00397D, 0x000820, + 0x058040, 0x038042, 0x09844A, 0x000606, + 0x08040A, 0x003264, 0x00008D, 0x000A24, + 0x001020, 0x00227D, 0x018040, 0x013C0D, + 0x000810, 0x08043A, 0x29D206, 0x000007, + 0x002820, 0x00207D, 0x018040, 0x00117D, + 0x038042, 0x13804A, 0x33800A, 0x00387D, + 0x018042, 0x08000A, 0x000904, 0x163A86, + 0x000007, 0x00008D, 0x030964, 0x01478D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x380102, + 0x000424, 0x000424, 0x001224, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x14A286, + 0x000007, 0x280502, 0x001A4C, 0x163986, + 0x000007, 0x032164, 0x00632C, 0x003DFD, + 0x018042, 0x08000A, 0x000095, 0x090904, + 0x000007, 0x000820, 0x001A4C, 0x156186, + 0x018040, 0x030000, 0x157A06, 0x002124, + 0x00010D, 0x000924, 0x006B24, 0x015B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x003A64, + 0x000095, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x01628D, 0x000810, 0x08043A, 0x29D206, + 0x000007, 0x14D206, 0x000007, 0x007020, + 0x08010A, 0x10012A, 0x0020FD, 0x038860, + 0x039060, 0x018040, 0x00227D, 0x018042, + 0x003DFD, 0x08000A, 0x31844A, 0x000904, + 0x16D886, 0x18008B, 0x00008D, 0x189904, + 0x00312C, 0x17AA06, 0x000007, 0x00324C, + 0x173386, 0x000007, 0x001904, 0x173086, + 0x000007, 0x000095, 0x199144, 0x00222C, + 0x003124, 0x00636C, 0x000E3D, 0x001375, + 0x000BFD, 0x010042, 0x09804A, 0x10000A, + 0x038AEC, 0x0393EC, 0x00224C, 0x17A986, + 0x000007, 0x00008D, 0x189904, 0x00226C, + 0x00322C, 0x30050A, 0x301DAB, 0x002083, + 0x0018FD, 0x018042, 0x08000A, 0x018924, + 0x300502, 0x001083, 0x001875, 0x010042, + 0x10000A, 0x00008D, 0x010924, 0x001375, + 0x330542, 0x330CCB, 0x332CCB, 0x3334CB, + 0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB, + 0x305C8B, 0x006083, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x187A86, 0x000007, + 0x001E2D, 0x0005FD, 0x018042, 0x08000A, + 0x028924, 0x280502, 0x00060D, 0x000810, + 0x280C3A, 0x00008D, 0x000810, 0x28143A, + 0x0A808D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x001275, 0x030042, 0x21004A, + 0x00008D, 0x1A0944, 0x000007, 0x01980D, + 0x000810, 0x08043A, 0x2B2206, 0x000007, + 0x0001F5, 0x030042, 0x0D004A, 0x10000A, + 0x089144, 0x000007, 0x000820, 0x010040, + 0x0025F5, 0x0A3144, 0x000007, 0x000820, + 0x032860, 0x030040, 0x00217D, 0x038042, + 0x0B804A, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x00008D, 0x000124, 0x00012C, + 0x000E64, 0x001A64, 0x00636C, 0x08010A, + 0x10012A, 0x000820, 0x031060, 0x030040, + 0x0020FD, 0x018042, 0x08000A, 0x00227D, + 0x018042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x00197D, 0x018042, 0x08000A, + 0x0022FD, 0x038042, 0x10000A, 0x000820, + 0x031060, 0x030040, 0x090D04, 0x000007, + 0x000820, 0x030040, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x038042, 0x13804A, 0x19804A, 0x110D04, + 0x198D04, 0x000007, 0x08000A, 0x001020, + 0x031860, 0x030860, 0x030040, 0x00008D, + 0x0B0944, 0x000007, 0x000820, 0x010040, + 0x0005F5, 0x030042, 0x08000A, 0x000820, + 0x010040, 0x0000F5, 0x010042, 0x08000A, + 0x000904, 0x1C6086, 0x001E75, 0x030042, + 0x01044A, 0x000C0A, 0x1C7206, 0x000007, + 0x000402, 0x000C02, 0x00177D, 0x001AF5, + 0x018042, 0x03144A, 0x031C4A, 0x03244A, + 0x032C4A, 0x03344A, 0x033C4A, 0x03444A, + 0x004C0A, 0x00043D, 0x0013F5, 0x001AFD, + 0x030042, 0x0B004A, 0x1B804A, 0x13804A, + 0x20000A, 0x089144, 0x19A144, 0x0389E4, + 0x0399EC, 0x005502, 0x005D0A, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x006502, 0x006D0A, 0x030042, 0x0B004A, + 0x19004A, 0x2B804A, 0x13804A, 0x21804A, + 0x30000A, 0x089144, 0x19A144, 0x2AB144, + 0x0389E4, 0x0399EC, 0x007502, 0x007D0A, + 0x03A9E4, 0x000702, 0x00107D, 0x000415, + 0x018042, 0x08000A, 0x0109E4, 0x000F02, + 0x002AF5, 0x0019FD, 0x010042, 0x09804A, + 0x10000A, 0x000934, 0x001674, 0x0029F5, + 0x010042, 0x10000A, 0x00917C, 0x002075, + 0x010042, 0x08000A, 0x000904, 0x1ED286, + 0x0026F5, 0x0027F5, 0x030042, 0x09004A, + 0x10000A, 0x000A3C, 0x00167C, 0x001A75, + 0x000BFD, 0x010042, 0x51804A, 0x48000A, + 0x160007, 0x001075, 0x010042, 0x282C0A, + 0x281D12, 0x282512, 0x001F32, 0x1E0007, + 0x0E0007, 0x001975, 0x010042, 0x002DF5, + 0x0D004A, 0x10000A, 0x009144, 0x1FB286, + 0x010042, 0x28340A, 0x000E5D, 0x00008D, + 0x000375, 0x000820, 0x010040, 0x05D2F4, + 0x54D104, 0x00735C, 0x205386, 0x000007, + 0x0C0007, 0x080007, 0x0A0007, 0x02040D, + 0x000810, 0x08043A, 0x332206, 0x000007, + 0x205A06, 0x000007, 0x080007, 0x002275, + 0x010042, 0x20000A, 0x002104, 0x212086, + 0x001E2D, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x209286, 0x000007, 0x002010, + 0x30043A, 0x00057D, 0x0180C3, 0x08000A, + 0x028924, 0x280502, 0x280C02, 0x0A810D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x0004FD, 0x018042, 0x70000A, 0x030000, + 0x007020, 0x06FA06, 0x018040, 0x02180D, + 0x000810, 0x08043A, 0x2B2206, 0x000007, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x218A86, 0x000007, 0x01F206, 0x000007, + 0x000875, 0x0009FD, 0x00010D, 0x220A06, + 0x000295, 0x000B75, 0x00097D, 0x00000D, + 0x000515, 0x010042, 0x18000A, 0x001904, + 0x287886, 0x0006F5, 0x001020, 0x010040, + 0x0004F5, 0x000820, 0x010040, 0x000775, + 0x010042, 0x09804A, 0x10000A, 0x001124, + 0x000904, 0x22BA86, 0x000815, 0x080102, + 0x101204, 0x22DA06, 0x000575, 0x081204, + 0x000007, 0x100102, 0x000575, 0x000425, + 0x021124, 0x100102, 0x000820, 0x031060, + 0x010040, 0x001924, 0x287886, 0x00008D, + 0x000464, 0x009D04, 0x278886, 0x180102, + 0x000575, 0x010042, 0x28040A, 0x00018D, + 0x000924, 0x280D02, 0x00000D, 0x000924, + 0x281502, 0x10000D, 0x000820, 0x0002F5, + 0x010040, 0x200007, 0x001175, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x23C286, + 0x000007, 0x000100, 0x080B20, 0x130B60, + 0x1B0B60, 0x030A60, 0x010040, 0x050042, + 0x3D004A, 0x35004A, 0x2D004A, 0x20000A, + 0x0006F5, 0x010042, 0x28140A, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x24CA86, 0x004015, 0x000095, 0x010D04, + 0x24B886, 0x100022, 0x10002A, 0x24E206, + 0x000007, 0x333104, 0x2AA904, 0x000007, + 0x032124, 0x280502, 0x001124, 0x000424, + 0x000424, 0x003224, 0x00292C, 0x00636C, + 0x25F386, 0x000007, 0x02B164, 0x000464, + 0x000464, 0x00008D, 0x000A64, 0x280D02, + 0x10008D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x00008D, 0x38B904, 0x000007, + 0x03296C, 0x30010A, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x25BA86, 0x000007, + 0x02312C, 0x28050A, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x267A86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x26C086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x26CA86, 0x000007, 0x003124, 0x300502, + 0x003924, 0x300583, 0x000883, 0x0005F5, + 0x010042, 0x28040A, 0x00008D, 0x008124, + 0x280D02, 0x00008D, 0x008124, 0x281502, + 0x10018D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x001025, 0x000575, 0x030042, + 0x09004A, 0x10000A, 0x0A0904, 0x121104, + 0x000007, 0x001020, 0x050860, 0x050040, + 0x0006FD, 0x018042, 0x09004A, 0x10000A, + 0x0000A5, 0x0A0904, 0x121104, 0x000007, + 0x000820, 0x019060, 0x010040, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x284286, + 0x000007, 0x230A06, 0x000007, 0x000606, + 0x000007, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x289286, 0x000007, 0x000100, + 0x080B20, 0x138B60, 0x1B8B60, 0x238B60, + 0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60, + 0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60, + 0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60, + 0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60, + 0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60, + 0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60, + 0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60, + 0x000606, 0x018040, 0x00008D, 0x000A64, + 0x280D02, 0x000A24, 0x00027D, 0x018042, + 0x10000A, 0x001224, 0x0003FD, 0x018042, + 0x08000A, 0x000904, 0x2A8286, 0x000007, + 0x00018D, 0x000A24, 0x000464, 0x000464, + 0x080102, 0x000924, 0x000424, 0x000424, + 0x100102, 0x02000D, 0x009144, 0x2AD986, + 0x000007, 0x0001FD, 0x018042, 0x08000A, + 0x000A44, 0x2ABB86, 0x018042, 0x0A000D, + 0x000820, 0x0002FD, 0x018040, 0x200007, + 0x00027D, 0x001020, 0x000606, 0x018040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x2B2A86, 0x000007, 0x00037D, 0x018042, + 0x08000A, 0x000904, 0x2B5A86, 0x000007, + 0x000075, 0x002E7D, 0x010042, 0x0B804A, + 0x000020, 0x000904, 0x000686, 0x010040, + 0x31844A, 0x30048B, 0x000883, 0x00008D, + 0x000810, 0x28143A, 0x00008D, 0x000810, + 0x280C3A, 0x000675, 0x010042, 0x08000A, + 0x003815, 0x010924, 0x280502, 0x0B000D, + 0x000820, 0x0002F5, 0x010040, 0x000606, + 0x220007, 0x000464, 0x000464, 0x000606, + 0x000007, 0x000134, 0x007F8D, 0x00093C, + 0x281D12, 0x282512, 0x001F32, 0x0E0007, + 0x00010D, 0x00037D, 0x000820, 0x018040, + 0x05D2F4, 0x000007, 0x080007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2D0286, + 0x000007, 0x000606, 0x000007, 0x000007, + 0x000012, 0x100007, 0x320007, 0x600007, + 0x100080, 0x48001A, 0x004904, 0x2D6186, + 0x000007, 0x001210, 0x58003A, 0x000145, + 0x5C5D04, 0x000007, 0x000080, 0x48001A, + 0x004904, 0x2DB186, 0x000007, 0x001210, + 0x50003A, 0x005904, 0x2E0886, 0x000045, + 0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524, + 0x004224, 0x500102, 0x200502, 0x000082, + 0x40001A, 0x004104, 0x2E3986, 0x000007, + 0x003865, 0x40001A, 0x004020, 0x00104D, + 0x04C184, 0x301B86, 0x000040, 0x040007, + 0x000165, 0x000145, 0x004020, 0x000040, + 0x000765, 0x080080, 0x40001A, 0x004104, + 0x2EC986, 0x000007, 0x001210, 0x40003A, + 0x004104, 0x2F2286, 0x00004D, 0x0000CD, + 0x004810, 0x20043A, 0x000882, 0x40001A, + 0x004104, 0x2F3186, 0x000007, 0x004820, + 0x005904, 0x300886, 0x000040, 0x0007E5, + 0x200480, 0x2816A0, 0x3216E0, 0x3A16E0, + 0x4216E0, 0x021260, 0x000040, 0x000032, + 0x400075, 0x00007D, 0x07D574, 0x200512, + 0x000082, 0x40001A, 0x004104, 0x2FE186, + 0x000007, 0x037206, 0x640007, 0x060007, + 0x0000E5, 0x000020, 0x000040, 0x000A65, + 0x000020, 0x020040, 0x020040, 0x000040, + 0x000165, 0x000042, 0x70000A, 0x007104, + 0x30A286, 0x000007, 0x018206, 0x640007, + 0x050000, 0x007020, 0x000040, 0x037206, + 0x640007, 0x000007, 0x00306D, 0x028860, + 0x029060, 0x08000A, 0x028860, 0x008040, + 0x100012, 0x00100D, 0x009184, 0x314186, + 0x000E0D, 0x009184, 0x325186, 0x000007, + 0x300007, 0x001020, 0x003B6D, 0x008040, + 0x000080, 0x08001A, 0x000904, 0x316186, + 0x000007, 0x001220, 0x000DED, 0x008040, + 0x008042, 0x10000A, 0x40000D, 0x109544, + 0x000007, 0x001020, 0x000DED, 0x008040, + 0x008042, 0x20040A, 0x000082, 0x08001A, + 0x000904, 0x31F186, 0x000007, 0x003B6D, + 0x008042, 0x08000A, 0x000E15, 0x010984, + 0x329B86, 0x600007, 0x08001A, 0x000C15, + 0x010984, 0x328386, 0x000020, 0x1A0007, + 0x0002ED, 0x008040, 0x620007, 0x00306D, + 0x028042, 0x0A804A, 0x000820, 0x0A804A, + 0x000606, 0x10804A, 0x000007, 0x282512, + 0x001F32, 0x05D2F4, 0x54D104, 0x00735C, + 0x000786, 0x000007, 0x0C0007, 0x0A0007, + 0x1C0007, 0x003465, 0x020040, 0x004820, + 0x025060, 0x40000A, 0x024060, 0x000040, + 0x454944, 0x000007, 0x004020, 0x003AE5, + 0x000040, 0x0028E5, 0x000042, 0x48000A, + 0x004904, 0x386886, 0x002C65, 0x000042, + 0x40000A, 0x0000D5, 0x454104, 0x000007, + 0x000655, 0x054504, 0x34F286, 0x0001D5, + 0x054504, 0x34F086, 0x002B65, 0x000042, + 0x003AE5, 0x50004A, 0x40000A, 0x45C3D4, + 0x000007, 0x454504, 0x000007, 0x0000CD, + 0x444944, 0x000007, 0x454504, 0x000007, + 0x00014D, 0x554944, 0x000007, 0x045144, + 0x34E986, 0x002C65, 0x000042, 0x48000A, + 0x4CD104, 0x000007, 0x04C144, 0x34F386, + 0x000007, 0x160007, 0x002CE5, 0x040042, + 0x40000A, 0x004020, 0x000040, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x356086, + 0x000007, 0x002402, 0x36A206, 0x005C02, + 0x0025E5, 0x000042, 0x40000A, 0x004274, + 0x002AE5, 0x000042, 0x40000A, 0x004274, + 0x500112, 0x0029E5, 0x000042, 0x40000A, + 0x004234, 0x454104, 0x000007, 0x004020, + 0x000040, 0x003EE5, 0x000020, 0x000040, + 0x002DE5, 0x400152, 0x50000A, 0x045144, + 0x364A86, 0x0000C5, 0x003EE5, 0x004020, + 0x000040, 0x002BE5, 0x000042, 0x40000A, + 0x404254, 0x000007, 0x002AE5, 0x004020, + 0x000040, 0x500132, 0x040134, 0x005674, + 0x0029E5, 0x020042, 0x42000A, 0x000042, + 0x50000A, 0x05417C, 0x0028E5, 0x000042, + 0x48000A, 0x0000C5, 0x4CC144, 0x371086, + 0x0026E5, 0x0027E5, 0x020042, 0x40004A, + 0x50000A, 0x00423C, 0x00567C, 0x0028E5, + 0x004820, 0x000040, 0x281D12, 0x282512, + 0x001F72, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x37AA86, 0x0E0007, 0x160007, + 0x1E0007, 0x003EE5, 0x000042, 0x40000A, + 0x004104, 0x37E886, 0x002D65, 0x000042, + 0x28340A, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x50004A, 0x05D2F4, + 0x54D104, 0x00735C, 0x385186, 0x000007, + 0x000606, 0x080007, 0x0C0007, 0x080007, + 0x0A0007, 0x0001E5, 0x020045, 0x004020, + 0x000060, 0x000365, 0x000040, 0x002E65, + 0x001A20, 0x0A1A60, 0x000040, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x000606, 0x50004A, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +// -------------------------------------------- +// DS-1E Controller InstructionRAM Code +// 1999/06/21 +// Buf441 slot is Enabled. +// -------------------------------------------- +// 04/09?@creat +// 04/12 stop nise fix +// 06/21?@WorkingOff timming +static unsigned long int CntrlInst1E[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x00800D, 0x000810, 0x20043A, 0x001A82, + 0x03460D, 0x000810, 0x10043A, 0x02EC0D, + 0x000810, 0x18043A, 0x00010D, 0x020015, + 0x0000FD, 0x000020, 0x038860, 0x039060, + 0x038060, 0x038040, 0x038040, 0x038040, + 0x018040, 0x000A7D, 0x038040, 0x038040, + 0x018040, 0x200402, 0x000882, 0x08001A, + 0x000904, 0x017186, 0x000007, 0x260007, + 0x400007, 0x000007, 0x03258D, 0x000810, + 0x18043A, 0x260007, 0x284402, 0x00087D, + 0x018042, 0x00160A, 0x05A206, 0x000007, + 0x440007, 0x00230D, 0x000810, 0x08043A, + 0x22FA06, 0x000007, 0x0007FD, 0x018042, + 0x08000A, 0x000904, 0x02AB86, 0x000195, + 0x090D04, 0x000007, 0x000820, 0x0000F5, + 0x000B7D, 0x01F060, 0x0000FD, 0x033A06, + 0x018040, 0x000A7D, 0x038042, 0x13804A, + 0x18000A, 0x001820, 0x059060, 0x058860, + 0x018040, 0x0000FD, 0x018042, 0x70000A, + 0x000115, 0x071144, 0x033B86, 0x030000, + 0x007020, 0x036206, 0x018040, 0x00360D, + 0x000810, 0x08043A, 0x232206, 0x000007, + 0x02EC0D, 0x000810, 0x18043A, 0x019A06, + 0x000007, 0x240007, 0x000F8D, 0x000810, + 0x00163A, 0x002402, 0x005C02, 0x0028FD, + 0x000020, 0x018040, 0x08000D, 0x000815, + 0x510984, 0x000007, 0x00004D, 0x000E5D, + 0x000E02, 0x00430D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x00008D, 0x000924, + 0x000F02, 0x00470D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x480480, 0x001210, + 0x28043A, 0x00778D, 0x000810, 0x280C3A, + 0x00068D, 0x000810, 0x28143A, 0x284402, + 0x03258D, 0x000810, 0x18043A, 0x07FF8D, + 0x000820, 0x0002FD, 0x018040, 0x260007, + 0x200007, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x051286, 0x000007, 0x240007, + 0x02EC0D, 0x000810, 0x18043A, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x019B86, 0x000007, 0x01B206, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x22B886, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x065A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x036186, 0x000007, 0x002104, 0x036186, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x07C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00788D, 0x000810, 0x08043A, 0x2A1206, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x070206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x229086, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x225886, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x08DA86, 0x00057D, 0x002820, + 0x03B060, 0x08F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x08FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x009D8D, 0x000810, + 0x08043A, 0x2A1206, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x0A5186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x00107D, 0x018042, + 0x08000A, 0x000215, 0x010984, 0x3A8186, + 0x000007, 0x007FBD, 0x383DC4, 0x000007, + 0x001A7D, 0x001375, 0x018042, 0x09004A, + 0x10000A, 0x0B8D04, 0x139504, 0x000007, + 0x000820, 0x019060, 0x001104, 0x225886, + 0x010040, 0x0017FD, 0x018042, 0x08000A, + 0x000904, 0x225A86, 0x000007, 0x00197D, + 0x038042, 0x09804A, 0x10000A, 0x000924, + 0x001664, 0x0011FD, 0x038042, 0x2B804A, + 0x19804A, 0x00008D, 0x218944, 0x000007, + 0x002244, 0x0C1986, 0x000007, 0x001A64, + 0x002A24, 0x00197D, 0x080102, 0x100122, + 0x000820, 0x039060, 0x018040, 0x003DFD, + 0x00008D, 0x000820, 0x018040, 0x001375, + 0x001A7D, 0x010042, 0x09804A, 0x10000A, + 0x00021D, 0x0189E4, 0x2992E4, 0x309144, + 0x000007, 0x00060D, 0x000A15, 0x000C1D, + 0x001025, 0x00A9E4, 0x012BE4, 0x000464, + 0x01B3E4, 0x0232E4, 0x000464, 0x000464, + 0x000464, 0x000464, 0x00040D, 0x08B1C4, + 0x000007, 0x000820, 0x000BF5, 0x030040, + 0x00197D, 0x038042, 0x09804A, 0x000A24, + 0x08000A, 0x080E64, 0x000007, 0x100122, + 0x000820, 0x031060, 0x010040, 0x0064AC, + 0x00027D, 0x000020, 0x018040, 0x00107D, + 0x018042, 0x0011FD, 0x3B804A, 0x09804A, + 0x20000A, 0x000095, 0x1A1144, 0x00A144, + 0x0E5886, 0x00040D, 0x00B984, 0x0E5986, + 0x0018FD, 0x018042, 0x0010FD, 0x09804A, + 0x28000A, 0x000095, 0x010924, 0x002A64, + 0x0E4986, 0x000007, 0x002904, 0x0E5A86, + 0x000007, 0x0E6206, 0x080002, 0x00008D, + 0x00387D, 0x000820, 0x018040, 0x00127D, + 0x018042, 0x10000A, 0x003904, 0x0F0986, + 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986, + 0x000025, 0x0FB206, 0x00002D, 0x000015, + 0x00082D, 0x02E00D, 0x000820, 0x0FFA06, + 0x00000D, 0x7F8035, 0x00B984, 0x0FA986, + 0x400025, 0x00008D, 0x110944, 0x000007, + 0x00018D, 0x109504, 0x000007, 0x009164, + 0x000424, 0x000424, 0x000424, 0x100102, + 0x280002, 0x02DF0D, 0x000820, 0x0FFA06, + 0x00018D, 0x00042D, 0x00008D, 0x109504, + 0x000007, 0x00020D, 0x109184, 0x000007, + 0x02DF8D, 0x000820, 0x00008D, 0x0038FD, + 0x018040, 0x003BFD, 0x001020, 0x03A860, + 0x000815, 0x313184, 0x212184, 0x000007, + 0x03B060, 0x03A060, 0x018040, 0x0022FD, + 0x000095, 0x010924, 0x000424, 0x000424, + 0x001264, 0x100102, 0x000820, 0x039060, + 0x018040, 0x001924, 0x010F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x000424, 0x000424, + 0x00117D, 0x018042, 0x08000A, 0x000A24, + 0x280502, 0x280C02, 0x09800D, 0x000820, + 0x0002FD, 0x018040, 0x200007, 0x0022FD, + 0x018042, 0x08000A, 0x000095, 0x280DC4, + 0x011924, 0x00197D, 0x018042, 0x0011FD, + 0x09804A, 0x10000A, 0x0000B5, 0x113144, + 0x0A8D04, 0x000007, 0x080A44, 0x129504, + 0x000007, 0x0023FD, 0x001020, 0x038040, + 0x101244, 0x000007, 0x000820, 0x039060, + 0x018040, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x123286, 0x000007, 0x003BFD, + 0x000100, 0x000A10, 0x0B807A, 0x13804A, + 0x090984, 0x000007, 0x000095, 0x013D04, + 0x12B886, 0x10000A, 0x100002, 0x090984, + 0x000007, 0x038042, 0x11804A, 0x090D04, + 0x000007, 0x10000A, 0x090D84, 0x000007, + 0x00257D, 0x000820, 0x018040, 0x00010D, + 0x000810, 0x28143A, 0x00127D, 0x018042, + 0x20000A, 0x00197D, 0x018042, 0x00117D, + 0x31804A, 0x10000A, 0x003124, 0x013B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x300102, + 0x003124, 0x000424, 0x000424, 0x001224, + 0x280502, 0x001A4C, 0x143986, 0x700002, + 0x00002D, 0x030000, 0x00387D, 0x018042, + 0x10000A, 0x146206, 0x002124, 0x0000AD, + 0x100002, 0x00010D, 0x000924, 0x006B24, + 0x014A0D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x003264, 0x00008D, 0x000A24, 0x001020, + 0x00227D, 0x018040, 0x014F8D, 0x000810, + 0x08043A, 0x2B5A06, 0x000007, 0x002820, + 0x00207D, 0x018040, 0x00117D, 0x038042, + 0x13804A, 0x33800A, 0x00387D, 0x018042, + 0x08000A, 0x000904, 0x177286, 0x000007, + 0x00008D, 0x030964, 0x015B0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x380102, 0x000424, + 0x000424, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x280502, 0x001A4C, 0x177186, 0x000007, + 0x032164, 0x00632C, 0x003DFD, 0x018042, + 0x08000A, 0x000095, 0x090904, 0x000007, + 0x000820, 0x001A4C, 0x169986, 0x018040, + 0x030000, 0x16B206, 0x002124, 0x00010D, + 0x000924, 0x006B24, 0x016F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x003A64, 0x000095, + 0x001224, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x171286, 0x000007, 0x01760D, + 0x000810, 0x08043A, 0x2B5A06, 0x000007, + 0x160A06, 0x000007, 0x007020, 0x08010A, + 0x10012A, 0x0020FD, 0x038860, 0x039060, + 0x018040, 0x00227D, 0x018042, 0x003DFD, + 0x08000A, 0x31844A, 0x000904, 0x181086, + 0x18008B, 0x00008D, 0x189904, 0x00312C, + 0x18E206, 0x000007, 0x00324C, 0x186B86, + 0x000007, 0x001904, 0x186886, 0x000007, + 0x000095, 0x199144, 0x00222C, 0x003124, + 0x00636C, 0x000E3D, 0x001375, 0x000BFD, + 0x010042, 0x09804A, 0x10000A, 0x038AEC, + 0x0393EC, 0x00224C, 0x18E186, 0x000007, + 0x00008D, 0x189904, 0x00226C, 0x00322C, + 0x30050A, 0x301DAB, 0x002083, 0x0018FD, + 0x018042, 0x08000A, 0x018924, 0x300502, + 0x001083, 0x001875, 0x010042, 0x10000A, + 0x00008D, 0x010924, 0x001375, 0x330542, + 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB, + 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B, + 0x006083, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x19B286, 0x000007, 0x001E2D, + 0x0005FD, 0x018042, 0x08000A, 0x028924, + 0x280502, 0x00060D, 0x000810, 0x280C3A, + 0x00008D, 0x000810, 0x28143A, 0x0A808D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x001275, 0x030042, 0x21004A, 0x00008D, + 0x1A0944, 0x000007, 0x01AB8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0001F5, + 0x030042, 0x0D004A, 0x10000A, 0x089144, + 0x000007, 0x000820, 0x010040, 0x0025F5, + 0x0A3144, 0x000007, 0x000820, 0x032860, + 0x030040, 0x00217D, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00008D, 0x000124, 0x00012C, 0x000E64, + 0x001A64, 0x00636C, 0x08010A, 0x10012A, + 0x000820, 0x031060, 0x030040, 0x0020FD, + 0x018042, 0x08000A, 0x00227D, 0x018042, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00197D, 0x018042, 0x08000A, 0x0022FD, + 0x038042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x090D04, 0x000007, 0x000820, + 0x030040, 0x038042, 0x0B804A, 0x10000A, + 0x000820, 0x031060, 0x030040, 0x038042, + 0x13804A, 0x19804A, 0x110D04, 0x198D04, + 0x000007, 0x08000A, 0x001020, 0x031860, + 0x030860, 0x030040, 0x00008D, 0x0B0944, + 0x000007, 0x000820, 0x010040, 0x0005F5, + 0x030042, 0x08000A, 0x000820, 0x010040, + 0x0000F5, 0x010042, 0x08000A, 0x000904, + 0x1D9886, 0x001E75, 0x030042, 0x01044A, + 0x000C0A, 0x1DAA06, 0x000007, 0x000402, + 0x000C02, 0x00177D, 0x001AF5, 0x018042, + 0x03144A, 0x031C4A, 0x03244A, 0x032C4A, + 0x03344A, 0x033C4A, 0x03444A, 0x004C0A, + 0x00043D, 0x0013F5, 0x001AFD, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x005502, 0x005D0A, 0x030042, 0x0B004A, + 0x1B804A, 0x13804A, 0x20000A, 0x089144, + 0x19A144, 0x0389E4, 0x0399EC, 0x006502, + 0x006D0A, 0x030042, 0x0B004A, 0x19004A, + 0x2B804A, 0x13804A, 0x21804A, 0x30000A, + 0x089144, 0x19A144, 0x2AB144, 0x0389E4, + 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4, + 0x000702, 0x00107D, 0x000415, 0x018042, + 0x08000A, 0x0109E4, 0x000F02, 0x002AF5, + 0x0019FD, 0x010042, 0x09804A, 0x10000A, + 0x000934, 0x001674, 0x0029F5, 0x010042, + 0x10000A, 0x00917C, 0x002075, 0x010042, + 0x08000A, 0x000904, 0x200A86, 0x0026F5, + 0x0027F5, 0x030042, 0x09004A, 0x10000A, + 0x000A3C, 0x00167C, 0x001A75, 0x000BFD, + 0x010042, 0x51804A, 0x48000A, 0x160007, + 0x001075, 0x010042, 0x282C0A, 0x281D12, + 0x282512, 0x001F32, 0x1E0007, 0x0E0007, + 0x001975, 0x010042, 0x002DF5, 0x0D004A, + 0x10000A, 0x009144, 0x20EA86, 0x010042, + 0x28340A, 0x000E5D, 0x00008D, 0x000375, + 0x000820, 0x010040, 0x05D2F4, 0x54D104, + 0x00735C, 0x218B86, 0x000007, 0x0C0007, + 0x080007, 0x0A0007, 0x02178D, 0x000810, + 0x08043A, 0x34B206, 0x000007, 0x219206, + 0x000007, 0x080007, 0x002275, 0x010042, + 0x20000A, 0x002104, 0x225886, 0x001E2D, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x21CA86, 0x000007, 0x002010, 0x30043A, + 0x00057D, 0x0180C3, 0x08000A, 0x028924, + 0x280502, 0x280C02, 0x0A810D, 0x000820, + 0x0002F5, 0x010040, 0x220007, 0x0004FD, + 0x018042, 0x70000A, 0x030000, 0x007020, + 0x07FA06, 0x018040, 0x022B8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x22C286, + 0x000007, 0x020206, 0x000007, 0x000875, + 0x0009FD, 0x00010D, 0x234206, 0x000295, + 0x000B75, 0x00097D, 0x00000D, 0x000515, + 0x010042, 0x18000A, 0x001904, 0x2A0086, + 0x0006F5, 0x001020, 0x010040, 0x0004F5, + 0x000820, 0x010040, 0x000775, 0x010042, + 0x09804A, 0x10000A, 0x001124, 0x000904, + 0x23F286, 0x000815, 0x080102, 0x101204, + 0x241206, 0x000575, 0x081204, 0x000007, + 0x100102, 0x000575, 0x000425, 0x021124, + 0x100102, 0x000820, 0x031060, 0x010040, + 0x001924, 0x2A0086, 0x00008D, 0x000464, + 0x009D04, 0x291086, 0x180102, 0x000575, + 0x010042, 0x28040A, 0x00018D, 0x000924, + 0x280D02, 0x00000D, 0x000924, 0x281502, + 0x10000D, 0x000820, 0x0002F5, 0x010040, + 0x200007, 0x001175, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x24FA86, 0x000007, + 0x000100, 0x080B20, 0x130B60, 0x1B0B60, + 0x030A60, 0x010040, 0x050042, 0x3D004A, + 0x35004A, 0x2D004A, 0x20000A, 0x0006F5, + 0x010042, 0x28140A, 0x0004F5, 0x010042, + 0x08000A, 0x000315, 0x010D04, 0x260286, + 0x004015, 0x000095, 0x010D04, 0x25F086, + 0x100022, 0x10002A, 0x261A06, 0x000007, + 0x333104, 0x2AA904, 0x000007, 0x032124, + 0x280502, 0x284402, 0x001124, 0x400102, + 0x000424, 0x000424, 0x003224, 0x00292C, + 0x00636C, 0x277386, 0x000007, 0x02B164, + 0x000464, 0x000464, 0x00008D, 0x000A64, + 0x280D02, 0x10008D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x00008D, 0x38B904, + 0x000007, 0x03296C, 0x30010A, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x270286, + 0x000007, 0x00212C, 0x28050A, 0x00316C, + 0x00046C, 0x00046C, 0x28450A, 0x001124, + 0x006B64, 0x100102, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x004124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x27FA86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x284086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x284A86, 0x000007, 0x284402, 0x003124, + 0x300502, 0x003924, 0x300583, 0x000883, + 0x0005F5, 0x010042, 0x28040A, 0x00008D, + 0x008124, 0x280D02, 0x00008D, 0x008124, + 0x281502, 0x10018D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001025, 0x000575, + 0x030042, 0x09004A, 0x10000A, 0x0A0904, + 0x121104, 0x000007, 0x001020, 0x050860, + 0x050040, 0x0006FD, 0x018042, 0x09004A, + 0x10000A, 0x0000A5, 0x0A0904, 0x121104, + 0x000007, 0x000820, 0x019060, 0x010040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x29CA86, 0x000007, 0x244206, 0x000007, + 0x000606, 0x000007, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x2A1A86, 0x000007, + 0x000100, 0x080B20, 0x138B60, 0x1B8B60, + 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60, + 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60, + 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60, + 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60, + 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60, + 0x038A60, 0x000606, 0x018040, 0x00008D, + 0x000A64, 0x280D02, 0x000A24, 0x00027D, + 0x018042, 0x10000A, 0x001224, 0x0003FD, + 0x018042, 0x08000A, 0x000904, 0x2C0A86, + 0x000007, 0x00018D, 0x000A24, 0x000464, + 0x000464, 0x080102, 0x000924, 0x000424, + 0x000424, 0x100102, 0x02000D, 0x009144, + 0x2C6186, 0x000007, 0x0001FD, 0x018042, + 0x08000A, 0x000A44, 0x2C4386, 0x018042, + 0x0A000D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00027D, 0x001020, 0x000606, + 0x018040, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x2CB286, 0x000007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2CE286, + 0x000007, 0x000075, 0x002E7D, 0x010042, + 0x0B804A, 0x000020, 0x000904, 0x000686, + 0x010040, 0x31844A, 0x30048B, 0x000883, + 0x00008D, 0x000810, 0x28143A, 0x00008D, + 0x000810, 0x280C3A, 0x000675, 0x010042, + 0x08000A, 0x003815, 0x010924, 0x280502, + 0x0B000D, 0x000820, 0x0002F5, 0x010040, + 0x000606, 0x220007, 0x000464, 0x000464, + 0x000606, 0x000007, 0x000134, 0x007F8D, + 0x00093C, 0x281D12, 0x282512, 0x001F32, + 0x0E0007, 0x00010D, 0x00037D, 0x000820, + 0x018040, 0x05D2F4, 0x000007, 0x080007, + 0x00037D, 0x018042, 0x08000A, 0x000904, + 0x2E8A86, 0x000007, 0x000606, 0x000007, + 0x000007, 0x000012, 0x100007, 0x320007, + 0x600007, 0x460007, 0x100080, 0x48001A, + 0x004904, 0x2EF186, 0x000007, 0x001210, + 0x58003A, 0x000145, 0x5C5D04, 0x000007, + 0x000080, 0x48001A, 0x004904, 0x2F4186, + 0x000007, 0x001210, 0x50003A, 0x005904, + 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5, + 0x7FFF7D, 0x07D524, 0x004224, 0x500102, + 0x200502, 0x000082, 0x40001A, 0x004104, + 0x2FC986, 0x000007, 0x003865, 0x40001A, + 0x004020, 0x00104D, 0x04C184, 0x31AB86, + 0x000040, 0x040007, 0x000165, 0x000145, + 0x004020, 0x000040, 0x000765, 0x080080, + 0x40001A, 0x004104, 0x305986, 0x000007, + 0x001210, 0x40003A, 0x004104, 0x30B286, + 0x00004D, 0x0000CD, 0x004810, 0x20043A, + 0x000882, 0x40001A, 0x004104, 0x30C186, + 0x000007, 0x004820, 0x005904, 0x319886, + 0x000040, 0x0007E5, 0x200480, 0x2816A0, + 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260, + 0x000040, 0x000032, 0x400075, 0x00007D, + 0x07D574, 0x200512, 0x000082, 0x40001A, + 0x004104, 0x317186, 0x000007, 0x038A06, + 0x640007, 0x0000E5, 0x000020, 0x000040, + 0x000A65, 0x000020, 0x020040, 0x020040, + 0x000040, 0x000165, 0x000042, 0x70000A, + 0x007104, 0x323286, 0x000007, 0x060007, + 0x019A06, 0x640007, 0x050000, 0x007020, + 0x000040, 0x038A06, 0x640007, 0x000007, + 0x00306D, 0x028860, 0x029060, 0x08000A, + 0x028860, 0x008040, 0x100012, 0x00100D, + 0x009184, 0x32D186, 0x000E0D, 0x009184, + 0x33E186, 0x000007, 0x300007, 0x001020, + 0x003B6D, 0x008040, 0x000080, 0x08001A, + 0x000904, 0x32F186, 0x000007, 0x001220, + 0x000DED, 0x008040, 0x008042, 0x10000A, + 0x40000D, 0x109544, 0x000007, 0x001020, + 0x000DED, 0x008040, 0x008042, 0x20040A, + 0x000082, 0x08001A, 0x000904, 0x338186, + 0x000007, 0x003B6D, 0x008042, 0x08000A, + 0x000E15, 0x010984, 0x342B86, 0x600007, + 0x08001A, 0x000C15, 0x010984, 0x341386, + 0x000020, 0x1A0007, 0x0002ED, 0x008040, + 0x620007, 0x00306D, 0x028042, 0x0A804A, + 0x000820, 0x0A804A, 0x000606, 0x10804A, + 0x000007, 0x282512, 0x001F32, 0x05D2F4, + 0x54D104, 0x00735C, 0x000786, 0x000007, + 0x0C0007, 0x0A0007, 0x1C0007, 0x003465, + 0x020040, 0x004820, 0x025060, 0x40000A, + 0x024060, 0x000040, 0x454944, 0x000007, + 0x004020, 0x003AE5, 0x000040, 0x0028E5, + 0x000042, 0x48000A, 0x004904, 0x39F886, + 0x002C65, 0x000042, 0x40000A, 0x0000D5, + 0x454104, 0x000007, 0x000655, 0x054504, + 0x368286, 0x0001D5, 0x054504, 0x368086, + 0x002B65, 0x000042, 0x003AE5, 0x50004A, + 0x40000A, 0x45C3D4, 0x000007, 0x454504, + 0x000007, 0x0000CD, 0x444944, 0x000007, + 0x454504, 0x000007, 0x00014D, 0x554944, + 0x000007, 0x045144, 0x367986, 0x002C65, + 0x000042, 0x48000A, 0x4CD104, 0x000007, + 0x04C144, 0x368386, 0x000007, 0x160007, + 0x002CE5, 0x040042, 0x40000A, 0x004020, + 0x000040, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x36F086, 0x000007, 0x002402, + 0x383206, 0x005C02, 0x0025E5, 0x000042, + 0x40000A, 0x004274, 0x002AE5, 0x000042, + 0x40000A, 0x004274, 0x500112, 0x0029E5, + 0x000042, 0x40000A, 0x004234, 0x454104, + 0x000007, 0x004020, 0x000040, 0x003EE5, + 0x000020, 0x000040, 0x002DE5, 0x400152, + 0x50000A, 0x045144, 0x37DA86, 0x0000C5, + 0x003EE5, 0x004020, 0x000040, 0x002BE5, + 0x000042, 0x40000A, 0x404254, 0x000007, + 0x002AE5, 0x004020, 0x000040, 0x500132, + 0x040134, 0x005674, 0x0029E5, 0x020042, + 0x42000A, 0x000042, 0x50000A, 0x05417C, + 0x0028E5, 0x000042, 0x48000A, 0x0000C5, + 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5, + 0x020042, 0x40004A, 0x50000A, 0x00423C, + 0x00567C, 0x0028E5, 0x004820, 0x000040, + 0x281D12, 0x282512, 0x001F72, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x393A86, + 0x0E0007, 0x160007, 0x1E0007, 0x003EE5, + 0x000042, 0x40000A, 0x004104, 0x397886, + 0x002D65, 0x000042, 0x28340A, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x50004A, 0x05D2F4, 0x54D104, 0x00735C, + 0x39E186, 0x000007, 0x000606, 0x080007, + 0x0C0007, 0x080007, 0x0A0007, 0x0001E5, + 0x020045, 0x004020, 0x000060, 0x000365, + 0x000040, 0x002E65, 0x001A20, 0x0A1A60, + 0x000040, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x000606, 0x50004A, + 0x0017FD, 0x018042, 0x08000A, 0x000904, + 0x225A86, 0x000007, 0x00107D, 0x018042, + 0x0011FD, 0x33804A, 0x19804A, 0x20000A, + 0x000095, 0x2A1144, 0x01A144, 0x3B9086, + 0x00040D, 0x00B184, 0x3B9186, 0x0018FD, + 0x018042, 0x0010FD, 0x09804A, 0x38000A, + 0x000095, 0x010924, 0x003A64, 0x3B8186, + 0x000007, 0x003904, 0x3B9286, 0x000007, + 0x3B9A06, 0x00000D, 0x00008D, 0x000820, + 0x00387D, 0x018040, 0x700002, 0x00117D, + 0x018042, 0x00197D, 0x29804A, 0x30000A, + 0x380002, 0x003124, 0x000424, 0x000424, + 0x002A24, 0x280502, 0x00068D, 0x000810, + 0x28143A, 0x00750D, 0x00B124, 0x002264, + 0x3D0386, 0x284402, 0x000810, 0x280C3A, + 0x0B800D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00758D, 0x00B124, 0x100102, + 0x012144, 0x3E4986, 0x001810, 0x10003A, + 0x00387D, 0x018042, 0x08000A, 0x000904, + 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD, + 0x00008D, 0x023164, 0x000A64, 0x280D02, + 0x0B808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00387D, 0x018042, 0x08000A, + 0x000904, 0x3E3286, 0x030000, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x3D8286, + 0x000007, 0x002810, 0x28043A, 0x00750D, + 0x030924, 0x002264, 0x280D02, 0x02316C, + 0x28450A, 0x0B810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x00008D, 0x000A24, + 0x3E4A06, 0x100102, 0x001810, 0x10003A, + 0x0000BD, 0x003810, 0x30043A, 0x00187D, + 0x018042, 0x0018FD, 0x09804A, 0x20000A, + 0x0000AD, 0x028924, 0x07212C, 0x001010, + 0x300583, 0x300D8B, 0x3014BB, 0x301C83, + 0x002083, 0x00137D, 0x038042, 0x33844A, + 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB, + 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083, + 0x001E0D, 0x0005FD, 0x018042, 0x20000A, + 0x020924, 0x00068D, 0x00A96C, 0x00009D, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x3F6A86, 0x000007, 0x280502, 0x280D0A, + 0x284402, 0x001810, 0x28143A, 0x0C008D, + 0x000820, 0x0002FD, 0x018040, 0x220007, + 0x003904, 0x225886, 0x001E0D, 0x00057D, + 0x018042, 0x20000A, 0x020924, 0x0000A5, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x402A86, 0x000007, 0x280502, 0x280C02, + 0x002010, 0x28143A, 0x0C010D, 0x000820, + 0x0002FD, 0x018040, 0x225A06, 0x220007, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +#endif //_HWMCODE_ + + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/Config.in linux.ac/drivers/sound/Config.in --- linux.vanilla/drivers/sound/Config.in Thu May 25 17:38:07 2000 +++ linux.ac/drivers/sound/Config.in Mon Jun 5 19:10:24 2000 @@ -27,7 +27,7 @@ dep_tristate ' SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND fi -dep_tristate ' Trident 4DWave DX/NX or SiS 7018 PCI Audio Core' CONFIG_SOUND_TRIDENT $CONFIG_SOUND +dep_tristate ' Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core' CONFIG_SOUND_TRIDENT $CONFIG_SOUND dep_tristate ' Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND if [ "$CONFIG_SOUND_MSNDCLAS" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then @@ -79,7 +79,7 @@ int 'MSND buffer size (kB)' CONFIG_MSND_FIFOSIZE 128 fi -tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX +dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_PCI dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND @@ -149,6 +149,7 @@ dep_tristate ' Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS + dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS @@ -181,3 +182,4 @@ fi +dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/Hwmcode.h linux.ac/drivers/sound/Hwmcode.h --- linux.vanilla/drivers/sound/Hwmcode.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/Hwmcode.h Wed May 31 11:15:34 2000 @@ -0,0 +1,804 @@ +//============================================================================= +// Copyright (c) 1997 Yamaha Corporation. All Rights Reserved. +// +// Title: +// hwmcode.c +// Desc: +// micro-code for CTRL & DSP +// HISTORY: +// April 03, 1997: 1st try by M. Mukojima +//============================================================================= +#define YDSXG_DSPLENGTH 0x0080 +#define YDSXG_CTRLLENGTH 0x3000 + + +static unsigned long int gdwDSPCode[YDSXG_DSPLENGTH >> 2] = { + 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, + 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, + 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, + 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + + +// -------------------------------------------- +// DS-1E Controller InstructionRAM Code +// 1999/06/21 +// Buf441 slot is Enabled. +// -------------------------------------------- +// 04/09?@creat +// 04/12 stop nise fix +// 06/21?@WorkingOff timming +static unsigned long gdwCtrl1eCode[YDSXG_CTRLLENGTH >> 2] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x00800D, 0x000810, 0x20043A, 0x001A82, + 0x03460D, 0x000810, 0x10043A, 0x02EC0D, + 0x000810, 0x18043A, 0x00010D, 0x020015, + 0x0000FD, 0x000020, 0x038860, 0x039060, + 0x038060, 0x038040, 0x038040, 0x038040, + 0x018040, 0x000A7D, 0x038040, 0x038040, + 0x018040, 0x200402, 0x000882, 0x08001A, + 0x000904, 0x017186, 0x000007, 0x260007, + 0x400007, 0x000007, 0x03258D, 0x000810, + 0x18043A, 0x260007, 0x284402, 0x00087D, + 0x018042, 0x00160A, 0x05A206, 0x000007, + 0x440007, 0x00230D, 0x000810, 0x08043A, + 0x22FA06, 0x000007, 0x0007FD, 0x018042, + 0x08000A, 0x000904, 0x02AB86, 0x000195, + 0x090D04, 0x000007, 0x000820, 0x0000F5, + 0x000B7D, 0x01F060, 0x0000FD, 0x033A06, + 0x018040, 0x000A7D, 0x038042, 0x13804A, + 0x18000A, 0x001820, 0x059060, 0x058860, + 0x018040, 0x0000FD, 0x018042, 0x70000A, + 0x000115, 0x071144, 0x033B86, 0x030000, + 0x007020, 0x036206, 0x018040, 0x00360D, + 0x000810, 0x08043A, 0x232206, 0x000007, + 0x02EC0D, 0x000810, 0x18043A, 0x019A06, + 0x000007, 0x240007, 0x000F8D, 0x000810, + 0x00163A, 0x002402, 0x005C02, 0x0028FD, + 0x000020, 0x018040, 0x08000D, 0x000815, + 0x510984, 0x000007, 0x00004D, 0x000E5D, + 0x000E02, 0x00430D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x00008D, 0x000924, + 0x000F02, 0x00470D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x480480, 0x001210, + 0x28043A, 0x00778D, 0x000810, 0x280C3A, + 0x00068D, 0x000810, 0x28143A, 0x284402, + 0x03258D, 0x000810, 0x18043A, 0x07FF8D, + 0x000820, 0x0002FD, 0x018040, 0x260007, + 0x200007, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x051286, 0x000007, 0x240007, + 0x02EC0D, 0x000810, 0x18043A, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x019B86, 0x000007, 0x01B206, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x22B886, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x065A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x036186, 0x000007, 0x002104, 0x036186, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x07C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00788D, 0x000810, 0x08043A, 0x2A1206, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x070206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x229086, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x225886, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x08DA86, 0x00057D, 0x002820, + 0x03B060, 0x08F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x08FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x009D8D, 0x000810, + 0x08043A, 0x2A1206, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x0A5186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x00107D, 0x018042, + 0x08000A, 0x000215, 0x010984, 0x3A8186, + 0x000007, 0x007FBD, 0x383DC4, 0x000007, + 0x001A7D, 0x001375, 0x018042, 0x09004A, + 0x10000A, 0x0B8D04, 0x139504, 0x000007, + 0x000820, 0x019060, 0x001104, 0x225886, + 0x010040, 0x0017FD, 0x018042, 0x08000A, + 0x000904, 0x225A86, 0x000007, 0x00197D, + 0x038042, 0x09804A, 0x10000A, 0x000924, + 0x001664, 0x0011FD, 0x038042, 0x2B804A, + 0x19804A, 0x00008D, 0x218944, 0x000007, + 0x002244, 0x0C1986, 0x000007, 0x001A64, + 0x002A24, 0x00197D, 0x080102, 0x100122, + 0x000820, 0x039060, 0x018040, 0x003DFD, + 0x00008D, 0x000820, 0x018040, 0x001375, + 0x001A7D, 0x010042, 0x09804A, 0x10000A, + 0x00021D, 0x0189E4, 0x2992E4, 0x309144, + 0x000007, 0x00060D, 0x000A15, 0x000C1D, + 0x001025, 0x00A9E4, 0x012BE4, 0x000464, + 0x01B3E4, 0x0232E4, 0x000464, 0x000464, + 0x000464, 0x000464, 0x00040D, 0x08B1C4, + 0x000007, 0x000820, 0x000BF5, 0x030040, + 0x00197D, 0x038042, 0x09804A, 0x000A24, + 0x08000A, 0x080E64, 0x000007, 0x100122, + 0x000820, 0x031060, 0x010040, 0x0064AC, + 0x00027D, 0x000020, 0x018040, 0x00107D, + 0x018042, 0x0011FD, 0x3B804A, 0x09804A, + 0x20000A, 0x000095, 0x1A1144, 0x00A144, + 0x0E5886, 0x00040D, 0x00B984, 0x0E5986, + 0x0018FD, 0x018042, 0x0010FD, 0x09804A, + 0x28000A, 0x000095, 0x010924, 0x002A64, + 0x0E4986, 0x000007, 0x002904, 0x0E5A86, + 0x000007, 0x0E6206, 0x080002, 0x00008D, + 0x00387D, 0x000820, 0x018040, 0x00127D, + 0x018042, 0x10000A, 0x003904, 0x0F0986, + 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986, + 0x000025, 0x0FB206, 0x00002D, 0x000015, + 0x00082D, 0x02E00D, 0x000820, 0x0FFA06, + 0x00000D, 0x7F8035, 0x00B984, 0x0FA986, + 0x400025, 0x00008D, 0x110944, 0x000007, + 0x00018D, 0x109504, 0x000007, 0x009164, + 0x000424, 0x000424, 0x000424, 0x100102, + 0x280002, 0x02DF0D, 0x000820, 0x0FFA06, + 0x00018D, 0x00042D, 0x00008D, 0x109504, + 0x000007, 0x00020D, 0x109184, 0x000007, + 0x02DF8D, 0x000820, 0x00008D, 0x0038FD, + 0x018040, 0x003BFD, 0x001020, 0x03A860, + 0x000815, 0x313184, 0x212184, 0x000007, + 0x03B060, 0x03A060, 0x018040, 0x0022FD, + 0x000095, 0x010924, 0x000424, 0x000424, + 0x001264, 0x100102, 0x000820, 0x039060, + 0x018040, 0x001924, 0x010F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x000424, 0x000424, + 0x00117D, 0x018042, 0x08000A, 0x000A24, + 0x280502, 0x280C02, 0x09800D, 0x000820, + 0x0002FD, 0x018040, 0x200007, 0x0022FD, + 0x018042, 0x08000A, 0x000095, 0x280DC4, + 0x011924, 0x00197D, 0x018042, 0x0011FD, + 0x09804A, 0x10000A, 0x0000B5, 0x113144, + 0x0A8D04, 0x000007, 0x080A44, 0x129504, + 0x000007, 0x0023FD, 0x001020, 0x038040, + 0x101244, 0x000007, 0x000820, 0x039060, + 0x018040, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x123286, 0x000007, 0x003BFD, + 0x000100, 0x000A10, 0x0B807A, 0x13804A, + 0x090984, 0x000007, 0x000095, 0x013D04, + 0x12B886, 0x10000A, 0x100002, 0x090984, + 0x000007, 0x038042, 0x11804A, 0x090D04, + 0x000007, 0x10000A, 0x090D84, 0x000007, + 0x00257D, 0x000820, 0x018040, 0x00010D, + 0x000810, 0x28143A, 0x00127D, 0x018042, + 0x20000A, 0x00197D, 0x018042, 0x00117D, + 0x31804A, 0x10000A, 0x003124, 0x013B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x300102, + 0x003124, 0x000424, 0x000424, 0x001224, + 0x280502, 0x001A4C, 0x143986, 0x700002, + 0x00002D, 0x030000, 0x00387D, 0x018042, + 0x10000A, 0x146206, 0x002124, 0x0000AD, + 0x100002, 0x00010D, 0x000924, 0x006B24, + 0x014A0D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x003264, 0x00008D, 0x000A24, 0x001020, + 0x00227D, 0x018040, 0x014F8D, 0x000810, + 0x08043A, 0x2B5A06, 0x000007, 0x002820, + 0x00207D, 0x018040, 0x00117D, 0x038042, + 0x13804A, 0x33800A, 0x00387D, 0x018042, + 0x08000A, 0x000904, 0x177286, 0x000007, + 0x00008D, 0x030964, 0x015B0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x380102, 0x000424, + 0x000424, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x280502, 0x001A4C, 0x177186, 0x000007, + 0x032164, 0x00632C, 0x003DFD, 0x018042, + 0x08000A, 0x000095, 0x090904, 0x000007, + 0x000820, 0x001A4C, 0x169986, 0x018040, + 0x030000, 0x16B206, 0x002124, 0x00010D, + 0x000924, 0x006B24, 0x016F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x003A64, 0x000095, + 0x001224, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x171286, 0x000007, 0x01760D, + 0x000810, 0x08043A, 0x2B5A06, 0x000007, + 0x160A06, 0x000007, 0x007020, 0x08010A, + 0x10012A, 0x0020FD, 0x038860, 0x039060, + 0x018040, 0x00227D, 0x018042, 0x003DFD, + 0x08000A, 0x31844A, 0x000904, 0x181086, + 0x18008B, 0x00008D, 0x189904, 0x00312C, + 0x18E206, 0x000007, 0x00324C, 0x186B86, + 0x000007, 0x001904, 0x186886, 0x000007, + 0x000095, 0x199144, 0x00222C, 0x003124, + 0x00636C, 0x000E3D, 0x001375, 0x000BFD, + 0x010042, 0x09804A, 0x10000A, 0x038AEC, + 0x0393EC, 0x00224C, 0x18E186, 0x000007, + 0x00008D, 0x189904, 0x00226C, 0x00322C, + 0x30050A, 0x301DAB, 0x002083, 0x0018FD, + 0x018042, 0x08000A, 0x018924, 0x300502, + 0x001083, 0x001875, 0x010042, 0x10000A, + 0x00008D, 0x010924, 0x001375, 0x330542, + 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB, + 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B, + 0x006083, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x19B286, 0x000007, 0x001E2D, + 0x0005FD, 0x018042, 0x08000A, 0x028924, + 0x280502, 0x00060D, 0x000810, 0x280C3A, + 0x00008D, 0x000810, 0x28143A, 0x0A808D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x001275, 0x030042, 0x21004A, 0x00008D, + 0x1A0944, 0x000007, 0x01AB8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0001F5, + 0x030042, 0x0D004A, 0x10000A, 0x089144, + 0x000007, 0x000820, 0x010040, 0x0025F5, + 0x0A3144, 0x000007, 0x000820, 0x032860, + 0x030040, 0x00217D, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00008D, 0x000124, 0x00012C, 0x000E64, + 0x001A64, 0x00636C, 0x08010A, 0x10012A, + 0x000820, 0x031060, 0x030040, 0x0020FD, + 0x018042, 0x08000A, 0x00227D, 0x018042, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00197D, 0x018042, 0x08000A, 0x0022FD, + 0x038042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x090D04, 0x000007, 0x000820, + 0x030040, 0x038042, 0x0B804A, 0x10000A, + 0x000820, 0x031060, 0x030040, 0x038042, + 0x13804A, 0x19804A, 0x110D04, 0x198D04, + 0x000007, 0x08000A, 0x001020, 0x031860, + 0x030860, 0x030040, 0x00008D, 0x0B0944, + 0x000007, 0x000820, 0x010040, 0x0005F5, + 0x030042, 0x08000A, 0x000820, 0x010040, + 0x0000F5, 0x010042, 0x08000A, 0x000904, + 0x1D9886, 0x001E75, 0x030042, 0x01044A, + 0x000C0A, 0x1DAA06, 0x000007, 0x000402, + 0x000C02, 0x00177D, 0x001AF5, 0x018042, + 0x03144A, 0x031C4A, 0x03244A, 0x032C4A, + 0x03344A, 0x033C4A, 0x03444A, 0x004C0A, + 0x00043D, 0x0013F5, 0x001AFD, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x005502, 0x005D0A, 0x030042, 0x0B004A, + 0x1B804A, 0x13804A, 0x20000A, 0x089144, + 0x19A144, 0x0389E4, 0x0399EC, 0x006502, + 0x006D0A, 0x030042, 0x0B004A, 0x19004A, + 0x2B804A, 0x13804A, 0x21804A, 0x30000A, + 0x089144, 0x19A144, 0x2AB144, 0x0389E4, + 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4, + 0x000702, 0x00107D, 0x000415, 0x018042, + 0x08000A, 0x0109E4, 0x000F02, 0x002AF5, + 0x0019FD, 0x010042, 0x09804A, 0x10000A, + 0x000934, 0x001674, 0x0029F5, 0x010042, + 0x10000A, 0x00917C, 0x002075, 0x010042, + 0x08000A, 0x000904, 0x200A86, 0x0026F5, + 0x0027F5, 0x030042, 0x09004A, 0x10000A, + 0x000A3C, 0x00167C, 0x001A75, 0x000BFD, + 0x010042, 0x51804A, 0x48000A, 0x160007, + 0x001075, 0x010042, 0x282C0A, 0x281D12, + 0x282512, 0x001F32, 0x1E0007, 0x0E0007, + 0x001975, 0x010042, 0x002DF5, 0x0D004A, + 0x10000A, 0x009144, 0x20EA86, 0x010042, + 0x28340A, 0x000E5D, 0x00008D, 0x000375, + 0x000820, 0x010040, 0x05D2F4, 0x54D104, + 0x00735C, 0x218B86, 0x000007, 0x0C0007, + 0x080007, 0x0A0007, 0x02178D, 0x000810, + 0x08043A, 0x34B206, 0x000007, 0x219206, + 0x000007, 0x080007, 0x002275, 0x010042, + 0x20000A, 0x002104, 0x225886, 0x001E2D, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x21CA86, 0x000007, 0x002010, 0x30043A, + 0x00057D, 0x0180C3, 0x08000A, 0x028924, + 0x280502, 0x280C02, 0x0A810D, 0x000820, + 0x0002F5, 0x010040, 0x220007, 0x0004FD, + 0x018042, 0x70000A, 0x030000, 0x007020, + 0x07FA06, 0x018040, 0x022B8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x22C286, + 0x000007, 0x020206, 0x000007, 0x000875, + 0x0009FD, 0x00010D, 0x234206, 0x000295, + 0x000B75, 0x00097D, 0x00000D, 0x000515, + 0x010042, 0x18000A, 0x001904, 0x2A0086, + 0x0006F5, 0x001020, 0x010040, 0x0004F5, + 0x000820, 0x010040, 0x000775, 0x010042, + 0x09804A, 0x10000A, 0x001124, 0x000904, + 0x23F286, 0x000815, 0x080102, 0x101204, + 0x241206, 0x000575, 0x081204, 0x000007, + 0x100102, 0x000575, 0x000425, 0x021124, + 0x100102, 0x000820, 0x031060, 0x010040, + 0x001924, 0x2A0086, 0x00008D, 0x000464, + 0x009D04, 0x291086, 0x180102, 0x000575, + 0x010042, 0x28040A, 0x00018D, 0x000924, + 0x280D02, 0x00000D, 0x000924, 0x281502, + 0x10000D, 0x000820, 0x0002F5, 0x010040, + 0x200007, 0x001175, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x24FA86, 0x000007, + 0x000100, 0x080B20, 0x130B60, 0x1B0B60, + 0x030A60, 0x010040, 0x050042, 0x3D004A, + 0x35004A, 0x2D004A, 0x20000A, 0x0006F5, + 0x010042, 0x28140A, 0x0004F5, 0x010042, + 0x08000A, 0x000315, 0x010D04, 0x260286, + 0x004015, 0x000095, 0x010D04, 0x25F086, + 0x100022, 0x10002A, 0x261A06, 0x000007, + 0x333104, 0x2AA904, 0x000007, 0x032124, + 0x280502, 0x284402, 0x001124, 0x400102, + 0x000424, 0x000424, 0x003224, 0x00292C, + 0x00636C, 0x277386, 0x000007, 0x02B164, + 0x000464, 0x000464, 0x00008D, 0x000A64, + 0x280D02, 0x10008D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x00008D, 0x38B904, + 0x000007, 0x03296C, 0x30010A, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x270286, + 0x000007, 0x00212C, 0x28050A, 0x00316C, + 0x00046C, 0x00046C, 0x28450A, 0x001124, + 0x006B64, 0x100102, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x004124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x27FA86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x284086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x284A86, 0x000007, 0x284402, 0x003124, + 0x300502, 0x003924, 0x300583, 0x000883, + 0x0005F5, 0x010042, 0x28040A, 0x00008D, + 0x008124, 0x280D02, 0x00008D, 0x008124, + 0x281502, 0x10018D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001025, 0x000575, + 0x030042, 0x09004A, 0x10000A, 0x0A0904, + 0x121104, 0x000007, 0x001020, 0x050860, + 0x050040, 0x0006FD, 0x018042, 0x09004A, + 0x10000A, 0x0000A5, 0x0A0904, 0x121104, + 0x000007, 0x000820, 0x019060, 0x010040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x29CA86, 0x000007, 0x244206, 0x000007, + 0x000606, 0x000007, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x2A1A86, 0x000007, + 0x000100, 0x080B20, 0x138B60, 0x1B8B60, + 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60, + 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60, + 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60, + 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60, + 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60, + 0x038A60, 0x000606, 0x018040, 0x00008D, + 0x000A64, 0x280D02, 0x000A24, 0x00027D, + 0x018042, 0x10000A, 0x001224, 0x0003FD, + 0x018042, 0x08000A, 0x000904, 0x2C0A86, + 0x000007, 0x00018D, 0x000A24, 0x000464, + 0x000464, 0x080102, 0x000924, 0x000424, + 0x000424, 0x100102, 0x02000D, 0x009144, + 0x2C6186, 0x000007, 0x0001FD, 0x018042, + 0x08000A, 0x000A44, 0x2C4386, 0x018042, + 0x0A000D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00027D, 0x001020, 0x000606, + 0x018040, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x2CB286, 0x000007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2CE286, + 0x000007, 0x000075, 0x002E7D, 0x010042, + 0x0B804A, 0x000020, 0x000904, 0x000686, + 0x010040, 0x31844A, 0x30048B, 0x000883, + 0x00008D, 0x000810, 0x28143A, 0x00008D, + 0x000810, 0x280C3A, 0x000675, 0x010042, + 0x08000A, 0x003815, 0x010924, 0x280502, + 0x0B000D, 0x000820, 0x0002F5, 0x010040, + 0x000606, 0x220007, 0x000464, 0x000464, + 0x000606, 0x000007, 0x000134, 0x007F8D, + 0x00093C, 0x281D12, 0x282512, 0x001F32, + 0x0E0007, 0x00010D, 0x00037D, 0x000820, + 0x018040, 0x05D2F4, 0x000007, 0x080007, + 0x00037D, 0x018042, 0x08000A, 0x000904, + 0x2E8A86, 0x000007, 0x000606, 0x000007, + 0x000007, 0x000012, 0x100007, 0x320007, + 0x600007, 0x460007, 0x100080, 0x48001A, + 0x004904, 0x2EF186, 0x000007, 0x001210, + 0x58003A, 0x000145, 0x5C5D04, 0x000007, + 0x000080, 0x48001A, 0x004904, 0x2F4186, + 0x000007, 0x001210, 0x50003A, 0x005904, + 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5, + 0x7FFF7D, 0x07D524, 0x004224, 0x500102, + 0x200502, 0x000082, 0x40001A, 0x004104, + 0x2FC986, 0x000007, 0x003865, 0x40001A, + 0x004020, 0x00104D, 0x04C184, 0x31AB86, + 0x000040, 0x040007, 0x000165, 0x000145, + 0x004020, 0x000040, 0x000765, 0x080080, + 0x40001A, 0x004104, 0x305986, 0x000007, + 0x001210, 0x40003A, 0x004104, 0x30B286, + 0x00004D, 0x0000CD, 0x004810, 0x20043A, + 0x000882, 0x40001A, 0x004104, 0x30C186, + 0x000007, 0x004820, 0x005904, 0x319886, + 0x000040, 0x0007E5, 0x200480, 0x2816A0, + 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260, + 0x000040, 0x000032, 0x400075, 0x00007D, + 0x07D574, 0x200512, 0x000082, 0x40001A, + 0x004104, 0x317186, 0x000007, 0x038A06, + 0x640007, 0x0000E5, 0x000020, 0x000040, + 0x000A65, 0x000020, 0x020040, 0x020040, + 0x000040, 0x000165, 0x000042, 0x70000A, + 0x007104, 0x323286, 0x000007, 0x060007, + 0x019A06, 0x640007, 0x050000, 0x007020, + 0x000040, 0x038A06, 0x640007, 0x000007, + 0x00306D, 0x028860, 0x029060, 0x08000A, + 0x028860, 0x008040, 0x100012, 0x00100D, + 0x009184, 0x32D186, 0x000E0D, 0x009184, + 0x33E186, 0x000007, 0x300007, 0x001020, + 0x003B6D, 0x008040, 0x000080, 0x08001A, + 0x000904, 0x32F186, 0x000007, 0x001220, + 0x000DED, 0x008040, 0x008042, 0x10000A, + 0x40000D, 0x109544, 0x000007, 0x001020, + 0x000DED, 0x008040, 0x008042, 0x20040A, + 0x000082, 0x08001A, 0x000904, 0x338186, + 0x000007, 0x003B6D, 0x008042, 0x08000A, + 0x000E15, 0x010984, 0x342B86, 0x600007, + 0x08001A, 0x000C15, 0x010984, 0x341386, + 0x000020, 0x1A0007, 0x0002ED, 0x008040, + 0x620007, 0x00306D, 0x028042, 0x0A804A, + 0x000820, 0x0A804A, 0x000606, 0x10804A, + 0x000007, 0x282512, 0x001F32, 0x05D2F4, + 0x54D104, 0x00735C, 0x000786, 0x000007, + 0x0C0007, 0x0A0007, 0x1C0007, 0x003465, + 0x020040, 0x004820, 0x025060, 0x40000A, + 0x024060, 0x000040, 0x454944, 0x000007, + 0x004020, 0x003AE5, 0x000040, 0x0028E5, + 0x000042, 0x48000A, 0x004904, 0x39F886, + 0x002C65, 0x000042, 0x40000A, 0x0000D5, + 0x454104, 0x000007, 0x000655, 0x054504, + 0x368286, 0x0001D5, 0x054504, 0x368086, + 0x002B65, 0x000042, 0x003AE5, 0x50004A, + 0x40000A, 0x45C3D4, 0x000007, 0x454504, + 0x000007, 0x0000CD, 0x444944, 0x000007, + 0x454504, 0x000007, 0x00014D, 0x554944, + 0x000007, 0x045144, 0x367986, 0x002C65, + 0x000042, 0x48000A, 0x4CD104, 0x000007, + 0x04C144, 0x368386, 0x000007, 0x160007, + 0x002CE5, 0x040042, 0x40000A, 0x004020, + 0x000040, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x36F086, 0x000007, 0x002402, + 0x383206, 0x005C02, 0x0025E5, 0x000042, + 0x40000A, 0x004274, 0x002AE5, 0x000042, + 0x40000A, 0x004274, 0x500112, 0x0029E5, + 0x000042, 0x40000A, 0x004234, 0x454104, + 0x000007, 0x004020, 0x000040, 0x003EE5, + 0x000020, 0x000040, 0x002DE5, 0x400152, + 0x50000A, 0x045144, 0x37DA86, 0x0000C5, + 0x003EE5, 0x004020, 0x000040, 0x002BE5, + 0x000042, 0x40000A, 0x404254, 0x000007, + 0x002AE5, 0x004020, 0x000040, 0x500132, + 0x040134, 0x005674, 0x0029E5, 0x020042, + 0x42000A, 0x000042, 0x50000A, 0x05417C, + 0x0028E5, 0x000042, 0x48000A, 0x0000C5, + 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5, + 0x020042, 0x40004A, 0x50000A, 0x00423C, + 0x00567C, 0x0028E5, 0x004820, 0x000040, + 0x281D12, 0x282512, 0x001F72, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x393A86, + 0x0E0007, 0x160007, 0x1E0007, 0x003EE5, + 0x000042, 0x40000A, 0x004104, 0x397886, + 0x002D65, 0x000042, 0x28340A, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x50004A, 0x05D2F4, 0x54D104, 0x00735C, + 0x39E186, 0x000007, 0x000606, 0x080007, + 0x0C0007, 0x080007, 0x0A0007, 0x0001E5, + 0x020045, 0x004020, 0x000060, 0x000365, + 0x000040, 0x002E65, 0x001A20, 0x0A1A60, + 0x000040, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x000606, 0x50004A, + 0x0017FD, 0x018042, 0x08000A, 0x000904, + 0x225A86, 0x000007, 0x00107D, 0x018042, + 0x0011FD, 0x33804A, 0x19804A, 0x20000A, + 0x000095, 0x2A1144, 0x01A144, 0x3B9086, + 0x00040D, 0x00B184, 0x3B9186, 0x0018FD, + 0x018042, 0x0010FD, 0x09804A, 0x38000A, + 0x000095, 0x010924, 0x003A64, 0x3B8186, + 0x000007, 0x003904, 0x3B9286, 0x000007, + 0x3B9A06, 0x00000D, 0x00008D, 0x000820, + 0x00387D, 0x018040, 0x700002, 0x00117D, + 0x018042, 0x00197D, 0x29804A, 0x30000A, + 0x380002, 0x003124, 0x000424, 0x000424, + 0x002A24, 0x280502, 0x00068D, 0x000810, + 0x28143A, 0x00750D, 0x00B124, 0x002264, + 0x3D0386, 0x284402, 0x000810, 0x280C3A, + 0x0B800D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00758D, 0x00B124, 0x100102, + 0x012144, 0x3E4986, 0x001810, 0x10003A, + 0x00387D, 0x018042, 0x08000A, 0x000904, + 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD, + 0x00008D, 0x023164, 0x000A64, 0x280D02, + 0x0B808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00387D, 0x018042, 0x08000A, + 0x000904, 0x3E3286, 0x030000, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x3D8286, + 0x000007, 0x002810, 0x28043A, 0x00750D, + 0x030924, 0x002264, 0x280D02, 0x02316C, + 0x28450A, 0x0B810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x00008D, 0x000A24, + 0x3E4A06, 0x100102, 0x001810, 0x10003A, + 0x0000BD, 0x003810, 0x30043A, 0x00187D, + 0x018042, 0x0018FD, 0x09804A, 0x20000A, + 0x0000AD, 0x028924, 0x07212C, 0x001010, + 0x300583, 0x300D8B, 0x3014BB, 0x301C83, + 0x002083, 0x00137D, 0x038042, 0x33844A, + 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB, + 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083, + 0x001E0D, 0x0005FD, 0x018042, 0x20000A, + 0x020924, 0x00068D, 0x00A96C, 0x00009D, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x3F6A86, 0x000007, 0x280502, 0x280D0A, + 0x284402, 0x001810, 0x28143A, 0x0C008D, + 0x000820, 0x0002FD, 0x018040, 0x220007, + 0x003904, 0x225886, 0x001E0D, 0x00057D, + 0x018042, 0x20000A, 0x020924, 0x0000A5, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x402A86, 0x000007, 0x280502, 0x280C02, + 0x002010, 0x28143A, 0x0C010D, 0x000820, + 0x0002FD, 0x018040, 0x225A06, 0x220007, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/Makefile linux.ac/drivers/sound/Makefile --- linux.vanilla/drivers/sound/Makefile Thu May 25 17:38:07 2000 +++ linux.ac/drivers/sound/Makefile Wed May 31 11:16:22 2000 @@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o +obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o obj-$(CONFIG_SOUND_VWSND) += vwsnd.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/ac97_codec.c linux.ac/drivers/sound/ac97_codec.c --- linux.vanilla/drivers/sound/ac97_codec.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/ac97_codec.c Thu Jun 8 15:10:06 2000 @@ -21,7 +21,7 @@ * * History * v0.4 Mar 15 2000 Ollie Lho - * dual codec support verified with 4 channel output + * dual codecs support verified with 4 channels output * v0.3 Feb 22 2000 Ollie Lho * bug fix for record mask setting * v0.2 Feb 10 2000 Ollie Lho @@ -332,9 +332,10 @@ /* else, write the first set in the mask as the output */ /* clear out current set value first (AC97 supports only 1 input!) */ - val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT)&0x07]); - if (mask != val) mask &= ~val; - + val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT) & 0x07]); + if (mask != val) + mask &= ~val; + val = ffs(mask); val = ac97_oss_rm[val-1]; val |= val << 8; /* set both channels */ @@ -423,7 +424,7 @@ switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ if (!codec->recmask_io) return -EINVAL; - if(!val) return 0; + if (!val) return 0; if (!(val &= codec->record_sources)) return -EINVAL; codec->recmask_io(codec, 0, val); @@ -449,6 +450,7 @@ { int len = 0, cap, extid, val, id1, id2; struct ac97_codec *codec; + int is_ac97_20 = 0; if ((codec = data) == NULL) return -ENODEV; @@ -462,6 +464,7 @@ extid &= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13)); len += sprintf (page+len, "AC97 Version : %s\n", extid ? "2.0 or later" : "1.0"); + if (extid) is_ac97_20 = 1; cap = codec->codec_read(codec, AC97_RESET); len += sprintf (page+len, "Capabilities :%s%s%s%s%s%s\n", @@ -500,6 +503,7 @@ val & 0x0100 ? "MIC2" : "MIC1", val & 0x0080 ? "on" : "off"); + extid = codec->codec_read(codec, AC97_EXTENDED_ID); cap = extid; len += sprintf (page+len, "Ext Capabilities :%s%s%s%s%s%s%s\n", cap & 0x0001 ? " -var rate PCM audio-" : "", @@ -509,6 +513,10 @@ cap & 0x0080 ? " -PCM surround DAC-" : "", cap & 0x0100 ? " -PCM LFE DAC-" : "", cap & 0x0200 ? " -slot/DAC mappings-" : ""); + if (is_ac97_20) { + len += sprintf (page+len, "Front DAC rate : %d\n", + codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE)); + } return len; } @@ -546,8 +554,8 @@ } if (codec->name == NULL) codec->name = "Unknown"; - printk(KERN_INFO "ac97_codec: AC97 %s codec, vendor id1: 0x%04x, " - "id2: 0x%04x (%s)\n", audio ? "Audio" : (modem ? "Modem" : ""), + printk(KERN_INFO "ac97_codec: AC97%s codec, id: 0x%04x:0x%04x (%s)\n", + audio ? " audio" : (modem ? " modem" : ""), id1, id2, codec->name); return ac97_init_mixer(codec); @@ -595,11 +603,6 @@ } return 1; -} - -static int ac97_init_modem(struct ac97_codec *codec) -{ - return 0; } static int sigmatel_init(struct ac97_codec * codec) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/awe_wave.c linux.ac/drivers/sound/awe_wave.c --- linux.vanilla/drivers/sound/awe_wave.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/awe_wave.c Sun Jun 4 22:25:51 2000 @@ -3252,7 +3252,7 @@ int removed = 0; prev = NULL; - for (p = sf->infos; p; prev = p, p = next) { + for (p = sf->infos; p; p = next) { next = p->next; if (p->type == V_ST_NORMAL && p->bank == bank && p->instr == instr) { @@ -3266,8 +3266,11 @@ sf->num_info--; removed++; kfree(p); - } + } else + prev = p; } + if (removed) + rebuild_preset_list(); return removed; } @@ -3318,7 +3321,7 @@ } break; case AWE_WR_REPLACE: - /* replace mode - remoe the instrument if it already exists */ + /* replace mode - remove the instrument if it already exists */ remove_info(sf, hdr.bank, hdr.instr); break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/cmpci.c linux.ac/drivers/sound/cmpci.c --- linux.vanilla/drivers/sound/cmpci.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/cmpci.c Tue May 30 15:24:13 2000 @@ -2321,6 +2321,8 @@ (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, pcidev)) || (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, pcidev)) || (pcidev = pci_find_device(PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, pcidev)))) { + if (pci_enable_device(pcidev)) + continue; if (pcidev->irq == 0) continue; if (!(s = kmalloc(sizeof(struct cm_state), GFP_KERNEL))) { @@ -2345,7 +2347,7 @@ init_MUTEX(&s->open_sem); spin_lock_init(&s->lock); s->magic = CM_MAGIC; - s->iobase = pcidev->resource[0].start; + s->iobase = pci_resource_start(pcidev, 0); s->iosynth = 0x388; s->iomidi = 0x330; spin_lock_init(&s->lock); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/dmasound/dmasound_awacs.c linux.ac/drivers/sound/dmasound/dmasound_awacs.c --- linux.vanilla/drivers/sound/dmasound/dmasound_awacs.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/sound/dmasound/dmasound_awacs.c Sat Jun 10 21:46:58 2000 @@ -1184,7 +1184,7 @@ } static struct timer_list beep_timer = { - NULL, NULL, 0, 0, awacs_nosound + function: awacs_nosound }; static void awacs_mksound(unsigned int hz, unsigned int ticks) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/emu10k1/main.c linux.ac/drivers/sound/emu10k1/main.c --- linux.vanilla/drivers/sound/emu10k1/main.c Thu May 25 17:38:09 2000 +++ linux.ac/drivers/sound/emu10k1/main.c Tue May 30 15:24:37 2000 @@ -622,7 +622,7 @@ pci_set_master(pci_dev); - card->iobase = pci_dev->resource[0].start; + card->iobase = pci_resource_start(pci_dev, 0); if (request_region(card->iobase, EMU10K1_EXTENT, card_names[pci_id->driver_data]) == NULL) { printk(KERN_ERR "emu10k1: IO space in use\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/es1371.c linux.ac/drivers/sound/es1371.c --- linux.vanilla/drivers/sound/es1371.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/sound/es1371.c Fri Jun 9 15:57:17 2000 @@ -168,6 +168,7 @@ #define CT5880REV_CT5880_C 0x02 #define ES1371REV_ES1371_B 0x09 #define EV1938REV_EV1938_A 0x00 +#define ES1371REV_ES1373_8 0x08 #define ES1371_MAGIC ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371) @@ -2778,7 +2779,8 @@ /* if we are a 5880 turn on the AC97 */ if (s->vendor == PCI_VENDOR_ID_ENSONIQ && ((s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 && s->rev == CT5880REV_CT5880_C) || - (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A))) { + (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_CT5880_A) || + (s->device == PCI_DEVICE_ID_ENSONIQ_ES1371 && s->rev == ES1371REV_ES1373_8))) { cssr |= CSTAT_5880_AC97_RST; outl(cssr, s->io+ES1371_REG_STATUS); /* need to delay around 20ms(bleech) to give diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/i810_audio.c linux.ac/drivers/sound/i810_audio.c --- linux.vanilla/drivers/sound/i810_audio.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/i810_audio.c Fri Jun 9 16:33:47 2000 @@ -46,6 +46,18 @@ * There is no midi support, no synth support. Use timidity. To get * esd working you need to use esd -r 48000 as it won't probe 48KHz * by default. mpg123 can't handle 48Khz only audio so use xmms. + * + * Fix The Sound On Dell + * + * Not everyone uses 48KHz. We know of no way to detect this reliably + * and certainly not to get the right data. If your i810 audio sounds + * stupid you may need to investigate other speeds. According to Analog + * they tend to use a 14.318MHz clock which gives you a base rate of + * 41194Hz. + * + * This is available via the 'ftsodell=1' option. + * + * If you need to force a specific rate set the clocking= option */ #include @@ -74,10 +86,17 @@ #ifndef PCI_DEVICE_ID_INTEL_82901 #define PCI_DEVICE_ID_INTEL_82901 0x2425 #endif +#ifndef PCI_DEVICE_ID_INTEL_ICH2 +#define PCI_DEVICE_ID_INTEL_ICH2 0x2445 +#endif #ifndef PCI_DEVICE_ID_INTEL_440MX #define PCI_DEVICE_ID_INTEL_440MX 0x7195 #endif +static int ftsodell=0; +static int clocking=48000; + + #define ADC_RUNNING 1 #define DAC_RUNNING 2 @@ -180,13 +199,15 @@ enum { ICH82801AA = 0, ICH82901AB, - INTEL440MX + INTEL440MX, + INTELICH2, }; static char * card_names[] = { "Intel ICH 82801AA", "Intel ICH 82901AB", - "Intel 440MX" + "Intel 440MX", + "Intel ICH2" }; static struct pci_device_id i810_pci_tbl [] __initdata = { @@ -196,6 +217,8 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2}, {0,} }; @@ -363,12 +386,24 @@ struct ac97_codec *codec=state->card->ac97_codec[0]; if(!(state->card->ac97_features&0x0001)) - return 48000; + return clocking; if (rate > 48000) rate = 48000; - if (rate < 4000) - rate = 4000; + if (rate < 8000) + rate = 8000; + + /* + * Adjust for misclocked crap + */ + + rate = ( rate * clocking)/48000; + + /* Analog codecs can go lower via magic registers but others + might not */ + + if(rate < 8000) + rate = 8000; /* Power down the DAC */ dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); @@ -378,10 +413,10 @@ i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate); rp=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE); - printk("DAC rate set to %d Returned %d\n", - rate, (int)rp); +// printk("DAC rate set to %d Returned %d\n", +// rate, (int)rp); - rate=rp; + rate=(rp * 48000) / clocking; /* Power it back up */ i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); @@ -406,21 +441,34 @@ if (rate > 48000) rate = 48000; - if (rate < 4000) - rate = 4000; + if (rate < 8000) + rate = 8000; + + /* + * Adjust for misclocked crap + */ + + rate = ( rate * clocking)/48000; + + /* Analog codecs can go lower via magic registers but others + might not */ + + if(rate < 8000) + rate = 8000; + /* Power down the ADC */ dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100); /* Load the rate and read the effective rate */ - i810_ac97_set(codec, AC97_PCM_LR_ADC_RATE, rate); - rp=i810_ac97_get(codec, AC97_PCM_LR_ADC_RATE); + i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate); + rp=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE); - printk("ADC rate set to %d Returned %d\n", - rate, (int)rp); +// printk("ADC rate set to %d Returned %d\n", +// rate, (int)rp); - rate=rp; + rate = (rp * 48000) / clocking; /* Power it back up */ i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); @@ -1828,8 +1876,11 @@ kfree(card); } + MODULE_AUTHOR(""); MODULE_DESCRIPTION("Intel 810 audio support"); +MODULE_PARM(ftsodell, "i"); +MODULE_PARM(clocking, "i"); #define I810_MODULE_NAME "intel810_audio" @@ -1845,6 +1896,9 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; + if(ftsodell=1) + clocking=41194; + printk(KERN_INFO "Intel 810 + AC97 Audio, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/maestro.c linux.ac/drivers/sound/maestro.c --- linux.vanilla/drivers/sound/maestro.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/maestro.c Sat May 27 15:44:24 2000 @@ -3447,11 +3447,7 @@ return 1; } -#ifdef MODULE -int init_module(void) -#else -int SILLY_MAKE_INIT(init_maestro(void)) -#endif +int __init init_maestro(void) { struct pci_dev *pcidev = NULL; int foundone = 0; @@ -3558,8 +3554,6 @@ nuke_maestros(); } -#else /* MODULE */ -__initcall(init_maestro); #endif /* --------------------------------------------------------------------- */ @@ -3718,3 +3712,5 @@ out: return 0; } + +module_init(init_maestro); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/pas2_mixer.c linux.ac/drivers/sound/pas2_mixer.c --- linux.vanilla/drivers/sound/pas2_mixer.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/sound/pas2_mixer.c Fri Jun 9 15:58:46 2000 @@ -69,7 +69,7 @@ if (pas_model == 4) { - outw(data | (data << 8), (ioaddr ^ translate_code) - 1); + outw(data | (data << 8), (ioaddr + translate_code) - 1); outb((0x80), 0); } else pas_write(data, ioaddr); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/sb_card.c linux.ac/drivers/sound/sb_card.c --- linux.vanilla/drivers/sound/sb_card.c Thu May 25 17:38:07 2000 +++ linux.ac/drivers/sound/sb_card.c Mon Jun 5 19:57:16 2000 @@ -42,6 +42,9 @@ * * 06-05-2000 added another card. Daniel M. Newman * + * 25-05-2000 Added Creative SB AWE64 Gold (CTL00B2). + * Pĺl-Kristian Engstad + * */ #include @@ -265,6 +268,11 @@ 0,0,0,0, 0,1,1,-1}, {"Sound Blaster 16", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), + 0,0,0,0, + 0,1,1,-1}, + {"Sound Blaster 16", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0,0,0,0, @@ -341,6 +349,11 @@ 0,1,1,-1}, {"Sound Blaster AWE 64 Gold", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), + 0,0,0,0, + 0,1,1,-1}, + {"Sound Blaster AWE 64 Gold", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0,0,0,0, 0,1,1,-1}, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/skeleton.c linux.ac/drivers/sound/skeleton.c --- linux.vanilla/drivers/sound/skeleton.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/skeleton.c Sat May 27 15:25:29 2000 @@ -78,9 +78,9 @@ * For the example we will only initialise the MSS */ - iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; - mssbase = pcidev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK; - mpubase = pcidev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK; + iobase = pci_resource_start(pcidev, 0); + mssbase = pci_resource_start(pcidev, 1); + mpubase = pci_resource_start(pcidev, 2); /* * Reset the board @@ -160,6 +160,8 @@ while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL) { + if (pci_enable_device(pcidev)) + continue; count+=mycard_install(pcidev); if(count) return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/trident.c linux.ac/drivers/sound/trident.c --- linux.vanilla/drivers/sound/trident.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/trident.c Tue May 30 15:24:37 2000 @@ -29,10 +29,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History - * v0.14.3 May 20 2000 Aaron Holtzman - * Fix kfree'd memory access in release - * Fix race in open while looking for a free virtual channel slot - * remove open_wait wq (which appears to be unused) + * v0.14.5 May 23 2000 Ollie Lho + * Misc bug fix from the Net + * v0.14.4 May 20 2000 Aaron Holtzman + * Fix kfree'd memory access in release + * Fix race in open while looking for a free virtual channel slot + * remove open_wait wq (which appears to be unused) + * v0.14.3 May 10 2000 Ollie Lho + * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU * v0.14.2 Mar 29 2000 Ching Ling Lee * Add clear to silence advance in trident_update_ptr * fix invalid data of the end of the sound @@ -109,13 +113,13 @@ #include "trident.h" -#define DRIVER_VERSION "0.14" +#define DRIVER_VERSION "0.14.5" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ -#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ +#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ #define NR_HW_CH 32 @@ -151,7 +155,7 @@ "ALi Audio Accelerator" }; -static struct pci_device_id trident_pci_tbl [] __initdata = { +static struct pci_device_id trident_pci_tbl [] __devinitdata = { {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, @@ -438,16 +442,14 @@ #endif } -static u32 trident_get_interrupt_mask (struct trident_card * card, - unsigned int b) +static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel) { - struct trident_pcm_bank *bank = &card->banks[b]; + struct trident_pcm_bank *bank = &card->banks[channel]; u32 addr = bank->addresses->aint; return inl(TRID_REG(card, addr)); } -static int trident_check_channel_interrupt(struct trident_card * card, - unsigned int channel) +static int trident_check_channel_interrupt(struct trident_card * card, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); u32 reg = trident_get_interrupt_mask (card, channel >> 5); @@ -460,8 +462,7 @@ return (reg & mask) ? TRUE : FALSE; } -static void trident_ack_channel_interrupt(struct trident_card * card, - unsigned int channel) +static void trident_ack_channel_interrupt(struct trident_card * card, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); struct trident_pcm_bank *bank = &card->banks[channel >> 5]; @@ -537,8 +538,7 @@ } -static void trident_free_pcm_channel(struct trident_card *card, - unsigned int channel) +static void trident_free_pcm_channel(struct trident_card *card, int channel) { int bank; @@ -551,7 +551,7 @@ card->banks[bank].bitmap &= ~(1 << (channel)); } -static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel) +static void ali_free_pcm_channel(struct trident_card *card, int channel) { int bank; @@ -574,18 +574,16 @@ if (channel > 63) return FALSE; - /* select hardware channel to write */ + /* select hardware channel to write */ outb(channel, TRID_REG(card, T4D_LFO_GC_CIR)); /* Output the channel registers, but don't write register three to an ALI chip. */ - for (i = 0; i < CHANNEL_REGS; i++) { if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451) continue; outl(data[i], TRID_REG(card, CHANNEL_START + 4*i)); } - return TRUE; } @@ -1141,7 +1139,7 @@ dmabuf->hwptr = hwptr; dmabuf->total_bytes += diff; - /* error handling and process wake up for DAC */ + /* error handling and process wake up for ADC */ if (dmabuf->enable == ADC_RUNNING) { if (dmabuf->mapped) { dmabuf->count -= diff; @@ -1171,7 +1169,10 @@ //there is invalid data in the end of half buffer if ((clear_cnt = half_dmasize - swptr) < 0) clear_cnt += half_dmasize; - memset (dmabuf->rawbuf + swptr, silence, clear_cnt); //clear the invalid data + //clear the invalid data + memset (dmabuf->rawbuf + swptr, + silence, clear_cnt); + dmabuf->endcleared = 1; } } else if (dmabuf->count < (signed) dmabuf->fragsize) { @@ -1181,12 +1182,15 @@ memset (dmabuf->rawbuf + swptr, silence, clear_cnt); dmabuf->endcleared = 1; } - } - /* since dma machine only interrupts at ESO and ESO/2, we sure have at - least half of dma buffer free, so wake up the process unconditionally */ - wake_up(&dmabuf->wait); + } + /* trident_update_ptr is called by interrupt handler or by process via + ioctl/poll, we only wake up the waiting process when we have more + than 1/2 buffer of data to process (always true for interrupt handler) */ + if (dmabuf->count > (signed)dmabuf->dmasize/2) + wake_up(&dmabuf->wait); } } + /* error handling and process wake up for DAC */ if (dmabuf->enable == DAC_RUNNING) { if (dmabuf->mapped) { @@ -1203,9 +1207,11 @@ __stop_dac(state); dmabuf->error++; } - /* since dma machine only interrupts at ESO and ESO/2, we sure have at - least half of dma buffer free, so wake up the process unconditionally */ - wake_up(&dmabuf->wait); + /* trident_update_ptr is called by interrupt handler or by process via + ioctl/poll, we only wake up the waiting process when we have more + than 1/2 buffer free (always true for interrupt handler) */ + if (dmabuf->count < (signed)dmabuf->dmasize/2) + wake_up(&dmabuf->wait); } } dmabuf->update_flag &= ~ALI_ADDRESS_INT_UPDATE; @@ -1336,7 +1342,8 @@ ret = 0; if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) - outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) | ALI_PCM_IN_ENABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL)); + outl(inl(TRID_REG (state->card, ALI_GLOBAL_CONTROL)) | ALI_PCM_IN_ENABLE, + TRID_REG (state->card, ALI_GLOBAL_CONTROL)); while (count > 0) { spin_lock_irqsave(&state->card->lock, flags); @@ -1439,7 +1446,8 @@ if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451) if (dmabuf->channel->num == ALI_PCM_IN_CHANNEL) - outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) & ALI_PCM_IN_DISABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL)); + outl ( inl (TRID_REG (state->card, ALI_GLOBAL_CONTROL)) & + ALI_PCM_IN_DISABLE, TRID_REG (state->card, ALI_GLOBAL_CONTROL)); while (count > 0) { spin_lock_irqsave(&state->card->lock, flags); @@ -1905,6 +1913,7 @@ struct trident_state *state = NULL; struct dmabuf *dmabuf = NULL; + MOD_INC_USE_COUNT; /* find an avaiable virtual channel (instance of /dev/dsp) */ while (card != NULL) { down(&card->open_sem); @@ -1912,8 +1921,10 @@ if (card->states[i] == NULL) { state = card->states[i] = (struct trident_state *) kmalloc(sizeof(struct trident_state), GFP_KERNEL); - if (state == NULL) + if (state == NULL) { + MOD_DEC_USE_COUNT; return -ENOMEM; + } memset(state, 0, sizeof(struct trident_state)); dmabuf = &state->dmabuf; goto found_virt; @@ -1923,9 +1934,10 @@ card = card->next; } /* no more virtual channel avaiable */ - if (!state) + if (!state) { + MOD_DEC_USE_COUNT; return -ENODEV; - + } found_virt: /* found a free virtual channel, allocate hardware channels */ if(file->f_mode & FMODE_READ) @@ -1936,6 +1948,7 @@ if (dmabuf->channel == NULL) { kfree (card->states[i]); card->states[i] = NULL; + MOD_DEC_USE_COUNT; return -ENODEV; } @@ -1946,7 +1959,6 @@ init_waitqueue_head(&dmabuf->wait); file->private_data = state; - /* set default sample format. According to OSS Programmer's Guide /dev/dsp should be default to unsigned 8-bits, mono, with sample rate 8kHz and /dev/dspW will accept 16-bits sample */ @@ -1991,11 +2003,10 @@ up(&card->open_sem); #ifdef DEBUG - printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", - state->virt, - dmabuf->channel->num); + printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", + state->virt, dmabuf->channel->num); #endif - MOD_INC_USE_COUNT; + return 0; } @@ -2020,7 +2031,6 @@ dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } - if (file->f_mode & FMODE_READ) { stop_adc(state); dealloc_dmabuf(state); @@ -2255,19 +2265,21 @@ int minor = MINOR(inode->i_rdev); struct trident_card *card = devs; + MOD_INC_USE_COUNT; for (card = devs; card != NULL; card = card->next) for (i = 0; i < NR_AC97; i++) if (card->ac97_codec[i] != NULL && card->ac97_codec[i]->dev_mixer == minor) goto match; - if (!card) + if (!card) { + MOD_DEC_USE_COUNT; return -ENODEV; - + } match: file->private_data = card->ac97_codec[i]; - MOD_INC_USE_COUNT; + return 0; } @@ -2385,7 +2397,7 @@ } pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); - iobase = pci_resource_start (pci_dev, 0); + iobase = pci_resource_start(pci_dev, 0); if (check_region(iobase, 256)) { printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n", iobase); @@ -2393,7 +2405,7 @@ } if (pci_enable_device(pci_dev)) - return -ENODEV; + return -ENODEV; if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) { printk(KERN_ERR "trident: out of memory\n"); @@ -2421,20 +2433,19 @@ printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", card_names[pci_id->driver_data], card->iobase, card->irq); - if(card->pci_id == PCI_DEVICE_ID_ALI_5451) - { + if(card->pci_id == PCI_DEVICE_ID_ALI_5451) { card->alloc_pcm_channel = ali_alloc_pcm_channel; card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel; card->free_pcm_channel = ali_free_pcm_channel; card->address_interrupt = ali_address_interrupt; } - else - { + else { card->alloc_pcm_channel = trident_alloc_pcm_channel; card->alloc_rec_pcm_channel = trident_alloc_pcm_channel; card->free_pcm_channel = trident_free_pcm_channel; card->address_interrupt = trident_address_interrupt; } + /* claim our iospace and irq */ request_region(card->iobase, 256, card_names[pci_id->driver_data]); if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, @@ -2462,12 +2473,12 @@ } outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); - if (card->pci_id == PCI_DEVICE_ID_ALI_5451) - { + if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { /* edited by HMSEO for GT sound */ #ifdef CONFIG_ALPHA_NAUTILUS ac97_data = trident_ac97_get (card->ac97_codec[0], AC97_POWER_CONTROL); - trident_ac97_set (card->ac97_codec[0], AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN); + trident_ac97_set (card->ac97_codec[0], AC97_POWER_CONTROL, + ac97_data | ALI_EAPD_POWER_DOWN); #endif /* edited by HMSEO for GT sound*/ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/via82cxxx_audio.c linux.ac/drivers/sound/via82cxxx_audio.c --- linux.vanilla/drivers/sound/via82cxxx_audio.c Thu May 25 17:38:08 2000 +++ linux.ac/drivers/sound/via82cxxx_audio.c Thu Jun 8 15:01:35 2000 @@ -6,12 +6,16 @@ * See the "COPYING" file distributed with this software for more info. * * For a list of known bugs (errata) and documentation, - * see via82cxxx.txt in linux/Documentation/sound. + * see via-audio.pdf in linux/Documentation/DocBook. + * If this documentation does not exist, run "make pdfdocs". + * If "make pdfdocs" fails, obtain the documentation from + * the driver's Website at + * http://gtf.org/garzik/drivers/via82cxxx/ * */ -#define VIA_VERSION "1.1.6" +#define VIA_VERSION "1.1.8" #include @@ -304,7 +308,7 @@ static struct pci_device_id via_pci_tbl[] __initdata = { - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; MODULE_DEVICE_TABLE(pci,via_pci_tbl); @@ -325,12 +329,40 @@ * */ +/** + * via_chan_stop - Terminate DMA on specified PCM channel + * @iobase: PCI base address for SGD channel registers + * + * Terminate scatter-gather DMA operation for given + * channel (derived from @iobase), if DMA is active. + * + * Note that @iobase is not the PCI base address, + * but the PCI base address plus an offset to + * one of three PCM channels supported by the chip. + * + */ + static inline void via_chan_stop (int iobase) { if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE) outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL); } + +/** + * via_chan_status_clear - Clear status flags on specified DMA channel + * @iobase: PCI base address for SGD channel registers + * + * Clear any pending status flags for the given + * DMA channel (derived from @iobase), if any + * flags are asserted. + * + * Note that @iobase is not the PCI base address, + * but the PCI base address plus an offset to + * one of three PCM channels supported by the chip. + * + */ + static inline void via_chan_status_clear (int iobase) { u8 tmp = inb (iobase + VIA_PCM_STATUS); @@ -339,12 +371,33 @@ outb (tmp, iobase + VIA_PCM_STATUS); } + +/** + * sg_begin - Begin recording or playback on a PCM channel + * @chan: Channel for which DMA operation shall begin + * + * Start scatter-gather DMA for the given channel. + * + */ + static inline void sg_begin (struct via_channel *chan) { outb (VIA_SGD_START, chan->iobase + VIA_PCM_CONTROL); } +/** + * via_chan_bufs_in_use - Number of buffers waiting to be consumed + * @chan: Channel for which DMA buffers will be counted + * + * Count the number of buffers waiting to be consumed. For a + * playback operation, this is the number of buffers which have + * yet to be sent to the DAC. For a recording operation, this + * is the number of buffers waiting to be consumed by software + * calling read() system call. + * + */ + static inline int via_chan_bufs_in_use (struct via_channel *chan) { return atomic_read(&chan->next_buf) - @@ -352,12 +405,31 @@ } +/** + * via_chan_full - Check for no-free-buffers condition + * @chan: Channel for which DMA full condition will be checked + * + * Count the number of buffers waiting to be consumed, and return + * true (non-zero) if no buffers are available to be filled on the + * given DMA channel. + * + */ + static inline int via_chan_full (struct via_channel *chan) { return (via_chan_bufs_in_use (chan) == VIA_DMA_BUFFERS); } +/** + * via_chan_empty - Check for no-buffers-in-use condition + * @chan: Channel for which DMA empty condition will be checked + * + * Count the number of buffers waiting to be consumed, and return + * true (non-zero) if no buffers are currently in use. + * + */ + static inline int via_chan_empty (struct via_channel *chan) { return (atomic_read(&chan->next_buf) == @@ -372,6 +444,15 @@ * */ + +/** + * via_stop_everything - Stop all audio operations + * @card: Private info for specified board + * + * Stops all DMA operations and interrupts, and clear + * any pending status bits resulting from those operations. + */ + static void via_stop_everything (struct via_info *card) { DPRINTK ("ENTER\n"); @@ -402,6 +483,24 @@ } +/** + * via_set_rate - Set PCM rate for given channel + * @card: Private info for specified board + * @rate: Desired PCM sample rate, in Khz + * @inhale_deeply: Boolean. If non-zero (true), the recording sample rate + * is set. If zero (false), the playback sample rate + * is set. + * + * Sets the PCM sample rate for a channel. + * + * Values for @rate are clamped to a range of 4000 Khz through 48000 Khz, + * due to hardware constraints. + * + * FIXME: @inhale_deeply argument is ignored, and %AC97_PCM_FRONT_DAC_RATE + * is the only rate which is really set. This needs to be fixed when + * recording support is added. + */ + static int via_set_rate (struct via_info *card, unsigned rate, int inhale_deeply) { @@ -423,12 +522,32 @@ } +/** + * via_set_adc_rate - Set PCM rate for recording channel + * @card: Private info for specified board + * @rate: Desired PCM sample rate, in Khz + * + * Sets the PCM sample rate for a recording channel. + * + * FIXME: @inhale_deeply argument to via_set_rate is ignored, and %AC97_PCM_FRONT_DAC_RATE + * is the only rate which is really set. Thus, this function will + * not work until via_set_rate is fixed. + */ + static inline int via_set_adc_rate (struct via_info *card, int rate) { return via_set_rate (card, rate, 1); } +/** + * via_set_dac_rate - Set PCM rate for playback channel + * @card: Private info for specified board + * @rate: Desired PCM sample rate, in Khz + * + * Sets the PCM sample rate for a playback channel. + */ + static inline int via_set_dac_rate (struct via_info *card, int rate) { return via_set_rate (card, rate, 0); @@ -442,6 +561,27 @@ * */ +/** + * via_chan_init - Initialize PCM channel + * @card: Private audio chip info + * @chan: Channel to be initialized + * @chan_ofs: Offset from PCI address, which determines the + * set of SGD registers to use. + * + * Performs all the preparations necessary to begin + * using a PCM channel. + * + * Currently the preparations include allocating the + * scatter-gather DMA table and buffers, setting the + * PCM channel to a known state, and passing the + * address of the DMA table to the hardware. + * + * Note that special care is taken when passing the + * DMA table address to hardware, because it was found + * during driver development that the hardware did not + * always "take" the address. + */ + static int via_chan_init (struct via_info *card, struct via_channel *chan, long chan_ofs) { @@ -533,6 +673,20 @@ } +/** + * via_chan_free - Release a PCM channel + * @card: Private audio chip info + * @chan: Channel to be released + * + * Performs all the functions necessary to clean up + * an initialized channel. + * + * Currently these functions include disabled any + * active DMA operations, setting the PCM channel + * back to a known state, and releasing any allocated + * sound buffers. + */ + static void via_chan_free (struct via_info *card, struct via_channel *chan) { int i; @@ -575,6 +729,22 @@ } +/** + * via_chan_pcm_fmt - Update PCM channel settings + * @card: Private audio chip info + * @chan: Channel to be updated + * @reset: Boolean. If non-zero, channel will be reset + * to 8-bit mono mode. + * + * Stores the settings of the current PCM format, + * 8-bit or 16-bit, and mono/stereo, into the + * hardware settings for the specified channel. + * If @reset is non-zero, the channel is reset + * to 8-bit mono mode. Otherwise, the channel + * is set to the values stored in the channel + * information struct @chan. + */ + static void via_chan_pcm_fmt (struct via_info *card, struct via_channel *chan, int reset) { @@ -603,6 +773,14 @@ } +/** + * via_chan_clear - Stop DMA channel operation, and reset pointers + * @chan: Channel to be cleared + * + * Call via_chan_stop to halt DMA operations, and then resets + * all software pointers which track DMA operation. + */ + static void via_chan_clear (struct via_channel *chan) { via_chan_stop (chan->iobase); @@ -612,6 +790,21 @@ } +/** + * via_chan_set_speed - Set PCM sample rate for given channel + * @card: Private info for specified board + * @chan: Channel whose sample rate will be adjusted + * @val: New sample rate, in Khz + * + * Helper function for the %SNDCTL_DSP_SPEED ioctl. OSS semantics + * demand that all audio operations halt (if they are not already + * halted) when the %SNDCTL_DSP_SPEED is given. + * + * This function halts all audio operations for the given channel + * @chan, and then calls via_set_rate to set the audio hardware + * to the new rate. + */ + static int via_chan_set_speed (struct via_info *card, struct via_channel *chan, int val) { @@ -626,6 +819,21 @@ } +/** + * via_chan_set_fmt - Set PCM sample size for given channel + * @card: Private info for specified board + * @chan: Channel whose sample size will be adjusted + * @val: New sample size, use the %AFMT_xxx constants + * + * Helper function for the %SNDCTL_DSP_SETFMT ioctl. OSS semantics + * demand that all audio operations halt (if they are not already + * halted) when the %SNDCTL_DSP_SETFMT is given. + * + * This function halts all audio operations for the given channel + * @chan, and then calls via_chan_pcm_fmt to set the audio hardware + * to the new sample size, either 8-bit or 16-bit. + */ + static int via_chan_set_fmt (struct via_info *card, struct via_channel *chan, int val) { @@ -656,6 +864,21 @@ } +/** + * via_chan_set_stereo - Enable or disable stereo for a DMA channel + * @card: Private info for specified board + * @chan: Channel whose stereo setting will be adjusted + * @val: New sample size, use the %AFMT_xxx constants + * + * Helper function for the %SNDCTL_DSP_CHANNELS and %SNDCTL_DSP_STEREO ioctls. OSS semantics + * demand that all audio operations halt (if they are not already + * halted) when %SNDCTL_DSP_CHANNELS or SNDCTL_DSP_STEREO is given. + * + * This function halts all audio operations for the given channel + * @chan, and then calls via_chan_pcm_fmt to set the audio hardware + * to enable or disable stereo. + */ + static int via_chan_set_stereo (struct via_info *card, struct via_channel *chan, int val) { @@ -690,6 +913,14 @@ #if 0 +/** + * via_chan_dump_bufs - Display DMA table contents + * @chan: Channel whose DMA table will be displayed + * + * Debugging function which displays the contents of the + * scatter-gather DMA table for the given channel @chan. + */ + static void via_chan_dump_bufs (struct via_channel *chan) { int i; @@ -715,6 +946,15 @@ * */ +/** + * via_ac97_wait_idle - Wait until AC97 codec is not busy + * @card: Private info for specified board + * + * Sleep until the AC97 codec is no longer busy. + * Returns the final value read from the SGD + * register being polled. + */ + static u8 via_ac97_wait_idle (struct via_info *card) { u8 tmp8; @@ -740,6 +980,21 @@ } +/** + * via_ac97_read_reg - Read AC97 standard register + * @codec: Pointer to generic AC97 codec info + * @reg: Index of AC97 register to be read + * + * Read the value of a single AC97 codec register, + * as defined by the Intel AC97 specification. + * + * Defines the standard AC97 read-register operation + * required by the kernel's ac97_codec interface. + * + * Returns the 16-bit value stored in the specified + * register. + */ + static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg) { u32 data; @@ -788,6 +1043,19 @@ } +/** + * via_ac97_write_reg - Write AC97 standard register + * @codec: Pointer to generic AC97 codec info + * @reg: Index of AC97 register to be written + * @value: Value to be written to AC97 register + * + * Write the value of a single AC97 codec register, + * as defined by the Intel AC97 specification. + * + * Defines the standard AC97 write-register operation + * required by the kernel's ac97_codec interface. + */ + static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value) { u32 data; @@ -971,9 +1239,11 @@ VIA_CR41_VRA | VIA_CR41_AC97_RESET); udelay (100); +#if 0 /* this breaks on K7M */ /* disable legacy stuff */ pci_write_config_byte (pdev, 0x42, 0x00); udelay(10); +#endif /* route FM trap to IRQ, disable FM trap */ pci_write_config_byte (pdev, 0x48, 0x05); @@ -1097,50 +1367,36 @@ struct via_info *card = dev_id; struct via_channel *chan; u8 status; - int unhandled = 1; - static long intcount = 0; - assert (irq == card->pdev->irq); - - intcount++; - status = inb (card->baseaddr + 0x00); if (status) { assert (card->open_mode & FMODE_WRITE); chan = &card->ch_out; - unhandled = 0; if (status & VIA_SGD_FLAG) { assert ((status & VIA_SGD_EOL) == 0); outb (VIA_SGD_FLAG, chan->iobase + 0x00); - DPRINTK("FLAG intr, status=0x%02X, intcount=%ld\n", - status, intcount); + DPRINTK("FLAG intr, status=0x%02X\n", status); via_interrupt_write (chan); } if (status & VIA_SGD_EOL) { assert ((status & VIA_SGD_FLAG) == 0); outb (VIA_SGD_EOL, chan->iobase + 0x00); - DPRINTK("EOL intr, status=0x%02X, intcount=%ld\n", - status, intcount); + DPRINTK("EOL intr, status=0x%02X\n", status); via_interrupt_write (chan); } if (status & VIA_SGD_STOPPED) { outb (VIA_SGD_STOPPED, chan->iobase + 0x00); - DPRINTK("STOPPED intr, status=0x%02X, intcount=%ld\n", - status, intcount); + DPRINTK("STOPPED intr, status=0x%02X\n", status); } #if 0 via_chan_dump_bufs (&card->ch_out); #endif } - - if (unhandled) - printk (KERN_WARNING PFX "unhandled interrupt, st=%02x, st32=%08x\n", - status, inl (card->baseaddr + 0x84)); } @@ -2331,6 +2587,7 @@ via_interrupt_cleanup (card); via_card_cleanup_proc (card); via_dsp_cleanup (card); + via_ac97_cleanup (card); release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/sound/ymf_sb.c linux.ac/drivers/sound/ymf_sb.c --- linux.vanilla/drivers/sound/ymf_sb.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/sound/ymf_sb.c Sun Jun 4 21:41:18 2000 @@ -0,0 +1,867 @@ +/* + Legacy audio driver for YMF724, 740, 744, 754 series. + Copyright 2000 Daisuke Nagano + + Based on the VIA 82Cxxx driver by Jeff Garzik + And ported to 2.3.x by Jeff Garzik too :) My it is a small world. + + Distribued under the GNU PUBLIC LICENSE (GPL) Version 2. + See the "COPYING" file distributed with kernel source tree for more info. + + ------------------------------------------------------------------------- + + It only supports SBPro compatible function of YMF7xx series s.t. + * 22.05kHz, 8-bit and stereo sample + * OPL3-compatible FM synthesizer + * MPU-401 compatible "external" MIDI interface + + ------------------------------------------------------------------------- + + Revision history + + Tue May 14 19:00:00 2000 0.0.1 + * initial release + + Tue May 16 19:29:29 2000 0.0.2 + + * add a little delays for reset devices. + * fixed addressing bug. + + Sun May 21 15:14:37 2000 0.0.3 + + * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97. + * remove native UART401 support. External MIDI port should be supported + by sb_midi driver. + * add support for SPDIF OUT. Module parameter 'spdif_out' is now available. + + Wed May 31 00:13:57 2000 0.0.4 + + * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions + in 724hwmcode.h. + * fixed wrong legacy_io setting on YMF744/YMF754 . + + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sound_config.h" +#include "soundmodule.h" +#include "sb.h" + +#include "724hwmcode.h" + +#undef YMF_DEBUG +#define SUPPORT_UART401_MIDI 1 + +/* ---------------------------------------------------------------------- */ + +#ifndef SOUND_LOCK +#define SOUND_LOCK do {} while (0) +#define SOUND_LOCK_END do {} while (0) +#endif + +#ifndef PCI_VENDOR_ID_YAMAHA +#define PCI_VENDOR_ID_YAMAHA 0x1073 +#endif +#ifndef PCI_DEVICE_ID_YMF724 +#define PCI_DEVICE_ID_YMF724 0x0004 +#endif +#ifndef PCI_DEVICE_ID_YMF740 +#define PCI_DEVICE_ID_YMF740 0x000A +#endif +#ifndef PCI_DEVICE_ID_YMF740C +#define PCI_DEVICE_ID_YMF740C 0x000C +#endif +#ifndef PCI_DEVICE_ID_YMF724F +#define PCI_DEVICE_ID_YMF724F 0x000D +#endif +#ifndef PCI_DEVICE_ID_YMF744 +#define PCI_DEVICE_ID_YMF744 0x0010 +#endif +#ifndef PCI_DEVICE_ID_YMF754 +#define PCI_DEVICE_ID_YMF754 0x0012 +#endif + +/* ---------------------------------------------------------------------- */ + +#define YMFSB_RESET_DELAY 5 + +#define YMFSB_REGSIZE 0x8000 + +#define YMFSB_AC97TIMEOUT 2000 + +#define YMFSB_WORKBITTIMEOUT 250000 + +#define YMFSB_DSPLENGTH 0x0080 +#define YMFSB_CTRLLENGTH 0x3000 + +#define YMFSB_PCIR_VENDORID 0x00 +#define YMFSB_PCIR_DEVICEID 0x02 +#define YMFSB_PCIR_CMD 0x04 +#define YMFSB_PCIR_REVISIONID 0x08 +#define YMFSB_PCIR_BASEADDR 0x10 +#define YMFSB_PCIR_IRQ 0x3c + +#define YMFSB_PCIR_LEGCTRL 0x40 +#define YMFSB_PCIR_ELEGCTRL 0x42 +#define YMFSB_PCIR_DSXGCTRL 0x48 +#define YMFSB_PCIR_OPLADR 0x60 +#define YMFSB_PCIR_SBADR 0x62 +#define YMFSB_PCIR_MPUADR 0x64 + +#define YMFSB_INTFLAG 0x0004 +#define YMFSB_ACTIVITY 0x0006 +#define YMFSB_GLOBALCTRL 0x0008 +#define YMFSB_ZVCTRL 0x000A +#define YMFSB_TIMERCTRL 0x0010 +#define YMFSB_TIMERCOUNT 0x0012 +#define YMFSB_SPDIFOUTCTRL 0x0018 +#define YMFSB_SPDIFOUTSTATUS 0x001C +#define YMFSB_EEPROMCTRL 0x0020 +#define YMFSB_SPDIFINCTRL 0x0034 +#define YMFSB_SPDIFINSTATUS 0x0038 +#define YMFSB_DSPPROGRAMDL 0x0048 +#define YMFSB_DLCNTRL 0x004C +#define YMFSB_GPIOININTFLAG 0x0050 +#define YMFSB_GPIOININTENABLE 0x0052 +#define YMFSB_GPIOINSTATUS 0x0054 +#define YMFSB_GPIOOUTCTRL 0x0056 +#define YMFSB_GPIOFUNCENABLE 0x0058 +#define YMFSB_GPIOTYPECONFIG 0x005A +#define YMFSB_AC97CMDDATA 0x0060 +#define YMFSB_AC97CMDADR 0x0062 +#define YMFSB_PRISTATUSDATA 0x0064 +#define YMFSB_PRISTATUSADR 0x0066 +#define YMFSB_SECSTATUSDATA 0x0068 +#define YMFSB_SECSTATUSADR 0x006A +#define YMFSB_SECCONFIG 0x0070 +#define YMFSB_LEGACYOUTVOL 0x0080 +#define YMFSB_LEGACYOUTVOLL 0x0080 +#define YMFSB_LEGACYOUTVOLR 0x0082 +#define YMFSB_NATIVEDACOUTVOL 0x0084 +#define YMFSB_NATIVEDACOUTVOLL 0x0084 +#define YMFSB_NATIVEDACOUTVOLR 0x0086 +#define YMFSB_SPDIFOUTVOL 0x0088 +#define YMFSB_SPDIFOUTVOLL 0x0088 +#define YMFSB_SPDIFOUTVOLR 0x008A +#define YMFSB_AC3OUTVOL 0x008C +#define YMFSB_AC3OUTVOLL 0x008C +#define YMFSB_AC3OUTVOLR 0x008E +#define YMFSB_PRIADCOUTVOL 0x0090 +#define YMFSB_PRIADCOUTVOLL 0x0090 +#define YMFSB_PRIADCOUTVOLR 0x0092 +#define YMFSB_LEGACYLOOPVOL 0x0094 +#define YMFSB_LEGACYLOOPVOLL 0x0094 +#define YMFSB_LEGACYLOOPVOLR 0x0096 +#define YMFSB_NATIVEDACLOOPVOL 0x0098 +#define YMFSB_NATIVEDACLOOPVOLL 0x0098 +#define YMFSB_NATIVEDACLOOPVOLR 0x009A +#define YMFSB_SPDIFLOOPVOL 0x009C +#define YMFSB_SPDIFLOOPVOLL 0x009E +#define YMFSB_SPDIFLOOPVOLR 0x009E +#define YMFSB_AC3LOOPVOL 0x00A0 +#define YMFSB_AC3LOOPVOLL 0x00A0 +#define YMFSB_AC3LOOPVOLR 0x00A2 +#define YMFSB_PRIADCLOOPVOL 0x00A4 +#define YMFSB_PRIADCLOOPVOLL 0x00A4 +#define YMFSB_PRIADCLOOPVOLR 0x00A6 +#define YMFSB_NATIVEADCINVOL 0x00A8 +#define YMFSB_NATIVEADCINVOLL 0x00A8 +#define YMFSB_NATIVEADCINVOLR 0x00AA +#define YMFSB_NATIVEDACINVOL 0x00AC +#define YMFSB_NATIVEDACINVOLL 0x00AC +#define YMFSB_NATIVEDACINVOLR 0x00AE +#define YMFSB_BUF441OUTVOL 0x00B0 +#define YMFSB_BUF441OUTVOLL 0x00B0 +#define YMFSB_BUF441OUTVOLR 0x00B2 +#define YMFSB_BUF441LOOPVOL 0x00B4 +#define YMFSB_BUF441LOOPVOLL 0x00B4 +#define YMFSB_BUF441LOOPVOLR 0x00B6 +#define YMFSB_SPDIFOUTVOL2 0x00B8 +#define YMFSB_SPDIFOUTVOL2L 0x00B8 +#define YMFSB_SPDIFOUTVOL2R 0x00BA +#define YMFSB_SPDIFLOOPVOL2 0x00BC +#define YMFSB_SPDIFLOOPVOL2L 0x00BC +#define YMFSB_SPDIFLOOPVOL2R 0x00BE +#define YMFSB_ADCSLOTSR 0x00C0 +#define YMFSB_RECSLOTSR 0x00C4 +#define YMFSB_ADCFORMAT 0x00C8 +#define YMFSB_RECFORMAT 0x00CC +#define YMFSB_P44SLOTSR 0x00D0 +#define YMFSB_STATUS 0x0100 +#define YMFSB_CTRLSELECT 0x0104 +#define YMFSB_MODE 0x0108 +#define YMFSB_SAMPLECOUNT 0x010C +#define YMFSB_NUMOFSAMPLES 0x0110 +#define YMFSB_CONFIG 0x0114 +#define YMFSB_PLAYCTRLSIZE 0x0140 +#define YMFSB_RECCTRLSIZE 0x0144 +#define YMFSB_EFFCTRLSIZE 0x0148 +#define YMFSB_WORKSIZE 0x014C +#define YMFSB_MAPOFREC 0x0150 +#define YMFSB_MAPOFEFFECT 0x0154 +#define YMFSB_PLAYCTRLBASE 0x0158 +#define YMFSB_RECCTRLBASE 0x015C +#define YMFSB_EFFCTRLBASE 0x0160 +#define YMFSB_WORKBASE 0x0164 +#define YMFSB_DSPINSTRAM 0x1000 +#define YMFSB_CTRLINSTRAM 0x4000 + + +/* ---------------------------------------------------------------------- */ + +#define MAX_CARDS 4 + +#define PFX "ymf_sb: " + +#define YMFSB_VERSION "0.0.4" +#define YMFSB_CARD_NAME "YMF7xx Legacy Audio driver " YMFSB_VERSION + +#ifdef SUPPORT_UART401_MIDI +#if 0 +# define ymf7xxsb_probe_midi probe_uart401 +# define ymf7xxsb_attach_midi attach_uart401 +# define ymf7xxsb_unload_midi unload_uart401 +#else +# define ymf7xxsb_probe_midi probe_sbmpu +# define ymf7xxsb_attach_midi attach_sbmpu +# define ymf7xxsb_unload_midi unload_sbmpu +#endif +#endif + +/* ---------------------------------------------------------------------- */ + +static struct address_info sb_data[MAX_CARDS]; +static struct address_info opl3_data[MAX_CARDS]; +#ifdef SUPPORT_UART401_MIDI +static struct address_info mpu_data[MAX_CARDS]; +#endif +static unsigned cards = 0; +static unsigned short *ymfbase[MAX_CARDS]; + +/* ---------------------------------------------------------------------- */ + +#ifdef MODULE +#ifdef SUPPORT_UART401_MIDI +static int mpu_io = 0; +#endif +static int synth_io = 0; +static int io = 0; +static int dma = 0; +static int master_vol = -1; +static int spdif_out = 0; +#ifdef SUPPORT_UART401_MIDI +MODULE_PARM(mpu_io, "i"); +#endif +MODULE_PARM(synth_io, "i"); +MODULE_PARM(io,"i"); +MODULE_PARM(dma,"i"); +MODULE_PARM(master_vol,"i"); +MODULE_PARM(spdif_out,"i"); +#else +#ifdef SUPPORT_UART401_MIDI +static int mpu_io = 0x330; +#endif +static int synth_io = 0x388; +static int io = 0x220; +static int dma = 1; +static int master_vol = 80; +static int spdif_out = 0; +#endif + +/* ---------------------------------------------------------------------- */ + +static int readRegWord( int adr ) { + + if (ymfbase[cards]==NULL) return 0; + + return readw(ymfbase[cards]+adr/2); +} + +static void writeRegWord( int adr, int val ) { + + if (ymfbase[cards]==NULL) return; + + writew((unsigned short)(val&0xffff), ymfbase[cards] + adr/2); + + return; +} + +static int readRegDWord( int adr ) { + + if (ymfbase[cards]==NULL) return 0; + + return (readl(ymfbase[cards]+adr/2)); +} + +static void writeRegDWord( int adr, int val ) { + + if (ymfbase[cards]==NULL) return; + + writel((unsigned int)(val&0xffffffff), ymfbase[cards]+adr/2); + + return; +} + +/* ---------------------------------------------------------------------- */ + +static int checkPrimaryBusy( void ) +{ + int timeout=0; + + while ( timeout++ < YMFSB_AC97TIMEOUT ) + { + if ( (readRegWord(YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 ) + return 0; + } + return -1; +} + +static int writeAc97( int adr, unsigned short val ) +{ + + if ( adr > 0x7f || adr < 0x00 ) return -1; + + if ( checkPrimaryBusy() ) return -1; + +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "AC97 0x%0x = 0x%0x\n",adr,val); +#endif + + writeRegWord( YMFSB_AC97CMDADR, 0x0000 | adr ); + writeRegWord( YMFSB_AC97CMDDATA, val ); + + return 0; +} + +static int checkCodec( struct pci_dev *pcidev ) +{ + u8 tmp8; + + pci_read_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8); + if ( tmp8 & 0x03 ) { + pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); + mdelay(YMFSB_RESET_DELAY); + pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03); + mdelay(YMFSB_RESET_DELAY); + pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); + mdelay(YMFSB_RESET_DELAY); + } + + if ( checkPrimaryBusy() ) return -1; + + return 0; +} + +static int setupLegacyIO( struct pci_dev *pcidev ) +{ + int v; + int sbio=0,mpuio=0,oplio=0,dma=0; + + switch(sb_data[cards].io_base) { + case 0x220: + sbio = 0; + break; + case 0x240: + sbio = 1; + break; + case 0x260: + sbio = 2; + break; + case 0x280: + sbio = 3; + break; + default: + return -1; + break; + } +#ifdef YMF_DEBUG + printk(PFX "set SBPro I/O at 0x%x\n",sb_data[cards].io_base); +#endif + +#ifdef SUPPORT_UART401_MIDI + switch(mpu_data[cards].io_base) { + case 0x330: + mpuio = 0; + break; + case 0x300: + mpuio = 1; + break; + case 0x332: + mpuio = 2; + break; + case 0x334: + mpuio = 3; + break; + default: + mpuio = 0; + break; + } +# ifdef YMF_DEBUG + printk(PFX "set MPU401 I/O at 0x%x\n",mpu_data[cards].io_base); +# endif +#endif + + switch(opl3_data[cards].io_base) { + case 0x388: + oplio = 0; + break; + case 0x398: + oplio = 1; + break; + case 0x3a0: + oplio = 2; + break; + case 0x3a8: + oplio = 3; + break; + default: + return -1; + break; + } +#ifdef YMF_DEBUG + printk(PFX "set OPL3 I/O at 0x%x\n",opl3_data[cards].io_base); +#endif + + dma = sb_data[cards].dma; +#ifdef YMF_DEBUG + printk(PFX "set DMA address at 0x%x\n",sb_data[cards].dma); +#endif + + v = 0x0000 | ((dma<<6)&0x03) | 0x003f; + pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v); +#ifdef YMF_DEBUG + printk(PFX "LEGCTRL: 0x%x\n",v); +#endif + switch( pcidev->device ) { + case PCI_DEVICE_ID_YMF724: + case PCI_DEVICE_ID_YMF740: + case PCI_DEVICE_ID_YMF724F: + case PCI_DEVICE_ID_YMF740C: + v = 0x8800 | ((mpuio<<4)&0x03) | ((sbio<<2)&0x03) | (oplio&0x03); + pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v); +#ifdef YMF_DEBUG + printk(PFX "ELEGCTRL: 0x%x\n",v); +#endif + break; + + case PCI_DEVICE_ID_YMF744: + case PCI_DEVICE_ID_YMF754: + v = 0x8800; + pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v); +#ifdef YMF_DEBUG + printk(PFX "ELEGCTRL: 0x%x\n",v); +#endif + pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, opl3_data[cards].io_base); + pci_write_config_word(pcidev, YMFSB_PCIR_SBADR, sb_data[cards]. +io_base); +#ifdef SUPPORT_UART401_MIDI + pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, mpu_data[cards].io_base); +#endif + break; + + default: + printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device); + return -1; + break; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static void enableDSP( void ) +{ + writeRegDWord( YMFSB_CONFIG, 0x00000001 ); + return; +} + +static void disableDSP( void ) +{ + int val; + int i; + + val = readRegDWord( YMFSB_CONFIG ); + if ( val ) { + writeRegDWord( YMFSB_CONFIG, 0 ); + } + + i=0; + while( ++i < YMFSB_WORKBITTIMEOUT ) { + val = readRegDWord(YMFSB_STATUS); + if ( (val & 0x00000002) == 0x00000000 ) break; + } + + return; +} + +static int setupInstruction( struct pci_dev *pcidev ) +{ + int i; + int val; + + writeRegDWord( YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */ + disableDSP(); + + writeRegDWord( YMFSB_MODE, 0x00010000 ); + + /* DS-XG Software Reset */ + writeRegDWord( YMFSB_MODE, 0x00000000 ); + writeRegDWord( YMFSB_MAPOFREC, 0x00000000 ); + writeRegDWord( YMFSB_MAPOFEFFECT, 0x00000000 ); + writeRegDWord( YMFSB_PLAYCTRLBASE, 0x00000000 ); + writeRegDWord( YMFSB_RECCTRLBASE, 0x00000000 ); + writeRegDWord( YMFSB_EFFCTRLBASE, 0x00000000 ); + + val = readRegWord( YMFSB_GLOBALCTRL ); + writeRegWord( YMFSB_GLOBALCTRL, (val&~0x0007) ); + + /* setup DSP instruction code */ + for ( i=0 ; i>2] ); + } + + switch( pcidev->device ) { + case PCI_DEVICE_ID_YMF724: + case PCI_DEVICE_ID_YMF740: + /* setup Control instruction code */ + for ( i=0 ; i>2] ); + } + break; + + case PCI_DEVICE_ID_YMF724F: + case PCI_DEVICE_ID_YMF740C: + case PCI_DEVICE_ID_YMF744: + case PCI_DEVICE_ID_YMF754: + /* setup Control instruction code */ + for ( i=0 ; i>2] ); + } + break; + + default: + return -1; + } + + enableDSP(); + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int __init ymf7xx_init(struct pci_dev *pcidev) +{ + unsigned short v; + + /* Read hardware information */ +#ifdef YMF_DEBUG + unsigned int dv; + pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v); + printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v); + pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v); + printk(KERN_INFO PFX "Device ID = 0x%x\n",v); + pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v); + printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff); + pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv); + printk(KERN_INFO PFX "Base address = 0x%x\n",dv); + pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v); + printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff); +#endif + + /* enables memory space access / bus mastering */ + pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v); + pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06); + + /* check codec */ +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "check codec...\n"); +#endif + if (checkCodec(pcidev)) return -1; + + /* setup legacy I/O */ +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "setup legacy I/O...\n"); +#endif + if (setupLegacyIO(pcidev)) return -1; + + /* setup instruction code */ +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "setup instructions...\n"); +#endif + if (setupInstruction(pcidev)) return -1; + + /* AC'97 setup */ +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "setup AC'97...\n"); +#endif + if ( writeAc97(AC97_RESET ,0x0000) ) /* Reset */ + return -1; + if ( writeAc97(AC97_MASTER_VOL_STEREO,0x0000) ) /* Master Volume */ + return -1; + + v = 31*(100-master_vol)/100; + v = (v<<8 | v)&0x7fff; + if ( writeAc97(AC97_PCMOUT_VOL ,v ) ) /* PCM out Volume */ + return -1; + +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "setup Legacy Volume...\n"); +#endif + /* Legacy Audio Output Volume L & R ch */ + writeRegDWord( YMFSB_LEGACYOUTVOL, 0x3fff3fff ); + +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "setup SPDIF output control...\n"); +#endif + /* SPDIF Output control */ + v = spdif_out != 0 ? 0x0001 : 0x0000; + writeRegWord( YMFSB_SPDIFOUTCTRL, v ); + /* no copyright protection, + sample-rate converted, + re-recorded software comercially available (the 1st generation), + original */ + writeRegWord( YMFSB_SPDIFOUTSTATUS, 0x9a04 ); + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static void __init ymf7xxsb_attach_sb(struct address_info *hw_config) +{ + if(!sb_dsp_init(hw_config)) + hw_config->slots[0] = -1; +} + +static int __init ymf7xxsb_probe_sb(struct address_info *hw_config) +{ + if (check_region(hw_config->io_base, 16)) + { + printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n", + hw_config->io_base); + return 0; + } + return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0, NULL); +} + + +static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu) +{ + if(hw_config->slots[0]!=-1) + sb_dsp_unload(hw_config, unload_mpu); +} + +/* ---------------------------------------------------------------------- */ + +enum chip_types { + CH_YMF724 = 0, + CH_YMF724F, + CH_YMF740, + CH_YMF740C, + CH_YMF744, + CH_YMF754, +}; + +/* directly indexed by chip_types enum above */ +/* note we keep this a struct to ease adding + * other per-board or per-chip info here */ +struct { + const char *devicename; +} devicetable[] __initdata = +{ + { "YMF724A-E" }, + { "YMF724F" }, + { "YMF740A-B" }, + { "YMF740C" }, + { "YMF744" }, + { "YMF754" }, +}; + +static struct pci_device_id ymf7xxsb_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724 }, + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724F }, + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740 }, + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740C }, + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF744 }, + { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF754, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF754 }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, ymf7xxsb_pci_tbl); + +static int __init ymf7xxsb_init_one (struct pci_dev *pcidev, const struct pci_device_id *ent) +{ + + const char *devicename; + unsigned long iobase; + + if (cards == MAX_CARDS) { + printk (KERN_DEBUG PFX "maximum number of cards reached\n"); + return -ENODEV; + } + + if ( pcidev->irq == 0 ) return -ENODEV; + iobase = pci_resource_start (pcidev, 0); + if ( iobase == 0x00000000 ) return -ENODEV; + + devicename = devicetable[ent->driver_data].devicename; + + /* remap memory mapped I/O onto kernel virtual memory */ + if ( (ymfbase[cards] = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 ) + { + printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase); + return -ENODEV; + } + printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase); +#ifdef YMF_DEBUG + printk(KERN_INFO PFX "remappling to 0x%p\n", ymfbase[cards]); +#endif + + memset (&sb_data[cards], 0, sizeof (struct address_info)); + memset (&opl3_data[cards], 0, sizeof (struct address_info)); +#ifdef SUPPORT_UART401_MIDI + memset (&mpu_data[cards], 0, sizeof (struct address_info)); +#endif + + sb_data[cards].name = YMFSB_CARD_NAME; + opl3_data[cards].name = YMFSB_CARD_NAME; +#ifdef SUPPORT_UART401_MIDI + mpu_data[cards].name = YMFSB_CARD_NAME; +#endif + + sb_data[cards].card_subtype = MDL_YMPCI; + + if ( io == 0 ) io = 0x220; + sb_data[cards].io_base = io; + sb_data[cards].irq = pcidev->irq; + sb_data[cards].dma = dma; + + if ( synth_io == 0 ) synth_io = 0x388; + opl3_data[cards].io_base = synth_io; + opl3_data[cards].irq = -1; + +#ifdef SUPPORT_UART401_MIDI + if ( mpu_io == 0 ) mpu_io = 0x330; + mpu_data[cards].io_base = mpu_io; + mpu_data[cards].irq = -1; +#endif + + if ( ymf7xx_init(pcidev) ) { + printk (KERN_ERR PFX + "Cannot initialize %s, aborting\n", + devicename); + return -ENODEV; + } + + /* register legacy SoundBlaster Pro */ + if (!ymf7xxsb_probe_sb(&sb_data[cards])) { + printk (KERN_ERR PFX + "SB probe at 0x%X failed, aborting\n", + io); + return -ENODEV; + } + ymf7xxsb_attach_sb (&sb_data[cards]); + +#ifdef SUPPORT_UART401_MIDI + /* register legacy MIDI */ + if ( mpu_io > 0 && 0) + { + if (!ymf7xxsb_probe_midi (&mpu_data[cards])) { + printk (KERN_ERR PFX + "MIDI probe @ 0x%X failed, aborting\n", + mpu_io); + ymf7xxsb_unload_sb (&sb_data[cards], 0); + return -ENODEV; + } + ymf7xxsb_attach_midi (&mpu_data[cards]); + } +#endif + + /* register legacy OPL3 */ + + cards++; + return 0; +} + +static struct pci_driver ymf7xxsb_driver = { + name: "ymf7xxsb", + id_table: ymf7xxsb_pci_tbl, + probe: ymf7xxsb_init_one, +}; + +static int __init init_ymf7xxsb_module(void) +{ + int i; + + /* + * Binds us to the sound subsystem + */ + SOUND_LOCK; + + if ( master_vol < 0 ) master_vol = 50; + if ( master_vol > 100 ) master_vol = 100; + + for (i=0 ; im_hook = 0; j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of change + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of change } goto timer_end; } @@ -536,8 +535,7 @@ j->proc_load = j->ssr.high << 8 | j->ssr.low; if (!j->m_hook) { j->m_hook = j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of change + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of change } } else { if (j->dsp.low == 0x21 && @@ -552,8 +550,7 @@ if (j->m_hook) { j->m_hook = 0; j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of change + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of change } } } @@ -642,8 +639,7 @@ } if (j->ex.bytes) { wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of change + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of change } } else { break; @@ -917,8 +913,7 @@ j->r_hook = fOffHook; if (j->port != PORT_POTS) { j->ex.bits.hookstate = 1; - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of change + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of change } } @@ -1471,8 +1466,7 @@ wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of frame + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of frame } } @@ -1557,8 +1551,7 @@ wake_up_interruptible(&j->poll_q); // Wake any blocked selects - if (j->async_queue) - kill_fasync(j->async_queue, SIGIO, POLL_IN); // Send apps notice of empty buffer + kill_fasync(&j->async_queue, SIGIO, POLL_IN); // Send apps notice of empty buffer #ifdef PERFMON_STATS ++j->frameswritten; #endif @@ -4615,10 +4608,12 @@ pci = pci_find_device(0x15E2, 0x0500, pci); if (!pci) break; + if (pci_enable_device(pci)) + break; { - ixj[cnt].DSPbase = pci->resource[0].start; + ixj[cnt].DSPbase = pci_resource_start(pci, 0); ixj[cnt].XILINXbase = ixj[cnt].DSPbase + 0x10; - ixj[cnt].serial = PCIEE_GetSerialNumber(pci->resource[2].start); + ixj[cnt].serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); result = check_region(ixj[cnt].DSPbase, 16); if (result) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/telephony/ixj.h linux.ac/drivers/telephony/ixj.h --- linux.vanilla/drivers/telephony/ixj.h Thu May 25 17:38:23 2000 +++ linux.ac/drivers/telephony/ixj.h Sat Jun 10 22:50:13 2000 @@ -879,6 +879,7 @@ typedef struct { struct phone_device p; + struct semaphore mutex; unsigned int board; unsigned int DSPbase; unsigned int XILINXbase; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/Config.in linux.ac/drivers/usb/Config.in --- linux.vanilla/drivers/usb/Config.in Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/Config.in Mon Jun 5 20:21:17 2000 @@ -55,6 +55,7 @@ dep_tristate ' USB ADMtek Pegasus-based device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB fi comment 'USB HID' diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/Makefile linux.ac/drivers/usb/Makefile --- linux.vanilla/drivers/usb/Makefile Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/Makefile Mon Jun 5 20:21:17 2000 @@ -82,6 +82,7 @@ obj-$(CONFIG_USB_PEGASUS) += pegasus.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_DSBR) += dsbr100.o +obj-$(CONFIG_USB_MICROTEK) += microtek.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/acm.c linux.ac/drivers/usb/acm.c --- linux.vanilla/drivers/usb/acm.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/acm.c Sat May 27 15:43:57 2000 @@ -329,6 +329,7 @@ if (!ACM_READY(acm)) return -EINVAL; if (acm->writeurb.status == -EINPROGRESS) return 0; + if (!count) return 0; count = (count > acm->writesize) ? acm->writesize : count; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/audio.c linux.ac/drivers/usb/audio.c --- linux.vanilla/drivers/usb/audio.c Thu May 25 17:46:15 2000 +++ linux.ac/drivers/usb/audio.c Sat May 27 15:42:10 2000 @@ -1788,7 +1788,7 @@ dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); continue; } - for (j = i; j < ms->numch; i++) { + for (j = i; j < ms->numch; j++) { if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) continue; mask |= 1 << j; @@ -1821,7 +1821,7 @@ } /* first generate smask */ smask = bmask = 0; - for (j = i; j < ms->numch; i++) { + for (j = i; j < ms->numch; j++) { if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) continue; smask |= 1 << ms->ch[j].osschannel; @@ -1835,7 +1835,7 @@ continue; if (j > 1) srcmask &= ~bmask; - for (j = i; j < ms->numch; i++) { + for (j = i; j < ms->numch; j++) { if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) continue; if (!(srcmask & (1 << ms->ch[j].osschannel))) @@ -3193,6 +3193,16 @@ state->termtype = 0; } +static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid) +{ + unsigned int i; + + for (i = 0; i < state->nrmixch; i++) + if (state->mixch[i].unitid == unitid) + return &state->mixch[i]; + return NULL; +} + static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector) { unsigned int chnum, i, mixch; @@ -3206,7 +3216,9 @@ usb_audio_recurseunit(state, selector[5]); if (state->nrmixch != mixch) { mch = &state->mixch[state->nrmixch-1]; - mch->slctunitid = selector[5] | (1 << 8); + mch->slctunitid = selector[3] | (1 << 8); + } else if ((mch = slctsrc_findunit(state, selector[5]))) { + mch->slctunitid = selector[3] | (1 << 8); } else { printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]); } @@ -3223,7 +3235,9 @@ } if (state->nrmixch != mixch) { mch = &state->mixch[state->nrmixch-1]; - mch->slctunitid = selector[5] | ((i + 1) << 8); + mch->slctunitid = selector[3] | ((i + 1) << 8); + } else if ((mch = slctsrc_findunit(state, selector[5+i]))) { + mch->slctunitid = selector[3] | ((i + 1) << 8); } else { printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1); } @@ -3604,8 +3618,10 @@ #endif if (config->interface[ifnum].altsetting[0].bInterfaceClass != USB_CLASS_AUDIO || config->interface[ifnum].altsetting[0].bInterfaceSubClass != 1) { +#if 0 printk(KERN_DEBUG "usbaudio: vendor id 0x%04x, product id 0x%04x contains no AudioControl interface\n", dev->descriptor.idVendor, dev->descriptor.idProduct); +#endif return NULL; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/dabusb.c linux.ac/drivers/usb/dabusb.c --- linux.vanilla/drivers/usb/dabusb.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/dabusb.c Sun Jun 4 22:13:29 2000 @@ -573,7 +573,7 @@ int devnum = MINOR (inode->i_rdev); pdabusb_t s; - if (devnum < DABUSB_MINOR || devnum > (DABUSB_MINOR + NRDABUSB)) + if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) return -EIO; MOD_INC_USE_COUNT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/dabusb.h linux.ac/drivers/usb/dabusb.h --- linux.vanilla/drivers/usb/dabusb.h Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/dabusb.h Sun Jun 4 22:13:28 2000 @@ -49,7 +49,7 @@ #define _DABUSB_IF 2 -#define _DABUSB_ISOPIPE 0x89 +#define _DABUSB_ISOPIPE 0x09 #define _ISOPIPESIZE 16384 #define _BULK_DATA_LEN 64 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/devio.c linux.ac/drivers/usb/devio.c --- linux.vanilla/drivers/usb/devio.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/devio.c Sat May 27 15:41:34 2000 @@ -187,26 +187,60 @@ ssize_t ret = 0; unsigned len; loff_t pos; + int i; pos = *ppos; down_read(&ps->devsem); - if (!ps->dev) + if (!ps->dev) { ret = -ENODEV; - else if (pos < 0) + goto err; + } else if (pos < 0) { ret = -EINVAL; - else if (pos < sizeof(struct usb_device_descriptor)) { + goto err; + } + + if (pos < sizeof(struct usb_device_descriptor)) { len = sizeof(struct usb_device_descriptor) - pos; if (len > nbytes) len = nbytes; - if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) + if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) { ret = -EFAULT; - else { + goto err; + } + + *ppos += len; + buf += len; + nbytes -= len; + ret += len; + } + + pos = sizeof(struct usb_device_descriptor); + for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) { + struct usb_config_descriptor *config = + (struct usb_config_descriptor *)ps->dev->rawdescriptors[i]; + unsigned int length = le16_to_cpu(config->wTotalLength); + + if (*ppos < pos + length) { + len = length - (*ppos - pos); + if (len > nbytes) + len = nbytes; + + if (copy_to_user(buf, + ps->dev->rawdescriptors[i] + (*ppos - pos), len)) { + ret = -EFAULT; + goto err; + } + *ppos += len; buf += len; nbytes -= len; ret += len; } + + pos += length; } + +err: up_read(&ps->devsem); return ret; } @@ -376,12 +410,9 @@ } struct usb_driver usbdevfs_driver = { - "usbdevfs", - driver_probe, - driver_disconnect, - LIST_HEAD_INIT(usbdevfs_driver.driver_list), - NULL, - 0 + name: "usbdevfs", + probe: driver_probe, + disconnect: driver_disconnect, }; static int claimintf(struct dev_state *ps, unsigned int intf) @@ -481,6 +512,28 @@ return -ENOENT; } +extern struct list_head usb_driver_list; + +static int finddriver(struct usb_driver **driver, char *name) +{ + struct list_head *tmp; + + tmp = usb_driver_list.next; + while (tmp != &usb_driver_list) { + struct usb_driver *d = list_entry(tmp, struct usb_driver, + driver_list); + + if (!strcmp(d->name, name)) { + *driver = d; + return 0; + } + + tmp = tmp->next; + } + + return -EINVAL; +} + /* * file operations */ @@ -662,16 +715,51 @@ return 0; } +static int proc_getdriver(struct dev_state *ps, void *arg) +{ + struct usbdevfs_getdriver gd; + struct usb_interface *interface; + int ret; + + copy_from_user_ret(&gd, arg, sizeof(gd), -EFAULT); + if ((ret = findintfif(ps->dev, gd.interface)) < 0) + return ret; + interface = usb_ifnum_to_if(ps->dev, gd.interface); + if (!interface) + return -EINVAL; + if (!interface->driver) + return -ENODATA; + strcpy(gd.driver, interface->driver->name); + copy_to_user_ret(arg, &gd, sizeof(gd), -EFAULT); + return 0; +} + +static int proc_connectinfo(struct dev_state *ps, void *arg) +{ + struct usbdevfs_connectinfo ci; + + ci.devnum = ps->dev->devnum; + ci.slow = ps->dev->slow; + copy_to_user_ret(arg, &ci, sizeof(ci), -EFAULT); + return 0; +} + static int proc_setintf(struct dev_state *ps, void *arg) { struct usbdevfs_setinterface setintf; + struct usb_interface *interface; int ret; copy_from_user_ret(&setintf, arg, sizeof(setintf), -EFAULT); if ((ret = findintfif(ps->dev, setintf.interface)) < 0) return ret; - if ((ret = checkintf(ps, ret))) - return ret; + interface = usb_ifnum_to_if(ps->dev, setintf.interface); + if (!interface) + return -EINVAL; + if (interface->driver) { + if ((ret = checkintf(ps, ret))) + return ret; + } if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting)) return -EINVAL; return 0; @@ -942,6 +1030,14 @@ ret = proc_resetep(ps, (void *)arg); if (ret >= 0) inode->i_mtime = CURRENT_TIME; + break; + + case USBDEVFS_GETDRIVER: + ret = proc_getdriver(ps, (void *)arg); + break; + + case USBDEVFS_CONNECTINFO: + ret = proc_connectinfo(ps, (void *)arg); break; case USBDEVFS_SETINTERFACE: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/dsbr100.c linux.ac/drivers/usb/dsbr100.c --- linux.vanilla/drivers/usb/dsbr100.c Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/dsbr100.c Mon Jun 5 19:11:28 2000 @@ -33,6 +33,9 @@ History: + Version 0.23: + Markus: Sign extension bug fixed by declaring transfer_buffer unsigned + Version 0.22: Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, thanks to Mike Cox for pointing the problem out. @@ -74,7 +77,7 @@ typedef struct { struct urb readurb,writeurb; struct usb_device *dev; - char transfer_buffer[TB_LEN]; + unsigned char transfer_buffer[TB_LEN]; int curfreq; int stereo; int ifnum; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/evdev.c linux.ac/drivers/usb/evdev.c --- linux.vanilla/drivers/usb/evdev.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/evdev.c Tue May 30 21:28:10 2000 @@ -1,7 +1,7 @@ /* - * evdev.c Version 0.1 + * $Id: evdev.c,v 1.8 2000/05/29 09:01:52 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * Event char devices, giving access to raw input device events. * @@ -72,8 +72,7 @@ list->buffer[list->head].value = value; list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1); - if (list->fasync) - kill_fasync(list->fasync, SIGIO, POLL_IN); + kill_fasync(&list->fasync, SIGIO, POLL_IN); list = list->next; } @@ -207,14 +206,20 @@ struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; + int retval; switch (cmd) { case EVIOCGVERSION: - return put_user(EV_VERSION, (__u32 *) arg); + return put_user(EV_VERSION, (int *) arg); + case EVIOCGID: - return copy_to_user(&dev->id, (void *) arg, - sizeof(struct input_id)) ? -EFAULT : 0; + if ((retval = put_user(dev->idbus, ((short *) arg) + 0))) return retval; + if ((retval = put_user(dev->idvendor, ((short *) arg) + 1))) return retval; + if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval; + if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval; + return 0; + default: if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) @@ -222,8 +227,8 @@ if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { - long *bits = NULL; - int len = 0; + long *bits; + int len; switch (_IOC_NR(cmd) & EV_MAX) { case 0: bits = dev->evbit; len = EV_MAX; break; @@ -235,15 +240,34 @@ default: return -EINVAL; } len = NBITS(len) * sizeof(long); - if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - return copy_to_user((void *) arg, bits, len) ? -EFAULT : len; + if (len > _IOC_SIZE(cmd)) { + printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n", + len, _IOC_SIZE(cmd)); + len = _IOC_SIZE(cmd); + } + return copy_to_user((char *) arg, bits, len) ? -EFAULT : len; } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { - int len = strlen(dev->name) + 1; + int len; + if (!dev->name) return 0; + len = strlen(dev->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len; } + + if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { + + int t = _IOC_NR(cmd) & ABS_MAX; + + if ((retval = put_user(dev->abs[t], ((int *) arg) + 0))) return retval; + if ((retval = put_user(dev->absmin[t], ((int *) arg) + 1))) return retval; + if ((retval = put_user(dev->absmax[t], ((int *) arg) + 2))) return retval; + if ((retval = put_user(dev->absfuzz[t], ((int *) arg) + 3))) return retval; + if ((retval = put_user(dev->absflat[t], ((int *) arg) + 4))) return retval; + + return 0; + } } return -EINVAL; } @@ -286,7 +310,7 @@ evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE); - printk("event%d: Event device for input%d\n", minor, dev->number); + printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number); return &evdev->handle; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/hid-debug.h linux.ac/drivers/usb/hid-debug.h --- linux.vanilla/drivers/usb/hid-debug.h Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/hid-debug.h Tue May 30 21:28:10 2000 @@ -1,5 +1,5 @@ /* - * driver/usb/hid-debug.h + * $Id: hid-debug.h,v 1.2 2000/05/29 10:54:53 vojtech Exp $ * * (c) 1999 Andreas Gal * (c) 2000 Vojtech Pavlik diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/hid.c linux.ac/drivers/usb/hid.c --- linux.vanilla/drivers/usb/hid.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/hid.c Tue May 30 21:28:10 2000 @@ -1,5 +1,5 @@ /* - * hid.c Version 0.8 + * $Id: hid.c,v 1.6 2000/05/29 09:01:52 vojtech Exp $ * * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000 Vojtech Pavlik @@ -80,6 +80,9 @@ __s32 y; } hid_hat_to_axis[] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}, { 0, 0}}; +static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", + "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; + /* * Register a new report for a device. */ @@ -1259,6 +1262,27 @@ return 0; } +static int hid_open(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + + if (hid->open++) + return 0; + + if (usb_submit_urb(&hid->urb)) + return -EIO; + + return 0; +} + +static void hid_close(struct input_dev *dev) +{ + struct hid_device *hid = dev->private; + + if (!--hid->open) + usb_unlink_urb(&hid->urb); +} + /* * Configure the input layer interface * Read all reports and initalize the absoulte field values. @@ -1272,6 +1296,8 @@ hid->input.private = hid; hid->input.event = hid_event; + hid->input.open = hid_open; + hid->input.close = hid_close; for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { @@ -1313,7 +1339,7 @@ { 0, 0 } }; -static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) +static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum, char *name) { struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0; struct hid_descriptor *hdesc; @@ -1380,11 +1406,6 @@ FILL_INT_URB(&hid->urb, dev, pipe, hid->buffer, maxp > 32 ? 32 : maxp, hid_irq, hid, endpoint->bInterval); - if (usb_submit_urb(&hid->urb)) { - dbg("submitting interrupt URB failed"); - continue; - } - break; } @@ -1405,6 +1426,20 @@ hid->dr.index = hid->ifnum; hid->dr.length = 1; + hid->input.name = hid->name; + hid->input.idbus = BUS_USB; + hid->input.idvendor = dev->descriptor.idVendor; + hid->input.idproduct = dev->descriptor.idProduct; + hid->input.idversion = dev->descriptor.bcdDevice; + + if (strlen(name)) + strcpy(hid->name, name); + else + sprintf(hid->name, "USB HID %s %04x:%04x", + ((hid->application >= 0x00010000) && (hid->application <= 0x00010008)) ? + hid_types[hid->application & 0xffff] : "Device", + hid->input.idvendor, hid->input.idproduct); + FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0), (void*) &hid->dr, hid->bufout, 1, hid_ctrl, hid); @@ -1416,13 +1451,27 @@ static void* hid_probe(struct usb_device *dev, unsigned int ifnum) { - char *hid_name[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", - "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; struct hid_device *hid; + char name[128]; + char *buf; dbg("HID probe called for ifnum %d", ifnum); - if (!(hid = usb_hid_configure(dev, ifnum))) + name[0] = 0; + + if (!(buf = kmalloc(63, GFP_KERNEL))) + return NULL; + + if (dev->descriptor.iManufacturer && + usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strcat(name, buf); + if (dev->descriptor.iProduct && + usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + sprintf(name, "%s %s", name, buf); + + kfree(buf); + + if (!(hid = usb_hid_configure(dev, ifnum, name))) return NULL; hid_dump_device(hid); @@ -1430,10 +1479,18 @@ hid_init_input(hid); input_register_device(&hid->input); - printk(KERN_INFO "input%d: USB HID v%x.%02x %s\n", - hid->input.number, hid->version >> 8, hid->version & 0xff, + printk(KERN_INFO "input%d: USB HID v%x.%02x %s", + hid->input.number, + hid->version >> 8, hid->version & 0xff, ((hid->application >= 0x00010000) && (hid->application <= 0x00010008)) ? - hid_name[hid->application & 0xffff] : "device"); + hid_types[hid->application & 0xffff] : "Device"); + + if (strlen(name)) + printk(" [%s]", name); + else + printk(" [%04x:%04x]", hid->input.idvendor, hid->input.idproduct); + + printk(" on usb%d:%d.%d\n", dev->bus->busnum, dev->devnum, ifnum); return hid; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/hid.h linux.ac/drivers/usb/hid.h --- linux.vanilla/drivers/usb/hid.h Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/hid.h Sat Jun 10 22:49:31 2000 @@ -2,7 +2,7 @@ #define __HID_H /* - * drivers/usb/hid.h Version 0.8 + * $Id: hid.h,v 1.4 2000/05/29 09:01:52 vojtech Exp $ * * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000 Vojtech Pavlik @@ -292,7 +292,9 @@ struct urb urb; /* USB URB structure */ struct urb urbout; /* Output URB */ struct input_dev input; /* input device structure */ + int open; /* is the device open by input? */ int quirks; /* Various nasty tricks the device can pull on us */ + char name[128]; /* Device name */ }; #define HID_GLOBAL_STACK_SIZE 4 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/hub.c linux.ac/drivers/usb/hub.c --- linux.vanilla/drivers/usb/hub.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/hub.c Fri Jun 9 22:38:54 2000 @@ -120,18 +120,25 @@ struct usb_hub_descriptor *descriptor; struct usb_descriptor_header *header; struct usb_hub_status *hubsts; - int i; + int i, ret; /* Get the length first */ - if (usb_get_hub_descriptor(dev, buffer, 4) < 0) + ret = usb_get_hub_descriptor(dev, buffer, sizeof(*header)); + if (ret < 0) { + err("Unable to get partial hub descriptor (err = %d)", ret); return -1; + } header = (struct usb_descriptor_header *)buffer; bitmap = kmalloc(header->bLength, GFP_KERNEL); - if (!bitmap) + if (!bitmap) { + err("Unable to kmalloc %d bytes for bitmap", header->bLength); return -1; + } - if (usb_get_hub_descriptor(dev, bitmap, header->bLength) < 0) { + ret = usb_get_hub_descriptor(dev, bitmap, header->bLength); + if (ret < 0) { + err("Unable to get hub descriptor (err = %d)", ret); kfree(bitmap); return -1; } @@ -182,8 +189,11 @@ kfree(bitmap); - if (usb_get_hub_status(dev, buffer) < 0) + ret = usb_get_hub_status(dev, buffer); + if (ret < 0) { + err("Unable to get hub status (err = %d)", ret); return -1; + } hubsts = (struct usb_hub_status *)buffer; dbg("local power source is %s", @@ -225,12 +235,16 @@ endpoint = &interface->endpoint[0]; /* Output endpoint? Curiousier and curiousier.. */ - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { + err("Device is hub class, but has output endpoint?"); return NULL; + } /* If it's not an interrupt endpoint, we'd better punt! */ - if ((endpoint->bmAttributes & 3) != 3) + if ((endpoint->bmAttributes & 3) != 3) { + err("Device is hub class, but has endpoint other than interrupt?"); return NULL; + } /* We found a hub */ info("USB hub found"); @@ -326,12 +340,13 @@ struct usb_device *usb; struct usb_port_status portsts; unsigned short portstatus, portchange; - int tries; + int ret, tries; wait_ms(100); - /* Check status */ - if (usb_get_port_status(hub, port + 1, &portsts)<0) { - err("get_port_status failed"); + + ret = usb_get_port_status(hub, port + 1, &portsts); + if (ret < 0) { + err("get_port_status(%d) failed (err = %d)", port + 1, ret); return; } @@ -353,19 +368,19 @@ } wait_ms(400); - /* Reset the port */ - #define MAX_TRIES 5 - - for(tries=0;tries= MAX_TRIES) { err("Cannot enable port %i after %i retries, disabling port.", port+1, MAX_TRIES); err("Maybe the USB cable is bad?"); return; @@ -390,7 +405,6 @@ usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET); /* Allocate a new device struct for it */ - usb = usb_alloc_dev(hub, hub->bus); if (!usb) { err("couldn't allocate usb_device"); @@ -405,11 +419,21 @@ usb_connect(usb); /* Run it through the hoops (find a driver, etc) */ - if (usb_new_device(usb)) { - usb_disconnect(&hub->children[port]); - /* Woops, disable the port */ - dbg("hub: disabling port %d", port + 1); - usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); + ret = usb_new_device(usb); + if (ret) { + /* Try resetting the device. Windows does this and it */ + /* gets some devices working correctly */ + usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); + + ret = usb_new_device(usb); + if (ret) { + usb_disconnect(&hub->children[port]); + + /* Woops, disable the port */ + dbg("hub: disabling port %d", port + 1); + usb_clear_port_feature(hub, port + 1, + USB_PORT_FEAT_ENABLE); + } } } @@ -556,10 +580,9 @@ } static struct usb_driver hub_driver = { - "hub", - hub_probe, - hub_disconnect, - { NULL, NULL } + name: "hub", + probe: hub_probe, + disconnect: hub_disconnect }; /* @@ -569,8 +592,10 @@ { int pid; - if (usb_register(&hub_driver) < 0) + if (usb_register(&hub_driver) < 0) { + err("Unable to register USB hub driver"); return -1; + } pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/input.c linux.ac/drivers/usb/input.c --- linux.vanilla/drivers/usb/input.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/input.c Tue May 30 21:28:07 2000 @@ -1,7 +1,7 @@ /* - * input.c Version 0.1 + * $Id: input.c,v 1.7 2000/05/28 17:31:36 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * The input layer module itself * @@ -91,11 +91,27 @@ case EV_ABS: - if (code > ABS_MAX || !test_bit(code, dev->absbit) || (value == dev->abs[code])) + if (code > ABS_MAX || !test_bit(code, dev->absbit)) return; - dev->abs[code] = value; + if (dev->absfuzz[code]) { + if ((value > dev->abs[code] - (dev->absfuzz[code] >> 1)) && + (value < dev->abs[code] + (dev->absfuzz[code] >> 1))) + return; + + if ((value > dev->abs[code] - dev->absfuzz[code]) && + (value < dev->abs[code] + dev->absfuzz[code])) + value = (dev->abs[code] * 3 + value) >> 2; + + if ((value > dev->abs[code] - (dev->absfuzz[code] << 1)) && + (value < dev->abs[code] + (dev->absfuzz[code] << 1))) + value = (dev->abs[code] + value) >> 1; + } + if (dev->abs[code] == value) + return; + + dev->abs[code] = value; break; case EV_REL: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/joydev.c linux.ac/drivers/usb/joydev.c --- linux.vanilla/drivers/usb/joydev.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/joydev.c Tue May 30 21:28:10 2000 @@ -1,7 +1,7 @@ /* - * joydev.c Version 0.1 + * $Id: joydev.c,v 1.7 2000/05/29 09:01:52 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * Copyright (c) 1999 Colin Van Dyke * * Joystick device driver for the input driver suite. @@ -53,7 +53,6 @@ int used; int open; int minor; - char name[32]; struct input_handle handle; wait_queue_head_t wait; devfs_handle_t devfs; @@ -139,8 +138,7 @@ if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1))) list->startup = 0; - if (list->fasync) - kill_fasync(list->fasync, SIGIO, POLL_IN); + kill_fasync(&list->fasync, SIGIO, POLL_IN); list = list->next; } @@ -322,6 +320,8 @@ { struct joydev_list *list = file->private_data; struct joydev *joydev = list->joydev; + struct input_dev *dev = joydev->handle.dev; + switch (cmd) { @@ -360,9 +360,11 @@ sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; default: if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { - int len = strlen(joydev->name) + 1; + int len; + if (!dev->name) return 0; + len = strlen(dev->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); - if (copy_to_user((char *) arg, joydev->name, len)) return -EFAULT; + if (copy_to_user((char *) arg, dev->name, len)) return -EFAULT; return len; } } @@ -401,8 +403,6 @@ init_waitqueue_head(&joydev->wait); - sprintf(joydev->name, "joydev%d", joydev->minor); - joydev->minor = minor; joydev_table[minor] = joydev; @@ -449,7 +449,7 @@ joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); - printk("js%d: Joystick device for input%d\n", minor, dev->number); + printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number); return &joydev->handle; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/keybdev.c linux.ac/drivers/usb/keybdev.c --- linux.vanilla/drivers/usb/keybdev.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/keybdev.c Tue May 30 21:28:07 2000 @@ -1,7 +1,7 @@ /* - * keybdev.c Version 0.1 + * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * Input driver to keyboard driver binding. * @@ -162,14 +162,14 @@ input_open_device(handle); - printk("keybdev.c: Adding keyboard: input%d\n", dev->number); + printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number); return handle; } static void keybdev_disconnect(struct input_handle *handle) { - printk("keybdev.c: Removing keyboard: input%d\n", handle->dev->number); + printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number); input_close_device(handle); kfree(handle); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/microtek.c linux.ac/drivers/usb/microtek.c --- linux.vanilla/drivers/usb/microtek.c Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/usb/microtek.c Tue Jun 6 12:37:13 2000 @@ -0,0 +1,1051 @@ +/* Driver for Microtek Scanmaker X6 USB scanner, and possibly others. + * + * (C) Copyright 2000 John Fremlin + * (C) Copyright 2000 Oliver Neukum + * + * Parts shamelessly stolen from usb-storage and copyright by their + * authors. Thanks to Matt Dharm for giving us permission! + * + * This driver implements a SCSI host controller driver and a USB + * device driver. To avoid confusion, all the USB related stuff is + * prefixed by mts_usb_ and all the SCSI stuff by mts_scsi_. + * + * Microtek (www.microtek.com) did not release the specifications for + * their USB protocol to us, so we had to reverse engineer them. We + * don't know for which models they are valid. + * + * The X6 USB has three bulk endpoints, one output (0x1) down which + * commands and outgoing data are sent, and two input: 0x82 from which + * normal data is read from the scanner (in packets of maximum 32 + * bytes) and from which the status byte is read, and 0x83 from which + * the results of a scan (or preview) are read in up to 64 * 1024 byte + * chunks by the Windows driver. We don't know how much it is possible + * to read at a time from 0x83. + * + * It seems possible to read (with URB transfers) everything from 0x82 + * in one go, without bothering to read in 32 byte chunks. + * + * There seems to be an optimisation of a further READ implicit if + * you simply read from 0x83. + * + * Guessed protocol: + * + * Send raw SCSI command to EP 0x1 + * + * If there is data to receive: + * If the command was READ datatype=image: + * Read a lot of data from EP 0x83 + * Else: + * Read data from EP 0x82 + * Else: + * If there is data to transmit: + * Write it to EP 0x1 + * + * Read status byte from EP 0x82 + * + * References: + * + * The SCSI command set for the scanner is available from + * ftp://ftp.microtek.com/microtek/devpack/ + * + * Microtek NV sent us a more up to date version of the document. If + * you want it, just send mail. + * + * Status: + * + * This driver does not work properly yet. + * Untested with multiple scanners. + * Untested on SMP. + * Untested on UHCI. + * + * History: + * + * 20000417 starting history + * 20000417 fixed load oops + * 20000417 fixed unload oops + * 20000419 fixed READ IMAGE detection + * 20000424 started conversion to use URBs + * 20000502 handled short transfers as errors + * 20000513 rename and organisation of functions (john) + * 20000513 added IDs for all products supported by Windows driver (john) + * 20000514 Rewrote mts_scsi_queuecommand to use URBs (john) + * 20000514 Version 0.0.8j + * 20000514 Fix reporting of non-existant devices to SCSI layer (john) + * 20000514 Added MTS_DEBUG_INT (john) + * 20000514 Changed "usb-microtek" to "microtek" for consistency (john) + * 20000514 Stupid bug fixes (john) + * 20000514 Version 0.0.9j + * 20000515 Put transfer context and URB in mts_desc (john) + * 20000515 Added prelim turn off debugging support (john) + * 20000515 Version 0.0.10j + * 20000515 Fixed up URB allocation (clear URB on alloc) (john) + * 20000515 Version 0.0.11j + * 20000516 Removed unnecessary spinlock in mts_transfer_context (john) + * 20000516 Removed unnecessary up on instance lock in mts_remove_nolock (john) + * 20000516 Implemented (badly) scsi_abort (john) + * 20000516 Version 0.0.12j + * 20000517 Hopefully removed mts_remove_nolock quasideadlock (john) + * 20000517 Added mts_debug_dump to print ll USB info (john) + * 20000518 Tweaks and documentation updates (john) + * 20000518 Version 0.0.13j + * 20000518 Cleaned up abort handling (john) + * 20000523 Removed scsi_command and various scsi_..._resets (john) + * 20000523 Added unlink URB on scsi_abort, now OHCI supports it (john) + * 20000523 Fixed last tiresome compile warning (john) + * 20000523 Version 0.0.14j (though version 0.1 has come out?) + * 20000602 Added primitive reset + * 20000602 Version 0.2.0 + * 20000603 various cosmetic changes + * 20000603 Version 0.2.1 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "../scsi/scsi.h" +#include "../scsi/hosts.h" +#include "../scsi/sd.h" + +#include "microtek.h" + +/* Constants */ + +#define MTS_ABORT_TIMEOUT HZ /*jiffies*/ + + +/* Should we do debugging? */ + +#define MTS_DO_DEBUG + + +/* USB layer driver interface */ + +static void *mts_usb_probe(struct usb_device *dev, unsigned int interface); +static void mts_usb_disconnect(struct usb_device *dev, void *ptr); + +static struct usb_driver mts_usb_driver = { + "microtek", + mts_usb_probe, + mts_usb_disconnect, + { NULL, NULL } /* we need no fops. let gcc fill it */ +}; + + +/* Internal driver stuff */ + +#define MTS_VERSION "0.2.1" +#define MTS_NAME "microtek usb (rev " MTS_VERSION "): " + +#define MTS_WARNING(x...) \ + printk( KERN_WARNING MTS_NAME ## x ) +#define MTS_ERROR(x...) \ + printk( KERN_ERR MTS_NAME ## x ) +#define MTS_INT_ERROR(x...) \ + MTS_ERROR( ## x ) +#define MTS_MESSAGE(x...) \ + printk( KERN_INFO MTS_NAME ## x ) + +#if defined MTS_DO_DEBUG + +#define MTS_DEBUG(x...) \ + printk( KERN_DEBUG MTS_NAME ## x ) + +#define MTS_DEBUG_GOT_HERE() \ + MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ ) +#define MTS_DEBUG_INT() \ + do { MTS_DEBUG_GOT_HERE(); \ + MTS_DEBUG("transfer = %x context = %x\n",(int)transfer,(int)context ); \ + MTS_DEBUG("status = %x data-length = %x sent = %x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \ + mts_debug_dump(context->instance);\ + } while(0) +#else + +#define MTS_NUL_STATEMENT do { } while(0) + +#define MTS_DEBUG(x...) MTS_NUL_STATEMENT +#define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT +#define MTS_DEBUG_INT() MTS_NUL_STATEMENT + +#endif + + + +#define MTS_INT_INIT()\ + do {\ + context = (struct mts_transfer_context*)transfer->context; \ + if (atomic_read(&context->do_abort)) {\ + mts_transfer_cleanup(transfer);\ + return;\ + }\ + MTS_DEBUG_INT();\ + } while (0) + +static inline void mts_debug_dump(struct mts_desc* desc) { + MTS_DEBUG("desc at 0x%x: halted = %x%x, toggle = %x%x\n", + (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0], + (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0] + ); + MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n", + usb_sndbulkpipe(desc->usb_dev,desc->ep_out), + usb_rcvbulkpipe(desc->usb_dev,desc->ep_response), + usb_rcvbulkpipe(desc->usb_dev,desc->ep_image) + ); +} + + +static inline void mts_show_command(Scsi_Cmnd *srb) +{ + char *what = NULL; + + switch (srb->cmnd[0]) { + case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; + case REZERO_UNIT: what = "REZERO_UNIT"; break; + case REQUEST_SENSE: what = "REQUEST_SENSE"; break; + case FORMAT_UNIT: what = "FORMAT_UNIT"; break; + case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; + case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; + case READ_6: what = "READ_6"; break; + case WRITE_6: what = "WRITE_6"; break; + case SEEK_6: what = "SEEK_6"; break; + case READ_REVERSE: what = "READ_REVERSE"; break; + case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; + case SPACE: what = "SPACE"; break; + case INQUIRY: what = "INQUIRY"; break; + case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; + case MODE_SELECT: what = "MODE_SELECT"; break; + case RESERVE: what = "RESERVE"; break; + case RELEASE: what = "RELEASE"; break; + case COPY: what = "COPY"; break; + case ERASE: what = "ERASE"; break; + case MODE_SENSE: what = "MODE_SENSE"; break; + case START_STOP: what = "START_STOP"; break; + case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; + case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; + case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; + case SET_WINDOW: what = "SET_WINDOW"; break; + case READ_CAPACITY: what = "READ_CAPACITY"; break; + case READ_10: what = "READ_10"; break; + case WRITE_10: what = "WRITE_10"; break; + case SEEK_10: what = "SEEK_10"; break; + case WRITE_VERIFY: what = "WRITE_VERIFY"; break; + case VERIFY: what = "VERIFY"; break; + case SEARCH_HIGH: what = "SEARCH_HIGH"; break; + case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; + case SEARCH_LOW: what = "SEARCH_LOW"; break; + case SET_LIMITS: what = "SET_LIMITS"; break; + case READ_POSITION: what = "READ_POSITION"; break; + case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; + case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; + case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; + case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; + case COMPARE: what = "COMPARE"; break; + case COPY_VERIFY: what = "COPY_VERIFY"; break; + case WRITE_BUFFER: what = "WRITE_BUFFER"; break; + case READ_BUFFER: what = "READ_BUFFER"; break; + case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; + case READ_LONG: what = "READ_LONG"; break; + case WRITE_LONG: what = "WRITE_LONG"; break; + case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; + case WRITE_SAME: what = "WRITE_SAME"; break; + case READ_TOC: what = "READ_TOC"; break; + case LOG_SELECT: what = "LOG_SELECT"; break; + case LOG_SENSE: what = "LOG_SENSE"; break; + case MODE_SELECT_10: what = "MODE_SELECT_10"; break; + case MODE_SENSE_10: what = "MODE_SENSE_10"; break; + case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; + case READ_12: what = "READ_12"; break; + case WRITE_12: what = "WRITE_12"; break; + case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; + case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; + case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; + case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; + case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; + case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; + case WRITE_LONG_2: what = "WRITE_LONG_2"; break; + default: + MTS_DEBUG("can't decode command\n"); + goto out; + break; + } + MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len); + + out: + MTS_DEBUG( " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], + srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); +} + +static inline int mts_is_aborting(struct mts_desc* desc) { + return (atomic_read(&desc->context.do_abort)); +} + +static inline void mts_request_abort(struct mts_desc* desc) { + MTS_DEBUG_GOT_HERE(); + mts_debug_dump(desc); + atomic_set(&desc->context.do_abort,1); +} + +static inline void mts_urb_abort(struct mts_desc* desc) { + MTS_DEBUG_GOT_HERE(); + mts_debug_dump(desc); + if ( desc->urb.status == USB_ST_URB_PENDING ) { + usb_unlink_urb( &desc->urb ); + } +} + +static inline void mts_wait_abort(struct mts_desc* desc) +{ + mts_request_abort(desc); + + while( !atomic_read(&desc->lock.count) ) { +/* Is there a function to check if the semaphore is locked? */ + schedule_timeout( MTS_ABORT_TIMEOUT ); + MTS_DEBUG_GOT_HERE(); + mts_urb_abort(desc); + } + +} + + +static struct mts_desc * mts_list; /* list of active scanners */ +struct semaphore mts_list_semaphore; + +/* Internal list operations */ + +static +void mts_remove_nolock( struct mts_desc* to_remove ) +{ + MTS_DEBUG( "removing 0x%x from list\n", + (int)to_remove ); + + mts_wait_abort(to_remove); + + down( &to_remove->lock ); + + MTS_DEBUG_GOT_HERE(); + + if ( to_remove != mts_list ) { + MTS_DEBUG_GOT_HERE(); + if (to_remove->prev && to_remove->next) + to_remove->prev->next = to_remove->next; + } else { + MTS_DEBUG_GOT_HERE(); + mts_list = to_remove->next; + if (mts_list) { + MTS_DEBUG_GOT_HERE(); + mts_list->prev = 0; + } + } + + if ( to_remove->next ) { + MTS_DEBUG_GOT_HERE(); + to_remove->next->prev = to_remove->prev; + } + + MTS_DEBUG_GOT_HERE(); + scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl)); + + kfree( to_remove ); +} + +static +void mts_add_nolock( struct mts_desc* to_add ) +{ + MTS_DEBUG( "adding 0x%x to list\n", (int)to_add ); + + to_add->prev = 0; + to_add->next = mts_list; + if ( mts_list ) { + mts_list->prev = to_add; + } + + mts_list = to_add; +} + + + + +/* SCSI driver interface */ + +/* scsi related functions - dummies for now mostly */ + +static int mts_scsi_release(struct Scsi_Host *psh) +{ + MTS_DEBUG_GOT_HERE(); + + return 0; +} + +static int mts_scsi_abort (Scsi_Cmnd *srb) +/* interrupt context (!) */ +{ + struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); + + MTS_DEBUG_GOT_HERE(); + + mts_request_abort(desc); + mts_urb_abort(desc); + + return SCSI_ABORT_PENDING; +} + +static int mts_scsi_host_reset (Scsi_Cmnd *srb) +{ + struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); + + MTS_DEBUG_GOT_HERE(); + mts_debug_dump(desc); + + usb_reset_device(desc->usb_dev); + return 0; /* RANT why here 0 and not SUCCESS */ +} + +/* the core of the scsi part */ + +/* faking a detection - which can't fail :-) */ + +static int mts_scsi_detect (struct SHT * sht) +{ + /* Whole function stolen from usb-storage */ + + struct mts_desc * desc = (struct mts_desc *)sht->proc_dir; + /* What a hideous hack! */ + + char local_name[48]; + + MTS_DEBUG_GOT_HERE(); + + /* set up the name of our subdirectory under /proc/scsi/ */ + sprintf(local_name, "microtek-%d", desc->host_number); + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); + /* FIXME: where is this freed ? */ + + if (!sht->proc_name) { + MTS_ERROR( "unable to allocate memory for proc interface!!\n" ); + return 0; + } + + strcpy(sht->proc_name, local_name); + + sht->proc_dir = NULL; + + /* In host->hostdata we store a pointer to desc */ + desc->host = scsi_register(sht, sizeof(desc)); + desc->host->hostdata[0] = (unsigned long)desc; +/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */ + + return 1; +} + + + +/* Main entrypoint: SCSI commands are dispatched to here */ + + + +static +int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ); + +static void mts_transfer_cleanup( struct urb *transfer ); + + +inline static +void mts_int_submit_urb (struct urb* transfer, + int pipe, + void* data, + unsigned length, + mts_usb_urb_callback callback ) +/* Interrupt context! */ + +/* Holding transfer->context->lock! */ +{ + int res; + struct mts_transfer_context* context; + + MTS_INT_INIT(); + + FILL_BULK_URB(transfer, + context->instance->usb_dev, + pipe, + data, + length, + callback, + context + ); + +/* transfer->transfer_flags = USB_DISABLE_SPD;*/ + transfer->transfer_flags = USB_ASYNC_UNLINK; + transfer->status = 0; + transfer->timeout = 100; + + res = usb_submit_urb( transfer ); + if ( res ) { + MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); + context->srb->result = DID_ERROR << 16; + context->state = mts_con_error; + mts_transfer_cleanup(transfer); + } + return; +} + + +static void mts_transfer_cleanup( struct urb *transfer ) +/* Interrupt context! */ +{ + struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; + + up( &context->instance->lock ); + if ( context->final_callback ) + context->final_callback(context->srb); + +} + +static void mts_transfer_done( struct urb *transfer ) +{ + struct mts_transfer_context* context; + + MTS_INT_INIT(); + + context->srb->result &= MTS_MAX_CHUNK_MASK; + context->srb->result |= (unsigned)context->status<<1; + + mts_transfer_cleanup(transfer); + + return; +} + + +static void mts_get_status( struct urb *transfer ) +/* Interrupt context! */ +{ + struct mts_transfer_context* context; + + MTS_INT_INIT(); + + context->state = mts_con_status; + + mts_int_submit_urb(transfer, + usb_rcvbulkpipe(context->instance->usb_dev, + context->instance->ep_response), + &context->status, + 1, + mts_transfer_done ); + + + return; +} + +static void mts_data_done( struct urb* transfer ) +/* Interrupt context! */ +{ + struct mts_transfer_context* context; + + MTS_INT_INIT(); + + if ( context->data_length != transfer->actual_length ) { + context->srb->resid = context->data_length - transfer->actual_length; + } else if ( transfer->status ) { + context->srb->result = DID_ERROR<<16; + } + + mts_get_status(transfer); + + return; +} + + +static void mts_command_done( struct urb *transfer ) +/* Interrupt context! */ +{ + struct mts_transfer_context* context; + + MTS_INT_INIT(); + + if ( transfer->status ) { + context->srb->result = DID_ERROR<<16; + mts_transfer_cleanup(transfer); + + return; + } + + if ( context->data ) { + context->state = mts_con_data; + mts_int_submit_urb(transfer, + context->data_pipe, + context->data, + context->data_length, + mts_data_done); + } else mts_get_status(transfer); + + return; +} + + + + static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 }; + static const u8 mts_read_image_sig_len = 4; + static const unsigned char mts_direction[256/8] = { + 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, + 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + +#define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1) + +static void +mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) +{ + + int pipe; + + + MTS_DEBUG_GOT_HERE(); + + desc->context.instance = desc; + desc->context.srb = srb; + desc->context.state = mts_con_command; + atomic_set(&desc->context.do_abort,0); + + if ( !srb->bufflen ){ + desc->context.data = 0; + desc->context.data_length = 0; + return; + } else { + desc->context.data = srb->buffer; + desc->context.data_length = srb->bufflen; + } + + /* can't rely on srb->sc_data_direction */ + + /* Brutally ripped from usb-storage */ + + if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len ) +) { pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image); + MTS_DEBUG( "transfering from desc->ep_image == %d\n", + (int)desc->ep_image ); + } else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) { + pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response); + MTS_DEBUG( "transfering from desc->ep_response == %d\n", + (int)desc->ep_response); + } else { + MTS_DEBUG("transfering to desc->ep_out == %d\n", + (int)desc->ep_out); + pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out); + } + desc->context.data_pipe = pipe; +} + + +static +int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) +{ + struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]); + int err = 0; + int res; + + MTS_DEBUG_GOT_HERE(); + mts_show_command(srb); + mts_debug_dump(desc); + + if ( srb->device->lun || srb->device->id || srb->device->channel ) { + + MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel ); + + MTS_DEBUG("this device doesn't exist\n"); + + srb->result = DID_BAD_TARGET << 16; + + if(callback) + callback(srb); + + goto out; + } + + down(&desc->lock); + + MTS_DEBUG_GOT_HERE(); + mts_show_command(srb); + + + FILL_BULK_URB(&desc->urb, + desc->usb_dev, + usb_sndbulkpipe(desc->usb_dev,desc->ep_out), + srb->cmnd, + srb->cmd_len, + mts_command_done, + &desc->context + ); + + + mts_build_transfer_context( srb, desc ); + desc->context.final_callback = callback; + desc->urb.timeout = 100; + desc->urb.transfer_flags = USB_ASYNC_UNLINK; + +/* desc->urb.transfer_flags = USB_DISABLE_SPD;*/ + + res=usb_submit_urb(&desc->urb); + + if(res){ + MTS_ERROR("error %d submitting URB\n",(int)res); + srb->result = DID_ERROR << 16; + + if(callback) + callback(srb); + + goto out; + } + + MTS_DEBUG_GOT_HERE(); + + out: + return err; +} +/* + * this defines our 'host' + */ + +/* NOTE: This is taken from usb-storage, should be right. */ + + +static Scsi_Host_Template mts_scsi_host_template = { + name: "microtek", + detect: mts_scsi_detect, + release: mts_scsi_release, + command: 0, + queuecommand: mts_scsi_queuecommand, + + eh_abort_handler: mts_scsi_abort, + eh_device_reset_handler:0, + eh_bus_reset_handler: 0, + eh_host_reset_handler: mts_scsi_host_reset, + + can_queue: 1, + this_id: -1, + cmd_per_lun: 1, + present: 0, + unchecked_isa_dma: FALSE, + use_clustering: FALSE, + use_new_eh_code: TRUE, + emulated: TRUE +}; + + +/* USB layer driver interface implementation */ + +static void mts_usb_disconnect (struct usb_device *dev, void *ptr) +{ + struct mts_desc* to_remove = (struct mts_desc*)ptr; + + MTS_DEBUG_GOT_HERE(); + + /* leave the list - lock it */ + down(&mts_list_semaphore); + + mts_remove_nolock(to_remove); + + up(&mts_list_semaphore); +} + +struct vendor_product +{ + u16 idVendor; + u16 idProduct; + char* name; + enum + { + mts_sup_unknown=0, + mts_sup_alpha, + mts_sup_full + } + support_status; +} ; + + +/* These are taken from the msmUSB.inf file on the Windows driver CD */ +const static struct vendor_product mts_supported_products[] = +{ + { + 0x4ce, 0x300,"Phantom 336CX",mts_sup_unknown + }, + { + 0x5da, 0x94,"Phantom 336CX",mts_sup_unknown + }, + { + 0x5da, 0x99,"Scanmaker X6",mts_sup_alpha + }, + { + 0x5da, 0x9a,"Phantom C6",mts_sup_unknown + }, + { + 0x5da, 0xa0,"Phantom 336CX",mts_sup_unknown + }, + { + 0x5da, 0xa3,"ScanMaker V6USL",mts_sup_unknown + }, + { + 0x5da, 0x80a3,"ScanMaker V6USL",mts_sup_unknown + }, + { + 0x5da, 0x80ac,"Scanmaker V6UL",mts_sup_unknown + } +} +; +const static struct vendor_product* mts_last_product = &mts_supported_products[ sizeof(mts_supported_products) / sizeof(struct vendor_product) ]; + /* Must never be derefed, points to one after last entry */ + + +static void * mts_usb_probe (struct usb_device *dev, unsigned int interface) +{ + int i; + int result; + int ep_out = -1; + int ep_in_set[3]; /* this will break if we have more than three endpoints + which is why we check */ + int *ep_in_current = ep_in_set; + + struct mts_desc * new_desc; + struct vendor_product const* p; + + /* the altsettting 0 on the interface we're probing */ + struct usb_interface_descriptor *altsetting; + + MTS_DEBUG_GOT_HERE(); + MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev ); + + MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n", + (int)dev->descriptor.idProduct, + (int)dev->descriptor.idVendor ); + + MTS_DEBUG_GOT_HERE(); + + /* checking IDs */ + for( p = mts_supported_products; p != mts_last_product; p++ ) + if ( dev->descriptor.idVendor == p->idVendor && + dev->descriptor.idProduct == p->idProduct ) + goto is_supported; + else + MTS_DEBUG( "doesn't appear to be model %s\n", p->name ); + + MTS_DEBUG( "returning NULL: unsupported\n" ); + + return NULL; + + is_supported: + + MTS_DEBUG_GOT_HERE(); + + MTS_DEBUG( "found model %s\n", p->name ); + if ( p->support_status != mts_sup_full ) + MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", + p->name ); + + /* the altsettting 0 on the interface we're probing */ + altsetting = + &(dev->actconfig->interface[interface].altsetting[0]); + + + /* Check if the config is sane */ + + if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) { + MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n", + (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints ); + return NULL; + } + + for( i = 0; i < altsetting->bNumEndpoints; i++ ) { + if ((altsetting->endpoint[i].bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { + + MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n", + (int)altsetting->endpoint[i].bEndpointAddress ); + } else { + if (altsetting->endpoint[i].bEndpointAddress & + USB_DIR_IN) + *ep_in_current++ + = altsetting->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + else { + if ( ep_out != -1 ) { + MTS_WARNING( "can only deal with one output endpoints. Bailing out." ); + return NULL; + } + + ep_out = altsetting->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + } + + } + + + if ( ep_out == -1 ) { + MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); + return NULL; + } + + + /* I don't understand the following fully (it's from usb-storage) -- John */ + + /* set the interface -- STALL is an acceptable response here */ + result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); + + MTS_DEBUG("usb_set_interface returned %d.\n",result); + switch( result ) + { + case 0: /* no error */ + break; + + case -EPIPE: + usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); + MTS_DEBUG( "clearing clearing stall on control interface\n" ); + break; + + default: + MTS_DEBUG( "unknown error %d from usb_set_interface\n", + (int)result ); + return NULL; + } + + + /* allocating a new descriptor */ + new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL); + if (new_desc == NULL) + { + MTS_ERROR("couldn't allocate scanner desc, bailing out!\n"); + return NULL; + } + + /* As done by usb_alloc_urb */ + memset( new_desc, 0, sizeof(*new_desc) ); + spin_lock_init(&new_desc->urb.lock); + + + /* initialising that descriptor */ + new_desc->usb_dev = dev; + new_desc->interface = interface; + + init_MUTEX(&new_desc->lock); + + if(mts_list){ + new_desc->host_number = mts_list->host_number+1; + } else { + new_desc->host_number = 0; + } + + /* endpoints */ + + new_desc->ep_out = ep_out; + new_desc->ep_response = ep_in_set[0]; + new_desc->ep_image = ep_in_set[1]; + + + if ( new_desc->ep_out != MTS_EP_OUT ) + MTS_WARNING( "will this work? Command EP is not usually %d\n", + (int)new_desc->ep_out ); + + if ( new_desc->ep_response != MTS_EP_RESPONSE ) + MTS_WARNING( "will this work? Response EP is not usually %d\n", + (int)new_desc->ep_response ); + + if ( new_desc->ep_image != MTS_EP_IMAGE ) + MTS_WARNING( "will this work? Image data EP is not usually %d\n", + (int)new_desc->ep_image ); + + + /* Initialize the host template based on the default one */ + memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template)); + /* HACK from usb-storage - this is needed for scsi detection */ + (struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */ + + MTS_DEBUG("registering SCSI module\n"); + + new_desc->ctempl.module = THIS_MODULE; + result = scsi_register_module(MODULE_SCSI_HA, &(new_desc->ctempl)); + /* Will get hit back in microtek_detect by this func */ + if ( result ) + { + MTS_ERROR( "error %d from scsi_register_module! Help!\n", + (int)result ); + + /* FIXME: need more cleanup? */ + kfree( new_desc ); + return NULL; + } + MTS_DEBUG_GOT_HERE(); + + /* FIXME: the bomb is armed, must the host be registered under lock ? */ + /* join the list - lock it */ + down(&mts_list_semaphore); + + mts_add_nolock( new_desc ); + + up(&mts_list_semaphore); + + + MTS_DEBUG("completed probe and exiting happily\n"); + + return (void *)new_desc; +} + + + +/* get us noticed by the rest of the kernel */ + +int __init microtek_drv_init(void) +{ + int result; + + MTS_DEBUG_GOT_HERE(); + init_MUTEX(&mts_list_semaphore); + + if ((result = usb_register(&mts_usb_driver)) < 0) { + MTS_DEBUG("usb_register returned %d\n", result ); + return -1; + } else { + MTS_DEBUG("driver registered.\n"); + } + + return 0; +} + +void __exit microtek_drv_exit(void) +{ + struct mts_desc* next; + + MTS_DEBUG_GOT_HERE(); + + usb_deregister(&mts_usb_driver); + + down(&mts_list_semaphore); + + while (mts_list) { + /* keep track of where the next one is */ + next = mts_list->next; + + mts_remove_nolock( mts_list ); + + /* advance the list pointer */ + mts_list = next; + } + + up(&mts_list_semaphore); +} + +module_init(microtek_drv_init); +module_exit(microtek_drv_exit); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/microtek.h linux.ac/drivers/usb/microtek.h --- linux.vanilla/drivers/usb/microtek.h Thu Jan 1 01:00:00 1970 +++ linux.ac/drivers/usb/microtek.h Mon Jun 5 20:21:17 2000 @@ -0,0 +1,73 @@ + /* + * Driver for Microtek Scanmaker X6 USB scanner and possibly others. + * + * (C) Copyright 2000 John Fremlin + * (C) Copyright 2000 Oliver Neukum + * + * See microtek.c for history + * + */ + +typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *); +typedef void (*mts_usb_urb_callback) (struct urb *); + + +struct mts_transfer_context +{ + struct mts_desc* instance; + mts_scsi_cmnd_callback final_callback; + Scsi_Cmnd *srb; + + void* data; + unsigned data_length; + int data_pipe; + + enum { + mts_con_none, + mts_con_command, + mts_con_data, + mts_con_status, + mts_con_error, + mts_con_done + } + state; + + atomic_t do_abort; /* when != 0 URB completion routines will + return straightaway */ + + u8 status; /* status returned from ep_response after command completion */ +}; + + +struct mts_desc { + struct mts_desc *next; + struct mts_desc *prev; + + struct usb_device *usb_dev; + + int interface; + + /* Endpoint addresses */ + u8 ep_out; + u8 ep_response; + u8 ep_image; + + struct Scsi_Host * host; + Scsi_Host_Template ctempl; + int host_number; + + struct semaphore lock; + + struct urb urb; + struct mts_transfer_context context; +}; + + +#define MTS_EP_OUT 0x1 +#define MTS_EP_RESPONSE 0x2 +#define MTS_EP_IMAGE 0x3 +#define MTS_EP_TOTAL 0x3 + +#define MTS_MAX_CHUNK_MASK ~0x3fu +/*maximum amount the scanner will transmit at once */ + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/mousedev.c linux.ac/drivers/usb/mousedev.c --- linux.vanilla/drivers/usb/mousedev.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/mousedev.c Tue May 30 21:28:07 2000 @@ -1,7 +1,7 @@ /* - * mousedev.c Version 0.1 + * $Id: mousedev.c,v 1.8 2000/05/28 17:31:36 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * Input driver to PS/2 or ImPS/2 device driver module. * @@ -138,8 +138,7 @@ list->ready = 1; - if (list->fasync) - kill_fasync(list->fasync, SIGIO, POLL_IN); + kill_fasync(&list->fasync, SIGIO, POLL_IN); list = list->next; } @@ -311,8 +310,7 @@ list->buffer = list->bufsiz; } - if (list->fasync) - kill_fasync(list->fasync, SIGIO, POLL_IN); + kill_fasync(&list->fasync, SIGIO, POLL_IN); wake_up_interruptible(&list->mousedev->wait); @@ -421,7 +419,7 @@ if (mousedev_mix.open) input_open_device(&mousedev->handle); - printk("mouse%d: PS/2 mouse device for input%d\n", minor, dev->number); + printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number); return &mousedev->handle; } @@ -459,7 +457,7 @@ mousedev_mix.minor = MOUSEDEV_MIX; mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); - printk("mice: PS/2 mouse device common for all mice\n"); + printk(KERN_INFO "mice: PS/2 mouse device common for all mice\n"); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/pegasus.c linux.ac/drivers/usb/pegasus.c --- linux.vanilla/drivers/usb/pegasus.c Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/pegasus.c Fri Jun 9 19:21:54 2000 @@ -16,7 +16,7 @@ #include -static const char *version = __FILE__ ": v0.3.12 2000/05/22 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n"; +static const char *version = __FILE__ ": v0.3.14 2000/06/09 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n"; #define PEGASUS_MTU 1500 @@ -64,8 +64,11 @@ {"D-Link DSB-650TX", 0x2001, 0x4001, NULL}, {"D-Link DSB-650TX", 0x2001, 0x4002, NULL}, {"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, NULL}, + {"D-Link DU-10", 0x07b8, 0xabc1, NULL}, + {"D-Link DU-E100", 0x07b8, 0x4002, NULL}, {"Linksys USB100TX", 0x066b, 0x2203, NULL}, {"Linksys USB100TX", 0x066b, 0x2204, NULL}, + {"Linksys USB Ethernet Adapter", 0x066b, 0x2206, NULL}, {"SMC 202 USB Ethernet", 0x0707, 0x0200, NULL}, {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, NULL}, {"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, NULL}, @@ -80,8 +83,8 @@ #define pegasus_set_registers(dev, indx, size, data)\ usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, 0, indx, data, size, HZ); #define pegasus_set_register(dev, indx, value) \ - { __u8 data = value; \ - usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, data, indx, &data, 1, HZ);} + { __u8 __data = value; \ + usb_control_msg(dev, usb_sndctrlpipe(dev,0), 0xf1, 0x40, __data, indx, &__data, 1, HZ);} static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regdata) @@ -223,7 +226,7 @@ __u16 pkt_len; if (urb->status) { - info("%s: RX status %d", net->name, urb->status); + dbg("%s: RX status %d", net->name, urb->status); goto goon; } @@ -369,9 +372,12 @@ netif_stop_queue(net); - usb_unlink_urb(&pegasus->rx_urb); - usb_unlink_urb(&pegasus->tx_urb); - usb_unlink_urb(&pegasus->intr_urb); + if ( pegasus->rx_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->rx_urb); + if ( pegasus->tx_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->tx_urb); + if ( pegasus->intr_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->intr_urb); MOD_DEC_USE_COUNT; @@ -510,9 +516,12 @@ unregister_netdev(pegasus->net); - usb_unlink_urb(&pegasus->rx_urb); - usb_unlink_urb(&pegasus->tx_urb); - usb_unlink_urb(&pegasus->intr_urb); + if ( pegasus->rx_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->rx_urb); + if ( pegasus->tx_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->tx_urb); + if ( pegasus->intr_urb.status == -EINPROGRESS ) + usb_unlink_urb(&pegasus->intr_urb); kfree(pegasus); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/printer.c linux.ac/drivers/usb/printer.c --- linux.vanilla/drivers/usb/printer.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/printer.c Thu Jun 8 15:14:02 2000 @@ -1,9 +1,10 @@ /* - * printer.c Version 0.4 + * printer.c Version 0.5 * - * Copyright (c) 1999 Michael Gee - * Copyright (c) 1999 Pavel Machek - * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 1999 Michael Gee + * Copyright (c) 1999 Pavel Machek + * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000 Randy Dunlap * * USB Printer Device Class driver for USB printers and printer cables * @@ -14,6 +15,7 @@ * v0.2 - some more cleanups * v0.3 - cleaner again, waitqueue fixes * v0.4 - fixes in unidirectional mode + * v0.5 - add DEVICE_ID string support */ /* @@ -44,6 +46,18 @@ #include #define USBLP_BUF_SIZE 8192 +#define DEVICE_ID_SIZE 1024 + +#define IOCNR_GET_DEVICE_ID 1 +#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */ + +/* + * A DEVICE_ID string may include the printer's serial number. + * It should end with a semi-colon (';'). + * An example from an HP 970C DeskJet printer is (this is one long string, + * with the serial number changed): +MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ: ; + */ /* * USB Printer Requests @@ -67,6 +81,8 @@ int minor; /* minor number of device */ unsigned char used; /* True if open */ unsigned char bidir; /* interface is bidirectional */ + unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ + /* first 2 bytes are (big-endian) length */ }; static struct usblp *usblp_table[USBLP_MINORS] = { NULL, /* ... */ }; @@ -75,21 +91,22 @@ * Functions for usblp control messages. */ -static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, void *buf, int len) +static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len) { int retval = usb_control_msg(usblp->dev, dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), - request, USB_TYPE_CLASS | dir | recip, 0, usblp->ifnum, buf, len, HZ * 5); - dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d len: %#x result: %d", request, !!dir, recip, len, retval); + request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5); + dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d", + request, !!dir, recip, value, len, retval); return retval < 0 ? retval : 0; } #define usblp_read_status(usblp, status)\ - usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, status, 1) -#define usblp_get_id(usblp, id, maxlen)\ - usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, id, maxlen) + usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1) +#define usblp_get_id(usblp, config, id, maxlen)\ + usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen) #define usblp_reset(usblp)\ - usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, NULL, 0) + usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0) /* * URB callback. @@ -122,7 +139,6 @@ } if (status & LP_PERRORP) { - if (status & LP_POUTPA) { info("usblp%d: out of paper", usblp->minor); return -ENOSPC; @@ -197,6 +213,7 @@ } usblp_table[usblp->minor] = NULL; + kfree(usblp->device_id_string); kfree(usblp); MOD_DEC_USE_COUNT; @@ -212,6 +229,34 @@ | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM); } +static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int length; + struct usblp *usblp = file->private_data; + + if ((_IOC_TYPE(cmd) != 'P') || (_IOC_DIR(cmd) != _IOC_READ)) + return -EINVAL; + + switch (_IOC_NR(cmd)) { + case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ + length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */ +#if 0 + dbg ("usblp_ioctl GET_DEVICE_ID: actlen=%d, user size=%d, string='%s'", + length, _IOC_SIZE(cmd), &usblp->device_id_string[2]); +#endif + if (length > _IOC_SIZE(cmd)) + length = _IOC_SIZE(cmd); /* truncate */ + if (copy_to_user ((unsigned char *)arg, usblp->device_id_string, (unsigned long) length)) + return -EFAULT; + break; + + default: + return -EINVAL; + } + + return 0; +} + static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct usblp *usblp = file->private_data; @@ -318,6 +363,7 @@ struct usb_endpoint_descriptor *epread, *epwrite; struct usblp *usblp; int minor, i, alts = -1, bidir = 0; + int length, err; char *buf; for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) { @@ -386,6 +432,13 @@ return NULL; } + if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) { + err("out of memory"); + kfree(usblp); + kfree(buf); + return NULL; + } + FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), buf, 0, usblp_bulk, usblp); @@ -393,6 +446,27 @@ FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp); + /* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */ + err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1); + if (err >= 0) { + length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */ + if (length < DEVICE_ID_SIZE) + usblp->device_id_string[length] = '\0'; + else + usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0'; + dbg ("usblp%d Device ID string [%d]=%s", + minor, length, &usblp->device_id_string[2]); + } + else { + err ("usblp%d: error = %d reading IEEE-1284 Device ID string", + minor, err); + usblp->device_id_string[0] = usblp->device_id_string[1] = '\0'; + } + +#ifdef DEBUG + usblp_check_status(usblp); +#endif + info("usblp%d: USB %sdirectional printer dev %d if %d alt %d", minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts); @@ -418,6 +492,8 @@ if (usblp->used) return; + kfree(usblp->device_id_string); + usblp_table[usblp->minor] = NULL; kfree(usblp); } @@ -425,9 +501,10 @@ static struct file_operations usblp_fops = { read: usblp_read, write: usblp_write, + poll: usblp_poll, + ioctl: usblp_ioctl, open: usblp_open, release: usblp_release, - poll: usblp_poll, }; static struct usb_driver usblp_driver = { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/scanner.c linux.ac/drivers/usb/scanner.c --- linux.vanilla/drivers/usb/scanner.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/scanner.c Sun Jun 4 22:20:40 2000 @@ -1,7 +1,7 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.3.99-pre6-3) + * Driver for USB Scanners (linux-2.4.0test1-ac7) * * Copyright (C) 1999, 2000 David E. Nelson * @@ -192,6 +192,12 @@ * scanner lookup/ident table. Thanks Randy. * - Documentation updates. * - Added wait queues to read_scanner(). + * + * + * 0.4.3.1 + * + * - Fixed HP S20 ID's...again..sigh. Thanks to Ruud + * Linders . * * * TODO diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/scanner.h linux.ac/drivers/usb/scanner.h --- linux.vanilla/drivers/usb/scanner.h Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/scanner.h Sat Jun 10 22:49:46 2000 @@ -1,5 +1,5 @@ /* - * Driver for USB Scanners (linux-2.3.99-pre6-3) + * Driver for USB Scanners (linux-2.4.0test1-ac7) * * Copyright (C) 1999, 2000 David E. Nelson * @@ -118,7 +118,7 @@ { 0x03f0, 0x0205 }, /* 3300C */ { 0x03f0, 0x0101 }, /* 4100C */ { 0x03f0, 0x0105 }, /* 4200C */ - { 0x03f0, 0x0202 }, /* PhotoSmart S20 */ + { 0x03f0, 0x0102 }, /* PhotoSmart S20 */ { 0x03f0, 0x0401 }, /* 5200C */ { 0x03f0, 0x0201 }, /* 6200C */ { 0x03f0, 0x0601 }, /* 6300C */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/serial/digi_acceleport.c linux.ac/drivers/usb/serial/digi_acceleport.c --- linux.vanilla/drivers/usb/serial/digi_acceleport.c Thu May 25 17:38:17 2000 +++ linux.ac/drivers/usb/serial/digi_acceleport.c Thu Jun 8 17:52:17 2000 @@ -14,24 +14,75 @@ * Peter Berger (pberger@brimson.com) * Al Borchers (borchers@steinerpoint.com) * +* (6/4/2000) pberger and borchers +* -- Replaced separate calls to spin_unlock_irqrestore and +* interruptible_sleep_on_interruptible with a new function +* cond_wait_interruptible_timeout_irqrestore. This eliminates +* the race condition where the wake up could happen after +* the unlock and before the sleep. +* -- Close now waits for output to drain. +* -- Open waits until any close in progress is finished. +* -- All out of band responses are now processed, not just the +* first in a USB packet. +* -- Fixed a bug that prevented the driver from working when the +* first Digi port was not the first USB serial port--the driver +* was mistakenly using the external USB serial port number to +* try to index into its internal ports. +* -- Fixed an SMP bug -- write_bulk_callback is called directly from +* an interrupt, so spin_lock_irqsave/spin_unlock_irqrestore are +* needed for locks outside write_bulk_callback that are also +* acquired by write_bulk_callback to prevent deadlocks. +* -- Fixed support for select() by making digi_chars_in_buffer() +* return 256 when -EINPROGRESS is set, as the line discipline +* code in n_tty.c expects. +* -- Fixed an include file ordering problem that prevented debugging +* messages from working. +* -- Fixed an intermittent timeout problem that caused writes to +* sometimes get stuck on some machines on some kernels. It turns +* out in these circumstances write_chan() (in n_tty.c) was +* asleep waiting for our wakeup call. Even though we call +* wake_up_interruptible() in digi_write_bulk_callback(), there is +* a race condition that could cause the wakeup to fail: if our +* wake_up_interruptible() call occurs between the time that our +* driver write routine finishes and write_chan() sets current->state +* to TASK_INTERRUPTIBLE, the effect of our wakeup setting the state +* to TASK_RUNNING will be lost and write_chan's subsequent call to +* schedule() will never return (unless it catches a signal). +* This race condition occurs because write_bulk_callback() (and thus +* the wakeup) are called asynchonously from an interrupt, rather than +* from the scheduler. We can avoid the race by calling the wakeup +* from the scheduler queue and that's our fix: Now, at the end of +* write_bulk_callback() we queue up a wakeup call on the scheduler +* task queue. We still also invoke the wakeup directly since that +* squeezes a bit more performance out of the driver, and any lost +* race conditions will get cleaned up at the next scheduler run. +* +* NOTE: The problem also goes away if you comment out +* the two code lines in write_chan() where current->state +* is set to TASK_RUNNING just before calling driver.write() and to +* TASK_INTERRUPTIBLE immediately afterwards. This is why the +* problem did not show up with the 2.2 kernels -- they do not +* include that code. +* * (5/16/2000) pberger and borchers -* -- added timeouts to sleeps -* -- handle transition to/from B0 in digi_set_termios +* -- Added timeouts to sleeps, to defend against lost wake ups. +* -- Handle transition to/from B0 baud rate in digi_set_termios. * * (5/13/2000) pberger and borchers -* -- all commands now sent on out of band port, using digi_write_oob -* -- get modem control signals whenever they change, support TIOCMGET/ -* SET/BIS/BIC ioctls +* -- All commands now sent on out of band port, using +* digi_write_oob_command. +* -- Get modem control signals whenever they change, support TIOCMGET/ +* SET/BIS/BIC ioctls. * -- digi_set_termios now supports parity, word size, stop bits, and -* receive enable -* -- cleaned up open and close, use digi_set_termios and digi_write_oob -* to set port parameters -* -- added digi_startup_device to start read chains on all ports -* -- write buffer is only used when count==1, to be sure put_char can -* write a char (unless the buffer is full) +* receive enable. +* -- Cleaned up open and close, use digi_set_termios and +* digi_write_oob_command to set port parameters. +* -- Added digi_startup_device to start read chains on all ports. +* -- Write buffer is only used when count==1, to be sure put_char can +* write a char (unless the buffer is full). * * (5/10/2000) pberger and borchers -* -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls +* -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls on open/close. * -- Fixed problem where the first incoming character is lost on * port opens after the first close on that port. Now we keep * the read_urb chain open until shutdown. @@ -43,7 +94,33 @@ * (5/3/2000) pberger and borchers * -- First alpha version of the driver--many known limitations and bugs. * -* $Id: digi_acceleport.c,v 1.43 2000/05/17 03:21:38 root Exp root $ +* +* Locking and SMP +* +* - Each port, including the out-of-band port, has a lock used to +* serialize all access to the port's private structure. +* - The port lock is also used to serialize all writes and access to +* the port's URB. +* - The port lock is also used for the port write_wait condition +* variable. Holding the port lock will prevent a wake up on the +* port's write_wait; this can be used with cond_wait_... to be sure +* the wake up is not lost in a race when dropping the lock and +* sleeping waiting for the wakeup. +* - digi_write() does not sleep, since it is sometimes called on +* interrupt time. +* - digi_write_bulk_callback() and digi_read_bulk_callback() are +* called directly from interrupts. Hence spin_lock_irqsave() +* and spin_lock_irqrestore() are used in the rest of the code +* for any locks they acquire. +* - digi_write_bulk_callback() gets the port lock before waking up +* processes sleeping on the port write_wait. It also schedules +* wake ups so they happen from the scheduler, because the tty +* system can miss wake ups from interrupts. +* - All sleeps use a timeout of DIGI_RETRY_TIMEOUT before looping to +* recheck the condition they are sleeping on. This is defensive, +* in case a wake up is lost. +* +* $Id: digi_acceleport.c,v 1.56 2000/06/07 22:47:30 root Exp root $ */ #include @@ -60,8 +137,7 @@ #include #include #include -#include -#include "usb-serial.h" +#include #ifdef CONFIG_USB_SERIAL_DEBUG #define DEBUG @@ -69,16 +145,25 @@ #undef DEBUG #endif +#include +#include "usb-serial.h" + /* Defines */ /* port buffer length -- must be <= transfer buffer length - 2 */ /* so we can be sure to send the full buffer in one urb */ -#define DIGI_PORT_BUF_LEN 16 +#define DIGI_PORT_BUF_LEN 8 -/* retry timeout while waiting for urb->status to go to 0 */ +/* retry timeout while sleeping */ #define DIGI_RETRY_TIMEOUT (HZ/10) +/* timeout while waiting for tty output to drain in close */ +/* this delay is used twice in close, so the total delay could */ +/* be twice this value */ +#define DIGI_CLOSE_TIMEOUT (5*HZ) + + /* AccelePort USB Defines */ /* ids */ @@ -173,6 +258,9 @@ #define DIGI_FLUSH_RX 2 #define DIGI_RESUME_TX 4 /* clears xoff condition */ +#define DIGI_TRANSMIT_NOT_IDLE 0 +#define DIGI_TRANSMIT_IDLE 1 + #define DIGI_DISABLE 0 #define DIGI_ENABLE 1 @@ -211,18 +299,29 @@ /* Structures */ typedef struct digi_private { + int dp_port_num; spinlock_t dp_port_lock; int dp_buf_len; unsigned char dp_buf[DIGI_PORT_BUF_LEN]; unsigned int dp_modem_signals; + int dp_transmit_idle; + int dp_in_close; + wait_queue_head_t dp_close_wait; /* wait queue for close */ + struct tq_struct dp_tasks; } digi_private_t; /* Local Function Declarations */ -static int digi_write_oob( unsigned char *buf, int count ); +static void digi_wakeup_write( struct usb_serial_port *port ); +static void digi_wakeup_write_lock( struct usb_serial_port *port ); +static int digi_write_oob_command( unsigned char *buf, int count ); +static int digi_write_inb_command( struct usb_serial_port *port, + unsigned char *buf, int count ) __attribute__((unused)); static int digi_set_modem_signals( struct usb_serial_port *port, unsigned int modem_signals ); +static int digi_transmit_idle( struct usb_serial_port *port, + unsigned long timeout ); static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); static void digi_set_termios( struct usb_serial_port *port, @@ -241,22 +340,24 @@ static int digi_startup( struct usb_serial *serial ); static void digi_shutdown( struct usb_serial *serial ); static void digi_read_bulk_callback( struct urb *urb ); -static void digi_read_oob( struct urb *urb ); +static void digi_read_oob_callback( struct urb *urb ); /* Statics */ /* device info needed for the Digi serial converter */ -static __u16 digi_vendor_id = DIGI_VENDOR_ID; -static __u16 digi_product_id = DIGI_ID; +static u16 digi_vendor_id = DIGI_VENDOR_ID; +static u16 digi_product_id = DIGI_ID; /* out of band port */ static int oob_port_num; /* index of out-of-band port */ static struct usb_serial_port *oob_port; /* out-of-band port */ static int device_startup = 0; -/* startup lock -- used to by digi_startup_device */ -spinlock_t startup_lock; +spinlock_t startup_lock; /* used by startup_device */ + +static wait_queue_head_t modem_change_wait; +static wait_queue_head_t transmit_idle_wait; /* Globals */ @@ -292,7 +393,84 @@ /* Functions */ /* -* Digi Write OOB +* Cond Wait Interruptible Timeout Irqrestore +* +* Do spin_unlock_irqrestore and interruptible_sleep_on_timeout +* so that wake ups are not lost if they occur between the unlock +* and the sleep. In other words, spin_lock_irqrestore and +* interruptible_sleep_on_timeout are "atomic" with respect to +* wake ups. This is used to implement condition variables. +*/ + +static long cond_wait_interruptible_timeout_irqrestore( + wait_queue_head_t *q, long timeout, + spinlock_t *lock, unsigned long flags ) +{ + + wait_queue_t wait; + + + init_waitqueue_entry( &wait, current ); + + set_current_state( TASK_INTERRUPTIBLE ); + + add_wait_queue( q, &wait ); + + spin_unlock_irqrestore( lock, flags ); + + timeout = schedule_timeout(timeout); + + set_current_state( TASK_RUNNING ); + + remove_wait_queue( q, &wait ); + + return( timeout ); + +} + + +/* +* Digi Wakeup Write +* +* Wake up port, line discipline, and tty processes sleeping +* on writes. +*/ + +static void digi_wakeup_write_lock( struct usb_serial_port *port ) +{ + + unsigned long flags; + digi_private_t *priv = (digi_private_t *)(port->private); + + + spin_lock_irqsave( &priv->dp_port_lock, flags ); + digi_wakeup_write( port ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + +} + +static void digi_wakeup_write( struct usb_serial_port *port ) +{ + + struct tty_struct *tty = port->tty; + + + /* wake up port processes */ + wake_up_interruptible( &port->write_wait ); + + /* wake up line discipline */ + if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup ) + (tty->ldisc.write_wakeup)(tty); + + /* wake up other tty processes */ + wake_up_interruptible( &tty->write_wait ); + +} + + +/* +* Digi Write OOB Command * * Write commands on the out of band port. Commands are 4 * bytes each, multiple commands can be sent at once, and @@ -301,28 +479,29 @@ * a negative error returned by usb_submit_urb. */ -static int digi_write_oob( unsigned char *buf, int count ) +static int digi_write_oob_command( unsigned char *buf, int count ) { int ret = 0; int len; digi_private_t *oob_priv = (digi_private_t *)(oob_port->private); + unsigned long flags = 0; -dbg( "digi_write_oob: TOP: port=%d, count=%d", oob_port->number, count ); +dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count ); - spin_lock( &oob_priv->dp_port_lock ); + spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); while( count > 0 ) { while( oob_port->write_urb->status == -EINPROGRESS ) { - spin_unlock( &oob_priv->dp_port_lock ); - interruptible_sleep_on_timeout( &oob_port->write_wait, - DIGI_RETRY_TIMEOUT ); + cond_wait_interruptible_timeout_irqrestore( + &oob_port->write_wait, DIGI_RETRY_TIMEOUT, + &oob_priv->dp_port_lock, flags ); if( signal_pending(current) ) { return( -EINTR ); } - spin_lock( &oob_priv->dp_port_lock ); + spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); } /* len must be a multiple of 4, so commands are not split */ @@ -337,14 +516,106 @@ count -= len; buf += len; } else { - dbg( "digi_write_oob: usb_submit_urb failed, ret=%d", - ret ); + dbg( + "digi_write_oob_command: usb_submit_urb failed, ret=%d", + ret ); + break; + } + + } + + spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); + + return( ret ); + +} + + +/* +* Digi Write In Band Command +* +* Write commands on the given port. Commands are 4 +* bytes each, multiple commands can be sent at once, and +* no command will be split across USB packets. Returns 0 +* if successful, or a negative error returned by digi_write. +*/ + +static int digi_write_inb_command( struct usb_serial_port *port, + unsigned char *buf, int count ) +{ + + int ret = 0; + int len; + digi_private_t *priv = (digi_private_t *)(port->private); + unsigned char *data = port->write_urb->transfer_buffer; + unsigned long flags = 0; + + +dbg( "digi_write_inb_command: TOP: port=%d, count=%d", priv->dp_port_num, +count ); + + spin_lock_irqsave( &priv->dp_port_lock, flags ); + + while( count > 0 ) { + + while( port->write_urb->status == -EINPROGRESS ) { + cond_wait_interruptible_timeout_irqrestore( + &port->write_wait, DIGI_RETRY_TIMEOUT, + &priv->dp_port_lock, flags ); + if( signal_pending(current) ) { + return( -EINTR ); + } + spin_lock_irqsave( &priv->dp_port_lock, flags ); + } + + /* len must be a multiple of 4 and small enough to */ + /* guarantee the write will send all data (or none), */ + /* so commands are not split */ + len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len ); + if( len > 4 ) + len &= ~3; + + /* write any buffered data first */ + if( priv->dp_buf_len > 0 ) { + data[0] = DIGI_CMD_SEND_DATA; + data[1] = priv->dp_buf_len; + memcpy( data+2, priv->dp_buf, priv->dp_buf_len ); + memcpy( data+2+priv->dp_buf_len, buf, len ); + port->write_urb->transfer_buffer_length + = priv->dp_buf_len+2+len; + } else { + memcpy( data, buf, len ); + port->write_urb->transfer_buffer_length = len; + } + +#ifdef DEBUG_DATA + { + int i; + + printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=", + priv->dp_port_num, port->write_urb->transfer_buffer_length ); + for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { + printk( "%.2x ", + ((unsigned char *)port->write_urb->transfer_buffer)[i] ); + } + printk( "\n" ); + } +#endif + + if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { + priv->dp_buf_len = 0; + count -= len; + buf += len; + } else { + dbg( + "digi_write_inb_command: usb_submit_urb failed, ret=%d", + ret ); break; } } - spin_unlock( &oob_priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( ret ); @@ -369,35 +640,35 @@ unsigned char *data = oob_port->write_urb->transfer_buffer; digi_private_t *port_priv = (digi_private_t *)(port->private); digi_private_t *oob_priv = (digi_private_t *)(oob_port->private); + unsigned long flags = 0; dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", -port->number, modem_signals ); +port_priv->dp_port_num, modem_signals ); - spin_lock( &oob_priv->dp_port_lock ); - spin_lock( &port_priv->dp_port_lock ); + spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); + spin_lock_irqsave( &port_priv->dp_port_lock, flags ); while( oob_port->write_urb->status == -EINPROGRESS ) { - spin_unlock( &port_priv->dp_port_lock ); - spin_unlock( &oob_priv->dp_port_lock ); - interruptible_sleep_on_timeout( &oob_port->write_wait, - DIGI_RETRY_TIMEOUT ); + spin_unlock_irqrestore( &port_priv->dp_port_lock, flags ); + cond_wait_interruptible_timeout_irqrestore( + &oob_port->write_wait, DIGI_RETRY_TIMEOUT, + &oob_priv->dp_port_lock, flags ); if( signal_pending(current) ) { return( -EINTR ); } - spin_lock( &oob_priv->dp_port_lock ); - spin_lock( &port_priv->dp_port_lock ); + spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); + spin_lock_irqsave( &port_priv->dp_port_lock, flags ); } - /* command is 4 bytes: command, line, argument, pad */ data[0] = DIGI_CMD_SET_DTR_SIGNAL; - data[1] = port->number; + data[1] = port_priv->dp_port_num; data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; data[3] = 0; data[4] = DIGI_CMD_SET_RTS_SIGNAL; - data[5] = port->number; + data[5] = port_priv->dp_port_num; data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; data[7] = 0; @@ -413,18 +684,77 @@ ret ); } - spin_unlock( &port_priv->dp_port_lock ); - spin_unlock( &oob_priv->dp_port_lock ); + spin_unlock_irqrestore( &port_priv->dp_port_lock, flags ); + spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); return( ret ); } +/* +* Digi Transmit Idle +* +* Digi transmit idle waits, up to timeout ticks, for the transmitter +* to go idle. It returns 0 if successful or a negative error. +* +* There are race conditions here if more than one process is calling +* digi_transmit_idle on the same port at the same time. However, this +* is only called from close, and only one process can be in close on a +* port at a time, so its ok. +*/ + +static int digi_transmit_idle( struct usb_serial_port *port, + unsigned long timeout ) +{ + + int ret; + unsigned char buf[2]; + digi_private_t *priv = (digi_private_t *)(port->private); + unsigned long flags = 0; + + + spin_lock_irqsave( &priv->dp_port_lock, flags ); + priv->dp_transmit_idle = 0; + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + + buf[0] = DIGI_CMD_TRANSMIT_IDLE; + buf[1] = 0; + + if( (ret=digi_write_inb_command( port, buf, 2 )) != 0 ) + return( ret ); + + timeout += jiffies; + + spin_lock_irqsave( &priv->dp_port_lock, flags ); + + while( jiffies < timeout && !priv->dp_transmit_idle ) { + cond_wait_interruptible_timeout_irqrestore( + &transmit_idle_wait, DIGI_RETRY_TIMEOUT, + &priv->dp_port_lock, flags ); + if( signal_pending(current) ) { + return( -EINTR ); + } + spin_lock_irqsave( &priv->dp_port_lock, flags ); + } + + priv->dp_transmit_idle = 0; + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + + return( 0 ); + +} + + static void digi_rx_throttle( struct usb_serial_port *port ) { -dbg( "digi_rx_throttle: TOP: port=%d", port->number ); +#ifdef DEBUG + digi_private_t *priv = (digi_private_t *)(port->private); +#endif + + +dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num ); /* stop receiving characters. We just turn off the URB request, and let chars pile up in the device. If we're doing hardware @@ -441,7 +771,12 @@ static void digi_rx_unthrottle( struct usb_serial_port *port ) { -dbg( "digi_rx_unthrottle: TOP: port=%d", port->number ); +#ifdef DEBUG + digi_private_t *priv = (digi_private_t *)(port->private); +#endif + + +dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); /* just restart the receive interrupt URB */ //if (usb_submit_urb(port->interrupt_in_urb)) @@ -454,6 +789,7 @@ struct termios *old_termios ) { + digi_private_t *priv = (digi_private_t *)(port->private); unsigned int iflag = port->tty->termios->c_iflag; unsigned int cflag = port->tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; @@ -463,7 +799,7 @@ int i = 0; -dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", port->number, iflag, old_iflag, cflag, old_cflag ); +dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag ); /* set baud rate */ if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { @@ -506,7 +842,7 @@ if( arg != -1 ) { buf[i++] = DIGI_CMD_SET_BAUD_RATE; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } @@ -526,7 +862,7 @@ } buf[i++] = DIGI_CMD_SET_PARITY; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; @@ -550,7 +886,7 @@ if( arg != -1 ) { buf[i++] = DIGI_CMD_SET_WORD_SIZE; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } @@ -566,7 +902,7 @@ arg = DIGI_STOP_BITS_1; buf[i++] = DIGI_CMD_SET_STOP_BITS; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; @@ -589,7 +925,7 @@ arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS; buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; @@ -612,7 +948,7 @@ arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; @@ -627,13 +963,13 @@ arg = DIGI_DISABLE; buf[i++] = DIGI_CMD_RECEIVE_ENABLE; - buf[i++] = port->number; + buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } - if( (ret=digi_write_oob( buf, i )) != 0 ) + if( (ret=digi_write_oob_command( buf, i )) != 0 ) dbg( "digi_set_termios: write oob failed, ret=%d", ret ); } @@ -641,7 +977,14 @@ static void digi_break_ctl( struct usb_serial_port *port, int break_state ) { -dbg( "digi_break_ctl: TOP: port=%d", port->number ); + +#ifdef DEBUG + digi_private_t *priv = (digi_private_t *)(port->private); +#endif + + +dbg( "digi_break_ctl: TOP: port=%d", priv->dp_port_num ); + } @@ -651,16 +994,17 @@ digi_private_t *priv = (digi_private_t *)(port->private); unsigned int val; + unsigned long flags = 0; -dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", port->number, cmd ); +dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd ); switch (cmd) { case TIOCMGET: - spin_lock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); val = priv->dp_modem_signals; - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) ) return( -EFAULT ); return( 0 ); @@ -670,12 +1014,12 @@ case TIOCMBIC: if( copy_from_user(&val, (unsigned int *)arg, sizeof(int)) ) return( -EFAULT ); - spin_lock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); if( cmd == TIOCMBIS ) val = priv->dp_modem_signals | val; else if( cmd == TIOCMBIC ) val = priv->dp_modem_signals & ~val; - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( digi_set_modem_signals( port, val ) ); case TIOCMIWAIT: @@ -701,15 +1045,17 @@ int ret,data_len,new_len; digi_private_t *priv = (digi_private_t *)(port->private); + unsigned char *data = port->write_urb->transfer_buffer; + unsigned long flags = 0; dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%d", -port->number, count, from_user, in_interrupt() ); +priv->dp_port_num, count, from_user, in_interrupt() ); /* be sure only one write proceeds at a time */ /* there are races on the port private buffer */ /* and races to check write_urb->status */ - spin_lock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); /* wait for urb status clear to submit another urb */ if( port->write_urb->status == -EINPROGRESS ) { @@ -724,7 +1070,7 @@ new_len = 0; } - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( new_len ); @@ -736,43 +1082,41 @@ data_len = new_len + priv->dp_buf_len; if( data_len == 0 ) { - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( 0 ); } - *((unsigned char *)(port->write_urb->transfer_buffer)) - = (unsigned char)DIGI_CMD_SEND_DATA; - *((unsigned char *)(port->write_urb->transfer_buffer)+1) - = (unsigned char)data_len; - port->write_urb->transfer_buffer_length = data_len+2; + *data++ = DIGI_CMD_SEND_DATA; + *data++ = data_len; + /* copy in buffered data first */ - memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf, - priv->dp_buf_len ); + memcpy( data, priv->dp_buf, priv->dp_buf_len ); + data += priv->dp_buf_len; /* copy in new data */ if( from_user ) { - copy_from_user( - port->write_urb->transfer_buffer+2+priv->dp_buf_len, - buf, new_len ); + if( copy_from_user( data, buf, new_len ) ) { + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + return( -EFAULT ); + } } else { - memcpy( port->write_urb->transfer_buffer+2+priv->dp_buf_len, - buf, new_len ); + memcpy( data, buf, new_len ); } #ifdef DEBUG_DATA -{ + { int i; printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=", - port->number, port->write_urb->transfer_buffer_length ); + priv->dp_port_num, port->write_urb->transfer_buffer_length ); for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { printk( "%.2x ", ((unsigned char *)port->write_urb->transfer_buffer)[i] ); } printk( "\n" ); -} + } #endif if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { @@ -781,13 +1125,11 @@ } else { dbg( "digi_write: usb_submit_urb failed, ret=%d", ret ); - /* no bytes written - should we return the error code or 0? */ - ret = 0; } /* return length of new data written, or error */ dbg( "digi_write: returning %d", ret ); - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( ret ); } @@ -798,17 +1140,18 @@ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; - struct tty_struct *tty = port->tty; digi_private_t *priv = (digi_private_t *)(port->private); int ret; -dbg( "digi_write_bulk_callback: TOP: port=%d", port->number ); +dbg( "digi_write_bulk_callback: TOP: port=%d", priv->dp_port_num ); /* handle callback on out-of-band port */ - if( port->number == oob_port_num ) { + if( priv->dp_port_num == oob_port_num ) { dbg( "digi_write_bulk_callback: oob callback" ); + spin_lock( &priv->dp_port_lock ); wake_up_interruptible( &port->write_wait ); + spin_unlock( &priv->dp_port_lock ); return; } @@ -833,17 +1176,17 @@ priv->dp_buf_len ); #ifdef DEBUG_DATA -{ + { int i; printk( KERN_DEBUG __FILE__ ": digi_write_bulk_callback: port=%d, length=%d, data=", - port->number, port->write_urb->transfer_buffer_length ); + priv->dp_port_num, port->write_urb->transfer_buffer_length ); for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { printk( "%.2x ", ((unsigned char *)port->write_urb->transfer_buffer)[i] ); } printk( "\n" ); -} + } #endif if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { @@ -853,19 +1196,17 @@ } } - spin_unlock( &priv->dp_port_lock ); - /* wake up port processes */ - wake_up_interruptible( &port->write_wait ); + /* wake up processes sleeping on writes immediately */ + digi_wakeup_write( port ); - /* wake up line discipline */ - tty = port->tty; - if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) - && tty->ldisc.write_wakeup ) - (tty->ldisc.write_wakeup)(tty); + spin_unlock( &priv->dp_port_lock ); - /* wake up other tty processes */ - wake_up_interruptible( &tty->write_wait ); + /* also queue up a wakeup at scheduler time, in case we */ + /* lost the race in write_chan(). */ + priv->dp_tasks.routine = (void *)digi_wakeup_write_lock; + priv->dp_tasks.data = (void *)port; + queue_task( &(priv->dp_tasks), &tq_scheduler ); } @@ -875,20 +1216,21 @@ int room; digi_private_t *priv = (digi_private_t *)(port->private); + unsigned long flags = 0; -dbg( "digi_write_room: TOP: port=%d", port->number ); +dbg( "digi_write_room: TOP: port=%d", priv->dp_port_num ); - spin_lock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); if( port->write_urb->status == -EINPROGRESS ) room = 0; else room = port->bulk_out_size - 2 - priv->dp_buf_len; - spin_unlock( &priv->dp_port_lock ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); -dbg( "digi_write_room: port=%d, room=%d", port->number, room ); +dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room ); return( room ); } @@ -900,13 +1242,14 @@ digi_private_t *priv = (digi_private_t *)(port->private); -dbg( "digi_chars_in_buffer: TOP: port=%d", port->number ); +dbg( "digi_chars_in_buffer: TOP: port=%d", priv->dp_port_num ); if( port->write_urb->status == -EINPROGRESS ) { -dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, port->bulk_out_size - 2 ); - return( port->bulk_out_size - 2 ); +dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 ); + /* return( port->bulk_out_size - 2 ); */ + return( 256 ); } else { -dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, priv->dp_buf_len ); +dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_buf_len ); return( priv->dp_buf_len ); } @@ -916,43 +1259,66 @@ static int digi_open( struct usb_serial_port *port, struct file *filp ) { - int i = 0; int ret; unsigned char buf[32]; digi_private_t *priv = (digi_private_t *)(port->private); struct termios not_termios; + unsigned long flags = 0; -dbg( "digi_open: TOP: port %d, active:%d", port->number, port->active ); +dbg( "digi_open: TOP: port %d, active:%d", priv->dp_port_num, port->active ); /* be sure the device is started up */ if( digi_startup_device( port->serial ) != 0 ) return( -ENXIO ); - MOD_INC_USE_COUNT; - /* if port is already open, just return */ /* be sure exactly one open proceeds */ - spin_lock( &priv->dp_port_lock ); - if( port->active++ ) { - spin_unlock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); + if( port->active >= 1 && !priv->dp_in_close ) { + ++port->active; + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + MOD_INC_USE_COUNT; return( 0 ); } - spin_unlock( &priv->dp_port_lock ); + + /* don't wait on a close in progress for non-blocking opens */ + if( priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + return( -EAGAIN ); + } + + /* prevent other opens from proceeding, before giving up lock */ + ++port->active; + + /* wait for close to finish */ + while( priv->dp_in_close ) { + cond_wait_interruptible_timeout_irqrestore( + &priv->dp_close_wait, DIGI_RETRY_TIMEOUT, + &priv->dp_port_lock, flags ); + if( signal_pending(current) ) { + --port->active; + return( -EINTR ); + } + spin_lock_irqsave( &priv->dp_port_lock, flags ); + } + + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + MOD_INC_USE_COUNT; /* read modem signals automatically whenever they change */ - buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS; - buf[i++] = port->number; - buf[i++] = DIGI_ENABLE; - buf[i++] = 0; + buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; + buf[1] = priv->dp_port_num; + buf[2] = DIGI_ENABLE; + buf[3] = 0; /* flush fifos */ - buf[i++] = DIGI_CMD_IFLUSH_FIFO; - buf[i++] = port->number; - buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; - buf[i++] = 0; + buf[4] = DIGI_CMD_IFLUSH_FIFO; + buf[5] = priv->dp_port_num; + buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; + buf[7] = 0; - if( (ret=digi_write_oob( buf, i )) != 0 ) + if( (ret=digi_write_oob_command( buf, 8 )) != 0 ) dbg( "digi_open: write oob failed, ret=%d", ret ); /* set termios settings */ @@ -971,58 +1337,83 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) { - int i = 0; int ret; unsigned char buf[32]; + struct tty_struct *tty = port->tty; digi_private_t *priv = (digi_private_t *)(port->private); + unsigned long flags = 0; -dbg( "digi_close: TOP: port %d, active:%d", port->number, port->active ); +dbg( "digi_close: TOP: port %d, active:%d", priv->dp_port_num, port->active ); /* do cleanup only after final close on this port */ - spin_lock( &priv->dp_port_lock ); - if( --port->active ) { - spin_unlock( &priv->dp_port_lock ); + spin_lock_irqsave( &priv->dp_port_lock, flags ); + if( port->active > 1 ) { + --port->active; + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); MOD_DEC_USE_COUNT; return; + } else if( port->active <= 0 ) { + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + return; } - spin_unlock( &priv->dp_port_lock ); - + priv->dp_in_close = 1; + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + + /* tell line discipline to process only XON/XOFF */ + tty->closing = 1; + + /* wait for output to drain */ + if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { + tty_wait_until_sent( tty, DIGI_CLOSE_TIMEOUT ); + } + + /* flush driver and line discipline buffers */ + if( tty->driver.flush_buffer ) + tty->driver.flush_buffer( tty ); + if( tty->ldisc.flush_buffer ) + tty->ldisc.flush_buffer( tty ); + + /* wait for transmit idle */ + if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { + digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT ); + } + /* drop DTR and RTS */ digi_set_modem_signals( port, 0 ); /* disable input flow control */ - buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; - buf[i++] = port->number; - buf[i++] = DIGI_DISABLE; - buf[i++] = 0; + buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; + buf[1] = priv->dp_port_num; + buf[2] = DIGI_DISABLE; + buf[3] = 0; /* disable output flow control */ - buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; - buf[i++] = port->number; - buf[i++] = DIGI_DISABLE; - buf[i++] = 0; + buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; + buf[5] = priv->dp_port_num; + buf[6] = DIGI_DISABLE; + buf[7] = 0; /* disable reading modem signals automatically */ - buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS; - buf[i++] = port->number; - buf[i++] = DIGI_DISABLE; - buf[i++] = 0; + buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; + buf[9] = priv->dp_port_num; + buf[10] = DIGI_DISABLE; + buf[11] = 0; /* flush fifos */ - buf[i++] = DIGI_CMD_IFLUSH_FIFO; - buf[i++] = port->number; - buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; - buf[i++] = 0; + buf[12] = DIGI_CMD_IFLUSH_FIFO; + buf[13] = priv->dp_port_num; + buf[14] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; + buf[15] = 0; /* disable receive */ - buf[i++] = DIGI_CMD_RECEIVE_ENABLE; - buf[i++] = port->number; - buf[i++] = DIGI_DISABLE; - buf[i++] = 0; + buf[16] = DIGI_CMD_RECEIVE_ENABLE; + buf[17] = priv->dp_port_num; + buf[18] = DIGI_DISABLE; + buf[19] = 0; - if( (ret=digi_write_oob( buf, i )) != 0 ) + if( (ret=digi_write_oob_command( buf, 20 )) != 0 ) dbg( "digi_close: write oob failed, ret=%d", ret ); /* wait for final commands on oob port to complete */ @@ -1033,12 +1424,21 @@ break; } } - + /* shutdown any outstanding bulk writes */ usb_unlink_urb (port->write_urb); + tty->closing = 0; + + spin_lock_irqsave( &priv->dp_port_lock, flags ); + --port->active; + priv->dp_in_close = 0; + wake_up_interruptible( &priv->dp_close_wait ); + spin_unlock_irqrestore( &priv->dp_port_lock, flags ); + MOD_DEC_USE_COUNT; +dbg( "digi_close: done" ); } @@ -1093,6 +1493,8 @@ dbg( "digi_startup: TOP" ); spin_lock_init( &startup_lock ); + init_waitqueue_head( &modem_change_wait ); + init_waitqueue_head( &transmit_idle_wait ); /* allocate the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ @@ -1108,8 +1510,14 @@ return( 1 ); /* error */ /* initialize private structure */ + priv->dp_port_num = i; priv->dp_buf_len = 0; priv->dp_modem_signals = 0; + priv->dp_transmit_idle = 0; + priv->dp_in_close = 0; + init_waitqueue_head( &priv->dp_close_wait ); + priv->dp_tasks.next = NULL; + priv->dp_tasks.data = NULL; spin_lock_init( &priv->dp_port_lock ); /* initialize write wait queue for this port */ @@ -1157,6 +1565,7 @@ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct tty_struct *tty = port->tty; + digi_private_t *priv = (digi_private_t *)(port->private); int opcode = ((unsigned char *)urb->transfer_buffer)[0]; int len = ((unsigned char *)urb->transfer_buffer)[1]; int status = ((unsigned char *)urb->transfer_buffer)[2]; @@ -1164,11 +1573,11 @@ int ret,i; -dbg( "digi_read_bulk_callback: TOP: port=%d", port->number ); +dbg( "digi_read_bulk_callback: TOP: port=%d", priv->dp_port_num ); /* handle oob callback */ - if( port->number == oob_port_num ) { - digi_read_oob( urb ); + if( priv->dp_port_num == oob_port_num ) { + digi_read_oob_callback( urb ); return; } @@ -1181,13 +1590,15 @@ if( urb->status ) { dbg( "digi_read_bulk_callback: nonzero read bulk status: %d", urb->status ); + if( urb->status == -ENOENT ) + return; goto resubmit; } #ifdef DEBUG_DATA if( urb->actual_length ) { printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: port=%d, length=%d, data=", - port->number, urb->actual_length ); + priv->dp_port_num, urb->actual_length ); for( i=0; iactual_length; ++i ) { printk( "%.2x ", ((unsigned char *)urb->transfer_buffer)[i] ); } @@ -1196,7 +1607,7 @@ #endif if( urb->actual_length != len + 2 ) - err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", port->number, opcode, len, urb->actual_length, status ); + err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", priv->dp_port_num, opcode, len, urb->actual_length, status ); /* receive data */ if( opcode == DIGI_CMD_RECEIVE_DATA && urb->actual_length > 3 ) { @@ -1209,67 +1620,89 @@ /* continue read */ resubmit: - if( (ret=usb_submit_urb(urb)) != 0 ) + if( (ret=usb_submit_urb(urb)) != 0 ) { dbg( "digi_read_bulk_callback: failed resubmitting urb, ret=%d", ret ); + } } -static void digi_read_oob( struct urb *urb ) +static void digi_read_oob_callback( struct urb *urb ) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; digi_private_t *priv; - int oob_opcode = ((unsigned char *)urb->transfer_buffer)[0]; - int oob_line = ((unsigned char *)urb->transfer_buffer)[1]; - int oob_status = ((unsigned char *)urb->transfer_buffer)[2]; - int oob_ret = ((unsigned char *)urb->transfer_buffer)[3]; - int ret; + int opcode, line, status, val; + int i,ret; -dbg( "digi_read_oob: opcode=%d, line=%d, status=%d, ret=%d", oob_opcode, oob_line, oob_status, oob_ret ); +dbg( "digi_read_oob_callback: len=%d", urb->actual_length ); if( urb->status ) { - dbg( "digi_read_oob: nonzero read bulk status on oob: %d", + dbg( "digi_read_oob_callback: nonzero read bulk status on oob: %d", urb->status ); + if( urb->status == -ENOENT ) + return; goto resubmit; } - if( oob_opcode == DIGI_CMD_READ_INPUT_SIGNALS && oob_status == 0 ) { + for( i=0; iactual_length-3; ) { - priv = serial->port[oob_line].private; + opcode = ((unsigned char *)urb->transfer_buffer)[i++]; + line = ((unsigned char *)urb->transfer_buffer)[i++]; + status = ((unsigned char *)urb->transfer_buffer)[i++]; + val = ((unsigned char *)urb->transfer_buffer)[i++]; - spin_lock( &priv->dp_port_lock ); +dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", opcode, line, status, val ); - /* convert from digi flags to termiox flags */ - if( oob_ret & DIGI_READ_INPUT_SIGNALS_CTS ) - priv->dp_modem_signals |= TIOCM_CTS; - else - priv->dp_modem_signals &= ~TIOCM_CTS; - if( oob_ret & DIGI_READ_INPUT_SIGNALS_DSR ) - priv->dp_modem_signals |= TIOCM_DSR; - else - priv->dp_modem_signals &= ~TIOCM_DSR; - if( oob_ret & DIGI_READ_INPUT_SIGNALS_RI ) - priv->dp_modem_signals |= TIOCM_RI; - else - priv->dp_modem_signals &= ~TIOCM_RI; - if( oob_ret & DIGI_READ_INPUT_SIGNALS_DCD ) - priv->dp_modem_signals |= TIOCM_CD; - else - priv->dp_modem_signals &= ~TIOCM_CD; + if( status != 0 ) + continue; - spin_unlock( &priv->dp_port_lock ); + priv = serial->port[line].private; + + if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) { + + spin_lock( &priv->dp_port_lock ); + + /* convert from digi flags to termiox flags */ + if( val & DIGI_READ_INPUT_SIGNALS_CTS ) + priv->dp_modem_signals |= TIOCM_CTS; + else + priv->dp_modem_signals &= ~TIOCM_CTS; + if( val & DIGI_READ_INPUT_SIGNALS_DSR ) + priv->dp_modem_signals |= TIOCM_DSR; + else + priv->dp_modem_signals &= ~TIOCM_DSR; + if( val & DIGI_READ_INPUT_SIGNALS_RI ) + priv->dp_modem_signals |= TIOCM_RI; + else + priv->dp_modem_signals &= ~TIOCM_RI; + if( val & DIGI_READ_INPUT_SIGNALS_DCD ) + priv->dp_modem_signals |= TIOCM_CD; + else + priv->dp_modem_signals &= ~TIOCM_CD; + + wake_up_interruptible( &modem_change_wait ); + spin_unlock( &priv->dp_port_lock ); + + } else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) { + + spin_lock( &priv->dp_port_lock ); + priv->dp_transmit_idle = 1; + wake_up_interruptible( &transmit_idle_wait ); + spin_unlock( &priv->dp_port_lock ); + + } } + resubmit: if( (ret=usb_submit_urb(urb)) != 0 ) { - dbg( "digi_read_oob: failed resubmitting oob urb, ret=%d", + dbg( "digi_read_oob_callback: failed resubmitting oob urb, ret=%d", ret ); } } - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/usb-core.c linux.ac/drivers/usb/usb-core.c --- linux.vanilla/drivers/usb/usb-core.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/usb-core.c Sat May 27 15:41:34 2000 @@ -65,7 +65,7 @@ #endif { usb_major_init(); - usbdevfs_init(); + usbdevfs_init(); usb_hub_init(); #ifndef CONFIG_USB_MODULE diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/usb-ohci.c linux.ac/drivers/usb/usb-ohci.c --- linux.vanilla/drivers/usb/usb-ohci.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/usb-ohci.c Thu Jun 8 16:35:49 2000 @@ -527,12 +527,12 @@ #ifdef DEBUG urb_print (urb, "UNLINK", 1); #endif - - usb_dec_dev_use (urb->dev); - if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) { + usb_dec_dev_use(urb->dev); return rh_unlink_urb (urb); /* a request to the virtual root hub */ - + } + if (urb->hcpriv) { /* URB active? */ if (urb->status == USB_ST_URB_PENDING && !ohci->disabled) { @@ -548,15 +548,19 @@ urb_priv->ed->state |= ED_URB_DEL; spin_unlock_irqrestore (&usb_ed_lock, flags); if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { + usb_dec_dev_use (urb->dev); add_wait_queue (&op_wakeup, &wait); current->state = TASK_UNINTERRUPTIBLE; if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ err("unlink URB timeout!"); remove_wait_queue (&op_wakeup, &wait); urb->status = -ENOENT; - } else + } else { + /* usb_dec_dev_use done in dl_del_list() */ urb->status = -EINPROGRESS; + } } else { + usb_dec_dev_use (urb->dev); urb_rm_priv (urb); if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) { urb->complete (urb); @@ -1974,7 +1978,7 @@ return -ENODEV; pci_set_master (dev); - mem_base = dev->resource[0].start; + mem_base = pci_resource_start(dev, 0); mem_base = (unsigned long) ioremap_nocache (mem_base, 4096); if (!mem_base) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/usb.c linux.ac/drivers/usb/usb.c --- linux.vanilla/drivers/usb/usb.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/usb.c Sat May 27 15:41:34 2000 @@ -61,6 +61,9 @@ } info("registered new driver %s", new_driver->name); + + init_MUTEX(&new_driver->serialize); + /* Add it to the list of known drivers */ list_add(&new_driver->driver_list, &usb_driver_list); @@ -105,7 +108,9 @@ struct usb_interface *interface = &dev->actconfig->interface[i]; if (interface->driver == driver) { + down(&driver->serialize); driver->disconnect(dev, interface->private_data); + up(&driver->serialize); usb_driver_release_interface(driver, interface); /* * This will go through the list looking for another @@ -142,6 +147,16 @@ } } +struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) +{ + int i; + + for (i = 0; i < dev->actconfig->bNumInterfaces; i++) + if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum) + return &dev->actconfig->interface[i]; + + return NULL; +} /* * calc_bus_time: @@ -242,7 +257,7 @@ bus->bandwidth_isoc_reqs = 0; INIT_LIST_HEAD(&bus->bus_list); - INIT_LIST_HEAD(&bus->inodes); + INIT_LIST_HEAD(&bus->inodes); return bus; } @@ -393,7 +408,10 @@ driver_list); tmp = tmp->next; - if (!(private = driver->probe(dev, ifnum))) + down(&driver->serialize); + private = driver->probe(dev, ifnum); + up(&driver->serialize); + if (!private) continue; usb_driver_claim_interface(driver, interface, private); @@ -452,8 +470,8 @@ dev->bus = bus; dev->parent = parent; atomic_set(&dev->refcnt, 1); - INIT_LIST_HEAD(&dev->inodes); - INIT_LIST_HEAD(&dev->filelist); + INIT_LIST_HEAD(&dev->inodes); + INIT_LIST_HEAD(&dev->filelist); dev->bus->op->allocate(dev); @@ -826,7 +844,7 @@ begin = buffer; numskipped = 0; - /* Skip over at Interface class or vendor descriptors */ + /* Skip over any interface, class or vendor descriptors */ while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; @@ -987,6 +1005,13 @@ if (!dev->config) return; + if (dev->rawdescriptors) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + kfree(dev->rawdescriptors[i]); + + kfree(dev->rawdescriptors); + } + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { struct usb_config_descriptor *cf = &dev->config[c]; @@ -1129,7 +1154,9 @@ struct usb_interface *interface = &dev->actconfig->interface[i]; struct usb_driver *driver = interface->driver; if (driver) { + down(&driver->serialize); driver->disconnect(dev, interface->private_data); + up(&driver->serialize); usb_driver_release_interface(driver, interface); } } @@ -1143,14 +1170,13 @@ } /* remove /proc/bus/usb entry */ - usbdevfs_remove_device(dev); + usbdevfs_remove_device(dev); /* Free up the device itself, including its device number */ if (dev->devnum > 0) clear_bit(dev->devnum, &dev->bus->devmap.devicemap); - + usb_free_dev(dev); - } /* @@ -1337,15 +1363,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) { - struct usb_interface *iface = NULL; - int ret, i; + struct usb_interface *iface; + int ret; - for (i=0; iactconfig->bNumInterfaces; i++) { - if (dev->actconfig->interface[i].altsetting->bInterfaceNumber == interface) { - iface = &dev->actconfig->interface[i]; - break; - } - } + iface = usb_ifnum_to_if(dev, interface); if (!iface) { warn("selecting invalid interface %d", interface); return -EINVAL; @@ -1407,11 +1428,10 @@ int usb_get_configuration(struct usb_device *dev) { - int result; - unsigned int cfgno; + int result; + unsigned int cfgno, length; unsigned char buffer[8]; unsigned char *bigbuffer; - unsigned int tmp; struct usb_config_descriptor *desc = (struct usb_config_descriptor *)buffer; @@ -1435,9 +1455,14 @@ memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); - for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { - + dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * + dev->descriptor.bNumConfigurations, GFP_KERNEL); + if (!dev->rawdescriptors) { + err("out of memory"); + return -1; + } + for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { /* We grab the first 8 bytes so we know how long the whole */ /* configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); @@ -1445,41 +1470,41 @@ if (result < 0) err("unable to get descriptor"); else - err("config descriptor too short (expected %i, got %i)",8,result); + err("config descriptor too short (expected %i, got %i)", 8, result); goto err; } /* Get the full buffer */ - le16_to_cpus(&desc->wTotalLength); + length = le16_to_cpu(desc->wTotalLength); - bigbuffer = kmalloc(desc->wTotalLength, GFP_KERNEL); + bigbuffer = kmalloc(length, GFP_KERNEL); if (!bigbuffer) { err("unable to allocate memory for configuration descriptors"); - result=-ENOMEM; + result = -ENOMEM; goto err; } - tmp=desc->wTotalLength; + /* Now that we know the length, get the whole thing */ - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength); + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { err("couldn't get all of config descriptors"); kfree(bigbuffer); goto err; } - if (result < tmp) { - err("config descriptor too short (expected %i, got %i)",tmp,result); + if (result < length) { + err("config descriptor too short (expected %i, got %i)", length, result); kfree(bigbuffer); goto err; } - result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); - kfree(bigbuffer); + dev->rawdescriptors[cfgno] = bigbuffer; + + result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); - else if (result < 0) - { - result=-1; + else if (result < 0) { + result = -1; goto err; } } @@ -1560,8 +1585,7 @@ */ int usb_new_device(struct usb_device *dev) { - int addr, err; - int tmp; + int err; info("USB new device connect, assigned device number %d", dev->devnum); @@ -1572,10 +1596,15 @@ dev->epmaxpacketin [0] = 8; dev->epmaxpacketout[0] = 8; - /* Even though we have assigned an address for the device, we */ - /* haven't told it what it's address is yet */ - addr = dev->devnum; - dev->devnum = 0; + err = usb_set_address(dev); + if (err < 0) { + err("USB device not accepting new address (error=%d)", err); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + wait_ms(10); /* Let the SET_ADDRESS settle */ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 8) { @@ -1583,34 +1612,19 @@ err("USB device not responding, giving up (error=%d)", err); else err("USB device descriptor short read (expected %i, got %i)",8,err); - clear_bit(addr, &dev->bus->devmap.devicemap); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; - dev->devnum = addr; - - err = usb_set_address(dev); - - if (err < 0) { - err("USB device not accepting new address (error=%d)", err); - clear_bit(dev->devnum, &dev->bus->devmap.devicemap); - dev->devnum = -1; - return 1; - } - - wait_ms(10); /* Let the SET_ADDRESS settle */ - - tmp = sizeof(dev->descriptor); - err = usb_get_device_descriptor(dev); - if (err < tmp) { + if (err < sizeof(dev->descriptor)) { if (err < 0) - err("unable to get device descriptor (error=%d)",err); + err("unable to get device descriptor (error=%d)", err); else - err("USB device descriptor short read (expected %i, got %i)",tmp,err); + err("USB device descriptor short read (expected %i, got %i)", sizeof(dev->descriptor), err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; @@ -1646,7 +1660,7 @@ #endif /* now that the basic setup is over, add a /proc/bus/usb entry */ - usbdevfs_add_device(dev); + usbdevfs_add_device(dev); /* find drivers willing to handle this device */ usb_find_drivers(dev); @@ -1704,6 +1718,8 @@ * into the kernel, and other device drivers are built as modules, * then these symbols need to be exported for the modules to use. */ +EXPORT_SYMBOL(usb_ifnum_to_if); + EXPORT_SYMBOL(usb_register); EXPORT_SYMBOL(usb_deregister); EXPORT_SYMBOL(usb_alloc_bus); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/usbkbd.c linux.ac/drivers/usb/usbkbd.c --- linux.vanilla/drivers/usb/usbkbd.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/usbkbd.c Tue May 30 21:28:10 2000 @@ -1,7 +1,7 @@ /* - * usbkbd.c Version 0.1 + * $Id: usbkbd.c,v 1.11 2000/05/29 09:01:52 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * USB HIDBP Keyboard support * @@ -63,6 +63,8 @@ struct urb irq, led; devrequest dr; unsigned char leds; + char name[128]; + int open; }; static void usb_kbd_irq(struct urb *urb) @@ -125,12 +127,34 @@ warn("led urb status %d received", urb->status); } +static int usb_kbd_open(struct input_dev *dev) +{ + struct usb_kbd *kbd = dev->private; + + if (kbd->open++) + return 0; + + if (usb_submit_urb(&kbd->irq)) + return -EIO; + + return 0; +} + +static void usb_kbd_close(struct input_dev *dev) +{ + struct usb_kbd *kbd = dev->private; + + if (!--kbd->open) + usb_unlink_urb(&kbd->irq); +} + static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_kbd *kbd; - int i; + int i, pipe, maxp; + char *buf; if (dev->descriptor.bNumConfigurations != 1) return NULL; interface = dev->config[0].interface[ifnum].altsetting + 0; @@ -144,6 +168,9 @@ if (!(endpoint->bEndpointAddress & 0x80)) return NULL; if ((endpoint->bmAttributes & 3) != 3) return NULL; + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + usb_set_protocol(dev, interface->bInterfaceNumber, 0); usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); @@ -159,14 +186,11 @@ kbd->dev.private = kbd; kbd->dev.event = usb_kbd_event; + kbd->dev.open = usb_kbd_open; + kbd->dev.close = usb_kbd_close; - { - int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - int maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, - usb_kbd_irq, kbd, endpoint->bInterval); - } + FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp, + usb_kbd_irq, kbd, endpoint->bInterval); kbd->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE; kbd->dr.request = USB_REQ_SET_REPORT; @@ -174,18 +198,37 @@ kbd->dr.index = interface->bInterfaceNumber; kbd->dr.length = 1; - FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0), - (void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd); - - if (usb_submit_urb(&kbd->irq)) { + kbd->dev.name = kbd->name; + kbd->dev.idbus = BUS_USB; + kbd->dev.idvendor = dev->descriptor.idVendor; + kbd->dev.idproduct = dev->descriptor.idProduct; + kbd->dev.idversion = dev->descriptor.bcdDevice; + + if (!(buf = kmalloc(63, GFP_KERNEL))) { kfree(kbd); return NULL; } - input_register_device(&kbd->dev); + if (dev->descriptor.iManufacturer && + usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strcat(kbd->name, buf); + if (dev->descriptor.iProduct && + usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + sprintf(kbd->name, "%s %s", kbd->name, buf); + + if (!strlen(kbd->name)) + sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x", + kbd->dev.idvendor, kbd->dev.idproduct); + + kfree(buf); - printk(KERN_INFO "input%d: USB HIDBP keyboard\n", kbd->dev.number); + FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0), + (void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd); + + input_register_device(&kbd->dev); + printk(KERN_INFO "input%d: %s on on usb%d:%d.%d\n", + kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum); return kbd; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/usbmouse.c linux.ac/drivers/usb/usbmouse.c --- linux.vanilla/drivers/usb/usbmouse.c Thu May 25 17:38:13 2000 +++ linux.ac/drivers/usb/usbmouse.c Tue May 30 21:28:10 2000 @@ -1,7 +1,7 @@ /* - * usbmouse.c Version 0.1 + * $Id: usbmouse.c,v 1.5 2000/05/29 09:01:52 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * USB HIDBP Mouse support * @@ -37,12 +37,12 @@ MODULE_AUTHOR("Vojtech Pavlik "); -#define USBMOUSE_EXTRA - struct usb_mouse { signed char data[8]; + char name[128]; struct input_dev dev; struct urb irq; + int open; }; static void usb_mouse_irq(struct urb *urb) @@ -53,16 +53,36 @@ if (urb->status) return; - input_report_key(dev, BTN_LEFT, !!(data[0] & 0x01)); - input_report_key(dev, BTN_RIGHT, !!(data[0] & 0x02)); - input_report_key(dev, BTN_MIDDLE, !!(data[0] & 0x04)); - input_report_rel(dev, REL_X, data[1]); - input_report_rel(dev, REL_Y, data[2]); -#ifdef USBMOUSE_EXTRA - input_report_key(dev, BTN_SIDE, !!(data[0] & 0x08)); - input_report_key(dev, BTN_EXTRA, !!(data[0] & 0x10)); + input_report_key(dev, BTN_LEFT, data[0] & 0x01); + input_report_key(dev, BTN_RIGHT, data[0] & 0x02); + input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); + input_report_key(dev, BTN_SIDE, data[0] & 0x08); + input_report_key(dev, BTN_EXTRA, data[0] & 0x10); + + input_report_rel(dev, REL_X, data[1]); + input_report_rel(dev, REL_Y, data[2]); input_report_rel(dev, REL_WHEEL, data[3]); -#endif +} + +static int usb_mouse_open(struct input_dev *dev) +{ + struct usb_mouse *mouse = dev->private; + + if (mouse->open++) + return 0; + + if (usb_submit_urb(&mouse->irq)) + return -EIO; + + return 0; +} + +static void usb_mouse_close(struct input_dev *dev) +{ + struct usb_mouse *mouse = dev->private; + + if (!--mouse->open) + usb_unlink_urb(&mouse->irq); } static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum) @@ -70,6 +90,8 @@ struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_mouse *mouse; + int pipe, maxp; + char *buf; if (dev->descriptor.bNumConfigurations != 1) return NULL; interface = dev->config[0].interface[ifnum].altsetting + 0; @@ -83,9 +105,9 @@ if (!(endpoint->bEndpointAddress & 0x80)) return NULL; if ((endpoint->bmAttributes & 3) != 3) return NULL; -#ifndef USBMOUSE_EXTRA - usb_set_protocol(dev, interface->bInterfaceNumber, 0); -#endif + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL; @@ -94,27 +116,44 @@ mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); -#ifdef USBMOUSE_EXTRA mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); mouse->dev.relbit[0] |= BIT(REL_WHEEL); -#endif - { - int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - int maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + mouse->dev.private = mouse; + mouse->dev.open = usb_mouse_open; + mouse->dev.close = usb_mouse_close; + + mouse->dev.name = mouse->name; + mouse->dev.idbus = BUS_USB; + mouse->dev.idvendor = dev->descriptor.idVendor; + mouse->dev.idproduct = dev->descriptor.idProduct; + mouse->dev.idversion = dev->descriptor.bcdDevice; - FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp, - usb_mouse_irq, mouse, endpoint->bInterval); - } - - if (usb_submit_urb(&mouse->irq)) { + if (!(buf = kmalloc(63, GFP_KERNEL))) { kfree(mouse); return NULL; } + if (dev->descriptor.iManufacturer && + usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) + strcat(mouse->name, buf); + if (dev->descriptor.iProduct && + usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) + sprintf(mouse->name, "%s %s", mouse->name, buf); + + if (!strlen(mouse->name)) + sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x", + mouse->dev.idvendor, mouse->dev.idproduct); + + kfree(buf); + + FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp, + usb_mouse_irq, mouse, endpoint->bInterval); + input_register_device(&mouse->dev); - printk(KERN_INFO "input%d: USB HIDBP mouse\n", mouse->dev.number); + printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", + mouse->dev.number, mouse->name, dev->bus->busnum, dev->devnum, ifnum); return mouse; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/uss720.c linux.ac/drivers/usb/uss720.c --- linux.vanilla/drivers/usb/uss720.c Thu May 25 17:38:12 2000 +++ linux.ac/drivers/usb/uss720.c Sun Jun 4 21:33:26 2000 @@ -546,13 +546,13 @@ 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) && (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284)) return NULL; + + printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); /* our known interfaces have 3 alternate settings */ if (usbdev->actconfig->interface[ifnum].num_altsetting != 3) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/wacom.c linux.ac/drivers/usb/wacom.c --- linux.vanilla/drivers/usb/wacom.c Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/wacom.c Tue May 30 21:28:10 2000 @@ -1,5 +1,5 @@ /* - * wacom.c Version 0.5 + * $Id: wacom.c,v 1.9 2000/05/29 09:01:52 vojtech Exp $ * * Copyright (c) 2000 Vojtech Pavlik * Copyright (c) 2000 Andreas Bach Aaen @@ -18,6 +18,9 @@ * relative mode, proximity. * v0.5 (vp) - Big cleanup, nifty features removed, * they belong in userspace + * v1.8 (vp) - Submit URB only when operating, moved to CVS, + * use input_report_key instead of report_btn and + * other cleanups */ /* @@ -116,6 +119,7 @@ struct urb irq; struct wacom_features *features; int tool; + int open; }; static void wacom_graphire_irq(struct urb *urb) @@ -137,18 +141,18 @@ switch ((data[1] >> 5) & 3) { case 0: /* Pen */ - input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x80); + input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); break; case 1: /* Rubber */ - input_report_btn(dev, BTN_TOOL_RUBBER, data[1] & 0x80); + input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); break; case 2: /* Mouse */ - input_report_btn(dev, BTN_TOOL_MOUSE, data[7] > 24); - input_report_btn(dev, BTN_LEFT, data[1] & 0x01); - input_report_btn(dev, BTN_RIGHT, data[1] & 0x02); - input_report_btn(dev, BTN_MIDDLE, data[1] & 0x04); + input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); + input_report_key(dev, BTN_LEFT, data[1] & 0x01); + input_report_key(dev, BTN_RIGHT, data[1] & 0x02); + input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); input_report_abs(dev, ABS_DISTANCE, data[7]); input_report_rel(dev, REL_WHEEL, (signed char) data[6]); return; @@ -156,9 +160,9 @@ input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8)); - input_report_btn(dev, BTN_TOUCH, data[1] & 0x01); - input_report_btn(dev, BTN_STYLUS, data[1] & 0x02); - input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04); + input_report_key(dev, BTN_TOUCH, data[1] & 0x01); + input_report_key(dev, BTN_STYLUS, data[1] & 0x02); + input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); } static void wacom_intuos_irq(struct urb *urb) @@ -177,21 +181,23 @@ switch (((__u32)data[2] << 4) | (data[3] >> 4)) { case 0x012: wacom->tool = BTN_TOOL_PENCIL; break; /* Inking pen */ + case 0x822: case 0x022: wacom->tool = BTN_TOOL_PEN; break; /* Pen */ case 0x032: wacom->tool = BTN_TOOL_BRUSH; break; /* Stroke pen */ case 0x094: wacom->tool = BTN_TOOL_MOUSE; break; /* Mouse 4D */ case 0x096: wacom->tool = BTN_TOOL_LENS; break; /* Lens cursor */ + case 0x82a: case 0x0fa: wacom->tool = BTN_TOOL_RUBBER; break; /* Eraser */ case 0x112: wacom->tool = BTN_TOOL_AIRBRUSH; break; /* Airbrush */ default: wacom->tool = BTN_TOOL_PEN; break; /* Unknown tool */ } - input_report_btn(dev, wacom->tool, 1); + input_report_key(dev, wacom->tool, 1); return; } if ((data[1] | data[2] | data[3] | data[4] | data[5] | data[6] | data[7] | data[8] | data[9]) == 0x80) { /* Exit report */ - input_report_btn(dev, wacom->tool, 0); + input_report_key(dev, wacom->tool, 0); return; } @@ -202,29 +208,50 @@ input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); - input_report_btn(dev, BTN_STYLUS, data[1] & 2); - input_report_btn(dev, BTN_STYLUS2, data[1] & 4); - input_report_btn(dev, BTN_TOUCH, t > 10); + input_report_key(dev, BTN_STYLUS, data[1] & 2); + input_report_key(dev, BTN_STYLUS2, data[1] & 4); + input_report_key(dev, BTN_TOUCH, t > 10); } #define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS)) struct wacom_features wacom_features[] = { - { "Graphire", 0x10, 8, 10206, 7422, 511, 32, wacom_graphire_irq, + { "Wacom Graphire", 0x10, 8, 10206, 7422, 511, 32, wacom_graphire_irq, BIT(EV_REL), 0, BIT(REL_WHEEL), BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE), 0 }, - { "Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq, 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, - { "Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq, 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, - { "Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq, 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, - { "Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq, 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, - { "Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq, 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, { NULL , 0 } }; +static int wacom_open(struct input_dev *dev) +{ + struct wacom *wacom = dev->private; + + if (wacom->open++) + return 0; + + if (usb_submit_urb(&wacom->irq)) + return -EIO; + + return 0; +} + +static void wacom_close(struct input_dev *dev) +{ + struct wacom *wacom = dev->private; + + if (!--wacom->open) + usb_unlink_urb(&wacom->irq); +} + static void *wacom_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_endpoint_descriptor *endpoint; @@ -256,17 +283,23 @@ wacom->dev.absmax[ABS_TILT_X] = 127; wacom->dev.absmax[ABS_TILT_Y] = 127; + wacom->dev.private = wacom; + wacom->dev.open = wacom_open; + wacom->dev.close = wacom_close; + + wacom->dev.name = wacom->features->name; + wacom->dev.idbus = BUS_USB; + wacom->dev.idvendor = dev->descriptor.idVendor; + wacom->dev.idproduct = dev->descriptor.idProduct; + wacom->dev.idversion = dev->descriptor.bcdDevice; + FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval); - if (usb_submit_urb(&wacom->irq)) { - kfree(wacom); - return NULL; - } - input_register_device(&wacom->dev); - printk(KERN_INFO "input%d: Wacom %s on usb%d\n", wacom->dev.number, wacom->features->name, dev->devnum); + printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", + wacom->dev.number, wacom->features->name, dev->bus->busnum, dev->devnum, ifnum); return wacom; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/usb/wmforce.c linux.ac/drivers/usb/wmforce.c --- linux.vanilla/drivers/usb/wmforce.c Thu May 25 17:38:14 2000 +++ linux.ac/drivers/usb/wmforce.c Tue May 30 21:28:10 2000 @@ -1,5 +1,5 @@ /* - * wmforce.c Version 0.1 + * $Id: wmforce.c,v 1.6 2000/05/29 09:01:52 vojtech Exp $ * * Copyright (c) 2000 Vojtech Pavlik * @@ -44,6 +44,7 @@ signed char data[8]; struct input_dev dev; struct urb irq; + int open; }; static struct { @@ -51,6 +52,8 @@ __s32 y; } wmforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; +static char *wmforce_name = "Logitech WingMan Force"; + static void wmforce_irq(struct urb *urb) { struct wmforce *wmforce = urb->context; @@ -71,15 +74,36 @@ input_report_abs(dev, ABS_HAT0X, wmforce_hat_to_axis[data[7] >> 4].x); input_report_abs(dev, ABS_HAT0Y, wmforce_hat_to_axis[data[7] >> 4].y); - input_report_key(dev, BTN_TRIGGER, !!(data[6] & 0x01)); - input_report_key(dev, BTN_TOP, !!(data[6] & 0x02)); - input_report_key(dev, BTN_THUMB, !!(data[6] & 0x04)); - input_report_key(dev, BTN_TOP2, !!(data[6] & 0x08)); - input_report_key(dev, BTN_BASE, !!(data[6] & 0x10)); - input_report_key(dev, BTN_BASE2, !!(data[6] & 0x20)); - input_report_key(dev, BTN_BASE3, !!(data[6] & 0x40)); - input_report_key(dev, BTN_BASE4, !!(data[6] & 0x80)); - input_report_key(dev, BTN_BASE5, !!(data[7] & 0x01)); + input_report_key(dev, BTN_TRIGGER, data[6] & 0x01); + input_report_key(dev, BTN_TOP, data[6] & 0x02); + input_report_key(dev, BTN_THUMB, data[6] & 0x04); + input_report_key(dev, BTN_TOP2, data[6] & 0x08); + input_report_key(dev, BTN_BASE, data[6] & 0x10); + input_report_key(dev, BTN_BASE2, data[6] & 0x20); + input_report_key(dev, BTN_BASE3, data[6] & 0x40); + input_report_key(dev, BTN_BASE4, data[6] & 0x80); + input_report_key(dev, BTN_BASE5, data[7] & 0x01); +} + +static int wmforce_open(struct input_dev *dev) +{ + struct wmforce *wmforce = dev->private; + + if (wmforce->open++) + return 0; + + if (usb_submit_urb(&wmforce->irq)) + return -EIO; + + return 0; +} + +static void wmforce_close(struct input_dev *dev) +{ + struct wmforce *wmforce = dev->private; + + if (!--wmforce->open) + usb_unlink_urb(&wmforce->irq); } static void *wmforce_probe(struct usb_device *dev, unsigned int ifnum) @@ -105,33 +129,34 @@ for (i = ABS_X; i <= ABS_Y; i++) { wmforce->dev.absmax[i] = 1920; wmforce->dev.absmin[i] = -1920; - wmforce->dev.absfuzz[i] = 0; wmforce->dev.absflat[i] = 128; } - wmforce->dev.absmax[ABS_THROTTLE] = 0; - wmforce->dev.absmin[ABS_THROTTLE] = 255; - wmforce->dev.absfuzz[ABS_THROTTLE] = 0; - wmforce->dev.absflat[ABS_THROTTLE] = 0; + wmforce->dev.absmax[ABS_THROTTLE] = 255; + wmforce->dev.absmin[ABS_THROTTLE] = 0; for (i = ABS_HAT0X; i <= ABS_HAT0Y; i++) { wmforce->dev.absmax[i] = 1; wmforce->dev.absmin[i] = -1; - wmforce->dev.absfuzz[i] = 0; - wmforce->dev.absflat[i] = 0; } + wmforce->dev.private = wmforce; + wmforce->dev.open = wmforce_open; + wmforce->dev.close = wmforce_close; + + wmforce->dev.name = wmforce_name; + wmforce->dev.idbus = BUS_USB; + wmforce->dev.idvendor = dev->descriptor.idVendor; + wmforce->dev.idproduct = dev->descriptor.idProduct; + wmforce->dev.idversion = dev->descriptor.bcdDevice; + FILL_INT_URB(&wmforce->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wmforce->data, 8, wmforce_irq, wmforce, endpoint->bInterval); - if (usb_submit_urb(&wmforce->irq)) { - kfree(wmforce); - return NULL; - } - input_register_device(&wmforce->dev); - printk(KERN_INFO "input%d: Logitech WingMan Force USB\n", wmforce->dev.number); + printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n", + wmforce->dev.number, wmforce_name, dev->bus->busnum, dev->devnum, ifnum); return wmforce; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/Config.in linux.ac/drivers/video/Config.in --- linux.vanilla/drivers/video/Config.in Thu May 25 17:46:15 2000 +++ linux.ac/drivers/video/Config.in Mon Jun 5 19:10:24 2000 @@ -251,8 +251,8 @@ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \ - "$CONFIG_FB_SIS" = "y" ]; then + "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \ + "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then define_tristate CONFIG_FBCON_CFB16 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ @@ -264,7 +264,8 @@ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ - "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then + "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ + "$CONFIG_FB_SA1100" = "m"]; then define_tristate CONFIG_FBCON_CFB16 m fi fi diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/atyfb.c linux.ac/drivers/video/atyfb.c --- linux.vanilla/drivers/video/atyfb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/atyfb.c Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.141 2000/03/12 03:53:16 davem Exp $ +/* $Id: atyfb.c,v 1.142 2000/04/12 01:39:41 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/clgenfb.c linux.ac/drivers/video/clgenfb.c --- linux.vanilla/drivers/video/clgenfb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/clgenfb.c Thu Jun 8 15:10:51 2000 @@ -31,10 +31,9 @@ * */ -#define CLGEN_VERSION "1.9.6" +#define CLGEN_VERSION "1.9.8" #include -#include #include #include #include @@ -628,12 +627,6 @@ long *nom, long *den, long *div, long maxfreq); -#ifdef CONFIG_PCI -static struct pci_dev *clgen_pci_dev_get (clgen_board_t *btype); -static unsigned int clgen_get_memsize (caddr_t regbase); -static int clgen_pci_setup (struct clgenfb_info *fb_info, clgen_board_t *btype); -#endif /* CONFIG_PCI */ - #ifdef CLGEN_DEBUG static void clgen_dump (void); static void clgen_dbg_reg_dump (caddr_t regbase); @@ -2493,20 +2486,25 @@ static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype) { - struct pci_dev *pdev = NULL; + struct pci_dev *pdev; int i; DPRINTK ("ENTER\n"); - for (i = 0; i < arraysize(clgen_pci_probe_list) && !pdev; i++) - pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, - clgen_pci_probe_list[i].device, NULL); + for (i = 0; i < arraysize(clgen_pci_probe_list); i++) { + pdev = NULL; + while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, + clgen_pci_probe_list[i].device, pdev)) != NULL) { + if (pci_enable_device(pdev) == 0) { + *btype = clgen_pci_probe_list[i - 1].btype; + DPRINTK ("EXIT, returning pdev=%p\n", pdev); + return pdev; + } + } + } - if (pdev) - *btype = clgen_pci_probe_list[i - 1].btype; - - DPRINTK ("EXIT, returning %p\n", pdev); - return pdev; + DPRINTK ("EXIT, returning NULL\n"); + return NULL; } @@ -2526,53 +2524,32 @@ /* This is a best-guess for now */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - - *display = pdev->base_address[0]; - if ((*display & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { - *registers = *display; - *display = pdev->base_address[1]; - } else { - *registers = pdev->base_address[1]; - } - -#else - - if (pdev->resource[0].flags & IORESOURCE_IO) { - *display = pdev->resource[1].start; - *registers = pdev->resource[0].start; + if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { + *display = pci_resource_start(pdev, 1); + *registers = pci_resource_start(pdev, 0); } else { - *display = pdev->resource[0].start; - *registers = pdev->resource[1].start; + *display = pci_resource_start(pdev, 0); + *registers = pci_resource_start(pdev, 1); } -#endif /* kernel older than 2.3.13 */ - assert (*display != 0); DPRINTK ("EXIT\n"); } - - -/* clgen_pci_unmap only used in modules */ -#ifdef MODULE -static void clgen_pci_unmap (struct clgenfb_info *info) +static void __exit clgen_pci_unmap (struct clgenfb_info *info) { iounmap (info->fbmem); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) release_mem_region(info->fbmem_phys, info->size); #if 0 /* if system didn't claim this region, we would... */ release_mem_region(0xA0000, 65535); #endif + if (release_io_ports) release_region(0x3C0, 32); -#endif } -#endif /* MODULE */ static int __init clgen_pci_setup (struct clgenfb_info *info, @@ -2604,12 +2581,6 @@ pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000); #endif - pci_read_config_word (pdev, PCI_COMMAND, &tmp16); - if (!(tmp16 & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) { - u16 tmp16_o = tmp16 | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - pci_write_config_word (pdev, PCI_COMMAND, tmp16_o); - } - #ifdef CONFIG_FB_OF /* Ok, so its an ugly hack, since we could have passed it down from * clgen_of_init() if we'd done it right. */ @@ -2649,8 +2620,6 @@ board_size = clgen_get_memsize (info->regs); } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) - if (!request_mem_region(board_addr, board_size, "clgenfb")) { pci_write_config_word (pdev, PCI_COMMAND, tmp16); printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n", @@ -2669,8 +2638,6 @@ if (request_region(0x3C0, 32, "clgenfb")) release_io_ports = 1; -#endif /* kernel > 2.3.13 */ - info->fbmem = ioremap (board_addr, board_size); info->fbmem_phys = board_addr; info->size = board_size; @@ -2721,14 +2688,10 @@ } - -/* clgen_zorro_unmap only used in modules */ -#ifdef MODULE -static void clgen_zorro_unmap (struct clgenfb_info *info) +static void __exit clgen_zorro_unmap (struct clgenfb_info *info) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) release_mem_region(info->board_addr, info->board_size); -#endif + if (info->btype == BT_PICASSO4) { iounmap (info->board_addr); iounmap (info->fbmem_phys); @@ -2737,8 +2700,6 @@ iounmap (info->board_addr); } } -#endif /* MODULE */ - static int __init clgen_zorro_setup (struct clgenfb_info *info, @@ -2835,7 +2796,7 @@ } #else -#error Unsupported bus. Supported: PCI, Zorro +#error This driver requires Zorro or PCI bus. #endif /* !CONFIG_PCI, !CONFIG_ZORRO */ /* sanity checks */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/controlfb.c linux.ac/drivers/video/controlfb.c --- linux.vanilla/drivers/video/controlfb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/controlfb.c Sat Jun 10 21:46:58 2000 @@ -805,14 +805,10 @@ * bitfields, horizontal timing, vertical timing. */ /* swiped by jonh from atyfb.c */ - if (xres <= 512 && yres <= 384) - par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */ - else if (xres <= 640 && yres <= 480) + if (xres <= 640 && yres <= 480) par->vmode = VMODE_640_480_67; /* 640x480, 67Hz */ else if (xres <= 640 && yres <= 870) par->vmode = VMODE_640_870_75P; /* 640x870, 75Hz (portrait) */ - else if (xres <= 768 && yres <= 576) - par->vmode = VMODE_768_576_50I; /* 768x576, 50Hz (PAL full frame) */ else if (xres <= 800 && yres <= 600) par->vmode = VMODE_800_600_75; /* 800x600, 75Hz */ else if (xres <= 832 && yres <= 624) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/cyber2000fb.c linux.ac/drivers/video/cyber2000fb.c --- linux.vanilla/drivers/video/cyber2000fb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/cyber2000fb.c Sun Jun 4 21:18:26 2000 @@ -12,8 +12,13 @@ * especially for the colourmap stuff. Once fbcon has been fully migrated, * we can kill the last 5 references to cfb->currcon. * - * We also use the new hotplug PCI subsystem. This doesn't work fully in - * the case of multiple CyberPro cards yet however. + * We also use the new hotplug PCI subsystem. I'm not sure if there are any + * such cards, but I'm erring on the side of caution. We don't want to go + * pop just because someone does have one. + * + * Note that this doesn't work fully in the case of multiple CyberPro cards + * with grabbers. We currently can only attach to the first CyberPro card + * found. */ #include #include @@ -47,7 +52,7 @@ /* * This is the offset of the PCI space in physical memory */ -#ifdef CONFIG_ARCH_FOOTBRIDGE +#ifdef CONFIG_FOOTBRIDGE #define PCI_PHYS_OFFSET 0x80000000 #else #define PCI_PHYS_OFFSET 0x00000000 @@ -62,6 +67,8 @@ struct display_switch *dispsw; struct pci_dev *dev; signed int currcon; + int func_use_count; + u_long ref_ps; /* * Clock divisors @@ -72,7 +79,10 @@ u8 red, green, blue; } palette[NR_PALETTE]; + u_char mem_ctl1; u_char mem_ctl2; + u_char mclk_mult; + u_char mclk_div; }; /* -------------------- Hardware specific routines ------------------------- */ @@ -363,7 +373,7 @@ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }; -static void cyber2000fb_set_timing(struct par_info *hw) +static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw) { u_int i; @@ -416,11 +426,10 @@ cyber2000_attrw(0x14, 0x00); /* PLL registers */ - cyber2000_grphw(0xb0, hw->clock_mult); - cyber2000_grphw(0xb1, hw->clock_div); - - cyber2000_grphw(0xb2, 0xdb); - cyber2000_grphw(0xb3, 0x54); /* MCLK: 75MHz */ + cyber2000_grphw(DCLK_MULT, hw->clock_mult); + cyber2000_grphw(DCLK_DIV, hw->clock_div); + cyber2000_grphw(MCLK_MULT, cfb->mclk_mult); + cyber2000_grphw(MCLK_DIV, cfb->mclk_div); cyber2000_grphw(0x90, 0x01); cyber2000_grphw(0xb9, 0x80); cyber2000_grphw(0xb9, 0x00); @@ -438,7 +447,9 @@ cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) | ((hw->pitch >> 4) & 0x30)); cyber2000_grphw(0x77, hw->visualid); - cyber2000_grphw(0x33, 0x0c); + + /* make sure we stay in linear mode */ + cyber2000_grphw(0x33, 0x0d); /* * Set up accelerator registers @@ -535,6 +546,7 @@ Htotal = var->xres + var->right_margin + var->hsync_len + var->left_margin; + if (Htotal > 2080) return -EINVAL; @@ -619,7 +631,7 @@ struct fb_var_screeninfo *var) { u_long pll_ps = var->pixclock; - const u_long ref_ps = 69842; + const u_long ref_ps = cfb->ref_ps; u_int div2, t_div1, best_div1, best_mult; int best_diff; @@ -641,7 +653,6 @@ if (div2 == 4) return -EINVAL; -#if 1 /* * Step 2: * Given pll_ps and ref_ps, find: @@ -689,94 +700,7 @@ if (diff == 0) break; } -#else - /* Note! This table will be killed shortly. --rmk */ - /* - * 1600x1200 1280x1024 1152x864 1024x768 800x600 640x480 - * 5051 5051 yes 76* - * 5814 5814 no 66 - * 6411 6411 no 60 - * 7408 7408 yes 75* - * 74* - * 7937 7937 yes 70* - * 9091 4545 yes 80* - * 75* 100* - * 9260 4630 yes 60* - * 10000 5000 no 70 90 - * 12500 6250 yes 47-lace* 60* - * 43-lace* - * 12699 6349 yes 75* - * 13334 6667 no 72 - * 70 - * 14815 7407 yes 100* - * 15385 7692 yes 47-lace* 60* - * 43-lace* - * 17656 4414 no 90 - * 20000 5000 no 72 - * 20203 5050 yes 75* - * 22272 5568 yes 43-lace* 70* 100* - * 25000 6250 yes 60* - * 25057 6264 no 90 - * 27778 6944 yes 56* - * 48-lace* - * 31747 7936 yes 75* - * 32052 8013 no 72 - * 39722 /6 6620 no - * 39722 /8 4965 yes 60* - */ - /* /1 /2 /4 /6 /8 */ - /* (2010) (2000) */ - if (pll_ps >= 4543 && pll_ps <= 4549) { - best_mult = 169; /*u220.0 110.0 54.99 36.663 27.497 */ - best_div1 = 11; /* 4546 9092 18184 27276 36367 */ - } else if (pll_ps >= 4596 && pll_ps <= 4602) { - best_mult = 243; /* 217.5 108.7 54.36 36.243 27.181 */ - best_div1 = 16; /* 4599 9197 18395 27592 36789 */ - } else if (pll_ps >= 4627 && pll_ps <= 4633) { - best_mult = 181; /*u216.0, 108.0, 54.00, 36.000 27.000 */ - best_div1 = 12; /* 4630 9260 18520 27780 37040 */ - } else if (pll_ps >= 4962 && pll_ps <= 4968) { - best_mult = 211; /*u201.0, 100.5, 50.25, 33.500 25.125 */ - best_div1 = 15; /* 4965 9930 19860 29790 39720 */ - } else if (pll_ps >= 5005 && pll_ps <= 5011) { - best_mult = 251; /* 200.0 99.8 49.92 33.280 24.960 */ - best_div1 = 18; /* 5008 10016 20032 30048 40064 */ - } else if (pll_ps >= 5047 && pll_ps <= 5053) { - best_mult = 83; /*u198.0, 99.0, 49.50, 33.000 24.750 */ - best_div1 = 6; /* 5050 10100 20200 30300 40400 */ - } else if (pll_ps >= 5490 && pll_ps <= 5496) { - best_mult = 89; /* 182.0 91.0 45.51 30.342 22.756 */ - best_div1 = 7; /* 5493 10986 21972 32958 43944 */ - } else if (pll_ps >= 5567 && pll_ps <= 5573) { - best_mult = 163; /*u179.5 89.8 44.88 29.921 22.441 */ - best_div1 = 13; /* 5570 11140 22281 33421 44562 */ - } else if (pll_ps >= 6246 && pll_ps <= 6252) { - best_mult = 190; /*u160.0, 80.0, 40.00, 26.671 20.003 */ - best_div1 = 17; /* 6249 12498 24996 37494 49992 */ - } else if (pll_ps >= 6346 && pll_ps <= 6352) { - best_mult = 209; /*u158.0, 79.0, 39.50, 26.333 19.750 */ - best_div1 = 19; /* 6349 12698 25396 38094 50792 */ - } else if (pll_ps >= 6648 && pll_ps <= 6655) { - best_mult = 210; /*u150.3 75.2 37.58 25.057 18.792 */ - best_div1 = 20; /* 6652 13303 26606 39909 53213 */ - } else if (pll_ps >= 6943 && pll_ps <= 6949) { - best_mult = 181; /*u144.0 72.0 36.00 23.996 17.997 */ - best_div1 = 18; /* 6946 13891 27782 41674 55565 */ - } else if (pll_ps >= 7404 && pll_ps <= 7410) { - best_mult = 198; /*u134.0 67.5 33.75 22.500 16.875 */ - best_div1 = 21; /* 7407 14815 29630 44445 59260 */ - } else if (pll_ps >= 7689 && pll_ps <= 7695) { - best_mult = 227; /*u130.0 65.0 32.50 21.667 16.251 */ - best_div1 = 25; /* 7692 15384 30768 46152 61536 */ - } else if (pll_ps >= 7808 && pll_ps <= 7814) { - best_mult = 152; /* 128.0 64.0 32.00 21.337 16.003 */ - best_div1 = 17; /* 7811 15623 31245 46868 62490 */ - } else if (pll_ps >= 7934 && pll_ps <= 7940) { - best_mult = 44; /*u126.0 63.0 31.498 20.999 15.749 */ - best_div1 = 5; /* 7937 15874 31748 47622 63494 */ - } else - return -EINVAL; -#endif + /* * Step 3: * combine values @@ -1018,7 +942,7 @@ cfb->fb.changevar(con); cyber2000fb_update_start(cfb, var); - cyber2000fb_set_timing(&hw); + cyber2000fb_set_timing(cfb, &hw); fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb); return 0; @@ -1195,26 +1119,32 @@ /* * Enable access to the extended registers - * Bug: this should track the usage of these registers */ -static void cyber2000fb_enable_extregs(void) +static void cyber2000fb_enable_extregs(struct cfb_info *cfb) { - int old; + cfb->func_use_count += 1; - old = cyber2000_grphr(FUNC_CTL); - cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL); + if (cfb->func_use_count == 1) { + int old; + + old = cyber2000_grphr(FUNC_CTL); + cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL); + } } /* * Disable access to the extended registers - * Bug: this should track the usage of these registers */ -static void cyber2000fb_disable_extregs(void) +static void cyber2000fb_disable_extregs(struct cfb_info *cfb) { - int old; + if (cfb->func_use_count == 1) { + int old; - old = cyber2000_grphr(FUNC_CTL); - cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL); + old = cyber2000_grphr(FUNC_CTL); + cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL); + } + + cfb->func_use_count -= 1; } /* @@ -1227,7 +1157,7 @@ /* * Attach a capture/tv driver to the core CyberX0X0 driver. */ -int cyber2000fb_attach(struct cyberpro_info *info) +int cyber2000fb_attach(struct cyberpro_info *info, int idx) { if (int_cfb_info != NULL) { info->dev = int_cfb_info->dev; @@ -1236,6 +1166,7 @@ info->fb_size = int_cfb_info->fb.fix.smem_len; info->enable_extregs = cyber2000fb_enable_extregs; info->disable_extregs = cyber2000fb_disable_extregs; + info->info = int_cfb_info; strncpy(info->dev_name, int_cfb_info->fb.fix.id, sizeof(info->dev_name)); @@ -1248,7 +1179,7 @@ /* * Detach a capture/tv driver from the core CyberX0X0 driver. */ -void cyber2000fb_detach(void) +void cyber2000fb_detach(int idx) { MOD_DEC_USE_COUNT; } @@ -1281,8 +1212,8 @@ } static char igs_regs[] __devinitdata = { - 0x10, 0x10, 0x12, 0x00, 0x13, 0x00, - 0x31, 0x00, 0x32, 0x00, 0x33, 0x01, + 0x12, 0x00, 0x13, 0x00, + 0x31, 0x00, 0x32, 0x00, 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, @@ -1290,22 +1221,129 @@ 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8 }; -static inline void cyberpro_init_hw(struct cfb_info *cfb) +/* + * We need to wake up the CyberPro, and make sure its in linear memory + * mode. Unfortunately, this is specific to the platform and card that + * we are running on. + * + * On x86 and ARM, should we be initialising the CyberPro first via the + * IO registers, and then the MMIO registers to catch all cases? Can we + * end up in the situation where the chip is in MMIO mode, but not awake + * on an x86 system? + * + * Note that on the NetWinder, the firmware automatically detects the + * type, width and size, and leaves this in extended registers 0x71 and + * 0x72 for us. + */ +static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot) { int i; /* - * Wake up the CyberPro + * Wake up the CyberPro. */ +#ifdef __sparc__ +#ifdef __sparc_v9__ +#error "You loose, consult DaveM." +#else + /* + * SPARC does not have an "outb" instruction, so we generate + * I/O cycles storing into a reserved memory space at + * physical address 0x3000000 + */ + { + unsigned char *iop; + + iop = ioremap(0x3000000, 0x5000); + if (iop == NULL) { + prom_printf("iga5000: cannot map I/O\n"); + return -ENOMEM; + } + + writeb(0x18, iop + 0x46e8); + writeb(0x01, iop + 0x102); + writeb(0x08, iop + 0x46e8); + writeb(0x33, iop + 0x3ce); + writeb(0x01, iop + 0x3cf); + + iounmap((void *)iop); + } +#endif + + if (at_boot) { + /* + * Use mclk from BIOS. Only read this if we're + * initialising this card for the first time. + * FIXME: what about hotplug? + */ + cfb->mclk_mult = cyber2000_grphr(MCLK_MULT); + cfb->mclk_div = cyber2000_grphr(MCLK_DIV); + } +#endif +#ifdef __i386__ + /* + * x86 is simple, we just do regular outb's instead of + * cyber2000_outb. + */ + outb(0x18, 0x46e8); + outb(0x01, 0x102); + outb(0x08, 0x46e8); + outb(0x33, 0x3ce); + outb(0x01, 0x3cf); + + if (at_boot) { + /* + * Use mclk from BIOS. Only read this if we're + * initialising this card for the first time. + * FIXME: what about hotplug? + */ + cfb->mclk_mult = cyber2000_grphr(MCLK_MULT); + cfb->mclk_div = cyber2000_grphr(MCLK_DIV); + } +#endif +#ifdef __arm__ cyber2000_outb(0x18, 0x46e8); cyber2000_outb(0x01, 0x102); cyber2000_outb(0x08, 0x46e8); + cyber2000_outb(0x33, 0x3ce); + cyber2000_outb(0x01, 0x3cf); + + /* + * MCLK on the NetWinder is fixed at 75MHz + */ + cfb->mclk_mult = 0xdb; + cfb->mclk_div = 0x54; +#endif /* * Initialise the CyberPro */ for (i = 0; i < sizeof(igs_regs); i += 2) cyber2000_grphw(igs_regs[i], igs_regs[i+1]); + + if (at_boot) { + /* + * get the video RAM size and width from the VGA register. + * This should have been already initialised by the BIOS, + * but if it's garbage, claim default 1MB VRAM (woody) + */ + cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1); + cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2); + } else { + /* + * Reprogram the MEM_CTL1 and MEM_CTL2 registers + */ + cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1); + cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2); + } + + /* + * Ensure thatwe are using the correct PLL. + * (CyberPro 5000's may be programmed to use + * an additional set of PLLs. + */ + cyber2000_outb(0xba, 0x3ce); + cyber2000_outb(cyber2000_inb(0x3cf) & 0x80, 0x3cf); } static struct cfb_info * __devinit @@ -1323,6 +1361,7 @@ cfb->currcon = -1; cfb->dev = dev; + cfb->ref_ps = 69842; cfb->divisors[0] = 1; cfb->divisors[1] = 2; cfb->divisors[2] = 4; @@ -1466,13 +1505,6 @@ u_long smem_size; int err; - /* - * We can only accept one CyberPro device at the moment. We can - * kill this once int_cfb_info and CyberRegs have been killed. - */ - if (int_cfb_info) - return -EBUSY; - err = pci_enable_device(dev); if (err) return err; @@ -1486,14 +1518,7 @@ if (err) goto failed; - cyberpro_init_hw(cfb); - - /* - * get the video RAM size and width from the VGA register. - * This should have been already initialised by the BIOS, - * but if it's garbage, claim default 1MB VRAM (woody) - */ - cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2); + cyberpro_init_hw(cfb, 1); switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) { case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break; @@ -1519,6 +1544,12 @@ cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb); + /* + * Calculate the hsync and vsync frequencies. Note that + * we split the 1e12 constant up so that we can preserve + * the precision and fit the results into 32-bit registers. + * (1953125000 * 512 = 1e12) + */ h_sync = 1953125000 / cfb->fb.var.pixclock; h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin + cfb->fb.var.right_margin + cfb->fb.var.hsync_len); @@ -1538,7 +1569,8 @@ * Our driver data */ dev->driver_data = cfb; - int_cfb_info = cfb; + if (int_cfb_info == NULL) + int_cfb_info = cfb; return 0; @@ -1555,7 +1587,15 @@ struct cfb_info *cfb = (struct cfb_info *)dev->driver_data; if (cfb) { - unregister_framebuffer(&cfb->fb); + /* + * If unregister_framebuffer fails, then + * we will be leaving hooks that could cause + * oopsen laying around. + */ + if (unregister_framebuffer(&cfb->fb)) + printk(KERN_WARNING "%s: danger Will Robinson, " + "danger danger! Oopsen imminent!\n", + cfb->fb.fix.id); cyberpro_unmap_smem(cfb); cyberpro_unmap_mmio(cfb); cyberpro_free_fb_info(cfb); @@ -1565,7 +1605,8 @@ * valid. */ dev->driver_data = NULL; - int_cfb_info = NULL; + if (cfb == int_cfb_info) + int_cfb_info = NULL; } } @@ -1581,12 +1622,7 @@ struct cfb_info *cfb = (struct cfb_info *)dev->driver_data; if (cfb) { - cyberpro_init_hw(cfb); - - /* - * Reprogram the MEM_CTL2 register - */ - cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2); + cyberpro_init_hw(cfb, 0); /* * Restore the old video mode and the palette. @@ -1620,7 +1656,8 @@ /* * I don't think we can use the "module_init" stuff here because - * the fbcon stuff may not be initialised yet. + * the fbcon stuff may not be initialised yet. Hence the #ifdef + * around module_init. */ int __init cyber2000fb_init(void) { @@ -1636,5 +1673,3 @@ module_init(cyber2000fb_init); #endif module_exit(cyberpro_exit); - -MODULE_DEVICE_TABLE(pci, cyberpro_pci_table); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/cyber2000fb.h linux.ac/drivers/video/cyber2000fb.h --- linux.vanilla/drivers/video/cyber2000fb.h Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/cyber2000fb.h Sun Jun 4 21:18:26 2000 @@ -127,6 +127,8 @@ #define CAP_DDA_Y_INIT 0x6c #define CAP_DDA_Y_INC 0x6e +#define MEM_CTL1 0x71 + #define MEM_CTL2 0x72 #define MEM_CTL2_SIZE_2MB 0x01 #define MEM_CTL2_SIZE_4MB 0x02 @@ -156,6 +158,11 @@ #define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */ #define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */ +#define DCLK_MULT 0xb0 +#define DCLK_DIV 0xb1 +#define MCLK_MULT 0xb2 +#define MCLK_DIV 0xb3 + #define CAP_MODE2 0xa5 #define Y_TV_CTL 0xae @@ -281,6 +288,11 @@ #define CO_REG_DEST_PTR 0xbf178 #define CO_REG_DEST_WIDTH 0xbf218 +/* + * Private structure + */ +struct cfb_info; + struct cyberpro_info { struct pci_dev *dev; unsigned char *regs; @@ -289,16 +301,27 @@ unsigned int fb_size; /* - * Use these to enable the BM or TV registers. + * The following is a pointer to be passed into the + * functions below. The modules outside the main + * cyber2000fb.c driver have no knowledge as to what + * is within this structure. + */ + struct cfb_info *info; + + /* + * Use these to enable the BM or TV registers. In an SMP + * environment, these two function pointers should only be + * called from the module_init() or module_exit() + * functions. */ - void (*enable_extregs)(void); - void (*disable_extregs)(void); + void (*enable_extregs)(struct cfb_info *); + void (*disable_extregs)(struct cfb_info *); }; /* * Note! Writing to the Cyber20x0 registers from an interrupt * routine is definitely a bad idea atm. */ -int cyber2000fb_attach(struct cyberpro_info *info); -void cyber2000fb_detach(void); +int cyber2000fb_attach(struct cyberpro_info *info, int idx); +void cyber2000fb_detach(int idx); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/macmodes.c linux.ac/drivers/video/macmodes.c --- linux.vanilla/drivers/video/macmodes.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/macmodes.c Sat Jun 10 21:46:58 2000 @@ -265,7 +265,7 @@ n = n_entries - i; if (n > 16) n = 16; - palette_cmap.start = 1; + palette_cmap.start = i; palette_cmap.len = n; for (j = 0; j < n; j++) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/matrox/matroxfb_base.c linux.ac/drivers/video/matrox/matroxfb_base.c --- linux.vanilla/drivers/video/matrox/matroxfb_base.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/matrox/matroxfb_base.c Tue May 30 15:25:46 2000 @@ -1595,11 +1595,11 @@ if (ACCESS_FBINFO(capable.cross4MB) < 0) ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB; if (b->flags & DEVF_SWAPS) { - ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[1].start; - video_base_phys = ACCESS_FBINFO(pcidev)->resource[0].start; + ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); + video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); } else { - ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[0].start; - video_base_phys = ACCESS_FBINFO(pcidev)->resource[1].start; + ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); + video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); } err = -EINVAL; if (!ctrlptr_phys) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/offb.c linux.ac/drivers/video/offb.c --- linux.vanilla/drivers/video/offb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/offb.c Sat Jun 10 21:46:58 2000 @@ -479,9 +479,11 @@ && len == sizeof(int)) height = *pp; if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL - && len == sizeof(int)) + && len == sizeof(int)) { pitch = *pp; - else + if (pitch == 1) + pitch = 0x1000; + } else pitch = width; if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL && len == sizeof(unsigned)) @@ -831,7 +833,6 @@ u_int transp, struct fb_info *info) { struct fb_info_offb *info2 = (struct fb_info_offb *)info; - int i; if (!info2->cmap_adr || regno > 255) return 1; @@ -867,9 +868,11 @@ #endif #ifdef FBCON_HAS_CFB32 case 32: - i = (regno << 8) | regno; + { + int i = (regno << 8) | regno; info2->fbcon_cmap.cfb32[regno] = (i << 16) | i; break; + } #endif } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/pm2fb.c linux.ac/drivers/video/pm2fb.c --- linux.vanilla/drivers/video/pm2fb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/pm2fb.c Tue May 30 15:26:08 2000 @@ -1107,12 +1107,12 @@ } #else if (pm2fb_options.flags & OPTF_VIRTUAL) { - p->regions.rg_base= __pa(pci->dev->resource[0].start); - p->regions.fb_base= __pa(pci->dev->resource[1].start); + p->regions.rg_base = __pa(pci_resource_start(pci->dev, 0)); + p->regions.fb_base = __pa(pci_resource_start(pci->dev, 1)); } else { - p->regions.rg_base= (pci->dev->resource[0].start); - p->regions.fb_base= (pci->dev->resource[0].start); + p->regions.rg_base = pci_resource_start(pci->dev, 0); + p->regions.fb_base = pci_resource_start(pci->dev, 0); } #endif #ifdef PM2FB_BE_APERTURE @@ -2049,10 +2049,13 @@ int __init pm2fb_init(void){ + MOD_INC_USE_COUNT; memset(&fb_info, 0, sizeof(fb_info)); memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par)); - if (!pm2fb_conf(&fb_info)) + if (!pm2fb_conf(&fb_info)) { + MOD_DEC_USE_COUNT; return -ENXIO; + } pm2fb_reset(&fb_info); fb_info.disp.scrollmode=SCROLL_YNOMOVE; fb_info.gen.parsize=sizeof(struct pm2fb_par); @@ -2071,6 +2074,7 @@ fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info)<0) { printk(KERN_ERR "pm2fb: unable to register.\n"); + MOD_DEC_USE_COUNT; return -EINVAL; } printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n", @@ -2078,7 +2082,6 @@ board_table[fb_info.board].name, permedia2_name, (u32 )(fb_info.regions.fb_size>>10)); - MOD_INC_USE_COUNT; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/riva/fbdev.c linux.ac/drivers/video/riva/fbdev.c --- linux.vanilla/drivers/video/riva/fbdev.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/riva/fbdev.c Tue May 30 15:26:22 2000 @@ -526,8 +526,8 @@ assert (rinfo->base0_region_size >= 0x00800000); /* from GGI */ assert (rinfo->base1_region_size >= 0x01000000); /* from GGI */ - rinfo->ctrl_base_phys = rinfo->pd->resource[0].start; - rinfo->fb_base_phys = rinfo->pd->resource[1].start; + rinfo->ctrl_base_phys = pci_resource_start (rinfo->pd, 0); + rinfo->fb_base_phys = pci_resource_start (rinfo->pd, 1); if (!request_mem_region (rinfo->ctrl_base_phys, rinfo->base0_region_size, "rivafb")) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/sa1100fb.c linux.ac/drivers/video/sa1100fb.c --- linux.vanilla/drivers/video/sa1100fb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/sa1100fb.c Sun Jun 4 21:17:38 2000 @@ -53,74 +53,23 @@ /* * Debug macros */ -// #define DEBUG +//#define DEBUG #ifdef DEBUG -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) #else # define DPRINTK(fmt, args...) #endif -/* - * The MAX_x defines are used to specify the maximum ranges for - * parameters that affect the size of the frame buffer memory - * region. Since the frame buffer memory is not dynamically - * alocated, the maximum size that will be used is allocated. - */ -#if defined (CONFIG_SA1100_PENNY) - -#define MAX_BITS_PER_PIXEL 8 -#define MAX_SCREEN_SIZE_H 640 -#define MAX_SCREEN_SIZE_V 480 - -#elif defined(CONFIG_SA1100_BRUTUS) - -#define MAX_BITS_PER_PIXEL 8 -#define MAX_SCREEN_SIZE_H 320 -#define MAX_SCREEN_SIZE_V 240 - -#elif defined (CONFIG_SA1100_THINCLIENT) - -#define MAX_BITS_PER_PIXEL 8 -/*#define MAX_BITS_PER_PIXEL 16*/ - -#define MAX_SCREEN_SIZE_H 640 -#define MAX_SCREEN_SIZE_V 480 - -#elif defined(CONFIG_SA1100_TIFON) - -#define MAX_BITS_PER_PIXEL 4 -#define MAX_SCREEN_SIZE_H 640 -#define MAX_SCREEN_SIZE_V 200 - -#define REVERSE_VIDEO_4BIT - -#elif defined(CONFIG_SA1100_LART) - -#define MAX_BITS_PER_PIXEL 4 -#define MAX_SCREEN_SIZE_H 320 -#define MAX_SCREEN_SIZE_V 240 - -#endif - -/* Default resolutions */ -#if defined(CONFIG_SA1100_PENNY) -#define DEFAULT_XRES 640 -#define DEFAULT_YRES 480 -#define DEFAULT_BPP 8 -#else -#define DEFAULT_XRES MAX_SCREEN_SIZE_H -#define DEFAULT_YRES MAX_SCREEN_SIZE_V -#define DEFAULT_BPP MAX_BITS_PER_PIXEL -#endif - /* Memory size macros for determining required FrameBuffer size */ -#define MAX_PALETTE_NUM_ENTRIES 256 -#define ADJUSTED_MAX_BITS_PER_PIXEL (MAX_BITS_PER_PIXEL > 8 ? 16 : MAX_BITS_PER_PIXEL) -#define MAX_PALETTE_MEM_SIZE (MAX_PALETTE_NUM_ENTRIES * 2) -#define MAX_PIXEL_MEM_SIZE ((MAX_SCREEN_SIZE_H * MAX_SCREEN_SIZE_V * ADJUSTED_MAX_BITS_PER_PIXEL ) / 8) -#define MAX_FRAMEBUFFER_MEM_SIZE (MAX_PIXEL_MEM_SIZE + MAX_PALETTE_MEM_SIZE + 32) -#define ALLOCATED_FB_MEM_SIZE (PAGE_ALIGN (MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2)) +#define MAX_PALETTE_NUM_ENTRIES 256 +#define MAX_PALETTE_MEM_SIZE (MAX_PALETTE_NUM_ENTRIES * 2) +#define MAX_PIXEL_MEM_SIZE \ + ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8) +#define MAX_FRAMEBUFFER_MEM_SIZE \ + (MAX_PIXEL_MEM_SIZE + MAX_PALETTE_MEM_SIZE + 32) +#define ALLOCATED_FB_MEM_SIZE \ + (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2)) #define SA1100_PALETTE_MEM_SIZE(bpp) (((bpp)==8?256:16)*2) #define SA1100_PALETTE_MODE_VAL(bpp) (((bpp) & 0x018) << 9) @@ -137,30 +86,34 @@ #define SA1100_NAME "SA1100" #define NR_MONTYPES 1 -static u_char *VideoMemRegion = NULL; -static u_char *VideoMemRegion_phys = NULL; +static u_char *VideoMemRegion; +static u_char *VideoMemRegion_phys; /* Local LCD controller parameters */ /* These can be reduced by making better use of fb_var_screeninfo parameters. */ /* Several duplicates exist in the two structures. */ struct sa1100fb_par { - u_char *p_screen_base; - u_char *v_screen_base; - u_short *p_palette_base; - u_short *v_palette_base; - unsigned long screen_size; - unsigned int palette_size; - unsigned int xres; - unsigned int yres; - unsigned int xres_virtual; - unsigned int yres_virtual; - unsigned int bits_per_pixel; - signed int montype; - unsigned int currcon; - unsigned int visual; - unsigned int allow_modeset : 1; - unsigned int active_lcd : 1; - volatile u_char controller_state; + u_char *p_screen_base; + u_char *v_screen_base; + u_short *p_palette_base; + u_short *v_palette_base; + unsigned long screen_size; + unsigned int palette_size; + unsigned int max_xres; + unsigned int max_yres; + unsigned int xres; + unsigned int yres; + unsigned int xres_virtual; + unsigned int yres_virtual; + unsigned int max_bpp; + unsigned int bits_per_pixel; + signed int montype; + unsigned int currcon; + unsigned int visual; + unsigned int allow_modeset : 1; + unsigned int active_lcd : 1; + unsigned int inv_4bpp : 1; + volatile u_char controller_state; }; /* Shadows for LCD controller registers */ @@ -177,7 +130,7 @@ 30000, 70000, 50, 65, 0 /* Generic */ }; -static struct display global_disp; /* Initial (default) Display Settings */ +static struct display global_disp; /* Initial (default) Display Settings */ static struct fb_info fb_info; static struct sa1100fb_par current_par; static struct fb_var_screeninfo __initdata init_var = {}; @@ -231,18 +184,16 @@ static inline u_short sa1100fb_palette_encode(u_int regno, u_int red, u_int green, u_int blue, u_int trans) { - u_short pal; - + u_int pal; if(current_par.bits_per_pixel == 4){ /* * RGB -> luminance is defined to be * Y = 0.299 * R + 0.587 * G + 0.114 * B */ - pal = ((19595 * red + 38470 * green + 7471 * blue) >> 28) & 0x00f; -#ifdef REVERSE_VIDEO_4BIT - pal = 15 - pal; -#endif + pal = (19595 * red + 38470 * green + 7471 * blue) >> 28; + if( current_par.inv_4bpp ) + pal = 15 - pal; } else{ pal = ((red >> 4) & 0xf00); @@ -268,9 +219,8 @@ pal = sa1100fb_palette_read(regno); if( current_par.bits_per_pixel == 4){ -#ifdef REVERSE_VIDEO_4BIT - pal = 15 - pal; -#endif + if( current_par.inv_4bpp ) + pal = 15 - pal; pal &= 0x000f; pal |= pal << 4; pal |= pal << 8; @@ -317,6 +267,7 @@ { int err = 0; + DPRINTK("current_par.visual=%d\n", current_par.visual); if (con == current_par.currcon) err = fb_get_cmap(cmap, kspc, sa1100fb_getcolreg, info); else if (fb_display[con].cmap.len) @@ -329,13 +280,13 @@ static int sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) + struct fb_info *info) { int err = 0; + DPRINTK("current_par.visual=%d\n", current_par.visual); if (!fb_display[con].cmap.len) err = fb_alloc_cmap(&fb_display[con].cmap, - current_par.palette_size, 0); if (!err) { if (con == current_par.currcon) @@ -372,6 +323,7 @@ var->bits_per_pixel = par->bits_per_pixel; + DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch(var->bits_per_pixel) { case 2: case 4: @@ -418,16 +370,17 @@ par->xres = MIN_XRES; if ((par->yres = var->yres) < MIN_YRES) par->yres = MIN_YRES; - if (par->xres > MAX_SCREEN_SIZE_H) - par->xres = MAX_SCREEN_SIZE_H; - if (par->yres > MAX_SCREEN_SIZE_V) - par->yres = MAX_SCREEN_SIZE_V; - par->xres_virtual = + if (par->xres > current_par.max_xres) + par->xres = current_par.max_xres; + if (par->yres > current_par.max_yres) + par->yres = current_par.max_yres; + par->xres_virtual = var->xres_virtual < par->xres ? par->xres : var->xres_virtual; par->yres_virtual = var->yres_virtual < par->yres ? par->yres : var->yres_virtual; par->bits_per_pixel = var->bits_per_pixel; + DPRINTK("par->bits_per_pixel=%d\n", par->bits_per_pixel); switch (par->bits_per_pixel) { #ifdef FBCON_HAS_CFB4 case 4: @@ -444,38 +397,38 @@ #ifdef FBCON_HAS_CFB16 case 16: /* RGB 555 */ par->visual = FB_VISUAL_TRUECOLOR; - par->palette_size = -1; + par->palette_size = 0; break; #endif default: return -EINVAL; } - palette_mem_size = SA1100_PALETTE_MEM_SIZE(par->bits_per_pixel); - palette_mem_phys = (u_long)VideoMemRegion_phys + PAGE_SIZE - - palette_mem_size; - par->p_palette_base = (u_short *)palette_mem_phys; - par->v_palette_base = (u_short *)((u_long)VideoMemRegion + PAGE_SIZE - palette_mem_size); - par->p_screen_base = (u_char *)((u_long)VideoMemRegion_phys + PAGE_SIZE); - par->v_screen_base = (u_char *)((u_long)VideoMemRegion + PAGE_SIZE); - - DPRINTK("p_palette_base = 0x%08lx\n",(u_long)par->p_palette_base); - DPRINTK("v_palette_base = 0x%08lx\n",(u_long)par->v_palette_base); - DPRINTK("p_screen_base = 0x%08lx\n",(u_long)par->p_screen_base); - DPRINTK("v_screen_base = 0x%08lx\n",(u_long)par->v_screen_base); - DPRINTK("VideoMemRegion = 0x%08lx\n",(u_long)VideoMemRegion); - DPRINTK("VideoMemRegion_phys = 0x%08lx\n",(u_long)VideoMemRegion_phys); + palette_mem_size = SA1100_PALETTE_MEM_SIZE(par->bits_per_pixel); + palette_mem_phys = (u_long)VideoMemRegion_phys + PAGE_SIZE - palette_mem_size; + par->p_palette_base = (u_short *)palette_mem_phys; + par->v_palette_base = (u_short *)((u_long)VideoMemRegion + PAGE_SIZE - palette_mem_size); + par->p_screen_base = (u_char *)((u_long)VideoMemRegion_phys + PAGE_SIZE); + par->v_screen_base = (u_char *)((u_long)VideoMemRegion + PAGE_SIZE); + + DPRINTK("p_palette_base = 0x%08lx\n",(u_long)par->p_palette_base); + DPRINTK("v_palette_base = 0x%08lx\n",(u_long)par->v_palette_base); + DPRINTK("p_screen_base = 0x%08lx\n",(u_long)par->p_screen_base); + DPRINTK("v_screen_base = 0x%08lx\n",(u_long)par->v_screen_base); + DPRINTK("VideoMemRegion = 0x%08lx\n",(u_long)VideoMemRegion); + DPRINTK("VideoMemRegion_phys = 0x%08lx\n",(u_long)VideoMemRegion_phys); return 0; } static int sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - struct sa1100fb_par par; + struct sa1100fb_par par; + DPRINTK("con=%d\n", con); if (con == -1) { - sa1100fb_get_par(&par); - sa1100fb_encode_var(var, &par); + sa1100fb_get_par(&par); + sa1100fb_encode_var(var, &par); } else *var = fb_display[con].var; @@ -491,7 +444,7 @@ { struct display *display; int err, chgvar = 0; - struct sa1100fb_par par; + struct sa1100fb_par par; if (con >= 0) display = &fb_display[con]; /* Display settings for console */ @@ -500,18 +453,18 @@ DPRINTK("xres = %d, yres = %d\n",var->xres, var->yres); - // Decode var contents into a par structure, adjusting any - // out of range values. + /* Decode var contents into a par structure, adjusting any */ + /* out of range values. */ if ((err = sa1100fb_decode_var(var, &par))) return err; - // Store adjusted par values into var structure - sa1100fb_encode_var(var, &par); + // Store adjusted par values into var structure + sa1100fb_encode_var(var, &par); - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; - else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) && - ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN)) - return -EINVAL; + else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) && + ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN)) + return -EINVAL; if (con >= 0) { if ((display->var.xres != var->xres) || @@ -525,6 +478,7 @@ (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))) chgvar = 1; } + DPRINTK("chgvar=%d\n", chgvar); display->var = *var; display->screen_base = par.v_screen_base; @@ -539,6 +493,8 @@ display->can_soft_blank = 1; display->inverse = 0; + DPRINTK("display->var.bits_per_pixel=%d xres=%d yres=%d display->dispsw=%p\n", + display->var.bits_per_pixel, var->xres, var->yres, display->dispsw); switch (display->var.bits_per_pixel) { #ifdef FBCON_HAS_CFB4 case 4: @@ -560,13 +516,13 @@ break; } - // If the console has changed and the console has defined - // a changevar function, call that function. + /* If the console has changed and the console has defined */ + /* a changevar function, call that function. */ if (chgvar && info && info->changevar) info->changevar(con); - // If the current console is selected, update the palette - if (con == current_par.currcon) + // If the current console is selected and it's not truecolor, update the palette + if ((con == current_par.currcon) && (current_par.visual != FB_VISUAL_TRUECOLOR)) { struct fb_cmap *cmap; @@ -575,10 +531,11 @@ cmap = &display->cmap; else cmap = fb_default_cmap(current_par.palette_size); + DPRINTK("visual=%d palette_size=%d cmap=%p\n", current_par.visual, current_par.palette_size, cmap); fb_set_cmap(cmap, 1, sa1100fb_setcolreg, info); - sa1100fb_activate_var(var); + sa1100fb_activate_var(var); } return 0; } @@ -606,7 +563,7 @@ else display = &global_disp; /* Default display settings */ - fix->smem_start = current_par.p_screen_base; + fix->smem_start = (unsigned long)current_par.p_screen_base; fix->smem_len = current_par.screen_size; fix->type = display->type; fix->type_aux = display->type_aux; @@ -627,78 +584,118 @@ strcpy(fb_info.modename, SA1100_NAME); strcpy(fb_info.fontname, "Acorn8x8"); - fb_info.node = -1; - fb_info.flags = FBINFO_FLAG_DEFAULT; - fb_info.fbops = &sa1100fb_ops; - fb_info.monspecs = monspecs; - fb_info.disp = &global_disp; - fb_info.changevar = NULL; - fb_info.switch_con = sa1100fb_switch; - fb_info.updatevar = sa1100fb_updatevar; - fb_info.blank = sa1100fb_blank; + fb_info.node = -1; + fb_info.flags = FBINFO_FLAG_DEFAULT; + fb_info.fbops = &sa1100fb_ops; + fb_info.monspecs = monspecs; + fb_info.disp = &global_disp; + fb_info.changevar = NULL; + fb_info.switch_con = sa1100fb_switch; + fb_info.updatevar = sa1100fb_updatevar; + fb_info.blank = sa1100fb_blank; /* * setup initial parameters */ memset(&init_var, 0, sizeof(init_var)); - init_var.xres = DEFAULT_XRES; - init_var.yres = DEFAULT_YRES; - init_var.xres_virtual = init_var.xres; - init_var.yres_virtual = init_var.yres; - init_var.xoffset = 0; - init_var.yoffset = 0; - init_var.bits_per_pixel = DEFAULT_BPP; - - init_var.transp.length = 0; - init_var.nonstd = 0; - init_var.activate = FB_ACTIVATE_NOW; - init_var.height = -1; - init_var.width = -1; - init_var.vmode = FB_VMODE_NONINTERLACED; - -#if defined(CONFIG_SA1100_PENNY) - init_var.red.length = 4; - init_var.green = init_var.red; - init_var.blue = init_var.red; - init_var.sync = 0; -#elif defined(CONFIG_SA1100_BRUTUS) - init_var.red.length = 4; - init_var.green = init_var.red; - init_var.blue = init_var.red; - init_var.sync = 0; -#elif defined(CONFIG_SA1100_THINCLIENT) - init_var.red.length = 4; - init_var.green = init_var.red; - init_var.blue = init_var.red; - init_var.sync = 0; -#elif defined(CONFIG_SA1100_TIFON) - init_var.red.length = 4; - init_var.green = init_var.red; - init_var.blue = init_var.red; - init_var.grayscale = 1; - init_var.pixclock = 150000; - init_var.left_margin = 20; - init_var.right_margin = 255; - init_var.upper_margin = 20; - init_var.lower_margin = 0; - init_var.hsync_len = 2; - init_var.vsync_len = 1; - init_var.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT; - init_var.vmode = 0; -#elif defined(CONFIG_SA1100_LART) - init_var.red.length = 4; - init_var.green = init_var.red; - init_var.blue = init_var.red; - init_var.grayscale = 1; - init_var.pixclock = 150000; - init_var.sync = 0; -#endif + init_var.transp.length = 0; + init_var.nonstd = 0; + init_var.activate = FB_ACTIVATE_NOW; + init_var.xoffset = 0; + init_var.yoffset = 0; + init_var.height = -1; + init_var.width = -1; + init_var.vmode = FB_VMODE_NONINTERLACED; + + if (machine_is_assabet()) { + current_par.max_xres = 320; + current_par.max_yres = 240; + current_par.max_bpp = 16; + init_var.red.length = 5; + init_var.green.length = 6; + init_var.blue.length = 5; + init_var.grayscale = 0; + init_var.sync = 0; + } else if (machine_is_bitsy()) { + current_par.max_xres = 320; + current_par.max_yres = 240; + current_par.max_bpp = 16; + init_var.red.length = 5; + init_var.green.length = 6; + init_var.blue.length = 5; + init_var.grayscale = 0; + } else if (machine_is_brutus()) { + current_par.max_xres = 320; + current_par.max_yres = 240; + current_par.max_bpp = 8; + init_var.red.length = 4; + init_var.green = init_var.red; + init_var.blue = init_var.red; + init_var.sync = 0; + } else if (machine_is_lart()) { + current_par.max_xres = 320; + current_par.max_yres = 240; + current_par.max_bpp = 4; + init_var.red.length = 4; + init_var.green = init_var.red; + init_var.blue = init_var.red; + init_var.grayscale = 1; + init_var.pixclock = 150000; + init_var.sync = 0; + } else if (machine_is_penny()) { + current_par.max_xres = 640; + current_par.max_yres = 480; + current_par.max_bpp = 8; + init_var.red.length = 4; + init_var.green = init_var.red; + init_var.blue = init_var.red; + init_var.sync = 0; + } else if (machine_is_thinclient() || machine_is_graphicsclient()) { + current_par.max_xres = 640; + current_par.max_yres = 480; + current_par.max_bpp = 8; + init_var.red.length = 4; + init_var.green = init_var.red; + init_var.blue = init_var.red; + init_var.sync = 0; + } else if (machine_is_tifon()) { + current_par.max_xres = 640; + current_par.max_yres = 200; + current_par.max_bpp = 4; + current_par.inv_4bpp = 1; + init_var.red.length = 4; + init_var.green = init_var.red; + init_var.blue = init_var.red; + init_var.grayscale = 1; + init_var.pixclock = 150000; + init_var.left_margin = 20; + init_var.right_margin = 255; + init_var.upper_margin = 20; + init_var.lower_margin = 0; + init_var.hsync_len = 2; + init_var.vsync_len = 1; + init_var.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT; + init_var.vmode = 0; + } - current_par.montype = -1; - current_par.currcon = -1; - current_par.allow_modeset = 1; - current_par.controller_state = LCD_MODE_DISABLED; + current_par.p_palette_base = NULL; + current_par.v_palette_base = NULL; + current_par.p_screen_base = NULL; + current_par.v_screen_base = NULL; + current_par.palette_size = MAX_PALETTE_NUM_ENTRIES; + current_par.screen_size = MAX_PIXEL_MEM_SIZE; + current_par.montype = -1; + current_par.currcon = -1; + current_par.allow_modeset = 1; + current_par.controller_state = LCD_MODE_DISABLED; + + init_var.xres = current_par.max_xres; + init_var.yres = current_par.max_yres; + init_var.xres_virtual = init_var.xres; + init_var.yres_virtual = init_var.yres; + init_var.bits_per_pixel = current_par.max_bpp; + } @@ -723,6 +720,8 @@ if (VideoMemRegion != NULL) return -EINVAL; + DPRINTK("-1-"); + /* Find order required to allocate enough memory for framebuffer */ required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT; for (order = 0 ; required_pages >> order ; order++) {;} @@ -741,7 +740,7 @@ free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT)); /* Set reserved flag for fb memory to allow it to be remapped into */ - /* user space by the common fbmem driver using remap_page_range(). */ + /* user space by the common fbmem driver using remap_page_range(). */ for(i = MAP_NR(VideoMemRegion); i < MAP_NR(VideoMemRegion + ALLOCATED_FB_MEM_SIZE); i++) set_bit(PG_reserved, &mem_map[i].flags); @@ -753,6 +752,7 @@ L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE); + memset(VideoMemRegion, 0xAA, ALLOCATED_FB_MEM_SIZE); return (VideoMemRegion == NULL ? -EINVAL : 0); } @@ -776,16 +776,21 @@ }; -static int get_pcd(unsigned int pixclock) +static inline int get_pcd(unsigned int pixclock) { - unsigned int pcd; - pcd = frequency[PPCR &0xf] / 1000; - pcd *= pixclock/1000; - return pcd / 10000000 * 12; - /* the last multiplication by 1.2 is to handle */ - /* sync problems */ + unsigned int pcd = 0; + + if (machine_is_tifon()) { + pcd = frequency[PPCR &0xf] / 1000; + pcd *= pixclock/1000; + pcd = pcd / 10000000 * 12; + /* the last multiplication by 1.2 is to handle */ + /* sync problems */ + } + return pcd; } + /* * sa1100fb_activate_var(): * Configures LCD Controller based on entries in var parameter. Settings are @@ -797,105 +802,138 @@ u_long flags; int pcd = get_pcd(var->pixclock); + DPRINTK("Configuring SA1100 LCD\n"); + if (current_par.p_palette_base == NULL) return -EINVAL; + DPRINTK("activating\n"); + /* Disable interrupts and save status */ save_flags_cli(flags); // disable the interrupts and save flags /* Reset the LCD Controller's DMA address if it has changed */ lcd_shadow.dbar1 = (Address)current_par.p_palette_base; -#if defined(CONFIG_SA1100_PENNY) - DPRINTK("Configuring SA1100 LCD\n"); - - DPRINTK("Configuring xres = %d, yres = %d\n",var->xres, var->yres); - - lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + - LCCR0_DMADel(0); - lcd_shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth (65) + - LCCR1_EndLnDel (43) + LCCR1_BegLnDel(43) ; - lcd_shadow.lccr2 = LCCR2_DisHght (var->yres) + LCCR2_VrtSnchWdth (35) + - LCCR2_EndFrmDel (0) + LCCR2_BegFrmDel (0) ; - lcd_shadow.lccr3 = LCCR3_PixClkDiv(16) + - LCCR3_ACBsDiv (2) + LCCR3_ACBsCntOff + - ((var->sync & FB_SYNC_HOR_HIGH_ACT) ?LCCR3_HorSnchH:LCCR3_HorSnchL) + - ((var->sync & FB_SYNC_VERT_HIGH_ACT)?LCCR3_VrtSnchH:LCCR3_VrtSnchL); - -#elif defined(CONFIG_SA1100_BRUTUS) - DPRINTK("Configuring BRUTUS LCD\n"); - lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + - LCCR0_DMADel(0); - lcd_shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + - LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101); - lcd_shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + - LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); - lcd_shadow.lccr3 = LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + LCCR3_HorSnchH + - LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44); -#elif defined(CONFIG_SA1100_THINCLIENT) - DPRINTK("Configuring ThinClient LCD\n"); DPRINTK("Configuring xres = %d, yres = %d\n",var->xres, var->yres); - lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + - LCCR0_Act; - lcd_shadow.lccr1 = LCCR1_DisWdth(var->xres) +LCCR1_HorSnchWdth(10)+ - LCCR1_EndLnDel (81) + LCCR1_BegLnDel(81) ; - lcd_shadow.lccr2 = LCCR2_DisHght (var->yres) +LCCR2_VrtSnchWdth(9) + - LCCR2_EndFrmDel (20) + LCCR2_BegFrmDel (20) ; - lcd_shadow.lccr3 = LCCR3_PixClkDiv(6) + - LCCR3_ACBsDiv (2) + LCCR3_ACBsCntOff + - LCCR3_HorSnchL + LCCR3_VrtSnchL; - -#elif defined(CONFIG_SA1100_TIFON) - DPRINTK("Configuring TIFON LCD\n"); - - lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + - LCCR0_BigEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + - LCCR0_8PixMono + LCCR0_DMADel(0); - lcd_shadow.lccr1 = LCCR1_DisWdth( var->xres ) + - LCCR1_HorSnchWdth( var->hsync_len) + - LCCR1_BegLnDel( var->left_margin) + - LCCR1_EndLnDel( var->right_margin); - lcd_shadow.lccr2 = LCCR2_DisHght( var->yres ) + - LCCR2_VrtSnchWdth( var->vsync_len )+ - LCCR2_BegFrmDel( var->upper_margin ) + - LCCR2_EndFrmDel( var->lower_margin ); - lcd_shadow.lccr3 = LCCR3_PixClkDiv( pcd ) + - LCCR3_ACBsDiv( 512 ) + - LCCR3_ACBsCnt(0) + - LCCR3_HorSnchH + LCCR3_VrtSnchH; - /* - ((current_var.sync & FB_SYNC_HOR_HIGH_ACT) ? - LCCR3_HorSnchH : LCCR3_HorSnchL) + - ((current_var.sync & FB_SYNC_VERT_HIGH_ACT) ? - LCCR3_VrtSnchH : LCCR3_VrtSnchL); - */ -#elif defined(CONFIG_SA1100_LART) - DPRINTK("Configuring LART LCD\n"); - - lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + - LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + - LCCR0_DMADel(0); - lcd_shadow.lccr1 = LCCR1_DisWdth( var->xres ) + - LCCR1_HorSnchWdth( 2 ) + - LCCR1_BegLnDel( 4 ) + - LCCR1_EndLnDel( 2 ); - lcd_shadow.lccr2 = LCCR2_DisHght( var->yres ) + - LCCR2_VrtSnchWdth( 1 )+ - LCCR2_BegFrmDel( 0 ) + - LCCR2_EndFrmDel( 0 ); - lcd_shadow.lccr3 = LCCR3_PixClkDiv( 34 ) + - LCCR3_ACBsDiv( 512 ) + - LCCR3_ACBsCntOff + - LCCR3_HorSnchH + - LCCR3_VrtSnchH; -#endif - - /* Restore status of interrupts */ - restore_flags(flags); + if (machine_is_assabet()) { + DPRINTK("Configuring Assabet LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Act + + LCCR0_LtlEnd + LCCR0_DMADel(0); + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + + LCCR1_BegLnDel(30) + LCCR1_EndLnDel(30); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); + lcd_shadow.lccr3 = + LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + + LCCR3_HorSnchH + LCCR3_ACBsCntOff + + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(28); + } else if (machine_is_bitsy()) { + DPRINTK("Configuring Bitsy LCD\n"); + lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + + LCCR0_DMADel(0); + lcd_shadow.lccr1 = LCCR1_DisWdth( var->xres ) + + LCCR1_HorSnchWdth( 4 ) + + LCCR1_BegLnDel( 0x1f ) + + LCCR1_EndLnDel( 0x1f ); + lcd_shadow.lccr2 = LCCR2_DisHght( var->yres ) + + LCCR2_VrtSnchWdth( 1 )+ + LCCR2_BegFrmDel( 0 ) + + LCCR2_EndFrmDel( 0 ); + lcd_shadow.lccr3 = 15; + } else if (machine_is_brutus()) { + DPRINTK("Configuring Brutus LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + + LCCR0_DMADel(0); + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + + LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); + lcd_shadow.lccr3 = + LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + + LCCR3_HorSnchH + LCCR3_ACBsCntOff + + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44); + } else if (machine_is_lart()) { + DPRINTK("Configuring LART LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + + LCCR0_DMADel(0); + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) + + LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); + lcd_shadow.lccr3 = + LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) + + LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH; + } else if (machine_is_penny()) { + DPRINTK("Configuring Penny LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + + LCCR0_DMADel(0); + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(65) + + LCCR1_EndLnDel(43) + LCCR1_BegLnDel(43); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(35) + + LCCR2_EndFrmDel(0) + LCCR2_BegFrmDel(0); + lcd_shadow.lccr3 = + LCCR3_PixClkDiv(16) + LCCR3_ACBsDiv (2) + LCCR3_ACBsCntOff + + ((var->sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HorSnchH : LCCR3_HorSnchL) + + ((var->sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); + } else if (machine_is_thinclient() || machine_is_graphicsclient()) { + DPRINTK("Configuring ThinClient LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act; + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(10) + + LCCR1_EndLnDel(81) + LCCR1_BegLnDel(81); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) + + LCCR2_EndFrmDel (20) + LCCR2_BegFrmDel(20); + lcd_shadow.lccr3 = + LCCR3_PixClkDiv(6) + LCCR3_ACBsDiv(2) + + LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL; + } else if (machine_is_tifon()) { + DPRINTK("Configuring TIFON LCD\n"); + lcd_shadow.lccr0 = + LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + + LCCR0_BigEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + + LCCR0_8PixMono + LCCR0_DMADel(0); + lcd_shadow.lccr1 = + LCCR1_DisWdth(var->xres) + + LCCR1_HorSnchWdth(var->hsync_len) + + LCCR1_BegLnDel(var->left_margin) + + LCCR1_EndLnDel(var->right_margin); + lcd_shadow.lccr2 = + LCCR2_DisHght(var->yres) + + LCCR2_VrtSnchWdth(var->vsync_len) + + LCCR2_BegFrmDel(var->upper_margin) + + LCCR2_EndFrmDel(var->lower_margin); + lcd_shadow.lccr3 = + LCCR3_PixClkDiv(pcd) + LCCR3_ACBsDiv(512) + + LCCR3_ACBsCnt(0) + LCCR3_HorSnchH + LCCR3_VrtSnchH; + /* + ((current_var.sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HorSnchH : LCCR3_HorSnchL) + + ((current_var.sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); + */ + } + /* Restore interrupt status */ + restore_flags(flags); if (( LCCR0 != lcd_shadow.lccr0 ) || ( LCCR1 != lcd_shadow.lccr1 ) || @@ -937,26 +975,36 @@ */ static void sa1100fb_disable_lcd_controller(void) { - DPRINTK("sa1100fb: Disabling LCD controller\n"); + DPRINTK("Disabling LCD controller\n"); /* Exit if already LCD disabled, or LDD IRQ unmasked */ if ((current_par.controller_state == LCD_MODE_DISABLED) || (!(LCCR0 & LCCR0_LDM))) { - DPRINTK("sa1100fb: LCD already disabled\n"); + DPRINTK("LCD already disabled\n"); return; } -#if defined(CONFIG_SA1100_PENNY) - FpgaLcdCS1 = 0x000; /* LCD Backlight to 0% */ - FpgaPortI &= ~LCD_ON; /* Turn off LCD Backlight */ -#elif defined(CONFIG_SA1100_TIFON) - GPCR = GPIO_GPIO(24); /* turn off display */ + if (machine_is_assabet()) { +#ifdef CONFIG_SA1100_ASSABET + BCR_clear(BCR_LCD_ON); +#endif + } else if (machine_is_bitsy()) { +#ifdef CONFIG_SA1100_BITSY + clr_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON); #endif + } else if (machine_is_penny()) { +#ifdef CONFIG_SA1100_PENNY + FpgaLcdCS1 = 0x000; /* LCD Backlight to 0% */ + FpgaPortI &= ~LCD_ON; /* Turn off LCD Backlight */ +#endif + } else if (machine_is_tifon()) { + GPCR = GPIO_GPIO(24); /* turn off display */ + } - LCSR = 0; /* Clear LCD Status Register */ - LCCR0 &= ~(LCCR0_LDM); /* Enable LCD Disable Done Interrupt */ + LCSR = 0; /* Clear LCD Status Register */ + LCCR0 &= ~(LCCR0_LDM); /* Enable LCD Disable Done Interrupt */ enable_irq(IRQ_LCD); /* Enable LCD IRQ */ - LCCR0 &= ~(LCCR0_LEN); /* Disable LCD Controller */ + LCCR0 &= ~(LCCR0_LEN); /* Disable LCD Controller */ } @@ -977,7 +1025,7 @@ current_par.controller_state = LCD_MODE_DISABLE_BEFORE_ENABLE; sa1100fb_disable_lcd_controller(); } else { - DPRINTK("sa1100fb: Enabling LCD controller\n"); + DPRINTK("Enabling LCD controller\n"); /* Make sure the mode bits are present in the first palette entry */ current_par.v_palette_base[0] &= 0x0FFF; @@ -992,21 +1040,35 @@ LCCR1 = lcd_shadow.lccr1; LCCR0 = lcd_shadow.lccr0; -#if defined(CONFIG_SA1100_PENNY) - FpgaLcdCS1 = 0x0FF; /* LCD Backlight to 100% */ - FpgaPortI |= LCD_ON; /* Turn on LCD Backlight */ -#elif defined(CONFIG_SA1100_TIFON) - GPCR = GPIO_GPIO(24); /* cycle on/off-switch */ - udelay(150); - GPSR = GPIO_GPIO(24); /* turn on display */ - udelay(150); - GPSR = GPIO_GPIO(24); /* turn on display */ + if (machine_is_assabet()) { +#ifdef CONFIG_SA1100_ASSABET + BCR_set(BCR_LCD_ON); +#endif + } else if (machine_is_bitsy()) { +#ifdef CONFIG_SA1100_BITSY + set_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON) + DPRINTK("DBAR1=%p\n", DBAR1); + DPRINTK("LCCR0=%x\n", LCCR0); + DPRINTK("LCCR1=%x\n", LCCR1); + DPRINTK("LCCR2=%x\n", LCCR2); + DPRINTK("LCCR3=%x\n", LCCR3); #endif + } else if (machine_is_penny()) { +#ifdef CONFIG_SA1100_PENNY + FpgaLcdCS1 = 0x0FF; /* LCD Backlight to 100% */ + FpgaPortI |= LCD_ON; /* Turn on LCD Backlight */ +#endif + } else if (machine_is_tifon()) { + GPCR = GPIO_GPIO(24); /* cycle on/off-switch */ + udelay(150); + GPSR = GPIO_GPIO(24); /* turn on display */ + } + current_par.controller_state = LCD_MODE_ENABLED; - /* Restore status of interrupts */ - } - restore_flags(flags); + } + /* Restore interrupt status */ + restore_flags(flags); } @@ -1046,12 +1108,14 @@ { int i; + DPRINTK("blank=%d info->modename=%s\n", blank, info->modename); if (blank) { for (i = 0; i < current_par.palette_size; i++) sa1100fb_palette_write(i, sa1100fb_palette_encode(i, 0, 0, 0, 0)); sa1100fb_disable_lcd_controller(); } else { + if (current_par.visual != FB_VISUAL_TRUECOLOR) sa1100fb_set_cmap(&fb_display[current_par.currcon].cmap, 1, current_par.currcon, info); sa1100fb_enable_lcd_controller(); @@ -1067,8 +1131,10 @@ static int sa1100fb_switch(int con, struct fb_info *info) { - struct fb_cmap *cmap; + DPRINTK("con=%d info->modename=%s\n", con, info->modename); + if (current_par.visual != FB_VISUAL_TRUECOLOR) { + struct fb_cmap *cmap; if (current_par.currcon >= 0) { // Get the colormap for the selected console cmap = &fb_display[current_par.currcon].cmap; @@ -1076,9 +1142,11 @@ if (cmap->len) fb_get_cmap(cmap, 1, sa1100fb_getcolreg, info); } + } current_par.currcon = con; fb_display[con].var.activate = FB_ACTIVATE_NOW; + DPRINTK("fb_display[%d].var.activate=%x\n", con, fb_display[con].var.activate); sa1100fb_set_var(&fb_display[con].var, con, info); return 0; } @@ -1086,44 +1154,47 @@ void __init sa1100fb_init(void) { - current_par.p_palette_base = NULL; - current_par.v_palette_base = NULL; - current_par.p_screen_base = NULL; - current_par.v_screen_base = NULL; - current_par.palette_size = MAX_PALETTE_NUM_ENTRIES; - current_par.screen_size = MAX_PIXEL_MEM_SIZE; - -#if defined(CONFIG_SA1100_PENNY) - GPDR |= GPIO_GPDR_GFX; /* GPIO Data Direction register for LCD data bits 8-11 */ - GAFR |= GPIO_GAFR_GFX; /* GPIO Alternate Function register for LCD data bits 8-11 */ -#elif defined(CONFIG_SA1100_TIFON) - - GPDR = GPDR | GPIO_GPIO(24); /* set GPIO24 to output */ -#endif + sa1100fb_init_fbinfo(); /* Initialize video memory */ if (sa1100fb_map_video_memory()) - return; + return; - sa1100fb_init_fbinfo(); if (current_par.montype < 0 || current_par.montype > NR_MONTYPES) current_par.montype = 1; - /* Request the interrupt in the init routine only because */ - /* this driver will not be used as a module. */ - if (request_irq(IRQ_LCD, sa1100fb_inter_handler, SA_INTERRUPT, "SA1100 LCD", NULL)!= 0) { - DPRINTK("sa1100fb: failed in request_irq\n"); + if (request_irq(IRQ_LCD, sa1100fb_inter_handler, SA_INTERRUPT, "SA1100 LCD", NULL) != 0) { + printk("sa1100fb: failed in request_irq\n"); + return; } DPRINTK("sa1100fb: request_irq succeeded\n"); disable_irq(IRQ_LCD); + if (machine_is_assabet()) { +#ifdef CONFIG_SA1100_ASSABET + GPDR |= 0x3fc; + GAFR |= 0x3fc; + BCR_clear(BCR_LCD_12RGB); +#endif + } else if (machine_is_bitsy()) { + GPDR = (GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8); + GAFR |= (GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8); + } else if (machine_is_penny()) { +#ifdef CONFIG_SA1100_PENNY + GPDR |= GPIO_GPDR_GFX; /* GPIO Data Direction register for LCD data bits 8-11 */ + GAFR |= GPIO_GAFR_GFX; /* GPIO Alternate Function register for LCD data bits 8-11 */ +#endif + } else if (machine_is_tifon()) { + GPDR |= GPIO_GPIO(24); /* set GPIO24 to output */ + } + if (sa1100fb_set_var(&init_var, -1, &fb_info)) current_par.allow_modeset = 0; sa1100fb_decode_var(&init_var, ¤t_par); register_framebuffer(&fb_info); - /* This driver cannot be unloaded */ + /* This driver cannot be unloaded at the moment */ MOD_INC_USE_COUNT; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/sbusfb.c linux.ac/drivers/video/sbusfb.c --- linux.vanilla/drivers/video/sbusfb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/sbusfb.c Sat Jun 10 21:50:43 2000 @@ -133,7 +133,6 @@ if (user) { if (fb->open == 0) { fb->mmaped = 0; - fb->open = 1; fb->vtconsole = -1; } fb->open++; @@ -160,7 +159,6 @@ if (fb->reset) fb->reset(fb); } - fb->open = 0; } else fb->consolecnt--; MOD_DEC_USE_COUNT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/video/vga16fb.c linux.ac/drivers/video/vga16fb.c --- linux.vanilla/drivers/video/vga16fb.c Thu May 25 17:38:11 2000 +++ linux.ac/drivers/video/vga16fb.c Sat May 27 15:23:43 2000 @@ -387,7 +387,7 @@ if (pos & 0x200) r7 |= 0x80; pos += vslen; - par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */ + par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */ pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/Config.in linux.ac/fs/Config.in --- linux.vanilla/fs/Config.in Thu May 25 17:37:32 2000 +++ linux.ac/fs/Config.in Fri Jun 9 15:51:51 2000 @@ -78,6 +78,7 @@ dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET dep_mbool ' Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD + dep_mbool ' Provide NFS server over TCP support (DEVELOPER-ONLY)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then define_tristate CONFIG_SUNRPC y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/affs/inode.c linux.ac/fs/affs/inode.c --- linux.vanilla/fs/affs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/affs/inode.c Sat Jun 10 22:18:33 2000 @@ -270,7 +270,7 @@ inode->i_ino,inode->i_nlink); affs_free_prealloc(inode); - if (inode->i_count == 1) { + if (atomic_read(&inode->i_count) == 1) { unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec; if (cache_page) { pr_debug("AFFS: freeing ext cache\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/affs/namei.c linux.ac/fs/affs/namei.c --- linux.vanilla/fs/affs/namei.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/affs/namei.c Sat Jun 10 22:18:33 2000 @@ -512,7 +512,7 @@ dir->i_version = ++event; mark_inode_dirty(dir); mark_inode_dirty(oldinode); - oldinode->i_count++; + atomic_inc(&oldinode->i_count); d_instantiate(dentry,oldinode); } mark_inode_dirty(inode); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/bfs/dir.c linux.ac/fs/bfs/dir.c --- linux.vanilla/fs/bfs/dir.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/bfs/dir.c Sat Jun 10 22:18:33 2000 @@ -152,7 +152,7 @@ inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(new, inode); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/bfs/inode.c linux.ac/fs/bfs/inode.c --- linux.vanilla/fs/bfs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/bfs/inode.c Sat Jun 10 22:18:33 2000 @@ -1,7 +1,7 @@ /* * fs/bfs/inode.c * BFS superblock and inode operations. - * Copyright (C) 1999 Tigran Aivazian + * Copyright (C) 1999 Tigran Aivazian * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds. */ @@ -16,7 +16,7 @@ #include "bfs_defs.h" -MODULE_AUTHOR("Tigran A. Aivazian"); +MODULE_AUTHOR("Tigran A. Aivazian "); MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux"); EXPORT_NO_SYMBOLS; @@ -139,8 +139,6 @@ dprintf("ino=%08lx\n", inode->i_ino); - if (!inode || !inode->i_dev || inode->i_count > 1 || inode->i_nlink || !s) - return; if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) { printf("invalid ino=%08lx\n", inode->i_ino); return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/binfmt_elf.c linux.ac/fs/binfmt_elf.c --- linux.vanilla/fs/binfmt_elf.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/binfmt_elf.c Mon Jun 5 19:37:23 2000 @@ -450,7 +450,7 @@ if (elf_ppnt->p_type == PT_INTERP) { retval = -EINVAL; if (elf_interpreter) - goto out_free_interp; + goto out_free_dentry; /* This is the program interpreter used for * shared libraries - for now assume that this diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/block_dev.c linux.ac/fs/block_dev.c --- linux.vanilla/fs/block_dev.c Thu May 25 17:46:15 2000 +++ linux.ac/fs/block_dev.c Sat Jun 10 21:51:07 2000 @@ -313,7 +313,7 @@ * since the vma has no handle. */ -static int block_fsync(struct file *filp, struct dentry *dentry) +static int block_fsync(struct file *filp, struct dentry *dentry, int datasync) { return fsync_dev(dentry->d_inode->i_rdev); } @@ -597,6 +597,8 @@ ret = bdev->bd_op->open(fake_inode, &fake_file); if (!ret) atomic_inc(&bdev->bd_openers); + else if (!atomic_read(&bdev->bd_openers)) + bdev->bd_op = NULL; iput(fake_inode); } } @@ -617,6 +619,8 @@ ret = bdev->bd_op->open(inode,filp); if (!ret) atomic_inc(&bdev->bd_openers); + else if (!atomic_read(&bdev->bd_openers)) + bdev->bd_op = NULL; } up(&bdev->bd_sem); return ret; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/buffer.c linux.ac/fs/buffer.c --- linux.vanilla/fs/buffer.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/buffer.c Sat Jun 10 21:51:07 2000 @@ -68,6 +68,8 @@ * lru_list_lock > hash_table_lock > free_list_lock > unused_list_lock */ +#define BH_ENTRY(list) list_entry((list), struct buffer_head, b_inode_buffers) + /* * Hash table gook.. */ @@ -323,7 +325,7 @@ * filp may be NULL if called via the msync of a vma. */ -int file_fsync(struct file *filp, struct dentry *dentry) +int file_fsync(struct file *filp, struct dentry *dentry, int datasync) { struct inode * inode = dentry->d_inode; struct super_block * sb; @@ -332,7 +334,7 @@ lock_kernel(); /* sync the inode to buffers */ - write_inode_now(inode); + write_inode_now(inode, 0); /* sync the superblock to buffers */ sb = inode->i_sb; @@ -373,7 +375,7 @@ /* We need to protect against concurrent writers.. */ down(&inode->i_sem); - err = file->f_op->fsync(file, dentry); + err = file->f_op->fsync(file, dentry, 0); up(&inode->i_sem); out_putf: @@ -406,9 +408,8 @@ if (!file->f_op || !file->f_op->fsync) goto out_putf; - /* this needs further work, at the moment it is identical to fsync() */ down(&inode->i_sem); - err = file->f_op->fsync(file, dentry); + err = file->f_op->fsync(file, dentry, 1); up(&inode->i_sem); out_putf: @@ -535,8 +536,7 @@ * As we don't lock buffers (unless we are reading them, that is), * something might happen to it while we sleep (ie a read-error * will force it bad). This shouldn't really happen currently, but - * the code is ready. - */ + * the code is ready. */ struct buffer_head * get_hash_table(kdev_t dev, int block, int size) { struct buffer_head **head = &hash(dev, block); @@ -574,6 +574,42 @@ return 0; } +void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode) +{ + spin_lock(&lru_list_lock); + if (bh->b_inode) + list_del(&bh->b_inode_buffers); + bh->b_inode = inode; + list_add(&bh->b_inode_buffers, &inode->i_dirty_buffers); + spin_unlock(&lru_list_lock); +} + +/* The caller must have the lru_list lock before calling the + remove_inode_queue functions. */ +static void __remove_inode_queue(struct buffer_head *bh) +{ + bh->b_inode = NULL; + list_del(&bh->b_inode_buffers); +} + +static inline void remove_inode_queue(struct buffer_head *bh) +{ + if (bh->b_inode) + __remove_inode_queue(bh); +} + +int inode_has_buffers(struct inode *inode) +{ + int ret; + + spin_lock(&lru_list_lock); + ret = !list_empty(&inode->i_dirty_buffers); + spin_unlock(&lru_list_lock); + + return ret; +} + + /* If invalidate_buffers() will trash dirty buffers, it means some kind of fs corruption is going on. Trashing dirty data always imply losing information that was supposed to be just stored on the physical layer @@ -801,6 +837,137 @@ return; } + +/* + * Synchronise all the inode's dirty buffers to the disk. + * + * We have conflicting pressures: we want to make sure that all + * initially dirty buffers get waited on, but that any subsequently + * dirtied buffers don't. After all, we don't want fsync to last + * forever if somebody is actively writing to the file. + * + * Do this in two main stages: first we copy dirty buffers to a + * temporary inode list, queueing the writes as we go. Then we clean + * up, waiting for those writes to complete. + * + * During this second stage, any subsequent updates to the file may end + * up refiling the buffer on the original inode's dirty list again, so + * there is a chance we will end up with a buffer queued for write but + * not yet completed on that list. So, as a final cleanup we go through + * the osync code to catch these locked, dirty buffers without requeuing + * any newly dirty buffers for write. + */ + +int fsync_inode_buffers(struct inode *inode) +{ + struct buffer_head *bh; + struct inode tmp; + int err = 0, err2; + + INIT_LIST_HEAD(&tmp.i_dirty_buffers); + + spin_lock(&lru_list_lock); + + while (!list_empty(&inode->i_dirty_buffers)) { + bh = BH_ENTRY(inode->i_dirty_buffers.next); + list_del(&bh->b_inode_buffers); + if (!buffer_dirty(bh) && !buffer_locked(bh)) + bh->b_inode = NULL; + else { + bh->b_inode = &tmp; + list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers); + atomic_inc(&bh->b_count); + if (buffer_dirty(bh)) { + spin_unlock(&lru_list_lock); + ll_rw_block(WRITE, 1, &bh); + spin_lock(&lru_list_lock); + } + } + } + + while (!list_empty(&tmp.i_dirty_buffers)) { + bh = BH_ENTRY(tmp.i_dirty_buffers.prev); + remove_inode_queue(bh); + spin_unlock(&lru_list_lock); + wait_on_buffer(bh); + if (!buffer_uptodate(bh)) + err = -EIO; + brelse(bh); + spin_lock(&lru_list_lock); + } + + spin_unlock(&lru_list_lock); + err2 = osync_inode_buffers(inode); + + if (err) + return err; + else + return err2; +} + + +/* + * osync is designed to support O_SYNC io. It waits synchronously for + * all already-submitted IO to complete, but does not queue any new + * writes to the disk. + * + * To do O_SYNC writes, just queue the buffer writes with ll_rw_block as + * you dirty the buffers, and then use osync_inode_buffers to wait for + * completion. Any other dirty buffers which are not yet queued for + * write will not be flushed to disk by the osync. + */ + +int osync_inode_buffers(struct inode *inode) +{ + struct buffer_head *bh; + struct list_head *list; + int err = 0; + + spin_lock(&lru_list_lock); + + repeat: + + for (list = inode->i_dirty_buffers.prev; + bh = BH_ENTRY(list), list != &inode->i_dirty_buffers; + list = bh->b_inode_buffers.prev) { + if (buffer_locked(bh)) { + atomic_inc(&bh->b_count); + spin_unlock(&lru_list_lock); + wait_on_buffer(bh); + brelse(bh); + if (!buffer_uptodate(bh)) + err = -EIO; + spin_lock(&lru_list_lock); + goto repeat; + } + } + + spin_unlock(&lru_list_lock); + return err; +} + + +/* + * Invalidate any and all dirty buffers on a given inode. We are + * probably unmounting the fs, but that doesn't mean we have already + * done a sync(). Just drop the buffers from the inode list. + */ + +void invalidate_inode_buffers(struct inode *inode) +{ + struct list_head *list, *next; + + spin_lock(&lru_list_lock); + list = inode->i_dirty_buffers.next; + while (list != &inode->i_dirty_buffers) { + next = list->next; + remove_inode_queue(BH_ENTRY(list)); + list = next; + } + spin_unlock(&lru_list_lock); +} + + /* * Ok, this is getblk, and it isn't very clear, again to hinder * race-conditions. Most of the code is seldom used, (ie repeating), @@ -932,6 +1099,8 @@ __remove_from_lru_list(bh, bh->b_list); bh->b_list = dispose; __insert_into_lru_list(bh, dispose); + if (dispose == BUF_CLEAN) + remove_inode_queue(bh); } } @@ -968,6 +1137,7 @@ if (!atomic_dec_and_test(&buf->b_count) || buffer_locked(buf)) goto in_use; __hash_unlink(buf); + remove_inode_queue(buf); write_unlock(&hash_table_lock); __remove_from_lru_list(buf, buf->b_list); spin_unlock(&lru_list_lock); @@ -1068,6 +1238,8 @@ */ static __inline__ void __put_unused_buffer_head(struct buffer_head * bh) { + if (bh->b_inode) + BUG(); if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) { kmem_cache_free(bh_cachep, bh); } else { @@ -1281,6 +1453,58 @@ } } +/** + * discard_buffer - discard that buffer without doing any IO + * @bh: buffer to discard + * + * This function removes a buffer from all the queues, without doing + * any IO, we are not interested in the contents of the buffer. This + * function can block if the buffer is locked. + */ +static struct buffer_head *discard_buffer(struct buffer_head * bh) +{ + int index = BUFSIZE_INDEX(bh->b_size); + struct buffer_head *next; + + /* grab the lru lock here to block bdflush. */ + atomic_inc(&bh->b_count); + lock_buffer(bh); + next = bh->b_this_page; + clear_bit(BH_Uptodate, &bh->b_state); + clear_bit(BH_Mapped, &bh->b_state); + clear_bit(BH_Req, &bh->b_state); + clear_bit(BH_New, &bh->b_state); + + spin_lock(&lru_list_lock); + write_lock(&hash_table_lock); + spin_lock(&free_list[index].lock); + spin_lock(&unused_list_lock); + + if (!atomic_dec_and_test(&bh->b_count)) + BUG(); + + __hash_unlink(bh); + /* The bunffer can be either on the regular + * queues or on the free list.. + */ + if (bh->b_dev != B_FREE) { + remove_inode_queue(bh); + __remove_from_queues(bh); + } + else + __remove_from_free_list(bh, index); + __put_unused_buffer_head(bh); + spin_unlock(&unused_list_lock); + write_unlock(&hash_table_lock); + spin_unlock(&free_list[index].lock); + spin_unlock(&lru_list_lock); + /* We can unlock the buffer, we have just returned it. + * Ditto for the counter + */ + return next; +} + + /* * We don't have to release all buffers here, but * we have to be sure that no dirty buffer is left @@ -1313,26 +1537,45 @@ bh = next; } while (bh != head); - /* - * subtle. We release buffer-heads only if this is - * the 'final' flushpage. We have invalidated the get_block - * cached value unconditionally, so real IO is not - * possible anymore. - * - * If the free doesn't work out, the buffers can be - * left around - they just turn into anonymous buffers - * instead. - */ - if (!offset) { - if (!try_to_free_buffers(page, 0)) { - atomic_inc(&buffermem_pages); - return 0; - } - } - return 1; } +/** + * block_destroy_buffers - Will destroy the contents of all the + * buffers in this page + * @page: page to examine the buffers + * + * This function destroy all the buffers in one page without making + * any IO. The function can block due to the fact that discad_bufferr + * can block. + */ +void block_destroy_buffers(struct page *page) +{ + struct buffer_head *bh, *head; + + if (!PageLocked(page)) + BUG(); + if (!page->buffers) + return; + + head = page->buffers; + bh = head; + do { + /* We need to get the next buffer from discard buffer + * because discard buffer can block and anybody else + * can change the buffer list under our feet. + */ + bh = discard_buffer(bh); + }while (bh != head); + + /* Wake up anyone waiting for buffer heads */ + wake_up(&buffer_wait); + + /* And free the page */ + page->buffers = NULL; + page_cache_release(page); +} + static void create_empty_buffers(struct page *page, struct inode *inode, unsigned long blocksize) { struct buffer_head *bh, *head, *tail; @@ -1507,6 +1750,7 @@ } else { set_bit(BH_Uptodate, &bh->b_state); if (!atomic_set_buffer_dirty(bh)) { + buffer_insert_inode_queue(bh, inode); __mark_dirty(bh, 0); need_balance_dirty = 1; } @@ -1799,6 +2043,7 @@ } spin_unlock(&unused_list_lock); + wake_up(&buffer_wait); return iosize; } @@ -1935,6 +2180,8 @@ __put_unused_buffer_head(bh[bhind]); } spin_unlock(&unused_list_lock); + wake_up(&buffer_wait); + goto finished; } @@ -2112,6 +2359,12 @@ } /* + * Can the buffer be thrown out? + */ +#define BUFFER_BUSY_BITS ((1<b_count) | ((bh)->b_state & BUFFER_BUSY_BITS)) + +/* * Sync all the buffers on one page.. * * If we have old buffers that are locked, we'll @@ -2121,7 +2374,7 @@ * This all is required so that we can free up memory * later. */ -static void sync_page_buffers(struct buffer_head *bh, int wait) +static int sync_page_buffers(struct buffer_head *bh, int wait) { struct buffer_head * tmp = bh; @@ -2134,13 +2387,17 @@ } else if (buffer_dirty(p)) ll_rw_block(WRITE, 1, &p); } while (tmp != bh); -} -/* - * Can the buffer be thrown out? - */ -#define BUFFER_BUSY_BITS ((1<b_count) | ((bh)->b_state & BUFFER_BUSY_BITS)) + do { + struct buffer_head *p = tmp; + tmp = tmp->b_this_page; + if (buffer_busy(p)) + return 0; + } while (tmp != bh); + + /* Success. Now try_to_free_buffers can free the page. */ + return 1; +} /* * try_to_free_buffers() checks if all the buffers on this particular page @@ -2158,6 +2415,7 @@ struct buffer_head * tmp, * bh = page->buffers; int index = BUFSIZE_INDEX(bh->b_size); +again: spin_lock(&lru_list_lock); write_lock(&hash_table_lock); spin_lock(&free_list[index].lock); @@ -2179,8 +2437,12 @@ /* The buffer can be either on the regular * queues or on the free list.. */ - if (p->b_dev != B_FREE) + if (p->b_dev != B_FREE) { + // @@@ + if (p->b_inode) + BUG(); __remove_from_queues(p); + } else __remove_from_free_list(p, index); __put_unused_buffer_head(p); @@ -2203,7 +2465,8 @@ spin_unlock(&free_list[index].lock); write_unlock(&hash_table_lock); spin_unlock(&lru_list_lock); - sync_page_buffers(bh, wait); + if (sync_page_buffers(bh, wait)) + goto again; return 0; } @@ -2499,7 +2762,7 @@ * the syscall above, but now we launch it ourselves internally with * kernel_thread(...) directly after the first thread in init/main.c */ -int bdflush(void * unused) +int bdflush(void *sem) { struct task_struct *tsk = current; int flushed; @@ -2521,6 +2784,8 @@ recalc_sigpending(tsk); spin_unlock_irq(&tsk->sigmask_lock); + up((struct semaphore *)sem); + for (;;) { CHECK_EMERGENCY_SYNC @@ -2555,7 +2820,7 @@ * You don't need to change your userspace configuration since * the userspace `update` will do_exit(0) at the first sys_bdflush(). */ -int kupdate(void * unused) +int kupdate(void *sem) { struct task_struct * tsk = current; int interval; @@ -2571,6 +2836,8 @@ recalc_sigpending(tsk); spin_unlock_irq(&tsk->sigmask_lock); + up((struct semaphore *)sem); + for (;;) { /* update interval */ interval = bdf_prm.b_un.interval; @@ -2604,8 +2871,11 @@ static int __init bdflush_init(void) { - kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - kernel_thread(kupdate, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + DECLARE_MUTEX_LOCKED(sem); + kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + down(&sem); + kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + down(&sem); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/coda/cnode.c linux.ac/fs/coda/cnode.c --- linux.vanilla/fs/coda/cnode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/coda/cnode.c Sat Jun 10 22:18:33 2000 @@ -139,7 +139,7 @@ if ( coda_fideq(fid, &cnp->c_fid) ) { CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n", - (*inode)->i_ino, (*inode)->i_count, + (*inode)->i_ino, atomic_read(&(*inode)->i_count), coda_f2s(&cnp->c_fid)); EXIT; return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/coda/dir.c linux.ac/fs/coda/dir.c --- linux.vanilla/fs/coda/dir.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/coda/dir.c Sat Jun 10 22:18:33 2000 @@ -50,7 +50,7 @@ /* support routines */ static int coda_venus_readdir(struct file *filp, void *dirent, filldir_t filldir); -int coda_fsync(struct file *, struct dentry *dentry); +int coda_fsync(struct file *, struct dentry *dentry, int); int coda_crossvol_rename = 0; int coda_hasmknod = 0; @@ -117,7 +117,7 @@ error = coda_cnode_makectl(&res_inode, dir->i_sb); CDEBUG(D_SPECIAL, "Lookup on CTL object; dir ino %ld, count %d\n", - dir->i_ino, dir->i_count); + dir->i_ino, atomic_read(&dir->i_count)); goto exit; } @@ -358,7 +358,7 @@ if ( ! error ) { dir_cnp->c_flags |= C_VATTR; - ++inode->i_count; + atomic_inc(&inode->i_count); d_instantiate(de, inode); inode->i_nlink++; } else { @@ -597,9 +597,9 @@ cnp->c_ocount++; CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", - error, i->i_count, i->i_ino); + error, atomic_read(&i->i_count), i->i_ino); CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", - cnp->c_ovp->i_ino, cnp->c_ovp->i_count, + cnp->c_ovp->i_ino, atomic_read(&cnp->c_ovp->i_count), (cnp->c_ovp->i_op)); EXIT; return 0; @@ -622,8 +622,9 @@ CHECK_CNODE(cnp); CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n", - i->i_ino, i->i_count, (cnp->c_ovp ? cnp->c_ovp->i_ino : 0), - (cnp->c_ovp ? cnp->c_ovp->i_count : -99)); + i->i_ino, atomic_read(&i->i_count), + (cnp->c_ovp ? cnp->c_ovp->i_ino : 0), + (cnp->c_ovp ? atomic_read(&cnp->c_ovp->i_count) : -99)); /* even when c_ocount=0 we cannot put c_ovp to diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/coda/file.c linux.ac/fs/coda/file.c --- linux.vanilla/fs/coda/file.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/coda/file.c Sat Jun 10 21:51:07 2000 @@ -30,7 +30,7 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma); /* also exported from this file (used for dirs) */ -int coda_fsync(struct file *, struct dentry *dentry); +int coda_fsync(struct file *, struct dentry *dentry, int); struct inode_operations coda_file_inode_operations = { permission: coda_permission, @@ -65,7 +65,7 @@ return res; } -int coda_fsync(struct file *coda_file, struct dentry *coda_dentry) +int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) { struct coda_inode_info *cnp; struct inode *coda_inode = coda_dentry->d_inode; @@ -96,7 +96,7 @@ down(&cont_inode->i_sem); - result = file_fsync(&cont_file ,&cont_dentry); + result = file_fsync(&cont_file ,&cont_dentry, 0); if ( result == 0 ) { result = venus_fsync(coda_inode->i_sb, &(cnp->c_fid)); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/coda/inode.c linux.ac/fs/coda/inode.c --- linux.vanilla/fs/coda/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/coda/inode.c Sat Jun 10 22:57:31 2000 @@ -148,10 +148,10 @@ { ENTRY; - CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count); + CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, atomic_read(&inode->i_count)); - if ( inode->i_count == 1 ) { - write_inode_now(inode); + if ( atomic_read(&inode->i_count) == 1 ) { + write_inode_now(inode, 0); inode->i_nlink = 0; } } @@ -163,7 +163,7 @@ ENTRY; CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); cii = ITOC(inode); if ( inode->i_ino == CTL_INO || cii->c_magic != CODA_CNODE_MAGIC ) { @@ -179,7 +179,7 @@ open_inode = cii->c_ovp; if ( open_inode ) { CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n", - open_inode->i_ino, open_inode->i_count); + open_inode->i_ino, atomic_read(&open_inode->i_count)); cii->c_ovp = NULL; inode->i_mapping = &inode->i_data; iput(open_inode); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/coda/pioctl.c linux.ac/fs/coda/pioctl.c --- linux.vanilla/fs/coda/pioctl.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/coda/pioctl.c Sat Jun 10 22:18:33 2000 @@ -120,7 +120,7 @@ CDEBUG(D_PIOCTL, "ioctl on inode %ld\n", target_inode->i_ino); CDEBUG(D_DOWNCALL, "dput on ino: %ld, icount %d, dcount %d\n", target_inode->i_ino, - target_inode->i_count, nd.dentry->d_count); + atomic_read(&target_inode->i_count), nd.dentry->d_count); path_release(&nd); return error; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/devfs/base.c linux.ac/fs/devfs/base.c --- linux.vanilla/fs/devfs/base.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/devfs/base.c Mon May 29 19:23:51 2000 @@ -737,7 +737,8 @@ * @namelen: The number of characters in @name. * @traverse_symlink: If %TRUE then the entry is traversed if it is a symlink. * - * Returns a pointer to the entry on success, else %NULL. + * Search for a devfs entry inside another devfs entry and returns a pointer + * to the entry on success, else %NULL. */ static struct devfs_entry *search_for_entry_in_dir (struct devfs_entry *parent, @@ -902,6 +903,7 @@ /** * find_by_dev - Find a devfs entry in a directory. + * @dir: The directory where to search * @major: The major number to search for. * @minor: The minor number to search for. * @type: The type of special file to search for. This may be either @@ -1746,8 +1748,8 @@ /** * devfs_set_file_size - Set the file size for a devfs regular file. - * de: The handle to the device entry. - * size: The new file size. + * @de: The handle to the device entry. + * @size: The new file size. * * Returns 0 on success, else a negative error code. */ @@ -1788,6 +1790,7 @@ /** * devfs_set_info - Set the info pointer written to private_data upon open. * @de: The handle to the device entry. + * @info: pointer to the data * * Returns 0 on success, else a negative error code. */ @@ -1940,8 +1943,8 @@ /** * devfs_unregister_chrdev - Optionally unregister a conventional character driver. - * major: The major number for the driver. - * name: The name of the driver (as seen in /proc/devices). + * @major: The major number for the driver. + * @name: The name of the driver (as seen in /proc/devices). * * This function will unregister a character driver provided the "devfs=only" * option was not provided at boot time. @@ -1976,7 +1979,6 @@ /** * devfs_setup - Process kernel boot options. * @str: The boot options after the "devfs=". - * @unused: Unused. */ SETUP_STATIC int __init devfs_setup (char *str) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/devpts/inode.c linux.ac/fs/devpts/inode.c --- linux.vanilla/fs/devpts/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/devpts/inode.c Sat Jun 10 22:18:33 2000 @@ -37,9 +37,9 @@ for ( i = 0 ; i < sbi->max_ptys ; i++ ) { if ( (inode = sbi->inodes[i]) ) { - if ( inode->i_count != 1 ) + if ( atomic_read(&inode->i_count) != 1 ) printk("devpts_put_super: badness: entry %d count %d\n", - i, inode->i_count); + i, atomic_read(&inode->i_count)); inode->i_nlink--; iput(inode); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/devpts/root.c linux.ac/fs/devpts/root.c --- linux.vanilla/fs/devpts/root.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/devpts/root.c Sat Jun 10 22:18:33 2000 @@ -129,7 +129,7 @@ dentry->d_inode = sbi->inodes[entry]; if ( dentry->d_inode ) - dentry->d_inode->i_count++; + atomic_inc(&dentry->d_inode->i_count); d_add(dentry, dentry->d_inode); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/exec.c linux.ac/fs/exec.c --- linux.vanilla/fs/exec.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/exec.c Wed May 31 11:17:01 2000 @@ -484,6 +484,8 @@ /* This is the point of no return */ release_old_signals(oldsig); + current->sas_ss_sp = current->sas_ss_size = 0; + if (current->euid == current->uid && current->egid == current->gid) current->dumpable = 1; name = bprm->filename; @@ -585,21 +587,18 @@ cap_clear(bprm->cap_effective); /* To support inheritance of root-permissions and suid-root - * executables under compatibility mode, we raise the - * effective and inherited bitmasks of the executable file - * (translation: we set the executable "capability dumb" and - * set the allowed set to maximum). We don't set any forced - * bits. + * executables under compatibility mode, we raise all three + * capability sets for the file. * * If only the real uid is 0, we only raise the inheritable - * bitmask of the executable file (translation: we set the - * allowed set to maximum and the application to "capability - * smart"). + * and permitted sets of the executable file. */ if (!issecure(SECURE_NOROOT)) { - if (bprm->e_uid == 0 || current->uid == 0) + if (bprm->e_uid == 0 || current->uid == 0) { cap_set_full(bprm->cap_inheritable); + cap_set_full(bprm->cap_permitted); + } if (bprm->e_uid == 0) cap_set_full(bprm->cap_effective); } @@ -610,10 +609,12 @@ * privilege does not go against other system constraints. * The new Permitted set is defined below -- see (***). */ { - kernel_cap_t working = - cap_combine(bprm->cap_permitted, - cap_intersect(bprm->cap_inheritable, - current->cap_inheritable)); + kernel_cap_t permitted, working; + + permitted = cap_intersect(bprm->cap_permitted, cap_bset); + working = cap_intersect(bprm->cap_inheritable, + current->cap_inheritable); + working = cap_combine(permitted, working); if (!cap_issubset(working, current->cap_permitted)) { cap_raised = 1; } @@ -646,26 +647,29 @@ * The formula used for evolving capabilities is: * * pI' = pI - * (***) pP' = fP | (fI & pI) + * (***) pP' = (fP & X) | (fI & pI) * pE' = pP' & fE [NB. fE is 0 or ~0] * * I=Inheritable, P=Permitted, E=Effective // p=process, f=file - * ' indicates post-exec(). + * ' indicates post-exec(), and X is the global 'cap_bset'. */ void compute_creds(struct linux_binprm *bprm) { - int new_permitted = cap_t(bprm->cap_permitted) | - (cap_t(bprm->cap_inheritable) & - cap_t(current->cap_inheritable)); + kernel_cap_t new_permitted, working; + + new_permitted = cap_intersect(bprm->cap_permitted, cap_bset); + working = cap_intersect(bprm->cap_inheritable, + current->cap_inheritable); + new_permitted = cap_combine(new_permitted, working); /* For init, we want to retain the capabilities set * in the init_task struct. Thus we skip the usual * capability rules */ if (current->pid != 1) { - cap_t(current->cap_permitted) = new_permitted; - cap_t(current->cap_effective) = new_permitted & - cap_t(bprm->cap_effective); + current->cap_permitted = new_permitted; + current->cap_effective = + cap_intersect(new_permitted, bprm->cap_effective); } /* AUD: Audit candidate if current->cap_effective is set */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/balloc.c linux.ac/fs/ext2/balloc.c --- linux.vanilla/fs/ext2/balloc.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/balloc.c Tue May 30 14:38:13 2000 @@ -473,11 +473,8 @@ if (i >= sb->u.ext2_sb.s_groups_count) i = 0; gdp = ext2_get_group_desc (sb, i, &bh2); - if (!gdp) { - *err = -EIO; - unlock_super (sb); - return 0; - } + if (!gdp) + goto io_error; if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/dir.c linux.ac/fs/ext2/dir.c --- linux.vanilla/fs/ext2/dir.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/dir.c Sat Jun 10 21:51:07 2000 @@ -26,7 +26,7 @@ read: generic_read_dir, readdir: ext2_readdir, ioctl: ext2_ioctl, - fsync: ext2_sync_file, + fsync: ext2_fsync_file, }; int ext2_check_dir_entry (const char * function, struct inode * dir, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/file.c linux.ac/fs/ext2/file.c --- linux.vanilla/fs/ext2/file.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/file.c Sat Jun 10 21:51:07 2000 @@ -91,6 +91,7 @@ return 0; } + /* * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. @@ -103,7 +104,7 @@ mmap: generic_file_mmap, open: ext2_open_file, release: ext2_release_file, - fsync: ext2_sync_file, + fsync: ext2_fsync_file, }; struct inode_operations ext2_file_inode_operations = { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/fsync.c linux.ac/fs/ext2/fsync.c --- linux.vanilla/fs/ext2/fsync.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/fsync.c Sat Jun 10 21:51:07 2000 @@ -27,131 +27,28 @@ #include -#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) -#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) - -static int sync_indirect(struct inode * inode, u32 * block, int wait) -{ - struct buffer_head * bh; - - if (!*block) - return 0; - bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize); - if (!bh) - return 0; - if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - /* There can be a parallell read(2) that started read-I/O - on the buffer so we can't assume that there's been - an I/O error without first waiting I/O completation. */ - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) - { - brelse (bh); - return -1; - } - } - if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - if (wait) - /* when we return from fsync all the blocks - must be _just_ stored on disk */ - wait_on_buffer(bh); - brelse(bh); - return 0; - } - ll_rw_block(WRITE, 1, &bh); - atomic_dec(&bh->b_count); - return 0; -} - -static int sync_iblock(struct inode * inode, u32 * iblock, - struct buffer_head ** bh, int wait) -{ - int rc, tmp; - - *bh = NULL; - tmp = le32_to_cpu(*iblock); - if (!tmp) - return 0; - rc = sync_indirect(inode, iblock, wait); - if (rc) - return rc; - *bh = bread(inode->i_dev, tmp, blocksize); - if (!*bh) - return -1; - return 0; -} - -static int sync_dindirect(struct inode * inode, u32 * diblock, int wait) -{ - int i; - struct buffer_head * dind_bh; - int rc, err = 0; - - rc = sync_iblock(inode, diblock, &dind_bh, wait); - if (rc || !dind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait); - if (rc) - err = rc; - } - brelse(dind_bh); - return err; -} - -static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait) -{ - int i; - struct buffer_head * tind_bh; - int rc, err = 0; - - rc = sync_iblock(inode, tiblock, &tind_bh, wait); - if (rc || !tind_bh) - return rc; - - for (i = 0; i < addr_per_block; i++) { - rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait); - if (rc) - err = rc; - } - brelse(tind_bh); - return err; -} - /* * File may be NULL when we are called. Perhaps we shouldn't * even pass file to fsync ? */ -int ext2_sync_file(struct file * file, struct dentry *dentry) +int ext2_fsync_file(struct file * file, struct dentry *dentry, int datasync) { - int wait, err = 0; struct inode *inode = dentry->d_inode; + return ext2_fsync_inode(inode, datasync); +} - lock_kernel(); - if (S_ISLNK(inode->i_mode) && !(inode->i_blocks)) - /* - * Don't sync fast links! - */ - goto skip; - - err = generic_buffer_fdatasync(inode, 0, ~0UL); - - for (wait=0; wait<=1; wait++) - { - err |= sync_indirect(inode, - inode->u.ext2_i.i_data+EXT2_IND_BLOCK, - wait); - err |= sync_dindirect(inode, - inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, - wait); - err |= sync_tindirect(inode, - inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, - wait); - } -skip: - err |= ext2_sync_inode (inode); - unlock_kernel(); +int ext2_fsync_inode(struct inode *inode, int datasync) +{ + int err; + + err = fsync_inode_buffers(inode); + if (!(inode->i_state & I_DIRTY)) + return err; + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + return err; + + err |= ext2_sync_inode(inode); return err ? -EIO : 0; } + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/ialloc.c linux.ac/fs/ext2/ialloc.c --- linux.vanilla/fs/ext2/ialloc.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/ialloc.c Sat Jun 10 22:18:33 2000 @@ -186,24 +186,6 @@ struct ext2_group_desc * gdp; struct ext2_super_block * es; - if (!inode->i_dev) { - printk ("ext2_free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk ("ext2_free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk ("ext2_free_inode: inode has nlink=%d\n", - inode->i_nlink); - return; - } - if (!sb) { - printk("ext2_free_inode: inode on nonexistent device\n"); - return; - } - ino = inode->i_ino; ext2_debug ("freeing inode %lu\n", ino); @@ -305,7 +287,6 @@ repeat: gdp = NULL; i=0; - *err = -ENOSPC; if (S_ISDIR(mode)) { avefreei = le32_to_cpu(es->s_free_inodes_count) / sb->u.ext2_sb.s_groups_count; @@ -387,6 +368,7 @@ if (!gdp) { unlock_super (sb); iput(inode); + *err = -ENOSPC; return NULL; } bitmap_nr = load_inode_bitmap (sb, i); @@ -416,9 +398,8 @@ ext2_error (sb, "ext2_new_inode", "Free inodes count corrupted in group %d", i); - unlock_super (sb); - iput (inode); - return NULL; + /* If we continue recover from this case */ + gdp->bg_free_inodes_count = 0; } goto repeat; } @@ -429,6 +410,7 @@ "block_group = %d,inode=%d", i, j); unlock_super (sb); iput (inode); + *err = EIO; /* Should never happen */ return NULL; } gdp->bg_free_inodes_count = diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/inode.c linux.ac/fs/ext2/inode.c --- linux.vanilla/fs/ext2/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/inode.c Sat Jun 10 21:51:07 2000 @@ -117,7 +117,7 @@ inode->u.ext2_i.i_prealloc_count--; ext2_debug ("preallocation hit (%lu/%lu).\n", ++alloc_hits, ++alloc_attempts); - + *err = 0; } else { ext2_discard_prealloc (inode); ext2_debug ("preallocation miss (%lu/%lu).\n", @@ -200,6 +200,7 @@ return ret; } +/* returns NULL and sets *err on error */ static struct buffer_head * inode_getblk (struct inode * inode, int nr, int new_block, int * err, int metadata, long *phys, int *new) { @@ -223,7 +224,6 @@ return NULL; } } - *err = -EFBIG; /* Check file limits.. */ { @@ -311,7 +311,7 @@ * can fail due to: - not present * - out of space * - * NULL return in the data case is mandatory. + * NULL return in the data case, or an error, is mandatory. */ static struct buffer_head * block_getblk (struct inode * inode, struct buffer_head * bh, int nr, @@ -341,6 +341,7 @@ if (tmp == le32_to_cpu(*p)) goto out; brelse (result); + result = NULL; goto repeat; } else { *phys = tmp; @@ -402,11 +403,9 @@ *new = 1; } *p = le32_to_cpu(tmp); - mark_buffer_dirty(bh, 1); - if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { + mark_buffer_dirty_inode(bh, 1, inode); + if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } inode->i_ctime = CURRENT_TIME; inode->i_blocks += blocksize/512; mark_inode_dirty(inode); @@ -487,9 +486,9 @@ #define GET_INODE_PTR(x) \ inode_getblk(inode, x, iblock, &err, 1, NULL, NULL) #define GET_INDIRECT_DATABLOCK(x) \ - block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new); + block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new) #define GET_INDIRECT_PTR(x) \ - block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL); + block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL) if (ptr < direct_blocks) { bh = GET_INODE_DATABLOCK(ptr); @@ -547,13 +546,11 @@ struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err) { struct buffer_head dummy; - int error; dummy.b_state = 0; dummy.b_blocknr = -1000; - error = ext2_get_block(inode, block, &dummy, create); - *err = error; - if (!error && buffer_mapped(&dummy)) { + *err = ext2_get_block(inode, block, &dummy, create); + if (!*err && buffer_mapped(&dummy)) { struct buffer_head *bh; bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); if (buffer_new(&dummy)) { @@ -881,8 +878,23 @@ raw_inode->i_file_acl = cpu_to_le32(inode->u.ext2_i.i_file_acl); if (S_ISDIR(inode->i_mode)) raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl); - else + else { raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32); + if (inode->i_size >> 31) { + struct super_block *sb = inode->i_sb; + struct ext2_super_block *es = sb->u.ext2_sb.s_es; + if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) { + /* If this is the first large file + * created, add a flag to the superblock + * SMP Note: we're currently protected by the + * big kernel lock here, so this will need + * to be changed if that's no longer true. + */ + es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE); + ext2_write_super(sb); + } + } + } raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) @@ -904,10 +916,10 @@ return err; } -void ext2_write_inode (struct inode * inode) +void ext2_write_inode (struct inode * inode, int wait) { lock_kernel(); - ext2_update_inode (inode, 0); + ext2_update_inode (inode, wait); unlock_kernel(); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/namei.c linux.ac/fs/ext2/namei.c --- linux.vanilla/fs/ext2/namei.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/namei.c Sat Jun 10 22:18:33 2000 @@ -366,12 +366,9 @@ struct inode * inode; int err; - /* - * N.B. Several error exits in ext2_new_inode don't set err. - */ inode = ext2_new_inode (dir, mode, &err); if (!inode) - return -EIO; + return err; inode->i_op = &ext2_file_inode_operations; inode->i_fop = &ext2_file_operations; @@ -397,7 +394,7 @@ inode = ext2_new_inode (dir, mode, &err); if (!inode) - return -EIO; + return err; inode->i_uid = current->fsuid; init_special_inode(inode, mode, rdev); @@ -428,7 +425,7 @@ inode = ext2_new_inode (dir, S_IFDIR, &err); if (!inode) - return -EIO; + return err; inode->i_op = &ext2_dir_inode_operations; inode->i_fop = &ext2_dir_operations; @@ -454,7 +451,7 @@ strcpy (de->name, ".."); ext2_set_de_type(dir->i_sb, de, S_IFDIR); inode->i_nlink = 2; - mark_buffer_dirty(dir_block, 1); + mark_buffer_dirty_inode(dir_block, 1, dir); brelse (dir_block); inode->i_mode = S_IFDIR | mode; if (dir->i_mode & S_ISGID) @@ -634,7 +631,7 @@ return -ENAMETOOLONG; if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) - return -EIO; + return err; inode->i_mode = S_IFLNK | S_IRWXUGO; @@ -685,7 +682,7 @@ inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } @@ -791,7 +788,7 @@ mark_inode_dirty(old_dir); if (dir_bh) { PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino); - mark_buffer_dirty(dir_bh, 1); + mark_buffer_dirty_inode(dir_bh, 1, old_inode); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ext2/truncate.c linux.ac/fs/ext2/truncate.c --- linux.vanilla/fs/ext2/truncate.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ext2/truncate.c Sat Jun 10 21:51:07 2000 @@ -211,7 +211,7 @@ inode->i_ino, tmp); *p = 0; if (dind_bh) - mark_buffer_dirty(dind_bh, 1); + mark_buffer_dirty_inode(dind_bh, 1, inode); else mark_inode_dirty(inode); return 0; @@ -279,7 +279,7 @@ inode->i_ino, tmp); *p = 0; if (tind_bh) - mark_buffer_dirty(tind_bh, 1); + mark_buffer_dirty_inode(tind_bh, 1, inode); else mark_inode_dirty(inode); return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/fcntl.c linux.ac/fs/fcntl.c --- linux.vanilla/fs/fcntl.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/fcntl.c Sat May 27 22:00:30 2000 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -330,7 +331,52 @@ read_unlock(&tasklist_lock); } -void kill_fasync(struct fasync_struct *fa, int sig, int band) +/* + * fasync_helper() is used by some character device drivers (mainly mice) + * to set up the fasync queue. It returns negative on error, 0 if it did + * no changes and positive if it added/deleted the entry. + */ +static rwlock_t fasync_lock = RW_LOCK_UNLOCKED; +int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) +{ + struct fasync_struct *fa, **fp; + struct fasync_struct *new = NULL; + int result = 0; + + if (on) { + new = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); + if (!new) + return -ENOMEM; + } + write_lock_irq(&fasync_lock); + for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { + if (fa->fa_file == filp) { + if(on) { + fa->fa_fd = fd; + kfree(new); + } else { + *fp = fa->fa_next; + kfree(fa); + result = 1; + } + goto out; + } + } + + if (on) { + new->magic = FASYNC_MAGIC; + new->fa_file = filp; + new->fa_fd = fd; + new->fa_next = *fapp; + *fapp = new; + result = 1; + } +out: + write_unlock_irq(&fasync_lock); + return result; +} + +void __kill_fasync(struct fasync_struct *fa, int sig, int band) { while (fa) { struct fown_struct * fown; @@ -347,4 +393,11 @@ send_sigio(fown, fa, band); fa = fa->fa_next; } +} + +void kill_fasync(struct fasync_struct **fp, int sig, int band) +{ + read_lock(&fasync_lock); + __kill_fasync(*fp, sig, band); + read_unlock(&fasync_lock); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/file_table.c linux.ac/fs/file_table.c --- linux.vanilla/fs/file_table.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/file_table.c Thu May 25 23:36:46 2000 @@ -15,9 +15,7 @@ static kmem_cache_t *filp_cache; /* sysctl tunables... */ -int nr_files; /* read only */ -int nr_free_files; /* read only */ -int max_files = NR_FILE;/* tunable */ +struct files_stat_struct files_stat = {0, 0, NR_FILE}; /* Here the new files go */ static LIST_HEAD(anon_list); @@ -52,11 +50,11 @@ struct file * f; file_list_lock(); - if (nr_free_files > NR_RESERVED_FILES) { + if (files_stat.nr_free_files > NR_RESERVED_FILES) { used_one: f = list_entry(free_list.next, struct file, f_list); list_del(&f->f_list); - nr_free_files--; + files_stat.nr_free_files--; new_one: file_list_unlock(); memset(f, 0, sizeof(*f)); @@ -72,25 +70,25 @@ /* * Use a reserved one if we're the superuser */ - if (nr_free_files && !current->euid) + if (files_stat.nr_free_files && !current->euid) goto used_one; /* * Allocate a new one if we're below the limit. */ - if (nr_files < max_files) { + if (files_stat.nr_files < files_stat.max_files) { file_list_unlock(); f = kmem_cache_alloc(filp_cache, SLAB_KERNEL); file_list_lock(); if (f) { - nr_files++; + files_stat.nr_files++; goto new_one; } /* Big problems... */ printk("VFS: filp allocation failed\n"); - } else if (max_files > old_max) { - printk("VFS: file-max limit %d reached\n", max_files); - old_max = max_files; + } else if (files_stat.max_files > old_max) { + printk("VFS: file-max limit %d reached\n", files_stat.max_files); + old_max = files_stat.max_files; } file_list_unlock(); return NULL; @@ -146,7 +144,7 @@ file_list_lock(); list_del(&file->f_list); list_add(&file->f_list, &free_list); - nr_free_files++; + files_stat.nr_free_files++; file_list_unlock(); } @@ -158,7 +156,7 @@ file_list_lock(); list_del(&file->f_list); list_add(&file->f_list, &free_list); - nr_free_files++; + files_stat.nr_free_files++; file_list_unlock(); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/hfs/inode.c linux.ac/fs/hfs/inode.c --- linux.vanilla/fs/hfs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/hfs/inode.c Sat Jun 10 22:18:33 2000 @@ -80,7 +80,7 @@ struct hfs_cat_entry *entry = HFS_I(inode)->entry; hfs_cat_put(entry); - if (inode->i_count == 1) { + if (atomic_read(&inode->i_count) == 1) { struct hfs_hdr_layout *tmp = HFS_I(inode)->layout; if (tmp) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/hpfs/inode.c linux.ac/fs/hpfs/inode.c --- linux.vanilla/fs/hpfs/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/hpfs/inode.c Sat Jun 10 22:18:33 2000 @@ -233,7 +233,7 @@ struct inode *parent; if (!i->i_nlink) return; if (i->i_ino == i->i_sb->s_hpfs_root) return; - if (i->i_hpfs_rddir_off && !i->i_count) { + if (i->i_hpfs_rddir_off && !atomic_read(&i->i_count)) { if (*i->i_hpfs_rddir_off) printk("HPFS: write_inode: some position still there\n"); kfree(i->i_hpfs_rddir_off); i->i_hpfs_rddir_off = NULL; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/inode.c linux.ac/fs/inode.c --- linux.vanilla/fs/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/inode.c Sat Jun 10 22:19:11 2000 @@ -96,6 +96,7 @@ INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_data.pages); INIT_LIST_HEAD(&inode->i_dentry); + INIT_LIST_HEAD(&inode->i_dirty_buffers); sema_init(&inode->i_sem, 1); sema_init(&inode->i_zombie, 1); spin_lock_init(&inode->i_data.i_shared_lock); @@ -122,14 +123,14 @@ * Mark an inode as dirty. Callers should use mark_inode_dirty. */ -void __mark_inode_dirty(struct inode *inode) +void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block * sb = inode->i_sb; if (sb) { spin_lock(&inode_lock); - if (!(inode->i_state & I_DIRTY)) { - inode->i_state |= I_DIRTY; + if ((inode->i_state & flags) != flags) { + inode->i_state |= flags; /* Only add valid (ie hashed) inodes to the dirty list */ if (!list_empty(&inode->i_hash)) { list_del(&inode->i_list); @@ -162,26 +163,27 @@ } -static inline void write_inode(struct inode *inode) +static inline void write_inode(struct inode *inode, int wait) { if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->write_inode) - inode->i_sb->s_op->write_inode(inode); + inode->i_sb->s_op->write_inode(inode, wait); } static inline void __iget(struct inode * inode) { - if (!inode->i_count++) - { - if (!(inode->i_state & I_DIRTY)) - { - list_del(&inode->i_list); - list_add(&inode->i_list, &inode_in_use); - } - inodes_stat.nr_unused--; + if (atomic_read(&inode->i_count)) { + atomic_inc(&inode->i_count); + return; } + atomic_inc(&inode->i_count); + if (!(inode->i_state & I_DIRTY)) { + list_del(&inode->i_list); + list_add(&inode->i_list, &inode_in_use); + } + inodes_stat.nr_unused--; } -static inline void sync_one(struct inode *inode) +static inline void sync_one(struct inode *inode, int wait) { if (inode->i_state & I_LOCK) { __iget(inode); @@ -191,13 +193,15 @@ spin_lock(&inode_lock); } else { list_del(&inode->i_list); - list_add(&inode->i_list, - inode->i_count ? &inode_in_use : &inode_unused); + list_add(&inode->i_list, atomic_read(&inode->i_count) + ? &inode_in_use + : &inode_unused); /* Set I_LOCK, reset I_DIRTY */ - inode->i_state ^= I_DIRTY | I_LOCK; + inode->i_state |= I_LOCK; + inode->i_state &= ~I_DIRTY; spin_unlock(&inode_lock); - write_inode(inode); + write_inode(inode, wait); spin_lock(&inode_lock); inode->i_state &= ~I_LOCK; @@ -210,7 +214,7 @@ struct list_head * tmp; while ((tmp = head->prev) != head) - sync_one(list_entry(tmp, struct inode, i_list)); + sync_one(list_entry(tmp, struct inode, i_list), 0); } /** @@ -243,6 +247,7 @@ spin_unlock(&inode_lock); } + /* * Called with the spinlock already held.. */ @@ -259,19 +264,20 @@ /** * write_inode_now - write an inode to disk * @inode: inode to write to disk + * @wait: if set, we wait for the write to complete on disk * * This function commits an inode to disk immediately if it is * dirty. This is primarily needed by knfsd. */ -void write_inode_now(struct inode *inode) +void write_inode_now(struct inode *inode, int wait) { struct super_block * sb = inode->i_sb; if (sb) { spin_lock(&inode_lock); while (inode->i_state & I_DIRTY) - sync_one(inode); + sync_one(inode, wait); spin_unlock(&inode_lock); } else @@ -279,6 +285,60 @@ } /** + * generic_osync_inode - flush all dirty data for a given inode to disk + * @inode: inode to write + * @datasync: if set, don't bother flushing timestamps + * + * This is called by generic_file_write for files which have the O_SYNC + * flag set, to flush dirty writes to disk. + */ + +int generic_osync_inode(struct inode *inode, int datasync) +{ + int err; + + /* + * WARNING + * + * Currently, the filesystem write path does not pass the + * filp down to the low-level write functions. Therefore it + * is impossible for (say) __block_commit_write to know if + * the operation is O_SYNC or not. + * + * Ideally, O_SYNC writes would have the filesystem call + * ll_rw_block as it went to kick-start the writes, and we + * could call osync_inode_buffers() here to wait only for + * those IOs which have already been submitted to the device + * driver layer. As it stands, if we did this we'd not write + * anything to disk since our writes have not been queued by + * this point: they are still on the dirty LRU. + * + * So, currently we will call fsync_inode_buffers() instead, + * to flush _all_ dirty buffers for this inode to disk on + * every O_SYNC write, not just the synchronous I/Os. --sct + */ + +#ifdef WRITERS_QUEUE_IO + err = osync_inode_buffers(inode); +#else + err = fsync_inode_buffers(inode); +#endif + + spin_lock(&inode_lock); + if (!(inode->i_state & I_DIRTY)) + goto out; + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + goto out; + spin_unlock(&inode_lock); + write_inode_now(inode, 1); + return err; + + out: + spin_unlock(&inode_lock); + return err; +} + +/** * clear_inode - clear an inode * @inode: inode to clear * @@ -322,7 +382,7 @@ inode = list_entry(inode_entry, struct inode, i_list); if (inode->i_data.nrpages) - truncate_inode_pages(&inode->i_data, 0); + truncate_all_inode_pages(&inode->i_data); clear_inode(inode); destroy_inode(inode); } @@ -347,7 +407,8 @@ inode = list_entry(tmp, struct inode, i_list); if (inode->i_sb != sb) continue; - if (!inode->i_count) { + invalidate_inode_buffers(inode); + if (!atomic_read(&inode->i_count)) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); list_del(&inode->i_list); @@ -408,7 +469,8 @@ * dispose_list. */ #define CAN_UNUSE(inode) \ - (((inode)->i_state | (inode)->i_data.nrpages) == 0) + ((((inode)->i_state | (inode)->i_data.nrpages) == 0) && \ + !inode_has_buffers(inode)) #define INODE(entry) (list_entry(entry, struct inode, i_list)) void prune_icache(int goal) @@ -433,7 +495,7 @@ BUG(); if (!CAN_UNUSE(inode)) continue; - if (inode->i_count) + if (atomic_read(&inode->i_count)) BUG(); list_del(tmp); list_del(&inode->i_hash); @@ -551,7 +613,7 @@ inode->i_dev = 0; inode->i_ino = ++last_ino; inode->i_flags = 0; - inode->i_count = 1; + atomic_set(&inode->i_count, 1); inode->i_state = 0; spin_unlock(&inode_lock); clean_inode(inode); @@ -583,7 +645,7 @@ inode->i_dev = sb->s_dev; inode->i_ino = ino; inode->i_flags = 0; - inode->i_count = 1; + atomic_set(&inode->i_count, 1); inode->i_state = I_LOCK; spin_unlock(&inode_lock); @@ -758,7 +820,7 @@ op->put_inode(inode); spin_lock(&inode_lock); - if (!--inode->i_count) { + if (atomic_dec_and_test(&inode->i_count)) { if (!inode->i_nlink) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); @@ -768,7 +830,7 @@ spin_unlock(&inode_lock); if (inode->i_data.nrpages) - truncate_inode_pages(&inode->i_data, 0); + truncate_all_inode_pages(&inode->i_data); destroy = 1; if (op && op->delete_inode) { @@ -807,15 +869,15 @@ if (!list_empty(&inode->i_dentry)) printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n", kdevname(inode->i_dev), inode->i_ino); -if (inode->i_count) +if (atomic_read(&inode->i_count)) printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n", -kdevname(inode->i_dev), inode->i_ino, inode->i_count); +kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_count)); if (atomic_read(&inode->i_sem.count) != 1) printk(KERN_ERR "iput: Aieee, semaphore in use inode %s/%ld, count=%d\n", kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); #endif } - if (inode->i_count > (1<<31)) { + if ((unsigned)atomic_read(&inode->i_count) > (1U<<31)) { printk(KERN_ERR "iput: inode %s/%ld count wrapped\n", kdevname(inode->i_dev), inode->i_ino); } @@ -825,6 +887,16 @@ } } +void force_delete(struct inode *inode) +{ + /* + * Kill off unused inodes ... iput() will unhash and + * delete the inode if we set i_nlink to zero. + */ + if (atomic_read(&inode->i_count) == 1) + inode->i_nlink = 0; +} + /** * bmap - find a block number in a file * @inode: inode of file @@ -913,7 +985,7 @@ if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; if ( IS_RDONLY (inode) ) return; inode->i_atime = CURRENT_TIME; - mark_inode_dirty (inode); + mark_inode_dirty_sync (inode); } /* End Function update_atime */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ioctl.c linux.ac/fs/ioctl.c --- linux.vanilla/fs/ioctl.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/ioctl.c Wed May 31 11:19:15 2000 @@ -88,8 +88,12 @@ /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) - filp->f_op->fasync(fd, filp, on); + error = filp->f_op->fasync(fd, filp, on); + else error = -ENOTTY; } + if (error != 0) + break; + if (on) filp->f_flags |= FASYNC; else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/lockd/svc.c linux.ac/fs/lockd/svc.c --- linux.vanilla/fs/lockd/svc.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/lockd/svc.c Sat Jun 10 22:03:20 2000 @@ -235,7 +235,10 @@ } if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0 - || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0) { +#ifdef CONFIG_NFSD_TCP + || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0 +#endif + ) { if (warned++ == 0) printk(KERN_WARNING "lockd_up: makesock failed, error=%d\n", error); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/locks.c linux.ac/fs/locks.c --- linux.vanilla/fs/locks.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/locks.c Thu May 25 23:32:32 2000 @@ -111,33 +111,43 @@ #include -static int flock_make_lock(struct file *filp, struct file_lock *fl, - unsigned int cmd); -static int posix_make_lock(struct file *filp, struct file_lock *fl, - struct flock *l); -static int flock_locks_conflict(struct file_lock *caller_fl, - struct file_lock *sys_fl); -static int posix_locks_conflict(struct file_lock *caller_fl, - struct file_lock *sys_fl); -static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl); -static int flock_lock_file(struct file *filp, struct file_lock *caller, - unsigned int wait); -static int posix_locks_deadlock(struct file_lock *caller, - struct file_lock *blocker); - -static struct file_lock *locks_empty_lock(void); -static struct file_lock *locks_init_lock(struct file_lock *, - struct file_lock *); -static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl); -static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait); -static void lock_get_status(char* out, struct file_lock *fl, int id, char *pfx); - -static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter); -static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter); -static void locks_wake_up_blocks(struct file_lock *blocker, unsigned int wait); - struct file_lock *file_lock_table = NULL; +/* + * Allocate an empty lock structure. We can use GFP_KERNEL now that + * all allocations are done in advance. + */ +static struct file_lock *locks_empty_lock(void) +{ + /* Okay, let's make a new file_lock structure... */ + return ((struct file_lock *) kmalloc(sizeof(struct file_lock), + GFP_KERNEL)); +} + +/* + * Initialize a new lock from an existing file_lock structure. + */ +static struct file_lock *locks_init_lock(struct file_lock *new, + struct file_lock *fl) +{ + if (new) { + memset(new, 0, sizeof(*new)); + new->fl_owner = fl->fl_owner; + new->fl_pid = fl->fl_pid; + init_waitqueue_head(&new->fl_wait); + new->fl_file = fl->fl_file; + new->fl_flags = fl->fl_flags; + new->fl_type = fl->fl_type; + new->fl_start = fl->fl_start; + new->fl_end = fl->fl_end; + new->fl_notify = fl->fl_notify; + new->fl_insert = fl->fl_insert; + new->fl_remove = fl->fl_remove; + new->fl_u = fl->fl_u; + } + return new; +} + /* Allocate a new lock, and initialize its fields from fl. * The lock is not inserted into any lists until locks_insert_lock() or * locks_insert_block() are called. @@ -161,6 +171,92 @@ return; } +/* Verify a call to flock() and fill in a file_lock structure with + * an appropriate FLOCK lock. + */ +static int flock_make_lock(struct file *filp, struct file_lock *fl, + unsigned int cmd) +{ + memset(fl, 0, sizeof(*fl)); + + init_waitqueue_head(&fl->fl_wait); + + switch (cmd & ~LOCK_NB) { + case LOCK_SH: + fl->fl_type = F_RDLCK; + break; + case LOCK_EX: + fl->fl_type = F_WRLCK; + break; + case LOCK_UN: + fl->fl_type = F_UNLCK; + break; + default: + return (0); + } + + fl->fl_flags = FL_FLOCK; + fl->fl_start = 0; + fl->fl_end = OFFSET_MAX; + fl->fl_file = filp; + fl->fl_owner = NULL; + + return (1); +} + +/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX + * style lock. + */ +static int posix_make_lock(struct file *filp, struct file_lock *fl, + struct flock *l) +{ + loff_t start; + + memset(fl, 0, sizeof(*fl)); + + init_waitqueue_head(&fl->fl_wait); + fl->fl_flags = FL_POSIX; + + switch (l->l_type) { + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: + fl->fl_type = l->l_type; + break; + default: + return (0); + } + + switch (l->l_whence) { + case 0: /*SEEK_SET*/ + start = 0; + break; + case 1: /*SEEK_CUR*/ + start = filp->f_pos; + break; + case 2: /*SEEK_END*/ + start = filp->f_dentry->d_inode->i_size; + break; + default: + return (0); + } + + if (((start += l->l_start) < 0) || (l->l_len < 0)) + return (0); + fl->fl_end = start + l->l_len - 1; + if (l->l_len > 0 && fl->fl_end < 0) + return (0); + fl->fl_start = start; /* we record the absolute position */ + if (l->l_len == 0) + fl->fl_end = OFFSET_MAX; + + fl->fl_file = filp; + fl->fl_owner = current->files; + fl->fl_pid = current->pid; + + return (1); +} + /* Check if two locks overlap each other. */ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2) @@ -181,6 +277,31 @@ (fl1->fl_pid == fl2->fl_pid); } +/* Remove waiter from blocker's block list. + * When blocker ends up pointing to itself then the list is empty. + */ +static void locks_delete_block(struct file_lock *blocker, + struct file_lock *waiter) +{ + struct file_lock *nextblock; + struct file_lock *prevblock; + + nextblock = waiter->fl_nextblock; + prevblock = waiter->fl_prevblock; + + if (nextblock == NULL) + return; + + nextblock->fl_prevblock = prevblock; + prevblock->fl_nextblock = nextblock; + + waiter->fl_prevblock = waiter->fl_nextblock = NULL; + if (blocker->fl_nextblock == blocker) + /* No more locks on blocker's blocked list */ + blocker->fl_prevblock = blocker->fl_nextblock = NULL; + return; +} + /* Insert waiter into blocker's block list. * We use a circular list so that processes can be easily woken up in * the order they blocked. The documentation doesn't require this but @@ -214,48 +335,6 @@ return; } -/* Remove waiter from blocker's block list. - * When blocker ends up pointing to itself then the list is empty. - */ -static void locks_delete_block(struct file_lock *blocker, - struct file_lock *waiter) -{ - struct file_lock *nextblock; - struct file_lock *prevblock; - - nextblock = waiter->fl_nextblock; - prevblock = waiter->fl_prevblock; - - if (nextblock == NULL) - return; - - nextblock->fl_prevblock = prevblock; - prevblock->fl_nextblock = nextblock; - - waiter->fl_prevblock = waiter->fl_nextblock = NULL; - if (blocker->fl_nextblock == blocker) - /* No more locks on blocker's blocked list */ - blocker->fl_prevblock = blocker->fl_nextblock = NULL; - return; -} - -/* The following two are for the benefit of lockd. - */ -void -posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) -{ - locks_insert_block(blocker, waiter); - return; -} - -void -posix_unblock_lock(struct file_lock *waiter) -{ - if (waiter->fl_prevblock) - locks_delete_block(waiter->fl_prevblock, waiter); - return; -} - /* Wake up processes blocked waiting for blocker. * If told to wait then schedule the processes until the block list * is empty, otherwise empty the block list ourselves. @@ -285,256 +364,110 @@ return; } -/* flock() system call entry point. Apply a FL_FLOCK style lock to - * an open file descriptor. +/* Insert file lock fl into an inode's lock list at the position indicated + * by pos. At the same time add the lock to the global file lock list. */ -asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) +static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) { - struct file_lock file_lock; - struct file *filp; - int error; + fl->fl_nextlink = file_lock_table; + fl->fl_prevlink = NULL; + if (file_lock_table != NULL) + file_lock_table->fl_prevlink = fl; + file_lock_table = fl; + fl->fl_next = *pos; /* insert into file's list */ + *pos = fl; - lock_kernel(); - error = -EBADF; - filp = fget(fd); - if (!filp) - goto out; - error = -EINVAL; - if (!flock_make_lock(filp, &file_lock, cmd)) - goto out_putf; - error = -EBADF; - if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) - goto out_putf; - error = flock_lock_file(filp, &file_lock, - (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); -out_putf: - fput(filp); -out: - unlock_kernel(); - return (error); + if (fl->fl_insert) + fl->fl_insert(fl); + + return; } -/* Report the first existing lock that would conflict with l. - * This implements the F_GETLK command of fcntl(). +/* Delete a lock and free it. + * First remove our lock from the active lock lists. Then call + * locks_wake_up_blocks() to wake up processes that are blocked + * waiting for this lock. Finally free the lock structure. */ -int fcntl_getlk(unsigned int fd, struct flock *l) +static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) { - struct file *filp; - struct file_lock *fl,file_lock; - struct flock flock; - int error; + struct file_lock *thisfl; + struct file_lock *prevfl; + struct file_lock *nextfl; + + thisfl = *thisfl_p; + *thisfl_p = thisfl->fl_next; - error = -EFAULT; - if (copy_from_user(&flock, l, sizeof(flock))) - goto out; - error = -EINVAL; - if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) - goto out; + prevfl = thisfl->fl_prevlink; + nextfl = thisfl->fl_nextlink; - error = -EBADF; - filp = fget(fd); - if (!filp) - goto out; + if (nextfl != NULL) + nextfl->fl_prevlink = prevfl; - if (!posix_make_lock(filp, &file_lock, &flock)) - goto out_putf; + if (prevfl != NULL) + prevfl->fl_nextlink = nextfl; + else + file_lock_table = nextfl; - if (filp->f_op->lock) { - error = filp->f_op->lock(filp, F_GETLK, &file_lock); - if (error < 0) - goto out_putf; - else if (error == LOCK_USE_CLNT) - /* Bypass for NFS with no locking - 2.0.36 compat */ - fl = posix_test_lock(filp, &file_lock); - else - fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); - } else { - fl = posix_test_lock(filp, &file_lock); - } - - flock.l_type = F_UNLCK; - if (fl != NULL) { - flock.l_pid = fl->fl_pid; - flock.l_start = fl->fl_start; - flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : - fl->fl_end - fl->fl_start + 1; - flock.l_whence = 0; - flock.l_type = fl->fl_type; - } - error = -EFAULT; - if (!copy_to_user(l, &flock, sizeof(flock))) - error = 0; - -out_putf: - fput(filp); -out: - return error; + if (thisfl->fl_remove) + thisfl->fl_remove(thisfl); + + locks_wake_up_blocks(thisfl, wait); + locks_free_lock(thisfl); + + return; } -/* Apply the lock described by l to an open file descriptor. - * This implements both the F_SETLK and F_SETLKW commands of fcntl(). +/* Determine if lock sys_fl blocks lock caller_fl. Common functionality + * checks for overlapping locks and shared/exclusive status. */ -int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) +static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { - struct file *filp; - struct file_lock file_lock; - struct flock flock; - struct inode *inode; - int error; - - /* - * This might block, so we do it before checking the inode. - */ - error = -EFAULT; - if (copy_from_user(&flock, l, sizeof(flock))) - goto out; - - /* Get arguments and validate them ... - */ - - error = -EBADF; - filp = fget(fd); - if (!filp) - goto out; - - error = -EINVAL; - inode = filp->f_dentry->d_inode; - - /* Don't allow mandatory locks on files that may be memory mapped - * and shared. - */ - if (IS_MANDLOCK(inode) && - (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) { - struct vm_area_struct *vma; - struct address_space *mapping = inode->i_mapping; - spin_lock(&mapping->i_shared_lock); - for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) { - if (!(vma->vm_flags & VM_MAYSHARE)) - continue; - spin_unlock(&mapping->i_shared_lock); - error = -EAGAIN; - goto out_putf; - } - spin_unlock(&mapping->i_shared_lock); - } + if (!locks_overlap(caller_fl, sys_fl)) + return (0); - error = -EINVAL; - if (!posix_make_lock(filp, &file_lock, &flock)) - goto out_putf; - - error = -EBADF; - switch (flock.l_type) { + switch (caller_fl->fl_type) { case F_RDLCK: - if (!(filp->f_mode & FMODE_READ)) - goto out_putf; - break; + return (sys_fl->fl_type == F_WRLCK); + case F_WRLCK: - if (!(filp->f_mode & FMODE_WRITE)) - goto out_putf; - break; - case F_UNLCK: - break; - case F_SHLCK: - case F_EXLCK: -#ifdef __sparc__ -/* warn a bit for now, but don't overdo it */ -{ - static int count = 0; - if (!count) { - count=1; - printk(KERN_WARNING - "fcntl_setlk() called by process %d (%s) with broken flock() emulation\n", - current->pid, current->comm); - } -} - if (!(filp->f_mode & 3)) - goto out_putf; - break; -#endif - default: - error = -EINVAL; - goto out_putf; - } + return (1); - if (filp->f_op->lock != NULL) { - error = filp->f_op->lock(filp, cmd, &file_lock); - if (error < 0) - goto out_putf; + default: + printk("locks_conflict(): impossible lock type - %d\n", + caller_fl->fl_type); + break; } - error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW); - -out_putf: - fput(filp); -out: - return error; + return (0); /* This should never happen */ } -/* - * This function is called when the file is being removed - * from the task's fd array. +/* Determine if lock sys_fl blocks lock caller_fl. POSIX specific + * checking before calling the locks_conflict(). */ -void locks_remove_posix(struct file *filp, fl_owner_t owner) +static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { - struct inode * inode = filp->f_dentry->d_inode; - struct file_lock file_lock, *fl; - struct file_lock **before; - - /* - * For POSIX locks we free all locks on this file for the given task. + /* POSIX locks owned by the same process do not conflict with + * each other. */ -repeat: - before = &inode->i_flock; - while ((fl = *before) != NULL) { - if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { - int (*lock)(struct file *, int, struct file_lock *); - lock = filp->f_op->lock; - if (lock) { - file_lock = *fl; - file_lock.fl_type = F_UNLCK; - } - locks_delete_lock(before, 0); - if (lock) { - lock(filp, F_SETLK, &file_lock); - /* List may have changed: */ - goto repeat; - } - continue; - } - before = &fl->fl_next; - } + if (!(sys_fl->fl_flags & FL_POSIX) || + locks_same_owner(caller_fl, sys_fl)) + return (0); + + return (locks_conflict(caller_fl, sys_fl)); } -/* - * This function is called on the last close of an open file. +/* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific + * checking before calling the locks_conflict(). */ -void locks_remove_flock(struct file *filp) +static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { - struct inode * inode = filp->f_dentry->d_inode; - struct file_lock file_lock, *fl; - struct file_lock **before; + /* FLOCK locks referring to the same filp do not conflict with + * each other. + */ + if (!(sys_fl->fl_flags & FL_FLOCK) || + (caller_fl->fl_file == sys_fl->fl_file)) + return (0); -repeat: - before = &inode->i_flock; - while ((fl = *before) != NULL) { - if ((fl->fl_flags & FL_FLOCK) && fl->fl_file == filp) { - int (*lock)(struct file *, int, struct file_lock *); - lock = NULL; - if (filp->f_op) - lock = filp->f_op->lock; - if (lock) { - file_lock = *fl; - file_lock.fl_type = F_UNLCK; - } - locks_delete_lock(before, 0); - if (lock) { - lock(filp, F_SETLK, &file_lock); - /* List may have changed: */ - goto repeat; - } - continue; - } - before = &fl->fl_next; - } + return (locks_conflict(caller_fl, sys_fl)); } struct file_lock * @@ -552,16 +485,65 @@ return (cfl); } -int locks_mandatory_locked(struct inode *inode) +/* This function tests for deadlock condition before putting a process to + * sleep. The detection scheme is no longer recursive. Recursive was neat, + * but dangerous - we risked stack corruption if the lock data was bad, or + * if the recursion was too deep for any other reason. + * + * We rely on the fact that a task can only be on one lock's wait queue + * at a time. When we find blocked_task on a wait queue we can re-search + * with blocked_task equal to that queue's owner, until either blocked_task + * isn't found, or blocked_task is found on a queue owned by my_task. + * + * Note: the above assumption may not be true when handling lock requests + * from a broken NFS client. But broken NFS clients have a lot more to + * worry about than proper deadlock detection anyway... --okir + */ +static int posix_locks_deadlock(struct file_lock *caller_fl, + struct file_lock *block_fl) { - fl_owner_t owner = current->files; struct file_lock *fl; + struct file_lock *bfl; + void *caller_owner, *blocked_owner; + unsigned int caller_pid, blocked_pid; - /* - * Search the lock list for this inode for any POSIX locks. - */ - lock_kernel(); - for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + caller_owner = caller_fl->fl_owner; + caller_pid = caller_fl->fl_pid; + blocked_owner = block_fl->fl_owner; + blocked_pid = block_fl->fl_pid; + +next_task: + if (caller_owner == blocked_owner && caller_pid == blocked_pid) + return (1); + for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) { + if (fl->fl_owner == NULL || fl->fl_nextblock == NULL) + continue; + for (bfl = fl->fl_nextblock; bfl != fl; bfl = bfl->fl_nextblock) { + if (bfl->fl_owner == blocked_owner && + bfl->fl_pid == blocked_pid) { + if (fl->fl_owner == caller_owner && + fl->fl_pid == caller_pid) { + return (1); + } + blocked_owner = fl->fl_owner; + blocked_pid = fl->fl_pid; + goto next_task; + } + } + } + return (0); +} + +int locks_mandatory_locked(struct inode *inode) +{ + fl_owner_t owner = current->files; + struct file_lock *fl; + + /* + * Search the lock list for this inode for any POSIX locks. + */ + lock_kernel(); + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & FL_POSIX)) continue; if (fl->fl_owner != owner) @@ -634,194 +616,6 @@ return error; } -/* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX - * style lock. - */ -static int posix_make_lock(struct file *filp, struct file_lock *fl, - struct flock *l) -{ - loff_t start; - - memset(fl, 0, sizeof(*fl)); - - init_waitqueue_head(&fl->fl_wait); - fl->fl_flags = FL_POSIX; - - switch (l->l_type) { - case F_RDLCK: - case F_WRLCK: - case F_UNLCK: - fl->fl_type = l->l_type; - break; - default: - return (0); - } - - switch (l->l_whence) { - case 0: /*SEEK_SET*/ - start = 0; - break; - case 1: /*SEEK_CUR*/ - start = filp->f_pos; - break; - case 2: /*SEEK_END*/ - start = filp->f_dentry->d_inode->i_size; - break; - default: - return (0); - } - - if (((start += l->l_start) < 0) || (l->l_len < 0)) - return (0); - fl->fl_end = start + l->l_len - 1; - if (l->l_len > 0 && fl->fl_end < 0) - return (0); - fl->fl_start = start; /* we record the absolute position */ - if (l->l_len == 0) - fl->fl_end = OFFSET_MAX; - - fl->fl_file = filp; - fl->fl_owner = current->files; - fl->fl_pid = current->pid; - - return (1); -} - -/* Verify a call to flock() and fill in a file_lock structure with - * an appropriate FLOCK lock. - */ -static int flock_make_lock(struct file *filp, struct file_lock *fl, - unsigned int cmd) -{ - memset(fl, 0, sizeof(*fl)); - - init_waitqueue_head(&fl->fl_wait); - - switch (cmd & ~LOCK_NB) { - case LOCK_SH: - fl->fl_type = F_RDLCK; - break; - case LOCK_EX: - fl->fl_type = F_WRLCK; - break; - case LOCK_UN: - fl->fl_type = F_UNLCK; - break; - default: - return (0); - } - - fl->fl_flags = FL_FLOCK; - fl->fl_start = 0; - fl->fl_end = OFFSET_MAX; - fl->fl_file = filp; - fl->fl_owner = NULL; - - return (1); -} - -/* Determine if lock sys_fl blocks lock caller_fl. POSIX specific - * checking before calling the locks_conflict(). - */ -static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) -{ - /* POSIX locks owned by the same process do not conflict with - * each other. - */ - if (!(sys_fl->fl_flags & FL_POSIX) || - locks_same_owner(caller_fl, sys_fl)) - return (0); - - return (locks_conflict(caller_fl, sys_fl)); -} - -/* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific - * checking before calling the locks_conflict(). - */ -static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) -{ - /* FLOCK locks referring to the same filp do not conflict with - * each other. - */ - if (!(sys_fl->fl_flags & FL_FLOCK) || - (caller_fl->fl_file == sys_fl->fl_file)) - return (0); - - return (locks_conflict(caller_fl, sys_fl)); -} - -/* Determine if lock sys_fl blocks lock caller_fl. Common functionality - * checks for overlapping locks and shared/exclusive status. - */ -static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) -{ - if (!locks_overlap(caller_fl, sys_fl)) - return (0); - - switch (caller_fl->fl_type) { - case F_RDLCK: - return (sys_fl->fl_type == F_WRLCK); - - case F_WRLCK: - return (1); - - default: - printk("locks_conflict(): impossible lock type - %d\n", - caller_fl->fl_type); - break; - } - return (0); /* This should never happen */ -} - -/* This function tests for deadlock condition before putting a process to - * sleep. The detection scheme is no longer recursive. Recursive was neat, - * but dangerous - we risked stack corruption if the lock data was bad, or - * if the recursion was too deep for any other reason. - * - * We rely on the fact that a task can only be on one lock's wait queue - * at a time. When we find blocked_task on a wait queue we can re-search - * with blocked_task equal to that queue's owner, until either blocked_task - * isn't found, or blocked_task is found on a queue owned by my_task. - * - * Note: the above assumption may not be true when handling lock requests - * from a broken NFS client. But broken NFS clients have a lot more to - * worry about than proper deadlock detection anyway... --okir - */ -static int posix_locks_deadlock(struct file_lock *caller_fl, - struct file_lock *block_fl) -{ - struct file_lock *fl; - struct file_lock *bfl; - void *caller_owner, *blocked_owner; - unsigned int caller_pid, blocked_pid; - - caller_owner = caller_fl->fl_owner; - caller_pid = caller_fl->fl_pid; - blocked_owner = block_fl->fl_owner; - blocked_pid = block_fl->fl_pid; - -next_task: - if (caller_owner == blocked_owner && caller_pid == blocked_pid) - return (1); - for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) { - if (fl->fl_owner == NULL || fl->fl_nextblock == NULL) - continue; - for (bfl = fl->fl_nextblock; bfl != fl; bfl = bfl->fl_nextblock) { - if (bfl->fl_owner == blocked_owner && - bfl->fl_pid == blocked_pid) { - if (fl->fl_owner == caller_owner && - fl->fl_pid == caller_pid) { - return (1); - } - blocked_owner = fl->fl_owner; - blocked_pid = fl->fl_pid; - goto next_task; - } - } - } - return (0); -} - /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks at * the head of the list, but that's secret knowledge known only to the next * two functions. @@ -1091,91 +885,272 @@ return error; } -/* - * Allocate an empty lock structure. We can use GFP_KERNEL now that - * all allocations are done in advance. +/* flock() system call entry point. Apply a FL_FLOCK style lock to + * an open file descriptor. */ -static struct file_lock *locks_empty_lock(void) +asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) { - /* Okay, let's make a new file_lock structure... */ - return ((struct file_lock *) kmalloc(sizeof(struct file_lock), - GFP_KERNEL)); -} + struct file_lock file_lock; + struct file *filp; + int error; -/* - * Initialize a new lock from an existing file_lock structure. - */ -static struct file_lock *locks_init_lock(struct file_lock *new, - struct file_lock *fl) -{ - if (new) { - memset(new, 0, sizeof(*new)); - new->fl_owner = fl->fl_owner; - new->fl_pid = fl->fl_pid; - init_waitqueue_head(&new->fl_wait); - new->fl_file = fl->fl_file; - new->fl_flags = fl->fl_flags; - new->fl_type = fl->fl_type; - new->fl_start = fl->fl_start; - new->fl_end = fl->fl_end; - new->fl_notify = fl->fl_notify; - new->fl_insert = fl->fl_insert; - new->fl_remove = fl->fl_remove; - new->fl_u = fl->fl_u; - } - return new; + lock_kernel(); + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + error = -EINVAL; + if (!flock_make_lock(filp, &file_lock, cmd)) + goto out_putf; + error = -EBADF; + if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) + goto out_putf; + error = flock_lock_file(filp, &file_lock, + (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); +out_putf: + fput(filp); +out: + unlock_kernel(); + return (error); } -/* Insert file lock fl into an inode's lock list at the position indicated - * by pos. At the same time add the lock to the global file lock list. +/* Report the first existing lock that would conflict with l. + * This implements the F_GETLK command of fcntl(). */ -static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) +int fcntl_getlk(unsigned int fd, struct flock *l) { - fl->fl_nextlink = file_lock_table; - fl->fl_prevlink = NULL; - if (file_lock_table != NULL) - file_lock_table->fl_prevlink = fl; - file_lock_table = fl; - fl->fl_next = *pos; /* insert into file's list */ - *pos = fl; + struct file *filp; + struct file_lock *fl,file_lock; + struct flock flock; + int error; - if (fl->fl_insert) - fl->fl_insert(fl); + error = -EFAULT; + if (copy_from_user(&flock, l, sizeof(flock))) + goto out; + error = -EINVAL; + if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) + goto out; - return; + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + if (!posix_make_lock(filp, &file_lock, &flock)) + goto out_putf; + + if (filp->f_op->lock) { + error = filp->f_op->lock(filp, F_GETLK, &file_lock); + if (error < 0) + goto out_putf; + else if (error == LOCK_USE_CLNT) + /* Bypass for NFS with no locking - 2.0.36 compat */ + fl = posix_test_lock(filp, &file_lock); + else + fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock); + } else { + fl = posix_test_lock(filp, &file_lock); + } + + flock.l_type = F_UNLCK; + if (fl != NULL) { + flock.l_pid = fl->fl_pid; + flock.l_start = fl->fl_start; + flock.l_len = fl->fl_end == OFFSET_MAX ? 0 : + fl->fl_end - fl->fl_start + 1; + flock.l_whence = 0; + flock.l_type = fl->fl_type; + } + error = -EFAULT; + if (!copy_to_user(l, &flock, sizeof(flock))) + error = 0; + +out_putf: + fput(filp); +out: + return error; } -/* Delete a lock and free it. - * First remove our lock from the active lock lists. Then call - * locks_wake_up_blocks() to wake up processes that are blocked - * waiting for this lock. Finally free the lock structure. +/* Apply the lock described by l to an open file descriptor. + * This implements both the F_SETLK and F_SETLKW commands of fcntl(). */ -static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) +int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) { - struct file_lock *thisfl; - struct file_lock *prevfl; - struct file_lock *nextfl; - - thisfl = *thisfl_p; - *thisfl_p = thisfl->fl_next; + struct file *filp; + struct file_lock file_lock; + struct flock flock; + struct inode *inode; + int error; - prevfl = thisfl->fl_prevlink; - nextfl = thisfl->fl_nextlink; + /* + * This might block, so we do it before checking the inode. + */ + error = -EFAULT; + if (copy_from_user(&flock, l, sizeof(flock))) + goto out; - if (nextfl != NULL) - nextfl->fl_prevlink = prevfl; + /* Get arguments and validate them ... + */ - if (prevfl != NULL) - prevfl->fl_nextlink = nextfl; - else - file_lock_table = nextfl; + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; - if (thisfl->fl_remove) - thisfl->fl_remove(thisfl); + error = -EINVAL; + inode = filp->f_dentry->d_inode; + + /* Don't allow mandatory locks on files that may be memory mapped + * and shared. + */ + if (IS_MANDLOCK(inode) && + (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) { + struct vm_area_struct *vma; + struct address_space *mapping = inode->i_mapping; + spin_lock(&mapping->i_shared_lock); + for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) { + if (!(vma->vm_flags & VM_MAYSHARE)) + continue; + spin_unlock(&mapping->i_shared_lock); + error = -EAGAIN; + goto out_putf; + } + spin_unlock(&mapping->i_shared_lock); + } + + error = -EINVAL; + if (!posix_make_lock(filp, &file_lock, &flock)) + goto out_putf; - locks_wake_up_blocks(thisfl, wait); - locks_free_lock(thisfl); + error = -EBADF; + switch (flock.l_type) { + case F_RDLCK: + if (!(filp->f_mode & FMODE_READ)) + goto out_putf; + break; + case F_WRLCK: + if (!(filp->f_mode & FMODE_WRITE)) + goto out_putf; + break; + case F_UNLCK: + break; + case F_SHLCK: + case F_EXLCK: +#ifdef __sparc__ +/* warn a bit for now, but don't overdo it */ +{ + static int count = 0; + if (!count) { + count=1; + printk(KERN_WARNING + "fcntl_setlk() called by process %d (%s) with broken flock() emulation\n", + current->pid, current->comm); + } +} + if (!(filp->f_mode & 3)) + goto out_putf; + break; +#endif + default: + error = -EINVAL; + goto out_putf; + } + if (filp->f_op->lock != NULL) { + error = filp->f_op->lock(filp, cmd, &file_lock); + if (error < 0) + goto out_putf; + } + error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW); + +out_putf: + fput(filp); +out: + return error; +} + +/* + * This function is called when the file is being removed + * from the task's fd array. + */ +void locks_remove_posix(struct file *filp, fl_owner_t owner) +{ + struct inode * inode = filp->f_dentry->d_inode; + struct file_lock file_lock, *fl; + struct file_lock **before; + + /* + * For POSIX locks we free all locks on this file for the given task. + */ +repeat: + before = &inode->i_flock; + while ((fl = *before) != NULL) { + if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { + int (*lock)(struct file *, int, struct file_lock *); + lock = filp->f_op->lock; + if (lock) { + file_lock = *fl; + file_lock.fl_type = F_UNLCK; + } + locks_delete_lock(before, 0); + if (lock) { + lock(filp, F_SETLK, &file_lock); + /* List may have changed: */ + goto repeat; + } + continue; + } + before = &fl->fl_next; + } +} + +/* + * This function is called on the last close of an open file. + */ +void locks_remove_flock(struct file *filp) +{ + struct inode * inode = filp->f_dentry->d_inode; + struct file_lock file_lock, *fl; + struct file_lock **before; + +repeat: + before = &inode->i_flock; + while ((fl = *before) != NULL) { + if ((fl->fl_flags & FL_FLOCK) && fl->fl_file == filp) { + int (*lock)(struct file *, int, struct file_lock *); + lock = NULL; + if (filp->f_op) + lock = filp->f_op->lock; + if (lock) { + file_lock = *fl; + file_lock.fl_type = F_UNLCK; + } + locks_delete_lock(before, 0); + if (lock) { + lock(filp, F_SETLK, &file_lock); + /* List may have changed: */ + goto repeat; + } + continue; + } + before = &fl->fl_next; + } +} + +/* The following two are for the benefit of lockd. + */ +void +posix_block_lock(struct file_lock *blocker, struct file_lock *waiter) +{ + locks_insert_block(blocker, waiter); + return; +} + +void +posix_unblock_lock(struct file_lock *waiter) +{ + if (waiter->fl_prevblock) + locks_delete_block(waiter->fl_prevblock, waiter); return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/minix/bitmap.c linux.ac/fs/minix/bitmap.c --- linux.vanilla/fs/minix/bitmap.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/minix/bitmap.c Sat Jun 10 22:18:33 2000 @@ -205,24 +205,6 @@ struct buffer_head * bh; unsigned long ino; - if (!inode) - return; - if (!inode->i_dev) { - printk("free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk("free_inode: inode has count=%d\n",inode->i_count); - return; - } - if (inode->i_nlink) { - printk("free_inode: inode has nlink=%d\n",inode->i_nlink); - return; - } - if (!inode->i_sb) { - printk("free_inode: inode on nonexistent device\n"); - return; - } if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) { printk("free_inode: inode 0 or nonexistent inode\n"); return; @@ -294,16 +276,13 @@ mark_inode_dirty(inode); unlock_super(sb); -printk("m_n_i: allocated inode "); if(DQUOT_ALLOC_INODE(sb, inode)) { -printk("fails quota test\n"); sb->dq_op->drop(inode); inode->i_nlink = 0; iput(inode); *error = -EDQUOT; return NULL; } -printk("is within quota\n"); *error = 0; return inode; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/minix/fsync.c linux.ac/fs/minix/fsync.c --- linux.vanilla/fs/minix/fsync.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/minix/fsync.c Sat Jun 10 21:51:07 2000 @@ -329,7 +329,7 @@ * NULL */ -int minix_sync_file(struct file * file, struct dentry *dentry) +int minix_sync_file(struct file * file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/minix/namei.c linux.ac/fs/minix/namei.c --- linux.vanilla/fs/minix/namei.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/minix/namei.c Sat Jun 10 22:18:33 2000 @@ -520,7 +520,7 @@ inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/namei.c linux.ac/fs/namei.c --- linux.vanilla/fs/namei.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/namei.c Sat Jun 10 22:59:46 2000 @@ -771,8 +771,6 @@ int error; if (!victim->d_inode || victim->d_parent->d_inode != dir) return -ENOENT; - if (IS_DEADDIR(dir)) - return -ENOENT; error = permission(dir,MAY_WRITE | MAY_EXEC); if (error) return error; @@ -786,8 +784,6 @@ return -ENOTDIR; if (IS_ROOT(victim)) return -EBUSY; - if (d_mountpoint(victim)) - return -EBUSY; } else if (S_ISDIR(victim->d_inode->i_mode)) return -EISDIR; return 0; @@ -917,6 +913,22 @@ error = -EEXIST; if (flag & O_EXCL) goto exit_dput; + if (flag & O_NOFOLLOW) { + error = -ELOOP; + if (dentry->d_inode->i_op && + dentry->d_inode->i_op->follow_link) + goto exit_dput; + if (d_mountpoint(dentry)) + goto exit_dput; + goto got_it; + } + /* Check mountpoints - it may be a binding on file. */ + while (d_mountpoint(dentry) && + __follow_down(&nd->mnt, &dentry)) + ; + error = -ENOENT; + if (!dentry->d_inode) + goto exit_dput; if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) { /* @@ -930,6 +942,7 @@ return error; dentry = nd->dentry; } else { + got_it: dput(nd->dentry); nd->dentry = dentry; } @@ -962,6 +975,10 @@ if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) goto exit; + error = -EOPNOTSUPP; + if (S_ISSOCK(inode->i_mode)) + goto exit; + error = permission(inode,acc_mode); if (error) goto exit; @@ -1213,9 +1230,15 @@ double_down(&dir->i_zombie, &dentry->d_inode->i_zombie); d_unhash(dentry); - error = dir->i_op->rmdir(dir, dentry); - if (!error) - dentry->d_inode->i_flags |= S_DEAD; + if (IS_DEADDIR(dir)) + error = -ENOENT; + else if (d_mountpoint(dentry)) + error = -EBUSY; + else { + error = dir->i_op->rmdir(dir, dentry); + if (!error) + dentry->d_inode->i_flags |= S_DEAD; + } double_up(&dir->i_zombie, &dentry->d_inode->i_zombie); if (!error) d_delete(dentry); @@ -1275,9 +1298,13 @@ error = -EPERM; if (dir->i_op && dir->i_op->unlink) { DQUOT_INIT(dir); - error = dir->i_op->unlink(dir, dentry); - if (!error) - d_delete(dentry); + if (d_mountpoint(dentry)) + error = -EBUSY; + else { + error = dir->i_op->unlink(dir, dentry); + if (!error) + d_delete(dentry); + } } } up(&dir->i_zombie); @@ -1555,7 +1582,12 @@ } else double_down(&old_dir->i_zombie, &new_dir->i_zombie); - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir)) + error = -ENOENT; + else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) + error = -EBUSY; + else + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); if (target) { if (!error) target->i_flags |= S_DEAD; @@ -1603,7 +1635,10 @@ DQUOT_INIT(old_dir); DQUOT_INIT(new_dir); double_down(&old_dir->i_zombie, &new_dir->i_zombie); - error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) + error = -EBUSY; + else + error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); double_up(&old_dir->i_zombie, &new_dir->i_zombie); if (error) return error; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/dir.c linux.ac/fs/ncpfs/dir.c --- linux.vanilla/fs/ncpfs/dir.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/dir.c Tue Jun 6 12:29:05 2000 @@ -973,7 +973,7 @@ /* * Check whether to close the file ... */ - if (inode && NCP_FINFO(inode)->opened) { + if (inode) { PPRINTK("ncp_unlink: closing file\n"); ncp_make_closed(inode); } @@ -982,7 +982,7 @@ #ifdef CONFIG_NCPFS_STRONG /* 9C is Invalid path.. It should be 8F, 90 - read only, but it is not :-( */ - if (error == 0x9C && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ + if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */ error = ncp_force_unlink(dir, dentry); } #endif @@ -1051,7 +1051,7 @@ error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name, new_dir, __new_name); #ifdef CONFIG_NCPFS_STRONG - if ((error == 0x90 || error == -EACCES) && + if ((error == 0x90 || error == 0x8B || error == -EACCES) && server->m.flags & NCP_MOUNT_STRONG) { /* RO */ error = ncp_force_rename(old_dir, old_dentry, __old_name, new_dir, new_dentry, __new_name); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/file.c linux.ac/fs/ncpfs/file.c --- linux.vanilla/fs/ncpfs/file.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/ncpfs/file.c Sat Jun 10 21:51:07 2000 @@ -26,7 +26,7 @@ return a < b ? a : b; } -static int ncp_fsync(struct file *file, struct dentry *dentry) +static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync) { return 0; } @@ -46,12 +46,12 @@ } DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n", - NCP_FINFO(inode)->opened, + atomic_read(&NCP_FINFO(inode)->opened), NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum); error = -EACCES; - lock_super(inode->i_sb); - if (!NCP_FINFO(inode)->opened) { + down(&NCP_FINFO(inode)->open_sem); + if (!atomic_read(&NCP_FINFO(inode)->opened)) { struct ncp_entry_info finfo; int result; @@ -88,15 +88,18 @@ */ update: ncp_update_inode(inode, &finfo); + atomic_set(&NCP_FINFO(inode)->opened, 1); } access = NCP_FINFO(inode)->access; PPRINTK("ncp_make_open: file open, access=%x\n", access); - if (access == right || access == O_RDWR) + if (access == right || access == O_RDWR) { + atomic_inc(&NCP_FINFO(inode)->opened); error = 0; + } out_unlock: - unlock_super(inode->i_sb); + up(&NCP_FINFO(inode)->open_sem); out: return error; } @@ -153,7 +156,7 @@ freelen = ncp_read_bounce_size(bufsize); freepage = kmalloc(freelen, GFP_NFS); if (!freepage) - goto out; + goto outrel; error = 0; /* First read in as much as possible for each bufsize. */ while (already_read < count) { @@ -166,9 +169,8 @@ pos, to_read, buf, &read_this_time, freepage, freelen); if (error) { - kfree(freepage); - error = -EIO; /* This is not exact, i know.. */ - goto out; + error = -EIO; /* NW errno -> Linux errno */ + break; } pos += read_this_time; buf += read_this_time; @@ -188,6 +190,8 @@ DPRINTK("ncp_file_read: exit %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); +outrel: + ncp_inode_close(inode); out: return already_read ? already_read : error; } @@ -236,8 +240,10 @@ already_written = 0; bouncebuffer = kmalloc(bufsize, GFP_NFS); - if (!bouncebuffer) - return -EIO; /* -ENOMEM */ + if (!bouncebuffer) { + errno = -EIO; /* -ENOMEM */ + goto outrel; + } while (already_written < count) { int written_this_time; size_t to_write = min(bufsize - (pos % bufsize), @@ -271,15 +277,15 @@ } DPRINTK("ncp_file_write: exit %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); +outrel: + ncp_inode_close(inode); out: return already_written ? already_written : errno; } static int ncp_release(struct inode *inode, struct file *file) { - if (NCP_FINFO(inode)->opened) { - if (ncp_make_closed(inode)) { - DPRINTK("ncp_release: failed to close\n"); - } + if (ncp_make_closed(inode)) { + DPRINTK("ncp_release: failed to close\n"); } return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/inode.c linux.ac/fs/ncpfs/inode.c --- linux.vanilla/fs/ncpfs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/inode.c Sat Jun 10 22:18:33 2000 @@ -31,14 +31,13 @@ #include "ncplib_kernel.h" -static void ncp_put_inode(struct inode *); static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); static int ncp_statfs(struct super_block *, struct statfs *); static struct super_operations ncp_sops = { - put_inode: ncp_put_inode, + put_inode: force_delete, delete_inode: ncp_delete_inode, put_super: ncp_put_super, statfs: ncp_statfs, @@ -62,7 +61,6 @@ #ifdef CONFIG_NCPFS_STRONG NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; #endif - NCP_FINFO(inode)->opened = nwinfo->opened; NCP_FINFO(inode)->access = nwinfo->access; NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle; memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, @@ -77,7 +75,7 @@ struct nw_info_struct *nwi = &nwinfo->i; struct ncp_server *server = NCP_SERVER(inode); - if (!NCP_FINFO(inode)->opened) { + if (!atomic_read(&NCP_FINFO(inode)->opened)) { #ifdef CONFIG_NCPFS_STRONG NCP_FINFO(inode)->nwattr = nwi->attributes; #endif @@ -217,6 +215,9 @@ inode = get_empty_inode(); if (inode) { + init_MUTEX(&NCP_FINFO(inode)->open_sem); + atomic_set(&NCP_FINFO(inode)->opened, info->opened); + inode->i_sb = sb; inode->i_dev = sb->s_dev; inode->i_ino = info->ino; @@ -239,12 +240,6 @@ return inode; } -static void ncp_put_inode(struct inode *inode) -{ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - static void ncp_delete_inode(struct inode *inode) { @@ -252,7 +247,7 @@ DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino); } - if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) { + if (ncp_make_closed(inode) != 0) { /* We can't do anything but complain. */ printk(KERN_ERR "ncp_delete_inode: could not close\n"); } @@ -325,7 +320,6 @@ sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; - sb->s_dev = dev; sb->s_op = &ncp_sops; server = NCP_SBP(sb); @@ -683,6 +677,7 @@ /* According to ndir, the changes only take effect after closing the file */ + ncp_inode_close(inode); result = ncp_make_closed(inode); if (!result) vmtruncate(inode, attr->ia_size); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/ioctl.c linux.ac/fs/ncpfs/ioctl.c --- linux.vanilla/fs/ncpfs/ioctl.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/ncpfs/ioctl.c Sun Jun 4 21:48:39 2000 @@ -335,18 +335,12 @@ { return result; } + result = -EIO; if (!ncp_conn_valid(server)) - { - return -EIO; - } + goto outrel; + result = -EISDIR; if (!S_ISREG(inode->i_mode)) - { - return -EISDIR; - } - if (!NCP_FINFO(inode)->opened) - { - return -EBADFD; - } + goto outrel; if (rqdata.cmd == NCP_LOCK_CLEAR) { result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), @@ -373,6 +367,8 @@ rqdata.timeout); if (result > 0) result = -EAGAIN; } +outrel: + ncp_inode_close(inode); return result; } #endif /* CONFIG_NCPFS_IOCTL_LOCKING */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/mmap.c linux.ac/fs/ncpfs/mmap.c --- linux.vanilla/fs/ncpfs/mmap.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/mmap.c Sun Jun 4 21:48:39 2000 @@ -82,6 +82,7 @@ break; } } + ncp_inode_close(inode); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/ncplib_kernel.c linux.ac/fs/ncpfs/ncplib_kernel.c --- linux.vanilla/fs/ncpfs/ncplib_kernel.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/ncplib_kernel.c Sun Jun 4 21:48:39 2000 @@ -221,20 +221,23 @@ return result; } -/* - * Called with the superblock locked. - */ int ncp_make_closed(struct inode *inode) { int err; - NCP_FINFO(inode)->opened = 0; - err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); - if (!err) - PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n", - NCP_FINFO(inode)->volNumber, - NCP_FINFO(inode)->dirEntNum, err); + err = 0; + down(&NCP_FINFO(inode)->open_sem); + if (atomic_read(&NCP_FINFO(inode)->opened) == 1) { + atomic_set(&NCP_FINFO(inode)->opened, 0); + err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); + + if (!err) + PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n", + NCP_FINFO(inode)->volNumber, + NCP_FINFO(inode)->dirEntNum, err); + } + up(&NCP_FINFO(inode)->open_sem); return err; } @@ -613,7 +616,8 @@ if ((result = ncp_request(server, 87)) != 0) goto out; - target->opened = 1; + if (!(create_attributes & aDIR)) + target->opened = 1; target->server_file_handle = ncp_reply_dword(server, 0); target->open_create_action = ncp_reply_byte(server, 4); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/ncplib_kernel.h linux.ac/fs/ncpfs/ncplib_kernel.h --- linux.vanilla/fs/ncpfs/ncplib_kernel.h Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/ncplib_kernel.h Sat Jun 10 23:05:52 2000 @@ -57,6 +57,10 @@ int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, const char *, int *); +static inline void ncp_inode_close(struct inode *inode) { + atomic_dec(&NCP_FINFO(inode)->opened); +} + int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, struct nw_info_struct *target); int ncp_lookup_volume(struct ncp_server *, char *, struct nw_info_struct *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ncpfs/symlink.c linux.ac/fs/ncpfs/symlink.c --- linux.vanilla/fs/ncpfs/symlink.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ncpfs/symlink.c Tue Jun 6 12:29:05 2000 @@ -50,10 +50,6 @@ char *link; char *buf = (char*)kmap(page); - error = -EIO; - if (ncp_make_open(inode,O_RDONLY)) - goto fail; - error = -ENOMEM; for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) { if (cnt > 10) @@ -61,20 +57,22 @@ schedule(); } + if (ncp_make_open(inode,O_RDONLY)) + goto failEIO; + error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle, 0,NCP_MAX_SYMLINK_SIZE,link,&length); - if (error) { - kfree(link); - goto fail; - } + ncp_inode_close(inode); + /* Close file handle if no other users... */ + ncp_make_closed(inode); + if (error) + goto failEIO; + if (lengthd_inode; + if (ncp_make_open(inode, O_WRONLY)) + goto failfree; + ((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0; ((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1; @@ -134,19 +137,26 @@ symlink can point out of ncp filesystem */ length += 1; err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0); - if (err) { - kfree(link); - return err; - } + if (err) + goto fail; if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 0, length+8, link, &i) || i!=length+8) { - kfree(link); - return -EIO; + err = -EIO; + goto fail; } + ncp_inode_close(inode); + ncp_make_closed(inode); kfree(link); return 0; + +fail: + ncp_inode_close(inode); + ncp_make_closed(inode); +failfree: + kfree(link); + return err; } #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfs/file.c linux.ac/fs/nfs/file.c --- linux.vanilla/fs/nfs/file.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/nfs/file.c Sat Jun 10 21:51:08 2000 @@ -39,7 +39,7 @@ static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *); static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); -static int nfs_fsync(struct file *, struct dentry *dentry); +static int nfs_fsync(struct file *, struct dentry *dentry, int); struct file_operations nfs_file_operations = { read: nfs_file_read, @@ -124,7 +124,7 @@ * whether any write errors occurred for this process. */ static int -nfs_fsync(struct file *file, struct dentry *dentry) +nfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int status; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfs/flushd.c linux.ac/fs/nfs/flushd.c --- linux.vanilla/fs/nfs/flushd.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/nfs/flushd.c Sat Jun 10 22:18:33 2000 @@ -175,7 +175,7 @@ * it from disappearing when on the flush list */ NFS_FLAGS(inode) |= NFS_INO_FLUSH; - inode->i_count++; + atomic_inc(&inode->i_count); out: spin_unlock(&nfs_flushd_lock); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfs/inode.c linux.ac/fs/nfs/inode.c --- linux.vanilla/fs/nfs/inode.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/nfs/inode.c Sat Jun 10 22:18:33 2000 @@ -44,7 +44,6 @@ static void nfs_invalidate_inode(struct inode *); static void nfs_read_inode(struct inode *); -static void nfs_put_inode(struct inode *); static void nfs_delete_inode(struct inode *); static void nfs_put_super(struct super_block *); static void nfs_umount_begin(struct super_block *); @@ -52,7 +51,7 @@ static struct super_operations nfs_sops = { read_inode: nfs_read_inode, - put_inode: nfs_put_inode, + put_inode: force_delete, delete_inode: nfs_delete_inode, put_super: nfs_put_super, statfs: nfs_statfs, @@ -115,17 +114,6 @@ } static void -nfs_put_inode(struct inode * inode) -{ - dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); - /* - * We want to get rid of unused inodes ... - */ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - -static void nfs_delete_inode(struct inode * inode) { dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); @@ -690,7 +678,7 @@ * don't invalidate their inodes even if all dentries are * unhashed. */ - if (unhashed && inode->i_count == unhashed + 1 + if (unhashed && atomic_read(&inode->i_count) == unhashed + 1 && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode)) is_stale = 1; @@ -784,7 +772,7 @@ break; dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n", - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); nfs_zap_caches(inode); remove_inode_hash(inode); iput(inode); @@ -795,7 +783,7 @@ nfs_fill_inode(inode, fattr); dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n", - inode->i_dev, inode->i_ino, inode->i_count); + inode->i_dev, inode->i_ino, atomic_read(&inode->i_count)); out: return inode; @@ -870,7 +858,7 @@ int error; if (!(NFS_FLAGS(inode) & flag)) return 0; - inode->i_count++; + atomic_inc(&inode->i_count); error = nfs_wait_event(clnt, inode->i_wait, !(NFS_FLAGS(inode) & flag)); iput(inode); return error; @@ -1019,8 +1007,8 @@ goto out; dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d info=0x%x)\n", - inode->i_dev, inode->i_ino, inode->i_count, - fattr->valid); + inode->i_dev, inode->i_ino, + atomic_read(&inode->i_count), fattr->valid); if (NFS_FSID(inode) != fattr->fsid || diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/export.c linux.ac/fs/nfsd/export.c --- linux.vanilla/fs/nfsd/export.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/export.c Mon Jun 5 19:45:46 2000 @@ -436,7 +436,6 @@ err = 0; memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh)); fh_put(&fh); - return err; out: path_release(&nd); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/nfs3proc.c linux.ac/fs/nfsd/nfs3proc.c --- linux.vanilla/fs/nfsd/nfs3proc.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/nfs3proc.c Mon Jun 5 19:45:46 2000 @@ -658,7 +658,7 @@ PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF), PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF), PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF), - PROC(rename, rename, rename, fhandle, RC_REPLBUFF), + PROC(rename, rename, rename, fhandle2, RC_REPLBUFF), PROC(link, link, link, fhandle2, RC_REPLBUFF), PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE), PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/nfs3xdr.c linux.ac/fs/nfsd/nfs3xdr.c --- linux.vanilla/fs/nfsd/nfs3xdr.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/nfs3xdr.c Fri Jun 9 15:50:44 2000 @@ -698,17 +698,9 @@ cd->eob = 1; return -EINVAL; } - *p++ = xdr_one; /* mark entry present */ - p = xdr_encode_hyper(p, ino); /* file id */ - p[slen - 1] = 0; /* don't leak kernel data */ -#ifdef XDR_ENCODE_STRING_TAKES_LENGTH - p = xdr_encode_string(p, name, namlen); /* name length & name */ -#else - /* just like nfsproc.c */ - *p++ = htonl((u32) namlen); - memcpy(p, name, namlen); - p += slen; -#endif + *p++ = xdr_one; /* mark entry present */ + p = xdr_encode_hyper(p, ino); /* file id */ + p = xdr_encode_array(p, name, namlen);/* name length & name */ cd->offset = p; /* remember pointer */ p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/nfsfh.c linux.ac/fs/nfsd/nfsfh.c --- linux.vanilla/fs/nfsd/nfsfh.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/nfsd/nfsfh.c Sat Jun 10 22:18:33 2000 @@ -142,7 +142,7 @@ /* we didn't find the right inode.. */ dprintk("fh_verify: Inode %lu, Bad count: %d %d or version %u %u\n", inode->i_ino, - inode->i_nlink, inode->i_count, + inode->i_nlink, atomic_read(&inode->i_count), inode->i_generation, generation); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/nfssvc.c linux.ac/fs/nfsd/nfssvc.c --- linux.vanilla/fs/nfsd/nfssvc.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/nfssvc.c Fri Jun 9 15:51:51 2000 @@ -83,7 +83,10 @@ if (error < 0) goto failure; -#if 0 /* Don't even pretend that TCP works. It doesn't. */ +#if CONFIG_NFSD_TCP + /* This is developer-only at the moment, + * there are untracked bugs as of 2.4.0-test1-ac11 + */ error = svc_makesock(nfsd_serv, IPPROTO_TCP, port); if (error < 0) goto failure; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/nfsxdr.c linux.ac/fs/nfsd/nfsxdr.c --- linux.vanilla/fs/nfsd/nfsxdr.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/nfsxdr.c Fri Jun 9 15:50:44 2000 @@ -412,11 +412,9 @@ cd->eob = 1; return -EINVAL; } - *p++ = xdr_one; /* mark entry present */ - *p++ = htonl((u32) ino); /* file id */ - *p++ = htonl((u32) namlen); /* name length & name */ - memcpy(p, name, namlen); - p += slen; + *p++ = xdr_one; /* mark entry present */ + *p++ = htonl((u32) ino); /* file id */ + p = xdr_encode_array(p, name, namlen);/* name length & name */ cd->offset = p; /* remember pointer */ *p++ = ~(u32) 0; /* offset of next entry */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfsd/vfs.c linux.ac/fs/nfsd/vfs.c --- linux.vanilla/fs/nfsd/vfs.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/nfsd/vfs.c Sat Jun 10 22:18:33 2000 @@ -312,7 +312,7 @@ if (err) goto out_nfserr; if (EX_ISSYNC(fhp->fh_export)) - write_inode_now(inode); + write_inode_now(inode, 0); err = 0; /* Don't unlock inode; the nfssvc_release functions are supposed @@ -492,16 +492,10 @@ struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - if (!inode->i_count) - printk(KERN_WARNING "nfsd: inode count == 0!\n"); - if (!dentry->d_count) - printk(KERN_WARNING "nfsd: wheee, %s/%s d_count == 0!\n", - dentry->d_parent->d_name.name, dentry->d_name.name); if (filp->f_op && filp->f_op->release) filp->f_op->release(inode, filp); - if (filp->f_mode & FMODE_WRITE) { + if (filp->f_mode & FMODE_WRITE) put_write_access(inode); - } } /* @@ -514,7 +508,7 @@ { dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); down(&filp->f_dentry->d_inode->i_sem); - filp->f_op->fsync(filp, filp->f_dentry); + filp->f_op->fsync(filp, filp->f_dentry,0); up(&filp->f_dentry->d_inode->i_sem); } @@ -522,10 +516,10 @@ nfsd_sync_dir(struct dentry *dp) { struct inode *inode = dp->d_inode; - int (*fsync) (struct file *, struct dentry *); + int (*fsync) (struct file *, struct dentry *, int); if (inode->i_fop && (fsync = inode->i_fop->fsync)) { - fsync(NULL, dp); + fsync(NULL, dp, 0); } } @@ -893,7 +887,7 @@ if (EX_ISSYNC(fhp->fh_export)) { nfsd_sync_dir(dentry); - write_inode_now(dchild->d_inode); + write_inode_now(dchild->d_inode, 0); } @@ -1120,7 +1114,7 @@ | S_IFLNK; err = notify_change(dnew, iap); if (!err && EX_ISSYNC(fhp->fh_export)) - write_inode_now(dentry->d_inode); + write_inode_now(dentry->d_inode, 0); } } } else @@ -1180,7 +1174,7 @@ if (!err) { if (EX_ISSYNC(ffhp->fh_export)) { nfsd_sync_dir(ddir); - write_inode_now(dest); + write_inode_now(dest, 0); } } else { if (err == -EXDEV && rqstp->rq_vers == 2) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ntfs/Makefile linux.ac/fs/ntfs/Makefile --- linux.vanilla/fs/ntfs/Makefile Thu May 25 17:37:32 2000 +++ linux.ac/fs/ntfs/Makefile Thu Jun 8 16:34:16 2000 @@ -3,7 +3,7 @@ O_TARGET := ntfs.o O_OBJS := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o M_OBJS := $(O_TARGET) -EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"000502\" +EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"000607\" include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ntfs/fs.c linux.ac/fs/ntfs/fs.c --- linux.vanilla/fs/ntfs/fs.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ntfs/fs.c Sat Jun 10 22:18:33 2000 @@ -80,7 +80,7 @@ io.param=buf; io.size=count; error=ntfs_read_attr(ino,ino->vol->at_data,NULL,*off,&io); - if(error)return -error; + if(error && !io.size)return -error; *off+=io.size; return io.size; @@ -218,7 +218,7 @@ (unsigned)dir->i_ino,(unsigned int)dir->i_mode); ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n", - (unsigned)filp->f_pos,dir->i_count); + (unsigned)filp->f_pos,atomic_read(&dir->i_count)); cb.pl=filp->f_pos & 0xFFFF; cb.ph=filp->f_pos >> 16; /* end of directory */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ntfs/inode.c linux.ac/fs/ntfs/inode.c --- linux.vanilla/fs/ntfs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ntfs/inode.c Thu Jun 8 16:34:22 2000 @@ -6,6 +6,7 @@ * Copyright (C) 1996-1997 Régis Duchesne * Copyright (C) 1998 Joseph Malicki * Copyright (C) 1999 Steve Dodd + * Copyright (C) 2000 Anton Altaparmakov */ #include "ntfstypes.h" @@ -551,11 +552,11 @@ dest->size=chunk; error=ntfs_getput_clusters(ino->vol,s_cluster, offset-s_vcn*clustersize,dest); - if(error)/* FIXME: maybe return failure */ + if(error) { ntfs_error("Read error\n"); dest->size=copied; - return 0; + return error; } l-=chunk; copied+=chunk; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ntfs/super.c linux.ac/fs/ntfs/super.c --- linux.vanilla/fs/ntfs/super.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ntfs/super.c Thu Jun 8 16:34:22 2000 @@ -221,7 +221,6 @@ int ntfs_get_version(ntfs_inode* volume) { ntfs_attribute *volinfo; - int i; volinfo = ntfs_find_attr(volume, volume->vol->at_volume_information, 0); if (!volinfo) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/generic.c linux.ac/fs/proc/generic.c --- linux.vanilla/fs/proc/generic.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/proc/generic.c Sat Jun 10 21:53:11 2000 @@ -403,7 +403,7 @@ } struct proc_dir_entry *proc_symlink(const char *name, - struct proc_dir_entry *parent, char *dest) + struct proc_dir_entry *parent, const char *dest) { struct proc_dir_entry *ent = NULL; const char *fn = name; @@ -535,7 +535,7 @@ { int ino = de->low_ino; - if (ino < PROC_DYNAMIC_FIRST && + if (ino < PROC_DYNAMIC_FIRST || ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC) return; if (S_ISLNK(de->mode) && de->data) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/inode.c linux.ac/fs/proc/inode.c --- linux.vanilla/fs/proc/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/proc/inode.c Sat Jun 10 22:18:33 2000 @@ -52,16 +52,6 @@ } } -static void proc_put_inode(struct inode *inode) -{ - /* - * Kill off unused inodes ... VFS will unhash and - * delete the inode if we set i_nlink to zero. - */ - if (inode->i_count == 1) - inode->i_nlink = 0; -} - /* * Decrement the use count of the proc_dir_entry. */ @@ -102,7 +92,7 @@ static struct super_operations proc_sops = { read_inode: proc_read_inode, - put_inode: proc_put_inode, + put_inode: force_delete, delete_inode: proc_delete_inode, statfs: proc_statfs, }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/proc_misc.c linux.ac/fs/proc/proc_misc.c --- linux.vanilla/fs/proc/proc_misc.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/proc/proc_misc.c Mon Jun 5 20:02:20 2000 @@ -325,14 +325,14 @@ for (major = 0; major < DK_MAX_MAJOR; major++) { for (disk = 0; disk < DK_MAX_DISK; disk++) { - int active = kstat.dk_drive_rio[major][disk] + + int active = kstat.dk_drive[major][disk] + kstat.dk_drive_rblk[major][disk] + - kstat.dk_drive_wio[major][disk] + kstat.dk_drive_wblk[major][disk]; if (active) len += sprintf(page + len, - "(%u,%u):(%u,%u,%u,%u) ", + "(%u,%u):(%u,%u,%u,%u,%u) ", major, disk, + kstat.dk_drive[major][disk], kstat.dk_drive_rio[major][disk], kstat.dk_drive_rblk[major][disk], kstat.dk_drive_wio[major][disk], diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/qnx4/bitmap.c linux.ac/fs/qnx4/bitmap.c --- linux.vanilla/fs/qnx4/bitmap.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/qnx4/bitmap.c Sat Jun 10 22:18:33 2000 @@ -153,25 +153,6 @@ void qnx4_free_inode(struct inode *inode) { - if (!inode) { - return; - } - if (!inode->i_dev) { - printk("free_inode: inode has no device\n"); - return; - } - if (inode->i_count > 1) { - printk("free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk("free_inode: inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!inode->i_sb) { - printk("free_inode: inode on nonexistent device\n"); - return; - } if (inode->i_ino < 1) { printk("free_inode: inode 0 or nonexistent inode\n"); return; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/qnx4/fsync.c linux.ac/fs/qnx4/fsync.c --- linux.vanilla/fs/qnx4/fsync.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/qnx4/fsync.c Sat Jun 10 21:51:08 2000 @@ -147,7 +147,7 @@ return err; } -int qnx4_sync_file(struct file *file, struct dentry *dentry) +int qnx4_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int wait, err = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ramfs/inode.c linux.ac/fs/ramfs/inode.c --- linux.vanilla/fs/ramfs/inode.c Thu May 25 17:37:33 2000 +++ linux.ac/fs/ramfs/inode.c Sat Jun 10 22:18:33 2000 @@ -181,7 +181,7 @@ return -EPERM; inode->i_nlink++; - inode->i_count++; /* New dentry reference */ + atomic_inc(&inode->i_count); /* New dentry reference */ dget(dentry); /* Extra pinning count for the created dentry */ d_instantiate(dentry, inode); return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/select.c linux.ac/fs/select.c --- linux.vanilla/fs/select.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/select.c Sat May 27 15:45:55 2000 @@ -52,6 +52,7 @@ if(out==NULL) return NULL; out->nr = 0; + out->err = 0; out->entry = (struct poll_table_entry *)(out + 1); out->next = NULL; nfds -=__MAX_POLL_TABLE_ENTRIES; @@ -97,19 +98,36 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) { + poll_table* walk = p; for (;;) { - if (p->nr < __MAX_POLL_TABLE_ENTRIES) { + if (walk->nr < __MAX_POLL_TABLE_ENTRIES) { struct poll_table_entry * entry; - entry = p->entry + p->nr; +ok_table: + entry = walk->entry + walk->nr; get_file(filp); entry->filp = filp; entry->wait_address = wait_address; init_waitqueue_entry(&entry->wait, current); add_wait_queue(wait_address,&entry->wait); - p->nr++; + walk->nr++; return; } - p = p->next; + if (walk->next == NULL) { + poll_table *tmp; + current->state=TASK_RUNNING; + tmp = (poll_table *) __get_free_page(GFP_KERNEL); + if (!tmp) { + p->err=-ENOMEM; + return; + } + tmp->nr = 0; + tmp->entry = (struct poll_table_entry *)(tmp + 1); + tmp->next = NULL; + walk->next = tmp; + walk = tmp; + goto ok_table; + } + walk = walk->next; } } @@ -226,11 +244,16 @@ wait = NULL; } } - wait = NULL; if (retval || !__timeout || signal_pending(current)) break; + if(orig_wait->err) { + retval=orig_wait->err; + goto out; + } + wait = NULL; __timeout = schedule_timeout(__timeout); } +out: current->state = TASK_RUNNING; free_wait(orig_wait); @@ -382,6 +405,7 @@ struct pollfd *fds[], poll_table *wait, long timeout) { int count = 0; + poll_table* orig_wait = wait; for (;;) { unsigned int i; @@ -391,11 +415,16 @@ do_pollfd(POLLFD_PER_PAGE, fds[i], &wait, &count); if (nleft) do_pollfd(nleft, fds[nchunks], &wait, &count); - wait = NULL; if (count || !timeout || signal_pending(current)) break; + if(orig_wait->err) { + count=orig_wait->err; + goto out; + } + wait=NULL; timeout = schedule_timeout(timeout); } +out: current->state = TASK_RUNNING; return count; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/smbfs/file.c linux.ac/fs/smbfs/file.c --- linux.vanilla/fs/smbfs/file.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/smbfs/file.c Sat Jun 10 21:51:08 2000 @@ -27,7 +27,7 @@ /* #define pr_debug printk */ static int -smb_fsync(struct file *file, struct dentry * dentry) +smb_fsync(struct file *file, struct dentry * dentry, int datasync) { #ifdef SMBFS_DEBUG_VERBOSE printk("smb_fsync: sync file %s/%s\n", diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/smbfs/inode.c linux.ac/fs/smbfs/inode.c --- linux.vanilla/fs/smbfs/inode.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/smbfs/inode.c Sat Jun 10 22:18:33 2000 @@ -29,7 +29,6 @@ #define SMBFS_PARANOIA 1 /* #define SMBFS_DEBUG_VERBOSE 1 */ -static void smb_put_inode(struct inode *); static void smb_delete_inode(struct inode *); static void smb_put_super(struct super_block *); static int smb_statfs(struct super_block *, struct statfs *); @@ -37,7 +36,7 @@ static struct super_operations smb_sops = { - put_inode: smb_put_inode, + put_inode: force_delete, delete_inode: smb_delete_inode, put_super: smb_put_super, statfs: smb_statfs, @@ -269,18 +268,6 @@ } out: return error; -} - -/* - * This routine is called for every iput(). We clear i_nlink - * on the last use to force a call to delete_inode. - */ -static void -smb_put_inode(struct inode *ino) -{ - pr_debug("smb_put_inode: count = %d\n", ino->i_count); - if (ino->i_count == 1) - ino->i_nlink = 0; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/super.c linux.ac/fs/super.c --- linux.vanilla/fs/super.c Thu May 25 17:46:16 2000 +++ linux.ac/fs/super.c Sun Jun 4 22:17:00 2000 @@ -738,10 +738,6 @@ /* Done with lookups, semaphore down */ down(&mount_sem); dev = to_kdev_t(bdev->bd_dev); - check_disk_change(dev); - error = -EACCES; - if (!(flags & MS_RDONLY) && is_read_only(dev)) - goto out; sb = get_super(dev); if (sb) { if (fs_type == sb->s_type) { @@ -755,6 +751,10 @@ error = blkdev_get(bdev, mode, 0, BDEV_FS); if (error) goto out; + check_disk_change(dev); + error = -EACCES; + if (!(flags & MS_RDONLY) && is_read_only(dev)) + goto out1; error = -EINVAL; sb = read_super(dev, bdev, fs_type, flags, data, 0); if (sb) { @@ -762,6 +762,7 @@ path_release(&nd); return sb; } +out1: blkdev_put(bdev, BDEV_FS); } out: @@ -1067,6 +1068,8 @@ { if (capable(CAP_SYS_ADMIN)) return 0; + return -EPERM; +#ifdef notyet if (S_ISLNK(nd->dentry->d_inode->i_mode)) return -EPERM; if (nd->dentry->d_inode->i_mode & S_ISVTX) { @@ -1076,6 +1079,7 @@ if (permission(nd->dentry->d_inode, MAY_WRITE)) return -EPERM; return 0; +#endif } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/sysv/fsync.c linux.ac/fs/sysv/fsync.c --- linux.vanilla/fs/sysv/fsync.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/sysv/fsync.c Sat Jun 10 21:51:08 2000 @@ -178,7 +178,7 @@ return err; } -int sysv_sync_file(struct file * file, struct dentry *dentry) +int sysv_sync_file(struct file * file, struct dentry *dentry, int datasync) { int wait, err = 0; struct inode *inode = dentry->d_inode; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/sysv/ialloc.c linux.ac/fs/sysv/ialloc.c --- linux.vanilla/fs/sysv/ialloc.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/sysv/ialloc.c Sat Jun 10 22:18:33 2000 @@ -56,24 +56,7 @@ struct buffer_head * bh; struct sysv_inode * raw_inode; - if (!inode) - return; - if (!inode->i_dev) { - printk("sysv_free_inode: inode has no device\n"); - return; - } - if (inode->i_count != 1) { - printk("sysv_free_inode: inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - printk("sysv_free_inode: inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!(sb = inode->i_sb)) { - printk("sysv_free_inode: inode on nonexistent device\n"); - return; - } + sb = inode->i_sb; ino = inode->i_ino; if (ino <= SYSV_ROOT_INO || ino > sb->sv_ninodes) { printk("sysv_free_inode: inode 0,1,2 or nonexistent inode\n"); @@ -112,7 +95,6 @@ return NULL; sb = dir->i_sb; inode->i_sb = sb; - inode->i_flags = 0; lock_super(sb); /* protect against task switches */ if ((*sb->sv_sb_fic_count == 0) || (*sv_sb_fic_inode(sb,(*sb->sv_sb_fic_count)-1) == 0) /* Applies only to SystemV2 FS */ @@ -149,8 +131,6 @@ mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */ if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1); sb->s_dirt = 1; /* and needs time stamp */ - inode->i_count = 1; - inode->i_nlink = 1; inode->i_dev = sb->s_dev; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/sysv/inode.c linux.ac/fs/sysv/inode.c --- linux.vanilla/fs/sysv/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/sysv/inode.c Sat Jun 10 22:18:33 2000 @@ -43,7 +43,8 @@ printk("ino %lu mode 0%6.6o lk %d uid %d gid %d" " sz %lu blks %lu cnt %u\n", inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, - inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count); + inode->i_gid, inode->i_size, inode->i_blocks, + atomic_read(&inode->i_count)); printk(" db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx" " 0x%lx 0x%lx>\n", inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1], diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/sysv/namei.c linux.ac/fs/sysv/namei.c --- linux.vanilla/fs/sysv/namei.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/sysv/namei.c Sat Jun 10 22:18:33 2000 @@ -507,7 +507,7 @@ oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; mark_inode_dirty(oldinode); - oldinode->i_count++; + atomic_inc(&oldinode->i_count); d_instantiate(dentry, oldinode); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/udf/ialloc.c linux.ac/fs/udf/ialloc.c --- linux.vanilla/fs/udf/ialloc.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/udf/ialloc.c Sat Jun 10 22:18:33 2000 @@ -38,27 +38,6 @@ int is_directory; unsigned long ino; - if (!inode->i_dev) - { - udf_debug("inode has no device\n"); - return; - } - if (inode->i_count > 1) - { - udf_debug("inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) - { - udf_debug("inode has nlink=%d\n", inode->i_nlink); - return; - } - if (!sb) - { - udf_debug("inode on nonexistent device\n"); - return; - } - ino = inode->i_ino; /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/udf/namei.c linux.ac/fs/udf/namei.c --- linux.vanilla/fs/udf/namei.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/udf/namei.c Sat Jun 10 22:18:33 2000 @@ -1108,7 +1108,7 @@ inode->i_ctime = CURRENT_TIME; UDF_I_UCTIME(inode) = CURRENT_UTIME; mark_inode_dirty(inode); - inode->i_count ++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ufs/ialloc.c linux.ac/fs/ufs/ialloc.c --- linux.vanilla/fs/ufs/ialloc.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ufs/ialloc.c Sat Jun 10 22:18:33 2000 @@ -70,22 +70,11 @@ UFSD(("ENTER, ino %lu\n", inode->i_ino)) - if (!inode) - return; sb = inode->i_sb; swab = sb->u.ufs_sb.s_swab; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); - if (inode->i_count > 1) { - ufs_warning(sb, "ufs_free_inode", "inode has count=%d\n", inode->i_count); - return; - } - if (inode->i_nlink) { - ufs_warning(sb, "ufs_free_inode", "inode has nlink=%d\n", inode->i_nlink); - return; - } - ino = inode->i_ino; lock_super (sb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/ufs/namei.c linux.ac/fs/ufs/namei.c --- linux.vanilla/fs/ufs/namei.c Thu May 25 17:37:32 2000 +++ linux.ac/fs/ufs/namei.c Sat Jun 10 22:18:33 2000 @@ -834,7 +834,7 @@ inode->i_nlink++; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/umsdos/dir.c linux.ac/fs/umsdos/dir.c --- linux.vanilla/fs/umsdos/dir.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/umsdos/dir.c Sat Jun 10 22:18:33 2000 @@ -537,7 +537,7 @@ * We've found it OK. Now hash the dentry with the inode. */ out_add: - inode->i_count++; + atomic_inc(&inode->i_count); d_add (dentry, inode); dentry->d_op = &umsdos_dentry_operations; ret = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/umsdos/inode.c linux.ac/fs/umsdos/inode.c --- linux.vanilla/fs/umsdos/inode.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/umsdos/inode.c Sat Jun 10 22:18:33 2000 @@ -51,14 +51,14 @@ "put inode %p (%lu) pos %lu count=%d\n" ,inode, inode->i_ino ,inode->u.umsdos_i.pos - ,inode->i_count)); + ,atomic_read(&inode->i_count))); if (inode == pseudo_root) { printk (KERN_ERR "Umsdos: Oops releasing pseudo_root." " Notify jacques@solucorp.qc.ca\n"); } - if (inode->i_count == 1) + if (atomic_read(&inode->i_count) == 1) inode->u.umsdos_i.i_patched = 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/umsdos/namei.c linux.ac/fs/umsdos/namei.c --- linux.vanilla/fs/umsdos/namei.c Thu May 25 17:37:31 2000 +++ linux.ac/fs/umsdos/namei.c Sat Jun 10 22:18:33 2000 @@ -279,14 +279,14 @@ goto out_remove_dput; inode = fake->d_inode; - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate (dentry, inode); dput(fake); - if (inode->i_count > 1) { + if (atomic_read(&inode->i_count) > 1) { printk(KERN_WARNING "umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n", dentry->d_parent->d_name.name, dentry->d_name.name, - inode->i_ino, inode->i_count); + inode->i_ino, atomic_read(&inode->i_count)); } umsdos_lookup_patch_new(dentry, &info); @@ -809,7 +809,7 @@ inode = temp->d_inode; down(&inode->i_sem); - inode->i_count++; + atomic_inc(&inode->i_count); d_instantiate(dentry, inode); /* N.B. this should have an option to create the EMD ... */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-alpha/mc146818rtc.h linux.ac/include/asm-alpha/mc146818rtc.h --- linux.vanilla/include/asm-alpha/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-alpha/mc146818rtc.h Mon May 29 19:28:27 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_ALPHA_MC146818RTC_H +#define __ASM_ALPHA_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_ALPHA_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-alpha/socket.h linux.ac/include/asm-alpha/socket.h --- linux.vanilla/include/asm-alpha/socket.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-alpha/socket.h Mon May 29 19:30:52 2000 @@ -50,4 +50,19 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 20 #define SO_SECURITY_ENCRYPTION_NETWORK 21 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-alpha/unistd.h linux.ac/include/asm-alpha/unistd.h --- linux.vanilla/include/asm-alpha/unistd.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-alpha/unistd.h Thu Jun 8 14:58:03 2000 @@ -315,7 +315,7 @@ #define __NR_mincore 375 #define __NR_pciconfig_iobase 376 -#if defined(__LIBRARY__) && defined(__GNUC__) +#if defined(__GNUC__) #define _syscall_return(type) \ return (_sc_err ? errno = _sc_ret, _sc_ret = -1L : 0), (type) _sc_ret diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-arc/hardware.h linux.ac/include/asm-arm/arch-arc/hardware.h --- linux.vanilla/include/asm-arm/arch-arc/hardware.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-arc/hardware.h Sun Jun 4 21:13:31 2000 @@ -25,11 +25,6 @@ #include #define HAS_VIDC -/* - * Optional hardware - */ -#define HAS_EXPMASK - /* Hardware addresses of major areas. * *_START is the physical address * *_SIZE is the size of the region @@ -100,7 +95,6 @@ #endif -#ifdef HAS_EXPMASK #ifndef __ASSEMBLY__ #define __EXPMASK(offset) (((volatile unsigned char *)EXPMASK_BASE)[offset]) #else @@ -109,7 +103,5 @@ #define EXPMASK_STATUS __EXPMASK(0x00) #define EXPMASK_ENABLE __EXPMASK(0x04) - -#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-ebsa285/hardware.h linux.ac/include/asm-arm/arch-ebsa285/hardware.h --- linux.vanilla/include/asm-arm/arch-ebsa285/hardware.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-ebsa285/hardware.h Sun Jun 4 21:13:31 2000 @@ -11,7 +11,7 @@ #include #include -#ifdef CONFIG_HOST_FOOTBRIDGE +#ifdef CONFIG_FOOTBRIDGE_HOST /* Virtual Physical Size * 0xff800000 0x40000000 1MB X-Bus * 0xff000000 0x7c000000 1MB PCI I/O space diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-ebsa285/irq.h linux.ac/include/asm-arm/arch-ebsa285/irq.h --- linux.vanilla/include/asm-arm/arch-ebsa285/irq.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-ebsa285/irq.h Mon Jun 5 19:54:47 2000 @@ -10,8 +10,6 @@ * 26-Jan-1999 PJB Don't use IACK on CATS * 16-Mar-1999 RMK Added autodetect of ISA PICs */ -/* no need for config.h - arch/arm/kernel/irq.c does this for us */ -#include #include #include #include @@ -36,29 +34,31 @@ IRQ_MASK_PCI, /* 12 */ IRQ_MASK_SDRAMPARITY, /* 13 */ IRQ_MASK_I2OINPOST, /* 14 */ - IRQ_MASK_PCI_ERR /* 15 */ + IRQ_MASK_PCI_ABORT, /* 15 */ + IRQ_MASK_PCI_SERR, /* 16 */ + IRQ_MASK_DISCARD_TIMER, /* 17 */ + IRQ_MASK_PCI_DPERR, /* 18 */ + IRQ_MASK_PCI_PERR, /* 19 */ }; static int isa_irq = -1; static inline int fixup_irq(unsigned int irq) { -#ifdef CONFIG_HOST_FOOTBRIDGE if (irq == isa_irq) irq = *(unsigned char *)PCIIACK_BASE; -#endif return irq; } static void dc21285_mask_irq(unsigned int irq) { - *CSR_IRQ_DISABLE = dc21285_irq_mask[irq & 15]; + *CSR_IRQ_DISABLE = dc21285_irq_mask[_DC21285_INR(irq)]; } static void dc21285_unmask_irq(unsigned int irq) { - *CSR_IRQ_ENABLE = dc21285_irq_mask[irq & 15]; + *CSR_IRQ_ENABLE = dc21285_irq_mask[_DC21285_INR(irq)]; } static void isa_mask_pic_lo_irq(unsigned int irq) @@ -124,7 +124,7 @@ *CSR_IRQ_DISABLE = -1; *CSR_FIQ_DISABLE = -1; - for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(16); irq++) { + for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) { irq_desc[irq].valid = 1; irq_desc[irq].probe_ok = 1; irq_desc[irq].mask_ack = dc21285_mask_irq; @@ -138,19 +138,21 @@ */ isa_irq = -1; - if (machine_is_ebsa285()) - /* The following is dependent on which slot - * you plug the Southbridge card into. We - * currently assume that you plug it into - * the right-hand most slot. - */ - isa_irq = IRQ_PCI; + if (footbridge_cfn_mode()) { + if (machine_is_ebsa285()) + /* The following is dependent on which slot + * you plug the Southbridge card into. We + * currently assume that you plug it into + * the right-hand most slot. + */ + isa_irq = IRQ_PCI; - if (machine_is_cats()) - isa_irq = IRQ_IN2; + if (machine_is_cats()) + isa_irq = IRQ_IN2; - if (machine_is_netwinder()) - isa_irq = IRQ_IN3; + if (machine_is_netwinder()) + isa_irq = IRQ_IN3; + } if (isa_irq != -1) { /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-ebsa285/irqs.h linux.ac/include/asm-arm/arch-ebsa285/irqs.h --- linux.vanilla/include/asm-arm/arch-ebsa285/irqs.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-ebsa285/irqs.h Sun Jun 4 21:13:31 2000 @@ -9,11 +9,13 @@ * 01-Feb-1999 PJB ISA IRQs start at 0 not 16 */ -#define NR_IRQS 32 +#define NR_IRQS 36 #define NR_DC21285_IRQS 16 #define _ISA_IRQ(x) (0 + (x)) +#define _ISA_INR(x) ((x) - 0) #define _DC21285_IRQ(x) (16 + (x)) +#define _DC21285_INR(x) ((x) - 16) /* * This is a list of all interrupts that the 21285 @@ -34,7 +36,11 @@ #define IRQ_PCI _DC21285_IRQ(12) #define IRQ_SDRAMPARITY _DC21285_IRQ(13) #define IRQ_I2OINPOST _DC21285_IRQ(14) -#define IRQ_PCI_ERR _DC21285_IRQ(15) +#define IRQ_PCI_ABORT _DC21285_IRQ(15) +#define IRQ_PCI_SERR _DC21285_IRQ(16) +#define IRQ_DISCARD_TIMER _DC21285_IRQ(17) +#define IRQ_PCI_DPERR _DC21285_IRQ(18) +#define IRQ_PCI_PERR _DC21285_IRQ(19) #define IRQ_ISA_TIMER _ISA_IRQ(0) #define IRQ_ISA_KEYBOARD _ISA_IRQ(1) @@ -64,7 +70,11 @@ #define IRQ_MASK_PCI (1 << 18) #define IRQ_MASK_SDRAMPARITY (1 << 24) #define IRQ_MASK_I2OINPOST (1 << 25) -#define IRQ_MASK_PCI_ERR ((1 <<23) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) | (1 << 31)) +#define IRQ_MASK_PCI_ABORT ((1 << 29) | (1 << 30)) +#define IRQ_MASK_PCI_SERR (1 << 23) +#define IRQ_MASK_DISCARD_TIMER (1 << 27) +#define IRQ_MASK_PCI_DPERR (1 << 28) +#define IRQ_MASK_PCI_PERR (1 << 31) /* * Netwinder interrupt allocations diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-ebsa285/memory.h linux.ac/include/asm-arm/arch-ebsa285/memory.h --- linux.vanilla/include/asm-arm/arch-ebsa285/memory.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-ebsa285/memory.h Sun Jun 4 21:13:31 2000 @@ -17,7 +17,7 @@ #include -#if defined(CONFIG_HOST_FOOTBRIDGE) +#if defined(CONFIG_FOOTBRIDGE_HOST) /* * Task size: 3GB @@ -36,7 +36,7 @@ #define __bus_to_virt__is_a_macro #define __bus_to_virt(x) ((x) + 0xe0000000) -#elif defined(CONFIG_ADDIN_FOOTBRIDGE) +#elif defined(CONFIG_FOOTBRIDGE_ADDIN) #if defined(CONFIG_ARCH_CO285) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-rpc/hardware.h linux.ac/include/asm-arm/arch-rpc/hardware.h --- linux.vanilla/include/asm-arm/arch-rpc/hardware.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-rpc/hardware.h Sun Jun 4 21:13:31 2000 @@ -93,7 +93,6 @@ #endif -#ifdef HAS_EXPMASK #ifndef __ASSEMBLY__ #define __EXPMASK(offset) (((volatile unsigned char *)EXPMASK_BASE)[offset]) #else @@ -102,7 +101,5 @@ #define EXPMASK_STATUS __EXPMASK(0x00) #define EXPMASK_ENABLE __EXPMASK(0x04) - -#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-sa1100/mmzone.h linux.ac/include/asm-arm/arch-sa1100/mmzone.h --- linux.vanilla/include/asm-arm/arch-sa1100/mmzone.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-arm/arch-sa1100/mmzone.h Sun Jun 4 21:13:31 2000 @@ -0,0 +1,81 @@ +/* + * linux/include/asm-arm/arch-sa1100/mmzone.h + * + * (C) 1999-2000, Nicolas Pitre + * (inspired by Kanoj Sarcar's code) + * + * Because of the wide memory address space between physical RAM banks on the + * SA1100, it's much convenient to use Linux's NUMA support to implement our + * memory map representation. Assuming all memory nodes have equal access + * characteristics, we then have generic discontigous memory support. + * + * Of course, all this isn't mandatory for SA1100 implementations with only + * one used memory bank. For those, simply undefine CONFIG_DISCONTIGMEM. + */ + + +/* + * Currently defined in arch/arm/mm/init.c + */ +extern pg_data_t sa1100_node_data[]; + +/* + * 32MB max in each bank, must fit with __virt_to_phys() & __phys_to_virt() + */ +#define NODE_MAX_MEM_SHIFT 25 +#define NODE_MAX_MEM_SIZE (1<> NODE_MAX_MEM_SHIFT) + +/* + * Return a pointer to the node data for node n. + */ +#define NODE_DATA(nid) (&sa1100_node_data[nid]) + +/* + * NODE_MEM_MAP gives the kaddr for the mem_map of the node. + */ +#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map) + +/* + * Given a mem_map_t, LOCAL_MAP_BASE finds the owning node for the + * physical page and returns the kaddr for the mem_map of that node. + */ +#define LOCAL_MAP_BASE(page) \ + NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(page))) + +/* + * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory + * and returns the the mem_map of that node. + */ +#define ADDR_TO_MAPBASE(kaddr) \ + NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr))) + +/* + * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory + * and returns the kaddr corresponding to first physical page in the + * node's mem_map. + */ +#define LOCAL_BASE_ADDR(kaddr) ((unsigned long)(kaddr) & ~(NODE_MAX_MEM_SIZE-1)) + +/* + * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory + * and returns the index corresponding to the appropriate page in the + * node's mem_map. + */ +#define LOCAL_MAP_NR(kvaddr) \ + (((unsigned long)(kvaddr)-LOCAL_BASE_ADDR((kvaddr))) >> PAGE_SHIFT) + +/* + * With discontigmem, the conceptual mem_map array starts from PAGE_OFFSET. + * Given a kaddr, MAP_NR returns the appropriate global mem_map index so + * it matches the corresponding node's local mem_map. + */ +#define MAP_NR(kaddr) (LOCAL_MAP_NR((kaddr)) + \ + (((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \ + sizeof(mem_map_t))) + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-sa1100/time.h linux.ac/include/asm-arm/arch-sa1100/time.h --- linux.vanilla/include/asm-arm/arch-sa1100/time.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-sa1100/time.h Sun Jun 4 21:13:31 2000 @@ -33,16 +33,22 @@ static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + long flags; int next_match; /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time acuracy. - * Should be IRQ race free. + * IRQs are disabled inside the loop to ensure coherence between + * lost_ticks (updated in do_timer()) and the match reg value, so we + * can use do_gettimeofday() from interrupt handlers. */ do { + do_leds(); + save_flags_cli( flags ); do_timer(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); + restore_flags( flags ); } while( (signed long)(next_match - OSCR) <= 0 ); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/arch-shark/time.h linux.ac/include/asm-arm/arch-shark/time.h --- linux.vanilla/include/asm-arm/arch-shark/time.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/arch-shark/time.h Mon Jun 5 19:54:47 2000 @@ -13,7 +13,6 @@ * Copyright (c) 1996,1997,1998 Russell King. */ -#include #include #include @@ -28,15 +27,7 @@ CMOS_READ(RTC_INTR_FLAGS); -#ifdef CONFIG_LEDS - { - static int count = 50; - if (--count == 0) { - count = 50; - leds_event(led_timer); - } - } -#endif + do_leds(); { #ifdef DIVISOR diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/dec21285.h linux.ac/include/asm-arm/dec21285.h --- linux.vanilla/include/asm-arm/dec21285.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/dec21285.h Mon Jun 5 19:54:47 2000 @@ -14,6 +14,7 @@ #define DC21285_PCI_IO 0x7c000000 #define DC21285_PCI_MEM 0x80000000 +#include #ifndef __ASSEMBLY__ #include #define DC21285_IO(x) ((volatile unsigned long *)(ARMCSR_BASE+(x))) @@ -79,6 +80,18 @@ #define SA110_CNTL_ROMTRISTATETIME(x) ((x)<<24) #define SA110_CNTL_XCSDIR(x) ((x)<<28) #define SA110_CNTL_PCICFN (1 << 31) + +/* + * footbridge_cfn_mode() is used when we want + * to check whether we are the central function + */ +#if defined(CONFIG_FOOTBRIDGE_HOST) && defined(CONFIG_FOOTBRIDGE_ADDIN) +#define footbridge_cfn_mode() (*CSR_SA110_CNTL & SA110_CNTL_PCICFN) +#elif defined(CONFIG_FOOTBRIDGE_HOST) +#define footbridge_cfn_mode() (1) +#else +#define footbridge_cfn_mode() (0) +#endif #define CSR_PCIADDR_EXTN DC21285_IO(0x0140) #define CSR_PREFETCHMEMRANGE DC21285_IO(0x0144) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/mc146818rtc.h linux.ac/include/asm-arm/mc146818rtc.h --- linux.vanilla/include/asm-arm/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-arm/mc146818rtc.h Mon May 29 19:28:27 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* _ASM_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/mmzone.h linux.ac/include/asm-arm/mmzone.h --- linux.vanilla/include/asm-arm/mmzone.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-arm/mmzone.h Sun Jun 4 21:13:31 2000 @@ -0,0 +1,12 @@ +/* + * linux/include/asm-arm/mmzone.h + * + * 1999-12-29 Nicolas Pitre Created + */ + +#ifndef __ASM_MMZONE_H +#define __ASM_MMZONE_H + +#include + +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/page.h linux.ac/include/asm-arm/page.h --- linux.vanilla/include/asm-arm/page.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/page.h Sun Jun 4 21:13:31 2000 @@ -84,11 +84,15 @@ #endif /* !__ASSEMBLY__ */ +#include #include #define __pa(x) __virt_to_phys((unsigned long)(x)) #define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) + +#ifndef CONFIG_DISCONTIGMEM #define MAP_NR(addr) ((__pa(addr) - PHYS_OFFSET) >> PAGE_SHIFT) +#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/pgtable.h linux.ac/include/asm-arm/pgtable.h --- linux.vanilla/include/asm-arm/pgtable.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/pgtable.h Mon Jun 5 19:54:47 2000 @@ -4,6 +4,7 @@ #ifndef _ASMARM_PGTABLE_H #define _ASMARM_PGTABLE_H +#include #include #include #include @@ -77,7 +78,18 @@ #define pte_none(pte) (!pte_val(pte)) #define pte_clear(ptep) set_pte((ptep), __pte(0)) + +#ifndef CONFIG_DISCONTIGMEM #define pte_pagenr(pte) ((unsigned long)(((pte_val(pte) - PHYS_OFFSET) >> PAGE_SHIFT))) +#else +/* + * I'm not happy with this - we needlessly convert a physical address + * to a virtual one, and then immediately back to a physical address, + * which, if __va and __pa are expensive causes twice the expense for + * zero gain. --rmk + */ +#define pte_pagenr(pte) MAP_NR(__va(pte_val(pte))) +#endif #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/proc-armv/assembler.h linux.ac/include/asm-arm/proc-armv/assembler.h --- linux.vanilla/include/asm-arm/proc-armv/assembler.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/proc-armv/assembler.h Sun Jun 4 21:13:31 2000 @@ -1,10 +1,10 @@ /* * linux/asm-arm/proc-armv/assembler.h * - * Copyright (C) 1996 Russell King + * Copyright (C) 1996-2000 Russell King * - * This file contains arm architecture specific defines - * for the different processors + * This file contains ARM processor specifics for + * the ARM6 and better processors. */ #ifndef __ASSEMBLY__ #error "Only include this from assembly code" @@ -19,68 +19,36 @@ /* * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) - * RETINSTR - return instruction (eg, mov pc, lr) */ #ifdef __STDC__ #define LOADREGS(cond, base, reglist...)\ ldm##cond base,reglist - -#define RETINSTR(instr, regs...)\ - instr regs #else #define LOADREGS(cond, base, reglist...)\ ldm/**/cond base,reglist - -#define RETINSTR(instr, regs...)\ - instr regs #endif /* - * No nop required after mode change - */ -#define MODENOP - -/* - * Change to `mode' - */ -#define MODE(savereg,tmpreg,mode) \ - mrs savereg, cpsr; \ - bic tmpreg, savereg, $0x1f; \ - orr tmpreg, tmpreg, $mode; \ - msr cpsr, tmpreg - -/* - * Restore mode + * Build a return instruction for this processor type. */ -#define RESTOREMODE(savereg) \ - msr cpsr, savereg - -/* - * save interrupt state (uses stack) - */ -#define SAVEIRQS(tmpreg)\ - mrs tmpreg, cpsr; \ - str tmpreg, [sp, $-4]! - -/* - * restore interrupt state (uses stack) - */ -#define RESTOREIRQS(tmpreg)\ - ldr tmpreg, [sp], $4; \ - msr cpsr, tmpreg - -/* - * disable IRQs - */ -#define DISABLEIRQS(tmpreg)\ - mrs tmpreg , cpsr; \ - orr tmpreg , tmpreg , $I_BIT; \ - msr cpsr, tmpreg +#define RETINSTR(instr, regs...)\ + instr regs /* - * enable IRQs - */ -#define ENABLEIRQS(tmpreg)\ - mrs tmpreg , cpsr; \ - bic tmpreg , tmpreg , $I_BIT; \ - msr cpsr, tmpreg + * Save the current IRQ state and disable IRQs + * Note that this macro assumes FIQs are enabled, and + * that the processor is in SVC mode. + */ + .macro save_and_disable_irqs, oldcpsr, temp + mrs \oldcpsr, cpsr + mov \temp, #I_BIT | MODE_SVC + msr cpsr_c, \temp + .endm + +/* + * Restore interrupt state previously stored in + * a register + */ + .macro restore_irqs, oldcpsr + msr cpsr_c, \oldcpsr + .endm diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/proc-armv/locks.h linux.ac/include/asm-arm/proc-armv/locks.h --- linux.vanilla/include/asm-arm/proc-armv/locks.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/proc-armv/locks.h Sun Jun 4 21:13:31 2000 @@ -72,7 +72,8 @@ * BIAS once per CPU will result in the long remaining * negative. */ -#define RW_LOCK_BIAS 0x01000000 +#define RW_LOCK_BIAS 0x01000000 +#define RW_LOCK_BIAS_STR "0x01000000" #define __down_op_write(ptr,fail) \ ({ \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/setup.h linux.ac/include/asm-arm/setup.h --- linux.vanilla/include/asm-arm/setup.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/setup.h Sun Jun 4 21:13:31 2000 @@ -74,6 +74,7 @@ struct { unsigned long start; unsigned long size; + int node; } bank[NR_BANKS]; }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/socket.h linux.ac/include/asm-arm/socket.h --- linux.vanilla/include/asm-arm/socket.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/socket.h Mon May 29 19:30:52 2000 @@ -41,4 +41,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/system.h linux.ac/include/asm-arm/system.h --- linux.vanilla/include/asm-arm/system.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/system.h Sun Jun 4 21:13:31 2000 @@ -280,6 +280,20 @@ # define machine_is_lart() (0) #endif +#ifdef CONFIG_SA1100_GRAPHICSCLIENT +# ifdef machine_arch_type +# undef machine_arch_type +# define machine_arch_type __machine_arch_type +# else +# define machine_arch_type MACH_TYPE_GRAPHICSCLIENT +# endif +# define machine_is_grpahicsclient() \ + (machine_arch_type == MACH_TYPE_GRAPHICSCLIENT) +#else +# define machine_is_graphicsclient() \ + (0) +#endif + /* * The following are currently unregistered */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-arm/unistd.h linux.ac/include/asm-arm/unistd.h --- linux.vanilla/include/asm-arm/unistd.h Thu May 25 17:37:36 2000 +++ linux.ac/include/asm-arm/unistd.h Sun Jun 4 21:13:31 2000 @@ -116,7 +116,7 @@ #define __NR_lstat (__NR_SYSCALL_BASE+107) #define __NR_fstat (__NR_SYSCALL_BASE+108) -#define __NR_iopl (__NR_SYSCALL_BASE+110) + #define __NR_vhangup (__NR_SYSCALL_BASE+111) #define __NR_idle (__NR_SYSCALL_BASE+112) #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/bugs.h linux.ac/include/asm-i386/bugs.h --- linux.vanilla/include/asm-i386/bugs.h Thu May 25 17:37:34 2000 +++ linux.ac/include/asm-i386/bugs.h Sat Jun 10 22:25:00 2000 @@ -8,6 +8,9 @@ * * - Channing Corn (tests & fixes), * - Andrew D. Balsa (code cleanup). + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 */ /* @@ -46,7 +49,7 @@ __setup("no387", no_387); -static char __initdata fpu_error = 0; +static char fpu_error __initdata = 0; static void __init copro_timeout(void) { @@ -59,8 +62,13 @@ outb_p(0,0xf0); } -static double __initdata x = 4195835.0; -static double __initdata y = 3145727.0; +static double x __initdata = 4195835.0; +static double y __initdata = 3145727.0; + +#ifdef CONFIG_X86_XMM +static float zero[4] __initdata = { 0.0, 0.0, 0.0, 0.0 }; +static float one[4] __initdata = { 1.0, 1.0, 1.0, 1.0 }; +#endif static void __init check_fpu(void) { @@ -139,6 +147,37 @@ printk("OK, FPU using exception 16 error reporting.\n"); else printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n"); + +#ifdef CONFIG_X86_FXSR + /* + * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. + */ + if (offsetof(struct task_struct, thread.i387.hard.fxsr_space[0]) & 15) + panic("Kernel compiled for PII/PIII+ with FXSR, data not 16-byte aligned!"); + + if (cpu_has_fxsr) { + printk(KERN_INFO "Enabling fast FPU save and restore... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } +#endif +#ifdef CONFIG_X86_XMM + if (cpu_has_xmm) { + printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + + /* Check if exception 19 works okay. */ + set_fpu_mxcsr(XMM_UNMASKED_MXCSR); + printk(KERN_INFO "Checking SIMD FPU exceptions... "); + __asm__("movups %0,%%xmm0\n\t" + "movups %1,%%xmm1\n\t" + "divps %%xmm0,%%xmm1\n\t" + : : "m" (*&zero), "m" (*&one)); + printk("OK, SIMD FPU using exception 19 error reporting.\n"); + set_fpu_mxcsr(XMM_DEFAULT_MXCSR); + } +#endif } static void __init check_hlt(void) @@ -423,6 +462,14 @@ && boot_cpu_data.x86_model == 2 && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11)) panic("Kernel compiled for PPro+, assumes a local APIC without the read-before-write bug!"); +#endif + +/* + * If we configured ourselves for FXSR, we'd better have it. + */ +#ifdef CONFIG_X86_FXSR + if (!cpu_has_fxsr) + panic("Kernel compiled for PII/PIII+, requires FXSR feature!"); #endif } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/mc146818rtc.h linux.ac/include/asm-i386/mc146818rtc.h --- linux.vanilla/include/asm-i386/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-i386/mc146818rtc.h Sat Jun 10 22:26:03 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* _ASM_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/processor.h linux.ac/include/asm-i386/processor.h --- linux.vanilla/include/asm-i386/processor.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-i386/processor.h Sat Jun 10 22:25:00 2000 @@ -2,6 +2,9 @@ * include/asm-i386/processor.h * * Copyright (C) 1994 Linus Torvalds + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 */ #ifndef __ASM_I386_PROCESSOR_H @@ -90,17 +93,15 @@ #define X86_FEATURE_20 0x00100000 #define X86_FEATURE_21 0x00200000 #define X86_FEATURE_22 0x00400000 -#define X86_FEATURE_MMX 0x00800000 /* multimedia extensions */ +#define X86_FEATURE_MMX 0x00800000 /* Multimedia Extensions */ #define X86_FEATURE_FXSR 0x01000000 /* FXSAVE and FXRSTOR instructions (fast save and restore of FPU context), and CR4.OSFXSR (OS uses these instructions) available */ -#define X86_FEATURE_XMM 0x02000000 /* Intel MMX2 instruction set */ +#define X86_FEATURE_XMM 0x02000000 /* Streaming SIMD Extensions */ #define X86_FEATURE_26 0x04000000 #define X86_FEATURE_27 0x08000000 #define X86_FEATURE_28 0x10000000 #define X86_FEATURE_29 0x20000000 #define X86_FEATURE_30 0x40000000 #define X86_FEATURE_AMD3D 0x80000000 -#define X86_CR4_OSFXSR 0x0200 /* fast FPU save/restore */ -#define X86_CR4_OSXMMEXCPT 0x0400 /* KNI (MMX2) unmasked exception 16 */ extern struct cpuinfo_x86 boot_cpu_data; extern struct tss_struct init_tss[NR_CPUS]; @@ -125,6 +126,10 @@ (boot_cpu_data.x86_capability & X86_FEATURE_DE) #define cpu_has_vme \ (boot_cpu_data.x86_capability & X86_FEATURE_VME) +#define cpu_has_fxsr \ + (boot_cpu_data.x86_capability & X86_FEATURE_FXSR) +#define cpu_has_xmm \ + (boot_cpu_data.x86_capability & X86_FEATURE_XMM) extern char ignore_irq13; @@ -150,15 +155,17 @@ /* * Intel CPU features in CR4 */ -#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ -#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ -#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ -#define X86_CR4_DE 0x0008 /* enable debugging extensions */ -#define X86_CR4_PSE 0x0010 /* enable page size extensions */ -#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ -#define X86_CR4_MCE 0x0040 /* Machine check enable */ -#define X86_CR4_PGE 0x0080 /* enable global pages */ -#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ +#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define X86_CR4_DE 0x0008 /* enable debugging extensions */ +#define X86_CR4_PSE 0x0010 /* enable page size extensions */ +#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ +#define X86_CR4_MCE 0x0040 /* Machine check enable */ +#define X86_CR4_PGE 0x0080 /* enable global pages */ +#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ +#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ /* * Save the cr4 feature set we're using (ie @@ -244,21 +251,7 @@ #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define INVALID_IO_BITMAP_OFFSET 0x8000 -#ifndef CONFIG_X86_FX - -#define i387_save_hard(x) \ - __asm__("fnsave %0\n\tfwait": :"m" (x)) -#define i387_restore_hard(x) \ - __asm__("frstor %0": :"m" (x)) - -#define i387_hard_to_user(uaddr, x) \ - __copy_to_user((uaddr), (x), sizeof(struct i387_hard_struct)) -#define i387_user_to_hard(x, uaddr) \ - __copy_from_user((x), (uaddr), sizeof(struct i387_hard_struct)) - -#define i387_set_cwd(x,v) do { (x).cwd = 0xffff0000 | (v); } while (0) -#define i387_set_swd(x,v) do { (x).swd = 0xffff0000 | (v); } while (0) -#define i387_set_twd(x,v) do { (x).twd = 0xffff0000 | (v); } while (0) +#ifndef CONFIG_X86_FXSR struct i387_hard_struct { long cwd; @@ -274,65 +267,25 @@ #else -/* - * has to be 128-bit aligned - */ struct i387_hard_struct { - unsigned short cwd; - unsigned short swd; - unsigned short twd; - unsigned short fopcode; - unsigned int fip; - unsigned short fcs; - unsigned short __reserved_01; - unsigned int fdp; - unsigned short fds; - unsigned short __reserved_02; - unsigned int mxcsr; - unsigned int __reserved_03; - unsigned int st_space[32]; /* 8*16 bytes for each FP/MMX-reg = 128 bytes */ - unsigned int xmm_space[22*4]; /* 22 cachelines for MMX2 registers */ - unsigned long status; + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long status; /* software status information */ + long fxsr_space[6]; /* FXSR FPU environment must not be used */ + long mxcsr; + long reserved; + long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long padding[56]; } __attribute__ ((aligned (16))); -/* - * tag word conversion (thanks to Gabriel Paubert for noticing the - * subtle format difference and implementing these functions) - * - * there are several erratas wrt. the tag word in the i387, thus - * any software relying on it's value is questionable, but we - * definitely want to be as close as possible. - */ -static inline unsigned short fputag_KNIto387(unsigned char tb) { - unsigned short tw = tb; - tw = ((tw<<4) | tw) &0x0f0f; /* zzzz7654zzzz3210 */ - tw = ((tw<<2) | tw) &0x3333; /* zz76zz54zz32zz10 */ - tw = ((tw<<1) | tw) &0x5555; /* z7z6z5z4z3z2z1z0 */ - return ~(tw*3); -} - -static inline unsigned char fputag_387toKNI(unsigned short tw) { - tw = ~tw; - tw = (tw | (tw>>1)) & 0x5555; /* z7z6z5z4z3z2z1z0 */ - tw = (tw | (tw>>1)) & 0x3333; /* zz76zz54zz32zz10 */ - tw = (tw | (tw>>3)) & 0x0f0f; /* zzzz7654zzzz3210 */ - return (tw|(tw>>4)) & 0x00ff; /* zzzzzzzz76543210 */ -} - -#define i387_set_cwd(x,v) do { (x).cwd = (short)(v); } while (0) -#define i387_set_swd(x,v) do { (x).swd = (short)(v); } while (0) -#define i387_set_twd(x,v) do { (x).twd = fputag_387toKNI(v); } while (0) - -#define i387_save_hard(x) \ - { __asm__ __volatile__(".byte 0x0f, 0xae, 0x06": :"S" (&(x))); } while (0) - -#define i387_restore_hard(x) \ -do { __asm__ __volatile__(".byte 0x0f, 0xae, 0x4f, 0x00": :"D" (&(x))); } while(0) - -extern int i387_hard_to_user ( struct _fpstate * user, - struct i387_hard_struct * hard); -extern int i387_user_to_hard (struct i387_hard_struct * hard, - struct _fpstate * user); +#define X86_FXSR_MAGIC 0x0000 +#define X86_FXSR_SIZE 512 #endif struct i387_soft_struct { @@ -469,12 +422,48 @@ /* * FPU lazy state save handling.. */ +#ifndef CONFIG_X86_FXSR + +#define save_fpu(tsk) do { \ + asm volatile("fnsave %0 ; fwait" \ + : "=m" (tsk->thread.i387.hard)); \ + tsk->flags &= ~PF_USEDFPU; \ + stts(); \ +} while (0) + +#define save_init_fpu(tsk) save_fpu(tsk) + +#define restore_fpu(tsk) do { \ + asm volatile("frstor %0" \ + : : "m" (tsk->thread.i387.hard)); \ +} while (0) + +#else /* CONFIG_X86_FXSR */ + #define save_fpu(tsk) do { \ - i387_save_hard(tsk->thread.i387); \ + asm volatile("fnstenv %0 ; fxsave %1 ; fwait" \ + : "=m" (tsk->thread.i387.hard), \ + "=m" (tsk->thread.i387.hard.fxsr_space[0])); \ + tsk->flags &= ~PF_USEDFPU; \ + stts(); \ +} while (0) + +#define save_init_fpu(tsk) do { \ + asm volatile("fnstenv %0 ; fxsave %1 ; fnclex" \ + : "=m" (tsk->thread.i387.hard), \ + "=m" (tsk->thread.i387.hard.fxsr_space[0])); \ tsk->flags &= ~PF_USEDFPU; \ stts(); \ } while (0) +#define restore_fpu(tsk) do { \ + asm volatile("fxrstor %0 ; fldenv %1" \ + : : "m" (tsk->thread.i387.hard.fxsr_space[0]), \ + "m" (tsk->thread.i387.hard)); \ +} while (0) + +#endif /* CONFIG_X86_FXSR */ + #define unlazy_fpu(tsk) do { \ if (tsk->flags & PF_USEDFPU) \ save_fpu(tsk); \ @@ -487,6 +476,18 @@ } \ } while (0) +#ifdef CONFIG_X86_XMM +#define XMM_DEFAULT_MXCSR 0x1f80 +#define XMM_UNMASKED_MXCSR 0x0000 + +#define set_fpu_mxcsr(val) do { \ + if (cpu_has_xmm) { \ + unsigned long __mxcsr = ((unsigned long)(val) & 0xffff); \ + asm volatile("ldmxcsr %0" : : "m" (__mxcsr)); \ + } \ +} while (0) +#endif + /* * Return saved PC of a blocked thread. */ @@ -518,5 +519,7 @@ unsigned int reserved[5]; unsigned int bits[500]; }; + +#define MICROCODE_IOCFREE _IO('6',0) /* because it is for P6 */ #endif /* __ASM_I386_PROCESSOR_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/ptrace.h linux.ac/include/asm-i386/ptrace.h --- linux.vanilla/include/asm-i386/ptrace.h Thu May 25 17:37:34 2000 +++ linux.ac/include/asm-i386/ptrace.h Sat Jun 10 21:56:02 2000 @@ -46,6 +46,8 @@ #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 #define PTRACE_SETFPREGS 15 +#define PTRACE_GETXFPREGS 25 +#define PTRACE_SETXFPREGS 26 #ifdef __KERNEL__ #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/semaphore.h linux.ac/include/asm-i386/semaphore.h --- linux.vanilla/include/asm-i386/semaphore.h Thu May 25 17:37:34 2000 +++ linux.ac/include/asm-i386/semaphore.h Sat Jun 10 22:25:00 2000 @@ -3,6 +3,8 @@ #include +#ifdef __KERNEL__ + /* * SMP- and interrupt-safe semaphores.. * @@ -372,4 +374,5 @@ __up_write(sem); } +#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/sigcontext.h linux.ac/include/asm-i386/sigcontext.h --- linux.vanilla/include/asm-i386/sigcontext.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-i386/sigcontext.h Sat Jun 10 21:56:02 2000 @@ -1,34 +1,55 @@ #ifndef _ASMi386_SIGCONTEXT_H #define _ASMi386_SIGCONTEXT_H -#include /* * As documented in the iBCS2 standard.. * - * The first part of "struct _fpstate" is just the - * normal i387 hardware setup, the extra "status" - * word is used to save the coprocessor status word - * before entering the handler. + * The first part of "struct _fpstate" is just the normal i387 + * hardware setup, the extra "status" word is used to save the + * coprocessor status word before entering the handler. + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 + * + * The FPU state data structure has had to grow to accomodate the + * extended FPU state required by the Streaming SIMD Extensions. + * There is no documented standard to accomplish this at the moment. */ struct _fpreg { unsigned short significand[4]; unsigned short exponent; }; +struct _fpxreg { + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg { + unsigned long element[4]; +}; + struct _fpstate { - unsigned long cw, - sw, - tag, - ipoff, - cssel, - dataoff, - datasel; + /* Regular FPU environment */ + unsigned long cw; + unsigned long sw; + unsigned long tag; + unsigned long ipoff; + unsigned long cssel; + unsigned long dataoff; + unsigned long datasel; struct _fpreg _st[8]; - unsigned long status; -#ifdef CONFIG_X86_FX + unsigned short status; + unsigned short magic; /* 0xffff = regular FPU data only */ + + /* FXSR FPU environment */ + unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */ unsigned long mxcsr; - unsigned long _xmm[4*22]; -#endif + unsigned long reserved; + struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ + struct _xmmreg _xmm[8]; + unsigned long padding[56]; }; struct sigcontext { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/socket.h linux.ac/include/asm-i386/socket.h --- linux.vanilla/include/asm-i386/socket.h Thu May 25 17:37:34 2000 +++ linux.ac/include/asm-i386/socket.h Mon May 29 19:30:52 2000 @@ -41,4 +41,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-i386/user.h linux.ac/include/asm-i386/user.h --- linux.vanilla/include/asm-i386/user.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-i386/user.h Sat Jun 10 22:30:19 2000 @@ -30,15 +30,44 @@ The minimum core file size is 3 pages, or 12288 bytes. */ +/* + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 + * + * Provide support for the GDB 5.0 PTRACE_*XFPREGS requests for interacting + * with the FXSR-format floating point environment. Floating point data + * can be accessed in the regular FSAVE format in the usual manner, and the + * XMM register/control data can be accessed via the new ptrace requests. + * Note that the floating point environment contained in the FXSR format + * is ignored and any changes to these fields will be lost. + */ + struct user_i387_struct { long cwd; long swd; long twd; long fip; long fcs; - long fdp; - long fds; + long foo; + long fos; long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ +}; + +struct user_xfpregs_struct { + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long __reserved_00; + long fxsr_space[6]; /* FXSR FPU environment must not be used */ + long mxcsr; + long __reserved_01; + long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long __reserved_02[56]; }; /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ia64/socket.h linux.ac/include/asm-ia64/socket.h --- linux.vanilla/include/asm-ia64/socket.h Thu May 25 17:37:37 2000 +++ linux.ac/include/asm-ia64/socket.h Mon May 29 19:30:52 2000 @@ -50,4 +50,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_IA64_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-m68k/socket.h linux.ac/include/asm-m68k/socket.h --- linux.vanilla/include/asm-m68k/socket.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-m68k/socket.h Mon May 29 19:30:52 2000 @@ -41,4 +41,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-mips/socket.h linux.ac/include/asm-mips/socket.h --- linux.vanilla/include/asm-mips/socket.h Thu May 25 17:37:34 2000 +++ linux.ac/include/asm-mips/socket.h Mon May 29 19:30:52 2000 @@ -60,19 +60,19 @@ #define SO_PEERNAME 28 -/* Types of sockets. */ -#define SOCK_DGRAM 1 /* Connectionless, unreliable datagrams - of fixed maximum length. */ -#define SOCK_STREAM 2 /* Sequenced, reliable, connection-based - byte streams. */ -#define SOCK_RAW 3 /* Raw protocol interface. */ -#define SOCK_RDM 4 /* Reliably-delivered messages. */ -#define SOCK_SEQPACKET 5 /* Sequenced, reliable, connection-based, - datagrams of fixed maximum length. */ -#define SOCK_PACKET 10 /* Linux specific way of getting packets at - the dev level. For writing rarp and - other similar things on the user level. */ - -#endif /* __KERNEL__ */ +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_DGRAM 1 /* datagram (conn.less) socket */ +#define SOCK_STREAM 2 /* stream (connection) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-mips64/socket.h linux.ac/include/asm-mips64/socket.h --- linux.vanilla/include/asm-mips64/socket.h Thu May 25 17:37:37 2000 +++ linux.ac/include/asm-mips64/socket.h Mon May 29 19:30:52 2000 @@ -61,22 +61,21 @@ #define SO_ATTACH_FILTER 26 #define SO_DETACH_FILTER 27 -#ifdef __KERNEL__ - #define SO_PEERNAME 28 -/* Types of sockets. */ -#define SOCK_DGRAM 1 /* Connectionless, unreliable datagrams - of fixed maximum length. */ -#define SOCK_STREAM 2 /* Sequenced, reliable, connection-based - byte streams. */ -#define SOCK_RAW 3 /* Raw protocol interface. */ -#define SOCK_RDM 4 /* Reliably-delivered messages. */ -#define SOCK_SEQPACKET 5 /* Sequenced, reliable, connection-based, - datagrams of fixed maximum length. */ -#define SOCK_PACKET 10 /* Linux specific way of getting packets at - the dev level. For writing rarp and - other similar things on the user level. */ -#endif /* __KERNEL__ */ +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_DGRAM 1 /* datagram (conn.less) socket */ +#define SOCK_STREAM 2 /* stream (connection) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/bitops.h linux.ac/include/asm-ppc/bitops.h --- linux.vanilla/include/asm-ppc/bitops.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/bitops.h Sat Jun 10 21:48:24 2000 @@ -29,67 +29,121 @@ #define SMP_MB #endif /* CONFIG_SMP */ +#define __INLINE_BITOPS 1 + +#if __INLINE_BITOPS /* - * These are if'd out here because using : "cc" as a constraint - * results in errors from gcc. -- Cort - * Besides, they need to be changed so we have both set_bit - * and test_and_set_bit, etc. + * These used to be if'd out here because using : "cc" as a constraint + * resulted in errors from egcs. Things may be OK with gcc-2.95. */ -#if 0 -extern __inline__ int set_bit(int nr, void * addr) +extern __inline__ void set_bit(int nr, volatile void * addr) { - unsigned long old, t; + unsigned long old; unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - __asm__ __volatile__( - "1:lwarx %0,0,%3 \n\t" - "or %1,%0,%2 \n\t" - "stwcx. %1,0,%3 \n\t" - "bne 1b \n\t" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) - /*: "cc" */); - - return (old & mask) != 0; + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + or %0,%0,%2 + stwcx. %0,0,%3 + bne 1b" + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc" ); } -extern __inline__ unsigned long clear_bit(unsigned long nr, void *addr) +extern __inline__ void clear_bit(int nr, volatile void *addr) { - unsigned long old, t; + unsigned long old; unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - __asm__ __volatile__("\n\ + __asm__ __volatile__(SMP_WMB "\ 1: lwarx %0,0,%3 - andc %1,%0,%2 - stwcx. %1,0,%3 + andc %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) - /*: "cc"*/); - - return (old & mask) != 0; + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); } -extern __inline__ unsigned long change_bit(unsigned long nr, void *addr) +extern __inline__ void change_bit(int nr, volatile void *addr) { - unsigned long old, t; + unsigned long old; unsigned long mask = 1 << (nr & 0x1f); unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - __asm__ __volatile__("\n\ + __asm__ __volatile__(SMP_WMB "\ 1: lwarx %0,0,%3 - xor %1,%0,%2 - stwcx. %1,0,%3 + xor %0,%0,%2 + stwcx. %0,0,%3 + bne 1b" + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); +} + +extern __inline__ int test_and_set_bit(int nr, volatile void *addr) +{ + unsigned int old, t; + unsigned int mask = 1 << (nr & 0x1f); + volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + or %1,%0,%3 + stwcx. %1,0,%4 bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) - /*: "cc"*/); + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); return (old & mask) != 0; } -#endif + +extern __inline__ int test_and_clear_bit(int nr, volatile void *addr) +{ + unsigned int old, t; + unsigned int mask = 1 << (nr & 0x1f); + volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + andc %1,%0,%3 + stwcx. %1,0,%4 + bne 1b" + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); + + return (old & mask) != 0; +} + +extern __inline__ int test_and_change_bit(int nr, volatile void *addr) +{ + unsigned int old, t; + unsigned int mask = 1 << (nr & 0x1f); + volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + xor %1,%0,%3 + stwcx. %1,0,%4 + bne 1b" + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); + + return (old & mask) != 0; +} +#endif /* __INLINE_BITOPS */ extern __inline__ int test_bit(int nr, __const__ volatile void *addr) { @@ -277,4 +331,3 @@ #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) #endif /* _PPC_BITOPS_H */ - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/byteorder.h linux.ac/include/asm-ppc/byteorder.h --- linux.vanilla/include/asm-ppc/byteorder.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/byteorder.h Sat Jun 10 21:46:58 2000 @@ -9,7 +9,7 @@ #ifdef __GNUC__ -extern __inline__ unsigned ld_le16(volatile unsigned short *addr) +extern __inline__ unsigned ld_le16(const volatile unsigned short *addr) { unsigned val; @@ -17,12 +17,12 @@ return val; } -extern __inline__ void st_le16(volatile unsigned short *addr, unsigned val) +extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val) { __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); } -extern __inline__ unsigned ld_le32(volatile unsigned *addr) +extern __inline__ unsigned ld_le32(const volatile unsigned *addr) { unsigned val; @@ -30,7 +30,7 @@ return val; } -extern __inline__ void st_le32(volatile unsigned *addr, unsigned val) +extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val) { __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/cache.h linux.ac/include/asm-ppc/cache.h --- linux.vanilla/include/asm-ppc/cache.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/cache.h Sat Jun 10 21:48:24 2000 @@ -9,7 +9,11 @@ /* bytes per L1 cache line */ #if !defined(CONFIG_8xx) || defined(CONFIG_8260) +#if defined(CONFIG_PPC64BRIDGE) +#define L1_CACHE_BYTES 128 +#else #define L1_CACHE_BYTES 32 +#endif /* PPC64 */ #else #define L1_CACHE_BYTES 16 #endif /* !8xx || 8260 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/est8260.h linux.ac/include/asm-ppc/est8260.h --- linux.vanilla/include/asm-ppc/est8260.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/est8260.h Sun Jun 4 21:10:57 2000 @@ -1,4 +1,10 @@ +/* Board information for the EST8260, which should be generic for + * all 8260 boards. The IMMR is now given to us so the hard define + * will soon be removed. All of the clock values are computed from + * the configuration SCMR and the Power-On-Reset word. + */ + #define IMAP_ADDR ((uint)0xf0000000) @@ -12,8 +18,10 @@ unsigned int bi_busfreq; /* Bus Freq, in MHz */ unsigned int bi_cpmfreq; /* CPM Freq, in MHz */ unsigned int bi_brgfreq; /* BRG Freq, in MHz */ + unsigned int bi_vco; /* VCO Out from PLL */ + unsigned int bi_baudrate; /* Default console baud rate */ + unsigned int bi_immr; /* IMMR when called from boot rom */ unsigned char bi_enetaddr[6]; - unsigned int bi_baudrate; } bd_t; extern bd_t m8xx_board_info; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/io.h linux.ac/include/asm-ppc/io.h --- linux.vanilla/include/asm-ppc/io.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/io.h Sat Jun 10 21:48:24 2000 @@ -161,6 +161,20 @@ } /* + * The PCI bus bridge can translate addresses issued by the processor(s) + * into a different address on the PCI bus. On 32-bit cpus, we assume + * this mapping is 1-1, but on 64-bit systems it often isn't. + */ +#ifndef CONFIG_PPC64BRIDGE +#define phys_to_bus(x) (x) +#define bus_to_phys(x) (x) + +#else +extern unsigned long phys_to_bus(unsigned long pa); +extern unsigned long bus_to_phys(unsigned int ba, int busnr); +#endif /* CONFIG_PPC64BRIDGE */ + +/* * Change virtual addresses to physical addresses and vv, for * addresses in the area where the kernel has the RAM mapped. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/mc146818rtc.h linux.ac/include/asm-ppc/mc146818rtc.h --- linux.vanilla/include/asm-ppc/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-ppc/mc146818rtc.h Mon May 29 19:28:27 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_PPC_MC146818RTC_H +#define __ASM_PPC_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_PPC_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/mmu.h linux.ac/include/asm-ppc/mmu.h --- linux.vanilla/include/asm-ppc/mmu.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/mmu.h Sat Jun 10 21:48:24 2000 @@ -10,20 +10,20 @@ #ifndef __ASSEMBLY__ /* Hardware Page Table Entry */ typedef struct _PTE { -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE unsigned long long vsid:52; unsigned long api:5; unsigned long :5; unsigned long h:1; unsigned long v:1; unsigned long long rpn:52; -#else /* CONFIG_PPC64 */ +#else /* CONFIG_PPC64BRIDGE */ unsigned long v:1; /* Entry is valid */ unsigned long vsid:24; /* Virtual segment identifier */ unsigned long h:1; /* Hash algorithm indicator */ unsigned long api:6; /* Abbreviated page index */ unsigned long rpn:20; /* Real (physical) page number */ -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ unsigned long :3; /* Unused */ unsigned long r:1; /* Referenced */ unsigned long c:1; /* Changed */ @@ -64,11 +64,11 @@ } P601_BATU; typedef struct _BATU { /* Upper part of BAT (all except 601) */ -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE unsigned long long bepi:47; -#else /* CONFIG_PPC64 */ +#else /* CONFIG_PPC64BRIDGE */ unsigned long bepi:15; /* Effective page index (virtual address) */ -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ unsigned long :4; /* Unused */ unsigned long bl:11; /* Block size mask */ unsigned long vs:1; /* Supervisor valid */ @@ -83,11 +83,11 @@ } P601_BATL; typedef struct _BATL { /* Lower part of BAT (all except 601) */ -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE unsigned long long brpn:47; -#else /* CONFIG_PPC64 */ +#else /* CONFIG_PPC64BRIDGE */ unsigned long brpn:15; /* Real page index (physical address) */ -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ unsigned long :10; /* Unused */ unsigned long w:1; /* Write-thru cache */ unsigned long i:1; /* Cache inhibit */ @@ -135,12 +135,7 @@ pte **pmap; /* Two-level page-map structure */ } MMU_context; -/* invalidate a TLB entry */ -extern inline void _tlbie(unsigned long va) -{ - asm volatile ("tlbie %0" : : "r"(va)); -} - +extern void _tlbie(unsigned long va); /* invalidate a TLB entry */ extern void _tlbia(void); /* invalidate all TLB entries */ #endif /* __ASSEMBLY__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/pgtable.h linux.ac/include/asm-ppc/pgtable.h --- linux.vanilla/include/asm-ppc/pgtable.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/pgtable.h Sun Jun 4 21:10:57 2000 @@ -72,7 +72,7 @@ #define flush_page_to_ram(page) __flush_page_to_ram(page_address(page)) extern unsigned long va_to_phys(unsigned long address); -extern pte_t *va_to_pte(struct task_struct *tsk, unsigned long address); +extern pte_t *va_to_pte(struct mm_struct *mm, unsigned long address); extern unsigned long ioremap_bot, ioremap_base; #endif /* __ASSEMBLY__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/posix_types.h linux.ac/include/asm-ppc/posix_types.h --- linux.vanilla/include/asm-ppc/posix_types.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/posix_types.h Sat Jun 10 21:48:24 2000 @@ -1,8 +1,6 @@ #ifndef _PPC_POSIX_TYPES_H #define _PPC_POSIX_TYPES_H -#include /* for CONFIG_PPC64 */ - /* * This file is generally used by user-level software, so you need to * be a little careful about namespace pollution etc. Also, we cannot @@ -17,17 +15,8 @@ typedef int __kernel_pid_t; typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; - -/* Grrr... gcc thinks size_t is unsigned int, so we either - have to have this nonsense or use -fno-builtin. - paulus */ -#ifdef CONFIG_PPC64 -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -#else typedef unsigned int __kernel_size_t; typedef int __kernel_ssize_t; -#endif /* CONFIG_PPC64 */ - typedef long __kernel_ptrdiff_t; typedef long __kernel_time_t; typedef long __kernel_suseconds_t; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/processor.h linux.ac/include/asm-ppc/processor.h --- linux.vanilla/include/asm-ppc/processor.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/processor.h Sat Jun 10 21:48:24 2000 @@ -15,10 +15,10 @@ /* Machine State Register (MSR) Fields */ -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE #define MSR_SF (1<<63) #define MSR_ISF (1<<61) -#endif /* CONFIG_PPC64 */ +#endif /* CONFIG_PPC64BRIDGE */ #define MSR_VEC (1<<25) /* Enable AltiVec */ #define MSR_POW (1<<18) /* Enable Power Management */ #define MSR_WE (1<<18) /* Wait State Enable */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/prom.h linux.ac/include/asm-ppc/prom.h --- linux.vanilla/include/asm-ppc/prom.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/prom.h Sat Jun 10 21:48:24 2000 @@ -4,6 +4,8 @@ * * Copyright (C) 1996 Paul Mackerras. */ +#ifndef _PPC_PROM_H +#define _PPC_PROM_H typedef void *phandle; typedef void *ihandle; @@ -86,3 +88,5 @@ extern void prom_drawstring(const char *c); extern void prom_drawhex(unsigned long v); extern void prom_drawchar(char c); + +#endif /* _PPC_PROM_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/ptrace.h linux.ac/include/asm-ppc/ptrace.h --- linux.vanilla/include/asm-ppc/ptrace.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/ptrace.h Sat Jun 10 21:48:24 2000 @@ -20,7 +20,7 @@ #include #ifndef __ASSEMBLY__ -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC64BRIDGE #define PPC_REG unsigned long /*long*/ #else #define PPC_REG unsigned long diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/rpxclassic.h linux.ac/include/asm-ppc/rpxclassic.h --- linux.vanilla/include/asm-ppc/rpxclassic.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/rpxclassic.h Mon Jun 5 19:54:47 2000 @@ -8,6 +8,8 @@ #ifndef __MACH_RPX_DEFS #define __MACH_RPX_DEFS +#include + /* A Board Information structure that is given to a program when * prom starts it up. */ @@ -26,8 +28,6 @@ * We just map a few things we need. The CSR is actually 4 byte-wide * registers that can be accessed as 8-, 16-, or 32-bit values. */ -#define PCMCIA_MEM_ADDR ((uint)0x04000000) -#define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) #define PCI_ISA_IO_ADDR ((unsigned)0x80000000) #define PCI_ISA_IO_SIZE ((uint)(512 * 1024 * 1024)) #define PCI_ISA_MEM_ADDR ((unsigned)0xc0000000) @@ -38,6 +38,12 @@ #define IMAP_SIZE ((uint)(64 * 1024)) #define PCI_CSR_ADDR ((uint)0x80000000) #define PCI_CSR_SIZE ((uint)(64 * 1024)) +#define PCMCIA_MEM_ADDR ((uint)0xe0000000) +#define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) +#define PCMCIA_IO_ADDR ((uint)0xe4000000) +#define PCMCIA_IO_SIZE ((uint)(4 * 1024)) +#define PCMCIA_ATTRB_ADDR ((uint)0xe8000000) +#define PCMCIA_ATTRB_SIZE ((uint)(4 * 1024)) /* Things of interest in the CSR. */ @@ -49,8 +55,19 @@ #define BCSR0_FLASH_SEL ((uint)0x02000000) #define BCSR0_ENMONXCVR ((uint)0x01000000) +#define BCSR0_PCMCIAVOLT ((uint)0x000f0000) /* CLLF */ +#define BCSR0_PCMCIA3VOLT ((uint)0x000a0000) /* CLLF */ +#define BCSR0_PCMCIA5VOLT ((uint)0x00060000) /* CLLF */ + #define BCSR2_EN232XCVR ((uint)0x00008000) #define BCSR2_QSPACESEL ((uint)0x00004000) +#define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */ + +#if defined(CONFIG_RPXLCD) || defined(CONFIG_HTDMSOUND) +/* HIOX Expansion card. +*/ +#include +#endif /* Interrupt level assignments. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/smp.h linux.ac/include/asm-ppc/smp.h --- linux.vanilla/include/asm-ppc/smp.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/smp.h Sat Jun 10 21:48:24 2000 @@ -37,8 +37,10 @@ #define cpu_number_map(x) (x) extern volatile unsigned long cpu_callin_map[NR_CPUS]; -#define hard_smp_processor_id() (0) #define smp_processor_id() (current->processor) + +extern int smp_hw_index[NR_CPUS]; +#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()]) struct klock_info_struct { unsigned long kernel_flag; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/socket.h linux.ac/include/asm-ppc/socket.h --- linux.vanilla/include/asm-ppc/socket.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/socket.h Mon May 29 19:30:52 2000 @@ -47,4 +47,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/system.h linux.ac/include/asm-ppc/system.h --- linux.vanilla/include/asm-ppc/system.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/system.h Sat Jun 10 21:46:58 2000 @@ -8,7 +8,6 @@ #include #include -#include #include #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-ppc/uaccess.h linux.ac/include/asm-ppc/uaccess.h --- linux.vanilla/include/asm-ppc/uaccess.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-ppc/uaccess.h Sat Jun 10 21:46:58 2000 @@ -211,16 +211,28 @@ extern inline unsigned long copy_from_user(void *to, const void *from, unsigned long n) { + unsigned long over; + if (access_ok(VERIFY_READ, from, n)) return __copy_tofrom_user(to, from, n); + if ((unsigned long)from < TASK_SIZE) { + over = (unsigned long)from + n - TASK_SIZE; + return __copy_tofrom_user(to, from, n - over) + over; + } return n; } extern inline unsigned long copy_to_user(void *to, const void *from, unsigned long n) { + unsigned long over; + if (access_ok(VERIFY_WRITE, to, n)) return __copy_tofrom_user(to, from, n); + if ((unsigned long)to < TASK_SIZE) { + over = (unsigned long)to + n - TASK_SIZE; + return __copy_tofrom_user(to, from, n - over) + over; + } return n; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-s390/pgtable.h linux.ac/include/asm-s390/pgtable.h --- linux.vanilla/include/asm-s390/pgtable.h Thu May 25 17:37:37 2000 +++ linux.ac/include/asm-s390/pgtable.h Sun Jun 4 22:06:32 2000 @@ -270,6 +270,7 @@ extern inline int pte_none(pte_t pte) { return ((pte_val(pte) & (_PAGE_INVALID | _PAGE_RO)) == _PAGE_INVALID); } extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = _PAGE_INVALID; } +#define PTE_INIT(x) pte_clear(x) extern inline int pte_pagenr(pte_t pte) { return ((unsigned long)((pte_val(pte) >> PAGE_SHIFT))); } extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-s390/socket.h linux.ac/include/asm-s390/socket.h --- linux.vanilla/include/asm-s390/socket.h Thu May 25 17:37:37 2000 +++ linux.ac/include/asm-s390/socket.h Mon May 29 19:30:52 2000 @@ -41,20 +41,6 @@ #define SO_SECURITY_ENCRYPTION_TRANSPORT 23 #define SO_SECURITY_ENCRYPTION_NETWORK 24 -#ifdef __KERNEL__ -/* Socket types. */ -#define SOCK_STREAM 1 /* stream (connection) socket */ -#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ -#define SOCK_RAW 3 /* raw socket */ -#define SOCK_RDM 4 /* reliably-delivered message */ -#define SOCK_SEQPACKET 5 /* sequential packet socket */ -#define SOCK_PACKET 10 /* linux specific way of */ - /* getting packets at the dev */ - /* level. For writing rarp and */ - /* other similar things on the */ - /* user level. */ -#endif - #define SO_BINDTODEVICE 25 /* Socket filtering */ @@ -62,5 +48,20 @@ #define SO_DETACH_FILTER 27 #define SO_PEERNAME 28 + +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sh/socket.h linux.ac/include/asm-sh/socket.h --- linux.vanilla/include/asm-sh/socket.h Thu May 25 17:37:37 2000 +++ linux.ac/include/asm-sh/socket.h Mon May 29 19:30:52 2000 @@ -41,4 +41,19 @@ #define SO_PEERNAME 28 +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif + #endif /* __ASM_SH_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/head.h linux.ac/include/asm-sparc/head.h --- linux.vanilla/include/asm-sparc/head.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/head.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: head.h,v 1.38 1999/12/01 23:52:04 davem Exp $ */ +/* $Id: head.h,v 1.39 2000/05/26 22:18:45 ecd Exp $ */ #ifndef __SPARC_HEAD_H #define __SPARC_HEAD_H @@ -95,7 +95,7 @@ /* The Get PSR software trap for userland. */ #define GETPSR_TRAP \ - mov %psr, %o0; jmpl %l2, %g0; rett %l2 + 4; nop; + mov %psr, %i0; jmp %l2; rett %l2 + 4; nop; /* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and * gets handled with another macro. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/ide.h linux.ac/include/asm-sparc/ide.h --- linux.vanilla/include/asm-sparc/ide.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-sparc/ide.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: ide.h,v 1.5 2000/05/22 07:29:43 davem Exp $ +/* $Id: ide.h,v 1.6 2000/05/27 00:49:37 davem Exp $ * ide.h: SPARC PCI specific IDE glue. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/kdebug.h linux.ac/include/asm-sparc/kdebug.h --- linux.vanilla/include/asm-sparc/kdebug.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/kdebug.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: kdebug.h,v 1.10 1997/12/14 23:24:40 ecd Exp $ +/* $Id: kdebug.h,v 1.11 2000/06/04 06:23:53 anton Exp $ * kdebug.h: Defines and definitions for debugging the Linux kernel * under various kernel debuggers. * @@ -8,13 +8,7 @@ #define _SPARC_KDEBUG_H #include - -/* The debugger lives in 1MB of virtual address space right underneath - * the boot prom. - */ - -#define DEBUG_FIRSTVADDR 0xffc00000 -#define DEBUG_LASTVADDR LINUX_OPPROM_BEGVM +#include /* Breakpoints are enter through trap table entry 126. So in sparc assembly * if you want to drop into the debugger you do: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/mc146818rtc.h linux.ac/include/asm-sparc/mc146818rtc.h --- linux.vanilla/include/asm-sparc/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-sparc/mc146818rtc.h Sat Jun 10 21:50:43 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_SPARC_MC146818RTC_H +#define __ASM_SPARC_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_SPARC_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/openprom.h linux.ac/include/asm-sparc/openprom.h --- linux.vanilla/include/asm-sparc/openprom.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/openprom.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: openprom.h,v 1.23 1998/09/21 05:07:26 jj Exp $ */ +/* $Id: openprom.h,v 1.24 2000/06/04 06:23:53 anton Exp $ */ #ifndef __SPARC_OPENPROM_H #define __SPARC_OPENPROM_H @@ -8,10 +8,9 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ +#include + /* Empirical constants... */ -#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */ -#define LINUX_OPPROM_BEGVM 0xffd00000 -#define LINUX_OPPROM_ENDVM 0xfff00000 #define LINUX_OPPROM_MAGIC 0x10010407 #ifndef __ASSEMBLY__ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/page.h linux.ac/include/asm-sparc/page.h --- linux.vanilla/include/asm-sparc/page.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/page.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: page.h,v 1.52 2000/03/28 06:07:25 anton Exp $ +/* $Id: page.h,v 1.53 2000/06/04 08:36:33 anton Exp $ * page.h: Various defines and such for MMU operations on the Sparc for * the Linux kernel. * @@ -32,7 +32,13 @@ #ifndef __ASSEMBLY__ -#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) +/* + * XXX I am hitting compiler bugs with __builtin_trap. This has + * hit me before and rusty was blaming his netfilter bugs on + * this so lets disable it. - Anton + */ +#if 0 +/* #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) */ /* We need the mb()'s so we don't trigger a compiler bug - Anton */ #define BUG() do { \ mb(); \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/pgalloc.h linux.ac/include/asm-sparc/pgalloc.h --- linux.vanilla/include/asm-sparc/pgalloc.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/pgalloc.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pgalloc.h,v 1.4 2000/05/09 17:40:15 davem Exp $ */ +/* $Id: pgalloc.h,v 1.5 2000/06/04 06:23:53 anton Exp $ */ #ifndef _SPARC_PGALLOC_H #define _SPARC_PGALLOC_H @@ -103,23 +103,7 @@ #define pgtable_cache_size (pgt_quicklists.pgtable_cache_sz) #define pgd_cache_size (pgt_quicklists.pgd_cache_sz) -BTFIXUPDEF_CALL(pte_t *, get_pte_fast, void) -BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void) -BTFIXUPDEF_CALL(void, free_pte_slow, pte_t *) -BTFIXUPDEF_CALL(void, free_pgd_slow, pgd_t *) BTFIXUPDEF_CALL(int, do_check_pgt_cache, int, int) - -#define get_pte_fast() BTFIXUP_CALL(get_pte_fast)() -extern __inline__ pmd_t *get_pmd_fast(void) -{ - return (pmd_t *)0; -} -#define get_pgd_fast() BTFIXUP_CALL(get_pgd_fast)() -#define free_pte_slow(pte) BTFIXUP_CALL(free_pte_slow)(pte) -extern __inline__ void free_pmd_slow(pmd_t *pmd) -{ -} -#define free_pgd_slow(pgd) BTFIXUP_CALL(free_pgd_slow)(pgd) #define do_check_pgt_cache(low,high) BTFIXUP_CALL(do_check_pgt_cache)(low,high) /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/pgtable.h linux.ac/include/asm-sparc/pgtable.h --- linux.vanilla/include/asm-sparc/pgtable.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/pgtable.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pgtable.h,v 1.94 2000/03/28 06:07:25 anton Exp $ */ +/* $Id: pgtable.h,v 1.96 2000/06/05 06:08:46 anton Exp $ */ #ifndef _SPARC_PGTABLE_H #define _SPARC_PGTABLE_H @@ -52,19 +52,14 @@ /* * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. - * mmu_flush/inval belong to CPU. Valid on IIep. */ BTFIXUPDEF_CALL(void, mmu_map_dma_area, unsigned long va, __u32 addr, int len) BTFIXUPDEF_CALL(unsigned long /*phys*/, mmu_translate_dvma, unsigned long busa) BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) -BTFIXUPDEF_CALL(void, mmu_inval_dma_area, unsigned long virt, int len) -BTFIXUPDEF_CALL(void, mmu_flush_dma_area, unsigned long virt, int len) #define mmu_map_dma_area(va, ba,len) BTFIXUP_CALL(mmu_map_dma_area)(va,ba,len) #define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) #define mmu_translate_dvma(ba) BTFIXUP_CALL(mmu_translate_dvma)(ba) -#define mmu_inval_dma_area(va,len) BTFIXUP_CALL(mmu_inval_dma_area)(va,len) -#define mmu_flush_dma_area(va,len) BTFIXUP_CALL(mmu_flush_dma_area)(va,len) BTFIXUPDEF_SIMM13(pmd_shift) BTFIXUPDEF_SETHI(pmd_size) @@ -92,9 +87,6 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd) #define VMALLOC_VMADDR(x) ((unsigned long)(x)) -/* This is the same accross all platforms */ -#define VMALLOC_START (0xfe300000) -#define VMALLOC_END ~0x0UL #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) #define pte_ERROR(e) __builtin_trap() diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/pgtsrmmu.h linux.ac/include/asm-sparc/pgtsrmmu.h --- linux.vanilla/include/asm-sparc/pgtsrmmu.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/pgtsrmmu.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pgtsrmmu.h,v 1.29 1998/07/26 03:05:42 davem Exp $ +/* $Id: pgtsrmmu.h,v 1.30 2000/06/05 06:08:46 anton Exp $ * pgtsrmmu.h: SRMMU page table defines and code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -28,9 +28,6 @@ #define SRMMU_PTE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ #define SRMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ #define SRMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */ - -#define SRMMU_VMALLOC_START (0xfe300000) -#define SRMMU_VMALLOC_END ~0x0UL /* Definition of the values in the ET field of PTD's and PTE's */ #define SRMMU_ET_MASK 0x3 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/pgtsun4.h linux.ac/include/asm-sparc/pgtsun4.h --- linux.vanilla/include/asm-sparc/pgtsun4.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/pgtsun4.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pgtsun4.h,v 1.4 1998/07/26 03:05:42 davem Exp $ +/* $Id: pgtsun4.h,v 1.5 2000/06/05 06:08:46 anton Exp $ * pgtsun4.h: Sun4 specific pgtable.h defines and code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -42,13 +42,6 @@ #define SUN4C_PTRS_PER_PTE 1024 #define SUN4C_PTRS_PER_PMD 1 #define SUN4C_PTRS_PER_PGD 1024 - -/* On the sun4 the physical ram limit is 128MB. We set up our I/O - * translations at KERNBASE + 128MB for 1MB, then we begin the VMALLOC - * area, makes sense. This works out to the value below. - */ -#define SUN4C_VMALLOC_START (0xfe300000) -#define SUN4C_VMALLOC_END ~0x0UL /* * Sparc SUN4C pte fields. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/pgtsun4c.h linux.ac/include/asm-sparc/pgtsun4c.h --- linux.vanilla/include/asm-sparc/pgtsun4c.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/pgtsun4c.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: pgtsun4c.h,v 1.36 1998/07/26 03:05:44 davem Exp $ +/* $Id: pgtsun4c.h,v 1.37 2000/06/05 06:08:46 anton Exp $ * pgtsun4c.h: Sun4c specific pgtable.h defines and code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -41,13 +41,6 @@ #define SUN4C_PTRS_PER_PTE 1024 #define SUN4C_PTRS_PER_PMD 1 #define SUN4C_PTRS_PER_PGD 1024 - -/* On the sun4c the physical ram limit is 128MB. We set up our I/O - * translations at KERNBASE + 128MB for 1MB, then we begin the VMALLOC - * area, makes sense. This works out to the value below. - */ -#define SUN4C_VMALLOC_START (0xfe300000) -#define SUN4C_VMALLOC_END ~0x0UL /* * Sparc SUN4C pte fields. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/siginfo.h linux.ac/include/asm-sparc/siginfo.h --- linux.vanilla/include/asm-sparc/siginfo.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-sparc/siginfo.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: siginfo.h,v 1.7 2000/01/29 07:41:51 davem Exp $ +/* $Id: siginfo.h,v 1.8 2000/05/27 00:49:37 davem Exp $ * siginfo.c: */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/socket.h linux.ac/include/asm-sparc/socket.h --- linux.vanilla/include/asm-sparc/socket.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/socket.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: socket.h,v 1.13 2000/02/27 19:47:43 davem Exp $ */ +/* $Id: socket.h,v 1.14 2000/06/09 07:35:28 davem Exp $ */ #ifndef _ASM_SOCKET_H #define _ASM_SOCKET_H @@ -46,5 +46,20 @@ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_NETWORK 0x5004 + +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc/vaddrs.h linux.ac/include/asm-sparc/vaddrs.h --- linux.vanilla/include/asm-sparc/vaddrs.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc/vaddrs.h Sat Jun 10 21:50:43 2000 @@ -1,38 +1,27 @@ -/* $Id: vaddrs.h,v 1.23 2000/03/12 04:10:46 davem Exp $ */ +/* $Id: vaddrs.h,v 1.25 2000/06/05 06:08:46 anton Exp $ */ #ifndef _SPARC_VADDRS_H #define _SPARC_VADDRS_H #include -/* asm-sparc/vaddrs.h: Here will be define the virtual addresses at - * which important I/O addresses will be mapped. - * For instance the timer register virtual address - * is defined here. +/* + * asm-sparc/vaddrs.h: Here we define the virtual addresses at + * which important things will be mapped. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) */ -/* I can see only one reason why we should have statically defined - * mappings for devices and is the speedup improvements of not loading - * a pointer and then the value in the assembly code - */ -#define IOBASE_VADDR 0xfe000000 /* Base for mapping pages */ -#define IOBASE_LEN 0x00300000 /* Length of the IO area */ -#define IOBASE_END 0xfe300000 -#define DVMA_VADDR 0xfff00000 /* Base area of the DVMA on suns */ -#define DVMA_LEN 0x000c0000 /* Size of the DVMA address space */ -#define DVMA_END 0xfffc0000 - -/* IOMMU Mapping area, must be on a 16MB boundary! Note this - * doesn't count the DVMA areas, the prom lives between the - * iommu mapping area (for scsi transfer buffers) and the - * dvma upper range (for lance packet ring buffers). - */ -#define IOMMU_VADDR 0xff000000 -#define IOMMU_LEN 0x00c00000 -#define IOMMU_END 0xffc00000 /* KADB debugger vm starts here */ +#define SUN4M_IOBASE_VADDR 0xfd000000 /* Base for mapping pages */ +#define IOBASE_VADDR 0xfe000000 +#define IOBASE_END 0xfe300000 + +#define VMALLOC_START 0xfe300000 +/* XXX Alter this when I get around to fixing sun4c - Anton */ +#define VMALLOC_END 0xffc00000 -/* On the sun4/4c we don't need an IOMMU area, but we need a place +/* + * On the sun4/4c we need a place * to reliably map locked down kernel data. This includes the * task_struct and kernel stack pages of each process plus the * scsi buffers during dvma IO transfers, also the floppy buffers @@ -44,22 +33,18 @@ * careful if you change NR_TASKS or else there won't be enough * room for it all. */ -#define SUN4C_LOCK_VADDR 0xff000000 -#define SUN4C_LOCK_LEN 0x00c00000 -#define SUN4C_LOCK_END 0xffc00000 - -/* On sun4m machines we need per-cpu virtual areas */ -#define PERCPU_VADDR 0xffc00000 /* Base for per-cpu virtual mappings */ -#define PERCPU_ENTSIZE 0x00100000 -#define PERCPU_LEN ((PERCPU_ENTSIZE*SUN4M_NCPUS)) - -/* per-cpu offsets */ -#define PERCPU_TBR_OFFSET 0x00000 /* %tbr, mainly used for identification. */ -#define PERCPU_KSTACK_OFFSET 0x01000 /* Beginning of kernel stack for this cpu */ -#define PERCPU_MBOX_OFFSET 0x03000 /* Prom SMP Mailbox */ -#define PERCPU_CPUID_OFFSET 0x04000 /* Per-cpu ID number. */ -#define PERCPU_ISALIVE_OFFSET 0x04004 /* Has CPU been initted yet? */ -#define PERCPU_ISIDLING_OFFSET 0x04008 /* Is CPU in idle loop spinning? */ +#define SUN4C_LOCK_VADDR 0xff000000 +#define SUN4C_LOCK_END 0xffc00000 -#endif /* !(_SPARC_VADDRS_H) */ +#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */ +#define KADB_DEBUGGER_ENDVM 0xffd00000 +#define DEBUG_FIRSTVADDR KADB_DEBUGGER_BEGVM +#define DEBUG_LASTVADDR KADB_DEBUGGER_ENDVM +#define LINUX_OPPROM_BEGVM 0xffd00000 +#define LINUX_OPPROM_ENDVM 0xfff00000 + +#define DVMA_VADDR 0xfff00000 /* Base area of the DVMA on suns */ +#define DVMA_END 0xfffc0000 + +#endif /* !(_SPARC_VADDRS_H) */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc64/ide.h linux.ac/include/asm-sparc64/ide.h --- linux.vanilla/include/asm-sparc64/ide.h Thu May 25 17:46:16 2000 +++ linux.ac/include/asm-sparc64/ide.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: ide.h,v 1.18 2000/05/22 07:29:43 davem Exp $ +/* $Id: ide.h,v 1.19 2000/05/27 00:49:37 davem Exp $ * ide.h: Ultra/PCI specific IDE glue. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc64/mc146818rtc.h linux.ac/include/asm-sparc64/mc146818rtc.h --- linux.vanilla/include/asm-sparc64/mc146818rtc.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/asm-sparc64/mc146818rtc.h Sat Jun 10 21:50:43 2000 @@ -0,0 +1,27 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef __ASM_SPARC64_MC146818RTC_H +#define __ASM_SPARC64_MC146818RTC_H + +#include + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_SPARC64_MC146818RTC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc64/socket.h linux.ac/include/asm-sparc64/socket.h --- linux.vanilla/include/asm-sparc64/socket.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc64/socket.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: socket.h,v 1.6 2000/02/27 19:47:58 davem Exp $ */ +/* $Id: socket.h,v 1.7 2000/06/09 07:35:28 davem Exp $ */ #ifndef _ASM_SOCKET_H #define _ASM_SOCKET_H @@ -46,5 +46,20 @@ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_NETWORK 0x5004 + +/* Nast libc5 fixup - bletch */ +#if defined(__KERNEL__) +/* Socket types. */ +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 /* sequential packet socket */ +#define SOCK_PACKET 10 /* linux specific way of */ + /* getting packets at the dev */ + /* level. For writing rarp and */ + /* other similar things on the */ + /* user level. */ +#endif #endif /* _ASM_SOCKET_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-sparc64/system.h linux.ac/include/asm-sparc64/system.h --- linux.vanilla/include/asm-sparc64/system.h Thu May 25 17:37:35 2000 +++ linux.ac/include/asm-sparc64/system.h Sat Jun 10 21:50:43 2000 @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.59 2000/05/09 17:40:15 davem Exp $ */ +/* $Id: system.h,v 1.60 2000/05/29 05:34:02 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -269,7 +269,8 @@ extern __inline__ unsigned long __cmpxchg_u32(volatile int *m, int old, int new) { - __asm__ __volatile__("cas [%2], %3, %0" + __asm__ __volatile__("cas [%2], %3, %0\n\t" + "membar #StoreStore | #StoreLoad" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); @@ -280,7 +281,8 @@ extern __inline__ unsigned long __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) { - __asm__ __volatile__("casx [%2], %3, %0" + __asm__ __volatile__("casx [%2], %3, %0\n\t" + "membar #StoreStore | #StoreLoad" : "=&r" (new) : "0" (new), "r" (m), "r" (old) : "memory"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/ac97_codec.h linux.ac/include/linux/ac97_codec.h --- linux.vanilla/include/linux/ac97_codec.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/ac97_codec.h Mon May 29 20:32:20 2000 @@ -32,7 +32,7 @@ #define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */ #define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */ #define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */ -#define AC97_PCM_LR_ADC_RATE 0x0032 /* PCM LR ADC Rate */ +#define AC97_PCM_LR_DAC_RATE 0x0032 /* PCM LR DAC Rate */ #define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */ #define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */ #define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */ @@ -133,7 +133,7 @@ SOUND_MASK_LINE1| SOUND_MASK_LINE|\ SOUND_MASK_PHONEIN) -#define supported_mixer(CODEC,FOO) ( CODEC->supported_mixers & (1<supported_mixers & (1< * Alexander Kjeldaas * with help from Aleph1, Roland Buresund and Andrew Main. + * + * See here for the libcap library ("POSIX draft" compliance): + * + * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/ */ #ifndef _LINUX_CAPABILITY_H @@ -170,8 +174,8 @@ #define CAP_IPC_OWNER 15 -/* Insert and remove kernel modules */ - +/* Insert and remove kernel modules - modify kernel without limit */ +/* Modify cap_bset */ #define CAP_SYS_MODULE 16 /* Allow ioperm/iopl access */ @@ -294,12 +298,12 @@ #define CAP_EMPTY_SET to_cap_t(0) #define CAP_FULL_SET to_cap_t(~0) #define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP)) -#define CAP_INIT_INH_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP)) +#define CAP_INIT_INH_SET to_cap_t(0) #define CAP_TO_MASK(x) (1 << (x)) #define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag)) #define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag)) -#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset) +#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag)) static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/cdrom.h linux.ac/include/linux/cdrom.h --- linux.vanilla/include/linux/cdrom.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/cdrom.h Sat Jun 10 22:25:04 2000 @@ -477,16 +477,11 @@ /* This seems to be a SCSI specific CD-ROM opcode * to play data at track/index */ #define GPCMD_PLAYAUDIO_TI 0x48 - -/* Is this really used by anything? I couldn't find these...*/ -#if 0 -/* MMC2/MTFuji Opcodes */ -#define ERASE 0x2c -#define READ_BUFFER 0x3c -#endif - - - +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda /* Mode page codes for mode sense/set */ #define GPMODE_R_W_ERROR_PAGE 0x01 @@ -997,6 +992,22 @@ __u8 subhdr2; __u8 subhdr3; } __attribute__((packed)) write_param_page; + +struct modesel_head +{ + __u8 reserved1; + __u8 medium; + __u8 reserved2; + __u8 block_desc_length; + __u8 density; + __u8 number_of_blocks_hi; + __u8 number_of_blocks_med; + __u8 number_of_blocks_lo; + __u8 reserved3; + __u8 block_length_hi; + __u8 block_length_med; + __u8 block_length_lo; +}; #endif /* End of kernel only stuff */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/ext2_fs.h linux.ac/include/linux/ext2_fs.h --- linux.vanilla/include/linux/ext2_fs.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/ext2_fs.h Sat Jun 10 21:51:08 2000 @@ -548,7 +548,9 @@ extern int ext2_write (struct inode *, struct file *, char *, int); /* fsync.c */ -extern int ext2_sync_file (struct file *, struct dentry *); +extern int ext2_fsync_file (struct file *, struct dentry *, int); +extern int ext2_fsync_inode (struct inode *, int); +extern int ext2_osync_inode (struct inode *, int); /* ialloc.c */ extern struct inode * ext2_new_inode (const struct inode *, int, int *); @@ -562,7 +564,7 @@ extern struct buffer_head * ext2_bread (struct inode *, int, int, int *); extern void ext2_read_inode (struct inode *); -extern void ext2_write_inode (struct inode *); +extern void ext2_write_inode (struct inode *, int); extern void ext2_put_inode (struct inode *); extern void ext2_delete_inode (struct inode *); extern int ext2_sync_inode (struct inode *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/fs.h linux.ac/include/linux/fs.h --- linux.vanilla/include/linux/fs.h Thu May 25 17:46:16 2000 +++ linux.ac/include/linux/fs.h Sat Jun 10 22:25:00 2000 @@ -47,7 +47,12 @@ #define BLOCK_SIZE (1<i_state & I_DIRTY)) - __mark_inode_dirty(inode); + if ((inode->i_state & I_DIRTY) != I_DIRTY) + __mark_inode_dirty(inode, I_DIRTY); +} +static inline void mark_inode_dirty_sync(struct inode *inode) +{ + if (!(inode->i_state & I_DIRTY_SYNC)) + __mark_inode_dirty(inode, I_DIRTY_SYNC); } struct fown_struct { @@ -554,6 +572,15 @@ struct file *fa_file; }; +#define FASYNC_MAGIC 0x4601 + +/* SMP safe fasync helpers: */ +extern int fasync_helper(int, struct file *, int, struct fasync_struct **); +/* can be called from interrupts */ +extern void kill_fasync(struct fasync_struct **, int, int); +/* only for net: no internal synchronization */ +extern void __kill_fasync(struct fasync_struct *, int, int); + struct nameidata { struct dentry *dentry; struct vfsmount *mnt; @@ -562,10 +589,6 @@ int last_type; }; -#define FASYNC_MAGIC 0x4601 - -extern int fasync_helper(int, struct file *, int, struct fasync_struct **); - #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ #define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ @@ -715,7 +738,7 @@ int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); - int (*fsync) (struct file *, struct dentry *); + int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); @@ -748,7 +771,7 @@ */ struct super_operations { void (*read_inode) (struct inode *); - void (*write_inode) (struct inode *); + void (*write_inode) (struct inode *, int); void (*put_inode) (struct inode *); void (*delete_inode) (struct inode *); void (*put_super) (struct super_block *); @@ -841,8 +864,8 @@ return locks_mandatory_area( FLOCK_VERIFY_WRITE, inode, filp, size < inode->i_size ? size : inode->i_size, - abs(inode->i_size - size) - ); + size < inode->i_size ? inode->i_size - size + : size - inode->i_size); return 0; } @@ -865,7 +888,6 @@ #define putname(name) free_page((unsigned long)(name)) enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDEV_RAW}; -extern void kill_fasync(struct fasync_struct *, int, int); extern int register_blkdev(unsigned int, const char *, struct block_device_operations *); extern int unregister_blkdev(unsigned int, const char *); extern struct block_device *bdget(dev_t); @@ -967,17 +989,28 @@ bh->b_end_io(bh, 0); } +extern void buffer_insert_inode_queue(struct buffer_head *, struct inode *); +static inline void mark_buffer_dirty_inode(struct buffer_head *bh, int flag, struct inode *inode) +{ + mark_buffer_dirty(bh, flag); + buffer_insert_inode_queue(bh, inode); +} + extern void balance_dirty(kdev_t); extern int check_disk_change(kdev_t); extern int invalidate_inodes(struct super_block *); extern void invalidate_inode_pages(struct inode *); +extern void invalidate_inode_buffers(struct inode *); #define invalidate_buffers(dev) __invalidate_buffers((dev), 0) #define destroy_buffers(dev) __invalidate_buffers((dev), 1) extern void __invalidate_buffers(kdev_t dev, int); extern void sync_inodes(kdev_t); -extern void write_inode_now(struct inode *); +extern void write_inode_now(struct inode *, int); extern void sync_dev(kdev_t); extern int fsync_dev(kdev_t); +extern int fsync_inode_buffers(struct inode *); +extern int osync_inode_buffers(struct inode *); +extern int inode_has_buffers(struct inode *); extern void sync_supers(kdev_t); extern int bmap(struct inode *, int); extern int notify_change(struct dentry *, struct iattr *); @@ -1058,6 +1091,7 @@ #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd) extern void iput(struct inode *); +extern void force_delete(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); @@ -1104,6 +1138,7 @@ /* Generic buffer handling for block filesystems.. */ extern int block_flushpage(struct page *, unsigned long); +extern void block_destroy_buffers(struct page *); extern int block_symlink(struct inode *, const char *, int); extern int block_write_full_page(struct page*, get_block_t*); extern int block_read_full_page(struct page*, get_block_t*); @@ -1157,7 +1192,7 @@ extern ssize_t char_write(struct file *, const char *, size_t, loff_t *); extern ssize_t block_write(struct file *, const char *, size_t, loff_t *); -extern int file_fsync(struct file *, struct dentry *); +extern int file_fsync(struct file *, struct dentry *, int); extern int generic_buffer_fdatasync(struct inode *inode, unsigned long start_idx, unsigned long end_idx); extern int inode_change_ok(struct inode *, struct iattr *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/ide.h linux.ac/include/linux/ide.h --- linux.vanilla/include/linux/ide.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/ide.h Sat Jun 10 22:26:31 2000 @@ -58,6 +58,10 @@ #endif #endif /* CONFIG_BLK_DEV_CMD640 */ +#ifndef DISABLE_IRQ_NOSYNC +#define DISABLE_IRQ_NOSYNC 0 +#endif + /* * IDE_DRIVE_CMD is used to implement many features of the hdparm utility */ @@ -181,6 +185,32 @@ OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \ } +#define SELECT_INTERRUPT(hwif,drive) \ +{ \ + if (hwif->intrproc) \ + hwif->intrproc(drive); \ + else \ + OUT_BYTE((drive)->ctl|2, hwif->io_ports[IDE_CONTROL_OFFSET]); \ +} + +#define SELECT_MASK(hwif,drive,mask) \ +{ \ + if (hwif->maskproc) \ + hwif->maskproc(drive,mask); \ +} + +#define SELECT_READ_WRITE(hwif,drive,func) \ +{ \ + if (hwif->rwproc) \ + hwif->rwproc(drive,func); \ +} + +#define QUIRK_LIST(hwif,drive) \ +{ \ + if (hwif->quirkproc) \ + (drive)->quirk_list = hwif->quirkproc(drive); \ +} + /* * Check for an interrupt and acknowledge the interrupt status */ @@ -309,6 +339,8 @@ int last_lun; /* last logical unit */ int forced_lun; /* if hdxlun was given at boot */ int lun; /* logical unit */ + int crc_count; /* crc counter to reduce drive speed */ + byte quirk_list; /* drive is considered quirky if set for a specific host */ byte init_speed; /* transfer rate set at boot */ byte current_speed; /* current transfer rate set */ byte dn; /* now wide spread use */ @@ -354,6 +386,10 @@ */ typedef void (ide_selectproc_t) (ide_drive_t *); typedef void (ide_resetproc_t) (ide_drive_t *); +typedef int (ide_quirkproc_t) (ide_drive_t *); +typedef void (ide_intrproc_t) (ide_drive_t *); +typedef void (ide_maskproc_t) (ide_drive_t *, int); +typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t); /* * hwif_chipset_t is used to keep track of the specific hardware @@ -388,6 +424,10 @@ ide_speedproc_t *speedproc; /* routine to retune DMA modes for drives */ ide_selectproc_t *selectproc; /* tweaks hardware to select drive */ ide_resetproc_t *resetproc; /* routine to reset controller after a disk reset */ + ide_intrproc_t *intrproc; /* special interrupt handling for shared pci interrupts */ + ide_maskproc_t *maskproc; /* special host masking for drive selection */ + ide_quirkproc_t *quirkproc; /* check host's drive quirk list */ + ide_rw_proc_t *rwproc; /* adjust timing based upon rq->cmd direction */ ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */ unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */ dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */ @@ -424,6 +464,7 @@ void *hwif_data; /* extra hwif data */ } ide_hwif_t; + /* * Status returned from various ide_ functions */ @@ -614,12 +655,14 @@ /* * This is used for (nearly) all data transfers from/to the IDE interface + * FIXME for 2.5, to a pointer pass verses memcpy........ */ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount); void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount); /* * This is used for (nearly) all ATAPI data transfers from/to the IDE interface + * FIXME for 2.5, to a pointer pass verses memcpy........ */ void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); @@ -750,6 +793,7 @@ int ide_driveid_update (ide_drive_t *drive); int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature); int ide_config_drive_speed (ide_drive_t *drive, byte speed); +byte eighty_ninty_three (ide_drive_t *drive); int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/input.h linux.ac/include/linux/input.h --- linux.vanilla/include/linux/input.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/input.h Sat Jun 10 22:49:22 2000 @@ -2,9 +2,9 @@ #define _INPUT_H /* - * input.h Version 0.1 + * $Id: input.h,v 1.13 2000/05/29 10:54:53 vojtech Exp $ * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 1999-2000 Vojtech Pavlik * * Sponsored by SuSE */ @@ -33,6 +33,7 @@ #include #else #include +#include #endif /* @@ -47,16 +48,6 @@ }; /* - * The device ID structure; - */ - -struct input_id { - __u16 bus; - __u16 vendor; - __u16 product; -}; - -/* * Protocol version. */ @@ -66,14 +57,17 @@ * IOCTLs (0x00 - 0x7f) */ -#define EVIOCGVERSION _IOR('E', 0x01, __u32) /* get driver version */ -#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ +#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ +#define EVIOCGID _IOR('E', 0x02, short[4]) /* get device ID */ #define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */ #define EVIOCSREP _IOW('E', 0x03, int[2]) /* get repeat settings */ -#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x03, len) /* get device name */ +#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */ +#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */ +#define EVIOCGKEY _IOR('E', 0x05, int[2]) /* get key value */ +#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ + #define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */ -#define EVIOCGABSLIM(num) _IOR('E', 0x40 + num, int[4]) /* get abs event limits */ -#define EVIOCGABS(num) _IOR('E', 0x80 + num, int) /* get abs value */ +#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, int[5]) /* get abs value/limits */ /* * Event types @@ -308,6 +302,7 @@ #define BTN_BASE3 0x128 #define BTN_BASE4 0x129 #define BTN_BASE5 0x12a +#define BTN_BASE6 0x12b #define BTN_GAMEPAD 0x130 #define BTN_A 0x130 @@ -364,6 +359,8 @@ #define ABS_RZ 0x05 #define ABS_THROTTLE 0x06 #define ABS_RUDDER 0x07 +#define ABS_TL 0x08 +#define ABS_TR 0x09 #define ABS_HAT0X 0x10 #define ABS_HAT0Y 0x11 #define ABS_HAT1X 0x12 @@ -406,6 +403,27 @@ #define SND_BELL 0x01 #define SND_MAX 0x07 +/* + * IDs. + */ + +#define ID_BUS 0 +#define ID_VENDOR 1 +#define ID_PRODUCT 2 +#define ID_VERSION 3 + +#define BUS_PCI 0x01 +#define BUS_ISAPNP 0x02 +#define BUS_USB 0x03 + +#define BUS_ISA 0x10 +#define BUS_I8042 0x11 +#define BUS_XTKBD 0x12 +#define BUS_RS232 0x13 +#define BUS_GAMEPORT 0x14 +#define BUS_PARPORT 0x15 +#define BUS_AMIGA 0x16 + #ifdef __KERNEL__ /* @@ -425,7 +443,10 @@ int number; char *name; - struct input_id id; + unsigned short idbus; + unsigned short idvendor; + unsigned short idproduct; + unsigned short idversion; unsigned long evbit[NBITS(EV_MAX)]; unsigned long keybit[NBITS(KEY_MAX)]; @@ -434,7 +455,10 @@ unsigned long ledbit[NBITS(LED_MAX)]; unsigned long sndbit[NBITS(SND_MAX)]; - unsigned char *keycode; + unsigned int keycodemax; + unsigned int keycodesize; + void *keycode; + unsigned int repeat_key; struct timer_list timer; @@ -500,8 +524,7 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); -#define input_report_key(a,b,c) input_event(a, EV_KEY, b, c) -#define input_report_btn(a,b,c) input_event(a, EV_KEY, b, !!(c)) +#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c)) #define input_report_rel(a,b,c) input_event(a, EV_REL, b, c) #define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/mc146818rtc.h linux.ac/include/linux/mc146818rtc.h --- linux.vanilla/include/linux/mc146818rtc.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/mc146818rtc.h Sat Jun 10 22:26:03 2000 @@ -10,22 +10,10 @@ #ifndef _MC146818RTC_H #define _MC146818RTC_H -#include -#include /* get the user-level API */ - -#ifndef RTC_PORT -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ALWAYS_BCD 1 -#endif -#define CMOS_READ(addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -inb_p(RTC_PORT(1)); \ -}) -#define CMOS_WRITE(val, addr) ({ \ -outb_p((addr),RTC_PORT(0)); \ -outb_p((val),RTC_PORT(1)); \ -}) +#include +#include /* get the user-level API */ +#include /* register access macros */ /********************************************************************** * register summary diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/minix_fs.h linux.ac/include/linux/minix_fs.h --- linux.vanilla/include/linux/minix_fs.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/minix_fs.h Sat Jun 10 21:51:08 2000 @@ -101,7 +101,7 @@ extern void minix_truncate(struct inode *); extern int minix_sync_inode(struct inode *); -extern int minix_sync_file(struct file *, struct dentry *); +extern int minix_sync_file(struct file *, struct dentry *, int); extern struct address_space_operations minix_aops; extern struct inode_operations minix_file_inode_operations; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/miscdevice.h linux.ac/include/linux/miscdevice.h --- linux.vanilla/include/linux/miscdevice.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/miscdevice.h Sat Jun 10 22:25:31 2000 @@ -20,6 +20,7 @@ #define SUN_OPENPROM_MINOR 139 #define NVRAM_MINOR 144 #define I2O_MINOR 166 +#define MICROCODE_MINOR 184 #define MISC_DYNAMIC_MINOR 255 #define SGI_GRAPHICS_MINOR 146 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/mm.h linux.ac/include/linux/mm.h --- linux.vanilla/include/linux/mm.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/mm.h Sat Jun 10 22:25:00 2000 @@ -153,6 +153,7 @@ struct buffer_head * buffers; unsigned long virtual; /* nonzero if kmapped */ struct zone_struct *zone; + unsigned int age; } mem_map_t; #define get_page(p) atomic_inc(&(p)->count) @@ -169,7 +170,7 @@ #define PG_dirty 4 #define PG_decr_after 5 #define PG_unused_01 6 -#define PG__unused_02 7 +#define PG_active 7 #define PG_slab 8 #define PG_swap_cache 9 #define PG_skip 10 @@ -185,6 +186,7 @@ #define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) #define PageDirty(page) test_bit(PG_dirty, &(page)->flags) #define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) +#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags) #define PageLocked(page) test_bit(PG_locked, &(page)->flags) #define LockPage(page) set_bit(PG_locked, &(page)->flags) #define TryLockPage(page) test_and_set_bit(PG_locked, &(page)->flags) @@ -192,11 +194,15 @@ clear_bit(PG_locked, &(page)->flags); \ wake_up(&page->wait); \ } while (0) +#define PageActive(page) test_bit(PG_active, &(page)->flags) +#define SetPageActive(page) set_bit(PG_active, &(page)->flags) +#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) #define PageError(page) test_bit(PG_error, &(page)->flags) #define SetPageError(page) set_bit(PG_error, &(page)->flags) #define ClearPageError(page) clear_bit(PG_error, &(page)->flags) #define PageReferenced(page) test_bit(PG_referenced, &(page)->flags) #define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags) +#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) #define PageTestandClearReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags) #define PageDecrAfter(page) test_bit(PG_decr_after, &(page)->flags) #define SetPageDecrAfter(page) set_bit(PG_decr_after, &(page)->flags) @@ -457,6 +463,7 @@ extern unsigned long page_unuse(struct page *); extern int shrink_mmap(int, int); extern void truncate_inode_pages(struct address_space *, loff_t); +extern void truncate_all_inode_pages(struct address_space *); /* generic vm_area_ops exported for stackable file systems */ extern int filemap_swapout(struct page * page, struct file *file); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/module.h linux.ac/include/linux/module.h --- linux.vanilla/include/linux/module.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/module.h Sat Jun 10 22:25:00 2000 @@ -144,6 +144,7 @@ /* Find a symbol exported by the kernel or another module */ extern unsigned long get_module_symbol(char *, char *); +extern void put_module_symbol(unsigned long); extern int try_inc_mod_count(struct module *mod); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/ncp_fs_i.h linux.ac/include/linux/ncp_fs_i.h --- linux.vanilla/include/linux/ncp_fs_i.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/ncp_fs_i.h Sun Jun 4 21:48:39 2000 @@ -19,7 +19,8 @@ __u32 DosDirNum __attribute__((packed)); __u32 volNumber __attribute__((packed)); __u32 nwattr; - int opened; + struct semaphore open_sem; + atomic_t opened; int access; __u32 server_file_handle __attribute__((packed)); __u8 open_create_action __attribute__((packed)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netdevice.h linux.ac/include/linux/netdevice.h --- linux.vanilla/include/linux/netdevice.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/netdevice.h Sat Jun 10 22:25:00 2000 @@ -13,6 +13,7 @@ * Donald J. Becker, * Alan Cox, * Bjorn Ekwall. + * Pekka Riikonen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -193,6 +194,17 @@ /* + * This structure holds at boot time configured netdevice settings. They + * are then used in the device probing. + */ +struct netdev_boot_setup { + char name[IFNAMSIZ]; + struct ifmap map; +}; +#define NETDEV_BOOT_SETUP_MAX 8 + + +/* * The DEVICE structure. * Actually, this whole structure is a big mistake. It mixes I/O * data with strictly "high-level" data, and it has to know about @@ -389,8 +401,11 @@ extern struct net_device loopback_dev; /* The loopback */ extern struct net_device *dev_base; /* All devices */ -extern rwlock_t dev_base_lock; /* Device list lock */ +extern rwlock_t dev_base_lock; /* Device list lock */ +extern struct netdev_boot_setup dev_boot_setup[]; +extern int netdev_boot_setup_add(char *name, struct ifmap *map); +extern int netdev_boot_setup_check(struct net_device *dev); extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr); extern void dev_add_pack(struct packet_type *pt); extern void dev_remove_pack(struct packet_type *pt); @@ -414,7 +429,7 @@ typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len); extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); -extern __inline__ int unregister_gifconf(unsigned int family) +static inline int unregister_gifconf(unsigned int family) { return register_gifconf(family, 0); } @@ -437,7 +452,7 @@ #define HAVE_NETIF_QUEUE -extern __inline__ void __netif_schedule(struct net_device *dev) +static inline void __netif_schedule(struct net_device *dev) { if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) { unsigned long flags; @@ -451,34 +466,34 @@ } } -extern __inline__ void netif_schedule(struct net_device *dev) +static inline void netif_schedule(struct net_device *dev) { if (!test_bit(__LINK_STATE_XOFF, &dev->state)) __netif_schedule(dev); } -extern __inline__ void netif_start_queue(struct net_device *dev) +static inline void netif_start_queue(struct net_device *dev) { clear_bit(__LINK_STATE_XOFF, &dev->state); } -extern __inline__ void netif_wake_queue(struct net_device *dev) +static inline void netif_wake_queue(struct net_device *dev) { if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state)) __netif_schedule(dev); } -extern __inline__ void netif_stop_queue(struct net_device *dev) +static inline void netif_stop_queue(struct net_device *dev) { set_bit(__LINK_STATE_XOFF, &dev->state); } -extern __inline__ int netif_queue_stopped(struct net_device *dev) +static inline int netif_queue_stopped(struct net_device *dev) { return test_bit(__LINK_STATE_XOFF, &dev->state); } -extern __inline__ int netif_running(struct net_device *dev) +static inline int netif_running(struct net_device *dev) { return test_bit(__LINK_STATE_START, &dev->state); } @@ -486,7 +501,7 @@ /* Use this variant when it is known for sure that it * is executing from interrupt context. */ -extern __inline__ void dev_kfree_skb_irq(struct sk_buff *skb) +static inline void dev_kfree_skb_irq(struct sk_buff *skb) { if (atomic_dec_and_test(&skb->users)) { int cpu =smp_processor_id(); @@ -503,7 +518,7 @@ /* Use this variant in places where it could be invoked * either from interrupt or non-interrupt context. */ -extern __inline__ void dev_kfree_skb_any(struct sk_buff *skb) +static inline void dev_kfree_skb_any(struct sk_buff *skb) { if (in_irq()) dev_kfree_skb_irq(skb); @@ -522,14 +537,14 @@ extern int netdev_nit; -extern __inline__ void dev_init_buffers(struct net_device *dev) +static inline void dev_init_buffers(struct net_device *dev) { /* DO NOTHING */ } extern int netdev_finish_unregister(struct net_device *dev); -extern __inline__ void dev_put(struct net_device *dev) +static inline void dev_put(struct net_device *dev) { if (atomic_dec_and_test(&dev->refcnt)) netdev_finish_unregister(dev); @@ -543,32 +558,32 @@ * who is responsible for serialization of these calls. */ -extern __inline__ int netif_carrier_ok(struct net_device *dev) +static inline int netif_carrier_ok(struct net_device *dev) { return !test_bit(__LINK_STATE_NOCARRIER, &dev->state); } extern void __netdev_watchdog_up(struct net_device *dev); -extern __inline__ void netif_carrier_on(struct net_device *dev) +static inline void netif_carrier_on(struct net_device *dev) { clear_bit(__LINK_STATE_NOCARRIER, &dev->state); if (netif_running(dev)) __netdev_watchdog_up(dev); } -extern __inline__ void netif_carrier_off(struct net_device *dev) +static inline void netif_carrier_off(struct net_device *dev) { set_bit(__LINK_STATE_NOCARRIER, &dev->state); } /* Hot-plugging. */ -extern __inline__ int netif_device_present(struct net_device *dev) +static inline int netif_device_present(struct net_device *dev) { return test_bit(__LINK_STATE_PRESENT, &dev->state); } -extern __inline__ void netif_device_detach(struct net_device *dev) +static inline void netif_device_detach(struct net_device *dev) { if (test_and_clear_bit(__LINK_STATE_PRESENT, &dev->state) && netif_running(dev)) { @@ -576,7 +591,7 @@ } } -extern __inline__ void netif_device_attach(struct net_device *dev) +static inline void netif_device_attach(struct net_device *dev) { if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) && netif_running(dev)) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv4/ip_conntrack_core.h linux.ac/include/linux/netfilter_ipv4/ip_conntrack_core.h --- linux.vanilla/include/linux/netfilter_ipv4/ip_conntrack_core.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/netfilter_ipv4/ip_conntrack_core.h Sat Jun 10 22:32:31 2000 @@ -22,7 +22,8 @@ /* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */ extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb, - enum ip_conntrack_info *ctinfo); + enum ip_conntrack_info *ctinfo, + unsigned int hooknum); extern int get_tuple(const struct iphdr *iph, size_t len, struct ip_conntrack_tuple *tuple, struct ip_conntrack_protocol *protocol); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux.ac/include/linux/netfilter_ipv4/ip_conntrack_tuple.h --- linux.vanilla/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Tue Jun 6 12:34:41 2000 @@ -31,7 +31,6 @@ { u_int32_t ip; union ip_conntrack_manip_proto u; - u_int16_t pad; /* Must be set to 0 for memcmp. */ }; /* This contains the information to distinguish a connection. */ @@ -78,7 +77,7 @@ IP_PARTS((tp)->src.ip), ntohs((tp)->src.u.all), \ IP_PARTS((tp)->dst.ip), ntohs((tp)->dst.u.all)) -#define CTINFO2DIR(ctinfo) ((ctinfo) == IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) +#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) /* If we're the first tuple, it's the original dir. */ #define DIRECTION(h) ((enum ip_conntrack_dir)(&(h)->ctrack->tuplehash[1] == (h))) @@ -89,6 +88,27 @@ IP_CT_DIR_REPLY, IP_CT_DIR_MAX }; + +extern inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) +{ + return t1->src.ip == t2->src.ip + && t1->src.u.all == t2->src.u.all; +} + +extern inline int ip_ct_tuple_dst_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) +{ + return t1->dst.ip == t2->dst.ip + && t1->dst.u.all == t2->dst.u.all + && t1->dst.protonum == t2->dst.protonum; +} + +extern inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1, + const struct ip_conntrack_tuple *t2) +{ + return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2); +} /* Connections have two entries in the hash table: one for each way */ struct ip_conntrack_tuple_hash diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_LOG.h linux.ac/include/linux/netfilter_ipv6/ip6t_LOG.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_LOG.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_LOG.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,15 @@ +#ifndef _IP6T_LOG_H +#define _IP6T_LOG_H + +#define IP6T_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */ +#define IP6T_LOG_TCPOPT 0x02 /* Log TCP options */ +#define IP6T_LOG_IPOPT 0x04 /* Log IP options */ +#define IP6T_LOG_MASK 0x07 + +struct ip6t_log_info { + unsigned char level; + unsigned char logflags; + char prefix[30]; +}; + +#endif /*_IPT_LOG_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_MARK.h linux.ac/include/linux/netfilter_ipv6/ip6t_MARK.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_MARK.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_MARK.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,8 @@ +#ifndef _IP6T_MARK_H_target +#define _IP6T_MARK_H_target + +struct ip6t_mark_target_info { + unsigned long mark; +}; + +#endif /*_IPT_MARK_H_target*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_REJECT.h linux.ac/include/linux/netfilter_ipv6/ip6t_REJECT.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_REJECT.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_REJECT.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,16 @@ +#ifndef _IP6T_REJECT_H +#define _IP6T_REJECT_H + +enum ip6t_reject_with { + IP6T_ICMP_NET_UNREACHABLE, + IP6T_ICMP_HOST_UNREACHABLE, + IP6T_ICMP_PROT_UNREACHABLE, + IP6T_ICMP_PORT_UNREACHABLE, + IP6T_ICMP_ECHOREPLY +}; + +struct ip6t_reject_info { + enum ip6t_reject_with with; /* reject type */ +}; + +#endif /*_IPT_REJECT_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_limit.h linux.ac/include/linux/netfilter_ipv6/ip6t_limit.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_limit.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_limit.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,21 @@ +#ifndef _IP6T_RATE_H +#define _IP6T_RATE_H + +/* timings are in milliseconds. */ +#define IP6T_LIMIT_SCALE 10000 + +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 + seconds, or one every 59 hours. */ +struct ip6t_rateinfo { + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + u_int32_t credit; + u_int32_t credit_cap, cost; + + /* Ugly, ugly fucker. */ + struct ip6t_rateinfo *master; +}; +#endif /*_IPT_RATE_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_mac.h linux.ac/include/linux/netfilter_ipv6/ip6t_mac.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_mac.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_mac.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,8 @@ +#ifndef _IP6T_MAC_H +#define _IP6T_MAC_H + +struct ip6t_mac_info { + unsigned char srcaddr[ETH_ALEN]; + int invert; +}; +#endif /*_IPT_MAC_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_mark.h linux.ac/include/linux/netfilter_ipv6/ip6t_mark.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_mark.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_mark.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,9 @@ +#ifndef _IP6T_MARK_H +#define _IP6T_MARK_H + +struct ip6t_mark_info { + unsigned long mark, mask; + u_int8_t invert; +}; + +#endif /*_IPT_MARK_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_multiport.h linux.ac/include/linux/netfilter_ipv6/ip6t_multiport.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_multiport.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_multiport.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,21 @@ +#ifndef _IP6T_MULTIPORT_H +#define _IP6T_MULTIPORT_H +#include + +enum ip6t_multiport_flags +{ + IP6T_MULTIPORT_SOURCE, + IP6T_MULTIPORT_DESTINATION, + IP6T_MULTIPORT_EITHER +}; + +#define IP6T_MULTI_PORTS 15 + +/* Must fit inside union ip6t_matchinfo: 16 bytes */ +struct ip6t_multiport +{ + u_int8_t flags; /* Type of comparison */ + u_int8_t count; /* Number of ports */ + u_int16_t ports[IP6T_MULTI_PORTS]; /* Ports */ +}; +#endif /*_IPT_MULTIPORT_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/netfilter_ipv6/ip6t_owner.h linux.ac/include/linux/netfilter_ipv6/ip6t_owner.h --- linux.vanilla/include/linux/netfilter_ipv6/ip6t_owner.h Thu Jan 1 01:00:00 1970 +++ linux.ac/include/linux/netfilter_ipv6/ip6t_owner.h Fri Jun 9 15:47:11 2000 @@ -0,0 +1,18 @@ +#ifndef _IP6T_OWNER_H +#define _IP6T_OWNER_H + +/* match and invert flags */ +#define IP6T_OWNER_UID 0x01 +#define IP6T_OWNER_GID 0x02 +#define IP6T_OWNER_PID 0x04 +#define IP6T_OWNER_SID 0x08 + +struct ip6t_owner_info { + uid_t uid; + gid_t gid; + pid_t pid; + pid_t sid; + u_int8_t match, invert; /* flags */ +}; + +#endif /*_IPT_OWNER_H*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/pci_ids.h linux.ac/include/linux/pci_ids.h --- linux.vanilla/include/linux/pci_ids.h Thu May 25 17:46:16 2000 +++ linux.ac/include/linux/pci_ids.h Mon Jun 5 19:35:17 2000 @@ -190,6 +190,8 @@ #define PCI_VENDOR_ID_NS 0x100b #define PCI_DEVICE_ID_NS_87415 0x0002 +#define PCI_DEVICE_ID_NS_87560_LIO 0x000e +#define PCI_DEVICE_ID_NS_87560_USB 0x0012 #define PCI_DEVICE_ID_NS_87410 0xd001 #define PCI_VENDOR_ID_TSENG 0x100c @@ -259,7 +261,10 @@ #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 #define PCI_DEVICE_ID_AMD_FE_GATE_7006 0x7006 -#define PCI_DEVICE_ID_AMD_VIPER_7403 0x7403 +#define PCI_DEVICE_ID_AMD_COBRA_7400 0x7400 +#define PCI_DEVICE_ID_AMD_COBRA_7401 0x7401 +#define PCI_DEVICE_ID_AMD_COBRA_7403 0x7403 +#define PCI_DEVICE_ID_AMD_COBRA_7404 0x7404 #define PCI_DEVICE_ID_AMD_VIPER_7408 0x7408 #define PCI_DEVICE_ID_AMD_VIPER_7409 0x7409 #define PCI_DEVICE_ID_AMD_VIPER_740B 0x740B @@ -411,6 +416,7 @@ #define PCI_DEVICE_ID_MOTOROLA_CPX8216 0x4806 #define PCI_VENDOR_ID_PROMISE 0x105a +#define PCI_DEVICE_ID_PROMISE_20267 0x4d30 #define PCI_DEVICE_ID_PROMISE_20246 0x4d33 #define PCI_DEVICE_ID_PROMISE_20262 0x4d38 #define PCI_DEVICE_ID_PROMISE_5300 0x5300 @@ -514,6 +520,7 @@ #define PCI_DEVICE_ID_CMD_646 0x0646 #define PCI_DEVICE_ID_CMD_647 0x0647 #define PCI_DEVICE_ID_CMD_648 0x0648 +#define PCI_DEVICE_ID_CMD_649 0x0649 #define PCI_DEVICE_ID_CMD_670 0x0670 #define PCI_VENDOR_ID_VISION 0x1098 @@ -545,6 +552,8 @@ #define PCI_DEVICE_ID_DATABOOK_87144 0xb106 #define PCI_VENDOR_ID_PLX 0x10b5 +#define PCI_VENDOR_ID_PLX_ROMULUS 0x106a +#define PCI_DEVICE_ID_PLX_SPCOM800 0x1076 #define PCI_DEVICE_ID_PLX_SPCOM200 0x1103 #define PCI_DEVICE_ID_PLX_9050 0x9050 #define PCI_DEVICE_ID_PLX_9060 0x9060 @@ -1074,6 +1083,9 @@ #define PCI_VENDOR_ID_AFAVLAB 0x14db #define PCI_DEVICE_ID_AFAVLAB_TK9902 0x2120 +#define PCI_VENDOR_ID_MORETON 0x15aa +#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 + #define PCI_VENDOR_ID_SYMPHONY 0x1c1c #define PCI_DEVICE_ID_SYMPHONY_101 0x0001 @@ -1172,6 +1184,13 @@ #define PCI_DEVICE_ID_INTEL_82801AB_5 0x2425 #define PCI_DEVICE_ID_INTEL_82801AB_6 0x2426 #define PCI_DEVICE_ID_INTEL_82801AB_8 0x2428 +#define PCI_DEVICE_ID_INTEL_82820FW_0 0x2440 +#define PCI_DEVICE_ID_INTEL_82820FW_1 0x2442 +#define PCI_DEVICE_ID_INTEL_82820FW_2 0x2443 +#define PCI_DEVICE_ID_INTEL_82820FW_3 0x2444 +#define PCI_DEVICE_ID_INTEL_82820FW_4 0x2449 +#define PCI_DEVICE_ID_INTEL_82820FW_5 0x244b +#define PCI_DEVICE_ID_INTEL_82820FW_6 0x244e #define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 #define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 #define PCI_DEVICE_ID_INTEL_82810_MC3 0x7122 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/poll.h linux.ac/include/linux/poll.h --- linux.vanilla/include/linux/poll.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/poll.h Sat Jun 10 22:25:00 2000 @@ -20,6 +20,7 @@ typedef struct poll_table_struct { struct poll_table_struct * next; unsigned int nr; + int err; struct poll_table_entry * entry; } poll_table; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/proc_fs.h linux.ac/include/linux/proc_fs.h --- linux.vanilla/include/linux/proc_fs.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/proc_fs.h Sat Jun 10 22:25:00 2000 @@ -127,7 +127,7 @@ extern void proc_device_tree_init(void); extern struct proc_dir_entry *proc_symlink(const char *, - struct proc_dir_entry *,char *); + struct proc_dir_entry *, const char *); extern struct proc_dir_entry *proc_mknod(const char *,mode_t, struct proc_dir_entry *,kdev_t); extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/qnx4_fs.h linux.ac/include/linux/qnx4_fs.h --- linux.vanilla/include/linux/qnx4_fs.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/qnx4_fs.h Sat Jun 10 21:51:08 2000 @@ -116,7 +116,7 @@ extern void qnx4_free_inode(struct inode *inode); extern int qnx4_unlink(struct inode *dir, struct dentry *dentry); extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry); -extern int qnx4_sync_file(struct file *file, struct dentry *dentry); +extern int qnx4_sync_file(struct file *file, struct dentry *dentry, int); extern int qnx4_sync_inode(struct inode *inode); extern int qnx4_get_block(struct inode *inode, long iblock, struct buffer_head *bh, int create); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/raid/md_k.h linux.ac/include/linux/raid/md_k.h --- linux.vanilla/include/linux/raid/md_k.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/raid/md_k.h Fri Jun 9 15:49:35 2000 @@ -337,7 +337,8 @@ typedef struct dev_name_s { struct md_list_head list; kdev_t dev; - char name [MAX_DISKNAME_LEN]; + char namebuf [MAX_DISKNAME_LEN]; + char *name; } dev_name_t; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/reboot.h linux.ac/include/linux/reboot.h --- linux.vanilla/include/linux/reboot.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/reboot.h Wed May 31 11:36:24 2000 @@ -34,7 +34,6 @@ #include -extern struct notifier_block *reboot_notifier_list; extern int register_reboot_notifier(struct notifier_block *); extern int unregister_reboot_notifier(struct notifier_block *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/serial.h linux.ac/include/linux/serial.h --- linux.vanilla/include/linux/serial.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/serial.h Tue May 30 14:53:12 2000 @@ -10,6 +10,7 @@ #ifndef _LINUX_SERIAL_H #define _LINUX_SERIAL_H +#ifdef __KERNEL__ #include /* @@ -27,10 +28,12 @@ */ #define SERIAL_XMIT_SIZE PAGE_SIZE +#endif + struct serial_struct { int type; int line; - unsigned long port; + unsigned int port; int irq; int flags; int xmit_fifo_size; @@ -44,7 +47,8 @@ unsigned short closing_wait2; /* no longer used... */ unsigned char *iomem_base; unsigned short iomem_reg_shift; - int reserved[2]; + unsigned int port_high; + int reserved[1]; }; /* @@ -70,7 +74,8 @@ #define PORT_16C950 10 /* Oxford Semiconductor */ #define PORT_16654 11 #define PORT_16850 12 -#define PORT_MAX 12 +#define PORT_RSA 13 /* RSA-DV II/S card */ +#define PORT_MAX 13 #define SERIAL_IO_PORT 0 #define SERIAL_IO_HUB6 1 @@ -115,7 +120,10 @@ #define ASYNC_LOW_LATENCY 0x2000 /* Request low latency behaviour */ -#define ASYNC_FLAGS 0x3FFF /* Possible legal async flags */ +#define ASYNC_BUGGY_UART 0x4000 /* This is a buggy UART, skip some safety + * checks. Note: can be dangerous! */ + +#define ASYNC_FLAGS 0x7FFF /* Possible legal async flags */ #define ASYNC_USR_MASK 0x3430 /* Legal flags that non-privileged * users can set or reset */ @@ -127,7 +135,9 @@ #define ASYNC_CLOSING 0x08000000 /* Serial port is closing */ #define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ #define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ -#define ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards */ +#define ASYNC_SHARE_IRQ 0x01000000 /* for multifunction cards + --- no longer used */ +#define ASYNC_AUTOPROBE 0x00800000 /* Port was autoprobed */ #define ASYNC_INTERNAL_FLAGS 0xFF000000 /* Internal flags */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/serialP.h linux.ac/include/linux/serialP.h --- linux.vanilla/include/linux/serialP.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/serialP.h Sat Jun 10 22:25:51 2000 @@ -24,6 +24,11 @@ #include #include #include +#if (LINUX_VERSION_CODE < 0x020300) +/* Unfortunate, but Linux 2.2 needs async_icount defined here and + * it got moved in 2.3 */ +#include +#endif struct serial_state { int magic; @@ -190,6 +195,9 @@ /* Do not use irq sharing for this device */ #define SPCI_FL_NO_SHIRQ 0x1000 -#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE) +/* This is a PNP device */ +#define SPCI_FL_ISPNP 0x2000 + +#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP) #endif /* _LINUX_SERIAL_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/serial_reg.h linux.ac/include/linux/serial_reg.h --- linux.vanilla/include/linux/serial_reg.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/serial_reg.h Tue May 30 14:53:12 2000 @@ -229,5 +229,54 @@ #define UART_TRG_120 0x78 #define UART_TRG_128 0x80 +/* + * These definitions are for the RSA-DV II/S card, from + * + * Kiyokazu SUTO + */ + +#define UART_RSA_BASE (-8) + +#define UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */ + +#define UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */ +#define UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */ +#define UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */ +#define UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */ + +#define UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */ + +#define UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */ +#define UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */ +#define UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */ +#define UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */ +#define UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */ + +#define UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */ + +#define UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */ +#define UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */ +#define UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */ +#define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */ +#define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */ +#define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */ +#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occured (1) */ +#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occured */ + +#define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */ + +#define UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */ + +#define UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */ + +#define UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */ + +/* + * The RSA DSV/II board has two fixed clock frequencies. One is the + * standard rate, and the other is 8 times faster. + */ +#define SERIAL_RSA_BAUD_BASE (921600) +#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8) + #endif /* _LINUX_SERIAL_REG_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/shm.h linux.ac/include/linux/shm.h --- linux.vanilla/include/linux/shm.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/shm.h Tue Jun 6 12:27:47 2000 @@ -2,7 +2,7 @@ #define _LINUX_SHM_H_ #include -#include +#include /* * SHMMAX, SHMMNI and SHMALL are upper limits are defaults which can diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/skbuff.h linux.ac/include/linux/skbuff.h --- linux.vanilla/include/linux/skbuff.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/skbuff.h Sat Jun 10 22:25:00 2000 @@ -168,17 +168,8 @@ #include extern void __kfree_skb(struct sk_buff *skb); -extern void skb_queue_head_init(struct sk_buff_head *list); -extern void skb_queue_head(struct sk_buff_head *list,struct sk_buff *buf); -extern void skb_queue_tail(struct sk_buff_head *list,struct sk_buff *buf); -extern struct sk_buff * skb_dequeue(struct sk_buff_head *list); -extern void skb_insert(struct sk_buff *old,struct sk_buff *newsk); -extern void skb_append(struct sk_buff *old,struct sk_buff *newsk); -extern void skb_unlink(struct sk_buff *buf); -extern __u32 skb_queue_len(struct sk_buff_head *list); extern struct sk_buff * skb_peek_copy(struct sk_buff_head *list); extern struct sk_buff * alloc_skb(unsigned int size, int priority); -extern struct sk_buff * dev_alloc_skb(unsigned int size); extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority); extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority); @@ -187,13 +178,6 @@ int newtailroom, int priority); #define dev_kfree_skb(a) kfree_skb(a) -extern unsigned char * skb_put(struct sk_buff *skb, unsigned int len); -extern unsigned char * skb_push(struct sk_buff *skb, unsigned int len); -extern unsigned char * skb_pull(struct sk_buff *skb, unsigned int len); -extern int skb_headroom(const struct sk_buff *skb); -extern int skb_tailroom(const struct sk_buff *skb); -extern void skb_reserve(struct sk_buff *skb, unsigned int len); -extern void skb_trim(struct sk_buff *skb, unsigned int len); extern void skb_over_panic(struct sk_buff *skb, int len, void *here); extern void skb_under_panic(struct sk_buff *skb, int len, void *here); @@ -201,7 +185,7 @@ #define skb_realloc_headroom(skb, nhr) skb_copy_expand(skb, nhr, skb_tailroom(skb), GFP_ATOMIC) /* Internal */ -extern __inline__ atomic_t *skb_datarefp(struct sk_buff *skb) +static inline atomic_t *skb_datarefp(struct sk_buff *skb) { return (atomic_t *)(skb->end); } @@ -213,7 +197,7 @@ * Returns true if the queue is empty, false otherwise. */ -extern __inline__ int skb_queue_empty(struct sk_buff_head *list) +static inline int skb_queue_empty(struct sk_buff_head *list) { return (list->next == (struct sk_buff *) list); } @@ -226,7 +210,7 @@ * to the buffer. */ -extern __inline__ struct sk_buff *skb_get(struct sk_buff *skb) +static inline struct sk_buff *skb_get(struct sk_buff *skb) { atomic_inc(&skb->users); return skb; @@ -245,14 +229,14 @@ * hit zero. */ -extern __inline__ void kfree_skb(struct sk_buff *skb) +static inline void kfree_skb(struct sk_buff *skb) { if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users)) __kfree_skb(skb); } /* Use this if you didn't touch the skb state [for fast switching] */ -extern __inline__ void kfree_skb_fast(struct sk_buff *skb) +static inline void kfree_skb_fast(struct sk_buff *skb) { if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users)) kfree_skbmem(skb); @@ -267,7 +251,7 @@ * shared data so must not be written to under normal circumstances. */ -extern __inline__ int skb_cloned(struct sk_buff *skb) +static inline int skb_cloned(struct sk_buff *skb) { return skb->cloned && atomic_read(skb_datarefp(skb)) != 1; } @@ -280,7 +264,7 @@ * buffer. */ -extern __inline__ int skb_shared(struct sk_buff *skb) +static inline int skb_shared(struct sk_buff *skb) { return (atomic_read(&skb->users) != 1); } @@ -299,7 +283,7 @@ * NULL is returned on a memory allocation failure. */ -extern __inline__ struct sk_buff *skb_share_check(struct sk_buff *skb, int pri) +static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri) { if (skb_shared(skb)) { struct sk_buff *nskb; @@ -332,7 +316,7 @@ * %NULL is returned on a memory allocation failure. */ -extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri) +static inline struct sk_buff *skb_unshare(struct sk_buff *skb, int pri) { struct sk_buff *nskb; if(!skb_cloned(skb)) @@ -356,7 +340,7 @@ * volatile. Use with caution. */ -extern __inline__ struct sk_buff *skb_peek(struct sk_buff_head *list_) +static inline struct sk_buff *skb_peek(struct sk_buff_head *list_) { struct sk_buff *list = ((struct sk_buff *)list_)->next; if (list == (struct sk_buff *)list_) @@ -378,7 +362,7 @@ * volatile. Use with caution. */ -extern __inline__ struct sk_buff *skb_peek_tail(struct sk_buff_head *list_) +static inline struct sk_buff *skb_peek_tail(struct sk_buff_head *list_) { struct sk_buff *list = ((struct sk_buff *)list_)->prev; if (list == (struct sk_buff *)list_) @@ -393,12 +377,12 @@ * Return the length of an &sk_buff queue. */ -extern __inline__ __u32 skb_queue_len(struct sk_buff_head *list_) +static inline __u32 skb_queue_len(struct sk_buff_head *list_) { return(list_->qlen); } -extern __inline__ void skb_queue_head_init(struct sk_buff_head *list) +static inline void skb_queue_head_init(struct sk_buff_head *list) { spin_lock_init(&list->lock); list->prev = (struct sk_buff *)list; @@ -424,7 +408,7 @@ * A buffer cannot be placed on two lists at the same time. */ -extern __inline__ void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) +static inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) { struct sk_buff *prev, *next; @@ -451,7 +435,7 @@ * A buffer cannot be placed on two lists at the same time. */ -extern __inline__ void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) +static inline void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) { unsigned long flags; @@ -472,7 +456,7 @@ */ -extern __inline__ void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +static inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) { struct sk_buff *prev, *next; @@ -498,7 +482,7 @@ * A buffer cannot be placed on two lists at the same time. */ -extern __inline__ void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) +static inline void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) { unsigned long flags; @@ -516,7 +500,7 @@ * returned or %NULL if the list is empty. */ -extern __inline__ struct sk_buff *__skb_dequeue(struct sk_buff_head *list) +static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) { struct sk_buff *next, *prev, *result; @@ -545,7 +529,7 @@ * returned or %NULL if the list is empty. */ -extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list) +static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list) { long flags; struct sk_buff *result; @@ -560,7 +544,7 @@ * Insert a packet on a list. */ -extern __inline__ void __skb_insert(struct sk_buff *newsk, +static inline void __skb_insert(struct sk_buff *newsk, struct sk_buff * prev, struct sk_buff *next, struct sk_buff_head * list) { @@ -582,7 +566,7 @@ * A buffer cannot be placed on two lists at the same time. */ -extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk) +static inline void skb_insert(struct sk_buff *old, struct sk_buff *newsk) { unsigned long flags; @@ -595,7 +579,7 @@ * Place a packet after a given packet in a list. */ -extern __inline__ void __skb_append(struct sk_buff *old, struct sk_buff *newsk) +static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk) { __skb_insert(newsk, old, old->next, old->list); } @@ -611,7 +595,7 @@ */ -extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk) +static inline void skb_append(struct sk_buff *old, struct sk_buff *newsk) { unsigned long flags; @@ -625,7 +609,7 @@ * the list known.. */ -extern __inline__ void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) +static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) { struct sk_buff * next, * prev; @@ -652,7 +636,7 @@ * destroyed. */ -extern __inline__ void skb_unlink(struct sk_buff *skb) +static inline void skb_unlink(struct sk_buff *skb) { struct sk_buff_head *list = skb->list; @@ -677,7 +661,7 @@ * returned or %NULL if the list is empty. */ -extern __inline__ struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) +static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek_tail(list); if (skb) @@ -694,7 +678,7 @@ * returned or %NULL if the list is empty. */ -extern __inline__ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) +static inline struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) { long flags; struct sk_buff *result; @@ -709,7 +693,7 @@ * Add data to an sk_buff */ -extern __inline__ unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) +static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) { unsigned char *tmp=skb->tail; skb->tail+=len; @@ -727,7 +711,7 @@ * first byte of the extra data is returned. */ -extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len) +static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len) { unsigned char *tmp=skb->tail; skb->tail+=len; @@ -738,7 +722,7 @@ return tmp; } -extern __inline__ unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) +static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) { skb->data-=len; skb->len+=len; @@ -755,7 +739,7 @@ * panic. A pointer to the first byte of the extra data is returned. */ -extern __inline__ unsigned char *skb_push(struct sk_buff *skb, unsigned int len) +static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len) { skb->data-=len; skb->len+=len; @@ -765,7 +749,7 @@ return skb->data; } -extern __inline__ char *__skb_pull(struct sk_buff *skb, unsigned int len) +static inline char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len-=len; return skb->data+=len; @@ -782,7 +766,7 @@ * the old data. */ -extern __inline__ unsigned char * skb_pull(struct sk_buff *skb, unsigned int len) +static inline unsigned char * skb_pull(struct sk_buff *skb, unsigned int len) { if (len > skb->len) return NULL; @@ -796,7 +780,7 @@ * Return the number of bytes of free space at the head of an &sk_buff. */ -extern __inline__ int skb_headroom(const struct sk_buff *skb) +static inline int skb_headroom(const struct sk_buff *skb) { return skb->data-skb->head; } @@ -808,7 +792,7 @@ * Return the number of bytes of free space at the tail of an sk_buff */ -extern __inline__ int skb_tailroom(const struct sk_buff *skb) +static inline int skb_tailroom(const struct sk_buff *skb) { return skb->end-skb->tail; } @@ -822,14 +806,14 @@ * room. This is only allowed for an empty buffer. */ -extern __inline__ void skb_reserve(struct sk_buff *skb, unsigned int len) +static inline void skb_reserve(struct sk_buff *skb, unsigned int len) { skb->data+=len; skb->tail+=len; } -extern __inline__ void __skb_trim(struct sk_buff *skb, unsigned int len) +static inline void __skb_trim(struct sk_buff *skb, unsigned int len) { skb->len = len; skb->tail = skb->data+len; @@ -844,7 +828,7 @@ * the buffer is already under the length specified it is not modified. */ -extern __inline__ void skb_trim(struct sk_buff *skb, unsigned int len) +static inline void skb_trim(struct sk_buff *skb, unsigned int len) { if (skb->len > len) { __skb_trim(skb, len); @@ -861,7 +845,7 @@ */ -extern __inline__ void skb_orphan(struct sk_buff *skb) +static inline void skb_orphan(struct sk_buff *skb) { if (skb->destructor) skb->destructor(skb); @@ -879,7 +863,7 @@ */ -extern __inline__ void skb_queue_purge(struct sk_buff_head *list) +static inline void skb_queue_purge(struct sk_buff_head *list) { struct sk_buff *skb; while ((skb=skb_dequeue(list))!=NULL) @@ -896,7 +880,7 @@ */ -extern __inline__ void __skb_queue_purge(struct sk_buff_head *list) +static inline void __skb_queue_purge(struct sk_buff_head *list) { struct sk_buff *skb; while ((skb=__skb_dequeue(list))!=NULL) @@ -916,7 +900,7 @@ * allocates memory it can be called from an interrupt. */ -extern __inline__ struct sk_buff *dev_alloc_skb(unsigned int length) +static inline struct sk_buff *dev_alloc_skb(unsigned int length) { struct sk_buff *skb; @@ -942,7 +926,7 @@ */ -extern __inline__ struct sk_buff * +static inline struct sk_buff * skb_cow(struct sk_buff *skb, unsigned int headroom) { headroom = (headroom+15)&~15; @@ -965,13 +949,13 @@ extern void skb_add_mtu(int mtu); #ifdef CONFIG_NETFILTER -extern __inline__ void +static inline void nf_conntrack_put(struct nf_ct_info *nfct) { if (nfct && atomic_dec_and_test(&nfct->master->use)) nfct->master->destroy(nfct->master); } -extern __inline__ void +static inline void nf_conntrack_get(struct nf_ct_info *nfct) { if (nfct) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/sunrpc/debug.h linux.ac/include/linux/sunrpc/debug.h --- linux.vanilla/include/linux/sunrpc/debug.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/sunrpc/debug.h Sun Jun 4 22:31:17 2000 @@ -9,13 +9,17 @@ #ifndef _LINUX_SUNRPC_DEBUG_H_ #define _LINUX_SUNRPC_DEBUG_H_ +#include + #include #include /* * Enable RPC debugging/profiling. */ +#ifdef CONFIG_SYSCTL #define RPC_DEBUG +#endif /* #define RPC_PROFILE */ /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/swap.h linux.ac/include/linux/swap.h --- linux.vanilla/include/linux/swap.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/swap.h Tue Jun 6 16:11:06 2000 @@ -161,6 +161,16 @@ extern spinlock_t pagemap_lru_lock; /* + * Magic constants for page aging. If the system is programmed + * right, tweaking these should have almost no effect... + * The 2.4 code, however, is mostly simple and stable ;) + */ +#define PG_AGE_MAX 64 +#define PG_AGE_START 2 +#define PG_AGE_ADV 3 +#define PG_AGE_DECL 1 + +/* * Helper macros for lru_pages handling. */ #define lru_cache_add(page) \ @@ -168,12 +178,16 @@ spin_lock(&pagemap_lru_lock); \ list_add(&(page)->lru, &lru_cache); \ nr_lru_pages++; \ + page->age = PG_AGE_START; \ + ClearPageReferenced(page); \ + SetPageActive(page); \ spin_unlock(&pagemap_lru_lock); \ } while (0) #define __lru_cache_del(page) \ do { \ list_del(&(page)->lru); \ + ClearPageActive(page); \ nr_lru_pages--; \ } while (0) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/sysv_fs.h linux.ac/include/linux/sysv_fs.h --- linux.vanilla/include/linux/sysv_fs.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/sysv_fs.h Sat Jun 10 23:04:57 2000 @@ -379,7 +379,7 @@ extern void sysv_truncate(struct inode *); extern void sysv_write_inode(struct inode *); extern int sysv_sync_inode(struct inode *); -extern int sysv_sync_file(struct file *, struct dentry *); +extern int sysv_sync_file(struct file *, struct dentry *, int); extern int sysv_notify_change(struct dentry *, struct iattr *); extern struct inode_operations sysv_file_inode_operations; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/timer.h linux.ac/include/linux/timer.h --- linux.vanilla/include/linux/timer.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/timer.h Sun Jun 4 22:04:00 2000 @@ -1,6 +1,8 @@ #ifndef _LINUX_TIMER_H #define _LINUX_TIMER_H +#ifdef __KERNEL__ + #include #include @@ -91,9 +93,11 @@ #define timer_set_running(t) (void)(t) #define timer_is_running(t) (0) #define timer_synchronize(t) do { (void)(t); barrier(); } while(0) -#define del_timer_sync(t) del_timer(t) +#define del_timer_sync del_timer #endif +#define del_timer_async del_timer + /* * These inlines deal with timer wrapping correctly. You are * strongly encouraged to use them @@ -111,4 +115,5 @@ #define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) #define time_before_eq(a,b) time_after_eq(b,a) +#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/types.h linux.ac/include/linux/types.h --- linux.vanilla/include/linux/types.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/types.h Sat May 27 22:01:22 2000 @@ -1,7 +1,10 @@ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H +#ifdef __KERNEL__ #include +#endif + #include #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/usb.h linux.ac/include/linux/usb.h --- linux.vanilla/include/linux/usb.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/usb.h Sat Jun 10 22:40:52 2000 @@ -307,6 +307,8 @@ struct file_operations *fops; int minor; + + struct semaphore serialize; }; /* @@ -492,7 +494,7 @@ int bandwidth_isoc_reqs; /* number of Isoc. requesters */ /* usbdevfs inode list */ - struct list_head inodes; + struct list_head inodes; }; #define USB_MAXCHILDREN (8) /* This is arbitrary */ @@ -506,7 +508,6 @@ unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ /* [0] = IN, [1] = OUT */ - struct usb_config_descriptor *actconfig;/* the active configuration */ int epmaxpacketin[16]; /* INput endpoint specific maximums */ int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ @@ -515,6 +516,9 @@ struct usb_device_descriptor descriptor;/* Descriptor */ struct usb_config_descriptor *config; /* All of the configs */ + struct usb_config_descriptor *actconfig;/* the active configuration */ + + char **rawdescriptors; /* Raw descriptors for each config */ int have_langid; /* whether string_langid is valid yet */ int string_langid; /* language ID for strings */ @@ -522,8 +526,8 @@ void *hcpriv; /* Host Controller private data */ /* usbdevfs inode list */ - struct list_head inodes; - struct list_head filelist; + struct list_head inodes; + struct list_head filelist; /* * Child devices - these can be either new devices @@ -536,6 +540,8 @@ int maxchild; /* Number of ports if hub */ struct usb_device *children[USB_MAXCHILDREN]; }; + +extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); extern int usb_register(struct usb_driver *); extern void usb_deregister(struct usb_driver *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/usbdevice_fs.h linux.ac/include/linux/usbdevice_fs.h --- linux.vanilla/include/linux/usbdevice_fs.h Thu May 25 17:37:34 2000 +++ linux.ac/include/linux/usbdevice_fs.h Sat Jun 10 22:49:58 2000 @@ -66,6 +66,18 @@ void *context; }; +#define USBDEVFS_MAXDRIVERNAME 255 + +struct usbdevfs_getdriver { + unsigned int interface; + char driver[USBDEVFS_MAXDRIVERNAME + 1]; +}; + +struct usbdevfs_connectinfo { + unsigned int devnum; + unsigned char slow; +}; + #define USBDEVFS_URB_DISABLE_SPD 1 #define USBDEVFS_URB_ISO_ASAP 2 @@ -101,6 +113,7 @@ #define USBDEVFS_RESETEP _IOR('U', 3, unsigned int) #define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface) #define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int) +#define USBDEVFS_GETDRIVER _IOW('U', 8, struct usbdevfs_getdriver) #define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb) #define USBDEVFS_DISCARDURB _IO('U', 11) #define USBDEVFS_REAPURB _IOW('U', 12, void *) @@ -108,6 +121,7 @@ #define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal) #define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int) #define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int) +#define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo) /* --------------------------------------------------------------------- */ @@ -164,7 +178,6 @@ extern struct inode_operations usbdevfs_bus_inode_operations; extern struct file_operations usbdevfs_bus_file_operations; extern void usbdevfs_conn_disc_event(void); - #endif /* __KERNEL__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/wrapper.h linux.ac/include/linux/wrapper.h --- linux.vanilla/include/linux/wrapper.h Thu May 25 17:37:33 2000 +++ linux.ac/include/linux/wrapper.h Sat Jun 10 22:18:34 2000 @@ -19,9 +19,6 @@ #define module_unregister_blkdev unregister_blkdev #define inode_get_rdev(i) i->i_rdev -#define inode_get_count(i) i->i_count -#define inode_inc_count(i) i->i_count++ -#define inode_dec_count(i) i->i_count-- #define file_get_flags(f) f->f_flags diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/scsi/sg.h linux.ac/include/scsi/sg.h --- linux.vanilla/include/scsi/sg.h Thu May 25 17:37:35 2000 +++ linux.ac/include/scsi/sg.h Mon Jun 5 19:14:46 2000 @@ -11,9 +11,18 @@ Version 2 and 3 extensions to driver: * Copyright (C) 1998 - 2000 Douglas Gilbert - Version: 3.1.13 (20000323) + Version: 3.1.15 (20000528) This version is for 2.3/2.4 series kernels. + Changes since 3.1.14 (20000503) + - fix aha1542 odd length buffer problem + - make multiple readers on same fd safe + Changes since 3.1.13 (20000324) + - revert change so sg_header interface doesn't send _UNKNOWN + - "discon" and "tq" in /proc/scsi/sg/devices replaced with + "bopens" and "busy"; correct duration output in procfs + - provision for SG_RESET + - lock file descriptor and request lists Changes since 3.1.12 (20000222) - make sg_header interface use SCSI_DATA_UNKNOWN - add SG_DXFER_UNKNOWN define to sg interface @@ -49,10 +58,9 @@ 2.1.31 2.2.6 and 2.2.7 2.1.32 2.2.8 and 2.2.9 2.1.34 2.2.10 to 2.2.13 - 2.1.36 2.2.14 - 2.3.35 2.3.x development series kernels (starting 2.3.20) + 2.1.36 2.2.14 and 2.2.15 3.0.x optional version 3 sg driver for 2.2 series - 3.1.x candidate version 3 sg driver for 2.3 series + 3.1.x first appeared in lk 2.3.43 Major new features in SG 3.x driver (cf SG 2.x drivers) - SG_IO ioctl() combines function if write() and read() @@ -100,10 +108,10 @@ The main documents are still based on 2.x versions: http://www.torque.net/sg/p/scsi-generic.txt http://www.torque.net/sg/p/scsi-generic_long.txt - The first document can also be found in the kernel source tree, probably at: - /usr/src/linux/Documentation/scsi-generic.txt . Documentation on the changes and additions in 3.x version of the sg driver can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt + This document can also be found in the kernel source tree, probably at: + /usr/src/linux/Documentation/scsi-generic.txt . Utility and test programs are also available at that web site. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/init/main.c linux.ac/init/main.c --- linux.vanilla/init/main.c Thu May 25 17:46:16 2000 +++ linux.ac/init/main.c Thu May 25 17:59:08 2000 @@ -737,7 +737,8 @@ #ifdef CONFIG_BLK_DEV_INITRD root_mountflags = real_root_mountflags; - if (mount_initrd && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) { + if (mount_initrd && ROOT_DEV != real_root_dev + && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) { int error; int i, pid; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/ipc/shm.c linux.ac/ipc/shm.c --- linux.vanilla/ipc/shm.c Thu May 25 17:37:50 2000 +++ linux.ac/ipc/shm.c Tue Jun 6 12:27:47 2000 @@ -16,11 +16,9 @@ * * The filesystem has the following restrictions/bugs: * 1) It only can handle one directory. - * 2) Because the directory is represented by the SYSV shm array it - * can only be mounted one time. - * 3) Private writeable mappings are not supported - * 4) Read and write are not implemented (should they?) - * 5) No special nodes are supported + * 2) Private writeable mappings are not supported + * 3) Read and write are not implemented (should they?) + * 4) No special nodes are supported * * There are the following mount options: * - nr_blocks (^= shmall) is the number of blocks of size PAGE_SIZE @@ -335,7 +333,7 @@ return (struct shmid_kernel *)ipc_rmid(&shm_ids,id); } -static __inline__ int shm_addid(struct shmid_kernel *shp) +static inline int shm_addid(struct shmid_kernel *shp) { return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); } @@ -544,13 +542,37 @@ return 0; } -#define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTRS_PER_PTE][(index)%PTRS_PER_PTE] +/* + * We cannot use kmalloc for shm_alloc since this restricts the + * maximum size of the segments. + * + * We also cannot use vmalloc, since this uses too much of the vmalloc + * space and we run out of this on highend machines. + * + * So we have to use this complicated indirect scheme to alloc the shm + * page tables. + * + */ + +#ifdef PTE_INIT +static inline void init_ptes (pte_t *pte, int number) { + while (number--) + PTE_INIT (pte++); +} +#else +static inline void init_ptes (pte_t *pte, int number) { + memset (pte, 0, number*sizeof(*pte)); +} +#endif + +#define PTES_PER_PAGE (PAGE_SIZE/sizeof(pte_t)) +#define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTES_PER_PAGE][(index)%PTES_PER_PAGE] static pte_t **shm_alloc(unsigned long pages, int doacc) { - unsigned short dir = pages / PTRS_PER_PTE; - unsigned short last = pages % PTRS_PER_PTE; - pte_t **ret, **ptr, *pte; + unsigned short dir = pages / PTES_PER_PAGE; + unsigned short last = pages % PTES_PER_PAGE; + pte_t **ret, **ptr; if (pages == 0) return NULL; @@ -564,8 +586,7 @@ *ptr = (pte_t *)__get_free_page (GFP_KERNEL); if (!*ptr) goto free; - for (pte = *ptr; pte < *ptr + PTRS_PER_PTE; pte++) - pte_clear (pte); + init_ptes (*ptr, PTES_PER_PAGE); } /* The last one is probably not of PAGE_SIZE: we use kmalloc */ @@ -573,8 +594,7 @@ *ptr = kmalloc (last*sizeof(pte_t), GFP_KERNEL); if (!*ptr) goto free; - for (pte = *ptr; pte < *ptr + last; pte++) - pte_clear (pte); + init_ptes (*ptr, last); } if (doacc) { shm_lockall(); @@ -597,14 +617,14 @@ static void shm_free(pte_t** dir, unsigned long pages, int doacc) { int i, rss, swp; - pte_t **ptr = dir+pages/PTRS_PER_PTE; + pte_t **ptr = dir+pages/PTES_PER_PAGE; if (!dir) return; for (i = 0, rss = 0, swp = 0; i < pages ; i++) { pte_t pte; - pte = dir[i/PTRS_PER_PTE][i%PTRS_PER_PTE]; + pte = dir[i/PTES_PER_PAGE][i%PTES_PER_PAGE]; if (pte_none(pte)) continue; if (pte_present(pte)) { @@ -617,7 +637,7 @@ } /* first the last page */ - if (pages%PTRS_PER_PTE) + if (pages%PTES_PER_PAGE) kfree (*ptr); /* now the whole pages */ while (--ptr >= dir) @@ -663,10 +683,10 @@ BUG(); error = -ENOSPC; if (shm_tot - shp->shm_npages >= shm_ctlall) - goto out; + goto size_out; error = 0; if (shp->shm_segsz == attr->ia_size) - goto out; + goto size_out; /* Now we set them to the real values */ old_dir = shp->shm_dir; old_pages = shp->shm_npages; @@ -674,8 +694,8 @@ pte_t *swap; int i,j; i = old_pages < new_pages ? old_pages : new_pages; - j = i % PTRS_PER_PTE; - i /= PTRS_PER_PTE; + j = i % PTES_PER_PAGE; + i /= PTES_PER_PAGE; if (j) memcpy (new_dir[i], old_dir[i], j * sizeof (pte_t)); while (i--) { @@ -687,10 +707,21 @@ shp->shm_dir = new_dir; shp->shm_npages = new_pages; shp->shm_segsz = attr->ia_size; -out: +size_out: shm_unlock(inode->i_ino); shm_free (old_dir, old_pages, 1); + set_attr: + if (!(shp = shm_lock(inode->i_ino))) + BUG(); + if (attr->ia_valid & ATTR_MODE) + shp->shm_perm.mode = attr->ia_mode; + if (attr->ia_valid & ATTR_UID) + shp->shm_perm.uid = attr->ia_uid; + if (attr->ia_valid & ATTR_GID) + shp->shm_perm.gid = attr->ia_gid; + shm_unlock (inode->i_ino); + inode_setattr(inode, attr); return error; } @@ -1073,6 +1104,9 @@ case IPC_SET: { + struct dentry * dentry; + char name[SHM_FMT_LEN+1]; + if ((shmid % SEQ_MULTIPLIER)== zero_id) return -EINVAL; @@ -1098,7 +1132,29 @@ shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO) | (setbuf.mode & S_IRWXUGO); shp->shm_ctim = CURRENT_TIME; - break; + shm_unlock(shmid); + up(&shm_ids.sem); + + sprintf (name, SHM_FMT, shmid); + lock_kernel(); + dentry = lookup_one(name, lock_parent(shm_sb->s_root)); + unlock_dir(shm_sb->s_root); + err = PTR_ERR(dentry); + if (IS_ERR(dentry)) + goto bad_dentry; + err = -ENOENT; + if (dentry->d_inode) { + struct inode *ino = dentry->d_inode; + ino->i_uid = setbuf.uid; + ino->i_gid = setbuf.gid; + ino->i_mode = (setbuf.mode & S_IRWXUGO) | (ino->i_mode & ~S_IALLUGO);; + ino->i_atime = ino->i_mtime = ino->i_ctime = CURRENT_TIME; + err = 0; + } + dput (dentry); + bad_dentry: + unlock_kernel(); + return err; } default: @@ -1142,6 +1198,7 @@ */ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) { + struct shmid_kernel *shp; unsigned long addr; struct file * file; int err; @@ -1169,13 +1226,25 @@ if (shmflg & SHM_RDONLY) { prot = PROT_READ; o_flags = O_RDONLY; - acc_mode = MAY_READ; + acc_mode = S_IRUGO; } else { prot = PROT_READ | PROT_WRITE; o_flags = O_RDWR; - acc_mode = MAY_READ | MAY_WRITE; + acc_mode = S_IRUGO | S_IWUGO; } + /* + * We cannot rely on the fs check since SYSV IPC does have an + * aditional creator id... + */ + shp = shm_lock(shmid); + if(shp==NULL) + return -EINVAL; + err = ipcperms(&shp->shm_perm, acc_mode); + shm_unlock(shmid); + if (err) + return -EACCES; + sprintf (name, SHM_FMT, shmid); lock_kernel(); @@ -1188,9 +1257,6 @@ err = -ENOENT; if (!dentry->d_inode) goto bad_file; - err = permission(dentry->d_inode, acc_mode); - if (err) - goto bad_file1; file = dentry_open(dentry, shm_fs_type.kern_mnt, o_flags); err = PTR_ERR(file); if (IS_ERR (file)) @@ -1492,7 +1558,7 @@ shm_lockall(); check_id: shp = shm_get(swap_id); - if(shp==NULL || shp->shm_flags & SHM_LOCKED) { + if(shp==NULL || shp->shm_flags & PRV_LOCKED) { next_id: swap_idx = 0; if (++swap_id > shm_ids.max_id) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/ipc/util.c linux.ac/ipc/util.c --- linux.vanilla/ipc/util.c Thu May 25 17:37:50 2000 +++ linux.ac/ipc/util.c Sun Jun 4 22:06:32 2000 @@ -310,7 +310,7 @@ int map_zero_setup(struct vm_area_struct *vma) { - return -EINVAL; + return -ENOSYS; } #endif /* CONFIG_SYSVIPC */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/acct.c linux.ac/kernel/acct.c --- linux.vanilla/kernel/acct.c Thu May 25 17:46:17 2000 +++ linux.ac/kernel/acct.c Sun Jun 4 22:17:00 2000 @@ -37,6 +37,10 @@ * one race (and leak) in BSD implementation. * OK, that's better. ANOTHER race and leak in BSD variant. There always * is one more bug... 10/11/98, AV. + * + * Oh, fsck... Oopsable SMP race in do_process_acct() - we must hold + * ->mmap_sem to walk the vma list of current->mm. Nasty, since it leaks + * a struct file opened for write. Fixed. 2/6/2000, AV. */ #include @@ -66,7 +70,6 @@ /* * External references and all of the globals. */ -void acct_timeout(unsigned long); static volatile int acct_active; static volatile int acct_needcheck; @@ -77,7 +80,7 @@ /* * Called whenever the timer says to check the free space. */ -void acct_timeout(unsigned long unused) +static void acct_timeout(unsigned long unused) { acct_needcheck = 1; } @@ -303,11 +306,14 @@ vsize = 0; if (current->mm) { - struct vm_area_struct *vma = current->mm->mmap; + struct vm_area_struct *vma; + down(¤t->mm->mmap_sem); + vma = current->mm->mmap; while (vma) { vsize += vma->vm_end - vma->vm_start; vma = vma->vm_next; } + up(¤t->mm->mmap_sem); } vsize = vsize / 1024; ac.ac_mem = encode_comp_t(vsize); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/capability.c linux.ac/kernel/capability.c --- linux.vanilla/kernel/capability.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/capability.c Wed May 31 11:17:01 2000 @@ -8,6 +8,8 @@ #include #include +kernel_cap_t cap_bset = CAP_INIT_EFF_SET; + /* Note: never hold tasklist_lock while spinning for this one */ spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED; @@ -16,8 +18,6 @@ * capability set pointers may be NULL -- indicating that that set is * uninteresting and/or not to be changed. */ - -kernel_cap_t cap_bset = CAP_FULL_SET; asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/dma.c linux.ac/kernel/dma.c --- linux.vanilla/kernel/dma.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/dma.c Wed May 31 11:36:24 2000 @@ -115,9 +115,8 @@ return -EINVAL; } -int free_dma(unsigned int dmanr) +void free_dma(unsigned int dmanr) { - return -EINVAL; } int get_dma_list(char *buf) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/exec_domain.c linux.ac/kernel/exec_domain.c --- linux.vanilla/kernel/exec_domain.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/exec_domain.c Sat Jun 10 22:59:46 2000 @@ -104,32 +104,37 @@ void __set_personality(unsigned long personality) { - struct exec_domain *it; + struct exec_domain *it, *prev; it = lookup_exec_domain(personality); - if (it) { - if (atomic_read(¤t->fs->count) != 1) { - struct fs_struct *new = copy_fs_struct(current->fs); - struct fs_struct *old; - if (!new) { - put_exec_domain(it); - return; - } - task_lock(current); - old = current->fs; - current->fs = new; - task_unlock(current); - put_fs_struct(old); - } - /* - * At that point we are guaranteed to be the sole owner of - * current->fs. - */ + if (it == current->exec_domain) { current->personality = personality; - current->exec_domain = it; - set_fs_altroot(); - put_exec_domain(current->exec_domain); + return; + } + if (!it) + return; + if (atomic_read(¤t->fs->count) != 1) { + struct fs_struct *new = copy_fs_struct(current->fs); + struct fs_struct *old; + if (!new) { + put_exec_domain(it); + return; + } + task_lock(current); + old = current->fs; + current->fs = new; + task_unlock(current); + put_fs_struct(old); } + /* + * At that point we are guaranteed to be the sole owner of + * current->fs. + */ + current->personality = personality; + prev = current->exec_domain; + current->exec_domain = it; + set_fs_altroot(); + put_exec_domain(prev); } asmlinkage long sys_personality(unsigned long personality) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/exit.c linux.ac/kernel/exit.c --- linux.vanilla/kernel/exit.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/exit.c Thu Jun 8 16:37:33 2000 @@ -432,6 +432,8 @@ printk("Aiee, killing interrupt handler\n"); if (!tsk->pid) panic("Attempted to kill the idle task!"); + if (tsk->pid == 1) + panic("Attempted to kill init!"); tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/kmod.c linux.ac/kernel/kmod.c --- linux.vanilla/kernel/kmod.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/kmod.c Sun Jun 4 22:06:05 2000 @@ -95,9 +95,8 @@ /* Drop the "current user" thing */ free_uid(current); - /* Give kmod all privileges.. */ + /* Give kmod all effective privileges.. */ current->uid = current->euid = current->fsuid = 0; - cap_set_full(current->cap_inheritable); cap_set_full(current->cap_effective); /* Allow execve args to be in kernel space. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/ksyms.c linux.ac/kernel/ksyms.c --- linux.vanilla/kernel/ksyms.c Thu May 25 17:46:17 2000 +++ linux.ac/kernel/ksyms.c Sat Jun 10 22:18:34 2000 @@ -80,6 +80,7 @@ #ifdef CONFIG_MODULES EXPORT_SYMBOL(get_module_symbol); +EXPORT_SYMBOL(put_module_symbol); EXPORT_SYMBOL(try_inc_mod_count); #endif EXPORT_SYMBOL(get_option); @@ -139,6 +140,7 @@ EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iget4); EXPORT_SYMBOL(iput); +EXPORT_SYMBOL(force_delete); EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(follow_down); EXPORT_SYMBOL(path_init); @@ -294,6 +296,8 @@ EXPORT_SYMBOL(max_sectors); EXPORT_SYMBOL(max_readahead); EXPORT_SYMBOL(file_moveto); +EXPORT_SYMBOL(drive_stat_acct); +EXPORT_SYMBOL(set_bh_page); /* tty routines */ EXPORT_SYMBOL(tty_hangup); @@ -495,6 +499,7 @@ /* all busmice */ EXPORT_SYMBOL(fasync_helper); +EXPORT_SYMBOL(kill_fasync); #ifdef CONFIG_BLK_DEV_MD EXPORT_SYMBOL(disk_name); /* for md.c */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/module.c linux.ac/kernel/module.c --- linux.vanilla/kernel/module.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/module.c Thu Jun 8 14:54:38 2000 @@ -973,7 +973,9 @@ * Gets the address for a symbol in the given module. If modname is * NULL, it looks for the name in any registered symbol table. If the * modname is an empty string, it looks for the symbol in kernel exported - * symbol tables. + * symbol tables. Increase the usage count of the module in which the + * symbol was found - it's the only way we can guarantee that it's still + * there by the time our caller actually uses it. */ unsigned long get_module_symbol(char *modname, char *symname) @@ -982,6 +984,7 @@ struct module_symbol *sym; int i; + spin_lock(&unload_lock); for (mp = module_list; mp; mp = mp->next) { if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) && MOD_CAN_QUERY(mp) && @@ -990,12 +993,32 @@ i > 0; --i, ++sym) { if (strcmp(sym->name, symname) == 0) { + __MOD_INC_USE_COUNT(mp); + spin_unlock(&unload_lock); return sym->value; } } } } + spin_unlock(&unload_lock); return 0; +} + +/* Decrease the use count of the module containing a symbol with the + * address passed. + */ +void put_module_symbol(unsigned long addr) +{ + struct module *mp; + + for (mp = module_list; mp; mp = mp->next) { + if (MOD_CAN_QUERY(mp) && + addr >= (unsigned long)mp && + addr < (unsigned long)mp + mp->size) { + __MOD_DEC_USE_COUNT(mp); + return; + } + } } #else /* CONFIG_MODULES */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/panic.c linux.ac/kernel/panic.c --- linux.vanilla/kernel/panic.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/panic.c Wed May 31 11:36:24 2000 @@ -19,7 +19,6 @@ asmlinkage void sys_sync(void); /* it's really int */ extern void unblank_console(void); -extern int C_A_D; int panic_timeout; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/signal.c linux.ac/kernel/signal.c --- linux.vanilla/kernel/signal.c Thu May 25 17:46:17 2000 +++ linux.ac/kernel/signal.c Thu Jun 8 17:05:21 2000 @@ -375,7 +375,7 @@ break; } } else if (sig >= SIGRTMIN && info && (unsigned long)info != 1 - && info->si_code < 0) { + && info->si_code != SI_USER) { /* * Queue overflow, abort. We may abort if the signal was rt * and sent by user using something other than kill(). @@ -1109,7 +1109,7 @@ } #endif /* !defined(__alpha__) */ -#if !defined(__alpha__) && !defined(__mips__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) /* * For backwards compatibility. Functionality superseded by sigaction. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sys.c linux.ac/kernel/sys.c --- linux.vanilla/kernel/sys.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/sys.c Wed May 31 11:36:24 2000 @@ -46,7 +46,7 @@ * and the like. */ -struct notifier_block *reboot_notifier_list = NULL; +static struct notifier_block *reboot_notifier_list = NULL; int register_reboot_notifier(struct notifier_block * nb) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/sysctl.c linux.ac/kernel/sysctl.c --- linux.vanilla/kernel/sysctl.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/sysctl.c Wed May 31 11:17:01 2000 @@ -255,9 +255,9 @@ 0444, NULL, &proc_dointvec}, {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int), 0444, NULL, &proc_dointvec}, - {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int), + {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int), 0444, NULL, &proc_dointvec}, - {FS_MAXFILE, "file-max", &max_files, sizeof(int), + {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int), 0644, NULL, &proc_dointvec}, {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int), 0444, NULL, &proc_dointvec}, @@ -803,8 +803,11 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp) { + if (!capable(CAP_SYS_MODULE)) { + return -EPERM; + } return do_proc_dointvec(table,write,filp,buffer,lenp,1, - (current->pid == 1) ? OP_SET : OP_AND); + (current->pid == 1) ? OP_SET : OP_AND); } int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/kernel/timer.c linux.ac/kernel/timer.c --- linux.vanilla/kernel/timer.c Thu May 25 17:37:33 2000 +++ linux.ac/kernel/timer.c Sun Jun 4 22:04:00 2000 @@ -238,7 +238,17 @@ if (!running) return ret; - timer_synchronize(timer); + + { + int count = 50*1000*1000; + while (timer_is_running(timer) && --count) + ; + if (count == 0) { + printk( "del_timer_sync(%p): deadlock! Called from %p\n", + timer, __builtin_return_address(0)); + printk("See http://www.uow.edu.au/~andrewm/linux/deadlock.html\n"); + } + } } return ret; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/lib/vsprintf.c linux.ac/lib/vsprintf.c --- linux.vanilla/lib/vsprintf.c Thu May 25 17:37:33 2000 +++ linux.ac/lib/vsprintf.c Wed May 31 11:36:24 2000 @@ -31,8 +31,8 @@ } } } - while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) - ? toupper(*cp) : *cp)-'A'+10) < base) { + while (isxdigit(*cp) && + (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { result = result*base + value; cp++; } @@ -48,14 +48,11 @@ return simple_strtoul(cp,endp,base); } -/* we use this so that we can do without the ctype library */ -#define is_digit(c) ((c) >= '0' && (c) <= '9') - static int skip_atoi(const char **s) { int i=0; - while (is_digit(**s)) + while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } @@ -175,7 +172,7 @@ /* get field width */ field_width = -1; - if (is_digit(*fmt)) + if (isdigit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; @@ -191,7 +188,7 @@ precision = -1; if (*fmt == '.') { ++fmt; - if (is_digit(*fmt)) + if (isdigit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/filemap.c linux.ac/mm/filemap.c --- linux.vanilla/mm/filemap.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/filemap.c Sat Jun 10 21:51:08 2000 @@ -56,6 +56,8 @@ #define CLUSTER_PAGES (1 << page_cluster) #define CLUSTER_OFFSET(x) (((x) >> page_cluster) << page_cluster) +#define min(a,b) ((a < b) ? a : b) + void __add_page_to_hash_queue(struct page * page, struct page **p) { atomic_inc(&page_cache_size); @@ -90,10 +92,16 @@ /* * Remove a page from the page cache and free it. Caller has to make * sure the page is locked and that nobody else uses it - or that usage - * is safe. + * is safe. We need that the page don't have any buffers. */ static inline void __remove_inode_page(struct page *page) { + if (!PageLocked(page)) + PAGE_BUG(page); + + if (page->buffers) + BUG(); + remove_page_from_inode_queue(page); remove_page_from_hash_queue(page); page->mapping = NULL; @@ -101,9 +109,6 @@ void remove_inode_page(struct page *page) { - if (!PageLocked(page)) - PAGE_BUG(page); - spin_lock(&pagecache_lock); __remove_inode_page(page); spin_unlock(&pagecache_lock); @@ -114,16 +119,16 @@ * @inode: the inode which pages we want to invalidate * * This function only removes the unlocked pages, if you want to - * remove all the pages of one inode, you must call truncate_inode_pages. + * remove all the pages of one inode, you must call + * truncate_inode_pages. This function is not supposed to be called + * by block based filesystems. */ - void invalidate_inode_pages(struct inode * inode) { struct list_head *head, *curr; struct page * page; head = &inode->i_mapping->pages; - spin_lock(&pagecache_lock); spin_lock(&pagemap_lru_lock); curr = head->next; @@ -135,20 +140,53 @@ /* We cannot invalidate a locked page */ if (TryLockPage(page)) continue; + /* We _should not be called_ by block based filesystems */ + if (page->buffers) + BUG(); - __lru_cache_del(page); __remove_inode_page(page); + __lru_cache_del(page); UnlockPage(page); page_cache_release(page); } - spin_unlock(&pagemap_lru_lock); spin_unlock(&pagecache_lock); } -/* +static inline void truncate_partial_page(struct page *page, unsigned partial) +{ + memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); + + if (page->buffers) + block_flushpage(page, partial); + +} + +static inline void truncate_complete_page(struct page *page) +{ + if (page->buffers) + block_destroy_buffers(page); + lru_cache_del(page); + + /* + * We remove the page from the page cache _after_ we have + * destroyed all buffer-cache references to it. Otherwise some + * other process might think this inode page is not in the + * page cache and creates a buffer-cache alias to it causing + * all sorts of fun problems ... + */ + remove_inode_page(page); + page_cache_release(page); +} + +/** + * truncate_inode_pages - truncate *all* the pages from an offset + * @mapping: mapping to truncate + * @lstart: offset from with to truncate + * * Truncate the page cache at a set offset, removing the pages * that are beyond that offset (and zeroing out partial pages). + * If any page is locked we wait for it to become unlocked. */ void truncate_inode_pages(struct address_space * mapping, loff_t lstart) { @@ -168,11 +206,10 @@ page = list_entry(curr, struct page, list); curr = curr->next; - offset = page->index; - /* page wholly truncated - free it */ - if (offset >= start) { + /* Is one of the pages to truncate? */ + if ((offset >= start) || (partial && (offset + 1) == start)) { if (TryLockPage(page)) { page_cache_get(page); spin_unlock(&pagecache_lock); @@ -183,22 +220,14 @@ page_cache_get(page); spin_unlock(&pagecache_lock); - if (!page->buffers || block_flushpage(page, 0)) - lru_cache_del(page); - - /* - * We remove the page from the page cache - * _after_ we have destroyed all buffer-cache - * references to it. Otherwise some other process - * might think this inode page is not in the - * page cache and creates a buffer-cache alias - * to it causing all sorts of fun problems ... - */ - remove_inode_page(page); + if (partial && (offset + 1) == start) { + truncate_partial_page(page, partial); + partial = 0; + } else + truncate_complete_page(page); UnlockPage(page); page_cache_release(page); - page_cache_release(page); /* * We have done things without the pagecache lock, @@ -209,38 +238,59 @@ */ goto repeat; } - /* - * there is only one partial page possible. - */ - if (!partial) - continue; + } + spin_unlock(&pagecache_lock); +} - /* and it's the one preceeding the first wholly truncated page */ - if ((offset + 1) != start) - continue; +/** + * truncate_all_inode_pages - truncate *all* the pages + * @mapping: mapping to truncate + * + * Truncate all the inode pages. If any page is locked we wait for it + * to become unlocked. This function can block. + */ +void truncate_all_inode_pages(struct address_space * mapping) +{ + struct list_head *head, *curr; + struct page * page; + + head = &mapping->pages; +repeat: + spin_lock(&pagecache_lock); + spin_lock(&pagemap_lru_lock); + curr = head->next; + + while (curr != head) { + page = list_entry(curr, struct page, list); + curr = curr->next; - /* partial truncate, clear end of page */ if (TryLockPage(page)) { + page_cache_get(page); + spin_unlock(&pagemap_lru_lock); spin_unlock(&pagecache_lock); + wait_on_page(page); + page_cache_release(page); goto repeat; } - page_cache_get(page); - spin_unlock(&pagecache_lock); - - memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); - if (page->buffers) - block_flushpage(page, partial); - - partial = 0; - - /* - * we have dropped the spinlock so we have to - * restart. - */ + if (page->buffers) { + page_cache_get(page); + spin_unlock(&pagemap_lru_lock); + spin_unlock(&pagecache_lock); + block_destroy_buffers(page); + remove_inode_page(page); + lru_cache_del(page); + page_cache_release(page); + UnlockPage(page); + page_cache_release(page); + goto repeat; + } + __lru_cache_del(page); + __remove_inode_page(page); UnlockPage(page); page_cache_release(page); - goto repeat; } + + spin_unlock(&pagemap_lru_lock); spin_unlock(&pagecache_lock); } @@ -264,7 +314,15 @@ page = list_entry(page_lru, struct page, lru); list_del(page_lru); - if (PageTestandClearReferenced(page)) + if (PageTestandClearReferenced(page)) { + page->age += PG_AGE_ADV; + if (page->age > PG_AGE_MAX) + page->age = PG_AGE_MAX; + goto dispose_continue; + } + page->age -= min(PG_AGE_DECL, page->age); + + if (page->age) goto dispose_continue; count--; @@ -303,6 +361,13 @@ } } + /* + * Page is from a zone we don't care about. + * Don't drop page cache entries in vain. + */ + if (page->zone->free_pages > page->zone->pages_high) + goto unlock_continue; + /* Take the pagecache_lock spinlock held to avoid other tasks to notice the page while we are looking at its page count. If it's a pagecache-page we'll free it @@ -322,17 +387,23 @@ * were to be marked referenced.. */ if (PageSwapCache(page)) { - spin_unlock(&pagecache_lock); - __delete_from_swap_cache(page); - goto made_inode_progress; - } - - /* - * Page is from a zone we don't care about. - * Don't drop page cache entries in vain. - */ - if (page->zone->free_pages > page->zone->pages_high) + if (!PageDirty(page)) { + spin_unlock(&pagecache_lock); + __delete_from_swap_cache(page); + goto made_inode_progress; + } + /* PageDeferswap -> we swap out the page now. */ + if (gfp_mask & __GFP_IO) { + spin_unlock(&pagecache_lock); + /* Do NOT unlock the page ... brw_page does. */ + ClearPageDirty(page); + rw_swap_page(WRITE, page, 0); + spin_lock(&pagemap_lru_lock); + page_cache_release(page); + goto dispose_continue; + } goto cache_unlock_continue; + } /* is it a page-cache page? */ if (page->mapping) { @@ -1744,7 +1815,7 @@ if (!error && (flags & MS_SYNC)) { struct file * file = vma->vm_file; if (file && file->f_op && file->f_op->fsync) - error = file->f_op->fsync(file, file->f_dentry); + error = file->f_op->fsync(file, file->f_dentry, 1); } return error; } @@ -2483,7 +2554,7 @@ if (count) { remove_suid(inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); + mark_inode_dirty_sync(inode); } while (count) { @@ -2540,7 +2611,13 @@ if (cached_page) page_cache_free(cached_page); + /* For now, when the user asks for O_SYNC, we'll actually + * provide O_DSYNC. */ + if ((status >= 0) && (file->f_flags & O_SYNC)) + status = generic_osync_inode(inode, 1); /* 1 means datasync */ + err = written ? written : status; + out: up(&inode->i_sem); return err; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/memory.c linux.ac/mm/memory.c --- linux.vanilla/mm/memory.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/memory.c Wed May 31 11:24:24 2000 @@ -847,7 +847,7 @@ UnlockPage(old_page); break; } - delete_from_swap_cache_nolock(old_page); + SetPageDirty(old_page); UnlockPage(old_page); /* FallThrough */ case 1: @@ -1058,7 +1058,7 @@ */ lock_page(page); swap_free(entry); - if (write_access && !is_page_shared(page)) { + if (write_access && !is_page_shared(page) && nr_free_highpages()) { delete_from_swap_cache_nolock(page); UnlockPage(page); page = replace_with_highmem(page); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/mremap.c linux.ac/mm/mremap.c --- linux.vanilla/mm/mremap.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/mremap.c Thu Jun 8 16:53:01 2000 @@ -144,7 +144,7 @@ vmlist_modify_lock(current->mm); insert_vm_struct(current->mm, new_vma); merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end); - vmlist_modify_unlock(vma->vm_mm); + vmlist_modify_unlock(current->mm); do_munmap(current->mm, addr, old_len); current->mm->total_vm += new_len >> PAGE_SHIFT; if (new_vma->vm_flags & VM_LOCKED) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/page_alloc.c linux.ac/mm/page_alloc.c --- linux.vanilla/mm/page_alloc.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/page_alloc.c Sun Jun 4 22:19:09 2000 @@ -29,7 +29,7 @@ pg_data_t *pgdat_list; static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; -static int zone_balance_ratio[MAX_NR_ZONES] = { 128, 128, 128, }; +static int zone_balance_ratio[MAX_NR_ZONES] = { 128, 128, 512, }; static int zone_balance_min[MAX_NR_ZONES] = { 10 , 10, 10, }; static int zone_balance_max[MAX_NR_ZONES] = { 255 , 255, 255, }; @@ -93,6 +93,8 @@ BUG(); if (PageDecrAfter(page)) BUG(); + if (PageDirty(page)) + BUG(); zone = page->zone; @@ -139,10 +141,13 @@ spin_unlock_irqrestore(&zone->lock, flags); - if (zone->free_pages > zone->pages_high) { - zone->zone_wake_kswapd = 0; + if (zone->free_pages >= zone->pages_low) { zone->low_on_memory = 0; } + + if (zone->free_pages >= zone->pages_high) { + zone->zone_wake_kswapd = 0; + } } #define MARK_USED(index, order, area) \ @@ -217,6 +222,9 @@ { zone_t **zone = zonelist->zones; extern wait_queue_head_t kswapd_wait; + static int last_woke_kswapd; + static int kswapd_pause = HZ; + int gfp_mask = zonelist->gfp_mask; /* * (If anyone calls gfp from interrupts nonatomically then it @@ -237,8 +245,6 @@ struct page *page = rmqueue(z, order); if (z->free_pages < z->pages_low) { z->zone_wake_kswapd = 1; - if (waitqueue_active(&kswapd_wait)) - wake_up_interruptible(&kswapd_wait); } if (page) return page; @@ -246,9 +252,27 @@ } /* + * Kswapd should be freeing enough memory to satisfy all allocations + * immediately. Calling try_to_free_pages from processes will slow + * down the system a lot. On the other hand, waking up kswapd too + * often means wasted memory and cpu time. + * + * We tune the kswapd pause interval in such a way that kswapd is + * always just agressive enough to free the amount of memory we + * want freed. + */ + if (waitqueue_active(&kswapd_wait) && + time_after(jiffies, last_woke_kswapd + kswapd_pause)) { + kswapd_pause++; + last_woke_kswapd = jiffies; + wake_up_interruptible(&kswapd_wait); + } + + /* * Ok, we don't have any zones that don't need some * balancing.. See if we have any that aren't critical.. */ +again: zone = zonelist->zones; for (;;) { zone_t *z = *(zone++); @@ -256,20 +280,33 @@ break; if (!z->low_on_memory) { struct page *page = rmqueue(z, order); - if (z->free_pages < z->pages_min) + if (z->free_pages < (z->pages_min + z->pages_low) / 2) z->low_on_memory = 1; if (page) return page; + } else { + if (kswapd_pause > 0) + kswapd_pause--; } } + /* We didn't kick kswapd often enough... */ + kswapd_pause /= 2; + if (waitqueue_active(&kswapd_wait)) + wake_up_interruptible(&kswapd_wait); + /* If we're low priority, we just wait a bit and try again later. */ + if ((gfp_mask & __GFP_WAIT) && current->need_resched && + current->state == TASK_RUNNING) { + schedule(); + goto again; + } + /* * Uhhuh. All the zones have been critical, which means that * we'd better do some synchronous swap-out. kswapd has not * been able to cope.. */ if (!(current->flags & PF_MEMALLOC)) { - int gfp_mask = zonelist->gfp_mask; if (!try_to_free_pages(gfp_mask)) { if (!(gfp_mask & __GFP_HIGH)) goto fail; @@ -277,7 +314,7 @@ } /* - * Final phase: allocate anything we can! + * We freed something, so we're allowed to allocate anything we can! */ zone = zonelist->zones; for (;;) { @@ -292,6 +329,18 @@ } fail: + /* Last try, zone->low_on_memory isn't reset until we hit pages_low */ + zone = zonelist->zones; + for (;;) { + zone_t *z = *(zone++); + if (!z) + break; + if (z->free_pages > z->pages_min) { + struct page *page = rmqueue(z, order); + if (page) + return page; + } + } /* No luck.. */ return NULL; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/swap_state.c linux.ac/mm/swap_state.c --- linux.vanilla/mm/swap_state.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/swap_state.c Tue May 30 17:07:33 2000 @@ -73,6 +73,7 @@ PAGE_BUG(page); PageClearSwapCache(page); + ClearPageDirty(page); remove_inode_page(page); } @@ -102,9 +103,10 @@ if (!PageLocked(page)) BUG(); - if (block_flushpage(page, 0)) - lru_cache_del(page); + if (page->buffers) + block_destroy_buffers(page); + lru_cache_del(page); __delete_from_swap_cache(page); page_cache_release(page); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/vmscan.c linux.ac/mm/vmscan.c --- linux.vanilla/mm/vmscan.c Thu May 25 17:37:33 2000 +++ linux.ac/mm/vmscan.c Sun Jun 4 22:19:09 2000 @@ -62,6 +62,10 @@ goto out_failed; } + /* Can only do this if we age all active pages. */ + if (PageActive(page) && page->age > 1) + goto out_failed; + if (TryLockPage(page)) goto out_failed; @@ -74,6 +78,8 @@ * memory, and we should just continue our scan. */ if (PageSwapCache(page)) { + if (pte_dirty(pte)) + SetPageDirty(page); entry.val = page->index; swap_duplicate(entry); set_pte(page_table, swp_entry_to_pte(entry)); @@ -181,7 +187,10 @@ vmlist_access_unlock(vma->vm_mm); /* OK, do a physical asynchronous write to swap. */ - rw_swap_page(WRITE, page, 0); + // rw_swap_page(WRITE, page, 0); + /* Let shrink_mmap handle this swapout. */ + SetPageDirty(page); + UnlockPage(page); out_free_success: page_cache_release(page); @@ -430,12 +439,12 @@ * latency. */ #define FREE_COUNT 8 -#define SWAP_COUNT 16 static int do_try_to_free_pages(unsigned int gfp_mask) { int priority; int count = FREE_COUNT; - int swap_count; + int swap_count = 0; + int ret = 0; /* Always trim SLAB caches when memory gets low. */ kmem_cache_reap(gfp_mask); @@ -443,6 +452,7 @@ priority = 64; do { while (shrink_mmap(priority, gfp_mask)) { + ret = 1; if (!--count) goto done; } @@ -457,9 +467,12 @@ */ count -= shrink_dcache_memory(priority, gfp_mask); count -= shrink_icache_memory(priority, gfp_mask); - if (count <= 0) + if (count <= 0) { + ret = 1; goto done; + } while (shm_swap(priority, gfp_mask)) { + ret = 1; if (!--count) goto done; } @@ -471,24 +484,30 @@ * This will not actually free any pages (they get * put in the swap cache), so we must not count this * as a "count" success. + * + * The amount we page out is the amount of pages we're + * short freeing, amplified by the number of times we + * failed above. This generates a negative feedback loop: + * the more difficult it was to free pages, the easier we + * will make it. */ - swap_count = SWAP_COUNT; - while (swap_out(priority, gfp_mask)) + swap_count += count; + while (swap_out(priority, gfp_mask)) { if (--swap_count < 0) break; + } } while (--priority >= 0); /* Always end on a shrink_mmap.. */ while (shrink_mmap(0, gfp_mask)) { + ret = 1; if (!--count) goto done; } - /* We return 1 if we are freed some page */ - return (count != FREE_COUNT); done: - return 1; + return ret; } DECLARE_WAIT_QUEUE_HEAD(kswapd_wait); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/Config.in linux.ac/net/Config.in --- linux.vanilla/net/Config.in Thu May 25 17:37:38 2000 +++ linux.ac/net/Config.in Fri Jun 9 19:39:39 2000 @@ -58,10 +58,10 @@ if [ "$CONFIG_DECNET" != "n" ]; then source net/decnet/Config.in fi +tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25 tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB - tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC # if [ "$CONFIG_LLC" = "y" ]; then # bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/bridge/br.c linux.ac/net/bridge/br.c --- linux.vanilla/net/bridge/br.c Thu May 25 17:37:38 2000 +++ linux.ac/net/bridge/br.c Fri Jun 9 15:47:11 2000 @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek * - * $Id: br.c,v 1.42 2000/04/14 10:10:34 davem Exp $ + * $Id: br.c,v 1.43 2000/05/25 02:21:36 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,7 +38,7 @@ MOD_INC_USE_COUNT; } -static int __init br_init(void) +int __init br_init(void) { printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/core/dev.c linux.ac/net/core/dev.c --- linux.vanilla/net/core/dev.c Thu May 25 17:37:37 2000 +++ linux.ac/net/core/dev.c Thu May 25 20:28:46 2000 @@ -17,6 +17,7 @@ * David Hinds * Alexey Kuznetsov * Adam Sulmicki + * Pekka Riikonen * * Changes: * Alan Cox : device private ioctl copies fields back. @@ -56,6 +57,7 @@ * A network device unload needs to purge * the backlog queue. * Paul Rusty Russell : SIOCSIFNAME + * Pekka Riikonen : Netdev boot-time settings code */ #include @@ -249,6 +251,120 @@ printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt); } +/****************************************************************************** + + Device Boot-time Settings Routines + +*******************************************************************************/ + +/* Boot time configuration table */ +struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX]; + +/** + * netdev_boot_setup_add - add new setup entry + * @name: name of the device + * @map: configured settings for the device + * + * Adds new setup entry to the dev_boot_setup list. The function + * returns 0 on error and 1 on success. This is a generic routine to + * all netdevices. + */ +int netdev_boot_setup_add(char *name, struct ifmap *map) +{ + struct netdev_boot_setup *s; + int i; + + s = dev_boot_setup; + for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) { + if (s[i].name[0] == '\0' || s[i].name[0] == ' ') { + memset(s[i].name, 0, sizeof(s[i].name)); + strcpy(s[i].name, name); + memcpy(&s[i].map, map, sizeof(s[i].map)); + break; + } + } + + if (i >= NETDEV_BOOT_SETUP_MAX) + return 0; + + return 1; +} + +/** + * netdev_boot_setup_check - check boot time settings + * @dev: the netdevice + * + * Check boot time settings for the device. If device's name is a + * mask (eg. eth%d) and settings are found then this will allocate + * name for the device. The found settings are set for the device + * to be used later in the device probing. Returns 0 if no settings + * found, 1 if they are. + */ +int netdev_boot_setup_check(struct net_device *dev) +{ + struct netdev_boot_setup *s; + char buf[IFNAMSIZ + 1]; + int i, mask = 0; + + memset(buf, 0, sizeof(buf)); + strcpy(buf, dev->name); + if (strchr(dev->name, '%')) { + *strchr(buf, '%') = '\0'; + mask = 1; + } + + s = dev_boot_setup; + for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) { + if (s[i].name[0] != '\0' && s[i].name[0] != ' ' && + !strncmp(buf, s[i].name, mask ? strlen(buf) : + strlen(s[i].name))) { + if (__dev_get_by_name(s[i].name)) { + if (!mask) + return 0; + continue; + } + memset(dev->name, 0, IFNAMSIZ); + strcpy(dev->name, s[i].name); + dev->irq = s[i].map.irq; + dev->base_addr = s[i].map.base_addr; + dev->mem_start = s[i].map.mem_start; + dev->mem_end = s[i].map.mem_end; + return 1; + } + } + + return 0; +} + +/* + * Saves at boot time configured settings for any netdevice. + */ +static int __init netdev_boot_setup(char *str) +{ + int ints[5]; + struct ifmap map; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (!str || !*str) + return 0; + + /* Save settings */ + memset(&map, -1, sizeof(map)); + if (ints[0] > 0) + map.irq = ints[1]; + if (ints[0] > 1) + map.base_addr = ints[2]; + if (ints[0] > 2) + map.mem_start = ints[3]; + if (ints[0] > 3) + map.mem_end = ints[4]; + + /* Add new entry to the list */ + return netdev_boot_setup_add(str, &map); +} + +__setup("netdev=", netdev_boot_setup); + /***************************************************************************************** Device Interface Subroutines @@ -2364,12 +2480,19 @@ dev->xmit_lock_owner = -1; dev->iflink = -1; dev_hold(dev); - /* - * We can allocate the name ahead of time. If the - * init fails the name will be reissued correctly. + + /* + * Check boot time settings for the device. */ - if (strchr(dev->name, '%')) - dev_alloc_name(dev, dev->name); + if (!netdev_boot_setup_check(dev)) { + /* + * No settings found - allocate name. If the init() + * fails the name will be reissued correctly. + */ + if (strchr(dev->name, '%')) + dev_alloc_name(dev, dev->name); + } + if (dev->init && dev->init(dev)) { /* * It failed to come up. Unhook it. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/decnet/dn_nsp_in.c linux.ac/net/decnet/dn_nsp_in.c --- linux.vanilla/net/decnet/dn_nsp_in.c Thu May 25 17:37:38 2000 +++ linux.ac/net/decnet/dn_nsp_in.c Sat May 27 22:00:30 2000 @@ -440,7 +440,7 @@ wake_up_interruptible(sk->sleep); if (sock && sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - kill_fasync(sock->fasync_list, sig, + __kill_fasync(sock->fasync_list, sig, (sig == SIGURG) ? POLL_PRI : POLL_IN); } read_unlock(&sk->callback_lock); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ethernet/eth.c linux.ac/net/ethernet/eth.c --- linux.vanilla/net/ethernet/eth.c Thu May 25 17:37:37 2000 +++ linux.ac/net/ethernet/eth.c Thu May 25 20:28:46 2000 @@ -63,31 +63,25 @@ static int __init eth_setup(char *str) { int ints[5]; - struct net_device *d; + struct ifmap map; str = get_options(str, ARRAY_SIZE(ints), ints); - if (!str || !*str) return 0; - d = dev_base; - while (d) - { - if (!strcmp(str,d->name)) - { - if (ints[0] > 0) - d->irq=ints[1]; - if (ints[0] > 1) - d->base_addr=ints[2]; - if (ints[0] > 2) - d->mem_start=ints[3]; - if (ints[0] > 3) - d->mem_end=ints[4]; - break; - } - d=d->next; - } - return 1; + /* Save settings */ + memset(&map, -1, sizeof(map)); + if (ints[0] > 0) + map.irq = ints[1]; + if (ints[0] > 1) + map.base_addr = ints[2]; + if (ints[0] > 2) + map.mem_start = ints[3]; + if (ints[0] > 3) + map.mem_end = ints[4]; + + /* Add new entry to the list */ + return netdev_boot_setup_add(str, &map); } __setup("ether=", eth_setup); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_conntrack_core.c linux.ac/net/ipv4/netfilter/ip_conntrack_core.c --- linux.vanilla/net/ipv4/netfilter/ip_conntrack_core.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_conntrack_core.c Tue Jun 6 12:34:41 2000 @@ -99,10 +99,6 @@ #if 0 dump_tuple(tuple); #endif -#ifdef CONFIG_NETFILTER_DEBUG - if (tuple->src.pad) - DEBUGP("Tuple %p has non-zero padding.\n", tuple); -#endif /* ntohl because more differences in low bits. */ /* To ensure that halves of the same connection don't hash clash, we add the source per-proto again. */ @@ -120,12 +116,10 @@ { int ret; - /* Can only happen when extracting tuples from inside ICMP - packets */ + /* Never happen */ if (iph->frag_off & htons(IP_OFFSET)) { - if (net_ratelimit()) - printk("ip_conntrack_core: Frag of proto %u.\n", - iph->protocol); + printk("ip_conntrack_core: Frag of proto %u.\n", + iph->protocol); return 0; } /* Guarantee 8 protocol bytes: if more wanted, use len param */ @@ -133,7 +127,6 @@ return 0; tuple->src.ip = iph->saddr; - tuple->src.pad = 0; tuple->dst.ip = iph->daddr; tuple->dst.protonum = iph->protocol; @@ -149,7 +142,6 @@ const struct ip_conntrack_protocol *protocol) { inverse->src.ip = orig->dst.ip; - inverse->src.pad = 0; inverse->dst.ip = orig->src.ip; inverse->dst.protonum = orig->dst.protonum; @@ -215,6 +207,7 @@ struct ip_conntrack *ct = (void *)ul_conntrack; WRITE_LOCK(&ip_conntrack_lock); + IP_NF_ASSERT(ct->status & IPS_CONFIRMED); clean_from_lists(ct); WRITE_UNLOCK(&ip_conntrack_lock); ip_conntrack_put(ct); @@ -227,7 +220,7 @@ { MUST_BE_READ_LOCKED(&ip_conntrack_lock); return i->ctrack != ignored_conntrack - && memcmp(tuple, &i->tuple, sizeof(*tuple)) == 0; + && ip_ct_tuple_equal(tuple, &i->tuple); } static struct ip_conntrack_tuple_hash * @@ -297,7 +290,9 @@ /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ struct ip_conntrack * -icmp_error_track(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +icmp_error_track(struct sk_buff *skb, + enum ip_conntrack_info *ctinfo, + unsigned int hooknum) { const struct iphdr *iph; struct icmphdr *hdr; @@ -326,6 +321,13 @@ && hdr->type != ICMP_REDIRECT) return NULL; + /* Ignore ICMP's containing fragments (shouldn't happen) */ + if (inner->frag_off & htons(IP_OFFSET)) { + DEBUGP("icmp_error_track: fragment of proto %u\n", + inner->protocol); + return NULL; + } + /* Ignore it if the checksum's bogus. */ if (ip_compute_csum((unsigned char *)hdr, sizeof(*hdr) + datalen)) { DEBUGP("icmp_error_track: bad csum\n"); @@ -353,7 +355,11 @@ DEBUGP("icmp_error_track: no match\n"); return NULL; } - if (!(h->ctrack->status & IPS_CONFIRMED)) { + + /* REJECT target does this commonly, so allow locally + generated ICMP errors --RR */ + if (!(h->ctrack->status & IPS_CONFIRMED) + && hooknum != NF_IP_LOCAL_OUT) { DEBUGP("icmp_error_track: unconfirmed\n"); ip_conntrack_put(h->ctrack); return NULL; @@ -447,6 +453,8 @@ /* Try dropping from random chain, or else from the chain about to put into (in case they're trying to bomb one hash chain). */ + if (drop_next >= ip_conntrack_htable_size) + drop_next = 0; if (!early_drop(&ip_conntrack_hash[drop_next++]) && !early_drop(&ip_conntrack_hash[hash])) return 1; @@ -528,11 +536,14 @@ static inline struct ip_conntrack * resolve_normal_ct(struct sk_buff *skb, struct ip_conntrack_protocol *proto, + unsigned int *newstatus, enum ip_conntrack_info *ctinfo) { struct ip_conntrack_tuple tuple; struct ip_conntrack_tuple_hash *h; + IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0); + if (!get_tuple(skb->nh.iph, skb->len, &tuple, proto)) return NULL; @@ -554,7 +565,7 @@ } *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY; - h->ctrack->status |= IPS_SEEN_REPLY; + *newstatus = (h->ctrack->status | IPS_SEEN_REPLY); } else { /* Once we've had two way comms, always ESTABLISHED. */ if (h->ctrack->status & IPS_SEEN_REPLY) { @@ -570,6 +581,7 @@ h->ctrack); *ctinfo = IP_CT_NEW; } + *newstatus = h->ctrack->status; } skb->nfct = &h->ctrack->infos[*ctinfo]; return h->ctrack; @@ -602,11 +614,27 @@ struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; struct ip_conntrack_protocol *proto; + unsigned int status; int ret; /* FIXME: Do this right please. --RR */ (*pskb)->nfcache |= NFC_UNKNOWN; +/* Doesn't cover locally-generated broadcast, so not worth it. */ +#if 0 + /* Ignore broadcast: no `connection'. */ + if ((*pskb)->pkt_type == PACKET_BROADCAST) { + printk("Broadcast packet!\n"); + return NF_ACCEPT; + } else if (((*pskb)->nh.iph->daddr & htonl(0x000000FF)) + == htonl(0x000000FF)) { + printk("Should bcast: %u.%u.%u.%u->%u.%u.%u.%u (sk=%p, ptype=%u)\n", + IP_PARTS((*pskb)->nh.iph->saddr), + IP_PARTS((*pskb)->nh.iph->daddr), + (*pskb)->sk, (*pskb)->pkt_type); + } +#endif + /* Previously seen (loopback)? Ignore. Do this before fragment check. */ if ((*pskb)->nfct) @@ -622,12 +650,13 @@ proto = find_proto((*pskb)->nh.iph->protocol); /* It may be an icmp error... */ - if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP - || !(ct = icmp_error_track(*pskb, &ctinfo))) { - if (!(ct = resolve_normal_ct(*pskb, proto, &ctinfo))) { - /* Not valid part of a connection */ - return NF_ACCEPT; - } + if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP + && icmp_error_track(*pskb, &ctinfo, hooknum)) + return NF_ACCEPT; + + if (!(ct = resolve_normal_ct(*pskb, proto, &status, &ctinfo))) { + /* Not valid part of a connection */ + return NF_ACCEPT; } IP_NF_ASSERT((*pskb)->nfct); @@ -649,6 +678,7 @@ return NF_ACCEPT; } } + ct->status = status; return ret; } @@ -845,7 +875,7 @@ else if (!(h->ctrack->status & IPS_CONFIRMED)) { /* Unconfirmed connection. Clean from lists, mark confirmed so it gets cleaned as soon - as packet comes back. */ + as skb freed. */ WRITE_LOCK(&ip_conntrack_lock); if (!(h->ctrack->status & IPS_CONFIRMED)) { clean_from_lists(h->ctrack); @@ -867,8 +897,7 @@ getorigdst(struct sock *sk, int optval, void *user, int *len) { struct ip_conntrack_tuple_hash *h; - struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { sk->sport }, - 0 }, + struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { sk->sport } }, { sk->daddr, { sk->dport }, IPPROTO_TCP } }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_conntrack_ftp.c linux.ac/net/ipv4/netfilter/ip_conntrack_ftp.c --- linux.vanilla/net/ipv4/netfilter/ip_conntrack_ftp.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_conntrack_ftp.c Tue Jun 6 12:34:40 2000 @@ -124,10 +124,6 @@ struct ip_conntrack_tuple t; struct ip_ct_ftp *info = &ct->help.ct_ftp_info; - /* Can't track connections formed before we registered */ - if (!info) - return NF_ACCEPT; - /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { @@ -200,15 +196,26 @@ /* Update the ftp info */ LOCK_BH(&ip_ftp_lock); - info->is_ftp = 1; - info->seq = ntohl(tcph->seq) + matchoff; - info->len = matchlen; - info->ftptype = dir; - info->port = array[4] << 8 | array[5]; + if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]) + == ct->tuplehash[dir].tuple.src.ip) { + info->is_ftp = 1; + info->seq = ntohl(tcph->seq) + matchoff; + info->len = matchlen; + info->ftptype = dir; + info->port = array[4] << 8 | array[5]; + } else { + /* Enrico Scholz's passive FTP to partially RNAT'd ftp + server: it really wants us to connect to a + different IP address. Simply don't record it for + NAT. */ + DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n", + array[0], array[1], array[2], array[3], + NIPQUAD(ct->tuplehash[dir].tuple.src.ip)); + } t = ((struct ip_conntrack_tuple) { { ct->tuplehash[!dir].tuple.src.ip, - { 0 }, 0 }, + { 0 } }, { htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]), { htons(array[4] << 8 | array[5]) }, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux.ac/net/ipv4/netfilter/ip_conntrack_proto_generic.c --- linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_generic.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_conntrack_proto_generic.c Tue Jun 6 12:34:40 2000 @@ -4,7 +4,7 @@ #include #include -#define GENERIC_TIMEOUT (3600*HZ) +#define GENERIC_TIMEOUT (600*HZ) static int generic_pkt_to_tuple(const void *datah, size_t datalen, struct ip_conntrack_tuple *tuple) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux.ac/net/ipv4/netfilter/ip_conntrack_proto_tcp.c --- linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Tue Jun 6 12:34:41 2000 @@ -23,10 +23,6 @@ /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */ -/* We steal a bit to indicate no reply yet (can't use status, because - it's set before we get into packet handling). */ -#define TCP_REPLY_BIT 0x1000 - /* Actually, I believe that neither ipmasq (where this code is stolen from) nor ipfilter do it exactly right. A new conntrack machine taking into account packet loss (which creates uncertainty as to exactly @@ -145,7 +141,7 @@ enum tcp_conntrack state; READ_LOCK(&tcp_lock); - state = (conntrack->proto.tcp_state & ~TCP_REPLY_BIT); + state = conntrack->proto.tcp_state; READ_UNLOCK(&tcp_lock); return sprintf(buffer, "%s ", tcp_conntrack_names[state]); @@ -180,7 +176,7 @@ newconntrack = tcp_conntracks [CTINFO2DIR(ctinfo)] - [get_conntrack_index(tcph)][oldtcpstate & ~TCP_REPLY_BIT]; + [get_conntrack_index(tcph)][oldtcpstate]; /* Invalid */ if (newconntrack == TCP_CONNTRACK_MAX) { @@ -192,17 +188,13 @@ } conntrack->proto.tcp_state = newconntrack; - if ((oldtcpstate & TCP_REPLY_BIT) - || ctinfo >= IP_CT_IS_REPLY) - conntrack->proto.tcp_state |= TCP_REPLY_BIT; - WRITE_UNLOCK(&tcp_lock); /* If only reply is a RST, we can consider ourselves not to have an established connection: this is a fairly common problem case, so we can delete the conntrack immediately. --RR */ - if (!(oldtcpstate & TCP_REPLY_BIT) && tcph->rst) { + if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) { if (del_timer(&conntrack->timeout)) conntrack->timeout.function((unsigned long)conntrack); } else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux.ac/net/ipv4/netfilter/ip_conntrack_proto_udp.c --- linux.vanilla/net/ipv4/netfilter/ip_conntrack_proto_udp.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_conntrack_proto_udp.c Tue Jun 6 12:34:40 2000 @@ -6,7 +6,8 @@ #include #include -#define UDP_TIMEOUT (60*HZ) +#define UDP_TIMEOUT (30*HZ) +#define UDP_STREAM_TIMEOUT (180*HZ) static int udp_pkt_to_tuple(const void *datah, size_t datalen, struct ip_conntrack_tuple *tuple) @@ -48,8 +49,13 @@ struct iphdr *iph, size_t len, enum ip_conntrack_info conntrackinfo) { - /* Refresh. */ - ip_ct_refresh(conntrack, UDP_TIMEOUT); + /* If we've seen traffic both ways, this is some kind of UDP + stream. Extend timeout. */ + if (conntrack->status & IPS_SEEN_REPLY) + ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT); + else + ip_ct_refresh(conntrack, UDP_TIMEOUT); + return NF_ACCEPT; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_fw_compat.c linux.ac/net/ipv4/netfilter/ip_fw_compat.c --- linux.vanilla/net/ipv4/netfilter/ip_fw_compat.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_fw_compat.c Tue Jun 6 12:34:41 2000 @@ -34,6 +34,9 @@ do_masquerade(struct sk_buff **pskb, const struct net_device *dev); extern unsigned int +check_for_masq_error(struct sk_buff *pskb); + +extern unsigned int check_for_demasq(struct sk_buff **pskb); extern int __init masq_init(void); @@ -151,9 +154,13 @@ if (hooknum == NF_IP_PRE_ROUTING) { check_for_demasq(pskb); check_for_redirect(*pskb); - } else if (hooknum == NF_IP_POST_ROUTING) + } else if (hooknum == NF_IP_POST_ROUTING) { check_for_unredirect(*pskb); - + /* Handle ICMP errors from client here */ + if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP + && (*pskb)->nfct) + check_for_masq_error(*pskb); + } return NF_ACCEPT; case FW_MASQUERADE: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_fw_compat_masq.c linux.ac/net/ipv4/netfilter/ip_fw_compat_masq.c --- linux.vanilla/net/ipv4/netfilter/ip_fw_compat_masq.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_fw_compat_masq.c Tue Jun 6 12:34:41 2000 @@ -95,6 +95,24 @@ return do_bindings(ct, ctinfo, info, NF_IP_POST_ROUTING, pskb); } +void +check_for_masq_error(struct sk_buff *skb) +{ + enum ip_conntrack_info ctinfo; + struct ip_conntrack *ct; + + ct = ip_conntrack_get(skb, &ctinfo); + /* Wouldn't be here if not tracked already => masq'ed ICMP + ping or error related to masq'd connection */ + IP_NF_ASSERT(ct); + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { + icmp_reply_translation(skb, ct, NF_IP_PRE_ROUTING, + CTINFO2DIR(ctinfo)); + icmp_reply_translation(skb, ct, NF_IP_POST_ROUTING, + CTINFO2DIR(ctinfo)); + } +} + unsigned int check_for_demasq(struct sk_buff **pskb) { @@ -114,15 +132,27 @@ switch (iph->protocol) { case IPPROTO_ICMP: /* ICMP errors. */ - if ((ct = icmp_error_track(*pskb, &ctinfo))) { - icmp_reply_translation(*pskb, ct, - NF_IP_PRE_ROUTING, - CTINFO2DIR(ctinfo)); + ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING); + if (ct) { + /* We only do SNAT in the compatibility layer. + So we can manipulate ICMP errors from + server here (== DNAT). Do SNAT icmp manips + in POST_ROUTING handling. */ + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { + icmp_reply_translation(*pskb, ct, + NF_IP_PRE_ROUTING, + CTINFO2DIR(ctinfo)); + icmp_reply_translation(*pskb, ct, + NF_IP_POST_ROUTING, + CTINFO2DIR(ctinfo)); + } return NF_ACCEPT; } /* Fall thru... */ case IPPROTO_TCP: case IPPROTO_UDP: + IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0); + if (!get_tuple(iph, (*pskb)->len, &tuple, protocol)) { if (net_ratelimit()) printk("ip_fw_compat_masq: Can't get tuple\n"); @@ -237,7 +267,17 @@ { unsigned int i; int len = 0; - off_t upto = 0; + off_t upto = 1; + + /* Header: first record */ + if (offset == 0) { + char temp[128]; + + sprintf(temp, + "Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=0,0,0)"); + len = sprintf(buffer, "%-127s\n", temp); + offset = 1; + } READ_LOCK(&ip_conntrack_lock); /* Traverse hash; print originals then reply. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_nat_core.c linux.ac/net/ipv4/netfilter/ip_nat_core.c --- linux.vanilla/net/ipv4/netfilter/ip_nat_core.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_nat_core.c Tue Jun 6 12:34:41 2000 @@ -269,7 +269,7 @@ unsigned int score; struct ip_conntrack_tuple tuple; } best = { NULL, 0xFFFFFFFF }; - u_int32_t *var_ipp, *other_ipp, saved_ip; + u_int32_t *var_ipp, *other_ipp, saved_ip, orig_dstip; if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) { var_ipp = &tuple->src.ip; @@ -280,6 +280,9 @@ saved_ip = tuple->src.ip; other_ipp = &tuple->src.ip; } + /* Don't do do_extra_mangle unless neccessary (overrides + explicit socket bindings, for example) */ + orig_dstip = tuple->dst.ip; IP_NF_ASSERT(mr->rangesize >= 1); for (i = 0; i < mr->rangesize; i++) { @@ -306,6 +309,7 @@ *other_ipp = saved_ip; if (hooknum == NF_IP_LOCAL_OUT + && *var_ipp != orig_dstip && !do_extra_mangle(*var_ipp, other_ipp)) { DEBUGP("Range %u %u.%u.%u.%u rt failed!\n", i, IP_PARTS(*var_ipp)); @@ -337,6 +341,35 @@ return (struct ip_nat_range *)best.range; } +/* Fast version doesn't iterate through hash chains, but only handles + common case of single IP address (null NAT, masquerade) */ +static struct ip_nat_range * +find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple, + const struct ip_nat_multi_range *mr, + const struct ip_conntrack *conntrack, + unsigned int hooknum) +{ + if (mr->rangesize != 1 + || (mr->range[0].flags & IP_NAT_RANGE_FULL) + || ((mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) + && mr->range[0].min_ip != mr->range[0].max_ip)) + return find_best_ips_proto(tuple, mr, conntrack, hooknum); + + if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) + tuple->src.ip = mr->range[0].min_ip; + else { + tuple->dst.ip = mr->range[0].min_ip; + if (hooknum == NF_IP_LOCAL_OUT + && !do_extra_mangle(tuple->dst.ip, &tuple->src.ip)) + return NULL; + } + } + + /* Discard const. */ + return (struct ip_nat_range *)&mr->range[0]; +} + static int get_unique_tuple(struct ip_conntrack_tuple *tuple, const struct ip_conntrack_tuple *orig_tuple, @@ -378,7 +411,7 @@ range. */ *tuple = *orig_tuple; - while ((rptr = find_best_ips_proto(tuple, mr, conntrack, hooknum)) + while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum)) != NULL) { DEBUGP("Found best for "); DUMP_TUPLE(tuple); /* 3) The per-protocol part of the manip is made to @@ -525,8 +558,7 @@ invert_tuplepr(&inv_tuple, &orig_tp); /* Has source changed?. */ - if (memcmp(&new_tuple.src, &orig_tp.src, sizeof(new_tuple.src)) - != 0) { + if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) { /* In this direction, a source manip. */ info->manips[info->num_manips++] = ((struct ip_nat_info_manip) @@ -544,8 +576,7 @@ } /* Has destination changed? */ - if (memcmp(&new_tuple.dst, &orig_tp.dst, sizeof(new_tuple.dst)) - != 0) { + if (!ip_ct_tuple_dst_equal(&new_tuple, &orig_tp)) { /* In this direction, a destination manip */ info->manips[info->num_manips++] = ((struct ip_nat_info_manip) @@ -734,12 +765,15 @@ DEBUGP("icmp_reply: manip %u dir %s hook %u\n", i, info->manips[i].direction == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY", info->manips[i].hooknum); + + if (info->manips[i].direction != dir) + continue; + /* Mapping the inner packet is just like a normal - packet in the other direction, except it was never - src/dst reversed, so where we would normally apply - a dst manip, we reply a src, and vice versa. */ - if (info->manips[i].direction != dir - && info->manips[i].hooknum == opposite_hook[hooknum]) { + packet, except it was never src/dst reversed, so + where we would normally apply a dst manip, we apply + a src, and vice versa. */ + if (info->manips[i].hooknum == opposite_hook[hooknum]) { DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n", info->manips[i].maniptype == IP_NAT_MANIP_SRC ? "DST" : "SRC", @@ -749,14 +783,13 @@ skb->len - ((void *)inner - (void *)iph), &info->manips[i].manip, !info->manips[i].maniptype); - } /* Outer packet needs to have IP header NATed like it's a reply. */ - else if (info->manips[i].direction != dir + } else if (info->manips[i].direction == dir && info->manips[i].hooknum == hooknum) { /* Use mapping to map outer packet: 0 give no per-proto mapping */ - DEBUGP("icmp_reply: outer %s %u.%u.%u.%u\n", + DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n", info->manips[i].maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", IP_PARTS(info->manips[i].manip.ip)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_nat_standalone.c linux.ac/net/ipv4/netfilter/ip_nat_standalone.c --- linux.vanilla/net/ipv4/netfilter/ip_nat_standalone.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_nat_standalone.c Tue Jun 6 12:34:41 2000 @@ -70,8 +70,16 @@ ct = ip_conntrack_get(*pskb, &ctinfo); /* Can't track? Maybe out of memory: this would make NAT unreliable. */ - if (!ct) + if (!ct) { + if (net_ratelimit()) + printk("NAT: %u dropping untracked packet %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n", + hooknum, + *pskb, + (*pskb)->nh.iph->protocol, + NIPQUAD((*pskb)->nh.iph->saddr), + NIPQUAD((*pskb)->nh.iph->daddr)); return NF_DROP; + } switch (ctinfo) { case IP_CT_RELATED: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_queue.c linux.ac/net/ipv4/netfilter/ip_queue.c --- linux.vanilla/net/ipv4/netfilter/ip_queue.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_queue.c Tue Jun 6 12:34:40 2000 @@ -3,6 +3,10 @@ * communicating with userspace via netlink. * * (C) 2000 James Morris, this code is GPL. + * + * 2000-03-27: Simplified code (thanks to Andi Kleen for clues). (JM) + * 2000-05-20: Fixed notifier problems (following Miguel Freitas' report). (JM) + * */ #include #include @@ -52,40 +56,36 @@ ipq_peer_t peer; /* Userland peer */ } ipq_queue_t; - /**************************************************************************** * * Packet queue * ****************************************************************************/ -/* Dequeue with element packet ID, or from end of queue if ID is zero. */ -static ipq_queue_element_t *ipq_dequeue(ipq_queue_t *q, unsigned long id) +/* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */ +static ipq_queue_element_t * +ipq_dequeue(ipq_queue_t *q, + int (*cmp)(ipq_queue_element_t *, unsigned long), + unsigned long data) { struct list_head *i; - ipq_queue_element_t *e = NULL; spin_lock_bh(&q->lock); - if (q->len == 0) - goto out_unlock; - i = q->list.prev; - if (id > 0) { - while (i != &q->list) { - if (id == (unsigned long )i) - goto out_unlink; - i = i->prev; + for (i = q->list.prev; i != &q->list; i = i->prev) { + ipq_queue_element_t *e = (ipq_queue_element_t *)i; + + if (!cmp || cmp(e, data)) { + list_del(&e->list); + q->len--; + spin_unlock_bh(&q->lock); + return e; } - goto out_unlock; } -out_unlink: - e = (ipq_queue_element_t *)i; - list_del(&e->list); - q->len--; -out_unlock: spin_unlock_bh(&q->lock); - return e; + return NULL; } +/* Flush all packets */ static void ipq_flush(ipq_queue_t *q) { ipq_queue_element_t *e; @@ -93,7 +93,7 @@ spin_lock_bh(&q->lock); q->flushing = 1; spin_unlock_bh(&q->lock); - while ((e = ipq_dequeue(q, 0))) { + while ((e = ipq_dequeue(q, NULL, 0))) { e->verdict = NF_DROP; nf_reinject(e->skb, e->info, e->verdict); kfree(e); @@ -232,6 +232,11 @@ return 0; } +static inline int id_cmp(ipq_queue_element_t *e, unsigned long id) +{ + return (id == (unsigned long )e); +} + static int ipq_set_verdict(ipq_queue_t *q, ipq_verdict_msg_t *v, unsigned int len) { @@ -239,7 +244,7 @@ if (v->value < 0 || v->value > NF_MAX_VERDICT) return -EINVAL; - e = ipq_dequeue(q, v->id); + e = ipq_dequeue(q, id_cmp, v->id); if (e == NULL) return -ENOENT; else { @@ -296,6 +301,30 @@ return status; } +static inline int dev_cmp(ipq_queue_element_t *e, unsigned long ifindex) +{ + if (e->info->indev) + if (e->info->indev->ifindex == ifindex) + return 1; + if (e->info->outdev) + if (e->info->outdev->ifindex == ifindex); + return 1; + return 0; + +} + +/* Drop any queued packets associated with device ifindex */ +static void ipq_dev_drop(ipq_queue_t *q, int ifindex) +{ + ipq_queue_element_t *e; + + while ((e = ipq_dequeue(q, dev_cmp, ifindex))) { + e->verdict = NF_DROP; + nf_reinject(e->skb, e->info, e->verdict); + kfree(e); + } +} + /**************************************************************************** * * Netfilter interface @@ -456,9 +485,11 @@ static int receive_event(struct notifier_block *this, unsigned long event, void *ptr) { - if (event == NETDEV_UNREGISTER) - if (nlq) - ipq_destroy_queue(nlq); + struct net_device *dev = ptr; + + /* Drop any packets associated with the downed device */ + if (event == NETDEV_DOWN) + ipq_dev_drop(nlq, dev->ifindex); return NOTIFY_DONE; } @@ -574,5 +605,3 @@ MODULE_DESCRIPTION("IPv4 packet queue handler"); module_init(init); module_exit(fini); - - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ip_tables.c linux.ac/net/ipv4/netfilter/ip_tables.c --- linux.vanilla/net/ipv4/netfilter/ip_tables.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ip_tables.c Tue Jun 6 12:34:40 2000 @@ -642,7 +642,7 @@ match = find_match_lock(m->u.user.name, &ret, &ipt_mutex); if (!match) { - duprintf("check_match: `%s' not found\n", m->u.name); + duprintf("check_match: `%s' not found\n", m->u.user.name); return ret; } if (match->me) @@ -689,8 +689,8 @@ t = ipt_get_target(e); target = find_target_lock(t->u.user.name, &ret, &ipt_mutex); if (!target) { - duprintf("check_entry: `%s' not found\n", t->u.name); - return ret; + duprintf("check_entry: `%s' not found\n", t->u.user.name); + goto cleanup_matches; } if (target->me) __MOD_INC_USE_COUNT(target->me); @@ -1300,9 +1300,10 @@ MOD_INC_USE_COUNT; ret = down_interruptible(&ipt_mutex); - if (ret != 0) + if (ret != 0) { + MOD_DEC_USE_COUNT; return ret; - + } if (!list_named_insert(&ipt_target, target)) { duprintf("ipt_register_target: `%s' already in list!\n", target->name); @@ -1333,9 +1334,7 @@ MOD_DEC_USE_COUNT; return ret; } - if (list_named_insert(&ipt_match, match)) { - ret = 0; - } else { + if (!list_named_insert(&ipt_match, match)) { duprintf("ipt_register_match: `%s' already in list!\n", match->name); MOD_DEC_USE_COUNT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ipfwadm_core.c linux.ac/net/ipv4/netfilter/ipfwadm_core.c --- linux.vanilla/net/ipv4/netfilter/ipfwadm_core.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ipfwadm_core.c Fri Jun 9 15:47:11 2000 @@ -2,12 +2,15 @@ Rusty.Russell@rustcorp.com.au */ +#include #define CONFIG_IP_FIREWALL #define CONFIG_IP_FIREWALL_VERBOSE #define CONFIG_IP_MASQUERADE #define CONFIG_IP_ACCT #define CONFIG_IP_TRANSPARENT_PROXY +#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE) #define CONFIG_IP_FIREWALL_NETLINK +#endif /* * IP firewalling code. This is taken from 4.4BSD. Please note the @@ -17,7 +20,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ipfwadm_core.c,v 1.2 2000/04/15 01:48:10 davem Exp $ + * $Id: ipfwadm_core.c,v 1.3 2000/06/09 07:35:49 davem Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. @@ -94,7 +97,6 @@ * This software is provided ``AS IS'' without any warranties of any kind. */ -#include #include #include #include @@ -1094,7 +1096,6 @@ } #endif /* CONFIG_IP_FIREWALL */ -#ifdef CONFIG_PROC_FS #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT) static int ip_chain_procinfo(int stage, char *buffer, char **start, @@ -1252,7 +1253,6 @@ return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length, reset); } -#endif #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ipt_MASQUERADE.c linux.ac/net/ipv4/netfilter/ipt_MASQUERADE.c --- linux.vanilla/net/ipv4/netfilter/ipt_MASQUERADE.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ipt_MASQUERADE.c Tue Jun 6 12:34:40 2000 @@ -30,6 +30,10 @@ { const struct ip_nat_multi_range *mr = targinfo; + if (strcmp(tablename, "nat") != 0) { + DEBUGP("masquerade_check: bad table `%s'.\n", table); + return 0; + } if (targinfosize != IPT_ALIGN(sizeof(*mr))) { DEBUGP("masquerade_check: size %u != %u.\n", targinfosize, sizeof(*mr)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ipt_REDIRECT.c linux.ac/net/ipv4/netfilter/ipt_REDIRECT.c --- linux.vanilla/net/ipv4/netfilter/ipt_REDIRECT.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ipt_REDIRECT.c Tue Jun 6 12:34:40 2000 @@ -28,6 +28,10 @@ { const struct ip_nat_multi_range *mr = targinfo; + if (strcmp(tablename, "nat") != 0) { + DEBUGP("redirect_check: bad table `%s'.\n", table); + return 0; + } if (targinfosize != IPT_ALIGN(sizeof(*mr))) { DEBUGP("redirect_check: size %u.\n", targinfosize); return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ipt_REJECT.c linux.ac/net/ipv4/netfilter/ipt_REJECT.c --- linux.vanilla/net/ipv4/netfilter/ipt_REJECT.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ipt_REJECT.c Tue Jun 6 12:34:40 2000 @@ -27,7 +27,7 @@ { const struct ipt_reject_info *reject = targinfo; - /* WARNING: This code has causes reentry within iptables. + /* WARNING: This code causes reentry within iptables. This means that the iptables jump stack is now crap. We must return an absolute verdict. --RR */ switch (reject->with) { @@ -95,6 +95,10 @@ } /* Only allow these for packet filtering. */ + if (strcmp(tablename, "filter") != 0) { + DEBUGP("REJECT: bad table `%s'.\n", table); + return 0; + } if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) != 0) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/netfilter/ipt_multiport.c linux.ac/net/ipv4/netfilter/ipt_multiport.c --- linux.vanilla/net/ipv4/netfilter/ipt_multiport.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/netfilter/ipt_multiport.c Tue Jun 6 12:34:40 2000 @@ -73,6 +73,9 @@ { const struct ipt_multiport *multiinfo = matchinfo; + if (matchsize != IPT_ALIGN(sizeof(struct ipt_multiport))) + return 0; + /* Must specify proto == TCP/UDP, no unknown flags or bad count */ return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) && !(ip->flags & IPT_INV_PROTO) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv4/udp.c linux.ac/net/ipv4/udp.c --- linux.vanilla/net/ipv4/udp.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv4/udp.c Fri Jun 9 15:47:11 2000 @@ -5,7 +5,7 @@ * * The User Datagram Protocol (UDP). * - * Version: $Id: udp.c,v 1.82 2000/05/03 06:37:07 davem Exp $ + * Version: $Id: udp.c,v 1.83 2000/06/09 07:35:49 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -718,6 +718,7 @@ sin->sin_family = AF_INET; sin->sin_port = skb->h.uh->source; sin->sin_addr.s_addr = skb->nh.iph->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); } if (sk->protinfo.af_inet.cmsg_flags) ip_cmsg_recv(msg, skb); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv6/netfilter/ip6_tables.c linux.ac/net/ipv6/netfilter/ip6_tables.c --- linux.vanilla/net/ipv6/netfilter/ip6_tables.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipv6/netfilter/ip6_tables.c Fri Jun 9 15:47:11 2000 @@ -736,7 +736,7 @@ target = find_target_lock(t->u.user.name, &ret, &ip6t_mutex); if (!target) { // duprintf("check_entry: `%s' not found\n", t->u.name); - return ret; + goto cleanup_matches; } if (target->me) __MOD_INC_USE_COUNT(target->me); @@ -1342,9 +1342,10 @@ MOD_INC_USE_COUNT; ret = down_interruptible(&ip6t_mutex); - if (ret != 0) + if (ret != 0) { + MOD_DEC_USE_COUNT; return ret; - + } if (!list_named_insert(&ip6t_target, target)) { duprintf("ip6t_register_target: `%s' already in list!\n", target->name); @@ -1375,9 +1376,7 @@ MOD_DEC_USE_COUNT; return ret; } - if (list_named_insert(&ip6t_match, match)) { - ret = 0; - } else { + if (!list_named_insert(&ip6t_match, match)) { duprintf("ip6t_register_match: `%s' already in list!\n", match->name); MOD_DEC_USE_COUNT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv6/netfilter/ip6t_mac.c linux.ac/net/ipv6/netfilter/ip6t_mac.c --- linux.vanilla/net/ipv6/netfilter/ip6t_mac.c Thu Jan 1 01:00:00 1970 +++ linux.ac/net/ipv6/netfilter/ip6t_mac.c Fri Jun 9 15:47:11 2000 @@ -0,0 +1,62 @@ +/* Kernel module to match MAC address parameters. */ +#include +#include +#include + +#include +#include + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *matchinfo, + int offset, + const void *hdr, + u_int16_t datalen, + int *hotdrop) +{ + const struct ip6t_mac_info *info = matchinfo; + + /* Is mac pointer valid? */ + return (skb->mac.raw >= skb->head + && skb->mac.raw < skb->head + skb->len - ETH_HLEN + /* If so, compare... */ + && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN) + == 0) ^ info->invert)); +} + +static int +ipt_mac_checkentry(const char *tablename, + const struct ip6t_ip6 *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + if (hook_mask + & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN))) { + printk("ipt_mac: only valid for PRE_ROUTING or LOCAL_IN.\n"); + return 0; + } + + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info))) + return 0; + + return 1; +} + +static struct ip6t_match mac_match += { { NULL, NULL }, "mac", &match, &ipt_mac_checkentry, NULL, THIS_MODULE }; + +static int __init init(void) +{ + return ip6t_register_match(&mac_match); +} + +static void __exit fini(void) +{ + ip6t_unregister_match(&mac_match); +} + +module_init(init); +module_exit(fini); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipv6/netfilter/ip6t_multiport.c linux.ac/net/ipv6/netfilter/ip6t_multiport.c --- linux.vanilla/net/ipv6/netfilter/ip6t_multiport.c Thu Jan 1 01:00:00 1970 +++ linux.ac/net/ipv6/netfilter/ip6t_multiport.c Fri Jun 9 15:47:11 2000 @@ -0,0 +1,101 @@ +/* Kernel module to match one of a list of TCP/UDP ports: ports are in + the same place so we can treat them as equal. */ +#include +#include +#include +#include +#include + +#include +#include + +#if 0 +#define duprintf(format, args...) printk(format , ## args) +#else +#define duprintf(format, args...) +#endif + +/* Returns 1 if the port is matched by the test, 0 otherwise. */ +static inline int +ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags, + u_int8_t count, u_int16_t src, u_int16_t dst) +{ + unsigned int i; + for (i=0; iports, + multiinfo->flags, multiinfo->count, + ntohs(udp->source), ntohs(udp->dest)); +} + +/* Called when user tries to insert an entry of this type. */ +static int +checkentry(const char *tablename, + const struct ip6t_ip6 *ip, + void *matchinfo, + unsigned int matchsize, + unsigned int hook_mask) +{ + const struct ip6t_multiport *multiinfo = matchinfo; + + /* Must specify proto == TCP/UDP, no unknown flags or bad count */ + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) + && !(ip->flags & IP6T_INV_PROTO) + && matchsize == IP6T_ALIGN(sizeof(struct ip6t_multiport)) + && (multiinfo->flags == IP6T_MULTIPORT_SOURCE + || multiinfo->flags == IP6T_MULTIPORT_DESTINATION + || multiinfo->flags == IP6T_MULTIPORT_EITHER) + && multiinfo->count <= IP6T_MULTI_PORTS; +} + +static struct ip6t_match multiport_match += { { NULL, NULL }, "multiport", &match, &checkentry, NULL, THIS_MODULE }; + +static int __init init(void) +{ + return ip6t_register_match(&multiport_match); +} + +static void __exit fini(void) +{ + ip6t_unregister_match(&multiport_match); +} + +module_init(init); +module_exit(fini); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/ipx/af_ipx.c linux.ac/net/ipx/af_ipx.c --- linux.vanilla/net/ipx/af_ipx.c Thu May 25 17:37:38 2000 +++ linux.ac/net/ipx/af_ipx.c Tue May 30 14:48:47 2000 @@ -600,8 +600,7 @@ memcpy(skb2->h.raw, skb->h.raw, skb->len); } kfree_skb(skb); - - return (NULL); + return (skb2); } static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/netsyms.c linux.ac/net/netsyms.c --- linux.vanilla/net/netsyms.c Thu May 25 17:37:38 2000 +++ linux.ac/net/netsyms.c Tue Jun 6 12:36:28 2000 @@ -196,7 +196,7 @@ /* Needed by unix.o */ EXPORT_SYMBOL(scm_fp_dup); -EXPORT_SYMBOL(max_files); +EXPORT_SYMBOL(files_stat); EXPORT_SYMBOL(memcpy_toiovec); EXPORT_SYMBOL(csum_partial); @@ -252,6 +252,8 @@ /* Route manipulation */ EXPORT_SYMBOL(ip_rt_ioctl); EXPORT_SYMBOL(devinet_ioctl); +EXPORT_SYMBOL(register_inetaddr_notifier); +EXPORT_SYMBOL(unregister_inetaddr_notifier); /* needed for ip_gre -cw */ EXPORT_SYMBOL(ip_statistics); @@ -522,7 +524,7 @@ EXPORT_SYMBOL(dev_mc_upload); EXPORT_SYMBOL(n_tty_ioctl); EXPORT_SYMBOL(tty_register_ldisc); -EXPORT_SYMBOL(kill_fasync); +EXPORT_SYMBOL(__kill_fasync); EXPORT_SYMBOL(if_port_text); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/socket.c linux.ac/net/socket.c --- linux.vanilla/net/socket.c Thu May 25 17:37:37 2000 +++ linux.ac/net/socket.c Fri Jun 9 15:47:11 2000 @@ -697,10 +697,10 @@ /* fall through */ case 0: call_kill: - kill_fasync(sock->fasync_list, SIGIO, band); + __kill_fasync(sock->fasync_list, SIGIO, band); break; case 3: - kill_fasync(sock->fasync_list, SIGURG, band); + __kill_fasync(sock->fasync_list, SIGURG, band); } return 0; } @@ -1548,6 +1548,11 @@ } extern void sk_init(void); + +#ifdef CONFIG_BRIDGE +extern int br_init(void); +#endif + #ifdef CONFIG_WAN_ROUTER extern void wanrouter_init(void); #endif @@ -1579,6 +1584,13 @@ skb_init(); #endif + /* + * Ethernet bridge layer. + */ + +#ifdef CONFIG_BRIDGE + br_init(); +#endif /* * Wan router layer. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/sunrpc/clnt.c linux.ac/net/sunrpc/clnt.c --- linux.vanilla/net/sunrpc/clnt.c Thu May 25 17:37:38 2000 +++ linux.ac/net/sunrpc/clnt.c Mon Jun 5 20:09:02 2000 @@ -656,9 +656,11 @@ if (req) printk(KERN_NOTICE "%s: server %s not responding, still trying\n", clnt->cl_protname, clnt->cl_server); +#ifdef RPC_DEBUG else printk(KERN_NOTICE "%s: task %d can't get a request slot\n", clnt->cl_protname, task->tk_pid); +#endif } if (clnt->cl_autobind) clnt->cl_port = 0; @@ -860,7 +862,7 @@ task->tk_client->cl_stats->rpcgarbage++; if (task->tk_garb_retry) { task->tk_garb_retry--; - printk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid); + dprintk(KERN_WARNING "RPC: garbage, retrying %4d\n", task->tk_pid); task->tk_action = call_encode; return NULL; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/sunrpc/sched.c linux.ac/net/sunrpc/sched.c --- linux.vanilla/net/sunrpc/sched.c Thu May 25 17:37:38 2000 +++ linux.ac/net/sunrpc/sched.c Mon Jun 5 20:09:02 2000 @@ -669,8 +669,10 @@ if (task->tk_lock) { spin_unlock_bh(&rpc_queue_lock); printk(KERN_ERR "RPC: Locked task was scheduled !!!!\n"); +#ifdef RPC_DEBUG rpc_debug = ~0; rpc_show_tasks(); +#endif break; } __rpc_remove_wait_queue(task); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/sunrpc/svc.c linux.ac/net/sunrpc/svc.c --- linux.vanilla/net/sunrpc/svc.c Thu May 25 17:37:38 2000 +++ linux.ac/net/sunrpc/svc.c Fri Jun 9 15:50:44 2000 @@ -273,8 +273,8 @@ if (prog != progp->pg_prog) goto err_bad_prog; - versp = progp->pg_vers[vers]; - if (!versp || vers >= progp->pg_nvers) + if (vers >= progp->pg_nvers || + !(versp = progp->pg_vers[vers])) goto err_bad_vers; procp = versp->vs_proc + proc; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/sunrpc/svcsock.c linux.ac/net/sunrpc/svcsock.c --- linux.vanilla/net/sunrpc/svcsock.c Thu May 25 17:37:38 2000 +++ linux.ac/net/sunrpc/svcsock.c Fri Jun 9 15:51:51 2000 @@ -301,7 +301,7 @@ mm_segment_t oldfs; struct msghdr msg; struct socket *sock; - int len; + int len, alen; rqstp->rq_addrlen = sizeof(rqstp->rq_addr); sock = rqstp->rq_sock->sk_sock; @@ -319,6 +319,13 @@ len = sock_recvmsg(sock, &msg, buflen, MSG_DONTWAIT); set_fs(oldfs); + /* sock_recvmsg doesn't fill in the name/namelen, so we must.. + * possibly we should cache this in the svc_sock structure + * at accept time. FIXME + */ + alen = sizeof(rqstp->rq_addr); + sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1); + dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len); @@ -539,15 +546,15 @@ } /* Ideally, we would want to reject connections from unauthorized - * hosts here, but we have no generic client tables. For now, - * we just punt connects from unprivileged ports. */ + * hosts here, but when we get encription, the IP of the host won't + * tell us anything. For now just warn about unpriv connections. + */ if (ntohs(sin.sin_port) >= 1024) { if (net_ratelimit()) printk(KERN_WARNING - "%s: connect from unprivileged port: %u.%u.%u.%u:%d", + "%s: connect from unprivileged port: %u.%u.%u.%u:%d\n", serv->sv_name, NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); - goto failed; } dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name, @@ -584,7 +591,7 @@ struct svc_sock *svsk = rqstp->rq_sock; struct svc_serv *serv = svsk->sk_server; struct svc_buf *bufp = &rqstp->rq_argbuf; - int len, ready; + int len, ready, used; dprintk("svc: tcp_recv %p data %d conn %d close %d\n", svsk, svsk->sk_data, svsk->sk_conn, svsk->sk_close); @@ -618,6 +625,11 @@ svsk->sk_reclen = ntohl(svsk->sk_reclen); if (!(svsk->sk_reclen & 0x80000000)) { + /* FIXME: technically, a record can be fragmented, + * and non-terminal fragments will not have the top + * bit set in the fragment length header. + * But apparently no known nfs clients send fragmented + * records. */ /* FIXME: shutdown socket */ printk(KERN_NOTICE "RPC: bad TCP reclen %08lx", (unsigned long) svsk->sk_reclen); @@ -633,11 +645,21 @@ goto error; if (len < svsk->sk_reclen) { + /* FIXME: if sk_reclen > window-size, then we will + * never be able to receive the record, so should + * shutdown the connection + */ dprintk("svc: incomplete TCP record (%d of %d)\n", len, svsk->sk_reclen); svc_sock_received(svsk, ready); return -EAGAIN; /* record not complete */ } + /* if we think there is only one more record to read, but + * it is bigger than we expect, then two records must have arrived + * together, so pretend we aren't using the record.. */ + if (len > svsk->sk_reclen && ready == 1) + used = 0; + else used = 1; /* Frob argbuf */ bufp->iov[0].iov_base += 4; @@ -664,7 +686,7 @@ svsk->sk_reclen = 0; svsk->sk_tcplen = 0; - svc_sock_received(svsk, 1); + svc_sock_received(svsk, used); if (serv->sv_stats) serv->sv_stats->nettcpcnt++; @@ -692,6 +714,7 @@ svc_tcp_sendto(struct svc_rqst *rqstp) { struct svc_buf *bufp = &rqstp->rq_resbuf; + int sent; /* Set up the first element of the reply iovec. * Any other iovecs that may be in use have been taken @@ -701,7 +724,17 @@ bufp->iov[0].iov_len = bufp->len << 2; bufp->base[0] = htonl(0x80000000|((bufp->len << 2) - 4)); - return svc_sendto(rqstp, bufp->iov, bufp->nriov); + sent = svc_sendto(rqstp, bufp->iov, bufp->nriov); + if (sent != bufp->len<<2) { + printk(KERN_NOTICE "rpc-srv/tcp: %s: sent only %d bytes of %d - should shutdown socket\n", + rqstp->rq_sock->sk_server->sv_name, + sent, bufp->len << 2); + /* FIXME: should shutdown the socket, or allocate more memort + * or wait and try again or something. Otherwise + * client will get confused + */ + } + return sent; } static int diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/net/unix/af_unix.c linux.ac/net/unix/af_unix.c --- linux.vanilla/net/unix/af_unix.c Thu May 25 17:37:37 2000 +++ linux.ac/net/unix/af_unix.c Fri Jun 9 15:47:11 2000 @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.96 2000/05/12 23:51:26 davem Exp $ + * Version: $Id: af_unix.c,v 1.97 2000/06/09 07:35:49 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -445,7 +445,7 @@ { struct sock *sk; - if (atomic_read(&unix_nr_socks) >= 2*max_files) + if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files) return NULL; MOD_INC_USE_COUNT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/cramfs/mkcramfs.c linux.ac/scripts/cramfs/mkcramfs.c --- linux.vanilla/scripts/cramfs/mkcramfs.c Thu May 25 17:38:37 2000 +++ linux.ac/scripts/cramfs/mkcramfs.c Fri Jun 9 15:48:26 2000 @@ -93,7 +93,7 @@ if(!orig) return 0; if(orig->size==newfile->size && orig->uncompressed && !memcmp(orig->uncompressed,newfile->uncompressed,orig->size)) { newfile->same=orig; - return 0; + return 1; } return find_identical_file(orig->child,newfile) || find_identical_file(orig->next,newfile); @@ -441,9 +441,9 @@ size -= input; if (!is_zero (uncompressed, input)) { compress(base + curr, &len, uncompressed, input); - uncompressed += input; curr += len; } + uncompressed += input; if (len > blksize*2) { /* (I don't think this can happen with zlib.) */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/header.tk linux.ac/scripts/header.tk --- linux.vanilla/scripts/header.tk Thu May 25 17:38:37 2000 +++ linux.ac/scripts/header.tk Wed May 31 11:30:18 2000 @@ -110,6 +110,8 @@ wm geometry $w +$winx+$winy } +bind all {maybe_exit .maybe} + proc maybe_exit { w } { catch {destroy $w} toplevel $w -class Dialog @@ -128,6 +130,8 @@ -width 20 -command "destroy $w; focus $oldFocus" pack $w.f.back $w.f.canc -side left -pady 10 -padx 45 pack $w.f -pady 10 -side bottom -padx 10 -anchor w + bind $w "exit" + bind $w "destroy $w; focus $oldFocus" focus $w global winx; global winy set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30] @@ -402,6 +406,7 @@ proc menusplit {w m n} { if { $n > 2 } then { + update idletasks set menuoptsize [expr [$m yposition 2] - [$m yposition 1]] set maxsize [winfo screenheight $w] set splitpoint [expr $maxsize * 4 / 5 / $menuoptsize - 1] @@ -411,6 +416,10 @@ } } +proc menutitle {text menu w} { + wm title $w "$text" +} + proc submenu { w mnum line text subnum } { frame $w.x$line button $w.x$line.l -text "" -width 15 -relief groove @@ -531,6 +540,9 @@ wm maxsize $w [winfo width $w] $sizy } +bind all { catch {exec cp -f .config .config.old}; \ + writeconfig .config include/linux/autoconf.h; wrapup .wrap } + proc wrapup {w } { catch {destroy $w} toplevel $w -class Dialog @@ -554,6 +566,7 @@ pack $w.f.back -side bottom -pady 10 -anchor s pack $w.f -pady 10 -side top -padx 10 -anchor s focus $w + bind $w "exit" global winx; global winy set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30] wm geometry $w +$winx+$winy diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/lxdialog/Makefile linux.ac/scripts/lxdialog/Makefile --- linux.vanilla/scripts/lxdialog/Makefile Thu May 25 17:38:37 2000 +++ linux.ac/scripts/lxdialog/Makefile Sat May 27 15:35:16 2000 @@ -1,20 +1,16 @@ -CC = $(HOSTCC) -CPP = $(HOSTCC) -E - -CFLAGS = $(HOSTCFLAGS) -DLOCALE -LDFLAGS = -s -L . -LDLIBS = -lncurses +HOSTCFLAGS += -DLOCALE +LIBS = -lncurses ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) - CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" + HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" else ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h)) - CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" + HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" else ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h)) - CFLAGS += -DCURSES_LOC="" + HOSTCFLAGS += -DCURSES_LOC="" else - CFLAGS += -DCURSES_LOC="" + HOSTCFLAGS += -DCURSES_LOC="" endif endif endif @@ -22,16 +18,18 @@ OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \ util.o lxdialog.o msgbox.o -SRCS = $(OBJS:.o=.c) +%.o: %.c + $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $< all: ncurses lxdialog lxdialog: $(OBJS) + $(HOSTCC) -o lxdialog $(OBJS) $(LIBS) ncurses: @echo "main() {}" > lxtemp.c - @if $(CC) -lncurses lxtemp.c ; then \ + @if $(HOSTCC) -lncurses lxtemp.c ; then \ rm -f lxtemp.c a.out; \ else \ rm -f lxtemp.c; \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/tail.tk linux.ac/scripts/tail.tk --- linux.vanilla/scripts/tail.tk Thu May 25 17:38:37 2000 +++ linux.ac/scripts/tail.tk Wed May 31 11:30:18 2000 @@ -32,11 +32,11 @@ update_define 1 $total_menus 0 update_mainmenu -button .f0.right.save -anchor w -text "Save and Exit" \ +button .f0.right.save -anchor w -text "Save and Exit" -underline 0\ -command { catch {exec cp -f .config .config.old}; \ writeconfig .config include/linux/autoconf.h; wrapup .wrap } -button .f0.right.quit -anchor w -text "Quit Without Saving" \ +button .f0.right.quit -anchor w -text "Quit Without Saving" -underline 0\ -command { maybe_exit .maybe } button .f0.right.load -anchor w -text "Load Configuration from File" \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/tkgen.c linux.ac/scripts/tkgen.c --- linux.vanilla/scripts/tkgen.c Thu May 25 17:38:37 2000 +++ linux.ac/scripts/tkgen.c Mon Jun 5 19:56:16 2000 @@ -149,18 +149,10 @@ printf( "\tpack $w.m -pady 10 -side top -padx 10\n" ); printf( "\twm title $w \"%s\" \n\n", label ); - /* - * Attach the "Prev", "Next" and "OK" buttons at the end of the window. - */ - printf( "\tframe $w.f\n" ); - if ( toplevel ) - printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" ); - else - printf( "\tbutton $w.f.back -text \"OK\" \\\n" ); - printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d\"\n", - menu_num ); - printf( "\tbutton $w.f.next -text \"Next\" \\\n" ); - printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; " ); + printf( "\tbind $w \"catch {focus $oldFocus}; destroy $w; unregister_active %d; break\"\n", menu_num); + + printf("\tset nextscript "); + printf("\"catch {focus $oldFocus}; " ); /* * We are checking which windows should be destroyed and which are * common parrents with the next one. Remember that menu_num field @@ -182,13 +174,48 @@ } printf( "menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1 ); - if ( menu_num == tot_menu_num ) - printf( "\t$w.f.next configure -state disabled\n" ); - printf( "\tbutton $w.f.prev -text \"Prev\" \\\n" ); + + /* + * Attach the "Prev", "Next" and "OK" buttons at the end of the window. + */ + printf( "\tframe $w.f\n" ); + if ( toplevel ) + printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" ); + else + printf( "\tbutton $w.f.back -text \"OK\" \\\n" ); + printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d\"\n", + menu_num ); + printf( "\tbutton $w.f.next -text \"Next\" -underline 0\\\n" ); + printf( "\t\t-width 15 -command $nextscript\n"); + + if ( menu_num == tot_menu_num ) { + printf( "\t$w.f.next configure -state disabled\n" ); + /* + * this is a bit hackish but Alt-n must be rebound + * otherwise if the user press Alt-n on the last menu + * it will give him/her the next menu of one of the + * previous options + */ + printf( "\tbind all \"puts \\\"no more menus\\\" \"\n"); + } + else + { + /* + * I should be binding to $w not all - but if I do nehat I get the error "unknown path" + */ + printf( "\tbind all $nextscript\n"); + } + printf( "\tbutton $w.f.prev -text \"Prev\" -underline 0\\\n" ); printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\"\"\n", menu_num, menu_num-1, menu_num-1 ); - if ( menu_num == 1 ) + if ( menu_num == 1 ) { printf( "\t$w.f.prev configure -state disabled\n" ); + } + else + { + printf( "\tbind $w \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\";break\"\n", + menu_num, menu_num-1, menu_num-1 ); + } printf( "\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n" ); printf( "\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n" ); @@ -215,6 +242,12 @@ printf( "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n" ); printf( "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n" ); printf( "\tframe $w.config.f\n" ); + printf( "\tbind $w \"$w.config.canvas yview scroll 1 unit;break;\"\n"); + printf( "\tbind $w \"$w.config.canvas yview scroll -1 unit;break;\"\n"); + printf( "\tbind $w \"$w.config.canvas yview scroll 1 page;break;\"\n"); + printf( "\tbind $w \"$w.config.canvas yview scroll -1 page;break;\"\n"); + printf( "\tbind $w \"$w.config.canvas yview moveto 0;break;\"\n"); + printf( "\tbind $w \"$w.config.canvas yview moveto 1 ;break;\"\n"); printf( "\tpack $w.config.canvas -side right -fill y\n" ); printf("\n\n"); } @@ -974,7 +1007,7 @@ } else printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" ); - printf( "\twm geometry $w +$winx+$winy\n" ); + printf( "\tif {[winfo exists $w]} then {wm geometry $w +$winx+$winy}\n" ); /* * Now that the whole window is in place, we need to wait for an "update" @@ -987,7 +1020,7 @@ * around frames. Sigh. */ printf( "\tupdate idletasks\n" ); - printf( "\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" ); + printf( "\tif {[winfo exists $w]} then {$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" ); printf( "\t$w.config.canvas configure \\\n" ); printf( "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n" ); printf( "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n" ); @@ -1005,17 +1038,17 @@ printf( "\t\t$w.config.canvas configure -height $canvtotal\n" ); printf( "\t} else {\n" ); printf( "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n" ); - printf( "\t}\n" ); + printf( "\t\t}\n\t}\n" ); /* * Limit the min/max window size. Height can vary, but not width, * because of the limitations of canvas and our laziness. */ printf( "\tupdate idletasks\n" ); - printf( "\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n" ); + printf( "\tif {[winfo exists $w]} then {\n\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n" ); printf( "\twm minsize $w [winfo width $w] 100\n\n" ); printf( "\twm deiconify $w\n" ); - printf( "}\n\n\n" ); + printf( "}\n}\n\n" ); /* * Now we generate the companion procedure for the menu we just @@ -1248,7 +1281,7 @@ printf( "\tminimenu $w.config.f %d %d \"%s\" tmpvar_%d %s\n", cfg->menu_number, cfg->menu_line, cfg->label, -(cfg->nameindex), vartable[cfg->next->nameindex].name ); - printf( "\tmenu $w.config.f.x%d.x.menu -title \"%s\"\n", + printf( "\tmenu $w.config.f.x%d.x.menu -tearoffcommand \"menutitle \\\"%s\\\"\"\n", cfg->menu_line, cfg->label ); cfg1 = cfg; opt_count = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/scripts/tkparse.c linux.ac/scripts/tkparse.c --- linux.vanilla/scripts/tkparse.c Thu May 25 17:38:37 2000 +++ linux.ac/scripts/tkparse.c Fri May 26 15:25:23 2000 @@ -173,6 +173,28 @@ /* + * Get a quoted or unquoted string. It is recognized by the first + * non-white character. '"' and '"' are not allowed inside the string. + */ +static const char * get_qnqstring( const char * pnt, char ** label ) +{ + char quote_char; + + while ( *pnt == ' ' || *pnt == '\t' ) + pnt++; + + if ( *pnt == '\0' ) + return pnt; + quote_char = *pnt; + if ( quote_char == '"' || quote_char == '\'' ) + return get_qstring( pnt, label ); + else + return get_string( pnt, label ); +} + + + +/* * Tokenize an 'if' statement condition. */ static struct condition * tokenize_if( const char * pnt ) @@ -505,6 +527,8 @@ if ( last_menuoption != NULL ) { pnt = get_qstring(pnt, &cfg->label); + if (cfg->label == NULL) + syntax_error( "missing comment text" ); last_menuoption->label = cfg->label; last_menuoption = NULL; } @@ -546,7 +570,9 @@ case token_define_string: pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); - pnt = get_qstring( pnt, &cfg->value ); + pnt = get_qnqstring( pnt, &cfg->value ); + if (cfg->value == NULL) + syntax_error( "missing value" ); break; case token_dep_bool: @@ -659,7 +685,9 @@ pnt = get_qstring ( pnt, &cfg->label ); pnt = get_string ( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); - pnt = get_qstring ( pnt, &cfg->value ); + pnt = get_qnqstring ( pnt, &cfg->value ); + if (cfg->value == NULL) + syntax_error( "missing initial value" ); break; case token_if: