diff -u --recursive --new-file v2.3.34/linux/CREDITS linux/CREDITS --- v2.3.34/linux/CREDITS Mon Dec 20 18:48:21 1999 +++ linux/CREDITS Sun Dec 26 19:34:04 1999 @@ -331,6 +331,10 @@ S: Amsterdam S: The Netherlands +N: Zach Brown +E: zab@zabbo.net +D: maestro pci sound + N: Ray Burr E: ryb@nightmare.com D: Original author of Amiga FFS filesystem @@ -997,12 +1001,12 @@ S: United Kingdom N: Jakub Jelinek -E: jj@sunsite.mff.cuni.cz +E: jakub@redhat.com W: http://sunsite.mff.cuni.cz/~jj P: 1024/0F7623C5 53 95 71 3C EB 73 99 97 02 49 40 47 F9 19 68 20 D: Sparc hacker, SILO, mc D: Maintain sunsite.mff.cuni.cz -S: Na Orechovce 7 +S: K osmidomkum 723 S: 160 00 Praha 6 S: Czech Republic diff -u --recursive --new-file v2.3.34/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.34/linux/Documentation/Configure.help Mon Dec 20 18:48:21 1999 +++ linux/Documentation/Configure.help Mon Dec 27 14:01:53 1999 @@ -7852,18 +7852,18 @@ Support for USB (EXPERIMENTAL) CONFIG_USB Universal Serial Bus (USB) is a specification for a serial bus - system which offers higher speeds and more features than the + subsystem which offers higher speeds and more features than the traditional PC serial port. The bus supplies power to peripherals and allows for hot swapping. Up to 127 USB peripherals can be - connected to a single USB port in a tree structure; the USB port is - the root of the tree, the peripherals are the leafs and the inner - nodes are special USB devices called hubs. Many newer PC's have USB + connected to a single USB port in a tree structure. The USB port is + the root of the tree, the peripherals are the leaves, and the inner + nodes are special USB devices called hubs. Many newer PCs have USB ports and newer peripherals such as scanners, keyboards, mice, - modems and printers support the USB protocol and can be connected to - the PC via those ports. + modems, and printers support the USB protocol and can be connected + to the PC via those ports. Say Y here if your computer has a USB port and you want to - experiment with USB devices. You then need to say Y to at least one + use USB devices. You then need to say Y to at least one of "UHCI support" or "OHCI support" below (the type of interface that the USB hardware in your computer provides) and then choose from among the drivers for USB peripherals. @@ -7873,7 +7873,7 @@ The module will be called usbcore.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -UHCI (intel PIIX4 and others) support? +UHCI (intel PIIX4, VIA, and others) support? CONFIG_USB_UHCI The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB @@ -7886,20 +7886,17 @@ The module will be called usb-uhci.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -OHCI-HCD (compaq and some others) support? +OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support? CONFIG_USB_OHCI_HCD - The Open Host Controller Interface is a standard by Compaq for - accessing the USB PC hardware (also called USB host controller). If - your USB host controller conforms to this standard, say Y. The USB - host controllers on most non-Intel architectures and on several x86 - compatibles with non-Intel chipsets conform to this standard. + The Open Host Controller Interface is a standard by + Compaq/Microsoft/National for accessing the USB PC hardware (also + called USB host controller). If your USB host controller conforms + to this standard, say Y. The USB host controllers on most + non-Intel architectures and on several x86 compatibles with + non-Intel chipsets conform to this standard. You may want to read the file drivers/usb/README.ohci_hcd. - There are currently two OHCI drivers in development. You should - compile at most one. The other one is "OHCI (compaq and some others) - support?", above. - 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 usb-ohci-hcd.o. If you want to compile it @@ -7915,11 +7912,11 @@ The module will be called mouse.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -USB HP scanner support -CONFIG_USB_HP_SCANNER - Say Y here if you want to connect a USB HP scanner to your - computer's USB port. Please read drivers/usb/README.hp_scanner - for more information. +USB scanner support +CONFIG_USB_SCANNER + Say Y here if you want to connect a USB scanner to your + computer's USB port. Please read drivers/usb/README.scanner + and drivers/usb/README.scanner_hp_sane for more information. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -7938,7 +7935,7 @@ USB audio parsing support CONFIG_USB_AUDIO - Say Y here if you want to connect audio equipment such as USB + Say Y here if you want to connect USB audio equipment such as speakers to your computer's USB port. This code is also available as a module ( = code which can be @@ -7957,9 +7954,10 @@ The module will be called acm.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -USB Belkin and Peracom serial support +USB serial converter support CONFIG_USB_SERIAL - Say Y here if you want to connect a Belkin, Peracom, or eTek + Say Y here if you want to connect a Connect Tech WhiteHEAT + multi-port USB to serial converter, or a Belkin, Peracom, or eTek single port USB to serial converter. This code is also available as a module ( = code which can be @@ -7969,7 +7967,7 @@ USB Printer support CONFIG_USB_PRINTER - Say Y here if you want to connect a printer to your computer's USB + Say Y here if you want to connect a USB printer to your computer's USB port. This code is also available as a module ( = code which can be @@ -8001,8 +7999,13 @@ USB SCSI Support CONFIG_USB_SCSI - Say Y here if you want to connect SCSI devices to your computer's - USB port. + Say Y here if you want to connect USB mass storage devices to your + computer's USB port. + + 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 usb-scsi.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. USB SCSI verbose debug CONFIG_USB_SCSI_DEBUG @@ -8027,7 +8030,7 @@ Manual mode is not limited to printers, any parallel port device should work. This driver utilizes manual mode. - Note however that some operations are three orders of a magnitude + Note however that some operations are three orders of magnitude slower than on a PCI/ISA Parallel Port, so timing critical applications might not work. @@ -8039,22 +8042,27 @@ The module will be called uss720.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -USB /proc filesystem entry support (Preliminary) +USB /proc filesystem support CONFIG_USB_PROC This reports USB drivers and devices in the /proc filesystem. Entries are located in /proc/bus/usb. The entries are described in the file Documentation/proc_usb_info.txt. - Note that you must say Y to "/proc filesystem support" below for - this to work. + Note that you must say Y to global "/proc filesystem support" under + Filesystems for this to work. DABUSB driver CONFIG_USB_DABUSB - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought to - you by the DAB-Team (http://dab.in.tum.de). + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought + to you by the DAB-Team (http://dab.in.tum.de). This driver can be taken as an example for URB-based bulk, control, and isochronous transactions. + 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 dabusb.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + ACPI support CONFIG_ACPI Advanced Configuration and Power Interface (ACPI) is an interface @@ -8834,10 +8842,9 @@ Lowercase DOS filenames on LONG namespace volume CONFIG_NCPFS_SMALLDOS If you say Y here, every filename on a NetWare server volume using - the OS2/LONG namespace will be converted to lowercase characters. - (For regular NetWare file server volumes with DOS namespace, this is - done automatically, even if you say N here.) Saying N here will give - you these filenames in uppercase. + the OS2/LONG namespace and created under DOS or on a volume using + DOS namespace will be converted to lowercase characters. + Saying N here will give you these filenames in uppercase. This is only a cosmetic option since the OS2/LONG namespace is case insensitive. The only major reason for this option is backward @@ -11171,6 +11178,12 @@ engine. See Documentation/sound/NM256 for further information. + +ESS Maestro sound chipsets +CONFIG_SOUND_MAESTRO + Say Y or M if you have a sound system driven by ESS's Maestro line + of PCI sound chips. These include the Maestro 1, Maestro 2, and + Maestro 2E. See Documentation/sound/Maestro for more details. Are you using a crosscompiler CONFIG_CROSSCOMPILE diff -u --recursive --new-file v2.3.34/linux/Documentation/filesystems/cramfs.txt linux/Documentation/filesystems/cramfs.txt --- v2.3.34/linux/Documentation/filesystems/cramfs.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/filesystems/cramfs.txt Mon Dec 27 13:16:57 1999 @@ -0,0 +1,13 @@ + + Cramfs - cram a filesystem onto a small ROM + +cramfs is designed to be simple and small, and to compress things well. + +It uses the zlib routines to compress a file one page at a time, and +allows random page access. The meta-data is not compressed, but is +expressed in a very terse representation to make it use much less +diskspace than traditional filesystems. + +You can't write to a cramfs filesystem (making it compressible and +compact also makes it _very_ hard to update on-the-fly), so you have to +create the disk image with the "mkcramfs" utility in scripts/cramfs. diff -u --recursive --new-file v2.3.34/linux/Documentation/filesystems/vfat.txt linux/Documentation/filesystems/vfat.txt --- v2.3.34/linux/Documentation/filesystems/vfat.txt Mon Dec 20 18:48:21 1999 +++ linux/Documentation/filesystems/vfat.txt Tue Dec 21 14:28:39 1999 @@ -29,8 +29,8 @@ a '?' is used when no translation is possible. The escape character is ':' because it is otherwise illegal on the vfat filesystem. The escape sequence - that gets used, where u is the unicode character, is: - ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12), + that gets used is ':' and the four digits of hexadecimal + unicode. posix= -- Allow names of same letters, different case such as 'LongFileName' and 'longfilename' to coexist. This has some problems currently because 8.3 conflicts are not handled diff -u --recursive --new-file v2.3.34/linux/Documentation/networking/sis900.txt linux/Documentation/networking/sis900.txt --- v2.3.34/linux/Documentation/networking/sis900.txt Tue Nov 23 22:42:20 1999 +++ linux/Documentation/networking/sis900.txt Sat Dec 25 11:21:15 1999 @@ -1,6 +1,6 @@ SiS 900/7016 Fast Ethernet Device Driver by Ollie Lho (ollie@sis.com.tw) - November 4, 1999. Document Revision: 0.1 + November 4, 1999. Document Revision: 0.2 This document gives some information on installation and usage of SiS 900/7016 device driver under Linux. @@ -17,7 +17,7 @@ 4. Tested Environment - 5. Files in This Rackage + 5. Files in This Package 6. Installation @@ -111,9 +111,11 @@ 9. Names of variables were changed to be more consistent. - 10. Clean up of auo-negotiation and timer code. + 10. + Clean up of auo-negotiation and timer code. - 11. Automatic detection and change of PHY on the fly. + 11. + Automatic detection and change of PHY on the fly. 4. Tested Environment @@ -137,7 +139,7 @@ o Samba version 2.0.3 - 5. Files in This Rackage + 5. Files in This Package In the package you can find these files: @@ -157,10 +159,16 @@ 6. Installation - Before trying to install the driver, be sure to get the latest - revision from SiS' Home Page. If you have no prior experience in - networking under Linux, please read Ethernet HOWTO and Networking - HOWTO available from Linux Documentation Project (LDP). + Silicon Integrated System Corp. is cooperating closely with core Linux + Kernel developers. The revisions of SiS 900 driver are distributed by + the usuall channels for kernel tar files and patches. Those kernel tar + files for official kernel and patches for kernel pre-release can be + download at official kernel ftp site + and its mirrors. The 1.06 + revision can be found in kernel version later than 2.3.15 and + pre-2.2.14. If you have no prior experience in networking under + Linux, please read Ethernet HOWTO and Networking HOWTO available from + Linux Documentation Project (LDP). The installation procedure are different according to your kernel versions. @@ -244,6 +252,7 @@ sis900.c: v1.06 11/04/99 eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4. eth0: SiS 900 Internal MII PHY transceiver found at address 1. + eth0: Using SiS 900 Internal MII PHY as default @@ -269,7 +278,6 @@ - eth0: Using SiS 900 Internal MII PHY as default eth0: Media Link On 100mbps full-duplex diff -u --recursive --new-file v2.3.34/linux/Documentation/proc_usb_info.txt linux/Documentation/proc_usb_info.txt --- v2.3.34/linux/Documentation/proc_usb_info.txt Mon Dec 20 18:48:21 1999 +++ linux/Documentation/proc_usb_info.txt Tue Dec 21 11:51:03 1999 @@ -149,6 +149,9 @@ of the USB devices on a system's root hub. (See more below on how to do this.) +The Interface lines can be used to determine what driver is +being used for each device. + The Configuration lines could be used to list maximum power (in milliamps) that a system's USB devices are using. For example, "grep ^C: /proc/bus/usb/devices". @@ -156,65 +159,57 @@ Here's an example, from a system which has a UHCI root hub, an external hub connected to the root hub, and a mouse and -a video camera connected to the external hub. [The video -camera is listed as (none) since it is not recognized by -any driver.] - +a serial converter connected to the external hub. -T: Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= -1 Spd=12 If#= 0 MxCh= 2 Driver=(root hub) -T: Lev=01 Prnt=00 Port=00 Cnt=01 Dev#= 1 Spd=12 If#= 0 MxCh= 4 Driver=hub +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0451 ProdID=1446 Rev= 1.00 -C:* #If= 1 Cfg#= 1 Atr=e0 MxPwr=100mA -I: If#= 0 Alt= 0 #EP= 1 Cls=09(hub ) Sub=00 Prot=00 +C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms -T: Lev=02 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=1.5 If#= 0 MxCh= 0 Driver=mouse +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 -P: Vendor=0458 ProdID=0001 Rev= 0.00 -C:* #If= 1 Cfg#= 1 Atr=a0 MxPwr=100mA -I: If#= 0 Alt= 0 #EP= 1 Cls=03(HID ) Sub=01 Prot=02 +P: Vendor=04b4 ProdID=0001 Rev= 0.00 +C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms -T: Lev=02 Prnt=01 Port=02 Cnt=02 Dev#= 4 Spd=12 If#= 0 MxCh= 0 Driver=(none) +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 -P: Vendor=04c8 ProdID=0720 Rev= 1.01 -C:* #If= 1 Cfg#= 1 Atr=80 MxPwr=500mA -I: If#= 0 Alt= 0 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00 -E: Ad=81(I) Atr=01(Isoc) MxPS= 1 Ivl= 1ms -E: Ad=82(I) Atr=01(Isoc) MxPS= 384 Ivl= 1ms -I: If#= 0 Alt= 1 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00 -E: Ad=81(I) Atr=01(Isoc) MxPS= 1 Ivl= 1ms -E: Ad=82(I) Atr=01(Isoc) MxPS= 240 Ivl= 1ms -I: If#= 0 Alt= 2 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00 -E: Ad=81(I) Atr=01(Isoc) MxPS= 1 Ivl= 1ms -E: Ad=82(I) Atr=01(Isoc) MxPS= 576 Ivl= 1ms -I: If#= 0 Alt= 3 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00 -E: Ad=81(I) Atr=01(Isoc) MxPS= 1 Ivl= 1ms -E: Ad=82(I) Atr=01(Isoc) MxPS= 464 Ivl= 1ms -I: If#= 0 Alt= 4 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00 -E: Ad=81(I) Atr=01(Isoc) MxPS= 1 Ivl= 1ms -E: Ad=82(I) Atr=01(Isoc) MxPS= 688 Ivl= 1ms - - -Selecting only the "T:" lines from this (for example, by using -"procusb t"), we have: - -T: Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= -1 Spd=12 If#= 0 MxCh= 2 Driver=(root hub) -T: Lev=01 Prnt=00 Port=00 Cnt=01 Dev#= 1 Spd=12 If#= 0 MxCh= 4 Driver=hub -T: Lev=02 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=1.5 If#= 0 MxCh= 0 Driver=mouse -T: Lev=02 Prnt=01 Port=02 Cnt=02 Dev#= 4 Spd=12 If#= 0 MxCh= 0 Driver=(none) +P: Vendor=0565 ProdID=0001 Rev= 1.08 +S: Manufacturer=Peracom Networks, Inc. +S: Product=Peracom USB to Serial Converter +C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial +E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl= 16ms +E: Ad=01(O) Atr=02(Bulk) MxPS= 16 Ivl= 16ms +E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms + + +Selecting only the "T:" and "I:" lines from this (for example, by using +"procusb ti"), we have: + +T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2 +T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4 +I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub +T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0 +I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse +T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 +I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial Physically this looks like (or could be converted to): +------------------+ - | PC/root_hub (12)| Dev# = -1 + | PC/root_hub (12)| Dev# = 1 +------------------+ (nn) is Mbps. Level 0 | CN.0 | CN.1 | [CN = connector/port #] +------------------+ / / +-----------------------+ - Level 1 | Dev#1: 4-port hub (12)| + Level 1 | Dev#2: 4-port hub (12)| +-----------------------+ |CN.0 |CN.1 |CN.2 |CN.3 | +-----------------------+ @@ -222,7 +217,7 @@ \_____ \ \ \ +--------------------+ +--------------------+ - Level 2 | Dev# 3: mouse (1.5)| | Dev# 4: (none) (12)| + Level 2 | Dev# 3: mouse (1.5)| | Dev# 4: serial (12)| +--------------------+ +--------------------+ @@ -230,11 +225,11 @@ Or, in a more tree-like structure (ports [Connectors] without connections could be omitted): -PC: Dev# -1, root hub, 2 ports, 12 Mbps -|_ CN.0: Dev# 1, hub, 4 ports, 12 Mbps +PC: Dev# 1, root hub, 2 ports, 12 Mbps +|_ CN.0: Dev# 2, hub, 4 ports, 12 Mbps |_ CN.0: Dev #3, mouse, 1.5 Mbps |_ CN.1: - |_ CN.2: Dev #4, (none), 12 Mbps [or use "unknown" for (none)] + |_ CN.2: Dev #4, serial, 12 Mbps |_ CN.3: |_ CN.1: diff -u --recursive --new-file v2.3.34/linux/Documentation/sound/Maestro linux/Documentation/sound/Maestro --- v2.3.34/linux/Documentation/sound/Maestro Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/Maestro Sun Dec 26 19:34:04 1999 @@ -0,0 +1,98 @@ + An OSS/Lite Driver for the ESS Maestro family of sound cards + + Zach Brown, December 1999 + +Driver Status and Availability +------------------------------ + +The most recent version of this driver will hopefully always be available at + http://people.redhat.com/zab/maestro/ + +I will try and maintain the most recent stable version of the driver +in both the stable and development kernel lines. + +ESS Maestro Chip Family +----------------------- + +There are 3 main variants of the ESS Maestro PCI sound chip. The first +is the Maestro 1. It was originally produced by Platform Tech as the +'AGOGO'. It can be recognized by Platform Tech's PCI ID 0x1285 with +0x0100 as the device ID. It was put on some sound boards and a few laptops. +ESS bought the design and cleaned it up as the Maestro 2. This starts +their marking with the ESS vendor ID 0x125D and the 'year' device IDs. +The Maestro 2 claims 0x1968 while the Maestro 2e has 0x1978. + +The various families of Maestro are mostly identical as far as this +driver is concerned. It doesn't touch the DSP parts that differ (though +it could for FM synthesis) + +Driver OSS Behavior +-------------------- + +This OSS driver exports /dev/mixer and /dev/dsp to applications, which +mostly adhere to the OSS spec. This driver doesn't register itself +with /dev/sndstat, so don't expect information to appear there. + +The /dev/dsp device exported behaves almost as expected. Playback is +supported in all the various lovely formats. 8/16bit stereo/mono from +8khz to 48khz, and mmap()ing for playback behaves. Capture/recording +is limited due to oddities with the Maestro hardware. One can only +record in 16bit stereo. For recording the maestro uses non interleaved +stereo buffers so that mmap()ing the incoming data does not result in +a ring buffer of LRLR data. mmap()ing of the read buffers is therefore +disallowed until this can be cleaned up. + +/dev/mixer is an interface to the AC'97 codec on the Maestro. It is +worth noting that there are a variety of AC'97s that can be wired to +the Maestro. Which is used is entirely up to the hardware implementor. +This should only be visible to the user by the presence, or lack, of +'Bass' and 'Treble' sliders in the mixer. Not all AC'97s have them. + +The driver doesn't support MIDI or FM playback at the moment. Typically +the Maestro is wired to an MPU MIDI chip, but some hardware implementations +don't. We need to assemble a white list of hardware implementations that +have MIDI wired properly before we can claim to support it safely. + +Compiling and Installing +------------------------ + +With the drivers inclusion into the kernel, compiling and installing +is the same as most OSS/Lite modular sound drivers. Compilation +of the driver is enabled through the CONFIG_SOUND_MAESTRO variable +in the config system. + +It may be modular or statically linked. If it is modular it should be +installed with the rest of the modules for the kernel on the system. +Typically this will be in /lib/modules/ somewhere. 'alias sound maestro' +should also be added to your module configs (typically /etc/conf.modules) +if you're using modular OSS/Lite sound and want to default to using a +maestro chip. + +As this is a PCI device, the module does not need to be informed of +any IO or IRQ resources it should use, it devines these from the +system. Somtimes, on sucky PCs, the BIOS fails to allocated resources +for the maestro. This will result in a message like: + maestro: PCI subsystem reports IRQ 0, this might not be correct. +from the kernel. Should this happen the sound chip most likely will +not operate correctly. To solve this one has to dig through their BIOS +(typically entered by hitting a hot key at boot time) and figure out +what magic needs to happen so that the BIOS will reward the maestro with +an IRQ. This operation is incredibly system specific, so you're on your +own. Sometimes the magic lies in 'PNP Capable Operating System' settings. + +There are very few options to the driver. One is 'debug' which will +tell the driver to print minimal debugging information as it runs. This +can be collected with 'dmesg' or through the klogd daemon. + +The other, more interesting option, is 'dsps_order'. Typically at +install time the driver will only register one available /dev/dsp device +for its use. The 'dsps_order' module parameter allows for more devices +to be allocated, as a power of two. Up to 4 devices can be registered +( dsps_order=2 ). These devices act as fully distinct units and use +separate channels in the maestro. + +.. more details .. +----------------- + +drivers/sound/maestro.c contains comments that hopefully explain +the maestro implementation. diff -u --recursive --new-file v2.3.34/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.34/linux/MAINTAINERS Mon Dec 20 18:48:21 1999 +++ linux/MAINTAINERS Sun Dec 26 19:34:04 1999 @@ -529,6 +529,12 @@ L: linuxppc-dev@lists.linuxppc.org S: Maintained +MAESTRO PCI SOUND DRIVER +P: Zach Brown +M: zab@redhat.com +W: http://people.redhat.com/zab/maestro/ +S: Supported + M68K P: Jes Sorensen M: Jes.Sorensen@cern.ch diff -u --recursive --new-file v2.3.34/linux/Makefile linux/Makefile --- v2.3.34/linux/Makefile Mon Dec 20 18:48:21 1999 +++ linux/Makefile Mon Dec 27 15:59:32 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 34 +SUBLEVEL = 35 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -109,7 +109,6 @@ # CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o -FILESYSTEMS =fs/filesystems.a NETWORKS =net/network.a DRIVERS =drivers/block/block.a \ drivers/char/char.o \ @@ -256,7 +255,6 @@ $(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \ --start-group \ $(CORE_FILES) \ - $(FILESYSTEMS) \ $(NETWORKS) \ $(DRIVERS) \ $(LIBS) \ diff -u --recursive --new-file v2.3.34/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.34/linux/arch/i386/config.in Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/config.in Sat Dec 25 15:03:57 1999 @@ -119,6 +119,7 @@ source drivers/parport/Config.in +bool 'ACPI support' CONFIG_ACPI bool 'Advanced Power Management BIOS support' CONFIG_APM if [ "$CONFIG_APM" != "n" ]; then bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND diff -u --recursive --new-file v2.3.34/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.34/linux/arch/i386/defconfig Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/defconfig Tue Dec 28 10:59:24 1999 @@ -59,8 +59,9 @@ # CONFIG_PCMCIA=y CONFIG_CARDBUS=y -CONFIG_I82365=y -# CONFIG_TCIC is not set +CONFIG_YENTA=y +# CONFIG_I82365 is not set +CONFIG_TCIC=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y @@ -70,6 +71,7 @@ CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y # CONFIG_PARPORT is not set +CONFIG_ACPI=y # CONFIG_APM is not set # @@ -404,7 +406,6 @@ # # Misc devices # -CONFIG_ACPI=y # # Filesystems @@ -416,6 +417,7 @@ # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set +# CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.3.34/linux/arch/i386/kernel/Makefile Thu Nov 11 20:11:31 1999 +++ linux/arch/i386/kernel/Makefile Sat Dec 25 15:04:47 1999 @@ -39,6 +39,10 @@ endif endif +ifeq ($(CONFIG_ACPI),y) + OX_OBJS += acpi.o +endif + ifeq ($(CONFIG_APM),y) OX_OBJS += apm.o else diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c --- v2.3.34/linux/arch/i386/kernel/acpi.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/kernel/acpi.c Sat Dec 25 14:52:52 1999 @@ -0,0 +1,1318 @@ +/* + * acpi.c - Linux ACPI driver + * + * Copyright (C) 1999 Andrew Henroid + * + * 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 + */ + +/* + * See http://www.geocities.com/SiliconValley/Hardware/3165/ + * for the user-level ACPI stuff + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Defines for 2.2.x + */ +#ifndef __exit +#define __exit +#endif +#ifndef module_init +#define module_init(x) int init_module(void) {return x();} +#endif +#ifndef module_exit +#define module_exit(x) void cleanup_module(void) {x();} +#endif +#ifndef DECLARE_WAIT_QUEUE_HEAD +#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL +#endif + +/* + * Yes, it's unfortunate that we are relying on get_cmos_time + * because it is slow (> 1 sec.) and i386 only. It might be better + * to use some of the code from drivers/char/rtc.c in the near future + */ +extern unsigned long get_cmos_time(void); + +static int acpi_control_thread(void *context); +static int acpi_do_ulong(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); +static int acpi_do_event_reg(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); +static int acpi_do_event(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); +static int acpi_do_sleep(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); + +DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait); + +static struct ctl_table_header *acpi_sysctl = NULL; + +static struct acpi_facp *acpi_facp = NULL; +static int acpi_fake_facp = 0; +static struct acpi_facs *acpi_facs = NULL; +static unsigned long acpi_facp_addr = 0; +static unsigned long acpi_dsdt_addr = 0; + +// current system sleep state (S0 - S4) +static acpi_sstate_t acpi_sleep_state = ACPI_S0; +// time sleep began +static unsigned long acpi_sleep_start = 0; + +static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; +static volatile u32 acpi_pm1_status = 0; +static volatile u32 acpi_gpe_status = 0; +static volatile u32 acpi_gpe_level = 0; +static volatile acpi_sstate_t acpi_event_state = ACPI_S0; +static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); + +static spinlock_t acpi_devs_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(acpi_devs); + +/* Make it impossible to enter C2/C3 until after we've initialized */ +static unsigned long acpi_enter_lvl2_lat = ACPI_INFINITE_LAT; +static unsigned long acpi_enter_lvl3_lat = ACPI_INFINITE_LAT; +static unsigned long acpi_p_lvl2_lat = ACPI_INFINITE_LAT; +static unsigned long acpi_p_lvl3_lat = ACPI_INFINITE_LAT; + +static unsigned long acpi_p_blk = 0; + +static int acpi_p_lvl2_tested = 0; +static int acpi_p_lvl3_tested = 0; + +// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb +static unsigned long acpi_slp_typ[] = +{ + ACPI_SLP_TYP_DISABLED, /* S0 */ + ACPI_SLP_TYP_DISABLED, /* S1 */ + ACPI_SLP_TYP_DISABLED, /* S2 */ + ACPI_SLP_TYP_DISABLED, /* S3 */ + ACPI_SLP_TYP_DISABLED, /* S4 */ + ACPI_SLP_TYP_DISABLED /* S5 */ +}; + +static struct ctl_table acpi_table[] = +{ + {ACPI_FACP, "facp", + &acpi_facp_addr, sizeof(acpi_facp_addr), + 0400, NULL, &acpi_do_ulong}, + + {ACPI_DSDT, "dsdt", + &acpi_dsdt_addr, sizeof(acpi_dsdt_addr), + 0400, NULL, &acpi_do_ulong}, + + {ACPI_PM1_ENABLE, "pm1_enable", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_GPE_ENABLE, "gpe_enable", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_GPE_LEVEL, "gpe_level", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, + + {ACPI_P_BLK, "p_blk", + &acpi_p_blk, sizeof(acpi_p_blk), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL2_LAT, "p_lvl2_lat", + &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL3_LAT, "p_lvl3_lat", + &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_S0_SLP_TYP, "s0_slp_typ", + &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_S1_SLP_TYP, "s1_slp_typ", + &acpi_slp_typ[ACPI_S1], sizeof(acpi_slp_typ[ACPI_S1]), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_S5_SLP_TYP, "s5_slp_typ", + &acpi_slp_typ[ACPI_S5], sizeof(acpi_slp_typ[ACPI_S5]), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, + + {0} +}; + +static struct ctl_table acpi_dir_table[] = +{ + {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, + {0} +}; + + +/* + * Get the value of the PM1 control register (SCI_EN, ...) + */ +static u32 acpi_read_pm1_control(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_cnt) + value = inw(facp->pm1a_cnt); + if (facp->pm1b_cnt) + value |= inw(facp->pm1b_cnt); + return value; +} + +/* + * Set the value of the PM1 control register (BM_RLD, ...) + */ +static void acpi_write_pm1_control(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_cnt) + outw(value, facp->pm1a_cnt); + if (facp->pm1b_cnt) + outw(value, facp->pm1b_cnt); +} + +/* + * Get the value of the fixed event status register + */ +static u32 acpi_read_pm1_status(struct acpi_facp *facp) +{ + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt); + if (facp->pm1b_evt) + value |= inw(facp->pm1b_evt); + return value; +} + +/* + * Set the value of the fixed event status register (clear events) + */ +static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value) +{ + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt); + if (facp->pm1b_evt) + outw(value, facp->pm1b_evt); +} + +/* + * Get the value of the fixed event enable register + */ +static u32 acpi_read_pm1_enable(struct acpi_facp *facp) +{ + int offset = facp->pm1_evt_len >> 1; + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt + offset); + if (facp->pm1b_evt) + value |= inw(facp->pm1b_evt + offset); + return value; +} + +/* + * Set the value of the fixed event enable register (enable events) + */ +static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value) +{ + int offset = facp->pm1_evt_len >> 1; + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt + offset); + if (facp->pm1b_evt) + outw(value, facp->pm1b_evt + offset); +} + +/* + * Get the value of the general-purpose event status register + */ +static u32 acpi_read_gpe_status(struct acpi_facp *facp) +{ + u32 value = 0; + int i, size; + + if (facp->gpe1) { + size = facp->gpe1_len >> 1; + for (i = size - 1; i >= 0; i--) + value = (value << 8) | inb(facp->gpe1 + i); + } + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = size - 1; i >= 0; i--) + value = (value << 8) | inb(facp->gpe0 + i); + } + return value; +} + +/* + * Set the value of the general-purpose event status register (clear events) + */ +static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value) +{ + int i, size; + + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = 0; i < size; i++) { + outb(value & 0xff, facp->gpe0 + i); + value >>= 8; + } + } + if (facp->gpe1) { + size = facp->gpe1_len >> 1; + for (i = 0; i < size; i++) { + outb(value & 0xff, facp->gpe1 + i); + value >>= 8; + } + } +} + +/* + * Get the value of the general-purpose event enable register + */ +static u32 acpi_read_gpe_enable(struct acpi_facp *facp) +{ + u32 value = 0; + int i, size, offset; + + offset = facp->gpe0_len >> 1; + if (facp->gpe1) { + size = facp->gpe1_len >> 1; + for (i = size - 1; i >= 0; i--) { + value = (value << 8) | inb(facp->gpe1 + offset + i); + } + } + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = size - 1; i >= 0; i--) + value = (value << 8) | inb(facp->gpe0 + offset + i); + } + return value; +} + +/* + * Set the value of the general-purpose event enable register (enable events) + */ +static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value) +{ + int i, offset; + + offset = facp->gpe0_len >> 1; + if (facp->gpe0) { + for (i = 0; i < offset; i++) { + outb(value & 0xff, facp->gpe0 + offset + i); + value >>= 8; + } + } + if (facp->gpe1) { + offset = facp->gpe1_len >> 1; + for (i = 0; i < offset; i++) { + outb(value & 0xff, facp->gpe1 + offset + i); + value >>= 8; + } + } +} + +/* + * Map an ACPI table into virtual memory + */ +static struct acpi_table *__init acpi_map_table(u32 addr) +{ + struct acpi_table *table = NULL; + if (addr) { + // map table header to determine size + table = (struct acpi_table *) + ioremap((unsigned long) addr, + sizeof(struct acpi_table)); + if (table) { + unsigned long table_size = table->length; + iounmap(table); + // remap entire table + table = (struct acpi_table *) + ioremap((unsigned long) addr, table_size); + } + + if (!table) { + /* ioremap is a pain, it returns NULL if the + * table starts within mapped physical memory. + * Hopefully, no table straddles a mapped/unmapped + * physical memory boundary, ugh + */ + table = (struct acpi_table*) phys_to_virt(addr); + } + } + return table; +} + +/* + * Unmap an ACPI table from virtual memory + */ +static void acpi_unmap_table(struct acpi_table *table) +{ + // iounmap ignores addresses within physical memory + if (table) + iounmap(table); +} + +/* + * Locate and map ACPI tables + */ +static int __init acpi_find_tables(void) +{ + struct acpi_rsdp *rsdp; + struct acpi_table *rsdt; + u32 *rsdt_entry; + int rsdt_entry_count; + unsigned long i; + + // search BIOS memory for RSDP + for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) { + rsdp = (struct acpi_rsdp *) phys_to_virt(i); + if (rsdp->signature[0] == ACPI_RSDP1_SIG + && rsdp->signature[1] == ACPI_RSDP2_SIG) { + char oem[7]; + int j; + + // strip trailing space and print OEM identifier + memcpy(oem, rsdp->oem, 6); + oem[6] = '\0'; + for (j = 5; + j > 0 && (oem[j] == '\0' || oem[j] == ' '); + j--) { + oem[j] = '\0'; + } + printk(KERN_INFO "ACPI: \"%s\" found at 0x%p\n", + oem, (void *) i); + + break; + } + } + if (i >= ACPI_BIOS_ROM_END) + return -ENODEV; + + // fetch RSDT from RSDP + rsdt = acpi_map_table(rsdp->rsdt); + if (!rsdt) { + printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n", + (void*) rsdp->rsdt); + return -ENODEV; + } + else if (rsdt->signature != ACPI_RSDT_SIG) { + printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n", + (void*) rsdp->rsdt, (unsigned) rsdt->signature); + acpi_unmap_table(rsdt); + return -ENODEV; + } + // search RSDT for FACP + acpi_facp = NULL; + rsdt_entry = (u32 *) (rsdt + 1); + rsdt_entry_count = (int) ((rsdt->length - sizeof(*rsdt)) >> 2); + while (rsdt_entry_count) { + struct acpi_table *dt = acpi_map_table(*rsdt_entry); + if (dt && dt->signature == ACPI_FACP_SIG) { + acpi_facp = (struct acpi_facp*) dt; + acpi_facp_addr = *rsdt_entry; + acpi_dsdt_addr = acpi_facp->dsdt; + + // map FACS if it exists + if (acpi_facp->facs) { + dt = acpi_map_table(acpi_facp->facs); + if (dt && dt->signature == ACPI_FACS_SIG) { + acpi_facs = (struct acpi_facs*) dt; + } + else { + acpi_unmap_table(dt); + } + } + } + else { + acpi_unmap_table(dt); + } + rsdt_entry++; + rsdt_entry_count--; + } + + acpi_unmap_table(rsdt); + + if (!acpi_facp) { + printk(KERN_ERR "ACPI: missing FACP\n"); + return -ENODEV; + } + return 0; +} + +/* + * Unmap or destroy ACPI tables + */ +static void acpi_destroy_tables(void) +{ + if (!acpi_fake_facp) + acpi_unmap_table((struct acpi_table*) acpi_facp); + else + kfree(acpi_facp); + acpi_unmap_table((struct acpi_table*) acpi_facs); +} + +/* + * Locate PIIX4 device and create a fake FACP + */ +static int __init acpi_find_piix4(void) +{ + struct pci_dev *dev; + u32 base; + u16 cmd; + u8 pmregmisc; + + dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, + NULL); + if (!dev) + return -ENODEV; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_IO)) + return -ENODEV; + + pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc); + if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) + return -ENODEV; + + pci_read_config_dword(dev, 0x40, &base); + if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) + return -ENODEV; + + base &= PCI_BASE_ADDRESS_IO_MASK; + if (!base) + return -ENODEV; + + printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base); + + acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL); + if (!acpi_facp) + return -ENOMEM; + + acpi_fake_facp = 1; + memset(acpi_facp, 0, sizeof(struct acpi_facp)); + acpi_facp->int_model = ACPI_PIIX4_INT_MODEL; + acpi_facp->sci_int = ACPI_PIIX4_SCI_INT; + acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD; + acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE; + acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE; + acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ; + acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT; + acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT; + acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT; + acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR; + acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0; + acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN; + acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN; + acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN; + acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN; + acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN; + acpi_facp->p_lvl2_lat = (__u16) ACPI_INFINITE_LAT; + acpi_facp->p_lvl3_lat = (__u16) ACPI_INFINITE_LAT; + + acpi_facp_addr = virt_to_phys(acpi_facp); + acpi_dsdt_addr = 0; + + acpi_p_blk = base + ACPI_PIIX4_P_BLK; + + return 0; +} + +/* + * Handle an ACPI SCI (fixed or general purpose event) + */ +static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + u32 pm1_status, gpe_status, gpe_level, gpe_edge; + unsigned long flags; + + // detect and clear fixed events + pm1_status = (acpi_read_pm1_status(acpi_facp) + & acpi_read_pm1_enable(acpi_facp)); + acpi_write_pm1_status(acpi_facp, pm1_status); + + // detect and handle general-purpose events + gpe_status = (acpi_read_gpe_status(acpi_facp) + & acpi_read_gpe_enable(acpi_facp)); + gpe_level = gpe_status & acpi_gpe_level; + if (gpe_level) { + // disable level-triggered events (re-enabled after handling) + acpi_write_gpe_enable( + acpi_facp, + acpi_read_gpe_enable(acpi_facp) & ~gpe_level); + } + gpe_edge = gpe_status & ~gpe_level; + if (gpe_edge) { + // clear edge-triggered events + while (acpi_read_gpe_status(acpi_facp) & gpe_edge) + acpi_write_gpe_status(acpi_facp, gpe_edge); + } + + // notify process waiting on /dev/acpi + spin_lock_irqsave(&acpi_event_lock, flags); + acpi_pm1_status |= pm1_status; + acpi_gpe_status |= gpe_status; + spin_unlock_irqrestore(&acpi_event_lock, flags); + acpi_event_state = acpi_sleep_state; + wake_up_interruptible(&acpi_event_wait); +} + +/* + * Is ACPI enabled or not? + */ +static inline int acpi_is_enabled(struct acpi_facp *facp) +{ + return ((acpi_read_pm1_control(facp) & ACPI_SCI_EN) ? 1:0); +} + +/* + * Enable SCI + */ +static int acpi_enable(struct acpi_facp *facp) +{ + if (facp->smi_cmd) + outb(facp->acpi_enable, facp->smi_cmd); + return (acpi_is_enabled(facp) ? 0:-1); +} + +/* + * Disable SCI + */ +static int acpi_disable(struct acpi_facp *facp) +{ + // disable and clear any pending events + acpi_write_gpe_enable(facp, 0); + while (acpi_read_gpe_status(facp)) + acpi_write_gpe_status(facp, acpi_read_gpe_status(facp)); + acpi_write_pm1_enable(facp, 0); + acpi_write_pm1_status(facp, acpi_read_pm1_status(facp)); + + /* writing acpi_disable to smi_cmd would be appropriate + * here but this causes a nasty crash on many systems + */ + + return 0; +} + +static inline int bm_activity(void) +{ + return 0 && acpi_read_pm1_status(acpi_facp) & ACPI_BM; +} + +static inline void clear_bm_activity(void) +{ + acpi_write_pm1_status(acpi_facp, ACPI_BM); +} + +static void sleep_on_busmaster(void) +{ + u32 pm1_cntr = acpi_read_pm1_control(acpi_facp); + if (pm1_cntr & ACPI_BM_RLD) { + pm1_cntr &= ~ACPI_BM_RLD; + acpi_write_pm1_control(acpi_facp, pm1_cntr); + } +} + +static void wake_on_busmaster(void) +{ + u32 pm1_cntr = acpi_read_pm1_control(acpi_facp); + if (!(pm1_cntr & ACPI_BM_RLD)) { + pm1_cntr |= ACPI_BM_RLD; + acpi_write_pm1_control(acpi_facp, pm1_cntr); + } + clear_bm_activity(); +} + +/* + * Idle loop (uniprocessor only) + */ +static void acpi_idle_handler(void) +{ + static int sleep_level = 1; + + if (!acpi_facp->pm_tmr || !acpi_p_blk) + goto not_initialized; + + /* + * start from the previous sleep level.. + */ + if (sleep_level == 1) + goto sleep1; + if (sleep_level == 2 || bm_activity()) + goto sleep2; +sleep3: + sleep_level = 3; + if (!acpi_p_lvl3_tested) { + printk("ACPI C3 works\n"); + acpi_p_lvl3_tested = 1; + } + wake_on_busmaster(); + if (acpi_facp->pm2_cnt) + goto sleep3_with_arbiter; + + for (;;) { + unsigned long time; + __cli(); + if (current->need_resched) + goto out; + time = inl(acpi_facp->pm_tmr); + inb(acpi_p_blk + ACPI_P_LVL3); + time = inl(acpi_facp->pm_tmr) - time; + __sti(); + if (time > acpi_p_lvl3_lat || bm_activity()) + goto sleep2; + } + +sleep3_with_arbiter: + for (;;) { + unsigned long time; + unsigned int pm2_cntr = acpi_facp->pm2_cnt; + __cli(); + if (current->need_resched) + goto out; + time = inl(acpi_facp->pm_tmr); + outb(inb(pm2_cntr) | ACPI_ARB_DIS, pm2_cntr); + inb(acpi_p_blk + ACPI_P_LVL3); + outb(inb(pm2_cntr) & ~ACPI_ARB_DIS, pm2_cntr); + time = inl(acpi_facp->pm_tmr) - time; + __sti(); + if (time > acpi_p_lvl3_lat || bm_activity()) + goto sleep2; + } + +sleep2: + sleep_level = 2; + if (!acpi_p_lvl2_tested) { + printk("ACPI C2 works\n"); + acpi_p_lvl2_tested = 1; + } + wake_on_busmaster(); /* Required to track BM activity.. */ + for (;;) { + unsigned long time; + __cli(); + if (current->need_resched) + goto out; + time = inl(acpi_facp->pm_tmr); + inb(acpi_p_blk + ACPI_P_LVL2); + time = inl(acpi_facp->pm_tmr) - time; + __sti(); + if (time > acpi_p_lvl2_lat) + goto sleep1; + if (bm_activity()) { + clear_bm_activity(); + continue; + } + if (time < acpi_enter_lvl3_lat) + goto sleep3; + } + +sleep1: + sleep_level = 1; + sleep_on_busmaster(); + for (;;) { + unsigned long time; + __cli(); + if (current->need_resched) + goto out; + time = inl(acpi_facp->pm_tmr); + __asm__ __volatile__("sti ; hlt": : :"memory"); + time = inl(acpi_facp->pm_tmr) - time; + if (time < acpi_enter_lvl2_lat) + goto sleep2; + } + +not_initialized: + for (;;) { + __cli(); + if (current->need_resched) + goto out; + __asm__ __volatile__("sti ; hlt": : :"memory"); + } + +out: + __sti(); +} + +/* + * Put all devices into specified D-state + */ +static int acpi_enter_dx(acpi_dstate_t state) +{ + int status = 0; + struct list_head *i = acpi_devs.next; + + while (i != &acpi_devs) { + struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry); + if (dev->state != state) { + int dev_status = 0; + if (dev->info.transition) + dev_status = dev->info.transition(dev, state); + if (!dev_status) { + // put hardware into D-state + dev->state = state; + } + if (dev_status) + status = dev_status; + } + + i = i->next; + } + + return status; +} + +/* + * Update system time from real-time clock + */ +static void acpi_update_clock(void) +{ + if (acpi_sleep_start) { + unsigned long delta; + struct timeval tv; + + delta = get_cmos_time() - acpi_sleep_start; + do_gettimeofday(&tv); + tv.tv_sec += delta; + do_settimeofday(&tv); + + acpi_sleep_start = 0; + } +} + + +/* + * Enter system sleep state + */ +static void acpi_enter_sx(acpi_sstate_t state) +{ + unsigned long slp_typ = acpi_slp_typ[(int) state]; + if (slp_typ != ACPI_SLP_TYP_DISABLED) { + u16 typa, typb, value; + + // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb + typa = (slp_typ >> 8) & 0xff; + typb = slp_typ & 0xff; + + typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); + typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); + + if (state != ACPI_S0) { + acpi_sleep_start = get_cmos_time(); + acpi_enter_dx(ACPI_D3); + acpi_sleep_state = state; + } + + // clear wake status + acpi_write_pm1_status(acpi_facp, ACPI_WAK); + + // set SLP_TYPa/b and SLP_EN + if (acpi_facp->pm1a_cnt) { + value = inw(acpi_facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; + outw(value | typa | ACPI_SLP_EN, acpi_facp->pm1a_cnt); + } + if (acpi_facp->pm1b_cnt) { + value = inw(acpi_facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; + outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt); + } + + if (state == ACPI_S0) { + acpi_sleep_state = state; + acpi_enter_dx(ACPI_D0); + acpi_sleep_start = 0; + } + else if (state == ACPI_S1) { + // wait until S1 is entered + while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ; + // finished sleeping, update system time + acpi_update_clock(); + } + } +} + +/* + * Enter soft-off (S5) + */ +static void acpi_power_off_handler(void) +{ + acpi_enter_sx(ACPI_S5); +} + +/* + * Claim ACPI I/O ports + */ +static int acpi_claim_ioports(struct acpi_facp *facp) +{ + // we don't get a guarantee of contiguity for any of the ACPI registers + if (facp->pm1a_evt) + request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi"); + if (facp->pm1b_evt) + request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi"); + if (facp->pm1a_cnt) + request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi"); + if (facp->pm1b_cnt) + request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi"); + if (facp->pm_tmr) + request_region(facp->pm_tmr, facp->pm_tm_len, "acpi"); + if (facp->gpe0) + request_region(facp->gpe0, facp->gpe0_len, "acpi"); + if (facp->gpe1) + request_region(facp->gpe1, facp->gpe1_len, "acpi"); + + return 0; +} + +/* + * Free ACPI I/O ports + */ +static int acpi_release_ioports(struct acpi_facp *facp) +{ + // we don't get a guarantee of contiguity for any of the ACPI registers + if (facp->pm1a_evt) + release_region(facp->pm1a_evt, facp->pm1_evt_len); + if (facp->pm1b_evt) + release_region(facp->pm1b_evt, facp->pm1_evt_len); + if (facp->pm1a_cnt) + release_region(facp->pm1a_cnt, facp->pm1_cnt_len); + if (facp->pm1b_cnt) + release_region(facp->pm1b_cnt, facp->pm1_cnt_len); + if (facp->pm_tmr) + release_region(facp->pm_tmr, facp->pm_tm_len); + if (facp->gpe0) + release_region(facp->gpe0, facp->gpe0_len); + if (facp->gpe1) + release_region(facp->gpe1, facp->gpe1_len); + + return 0; +} + +/* + * Examine/modify value + */ +static int acpi_do_ulong(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + char str[2 * sizeof(unsigned long) + 4], *strend; + unsigned long val; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = *(unsigned long*) ctl->data; + size = sprintf(str, "0x%08lx\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else { + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + *(unsigned long*) ctl->data = val; + } + + file->f_pos += *len; + return 0; +} + +/* + * Examine/modify event register + */ +static int acpi_do_event_reg(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + char str[2 * sizeof(u32) + 4], *strend; + u32 val, enabling; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = 0; + switch (ctl->ctl_name) { + case ACPI_PM1_ENABLE: + val = acpi_read_pm1_enable(acpi_facp); + break; + case ACPI_GPE_ENABLE: + val = acpi_read_gpe_enable(acpi_facp); + break; + case ACPI_GPE_LEVEL: + val = acpi_gpe_level; + break; + } + + size = sprintf(str, "0x%08x\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else + { + // fetch user value + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = (u32) simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + + // store value in register + switch (ctl->ctl_name) { + case ACPI_PM1_ENABLE: + // clear previously disabled events + enabling = (val + & ~acpi_read_pm1_enable(acpi_facp)); + acpi_write_pm1_status(acpi_facp, enabling); + + if (val) { + // enable ACPI unless it is already + if (!acpi_is_enabled(acpi_facp)) + acpi_enable(acpi_facp); + } + else if (!acpi_read_gpe_enable(acpi_facp)) { + // disable ACPI unless it is already + if (acpi_is_enabled(acpi_facp)) + acpi_disable(acpi_facp); + } + + acpi_write_pm1_enable(acpi_facp, val); + break; + case ACPI_GPE_ENABLE: + // clear previously disabled events + enabling = (val + & ~acpi_read_gpe_enable(acpi_facp)); + while (acpi_read_gpe_status(acpi_facp) & enabling) + acpi_write_gpe_status(acpi_facp, enabling); + + if (val) { + // enable ACPI unless it is already + if (!acpi_is_enabled(acpi_facp)) + acpi_enable(acpi_facp); + } + else if (!acpi_read_pm1_enable(acpi_facp)) { + // disable ACPI unless it is already + if (acpi_is_enabled(acpi_facp)) + acpi_disable(acpi_facp); + } + + acpi_write_gpe_enable(acpi_facp, val); + break; + case ACPI_GPE_LEVEL: + acpi_gpe_level = val; + break; + } + } + + file->f_pos += *len; + return 0; +} + +/* + * Wait for next event + */ +static int acpi_do_event(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + u32 pm1_status = 0, gpe_status = 0; + acpi_sstate_t event_state = 0; + char str[27]; + int size; + + if (write) + return -EPERM; + if (*len < sizeof(str)) { + *len = 0; + return 0; + } + + for (;;) { + unsigned long flags; + + // we need an atomic exchange here + spin_lock_irqsave(&acpi_event_lock, flags); + pm1_status = acpi_pm1_status; + acpi_pm1_status = 0; + gpe_status = acpi_gpe_status; + acpi_gpe_status = 0; + spin_unlock_irqrestore(&acpi_event_lock, flags); + event_state = acpi_event_state; + + if (pm1_status || gpe_status) + break; + + // wait for an event to arrive + interruptible_sleep_on(&acpi_event_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + size = sprintf(str, "0x%08x 0x%08x 0x%01x\n", + pm1_status, + gpe_status, + event_state); + copy_to_user(buffer, str, size); + *len = size; + file->f_pos += size; + + return 0; +} + +/* + * Enter system sleep state + */ +static int acpi_do_sleep(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + } + else + { + acpi_enter_sx(ACPI_S1); + acpi_enter_sx(ACPI_S0); + } + file->f_pos += *len; + return 0; +} + +/* + * Initialize and enable ACPI + */ +static int __init acpi_init(void) +{ + int pid; + + if (acpi_find_tables() && acpi_find_piix4()) { + // no ACPI tables and not PIIX4 + return -ENODEV; + } + + /* + * Are the latencies in uS or in ticks in the tables? + * Maybe this should do ACPI_uS_TO_TMR_TICKS? + * + * Whatever. Internally we always keep them in timer + * ticks, which is simpler and more consistent (what is + * an uS to us?). Besides, that gives people more + * control in the /proc interfaces. + */ + if (acpi_facp->p_lvl2_lat + && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { + acpi_p_lvl2_lat = acpi_facp->p_lvl2_lat; + acpi_enter_lvl2_lat = ACPI_TMR_HZ / 1000; + } + if (acpi_facp->p_lvl3_lat + && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { + acpi_p_lvl3_lat = acpi_facp->p_lvl3_lat; + acpi_enter_lvl3_lat = acpi_facp->p_lvl3_lat * 5; + } + + if (acpi_facp->sci_int + && request_irq(acpi_facp->sci_int, + acpi_irq, + SA_INTERRUPT | SA_SHIRQ, + "acpi", + acpi_facp)) { + printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", + acpi_facp->sci_int); + acpi_destroy_tables(); + return -ENODEV; + } + + acpi_claim_ioports(acpi_facp); + acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); + + pid = kernel_thread(acpi_control_thread, + NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + + acpi_power_off = acpi_power_off_handler; + + /* + * Set up the ACPI idle function. Note that we can't really + * do this with multiple CPU's, we'd need a per-CPU ACPI + * device.. + */ +#ifdef __SMP__ + if (smp_num_cpus > 1) + return 0; +#endif + + if (acpi_facp->pm_tmr) + acpi_idle = acpi_idle_handler; + + return 0; +} + +/* + * Disable and deinitialize ACPI + */ +static void __exit acpi_exit(void) +{ + acpi_idle = NULL; + acpi_power_off = NULL; + + unregister_sysctl_table(acpi_sysctl); + acpi_disable(acpi_facp); + acpi_release_ioports(acpi_facp); + + if (acpi_facp->sci_int) + free_irq(acpi_facp->sci_int, acpi_facp); + + acpi_destroy_tables(); +} + +/* + * Register a device with the ACPI subsystem + */ +struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr) +{ + struct acpi_dev *dev = NULL; + if (info) { + dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL); + if (dev) { + unsigned long flags; + + memset(dev, 0, sizeof(*dev)); + memcpy(&dev->info, info, sizeof(dev->info)); + dev->adr = adr; + + spin_lock_irqsave(&acpi_devs_lock, flags); + list_add(&dev->entry, &acpi_devs); + spin_unlock_irqrestore(&acpi_devs_lock, flags); + } + } + return dev; +} + +/* + * Unregister a device with ACPI + */ +void acpi_unregister(struct acpi_dev *dev) +{ + if (dev) { + unsigned long flags; + + spin_lock_irqsave(&acpi_devs_lock, flags); + list_del(&dev->entry); + spin_unlock_irqrestore(&acpi_devs_lock, flags); + + kfree(dev); + } +} + +/* + * Wake up a device + */ +void acpi_wakeup(struct acpi_dev *dev) +{ + // run _PS0 or tell parent bus to wake device up +} + +/* + * Manage idle devices + */ +static int acpi_control_thread(void *context) +{ + exit_mm(current); + exit_files(current); + strcpy(current->comm, "acpi"); + + for(;;) { + interruptible_sleep_on(&acpi_control_wait); + if (signal_pending(current)) + break; + + // find all idle devices and set idle timer + } + + return 0; +} + +__initcall(acpi_init); + +/* + * Module visible symbols + */ +EXPORT_SYMBOL(acpi_control_wait); +EXPORT_SYMBOL(acpi_register); +EXPORT_SYMBOL(acpi_unregister); +EXPORT_SYMBOL(acpi_wakeup); diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.34/linux/arch/i386/kernel/irq.c Tue Dec 7 09:32:40 1999 +++ linux/arch/i386/kernel/irq.c Thu Dec 23 14:32:16 1999 @@ -772,6 +772,41 @@ return 0x12345678; } +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ +unsigned int probe_irq_mask(unsigned long unused) +{ + int i; + unsigned int mask; + + if (unused != 0x12345678) + printk("Bad IRQ probe from %lx\n", (&unused)[-1]); + + mask = 0; + spin_lock_irq(&irq_controller_lock); + for (i = 0; i < 16; i++) { + unsigned int status = irq_desc[i].status; + + if (!(status & IRQ_AUTODETECT)) + continue; + + if (!(status & IRQ_WAITING)) + mask |= 1 << i; + + irq_desc[i].status = status & ~IRQ_AUTODETECT; + irq_desc[i].handler->shutdown(i); + } + spin_unlock_irq(&irq_controller_lock); + + return mask; +} + +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source) + */ int probe_irq_off(unsigned long unused) { int i, irq_found, nr_irqs; diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c --- v2.3.34/linux/arch/i386/kernel/pci-i386.c Tue Dec 7 09:32:40 1999 +++ linux/arch/i386/kernel/pci-i386.c Tue Dec 21 12:07:32 1999 @@ -102,7 +102,7 @@ * Expects start=0, end=size-1, flags=resource type. */ -static int __init pcibios_assign_resource(struct pci_dev *dev, int i) +int pci_assign_resource(struct pci_dev *dev, int i) { struct resource *r = &dev->resource[i]; struct resource *pr = pci_find_parent_resource(dev, r); @@ -272,7 +272,7 @@ * the BIOS forgot to do so or because we have decided the old * address was unusable for some reason. */ - pcibios_assign_resource(dev, idx); + pci_assign_resource(dev, idx); } } if (pci_probe & PCI_ASSIGN_ROMS) { @@ -280,7 +280,7 @@ r->end -= r->start; r->start = 0; if (r->end) - pcibios_assign_resource(dev, PCI_ROM_RESOURCE); + pci_assign_resource(dev, PCI_ROM_RESOURCE); } } } diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.34/linux/arch/i386/kernel/setup.c Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/kernel/setup.c Fri Dec 24 13:06:05 1999 @@ -709,7 +709,7 @@ #endif #ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE) { + if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = diff -u --recursive --new-file v2.3.34/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.3.34/linux/arch/ppc/config.in Wed Dec 8 14:11:25 1999 +++ linux/arch/ppc/config.in Mon Dec 27 14:10:20 1999 @@ -85,12 +85,16 @@ if [ "$CONFIG_APUS" = "y" ]; then define_bool CONFIG_PCI n -else if [ "$CONFIG_OAK" = "y" ]; then +fi +if [ "$CONFIG_OAK" = "y" ]; then define_bool CONFIG_PCI n -else if [ "$CONFIG_8xx" = "y" ]; then +fi +if [ "$CONFIG_8xx" = "y" ]; then bool 'QSpan PCI' CONFIG_PCI else + if [ "$CONFIG_APUS" != "y" ]; then define_bool CONFIG_PCI y + fi fi bool 'Networking support' CONFIG_NET diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.3.34/linux/arch/ppc/kernel/chrp_setup.c Thu Nov 11 20:11:32 1999 +++ linux/arch/ppc/kernel/chrp_setup.c Mon Dec 27 14:10:20 1999 @@ -249,7 +249,7 @@ else #endif ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */ - +sprintf(cmd_line, "console=ttyS0,9600 console=tty0"); printk("Boot arguments: %s\n", cmd_line); request_region(0x20,0x20,"pic1"); @@ -391,7 +391,7 @@ * openpic irq. So we just check to make sure the controller * is an openpic and if it is then eoi * - * We do it this way since our irq_desc[irq].ctl can change + * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ if ( irq >= open_pic.irq_offset) @@ -413,10 +413,10 @@ } open_pic.irq_offset = 16; for ( i = 16 ; i < NR_IRQS ; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_init(); #ifdef CONFIG_XMON request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI), diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c --- v2.3.34/linux/arch/ppc/kernel/gemini_setup.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/gemini_setup.c Mon Dec 27 14:10:20 1999 @@ -332,7 +332,7 @@ /* gemini has no 8259 */ open_pic.irq_offset = 0; for( i=0; i < NR_IRQS; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); #ifdef __SMP__ request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, @@ -512,7 +512,7 @@ * openpic irq. So we just check to make sure the controller * is an openpic and if it is then eoi * - * We do it this way since our irq_desc[irq].ctl can change + * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ if ( irq >= open_pic.irq_offset) diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.3.34/linux/arch/ppc/kernel/irq.c Sun Nov 7 16:37:34 1999 +++ linux/arch/ppc/kernel/irq.c Mon Dec 27 14:10:20 1999 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -71,7 +72,7 @@ #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) -struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, }; +irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; unsigned int ppc_local_bh_count[NR_CPUS]; unsigned int ppc_local_irq_count[NR_CPUS]; @@ -244,8 +245,8 @@ #else len += sprintf(buf+len, "%10u ", kstat_irqs(i)); #endif /* __SMP__ */ - if ( irq_desc[i].ctl ) - len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename ); + if ( irq_desc[i].handler ) + len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename ); else len += sprintf(buf+len, " None "); len += sprintf(buf+len, " %s",action->name); diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h --- v2.3.34/linux/arch/ppc/kernel/local_irq.h Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/local_irq.h Mon Dec 27 14:10:20 1999 @@ -4,7 +4,7 @@ #include #include -#include +#include void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c --- v2.3.34/linux/arch/ppc/kernel/m8xx_setup.c Fri Oct 22 13:21:45 1999 +++ linux/arch/ppc/kernel/m8xx_setup.c Mon Dec 27 14:10:20 1999 @@ -278,7 +278,7 @@ ppc8xx_pic.irq_offset = 0; for ( i = 0 ; i < NR_SIU_INTS ; i++ ) - irq_desc[i].ctl = &ppc8xx_pic; + irq_desc[i].handler = &ppc8xx_pic; /* We could probably incorporate the CPM into the multilevel * interrupt structure. @@ -288,7 +288,7 @@ #if defined(CONFIG_PCI) for ( i = NR_SIU_INTS ; i < (NR_SIU_INTS + NR_8259_INTS) ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_pic.irq_offset = NR_SIU_INTS; i8259_init(); request_8xxirq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL); diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/mbx_pci.c linux/arch/ppc/kernel/mbx_pci.c --- v2.3.34/linux/arch/ppc/kernel/mbx_pci.c Tue Aug 31 17:29:13 1999 +++ linux/arch/ppc/kernel/mbx_pci.c Wed Dec 31 16:00:00 1969 @@ -1,269 +0,0 @@ -/* - * MBX pci routines. - * The MBX uses the QSpan PCI bridge. The config address register - * is located 0x500 from the base of the bridge control/status registers. - * The data register is located at 0x504. - * This is a two step operation. First, the address register is written, - * then the data register is read/written as required. - * I don't know what to do about interrupts (yet). - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * This blows......The MBX uses the Tundra QSpan PCI bridge. When - * reading the configuration space, if something does not respond - * the bus times out and we get a machine check interrupt. So, the - * good ol' exception tables come to mind to trap it and return some - * value. - * - * On an error we just return a -1, since that is what the caller wants - * returned if nothing is present. I copied this from __get_user_asm, - * with the only difference of returning -1 instead of EFAULT. - * There is an associated hack in the machine check trap code. - * - * The QSPAN is also a big endian device, that is it makes the PCI - * look big endian to us. This presents a problem for the Linux PCI - * functions, which assume little endian. For example, we see the - * first 32-bit word like this: - * ------------------------ - * | Device ID | Vendor ID | - * ------------------------ - * If we read/write as a double word, that's OK. But in our world, - * when read as a word, device ID is at location 0, not location 2 as - * the little endian PCI would believe. We have to switch bits in - * the PCI addresses given to us to get the data to/from the correct - * byte lanes. - * - * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5. - * It always forces the MS bit to zero. Therefore, dev_fn values - * greater than 128 are returned as "no device found" errors. - * - * The QSPAN can only perform long word (32-bit) configuration cycles. - * The "offset" must have the two LS bits set to zero. Read operations - * require we read the entire word and then sort out what should be - * returned. Write operations other than long word require that we - * read the long word, update the proper word or byte, then write the - * entire long word back. - * - * PCI Bridge hack. We assume (correctly) that bus 0 is the primary - * PCI bus from the QSPAN. If we are called with a bus number other - * than zero, we create a Type 1 configuration access that a downstream - * PCI bridge will interpret. - */ - -#define __get_mbx_pci_config(x, addr, op) \ - __asm__ __volatile__( \ - "1: "op" %0,0(%1)\n" \ - " eieio\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,-1\n" \ - " b 2b\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".text" \ - : "=r"(x) : "r"(addr)) - -#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500)) -#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504)) - -#define mk_config_addr(bus, dev, offset) \ - (((bus)<<16) | ((dev)<<8) | (offset & 0xfc)) - -#define mk_config_type1(bus, dev, offset) \ - mk_config_addr(bus, dev, offset) | 1; - -int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - uint temp; - u_char *cp; - - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz"); - - offset ^= 0x03; - cp = ((u_char *)&temp) + (offset & 0x03); - *val = *cp; - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - uint temp; - ushort *sp; - - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz"); - offset ^= 0x02; - - sp = ((ushort *)&temp) + ((offset >> 1) & 1); - *val = *sp; - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(*val, QS_CONFIG_DATA, "lwz"); - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - uint temp; - u_char *cp; - - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp); - - offset ^= 0x03; - cp = ((u_char *)&temp) + (offset & 0x03); - *cp = val; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *QS_CONFIG_DATA = temp; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - uint temp; - ushort *sp; - - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp); - - offset ^= 0x02; - sp = ((ushort *)&temp) + ((offset >> 1) & 1); - *sp = val; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *QS_CONFIG_DATA = temp; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *(unsigned int *)QS_CONFIG_DATA = val; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_find_device(unsigned short vendor, unsigned short dev_id, - unsigned short index, unsigned char *bus_ptr, - unsigned char *dev_fn_ptr) -{ - int num, devfn; - unsigned int x, vendev; - - if (vendor == 0xffff) - return PCIBIOS_BAD_VENDOR_ID; - vendev = (dev_id << 16) + vendor; - num = 0; - for (devfn = 0; devfn < 32; devfn++) { - mbx_pcibios_read_config_dword(0, devfn<<3, PCI_VENDOR_ID, &x); - if (x == vendev) { - if (index == num) { - *bus_ptr = 0; - *dev_fn_ptr = devfn<<3; - return PCIBIOS_SUCCESSFUL; - } - ++num; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} - -int mbx_pcibios_find_class(unsigned int class_code, unsigned short index, - unsigned char *bus_ptr, unsigned char *dev_fn_ptr) -{ - int devnr, x, num; - - num = 0; - for (devnr = 0; devnr < 32; devnr++) { - mbx_pcibios_read_config_dword(0, devnr<<3, PCI_CLASS_REVISION, &x); - if ((x>>8) == class_code) { - if (index == num) { - *bus_ptr = 0; - *dev_fn_ptr = devnr<<3; - return PCIBIOS_SUCCESSFUL; - } - ++num; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} - -void __init -mbx_pcibios_fixup(void) -{ - /* Nothing to do here? */ -} - -void __init -mbx_setup_pci_ptrs(void) -{ - set_config_access_method(mbx); - - ppc_md.pcibios_fixup = mbx_pcibios_fixup; -} - diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c --- v2.3.34/linux/arch/ppc/kernel/mbx_setup.c Fri Oct 22 13:21:45 1999 +++ linux/arch/ppc/kernel/mbx_setup.c Wed Dec 31 16:00:00 1969 @@ -1,486 +0,0 @@ -/* - * $Id: mbx_setup.c,v 1.12 1999/08/31 06:53:56 davem Exp $ - * - * linux/arch/ppc/kernel/setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Adapted from 'alpha' version by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu) - * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net) - */ - -/* - * bootup setup stuff.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "time.h" -#include "local_irq.h" - -static int mbx_set_rtc_time(unsigned long time); -unsigned long mbx_get_rtc_time(void); -void mbx_calibrate_decr(void); - -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); - -extern unsigned long loops_per_sec; - -unsigned long empty_zero_page[1024]; - -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - -extern char saved_command_line[256]; - -extern unsigned long find_available_memory(void); -extern void m8xx_cpm_reset(uint); - -void __init adbdev_init(void) -{ -} - -void __init -mbx_setup_arch(void) -{ - int cpm_page; - extern char cmd_line[]; - - cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE); - - sprintf(cmd_line, -"%s root=/dev/nfs nfsroot=/sys/mbxroot", - cmd_line); - printk("Boot arguments: %s\n", cmd_line); - - /* Reset the Communication Processor Module. - */ - m8xx_cpm_reset(cpm_page); - -#ifdef notdef - ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ -#endif - -#ifdef CONFIG_BLK_DEV_INITRD -#if 0 - ROOT_DEV = to_kdev_t(0x0200); /* floppy */ - rd_prompt = 1; - rd_doload = 1; - rd_image_start = 0; -#endif -#if 0 /* XXX this may need to be updated for the new bootmem stuff, - or possibly just deleted (see set_phys_avail() in init.c). - - paulus. */ - /* initrd_start and size are setup by boot/head.S and kernel/head.S */ - if ( initrd_start ) - { - if (initrd_end > *memory_end_p) - { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end,*memory_end_p); - initrd_start = 0; - } - } -#endif -#endif - -#ifdef notdef - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); -#endif -} - -void -abort(void) -{ -#ifdef CONFIG_XMON - extern void xmon(void *); - xmon(0); -#endif - machine_restart(NULL); -} - -/* The decrementer counts at the system (internal) clock frequency divided by - * sixteen, or external oscillator divided by four. Currently, we only - * support the MBX, which is system clock divided by sixteen. - */ -void __init mbx_calibrate_decr(void) -{ - bd_t *binfo = (bd_t *)&res; - int freq, fp, divisor; - - if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) - printk("WARNING: Wrong decrementer source clock.\n"); - - /* The manual says the frequency is in Hz, but it is really - * as MHz. The value 'fp' is the number of decrementer ticks - * per second. - */ - fp = (binfo->bi_intfreq * 1000000) / 16; - freq = fp*60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; -} - -/* A place holder for time base interrupts, if they are ever enabled. -*/ -void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) -{ - printk("timebase_interrupt()\n"); -} - -/* The RTC on the MPC8xx is an internal register. - * We want to protect this during power down, so we need to unlock, - * modify, and re-lock. - */ -static int -mbx_set_rtc_time(unsigned long time) -{ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; - return(0); -} - -unsigned long __init mbx_get_rtc_time(void) -{ - /* First, unlock all of the registers we are going to modify. - * To protect them from corruption during power down, registers - * that are maintained by keep alive power are "locked". To - * modify these registers we have to write the key value to - * the key location associated with the register. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; - - - /* Disable the RTC one second and alarm interrupts. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &= - ~(RTCSC_SIE | RTCSC_ALE); - - /* Enabling the decrementer also enables the timebase interrupts - * (or from the other point of view, to get decrementer interrupts - * we have to enable the timebase). The decrementer interrupt - * is wired into the vector table, nothing to do here for that. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr = - ((mk_int_int_mask(DEC_INTERRUPT) << 8) | - (TBSCR_TBF | TBSCR_TBE)); - if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) - panic("Could not allocate timer IRQ!"); - - /* Get time from the RTC. - */ - return ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc; -} - -void -mbx_restart(char *cmd) -{ - extern void MBX_gorom(void); - - MBX_gorom(); -} - -void -mbx_power_off(void) -{ - mbx_restart(NULL); -} - -void -mbx_halt(void) -{ - mbx_restart(NULL) -} - - -int mbx_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp; - extern RESIDUAL *res; - - bp = (bd_t *)res; - - len += sprintf(len+buffer,"clock\t\t: %dMHz\n" - "bus clock\t: %dMHz\n", - bp->bi_intfreq /*/ 1000000*/, - bp->bi_busfreq /*/ 1000000*/); - - return len; -} - -void -mbx_do_IRQ(struct pt_regs *regs, - int cpu, - int isfake) -{ - int irq; - unsigned long bits = 0; - - /* For MPC8xx, read the SIVEC register and shift the bits down - * to get the irq number. */ - bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec; - irq = bits >> 26; - irq += ppc8xx_pic.irq_offset; - bits = 1UL << irq; - - if (irq < 0) { - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", - irq, regs->nip); - spurious_interrupts++; - } - else { - ppc_irq_dispatch_handler( regs, irq ); - } - -} - -static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - int bits, irq; - - /* A bug in the QSpan chip causes it to give us 0xff always - * when doing a character read. So read 32 bits and shift. - * This doesn't seem to return useful values anyway, but - * read it to make sure things are acked. - * -- Cort - */ - irq = (inl(0x508) >> 24)&0xff; - if ( irq != 0xff ) printk("iack %d\n", irq); - - outb(0x0C, 0x20); - irq = inb(0x20) & 7; - if (irq == 2) - { - outb(0x0C, 0xA0); - irq = inb(0xA0); - irq = (irq&7) + 8; - } - bits = 1UL << irq; - irq += i8259_pic.irq_offset; - ppc_irq_dispatch_handler( regs, irq ); -} - - -/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External - * interrupts can be either edge or level triggered, but there is no - * reason for us to change the EPPC-bug values (it would not work if we did). - */ -void __init -mbx_init_IRQ(void) -{ - int i; - - ppc8xx_pic.irq_offset = 16; - for ( i = 16 ; i < 32 ; i++ ) - irq_desc[i].ctl = &ppc8xx_pic; - unmask_irq(CPM_INTERRUPT); - - for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; - i8259_init(); - request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL); - enable_irq(ISA_BRIDGE_INT); -} - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -/* - * IDE stuff. - */ -void -mbx_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port+_IO_BASE), buf, ns); -} - -void -mbx_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port+_IO_BASE, buf, ns); -} - -int -mbx_ide_default_irq(ide_ioreg_t base) -{ - return 14; -} - -ide_ioreg_t -mbx_ide_default_io_base(int index) -{ - return index; -} - -int -mbx_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return 0 -} - -void -mbx_ide_request_region(ide_ioreg_t from, - unsigned int extent, - const char *name) -{ -} - -void -mbx_ide_release_region(ide_ioreg_t from, - unsigned int extent) -{ -} - -void -mbx_ide_fix_driveid(struct hd_driveid *id) -{ - ppc_generic_ide_fix_driveid(id); -} - -void -mbx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t reg = data_port; - int i; - - *irq = 0; - - if (data_port != 0) /* Only map the first ATA flash drive */ - return; - -#ifdef ATA_FLASH - - reg = (ide_ioreg_t) ioremap(PCMCIA_MEM_ADDR, 0x200); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - - /* Does not matter */ - - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = reg; - } - if (irq) - hw->irq = 13; -#endif -} -#endif - -void __init -mbx_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - - if ( r3 ) - memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); - -#ifdef CONFIG_PCI - mbx_setup_pci_ptrs(); -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - /* take care of initrd if we have one */ - if ( r4 ) - { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - /* take care of cmd line */ - if ( r6 ) - { - - *(char *)(r7+KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6+KERNELBASE)); - } - - ppc_md.setup_arch = mbx_setup_arch; - ppc_md.setup_residual = mbx_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = mbx_init_IRQ; - ppc_md.do_IRQ = mbx_do_IRQ; - ppc_md.init = NULL; - - ppc_md.restart = mbx_restart; - ppc_md.power_off = mbx_power_off; - ppc_md.halt = mbx_halt; - - ppc_md.time_init = NULL; - ppc_md.set_rtc_time = mbx_set_rtc_time; - ppc_md.get_rtc_time = mbx_get_rtc_time; - ppc_md.calibrate_decr = mbx_calibrate_decr; - - ppc_md.kbd_setkeycode = pckbd_setkeycode; - ppc_md.kbd_getkeycode = pckbd_getkeycode; - ppc_md.kbd_translate = pckbd_translate; - ppc_md.kbd_unexpected_up = pckbd_unexpected_up; - ppc_md.kbd_leds = pckbd_leds; - ppc_md.kbd_init_hw = pckbd_init_hw; -#ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate; -#endif - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = mbx_ide_insw; - ppc_ide_md.outsw = mbx_ide_outsw; - ppc_ide_md.default_irq = mbx_ide_default_irq; - ppc_ide_md.default_io_base = mbx_ide_default_io_base; - ppc_ide_md.ide_check_region = mbx_ide_check_region; - ppc_ide_md.ide_request_region = mbx_ide_request_region; - ppc_ide_md.ide_release_region = mbx_ide_release_region; - ppc_ide_md.fix_driveid = mbx_ide_fix_driveid; - ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; -#endif -} diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c --- v2.3.34/linux/arch/ppc/kernel/open_pic.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/open_pic.c Mon Dec 27 14:10:20 1999 @@ -416,13 +416,13 @@ void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); } void openpic_disable_irq(u_int irq) { check_arg_irq(irq); - openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); } /* diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c --- v2.3.34/linux/arch/ppc/kernel/pmac_pic.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/pmac_pic.c Mon Dec 27 14:10:20 1999 @@ -135,7 +135,7 @@ * don't. Put this here to check for it. * -- Cort */ - if ( irq_desc[irq].ctl != &gatwick_pic ) + if ( irq_desc[irq].handler != &gatwick_pic ) printk("gatwick irq not from gatwick pic\n"); else ppc_irq_dispatch_handler( regs, irq ); @@ -361,7 +361,7 @@ max_irqs = 64; } for ( i = 0; i < max_real_irqs ; i++ ) - irq_desc[i].ctl = &pmac_pic; + irq_desc[i].handler = &pmac_pic; /* get addresses of first controller */ if (irqctrler) { @@ -401,7 +401,7 @@ if (device_is_compatible(irqctrler, "gatwick")) pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); for ( i = max_real_irqs ; i < max_irqs ; i++ ) - irq_desc[i].ctl = &gatwick_pic; + irq_desc[i].handler = &gatwick_pic; request_irq( second_irq, gatwick_action, SA_INTERRUPT, "gatwick cascade", 0 ); } diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.3.34/linux/arch/ppc/kernel/ppc_ksyms.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/ppc_ksyms.c Mon Dec 27 14:10:20 1999 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c --- v2.3.34/linux/arch/ppc/kernel/prep_setup.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/kernel/prep_setup.c Mon Dec 27 14:10:20 1999 @@ -617,12 +617,12 @@ if (OpenPIC != NULL) { for ( i = 16 ; i < 36 ; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); } for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_init(); #ifdef __SMP__ request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action, diff -u --recursive --new-file v2.3.34/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.3.34/linux/arch/sparc/config.in Wed Dec 8 14:11:25 1999 +++ linux/arch/sparc/config.in Wed Dec 22 19:55:38 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.73 1999/08/31 10:09:01 davem Exp $ +# $Id: config.in,v 1.79 1999/12/23 01:46:00 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -57,21 +57,18 @@ fi fi -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS -fi +tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then - choice 'Kernel core (/proc/kcore) format' \ - "ELF CONFIG_KCORE_ELF \ - A.OUT CONFIG_KCORE_AOUT" ELF + define_bool CONFIG_KCORE_ELF y fi tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL source drivers/parport/Config.in dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT endmenu @@ -89,7 +86,7 @@ comment 'Floppy, IDE, and other block devices' bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD - +define_bool CONFIG_BLK_DEV_IDE n bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then tristate ' Linear (append) mode' CONFIG_MD_LINEAR @@ -146,7 +143,7 @@ mainmenu_option next_comment comment 'SCSI low-level drivers' - bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI + tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI endmenu fi @@ -173,9 +170,7 @@ fi tristate ' Sun LANCE support' CONFIG_SUNLANCE tristate ' Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC - fi + tristate ' Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC tristate ' Sun QuadEthernet support' CONFIG_SUNQE tristate ' MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS # bool ' FDDI driver support' CONFIG_FDDI diff -u --recursive --new-file v2.3.34/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.3.34/linux/arch/sparc/defconfig Wed Dec 8 14:11:25 1999 +++ linux/arch/sparc/defconfig Mon Dec 20 22:05:52 1999 @@ -37,6 +37,7 @@ CONFIG_FB_CGTHREE=y CONFIG_FB_TCX=y CONFIG_FB_CGFOURTEEN=y +# CONFIG_FB_P9100 is not set CONFIG_FB_LEO=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -47,7 +48,7 @@ # CONFIG_FBCON_FONTS is not set CONFIG_SBUS=y CONFIG_SBUSCHAR=y -CONFIG_MOUSE=y +CONFIG_BUSMOUSE=y CONFIG_SUN_MOUSE=y CONFIG_SERIAL=y CONFIG_SUN_SERIAL=y @@ -65,6 +66,7 @@ # CONFIG_SUN_BPP is not set # CONFIG_SUN_VIDEOPIX is not set CONFIG_SUN_AURORA=m +# CONFIG_TADPOLE_TS102_UCTRL is not set # # Linux/SPARC audio subsystem (EXPERIMENTAL) @@ -84,6 +86,9 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +CONFIG_SUNOS_EMUL=y +# CONFIG_PARPORT is not set +# CONFIG_PRINTER is not set # # Floppy, IDE, and other block devices @@ -103,8 +108,9 @@ # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -120,10 +126,11 @@ # # (it is safe to leave these untouched) # -CONFIG_INET_RARP=m CONFIG_SKB_LARGE=y CONFIG_IPV6=m # CONFIG_IPV6_EUI64 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # @@ -144,7 +151,6 @@ # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -240,6 +246,7 @@ CONFIG_EFS_FS=m CONFIG_ISO9660_FS=m # CONFIG_JOLIET is not set +# CONFIG_UDF_FS is not set CONFIG_MINIX_FS=m # CONFIG_NTFS_FS is not set CONFIG_HPFS_FS=m @@ -275,13 +282,13 @@ # # Partition Types # +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y CONFIG_BSD_DISKLABEL=y -# CONFIG_MAC_PARTITION is not set -CONFIG_SMD_DISKLABEL=y CONFIG_SOLARIS_X86_PARTITION=y -# CONFIG_SGI_DISKLABEL is not set # CONFIG_UNIXWARE_DISKLABEL is not set -CONFIG_AMIGA_PARTITION=y +# CONFIG_SGI_PARTITION is not set +CONFIG_SUN_PARTITION=y CONFIG_NLS=y # @@ -312,6 +319,7 @@ # CONFIG_NLS_ISO8859_7 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.3.34/linux/arch/sparc/kernel/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc/kernel/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.50 1999/08/31 13:26:13 anton Exp $ +# $Id: Makefile,v 1.52 1999/12/21 04:02:17 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -19,15 +19,19 @@ IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o O_OBJS := entry.o wof.o wuf.o etrap.o rtrap.o traps.o ${IRQ_OBJS} \ process.o signal.o ioport.o setup.o idprom.o \ - sys_sparc.o sunos_asm.o sparc-stub.o systbls.o sys_sunos.o \ - sunos_ioctl.o time.o windows.o cpu.o devices.o \ - sclow.o solaris.o tadpole.o tick14.o ptrace.o sys_solaris.o \ + sys_sparc.o sunos_asm.o sparc-stub.o systbls.o \ + time.o windows.o cpu.o devices.o sclow.o solaris.o \ + tadpole.o tick14.o ptrace.o sys_solaris.o \ unaligned.o muldiv.o pcic.o semaphore.o OX_OBJS := sparc_ksyms.o ifdef CONFIG_SUN4 O_OBJS += sun4setup.o +endif + +ifdef CONFIG_SUNOS_EMUL +O_OBJS += sys_sunos.o sunos_ioctl.o endif ifdef CONFIG_SMP diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/auxio.c linux/arch/sparc/kernel/auxio.c --- v2.3.34/linux/arch/sparc/kernel/auxio.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/auxio.c Mon Dec 20 22:05:52 1999 @@ -9,6 +9,7 @@ #include #include #include +#include /* memset(), Linux has no bzero() */ /* Probe and map in the Auxiliary I/O register */ unsigned char *auxio_register; @@ -17,6 +18,7 @@ { int node, auxio_nd; struct linux_prom_registers auxregs[1]; + struct resource r; switch (sparc_cpu_model) { case sun4d: @@ -51,10 +53,11 @@ prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs)); prom_apply_obio_ranges(auxregs, 0x1); /* Map the register both read and write */ - auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0, - auxregs[0].reg_size, - "auxiliaryIO", - auxregs[0].which_io, 0x0); + r.flags = auxregs[0].which_io & 0xF; + r.start = auxregs[0].phys_addr; + r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; + auxio_register = (unsigned char *) sbus_ioremap(&r, 0, + auxregs[0].reg_size, "auxio"); /* Fix the address on sun4m and sun4c. */ if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || sparc_cpu_model == sun4c) @@ -72,6 +75,7 @@ { struct linux_prom_registers regs; int node; + struct resource r; /* Attempt to find the sun4m power control node. */ node = prom_getchild(prom_root_node); @@ -84,9 +88,12 @@ /* Map the power control register. */ prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); prom_apply_obio_ranges(®s, 1); - auxio_power_register = (volatile unsigned char *) - sparc_alloc_io(regs.phys_addr, 0, regs.reg_size, - "power off control", regs.which_io, 0); + memset(&r, 0, sizeof(r)); + r.flags = regs.which_io & 0xF; + r.start = regs.phys_addr; + r.end = regs.phys_addr + regs.reg_size - 1; + auxio_power_register = (unsigned char *) sbus_ioremap(&r, 0, + regs.reg_size, "auxpower"); /* Display a quick message on the console. */ if (auxio_power_register) diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c --- v2.3.34/linux/arch/sparc/kernel/ebus.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/ebus.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.4 1999/08/31 06:54:19 davem Exp $ +/* $Id: ebus.c,v 1.8 1999/11/27 22:40:38 zaitcev Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -23,9 +23,8 @@ #include #undef PROM_DEBUG -#undef DEBUG_FILL_EBUS_DEV -#ifdef PROM_DEBUG +#if 0 /* separate from PROM_DEBUG for the sake of PROLL */ #define dprintk prom_printf #else #define dprintk printk @@ -79,7 +78,7 @@ dev->prom_name, len, dev->parent->num_addrs); panic(__FUNCTION__); } - dev->base_address[i] = dev->parent->base_address[regs[i]]; + dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */ } /* @@ -110,22 +109,8 @@ dev->irqs[0] = 0; } else { dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); -/* P3 remove */ printk("EBUS: dev %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]); } } - -#ifdef DEBUG_FILL_EBUS_DEV - dprintk("child '%s': address%s\n", dev->prom_name, - dev->num_addrs > 1 ? "es" : ""); - for (i = 0; i < dev->num_addrs; i++) - dprintk(" %016lx\n", dev->base_address[i]); - if (dev->num_irqs) { - dprintk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); - for (i = 0; i < dev->num_irqs; i++) - dprintk(" %08x", dev->irqs[i]); - dprintk("\n"); - } -#endif } void __init fill_ebus_device(int node, struct linux_ebus_device *dev) @@ -135,6 +120,7 @@ int irqs[PROMINTR_MAX]; char lbuf[128]; int i, n, len; + unsigned long baseaddr; dev->prom_node = node; prom_getstring(node, "name", lbuf, sizeof(lbuf)); @@ -175,28 +161,20 @@ ; } - dev->base_address[i] = dev->bus->self->base_address[n]; - dev->base_address[i] += regs[i].phys_addr; - - if (dev->base_address[i]) { - dev->base_address[i] = - (unsigned long)sparc_alloc_io (dev->base_address[i], 0, - regs[i].reg_size, - dev->prom_name, 0, 0); -#if 0 /* - * This release_region() screwes those who do sparc_alloc_io(). - * Change drivers which do check_region(). See drivers/block/floppy.c. + * XXX Now as we have regions, why don't we make an on-demand allocation... */ - /* Some drivers call 'check_region', so we release it */ - release_region(dev->base_address[i] & PAGE_MASK, PAGE_SIZE); -#endif - - if (dev->base_address[i] == 0 ) { - panic("ebus: unable sparc_alloc_io for dev %s", - dev->prom_name); - } + dev->resource[i].start = 0; + if ((baseaddr = dev->bus->self->resource[n].start + + regs[i].phys_addr) != 0) { + /* dev->resource[i].name = dev->prom_name; */ + if ((baseaddr = (unsigned long) ioremap(baseaddr, + regs[i].reg_size)) == 0) { + panic("ebus: unable to remap dev %s", + dev->prom_name); + } } + dev->resource[i].start = baseaddr; /* XXX Unaligned */ } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); @@ -216,22 +194,9 @@ dev->irqs[0] = 0; } else { dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name); -/* P3 remove */ printk("EBUS: child %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]); } } -#ifdef DEBUG_FILL_EBUS_DEV - dprintk("'%s': address%s\n", dev->prom_name, - dev->num_addrs > 1 ? "es" : ""); - for (i = 0; i < dev->num_addrs; i++) - dprintk(" %016lx\n", dev->base_address[i]); - if (dev->num_irqs) { - dprintk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); - for (i = 0; i < dev->num_irqs; i++) - dprintk(" %08x", dev->irqs[i]); - dprintk("\n"); - } -#endif if ((node = prom_getchild(node))) { dev->children = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); @@ -312,7 +277,7 @@ } nreg = len / sizeof(struct linux_prom_pci_registers); - base = &ebus->self->base_address[0]; + base = &ebus->self->resource[0].start; for (reg = 0; reg < nreg; reg++) { if (!(regs[reg].which_io & 0x03000000)) continue; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S --- v2.3.34/linux/arch/sparc/kernel/entry.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/entry.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.161 1999/08/14 03:51:05 anton Exp $ +/* $Id: entry.S,v 1.163 1999/11/19 04:11:24 davem Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -826,13 +826,13 @@ .globl C_LABEL(invalid_segment_patch1_ff) .globl C_LABEL(invalid_segment_patch2_ff) C_LABEL(invalid_segment_patch1_ff): cmp %l4, 0xff -C_LABEL(invalid_segment_patch2_ff): mov 0xff, %l4 +C_LABEL(invalid_segment_patch2_ff): mov 0xff, %l3 .align 4 .globl C_LABEL(invalid_segment_patch1_1ff) .globl C_LABEL(invalid_segment_patch2_1ff) C_LABEL(invalid_segment_patch1_1ff): cmp %l4, 0x1ff -C_LABEL(invalid_segment_patch2_1ff): mov 0x1ff, %l4 +C_LABEL(invalid_segment_patch2_1ff): mov 0x1ff, %l3 .align 4 .globl C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16) @@ -853,7 +853,7 @@ #ifdef CONFIG_SUN4 C_LABEL(vac_hwflush_patch1_on): nop #else -C_LABEL(vac_hwflush_patch1_on): subcc %l7, (PAGE_SIZE - 4), %l7 +C_LABEL(vac_hwflush_patch1_on): addcc %l7, -PAGE_SIZE, %l7 #endif C_LABEL(vac_hwflush_patch2_on): sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG @@ -969,12 +969,12 @@ bne 1f sethi %hi(C_LABEL(sun4c_kfree_ring)), %l4 or %l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4 - ld [%l4 + 0x10], %l3 + ld [%l4 + 0x18], %l3 deccc %l3 ! do we have a free entry? bcs,a 2f ! no, unmap one. sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 - st %l3, [%l4 + 0x10] ! sun4c_kfree_ring.num_entries-- + st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries-- ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next st %l5, [%l6 + 0x08] ! entry->vaddr = address @@ -997,10 +997,10 @@ st %l6, [%l4 + 0x00] ! head->next = entry - ld [%l4 + 0x10], %l3 + ld [%l4 + 0x18], %l3 inc %l3 ! sun4c_kernel_ring.num_entries++ b 4f - st %l3, [%l4 + 0x10] + ld [%l6 + 0x08], %l5 2: or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4 @@ -1020,7 +1020,7 @@ C_LABEL(vac_hwflush_patch1): C_LABEL(vac_linesize_patch): subcc %l7, 16, %l7 - bg 9b + bne 9b C_LABEL(vac_hwflush_patch2): sta %g0, [%l3 + %l7] ASI_FLUSHSEG @@ -1041,47 +1041,36 @@ mov %l3, %l5 ! address = tmp +4: C_LABEL(num_context_patch1): mov 0x08, %l7 -C_LABEL(invalid_segment_patch2): - mov 0x7f, %l4 + ld [%l6 + 0x08], %l4 + ldub [%l6 + 0x0c], %l3 + or %l4, %l3, %l4 ! encode new vaddr/pseg into l4 sethi %hi(AC_CONTEXT), %l3 lduba [%l3] ASI_CONTROL, %l6 -3: - deccc %l7 - stba %l7, [%l3] ASI_CONTROL - bne 3b - stXa %l4, [%l5] ASI_SEGMAP - - stba %l6, [%l3] ASI_CONTROL - - ! reload the entry - - sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 - ld [%l4 + %lo(C_LABEL(sun4c_kernel_ring))], %l6 - - ld [%l6 + 0x08], %l5 ! restore address from entry->vaddr - -4: -C_LABEL(num_context_patch2): - mov 0x08, %l7 - - ldub [%l6 + 0x0c], %l4 ! entry->pseg - + /* Invalidate old mapping, instantiate new mapping, + * for each context. Registers l6/l7 are live across + * this loop. + */ +3: deccc %l7 sethi %hi(AC_CONTEXT), %l3 - lduba [%l3] ASI_CONTROL, %l6 - -3: - deccc %l7 stba %l7, [%l3] ASI_CONTROL +C_LABEL(invalid_segment_patch2): + mov 0x7f, %l3 + stXa %l3, [%l5] ASI_SEGMAP + andn %l4, 0x1ff, %l3 bne 3b - stXa %l4, [%l5] ASI_SEGMAP + stXa %l4, [%l3] ASI_SEGMAP + sethi %hi(AC_CONTEXT), %l3 stba %l6, [%l3] ASI_CONTROL + andn %l4, 0x1ff, %l5 + 1: sethi %hi(SUN4C_VMALLOC_START), %l4 cmp %l5, %l4 @@ -1149,6 +1138,7 @@ sun4c_fault_fromuser: SAVE_ALL + nop mov %l7, %o1 ! Decode the info from %l7 mov %l7, %o2 @@ -1199,6 +1189,7 @@ RESTORE_ALL +#ifdef CONFIG_SUNOS_EMUL /* SunOS uses syscall zero as the 'indirect syscall' it looks * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. * This is complete brain damage. @@ -1226,6 +1217,7 @@ mov %o5, %o4 call %l6 mov %l4, %o7 +#endif .align 4 .globl C_LABEL(sys_nis_syscall) @@ -1638,6 +1630,20 @@ sub %l1, 1, %l1 b ret_trap_entry st %l1, [%sp + REGWIN_SZ + PT_NPC] + +#ifndef CONFIG_SUNOS_EMUL + .align 4 + .globl sunos_syscall +sunos_syscall: + SAVE_ALL_HEAD + rd %wim, %l3 + wr %l0, PSR_ET, %psr + nop + nop + mov %i0, %l5 + call C_LABEL(do_sunos_syscall) + add %sp, REGWIN_SZ, %o0 +#endif /* {net, open}bsd system calls enter here... */ .align 4 diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v2.3.34/linux/arch/sparc/kernel/head.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/head.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.97 1999/08/14 03:51:10 anton Exp $ +/* $Id: head.S,v 1.101 1999/12/02 08:34:56 jj Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -78,6 +78,11 @@ .asciz "Sparc-Linux sun4e support does not exist\n\n" .align 4 +#ifndef CONFIG_SUNOS_EMUL +#undef SUNOS_SYSCALL_TRAP +#define SUNOS_SYSCALL_TRAP SUNOS_NO_SYSCALL_TRAP +#endif + /* The Sparc trap table, bootloader gives us control at _start. */ .text .globl start, _stext, _start, __stext @@ -171,7 +176,8 @@ t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) t_getcc:GETCC_TRAP /* Get Condition Codes */ t_setcc:SETCC_TRAP /* Set Condition Codes */ -t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) +t_getpsr:GETPSR_TRAP /* Get PSR Register */ +t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) t_slowi:INDIRECT_SOLARIS_SYSCALL(156) t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) @@ -247,8 +253,8 @@ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) - BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP - BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) + BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP + BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) @@ -315,8 +321,8 @@ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) - BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP - BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) + BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP + BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) @@ -383,8 +389,8 @@ LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) - BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP - BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) + BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP + BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) @@ -436,7 +442,7 @@ */ .ascii "HdrS" .word LINUX_VERSION_CODE - .half 0x0201 /* HdrS version */ + .half 0x0203 /* HdrS version */ C_LABEL(root_flags): .half 1 C_LABEL(root_dev): @@ -448,6 +454,8 @@ C_LABEL(sparc_ramdisk_size): .word 0 .word C_LABEL(reboot_command) + .word 0, 0, 0 + .word _end /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in * %g7 and at prom_vector_p. And also quickly check whether we are on diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c --- v2.3.34/linux/arch/sparc/kernel/ioport.c Mon Apr 14 16:28:07 1997 +++ linux/arch/sparc/kernel/ioport.c Mon Dec 20 22:05:52 1999 @@ -1,22 +1,20 @@ -/* $Id: ioport.c,v 1.24 1997/04/10 03:02:32 davem Exp $ +/* $Id: ioport.c,v 1.27 1999/11/14 06:23:04 zaitcev Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * - * The routines in this file should be changed for a memory allocator - * that would be setup just like NetBSD does : you create regions that - * are administered by a general purpose allocator, and then you call - * that allocator with your handle and the block size instead of this - * weak stuff. + * 1996: sparc_free_io, 1999: ioremap()/iounmap() by Pete Zaitcev. */ +#include #include #include #include #include #include #include +#include #include #include @@ -24,116 +22,511 @@ #include #include -/* This points to the next to use virtual memory for io mappings */ -static unsigned long dvma_next_free = DVMA_VADDR; -unsigned long sparc_iobase_vaddr = IOBASE_VADDR; +struct resource *sparc_find_resource_bystart(struct resource *, unsigned long); +struct resource *sparc_find_resource_by_hit(struct resource *, unsigned long); + +static void *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz); +static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, + unsigned long size, char *name); +static void _sparc_free_io(struct resource *res); + +/* 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 +}; +/* This points to the start of I/O mappings, cluable from outside. */ + struct resource sparc_iomap = { + "sparc_iomap", IOBASE_VADDR, IOBASE_END-1 +}; /* - * sparc_alloc_io: - * Map and allocates an obio device. - * Implements a simple linear allocator, you can force the function - * to use your own mapping, but in practice this should not be used. - * - * Input: - * address: the obio address to map - * virtual: if non zero, specifies a fixed virtual address where - * the mapping should take place. - * len: the length of the mapping - * bus_type: The bus on which this io area sits. + * Our mini-allocator... + * Boy this is gross! We need it because we must map I/O for + * timers and interrupt controller before the kmalloc is available. + */ + +#define XNMLN 15 +#define XNRES 10 /* SS-10 uses 8 */ + +struct xresource { + struct resource xres; /* Must be first */ + int xflag; /* 1 == used */ + char xname[XNMLN+1]; +}; + +static struct xresource xresv[XNRES]; + +static struct xresource *xres_alloc(void) { + struct xresource *xrp; + int n; + + xrp = xresv; + for (n = 0; n < XNRES; n++) { + if (xrp->xflag == 0) { + xrp->xflag = 1; + return xrp; + } + xrp++; + } + return NULL; +} + +static void xres_free(struct xresource *xrp) { + xrp->xflag = 0; +} + +/* + */ +extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly); +extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly); + +static void mapioaddr(unsigned long physaddr, unsigned long virt_addr, + int bus, int rdonly) +{ + switch(sparc_cpu_model) { + case sun4c: + case sun4: + sun4c_mapioaddr(physaddr, virt_addr, bus, rdonly); + break; + case sun4m: + case sun4d: + case sun4e: + srmmu_mapioaddr(physaddr, virt_addr, bus, rdonly); + break; + default: + printk("mapioaddr: Trying to map IO space for unsupported machine.\n"); + printk("mapioaddr: sparc_cpu_model = %d\n", sparc_cpu_model); + printk("mapioaddr: Halting...\n"); + halt(); + }; + return; +} + +extern void srmmu_unmapioaddr(unsigned long virt); +extern void sun4c_unmapioaddr(unsigned long virt); + +static void unmapioaddr(unsigned long virt_addr) +{ + switch(sparc_cpu_model) { + case sun4c: + case sun4: + sun4c_unmapioaddr(virt_addr); + break; + case sun4m: + case sun4d: + case sun4e: + srmmu_unmapioaddr(virt_addr); + break; + default: + printk("unmapioaddr: sparc_cpu_model = %d, halt...\n", sparc_cpu_model); + halt(); + }; + return; +} + +/* + * These are typically used in PCI drivers + * which are trying to be cross-platform. * - * Returns: - * The virtual address where the mapping actually took place. + * Bus type is always zero on IIep. */ +void *ioremap(unsigned long offset, unsigned long size) +{ + char name[14]; + + sprintf(name, "phys_%08x", (u32)offset); + return _sparc_alloc_io(0, offset, size, name); +} -void *sparc_alloc_io (u32 address, void *virtual, int len, char *name, - u32 bus_type, int rdonly) +/* + * Comlimentary to ioremap(). + */ +void iounmap(void *virtual) { - unsigned long vaddr, base_address; - unsigned long addr = (unsigned long) address; - unsigned long offset = (addr & (~PAGE_MASK)); + unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; + struct resource *res; - if (virtual) { - vaddr = (unsigned long) virtual; + if ((res = sparc_find_resource_bystart(&sparc_iomap, vaddr)) == NULL) { + printk("free_io/iounmap: cannot free %lx\n", vaddr); + return; + } + _sparc_free_io(res); - len += offset; - if(((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)) { - prom_printf("alloc_io: Mapping outside IOBASE area\n"); - prom_halt(); - } - if(check_region ((vaddr | offset), len)) { - prom_printf("alloc_io: 0x%lx is already in use\n", vaddr); - prom_halt(); - } + if ((char *)res >= (char*)xresv && (char *)res < (char *)&xresv[XNRES]) { + xres_free((struct xresource *)res); + } else { + kfree(res); + } +} - /* Tell Linux resource manager about the mapping */ - request_region ((vaddr | offset), len, name); +/* + * Davem's version of sbus_ioremap. + */ +unsigned long sbus_ioremap(struct resource *phyres, unsigned long offset, + unsigned long size, char *name) +{ + return (unsigned long) _sparc_alloc_io(phyres->flags & 0xF, + phyres->start + offset, size, name); +} + +/* + */ +void sbus_iounmap(unsigned long addr, unsigned long size) +{ + iounmap((void *)addr); +} + +/* + * Meat of mapping + */ +static void *_sparc_alloc_io(unsigned int busno, unsigned long phys, + unsigned long size, char *name) +{ + static int printed_full = 0; + struct xresource *xres; + struct resource *res; + char *tack; + int tlen; + void *va; /* P3 diag */ + + if (name == NULL) name = "???"; + + if ((xres = xres_alloc()) != 0) { + tack = xres->xname; + res = &xres->xres; } else { - vaddr = occupy_region(sparc_iobase_vaddr, IOBASE_END, - (offset + len + PAGE_SIZE-1) & PAGE_MASK, PAGE_SIZE, name); - if (vaddr == 0) { - /* Usually we cannot see printks in this case. */ - prom_printf("alloc_io: cannot occupy %d region\n", len); - prom_halt(); + if (!printed_full) { + printk("ioremap: done with statics, switching to malloc\n"); + printed_full = 1; } + tlen = strlen(name); + tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL); + if (tack == NULL) return NULL; + res = (struct resource *) tack; + tack += sizeof (struct resource); } - base_address = vaddr; - /* Do the actual mapping */ - for (; len > 0; len -= PAGE_SIZE) { - mapioaddr(addr, vaddr, bus_type, rdonly); - vaddr += PAGE_SIZE; - addr += PAGE_SIZE; + strncpy(tack, name, XNMLN); + tack[XNMLN] = 0; + res->name = tack; + + va = _sparc_ioremap(res, busno, phys, size); + /* printk("ioremap(0x%x:%08lx[0x%lx])=%p\n", busno, phys, size, va); */ /* P3 diag */ + return va; +} + +/* + * This is called from _sparc_alloc_io only, we left it separate + * in case Davem changes his mind about interface to sbus_ioremap(). + */ +static void * +_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz) +{ + unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK); + unsigned long va; + unsigned int psz; + + if (allocate_resource(&sparc_iomap, res, + (offset + sz + PAGE_SIZE-1) & PAGE_MASK, + sparc_iomap.start, sparc_iomap.end, PAGE_SIZE) != 0) { + /* Usually we cannot see printks in this case. */ + prom_printf("alloc_io_res(%s): cannot occupy\n", + (res->name != NULL)? res->name: "???"); + prom_halt(); + } + + va = res->start; + pa &= PAGE_MASK; + for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) { + mapioaddr(pa, va, bus, 0); + va += PAGE_SIZE; + pa += PAGE_SIZE; } - return (void *) (base_address | offset); + /* + * XXX Playing with implementation details here. + * On sparc64 Ebus has resources with precise boundaries. + * We share drivers with sparc64. Too clever drivers use + * start of a resource instead of a base adress. + * + * XXX-2 This may be not valid anymore, clean when + * interface to sbus_ioremap() is resolved. + */ + res->start += offset; + res->end = res->start + sz - 1; /* not strictly necessary.. */ + + return (void *) res->start; } -void sparc_free_io (void *virtual, int len) +/* + * Comlimentary to _sparc_ioremap(). + */ +static void _sparc_free_io(struct resource *res) { - unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; - unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + len + PAGE_SIZE-1) & PAGE_MASK; - - release_region(vaddr, plen); + unsigned long plen; - for (; plen != 0;) { + plen = res->end - res->start + 1; + while (plen != 0) { plen -= PAGE_SIZE; - unmapioaddr(vaddr + plen); + unmapioaddr(res->start + plen); } + + release_resource(res); +} + +#ifdef CONFIG_SBUS + +void sbus_set_sbus64(struct sbus_dev *sdev, int x) { + printk("sbus_set_sbus64: unsupported\n"); } -/* Does DVMA allocations with PAGE_SIZE granularity. How this basically - * works is that the ESP chip can do DVMA transfers at ANY address with - * certain size and boundary restrictions. But other devices that are - * attached to it and would like to do DVMA have to set things up in - * a special way, if the DVMA sees a device attached to it transfer data - * at addresses above DVMA_VADDR it will grab them, this way it does not - * now have to know the peculiarities of where to read the Lance data - * from. (for example) +/* + * Allocate a chunk of memory suitable for DMA. + * Typically devices use them for control blocks. + * CPU may access them without any explicit flushing. */ -void *_sparc_dvma_malloc (int len, char *name) +void *sbus_alloc_consistant(struct sbus_dev *sdev, long len, u32 *dma_addrp) { - unsigned long vaddr, base_address; + unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; + unsigned long va; + struct resource *res; + int order; + + /* XXX why are some lenghts signed, others unsigned? */ + if (len <= 0) { + return NULL; + } + /* XXX So what is maxphys for us and how do drivers know it? */ + if (len > 256*1024) { /* __get_free_pages() limit */ + return NULL; + } - vaddr = dvma_next_free; - if(check_region (vaddr, len)) { - prom_printf("alloc_dma: 0x%lx is already in use\n", vaddr); - prom_halt(); + for (order = 0; order < 6; order++) /* 2^6 pages == 256K */ + if ((1 << (order + PAGE_SHIFT)) >= len_total) + break; + va = __get_free_pages(GFP_KERNEL, order); + if (va == 0) { + /* + * printk here may be flooding... Consider removal XXX. + */ + printk("sbus_alloc_consistant: no %ld pages\n", len_total>>PAGE_SHIFT); + return NULL; } - if(vaddr + len > (DVMA_VADDR + DVMA_LEN)) { - prom_printf("alloc_dvma: out of dvma memory\n"); - prom_halt(); + + if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { + free_pages(va, order); + printk("sbus_alloc_consistant: no core\n"); + return NULL; } - /* Basically these can be mapped just like any old - * IO pages, cacheable bit off, etc. The physical - * pages are now mapped dynamically to save space. + if (allocate_resource(&sparc_dvma, res, len_total, + sparc_dvma.start, sparc_dvma.end, PAGE_SIZE) != 0) { + printk("sbus_alloc_consistant: cannot occupy 0x%lx", len); + free_pages(va, order); + kfree(res); + return NULL; + } + + *dma_addrp = res->start; + mmu_map_dma_area(va, res->start, len); + + /* + * "Official" or "natural" address of pages we got is va. + * We want to return uncached range. We could make va[len] + * uncached but it's difficult to make cached back [P3: hmm] + * We use the artefact of sun4c, replicated everywhere else, + * that CPU can use bus addresses to access the same memory. */ - base_address = vaddr; - mmu_map_dma_area(base_address, len); - /* Assign the memory area. */ - dvma_next_free = PAGE_ALIGN(dvma_next_free+len); + res->name = (void *)va; /* XXX Ouch.. we got to hide it somewhere */ + return (void *)res->start; +} + +void sbus_free_consistant(struct sbus_dev *sdev, long n, void *p, u32 ba) +{ + struct resource *res; + unsigned long pgp; + int order; + + if ((res = sparc_find_resource_bystart(&sparc_dvma, + (unsigned long)p)) == NULL) { + printk("sbus_free_consistant: cannot free %p\n", p); + return; + } + + if (((unsigned long)p & (PAGE_MASK-1)) != 0) { + printk("sbus_free_consistant: unaligned va %p\n", p); + return; + } + + n = (n + PAGE_SIZE-1) & PAGE_MASK; + if ((res->end-res->start)+1 != n) { + printk("sbus_free_consistant: region 0x%lx asked 0x%lx\n", + (long)((res->end-res->start)+1), n); + return; + } + + mmu_inval_dma_area((unsigned long)res->name, n); /* XXX Ouch */ + mmu_unmap_dma_area(ba, n); + release_resource(res); + + pgp = (unsigned long) res->name; /* XXX Ouch */ + for (order = 0; order < 6; order++) + if ((1 << (order + PAGE_SHIFT)) >= n) + break; + free_pages(pgp, order); + + kfree(res); +} + +/* + * Map a chunk of memory so that devices can see it. + * CPU view of this memory may be inconsistent with + * a device view and explicit flushing is necessary. + */ +u32 sbus_map_single(struct sbus_dev *sdev, void *va, long len) +{ +#if 0 /* This is the version that abuses consistant space */ + unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; + struct resource *res; + + /* XXX why are some lenghts signed, others unsigned? */ + if (len <= 0) { + return 0; + } + /* XXX So what is maxphys for us and how do drivers know it? */ + if (len > 256*1024) { /* __get_free_pages() limit */ + return 0; + } + + if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { + printk("sbus_map_single: no core\n"); + return 0; + } + res->name = va; + + if (allocate_resource(&sparc_dvma, res, len_total, + sparc_dvma.start, sparc_dvma.end, PAGE_SIZE) != 0) { + printk("sbus_map_single: cannot occupy 0x%lx", len); + kfree(res); + return 0; + } + + mmu_map_dma_area(va, res->start, len_total); + mmu_flush_dma_area((unsigned long)va, len_total); /* in all contexts? */ + + return res->start; +#endif +#if 1 /* "trampoline" version */ + /* XXX why are some lenghts signed, others unsigned? */ + if (len <= 0) { + return 0; + } + /* XXX So what is maxphys for us and how do drivers know it? */ + if (len > 256*1024) { /* __get_free_pages() limit */ + return 0; + } +/* BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) */ + return mmu_get_scsi_one(va, len, sdev->bus); +#endif +} - request_region(base_address, len, name); +void sbus_unmap_single(struct sbus_dev *sdev, u32 ba, long n) +{ +#if 0 /* This is the version that abuses consistant space */ + struct resource *res; + unsigned long va; + + if ((res = sparc_find_resource_bystart(&sparc_dvma, ba)) == NULL) { + printk("sbus_unmap_single: cannot find %08x\n", (unsigned)ba); + return; + } + + n = (n + PAGE_SIZE-1) & PAGE_MASK; + if ((res->end-res->start)+1 != n) { + printk("sbus_unmap_single: region 0x%lx asked 0x%lx\n", + (long)((res->end-res->start)+1), n); + return; + } + + va = (unsigned long) res->name; /* XXX Ouch */ + mmu_inval_dma_area(va, n); /* in all contexts, mm's?... */ + mmu_unmap_dma_area(ba, n); /* iounit cache flush is here */ + release_resource(res); + kfree(res); +#endif +#if 1 /* "trampoline" version */ +/* BTFIXUPDEF_CALL(void, mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) */ + mmu_release_scsi_one(ba, n, sdev->bus); +#endif +} + +void sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n) +{ +/* BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */ + mmu_get_scsi_sgl(sg, n, sdev->bus); +} + +void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n) +{ +/* BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */ + mmu_release_scsi_sgl(sg, n, sdev->bus); +} +#endif + +/* + * P3: I think a partial flush is permitted... + * We are not too efficient at doing it though. + * + * If only DaveM understood a concept of an allocation cookie, + * we could avoid find_resource_by_hit() here and a major + * performance hit. + */ +void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size) +{ + unsigned long va; + struct resource *res; + + res = sparc_find_resource_by_hit(&sparc_dvma, ba); + if (res == NULL) + panic("sbus_dma_sync_single: 0x%x\n", ba); + + va = (unsigned long) res->name; + /* if (va == 0) */ + + mmu_inval_dma_area(va, (res->end - res->start) + 1); +} + +void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n) +{ + printk("dma_sync_sg: not implemented yet\n"); +} + +/* + * This is a version of find_resource and it belongs to kernel/resource.c. + * Until we have agreement with Linus and Martin, it lingers here. + * + * "same start" is more strict than "hit into" + */ +struct resource * +sparc_find_resource_bystart(struct resource *root, unsigned long start) +{ + struct resource *tmp; + + for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { + if (tmp->start == start) + return tmp; + } + return NULL; +} + +struct resource * +sparc_find_resource_by_hit(struct resource *root, unsigned long hit) +{ + struct resource *tmp; - return (void *) base_address; + for (tmp = root->child; tmp != 0; tmp = tmp->sibling) { + if (tmp->start <= hit && tmp->end >= hit) + return tmp; + } + return NULL; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.3.34/linux/arch/sparc/kernel/irq.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/irq.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.97 1999/09/10 10:40:21 davem Exp $ +/* $Id: irq.c,v 1.98 1999/11/17 07:34:05 zaitcev Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -726,7 +726,7 @@ case sun4m: #ifdef CONFIG_PCI pcic_probe(); - if (pci_present()) { + if (pcic_present()) { sun4m_pci_init_IRQ(); break; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c --- v2.3.34/linux/arch/sparc/kernel/pcic.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/pcic.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.8 1999/08/31 06:54:22 davem Exp $ +/* $Id: pcic.c,v 1.11 1999/11/25 05:22:05 zaitcev Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko @@ -22,17 +22,6 @@ #include /* for cache flushing. */ #include -#undef PROM_DEBUG -#undef FIXUP_REGS_DEBUG -#undef FIXUP_IRQ_DEBUG -#undef FIXUP_VMA_DEBUG - -#ifdef PROM_DEBUG -#define dprintf prom_printf -#else -#define dprintf printk -#endif - #include #include #include @@ -57,7 +46,7 @@ unsigned long len, unsigned char *buf) { - return 0; + return -EINVAL; } asmlinkage int sys_pciconfig_write(unsigned long bus, @@ -66,11 +55,19 @@ unsigned long len, unsigned char *buf) { - return 0; + return -EINVAL; } #else +#ifdef CONFIG_SUN_JSFLASH +extern int jsflash_init(void); +#endif + +struct pci_fixup pcibios_fixups[] = { + { 0 } +}; + unsigned int pcic_pin_to_irq(unsigned int pin, char *name); /* @@ -120,7 +117,8 @@ { 0, 0x00, 0, 13, 0 }, /* Ebus - serial and keyboard */ { 0, 0x01, 1, 6, 0 }, /* hme */ { 0, 0x08, 2, 9, 0 }, /* VGA - we hope not used :) */ - { 0, 0x18, 6, 8, 0 }, /* PCI INTA# in Slot 1 */ + { 0, 0x10, 6, 8, 0 }, /* PCI INTA# in Slot 1 */ + { 0, 0x18, 7, 12, 0 }, /* PCI INTA# in Slot 2, shared w. RTC */ { 0, 0x38, 4, 9, 0 }, /* All ISA devices. Read 8259. */ { 0, 0x80, 5, 11, 0 }, /* EIDE */ /* {0,0x88, 0,0,0} - unknown device... PMU? Probably no interrupt. */ @@ -144,6 +142,16 @@ }; /* + * Krups (courtesy of Varol Kaptan) + * No documentation available, so we guess it, based on Espresso layout. + * Since we always run PROLL on Krups we may put map in there. + */ +static struct pcic_ca2irq pcic_i_jk[] = { + { 0, 0x00, 0, 13, 0 }, /* Ebus - serial and keyboard */ + { 0, 0x01, 1, 6, 0 }, /* hme */ +}; + +/* * Several entries in this list may point to the same routing map * as several PROMs may be installed on the same physical board. */ @@ -154,11 +162,17 @@ SN2L_INIT("JE-1-name", pcic_i_je1), /* XXX Gleb, put name here, pls */ SN2L_INIT("SUNW,JS-E", pcic_i_jse), /* PROLL JavaStation-E */ SN2L_INIT("SUNW,SPARCengine-6", pcic_i_se6), /* SPARCengine-6/CP-1200 */ + SN2L_INIT("SUNW,JS-NC", pcic_i_jk), /* PROLL JavaStation-NC */ + SN2L_INIT("SUNW,JSIIep", pcic_i_jk), /* OBP JavaStation-NC */ { NULL, NULL, 0 } }; -static struct linux_pcic PCIC; -static struct linux_pcic *pcic = NULL; +/* + * Only one PCIC per IIep, + * and since we have no SMP IIep, only one per system. + */ +static int pcic0_up = 0; +static struct linux_pcic pcic0; unsigned int pcic_regs; volatile int pcic_speculative; @@ -167,23 +181,144 @@ static void pci_do_gettimeofday(struct timeval *tv); static void pci_do_settimeofday(struct timeval *tv); -void __init pcic_probe(void) +#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) + +static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value); +static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value); + +static int pcic_read_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + unsigned int v; + + pcic_read_config_dword(dev, where&~3, &v); + *value = 0xff & (v >> (8*(where & 3))); + return PCIBIOS_SUCCESSFUL; +} + +static int pcic_read_config_word(struct pci_dev *dev, int where, u16 *value) +{ + unsigned int v; + if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; + + pcic_read_config_dword(dev, where&~3, &v); + *value = 0xffff & (v >> (8*(where & 3))); + return PCIBIOS_SUCCESSFUL; +} + +static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value) { + unsigned char bus = dev->bus->number; + unsigned char device_fn = dev->devfn; + /* unsigned char where; */ + + struct linux_pcic *pcic; + unsigned long flags; + + if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND; + pcic = &pcic0; + + save_and_cli(flags); +#if 0 /* does not fail here */ + pcic_speculative = 1; + pcic_trapped = 0; +#endif + writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr); +#if 0 /* does not fail here */ + nop(); + if (pcic_trapped) { + restore_flags(flags); + *value = ~0; + return PCIBIOS_SUCCESSFUL; + } +#endif + pcic_speculative = 2; + pcic_trapped = 0; + *value = readl(pcic->pcic_config_space_data + (where&4)); + nop(); + if (pcic_trapped) { + pcic_speculative = 0; + restore_flags(flags); + *value = ~0; + return PCIBIOS_SUCCESSFUL; + } + pcic_speculative = 0; + restore_flags(flags); + return PCIBIOS_SUCCESSFUL; +} + +static int pcic_write_config_byte(struct pci_dev *dev, int where, u8 value) +{ + unsigned int v; + + pcic_read_config_dword(dev, where&~3, &v); + v = (v & ~(0xff << (8*(where&3)))) | + ((0xff&(unsigned)value) << (8*(where&3))); + return pcic_write_config_dword(dev, where&~3, v); +} + +static int pcic_write_config_word(struct pci_dev *dev, int where, u16 value) +{ + unsigned int v; + + if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; + pcic_read_config_dword(dev, where&~3, &v); + v = (v & ~(0xffff << (8*(where&3)))) | + ((0xffff&(unsigned)value) << (8*(where&3))); + return pcic_write_config_dword(dev, where&~3, v); +} + +static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + unsigned char bus = dev->bus->number; + unsigned char devfn = dev->devfn; + struct linux_pcic *pcic; + unsigned long flags; + + if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND; + pcic = &pcic0; + + save_and_cli(flags); + writel(CONFIG_CMD(bus,devfn,where), pcic->pcic_config_space_addr); + writel(value, pcic->pcic_config_space_data + (where&4)); + restore_flags(flags); + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pcic_ops = { + pcic_read_config_byte, + pcic_read_config_word, + pcic_read_config_dword, + pcic_write_config_byte, + pcic_write_config_word, + pcic_write_config_dword, +}; + +/* + * On sparc64 pcibios_init() calls pci_controller_probe(). + * We want PCIC probed little ahead so that interrupt controller + * would be operational. + */ +int __init pcic_probe(void) +{ + struct linux_pcic *pcic; struct linux_prom_registers regs[PROMREG_MAX]; struct linux_pbm_info* pbm; char namebuf[64]; int node; int err; - if (pcibios_present()) { + if (pcic0_up) { prom_printf("PCIC: called twice!\n"); prom_halt(); } + pcic = &pcic0; node = prom_getchild (prom_root_node); node = prom_searchsiblings (node, "pci"); if (node == 0) - return; + return -ENODEV; /* * Map in PCIC register set, config space, and IO base */ @@ -193,31 +328,27 @@ "from PROM.\n"); prom_halt(); } - - pcic = &PCIC; - pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL, - regs[0].reg_size, - "PCIC Registers", 0, 0); + pcic0_up = 1; + + pcic->pcic_res_regs.name = "pcic_registers"; + pcic->pcic_regs = (unsigned long) + ioremap(regs[0].phys_addr, regs[0].reg_size); if (!pcic->pcic_regs) { prom_printf("PCIC: Error, cannot map PCIC registers.\n"); prom_halt(); } - pcic->pcic_io_phys = regs[1].phys_addr; - pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL, - regs[1].reg_size, - "PCIC IO Base", 0, 0); - if (pcic->pcic_io == 0UL) { + pcic->pcic_res_io.name = "pcic_io"; + if ((pcic->pcic_io = (unsigned long) + ioremap(regs[1].phys_addr, 0x10000)) == 0) { prom_printf("PCIC: Error, cannot map PCIC IO Base.\n"); prom_halt(); } - pcic->pcic_config_space_addr = - (unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL, - regs[2].reg_size * 2, - "PCI Config Space Address", 0, 0); - if (pcic->pcic_config_space_addr == 0UL) { + pcic->pcic_res_cfg_addr.name = "pcic_cfg_addr"; + if ((pcic->pcic_config_space_addr = (unsigned long) + ioremap(regs[2].phys_addr, regs[2].reg_size * 2)) == 0) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Address.\n"); prom_halt(); @@ -227,11 +358,9 @@ * Docs say three least significant bits in address and data * must be the same. Thus, we need adjust size of data. */ - pcic->pcic_config_space_data = - (unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL, - regs[3].reg_size * 2, - "PCI Config Space Data", 0, 0); - if (pcic->pcic_config_space_data == 0UL) { + pcic->pcic_res_cfg_data.name = "pcic_cfg_data"; + if ((pcic->pcic_config_space_data = (unsigned long) + ioremap(regs[3].phys_addr, regs[3].reg_size * 2)) == 0) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Data.\n"); prom_halt(); @@ -239,7 +368,7 @@ pbm = &pcic->pbm; pbm->prom_node = node; - prom_getstring(node, "name", namebuf, sizeof(namebuf)); + prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0; strcpy(pbm->prom_name, namebuf); { @@ -254,7 +383,7 @@ pcic_regs = pcic->pcic_regs; } - prom_getstring(prom_root_node, "name", namebuf, sizeof(namebuf)); + prom_getstring(prom_root_node, "name", namebuf, 63); namebuf[63] = 0; { struct pcic_sn2list *p; @@ -272,21 +401,37 @@ printk("PCIC: System %s is unknown, cannot route interrupts\n", namebuf); } + + return 0; +} + +static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic) +{ + struct linux_pbm_info *pbm = &pcic->pbm; + + pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm); +#if 0 /* deadwood transplanted from sparc64 */ + pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); + pci_record_assignments(pbm, pbm->pci_bus); + pci_assign_unassigned(pbm, pbm->pci_bus); + pci_fixup_irq(pbm, pbm->pci_bus); +#endif } +/* + * Main entry point from the PCI subsystem. + */ void __init pcibios_init(void) { + struct linux_pcic *pcic; + /* * PCIC should be initialized at start of the timer. * So, here we report the presence of PCIC and do some magic passes. */ - if(!pcic) + if(!pcic0_up) return; - - printk("PCIC MAP: config addr=0x%lx; config data=0x%lx, " - "regs=0x%lx io=0x%lx\n", - pcic->pcic_config_space_addr, pcic->pcic_config_space_data, - pcic->pcic_regs, pcic->pcic_io); + pcic = &pcic0; /* * Switch off IOTLB translation. @@ -302,11 +447,18 @@ writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0); writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, pcic->pcic_regs+PCI_BASE_ADDRESS_0); + + pcic_pbm_scan_bus(pcic); + + ebus_init(); +#ifdef CONFIG_SUN_JSFLASH + jsflash_init(); +#endif } -int pcibios_present(void) +int pcic_present(void) { - return pcic != NULL; + return pcic0_up; } static int __init pdev_to_pnode(struct linux_pbm_info *pbm, @@ -334,91 +486,77 @@ return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC); } -static void pcic_map_pci_device (struct pci_dev *dev, int node) { - struct linux_prom_pci_assigned_addresses addrs[6]; - int addrlen; - int i, j; - - /* Is any valid address present ? */ - i = 0; - for(j = 0; j < 6; j++) - if (dev->base_address[j]) i++; - if (!i) return; /* nothing to do */ +static void pcic_map_pci_device(struct linux_pcic *pcic, + struct pci_dev *dev, int node) +{ + char namebuf[64]; + unsigned long address; + unsigned long flags; + int j; if (node == 0 || node == -1) { - printk("PCIC: no prom node for device ID (%x,%x)\n", - dev->device, dev->vendor); - return; - } - - /* - * find related address and get it's window length - */ - addrlen = prom_getproperty(node,"assigned-addresses", - (char*)addrs, sizeof(addrs)); - if (addrlen == -1) { - printk("PCIC: no \"assigned-addresses\" for device (%x,%x)\n", - dev->device, dev->vendor); - return; + strcpy(namebuf, "???"); + } else { + prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0; } - addrlen /= sizeof(struct linux_prom_pci_assigned_addresses); - for (i = 0; i < addrlen; i++ ) - for (j = 0; j < 6; j++) { - if (!dev->base_address[j] || !addrs[i].phys_lo) - continue; - if (addrs[i].phys_lo == dev->base_address[j]) { - unsigned long address = dev->base_address[j]; - int length = addrs[i].size_lo; - char namebuf[128] = { 0, }; - unsigned long mapaddr, addrflags; - - prom_getstring(node, "name", namebuf, sizeof(namebuf)); - - /* - * failure in allocation too large space - */ - if (length > 0x200000) { - length = 0x200000; - prom_printf("PCIC: map window for device '%s' " - "reduced to 2MB !\n", namebuf); - } - - /* - * Be careful with MEM/IO address flags - */ - if ((address & PCI_BASE_ADDRESS_SPACE) == - PCI_BASE_ADDRESS_SPACE_IO) { - mapaddr = address & PCI_BASE_ADDRESS_IO_MASK; + for (j = 0; j < 6; j++) { + address = dev->resource[j].start; + if (address == 0) break; /* are sequential */ + flags = dev->resource[j].flags; + if ((flags & IORESOURCE_IO) != 0) { + if (address < 0x10000) { + /* + * A device responds to I/O cycles on PCI. + * We generate these cycles with memory + * access into the fixed map (phys 0x30000000). + * + * Since a device driver does not want to + * do ioremap() before accessing PC-style I/O, + * we supply virtual, ready to access address. + * + * Ebus devices do not come here even if + * CheerIO makes a similar conversion. + * See ebus.c for details. + * + * Note that check_region()/request_region() + * work for these devices. + * + * XXX Neat trick, but it's a *bad* idea + * to shit into regions like that. + * What if we want to allocate one more + * PCI base address... + */ + dev->resource[j].start = + pcic->pcic_io + address; + dev->resource[j].end = 1; /* XXX */ + dev->resource[j].flags = + (flags & ~IORESOURCE_IO) | IORESOURCE_MEM; } else { - mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK; + /* + * OOPS... PCI Spec allows this. Sun does + * not have any devices getting above 64K + * so it must be user with a weird I/O + * board in a PCI slot. We must remap it + * under 64K but it is not done yet. XXX + */ + printk("PCIC: Skipping I/O space at 0x%lx," + "this will Oops if a driver attaches;" + "device '%s' (%x,%x)\n", address, namebuf, + dev->device, dev->vendor); } - addrflags = address ^ mapaddr; - - dev->base_address[j] = - (unsigned long)sparc_alloc_io(address, 0, - length, - namebuf, 0, 0); - if ( dev->base_address[j] == 0 ) - panic("PCIC: failed make mapping for " - "pci device '%s' with address %lx\n", - namebuf, address); - - dev->base_address[j] ^= addrflags; - return; } - } - - printk("PCIC: unable to match addresses for device (%x,%x)\n", - dev->device, dev->vendor); + } } -static void pcic_fill_irq(struct pci_dev *dev, int node) { +static void +pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) +{ struct pcic_ca2irq *p; int i, ivec; char namebuf[64]; /* P3 remove */ - if (node == -1) { + if (node == 0 || node == -1) { strcpy(namebuf, "???"); } else { prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */ @@ -474,53 +612,33 @@ } /* - * Assign IO space for a device. - * This is a chance for devices which have the same IO and Mem Space to - * fork access to IO and Mem. - * - * Now, we assume there is one such device only (IGA 1682) but code below - * should work in cases when space of all such devices is less then 16MB. - */ -unsigned long pcic_alloc_io( unsigned long* addr ) -{ - unsigned long paddr = *addr; - unsigned long offset; - - if(pcic->pcic_mapped_io == 0) { - pcic->pcic_mapped_io = paddr & ~(PCI_SPACE_SIZE-1) ; - writeb((pcic->pcic_mapped_io>>24) & 0xff, - pcic->pcic_regs+PCI_PIBAR); - writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK, - pcic->pcic_regs+PCI_SIBAR); - writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE); - - } - if(paddr < pcic->pcic_mapped_io || - paddr >= pcic->pcic_mapped_io + 0x10000) - return 0; - offset = paddr - pcic->pcic_mapped_io; - *addr = pcic->pcic_io_phys + offset; - return pcic->pcic_io + offset; -} - -/* - * Stolen from both i386 and sparc64 branch + * Normally called from {do_}pci_scan_bus... */ -void __init pcibios_fixup(void) +void __init pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_dev *dev; - int i, has_io, has_mem; - unsigned short cmd; - struct linux_pbm_info* pbm = &pcic->pbm; + struct pci_dev *dev; + int i, has_io, has_mem; + unsigned short cmd; + struct linux_pcic *pcic; + /* struct linux_pbm_info* pbm = &pcic->pbm; */ int node; struct pcidev_cookie *pcp; - if(pcic == NULL) { - prom_printf("PCI: Error, PCIC not found.\n"); - prom_halt(); + if (!pcic0_up) { + printk("pcibios_fixup_bus: no PCIC\n"); + return; } + pcic = &pcic0; - for (dev = pci_devices; dev; dev=dev->next) { + /* + * Next crud is an equivalent of pbm = pcic_bus_to_pbm(bus); + */ + if (bus->number != 0) { + printk("pcibios_fixup_bus: nonzero bus 0x%x\n", bus->number); + return; + } + + for (dev = bus->devices; dev; dev = dev->sibling) { /* * Comment from i386 branch: * There are buggy BIOSes that forget to enable I/O and memory @@ -531,44 +649,42 @@ */ has_io = has_mem = 0; for(i=0; i<6; i++) { - unsigned long a = dev->base_address[i]; - if (a & PCI_BASE_ADDRESS_SPACE_IO) { + unsigned long f = dev->resource[i].flags; + if (f & IORESOURCE_IO) { has_io = 1; - } else if (a & PCI_BASE_ADDRESS_MEM_MASK) + } else if (f & IORESOURCE_MEM) has_mem = 1; } - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pcic_read_config_word(dev, PCI_COMMAND, &cmd); if (has_io && !(cmd & PCI_COMMAND_IO)) { printk("PCIC: Enabling I/O for device %02x:%02x\n", dev->bus->number, dev->devfn); cmd |= PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, cmd); + pcic_write_config_word(dev, PCI_COMMAND, cmd); } if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { printk("PCIC: Enabling memory for device %02x:%02x\n", dev->bus->number, dev->devfn); cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(dev, PCI_COMMAND, cmd); + pcic_write_config_word(dev, PCI_COMMAND, cmd); } - node = pdev_to_pnode(pbm, dev); + node = pdev_to_pnode(&pcic->pbm, dev); if(node == 0) node = -1; /* cookies */ pcp = pci_devcookie_alloc(); - pcp->pbm = pbm; + pcp->pbm = &pcic->pbm; pcp->prom_node = node; dev->sysdata = pcp; - /* memory mapping */ + /* fixing I/O to look like memory */ if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE) - pcic_map_pci_device(dev, node); + pcic_map_pci_device(pcic, dev, node); - pcic_fill_irq(dev, node); + pcic_fill_irq(pcic, dev, node); } - - ebus_init(); } /* @@ -577,6 +693,7 @@ unsigned int pcic_pin_to_irq(unsigned int pin, char *name) { + struct linux_pcic *pcic = &pcic0; unsigned int irq; unsigned int ivec; @@ -599,7 +716,7 @@ static void pcic_clear_clock_irq(void) { - pcic_timer_dummy = readl(pcic->pcic_regs+PCI_SYS_LIMIT); + pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); } static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs) @@ -613,6 +730,7 @@ void __init pci_time_init(void) { + struct linux_pcic *pcic = &pcic0; unsigned long v; int timer_irq, irq; @@ -620,9 +738,9 @@ /* A hack until do_gettimeofday prototype is moved to arch specific headers and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */ ((unsigned int *)do_gettimeofday)[0] = - 0x10800000 | ((((unsigned long)pci_do_gettimeofday - (unsigned long)do_gettimeofday) >> 2) & 0x003fffff); - ((unsigned int *)do_gettimeofday)[1] = - 0x01000000; + 0x10800000 | ((((unsigned long)pci_do_gettimeofday - + (unsigned long)do_gettimeofday) >> 2) & 0x003fffff); + ((unsigned int *)do_gettimeofday)[1] = 0x01000000; BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); @@ -650,7 +768,7 @@ * to have microsecond resolution and to avoid overflow */ unsigned long count = - readl(pcic->pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; + readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); if(test_bit(TIMER_BH, &bh_active)) @@ -705,103 +823,9 @@ } #endif -#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) - -int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned int v; - - pcibios_read_config_dword (bus, device_fn, where&~3, &v); - *value = 0xff & (v >> (8*(where & 3))); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_read_config_word (unsigned char bus, - unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned int v; - if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; - - pcibios_read_config_dword (bus, device_fn, where&~3, &v); - *value = 0xffff & (v >> (8*(where & 3))); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long flags; - - if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_and_cli(flags); -#if 0 - pcic_speculative = 1; - pcic_trapped = 0; -#endif - writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr); -#if 0 - nop(); - if (pcic_trapped) { - restore_flags(flags); - *value = ~0; - return PCIBIOS_SUCCESSFUL; - } -#endif - pcic_speculative = 2; - pcic_trapped = 0; - *value = readl(pcic->pcic_config_space_data + (where&4)); - nop(); - if (pcic_trapped) { - pcic_speculative = 0; - restore_flags(flags); - *value = ~0; - return PCIBIOS_SUCCESSFUL; - } - pcic_speculative = 0; - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_write_config_byte (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned char value) -{ - unsigned int v; - - pcibios_read_config_dword (bus, devfn, where&~3, &v); - v = (v & ~(0xff << (8*(where&3)))) | - ((0xff&(unsigned)value) << (8*(where&3))); - return pcibios_write_config_dword (bus, devfn, where&~3, v); -} - -int pcibios_write_config_word (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned short value) -{ - unsigned int v; - if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER; - - pcibios_read_config_dword (bus, devfn, where&~3, &v); - v = (v & ~(0xffff << (8*(where&3)))) | - ((0xffff&(unsigned)value) << (8*(where&3))); - return pcibios_write_config_dword (bus, devfn, where&~3, v); -} - -int pcibios_write_config_dword (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned int value) -{ - unsigned long flags; - - if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER; - - save_and_cli(flags); - writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr); - writel(value, pcic->pcic_config_space_data + (where&4)); - restore_flags(flags); - return PCIBIOS_SUCCESSFUL; -} - +/* + * Other archs parse arguments here. + */ char * __init pcibios_setup(char *str) { return str; @@ -831,6 +855,9 @@ } /* + * XXX Gleb wrote me that he needs this for X server (only). + * Since we successfuly use XF86_FBDev, we do not need these anymore. + * * Following code added to handle extra PCI-related system calls */ asmlinkage int sys_pciconfig_read(unsigned long bus, @@ -870,7 +897,7 @@ return err; } - + asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, @@ -936,7 +963,7 @@ mask = get_irqmask(irq_nr); save_and_cli(flags); - writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); + writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); restore_flags(flags); } @@ -946,7 +973,7 @@ mask = get_irqmask(irq_nr); save_and_cli(flags); - writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); + writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); restore_flags(flags); } @@ -965,12 +992,12 @@ */ static void pcic_disable_pil_irq(unsigned int pil) { - writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); + writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); } static void pcic_enable_pil_irq(unsigned int pil) { - writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); + writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); } void __init sun4m_pci_init_IRQ(void) @@ -985,8 +1012,9 @@ BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM); } -void __init pcibios_fixup_bus(struct pci_bus *bus) +int pcibios_assign_resource(struct pci_dev *pdev, int resource) { + return -ENXIO; } #endif diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.3.34/linux/arch/sparc/kernel/process.c Thu Nov 11 20:11:32 1999 +++ linux/arch/sparc/kernel/process.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.139 1999/08/14 03:51:14 anton Exp $ +/* $Id: process.c,v 1.141 1999/10/24 06:25:02 anton Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -55,7 +55,6 @@ { int ret = -EPERM; - lock_kernel(); if (current->pid != 0) goto out; @@ -100,7 +99,6 @@ } ret = 0; out: - unlock_kernel(); return ret; } @@ -188,9 +186,7 @@ rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]); } -#ifdef __SMP__ static spinlock_t sparc_backtrace_lock = SPIN_LOCK_UNLOCKED; -#endif void __show_backtrace(unsigned long fp) { @@ -702,37 +698,3 @@ "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; } - -/* - * These bracket the sleeping functions.. - */ -extern void scheduling_functions_start_here(void); -extern void scheduling_functions_end_here(void); -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long pc, fp, bias = 0; - unsigned long task_base = (unsigned long) p; - struct reg_window *rw; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - fp = p->thread.ksp + bias; - do { - /* Bogus frame pointer? */ - if (fp < (task_base + sizeof(struct task_struct)) || - fp >= (task_base + (2 * PAGE_SIZE))) - break; - rw = (struct reg_window *) fp; - pc = rw->ins[7]; - if (pc < first_sched || pc >= last_sched) - return pc; - fp = rw->ins[6] + bias; - } while (++count < 16); - return 0; -} -#undef last_sched -#undef first_sched diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.3.34/linux/arch/sparc/kernel/setup.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/setup.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.111 1999/09/10 10:40:24 davem Exp $ +/* $Id: setup.c,v 1.113 1999/12/16 14:37:35 anton Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -124,7 +124,9 @@ #ifdef CONFIG_SUN_CONSOLE static int console_fb = 0; #endif -static unsigned long memory_size __initdata = 0; + +/* Exported for mm/init.c:paging_init. */ +unsigned long cmdline_memory_size __initdata = 0; void kernel_enter_debugger(void) { @@ -238,13 +240,13 @@ * "mem=XXX[kKmM] overrides the PROM-reported * memory size. */ - memory_size = simple_strtoul(commands + 4, + cmdline_memory_size = simple_strtoul(commands + 4, &commands, 0); if (*commands == 'K' || *commands == 'k') { - memory_size <<= 10; + cmdline_memory_size <<= 10; commands++; } else if (*commands=='M' || *commands=='m') { - memory_size <<= 20; + cmdline_memory_size <<= 20; commands++; } } @@ -266,7 +268,7 @@ extern unsigned long start, end; extern void panic_setup(char *, int *); extern void srmmu_end_memory(unsigned long, unsigned long *); -extern unsigned long sun_serial_setup(unsigned long); +extern void sun_serial_setup(void); extern unsigned short root_flags; extern unsigned short root_dev; @@ -297,10 +299,10 @@ "PROM", prom_cons_write, 0, 0, 0, 0, 0, CON_PRINTBUFFER, 0, 0, 0 }; -void __init setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p) +void __init setup_arch(char **cmdline_p) { - int total, i, packed; + int i; + unsigned long highest_paddr; sparc_ttable = (struct tt_entry *) &start; @@ -329,27 +331,21 @@ strcpy(&cputypval, "ap+"); #endif printk("ARCH: "); - packed = 0; switch(sparc_cpu_model) { case sun4: printk("SUN4\n"); - packed = 0; break; case sun4c: printk("SUN4C\n"); - packed = 0; break; case sun4m: printk("SUN4M\n"); - packed = 1; break; case sun4d: printk("SUN4D\n"); - packed = 1; break; case sun4e: printk("SUN4E\n"); - packed = 0; break; case sun4u: printk("SUN4U\n"); @@ -357,7 +353,6 @@ case ap1000: register_console(&prom_console); printk("AP1000\n"); - packed = 1; break; default: printk("UNKNOWN!\n"); @@ -375,26 +370,20 @@ if (ARCH_SUN4C_SUN4) sun4c_probe_vac(); load_mmu(); - total = prom_probe_memory(); - *memory_start_p = PAGE_ALIGN(((unsigned long) &end)); + (void) prom_probe_memory(); - if(!packed) { - for(i=0; sp_banks[i].num_bytes != 0; i++) { - end_of_phys_memory = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - if (memory_size) { - if (end_of_phys_memory > memory_size) { - sp_banks[i].num_bytes -= - (end_of_phys_memory - memory_size); - end_of_phys_memory = memory_size; - sp_banks[++i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; - } - } - } - *memory_end_p = (end_of_phys_memory + KERNBASE); - } else - srmmu_end_memory(memory_size, memory_end_p); + phys_base = 0xffffffffUL; + highest_paddr = 0UL; + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long top; + + if (sp_banks[i].base_addr < phys_base) + phys_base = sp_banks[i].base_addr; + top = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + if (highest_paddr < top) + highest_paddr = top; + } if (!root_flags) root_mountflags &= ~MS_RDONLY; @@ -405,6 +394,7 @@ rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif #ifdef CONFIG_BLK_DEV_INITRD +// FIXME needs to do the new bootmem alloc stuff if (sparc_ramdisk_image) { initrd_start = sparc_ramdisk_image; if (initrd_start < KERNBASE) initrd_start += KERNBASE; @@ -434,7 +424,10 @@ prom_setsync(prom_sync_me); #ifdef CONFIG_SUN_SERIAL - *memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */ +#if 0 + /* XXX We can't do this until the bootmem allocator is working. */ + sun_serial_setup(); /* set this up ASAP */ +#endif #endif { #if !CONFIG_SUN_SERIAL @@ -489,11 +482,10 @@ breakpoint(); } - /* Due to stack alignment restrictions and assumptions... */ init_mm.mmap->vm_page_prot = PAGE_SHARED; - init_mm.mmap->vm_start = KERNBASE; - init_mm.mmap->vm_end = *memory_end_p; + init_mm.mmap->vm_start = PAGE_OFFSET; + init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr; init_mm.context = (unsigned long) NO_CONTEXT; init_task.thread.kregs = &fake_swapper_regs; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.3.34/linux/arch/sparc/kernel/signal.c Tue Nov 23 22:42:20 1999 +++ linux/arch/sparc/kernel/signal.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.95 1999/08/14 03:51:22 anton Exp $ +/* $Id: signal.c,v 1.98 1999/12/15 22:24:23 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.3.34/linux/arch/sparc/kernel/smp.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/smp.c Mon Dec 20 22:05:52 1999 @@ -163,7 +163,7 @@ local_flush_tlb_mm(mm); } else { xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm); - if(atomic_read(&mm->count) == 1 && current->mm == mm) + if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm) mm->cpu_vm_mask = (1 << smp_processor_id()); } } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.3.34/linux/arch/sparc/kernel/sparc_ksyms.c Thu Nov 11 20:11:32 1999 +++ linux/arch/sparc/kernel/sparc_ksyms.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.79 1999/09/10 10:40:28 davem Exp $ +/* $Id: sparc_ksyms.c,v 1.83 1999/11/19 04:11:28 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -50,8 +50,6 @@ extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); -extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); void _sigpause_common (unsigned int set, struct pt_regs *); extern void (*__copy_1page)(void *, const void *); extern void __memmove(void *, const void *, __kernel_size_t); @@ -65,6 +63,7 @@ extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); +extern int __ashldi3(int, int); extern int __lshrdi3(int, int); extern void dump_thread(struct pt_regs *, struct user *); @@ -157,11 +156,10 @@ EXPORT_SYMBOL(auxio_register); #endif EXPORT_SYMBOL(request_fast_irq); -EXPORT_SYMBOL(sparc_alloc_io); -EXPORT_SYMBOL(sparc_free_io); EXPORT_SYMBOL(io_remap_page_range); -EXPORT_SYMBOL(iounit_map_dma_init); -EXPORT_SYMBOL(iounit_map_dma_page); + /* P3: iounit_xxx may be needed, sun4d users */ +/* EXPORT_SYMBOL(iounit_map_dma_init); */ +/* EXPORT_SYMBOL(iounit_map_dma_page); */ /* Btfixup stuff cannot have versions, it would be complicated too much */ #ifndef __SMP__ @@ -180,19 +178,27 @@ EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_sgl)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_one)); -EXPORT_SYMBOL(_sparc_dvma_malloc); -EXPORT_SYMBOL(sun4c_unmapioaddr); -EXPORT_SYMBOL(srmmu_unmapioaddr); #if CONFIG_SBUS -EXPORT_SYMBOL(SBus_chain); +EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); +EXPORT_SYMBOL(sbus_set_sbus64); +EXPORT_SYMBOL(sbus_alloc_consistant); +EXPORT_SYMBOL(sbus_free_consistant); +EXPORT_SYMBOL(sbus_map_single); +EXPORT_SYMBOL(sbus_unmap_single); +EXPORT_SYMBOL(sbus_map_sg); +EXPORT_SYMBOL(sbus_unmap_sg); +EXPORT_SYMBOL(sbus_dma_sync_single); +EXPORT_SYMBOL(sbus_dma_sync_sg); +#endif +#if CONFIG_PCI +/* We do not have modular drivers for PCI devices yet. */ #endif /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(svr4_setcontext); EXPORT_SYMBOL(svr4_getcontext); EXPORT_SYMBOL(_sigpause_common); -EXPORT_SYMBOL(sunos_mmap); /* Should really be in linux/kernel/ksyms.c */ EXPORT_SYMBOL(dump_thread); @@ -215,9 +221,9 @@ EXPORT_SYMBOL(prom_feval); EXPORT_SYMBOL(prom_getbool); EXPORT_SYMBOL(prom_getstring); -EXPORT_SYMBOL(prom_apply_sbus_ranges); EXPORT_SYMBOL(prom_getint); EXPORT_SYMBOL(prom_getintdefault); +EXPORT_SYMBOL(prom_finddevice); EXPORT_SYMBOL(romvec); EXPORT_SYMBOL(__prom_getchild); EXPORT_SYMBOL(__prom_getsibling); @@ -271,6 +277,7 @@ EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(__ashrdi3); +EXPORT_SYMBOL_NOVERS(__ashldi3); EXPORT_SYMBOL_NOVERS(__lshrdi3); EXPORT_SYMBOL_DOT(rem); @@ -279,5 +286,3 @@ EXPORT_SYMBOL_DOT(umul); EXPORT_SYMBOL_DOT(div); EXPORT_SYMBOL_DOT(udiv); - -EXPORT_SYMBOL(get_wchan); diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c --- v2.3.34/linux/arch/sparc/kernel/sun4c_irq.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/sun4c_irq.c Mon Dec 20 22:05:52 1999 @@ -35,6 +35,11 @@ #include #include +#if 0 +static struct resource sun4c_timer_eb = { "sun4c_timer" }; +static struct resource sun4c_intr_eb = { "sun4c_intr" }; +#endif + /* Pointer to the interrupt enable byte * * Dave Redman (djhr@tadpole.co.uk) @@ -150,10 +155,9 @@ sun4c_timers = &sun4_timer; else #endif - sun4c_timers = sparc_alloc_io (SUN_TIMER_PHYSADDR, 0, - sizeof(struct sun4c_timer_info), - "timer", 0x0, 0x0); - + sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, + sizeof(struct sun4c_timer_info)); + /* Have the level 10 timer tick at 100HZ. We don't touch the * level 14 timer limit since we are letting the prom handle * them until we have a real console driver so L1-A works. @@ -190,13 +194,11 @@ int ie_node; if (ARCH_SUN4) { - interrupt_enable = - (char *) sparc_alloc_io(sun4_ie_physaddr, 0, - PAGE_SIZE, - "sun4c_interrupts", - 0x0, 0x0); + interrupt_enable = (char *) + ioremap(sun4_ie_physaddr, PAGE_SIZE); } else { - + struct resource phyres; + ie_node = prom_searchsiblings (prom_getchild(prom_root_node), "interrupt-enable"); if(ie_node == 0) @@ -204,11 +206,11 @@ /* Depending on the "address" property is bad news... */ prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs)); - interrupt_enable = - (char *) sparc_alloc_io(int_regs[0].phys_addr, 0, - int_regs[0].reg_size, - "sun4c_interrupts", - int_regs[0].which_io, 0x0); + memset(&phyres, 0, sizeof(struct resource)); + phyres.flags = int_regs[0].which_io; + phyres.start = int_regs[0].phys_addr; + interrupt_enable = (char *) sbus_ioremap(&phyres, 0, + int_regs[0].reg_size, "sun4c_intr"); } BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- v2.3.34/linux/arch/sparc/kernel/sun4d_irq.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/sun4d_irq.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.20 1999/09/10 10:40:30 davem Exp $ +/* $Id: sun4d_irq.c,v 1.23 1999/10/19 04:33:26 zaitcev Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * @@ -237,12 +237,12 @@ irq_exit(cpu, irq); } -unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq) +unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq) { int sbusl = pil_to_sbus[irq]; - + if (sbusl) - return ((sdev->my_bus->board + 1) << 5) + (sbusl << 2) + sdev->slot; + return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot; else return irq; } @@ -369,7 +369,7 @@ void __init sun4d_distribute_irqs(void) { #ifdef DISTRIBUTE_IRQS - struct linux_sbus *sbus; + struct sbus_bus *sbus; unsigned long sbus_serving_map; sbus_serving_map = cpu_present_map; @@ -401,7 +401,7 @@ set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3); } #else - struct linux_sbus *sbus; + struct sbus_bus *sbus; int cpuid = cpu_logical_map(1); if (cpuid == -1) @@ -436,16 +436,19 @@ int irq; extern struct prom_cpuinfo linux_cpus[NR_CPUS]; int cpu; + struct resource r; /* Map the User Timer registers. */ + memset(&r, 0, sizeof(r)); #ifdef __SMP__ - sun4d_timers = sparc_alloc_io(CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT, 0, - PAGE_SIZE, "user timer", 0xf, 0x0); + r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT; #else - sun4d_timers = sparc_alloc_io(CSR_BASE(0)+BW_TIMER_LIMIT, 0, - PAGE_SIZE, "user timer", 0xf, 0x0); + r.start = CSR_BASE(0)+BW_TIMER_LIMIT; #endif - + r.flags = 0xf; + sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0, + PAGE_SIZE, "user timer"); + sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4d_timers->l10_cur_count; master_l10_limit = &sun4d_timers->l10_timer_limit; @@ -494,7 +497,7 @@ void __init sun4d_init_sbi_irq(void) { - struct linux_sbus *sbus; + struct sbus_bus *sbus; unsigned mask; nsbi = 0; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- v2.3.34/linux/arch/sparc/kernel/sun4d_smp.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/sun4d_smp.c Mon Dec 20 22:05:52 1999 @@ -99,6 +99,14 @@ local_flush_cache_all(); local_flush_tlb_all(); + /* + * Unblock the master CPU _only_ when the scheduler state + * of all secondary CPUs will be up-to-date, so after + * the SMP initialization the master will be just allowed + * to call the scheduler code. + */ + init_idle(); + /* Get our local ticker going. */ smp_setup_percpu_timer(); diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c --- v2.3.34/linux/arch/sparc/kernel/sun4m_irq.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/sun4m_irq.c Mon Dec 20 22:05:52 1999 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -225,6 +226,7 @@ int reg_count, irq, cpu; struct linux_prom_registers cnt_regs[PROMREG_MAX]; int obio_node, cnt_node; + struct resource r; cnt_node = 0; if((obio_node = @@ -250,18 +252,19 @@ cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; } - + + memset((char*)&r, 0, sizeof(struct resource)); /* Map the per-cpu Counter registers. */ - sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0, - PAGE_SIZE*SUN4M_NCPUS, "counters_percpu", - cnt_regs[0].which_io, 0x0); - + r.flags = cnt_regs[0].which_io; + r.start = cnt_regs[0].phys_addr; + sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, + PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); /* Map the system Counter register. */ - sparc_alloc_io(cnt_regs[4].phys_addr, 0, - cnt_regs[4].reg_size, - "counters_system", - cnt_regs[4].which_io, 0x0); - + /* XXX Here we expect consequent calls to yeld adjusent maps. */ + r.flags = cnt_regs[4].which_io; + r.start = cnt_regs[4].phys_addr; + sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); + sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; master_l10_limit = &sun4m_timers->l10_timer_limit; @@ -308,6 +311,7 @@ int ie_node,i; struct linux_prom_registers int_regs[PROMREG_MAX]; int num_regs; + struct resource r; __cli(); if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || @@ -332,16 +336,18 @@ int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; } + memset((char *)&r, 0, sizeof(struct resource)); /* Map the interrupt registers for all possible cpus. */ - sun4m_interrupts = sparc_alloc_io(int_regs[0].phys_addr, 0, - PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu", - int_regs[0].which_io, 0x0); - + r.flags = int_regs[0].which_io; + r.start = int_regs[0].phys_addr; + sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0, + PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); + /* Map the system interrupt control registers. */ - sparc_alloc_io(int_regs[4].phys_addr, 0, - int_regs[4].reg_size, "interrupts_system", - int_regs[4].which_io, 0x0); - + r.flags = int_regs[4].which_io; + r.start = int_regs[4].phys_addr; + sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + sun4m_interrupts->set = ~SUN4M_INT_MASKALL; for (i=0; icpu_intregs[i].clear = ~0x17fff; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.3.34/linux/arch/sparc/kernel/sun4m_smp.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/kernel/sun4m_smp.c Mon Dec 20 22:05:52 1999 @@ -93,6 +93,14 @@ local_flush_cache_all(); local_flush_tlb_all(); + /* + * Unblock the master CPU _only_ when the scheduler state + * of all secondary CPUs will be up-to-date, so after + * the SMP initialization the master will be just allowed + * to call the scheduler code. + */ + init_idle(); + /* Allow master to continue. */ swap((unsigned long *)&cpu_callin_map[cpuid], 1); local_flush_cache_all(); diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_solaris.c linux/arch/sparc/kernel/sys_solaris.c --- v2.3.34/linux/arch/sparc/kernel/sys_solaris.c Sun Jan 26 02:07:08 1997 +++ linux/arch/sparc/kernel/sys_solaris.c Mon Dec 20 22:05:52 1999 @@ -4,6 +4,7 @@ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) */ +#include #include #include #include @@ -24,7 +25,7 @@ current->exec_domain = lookup_exec_domain(PER_SVR4); if (current->exec_domain && current->exec_domain->handler){ - current->exec_domain->handler (regs); + current->exec_domain->handler (0, regs); /* What is going on here? Why do we do this? */ @@ -39,3 +40,16 @@ unlock_kernel(); return ret; } + +#ifndef CONFIG_SUNOS_EMUL +asmlinkage int +do_sunos_syscall (struct pt_regs *regs) +{ + static int cnt = 0; + if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n"); + lock_kernel(); + force_sig (SIGSEGV, current); + unlock_kernel(); + return 0; +} +#endif diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c --- v2.3.34/linux/arch/sparc/kernel/sys_sparc.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/sys_sparc.c Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.53 1999/08/14 03:51:25 anton Exp $ +/* $Id: sys_sparc.c,v 1.55 1999/12/21 14:09:09 jj Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -176,26 +176,34 @@ } /* Linux version of mmap */ -asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, +static unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, - unsigned long off) + unsigned long pgoff) { struct file * file = NULL; unsigned long retval = -EBADF; - down(¤t->mm->mmap_sem); - lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } + + down(¤t->mm->mmap_sem); + lock_kernel(); retval = -ENOMEM; len = PAGE_ALIGN(len); - if(!(flags & MAP_FIXED) && !addr) { - addr = get_unmapped_area(addr, len); + if(!(flags & MAP_FIXED) && + (!addr || (ARCH_SUN4C_SUN4 && + (addr >= 0x20000000 && addr < 0xe0000000)))) { + addr = get_unmapped_area(0, len); if(!addr) goto out_putf; + if (ARCH_SUN4C_SUN4 && + (addr >= 0x20000000 && addr < 0xe0000000)) { + retval = -EINVAL; + goto out_putf; + } } /* See asm-sparc/uaccess.h */ @@ -203,24 +211,30 @@ if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE))) goto out_putf; - if(ARCH_SUN4C_SUN4) { - if(((addr >= 0x20000000) && (addr < 0xe0000000))) { - /* VM hole */ - retval = current->mm->brk; - goto out_putf; - } - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - retval = do_mmap(file, addr, len, prot, flags, off); + retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); out_putf: + unlock_kernel(); + up(¤t->mm->mmap_sem); if (file) fput(file); out: - unlock_kernel(); - up(¤t->mm->mmap_sem); return retval; +} + +asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + +asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long off) +{ + return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } /* we come to here via sys_nis_syscall so it can setup the regs argument */ diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.34/linux/arch/sparc/kernel/sys_sunos.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/sys_sunos.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.104 1999/08/31 12:30:50 anton Exp $ +/* $Id: sys_sunos.c,v 1.106 1999/12/16 11:57:27 anton Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -85,10 +85,17 @@ } retval = -ENOMEM; - if(!(flags & MAP_FIXED) && !addr) { - addr = get_unmapped_area(addr, len); + if(!(flags & MAP_FIXED) && + (!addr || (ARCH_SUN4C_SUN4 && + (addr >= 0x20000000 && addr < 0xe0000000)))) { + addr = get_unmapped_area(0, len); if(!addr) goto out_putf; + if (ARCH_SUN4C_SUN4 && + (addr >= 0x20000000 && addr < 0xe0000000)) { + retval = -EINVAL; + goto out_putf; + } } /* If this is ld.so or a shared library doing an mmap * of /dev/zero, transform it into an anonymous mapping. @@ -111,13 +118,6 @@ if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE))) goto out_putf; - if(ARCH_SUN4C_SUN4) { - if(((addr >= 0x20000000) && (addr < 0xe0000000))) { - retval = current->mm->brk; - goto out_putf; - } - } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, off); if(!ret_type) @@ -195,7 +195,7 @@ * simple, it hopefully works in most obvious cases.. Easy to * fool it, but this should catch most mistakes. */ - freepages = atomic_read(&buffermem) >> PAGE_SHIFT; + freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT; freepages += atomic_read(&page_cache_size); freepages >>= 1; freepages += nr_free_pages; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S --- v2.3.34/linux/arch/sparc/kernel/systbls.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/systbls.S Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.84 1999/08/14 03:51:29 anton Exp $ +/* $Id: systbls.S,v 1.88 1999/12/21 14:09:06 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -9,6 +9,8 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ +#include + .data .align 4 @@ -27,12 +29,12 @@ /*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall /*45*/ .long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl -/*55*/ .long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve -/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize +/*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve +/*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize /*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall /*70*/ .long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect -/*75*/ .long sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups -/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall +/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups +/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64 /*85*/ .long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall /*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall @@ -42,8 +44,8 @@ /*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod /*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate -/*130*/ .long sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall +/*130*/ .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall +/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64 /*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit /*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write /*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall @@ -70,6 +72,7 @@ /*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl /*255*/ .long sys_aplib, sys_nis_syscall +#ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ .align 4 @@ -162,3 +165,5 @@ .long sunos_nosys, sunos_nosys /*250*/ .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sys_aplib + +#endif diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c --- v2.3.34/linux/arch/sparc/kernel/time.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/time.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.46 1999/08/31 13:11:26 anton Exp $ +/* $Id: time.c,v 1.49 1999/11/17 07:34:07 zaitcev Exp $ * linux/arch/sparc/kernel/time.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include extern rwlock_t xtime_lock; @@ -207,13 +209,14 @@ { #ifdef CONFIG_SUN4 int temp; + struct resource r; + memset(&r, 0, sizeof(r)); if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) { sp_clock_typ = MSTK48T02; - mstk48t02_regs = (unsigned long) - sparc_alloc_io(sun4_clock_physaddr, 0, - sizeof(struct mostek48t02), - "clock", 0x0, 0x0); + r.start = sun4_clock_physaddr; + mstk48t02_regs = sbus_ioremap(&r, 0, + sizeof(struct mostek48t02), 0); mstk48t08_regs = 0; /* To catch weirdness */ intersil_clock = 0; /* just in case */ @@ -224,10 +227,9 @@ /* intersil setup code */ printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr); sp_clock_typ = INTERSIL; + r.start = sun4_clock_physaddr; intersil_clock = (struct intersil *) - sparc_alloc_io(sun4_clock_physaddr, 0, - sizeof(*intersil_clock), - "clock", 0x0, 0x0); + sparc_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); mstk48t02_regs = 0; /* just be sure */ mstk48t08_regs = 0; /* ditto */ /* initialise the clock */ @@ -256,8 +258,10 @@ struct linux_prom_registers clk_reg[2]; char model[128]; register int node, cpuunit, bootbus; + struct resource r; cpuunit = bootbus = 0; + memset(&r, 0, sizeof(r)); /* Determine the correct starting PROM node for the probe. */ node = prom_getchild(prom_root_node); @@ -297,10 +301,10 @@ else prom_apply_obio_ranges(clk_reg, 1); /* Map the clock register io area read-only */ - mstk48t02_regs = (unsigned long) - sparc_alloc_io(clk_reg[0].phys_addr, - (void *) 0, sizeof(struct mostek48t02), - "clock", clk_reg[0].which_io, 0x0); + r.flags = clk_reg[0].which_io; + r.start = clk_reg[0].phys_addr; + mstk48t02_regs = sbus_ioremap(&r, 0, + sizeof(struct mostek48t02), "mk48t02"); mstk48t08_regs = 0; /* To catch weirdness */ } else if (strcmp(model, "mk48t08") == 0) { sp_clock_typ = MSTK48T08; @@ -314,10 +318,11 @@ else prom_apply_obio_ranges(clk_reg, 1); /* Map the clock register io area read-only */ - mstk48t08_regs = (struct mostek48t08 *) - sparc_alloc_io(clk_reg[0].phys_addr, - (void *) 0, sizeof(*mstk48t08_regs), - "clock", clk_reg[0].which_io, 0x0); + /* XXX r/o attribute is somewhere in r.flags */ + r.flags = clk_reg[0].which_io; + r.start = clk_reg[0].phys_addr; + mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0, + sizeof(struct mostek48t08), "mk48t08"); mstk48t02_regs = (unsigned long)&mstk48t08_regs->regs; } else { @@ -420,7 +425,7 @@ { #ifdef CONFIG_PCI extern void pci_time_init(void); - if (pci_present()) { + if (pcic_present()) { pci_time_init(); return; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile --- v2.3.34/linux/arch/sparc/lib/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc/lib/Makefile Mon Dec 20 22:05:52 1999 @@ -1,11 +1,12 @@ -# $Id: Makefile,v 1.28 1999/03/21 06:37:44 davem Exp $ +# $Id: Makefile,v 1.30 1999/12/21 04:02:18 davem Exp $ # Makefile for Sparc library files.. # OBJS = mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ - copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o + copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \ + ashldi3.o ifdef CONFIG_SMP OBJS += irqlock.o @@ -88,6 +89,9 @@ ashrdi3.o: ashrdi3.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o ashrdi3.o ashrdi3.S + +ashldi3.o: ashldi3.S + $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o ashldi3.o ashldi3.S lshrdi3.o: lshrdi3.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o lshrdi3.o lshrdi3.S diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/ashldi3.S linux/arch/sparc/lib/ashldi3.S --- v2.3.34/linux/arch/sparc/lib/ashldi3.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc/lib/ashldi3.S Mon Dec 20 22:05:52 1999 @@ -0,0 +1,36 @@ +/* $Id: ashldi3.S,v 1.2 1999/11/19 04:11:46 davem Exp $ + * ashldi3.S: GCC emits these for certain drivers playing + * with long longs. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +#include + + .text + .align 4 + .globl C_LABEL(__ashldi3) +C_LABEL(__ashldi3): + cmp %o2, 0 + be 9f + mov 0x20, %g2 + + sub %g2, %o2, %g2 + cmp %g2, 0 + bg 7f + sll %o0, %o2, %g3 + + neg %g2 + clr %o5 + b 8f + sll %o1, %g2, %o4 +7: + srl %o1, %g2, %g2 + sll %o1, %o2, %o5 + or %g3, %g2, %o4 +8: + mov %o4, %o0 + mov %o5, %o1 +9: + retl + nop diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/ashrdi3.S linux/arch/sparc/lib/ashrdi3.S --- v2.3.34/linux/arch/sparc/lib/ashrdi3.S Sat Nov 9 00:12:00 1996 +++ linux/arch/sparc/lib/ashrdi3.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ashrdi3.S,v 1.3 1996/09/07 23:18:10 davem Exp $ +/* $Id: ashrdi3.S,v 1.4 1999/11/19 04:11:49 davem Exp $ * ashrdi3.S: The filesystem code creates all kinds of references to * this little routine on the sparc with gcc. * @@ -7,7 +7,9 @@ #include - .globl C_LABEL(__ashrdi3) + .text + .align 4 + .globl C_LABEL(__ashrdi3) C_LABEL(__ashrdi3): tst %o2 be 3f diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/strlen_user.S linux/arch/sparc/lib/strlen_user.S --- v2.3.34/linux/arch/sparc/lib/strlen_user.S Fri Dec 13 01:37:31 1996 +++ linux/arch/sparc/lib/strlen_user.S Mon Dec 20 22:05:52 1999 @@ -47,8 +47,11 @@ mov 3, %o0 .align 4 - .global C_LABEL(__strlen_user) + .global C_LABEL(__strlen_user), C_LABEL(__strnlen_user) C_LABEL(__strlen_user): + sethi %hi(32768), %o1 +C_LABEL(__strnlen_user): + mov %o1, %g1 mov %o0, %o1 andcc %o0, 3, %g0 bne 10b @@ -63,11 +66,16 @@ 2: sub %o5, %o2, %o4 andcc %o4, %o3, %g0 - be 13b + bne 82f add %o0, 4, %o0 + sub %o0, %o1, %g2 +81: cmp %g2, %g1 + blu 13b + mov %o0, %o4 + ba,a 1f /* Check every byte. */ - srl %o5, 24, %g5 +82: srl %o5, 24, %g5 andcc %g5, 0xff, %g0 be 1f add %o0, -3, %o4 @@ -80,9 +88,9 @@ be 1f add %o4, 1, %o4 andcc %o5, 0xff, %g0 - bne,a 2b -14: - ld [%o0], %o5 + bne 81b + sub %o0, %o1, %g2 + add %o4, 1, %o4 1: retl @@ -101,4 +109,3 @@ .word 11b, 9b .word 12b, 9b .word 13b, 9b - .word 14b, 9b diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile --- v2.3.34/linux/arch/sparc/mm/Makefile Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.34 1999/08/14 03:51:42 anton Exp $ +# $Id: Makefile,v 1.35 1999/10/09 05:32:01 zaitcev Exp $ # Makefile for the linux Sparc-specific parts of the memory manager. # # Note! Dependencies are done automagically by 'make dep', which also @@ -15,7 +15,7 @@ ifeq ($(CONFIG_SUN4),y) O_OBJS += nosrmmu.o else -O_OBJS += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o +O_OBJS += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o endif ifdef CONFIG_SMP O_OBJS += nosun4c.o @@ -33,3 +33,6 @@ tsunami.o: tsunami.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S + +swift.o: swift.S + $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o swift.o swift.S diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c --- v2.3.34/linux/arch/sparc/mm/fault.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/fault.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.107 1999/08/14 03:51:46 anton Exp $ +/* $Id: fault.c,v 1.111 1999/10/24 13:45:59 anton Exp $ * fault.c: Page fault handlers for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -146,10 +146,11 @@ printk(KERN_ALERT "Unable to handle kernel paging request " "at virtual address %08lx\n", address); } - printk(KERN_ALERT "tsk->mm->context = %08lx\n", - (unsigned long) tsk->mm->context); - printk(KERN_ALERT "tsk->mm->pgd = %08lx\n", - (unsigned long) tsk->mm->pgd); + printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n", + (tsk->mm ? tsk->mm->context : tsk->active_mm->context)); + printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n", + (tsk->mm ? (unsigned long) tsk->mm->pgd : + (unsigned long) tsk->active_mm->pgd)); die_if_kernel("Oops", regs); } @@ -309,8 +310,18 @@ pgd_t *pgdp; pte_t *ptep; - if (text_fault) + if (text_fault) { address = regs->pc; + } else if (!write && + !(regs->psr & PSR_PS)) { + unsigned int insn, *ip; + + ip = (unsigned int *)regs->pc; + if (! get_user(insn, ip)) { + if ((insn & 0xc1680000) == 0xc0680000) + write = 1; + } + } pgdp = sun4c_pgd_offset(mm, address); ptep = sun4c_pte_offset((pmd_t *) pgdp, address); @@ -319,28 +330,36 @@ if (write) { if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) { + unsigned long flags; *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED | _SUN4C_PAGE_MODIFIED | _SUN4C_PAGE_VALID | _SUN4C_PAGE_DIRTY); + save_and_cli(flags); if (sun4c_get_segmap(address) != invalid_segment) { sun4c_put_pte(address, pte_val(*ptep)); + restore_flags(flags); return; } + restore_flags(flags); } } else { if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) { + unsigned long flags; *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED | _SUN4C_PAGE_VALID); + save_and_cli(flags); if (sun4c_get_segmap(address) != invalid_segment) { sun4c_put_pte(address, pte_val(*ptep)); + restore_flags(flags); return; } + restore_flags(flags); } } } @@ -415,31 +434,25 @@ { unsigned long sp; - lock_kernel(); sp = current->thread.rwbuf_stkptrs[0]; if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) force_user_fault(sp + 0x38, 1); force_user_fault(sp, 1); - unlock_kernel(); } void window_underflow_fault(unsigned long sp) { - lock_kernel(); if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) force_user_fault(sp + 0x38, 0); force_user_fault(sp, 0); - unlock_kernel(); } void window_ret_fault(struct pt_regs *regs) { unsigned long sp; - lock_kernel(); sp = regs->u_regs[UREG_FP]; if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK)) force_user_fault(sp + 0x38, 0); force_user_fault(sp, 0); - unlock_kernel(); } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/generic.c linux/arch/sparc/mm/generic.c --- v2.3.34/linux/arch/sparc/mm/generic.c Tue Dec 7 09:32:42 1999 +++ linux/arch/sparc/mm/generic.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: generic.c,v 1.6 1998/10/27 23:28:00 davem Exp $ +/* $Id: generic.c,v 1.8 1999/12/20 05:01:49 davem Exp $ * generic.c: Generic Sparc mm routines that are not dependent upon * MMU type but are Sparc specific. * @@ -12,43 +12,22 @@ #include #include - -/* Allocate a block of RAM which is aligned to its size. - * This procedure can be used until the call to mem_init(). - */ -void *sparc_init_alloc(unsigned long *kbrk, unsigned long size) -{ - unsigned long mask = size - 1; - unsigned long ret; - - if(!size) - return 0x0; - if(size & mask) { - prom_printf("panic: sparc_init_alloc botch\n"); - prom_halt(); - } - ret = (*kbrk + mask) & ~mask; - *kbrk = ret + size; - memset((void*) ret, 0, size); - return (void*) ret; -} - static inline void forget_pte(pte_t page) { if (pte_none(page)) return; if (pte_present(page)) { - unsigned long addr = pte_page(page); - if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr))) + unsigned long nr = pte_pagenr(page); + if (nr >= max_mapnr || PageReserved(mem_map+nr)) return; /* * free_page() used to be able to clear swap cache * entries. We may now have to do it manually. */ - free_page_and_swap_cache(addr); + free_page_and_swap_cache(mem_map+nr); return; } - swap_free(pte_val(page)); + swap_free(page); } /* Remap IO memory, the same way as remap_page_range(), but use diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.3.34/linux/arch/sparc/mm/init.c Fri Oct 22 13:21:46 1999 +++ linux/arch/sparc/mm/init.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.69 1999/09/06 22:56:17 ecd Exp $ +/* $Id: init.c,v 1.71 1999/12/16 12:58:33 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -22,6 +22,8 @@ #include #endif #include +#include +#include #include #include @@ -30,22 +32,21 @@ #include #include -/* Turn this off if you suspect some place in some physical memory hole - might get into page tables (something would be broken very much). */ - -#define FREE_UNUSED_MEM_MAP - extern void show_net_buffers(void); unsigned long *sparc_valid_addr_bitmap; +unsigned long phys_base; + struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; unsigned long sparc_unmapped_base; struct pgtable_cache_struct pgt_quicklists; /* References to section boundaries */ -extern char __init_begin, __init_end, etext; +extern char __init_begin, __init_end, _start, _end, etext , edata; + +static unsigned long totalram_pages = 0; /* * BAD_PAGE is the page that is used for page faults when linux @@ -62,50 +63,31 @@ */ pte_t *__bad_pagetable(void) { - memset((void *) EMPTY_PGT, 0, PAGE_SIZE); - return (pte_t *) EMPTY_PGT; + memset((void *) &empty_bad_page_table, 0, PAGE_SIZE); + return (pte_t *) &empty_bad_page_table; } pte_t __bad_page(void) { - memset((void *) EMPTY_PGE, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED)); + memset((void *) &empty_bad_page, 0, PAGE_SIZE); + return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) + - PAGE_OFFSET + phys_base), + PAGE_SHARED)); } void show_mem(void) { - int free = 0,total = 0,reserved = 0; - int shared = 0, cached = 0; - struct page *page, *end; - - printk("\nMem-info:\n"); + printk("Mem-info:\n"); show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - for (page = mem_map, end = mem_map + max_mapnr; - page < end; page++) { - if (PageSkip(page)) { - if (page->next_hash < page) - break; - page = page->next_hash; - } - total++; - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (!atomic_read(&page->count)) - free++; - else - shared += atomic_read(&page->count) - 1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); - printk("%ld page tables cached\n",pgtable_cache_size); + printk("Free swap: %6dkB\n", + nr_swap_pages << (PAGE_SHIFT-10)); + printk("%ld pages of RAM\n", totalram_pages); + printk("%d free pages\n", nr_free_pages); + printk("%ld pages in page table cache\n",pgtable_cache_size); +#ifndef __SMP__ if (sparc_cpu_model == sun4m || sparc_cpu_model == sun4d) - printk("%ld page dirs cached\n", pgd_cache_size); + printk("%ld entries in page dir cache\n",pgd_cache_size); +#endif show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -114,12 +96,12 @@ extern pgprot_t protection_map[16]; -unsigned long __init sparc_context_init(unsigned long start_mem, int numctx) +void __init sparc_context_init(int numctx) { int ctx; - ctx_list_pool = (struct ctx_list *) start_mem; - start_mem += (numctx * sizeof(struct ctx_list)); + ctx_list_pool = __alloc_bootmem(numctx * sizeof(struct ctx_list), SMP_CACHE_BYTES, 0UL); + for(ctx = 0; ctx < numctx; ctx++) { struct ctx_list *clist; @@ -131,7 +113,98 @@ ctx_used.next = ctx_used.prev = &ctx_used; for(ctx = 0; ctx < numctx; ctx++) add_to_free_ctxlist(ctx_list_pool + ctx); - return start_mem; +} + +#undef DEBUG_BOOTMEM + +extern unsigned long cmdline_memory_size; + +unsigned long __init bootmem_init(void) +{ + unsigned long bootmap_size, start_pfn, end_pfn; + unsigned long end_of_phys_memory = 0UL; + int i; + + /* XXX It is a bit ambiguous here, whether we should + * XXX treat the user specified mem=xxx as total wanted + * XXX physical memory, or as a limit to the upper + * XXX physical address we allow. For now it is the + * XXX latter. -DaveM + */ +#ifdef DEBUG_BOOTMEM + prom_printf("bootmem_init: Scan sp_banks, "); +#endif + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + end_of_phys_memory = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + if (cmdline_memory_size) { + if (end_of_phys_memory > cmdline_memory_size) { + if (cmdline_memory_size > sp_banks[i].base_addr) { + end_of_phys_memory = + sp_banks[i-1].base_addr + + sp_banks[i-1].num_bytes; + sp_banks[i].base_addr = 0xdeadbeef; + sp_banks[i].num_bytes = 0; + } else { + sp_banks[i].num_bytes -= + (end_of_phys_memory - + cmdline_memory_size); + end_of_phys_memory = cmdline_memory_size; + sp_banks[++i].base_addr = 0xdeadbeef; + sp_banks[i].num_bytes = 0; + } + break; + } + } + } + + /* Start with page aligned address of last symbol in kernel + * image. + */ + start_pfn = PAGE_ALIGN((unsigned long) &_end) - PAGE_OFFSET; + + /* Adjust up to the physical address where the kernel begins. */ + start_pfn += phys_base; + + /* Now shift down to get the real physical page frame number. */ + start_pfn >>= PAGE_SHIFT; + + end_pfn = end_of_phys_memory >> PAGE_SHIFT; + + /* Initialize the boot-time allocator. */ +#ifdef DEBUG_BOOTMEM + prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n", + start_pfn, end_pfn); +#endif + bootmap_size = init_bootmem(start_pfn, end_pfn); + + /* Now register the available physical memory with the + * allocator. + */ + for (i = 0; sp_banks[i].num_bytes != 0; i++) { +#ifdef DEBUG_BOOTMEM + prom_printf("free_bootmem: base[%lx] size[%lx]\n", + sp_banks[i].base_addr, + sp_banks[i].num_bytes); +#endif + free_bootmem(sp_banks[i].base_addr, + sp_banks[i].num_bytes); + } + + /* Reserve the kernel text/data/bss and the bootmem bitmap. */ +#ifdef DEBUG_BOOTMEM + prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", + phys_base, + (((start_pfn << PAGE_SHIFT) + + bootmap_size) - phys_base)); +#endif + reserve_bootmem(phys_base, (((start_pfn << PAGE_SHIFT) + + bootmap_size) - phys_base)); + +#ifdef DEBUG_BOOTMEM + prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn); +#endif + return end_pfn; } /* @@ -139,31 +212,32 @@ * init routine based upon the Sun model type on the Sparc. * */ -extern unsigned long sun4c_paging_init(unsigned long, unsigned long); -extern unsigned long srmmu_paging_init(unsigned long, unsigned long); -extern unsigned long device_scan(unsigned long); +extern void sun4c_paging_init(void); +extern void srmmu_paging_init(void); +extern void device_scan(void); + +unsigned long last_valid_pfn; -unsigned long __init -paging_init(unsigned long start_mem, unsigned long end_mem) +void __init paging_init(void) { switch(sparc_cpu_model) { case sun4c: case sun4e: case sun4: - start_mem = sun4c_paging_init(start_mem, end_mem); + sun4c_paging_init(); sparc_unmapped_base = 0xe0000000; BTFIXUPSET_SETHI(sparc_unmapped_base, 0xe0000000); break; case sun4m: case sun4d: - start_mem = srmmu_paging_init(start_mem, end_mem); + srmmu_paging_init(); sparc_unmapped_base = 0x50000000; BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000); break; case ap1000: #if CONFIG_AP1000 - start_mem = apmmu_paging_init(start_mem, end_mem); + apmmu_paging_init(); sparc_unmapped_base = 0x50000000; BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000); break; @@ -194,74 +268,121 @@ protection_map[14] = PAGE_SHARED; protection_map[15] = PAGE_SHARED; btfixup(); - return device_scan(start_mem); + device_scan(); } struct cache_palias *sparc_aliases; -extern void srmmu_frob_mem_map(unsigned long); +static void __init taint_real_pages(void) +{ + int i; -int physmem_mapped_contig __initdata = 1; + for (i = 0; sp_banks[i].num_bytes; i++) { + unsigned long start, end; -static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem) + start = sp_banks[i].base_addr; + end = start + + sp_banks[i].num_bytes; + while (start < end) { + set_bit (start >> 20, + sparc_valid_addr_bitmap); + start += PAGE_SIZE; + } + } +} + +void __init free_mem_map_range(struct page *first, struct page *last) { - unsigned long addr, tmp2 = 0; + first = (struct page *) PAGE_ALIGN((unsigned long)first); + last = (struct page *) ((unsigned long)last & PAGE_MASK); +#ifdef DEBUG_BOOTMEM + prom_printf("[%p,%p] ", first, last); +#endif + while (first < last) { + ClearPageReserved(mem_map + MAP_NR(first)); + set_page_count(mem_map + MAP_NR(first), 1); + free_page((unsigned long)first); + totalram_pages++; + num_physpages++; - if(physmem_mapped_contig) { - for(addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) { - if(addr >= KERNBASE && addr < start_mem) - addr = start_mem; - for(tmp2=0; sp_banks[tmp2].num_bytes != 0; tmp2++) { - unsigned long phys_addr = (addr - PAGE_OFFSET); - unsigned long base = sp_banks[tmp2].base_addr; - unsigned long limit = base + sp_banks[tmp2].num_bytes; - - if((phys_addr >= base) && (phys_addr < limit) && - ((phys_addr + PAGE_SIZE) < limit)) { - mem_map[MAP_NR(addr)].flags &= ~(1<> 8, sparc_valid_addr_bitmap); - } - } - } - } else { - if((sparc_cpu_model == sun4m) || (sparc_cpu_model == sun4d)) { - srmmu_frob_mem_map(start_mem); + first = (struct page *)((unsigned long)first + PAGE_SIZE); + } +} + +/* Walk through holes in sp_banks regions, if the mem_map array + * areas representing those holes consume a page or more, free + * up such pages. This helps a lot on machines where physical + * ram is configured such that it begins at some hugh value. + * + * The sp_banks array is sorted by base address. + */ +void __init free_unused_mem_map(void) +{ + int i; + +#ifdef DEBUG_BOOTMEM + prom_printf("free_unused_mem_map: "); +#endif + for (i = 0; sp_banks[i].num_bytes; i++) { + if (i == 0) { + struct page *first, *last; + + first = mem_map; + last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; + free_mem_map_range(first, last); } else { - for(addr = start_mem; addr < end_mem; addr += PAGE_SIZE) { - mem_map[MAP_NR(addr)].flags &= ~(1<> 8, sparc_valid_addr_bitmap); + struct page *first, *last; + unsigned long prev_end; + + prev_end = sp_banks[i-1].base_addr + + sp_banks[i-1].num_bytes; + prev_end = PAGE_ALIGN(prev_end); + first = &mem_map[prev_end >> PAGE_SHIFT]; + last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; + + free_mem_map_range(first, last); + + if (!sp_banks[i+1].num_bytes) { + prev_end = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + first = &mem_map[prev_end >> PAGE_SHIFT]; + last = &mem_map[last_valid_pfn]; + free_mem_map_range(first, last); } } } +#ifdef DEBUG_BOOTMEM + prom_printf("\n"); +#endif } -void __init mem_init(unsigned long start_mem, unsigned long end_mem) +void __init mem_init(void) { int codepages = 0; int datapages = 0; int initpages = 0; int i; - unsigned long addr; - struct page *page, *end; + unsigned long addr, last; /* Saves us work later. */ memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE); - end_mem &= PAGE_MASK; - max_mapnr = MAP_NR(end_mem); - high_memory = (void *) end_mem; - - sparc_valid_addr_bitmap = (unsigned long *)start_mem; - i = max_mapnr >> (8 + 5); + i = last_valid_pfn >> (8 + 5); i += 1; - memset(sparc_valid_addr_bitmap, 0, i << 2); - start_mem += i << 2; - start_mem = PAGE_ALIGN(start_mem); - num_physpages = 0; + sparc_valid_addr_bitmap = (unsigned long *) + __alloc_bootmem(i << 2, SMP_CACHE_BYTES, 0UL); + + if (sparc_valid_addr_bitmap == NULL) { + prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); + prom_halt(); + } + memset(sparc_valid_addr_bitmap, 0, i << 2); addr = KERNBASE; - while(addr < start_mem) { + last = PAGE_ALIGN((unsigned long)&_end); + /* fix this */ + while(addr < last) { #ifdef CONFIG_BLK_DEV_INITRD if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end) mem_map[MAP_NR(addr)].flags &= ~(1<next_hash < page) - high = ((unsigned long)end) & PAGE_MASK; - else - high = ((unsigned long)page->next_hash) & PAGE_MASK; - while (low < high) { - mem_map[MAP_NR(low)].flags &= ~(1<= end_mem) - break; - addr = next; - } - num_physpages++; - if(PageReserved(mem_map + MAP_NR(addr))) { - if ((addr < (unsigned long) &etext) && (addr >= KERNBASE)) - codepages++; - else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end)) - initpages++; - else if((addr < start_mem) && (addr >= KERNBASE)) - datapages++; - continue; - } - atomic_set(&mem_map[MAP_NR(addr)].count, 1); -#ifdef CONFIG_BLK_DEV_INITRD - if (!initrd_start || - (addr < initrd_start || addr >= initrd_end)) +#ifdef DEBUG_BOOTMEM + prom_printf("mem_init: Calling free_all_bootmem().\n"); #endif - free_page(addr); - } + num_physpages = totalram_pages = free_all_bootmem(); + + free_unused_mem_map(); + + max_mapnr = last_valid_pfn; + high_memory = __va(last_valid_pfn << PAGE_SHIFT); + + codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); + codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; + datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); + datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT; + initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); + initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; printk("Memory: %dk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", nr_free_pages << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10), - (unsigned long)PAGE_OFFSET, end_mem); + (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); /* NOTE NOTE NOTE NOTE * Please keep track of things and make sure this @@ -347,39 +436,26 @@ void free_initmem (void) { unsigned long addr; - + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - atomic_set(&mem_map[MAP_NR(addr)].count, 1); + ClearPageReserved(mem_map + MAP_NR(addr)); + set_page_count(mem_map + MAP_NR(addr), 1); free_page(addr); + totalram_pages++; + num_physpages++; } } void si_meminfo(struct sysinfo *val) { - struct page *page, *end; - - val->totalram = 0; + val->totalram = totalram_pages; val->sharedram = 0; - val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = atomic_read(&buffermem); - for (page = mem_map, end = mem_map + max_mapnr; - page < end; page++) { - if (PageSkip(page)) { - if (page->next_hash < page) - break; - page = page->next_hash; - } - if (PageReserved(page)) - continue; - val->totalram++; - if (!atomic_read(&page->count)) - continue; - val->sharedram += atomic_read(&page->count) - 1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - val->totalbig = 0; - val->freebig = 0; + val->freeram = nr_free_pages; + val->bufferram = atomic_read(&buffermem_pages); + + val->totalhigh = 0; + val->freehigh = nr_free_highpages; + + val->mem_unit = PAGE_SIZE; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c --- v2.3.34/linux/arch/sparc/mm/io-unit.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/mm/io-unit.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: io-unit.c,v 1.15 1999/09/10 10:40:38 davem Exp $ +/* $Id: io-unit.c,v 1.17 1999/10/18 01:46:54 zaitcev Exp $ * io-unit.c: IO-UNIT specific routines for memory management. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -27,14 +28,15 @@ #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) void __init -iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus) +iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) { iopte_t *xpt, *xptend; struct iounit_struct *iounit; struct linux_prom_registers iommu_promregs[PROMREG_MAX]; - + struct resource r; + iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC); - + memset(iounit, 0, sizeof(*iounit)); iounit->limit[0] = IOUNIT_BMAP1_START; iounit->limit[1] = IOUNIT_BMAP2_START; @@ -42,13 +44,14 @@ iounit->limit[3] = IOUNIT_BMAPM_END; iounit->rotor[1] = IOUNIT_BMAP2_START; iounit->rotor[2] = IOUNIT_BMAPM_START; - + prom_getproperty(sbi_node, "reg", (void *) iommu_promregs, sizeof(iommu_promregs)); prom_apply_generic_ranges(io_node, 0, iommu_promregs, 3); - xpt = (iopte_t *) - sparc_alloc_io(iommu_promregs[2].phys_addr, 0, (PAGE_SIZE * 16), - "XPT", iommu_promregs[2].which_io, 0x0); + memset(&r, 0, sizeof(r)); + r.flags = iommu_promregs[2].which_io; + r.start = iommu_promregs[2].phys_addr; + xpt = (iopte_t *) sbus_ioremap(&r, 0, PAGE_SIZE * 16, "XPT"); if(!xpt) panic("Cannot map External Page Table."); sbus->iommu = (struct iommu_struct *)iounit; @@ -108,7 +111,7 @@ return vaddr; } -static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus) +static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus) { unsigned long ret, flags; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; @@ -119,7 +122,7 @@ return ret; } -static void iounit_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { unsigned long flags; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; @@ -127,12 +130,13 @@ /* FIXME: Cache some resolved pages - often several sg entries are to the same page */ spin_lock_irqsave(&iounit->lock, flags); for (; sz >= 0; sz--) { - sg[sz].dvma_addr = iounit_get_area(iounit, (unsigned long)sg[sz].addr, sg[sz].len); + sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)sg[sz].address, sg[sz].length); + sg[sz].dvma_length = sg[sz].length; } spin_unlock_irqrestore(&iounit->lock, flags); } -static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct linux_sbus *sbus) +static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) { unsigned long flags; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; @@ -146,16 +150,16 @@ spin_unlock_irqrestore(&iounit->lock, flags); } -static void iounit_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { unsigned long flags; unsigned long vaddr, len; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; - + spin_lock_irqsave(&iounit->lock, flags); for (; sz >= 0; sz--) { - len = ((sg[sz].dvma_addr & ~PAGE_MASK) + sg[sz].len + (PAGE_SIZE-1)) >> PAGE_SHIFT; - vaddr = (sg[sz].dvma_addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT; + len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT; + vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); for (len += vaddr; vaddr < len; vaddr++) clear_bit(vaddr, iounit->bmap); @@ -164,21 +168,18 @@ } #ifdef CONFIG_SBUS -static void iounit_map_dma_area(unsigned long addr, int len) +static void iounit_map_dma_area(unsigned long va, __u32 addr, int len) { unsigned long page, end; pgprot_t dvma_prot; iopte_t *iopte; - struct linux_sbus *sbus; + struct sbus_bus *sbus; dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV); end = PAGE_ALIGN((addr + len)); while(addr < end) { - page = get_free_page(GFP_KERNEL); - if(!page) { - prom_printf("alloc_dvma: Cannot get a dvma page\n"); - prom_halt(); - } else { + page = va; + { pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; @@ -200,10 +201,15 @@ } } addr += PAGE_SIZE; + va += PAGE_SIZE; } flush_cache_all(); flush_tlb_all(); } + +static void iounit_unmap_dma_area(unsigned long addr, int len) +{ +} #endif static char *iounit_lockarea(char *vaddr, unsigned long len) @@ -229,10 +235,11 @@ #ifdef CONFIG_SBUS BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM); #endif } -__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size) +__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) { int i, j, k, npages; unsigned long rotor, scan, limit; @@ -271,7 +278,7 @@ return ret; } -__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus) +__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) { int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c --- v2.3.34/linux/arch/sparc/mm/iommu.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/iommu.c Mon Dec 20 22:05:52 1999 @@ -1,8 +1,8 @@ -/* $Id: iommu.c,v 1.11 1999/08/31 06:54:34 davem Exp $ +/* $Id: iommu.c,v 1.15 1999/11/19 04:11:53 davem Exp $ * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@ithil.mcst.ru) + * 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) */ @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include /* srmmu.c */ extern int viking_mxcc_present; @@ -45,20 +47,23 @@ } void __init -iommu_init(int iommund, struct linux_sbus *sbus) +iommu_init(int iommund, struct sbus_bus *sbus) { unsigned int impl, vers, ptsize; unsigned long tmp; struct iommu_struct *iommu; struct linux_prom_registers iommu_promregs[PROMREG_MAX]; + struct resource r; int i; iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); prom_getproperty(iommund, "reg", (void *) iommu_promregs, sizeof(iommu_promregs)); + memset(&r, 0, sizeof(r)); + r.flags = iommu_promregs[0].which_io; + r.start = iommu_promregs[0].phys_addr; iommu->regs = (struct iommu_regs *) - sparc_alloc_io(iommu_promregs[0].phys_addr, 0, (PAGE_SIZE * 3), - "IOMMU registers", iommu_promregs[0].which_io, 0x0); + sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs"); if(!iommu->regs) panic("Cannot map IOMMU registers."); impl = (iommu->regs->control & IOMMU_CTRL_IMPL) >> 28; @@ -137,18 +142,18 @@ impl, vers, iommu->page_table, ptsize); } -static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct linux_sbus *sbus) +static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) { return (__u32)vaddr; } -static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct linux_sbus *sbus) +static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) { flush_page_for_dma(0); return (__u32)vaddr; } -static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct linux_sbus *sbus) +static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) { unsigned long page = ((unsigned long) vaddr) & PAGE_MASK; @@ -159,81 +164,110 @@ return (__u32)vaddr; } -static void iommu_get_scsi_sgl_noflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { - for (; sz >= 0; sz--) - sg[sz].dvma_addr = (__u32) (sg[sz].addr); + for (; sz >= 0; sz--) { + sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_length = (__u32) (sg[sz].length); + } } -static void iommu_get_scsi_sgl_gflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { flush_page_for_dma(0); - for (; sz >= 0; sz--) - sg[sz].dvma_addr = (__u32) (sg[sz].addr); + for (; sz >= 0; sz--) { + sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_length = (__u32) (sg[sz].length); + } } -static void iommu_get_scsi_sgl_pflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { unsigned long page, oldpage = 0; while(sz >= 0) { - page = ((unsigned long) sg[sz].addr) & PAGE_MASK; + page = ((unsigned long) sg[sz].address) & PAGE_MASK; if (oldpage == page) page += PAGE_SIZE; /* We flushed that page already */ - while(page < (unsigned long)(sg[sz].addr + sg[sz].len)) { + while(page < (unsigned long)(sg[sz].address + sg[sz].length)) { flush_page_for_dma(page); page += PAGE_SIZE; } - sg[sz].dvma_addr = (__u32) (sg[sz].addr); + sg[sz].dvma_address = (__u32) (sg[sz].address); + sg[sz].dvma_length = (__u32) (sg[sz].length); sz--; oldpage = page - PAGE_SIZE; } } -static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct linux_sbus *sbus) +static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) { } -static void iommu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { } #ifdef CONFIG_SBUS -static void iommu_map_dma_area(unsigned long addr, int len) +static void iommu_map_dma_area(unsigned long va, __u32 addr, int len) { - unsigned long page, end; + unsigned long page, end, ipte_cache; pgprot_t dvma_prot; - struct iommu_struct *iommu = SBus_chain->iommu; + struct iommu_struct *iommu = sbus_root->iommu; iopte_t *iopte = iommu->page_table; iopte_t *first; - if(viking_mxcc_present) + if(viking_mxcc_present || srmmu_modtype == HyperSparc) { dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV); - else + ipte_cache = 1; + } else { dvma_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV); + ipte_cache = 0; + } iopte += ((addr - iommu->start) >> PAGE_SHIFT); first = iopte; end = PAGE_ALIGN((addr + len)); while(addr < end) { - page = get_free_page(GFP_KERNEL); - if(!page) { - prom_printf("alloc_dvma: Cannot get a dvma page\n"); - prom_halt(); - } else { + page = va; + { pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - pgdp = pgd_offset(init_task.mm, addr); + if (viking_mxcc_present) + viking_mxcc_flush_page(page); + else if (viking_flush) + viking_flush_page(page); + else + flush_page_to_ram(page); + + pgdp = pgd_offset(&init_mm, addr); pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); set_pte(ptep, pte_val(mk_pte(page, dvma_prot))); - iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page)); + if (ipte_cache != 0) { + iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page)); + } else { + iopte_val(*iopte++) = + MKIOPTE(mmu_v2p(page)) & ~IOPTE_CACHE; + } } addr += PAGE_SIZE; + va += PAGE_SIZE; } + /* P3: why do we need this? + * + * DAVEM: Because there are several aspects, none of which + * are handled by a single interface. Some cpus are + * completely not I/O DMA coherent, and some have + * virtually indexed caches. The driver DMA flushing + * methods handle the former case, but here during + * IOMMU page table modifications, and usage of non-cacheable + * cpu mappings of pages potentially in the cpu caches, we have + * to handle the latter case as well. + */ flush_cache_all(); if(viking_mxcc_present) { unsigned long start = ((unsigned long) first) & PAGE_MASK; @@ -253,6 +287,10 @@ flush_tlb_all(); iommu_invalidate(iommu->regs); } + +static void iommu_unmap_dma_area(unsigned long addr, int len) +{ +} #endif static char *iommu_lockarea(char *vaddr, unsigned long len) @@ -287,5 +325,6 @@ #ifdef CONFIG_SBUS BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM); #endif } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/nosrmmu.c linux/arch/sparc/mm/nosrmmu.c --- v2.3.34/linux/arch/sparc/mm/nosrmmu.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/nosrmmu.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: nosrmmu.c,v 1.3 1999/08/31 06:54:35 davem Exp $ +/* $Id: nosrmmu.c,v 1.5 1999/11/19 04:11:54 davem Exp $ * nosrmmu.c: This file is a bunch of dummies for sun4 compiles, * so that it does not need srmmu and avoid ifdefs. * @@ -14,6 +14,8 @@ enum mbus_module srmmu_modtype; +int vac_cache_size = 0; + static void __init should_not_happen(void) { prom_printf(shouldnothappen); @@ -49,12 +51,12 @@ return 0; } -__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size) +__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) { return 0; } -__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus) +__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) { return 0; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.3.34/linux/arch/sparc/mm/srmmu.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc/mm/srmmu.c Wed Dec 22 19:55:38 1999 @@ -1,8 +1,8 @@ -/* $Id: srmmu.c,v 1.192 1999/09/10 10:40:40 davem Exp $ +/* $Id: srmmu.c,v 1.199 1999/12/23 02:00:51 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@ithil.mcst.ru) + * 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) */ @@ -53,7 +53,7 @@ int vac_line_size; int vac_badbits; -extern unsigned long sparc_iobase_vaddr; +extern struct resource sparc_iomap; #ifdef __SMP__ #define FLUSH_BEGIN(mm) @@ -284,7 +284,7 @@ } /* The very generic SRMMU page table operations. */ -static inline int srmmu_device_memory(unsigned long x) +static inline int srmmu_device_memory(unsigned long x) { return ((x & 0xF0000000) != 0); } @@ -464,17 +464,6 @@ return (pte_t *) srmmu_s_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); } -/* This must update the context table entry for this process. */ -static void srmmu_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) -{ - if(tsk->mm->context != NO_CONTEXT && - tsk->mm->pgd != pgdp) { - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); - flush_tlb_mm(tsk->mm); - } -} - static inline pte_t *srmmu_get_pte_fast(void) { struct page *ret; @@ -777,11 +766,11 @@ #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->tss.kregs); + die_if_kernel("SRMMU bolixed...", current->thread.kregs); #endif } -static inline void alloc_context(struct mm_struct *mm) +static inline void alloc_context(struct mm_struct *old_mm, struct mm_struct *mm) { struct ctx_list *ctxp; @@ -794,7 +783,7 @@ return; } ctxp = ctx_used.next; - if(ctxp->ctx_mm == current->mm) + if(ctxp->ctx_mm == old_mm) ctxp = ctxp->next; if(ctxp == &ctx_used) panic("out of mmu contexts"); @@ -817,29 +806,16 @@ } -static void srmmu_switch_to_context(struct task_struct *tsk) +static void srmmu_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, + struct task_struct *tsk, int cpu) { - if(tsk->mm->context == NO_CONTEXT) { + if(mm->context == NO_CONTEXT) { spin_lock(&srmmu_context_spinlock); - alloc_context(tsk->mm); + alloc_context(old_mm, mm); spin_unlock(&srmmu_context_spinlock); - ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd); + ctxd_set(&srmmu_context_table[mm->context], mm->pgd); } - srmmu_set_context(tsk->mm->context); -} - -static void srmmu_init_new_context(struct mm_struct *mm) -{ - spin_lock(&srmmu_context_spinlock); - alloc_context(mm); - spin_unlock(&srmmu_context_spinlock); - - flush_cache_mm(mm); - ctxd_set(&srmmu_context_table[mm->context], mm->pgd); - flush_tlb_mm(mm); - - if(mm == current->mm) - srmmu_set_context(mm->context); + srmmu_set_context(mm->context); } /* Low level IO area allocation on the SRMMU. */ @@ -885,9 +861,6 @@ flush_tlb_all(); } -/* This is used in many routines below. */ -#define UWINMASK_OFFSET (const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask)) - /* 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 @@ -919,110 +892,85 @@ 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, 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 - * are right, flush_tlb_all is done as well, and it faults again... Strange. -jj +/* 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 + * are right, flush_tlb_all is done as well, and it faults again... + * Strange. -jj + * + * The following code is a deadwood that may be necessary when + * we start to make precise page flushes again. --zaitcev */ static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte) { +#if 0 static unsigned long last; + unsigned int val; + /* unsigned int n; */ - if (last == address) viking_hwprobe(address); + if (address == last) { + val = srmmu_hwprobe(address); + if (val != 0 && pte_val(pte) != val) { + printk("swift_update_mmu_cache: " + "addr %lx put %08x probed %08x from %p\n", + address, pte_val(pte), val, + __builtin_return_address(0)); + srmmu_flush_whole_tlb(); + } + } last = address; +#endif } -/* Swift flushes. It has the recommended SRMMU specification flushing - * facilities, so we can do things in a more fine grained fashion than we - * could on the tsunami. Let's watch out for HARDWARE BUGS... - */ - -static void swift_flush_cache_all(void) -{ - flush_user_windows(); - swift_idflash_clear(); -} - -static void swift_flush_cache_mm(struct mm_struct *mm) -{ - FLUSH_BEGIN(mm) - flush_user_windows(); - swift_idflash_clear(); - FLUSH_END -} - -static void swift_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) -{ - FLUSH_BEGIN(mm) - flush_user_windows(); - swift_idflash_clear(); - FLUSH_END -} - -static void swift_flush_cache_page(struct vm_area_struct *vma, unsigned long page) -{ - FLUSH_BEGIN(vma->vm_mm) - flush_user_windows(); - if(vma->vm_flags & VM_EXEC) - swift_flush_icache(); - swift_flush_dcache(); - FLUSH_END -} - -/* Not copy-back on swift. */ -static void swift_flush_page_to_ram(unsigned long page) -{ -} - -/* But not IO coherent either. */ -static void swift_flush_page_for_dma(unsigned long page) -{ - swift_flush_dcache(); -} - -/* Again, Swift is non-snooping split I/D cache'd just like tsunami, - * so have to punt the icache for on-stack signal insns. Only the - * icache need be flushed since the dcache is write-through. - */ -static void swift_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) -{ - swift_flush_icache(); -} - -static void swift_flush_chunk(unsigned long chunk) -{ -} - -static void swift_flush_tlb_all(void) -{ - srmmu_flush_whole_tlb(); - module_stats.invall++; -} - -static void swift_flush_tlb_mm(struct mm_struct *mm) -{ - FLUSH_BEGIN(mm) - srmmu_flush_whole_tlb(); - module_stats.invmm++; - FLUSH_END -} +/* swift.S */ +extern void swift_flush_cache_all(void); +extern void swift_flush_cache_mm(struct mm_struct *mm); +extern void swift_flush_cache_range(struct mm_struct *mm, + unsigned long start, unsigned long end); +extern void swift_flush_cache_page(struct vm_area_struct *vma, unsigned long page); +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, + unsigned long start, unsigned long end); +extern void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page); -static void swift_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +#if 0 /* P3: deadwood to debug precise flushes on Swift. */ +void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - FLUSH_BEGIN(mm) - srmmu_flush_whole_tlb(); - module_stats.invrnge++; - FLUSH_END -} + int cctx, ctx1; -static void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - FLUSH_BEGIN(vma->vm_mm) - srmmu_flush_whole_tlb(); + page &= PAGE_MASK; + if ((ctx1 = vma->vm_mm->context) != -1) { + cctx = srmmu_get_context(); +/* Is context # ever different from current context? P3 */ + if (cctx != ctx1) { + printk("flush ctx %02x curr %02x\n", ctx1, cctx); + srmmu_set_context(ctx1); + swift_flush_page(page); + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (page), "i" (ASI_M_FLUSH_PROBE)); + srmmu_set_context(cctx); + } else { + /* Rm. prot. bits from virt. c. */ + /* swift_flush_cache_all(); */ + /* swift_flush_cache_page(vma, page); */ + swift_flush_page(page); + + __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : + "r" (page), "i" (ASI_M_FLUSH_PROBE)); + /* same as above: srmmu_flush_tlb_page() */ + } + } module_stats.invpg++; - FLUSH_END } +#endif /* The following are all MBUS based SRMMU modules, and therefore could * be found in a multiprocessor configuration. On the whole, these @@ -1333,103 +1281,21 @@ hyper_flush_whole_icache(); } -static void hypersparc_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) -{ - unsigned long page = ((unsigned long) pgdp) & PAGE_MASK; - - if(pgdp != swapper_pg_dir) - hypersparc_flush_page_to_ram(page); - - if(tsk->mm->context != NO_CONTEXT && - tsk->mm->pgd != pgdp) { - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); - flush_tlb_mm(tsk->mm); - } -} - -static void viking_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) -{ - if(pgdp != swapper_pg_dir) - flush_chunk((unsigned long)pgdp); - if(tsk->mm->context != NO_CONTEXT && - tsk->mm->pgd != pgdp) { - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); - flush_tlb_mm(tsk->mm); - } -} - -static void cypress_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) -{ - register unsigned long a, b, c, d, e, f, g; - unsigned long page = ((unsigned long) pgdp) & PAGE_MASK; - unsigned long line; - - if(pgdp == swapper_pg_dir) - goto skip_flush; - - a = 0x20; b = 0x40; c = 0x60; d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0; - page &= PAGE_MASK; - line = (page + PAGE_SIZE) - 0x100; - 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); -skip_flush: - if(tsk->mm->context != NO_CONTEXT && - tsk->mm->pgd != pgdp) { - flush_cache_mm(tsk->mm); - ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp); - flush_tlb_mm(tsk->mm); - } -} - -static void hypersparc_switch_to_context(struct task_struct *tsk) +static void hypersparc_switch_mm(struct mm_struct *old_mm, + struct mm_struct *mm, struct task_struct *tsk, int cpu) { - if(tsk->mm->context == NO_CONTEXT) { + if(mm->context == NO_CONTEXT) { ctxd_t *ctxp; spin_lock(&srmmu_context_spinlock); - alloc_context(tsk->mm); + alloc_context(old_mm, mm); spin_unlock(&srmmu_context_spinlock); - ctxp = &srmmu_context_table[tsk->mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4)))); + ctxp = &srmmu_context_table[mm->context]; + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); hypersparc_flush_page_to_ram((unsigned long)ctxp); } hyper_flush_whole_icache(); - srmmu_set_context(tsk->mm->context); -} - -static void hypersparc_init_new_context(struct mm_struct *mm) -{ - ctxd_t *ctxp; - - spin_lock(&srmmu_context_spinlock); - alloc_context(mm); - spin_unlock(&srmmu_context_spinlock); - - ctxp = &srmmu_context_table[mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); - hypersparc_flush_page_to_ram((unsigned long)ctxp); - - if(mm == current->mm) { - hyper_flush_whole_icache(); - srmmu_set_context(mm->context); - } + srmmu_set_context(mm->context); } static unsigned long mempool; @@ -1694,7 +1560,8 @@ srmmu_map[srmmu_bank].vbase = vbase; srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr; srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes; - srmmu_bank++; + if (srmmu_map[srmmu_bank].size) + srmmu_bank++; map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE; return vstart; } @@ -1949,8 +1816,8 @@ int i, cpunode; char node_str[128]; - sparc_iobase_vaddr = 0xfd000000; /* 16MB of IOSPACE on all sun4m's. */ - physmem_mapped_contig = 0; /* for init.c:taint_real_pages() */ + sparc_iomap.start = 0xfd000000; /* 16MB of IOSPACE on all sun4m's. */ + physmem_mapped_contig = 0; /* for init.c:taint_real_pages() */ if (sparc_cpu_model == sun4d) num_contexts = 65536; /* We know it is Viking */ @@ -1981,7 +1848,7 @@ srmmu_allocate_ptable_skeleton(KERNBASE, end_mem); #if CONFIG_SUN_IO - srmmu_allocate_ptable_skeleton(sparc_iobase_vaddr, IOBASE_END); + srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif @@ -2051,16 +1918,14 @@ static void srmmu_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { - /* XXX This could be drastically improved. - * XXX We are only called from __exit_mm and it just did - * XXX cache/tlb mm flush and right after this will (re-) - * XXX SET_PAGE_DIR to swapper_pg_dir. -DaveM - */ + + if(mm->context != NO_CONTEXT) { flush_cache_mm(mm); ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir); flush_tlb_mm(mm); + spin_lock(&srmmu_context_spinlock); free_context(mm->context); + spin_unlock(&srmmu_context_spinlock); mm->context = NO_CONTEXT; } } @@ -2136,7 +2001,7 @@ static void hypersparc_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if(mm->context != NO_CONTEXT) { ctxd_t *ctxp; /* HyperSparc is copy-back, any data for this @@ -2151,7 +2016,9 @@ 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; } } @@ -2267,11 +2134,9 @@ BTFIXUPSET_CALL(flush_chunk, hypersparc_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ BTFIXUPSET_CALL(ctxd_set, hypersparc_ctxd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(switch_to_context, hypersparc_switch_to_context, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(init_new_context, hypersparc_init_new_context, 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); - BTFIXUPSET_CALL(sparc_update_rootmmu_dir, hypersparc_update_rootmmu_dir, BTFIXUPCALL_NORM); poke_srmmu = poke_hypersparc; hypersparc_setup_blockops(); @@ -2339,7 +2204,6 @@ BTFIXUPSET_CALL(flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(sparc_update_rootmmu_dir, cypress_update_rootmmu_dir, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM); poke_srmmu = poke_cypress; @@ -2371,12 +2235,14 @@ static void __init poke_swift(void) { - unsigned long mreg = srmmu_get_mmureg(); + unsigned long mreg; /* Clear any crap from the cache or else... */ - swift_idflash_clear(); - mreg |= (SWIFT_IE | SWIFT_DE); /* I & D caches on */ + swift_flush_cache_all(); + /* Enable I & D caches */ + mreg = srmmu_get_mmureg(); + mreg |= (SWIFT_IE | SWIFT_DE); /* 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 @@ -2442,19 +2308,21 @@ 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_NOP); /* local flush _only_ */ + 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); BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NOP); + BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(update_mmu_cache, swift_update_mmu_cache, BTFIXUPCALL_NORM); + flush_page_for_dma_global = 0; + /* 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 @@ -2611,7 +2479,7 @@ 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_NOP); + BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM); poke_srmmu = poke_turbosparc; } @@ -2642,7 +2510,7 @@ 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_NOP); /* local flush _only_ */ + 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); @@ -2654,6 +2522,8 @@ BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM); poke_srmmu = poke_tsunami; + + tsunami_setup_blockops(); } static void __init poke_viking(void) @@ -2725,7 +2595,6 @@ 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(sparc_update_rootmmu_dir, viking_update_rootmmu_dir, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_chunk, viking_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ @@ -2736,8 +2605,7 @@ * which we use the IOMMU. */ BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page, BTFIXUPCALL_NORM); - /* Also, this is so far the only chip which actually uses - the page argument to flush_page_for_dma */ + flush_page_for_dma_global = 0; } else { srmmu_name = "TI Viking/MXCC"; @@ -2928,6 +2796,16 @@ 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 */ +} + extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme, tsetup_mmu_patchme, rtrap_mmu_patchme; @@ -2999,21 +2877,18 @@ 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); - + BTFIXUPSET_CALL(set_pte, srmmu_set_pte_cacheable, BTFIXUPCALL_SWAPO0O1); - BTFIXUPSET_CALL(init_new_context, srmmu_init_new_context, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(switch_to_context, srmmu_switch_to_context, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(sparc_update_rootmmu_dir, srmmu_update_rootmmu_dir, BTFIXUPCALL_NORM); + BTFIXUPSET_SETHI(none_mask, 0xF0000000); /* P3: is it used? */ - BTFIXUPSET_SETHI(none_mask, 0xF0000000); - BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0); @@ -3072,6 +2947,11 @@ 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(); @@ -3104,6 +2984,7 @@ BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM); #endif + if (sparc_cpu_model == sun4d) ld_mmu_iounit(); else diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.3.34/linux/arch/sparc/mm/sun4c.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/sun4c.c Mon Dec 20 22:05:52 1999 @@ -1,18 +1,22 @@ -/* $Id: sun4c.c,v 1.176 1999/08/31 06:54:42 davem Exp $ +/* $Id: sun4c.c,v 1.181 1999/12/16 14:34:21 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 Anton Blanchard (anton@progsoc.uts.edu.au) + * Copyright (C) 1997,99 Anton Blanchard (anton@progsoc.uts.edu.au) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ +#define NR_TASK_BUCKETS 512 + #include #include #include #include +#include +#include #include #include #include @@ -27,42 +31,19 @@ #include #include -/* TODO: Make it such that interrupt handlers cannot dick with - * the user segment lists, most of the cli/sti pairs can - * disappear once that is taken care of. - */ - -/* XXX Ok the real performance win, I figure, will be to use a combined hashing - * XXX and bitmap scheme to keep track of what we have mapped where. The whole - * XXX incentive is to make it such that the range flushes can be serviced - * XXX always in near constant time. --DaveM +/* Because of our dynamic kernel TLB miss strategy, and how + * our DVMA mapping allocation works, you _MUST_: + * + * 1) Disable interrupts _and_ not touch any dynamic kernel + * memory while messing with kernel MMU state. By + * dynamic memory I mean any object which is not in + * the kernel image itself or a task_struct (both of + * which are locked into the MMU). + * 2) Disable interrupts while messing with user MMU state. */ extern int num_segmaps, num_contexts; -/* Define this to get extremely anal debugging, undefine for performance. */ -/* #define DEBUG_SUN4C_MM */ - -#define UWINMASK_OFFSET (const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask)) - -/* This is used in many routines below. */ -#define FUW_INLINE do { \ - register int ctr asm("g5"); \ - ctr = 0; \ - __asm__ __volatile__("\n" \ - "1: ld [%%g6 + %2], %%g4 ! flush user windows\n" \ - " orcc %%g0, %%g4, %%g0\n" \ - " add %0, 1, %0\n" \ - " bne 1b\n" \ - " save %%sp, -64, %%sp\n" \ - "2: subcc %0, 1, %0\n" \ - " bne 2b\n" \ - " restore %%g0, %%g0, %%g0\n" \ - : "=&r" (ctr) \ - : "0" (ctr), "i" (UWINMASK_OFFSET) \ - : "g4", "cc"); \ -} while(0); - #ifdef CONFIG_SUN4 #define SUN4C_VAC_SIZE sun4c_vacinfo.num_bytes #else @@ -82,58 +63,21 @@ #define MIN(a,b) ((a)<(b)?(a):(b)) #endif - -#define KGPROF_PROFILING 0 -#if KGPROF_PROFILING -#define KGPROF_DEPTH 3 /* this needs to match the code below */ -#define KGPROF_SIZE 100 -static struct { - unsigned addr[KGPROF_DEPTH]; - unsigned count; -} kgprof_counters[KGPROF_SIZE]; - -/* just call this function from whatever function you think needs it then - look at /proc/cpuinfo to see where the function is being called from - and how often. This gives a type of "kernel gprof" */ -#define NEXT_PROF(prev,lvl) (prev>PAGE_OFFSET?__builtin_return_address(lvl):0) -static inline void kgprof_profile(void) -{ - unsigned ret[KGPROF_DEPTH]; - int i,j; - /* you can't use a variable argument to __builtin_return_address() */ - ret[0] = (unsigned)__builtin_return_address(0); - ret[1] = (unsigned)NEXT_PROF(ret[0],1); - ret[2] = (unsigned)NEXT_PROF(ret[1],2); - - for (i=0;iid_machtype) { + switch (idprom->id_machtype) { case (SM_SUN4|SM_4_110): sun4c_vacinfo.type = NONE; @@ -477,12 +366,12 @@ default: prom_printf("Cannot initialize VAC - wierd sun4 model idprom->id_machtype = %d", idprom->id_machtype); prom_halt(); - } + }; } else { sun4c_vacinfo.type = WRITE_THROUGH; - if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { /* PROM on SS1 lacks this info, to be super safe we * hard code it here since this arch is cast in stone. */ @@ -497,7 +386,7 @@ sun4c_vacinfo.do_hwflushes = prom_getintdefault(prom_root_node, "vac-hwflush", 0); - if(sun4c_vacinfo.do_hwflushes == 0) + if (sun4c_vacinfo.do_hwflushes == 0) sun4c_vacinfo.do_hwflushes = prom_getintdefault(prom_root_node, "vac_hwflush", 0); @@ -509,7 +398,7 @@ sun4c_vacinfo.num_lines = (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize); - switch(sun4c_vacinfo.linesize) { + switch (sun4c_vacinfo.linesize) { case 16: sun4c_vacinfo.log2lsize = 4; break; @@ -566,7 +455,7 @@ prom_printf("Unhandled number of segmaps: %d\n", num_segmaps); prom_halt(); - } + }; switch (num_contexts) { case 8: /* Default, nothing to do. */ @@ -574,19 +463,22 @@ case 16: PATCH_INSN(num_context_patch1_16, num_context_patch1); +#if 0 PATCH_INSN(num_context_patch2_16, num_context_patch2); +#endif break; default: prom_printf("Unhandled number of contexts: %d\n", num_contexts); prom_halt(); - } - if(sun4c_vacinfo.do_hwflushes != 0) { + }; + + if (sun4c_vacinfo.do_hwflushes != 0) { PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1); PATCH_INSN(vac_hwflush_patch2_on, vac_hwflush_patch2); } else { - switch(sun4c_vacinfo.linesize) { + switch (sun4c_vacinfo.linesize) { case 16: /* Default, nothing to do. */ break; @@ -604,7 +496,7 @@ static void __init sun4c_probe_mmu(void) { if (ARCH_SUN4) { - switch(idprom->id_machtype) { + switch (idprom->id_machtype) { case (SM_SUN4|SM_4_110): prom_printf("No support for 4100 yet\n"); prom_halt(); @@ -631,10 +523,10 @@ default: prom_printf("Invalid SUN4 model\n"); prom_halt(); - } + }; } else { - if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { /* Hardcode these just to be safe, PROM on SS1 does * not have this info available in the root node. */ @@ -658,20 +550,15 @@ struct linux_prom_registers regs[1]; if (ARCH_SUN4) { - sun4c_memerr_reg = sparc_alloc_io(sun4_memreg_physaddr, 0, - PAGE_SIZE, - "memory parity error", - 0x0, 0); + sun4c_memerr_reg = ioremap(sun4_memreg_physaddr, PAGE_SIZE); } else { node = prom_getchild(prom_root_node); node = prom_searchsiblings(prom_root_node, "memory-error"); if (!node) return; prom_getproperty(node, "reg", (char *)regs, sizeof(regs)); - sun4c_memerr_reg = sparc_alloc_io(regs[0].phys_addr, 0, - regs[0].reg_size, - "memory parity error", - regs[0].which_io, 0); + /* hmm I think regs[0].which_io is zero here anyways */ + sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size); } } @@ -679,10 +566,10 @@ { extern unsigned long start; - if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || - (idprom->id_machtype == (SM_SUN4 | SM_4_330)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || + (idprom->id_machtype == (SM_SUN4 | SM_4_330)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { /* Whee.. */ printk("SS2 cache bug detected, uncaching trap table page\n"); sun4c_flush_page((unsigned int) &start); @@ -692,17 +579,13 @@ } /* Addr is always aligned on a page boundry for us already. */ -static void sun4c_map_dma_area(unsigned long addr, int len) +static void sun4c_map_dma_area(unsigned long va, u32 addr, int len) { unsigned long page, end; end = PAGE_ALIGN((addr + len)); - while(addr < end) { - page = get_free_page(GFP_KERNEL); - if(!page) { - prom_printf("alloc_dvma: Cannot get a dvma page\n"); - prom_halt(); - } + while (addr < end) { + page = va; sun4c_flush_page(page); page -= PAGE_OFFSET; page >>= PAGE_SHIFT; @@ -710,9 +593,21 @@ _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_PRIV); sun4c_put_pte(addr, page); addr += PAGE_SIZE; + va += PAGE_SIZE; } } +static void sun4c_unmap_dma_area(unsigned long addr, int len) +{ +} + +static void sun4c_inval_dma_area(unsigned long addr, int len) +{ +} + +static void sun4c_flush_dma_area(unsigned long addr, int len) +{ +} /* TLB management. */ @@ -726,6 +621,13 @@ unsigned long vaddr; unsigned char pseg; unsigned char locked; + + /* For user mappings only, and completely hidden from kernel + * TLB miss code. + */ + unsigned char ctx; + struct sun4c_mmu_entry *lru_next; + struct sun4c_mmu_entry *lru_prev; }; static struct sun4c_mmu_entry mmu_entry_pool[SUN4C_MAX_SEGMAPS]; @@ -734,12 +636,15 @@ { int i; - for(i=0; i < SUN4C_MAX_SEGMAPS; i++) { + for (i=0; i < SUN4C_MAX_SEGMAPS; i++) { mmu_entry_pool[i].pseg = i; mmu_entry_pool[i].next = 0; mmu_entry_pool[i].prev = 0; mmu_entry_pool[i].vaddr = 0; mmu_entry_pool[i].locked = 0; + mmu_entry_pool[i].ctx = 0; + mmu_entry_pool[i].lru_next = 0; + mmu_entry_pool[i].lru_prev = 0; } mmu_entry_pool[invalid_segment].locked = 1; } @@ -750,8 +655,8 @@ unsigned long start, end; end = vaddr + SUN4C_REAL_PGDIR_SIZE; - for(start = vaddr; start < end; start += PAGE_SIZE) - if(sun4c_get_pte(start) & _SUN4C_PAGE_VALID) + for (start = vaddr; start < end; start += PAGE_SIZE) + if (sun4c_get_pte(start) & _SUN4C_PAGE_VALID) sun4c_put_pte(start, (sun4c_get_pte(start) | bits_on) & ~bits_off); } @@ -762,16 +667,16 @@ unsigned char pseg, ctx; #ifdef CONFIG_SUN4 /* sun4/110 and 260 have no kadb. */ - if((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && - (idprom->id_machtype != (SM_SUN4 | SM_4_110))) { + if ((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && + (idprom->id_machtype != (SM_SUN4 | SM_4_110))) { #endif - for(vaddr = KADB_DEBUGGER_BEGVM; - vaddr < LINUX_OPPROM_ENDVM; - vaddr += SUN4C_REAL_PGDIR_SIZE) { + for (vaddr = KADB_DEBUGGER_BEGVM; + vaddr < LINUX_OPPROM_ENDVM; + vaddr += SUN4C_REAL_PGDIR_SIZE) { pseg = sun4c_get_segmap(vaddr); - if(pseg != invalid_segment) { + if (pseg != invalid_segment) { mmu_entry_pool[pseg].locked = 1; - for(ctx = 0; ctx < num_contexts; ctx++) + for (ctx = 0; ctx < num_contexts; ctx++) prom_putsegment(ctx, vaddr, pseg); fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0); } @@ -779,10 +684,10 @@ #ifdef CONFIG_SUN4 } #endif - for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { + for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { pseg = sun4c_get_segmap(vaddr); mmu_entry_pool[pseg].locked = 1; - for(ctx = 0; ctx < num_contexts; ctx++) + for (ctx = 0; ctx < num_contexts; ctx++) prom_putsegment(ctx, vaddr, pseg); fix_permissions(vaddr, _SUN4C_PAGE_PRIV, _SUN4C_PAGE_NOCACHE); } @@ -792,13 +697,13 @@ { int i, ctx; - while(start < end) { - for(i=0; i < invalid_segment; i++) - if(!mmu_entry_pool[i].locked) + while (start < end) { + for (i = 0; i < invalid_segment; i++) + if (!mmu_entry_pool[i].locked) break; mmu_entry_pool[i].locked = 1; sun4c_init_clean_segmap(i); - for(ctx = 0; ctx < num_contexts; ctx++) + for (ctx = 0; ctx < num_contexts; ctx++) prom_putsegment(ctx, start, mmu_entry_pool[i].pseg); start += SUN4C_REAL_PGDIR_SIZE; } @@ -815,13 +720,15 @@ static struct sun4c_mmu_ring sun4c_context_ring[SUN4C_MAX_CONTEXTS]; /* used user entries */ static struct sun4c_mmu_ring sun4c_ufree_ring; /* free user entries */ +static struct sun4c_mmu_ring sun4c_ulru_ring; /* LRU user entries */ struct sun4c_mmu_ring sun4c_kernel_ring; /* used kernel entries */ struct sun4c_mmu_ring sun4c_kfree_ring; /* free kernel entries */ -static inline void sun4c_init_rings(unsigned long *mempool) +static inline void sun4c_init_rings(void) { int i; - for(i=0; iringhd; @@ -849,49 +759,58 @@ ring->num_entries++; } -static inline void add_ring_ordered(struct sun4c_mmu_ring *ring, - struct sun4c_mmu_entry *entry) +static __inline__ void add_lru(struct sun4c_mmu_entry *entry) +{ + struct sun4c_mmu_ring *ring = &sun4c_ulru_ring; + struct sun4c_mmu_entry *head = &ring->ringhd; + + entry->lru_next = head; + (entry->lru_prev = head->lru_prev)->lru_next = entry; + head->lru_prev = entry; +} + +static void add_ring_ordered(struct sun4c_mmu_ring *ring, + struct sun4c_mmu_entry *entry) { struct sun4c_mmu_entry *head = &ring->ringhd; unsigned long addr = entry->vaddr; - if(head->next != &ring->ringhd) { - while((head->next != &ring->ringhd) && (head->next->vaddr < addr)) - head = head->next; - } + while ((head->next != &ring->ringhd) && (head->next->vaddr < addr)) + head = head->next; + entry->prev = head; (entry->next = head->next)->prev = entry; head->next = entry; ring->num_entries++; + + add_lru(entry); } -static inline void remove_ring(struct sun4c_mmu_ring *ring, - struct sun4c_mmu_entry *entry) +static __inline__ void remove_ring(struct sun4c_mmu_ring *ring, + struct sun4c_mmu_entry *entry) { struct sun4c_mmu_entry *next = entry->next; (next->prev = entry->prev)->next = next; ring->num_entries--; -#ifdef DEBUG_SUN4C_MM - if(ring->num_entries < 0) - panic("sun4c: Ring num_entries < 0!"); -#endif } -static inline void free_user_entry(int ctx, struct sun4c_mmu_entry *entry) +static void remove_lru(struct sun4c_mmu_entry *entry) { - remove_ring(sun4c_context_ring+ctx, entry); - add_ring(&sun4c_ufree_ring, entry); + struct sun4c_mmu_entry *next = entry->lru_next; + + (next->lru_prev = entry->lru_prev)->lru_next = next; } -static inline void assign_user_entry(int ctx, struct sun4c_mmu_entry *entry) +static void free_user_entry(int ctx, struct sun4c_mmu_entry *entry) { - remove_ring(&sun4c_ufree_ring, entry); - add_ring_ordered(sun4c_context_ring+ctx, entry); + remove_ring(sun4c_context_ring+ctx, entry); + remove_lru(entry); + add_ring(&sun4c_ufree_ring, entry); } -static inline void free_kernel_entry(struct sun4c_mmu_entry *entry, - struct sun4c_mmu_ring *ring) +static void free_kernel_entry(struct sun4c_mmu_entry *entry, + struct sun4c_mmu_ring *ring) { remove_ring(ring, entry); add_ring(&sun4c_kfree_ring, entry); @@ -901,9 +820,9 @@ { int i; - while(howmany) { - for(i=0; i < invalid_segment; i++) - if(!mmu_entry_pool[i].locked) + while (howmany) { + for (i = 0; i < invalid_segment; i++) + if (!mmu_entry_pool[i].locked) break; mmu_entry_pool[i].locked = 1; sun4c_init_clean_segmap(i); @@ -916,54 +835,40 @@ { int i; - for(i=0; i < invalid_segment; i++) { - if(mmu_entry_pool[i].locked) + for (i = 0; i < invalid_segment; i++) { + if (mmu_entry_pool[i].locked) continue; sun4c_init_clean_segmap(i); add_ring(&sun4c_ufree_ring, &mmu_entry_pool[i]); } } -static inline void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry) +static void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry) { int savectx, ctx; savectx = sun4c_get_context(); - for(ctx = 0; ctx < num_contexts; ctx++) { + for (ctx = 0; ctx < num_contexts; ctx++) { sun4c_set_context(ctx); sun4c_put_segmap(kentry->vaddr, invalid_segment); } sun4c_set_context(savectx); } -static inline void sun4c_kernel_map(struct sun4c_mmu_entry *kentry) +static void sun4c_kernel_map(struct sun4c_mmu_entry *kentry) { int savectx, ctx; savectx = sun4c_get_context(); - for(ctx = 0; ctx < num_contexts; ctx++) { + for (ctx = 0; ctx < num_contexts; ctx++) { sun4c_set_context(ctx); sun4c_put_segmap(kentry->vaddr, kentry->pseg); } sun4c_set_context(savectx); } -static inline void sun4c_user_unmap(struct sun4c_mmu_entry *uentry) -{ - sun4c_put_segmap(uentry->vaddr, invalid_segment); -} - -static inline void sun4c_user_map(struct sun4c_mmu_entry *uentry) -{ - unsigned long start = uentry->vaddr; - unsigned long end = start + SUN4C_REAL_PGDIR_SIZE; - - sun4c_put_segmap(uentry->vaddr, uentry->pseg); - while(start < end) { - sun4c_put_pte(start, 0); - start += PAGE_SIZE; - } -} +#define sun4c_user_unmap(__entry) \ + sun4c_put_segmap((__entry)->vaddr, invalid_segment) static void sun4c_demap_context_hw(struct sun4c_mmu_ring *crp, unsigned char ctx) { @@ -971,11 +876,11 @@ unsigned long flags; save_and_cli(flags); - if(head->next != head) { + if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); - FUW_INLINE + flush_user_windows(); sun4c_set_context(ctx); sun4c_flush_context_hw(); do { @@ -985,7 +890,7 @@ free_user_entry(ctx, entry); entry = next; - } while(entry != head); + } while (entry != head); sun4c_set_context(savectx); } restore_flags(flags); @@ -997,11 +902,11 @@ unsigned long flags; save_and_cli(flags); - if(head->next != head) { + if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); - FUW_INLINE + flush_user_windows(); sun4c_set_context(ctx); sun4c_flush_context_sw(); do { @@ -1011,49 +916,31 @@ free_user_entry(ctx, entry); entry = next; - } while(entry != head); + } while (entry != head); sun4c_set_context(savectx); } restore_flags(flags); } -static inline void sun4c_demap_one(struct sun4c_mmu_ring *crp, unsigned char ctx) -{ - /* by using .prev we get a kind of "lru" algorithm */ - struct sun4c_mmu_entry *entry = crp->ringhd.prev; - unsigned long flags; - int savectx = sun4c_get_context(); - -#ifdef DEBUG_SUN4C_MM - if(entry == &crp->ringhd) - panic("sun4c_demap_one: Freeing from empty ctx ring."); -#endif - FUW_INLINE - save_and_cli(flags); - sun4c_set_context(ctx); - sun4c_flush_segment(entry->vaddr); - sun4c_user_unmap(entry); - free_user_entry(ctx, entry); - sun4c_set_context(savectx); - restore_flags(flags); -} - static int sun4c_user_taken_entries = 0; /* This is how much we have. */ static int max_user_taken_entries = 0; /* This limits us and prevents deadlock. */ -static inline struct sun4c_mmu_entry *sun4c_kernel_strategy(void) +static struct sun4c_mmu_entry *sun4c_kernel_strategy(void) { struct sun4c_mmu_entry *this_entry; /* If some are free, return first one. */ - if(sun4c_kfree_ring.num_entries) { + if (sun4c_kfree_ring.num_entries) { this_entry = sun4c_kfree_ring.ringhd.next; return this_entry; } /* Else free one up. */ this_entry = sun4c_kernel_ring.ringhd.prev; - sun4c_flush_segment(this_entry->vaddr); + if (sun4c_vacinfo.do_hwflushes) + sun4c_flush_segment_hw(this_entry->vaddr); + else + sun4c_flush_segment_sw(this_entry->vaddr); sun4c_kernel_unmap(this_entry); free_kernel_entry(this_entry, &sun4c_kernel_ring); this_entry = sun4c_kfree_ring.ringhd.next; @@ -1061,141 +948,73 @@ return this_entry; } -void sun4c_shrink_kernel_ring(void) -{ - struct sun4c_mmu_entry *entry; - unsigned long flags; - - /* If an interrupt comes in here, we die... */ - save_and_cli(flags); - - if (sun4c_user_taken_entries) { - entry = sun4c_kernel_strategy(); - remove_ring(&sun4c_kfree_ring, entry); - add_ring(&sun4c_ufree_ring, entry); - sun4c_user_taken_entries--; -#if 0 - printk("shrink: ufree= %d, kfree= %d, kernel= %d\n", - sun4c_ufree_ring.num_entries, - sun4c_kfree_ring.num_entries, - sun4c_kernel_ring.num_entries); -#endif -#ifdef DEBUG_SUN4C_MM - if(sun4c_user_taken_entries < 0) - panic("sun4c_shrink_kernel_ring: taken < 0."); -#endif - } - restore_flags(flags); -} - /* Using this method to free up mmu entries eliminates a lot of * potential races since we have a kernel that incurs tlb * replacement faults. There may be performance penalties. + * + * NOTE: Must be called with interrupts disabled. */ -static inline struct sun4c_mmu_entry *sun4c_user_strategy(void) +static struct sun4c_mmu_entry *sun4c_user_strategy(void) { - struct ctx_list *next_one; - struct sun4c_mmu_ring *rp = 0; + struct sun4c_mmu_entry *entry; unsigned char ctx; -#ifdef DEBUG_SUN4C_MM - int lim = num_contexts; -#endif + int savectx; /* If some are free, return first one. */ - if(sun4c_ufree_ring.num_entries) { -#ifdef DEBUG_SUN4C_MM - if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd) - panic("sun4c_user_strategy: num_entries!=0 but ring empty."); -#endif - return sun4c_ufree_ring.ringhd.next; + if (sun4c_ufree_ring.num_entries) { + entry = sun4c_ufree_ring.ringhd.next; + goto unlink_out; } if (sun4c_user_taken_entries) { - sun4c_shrink_kernel_ring(); -#ifdef DEBUG_SUN4C_MM - if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd) - panic("sun4c_user_strategy: kernel shrunk but ufree empty."); -#endif - return sun4c_ufree_ring.ringhd.next; + entry = sun4c_kernel_strategy(); + sun4c_user_taken_entries--; + goto kunlink_out; } - /* Grab one from the LRU context. */ - next_one = ctx_used.next; - while ((sun4c_context_ring[next_one->ctx_number].num_entries == 0) -#ifdef DEBUG_SUN4C_MM - && (--lim >= 0) -#endif - ) - next_one = next_one->next; + /* Grab from the beginning of the LRU list. */ + entry = sun4c_ulru_ring.ringhd.lru_next; + ctx = entry->ctx; -#ifdef DEBUG_SUN4C_MM - if(lim < 0) - panic("No user segmaps!"); -#endif + savectx = sun4c_get_context(); + flush_user_windows(); + sun4c_set_context(ctx); + if (sun4c_vacinfo.do_hwflushes) + sun4c_flush_segment_hw(entry->vaddr); + else + sun4c_flush_segment_sw(entry->vaddr); + sun4c_user_unmap(entry); + remove_ring(sun4c_context_ring + ctx, entry); + remove_lru(entry); + sun4c_set_context(savectx); - ctx = next_one->ctx_number; - rp = &sun4c_context_ring[ctx]; + return entry; - sun4c_demap_one(rp, ctx); -#ifdef DEBUG_SUN4C_MM - if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd) - panic("sun4c_user_strategy: demapped one but ufree empty."); -#endif - return sun4c_ufree_ring.ringhd.next; +unlink_out: + remove_ring(&sun4c_ufree_ring, entry); + return entry; +kunlink_out: + remove_ring(&sun4c_kfree_ring, entry); + return entry; } +/* NOTE: Must be called with interrupts disabled. */ void sun4c_grow_kernel_ring(void) { struct sun4c_mmu_entry *entry; -#if 0 - printk("grow: "); -#endif - /* Prevent deadlock condition. */ - if(sun4c_user_taken_entries >= max_user_taken_entries) { -#if 0 - printk("deadlock avoidance, taken= %d max= %d\n", - sun4c_user_taken_entries, max_user_taken_entries); -#endif + if (sun4c_user_taken_entries >= max_user_taken_entries) return; - } if (sun4c_ufree_ring.num_entries) { entry = sun4c_ufree_ring.ringhd.next; -#ifdef DEBUG_SUN4C_MM - if(entry == &sun4c_ufree_ring.ringhd) - panic("\nsun4c_grow_kernel_ring: num_entries!=0, ring empty."); -#endif remove_ring(&sun4c_ufree_ring, entry); add_ring(&sun4c_kfree_ring, entry); -#ifdef DEBUG_SUN4C_MM - if(sun4c_user_taken_entries < 0) - panic("\nsun4c_grow_kernel_ring: taken < 0."); -#endif sun4c_user_taken_entries++; -#if 0 - printk("ufree= %d, kfree= %d, kernel= %d\n", - sun4c_ufree_ring.num_entries, - sun4c_kfree_ring.num_entries, - sun4c_kernel_ring.num_entries); -#endif } } -static inline void alloc_user_segment(unsigned long address, unsigned char ctx) -{ - struct sun4c_mmu_entry *entry; - unsigned long flags; - - save_and_cli(flags); - entry = sun4c_user_strategy(); - entry->vaddr = (address & SUN4C_REAL_PGDIR_MASK); - assign_user_entry(ctx, entry); - sun4c_user_map(entry); - restore_flags(flags); -} - /* This is now a fast in-window trap handler to avoid any and all races. */ static void sun4c_quick_kernel_fault(unsigned long address) { @@ -1209,8 +1028,8 @@ * bucket[0] * bucket[1] * [ ... ] - * bucket[NR_TASKS-1] - * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASKS) + * bucket[NR_TASK_BUCKETS-1] + * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASK_BUCKETS) * * Each slot looks like: * @@ -1218,7 +1037,7 @@ * page 2 -- rest of kernel stack */ -union task_union *sun4c_bucket[NR_TASKS]; +union task_union *sun4c_bucket[NR_TASK_BUCKETS]; static int sun4c_lowbucket_avail; @@ -1232,7 +1051,7 @@ #define BUCKET_PTE_PAGE(pte) \ (PAGE_OFFSET + (((pte) & SUN4C_PFN_MASK) << PAGE_SHIFT)) -static inline void get_locked_segment(unsigned long addr) +static void get_locked_segment(unsigned long addr) { struct sun4c_mmu_entry *stolen; unsigned long flags; @@ -1240,19 +1059,14 @@ save_and_cli(flags); addr &= SUN4C_REAL_PGDIR_MASK; stolen = sun4c_user_strategy(); - remove_ring(&sun4c_ufree_ring, stolen); max_user_taken_entries--; -#ifdef DEBUG_SUN4C_MM - if(max_user_taken_entries < 0) - panic("get_locked_segment: max_user_taken < 0."); -#endif stolen->vaddr = addr; - FUW_INLINE + flush_user_windows(); sun4c_kernel_map(stolen); restore_flags(flags); } -static inline void free_locked_segment(unsigned long addr) +static void free_locked_segment(unsigned long addr) { struct sun4c_mmu_entry *entry; unsigned long flags; @@ -1263,14 +1077,13 @@ pseg = sun4c_get_segmap(addr); entry = &mmu_entry_pool[pseg]; - FUW_INLINE - sun4c_flush_segment(addr); + flush_user_windows(); + if (sun4c_vacinfo.do_hwflushes) + sun4c_flush_segment_hw(addr); + else + sun4c_flush_segment_sw(addr); sun4c_kernel_unmap(entry); add_ring(&sun4c_ufree_ring, entry); -#ifdef DEBUG_SUN4C_MM - if(max_user_taken_entries < 0) - panic("free_locked_segment: max_user_taken < 0."); -#endif max_user_taken_entries++; restore_flags(flags); } @@ -1282,8 +1095,8 @@ /* 32 buckets per segment... */ entry &= ~31; start = entry; - for(end = (start + 32); start < end; start++) - if(sun4c_bucket[start] != BUCKET_EMPTY) + for (end = (start + 32); start < end; start++) + if (sun4c_bucket[start] != BUCKET_EMPTY) return; /* Entire segment empty, release it. */ @@ -1302,23 +1115,39 @@ int entry; pages = __get_free_pages(GFP_KERNEL, TASK_STRUCT_ORDER); - if(!pages) + if (!pages) return (struct task_struct *) 0; - for(entry = sun4c_lowbucket_avail; entry < NR_TASKS; entry++) - if(sun4c_bucket[entry] == BUCKET_EMPTY) + for (entry = sun4c_lowbucket_avail; entry < NR_TASK_BUCKETS; entry++) + if (sun4c_bucket[entry] == BUCKET_EMPTY) break; - if(entry == NR_TASKS) { + if (entry == NR_TASK_BUCKETS) { free_pages(pages, TASK_STRUCT_ORDER); return (struct task_struct *) 0; } - if(entry >= sun4c_lowbucket_avail) + if (entry >= sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry + 1; addr = BUCKET_ADDR(entry); sun4c_bucket[entry] = (union task_union *) addr; if(sun4c_get_segmap(addr) == invalid_segment) get_locked_segment(addr); + + /* We are changing the virtual color of the page(s) + * so we must flush the cache to guarentee consistancy. + */ + if (sun4c_vacinfo.do_hwflushes) { + sun4c_flush_page_hw(pages); +#ifndef CONFIG_SUN4 + sun4c_flush_page_hw(pages + PAGE_SIZE); +#endif + } else { + sun4c_flush_page_sw(pages); +#ifndef CONFIG_SUN4 + sun4c_flush_page_sw(pages + PAGE_SIZE); +#endif + } + sun4c_put_pte(addr, BUCKET_PTE(pages)); #ifndef CONFIG_SUN4 sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); @@ -1342,7 +1171,7 @@ sun4c_put_pte(tsaddr + PAGE_SIZE, 0); #endif sun4c_bucket[entry] = BUCKET_EMPTY; - if(entry < sun4c_lowbucket_avail) + if (entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; free_pages(pages, TASK_STRUCT_ORDER); @@ -1365,7 +1194,7 @@ sun4c_put_pte(tsaddr + PAGE_SIZE, 0); #endif sun4c_bucket[entry] = BUCKET_EMPTY; - if(entry < sun4c_lowbucket_avail) + if (entry < sun4c_lowbucket_avail) sun4c_lowbucket_avail = entry; free_pages(pages, TASK_STRUCT_ORDER); @@ -1376,10 +1205,10 @@ { int entry; - if(sizeof(union task_union) != (PAGE_SIZE << TASK_STRUCT_ORDER)) { + if (sizeof(union task_union) != (PAGE_SIZE << TASK_STRUCT_ORDER)) { prom_printf("task union not %d page(s)!\n", 1 << TASK_STRUCT_ORDER); } - for(entry = 0; entry < NR_TASKS; entry++) + for (entry = 0; entry < NR_TASK_BUCKETS; entry++) sun4c_bucket[entry] = BUCKET_EMPTY; sun4c_lowbucket_avail = 0; } @@ -1494,37 +1323,38 @@ * by implication and fool the page locking code above * if passed to by mistake. */ -static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct linux_sbus *sbus) +static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus *sbus) { unsigned long page; page = ((unsigned long)bufptr) & PAGE_MASK; - if(MAP_NR(page) > max_mapnr) { + if (MAP_NR(page) > max_mapnr) { sun4c_flush_page(page); return (__u32)bufptr; /* already locked */ } return (__u32)sun4c_lockarea(bufptr, len); } -static void sun4c_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { - while(sz >= 0) { - sg[sz].dvma_addr = (__u32)sun4c_lockarea(sg[sz].addr, sg[sz].len); + while (sz >= 0) { + sg[sz].dvma_address = (__u32)sun4c_lockarea(sg[sz].address, sg[sz].length); + sg[sz].dvma_length = sg[sz].length; sz--; } } -static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct linux_sbus *sbus) +static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_bus *sbus) { - if(bufptr < sun4c_iobuffer_start) + if (bufptr < sun4c_iobuffer_start) return; /* On kernel stack or similar, see above */ sun4c_unlockarea((char *)bufptr, len); } -static void sun4c_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) +static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) { - while(sz >= 0) { - sun4c_unlockarea((char *)sg[sz].dvma_addr, sg[sz].len); + while (sz >= 0) { + sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length); sz--; } } @@ -1534,7 +1364,7 @@ struct vm_area_struct sun4c_kstack_vma; -static unsigned long __init sun4c_init_lock_areas(unsigned long start_mem) +static void __init sun4c_init_lock_areas(void) { unsigned long sun4c_taskstack_start; unsigned long sun4c_taskstack_end; @@ -1543,9 +1373,9 @@ sun4c_init_buckets(); sun4c_taskstack_start = SUN4C_LOCK_VADDR; sun4c_taskstack_end = (sun4c_taskstack_start + - (TASK_ENTRY_SIZE * NR_TASKS)); - if(sun4c_taskstack_end >= SUN4C_LOCK_END) { - prom_printf("Too many tasks, decrease NR_TASKS please.\n"); + (TASK_ENTRY_SIZE * NR_TASK_BUCKETS)); + if (sun4c_taskstack_end >= SUN4C_LOCK_END) { + prom_printf("Too many tasks, decrease NR_TASK_BUCKETS please.\n"); prom_halt(); } @@ -1556,9 +1386,8 @@ bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = LONG_ALIGN(bitmap_size); iobuffer_map_size = bitmap_size << 3; - sun4c_iobuffer_map = (unsigned long *) start_mem; - memset((void *) start_mem, 0, bitmap_size); - start_mem += bitmap_size; + sun4c_iobuffer_map = __alloc_bootmem(bitmap_size, SMP_CACHE_BYTES, 0UL); + memset((void *) sun4c_iobuffer_map, 0, bitmap_size); sun4c_kstack_vma.vm_mm = &init_mm; sun4c_kstack_vma.vm_start = sun4c_taskstack_start; @@ -1566,7 +1395,6 @@ sun4c_kstack_vma.vm_page_prot = PAGE_SHARED; sun4c_kstack_vma.vm_flags = VM_READ | VM_WRITE | VM_EXEC; insert_vm_struct(&init_mm, &sun4c_kstack_vma); - return start_mem; } /* Cache flushing on the sun4c. */ @@ -1574,12 +1402,12 @@ { unsigned long begin, end; - FUW_INLINE + flush_user_windows(); begin = (KERNBASE + SUN4C_REAL_PGDIR_SIZE); end = (begin + SUN4C_VAC_SIZE); - if(sun4c_vacinfo.linesize == 32) { - while(begin < end) { + if (sun4c_vacinfo.linesize == 32) { + while (begin < end) { __asm__ __volatile__(" ld [%0 + 0x00], %%g0 ld [%0 + 0x20], %%g0 @@ -1601,7 +1429,7 @@ begin += 512; } } else { - while(begin < end) { + while (begin < end) { __asm__ __volatile__(" ld [%0 + 0x00], %%g0 ld [%0 + 0x10], %%g0 @@ -1629,29 +1457,31 @@ { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT && sun4c_context_ring[new_ctx].num_entries) { - struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; - unsigned long flags; - - save_and_cli(flags); - if(head->next != head) { - struct sun4c_mmu_entry *entry = head->next; - int savectx = sun4c_get_context(); - - FUW_INLINE - sun4c_set_context(new_ctx); - sun4c_flush_context_hw(); - do { - struct sun4c_mmu_entry *next = entry->next; + if (new_ctx != NO_CONTEXT) { + flush_user_windows(); + if (sun4c_context_ring[new_ctx].num_entries) { + struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; + unsigned long flags; + + save_and_cli(flags); + if (head->next != head) { + struct sun4c_mmu_entry *entry = head->next; + int savectx = sun4c_get_context(); + + sun4c_set_context(new_ctx); + sun4c_flush_context_hw(); + do { + struct sun4c_mmu_entry *next = entry->next; - sun4c_user_unmap(entry); - free_user_entry(new_ctx, entry); + sun4c_user_unmap(entry); + free_user_entry(new_ctx, entry); - entry = next; - } while(entry != head); - sun4c_set_context(savectx); + entry = next; + } while (entry != head); + sun4c_set_context(savectx); + } + restore_flags(flags); } - restore_flags(flags); } } @@ -1659,29 +1489,28 @@ { int new_ctx = mm->context; -#if KGPROF_PROFILING - kgprof_profile(); -#endif - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; struct sun4c_mmu_entry *entry; unsigned long flags; - FUW_INLINE + flush_user_windows(); + save_and_cli(flags); /* All user segmap chains are ordered on entry->vaddr. */ - for(entry = head->next; - (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); - entry = entry->next) + for (entry = head->next; + (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); + entry = entry->next) ; /* Tracing various job mixtures showed that this conditional * only passes ~35% of the time for most worse case situations, * therefore we avoid all of this gross overhead ~65% of the time. */ - if((entry != head) && (entry->vaddr < end)) { + if ((entry != head) && (entry->vaddr < end)) { int octx = sun4c_get_context(); + sun4c_set_context(new_ctx); /* At this point, always, (start >= entry->vaddr) and @@ -1696,11 +1525,11 @@ /* "realstart" is always >= entry->vaddr */ realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE; - if(end < realend) + if (end < realend) realend = end; - if((realend - entry->vaddr) <= (PAGE_SIZE << 3)) { + if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) { unsigned long page = entry->vaddr; - while(page < realend) { + while (page < realend) { sun4c_flush_page_hw(page); page += PAGE_SIZE; } @@ -1710,14 +1539,13 @@ free_user_entry(new_ctx, entry); } entry = next; - } while((entry != head) && (entry->vaddr < end)); + } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } restore_flags(flags); } } -/* XXX no save_and_cli/restore_flags needed, but put here if darkside still crashes */ static void sun4c_flush_cache_page_hw(struct vm_area_struct *vma, unsigned long page) { struct mm_struct *mm = vma->vm_mm; @@ -1726,76 +1554,85 @@ /* Sun4c has no separate I/D caches so cannot optimize for non * text page flushes. */ - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { int octx = sun4c_get_context(); + unsigned long flags; - FUW_INLINE + flush_user_windows(); + save_and_cli(flags); sun4c_set_context(new_ctx); sun4c_flush_page_hw(page); sun4c_set_context(octx); + restore_flags(flags); } } -static void sun4c_flush_page_to_ram_hw(unsigned long page) +static void sun4c_flush_page_to_ram_hw(struct page *page) { - sun4c_flush_page_hw(page); + unsigned long flags; + unsigned long addr = page_address(page); + + save_and_cli(flags); + sun4c_flush_page_hw(addr); + restore_flags(flags); } static void sun4c_flush_cache_mm_sw(struct mm_struct *mm) { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT && sun4c_context_ring[new_ctx].num_entries) { - struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; - unsigned long flags; + if (new_ctx != NO_CONTEXT) { + flush_user_windows(); - save_and_cli(flags); - if(head->next != head) { - struct sun4c_mmu_entry *entry = head->next; - int savectx = sun4c_get_context(); + if (sun4c_context_ring[new_ctx].num_entries) { + struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; + unsigned long flags; + + save_and_cli(flags); + if (head->next != head) { + struct sun4c_mmu_entry *entry = head->next; + int savectx = sun4c_get_context(); + + sun4c_set_context(new_ctx); + sun4c_flush_context_sw(); + do { + struct sun4c_mmu_entry *next = entry->next; - FUW_INLINE - sun4c_set_context(new_ctx); - sun4c_flush_context_sw(); - do { - struct sun4c_mmu_entry *next = entry->next; - - sun4c_user_unmap(entry); - free_user_entry(new_ctx, entry); + sun4c_user_unmap(entry); + free_user_entry(new_ctx, entry); - entry = next; - } while(entry != head); - sun4c_set_context(savectx); + entry = next; + } while (entry != head); + sun4c_set_context(savectx); + } + restore_flags(flags); } - restore_flags(flags); } } static void sun4c_flush_cache_range_sw(struct mm_struct *mm, unsigned long start, unsigned long end) { int new_ctx = mm->context; - -#if KGPROF_PROFILING - kgprof_profile(); -#endif - if(new_ctx != NO_CONTEXT) { + + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; struct sun4c_mmu_entry *entry; unsigned long flags; - FUW_INLINE + flush_user_windows(); + save_and_cli(flags); /* All user segmap chains are ordered on entry->vaddr. */ - for(entry = head->next; - (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); - entry = entry->next) + for (entry = head->next; + (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); + entry = entry->next) ; /* Tracing various job mixtures showed that this conditional * only passes ~35% of the time for most worse case situations, * therefore we avoid all of this gross overhead ~65% of the time. */ - if((entry != head) && (entry->vaddr < end)) { + if ((entry != head) && (entry->vaddr < end)) { int octx = sun4c_get_context(); sun4c_set_context(new_ctx); @@ -1811,11 +1648,11 @@ /* "realstart" is always >= entry->vaddr */ realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE; - if(end < realend) + if (end < realend) realend = end; - if((realend - entry->vaddr) <= (PAGE_SIZE << 3)) { + if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) { unsigned long page = entry->vaddr; - while(page < realend) { + while (page < realend) { sun4c_flush_page_sw(page); page += PAGE_SIZE; } @@ -1825,7 +1662,7 @@ free_user_entry(new_ctx, entry); } entry = next; - } while((entry != head) && (entry->vaddr < end)); + } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } restore_flags(flags); @@ -1840,19 +1677,27 @@ /* Sun4c has no separate I/D caches so cannot optimize for non * text page flushes. */ - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { int octx = sun4c_get_context(); + unsigned long flags; - FUW_INLINE + flush_user_windows(); + save_and_cli(flags); sun4c_set_context(new_ctx); sun4c_flush_page_sw(page); sun4c_set_context(octx); + restore_flags(flags); } } -static void sun4c_flush_page_to_ram_sw(unsigned long page) +static void sun4c_flush_page_to_ram_sw(struct page *page) { - sun4c_flush_page_sw(page); + unsigned long flags; + unsigned long addr = page_address(page); + + save_and_cli(flags); + sun4c_flush_page_sw(addr); + restore_flags(flags); } /* Sun4c cache is unified, both instructions and data live there, so @@ -1879,8 +1724,11 @@ flush_user_windows(); while (sun4c_kernel_ring.num_entries) { next_entry = this_entry->next; - sun4c_flush_segment(this_entry->vaddr); - for(ctx = 0; ctx < num_contexts; ctx++) { + if (sun4c_vacinfo.do_hwflushes) + sun4c_flush_segment_hw(this_entry->vaddr); + else + sun4c_flush_segment_sw(this_entry->vaddr); + for (ctx = 0; ctx < num_contexts; ctx++) { sun4c_set_context(ctx); sun4c_put_segmap(this_entry->vaddr, invalid_segment); } @@ -1895,16 +1743,15 @@ { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; unsigned long flags; save_and_cli(flags); - if(head->next != head) { + if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); - FUW_INLINE sun4c_set_context(new_ctx); sun4c_flush_context_hw(); do { @@ -1914,7 +1761,7 @@ free_user_entry(new_ctx, entry); entry = next; - } while(entry != head); + } while (entry != head); sun4c_set_context(savectx); } restore_flags(flags); @@ -1925,26 +1772,21 @@ { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; struct sun4c_mmu_entry *entry; unsigned long flags; -#if KGPROF_PROFILING - kgprof_profile(); -#endif save_and_cli(flags); /* See commentary in sun4c_flush_cache_range_*(). */ - for(entry = head->next; - (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); - entry = entry->next) + for (entry = head->next; + (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); + entry = entry->next) ; - if((entry != head) && (entry->vaddr < end)) { + if ((entry != head) && (entry->vaddr < end)) { int octx = sun4c_get_context(); - /* This window flush is paranoid I think... -DaveM */ - FUW_INLINE sun4c_set_context(new_ctx); do { struct sun4c_mmu_entry *next = entry->next; @@ -1954,7 +1796,7 @@ free_user_entry(new_ctx, entry); entry = next; - } while((entry != head) && (entry->vaddr < end)); + } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } restore_flags(flags); @@ -1966,15 +1808,17 @@ struct mm_struct *mm = vma->vm_mm; int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { int savectx = sun4c_get_context(); + unsigned long flags; - FUW_INLINE + save_and_cli(flags); sun4c_set_context(new_ctx); page &= PAGE_MASK; sun4c_flush_page_hw(page); sun4c_put_pte(page, 0); sun4c_set_context(savectx); + restore_flags(flags); } } @@ -1982,16 +1826,15 @@ { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; unsigned long flags; save_and_cli(flags); - if(head->next != head) { + if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); - FUW_INLINE sun4c_set_context(new_ctx); sun4c_flush_context_sw(); do { @@ -2001,7 +1844,7 @@ free_user_entry(new_ctx, entry); entry = next; - } while(entry != head); + } while (entry != head); sun4c_set_context(savectx); } restore_flags(flags); @@ -2012,27 +1855,21 @@ { int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; struct sun4c_mmu_entry *entry; unsigned long flags; -#if KGPROF_PROFILING - kgprof_profile(); -#endif - save_and_cli(flags); /* See commentary in sun4c_flush_cache_range_*(). */ - for(entry = head->next; - (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); - entry = entry->next) + for (entry = head->next; + (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); + entry = entry->next) ; - if((entry != head) && (entry->vaddr < end)) { + if ((entry != head) && (entry->vaddr < end)) { int octx = sun4c_get_context(); - /* This window flush is paranoid I think... -DaveM */ - FUW_INLINE sun4c_set_context(new_ctx); do { struct sun4c_mmu_entry *next = entry->next; @@ -2042,7 +1879,7 @@ free_user_entry(new_ctx, entry); entry = next; - } while((entry != head) && (entry->vaddr < end)); + } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } restore_flags(flags); @@ -2054,15 +1891,17 @@ struct mm_struct *mm = vma->vm_mm; int new_ctx = mm->context; - if(new_ctx != NO_CONTEXT) { + if (new_ctx != NO_CONTEXT) { int savectx = sun4c_get_context(); + unsigned long flags; - FUW_INLINE + save_and_cli(flags); sun4c_set_context(new_ctx); page &= PAGE_MASK; sun4c_flush_page_sw(page); sun4c_put_pte(page, 0); sun4c_set_context(savectx); + restore_flags(flags); } } @@ -2075,7 +1914,6 @@ { } - void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_type, int rdonly) { @@ -2083,7 +1921,7 @@ page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK); page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT)); - if(rdonly) + if (rdonly) page_entry &= ~_SUN4C_WRITEABLE; sun4c_put_pte(virt_addr, page_entry); } @@ -2093,12 +1931,12 @@ sun4c_put_pte(virt_addr, 0); } -static void sun4c_alloc_context_hw(struct mm_struct *mm) +static void sun4c_alloc_context_hw(struct mm_struct *old_mm, struct mm_struct *mm) { struct ctx_list *ctxp; ctxp = ctx_free.next; - if(ctxp != &ctx_free) { + if (ctxp != &ctx_free) { remove_from_ctx_list(ctxp); add_to_used_ctxlist(ctxp); mm->context = ctxp->ctx_number; @@ -2106,40 +1944,37 @@ return; } ctxp = ctx_used.next; - if(ctxp->ctx_mm == current->mm) + if (ctxp->ctx_mm == old_mm) ctxp = ctxp->next; -#ifdef DEBUG_SUN4C_MM - if(ctxp == &ctx_used) - panic("out of mmu contexts"); -#endif remove_from_ctx_list(ctxp); add_to_used_ctxlist(ctxp); ctxp->ctx_mm->context = NO_CONTEXT; ctxp->ctx_mm = mm; mm->context = ctxp->ctx_number; sun4c_demap_context_hw(&sun4c_context_ring[ctxp->ctx_number], - ctxp->ctx_number); + ctxp->ctx_number); } -static void sun4c_switch_to_context_hw(struct task_struct *tsk) +/* Switch the current MM context. */ +static void sun4c_switch_mm_hw(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu) { struct ctx_list *ctx; + int dirty = 0; - if(tsk->mm->context == NO_CONTEXT) { - sun4c_alloc_context_hw(tsk->mm); + if (mm->context == NO_CONTEXT) { + dirty = 1; + sun4c_alloc_context_hw(old_mm, mm); } else { /* Update the LRU ring of contexts. */ - ctx = ctx_list_pool + tsk->mm->context; + ctx = ctx_list_pool + mm->context; +#ifdef DEBUG_SUN4C_MM + if (!ctx->ctx_mm) + panic("context was not set up"); +#endif remove_from_ctx_list(ctx); add_to_used_ctxlist(ctx); } - sun4c_set_context(tsk->mm->context); -} - -static void sun4c_init_new_context_hw(struct mm_struct *mm) -{ - sun4c_alloc_context_hw(mm); - if(mm == current->mm) + if (dirty || old_mm != mm) sun4c_set_context(mm->context); } @@ -2147,7 +1982,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if (mm->context != NO_CONTEXT) { sun4c_demap_context_hw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); @@ -2156,12 +1991,12 @@ } } -static void sun4c_alloc_context_sw(struct mm_struct *mm) +static void sun4c_alloc_context_sw(struct mm_struct *old_mm, struct mm_struct *mm) { struct ctx_list *ctxp; ctxp = ctx_free.next; - if(ctxp != &ctx_free) { + if (ctxp != &ctx_free) { remove_from_ctx_list(ctxp); add_to_used_ctxlist(ctxp); mm->context = ctxp->ctx_number; @@ -2169,40 +2004,38 @@ return; } ctxp = ctx_used.next; - if(ctxp->ctx_mm == current->mm) + if(ctxp->ctx_mm == old_mm) ctxp = ctxp->next; -#ifdef DEBUG_SUN4C_MM - if(ctxp == &ctx_used) - panic("out of mmu contexts"); -#endif remove_from_ctx_list(ctxp); add_to_used_ctxlist(ctxp); ctxp->ctx_mm->context = NO_CONTEXT; ctxp->ctx_mm = mm; mm->context = ctxp->ctx_number; sun4c_demap_context_sw(&sun4c_context_ring[ctxp->ctx_number], - ctxp->ctx_number); + ctxp->ctx_number); } -static void sun4c_switch_to_context_sw(struct task_struct *tsk) +/* Switch the current MM context. */ +static void sun4c_switch_mm_sw(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu) { struct ctx_list *ctx; + int dirty = 0; - if(tsk->mm->context == NO_CONTEXT) { - sun4c_alloc_context_sw(tsk->mm); + if (mm->context == NO_CONTEXT) { + dirty = 1; + sun4c_alloc_context_sw(old_mm, mm); } else { /* Update the LRU ring of contexts. */ - ctx = ctx_list_pool + tsk->mm->context; + ctx = ctx_list_pool + mm->context; +#ifdef DEBUG_SUN4C_MM + if (!ctx->ctx_mm) + panic("context was not set up"); +#endif remove_from_ctx_list(ctx); add_to_used_ctxlist(ctx); } - sun4c_set_context(tsk->mm->context); -} -static void sun4c_init_new_context_sw(struct mm_struct *mm) -{ - sun4c_alloc_context_sw(mm); - if(mm == current->mm) + if (dirty || old_mm != mm) sun4c_set_context(mm->context); } @@ -2210,7 +2043,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if (mm->context != NO_CONTEXT) { sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); @@ -2225,7 +2058,7 @@ int len; used_user_entries = 0; - for(i=0; i < num_contexts; i++) + for (i = 0; i < num_contexts; i++) used_user_entries += sun4c_context_ring[i].num_entries; len = sprintf(buf, @@ -2239,10 +2072,7 @@ "usedpsegs\t: %d\n" "ufreepsegs\t: %d\n" "user_taken\t: %d\n" - "max_taken\t: %d\n" - "context\t\t: %d flushes\n" - "segment\t\t: %d flushes\n" - "page\t\t: %d flushes\n", + "max_taken\t: %d\n", sun4c_vacinfo.num_bytes, (sun4c_vacinfo.do_hwflushes ? "yes" : "no"), sun4c_vacinfo.linesize, @@ -2253,22 +2083,7 @@ used_user_entries, sun4c_ufree_ring.num_entries, sun4c_user_taken_entries, - max_user_taken_entries, - ctxflushes, segflushes, pageflushes); - -#if KGPROF_PROFILING - { - int i,j; - len += sprintf(buf + len,"kgprof profiling:\n"); - for (i=0;i> PAGE_SHIFT) | pgprot_val(pgprot)); + return __pte((page - mem_map) | pgprot_val(pgprot)); } static pte_t sun4c_mk_pte_phys(unsigned long phys_page, pgprot_t pgprot) @@ -2419,17 +2174,9 @@ return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot)); } -#if 0 /* Not used due to BTFIXUPs */ -static pte_t sun4c_pte_modify(pte_t pte, pgprot_t newprot) -{ - return __pte((pte_val(pte) & _SUN4C_PAGE_CHG_MASK) | - pgprot_val(newprot)); -} -#endif - -static unsigned long sun4c_pte_page(pte_t pte) +static unsigned long sun4c_pte_pagenr(pte_t pte) { - return (PAGE_OFFSET + ((pte_val(pte) & SUN4C_PFN_MASK) << (PAGE_SHIFT))); + return (pte_val(pte) & SUN4C_PFN_MASK); } static inline unsigned long sun4c_pmd_page(pmd_t pmd) @@ -2460,11 +2207,6 @@ return (pte_t *) sun4c_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1)); } -/* Update the root mmu directory. */ -static void sun4c_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdir) -{ -} - /* Please take special note on the foo_kernel() routines below, our * fast in window fault handler wants to get at the pte's for vmalloc * area with traps off, therefore they _MUST_ be locked down to prevent @@ -2487,7 +2229,7 @@ static pte_t *sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address) { - if(address >= SUN4C_LOCK_VADDR) + if (address >= SUN4C_LOCK_VADDR) return NULL; address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1); if (sun4c_pmd_none(*pmd)) @@ -2527,7 +2269,7 @@ { unsigned long *ret; - if((ret = pgd_quicklist) != NULL) { + if ((ret = pgd_quicklist) != NULL) { pgd_quicklist = (unsigned long *)(*ret); ret[0] = ret[1]; pgtable_cache_size--; @@ -2546,15 +2288,15 @@ static int sun4c_check_pgt_cache(int low, int high) { int freed = 0; - if(pgtable_cache_size > high) { + if (pgtable_cache_size > high) { do { - if(pgd_quicklist) + if (pgd_quicklist) free_pgd_slow(get_pgd_fast()), freed++; - if(pmd_quicklist) + if (pmd_quicklist) free_pmd_slow(get_pmd_fast()), freed++; - if(pte_quicklist) + if (pte_quicklist) free_pte_slow(get_pte_fast()), freed++; - } while(pgtable_cache_size > low); + } while (pgtable_cache_size > low); } return freed; } @@ -2575,7 +2317,7 @@ { unsigned long *ret; - if((ret = (unsigned long *)pte_quicklist) != NULL) { + if ((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); ret[0] = ret[1]; pgtable_cache_size--; @@ -2691,19 +2433,21 @@ unsigned long start; /* Do not mistake ourselves as another mapping. */ - if(vmaring == vma) + if (vmaring == vma) continue; if (S4CVAC_BADALIAS(vaddr, address)) { alias_found++; start = vmaring->vm_start; - while(start < vmaring->vm_end) { + while (start < vmaring->vm_end) { pgdp = sun4c_pgd_offset(vmaring->vm_mm, start); - if(!pgdp) goto next; + if (!pgdp) + goto next; ptep = sun4c_pte_offset((pmd_t *) pgdp, start); - if(!ptep) goto next; + if (!ptep) + goto next; - if(pte_val(*ptep) & _SUN4C_PAGE_PRESENT) { + if (pte_val(*ptep) & _SUN4C_PAGE_PRESENT) { flush_cache_page(vmaring, start); *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_NOCACHE); @@ -2716,7 +2460,7 @@ } while ((vmaring = vmaring->vm_next_share) != NULL); spin_unlock(&inode->i_shared_lock); - if(alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) { + if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) { pgdp = sun4c_pgd_offset(vma->vm_mm, address); ptep = sun4c_pte_offset((pmd_t *) pgdp, address); *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_NOCACHE); @@ -2725,45 +2469,103 @@ } } +/* An experiment, turn off by default for now... -DaveM */ +#define SUN4C_PRELOAD_PSEG + void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { unsigned long flags; + int pseg; save_and_cli(flags); address &= PAGE_MASK; - if(sun4c_get_segmap(address) == invalid_segment) - alloc_user_segment(address, sun4c_get_context()); + if ((pseg = sun4c_get_segmap(address)) == invalid_segment) { + struct sun4c_mmu_entry *entry = sun4c_user_strategy(); + struct mm_struct *mm = vma->vm_mm; + unsigned long start, end; + + entry->vaddr = start = (address & SUN4C_REAL_PGDIR_MASK); + entry->ctx = mm->context; + add_ring_ordered(sun4c_context_ring + mm->context, entry); + sun4c_put_segmap(entry->vaddr, entry->pseg); + end = start + SUN4C_REAL_PGDIR_SIZE; + while (start < end) { +#ifdef SUN4C_PRELOAD_PSEG + pgd_t *pgdp = sun4c_pgd_offset(mm, start); + pte_t *ptep; + + if (!pgdp) + goto no_mapping; + ptep = sun4c_pte_offset((pmd_t *) pgdp, start); + if (!ptep || !(pte_val(*ptep) & _SUN4C_PAGE_PRESENT)) + goto no_mapping; + sun4c_put_pte(start, pte_val(*ptep)); + goto next; + + no_mapping: +#endif + sun4c_put_pte(start, 0); +#ifdef SUN4C_PRELOAD_PSEG + next: +#endif + start += PAGE_SIZE; + } + if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) + sun4c_vac_alias_fixup(vma, address, pte); +#ifndef SUN4C_PRELOAD_PSEG + sun4c_put_pte(address, pte_val(pte)); +#endif + restore_flags(flags); + return; + } else { + struct sun4c_mmu_entry *entry = &mmu_entry_pool[pseg]; + + remove_lru(entry); + add_lru(entry); + } - if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) + if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) sun4c_vac_alias_fixup(vma, address, pte); sun4c_put_pte(address, pte_val(pte)); restore_flags(flags); } -extern unsigned long free_area_init(unsigned long, unsigned long); -extern unsigned long sparc_context_init(unsigned long, int); +extern void sparc_context_init(int); extern unsigned long end; +extern unsigned long bootmem_init(void); +extern unsigned long last_valid_pfn; +extern void sun_serial_setup(void); -unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem) +void __init sun4c_paging_init(void) { int i, cnt; unsigned long kernel_end, vaddr; - extern unsigned long sparc_iobase_vaddr; + extern struct resource sparc_iomap; + unsigned long end_pfn; kernel_end = (unsigned long) &end; kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4); kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end); + + last_valid_pfn = end_pfn = bootmem_init(); + + /* 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(); + sun4c_probe_mmu(); invalid_segment = (num_segmaps - 1); sun4c_init_mmu_entry_pool(); - sun4c_init_rings(&start_mem); + sun4c_init_rings(); sun4c_init_map_kernelprom(kernel_end); sun4c_init_clean_mmu(kernel_end); sun4c_init_fill_kernel_ring(SUN4C_KERNEL_BUCKETS); - sun4c_init_lock_area(sparc_iobase_vaddr, IOBASE_END); + sun4c_init_lock_area(sparc_iomap.start, IOBASE_END); sun4c_init_lock_area(DVMA_VADDR, DVMA_END); - start_mem = sun4c_init_lock_areas(start_mem); + sun4c_init_lock_areas(); sun4c_init_fill_user_ring(); sun4c_set_context(0); @@ -2783,18 +2585,16 @@ vaddr += SUN4C_PGDIR_SIZE; swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg3); sun4c_init_ss2_cache_bug(); - start_mem = PAGE_ALIGN(start_mem); - start_mem = sparc_context_init(start_mem, num_contexts); - start_mem = free_area_init(start_mem, end_mem); + sparc_context_init(num_contexts); + free_area_init(end_pfn); cnt = 0; - for(i = 0; i < num_segmaps; i++) - if(mmu_entry_pool[i].locked) + for (i = 0; i < num_segmaps; i++) + if (mmu_entry_pool[i].locked) cnt++; max_user_taken_entries = num_segmaps - cnt - 40 - 1; printk("SUN4C: %d mmu entries for the kernel\n", cnt); - return start_mem; } /* Load up routines and constants for sun4c mmu */ @@ -2839,7 +2639,7 @@ BTFIXUPSET_CALL(flush_cache_all, sun4c_flush_cache_all, BTFIXUPCALL_NORM); - if(sun4c_vacinfo.do_hwflushes) { + if (sun4c_vacinfo.do_hwflushes) { BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_hw, BTFIXUPCALL_NORM); @@ -2848,9 +2648,8 @@ BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(free_task_struct, sun4c_free_task_struct_hw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(switch_to_context, sun4c_switch_to_context_hw, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_hw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(init_new_context, sun4c_init_new_context_hw, BTFIXUPCALL_NORM); } else { BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_sw, BTFIXUPCALL_NORM); @@ -2860,9 +2659,8 @@ BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(free_task_struct, sun4c_free_task_struct_sw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(switch_to_context, sun4c_switch_to_context_sw, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_sw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(init_new_context, sun4c_init_new_context_sw, BTFIXUPCALL_NORM); } BTFIXUPSET_CALL(flush_tlb_all, sun4c_flush_tlb_all, BTFIXUPCALL_NORM); @@ -2871,15 +2669,13 @@ BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0); - BTFIXUPSET_CALL(pte_page, sun4c_pte_page, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM); #if PAGE_SHIFT <= 12 BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1)); #else BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_NORM); #endif - BTFIXUPSET_CALL(sparc_update_rootmmu_dir, sun4c_update_rootmmu_dir, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0); @@ -2931,6 +2727,9 @@ BTFIXUPSET_CALL(mmu_release_scsi_sgl, sun4c_release_scsi_sgl, BTFIXUPCALL_NORM); 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_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP); + BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_v2p, sun4c_v2p, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_p2v, sun4c_p2v, BTFIXUPCALL_NORM); diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S --- v2.3.34/linux/arch/sparc/mm/swift.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc/mm/swift.S Mon Dec 20 22:05:52 1999 @@ -0,0 +1,275 @@ +/* $Id: swift.S,v 1.3 1999/11/14 06:13:56 zaitcev Exp $ + * swift.S: MicroSparc-II mmu/cache operations. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +#include +#include +#include +#include +#include + +#define WINDOW_FLUSH(tmp1, tmp2) \ + mov 0, tmp1; \ +98: ld [%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2; \ + orcc %g0, tmp2, %g0; \ + add tmp1, 1, tmp1; \ + bne 98b; \ + save %sp, -64, %sp; \ +99: subcc tmp1, 1, tmp1; \ + bne 99b; \ + restore %g0, %g0, %g0; + + .text + .align 4 + +#if 1 /* XXX screw this, I can't get the VAC flushes working + * XXX reliably... -DaveM + */ + .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_to_ram + +swift_flush_cache_all: +swift_flush_cache_mm: +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 + sta %g0, [%o0] ASI_M_TXTC_TAG + sta %g0, [%o0] ASI_M_DATAC_TAG + bne 1b + nop + retl + nop +#else + + .globl swift_flush_cache_all +swift_flush_cache_all: + WINDOW_FLUSH(%g4, %g5) + + /* Just clear out all the tags. */ + sethi %hi(16 * 1024), %o0 +1: subcc %o0, 16, %o0 + sta %g0, [%o0] ASI_M_TXTC_TAG + bne 1b + sta %g0, [%o0] ASI_M_DATAC_TAG + retl + nop + + .globl swift_flush_cache_mm +swift_flush_cache_mm: +#ifndef __SMP__ + ld [%o0 + AOFF_mm_context], %g2 + cmp %g2, -1 + be swift_flush_cache_mm_out +#endif + WINDOW_FLUSH(%g4, %g5) + rd %psr, %g1 + andn %g1, PSR_ET, %g3 + wr %g3, 0x0, %psr + nop + nop + mov SRMMU_CTX_REG, %g7 + lda [%g7] ASI_M_MMUREGS, %g5 + sta %g2, [%g7] ASI_M_MMUREGS + +#if 1 + sethi %hi(0x2000), %o0 +1: subcc %o0, 0x10, %o0 + sta %g0, [%o0] ASI_M_FLUSH_CTX + bne 1b + nop +#else + clr %o0 + or %g0, 2048, %g7 + or %g0, 2048, %o1 + add %o1, 2048, %o2 + add %o2, 2048, %o3 + mov 16, %o4 + add %o4, 2048, %o5 + add %o5, 2048, %g2 + add %g2, 2048, %g3 +1: sta %g0, [%o0 ] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %o1] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %o2] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %o3] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %o4] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %o5] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %g2] ASI_M_FLUSH_CTX + sta %g0, [%o0 + %g3] ASI_M_FLUSH_CTX + subcc %g7, 32, %g7 + bne 1b + add %o0, 32, %o0 +#endif + + mov SRMMU_CTX_REG, %g7 + sta %g5, [%g7] ASI_M_MMUREGS + wr %g1, 0x0, %psr + nop + nop +swift_flush_cache_mm_out: + retl + nop + + .globl swift_flush_cache_range +swift_flush_cache_range: + sub %o2, %o1, %o2 + sethi %hi(4096), %o3 + cmp %o2, %o3 + bgu swift_flush_cache_mm + nop + b 70f + nop + + .globl swift_flush_cache_page +swift_flush_cache_page: + ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ +70: +#ifndef __SMP__ + ld [%o0 + AOFF_mm_context], %g2 + cmp %g2, -1 + be swift_flush_cache_page_out +#endif + WINDOW_FLUSH(%g4, %g5) + rd %psr, %g1 + andn %g1, PSR_ET, %g3 + wr %g3, 0x0, %psr + nop + nop + mov SRMMU_CTX_REG, %g7 + lda [%g7] ASI_M_MMUREGS, %g5 + sta %g2, [%g7] ASI_M_MMUREGS + + andn %o1, (PAGE_SIZE - 1), %o1 +#if 1 + sethi %hi(0x1000), %o0 +1: subcc %o0, 0x10, %o0 + sta %g0, [%o1 + %o0] ASI_M_FLUSH_PAGE + bne 1b + nop +#else + or %g0, 512, %g7 + or %g0, 512, %o0 + add %o0, 512, %o2 + add %o2, 512, %o3 + add %o3, 512, %o4 + add %o4, 512, %o5 + add %o5, 512, %g3 + add %g3, 512, %g4 +1: sta %g0, [%o1 ] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o0] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o2] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o3] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o4] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o5] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %g3] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %g4] ASI_M_FLUSH_PAGE + subcc %g7, 16, %g7 + bne 1b + add %o1, 16, %o1 +#endif + + mov SRMMU_CTX_REG, %g7 + sta %g5, [%g7] ASI_M_MMUREGS + wr %g1, 0x0, %psr + nop + nop +swift_flush_cache_page_out: + retl + nop + + /* Swift is write-thru, however it is not + * I/O nor TLB-walk coherent. Also it has + * 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 + sethi %hi(0x1000), %o0 +1: subcc %o0, 0x10, %o0 + sta %g0, [%o1 + %o0] ASI_M_FLUSH_PAGE + bne 1b + nop +#else + or %g0, 512, %g7 + or %g0, 512, %o0 + add %o0, 512, %o2 + add %o2, 512, %o3 + add %o3, 512, %o4 + add %o4, 512, %o5 + add %o5, 512, %g3 + add %g3, 512, %g4 +1: sta %g0, [%o1 ] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o0] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o2] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o3] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o4] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %o5] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %g3] ASI_M_FLUSH_PAGE + sta %g0, [%o1 + %g4] ASI_M_FLUSH_PAGE + subcc %g7, 16, %g7 + bne 1b + add %o1, 16, %o1 +#endif + retl + nop +#endif + + .globl swift_flush_sig_insns +swift_flush_sig_insns: + flush %o1 + retl + flush %o1 + 4 + + .globl swift_flush_tlb_mm + .globl swift_flush_tlb_range + .globl swift_flush_tlb_all +swift_flush_tlb_mm: +swift_flush_tlb_range: +#ifndef __SMP__ + ld [%o0 + AOFF_mm_context], %g2 + cmp %g2, -1 + be swift_flush_tlb_all_out +#endif +swift_flush_tlb_all: + mov 0x400, %o1 + sta %g0, [%o1] ASI_M_FLUSH_PROBE +swift_flush_tlb_all_out: + retl + nop + + .globl swift_flush_tlb_page +swift_flush_tlb_page: + ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + mov SRMMU_CTX_REG, %g1 + ld [%o0 + AOFF_mm_context], %o3 + andn %o1, (PAGE_SIZE - 1), %o1 +#ifndef __SMP__ + cmp %o3, -1 + be swift_flush_tlb_page_out + nop +#endif +#if 1 + mov 0x400, %o1 + sta %g0, [%o1] ASI_M_FLUSH_PROBE +#else + lda [%g1] ASI_M_MMUREGS, %g5 + sta %o3, [%g1] ASI_M_MMUREGS + sta %g0, [%o1] ASI_M_FLUSH_PAGE /* rem. virt. cache. prot. */ + sta %g0, [%o1] ASI_M_FLUSH_PROBE + sta %g5, [%g1] ASI_M_MMUREGS +#endif +swift_flush_tlb_page_out: + retl + nop diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/tsunami.S linux/arch/sparc/mm/tsunami.S --- v2.3.34/linux/arch/sparc/mm/tsunami.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/tsunami.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: tsunami.S,v 1.2 1999/08/14 03:51:48 anton Exp $ +/* $Id: tsunami.S,v 1.3 1999/10/09 05:32:19 zaitcev Exp $ * tsunami.S: High speed MicroSparc-I mmu/cache operations. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -44,11 +44,11 @@ tsunami_flush_cache_all: WINDOW_FLUSH(%g4, %g5) tsunami_flush_page_for_dma: - sta %g0, [%g0] ASI_M_DC_FLCLEAR 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: -tsunami_flush_chunk: retl nop @@ -68,6 +68,11 @@ tsunami_flush_tlb_all: mov 0x400, %o1 sta %g0, [%o1] ASI_M_FLUSH_PROBE + nop + nop + nop + nop + nop tsunami_flush_tlb_out: retl nop @@ -85,6 +90,59 @@ lda [%g1] ASI_M_MMUREGS, %g5 sta %o3, [%g1] ASI_M_MMUREGS sta %g0, [%o1] ASI_M_FLUSH_PROBE + nop + nop + nop + nop + nop tsunami_flush_tlb_page_out: retl sta %g5, [%g1] ASI_M_MMUREGS + +#define MIRROR_BLOCK(dst, src, offset, t0, t1, t2, t3) \ + ldd [src + offset + 0x18], t0; \ + std t0, [dst + offset + 0x18]; \ + ldd [src + offset + 0x10], t2; \ + std t2, [dst + offset + 0x10]; \ + ldd [src + offset + 0x08], t0; \ + std t0, [dst + offset + 0x08]; \ + ldd [src + offset + 0x00], t2; \ + std t2, [dst + offset + 0x00]; + + .globl tsunami_copy_1page +tsunami_copy_1page: +/* NOTE: This routine has to be shorter than 70insns --jj */ + or %g0, (PAGE_SIZE >> 8), %g1 +1: + MIRROR_BLOCK(%o0, %o1, 0x00, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0x20, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0x40, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0x60, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0x80, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0xa0, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0xc0, %o2, %o3, %o4, %o5) + MIRROR_BLOCK(%o0, %o1, 0xe0, %o2, %o3, %o4, %o5) + subcc %g1, 1, %g1 + add %o0, 0x100, %o0 + bne 1b + add %o1, 0x100, %o1 + + .globl tsunami_setup_blockops +tsunami_setup_blockops: + sethi %hi(__copy_1page), %o0 + or %o0, %lo(__copy_1page), %o0 + sethi %hi(tsunami_copy_1page), %o1 + or %o1, %lo(tsunami_copy_1page), %o1 + sethi %hi(tsunami_setup_blockops), %o2 + or %o2, %lo(tsunami_setup_blockops), %o2 + ld [%o1], %o4 +1: add %o1, 4, %o1 + st %o4, [%o0] + add %o0, 4, %o0 + cmp %o1, %o2 + bne 1b + ld [%o1], %o4 + sta %g0, [%g0] ASI_M_IC_FLCLEAR + sta %g0, [%g0] ASI_M_DC_FLCLEAR + retl + nop diff -u --recursive --new-file v2.3.34/linux/arch/sparc/prom/Makefile linux/arch/sparc/prom/Makefile --- v2.3.34/linux/arch/sparc/prom/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc/prom/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.6 1998/01/30 10:58:59 jj Exp $ +# $Id: Makefile,v 1.7 1999/12/21 04:02:21 davem Exp $ # Makefile for the Sun Boot PROM interface library under # Linux. # diff -u --recursive --new-file v2.3.34/linux/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c --- v2.3.34/linux/arch/sparc/prom/ranges.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/prom/ranges.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ranges.c,v 1.12 1999/08/31 06:54:47 davem Exp $ +/* $Id: ranges.c,v 1.14 1999/10/06 19:28:54 zaitcev Exp $ * ranges.c: Handle ranges in newer proms for obio/sbus. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -64,24 +65,6 @@ prom_adjust_regs(regs, nregs, promlib_obio_ranges, num_obio_ranges); } -/* Apply probed sbus ranges to registers passed, if no ranges return. */ -void prom_apply_sbus_ranges(struct linux_sbus *sbus, struct linux_prom_registers *regs, - int nregs, struct linux_sbus_device *sdev) -{ - if(sbus && sbus->num_sbus_ranges) { - if(sdev && (sdev->ranges_applied == 0)) { - sdev->ranges_applied = 1; - prom_adjust_regs(regs, nregs, sbus->sbus_ranges, - sbus->num_sbus_ranges); - } else if(!sdev) { - printk("PROMLIB: Aieee, old SBUS driver, update it to use new " - "prom_apply_sbus_ranges interface now!\n"); - prom_adjust_regs(regs, nregs, sbus->sbus_ranges, - sbus->num_sbus_ranges); - } - } -} - void __init prom_ranges_init(void) { int node, obio_node; @@ -105,32 +88,6 @@ prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges); return; -} - -void __init prom_sbus_ranges_init(int parentnd, struct linux_sbus *sbus) -{ - int success; - - sbus->num_sbus_ranges = 0; - if(sparc_cpu_model == sun4c) - return; - success = prom_getproperty(sbus->prom_node, "ranges", - (char *) sbus->sbus_ranges, - sizeof (sbus->sbus_ranges)); - if (success != -1) - sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges)); - if (sparc_cpu_model == sun4d) { - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; - int num_iounit_ranges; - - success = prom_getproperty(parentnd, "ranges", - (char *) iounit_ranges, - sizeof (iounit_ranges)); - if (success != -1) { - num_iounit_ranges = (success/sizeof(struct linux_prom_ranges)); - prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges); - } - } } void diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile --- v2.3.34/linux/arch/sparc64/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc64/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.40 1999/08/19 02:31:57 davem Exp $ +# $Id: Makefile,v 1.41 1999/12/21 04:02:23 davem Exp $ # sparc64/Makefile # # Makefile for the architecture dependent flags and dependencies on the diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.34/linux/arch/sparc64/config.in Wed Dec 8 14:11:25 1999 +++ linux/arch/sparc64/config.in Wed Dec 22 19:55:38 1999 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.78 1999/09/06 01:17:28 davem Exp $ +# $Id: config.in,v 1.86 1999/12/23 01:46:09 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -41,17 +41,13 @@ source drivers/sbus/char/Config.in source drivers/sbus/audio/Config.in -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS -fi +tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then - choice 'Kernel core (/proc/kcore) format' \ - "ELF CONFIG_KCORE_ELF \ - A.OUT CONFIG_KCORE_AOUT" ELF + define_bool CONFIG_KCORE_ELF y fi bool 'Kernel support for Linux/Sparc 32bit binary compatibility' CONFIG_SPARC32_COMPAT if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; then @@ -60,6 +56,7 @@ fi tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'Solaris binary emulation (EXPERIMENTAL)' CONFIG_SOLARIS_EMUL fi @@ -148,7 +145,7 @@ mainmenu_option next_comment comment 'SCSI low-level drivers' - bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI + tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI if [ "$CONFIG_PCI" != "n" ]; then @@ -159,8 +156,8 @@ bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N int ' Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5 fi - dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI - if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then + dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI + if [ "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8 int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32 int 'synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10 @@ -190,7 +187,10 @@ tristate ' Dummy net driver support' CONFIG_DUMMY tristate ' PPP (point-to-point) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then - comment ' CCP compressors for PPP are only built as modules.' + dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP + dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP + dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP + dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m fi tristate ' SLIP (serial line) support' CONFIG_SLIP if [ "$CONFIG_SLIP" != "n" ]; then diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.3.34/linux/arch/sparc64/defconfig Tue Dec 14 01:27:23 1999 +++ linux/arch/sparc64/defconfig Mon Dec 20 22:05:52 1999 @@ -8,13 +8,6 @@ CONFIG_EXPERIMENTAL=y # -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# # General setup # CONFIG_VT=y @@ -26,11 +19,21 @@ # CONFIG_PROM_CONSOLE=y CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_RIVA is not set # CONFIG_FB_CLGEN is not set -# CONFIG_FB_PM2 is not set +CONFIG_FB_PM2=y +# CONFIG_FB_PM2_FIFO_DISCONNECT is not set +CONFIG_FB_PM2_PCI=y # CONFIG_FB_MATROX is not set CONFIG_FB_ATY=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set CONFIG_FB_SBUS=y CONFIG_FB_CREATOR=y CONFIG_FB_CGSIX=y @@ -73,6 +76,7 @@ # CONFIG_SUN_VIDEOPIX is not set CONFIG_SUN_AURORA=m # CONFIG_TADPOLE_TS102_UCTRL is not set +# CONFIG_SUN_JSFLASH is not set CONFIG_APM_RTC_IS_GMT=y # CONFIG_RTC is not set @@ -90,12 +94,12 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set CONFIG_SPARC32_COMPAT=y -CONFIG_BINFMT_ELF=y CONFIG_BINFMT_ELF32=y # CONFIG_BINFMT_AOUT32 is not set +CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_SUNOS_EMUL is not set CONFIG_SOLARIS_EMUL=m CONFIG_PARPORT=m CONFIG_PARPORT_PC=m @@ -110,12 +114,18 @@ CONFIG_ENVCTRL=m # +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Floppy, IDE, and other block devices # CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_MD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_RAM is not set CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_IDE=y @@ -127,7 +137,7 @@ CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_AUTO=y -IDEDMA_NEW_DRIVE_LISTINGS=y +CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_CMD646=y @@ -210,11 +220,11 @@ CONFIG_SCSI_SUNESP=y CONFIG_SCSI_QLOGICPTI=m CONFIG_SCSI_AIC7XXX=y -# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set -# CONFIG_CMDS_PER_DEVICE is not set +CONFIG_AIC7XXX_TAGGED_QUEUEING=y +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_PROC_STATS=y CONFIG_AIC7XXX_RESET_DELAY=5 -CONFIG_SCSI_NCR53C8XX=y +CONFIG_SCSI_SYM53C8XX=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=10 @@ -245,10 +255,10 @@ CONFIG_NETDEVICES=y CONFIG_DUMMY=m CONFIG_PPP=m - -# -# CCP compressors for PPP are only built as modules. -# +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y @@ -275,7 +285,7 @@ # Video For Linux # CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_BT848=y +# CONFIG_VIDEO_BT848 is not set # # Filesystems @@ -285,6 +295,8 @@ # CONFIG_ADFS_FS is not set CONFIG_AFFS_FS=m # CONFIG_HFS_FS is not set +CONFIG_BFS_FS=m +# CONFIG_BFS_FS_WRITE is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set @@ -292,8 +304,6 @@ CONFIG_EFS_FS=m CONFIG_ISO9660_FS=m # CONFIG_JOLIET is not set -CONFIG_UDF_FS=m -# CONFIG_UDF_RW is not set CONFIG_MINIX_FS=m # CONFIG_NTFS_FS is not set CONFIG_HPFS_FS=m @@ -303,6 +313,9 @@ CONFIG_ROMFS_FS=m CONFIG_EXT2_FS=y CONFIG_SYSV_FS=m +# CONFIG_SYSV_FS_WRITE is not set +CONFIG_UDF_FS=m +# CONFIG_UDF_RW is not set CONFIG_UFS_FS=m CONFIG_UFS_FS_WRITE=y @@ -312,7 +325,7 @@ CONFIG_CODA_FS=m CONFIG_NFS_FS=y CONFIG_NFSD=m -# CONFIG_NFSD_SUN is not set +CONFIG_NFSD_V3=y CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_SMB_FS=m @@ -322,7 +335,9 @@ # 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 diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.3.34/linux/arch/sparc64/kernel/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc64/kernel/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.46 1999/08/31 04:39:34 davem Exp $ +# $Id: Makefile,v 1.50 1999/12/21 04:02:24 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -17,16 +17,23 @@ O_TARGET := kernel.o O_OBJS := process.o setup.o cpu.o idprom.o \ - traps.o devices.o auxio.o ioport.o \ + traps.o devices.o auxio.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o sys_sunos32.o sunos_ioctl32.o \ - central.o pci.o pci_common.o pci_iommu.o \ + unaligned.o central.o pci.o pci_common.o pci_iommu.o \ pci_psycho.o pci_sabre.o starfire.o semaphore.o \ - power.o + power.o sbus.o iommu_common.o OX_OBJS := sparc64_ksyms.o ifdef CONFIG_PCI O_OBJS += ebus.o +endif + +ifdef CONFIG_SUNOS_EMUL + O_OBJS += sys_sunos32.o sunos_ioctl32.o +else + ifdef CONFIG_SOLARIS_EMUL + O_OBJS += sys_sunos32.o sunos_ioctl32.o + endif endif ifdef CONFIG_SMP diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/auxio.c linux/arch/sparc64/kernel/auxio.c --- v2.3.34/linux/arch/sparc64/kernel/auxio.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/auxio.c Mon Dec 20 22:05:52 1999 @@ -20,22 +20,21 @@ #include /* Probe and map in the Auxiliary I/O register */ -unsigned char *auxio_register; +unsigned long auxio_register = 0; void __init auxio_probe(void) { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; - struct linux_prom_registers auxregs[1]; - - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { - if(!strcmp(sdev->prom_name, "auxio")) { - break; - } + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; + + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if(!strcmp(sdev->prom_name, "auxio")) + goto found_sdev; } } +found_sdev: if (!sdev) { #ifdef CONFIG_PCI struct linux_ebus *ebus; @@ -57,19 +56,15 @@ } #endif if(central_bus) { - auxio_register = NULL; + auxio_register = 0UL; return; } prom_printf("Cannot find auxio node, cannot continue...\n"); prom_halt(); } - prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs)); - prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev); /* Map the register both read and write */ - auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0, - auxregs[0].reg_size, - "auxiliaryIO", - auxregs[0].which_io, 0x0); + auxio_register = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, "auxiliaryIO"); TURN_ON_LED; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c --- v2.3.34/linux/arch/sparc64/kernel/central.c Wed Mar 10 16:53:37 1999 +++ linux/arch/sparc64/kernel/central.c Mon Dec 20 22:05:52 1999 @@ -1,7 +1,7 @@ -/* $Id: central.c,v 1.11 1998/12/14 12:18:16 davem Exp $ +/* $Id: central.c,v 1.13 1999/12/01 10:44:43 davem Exp $ * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. * - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) */ #include @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -25,10 +27,80 @@ ~(sizeof(unsigned long) - 1)); } -extern void prom_central_ranges_init(int cnode, struct linux_central *central); -extern void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc); +static void central_ranges_init(int cnode, struct linux_central *central) +{ + int success; + + central->num_central_ranges = 0; + success = prom_getproperty(central->prom_node, "ranges", + (char *) central->central_ranges, + sizeof (central->central_ranges)); + if (success != -1) + central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +static void fhc_ranges_init(int fnode, struct linux_fhc *fhc) +{ + int success; + + fhc->num_fhc_ranges = 0; + success = prom_getproperty(fhc->prom_node, "ranges", + (char *) fhc->fhc_ranges, + sizeof (fhc->fhc_ranges)); + if (success != -1) + fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); +} + +/* Range application routines are exported to various drivers, + * so do not __init this. + */ +static void adjust_regs(struct linux_prom_registers *regp, int nregs, + struct linux_prom_ranges *rangep, int nranges) +{ + int regc, rngc; + + for (regc = 0; regc < nregs; regc++) { + for (rngc = 0; rngc < nranges; rngc++) + if (regp[regc].which_io == rangep[rngc].ot_child_space) + break; /* Fount it */ + if (rngc == nranges) /* oops */ + prom_printf("adjust_regs: Could not find range with matching bus type...\n"); + regp[regc].which_io = rangep[rngc].ot_parent_space; + regp[regc].phys_addr += rangep[rngc].ot_parent_base; + } +} + +/* Apply probed fhc ranges to registers passed, if no ranges return. */ +void apply_fhc_ranges(struct linux_fhc *fhc, + struct linux_prom_registers *regs, + int nregs) +{ + if(fhc->num_fhc_ranges) + adjust_regs(regs, nregs, fhc->fhc_ranges, + fhc->num_fhc_ranges); +} + +/* Apply probed central ranges to registers passed, if no ranges return. */ +void apply_central_ranges(struct linux_central *central, + struct linux_prom_registers *regs, int nregs) +{ + if(central->num_central_ranges) + adjust_regs(regs, nregs, central->central_ranges, + central->num_central_ranges); +} -static unsigned long probe_other_fhcs(unsigned long memory_start) +void * __init central_alloc_bootmem(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + +static void probe_other_fhcs(void) { struct linux_prom64_registers fpregs[6]; char namebuf[128]; @@ -45,9 +117,12 @@ int board; u32 tmp; - fhc = (struct linux_fhc *)memory_start; - memory_start += sizeof(struct linux_fhc); - memory_start = long_align(memory_start); + fhc = (struct linux_fhc *) + central_alloc_bootmem(sizeof(struct linux_fhc)); + if (fhc == NULL) { + prom_printf("probe_other_fhcs: Cannot alloc fhc.\n"); + prom_halt(); + } /* Link it into the FHC chain. */ fhc->next = fhc_list; @@ -59,7 +134,7 @@ fhc->prom_node = node; prom_getstring(node, "name", namebuf, sizeof(namebuf)); strcpy(fhc->prom_name, namebuf); - prom_fhc_ranges_init(node, fhc); + fhc_ranges_init(node, fhc); /* Non-central FHC's have 64-bit OBP format registers. */ if(prom_getproperty(node, "reg", @@ -69,29 +144,23 @@ } /* Only central FHC needs special ranges applied. */ - fhc->fhc_regs.pregs = (struct fhc_internal_regs *) - __va(fpregs[0].phys_addr); - fhc->fhc_regs.ireg = (struct fhc_ign_reg *) - __va(fpregs[1].phys_addr); - fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *) - __va(fpregs[2].phys_addr); - fhc->fhc_regs.sregs = (struct fhc_system_regs *) - __va(fpregs[3].phys_addr); - fhc->fhc_regs.uregs = (struct fhc_uart_regs *) - __va(fpregs[4].phys_addr); - fhc->fhc_regs.tregs = (struct fhc_tod_regs *) - __va(fpregs[5].phys_addr); + fhc->fhc_regs.pregs = fpregs[0].phys_addr; + fhc->fhc_regs.ireg = fpregs[1].phys_addr; + fhc->fhc_regs.ffregs = fpregs[2].phys_addr; + fhc->fhc_regs.sregs = fpregs[3].phys_addr; + fhc->fhc_regs.uregs = fpregs[4].phys_addr; + fhc->fhc_regs.tregs = fpregs[5].phys_addr; board = prom_getintdefault(node, "board#", -1); fhc->board = board; - tmp = fhc->fhc_regs.pregs->fhc_jtag_ctrl; + tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); if((tmp & FHC_JTAG_CTRL_MENAB) != 0) fhc->jtag_master = 1; else fhc->jtag_master = 0; - tmp = fhc->fhc_regs.pregs->fhc_id; + tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", board, (tmp & FHC_ID_VERS) >> 28, @@ -103,7 +172,9 @@ * the system. When it is clear, this identifies * the central board. */ - fhc->fhc_regs.pregs->fhc_control |= FHC_CONTROL_IXIST; + tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + tmp |= FHC_CONTROL_IXIST; + upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); /* Look for the next FHC. */ node = prom_getsibling(node); @@ -113,8 +184,6 @@ if(node == 0) break; } - - return memory_start; } static void probe_clock_board(struct linux_central *central, @@ -135,22 +204,20 @@ prom_halt(); } nregs /= sizeof(struct linux_prom_registers); - prom_apply_fhc_ranges(fhc, &cregs[0], nregs); - prom_apply_central_ranges(central, &cregs[0], nregs); - central->cfreg = (volatile u8 *) - __va((((unsigned long)cregs[0].which_io) << 32) | - (((unsigned long)cregs[0].phys_addr)+0x02)); - central->clkregs = (struct clock_board_regs *) - __va((((unsigned long)cregs[1].which_io) << 32) | - (((unsigned long)cregs[1].phys_addr))); + apply_fhc_ranges(fhc, &cregs[0], nregs); + apply_central_ranges(central, &cregs[0], nregs); + central->cfreg = ((((unsigned long)cregs[0].which_io) << 32UL) | + ((unsigned long)cregs[0].phys_addr)); + central->clkregs = ((((unsigned long)cregs[1].which_io) << 32UL) | + ((unsigned long)cregs[1].phys_addr)); + if(nregs == 2) - central->clkver = NULL; + central->clkver = 0UL; else - central->clkver = (volatile u8 *) - __va((((unsigned long)cregs[2].which_io) << 32) | - (((unsigned long)cregs[2].phys_addr))); + central->clkver = ((((unsigned long)cregs[2].which_io) << 32UL) | + ((unsigned long)cregs[2].phys_addr)); - tmp = central->clkregs->stat1; + tmp = upa_readb(central->clkregs + CLOCK_STAT1); tmp &= 0xc0; switch(tmp) { case 0x40: @@ -160,9 +227,9 @@ nslots = 8; break; case 0x80: - if(central->clkver != NULL && - *(central->clkver) != 0) { - if((*(central->clkver) & 0x80) != 0) + if(central->clkver != 0UL && + upa_readb(central->clkver) != 0) { + if((upa_readb(central->clkver) & 0x80) != 0) nslots = 4; else nslots = 5; @@ -174,11 +241,11 @@ }; central->slots = nslots; printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", - central->slots, *(central->cfreg), - (central->clkver ? *(central->clkver) : 0x00)); + central->slots, upa_readb(central->cfreg), + (central->clkver ? upa_readb(central->clkver) : 0x00)); } -unsigned long central_probe(unsigned long memory_start) +void central_probe(void) { struct linux_prom_registers fpregs[6]; struct linux_fhc *fhc; @@ -190,18 +257,23 @@ extern void starfire_check(void); starfire_check(); - return memory_start; + return; } /* Ok we got one, grab some memory for software state. */ - memory_start = long_align(memory_start); - central_bus = (struct linux_central *) (memory_start); + central_bus = (struct linux_central *) + central_alloc_bootmem(sizeof(struct linux_central)); + if (central_bus == NULL) { + prom_printf("central_probe: Cannot alloc central_bus.\n"); + prom_halt(); + } - memory_start += sizeof(struct linux_central); - memory_start = long_align(memory_start); - fhc = (struct linux_fhc *)(memory_start); - memory_start += sizeof(struct linux_fhc); - memory_start = long_align(memory_start); + fhc = (struct linux_fhc *) + central_alloc_bootmem(sizeof(struct linux_fhc)); + if (fhc == NULL) { + prom_printf("central_probe: Cannot alloc central fhc.\n"); + prom_halt(); + } /* First init central. */ central_bus->child = fhc; @@ -210,7 +282,7 @@ prom_getstring(cnode, "name", namebuf, sizeof(namebuf)); strcpy(central_bus->prom_name, namebuf); - prom_central_ranges_init(cnode, central_bus); + central_ranges_init(cnode, central_bus); /* And then central's FHC. */ fhc->next = fhc_list; @@ -226,38 +298,32 @@ prom_getstring(fnode, "name", namebuf, sizeof(namebuf)); strcpy(fhc->prom_name, namebuf); - prom_fhc_ranges_init(fnode, fhc); + fhc_ranges_init(fnode, fhc); /* Now, map in FHC register set. */ if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) { prom_printf("CENTRAL: Fatal error, cannot get fhc regs.\n"); prom_halt(); } - prom_apply_central_ranges(central_bus, &fpregs[0], 6); + apply_central_ranges(central_bus, &fpregs[0], 6); - fhc->fhc_regs.pregs = (struct fhc_internal_regs *) - __va((((unsigned long)fpregs[0].which_io)<<32) | - (((unsigned long)fpregs[0].phys_addr))); - fhc->fhc_regs.ireg = (struct fhc_ign_reg *) - __va((((unsigned long)fpregs[1].which_io)<<32) | - (((unsigned long)fpregs[1].phys_addr))); - fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *) - __va((((unsigned long)fpregs[2].which_io)<<32) | - (((unsigned long)fpregs[2].phys_addr))); - fhc->fhc_regs.sregs = (struct fhc_system_regs *) - __va((((unsigned long)fpregs[3].which_io)<<32) | - (((unsigned long)fpregs[3].phys_addr))); - fhc->fhc_regs.uregs = (struct fhc_uart_regs *) - __va((((unsigned long)fpregs[4].which_io)<<32) | - (((unsigned long)fpregs[4].phys_addr))); - fhc->fhc_regs.tregs = (struct fhc_tod_regs *) - __va((((unsigned long)fpregs[5].which_io)<<32) | - (((unsigned long)fpregs[5].phys_addr))); + fhc->fhc_regs.pregs = ((((unsigned long)fpregs[0].which_io)<<32UL) | + ((unsigned long)fpregs[0].phys_addr)); + fhc->fhc_regs.ireg = ((((unsigned long)fpregs[1].which_io)<<32UL) | + ((unsigned long)fpregs[1].phys_addr)); + fhc->fhc_regs.ffregs = ((((unsigned long)fpregs[2].which_io)<<32UL) | + ((unsigned long)fpregs[2].phys_addr)); + fhc->fhc_regs.sregs = ((((unsigned long)fpregs[3].which_io)<<32UL) | + ((unsigned long)fpregs[3].phys_addr)); + fhc->fhc_regs.uregs = ((((unsigned long)fpregs[4].which_io)<<32UL) | + ((unsigned long)fpregs[4].phys_addr)); + fhc->fhc_regs.tregs = ((((unsigned long)fpregs[5].which_io)<<32UL) | + ((unsigned long)fpregs[5].phys_addr)); /* Obtain board number from board status register, Central's * FHC lacks "board#" property. */ - err = fhc->fhc_regs.pregs->fhc_bsr; + err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); fhc->board = (((err >> 16) & 0x01) | ((err >> 12) & 0x0e)); @@ -266,23 +332,21 @@ /* Attach the clock board registers for CENTRAL. */ probe_clock_board(central_bus, fhc, cnode, fnode); - err = fhc->fhc_regs.pregs->fhc_id; + err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", fhc->board, ((err & FHC_ID_VERS) >> 28), ((err & FHC_ID_PARTID) >> 12), ((err & FHC_ID_MANUF) >> 1)); - return probe_other_fhcs(memory_start); + probe_other_fhcs(); } static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on) { - volatile u32 *ctrl = (volatile u32 *) - &fhc->fhc_regs.pregs->fhc_control; u32 tmp; - tmp = *ctrl; + tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); /* NOTE: reverse logic on this bit */ if (on) @@ -291,16 +355,15 @@ tmp |= FHC_CONTROL_RLED; tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); - *ctrl = tmp; - tmp = *ctrl; + upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); } static __inline__ void central_ledblink(struct linux_central *central, int on) { - volatile u8 *ctrl = (volatile u8 *) ¢ral->clkregs->control; - int tmp; + u8 tmp; - tmp = *ctrl; + tmp = upa_readb(central->clkregs + CLOCK_CTRL); /* NOTE: reverse logic on this bit */ if(on) @@ -308,8 +371,8 @@ else tmp |= CLOCK_CTRL_RLED; - *ctrl = tmp; - tmp = *ctrl; + upa_writeb(tmp, central->clkregs + CLOCK_CTRL); + upa_readb(central->clkregs + CLOCK_CTRL); } static struct timer_list sftimer; @@ -335,41 +398,41 @@ { struct linux_central *central = central_bus; struct linux_fhc *fhc; + u8 ctrl; /* No central bus, nothing to do. */ if (central == NULL) return; for(fhc = fhc_list; fhc != NULL; fhc = fhc->next) { - volatile u32 *ctrl = (volatile u32 *) - &fhc->fhc_regs.pregs->fhc_control; u32 tmp; /* Clear all of the interrupt mapping registers * just in case OBP left them in a foul state. */ -#define ZAP(REG1, REG2) \ -do { volatile u32 *__iclr = (volatile u32 *)(&(REG1)); \ - volatile u32 *__imap = (volatile u32 *)(&(REG2)); \ - *(__iclr) = 0; \ - (void) *(__iclr); \ - *(__imap) &= ~(0x80000000); \ - (void) *(__imap); \ -} while(0) - - ZAP(fhc->fhc_regs.ffregs->fhc_ff_iclr, - fhc->fhc_regs.ffregs->fhc_ff_imap); - ZAP(fhc->fhc_regs.sregs->fhc_sys_iclr, - fhc->fhc_regs.sregs->fhc_sys_imap); - ZAP(fhc->fhc_regs.uregs->fhc_uart_iclr, - fhc->fhc_regs.uregs->fhc_uart_imap); - ZAP(fhc->fhc_regs.tregs->fhc_tod_iclr, - fhc->fhc_regs.tregs->fhc_tod_imap); +#define ZAP(ICLR, IMAP) \ +do { u32 imap_tmp; \ + upa_writel(0, (ICLR)); \ + upa_readl(ICLR); \ + imap_tmp = upa_readl(IMAP); \ + imap_tmp &= ~(0x80000000); \ + upa_writel(imap_tmp, (IMAP)); \ + upa_readl(IMAP); \ +} while (0) + + ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, + fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); + ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, + fhc->fhc_regs.sregs + FHC_SREGS_IMAP); + ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, + fhc->fhc_regs.uregs + FHC_UREGS_IMAP); + ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, + fhc->fhc_regs.tregs + FHC_TREGS_IMAP); #undef ZAP /* Setup FHC control register. */ - tmp = *ctrl; + tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); /* All non-central boards have this bit set. */ if(! IS_CENTRAL_FHC(fhc)) @@ -379,14 +442,17 @@ * line and both low power mode enables. */ tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); - *ctrl = tmp; - tmp = *ctrl; /* Ensure completion */ + + upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); } /* OBP leaves it on, turn it off so clock board timer LED * is in sync with FHC ones. */ - central->clkregs->control &= ~(CLOCK_CTRL_RLED); + ctrl = upa_readb(central->clkregs + CLOCK_CTRL); + ctrl &= ~(CLOCK_CTRL_RLED); + upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); led_state = 0; init_timer(&sftimer); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c --- v2.3.34/linux/arch/sparc64/kernel/devices.c Tue Sep 7 12:14:06 1999 +++ linux/arch/sparc64/kernel/devices.c Mon Dec 20 22:05:52 1999 @@ -19,10 +19,9 @@ int linux_num_cpus = 0; extern void cpu_probe(void); -extern unsigned long central_probe(unsigned long); +extern void central_probe(void); -unsigned long __init -device_scan(unsigned long mem_start) +void __init device_scan(void) { char node_str[128]; int nd, prom_node_cpu, thismid; @@ -54,13 +53,8 @@ prom_getproperty(scan, "upa-portid", (char *) &thismid, sizeof(thismid)); linux_cpus[cpu_ctr].mid = thismid; -#ifdef __SMP__ - /* Don't pollute PROM screen with these messages. If the kernel is screwed enough - that console does not start up, then we don't care how many CPUs have been found, - if it starts up, the user can use console=prom to see it. */ - /* prom_printf("Found CPU %d (node=%08x,mid=%d)\n", cpu_ctr, (unsigned) scan, thismid); */ - printk("Found CPU %d (node=%08x,mid=%d)\n", cpu_ctr, (unsigned) scan, thismid); -#endif + printk("Found CPU %d (node=%08x,mid=%d)\n", + cpu_ctr, (unsigned) scan, thismid); cpu_ctr++; } }; @@ -68,19 +62,15 @@ prom_printf("No CPU nodes found, cannot continue.\n"); prom_halt(); } -#ifdef __SMP__ printk("Found %d CPU prom device tree node(s).\n", cpu_ctr); -#endif - }; + } prom_node_cpu = cpu_nds[0]; linux_num_cpus = cpu_ctr; prom_cpu_nodes[0] = prom_node_cpu; - mem_start = central_probe(mem_start); + central_probe(); cpu_probe(); - - return mem_start; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S --- v2.3.34/linux/arch/sparc64/kernel/dtlb_backend.S Wed Mar 10 16:53:37 1999 +++ linux/arch/sparc64/kernel/dtlb_backend.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: dtlb_backend.S,v 1.7 1998/12/16 04:33:28 davem Exp $ +/* $Id: dtlb_backend.S,v 1.8 1999/12/05 10:41:35 davem Exp $ * dtlb_backend.S: Back end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -10,7 +10,7 @@ #define VPTE_SHIFT (PAGE_SHIFT - 3) #define PMD_SHIFT (23 - PAGE_SHIFT + 3) #define PGD_SHIFT (34 - PAGE_SHIFT + 3) -#define VPTE_BITS (_PAGE_CP | _PAGE_P | _PAGE_W) +#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) /* Ways we can get here: * diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.3.34/linux/arch/sparc64/kernel/ebus.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/ebus.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.44 1999/09/05 09:28:09 ecd Exp $ +/* $Id: ebus.c,v 1.46 1999/11/19 05:52:48 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -22,9 +22,6 @@ struct linux_ebus *ebus_chain = 0; -extern void prom_ebus_ranges_init(struct linux_ebus *); -extern void prom_ebus_intmap_init(struct linux_ebus *); - #ifdef CONFIG_SUN_OPENPROMIO extern int openprom_init(void); #endif @@ -49,15 +46,49 @@ return mem; } -void __init ebus_intmap_match(struct linux_ebus *ebus, - struct linux_prom_registers *reg, - int *interrupt) +static void __init ebus_ranges_init(struct linux_ebus *ebus) +{ + int success; + + ebus->num_ebus_ranges = 0; + success = prom_getproperty(ebus->prom_node, "ranges", + (char *)ebus->ebus_ranges, + sizeof(ebus->ebus_ranges)); + if (success != -1) + ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); +} + +static void __init ebus_intmap_init(struct linux_ebus *ebus) +{ + int success; + + ebus->num_ebus_intmap = 0; + success = prom_getproperty(ebus->prom_node, "interrupt-map", + (char *)ebus->ebus_intmap, + sizeof(ebus->ebus_intmap)); + if (success == -1) + return; + + ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); + + success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", + (char *)&ebus->ebus_intmask, + sizeof(ebus->ebus_intmask)); + if (success == -1) { + prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); + prom_halt(); + } +} + +int __init ebus_intmap_match(struct linux_ebus *ebus, + struct linux_prom_registers *reg, + int *interrupt) { unsigned int hi, lo, irq; int i; if (!ebus->num_ebus_intmap) - return; + return 0; hi = reg->which_io & ebus->ebus_intmask.phys_hi; lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; @@ -67,13 +98,10 @@ (ebus->ebus_intmap[i].phys_lo == lo) && (ebus->ebus_intmap[i].interrupt == irq)) { *interrupt = ebus->ebus_intmap[i].cinterrupt; - return; + return 0; } } - - prom_printf("ebus: IRQ [%08x.%08x.%08x] not found in interrupt-map\n", - reg->which_io, reg->phys_addr, *interrupt); - prom_halt(); + return -1; } void __init fill_ebus_child(int node, struct linux_prom_registers *preg, @@ -139,8 +167,16 @@ struct pci_pbm_info *pbm = dev->bus->parent; struct pci_controller_info *p = pbm->parent; - ebus_intmap_match(dev->bus, preg, &irqs[i]); - dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]); + if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) { + dev->irqs[i] = p->irq_build(p, + dev->bus->self, + irqs[i]); + } else { + /* If we get a bogus interrupt property, just + * record the raw value instead of punting. + */ + dev->irqs[i] = irqs[i]; + } } } } @@ -194,8 +230,16 @@ struct pci_pbm_info *pbm = dev->bus->parent; struct pci_controller_info *p = pbm->parent; - ebus_intmap_match(dev->bus, ®s[0], &irqs[i]); - dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]); + if (ebus_intmap_match(dev->bus, ®s[0], &irqs[i]) != -1) { + dev->irqs[i] = p->irq_build(p, + dev->bus->self, + irqs[i]); + } else { + /* If we get a bogus interrupt property, just + * record the raw value instead of punting. + */ + dev->irqs[i] = irqs[i]; + } } } @@ -295,8 +339,8 @@ /* NOTE: Cache line size is in 32-bit word units. */ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32)); - prom_ebus_ranges_init(ebus); - prom_ebus_intmap_init(ebus); + ebus_ranges_init(ebus); + ebus_intmap_init(ebus); nd = prom_getchild(ebusnd); if (!nd) diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.3.34/linux/arch/sparc64/kernel/entry.S Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/entry.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.107 1999/08/31 19:25:29 davem Exp $ +/* $Id: entry.S,v 1.110 1999/11/19 05:52:50 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -214,8 +214,8 @@ .align 32 .globl do_ivec do_ivec: - wr %g0, ASI_UDB_INTR_R, %asi - ldxa [%g0 + 0x40] %asi, %g3 + mov 0x40, %g3 + ldxa [%g3 + %g0] ASI_UDB_INTR_R, %g3 sethi %hi(KERNBASE), %g4 cmp %g3, %g4 bgeu,pn %xcc, do_ivec_xcall @@ -234,22 +234,25 @@ sllx %g2, %g4, %g2 sllx %g4, 2, %g4 - lduw [%g1 + %g4], %g5 /* g5 = irq_work(cpu, pil) */ + lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */ stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ - stw %g3, [%g1 + %g4] /* irq_work(cpu, pil) = bucket */ + stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */ wr %g2, 0x0, %set_softint retry do_ivec_xcall: - ldxa [%g0 + 0x50] %asi, %g6 + mov 0x50, %g1 + ldxa [%g1 + %g0] ASI_UDB_INTR_R, %g1 srl %g3, 0, %g3 - ldxa [%g0 + 0x60] %asi, %g7 + mov 0x60, %g7 + ldxa [%g7 + %g0] ASI_UDB_INTR_R, %g7 stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync jmpl %g3, %g0 nop + do_ivec_spurious: - stw %g3, [%g1 + 0x00] /* irq_work(cpu, 0) = bucket */ + stw %g3, [%g6 + 0x00] /* irq_work(cpu, 0) = bucket */ rdpr %pstate, %g5 wrpr %g5, PSTATE_IG | PSTATE_AG, %pstate @@ -261,6 +264,76 @@ ba,pt %xcc, rtrap clr %l6 + .globl save_alternate_globals +save_alternate_globals: /* %o0 = save_area */ + rdpr %pstate, %o5 + andn %o5, PSTATE_IE, %o1 + wrpr %o1, PSTATE_AG, %pstate + stx %g0, [%o0 + 0x00] + stx %g1, [%o0 + 0x08] + stx %g2, [%o0 + 0x10] + stx %g3, [%o0 + 0x18] + stx %g4, [%o0 + 0x20] + stx %g5, [%o0 + 0x28] + stx %g6, [%o0 + 0x30] + stx %g7, [%o0 + 0x38] + wrpr %o1, PSTATE_IG, %pstate + stx %g0, [%o0 + 0x40] + stx %g1, [%o0 + 0x48] + stx %g2, [%o0 + 0x50] + stx %g3, [%o0 + 0x58] + stx %g4, [%o0 + 0x60] + stx %g5, [%o0 + 0x68] + stx %g6, [%o0 + 0x70] + stx %g7, [%o0 + 0x78] + wrpr %o1, PSTATE_MG, %pstate + stx %g0, [%o0 + 0x80] + stx %g1, [%o0 + 0x88] + stx %g2, [%o0 + 0x90] + stx %g3, [%o0 + 0x98] + stx %g4, [%o0 + 0xa0] + stx %g5, [%o0 + 0xa8] + stx %g6, [%o0 + 0xb0] + stx %g7, [%o0 + 0xb8] + wrpr %o5, 0x0, %pstate + retl + nop + + .globl restore_alternate_globals +restore_alternate_globals: /* %o0 = save_area */ + rdpr %pstate, %o5 + andn %o5, PSTATE_IE, %o1 + wrpr %o1, PSTATE_AG, %pstate + ldx [%o0 + 0x00], %g0 + ldx [%o0 + 0x08], %g1 + ldx [%o0 + 0x10], %g2 + ldx [%o0 + 0x18], %g3 + ldx [%o0 + 0x20], %g4 + ldx [%o0 + 0x28], %g5 + ldx [%o0 + 0x30], %g6 + ldx [%o0 + 0x38], %g7 + wrpr %o1, PSTATE_IG, %pstate + ldx [%o0 + 0x40], %g0 + ldx [%o0 + 0x48], %g1 + ldx [%o0 + 0x50], %g2 + ldx [%o0 + 0x58], %g3 + ldx [%o0 + 0x60], %g4 + ldx [%o0 + 0x68], %g5 + ldx [%o0 + 0x70], %g6 + ldx [%o0 + 0x78], %g7 + wrpr %o1, PSTATE_MG, %pstate + ldx [%o0 + 0x80], %g0 + ldx [%o0 + 0x88], %g1 + ldx [%o0 + 0x90], %g2 + ldx [%o0 + 0x98], %g3 + ldx [%o0 + 0xa0], %g4 + ldx [%o0 + 0xa8], %g5 + ldx [%o0 + 0xb0], %g6 + ldx [%o0 + 0xb8], %g7 + wrpr %o5, 0x0, %pstate + retl + nop + .globl getcc, setcc getcc: ldx [%o0 + PT_V9_TSTATE], %o1 @@ -313,7 +386,7 @@ ldx [%g5 + %lo(pdma_size)], %g5 next_byte: - ldub [%g3], %g7 + lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 andcc %g7, 0x80, %g0 be,pn %icc, floppy_fifo_emptied andcc %g7, 0x20, %g0 @@ -322,7 +395,9 @@ be,pn %icc, floppy_write sub %g5, 1, %g5 - ldub [%g3 + 1], %g7 + inc %g3 + lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 + dec %g3 orcc %g0, %g5, %g0 stb %g7, [%g4] bne,pn %xcc, next_byte @@ -334,7 +409,9 @@ floppy_write: ldub [%g4], %g7 orcc %g0, %g5, %g0 - stb %g7, [%g3 + 1] + inc %g3 + stba %g7, [%g3] ASI_PHYS_BYPASS_EC_E + dec %g3 bne,pn %xcc, next_byte add %g4, 1, %g4 @@ -368,7 +445,7 @@ ldx [%g1 + (11 << 3)], %g3 ! irqaction[floppy_irq] ldx [%g3 + 0x10], %g4 ! action->mask == ino_bucket ptr ldx [%g4 + 0x10], %g4 ! bucket->iclr - stw %g0, [%g4] ! SYSIO_ICLR_IDLE + stwa %g0, [%g4] ASI_PHYS_BYPASS_EC_E ! ICLR_IDLE membar #Sync ! probably not needed... retry @@ -652,6 +729,8 @@ ba,pt %xcc, rtrap nop +#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ + defined(CONFIG_SOLARIS_EMUL_MODULE) /* SunOS uses syscall zero as the 'indirect syscall' it looks * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. * This is complete brain damage. @@ -705,6 +784,7 @@ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] b,pt %xcc, ret_sys_call stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] +#endif /* SunOS's execv() call only specifies the argv argument, the * environment settings are the same as the calling processes. diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.3.34/linux/arch/sparc64/kernel/head.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/kernel/head.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.61 1999/05/25 16:53:10 jj Exp $ +/* $Id: head.S,v 1.63 1999/11/19 05:52:49 davem Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -52,7 +52,7 @@ .ascii "HdrS" .word LINUX_VERSION_CODE - .half 0x0202 /* HdrS version */ + .half 0x0203 /* HdrS version */ root_flags: .half 1 root_dev: @@ -65,6 +65,7 @@ .word 0 .xword reboot_command .xword bootstr_len + .word _end /* We must be careful, 32-bit OpenBOOT will get confused if it * tries to save away a register window to a 64-bit kernel @@ -92,28 +93,6 @@ wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate wr %g0, 0, %fprs -#ifdef __SMP__ - /* Ugly but necessary... */ - sethi %hi(KERNBASE), %g7 - sethi %hi(sparc64_cpu_startup), %g5 - or %g5, %lo(sparc64_cpu_startup), %g5 - sub %g5, %g7, %g5 - sethi %hi(sparc64_cpu_startup_end), %g6 - or %g6, %lo(sparc64_cpu_startup_end), %g6 - sub %g6, %g7, %g6 - sethi %hi(smp_trampoline), %g3 - or %g3, %lo(smp_trampoline), %g3 - sub %g3, %g7, %g3 -1: ldx [%g5], %g1 - stx %g1, [%g3] - membar #StoreStore - flush %g3 - add %g5, 8, %g5 - cmp %g5, %g6 - blu,pt %xcc, 1b - add %g3, 8, %g3 -#endif - create_mappings: /* %g5 holds the tlb data */ sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 @@ -380,7 +359,7 @@ wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate #ifndef __SMP__ sethi %hi(__up_workvec), %g5 - or %g5, %lo(__up_workvec), %g1 + or %g5, %lo(__up_workvec), %g6 #else /* By definition of where we are, this is boot_cpu. */ sethi %hi(cpu_data), %g5 @@ -404,7 +383,7 @@ set_worklist: sllx %g1, 7, %g1 add %g5, %g1, %g5 - add %g5, 64, %g1 + add %g5, 64, %g6 #endif /* Kill PROM timer */ diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.3.34/linux/arch/sparc64/kernel/ioctl32.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/ioctl32.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.68 1999/09/10 05:59:25 davem Exp $ +/* $Id: ioctl32.c,v 1.71 1999/12/19 23:13:13 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1921,6 +1921,9 @@ case TIOCSCTTY: case TIOCGPTN: case TIOCSPTLCK: + case TIOCGSERIAL: + case TIOCSSERIAL: + case TIOCSERGETLSR: /* Big F */ case FBIOGTYPE: @@ -2124,6 +2127,9 @@ case OPROMGETCONS: case OPROMGETFBNAME: case OPROMGETBOOTARGS: + case OPROMSETCUR: + case OPROMPCI2NODE: + case OPROMPATH2NODE: /* Socket level stuff */ case FIOSETOWN: @@ -2175,6 +2181,10 @@ case PPPIOCSNPMODE: case PPPIOCGDEBUG: case PPPIOCSDEBUG: + case PPPIOCGIDLE: + case PPPIOCNEWUNIT: + case PPPIOCATTACH: + case PPPIOCDETACH: /* CDROM stuff */ case CDROMPAUSE: @@ -2204,6 +2214,9 @@ case CDROM_DRIVE_STATUS: case CDROM_DISC_STATUS: case CDROM_CHANGER_NSLOTS: + case CDROM_LOCKDOOR: + case CDROM_DEBUG: + case CDROM_GET_CAPABILITY: /* Big L */ case LOOP_SET_FD: diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c --- v2.3.34/linux/arch/sparc64/kernel/iommu_common.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/iommu_common.c Mon Dec 20 22:05:52 1999 @@ -0,0 +1,233 @@ +/* $Id: iommu_common.c,v 1.2 1999/12/19 09:17:53 davem Exp $ + * iommu_common.c: UltraSparc SBUS/PCI common iommu code. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +#include "iommu_common.h" + +/* You are _strongly_ advised to enable the following debugging code + * any time you make changes to the sg code below, run it for a while + * with filesystems mounted read-only before buying the farm... -DaveM + */ + +#ifdef VERIFY_SG +int verify_lengths(struct scatterlist *sg, int nents, int npages) +{ + int sg_len, dma_len; + int i, pgcount; + + sg_len = 0; + for (i = 0; i < nents; i++) + sg_len += sg[i].length; + + dma_len = 0; + for (i = 0; i < nents && sg[i].dvma_length; i++) + dma_len += sg[i].dvma_length; + + if (sg_len != dma_len) { + printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", + sg_len, dma_len); + return -1; + } + + pgcount = 0; + for (i = 0; i < nents && sg[i].dvma_length; i++) { + unsigned long start, end; + + start = sg[i].dvma_address; + start = start & PAGE_MASK; + + end = sg[i].dvma_address + sg[i].dvma_length; + end = (end + (PAGE_SIZE - 1)) & PAGE_MASK; + + pgcount += ((end - start) >> PAGE_SHIFT); + } + + if (pgcount != npages) { + printk("verify_langths: Error, page count wrong, " + "npages[%d] pgcount[%d]\n", + npages, pgcount); + return -1; + } + + /* This test passes... */ + return 0; +} + +int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte) +{ + struct scatterlist *sg = *__sg; + iopte_t *iopte = *__iopte; + int retval = 0; + u32 dlen = dma_sg->dvma_length; + u32 daddr = dma_sg->dvma_address; + unsigned int sglen; + unsigned long sgaddr; + + sglen = sg->length; + sgaddr = (unsigned long) sg->address; + while (dlen > 0) { + unsigned long paddr; + + /* SG and DMA_SG must begin at the same sub-page boundary. */ + if ((sgaddr & ~PAGE_MASK) != (daddr & ~PAGE_MASK)) { + printk("verify_one_map: Wrong start offset " + "sg[%08lx] dma[%08x]\n", + sgaddr, daddr); + retval = -nents; + goto out; + } + + /* Verify the IOPTE points to the right page. */ + paddr = iopte_val(*iopte) & IOPTE_PAGE; + if ((paddr + PAGE_OFFSET) != (sgaddr & PAGE_MASK)) { + printk("verify_one_map: IOPTE[%08lx] maps the " + "wrong page, should be [%08lx]\n", + iopte_val(*iopte), (sgaddr & PAGE_MASK) - PAGE_OFFSET); + retval = -nents; + goto out; + } + + /* If this SG crosses a page, adjust to that next page + * boundary and loop. + */ + if ((sgaddr & PAGE_MASK) ^ ((sgaddr + sglen - 1) & PAGE_MASK)) { + unsigned long next_page, diff; + + next_page = (sgaddr + PAGE_SIZE) & PAGE_MASK; + diff = next_page - sgaddr; + sgaddr += diff; + daddr += diff; + sglen -= diff; + dlen -= diff; + if (dlen > 0) + iopte++; + continue; + } + + /* SG wholly consumed within this page. */ + daddr += sglen; + dlen -= sglen; + + if (dlen > 0 && ((daddr & ~PAGE_MASK) == 0)) + iopte++; + + sg++; + sgaddr = (unsigned long) sg->address; + sglen = sg->length; + } + if (dlen < 0) { + /* Transfer overrun, big problems. */ + printk("verify_one_map: Transfer overrun by %d bytes.\n", + -dlen); + retval = -nents; + } else { + /* Advance to next dma_sg implies that the next iopte will + * begin it. + */ + iopte++; + } + +out: + *__sg = sg; + *__iopte = iopte; + return retval; +} + +int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) +{ + struct scatterlist *dma_sg = sg; + struct scatterlist *orig_dma_sg = dma_sg; + int orig_nents = nents; + + for (;;) { + nents = verify_one_map(dma_sg, &sg, nents, &iopte); + if (nents <= 0) + break; + dma_sg++; + if (dma_sg->dvma_length == 0) + break; + } + + if (nents > 0) { + printk("verify_maps: dma maps consumed by some sgs remain (%d)\n", + nents); + return -1; + } + + if (nents < 0) { + printk("verify_maps: Error, messed up mappings, " + "at sg %d dma_sg %d\n", + (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg)); + return -1; + } + + /* This test passes... */ + return 0; +} + +void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages) +{ + if (verify_lengths(sg, nents, npages) < 0 || + verify_maps(sg, nents, iopte) < 0) { + int i; + + printk("verify_sglist: Crap, messed up mappings, dumping, iodma at %08x.\n", + (u32) (sg->dvma_address & PAGE_MASK)); + for (i = 0; i < nents; i++) { + printk("sg(%d): address(%p) length(%x) " + "dma_address[%08x] dma_length[%08x]\n", + i, + sg[i].address, sg[i].length, + sg[i].dvma_address, sg[i].dvma_length); + } + } + + /* Seems to be ok */ +} +#endif + +/* Two addresses are "virtually contiguous" if and only if: + * 1) They are equal, or... + * 2) They are both on a page boundry + */ +#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ + (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) + +unsigned long prepare_sg(struct scatterlist *sg, int nents) +{ + struct scatterlist *dma_sg = sg; + unsigned long prev; + u32 dent_addr, dent_len; + + prev = (unsigned long) sg->address; + prev += (unsigned long) (dent_len = sg->length); + dent_addr = (u32) ((unsigned long)sg->address & (PAGE_SIZE - 1UL)); + while (--nents) { + unsigned long addr; + + sg++; + addr = (unsigned long) sg->address; + if (! VCONTIG(prev, addr)) { + dma_sg->dvma_address = dent_addr; + dma_sg->dvma_length = dent_len; + dma_sg++; + + dent_addr = ((dent_addr + + dent_len + + (PAGE_SIZE - 1UL)) >> PAGE_SHIFT); + dent_addr <<= PAGE_SHIFT; + dent_addr += addr & (PAGE_SIZE - 1UL); + dent_len = 0; + } + dent_len += sg->length; + prev = addr + sg->length; + } + dma_sg->dvma_address = dent_addr; + dma_sg->dvma_length = dent_len; + + return ((unsigned long) dent_addr + + (unsigned long) dent_len + + (PAGE_SIZE - 1UL)) >> PAGE_SHIFT; +} diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/iommu_common.h linux/arch/sparc64/kernel/iommu_common.h --- v2.3.34/linux/arch/sparc64/kernel/iommu_common.h Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/iommu_common.h Mon Dec 20 22:05:52 1999 @@ -0,0 +1,34 @@ +/* $Id: iommu_common.h,v 1.1 1999/12/17 12:31:54 jj Exp $ + * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +#include +#include + +#include +#include +#include + +/* You are _strongly_ advised to enable the following debugging code + * any time you make changes to the sg code below, run it for a while + * with filesystems mounted read-only before buying the farm... -DaveM + */ +#undef VERIFY_SG + +#ifdef VERIFY_SG +int verify_lengths(struct scatterlist *sg, int nents, int npages); +int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte); +int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte); +void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages); +#endif + +/* Two addresses are "virtually contiguous" if and only if: + * 1) They are equal, or... + * 2) They are both on a page boundry + */ +#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \ + (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL) + +unsigned long prepare_sg(struct scatterlist *sg, int nents); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ioport.c linux/arch/sparc64/kernel/ioport.c --- v2.3.34/linux/arch/sparc64/kernel/ioport.c Tue Aug 4 16:03:35 1998 +++ linux/arch/sparc64/kernel/ioport.c Wed Dec 31 16:00:00 1969 @@ -1,107 +0,0 @@ -/* $Id: ioport.c,v 1.14 1998/05/11 06:23:36 davem Exp $ - * ioport.c: Simple io mapping allocator. - * - * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* This points to the next to use virtual memory for io mappings */ -static unsigned long dvma_next_free = DVMA_VADDR; - -extern void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr); - -/* - * sparc_alloc_io: - * Map and allocates an obio device. - * Implements a simple linear allocator, you can force the function - * to use your own mapping, but in practice this should not be used. - * - * Input: - * address: Physical address to map - * virtual: if non zero, specifies a fixed virtual address where - * the mapping should take place, not supported on Ultra - * and this feature is scheduled to be removed as nobody - * uses it. -DaveM - * len: the length of the mapping - * bus_type: Optional high word of physical address. - * - * Returns: - * The virtual address where the mapping actually took place. - */ - -void *sparc_alloc_io (u32 address, void *virtual, int len, char *name, - u32 bus_type, int rdonly) -{ - unsigned long addr = ((unsigned long)address) + (((unsigned long)bus_type)<<32); - unsigned long vaddr = (unsigned long) __va(addr); - - if(virtual) - panic("sparc_alloc_io: Fixed virtual mappings unsupported on Ultra."); - - if(!check_region(vaddr, len)) - request_region(vaddr, len, name); - - return (void *) vaddr; -} - -void sparc_free_io (void *virtual, int len) -{ - unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; - unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + - len + PAGE_SIZE-1) & PAGE_MASK; - release_region(vaddr, plen); -} - -/* Does DVMA allocations with PAGE_SIZE granularity. How this basically - * works is that the ESP chip can do DVMA transfers at ANY address with - * certain size and boundary restrictions. But other devices that are - * attached to it and would like to do DVMA have to set things up in - * a special way, if the DVMA sees a device attached to it transfer data - * at addresses above DVMA_VADDR it will grab them, this way it does not - * now have to know the peculiarities of where to read the Lance data - * from. (for example) - * - * Returns CPU visible address for the buffer returned, dvma_addr is - * set to the DVMA visible address. - */ -void *sparc_dvma_malloc (int len, char *name, __u32 *dvma_addr) -{ - unsigned long vaddr, base_address; - - vaddr = dvma_next_free; - if(check_region (vaddr, len)) { - prom_printf("alloc_dma: 0x%lx is already in use\n", vaddr); - prom_halt(); - } - if(vaddr + len > (DVMA_VADDR + DVMA_LEN)) { - prom_printf("alloc_dvma: out of dvma memory\n"); - prom_halt(); - } - - /* Basically these can be mapped just like any old - * IO pages, cacheable bit off, etc. The physical - * pages are now mapped dynamically to save space. - */ - base_address = vaddr; - mmu_map_dma_area(base_address, len, dvma_addr); - - /* Assign the memory area. */ - dvma_next_free = PAGE_ALIGN(dvma_next_free+len); - - request_region(base_address, len, name); - - return (void *) base_address; -} diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.3.34/linux/arch/sparc64/kernel/irq.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/irq.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.78 1999/08/31 06:54:54 davem Exp $ +/* $Id: irq.c,v 1.80 1999/12/06 03:14:48 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -106,89 +106,16 @@ return len; } -/* SBUS SYSIO INO number to Sparc PIL level. */ -unsigned char sysio_ino_to_pil[] = { - 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 0 */ - 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 1 */ - 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 2 */ - 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 3 */ - 3, /* Onboard SCSI */ - 5, /* Onboard Ethernet */ -/*XXX*/ 8, /* Onboard BPP */ - 0, /* Bogon */ - 13, /* Audio */ -/*XXX*/15, /* PowerFail */ - 0, /* Bogon */ - 0, /* Bogon */ - 12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */ - 11, /* Floppy */ - 0, /* Spare Hardware (bogon for now) */ - 0, /* Keyboard (bogon for now) */ - 0, /* Mouse (bogon for now) */ - 0, /* Serial (bogon for now) */ - 0, 0, /* Bogon, Bogon */ - 10, /* Timer 0 */ - 11, /* Timer 1 */ - 0, 0, /* Bogon, Bogon */ - 15, /* Uncorrectable SBUS Error */ - 15, /* Correctable SBUS Error */ - 15, /* SBUS Error */ -/*XXX*/ 0, /* Power Management (bogon for now) */ -}; - -/* INO number to IMAP register offset for SYSIO external IRQ's. - * This should conform to both Sunfire/Wildfire server and Fusion - * desktop designs. - */ -#define offset(x) ((unsigned long)(&(((struct sysio_regs *)0)->x))) -#define bogon ((unsigned long) -1) -static unsigned long sysio_irq_offsets[] = { -/* SBUS Slot 0 --> 3, level 1 --> 7 */ -offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), -offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0), -offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),offset(imap_slot1), -offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),offset(imap_slot1), -offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),offset(imap_slot2), -offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),offset(imap_slot2), -offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),offset(imap_slot3), -offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),offset(imap_slot3), -/* Onboard devices (not relevant/used on SunFire). */ -offset(imap_scsi), offset(imap_eth), offset(imap_bpp), bogon, -offset(imap_audio), offset(imap_pfail), bogon, bogon, -offset(imap_kms), offset(imap_flpy), offset(imap_shw), -offset(imap_kbd), offset(imap_ms), offset(imap_ser), bogon, bogon, -offset(imap_tim0), offset(imap_tim1), bogon, bogon, -offset(imap_ue), offset(imap_ce), offset(imap_sberr), -offset(imap_pmgmt), -}; - -#undef bogon - -#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0])) - -/* Convert Interrupt Mapping register pointer to assosciated - * Interrupt Clear register pointer, SYSIO specific version. - */ -static volatile unsigned int *sysio_imap_to_iclr(volatile unsigned int *imap) -{ - unsigned long diff; - - diff = offset(iclr_unused0) - offset(imap_slot0); - return (volatile unsigned int *) (((unsigned long)imap) + diff); -} - -#undef offset - /* Now these are always passed a true fully specified sun4u INO. */ void enable_irq(unsigned int irq) { extern int this_is_starfire; struct ino_bucket *bucket = __bucket(irq); - volatile unsigned int *imap; + unsigned long imap; unsigned long tid; imap = bucket->imap; - if (!imap) + if (imap == 0UL) return; if(this_is_starfire == 0) { @@ -198,7 +125,7 @@ : "i" (ASI_UPA_CONFIG)); tid = ((tid & UPA_CONFIG_MID) << 9); } else { - extern unsigned int starfire_translate(volatile unsigned int *imap, + extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); tid = (starfire_translate(imap, current->processor) << 26); @@ -208,27 +135,31 @@ * of this SYSIO's preconfigured IGN in the SYSIO Control * Register, the hardware just mirrors that value here. * However for Graphics and UPA Slave devices the full - * SYSIO_IMAP_INR field can be set by the programmer here. + * IMAP_INR field can be set by the programmer here. * * Things like FFB can now be handled via the new IRQ mechanism. */ - *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); + upa_writel(IMAP_VALID | (tid & IMAP_TID), imap); } /* This now gets passed true ino's as well. */ void disable_irq(unsigned int irq) { struct ino_bucket *bucket = __bucket(irq); - volatile unsigned int *imap; + unsigned long imap; imap = bucket->imap; - if (imap != NULL) { + if (imap != 0UL) { + u32 tmp; + /* NOTE: We do not want to futz with the IRQ clear registers * and move the state to IDLE, the SCSI code does call * disable_irq() to assure atomicity in the queue cmd * SCSI adapter driver code. Thus we'd lose interrupts. */ - *imap &= ~(SYSIO_IMAP_VALID); + tmp = upa_readl(imap); + tmp &= ~IMAP_VALID; + upa_writel(tmp, imap); } } @@ -243,18 +174,18 @@ 0, /* flags */ 0, /* __unused */ NULL, /* irq_info */ - NULL, /* iclr */ - NULL, /* imap */ + 0UL, /* iclr */ + 0UL, /* imap */ }; -unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap) +unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap) { struct ino_bucket *bucket; int ino; if(pil == 0) { - if(iclr != NULL || imap != NULL) { - prom_printf("Invalid dummy bucket for PIL0 (%p:%p)\n", + if(iclr != 0UL || imap != 0UL) { + prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n", iclr, imap); prom_halt(); } @@ -262,13 +193,13 @@ } /* RULE: Both must be specified in all other cases. */ - if (iclr == NULL || imap == NULL) { + if (iclr == 0UL || imap == 0UL) { prom_printf("Invalid build_irq %d %d %016lx %016lx\n", pil, inofixup, iclr, imap); prom_halt(); } - ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup; + ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; if(ino > NUM_IVECS) { prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n", ino, pil, inofixup, iclr, imap); @@ -300,64 +231,6 @@ return __irq(bucket); } -unsigned int sbus_build_irq(void *buscookie, unsigned int ino) -{ - struct linux_sbus *sbus = (struct linux_sbus *)buscookie; - struct sysio_regs *sregs = sbus->iommu->sysio_regs; - unsigned long offset; - int pil; - volatile unsigned int *imap, *iclr; - int sbus_level = 0; - - pil = sysio_ino_to_pil[ino]; - if(!pil) { - printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino); - panic("Bad SYSIO IRQ translations..."); - } - offset = sysio_irq_offsets[ino]; - if(offset == ((unsigned long)-1)) { - printk("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", - ino, pil); - panic("BAD SYSIO IRQ offset..."); - } - offset += ((unsigned long)sregs); - imap = ((volatile unsigned int *)offset); - - /* SYSIO inconsistancy. For external SLOTS, we have to select - * the right ICLR register based upon the lower SBUS irq level - * bits. - */ - if(ino >= 0x20) { - iclr = sysio_imap_to_iclr(imap); - } else { - unsigned long iclraddr; - int sbus_slot = (ino & 0x18)>>3; - - sbus_level = ino & 0x7; - - switch(sbus_slot) { - case 0: - iclr = &sregs->iclr_slot0; - break; - case 1: - iclr = &sregs->iclr_slot1; - break; - case 2: - iclr = &sregs->iclr_slot2; - break; - default: - case 3: - iclr = &sregs->iclr_slot3; - break; - }; - - iclraddr = (unsigned long) iclr; - iclraddr += ((sbus_level - 1) * 8); - iclr = (volatile unsigned int *) iclraddr; - } - return build_irq(pil, sbus_level, iclr, imap); -} - static void atomic_bucket_insert(struct ino_bucket *bucket) { unsigned long pstate; @@ -602,7 +475,7 @@ *(bucket->pil + irq_action) = action->next; if(action->flags & SA_IMAP_MASKED) { - volatile unsigned int *imap = bucket->imap; + unsigned long imap = bucket->imap; void **vector, *orig; int ent; @@ -696,10 +569,10 @@ int cpu = smp_processor_id(); printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [%ld %ld]\n", + printk("irq: %d [%u %u]\n", atomic_read(&global_irq_count), cpu_data[0].irq_count, cpu_data[1].irq_count); - printk("bh: %d [%ld %ld]\n", + printk("bh: %d [%u %u]\n", (spin_is_locked(&global_bh_count) ? 1 : 0), cpu_data[0].bh_count, cpu_data[1].bh_count); } @@ -947,10 +820,10 @@ if (should_forward != 0) { /* Push it to our buddy. */ should_forward = 0; - *(bp->imap) = (buddy | SYSIO_IMAP_VALID); + upa_writel(buddy | IMAP_VALID, bp->imap); } #endif - *(bp->iclr) = SYSIO_ICLR_IDLE; + upa_writel(ICLR_IDLE, bp->iclr); } } else bp->pending = 1; @@ -974,7 +847,7 @@ bucket = (struct ino_bucket *)action->mask; floppy_interrupt(irq, dev_cookie, regs); - *(bucket->iclr) = SYSIO_ICLR_IDLE; + upa_writel(ICLR_IDLE, bucket->iclr); irq_exit(cpu, irq); } @@ -1116,7 +989,7 @@ #endif /* Register IRQ handler. */ - err = request_irq(build_irq(0, 0, NULL, NULL), cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC), + err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); if(err) { @@ -1157,7 +1030,7 @@ { extern int this_is_starfire; struct ino_bucket *bucket = __bucket(p->mask); - volatile unsigned int *imap = bucket->imap; + unsigned long imap = bucket->imap; unsigned int tid; /* Never change this, it causes problems on Ex000 systems. */ @@ -1167,12 +1040,12 @@ if(this_is_starfire == 0) { tid = __cpu_logical_map[goal_cpu] << 26; } else { - extern unsigned int starfire_translate(volatile unsigned int *imap, + extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26); } - *imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID); + upa_writel(IMAP_VALID | (tid & IMAP_TID), imap); goal_cpu++; if(goal_cpu >= NR_CPUS || diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c --- v2.3.34/linux/arch/sparc64/kernel/pci.c Sat Oct 9 11:47:50 1999 +++ linux/arch/sparc64/kernel/pci.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.6 1999/09/08 03:40:41 davem Exp $ +/* $Id: pci.c,v 1.11 1999/12/20 05:02:07 davem Exp $ * pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) @@ -20,8 +20,11 @@ #include #include +#ifndef NEW_PCI_DMA_MAP unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ]; unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ]; +#endif + unsigned long pci_memspace_mask = 0xffffffffUL; #ifndef CONFIG_PCI @@ -199,6 +202,30 @@ }; void pcibios_fixup_bus(struct pci_bus *pbus) +{ +} + +void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1, + struct resource *res2, int index) +{ +} + +void pcibios_update_irq(struct pci_dev *pdev, int irq) +{ +} + +unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res, + unsigned long start, unsigned long size) +{ + return start; +} + +void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, + struct pbus_set_ranges_data *pranges) +{ +} + +void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c --- v2.3.34/linux/arch/sparc64/kernel/pci_common.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/pci_common.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: pci_common.c,v 1.3 1999/09/04 22:26:32 ecd Exp $ +/* $Id: pci_common.c,v 1.5 1999/12/20 05:02:11 davem Exp $ * pci_common.c: PCI controller common support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -362,7 +362,7 @@ size = res->end - res->start; align = size + 1; - if (allocate_resource(root, res, size + 1, min, max, align) < 0) { + if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) { /* uh oh */ prom_printf("PCI: Failed to allocate resource %d for %s\n", i, pdev->name); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h --- v2.3.34/linux/arch/sparc64/kernel/pci_impl.h Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/pci_impl.h Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: pci_impl.h,v 1.3 1999/09/10 10:40:44 davem Exp $ +/* $Id: pci_impl.h,v 1.4 1999/12/17 12:32:03 jj Exp $ * pci_impl.h: Helper definitions for PCI controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -34,6 +34,7 @@ extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); +#ifndef NEW_PCI_DMA_MAP /* IOMMU/DVMA initialization. */ #define PCI_DVMA_HASH_NONE ~0UL static __inline__ void set_dvma_hash(unsigned long dvma_offset, @@ -46,6 +47,7 @@ pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr; pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr; } +#endif /* Configuration space access. */ extern spinlock_t pci_poke_lock; diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c --- v2.3.34/linux/arch/sparc64/kernel/pci_iommu.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/pci_iommu.c Mon Dec 20 22:05:52 1999 @@ -1,12 +1,17 @@ -/* $Id: pci_iommu.c,v 1.1 1999/08/30 10:00:47 davem Exp $ +/* $Id: pci_iommu.c,v 1.7 1999/12/20 14:08:15 jj Exp $ * pci_iommu.c: UltraSparc PCI controller IOM/STC support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) + * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */ +#include +#include +#include + #include -#include -#include + +#include "iommu_common.h" #define PCI_STC_CTXMATCH_ADDR(STC, CTX) \ ((STC)->strbuf_ctxmatch_base + ((CTX) << 3)) @@ -29,27 +34,67 @@ : "r" (__val), "r" (__reg), \ "i" (ASI_PHYS_BYPASS_EC_E)) -/* Find a range of iommu mappings of size NPAGES in page - * table PGT. Return pointer to first iopte. - */ -static iopte_t *iommu_find_range(unsigned long npages, iopte_t *pgt, int pgt_size) +static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) { - int i; + iopte_t *iopte; + unsigned long cnum, ent; - pgt_size -= npages; - for (i = 0; i < pgt_size; i++) { - if (!iopte_val(pgt[i]) & IOPTE_VALID) { - int scan; - - for (scan = 1; scan < npages; scan++) { - if (iopte_val(pgt[i + scan]) & IOPTE_VALID) { - i += scan; - goto do_next; - } + cnum = 0; + while ((1UL << cnum) < npages) + cnum++; + iopte = iommu->page_table + (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); + iopte += ((ent = iommu->lowest_free[cnum]) << cnum); + + if (iopte_val(iopte[(1UL << cnum)]) == 0UL) { + /* Fast path. */ + iommu->lowest_free[cnum] = ent + 1; + } else { + unsigned long pte_off = 1; + + ent += 1; + do { + pte_off++; + ent++; + } while (iopte_val(iopte[(pte_off << cnum)]) != 0UL); + iommu->lowest_free[cnum] = ent; + } + + /* I've got your streaming cluster right here buddy boy... */ + return iopte; +} + +static inline void free_streaming_cluster(struct pci_iommu *iommu, u32 base, unsigned long npages) +{ + unsigned long cnum, ent; + + cnum = 0; + while ((1UL << cnum) < npages) + cnum++; + ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) + >> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits); + if (ent < iommu->lowest_free[cnum]) + iommu->lowest_free[cnum] = ent; +} + +/* We allocate consistant mappings from the end of cluster zero. */ +static iopte_t *alloc_consistant_cluster(struct pci_iommu *iommu, unsigned long npages) +{ + iopte_t *iopte; + + iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); + while (iopte > iommu->page_table) { + iopte--; + if (!(iopte_val(*iopte) & IOPTE_VALID)) { + unsigned long tmp = npages; + + while (--tmp) { + iopte--; + if (iopte_val(*iopte) & IOPTE_VALID) + break; } - return &pgt[i]; + if (tmp == 0) + return iopte; } - do_next: } return NULL; } @@ -64,123 +109,168 @@ #define IOPTE_INVALID 0UL -/* Map kernel buffer at ADDR of size SZ using consistant mode - * DMA for PCI device PDEV. Return 32-bit PCI DMA address. +/* Allocate and map kernel buffer of size SIZE using consistant mode + * DMA for PCI device PDEV. Return non-NULL cpu-side address if + * successful and set *DMA_ADDRP to the PCI side dma address. */ -u32 pci_map_consistant(struct pci_dev *pdev, void *addr, int sz) +void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_iommu *iommu = &pcp->pbm->parent->iommu; - iopte_t *base; - unsigned long flags, npages, oaddr; - u32 ret; + struct pcidev_cookie *pcp; + struct pci_iommu *iommu; + iopte_t *iopte; + unsigned long flags, order, first_page, ctx; + void *ret; + int npages; + + if (size <= 0 || pdev == NULL || + pdev->sysdata == NULL || dma_addrp == NULL) + return NULL; + + size = PAGE_ALIGN(size); + for (order = 0; order < 10; order++) { + if ((PAGE_SIZE << order) >= size) + break; + } + if (order == 10) + return NULL; + + first_page = __get_free_pages(GFP_ATOMIC, order); + if (first_page == 0UL) + return NULL; + memset((char *)first_page, 0, PAGE_SIZE << order); + + pcp = pdev->sysdata; + iommu = &pcp->pbm->parent->iommu; spin_lock_irqsave(&iommu->lock, flags); - oaddr = (unsigned long)addr; - npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - base = iommu_find_range(npages, - iommu->page_table, iommu->page_table_sz); - ret = 0; - if (base != NULL) { - unsigned long i, base_paddr, ctx; - - ret = (iommu->page_table_map_base + - ((base - iommu->page_table) << PAGE_SHIFT)); - ret |= (oaddr & ~PAGE_MASK); - base_paddr = __pa(oaddr & PAGE_MASK); - ctx = 0; - if (iommu->iommu_has_ctx_flush) - ctx = iommu->iommu_cur_ctx++; - for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) - iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr); + iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT); + if (iopte == NULL) { + spin_unlock_irqrestore(&iommu->lock, flags); + free_pages(first_page, order); + return NULL; } + + *dma_addrp = (iommu->page_table_map_base + + ((iopte - iommu->page_table) << PAGE_SHIFT)); + ret = (void *) first_page; + npages = size >> PAGE_SHIFT; + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = iommu->iommu_cur_ctx++; + first_page = __pa(first_page); + while (npages--) { + iopte_val(*iopte) = IOPTE_CONSISTANT(ctx, first_page); + iopte++; + first_page += PAGE_SIZE; + } + + if (iommu->iommu_ctxflush) { + pci_iommu_write(iommu->iommu_ctxflush, ctx); + } else { + int i; + u32 daddr = *dma_addrp; + + npages = size >> PAGE_SHIFT; + for (i = 0; i < npages; i++) { + pci_iommu_write(iommu->iommu_flush, daddr); + daddr += PAGE_SIZE; + } + } + spin_unlock_irqrestore(&iommu->lock, flags); return ret; } -/* Unmap a consistant DMA translation. */ -void pci_unmap_consistant(struct pci_dev *pdev, u32 bus_addr, int sz) +/* Free and unmap a consistant DMA translation. */ +void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu, u32 dvma) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_iommu *iommu = &pcp->pbm->parent->iommu; - iopte_t *base; - unsigned long flags, npages, i, ctx; + struct pcidev_cookie *pcp; + struct pci_iommu *iommu; + iopte_t *iopte; + unsigned long flags, order, npages, i; + + if (size <= 0 || pdev == NULL || + pdev->sysdata == NULL || cpu == NULL) + return; + + npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + pcp = pdev->sysdata; + iommu = &pcp->pbm->parent->iommu; + iopte = iommu->page_table + + ((dvma - iommu->page_table_map_base) >> PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); - npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; - base = iommu->page_table + - ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); /* Data for consistant mappings cannot enter the streaming - * buffers, so we only need to update the TSB and flush - * those entries from the IOMMU's TLB. + * buffers, so we only need to update the TSB. Flush of the + * IOTLB is done later when these ioptes are used for a new + * allocation. */ - /* Step 1: Clear out the TSB entries. Save away - * the context if necessary. - */ - ctx = 0; - if (iommu->iommu_has_ctx_flush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - for (i = 0; i < npages; i++, base++) - iopte_val(*base) = IOPTE_INVALID; - - /* Step 2: Flush from IOMMU TLB. */ - if (iommu->iommu_has_ctx_flush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - bus_addr &= PAGE_MASK; - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) - pci_iommu_write(iommu->iommu_flush, bus_addr); - } - - /* Step 3: Ensure completion of previous PIO writes. */ - (void) pci_iommu_read(iommu->write_complete_reg); + for (i = 0; i < npages; i++, iopte++) + iopte_val(*iopte) = IOPTE_INVALID; spin_unlock_irqrestore(&iommu->lock, flags); + + for (order = 0; order < 10; order++) { + if ((PAGE_SIZE << order) >= size) + break; + } + if (order < 10) + free_pages((unsigned long)cpu, order); } /* Map a single buffer at PTR of SZ bytes for PCI DMA * in streaming mode. */ -u32 pci_map_single(struct pci_dev *pdev, void *ptr, int sz) +u32 pci_map_single(struct pci_dev *pdev, void *ptr, long sz) { struct pcidev_cookie *pcp = pdev->sysdata; struct pci_iommu *iommu = &pcp->pbm->parent->iommu; + struct pci_strbuf *strbuf = &pcp->pbm->stc; iopte_t *base; unsigned long flags, npages, oaddr; - u32 ret; + unsigned long i, base_paddr, ctx; + u32 bus_addr, ret; - spin_lock_irqsave(&iommu->lock, flags); oaddr = (unsigned long)ptr; npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK); npages >>= PAGE_SHIFT; - base = iommu_find_range(npages, - iommu->page_table, iommu->page_table_sz); - ret = 0; - if (base != NULL) { - unsigned long i, base_paddr, ctx; - - ret = (iommu->page_table_map_base + - ((base - iommu->page_table) << PAGE_SHIFT)); - ret |= (oaddr & ~PAGE_MASK); - base_paddr = __pa(oaddr & PAGE_MASK); - ctx = 0; - if (iommu->iommu_has_ctx_flush) - ctx = iommu->iommu_cur_ctx++; + + spin_lock_irqsave(&iommu->lock, flags); + + base = alloc_streaming_cluster(iommu, npages); + bus_addr = (iommu->page_table_map_base + + ((base - iommu->page_table) << PAGE_SHIFT)); + ret = bus_addr | (oaddr & ~PAGE_MASK); + base_paddr = __pa(oaddr & PAGE_MASK); + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = iommu->iommu_cur_ctx++; + if (strbuf->strbuf_enabled) { for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr); + } else { + for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE) + iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr); + } + + /* Flush the IOMMU TLB. */ + if (iommu->iommu_ctxflush) { + pci_iommu_write(iommu->iommu_ctxflush, ctx); + } else { + for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + pci_iommu_write(iommu->iommu_flush, bus_addr); } + spin_unlock_irqrestore(&iommu->lock, flags); return ret; } /* Unmap a single streaming mode DMA translation. */ -void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, int sz) +void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, long sz) { struct pcidev_cookie *pcp = pdev->sysdata; struct pci_iommu *iommu = &pcp->pbm->parent->iommu; @@ -188,25 +278,26 @@ iopte_t *base; unsigned long flags, npages, i, ctx; - spin_lock_irqsave(&iommu->lock, flags); npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK); npages >>= PAGE_SHIFT; base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); bus_addr &= PAGE_MASK; - /* Step 1: Record the context, if any. */ - ctx = 0; - if (iommu->iommu_has_ctx_flush) - ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; + spin_lock_irqsave(&iommu->lock, flags); - /* Step 2: Kick data out of streaming buffers if necessary. */ + /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) { u32 vaddr = bus_addr; + /* Record the context, if any. */ + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; + PCI_STC_FLUSHFLAG_INIT(strbuf); - if (strbuf->strbuf_has_ctx_flush && - iommu->iommu_has_ctx_flush) { + if (strbuf->strbuf_ctxflush && + iommu->iommu_ctxflush) { unsigned long matchreg, flushreg; flushreg = strbuf->strbuf_ctxflush; @@ -225,69 +316,159 @@ membar("#LoadLoad"); } - /* Step 3: Clear out TSB entries. */ - for (i = 0; i < npages; i++, base++) - iopte_val(*base) = IOPTE_INVALID; + /* Step 2: Clear out first TSB entry. */ + iopte_val(*base) = IOPTE_INVALID; - /* Step 4: Flush the IOMMU TLB. */ - if (iommu->iommu_has_ctx_flush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) - pci_iommu_write(iommu->iommu_flush, bus_addr); - } + free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages); - /* Step 5: Ensure completion of previous PIO writes. */ + /* Step 3: Ensure completion of previous PIO writes. */ (void) pci_iommu_read(iommu->write_complete_reg); spin_unlock_irqrestore(&iommu->lock, flags); } +static inline struct scatterlist *fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents, unsigned long ctx, int streaming) +{ + struct scatterlist *dma_sg = sg; + + do { + unsigned long pteval = ~0UL; + u32 dma_npages; + + dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_sg->dvma_length + + ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + do { + unsigned long offset; + signed int len; + + /* If we are here, we know we have at least one + * more page to map. So walk forward until we + * hit a page crossing, and begin creating new + * mappings from that spot. + */ + for (;;) { + unsigned long tmp; + + tmp = (unsigned long) __pa(sg->address); + len = sg->length; + if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { + pteval = tmp & PAGE_MASK; + offset = tmp & (PAGE_SIZE - 1UL); + break; + } + if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { + pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + offset = 0UL; + len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + break; + } + sg++; + } + + if (streaming) + pteval = IOPTE_STREAMING(ctx, pteval); + else + pteval = IOPTE_CONSISTANT(ctx, pteval); + while (len > 0) { + *iopte++ = __iopte(pteval); + pteval += PAGE_SIZE; + len -= (PAGE_SIZE - offset); + offset = 0; + dma_npages--; + } + + pteval = (pteval & IOPTE_PAGE) + len; + sg++; + + /* Skip over any tail mappings we've fully mapped, + * adjusting pteval along the way. Stop when we + * detect a page crossing event. + */ + while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + pteval == __pa(sg->address) && + ((pteval ^ + (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + pteval += sg->length; + sg++; + } + if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + pteval = ~0UL; + } while (dma_npages != 0); + dma_sg++; + } while (dma_sg->dvma_length != 0); + return dma_sg; +} + /* Map a set of buffers described by SGLIST with NELEMS array * elements in streaming mode for PCI DMA. + * When making changes here, inspect the assembly output. I was having + * hard time to kepp this routine out of using stack slots for holding variables. */ -void pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems) +int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems) { - struct pcidev_cookie *pcp = pdev->sysdata; - struct pci_iommu *iommu = &pcp->pbm->parent->iommu; - unsigned long flags, ctx, i; + struct pcidev_cookie *pcp; + struct pci_iommu *iommu; + struct pci_strbuf *strbuf; + unsigned long flags, ctx, i, npages; + iopte_t *base; + u32 dma_base; + struct scatterlist *sgtmp; + int tmp; + + /* Fast path single entry scatterlists. */ + if (nelems == 1) { + sglist->dvma_address = pci_map_single(pdev, sglist->address, sglist->length); + sglist->dvma_length = sglist->length; + return 1; + } + + pcp = pdev->sysdata; + iommu = &pcp->pbm->parent->iommu; + strbuf = &pcp->pbm->stc; + + /* Step 1: Prepare scatter list. */ + + npages = prepare_sg(sglist, nelems); + + /* Step 2: Allocate a cluster. */ spin_lock_irqsave(&iommu->lock, flags); - /* Step 1: Choose a context if necessary. */ + base = alloc_streaming_cluster(iommu, npages); + dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT); + + /* Step 3: Normalize DMA addresses. */ + tmp = nelems; + + sgtmp = sglist; + while (tmp-- && sgtmp->dvma_length) { + sgtmp->dvma_address += dma_base; + sgtmp++; + } + + /* Step 4: Choose a context if necessary. */ ctx = 0; - if (iommu->iommu_has_ctx_flush) + if (iommu->iommu_ctxflush) ctx = iommu->iommu_cur_ctx++; - /* Step 2: Create the mappings. */ - for (i = 0; i < nelems; i++) { - unsigned long oaddr, npages; - iopte_t *base; - - oaddr = (unsigned long)sglist[i].address; - npages = PAGE_ALIGN(oaddr + sglist[i].length) - (oaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - base = iommu_find_range(npages, - iommu->page_table, iommu->page_table_sz); - if (base != NULL) { - unsigned long j, base_paddr; - u32 dvma_addr; - - dvma_addr = (iommu->page_table_map_base + - ((base - iommu->page_table) << PAGE_SHIFT)); - dvma_addr |= (oaddr & ~PAGE_MASK); - sglist[i].dvma_address = dvma_addr; - sglist[i].dvma_length = sglist[i].length; - base_paddr = __pa(oaddr & PAGE_MASK); - for (j = 0; j < npages; j++, base++, base_paddr += PAGE_SIZE) - iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr); - } else { - sglist[i].dvma_address = 0; - sglist[i].dvma_length = 0; - } + /* Step 5: Create the mappings. */ + sgtmp = fill_sg (base, sglist, nelems, ctx, strbuf->strbuf_enabled); +#ifdef VERIFY_SG + verify_sglist(sglist, nelems, base, npages); +#endif + + /* Step 6: Flush the IOMMU TLB. */ + if (iommu->iommu_ctxflush) { + pci_iommu_write(iommu->iommu_ctxflush, ctx); + } else { + for (i = 0; i < npages; i++, dma_base += PAGE_SIZE) + pci_iommu_write(iommu->iommu_flush, dma_base); } spin_unlock_irqrestore(&iommu->lock, flags); + + return sgtmp - sglist; } /* Unmap a set of streaming mode DMA translations. */ @@ -296,25 +477,38 @@ struct pcidev_cookie *pcp = pdev->sysdata; struct pci_iommu *iommu = &pcp->pbm->parent->iommu; struct pci_strbuf *strbuf = &pcp->pbm->stc; - unsigned long flags, ctx, i; + iopte_t *base; + unsigned long flags, ctx, i, npages; + u32 bus_addr; + + bus_addr = sglist->dvma_address & PAGE_MASK; + + i = 0; + if (nelems > 1) { + for (; i < nelems; i++) + if (sglist[i].dvma_length == 0) + break; + i--; + } + npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + + base = iommu->page_table + + ((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT); spin_lock_irqsave(&iommu->lock, flags); - /* Step 1: Record the context, if any. */ - ctx = 0; - if (iommu->iommu_has_ctx_flush) { - iopte_t *iopte; + /* Step 1: Kick data out of streaming buffers if necessary. */ + if (strbuf->strbuf_enabled) { + u32 vaddr = bus_addr; - iopte = iommu->page_table + - ((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT); - ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; - } + /* Record the context, if any. */ + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL; - /* Step 2: Kick data out of streaming buffers if necessary. */ - if (strbuf->strbuf_enabled) { PCI_STC_FLUSHFLAG_INIT(strbuf); - if (strbuf->strbuf_has_ctx_flush && - iommu->iommu_has_ctx_flush) { + if (strbuf->strbuf_ctxflush && + iommu->iommu_ctxflush) { unsigned long matchreg, flushreg; flushreg = strbuf->strbuf_ctxflush; @@ -323,66 +517,22 @@ pci_iommu_write(flushreg, ctx); } while(((long)pci_iommu_read(matchreg)) < 0L); } else { - for (i = 0; i < nelems; i++) { - unsigned long j, npages; - u32 vaddr; - - j = sglist[i].dvma_length; - if (!j) - break; - vaddr = sglist[i].dvma_address; - npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - vaddr &= PAGE_MASK; - for (j = 0; j < npages; j++, vaddr += PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, vaddr); - } - - pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); - (void) pci_iommu_read(iommu->write_complete_reg); - while (!PCI_STC_FLUSHFLAG_SET(strbuf)) - membar("#LoadLoad"); + for (i = 0; i < npages; i++, vaddr += PAGE_SIZE) + pci_iommu_write(strbuf->strbuf_pflush, vaddr); } - } - - /* Step 3: Clear out TSB entries. */ - for (i = 0; i < nelems; i++) { - unsigned long j, npages; - iopte_t *base; - u32 vaddr; - j = sglist[i].dvma_length; - if (!j) - break; - vaddr = sglist[i].dvma_address; - npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - base = iommu->page_table + - ((vaddr - iommu->page_table_map_base) >> PAGE_SHIFT); - for (j = 0; j < npages; j++, base++) - iopte_val(*base) = IOPTE_INVALID; + pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa); + (void) pci_iommu_read(iommu->write_complete_reg); + while (!PCI_STC_FLUSHFLAG_SET(strbuf)) + membar("#LoadLoad"); } - /* Step 4: Flush the IOMMU TLB. */ - if (iommu->iommu_has_ctx_flush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - for (i = 0; i < nelems; i++) { - unsigned long j, npages; - u32 vaddr; + /* Step 2: Clear out first TSB entry. */ + iopte_val(*base) = IOPTE_INVALID; - j = sglist[i].dvma_length; - if (!j) - break; - vaddr = sglist[i].dvma_address; - npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK); - npages >>= PAGE_SHIFT; - for (j = 0; j < npages; j++, vaddr += PAGE_SIZE) - pci_iommu_write(iommu->iommu_flush, vaddr); - } - } + free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages); - /* Step 5: Ensure completion of previous PIO writes. */ + /* Step 3: Ensure completion of previous PIO writes. */ (void) pci_iommu_read(iommu->write_complete_reg); spin_unlock_irqrestore(&iommu->lock, flags); @@ -391,7 +541,7 @@ /* Make physical memory consistant for a single * streaming mode DMA translation after a transfer. */ -void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, int sz) +void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, long sz) { struct pcidev_cookie *pcp = pdev->sysdata; struct pci_iommu *iommu = &pcp->pbm->parent->iommu; @@ -409,8 +559,8 @@ /* Step 1: Record the context, if any. */ ctx = 0; - if (iommu->iommu_has_ctx_flush && - strbuf->strbuf_has_ctx_flush) { + if (iommu->iommu_ctxflush && + strbuf->strbuf_ctxflush) { iopte_t *iopte; iopte = iommu->page_table + @@ -420,8 +570,8 @@ /* Step 2: Kick data out of streaming buffers. */ PCI_STC_FLUSHFLAG_INIT(strbuf); - if (iommu->iommu_has_ctx_flush && - strbuf->strbuf_has_ctx_flush) { + if (iommu->iommu_ctxflush && + strbuf->strbuf_ctxflush) { unsigned long matchreg, flushreg; flushreg = strbuf->strbuf_ctxflush; @@ -462,8 +612,8 @@ /* Step 1: Record the context, if any. */ ctx = 0; - if (iommu->iommu_has_ctx_flush && - strbuf->strbuf_has_ctx_flush) { + if (iommu->iommu_ctxflush && + strbuf->strbuf_ctxflush) { iopte_t *iopte; iopte = iommu->page_table + @@ -473,8 +623,8 @@ /* Step 2: Kick data out of streaming buffers. */ PCI_STC_FLUSHFLAG_INIT(strbuf); - if (iommu->iommu_has_ctx_flush && - strbuf->strbuf_has_ctx_flush) { + if (iommu->iommu_ctxflush && + strbuf->strbuf_ctxflush) { unsigned long matchreg, flushreg; flushreg = strbuf->strbuf_ctxflush; @@ -483,21 +633,21 @@ pci_iommu_write(flushreg, ctx); } while (((long)pci_iommu_read(matchreg)) < 0L); } else { - unsigned long i; + unsigned long i, npages; + u32 bus_addr; - for(i = 0; i < nelems; i++) { - unsigned long bus_addr, npages, j; + i = 0; + bus_addr = sglist[0].dvma_address & PAGE_MASK; - j = sglist[i].dvma_length; - if (!j) - break; - bus_addr = sglist[i].dvma_address; - npages = PAGE_ALIGN(bus_addr + j) - (bus_addr & PAGE_MASK); - npages >>= PAGE_SHIFT; - bus_addr &= PAGE_MASK; - for(j = 0; i < npages; i++, bus_addr += PAGE_SIZE) - pci_iommu_write(strbuf->strbuf_pflush, bus_addr); + if (nelems > 1) { + for(; i < nelems; i++) + if (!sglist[i].dvma_length) + break; + i--; } + npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT; + for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE) + pci_iommu_write(strbuf->strbuf_pflush, bus_addr); } /* Step 3: Perform flush synchronization sequence. */ diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c --- v2.3.34/linux/arch/sparc64/kernel/pci_psycho.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/pci_psycho.c Mon Dec 20 22:05:52 1999 @@ -1,9 +1,9 @@ -/* $Id: pci_psycho.c,v 1.4 1999/09/05 09:33:36 ecd Exp $ +/* $Id: pci_psycho.c,v 1.7 1999/12/17 12:31:57 jj Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */ #include @@ -380,7 +380,7 @@ unsigned int ino) { struct ino_bucket *bucket; - volatile unsigned int *imap, *iclr; + unsigned long imap, iclr; unsigned long imap_off, iclr_off; int pil, inofixup = 0; @@ -399,12 +399,12 @@ /* Now build the IRQ bucket. */ pil = psycho_ino_to_pil(pdev, ino); - imap = (volatile unsigned int *)__va(p->controller_regs + imap_off); - imap += 1; + imap = p->controller_regs + imap_off; + imap += 4; iclr_off = psycho_iclr_offset(ino); - iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off); - iclr += 1; + iclr = p->controller_regs + iclr_off; + iclr += 4; if ((ino & 0x20) == 0) inofixup = ino & 0x03; @@ -838,6 +838,10 @@ "DMA Read" : ((error_bits & PSYCHO_CEAFSR_PDWR) ? "DMA Write" : "???"))))); + + /* XXX Use syndrome and afar to print out module string just like + * XXX UDB CE trap handler does... -DaveM + */ printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "UPA_MID[%02lx] was_block(%d)\n", p->index, @@ -1213,26 +1217,28 @@ psycho_register_error_handlers(p); } -static void __init psycho_iommu_init(struct pci_controller_info *p, int tsbsize) +static void __init psycho_iommu_init(struct pci_controller_info *p) { - extern int this_is_starfire; - extern void *starfire_hookup(int); +#ifndef NEW_PCI_DMA_MAP struct linux_mlist_p1275 *mlist; - unsigned long tsbbase, i, n, order; + unsigned long n; iopte_t *iopte; + int tsbsize = 32; +#endif + extern int this_is_starfire; + extern void *starfire_hookup(int); + unsigned long tsbbase, i; u64 control; /* Setup initial software IOMMU state. */ spin_lock_init(&p->iommu.lock); p->iommu.iommu_cur_ctx = 0; - /* PSYCHO's IOMMU lacks ctx flushing. */ - p->iommu.iommu_has_ctx_flush = 0; - /* Register addresses. */ p->iommu.iommu_control = p->controller_regs + PSYCHO_IOMMU_CONTROL; p->iommu.iommu_tsbbase = p->controller_regs + PSYCHO_IOMMU_TSBBASE; p->iommu.iommu_flush = p->controller_regs + PSYCHO_IOMMU_FLUSH; + /* PSYCHO's IOMMU lacks ctx flushing. */ p->iommu.iommu_ctxflush = 0; /* We use the main control register of PSYCHO as the write @@ -1252,18 +1258,29 @@ control &= ~(PSYCHO_IOMMU_CTRL_DENAB); psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for(order = 0;; order++) - if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8)) - break; - - tsbbase = __get_free_pages(GFP_DMA, order); +#ifndef NEW_PCI_DMA_MAP + /* Using assumed page size 64K with 32K entries we need 256KB iommu page + * table (32K ioptes * 8 bytes per iopte). This is + * page order 5 on UltraSparc. + */ + tsbbase = __get_free_pages(GFP_KERNEL, 5); +#else + /* Using assumed page size 8K with 128K entries we need 1MB iommu page + * table (128K ioptes * 8 bytes per iopte). This is + * page order 7 on UltraSparc. + */ + tsbbase = __get_free_pages(GFP_KERNEL, 7); +#endif if (!tsbbase) { prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); } - p->iommu.page_table = iopte = (iopte_t *)tsbbase; - p->iommu.page_table_sz = (tsbsize * 1024); + p->iommu.page_table = (iopte_t *)tsbbase; + p->iommu.page_table_sz_bits = 17; + p->iommu.page_table_map_base = 0xc0000000; +#ifndef NEW_PCI_DMA_MAP + iopte = (iopte_t *)tsbbase; /* Initialize to "none" settings. */ for(i = 0; i < PCI_DVMA_HASHSZ; i++) { pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE; @@ -1329,10 +1346,11 @@ prom_printf("Try booting with mem=xxxM or similar\n"); prom_halt(); } - +#endif psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase)); control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL); +#ifndef NEW_PCI_DMA_MAP control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ); control |= (PSYCHO_IOMMU_CTRL_TBWSZ | PSYCHO_IOMMU_CTRL_ENAB); switch(tsbsize) { @@ -1353,6 +1371,10 @@ prom_halt(); break; } +#else + control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); + control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); +#endif psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control); /* If necessary, hook us up for starfire IRQ translations. */ @@ -1426,9 +1448,6 @@ /* Currently we don't even use it. */ pbm->stc.strbuf_enabled = 0; - /* PSYCHO's streaming buffer lacks ctx flushing. */ - pbm->stc.strbuf_has_ctx_flush = 0; - if (is_pbm_a) { pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; @@ -1438,6 +1457,7 @@ pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; } + /* PSYCHO's streaming buffer lacks ctx flushing. */ pbm->stc.strbuf_ctxflush = 0; pbm->stc.strbuf_ctxmatch_base = 0; @@ -1599,7 +1619,7 @@ psycho_controller_hwinit(p); - psycho_iommu_init(p, 32); + psycho_iommu_init(p); is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); psycho_pbm_init(p, node, is_pbm_a); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c --- v2.3.34/linux/arch/sparc64/kernel/pci_sabre.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/pci_sabre.c Mon Dec 20 22:05:52 1999 @@ -1,9 +1,9 @@ -/* $Id: pci_sabre.c,v 1.2 1999/09/05 04:58:06 davem Exp $ +/* $Id: pci_sabre.c,v 1.7 1999/12/19 09:17:51 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */ #include @@ -65,6 +65,14 @@ #define SABRE_IOMMUCTRL_LCKEN 0x0000000000800000UL /* IOTLB lock enable */ #define SABRE_IOMMUCTRL_LCKPTR 0x0000000000780000UL /* IOTLB lock pointer */ #define SABRE_IOMMUCTRL_TSBSZ 0x0000000000070000UL /* TSB Size */ +#define SABRE_IOMMU_TSBSZ_1K 0x0000000000000000 +#define SABRE_IOMMU_TSBSZ_2K 0x0000000000010000 +#define SABRE_IOMMU_TSBSZ_4K 0x0000000000020000 +#define SABRE_IOMMU_TSBSZ_8K 0x0000000000030000 +#define SABRE_IOMMU_TSBSZ_16K 0x0000000000040000 +#define SABRE_IOMMU_TSBSZ_32K 0x0000000000050000 +#define SABRE_IOMMU_TSBSZ_64K 0x0000000000060000 +#define SABRE_IOMMU_TSBSZ_128K 0x0000000000070000 #define SABRE_IOMMUCTRL_TBWSZ 0x0000000000000004UL /* TSB assumed page size */ #define SABRE_IOMMUCTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */ #define SABRE_IOMMUCTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */ @@ -601,7 +609,7 @@ unsigned int ino) { struct ino_bucket *bucket; - volatile unsigned int *imap, *iclr; + unsigned long imap, iclr; unsigned long imap_off, iclr_off; int pil, inofixup = 0; @@ -620,12 +628,12 @@ /* Now build the IRQ bucket. */ pil = sabre_ino_to_pil(pdev, ino); - imap = (volatile unsigned int *)__va(p->controller_regs + imap_off); - imap += 1; + imap = p->controller_regs + imap_off; + imap += 4; iclr_off = sabre_iclr_offset(ino); - iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off); - iclr += 1; + iclr = p->controller_regs + iclr_off; + iclr += 4; if ((ino & 0x20) == 0) inofixup = ino & 0x03; @@ -717,13 +725,13 @@ type_string = "Unknown"; break; }; - printk("SABRE%d: IOMMU TAG(%d)[error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - p->index, i, type_string, + printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", + p->index, i, tag, type_string, ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), ((tag & SABRE_IOMMUTAG_VPN) << PAGE_SHIFT)); - printk("SABRE%d: IOMMU DATA(%d)[valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - p->index, i, + printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", + p->index, i, data, ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), @@ -814,6 +822,10 @@ "DMA Read" : ((error_bits & SABRE_CEAFSR_PDWR) ? "DMA Write" : "???"))); + + /* XXX Use syndrome and afar to print out module string just like + * XXX UDB CE trap handler does... -DaveM + */ printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "was_block(%d)\n", p->index, @@ -1021,17 +1033,8 @@ static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) { struct pci_dev *pdev; - u32 dword; u16 word; - for(pdev = pci_devices; pdev; pdev = pdev->next) { - if(pdev->vendor == PCI_VENDOR_ID_SUN && - pdev->device == PCI_DEVICE_ID_SUN_SABRE) { - sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64); - break; - } - } - for (pdev = sabre_bus->devices; pdev; pdev = pdev->sibling) { if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { @@ -1044,32 +1047,6 @@ /* Status register bits are "write 1 to clear". */ sabre_write_word(pdev, PCI_STATUS, 0xffff); sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff); - - sabre_read_word(pdev, PCI_BRIDGE_CONTROL, &word); - word = PCI_BRIDGE_CTL_MASTER_ABORT | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_PARITY; - sabre_write_word(pdev, PCI_BRIDGE_CONTROL, word); - - sabre_read_dword(pdev, APB_PCI_CONTROL_HIGH, &dword); - dword = APB_PCI_CTL_HIGH_SERR | - APB_PCI_CTL_HIGH_ARBITER_EN; - sabre_write_dword(pdev, APB_PCI_CONTROL_HIGH, dword); - - /* Systems with SIMBA are usually workstations, so - * we configure to park to SIMBA not to the previous - * bus owner. - */ - sabre_read_dword(pdev, APB_PCI_CONTROL_LOW, &dword); - dword = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f; - sabre_write_dword(pdev, APB_PCI_CONTROL_LOW, dword); - - /* Don't mess with the retry limit and PIO/DMA latency - * timer settings. But do set primary and secondary - * latency timers. - */ - sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64); - sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); } } } @@ -1124,30 +1101,49 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, int tsbsize, unsigned long dvma_offset) { +#ifndef NEW_PCI_DMA_MAP struct linux_mlist_p1275 *mlist; - unsigned long tsbbase, i, n, order; + unsigned long n; iopte_t *iopte; +#endif + unsigned long tsbbase, i, order; u64 control; + /* Setup initial software IOMMU state. */ + spin_lock_init(&p->iommu.lock); + p->iommu.iommu_cur_ctx = 0; + + /* Register addresses. */ + p->iommu.iommu_control = p->controller_regs + SABRE_IOMMU_CONTROL; + p->iommu.iommu_tsbbase = p->controller_regs + SABRE_IOMMU_TSBBASE; + p->iommu.iommu_flush = p->controller_regs + SABRE_IOMMU_FLUSH; + p->iommu.write_complete_reg = p->controller_regs + SABRE_WRSYNC; + /* Sabre's IOMMU lacks ctx flushing. */ + p->iommu.iommu_ctxflush = 0; + /* Invalidate TLB Entries. */ control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL); - control |= IOMMU_CTRL_DENAB; + control |= SABRE_IOMMUCTRL_DENAB; sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); for(i = 0; i < 16; i++) sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); - control &= ~(IOMMU_CTRL_DENAB); + control &= ~(SABRE_IOMMUCTRL_DENAB); sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); for(order = 0;; order++) if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8)) break; - tsbbase = __get_free_pages(GFP_DMA, order); + tsbbase = __get_free_pages(GFP_KERNEL, order); if (!tsbbase) { prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n"); prom_halt(); } + p->iommu.page_table = (iopte_t *)tsbbase; + p->iommu.page_table_map_base = dvma_offset; + +#ifndef NEW_PCI_DMA_MAP iopte = (iopte_t *)tsbbase; /* Initialize to "none" settings. */ @@ -1216,27 +1212,47 @@ prom_printf("Try booting with mem=xxxM or similar\n"); prom_halt(); } +#endif sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL); - control &= ~(IOMMU_CTRL_TSBSZ); - control |= (IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB); +#ifndef NEW_PCI_DMA_MAP + control &= ~(SABRE_IOMMUCTRL_TSBSZ); + control |= (SABRE_IOMMUCTRL_TBWSZ | SABRE_IOMMUCTRL_ENAB); switch(tsbsize) { case 8: - control |= IOMMU_TSBSZ_8K; + control |= SABRE_IOMMU_TSBSZ_8K; break; case 16: - control |= IOMMU_TSBSZ_16K; + control |= SABRE_IOMMU_TSBSZ_16K; break; case 32: - control |= IOMMU_TSBSZ_32K; + control |= SABRE_IOMMU_TSBSZ_32K; break; default: prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); prom_halt(); break; } +#else + control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); + control |= SABRE_IOMMUCTRL_ENAB; + switch(tsbsize) { + case 64: + control |= SABRE_IOMMU_TSBSZ_64K; + p->iommu.page_table_sz_bits = 16; + break; + case 128: + control |= SABRE_IOMMU_TSBSZ_128K; + p->iommu.page_table_sz_bits = 17; + break; + default: + prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); + prom_halt(); + break; + } +#endif sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control); } @@ -1445,6 +1461,7 @@ } switch(vdma[1]) { +#ifndef NEW_PCI_DMA_MAP case 0x20000000: tsbsize = 8; break; @@ -1454,6 +1471,15 @@ case 0x80000000: tsbsize = 32; break; +#else + case 0x20000000: + tsbsize = 64; + break; + case 0x40000000: + case 0x80000000: + tsbsize = 128; + break; +#endif default: prom_printf("SABRE: strange virtual-dma size.\n"); prom_halt(); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c --- v2.3.34/linux/arch/sparc64/kernel/power.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/power.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: power.c,v 1.4 1999/08/31 18:22:05 davem Exp $ +/* $Id: power.c,v 1.5 1999/12/19 23:28:00 davem Exp $ * power.c: Power management driver. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -90,16 +90,18 @@ return; found: - power_reg = edev->resource[0].start; + power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4); printk("power: Control reg at %016lx ... ", power_reg); if (kernel_thread(powerd, 0, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; } printk("powerd running.\n"); - if (request_irq(edev->irqs[0], - power_handler, SA_SHIRQ, "power", - (void *) power_reg) < 0) - printk("power: Error, cannot register IRQ handler.\n"); + if (edev->irqs[0] != 0) { + if (request_irq(edev->irqs[0], + power_handler, SA_SHIRQ, "power", + (void *) power_reg) < 0) + printk("power: Error, cannot register IRQ handler.\n"); + } } #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.3.34/linux/arch/sparc64/kernel/process.c Thu Nov 11 20:11:32 1999 +++ linux/arch/sparc64/kernel/process.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.100 1999/08/31 04:39:39 davem Exp $ +/* $Id: process.c,v 1.102 1999/12/15 22:24:49 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -268,7 +269,7 @@ unsigned long flags; spin_lock_irqsave(®dump_lock, flags); - printk("CPU[%d]: local_irq_count[%ld] global_irq_count[%d]\n", + printk("CPU[%d]: local_irq_count[%u] global_irq_count[%d]\n", smp_processor_id(), local_irq_count, atomic_read(&global_irq_count)); #endif @@ -801,36 +802,4 @@ out: unlock_kernel(); return error; -} - -/* - * These bracket the sleeping functions.. - */ -extern void scheduling_functions_start_here(void); -extern void scheduling_functions_end_here(void); -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long pc, fp, bias = 0; - unsigned long task_base = (unsigned long) p; - struct reg_window *rw; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - bias = STACK_BIAS; - fp = p->thread.ksp + bias; - do { - /* Bogus frame pointer? */ - if (fp < (task_base + sizeof(struct task_struct)) || - fp >= (task_base + (2 * PAGE_SIZE))) - break; - rw = (struct reg_window *) fp; - pc = rw->ins[7]; - if (pc < first_sched || pc >= last_sched) - return pc; - fp = rw->ins[6] + bias; - } while (++count < 16); - return 0; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c --- v2.3.34/linux/arch/sparc64/kernel/sbus.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/kernel/sbus.c Mon Dec 20 22:05:52 1999 @@ -0,0 +1,1145 @@ +/* $Id: sbus.c,v 1.6 1999/12/20 14:08:17 jj Exp $ + * sbus.c: UltraSparc SBUS controller support. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "iommu_common.h" + +/* These should be allocated on an SMP_CACHE_BYTES + * aligned boundry for optimal performance. + * + * On SYSIO, using an 8K page size we have 1GB of SBUS + * DMA space mapped. We divide this space into equally + * sized clusters. Currently we allow clusters up to a + * size of 1MB. If anything begins to generate DMA + * mapping requests larger than this we will need to + * increase things a bit. + */ + +#define NCLUSTERS 8UL +#define ONE_GIG (1UL * 1024UL * 1024UL * 1024UL) +#define CLUSTER_SIZE (ONE_GIG / NCLUSTERS) +#define CLUSTER_MASK (CLUSTER_SIZE - 1) +#define CLUSTER_NPAGES (CLUSTER_SIZE >> PAGE_SHIFT) +#define MAP_BASE ((u32)0xc0000000) + +struct sbus_iommu { +/*0x00*/spinlock_t lock; + +/*0x08*/iopte_t *page_table; +/*0x10*/unsigned long strbuf_regs; +/*0x18*/unsigned long iommu_regs; +/*0x20*/unsigned long sbus_control_reg; + +/*0x28*/volatile unsigned long strbuf_flushflag; + + /* If NCLUSTERS is ever decresed to 4 or lower, + * you must increase the size of the type of + * these counters. You have been duly warned. -DaveM + */ +/*0x30*/u16 lowest_free[NCLUSTERS]; +}; + +/* Flushing heuristics */ +#define IOMMU_DIAG_LIM 16 +#define STRBUF_DIAG_LIM 32 + +/* Offsets from iommu_regs */ +#define SYSIO_IOMMUREG_BASE 0x2400UL +#define IOMMU_CONTROL (0x2400UL - 0x2400UL) /* IOMMU control register */ +#define IOMMU_TSBBASE (0x2408UL - 0x2400UL) /* TSB base address register */ +#define IOMMU_FLUSH (0x2410UL - 0x2400UL) /* IOMMU flush register */ +#define IOMMU_VADIAG (0x4400UL - 0x2400UL) /* SBUS virtual address diagnostic */ +#define IOMMU_TAGCMP (0x4408UL - 0x2400UL) /* TLB tag compare diagnostics */ +#define IOMMU_LRUDIAG (0x4500UL - 0x2400UL) /* IOMMU LRU queue diagnostics */ +#define IOMMU_TAGDIAG (0x4580UL - 0x2400UL) /* TLB tag diagnostics */ +#define IOMMU_DRAMDIAG (0x4600UL - 0x2400UL) /* TLB data RAM diagnostics */ + +#define IOMMU_DRAM_VALID (1UL << 30UL) + +static void __iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) +{ + int hit = 0; + + if (npages <= IOMMU_DIAG_LIM) { + while (npages--) + upa_writeq(base + (npages << PAGE_SHIFT), + iommu->iommu_regs + IOMMU_FLUSH); + hit = 1; + } else { + u32 limit = base + ((npages << PAGE_SHIFT) - 1UL); + unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; + unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG; + int entry; + + for (entry = 0; entry < 16; entry++, dram += 8, tag += 8) { + u32 addr = ((u32)upa_readq(tag) << PAGE_SHIFT); + if (addr >= base && addr <= limit) { + u64 val = upa_readq(dram); + + if (val & IOMMU_DRAM_VALID) { + upa_writeq(addr, + iommu->iommu_regs + IOMMU_FLUSH); + hit = 1; + } + } + } + } + if (hit != 0) + upa_readq(iommu->sbus_control_reg); +} + +/* In an effort to keep latency under control, we special + * case single page IOMMU flushes. + */ +static __inline__ void iommu_flush(struct sbus_iommu *iommu, + u32 base, unsigned long npages) +{ + if (npages == 1) { + upa_writeq(base, iommu->iommu_regs + IOMMU_FLUSH); + upa_readq(iommu->sbus_control_reg); + } else + __iommu_flush(iommu, base, npages); +} + +/* Offsets from strbuf_regs */ +#define SYSIO_STRBUFREG_BASE 0x2800UL +#define STRBUF_CONTROL (0x2800UL - 0x2800UL) /* Control */ +#define STRBUF_PFLUSH (0x2808UL - 0x2800UL) /* Page flush/invalidate */ +#define STRBUF_FSYNC (0x2810UL - 0x2800UL) /* Flush synchronization */ +#define STRBUF_DRAMDIAG (0x5000UL - 0x2800UL) /* data RAM diagnostic */ +#define STRBUF_ERRDIAG (0x5400UL - 0x2800UL) /* error status diagnostics */ +#define STRBUF_PTAGDIAG (0x5800UL - 0x2800UL) /* Page tag diagnostics */ +#define STRBUF_LTAGDIAG (0x5900UL - 0x2800UL) /* Line tag diagnostics */ + +#define STRBUF_TAG_VALID 0x02UL + +static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages) +{ + int hit = 0; + + iommu->strbuf_flushflag = 0UL; + if (npages <= STRBUF_DIAG_LIM) { + while (npages--) + upa_writeq(base + (npages << PAGE_SHIFT), + iommu->strbuf_regs + STRBUF_PFLUSH); + hit = 1; + } else { + u32 limit = base + ((npages << PAGE_SHIFT) - 1UL); + unsigned long tag = iommu->strbuf_regs + STRBUF_PTAGDIAG; + int entry; + + for (entry = 0; entry < 16; entry++, tag += 8) { + u64 val = upa_readq(tag); + + if (val & STRBUF_TAG_VALID) { + u32 addr = ((u32)(val & ~3UL)) << (PAGE_SHIFT - 2UL); + if (addr >= base && addr <= limit) { + upa_writeq(addr, + iommu->strbuf_regs + STRBUF_PFLUSH); + hit = 1; + } + } + } + } + if (hit != 0) { + /* Whoopee cushion! */ + upa_writeq(__pa(&iommu->strbuf_flushflag), + iommu->strbuf_regs + STRBUF_FSYNC); + upa_readq(iommu->sbus_control_reg); + while (iommu->strbuf_flushflag == 0UL) + membar("#LoadLoad"); + } +} + +static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages) +{ + iopte_t *iopte; + unsigned long cnum, ent; + + cnum = 0; + while ((1UL << cnum) < npages) + cnum++; + iopte = iommu->page_table + (cnum * CLUSTER_NPAGES); + iopte += ((ent = iommu->lowest_free[cnum]) << cnum); + + if (iopte_val(iopte[(1UL << cnum)]) == 0UL) { + /* Fast path. */ + iommu->lowest_free[cnum] = ent + 1; + } else { + unsigned long pte_off = 1; + + ent += 1; + do { + pte_off++; + ent++; + } while (iopte_val(iopte[(pte_off << cnum)]) != 0UL); + iommu->lowest_free[cnum] = ent; + } + + /* I've got your streaming cluster right here buddy boy... */ + return iopte; +} + +static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) +{ + unsigned long cnum, ent; + iopte_t *iopte; + + cnum = 0; + while ((1UL << cnum) < npages) + cnum++; + ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum); + iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + iopte_val(*iopte) = 0UL; + if (ent < iommu->lowest_free[cnum]) + iommu->lowest_free[cnum] = ent; +} + +/* We allocate consistant mappings from the end of cluster zero. */ +static iopte_t *alloc_consistant_cluster(struct sbus_iommu *iommu, unsigned long npages) +{ + iopte_t *iopte; + + iopte = iommu->page_table + (1 * CLUSTER_NPAGES); + while (iopte > iommu->page_table) { + iopte--; + if (!(iopte_val(*iopte) & IOPTE_VALID)) { + unsigned long tmp = npages; + + while (--tmp) { + iopte--; + if (iopte_val(*iopte) & IOPTE_VALID) + break; + } + if (tmp == 0) + return iopte; + } + } + return NULL; +} + +static void free_consistant_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages) +{ + iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT); + + while (npages--) + *iopte++ = __iopte(0UL); +} + +void *sbus_alloc_consistant(struct sbus_dev *sdev, long size, u32 *dvma_addr) +{ + unsigned long order, first_page, flags; + struct sbus_iommu *iommu; + iopte_t *iopte; + void *ret; + int npages; + + if (size <= 0 || sdev == NULL || dvma_addr == NULL) + return NULL; + + size = PAGE_ALIGN(size); + for (order = 0; order < 10; order++) { + if ((PAGE_SIZE << order) >= size) + break; + } + if (order == 10) + return NULL; + first_page = __get_free_pages(GFP_KERNEL, order); + if (first_page == 0UL) + return NULL; + memset((char *)first_page, 0, PAGE_SIZE << order); + + iommu = sdev->bus->iommu; + + spin_lock_irqsave(&iommu->lock, flags); + iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT); + if (iopte == NULL) { + spin_unlock_irqrestore(&iommu->lock, flags); + free_pages(first_page, order); + return NULL; + } + + /* Ok, we're committed at this point. */ + *dvma_addr = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + ret = (void *) first_page; + npages = size >> PAGE_SHIFT; + while (npages--) { + *iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | + (__pa(first_page) & IOPTE_PAGE)); + first_page += PAGE_SIZE; + } + iommu_flush(iommu, *dvma_addr, size >> PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); + + return ret; +} + +void sbus_free_consistant(struct sbus_dev *sdev, long size, void *cpu, u32 dvma) +{ + unsigned long order, npages; + struct sbus_iommu *iommu; + + if (size <= 0 || sdev == NULL || cpu == NULL) + return; + + npages = PAGE_ALIGN(size) >> PAGE_SHIFT; + iommu = sdev->bus->iommu; + + spin_lock_irq(&iommu->lock); + free_consistant_cluster(iommu, dvma, npages); + spin_unlock_irq(&iommu->lock); + + for (order = 0; order < 10; order++) { + if ((PAGE_SIZE << order) >= size) + break; + } + if (order < 10) + free_pages((unsigned long)cpu, order); +} + +u32 sbus_map_single(struct sbus_dev *sdev, void *ptr, long size) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + unsigned long npages, phys_base, flags; + iopte_t *iopte; + u32 dma_base, offset; + + phys_base = (unsigned long) ptr; + offset = (u32) (phys_base & ~PAGE_MASK); + size = (PAGE_ALIGN(phys_base + size) - (phys_base & PAGE_MASK)); + phys_base = (unsigned long) __pa(phys_base & PAGE_MASK); + + spin_lock_irqsave(&iommu->lock, flags); + npages = size >> PAGE_SHIFT; + iopte = alloc_streaming_cluster(iommu, npages); + dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + npages = size >> PAGE_SHIFT; + while (npages--) { + *iopte++ = __iopte(IOPTE_VALID | IOPTE_STBUF | + IOPTE_CACHE | IOPTE_WRITE | + (phys_base & IOPTE_PAGE)); + phys_base += PAGE_SIZE; + } + npages = size >> PAGE_SHIFT; + iommu_flush(iommu, dma_base, npages); + spin_unlock_irqrestore(&iommu->lock, flags); + + return (dma_base | offset); +} + +void sbus_unmap_single(struct sbus_dev *sdev, u32 dma_addr, long size) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + u32 dma_base = dma_addr & PAGE_MASK; + unsigned long flags; + + size = (PAGE_ALIGN(dma_addr + size) - dma_base); + + spin_lock_irqsave(&iommu->lock, flags); + free_streaming_cluster(iommu, dma_base, size >> PAGE_SHIFT); + strbuf_flush(iommu, dma_base, size >> PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents) +{ + struct scatterlist *dma_sg = sg; + + do { + unsigned long pteval = ~0UL; + u32 dma_npages; + + dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) + + dma_sg->dvma_length + + ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT; + do { + unsigned long offset; + signed int len; + + /* If we are here, we know we have at least one + * more page to map. So walk forward until we + * hit a page crossing, and begin creating new + * mappings from that spot. + */ + for (;;) { + unsigned long tmp; + + tmp = (unsigned long) __pa(sg->address); + len = sg->length; + if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) { + pteval = tmp & PAGE_MASK; + offset = tmp & (PAGE_SIZE - 1UL); + break; + } + if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) { + pteval = (tmp + PAGE_SIZE) & PAGE_MASK; + offset = 0UL; + len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL))); + break; + } + sg++; + } + + pteval = ((pteval & IOPTE_PAGE) | + IOPTE_VALID | IOPTE_STBUF | + IOPTE_CACHE | IOPTE_WRITE); + while (len > 0) { + *iopte++ = __iopte(pteval); + pteval += PAGE_SIZE; + len -= (PAGE_SIZE - offset); + offset = 0; + dma_npages--; + } + + pteval = (pteval & IOPTE_PAGE) + len; + sg++; + + /* Skip over any tail mappings we've fully mapped, + * adjusting pteval along the way. Stop when we + * detect a page crossing event. + */ + while ((pteval << (64 - PAGE_SHIFT)) != 0UL && + pteval == __pa(sg->address) && + ((pteval ^ + (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) { + pteval += sg->length; + sg++; + } + if ((pteval << (64 - PAGE_SHIFT)) == 0UL) + pteval = ~0UL; + } while (dma_npages != 0); + dma_sg++; + } while (dma_sg->dvma_length != 0); +} + +int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + unsigned long flags, npages; + iopte_t *iopte; + u32 dma_base; + struct scatterlist *sgtmp; + int unused; + + /* Fast path single entry scatterlists. */ + if (nents == 1) { + sg->dvma_address = sbus_map_single(sdev, sg->address, sg->length); + sg->dvma_length = sg->length; + return 1; + } + + npages = prepare_sg(sg, nents); + + spin_lock_irqsave(&iommu->lock, flags); + iopte = alloc_streaming_cluster(iommu, npages); + dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT); + + /* Normalize DVMA addresses. */ + sgtmp = sg; + unused = nents; + + while (unused && sgtmp->dvma_length) { + sgtmp->dvma_address += dma_base; + sgtmp++; + unused--; + } + + fill_sg(iopte, sg, nents); +#ifdef VERIFY_SG + verify_sglist(sg, nents, iopte, npages); +#endif + iommu_flush(iommu, dma_base, npages); + spin_unlock_irqrestore(&iommu->lock, flags); + + return nents - unused; +} + +void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents) +{ + unsigned long size, flags; + struct sbus_iommu *iommu; + u32 dvma_base; + int i; + + /* Fast path single entry scatterlists. */ + if (nents == 1) { + sbus_unmap_single(sdev, sg->dvma_address, sg->dvma_length); + return; + } + + dvma_base = sg[0].dvma_address & PAGE_MASK; + for (i = 0; i < nents; i++) { + if (sg[i].dvma_length == 0) + break; + } + i--; + size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base; + + iommu = sdev->bus->iommu; + spin_lock_irqsave(&iommu->lock, flags); + free_streaming_cluster(iommu, dvma_base, size >> PAGE_SHIFT); + strbuf_flush(iommu, dvma_base, size >> PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +void sbus_dma_sync_single(struct sbus_dev *sdev, u32 base, long size) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + unsigned long flags; + + size = (PAGE_ALIGN(base + size) - (base & PAGE_MASK)); + + spin_lock_irqsave(&iommu->lock, flags); + strbuf_flush(iommu, base & PAGE_MASK, size >> PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + unsigned long flags, size; + u32 base; + int i; + + base = sg[0].dvma_address & PAGE_MASK; + for (i = 0; i < nents; i++) { + if (sg[i].dvma_length == 0) + break; + } + i--; + size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base; + + spin_lock_irqsave(&iommu->lock, flags); + strbuf_flush(iommu, base, size >> PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +/* Enable 64-bit DVMA mode for the given device. */ +void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) +{ + struct sbus_iommu *iommu = sdev->bus->iommu; + int slot = sdev->slot; + unsigned long cfg_reg; + u64 val; + + cfg_reg = iommu->sbus_control_reg; + switch (slot) { + case 0: + cfg_reg += 0x20UL; + break; + case 1: + cfg_reg += 0x28UL; + break; + case 2: + cfg_reg += 0x30UL; + break; + case 3: + cfg_reg += 0x38UL; + break; + case 13: + cfg_reg += 0x40UL; + break; + case 14: + cfg_reg += 0x48UL; + break; + case 15: + cfg_reg += 0x50UL; + break; + + default: + return; + }; + + val = upa_readq(cfg_reg); + if (val & (1UL << 14UL)) { + /* Extended transfer mode already enabled. */ + return; + } + + val |= (1UL << 14UL); + + if (bursts & DMA_BURST8) + val |= (1UL << 1UL); + if (bursts & DMA_BURST16) + val |= (1UL << 2UL); + if (bursts & DMA_BURST32) + val |= (1UL << 3UL); + if (bursts & DMA_BURST64) + val |= (1UL << 4UL); + upa_writeq(val, cfg_reg); +} + +/* SBUS SYSIO INO number to Sparc PIL level. */ +static unsigned char sysio_ino_to_pil[] = { + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 0 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 1 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 2 */ + 0, 1, 2, 7, 5, 7, 8, 9, /* SBUS slot 3 */ + 3, /* Onboard SCSI */ + 5, /* Onboard Ethernet */ +/*XXX*/ 8, /* Onboard BPP */ + 0, /* Bogon */ + 13, /* Audio */ +/*XXX*/15, /* PowerFail */ + 0, /* Bogon */ + 0, /* Bogon */ + 12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */ + 11, /* Floppy */ + 0, /* Spare Hardware (bogon for now) */ + 0, /* Keyboard (bogon for now) */ + 0, /* Mouse (bogon for now) */ + 0, /* Serial (bogon for now) */ + 0, 0, /* Bogon, Bogon */ + 10, /* Timer 0 */ + 11, /* Timer 1 */ + 0, 0, /* Bogon, Bogon */ + 15, /* Uncorrectable SBUS Error */ + 15, /* Correctable SBUS Error */ + 15, /* SBUS Error */ +/*XXX*/ 0, /* Power Management (bogon for now) */ +}; + +/* INO number to IMAP register offset for SYSIO external IRQ's. + * This should conform to both Sunfire/Wildfire server and Fusion + * desktop designs. + */ +#define SYSIO_IMAP_SLOT0 0x2c04UL +#define SYSIO_IMAP_SLOT1 0x2c0cUL +#define SYSIO_IMAP_SLOT2 0x2c14UL +#define SYSIO_IMAP_SLOT3 0x2c1cUL +#define SYSIO_IMAP_SCSI 0x3004UL +#define SYSIO_IMAP_ETH 0x300cUL +#define SYSIO_IMAP_BPP 0x3014UL +#define SYSIO_IMAP_AUDIO 0x301cUL +#define SYSIO_IMAP_PFAIL 0x3024UL +#define SYSIO_IMAP_KMS 0x302cUL +#define SYSIO_IMAP_FLPY 0x3034UL +#define SYSIO_IMAP_SHW 0x303cUL +#define SYSIO_IMAP_KBD 0x3044UL +#define SYSIO_IMAP_MS 0x304cUL +#define SYSIO_IMAP_SER 0x3054UL +#define SYSIO_IMAP_TIM0 0x3064UL +#define SYSIO_IMAP_TIM1 0x306cUL +#define SYSIO_IMAP_UE 0x3074UL +#define SYSIO_IMAP_CE 0x307cUL +#define SYSIO_IMAP_SBERR 0x3084UL +#define SYSIO_IMAP_PMGMT 0x308cUL +#define SYSIO_IMAP_GFX 0x3094UL +#define SYSIO_IMAP_EUPA 0x309cUL + +#define bogon ((unsigned long) -1) +static unsigned long sysio_irq_offsets[] = { + /* SBUS Slot 0 --> 3, level 1 --> 7 */ + SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, + SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, + SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, + SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, + SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, + SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, + SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, + SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, + + /* Onboard devices (not relevant/used on SunFire). */ + SYSIO_IMAP_SCSI, + SYSIO_IMAP_ETH, + SYSIO_IMAP_BPP, + bogon, + SYSIO_IMAP_AUDIO, + SYSIO_IMAP_PFAIL, + bogon, + bogon, + SYSIO_IMAP_KMS, + SYSIO_IMAP_FLPY, + SYSIO_IMAP_SHW, + SYSIO_IMAP_KBD, + SYSIO_IMAP_MS, + SYSIO_IMAP_SER, + bogon, + bogon, + SYSIO_IMAP_TIM0, + SYSIO_IMAP_TIM1, + bogon, + bogon, + SYSIO_IMAP_UE, + SYSIO_IMAP_CE, + SYSIO_IMAP_SBERR, + SYSIO_IMAP_PMGMT, +}; + +#undef bogon + +#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0])) + +/* Convert Interrupt Mapping register pointer to assosciated + * Interrupt Clear register pointer, SYSIO specific version. + */ +#define SYSIO_ICLR_UNUSED0 0x3400UL +#define SYSIO_ICLR_SLOT0 0x340cUL +#define SYSIO_ICLR_SLOT1 0x344cUL +#define SYSIO_ICLR_SLOT2 0x348cUL +#define SYSIO_ICLR_SLOT3 0x34ccUL +static unsigned long sysio_imap_to_iclr(unsigned long imap) +{ + unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0; + return imap + diff; +} + +unsigned int sbus_build_irq(void *buscookie, unsigned int ino) +{ + struct sbus_bus *sbus = (struct sbus_bus *)buscookie; + struct sbus_iommu *iommu = sbus->iommu; + unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + unsigned long imap, iclr; + int pil, sbus_level = 0; + + pil = sysio_ino_to_pil[ino]; + if (!pil) { + printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino); + panic("Bad SYSIO IRQ translations..."); + } + imap = sysio_irq_offsets[ino]; + if (imap == ((unsigned long)-1)) { + prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n", + ino, pil); + prom_halt(); + } + imap += reg_base; + + /* SYSIO inconsistancy. For external SLOTS, we have to select + * the right ICLR register based upon the lower SBUS irq level + * bits. + */ + if (ino >= 0x20) { + iclr = sysio_imap_to_iclr(imap); + } else { + int sbus_slot = (ino & 0x18)>>3; + + sbus_level = ino & 0x7; + + switch(sbus_slot) { + case 0: + iclr = reg_base + SYSIO_ICLR_SLOT0; + break; + case 1: + iclr = reg_base + SYSIO_ICLR_SLOT1; + break; + case 2: + iclr = reg_base + SYSIO_ICLR_SLOT2; + break; + default: + case 3: + iclr = reg_base + SYSIO_ICLR_SLOT3; + break; + }; + + iclr += ((unsigned long)sbus_level - 1UL) * 8UL; + } + return build_irq(pil, sbus_level, iclr, imap); +} + +/* Error interrupt handling. */ +#define SYSIO_UE_AFSR 0x0030UL +#define SYSIO_UE_AFAR 0x0038UL +#define SYSIO_UEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define SYSIO_UEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define SYSIO_UEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define SYSIO_UEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define SYSIO_UEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define SYSIO_UEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define SYSIO_UEAFSR_RESV1 0x03ff000000000000 /* Reserved */ +#define SYSIO_UEAFSR_DOFF 0x0000e00000000000 /* Doubleword Offset */ +#define SYSIO_UEAFSR_SIZE 0x00001c0000000000 /* Bad transfer size is 2**SIZE */ +#define SYSIO_UEAFSR_MID 0x000003e000000000 /* UPA MID causing the fault */ +#define SYSIO_UEAFSR_RESV2 0x0000001fffffffff /* Reserved */ +static void sysio_ue_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sbus_bus *sbus = dev_id; + struct sbus_iommu *iommu = sbus->iommu; + unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + unsigned long afsr_reg, afar_reg; + unsigned long afsr, afar, error_bits; + int reported; + + afsr_reg = reg_base + SYSIO_UE_AFSR; + afar_reg = reg_base + SYSIO_UE_AFAR; + + /* Latch error status. */ + afsr = upa_readq(afsr_reg); + afar = upa_readq(afar_reg); + + /* Clear primary/secondary error status bits. */ + error_bits = afsr & + (SYSIO_UEAFSR_PPIO | SYSIO_UEAFSR_PDRD | SYSIO_UEAFSR_PDWR | + SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); + upa_writeq(error_bits, afsr_reg); + + /* Log the error. */ + printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", + sbus->portid, + (((error_bits & SYSIO_UEAFSR_PPIO) ? + "PIO" : + ((error_bits & SYSIO_UEAFSR_PDRD) ? + "DVMA Read" : + ((error_bits & SYSIO_UEAFSR_PDWR) ? + "DVMA Write" : "???"))))); + printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", + sbus->portid, + (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, + (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, + (afsr & SYSIO_UEAFSR_MID) >> 37UL); + printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); + printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); + reported = 0; + if (afsr & SYSIO_UEAFSR_SPIO) { + reported++; + printk("(PIO)"); + } + if (afsr & SYSIO_UEAFSR_SDRD) { + reported++; + printk("(DVMA Read)"); + } + if (afsr & SYSIO_UEAFSR_SDWR) { + reported++; + printk("(DVMA Write)"); + } + if (!reported) + printk("(none)"); + printk("]\n"); +} + +#define SYSIO_CE_AFSR 0x0040UL +#define SYSIO_CE_AFAR 0x0048UL +#define SYSIO_CEAFSR_PPIO 0x8000000000000000 /* Primary PIO is cause */ +#define SYSIO_CEAFSR_PDRD 0x4000000000000000 /* Primary DVMA read is cause */ +#define SYSIO_CEAFSR_PDWR 0x2000000000000000 /* Primary DVMA write is cause */ +#define SYSIO_CEAFSR_SPIO 0x1000000000000000 /* Secondary PIO is cause */ +#define SYSIO_CEAFSR_SDRD 0x0800000000000000 /* Secondary DVMA read is cause */ +#define SYSIO_CEAFSR_SDWR 0x0400000000000000 /* Secondary DVMA write is cause*/ +#define SYSIO_CEAFSR_RESV1 0x0300000000000000 /* Reserved */ +#define SYSIO_CEAFSR_ESYND 0x00ff000000000000 /* Syndrome Bits */ +#define SYSIO_CEAFSR_DOFF 0x0000e00000000000 /* Double Offset */ +#define SYSIO_CEAFSR_SIZE 0x00001c0000000000 /* Bad transfer size is 2**SIZE */ +#define SYSIO_CEAFSR_MID 0x000003e000000000 /* UPA MID causing the fault */ +#define SYSIO_CEAFSR_RESV2 0x0000001fffffffff /* Reserved */ +static void sysio_ce_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sbus_bus *sbus = dev_id; + struct sbus_iommu *iommu = sbus->iommu; + unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + unsigned long afsr_reg, afar_reg; + unsigned long afsr, afar, error_bits; + int reported; + + afsr_reg = reg_base + SYSIO_CE_AFSR; + afar_reg = reg_base + SYSIO_CE_AFAR; + + /* Latch error status. */ + afsr = upa_readq(afsr_reg); + afar = upa_readq(afar_reg); + + /* Clear primary/secondary error status bits. */ + error_bits = afsr & + (SYSIO_CEAFSR_PPIO | SYSIO_CEAFSR_PDRD | SYSIO_CEAFSR_PDWR | + SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); + upa_writeq(error_bits, afsr_reg); + + printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", + sbus->portid, + (((error_bits & SYSIO_CEAFSR_PPIO) ? + "PIO" : + ((error_bits & SYSIO_CEAFSR_PDRD) ? + "DVMA Read" : + ((error_bits & SYSIO_CEAFSR_PDWR) ? + "DVMA Write" : "???"))))); + + /* XXX Use syndrome and afar to print out module string just like + * XXX UDB CE trap handler does... -DaveM + */ + printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", + sbus->portid, + (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, + (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, + (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, + (afsr & SYSIO_CEAFSR_MID) >> 37UL); + printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); + + printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); + reported = 0; + if (afsr & SYSIO_CEAFSR_SPIO) { + reported++; + printk("(PIO)"); + } + if (afsr & SYSIO_CEAFSR_SDRD) { + reported++; + printk("(DVMA Read)"); + } + if (afsr & SYSIO_CEAFSR_SDWR) { + reported++; + printk("(DVMA Write)"); + } + if (!reported) + printk("(none)"); + printk("]\n"); +} + +#define SYSIO_SBUS_AFSR 0x2010UL +#define SYSIO_SBUS_AFAR 0x2018UL +#define SYSIO_SBAFSR_PLE 0x8000000000000000 /* Primary Late PIO Error */ +#define SYSIO_SBAFSR_PTO 0x4000000000000000 /* Primary SBUS Timeout */ +#define SYSIO_SBAFSR_PBERR 0x2000000000000000 /* Primary SBUS Error ACK */ +#define SYSIO_SBAFSR_SLE 0x1000000000000000 /* Secondary Late PIO Error */ +#define SYSIO_SBAFSR_STO 0x0800000000000000 /* Secondary SBUS Timeout */ +#define SYSIO_SBAFSR_SBERR 0x0400000000000000 /* Secondary SBUS Error ACK */ +#define SYSIO_SBAFSR_RESV1 0x03ff000000000000 /* Reserved */ +#define SYSIO_SBAFSR_RD 0x0000800000000000 /* Primary was late PIO read */ +#define SYSIO_SBAFSR_RESV2 0x0000600000000000 /* Reserved */ +#define SYSIO_SBAFSR_SIZE 0x00001c0000000000 /* Size of transfer */ +#define SYSIO_SBAFSR_MID 0x000003e000000000 /* MID causing the error */ +#define SYSIO_SBAFSR_RESV3 0x0000001fffffffff /* Reserved */ +static void sysio_sbus_error_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sbus_bus *sbus = dev_id; + struct sbus_iommu *iommu = sbus->iommu; + unsigned long afsr_reg, afar_reg, reg_base; + unsigned long afsr, afar, error_bits; + int reported; + + reg_base = iommu->sbus_control_reg - 0x2000UL; + afsr_reg = reg_base + SYSIO_SBUS_AFSR; + afar_reg = reg_base + SYSIO_SBUS_AFAR; + + afsr = upa_readq(afsr_reg); + afar = upa_readq(afar_reg); + + /* Clear primary/secondary error status bits. */ + error_bits = afsr & + (SYSIO_SBAFSR_PLE | SYSIO_SBAFSR_PTO | SYSIO_SBAFSR_PBERR | + SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); + upa_writeq(error_bits, afsr_reg); + + /* Log the error. */ + printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", + sbus->portid, + (((error_bits & SYSIO_SBAFSR_PLE) ? + "Late PIO Error" : + ((error_bits & SYSIO_SBAFSR_PTO) ? + "Time Out" : + ((error_bits & SYSIO_SBAFSR_PBERR) ? + "Error Ack" : "???")))), + (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); + printk("SYSIO[%x]: size[%lx] MID[%lx]\n", + sbus->portid, + (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, + (afsr & SYSIO_SBAFSR_MID) >> 37UL); + printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); + printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); + reported = 0; + if (afsr & SYSIO_SBAFSR_SLE) { + reported++; + printk("(Late PIO Error)"); + } + if (afsr & SYSIO_SBAFSR_STO) { + reported++; + printk("(Time Out)"); + } + if (afsr & SYSIO_SBAFSR_SBERR) { + reported++; + printk("(Error Ack)"); + } + if (!reported) + printk("(none)"); + printk("]\n"); + + /* XXX check iommu/strbuf for further error status XXX */ +} + +#define ECC_CONTROL 0x0020UL +#define SYSIO_ECNTRL_ECCEN 0x8000000000000000 /* Enable ECC Checking */ +#define SYSIO_ECNTRL_UEEN 0x4000000000000000 /* Enable UE Interrupts */ +#define SYSIO_ECNTRL_CEEN 0x2000000000000000 /* Enable CE Interrupts */ + +#define SYSIO_UE_INO 0x34 +#define SYSIO_CE_INO 0x35 +#define SYSIO_SBUSERR_INO 0x36 + +static void __init sysio_register_error_handlers(struct sbus_bus *sbus) +{ + struct sbus_iommu *iommu = sbus->iommu; + unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL; + unsigned int irq; + u64 control; + + irq = sbus_build_irq(sbus, SYSIO_UE_INO); + if (request_irq(irq, sysio_ue_handler, + SA_SHIRQ, "SYSIO UE", sbus) < 0) { + prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", + sbus->portid); + prom_halt(); + } + + irq = sbus_build_irq(sbus, SYSIO_CE_INO); + if (request_irq(irq, sysio_ce_handler, + SA_SHIRQ, "SYSIO CE", sbus) < 0) { + prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", + sbus->portid); + prom_halt(); + } + + irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); + if (request_irq(irq, sysio_sbus_error_handler, + SA_SHIRQ, "SYSIO SBUS Error", sbus) < 0) { + prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", + sbus->portid); + prom_halt(); + } + + /* Now turn the error interrupts on and also enable ECC checking. */ + upa_writeq((SYSIO_ECNTRL_ECCEN | + SYSIO_ECNTRL_UEEN | + SYSIO_ECNTRL_CEEN), + reg_base + ECC_CONTROL); + + control = upa_readq(iommu->sbus_control_reg); + control |= 0x100UL; /* SBUS Error Interrupt Enable */ + upa_writeq(control, iommu->sbus_control_reg); +} + +/* Boot time initialization. */ +void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) +{ + struct linux_prom64_registers rprop; + struct sbus_iommu *iommu; + unsigned long regs, tsb_base; + u64 control; + int err, i; + + sbus->portid = prom_getintdefault(sbus->prom_node, + "upa-portid", -1); + + err = prom_getproperty(prom_node, "reg", + (char *)&rprop, sizeof(rprop)); + if (err < 0) { + prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n"); + prom_halt(); + } + regs = rprop.phys_addr; + + iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC); + if (iommu == NULL) { + prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n"); + prom_halt(); + } + + /* Align on E$ line boundry. */ + iommu = (struct sbus_iommu *) + (((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) & + ~(SMP_CACHE_BYTES - 1UL)); + + memset(iommu, 0, sizeof(*iommu)); + + /* Setup spinlock. */ + spin_lock_init(&iommu->lock); + + /* Init register offsets. */ + iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE; + iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE; + + /* The SYSIO SBUS control register is used for dummy reads + * in order to ensure write completion. + */ + iommu->sbus_control_reg = regs + 0x2000UL; + + /* Link into SYSIO software state. */ + sbus->iommu = iommu; + + printk("SYSIO: UPA portID %x, at %016lx\n", + sbus->portid, regs); + + /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ + control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL); + control = ((7UL << 16UL) | + (0UL << 2UL) | + (1UL << 1UL) | + (1UL << 0UL)); + + /* Using the above configuration we need 1MB iommu page + * table (128K ioptes * 8 bytes per iopte). This is + * page order 7 on UltraSparc. + */ + tsb_base = __get_free_pages(GFP_ATOMIC, 7); + if (tsb_base == 0UL) { + prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n"); + prom_halt(); + } + + iommu->page_table = (iopte_t *) tsb_base; + memset(iommu->page_table, 0, (PAGE_SIZE << 7)); + + upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL); + + /* Clean out any cruft in the IOMMU using + * diagnostic accesses. + */ + for (i = 0; i < 16; i++) { + unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG; + + dram += (unsigned long)i * 8UL; + upa_writeq(0, dram); + } + upa_readq(iommu->sbus_control_reg); + + /* Give the TSB to SYSIO. */ + upa_writeq(__pa(tsb_base), iommu->iommu_regs + IOMMU_TSBBASE); + + /* Setup streaming buffer, DE=1 SB_EN=1 */ + control = (1UL << 1UL) | (1UL << 0UL); + upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL); + + /* Clear out the tags using diagnostics. */ + for (i = 0; i < 16; i++) { + unsigned long ptag, ltag; + + ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG; + ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG; + ptag += (unsigned long)i * 8UL; + ltag += (unsigned long)i * 8UL; + + upa_writeq(0UL, ptag); + upa_writeq(0UL, ltag); + } + + /* Enable DVMA arbitration for all devices/slots. */ + control = upa_readq(iommu->sbus_control_reg); + control |= 0x3fUL; + upa_writeq(control, iommu->sbus_control_reg); + + /* Now some Xfire specific grot... */ + { + extern void *starfire_hookup(int); + extern int this_is_starfire; + + if (this_is_starfire) + sbus->starfire_cookie = starfire_hookup(sbus->portid); + else + sbus->starfire_cookie = NULL; + } + + sysio_register_error_handlers(sbus); +} diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.3.34/linux/arch/sparc64/kernel/setup.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/setup.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.47 1999/08/31 06:54:55 davem Exp $ +/* $Id: setup.c,v 1.50 1999/12/01 10:44:45 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -279,7 +279,9 @@ #ifdef CONFIG_SUN_CONSOLE static int console_fb __initdata = 0; #endif -static unsigned long memory_size = 0; + +/* Exported for mm/init.c:paging_init. */ +unsigned long cmdline_memory_size = 0; #ifdef PROM_DEBUG_CONSOLE static struct console prom_debug_console = { @@ -398,13 +400,13 @@ * "mem=XXX[kKmM]" overrides the PROM-reported * memory size. */ - memory_size = simple_strtoul(commands + 4, - &commands, 0); + cmdline_memory_size = simple_strtoul(commands + 4, + &commands, 0); if (*commands == 'K' || *commands == 'k') { - memory_size <<= 10; + cmdline_memory_size <<= 10; commands++; } else if (*commands=='M' || *commands=='m') { - memory_size <<= 20; + cmdline_memory_size <<= 20; commands++; } } @@ -438,12 +440,22 @@ extern struct consw sun_serial_con; -void __init setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p) +void register_prom_callbacks(void) +{ + prom_setcallback(prom_callback); + prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; " + "' linux-va>tte-data to va>tte-data"); + prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; " + "' linux-.soft1 to .soft1"); + prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; " + "' linux-.soft2 to .soft2"); +} + +void __init setup_arch(char **cmdline_p) { extern int serial_console; /* in console.c, of course */ - unsigned long lowest_paddr, end_of_phys_memory = 0; - int total, i; + unsigned long highest_paddr; + int i; /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); @@ -464,44 +476,23 @@ boot_flags_init(*cmdline_p); idprom_init(); - total = prom_probe_memory(); - - lowest_paddr = 0xffffffffffffffffUL; - for(i=0; sp_banks[i].num_bytes != 0; i++) { - if(sp_banks[i].base_addr < lowest_paddr) - lowest_paddr = sp_banks[i].base_addr; - end_of_phys_memory = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - if (memory_size) { - if (end_of_phys_memory > memory_size) { - sp_banks[i].num_bytes -= - (end_of_phys_memory - memory_size); - end_of_phys_memory = memory_size; - sp_banks[++i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; - } - } - } - prom_setcallback(prom_callback); - prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; " - "' linux-va>tte-data to va>tte-data"); - prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; " - "' linux-.soft1 to .soft1"); - prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; " - "' linux-.soft2 to .soft2"); + (void) prom_probe_memory(); /* In paging_init() we tip off this value to see if we need * to change init_mm.pgd to point to the real alias mapping. */ - phys_base = lowest_paddr; - - *memory_start_p = PAGE_ALIGN(((unsigned long) &end)); - *memory_end_p = (end_of_phys_memory + PAGE_OFFSET); - -#ifdef DAVEM_DEBUGGING - prom_printf("phys_base[%016lx] memory_start[%016lx] memory_end[%016lx]\n", - phys_base, *memory_start_p, *memory_end_p); -#endif + phys_base = 0xffffffffffffffffUL; + highest_paddr = 0UL; + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long top; + + if (sp_banks[i].base_addr < phys_base) + phys_base = sp_banks[i].base_addr; + top = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + if (highest_paddr < top) + highest_paddr = top; + } if (!root_flags) root_mountflags &= ~MS_RDONLY; @@ -512,6 +503,7 @@ rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); #endif #ifdef CONFIG_BLK_DEV_INITRD +// FIXME needs to do the new bootmem alloc stuff if (sparc_ramdisk_image) { unsigned long start = 0; @@ -537,7 +529,7 @@ /* Due to stack alignment restrictions and assumptions... */ init_mm.mmap->vm_page_prot = PAGE_SHARED; init_mm.mmap->vm_start = PAGE_OFFSET; - init_mm.mmap->vm_end = *memory_end_p; + init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr; init_task.thread.kregs = &fake_swapper_regs; #ifdef CONFIG_IP_PNP @@ -642,6 +634,13 @@ len += mmu_info(buffer + len); #ifdef __SMP__ len += smp_info(buffer + len); +#endif +#undef ZS_LOG +#ifdef ZS_LOG + { + extern int zs_dumplog(char *); + len += zs_dumplog(buffer + len); + } #endif return len; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.3.34/linux/arch/sparc64/kernel/signal.c Tue Nov 23 22:42:20 1999 +++ linux/arch/sparc64/kernel/signal.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.45 1999/09/06 08:21:59 jj Exp $ +/* $Id: signal.c,v 1.48 1999/12/15 22:24:52 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.3.34/linux/arch/sparc64/kernel/signal32.c Sun Nov 7 16:37:34 1999 +++ linux/arch/sparc64/kernel/signal32.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.50 1999/07/30 09:35:25 davem Exp $ +/* $Id: signal32.c,v 1.56 1999/12/20 01:16:16 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -663,7 +663,8 @@ goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = pte_page(*ptep); + unsigned long page = (unsigned long) + __va(pte_pagenr(*ptep) << PAGE_SHIFT); __asm__ __volatile__(" membar #StoreStore @@ -1033,6 +1034,26 @@ err |= __put_user(0, &sf->fpu_save); } + /* Update the siginfo structure. Is this good? */ + if (info->si_code == 0) { + info->si_signo = signr; + info->si_errno = 0; + + switch (signr) { + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: + case SIGEMT: + info->si_code = current->thread.sig_desc; + info->si_addr = (void *)current->thread.sig_address; + info->si_trapno = 0; + break; + default: + break; + } + } + err = __put_user (info->si_signo, &sf->info.si_signo); err |= __put_user (info->si_errno, &sf->info.si_errno); err |= __put_user (info->si_code, &sf->info.si_code); @@ -1084,7 +1105,7 @@ case 1: seta.sig[1] = (oldset->sig[0] >> 32); seta.sig[0] = oldset->sig[0]; } - err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t)); + err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t32)); err |= copy_in_user((u32 *)sf, (u32 *)(regs->u_regs[UREG_FP]), @@ -1122,7 +1143,8 @@ goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = pte_page(*ptep); + unsigned long page = (unsigned long) + __va(pte_pagenr(*ptep) << PAGE_SHIFT); __asm__ __volatile__(" membar #StoreStore @@ -1326,7 +1348,8 @@ continue; case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: + case SIGABRT: case SIGFPE: case SIGSEGV: + case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, regs)) exit_code |= 0x80; #ifdef DEBUG_SIGNALS diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.3.34/linux/arch/sparc64/kernel/smp.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/smp.c Mon Dec 20 22:05:52 1999 @@ -94,7 +94,8 @@ cpu_data[id].udelay_val = loops_per_sec; cpu_data[id].pgcache_size = 0; - cpu_data[id].pte_cache = NULL; + cpu_data[id].pte_cache[0] = NULL; + cpu_data[id].pte_cache[1] = NULL; cpu_data[id].pgdcache_size = 0; cpu_data[id].pgd_cache = NULL; cpu_data[id].idle_volume = 1; @@ -184,7 +185,7 @@ extern struct prom_cpuinfo linux_cpus[64]; -extern unsigned long smp_trampoline; +extern unsigned long sparc64_cpu_startup; /* The OBP cpu startup callback truncates the 3rd arg cookie to * 32-bits (I think) so to be safe we have it read the pointer @@ -210,15 +211,13 @@ continue; if(cpu_present_map & (1UL << i)) { - unsigned long entry = (unsigned long)(&smp_trampoline); + unsigned long entry = (unsigned long)(&sparc64_cpu_startup); unsigned long cookie = (unsigned long)(&cpu_new_task); struct task_struct *p; int timeout; int no; - extern unsigned long phys_base; - entry += phys_base - KERNBASE; - cookie += phys_base - KERNBASE; + prom_printf("Starting CPU %d... ", i); kernel_thread(start_secondary, NULL, CLONE_PID); cpucount++; @@ -247,9 +246,11 @@ cpu_number_map[i] = cpucount; __cpu_logical_map[cpucount] = i; prom_cpu_nodes[i] = linux_cpus[no].prom_node; + prom_printf("OK\n"); } else { cpucount--; printk("Processor %d is stuck.\n", i); + prom_printf("FAILED\n"); } } if(!callin_flag) { @@ -537,14 +538,31 @@ /* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they * can service tlb flush xcalls... */ +extern void prom_world(int); +extern void save_alternate_globals(unsigned long *); +extern void restore_alternate_globals(unsigned long *); void smp_penguin_jailcell(void) { - flushw_user(); + unsigned long global_save[24]; + + __asm__ __volatile__("flushw"); + save_alternate_globals(global_save); + prom_world(1); atomic_inc(&smp_capture_registry); membar("#StoreLoad | #StoreStore"); while(penguins_are_doing_time) membar("#LoadLoad"); + restore_alternate_globals(global_save); atomic_dec(&smp_capture_registry); + prom_world(0); +} + +extern unsigned long xcall_promstop; + +void smp_promstop_others(void) +{ + if (smp_processors_ready) + smp_cross_call(&xcall_promstop, 0, 0, 0); } static inline void sparc64_do_profile(unsigned long pc, unsigned long g3) @@ -701,14 +719,13 @@ /* Failure. */ if(p >= (mem_map + max_mapnr)) return 0UL; - if(PageSkip(p)) { - p = p->next_hash; - base = page_address(p); + if(PageReserved(p)) { found = size; + base = page_address(p); } else { found -= PAGE_SIZE; - p++; } + p++; } return base; } @@ -718,7 +735,7 @@ static void __init smp_tune_scheduling (void) { unsigned long flush_base, flags, *p; - unsigned int ecache_size; + unsigned int ecache_size, order; cycles_t tick1, tick2, raw; /* Approximate heuristic for SMP scheduling. It is an @@ -733,18 +750,22 @@ */ printk("SMP: Calibrating ecache flush... "); ecache_size = prom_getintdefault(linux_cpus[0].prom_node, - "ecache-size", (512 *1024)); - flush_base = find_flush_base(ecache_size << 1); + "ecache-size", (512 * 1024)); + if (ecache_size > (4 * 1024 * 1024)) + ecache_size = (4 * 1024 * 1024); + for (order = 0UL; (PAGE_SIZE << order) < ecache_size; order++) + ; + flush_base = __get_free_pages(GFP_KERNEL, order); - if(flush_base != 0UL) { + if (flush_base != 0UL) { __save_and_cli(flags); /* Scan twice the size once just to get the TLB entries * loaded and make sure the second scan measures pure misses. */ - for(p = (unsigned long *)flush_base; - ((unsigned long)p) < (flush_base + (ecache_size<<1)); - p += (64 / sizeof(unsigned long))) + for (p = (unsigned long *)flush_base; + ((unsigned long)p) < (flush_base + (ecache_size<<1)); + p += (64 / sizeof(unsigned long))) *((volatile unsigned long *)p); /* Now the real measurement. */ @@ -775,9 +796,12 @@ * sharing the cache and fitting. */ cacheflush_time = (raw - (raw >> 2)); - } else + + free_pages(flush_base, order); + } else { cacheflush_time = ((ecache_size << 2) + (ecache_size << 1)); + } printk("Using heuristic of %d cycles.\n", (int) cacheflush_time); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.3.34/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu Nov 11 20:11:32 1999 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.64 1999/09/05 09:33:38 ecd Exp $ +/* $Id: sparc64_ksyms.c,v 1.68 1999/12/17 12:32:05 jj Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -55,8 +55,6 @@ extern unsigned prom_cpu_nodes[64]; extern void die_if_kernel(char *str, struct pt_regs *regs); extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long, - unsigned long, unsigned long, unsigned long); void _sigpause_common (unsigned int set, struct pt_regs *); extern void *__bzero(void *, size_t); extern void *__bzero_noasi(void *, size_t); @@ -117,11 +115,13 @@ /* used by various drivers */ #ifdef __SMP__ +#ifndef SPIN_LOCK_DEBUG /* Out of line rw-locking implementation. */ EXPORT_SYMBOL_PRIVATE(read_lock); EXPORT_SYMBOL_PRIVATE(read_unlock); EXPORT_SYMBOL_PRIVATE(write_lock); EXPORT_SYMBOL_PRIVATE(write_unlock); +#endif /* Kernel wide locking */ EXPORT_SYMBOL(kernel_flag); @@ -175,23 +175,25 @@ EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(request_fast_irq); -EXPORT_SYMBOL(sparc_alloc_io); -EXPORT_SYMBOL(sparc_free_io); -EXPORT_SYMBOL(sparc_ultra_unmapioaddr); -EXPORT_SYMBOL(mmu_get_scsi_sgl); -EXPORT_SYMBOL(mmu_get_scsi_one); -EXPORT_SYMBOL(sparc_dvma_malloc); -EXPORT_SYMBOL(mmu_release_scsi_one); -EXPORT_SYMBOL(mmu_release_scsi_sgl); #if CONFIG_SBUS -EXPORT_SYMBOL(mmu_set_sbus64); -EXPORT_SYMBOL(SBus_chain); +EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); +EXPORT_SYMBOL(sbus_set_sbus64); +EXPORT_SYMBOL(sbus_alloc_consistant); +EXPORT_SYMBOL(sbus_free_consistant); +EXPORT_SYMBOL(sbus_map_single); +EXPORT_SYMBOL(sbus_unmap_single); +EXPORT_SYMBOL(sbus_map_sg); +EXPORT_SYMBOL(sbus_unmap_sg); +EXPORT_SYMBOL(sbus_dma_sync_single); +EXPORT_SYMBOL(sbus_dma_sync_sg); #endif #if CONFIG_PCI EXPORT_SYMBOL(ebus_chain); +#ifndef NEW_PCI_DMA_MAP EXPORT_SYMBOL(pci_dvma_v2p_hash); EXPORT_SYMBOL(pci_dvma_p2v_hash); +#endif EXPORT_SYMBOL(pci_memspace_mask); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(outsb); @@ -204,7 +206,6 @@ /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); -EXPORT_SYMBOL(sunos_mmap); /* Should really be in linux/kernel/ksyms.c */ EXPORT_SYMBOL(dump_thread); @@ -229,10 +230,10 @@ EXPORT_SYMBOL(prom_setprop); EXPORT_SYMBOL(saved_command_line); EXPORT_SYMBOL(prom_getname); +EXPORT_SYMBOL(prom_finddevice); EXPORT_SYMBOL(prom_feval); EXPORT_SYMBOL(prom_getbool); EXPORT_SYMBOL(prom_getstring); -EXPORT_SYMBOL(prom_apply_sbus_ranges); EXPORT_SYMBOL(prom_getint); EXPORT_SYMBOL(prom_getintdefault); EXPORT_SYMBOL(__prom_getchild); @@ -311,5 +312,3 @@ EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memmove); - -EXPORT_SYMBOL(get_wchan); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c --- v2.3.34/linux/arch/sparc64/kernel/starfire.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/starfire.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: starfire.c,v 1.3 1999/08/30 10:01:13 davem Exp $ +/* $Id: starfire.c,v 1.4 1999/09/21 14:35:25 davem Exp $ * starfire.c: Starfire/E10000 support. * * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com) @@ -10,6 +10,7 @@ #include #include #include +#include /* A few places around the kernel check this to see if * they need to call us to do things in a Starfire specific @@ -43,7 +44,7 @@ int starfire_hard_smp_processor_id(void) { - return *((volatile unsigned int *) __va(0x1fff40000d0)); + return upa_readl(0x1fff40000d0UL); } /* Each Starfire board has 32 registers which perform translation @@ -52,8 +53,8 @@ * bits than in all previous Sun5 systems. */ struct starfire_irqinfo { - volatile unsigned int *imap_slots[32]; - volatile unsigned int *tregs[32]; + unsigned long imap_slots[32]; + unsigned long tregs[32]; struct starfire_irqinfo *next; int upaid, hwmid; }; @@ -79,8 +80,8 @@ treg_base += (hwmid << 33UL); treg_base += 0x200UL; for(i = 0; i < 32; i++) { - p->imap_slots[i] = NULL; - p->tregs[i] = (volatile unsigned int *)__va(treg_base + (i * 0x10)); + p->imap_slots[i] = 0UL; + p->tregs[i] = treg_base + (i * 0x10UL); } p->upaid = upaid; p->next = sflist; @@ -89,7 +90,7 @@ return (void *) p; } -unsigned int starfire_translate(volatile unsigned int *imap, +unsigned int starfire_translate(unsigned long imap, unsigned int upaid) { struct starfire_irqinfo *p; @@ -107,7 +108,7 @@ } for(i = 0; i < 32; i++) { if(p->imap_slots[i] == imap || - p->imap_slots[i] == NULL) + p->imap_slots[i] == 0UL) break; } if(i == 32) { @@ -115,7 +116,7 @@ panic("Lucy in the sky...."); } p->imap_slots[i] = imap; - *(p->tregs[i]) = upaid; + upa_writel(upaid, p->tregs[i]); return i; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S --- v2.3.34/linux/arch/sparc64/kernel/sys32.S Mon Nov 16 10:37:28 1998 +++ linux/arch/sparc64/kernel/sys32.S Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $ +/* $Id: sys32.S,v 1.9 1999/12/21 14:09:18 jj Exp $ * sys32.S: I-cache tricks for 32-bit compatability layer simple * conversions. * @@ -74,3 +74,12 @@ sethi %hi(sys_bdflush), %g1 jmpl %g1 + %lo(sys_bdflush), %g0 sra %o1, 0, %o1 + + .align 32 + .globl sys32_mmap2 +sys32_mmap2: + srl %o4, 0, %o4 + sethi %hi(sys_mmap), %g1 + srl %o5, 0, %o5 + jmpl %g1 + %lo(sys_mmap), %g0 + sllx %o5, 12, %o5 diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.3.34/linux/arch/sparc64/kernel/sys_sparc.c Fri Aug 6 11:58:00 1999 +++ linux/arch/sparc64/kernel/sys_sparc.c Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.29 1999/08/04 07:04:10 jj Exp $ +/* $Id: sys_sparc.c,v 1.31 1999/12/21 14:09:25 jj Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -156,15 +156,16 @@ struct file * file = NULL; unsigned long retval = -EBADF; - down(¤t->mm->mmap_sem); - lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = -ENOMEM; len = PAGE_ALIGN(len); + down(¤t->mm->mmap_sem); + lock_kernel(); if(!(flags & MAP_FIXED) && !addr) { addr = get_unmapped_area(addr, len); if(!addr) @@ -187,15 +188,14 @@ } } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); retval = do_mmap(file, addr, len, prot, flags, off); out_putf: + unlock_kernel(); + up(¤t->mm->mmap_sem); if (file) fput(file); out: - unlock_kernel(); - up(¤t->mm->mmap_sem); return retval; } @@ -274,6 +274,21 @@ unlock_kernel(); return -ENOSYS; } + +#ifndef CONFIG_SUNOS_EMUL +asmlinkage int sunos_syscall(struct pt_regs *regs) +{ + static int count = 0; + lock_kernel(); + regs->tpc = regs->tnpc; + regs->tnpc += 4; + if(++count <= 20) + printk ("SunOS binary emulation not compiled in\n"); + force_sig(SIGSEGV, current); + unlock_kernel(); + return -ENOSYS; +} +#endif asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, utrap_handler_t new_d, diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.3.34/linux/arch/sparc64/kernel/sys_sparc32.c Tue Dec 14 01:27:23 1999 +++ linux/arch/sparc64/kernel/sys_sparc32.c Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.118 1999/08/30 10:01:15 davem Exp $ +/* $Id: sys_sparc32.c,v 1.126 1999/12/21 14:09:21 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,8 @@ #include #include #include +#include +#include #include #include @@ -712,6 +715,25 @@ return ret; } +extern asmlinkage long sys_truncate(const char * path, unsigned long length); +extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); + +asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low) +{ + if ((int)high < 0) + return -EINVAL; + else + return sys_truncate(path, (high << 32) | low); +} + +asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) +{ + if ((int)high < 0) + return -EINVAL; + else + return sys_ftruncate(fd, (high << 32) | low); +} + extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); struct utimbuf32 { @@ -1125,8 +1147,10 @@ } ret = -EINVAL; - if (n < 0 || n > KFDS_NR) + if (n < 0) goto out_nofds; + if (n > current->files->max_fdset) + n = current->files->max_fdset; /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), @@ -1186,84 +1210,157 @@ return ret; } -static inline int putstat(struct stat32 *ubuf, struct stat *kbuf) +static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf) { + unsigned long ino, blksize, blocks; + kdev_t dev, rdev; + umode_t mode; + nlink_t nlink; + uid_t uid; + gid_t gid; + off_t size; + time_t atime, mtime, ctime; int err; - - err = put_user (kbuf->st_dev, &ubuf->st_dev); - err |= __put_user (kbuf->st_ino, &ubuf->st_ino); - err |= __put_user (kbuf->st_mode, &ubuf->st_mode); - err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink); - err |= __put_user (kbuf->st_uid, &ubuf->st_uid); - err |= __put_user (kbuf->st_gid, &ubuf->st_gid); - err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev); - err |= __put_user (kbuf->st_size, &ubuf->st_size); - err |= __put_user (kbuf->st_atime, &ubuf->st_atime); - err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime); - err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime); - err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize); - err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks); + + /* Stream the loads of inode data into the load buffer, + * then we push it all into the store buffer below. This + * should give optimal cache performance. + */ + ino = inode->i_ino; + dev = inode->i_dev; + mode = inode->i_mode; + nlink = inode->i_nlink; + uid = inode->i_uid; + gid = inode->i_gid; + rdev = inode->i_rdev; + size = inode->i_size; + atime = inode->i_atime; + mtime = inode->i_mtime; + ctime = inode->i_ctime; + blksize = inode->i_blksize; + blocks = inode->i_blocks; + + err = put_user(kdev_t_to_nr(dev), &statbuf->st_dev); + err |= put_user(ino, &statbuf->st_ino); + err |= put_user(mode, &statbuf->st_mode); + err |= put_user(nlink, &statbuf->st_nlink); + err |= put_user(uid, &statbuf->st_uid); + err |= put_user(gid, &statbuf->st_gid); + err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev); + err |= put_user(size, &statbuf->st_size); + err |= put_user(atime, &statbuf->st_atime); + err |= put_user(0, &statbuf->__unused1); + err |= put_user(mtime, &statbuf->st_mtime); + err |= put_user(0, &statbuf->__unused2); + err |= put_user(ctime, &statbuf->st_ctime); + err |= put_user(0, &statbuf->__unused3); + if (blksize) { + err |= put_user(blksize, &statbuf->st_blksize); + err |= put_user(blocks, &statbuf->st_blocks); + } else { + unsigned int tmp_blocks; + +#define D_B 7 +#define I_B (BLOCK_SIZE / sizeof(unsigned short)) + tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (tmp_blocks > D_B) { + unsigned int indirect; + + indirect = (tmp_blocks - D_B + I_B - 1) / I_B; + tmp_blocks += indirect; + if (indirect > 1) { + indirect = (indirect - 1 + I_B - 1) / I_B; + tmp_blocks += indirect; + if (indirect > 1) + tmp_blocks++; + } + } + err |= put_user(BLOCK_SIZE, &statbuf->st_blksize); + err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks); +#undef D_B +#undef I_B + } + err |= put_user(0, &statbuf->__unused4[0]); + err |= put_user(0, &statbuf->__unused4[1]); + return err; } -extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf); - asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) { - int ret; - struct stat s; - char *filenam; - mm_segment_t old_fs = get_fs(); - - filenam = getname32 (filename); - ret = PTR_ERR(filenam); - if (!IS_ERR(filenam)) { - set_fs (KERNEL_DS); - ret = sys_newstat(filenam, &s); - set_fs (old_fs); - putname (filenam); - if (putstat (statbuf, &s)) - return -EFAULT; + struct dentry *dentry; + int error; + + lock_kernel(); + dentry = namei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + struct inode *inode = dentry->d_inode; + + if (inode->i_op && + inode->i_op->revalidate) + error = inode->i_op->revalidate(dentry); + else + error = 0; + if (!error) + error = cp_new_stat32(inode, statbuf); + + dput(dentry); } - return ret; + unlock_kernel(); + return error; } -extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf); - asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf) { - int ret; - struct stat s; - char *filenam; - mm_segment_t old_fs = get_fs(); - - filenam = getname32 (filename); - ret = PTR_ERR(filenam); - if (!IS_ERR(filenam)) { - set_fs (KERNEL_DS); - ret = sys_newlstat(filenam, &s); - set_fs (old_fs); - putname (filenam); - if (putstat (statbuf, &s)) - return -EFAULT; + struct dentry *dentry; + int error; + + lock_kernel(); + dentry = lnamei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + struct inode *inode = dentry->d_inode; + + if (inode->i_op && + inode->i_op->revalidate) + error = inode->i_op->revalidate(dentry); + else + error = 0; + if (!error) + error = cp_new_stat32(inode, statbuf); + + dput(dentry); } - return ret; + unlock_kernel(); + return error; } -extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf); - asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf) { - int ret; - struct stat s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_newfstat(fd, &s); - set_fs (old_fs); - if (putstat (statbuf, &s)) - return -EFAULT; - return ret; + struct file *f; + int err = -EBADF; + + lock_kernel(); + f = fget(fd); + if (f) { + struct dentry *dentry = f->f_dentry; + struct inode *inode = dentry->d_inode; + + if (inode->i_op && + inode->i_op->revalidate) + err = inode->i_op->revalidate(dentry); + else + err = 0; + if (!err) + err = cp_new_stat32(inode, statbuf); + + fput(f); + } + unlock_kernel(); + return err; } extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2); @@ -1912,8 +2009,8 @@ #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) struct rlimit32 { - s32 rlim_cur; - s32 rlim_max; + u32 rlim_cur; + u32 rlim_max; }; extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim); @@ -2523,6 +2620,48 @@ return len; } +extern asmlinkage int sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen); + +asmlinkage int sys32_setsockopt(int fd, int level, int optname, + char *optval, int optlen) +{ + if (optname == SO_ATTACH_FILTER) { + struct sock_fprog32 { + __u16 len; + __u32 filter; + } *fprog32 = (struct sock_fprog32 *)optval; + struct sock_fprog kfprog; + struct sock_filter *kfilter; + unsigned int fsize; + mm_segment_t old_fs; + __u32 uptr; + int ret; + + if (get_user(kfprog.len, &fprog32->len) || + __get_user(uptr, &fprog32->filter)) + return -EFAULT; + kfprog.filter = (struct sock_filter *)A(uptr); + fsize = kfprog.len * sizeof(struct sock_filter); + kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); + if (kfilter == NULL) + return -ENOMEM; + if (copy_from_user(kfilter, kfprog.filter, fsize)) { + kfree(kfilter); + return -EFAULT; + } + kfprog.filter = kfilter; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *)&kfprog, sizeof(kfprog)); + set_fs(old_fs); + kfree(kfilter); + return ret; + } + return sys_setsockopt(fd, level, optname, optval, optlen); +} + /* Argument list sizes for sys_socketcall */ #define AL(x) ((x) * sizeof(u32)) static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), @@ -2541,8 +2680,6 @@ extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags); extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen); @@ -2593,7 +2730,7 @@ case SYS_SHUTDOWN: return sys_shutdown(a0,a1); case SYS_SETSOCKOPT: - return sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]); + return sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]); case SYS_GETSOCKOPT: return sys32_getsockopt(a0, a1, a[2], a[3], a[4]); case SYS_SENDMSG: @@ -2727,8 +2864,9 @@ if (get_user(str, argv + argc) || !str || - !(len = strlen_user((char *)A(str)))) + !(len = strnlen_user((char *)A(str), bprm->p))) return -EFAULT; + if (bprm->p < len) return -E2BIG; @@ -2736,20 +2874,38 @@ pos = bprm->p; while (len) { - char *pag; - int offset, bytes_to_copy; + char *kaddr; + struct page *page; + int offset, bytes_to_copy, new, err; offset = pos % PAGE_SIZE; - if (!(pag = (char *) bprm->page[pos/PAGE_SIZE]) && - !(pag = (char *) bprm->page[pos/PAGE_SIZE] = - (unsigned long *) get_free_page(GFP_USER))) - return -ENOMEM; + page = bprm->page[pos / PAGE_SIZE]; + new = 0; + if (!page) { + page = alloc_page(GFP_USER); + bprm->page[pos / PAGE_SIZE] = page; + if (!page) + return -ENOMEM; + new = 1; + } + kaddr = (char *)kmap(page); + if (new && offset) + memset(kaddr, 0, offset); bytes_to_copy = PAGE_SIZE - offset; - if (bytes_to_copy > len) + if (bytes_to_copy > len) { bytes_to_copy = len; + if (new) + memset(kaddr+offset+len, 0, + PAGE_SIZE-offset-len); + } + + err = copy_from_user(kaddr + offset, (char *)A(str), + bytes_to_copy); + flush_page_to_ram(page); + kunmap((unsigned long)kaddr); - if (copy_from_user(pag + offset, (char *)A(str), bytes_to_copy)) + if (err) return -EFAULT; pos += bytes_to_copy; @@ -2772,8 +2928,7 @@ int i; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - for (i=0 ; i> PAGE_SHIFT; + freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT; freepages += atomic_read(&page_cache_size); freepages >>= 1; - freepages += nr_free_pages; + freepages += nr_free_pages(); freepages += nr_swap_pages; freepages -= num_physpages >> 4; freepages -= (newbrk-oldbrk) >> PAGE_SHIFT; diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.3.34/linux/arch/sparc64/kernel/systbls.S Mon Aug 2 22:07:16 1999 +++ linux/arch/sparc64/kernel/systbls.S Tue Dec 21 21:56:42 1999 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.56 1999/07/31 00:06:17 davem Exp $ +/* $Id: systbls.S,v 1.61 1999/12/21 14:09:15 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -10,6 +10,8 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ +#include + .text .align 1024 @@ -28,12 +30,12 @@ /*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl - .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys32_execve -/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize + .word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve +/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall /*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect - .word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups -/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall + .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups +/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64 .word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall /*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall @@ -43,8 +45,8 @@ .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod .word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate -/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall +/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall + .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64 /*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit .word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall @@ -129,6 +131,8 @@ /*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl .word sys_aplib +#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ + defined(CONFIG_SOLARIS_EMUL_MODULE) /* Now the 32-bit SunOS syscall table. */ .align 1024 @@ -221,3 +225,5 @@ .word sunos_nosys, sunos_nosys /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sys_aplib + +#endif diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.3.34/linux/arch/sparc64/kernel/time.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/kernel/time.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $ +/* $Id: time.c,v 1.23 1999/09/21 14:35:27 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -268,7 +268,7 @@ int node, busnd = -1, err; unsigned long flags; #ifdef CONFIG_PCI - struct linux_ebus *ebus = 0; + struct linux_ebus *ebus = NULL; #endif __save_and_cli(flags); @@ -282,8 +282,8 @@ busnd = ebus->prom_node; } #endif - else { - busnd = SBus_chain->prom_node; + else if (sbus_root != NULL) { + busnd = sbus_root->prom_node; } if(busnd == -1) { @@ -304,9 +304,9 @@ if (node) node = prom_getsibling(node); #ifdef CONFIG_PCI - while ((node == 0) && ebus) { + while ((node == 0) && ebus != NULL) { ebus = ebus->next; - if (ebus) { + if (ebus != NULL) { busnd = ebus->prom_node; node = prom_getchild(busnd); } @@ -327,17 +327,17 @@ } if(central_bus) { - prom_apply_fhc_ranges(central_bus->child, clk_reg, 1); - prom_apply_central_ranges(central_bus, clk_reg, 1); + apply_fhc_ranges(central_bus->child, clk_reg, 1); + apply_central_ranges(central_bus, clk_reg, 1); } #ifdef CONFIG_PCI - else if (ebus_chain) { + else if (ebus_chain != NULL) { struct linux_ebus_device *edev; for_each_ebusdev(edev, ebus) if (edev->prom_node == node) break; - if (!edev) { + if (edev == NULL) { prom_printf("%s: Mostek not probed by EBUS\n", __FUNCTION__); prom_halt(); @@ -349,9 +349,24 @@ } #endif else { - prom_adjust_regs(clk_reg, 1, - SBus_chain->sbus_ranges, - SBus_chain->num_sbus_ranges); + if (sbus_root->num_sbus_ranges) { + int nranges = sbus_root->num_sbus_ranges; + int rngc; + + for (rngc = 0; rngc < nranges; rngc++) + if (clk_reg[0].which_io == + sbus_root->sbus_ranges[rngc].ot_child_space) + break; + if (rngc == nranges) { + prom_printf("clock_probe: Cannot find ranges for " + "clock regs.\n"); + prom_halt(); + } + clk_reg[0].which_io = + sbus_root->sbus_ranges[rngc].ot_parent_space; + clk_reg[0].phys_addr += + sbus_root->sbus_ranges[rngc].ot_parent_base; + } } if(model[5] == '0' && model[6] == '2') { diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S --- v2.3.34/linux/arch/sparc64/kernel/trampoline.S Thu Nov 18 20:25:37 1999 +++ linux/arch/sparc64/kernel/trampoline.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.10 1999/09/10 10:40:48 davem Exp $ +/* $Id: trampoline.S,v 1.12 1999/12/15 15:45:12 davem Exp $ * trampoline.S: Jump start slave processors on sparc64. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -14,21 +14,107 @@ #include .data - .align 8 - .globl smp_trampoline -smp_trampoline: .skip 0x300 + .align 8 +call_method: + .asciz "call-method" + .align 8 +itlb_load: + .asciz "SUNW,itlb-load" + .align 8 +dtlb_load: + .asciz "SUNW,dtlb-load" .text .align 8 .globl sparc64_cpu_startup, sparc64_cpu_startup_end sparc64_cpu_startup: flushw + mov (LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1 stxa %g1, [%g0] ASI_LSU_CONTROL membar #Sync - wrpr %g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate - wr %g0, 0, %fprs + wrpr %g0, 15, %pil + wr %g0, 0, %tick_cmpr + + /* Call OBP by hand to lock KERNBASE into i/d tlbs. */ + mov %o0, %l0 + + sethi %hi(prom_entry_lock), %g2 +1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 + brnz,pn %g1, 1b + membar #StoreLoad | #StoreStore + + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x10], %l2 + mov %sp, %l1 + add %l2, -(192 + 128), %sp + flushw + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(itlb_load), %g2 + or %g2, %lo(itlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + mov 63, %g2 + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + + sethi %hi(call_method), %g2 + or %g2, %lo(call_method), %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 5, %g2 + stx %g2, [%sp + 2047 + 128 + 0x08] + mov 1, %g2 + stx %g2, [%sp + 2047 + 128 + 0x10] + sethi %hi(dtlb_load), %g2 + or %g2, %lo(dtlb_load), %g2 + stx %g2, [%sp + 2047 + 128 + 0x18] + sethi %hi(mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x20] + sethi %hi(KERNBASE), %g2 + stx %g2, [%sp + 2047 + 128 + 0x28] + sethi %hi(kern_locked_tte_data), %g2 + ldx [%g2 + %lo(kern_locked_tte_data)], %g2 + stx %g2, [%sp + 2047 + 128 + 0x30] + mov 63, %g2 + stx %g2, [%sp + 2047 + 128 + 0x38] + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x08], %o1 + call %o1 + add %sp, (2047 + 128), %o0 + + sethi %hi(prom_entry_lock), %g2 + stb %g0, [%g2 + %lo(prom_entry_lock)] + membar #StoreStore | #StoreLoad + + mov %l1, %sp + flushw + + mov %l0, %o0 + + wrpr %g0, (PSTATE_PRIV | PSTATE_PEF), %pstate + wr %g0, 0, %fprs sethi %uhi(PAGE_OFFSET), %g4 sllx %g4, 32, %g4 @@ -37,99 +123,6 @@ srl %o0, 0, %o0 ldx [%o0], %g6 - sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 - sllx %g5, 32, %g5 - or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5 - - sethi %uhi(_PAGE_PADDR), %g3 - or %g3, %ulo(_PAGE_PADDR), %g3 - sllx %g3, 32, %g3 - sethi %hi(_PAGE_PADDR), %g7 - or %g7, %lo(_PAGE_PADDR), %g7 - or %g3, %g7, %g3 - - clr %l0 - set 0x1fff, %l2 - rd %pc, %l3 - andn %l3, %l2, %g2 -1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 - cmp %g1, %g2 - be,a,pn %xcc, 2f - ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1 - cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - -2: nop - nop - nop - and %g1, %g3, %g1 - sub %g1, %g2, %g1 - or %g5, %g1, %g5 - clr %l0 - sethi %hi(KERNBASE), %g3 - sethi %hi(KERNBASE<<1), %g7 - mov TLB_TAG_ACCESS, %l7 -1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_IMMU - stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS -2: cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - nop - nop - nop - clr %l0 -1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_DMMU - stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS -2: cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - nop - nop - nop - sethi %hi(KERNBASE), %g3 - mov (63 << 3), %g7 - stxa %g3, [%l7] ASI_DMMU - stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - stxa %g3, [%l7] ASI_IMMU - stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - flush %g3 - membar #Sync - b,pt %xcc, 1f - nop -1: set bounce, %g2 - jmpl %g2 + %g0, %g0 - nop - -bounce: wr %g0, ASI_P, %asi mov PRIMARY_CONTEXT, %g7 @@ -139,24 +132,6 @@ stxa %g0, [%g7] ASI_DMMU membar #Sync - mov TLB_TAG_ACCESS, %g2 - stxa %g3, [%g2] ASI_IMMU - stxa %g3, [%g2] ASI_DMMU - - mov (63 << 3), %g7 - ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - - ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - - flush %g3 - membar #Sync - mov 1, %g5 sllx %g5, (PAGE_SHIFT + 1), %g5 sub %g5, (REGWIN_SZ + STACK_BIAS), %g5 @@ -169,12 +144,12 @@ /* Setup the trap globals, then we can resurface. */ rdpr %pstate, %o1 mov %g6, %o2 - wrpr %o1, (PSTATE_AG | PSTATE_IE), %pstate + wrpr %o1, PSTATE_AG, %pstate sethi %hi(sparc64_ttable_tl0), %g5 wrpr %g5, %tba mov %o2, %g6 - wrpr %o1, (PSTATE_MG | PSTATE_IE), %pstate + wrpr %o1, PSTATE_MG, %pstate #define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000) #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) #ifdef THIS_IS_CHEETAH @@ -200,7 +175,7 @@ #undef VPTE_BASE /* Setup interrupt globals, we are always SMP. */ - wrpr %o1, (PSTATE_IG | PSTATE_IE), %pstate + wrpr %o1, PSTATE_IG, %pstate /* Get our UPA MID. */ lduw [%o2 + AOFF_task_processor], %g1 @@ -210,11 +185,14 @@ /* In theory this is: &(cpu_data[this_upamid].irq_worklists[0]) */ sllx %g1, 7, %g1 add %g5, %g1, %g1 - add %g1, 64, %g1 + add %g1, 64, %g6 wrpr %g0, 0, %wstate or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate + + call prom_set_trap_table + sethi %hi(sparc64_ttable_tl0), %o0 call smp_callin nop diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.3.34/linux/arch/sparc64/kernel/traps.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/traps.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.62 1999/08/31 19:25:35 davem Exp $ +/* $Id: traps.c,v 1.64 1999/12/19 23:53:13 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CONFIG_KMOD #include #endif @@ -519,8 +520,22 @@ regs->tpc = regs->tnpc; regs->tnpc += 4; } else { + unsigned long fsr = current->thread.xfsr[0]; + current->thread.sig_address = regs->tpc; current->thread.sig_desc = SUBSIG_FPERROR; + if ((fsr & 0x1c000) == (1 << 14)) { + if (fsr & 0x01) + current->thread.sig_desc = SUBSIG_FPINEXACT; + else if (fsr & 0x02) + current->thread.sig_desc = SUBSIG_FPDIVZERO; + else if (fsr & 0x04) + current->thread.sig_desc = SUBSIG_FPUNFLOW; + else if (fsr & 0x08) + current->thread.sig_desc = SUBSIG_FPOVFLOW; + else if (fsr & 0x10) + current->thread.sig_desc = SUBSIG_FPINTOVFL; + } send_sig(SIGFPE, current, 1); } } @@ -564,7 +579,9 @@ void do_div0(struct pt_regs *regs) { - send_sig(SIGILL, current, 1); + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_IDIVZERO; + send_sig(SIGFPE, current, 1); } void instruction_dump (unsigned int *pc) @@ -712,10 +729,12 @@ send_sig(SIGILL, current, 1); } -void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc, - unsigned long psr) +void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, + unsigned long npc, unsigned long psr) { - send_sig(SIGILL, current, 1); + current->thread.sig_address = regs->tpc; + current->thread.sig_desc = SUBSIG_IDIVZERO; + send_sig(SIGFPE, current, 1); } /* Trap level 1 stuff or other traps we should never see... */ @@ -841,6 +860,13 @@ #endif } #endif + +void do_getpsr(struct pt_regs *regs) +{ + regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate); + regs->tpc = regs->tnpc; + regs->tnpc += 4; +} void trap_init(void) { diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.3.34/linux/arch/sparc64/kernel/ttable.S Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/kernel/ttable.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.29 1999/08/31 19:25:37 davem Exp $ +/* $Id: ttable.S,v 1.30 1999/12/01 23:52:03 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -120,7 +120,8 @@ tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUCTION_31,0x11f) tl0_getcc: GETCC_TRAP tl0_setcc: SETCC_TRAP -tl0_resv122: BTRAP(0x122) BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) +tl0_getpsr: TRAP(do_getpsr) +tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) tl0_solindir: INDIRECT_SOLARIS_SYSCALL(156) tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c) tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131) diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S --- v2.3.34/linux/arch/sparc64/lib/blockops.S Mon Aug 2 22:07:16 1999 +++ linux/arch/sparc64/lib/blockops.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.18 1999/07/30 09:35:37 davem Exp $ +/* $Id: blockops.S,v 1.19 1999/11/19 05:52:45 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) @@ -136,19 +136,19 @@ faddd %f0, %f2, %f12 ! FPA Group fmuld %f0, %f2, %f14 ! FPM - rd %asi, %g2 ! LSU Group - wr %g0, ASI_BLK_P, %asi ! LSU Group membar #StoreLoad | #StoreStore | #LoadStore ! LSU Group -1: stda %f0, [%o0 + 0x00] %asi ! Store Group - stda %f0, [%o0 + 0x40] %asi ! Store Group - stda %f0, [%o0 + 0x80] %asi ! Store Group - stda %f0, [%o0 + 0xc0] %asi ! Store Group +1: stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group + add %o0, 0x40, %o0 ! IEU0 + stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group + add %o0, 0x40, %o0 ! IEU0 + stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group + add %o0, 0x40, %o0 ! IEU0 Group + stda %f0, [%o0 + %g0] ASI_BLK_P ! Store Group subcc %o1, 1, %o1 ! IEU1 bne,pt %icc, 1b ! CTI - add %o0, 0x100, %o0 ! IEU0 Group + add %o0, 0x40, %o0 ! IEU0 Group membar #Sync ! LSU Group - wr %g2, %g0, %asi ! LSU Group VISExitHalf stxa %g5, [%o2] ASI_DMMU diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/lib/strlen_user.S linux/arch/sparc64/lib/strlen_user.S --- v2.3.34/linux/arch/sparc64/lib/strlen_user.S Thu May 27 09:55:21 1999 +++ linux/arch/sparc64/lib/strlen_user.S Mon Dec 20 22:05:52 1999 @@ -4,7 +4,7 @@ * or 0 for error * * Copyright (C) 1991,1996 Free Software Foundation - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996,1999 David S. Miller (davem@redhat.com) * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ @@ -14,8 +14,11 @@ #define HI_MAGIC 0x80808080 .align 4 - .global __strlen_user + .global __strlen_user, __strnlen_user __strlen_user: + sethi %hi(32768), %o1 +__strnlen_user: + mov %o1, %g1 mov %o0, %o1 andcc %o0, 3, %g0 be,pt %icc, 9f @@ -42,11 +45,16 @@ 13: lda [%o0] %asi, %o5 2: sub %o5, %o2, %o4 andcc %o4, %o3, %g0 - be,pt %icc, 13b + bne,pn %icc, 82f add %o0, 4, %o0 + sub %o0, %o1, %g2 +81: cmp %g2, %g1 + blu,pt %icc, 13b + mov %o0, %o4 + ba,a,pt %xcc, 1f /* Check every byte. */ - srl %o5, 24, %g5 +82: srl %o5, 24, %g5 andcc %g5, 0xff, %g0 be,pn %icc, 1f add %o0, -3, %o4 @@ -59,8 +67,8 @@ be,pn %icc, 1f add %o4, 1, %o4 andcc %o5, 0xff, %g0 - bne,a,pt %icc, 2b -14: lda [%o0] %asi, %o5 + bne,pt %icc, 81b + sub %o0, %o1, %g2 add %o4, 1, %o4 1: retl sub %o4, %o1, %o0 @@ -85,4 +93,3 @@ .word 12b, 30b .word 15b, 30b .word 13b, 30b - .word 14b, 30b diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c --- v2.3.34/linux/arch/sparc64/math-emu/math.c Tue Dec 7 09:32:42 1999 +++ linux/arch/sparc64/math-emu/math.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: math.c,v 1.10 1999/08/13 16:02:06 jj Exp $ +/* $Id: math.c,v 1.11 1999/12/20 05:02:25 davem Exp $ * arch/sparc64/math-emu/math.c * * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz) diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/math-emu/sfp-util.h linux/arch/sparc64/math-emu/sfp-util.h --- v2.3.34/linux/arch/sparc64/math-emu/sfp-util.h Wed Jun 9 14:44:25 1999 +++ linux/arch/sparc64/math-emu/sfp-util.h Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: sfp-util.h,v 1.2 1999/06/07 18:24:15 jj Exp $ +/* $Id: sfp-util.h,v 1.4 1999/09/20 12:14:19 jj Exp $ * arch/sparc64/math-emu/sfp-util.h * * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c --- v2.3.34/linux/arch/sparc64/mm/asyncd.c Mon Aug 2 22:07:16 1999 +++ linux/arch/sparc64/mm/asyncd.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.9 1999/07/30 09:35:43 davem Exp $ +/* $Id: asyncd.c,v 1.10 1999/12/15 22:25:02 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. @@ -25,6 +25,7 @@ #include /* for cli()/sti() */ #include /* for memcpy_to/fromfs */ #include +#include #include #define DEBUG 0 diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.3.34/linux/arch/sparc64/mm/fault.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/mm/fault.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.39 1999/08/30 10:07:09 davem Exp $ +/* $Id: fault.c,v 1.40 1999/12/01 10:44:53 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -113,7 +113,9 @@ ptep = pte_offset(pmdp, tpc); if(!pte_present(*ptep)) return 0; - insn = *(unsigned int *)(pte_page(*ptep) + (tpc & ~PAGE_MASK)); + insn = *(unsigned int *) + ((unsigned long)__va(pte_pagenr(*ptep) << PAGE_SHIFT) + + (tpc & ~PAGE_MASK)); #else register unsigned long pte asm("l1"); diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c --- v2.3.34/linux/arch/sparc64/mm/generic.c Tue Dec 7 09:32:42 1999 +++ linux/arch/sparc64/mm/generic.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: generic.c,v 1.9 1999/07/23 22:32:01 davem Exp $ +/* $Id: generic.c,v 1.13 1999/12/20 05:02:33 davem Exp $ * generic.c: Generic Sparc mm routines that are not dependent upon * MMU type but are Sparc specific. * @@ -9,46 +9,26 @@ #include #include +#include #include #include - -/* Allocate a block of RAM which is aligned to its size. - * This procedure can be used until the call to mem_init(). - */ -void *sparc_init_alloc(unsigned long *kbrk, unsigned long size) -{ - unsigned long mask = size - 1; - unsigned long ret; - - if(!size) - return 0x0; - if(size & mask) { - prom_printf("panic: sparc_init_alloc botch\n"); - prom_halt(); - } - ret = (*kbrk + mask) & ~mask; - *kbrk = ret + size; - memset((void*) ret, 0, size); - return (void*) ret; -} - static inline void forget_pte(pte_t page) { if (pte_none(page)) return; if (pte_present(page)) { - unsigned long addr = pte_page(page); - if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr))) + unsigned long nr = pte_pagenr(page); + if (nr >= max_mapnr || PageReserved(mem_map+nr)) return; /* * free_page() used to be able to clear swap cache * entries. We may now have to do it manually. */ - free_page_and_swap_cache(addr); + free_page_and_swap_cache(mem_map+nr); return; } - swap_free(pte_val(page)); + swap_free(pte_to_swp_entry(page)); } /* Remap IO memory, the same way as remap_page_range(), but use diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.3.34/linux/arch/sparc64/mm/init.c Fri Oct 22 13:21:47 1999 +++ linux/arch/sparc64/mm/init.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.135 1999/09/06 22:55:10 ecd Exp $ +/* $Id: init.c,v 1.143 1999/12/16 16:15:14 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -6,8 +6,11 @@ */ #include +#include +#include #include #include +#include #include #include #include @@ -17,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -26,13 +30,8 @@ #include #include -/* Turn this off if you suspect some place in some physical memory hole - might get into page tables (something would be broken very much). */ - -#define FREE_UNUSED_MEM_MAP - extern void show_net_buffers(void); -extern unsigned long device_scan(unsigned long); +extern void device_scan(void); struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; @@ -41,6 +40,8 @@ /* Ugly, but necessary... -DaveM */ unsigned long phys_base; +static unsigned long totalram_pages = 0; + /* get_new_mmu_context() uses "cache + 1". */ spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED; unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; @@ -48,7 +49,7 @@ unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; /* References to section boundaries */ -extern char __init_begin, __init_end, etext, __bss_start; +extern char __init_begin, __init_end, _start, _end, etext, edata; int do_check_pgt_cache(int low, int high) { @@ -60,8 +61,10 @@ if(pgd_quicklist) free_pgd_slow(get_pgd_fast()), freed++; #endif - if(pte_quicklist) - free_pte_slow(get_pte_fast()), freed++; + if(pte_quicklist[0]) + free_pte_slow(get_pte_fast(0)), freed++; + if(pte_quicklist[1]) + free_pte_slow(get_pte_fast(1)), freed++; } while(pgtable_cache_size > low); } #ifndef __SMP__ @@ -110,42 +113,20 @@ pte_t __bad_page(void) { memset((void *) &empty_bad_page, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte((((unsigned long) &empty_bad_page) - - ((unsigned long)&empty_zero_page) + phys_base + PAGE_OFFSET), - PAGE_SHARED)); + return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) + - ((unsigned long)&empty_zero_page) + + phys_base), + PAGE_SHARED)); } void show_mem(void) { - int free = 0,total = 0,reserved = 0; - int shared = 0, cached = 0; - struct page *page, *end; - - printk("\nMem-info:\n"); + printk("Mem-info:\n"); show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - for (page = mem_map, end = mem_map + max_mapnr; - page < end; page++) { - if (PageSkip(page)) { - if (page->next_hash < page) - break; - page = page->next_hash; - } - total++; - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (!atomic_read(&page->count)) - free++; - else - shared += atomic_read(&page->count) - 1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); + printk("Free swap: %6dkB\n", + nr_swap_pages << (PAGE_SHIFT-10)); + printk("%ld pages of RAM\n", totalram_pages); + printk("%d free pages\n", nr_free_pages()); printk("%d pages in page table cache\n",pgtable_cache_size); #ifndef __SMP__ printk("%d entries in page dir cache\n",pgd_cache_size); @@ -156,508 +137,46 @@ #endif } -/* IOMMU support, the ideas are right, the code should be cleaned a bit still... */ - -/* This keeps track of pages used in sparc_alloc_dvma() invocations. */ -/* NOTE: All of these are inited to 0 in bss, don't need to make data segment bigger */ -#define DVMAIO_SIZE 0x2000000 -static unsigned long dvma_map_pages[DVMAIO_SIZE >> 16]; -static unsigned long dvma_pages_current_offset; -static int dvma_pages_current_index; -static unsigned long dvmaiobase = 0; -static unsigned long dvmaiosz __initdata = 0; - -void __init dvmaio_init(void) -{ - long i; - - if (!dvmaiobase) { - for (i = 0; sp_banks[i].num_bytes != 0; i++) - if (sp_banks[i].base_addr + sp_banks[i].num_bytes > dvmaiobase) - dvmaiobase = sp_banks[i].base_addr + sp_banks[i].num_bytes; - - /* We map directly phys_base to phys_base+(4GB-DVMAIO_SIZE). */ - dvmaiobase -= phys_base; - - dvmaiobase = (dvmaiobase + DVMAIO_SIZE + 0x400000 - 1) & ~(0x400000 - 1); - for (i = 0; i < 6; i++) - if (dvmaiobase <= ((1024L * 64 * 1024) << i)) - break; - dvmaiobase = ((1024L * 64 * 1024) << i) - DVMAIO_SIZE; - dvmaiosz = i; - } -} - -void __init iommu_init(int iommu_node, struct linux_sbus *sbus) -{ - extern int this_is_starfire; - extern void *starfire_hookup(int); - struct iommu_struct *iommu; - struct sysio_regs *sregs; - struct linux_prom64_registers rprop; - unsigned long impl, vers; - unsigned long control, tsbbase; - unsigned long tsbbases[32]; - unsigned long *iopte; - int err, i, j; - - dvmaio_init(); - err = prom_getproperty(iommu_node, "reg", (char *)&rprop, - sizeof(rprop)); - if(err == -1) { - prom_printf("iommu_init: Cannot map SYSIO control registers.\n"); - prom_halt(); - } - sregs = (struct sysio_regs *) __va(rprop.phys_addr); - - if(!sregs) { - prom_printf("iommu_init: Fatal error, sysio regs not mapped\n"); - prom_halt(); - } - - iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); - if (!iommu) { - prom_printf("iommu_init: Fatal error, kmalloc(iommu) failed\n"); - prom_halt(); - } - - spin_lock_init(&iommu->iommu_lock); - iommu->sysio_regs = sregs; - sbus->iommu = iommu; - - control = sregs->iommu_control; - impl = (control & IOMMU_CTRL_IMPL) >> 60; - vers = (control & IOMMU_CTRL_VERS) >> 56; - printk("IOMMU(SBUS): IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n", - (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs); - - /* Streaming buffer is unreliable on VERS 0 of SYSIO, - * although such parts were never shipped in production - * Sun hardware, I check just to be robust. --DaveM - */ - vers = ((sregs->control & SYSIO_CONTROL_VER) >> 56); - if (vers == 0) - iommu->strbuf_enabled = 0; - else - iommu->strbuf_enabled = 1; - - control &= ~(IOMMU_CTRL_TSBSZ); - control |= ((IOMMU_TSBSZ_2K * dvmaiosz) | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB); - - /* Use only 64k pages, things are layed out in the 32-bit SBUS - * address space like this: - * - * 0x00000000 ---------------------------------------- - * | Direct physical mappings for most | - * | DVMA to paddr's within this range | - * dvmaiobase ---------------------------------------- - * | For mappings requested via | - * | sparc_alloc_dvma() | - * dvmaiobase+32M ---------------------------------------- - * - * NOTE: we need to order 2 contiguous order 5, that's the largest - * chunk page_alloc will give us. -JJ */ - tsbbase = 0; - if (dvmaiosz == 6) { - memset (tsbbases, 0, sizeof(tsbbases)); - for (i = 0; i < 32; i++) { - tsbbases[i] = __get_free_pages(GFP_DMA, 5); - for (j = 0; j < i; j++) - if (tsbbases[j] == tsbbases[i] + 32768*sizeof(iopte_t)) { - tsbbase = tsbbases[i]; - break; - } else if (tsbbases[i] == tsbbases[j] + 32768*sizeof(iopte_t)) { - tsbbase = tsbbases[j]; - break; - } - if (tsbbase) { - tsbbases[i] = 0; - tsbbases[j] = 0; - break; - } - } - for (i = 0; i < 32; i++) - if (tsbbases[i]) - free_pages(tsbbases[i], 5); - } else - tsbbase = __get_free_pages(GFP_DMA, dvmaiosz); - if (!tsbbase) { - prom_printf("Strange. Could not allocate 512K of contiguous RAM.\n"); - prom_halt(); - } - iommu->page_table = (iopte_t *) tsbbase; - iopte = (unsigned long *) tsbbase; - - /* Setup aliased mappings... */ - for(i = 0; i < (dvmaiobase >> 16); i++) { - unsigned long val = ((((unsigned long)i) << 16UL) + phys_base); - - val |= IOPTE_VALID | IOPTE_64K | IOPTE_WRITE; - if (iommu->strbuf_enabled) - val |= IOPTE_STBUF; - else - val |= IOPTE_CACHE; - *iopte = val; - iopte++; - } - - /* Clear all sparc_alloc_dvma() maps. */ - for( ; i < ((dvmaiobase + DVMAIO_SIZE) >> 16); i++) - *iopte++ = 0; - - sregs->iommu_tsbbase = __pa(tsbbase); - sregs->iommu_control = control; - - /* Get the streaming buffer going. */ - control = sregs->sbuf_control; - impl = (control & SYSIO_SBUFCTRL_IMPL) >> 60; - vers = (control & SYSIO_SBUFCTRL_REV) >> 56; - printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ... ", - (unsigned int)impl, (unsigned int)vers); - iommu->flushflag = 0; - - if (iommu->strbuf_enabled != 0) { - sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN); - printk("ENABLED\n"); - } else { - sregs->sbuf_control = (control & ~(SYSIO_SBUFCTRL_SB_EN)); - printk("DISABLED\n"); - } - - /* Finally enable DVMA arbitration for all devices, just in case. */ - sregs->sbus_control |= SYSIO_SBCNTRL_AEN; - - /* If necessary, hook us up for starfire IRQ translations. */ - sbus->upaid = prom_getintdefault(sbus->prom_node, "upa-portid", -1); - if(this_is_starfire) - sbus->starfire_cookie = starfire_hookup(sbus->upaid); - else - sbus->starfire_cookie = NULL; -} - -void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr, - struct linux_sbus *sbus) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* Find out if we need to grab some pages. */ - if(!dvma_map_pages[dvma_pages_current_index] || - ((dvma_pages_current_offset + len) > (1 << 16))) { - struct linux_sbus *sbus; - unsigned long *iopte; - unsigned long newpages = __get_free_pages(GFP_KERNEL, 3); - int i; - - if(!newpages) - panic("AIEEE cannot get DVMA pages."); - - memset((char *)newpages, 0, (1 << 16)); - - if(!dvma_map_pages[dvma_pages_current_index]) { - dvma_map_pages[dvma_pages_current_index] = newpages; - i = dvma_pages_current_index; - } else { - dvma_map_pages[dvma_pages_current_index + 1] = newpages; - i = dvma_pages_current_index + 1; - } - - /* Stick it in the IOMMU. */ - i = (dvmaiobase >> 16) + i; - for_each_sbus(sbus) { - struct iommu_struct *iommu = sbus->iommu; - unsigned long flags; - - spin_lock_irqsave(&iommu->iommu_lock, flags); - iopte = (unsigned long *)(iommu->page_table + i); - *iopte = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE); - *iopte |= __pa(newpages); - spin_unlock_irqrestore(&iommu->iommu_lock, flags); - } - } - - /* Get this out of the way. */ - *dvma_addr = (__u32) ((dvmaiobase) + - (dvma_pages_current_index << 16) + - (dvma_pages_current_offset)); - - while(len > 0) { - while((len > 0) && (dvma_pages_current_offset < (1 << 16))) { - pte_t pte; - unsigned long the_page = - dvma_map_pages[dvma_pages_current_index] + - dvma_pages_current_offset; - - /* Map the CPU's view. */ - pgdp = pgd_offset(&init_mm, addr); - pmdp = pmd_alloc_kernel(pgdp, addr); - ptep = pte_alloc_kernel(pmdp, addr); - pte = mk_pte(the_page, PAGE_KERNEL); - set_pte(ptep, pte); - - dvma_pages_current_offset += PAGE_SIZE; - addr += PAGE_SIZE; - len -= PAGE_SIZE; - } - dvma_pages_current_index++; - dvma_pages_current_offset = 0; - } -} - -__u32 mmu_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus) -{ - struct iommu_struct *iommu = sbus->iommu; - struct sysio_regs *sregs = iommu->sysio_regs; - unsigned long start = (unsigned long) vaddr; - unsigned long end = PAGE_ALIGN(start + len); - unsigned long flags, tmp; - volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; - - start &= PAGE_MASK; - if (end > MAX_DMA_ADDRESS) { - printk("mmu_get_scsi_one: Bogus DMA buffer address [%016lx:%d]\n", - (unsigned long) vaddr, (int)len); - panic("DMA address too large, tell DaveM"); - } - - if (iommu->strbuf_enabled) { - volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; - - spin_lock_irqsave(&iommu->iommu_lock, flags); - iommu->flushflag = 0; - while(start < end) { - *sbuf_pflush = start; - start += PAGE_SIZE; - } - sregs->sbuf_fsync = __pa(&(iommu->flushflag)); - tmp = *sbctrl; - while(iommu->flushflag == 0) - membar("#LoadLoad"); - spin_unlock_irqrestore(&iommu->iommu_lock, flags); - } - - return sbus_dvma_addr(vaddr); -} - -void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus) -{ - struct iommu_struct *iommu = sbus->iommu; - struct sysio_regs *sregs = iommu->sysio_regs; - unsigned long start = (unsigned long) vaddr; - unsigned long end = PAGE_ALIGN(start + len); - unsigned long flags, tmp; - volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; - - start &= PAGE_MASK; - - if (iommu->strbuf_enabled) { - volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; - - spin_lock_irqsave(&iommu->iommu_lock, flags); - - /* 1) Clear the flush flag word */ - iommu->flushflag = 0; - - /* 2) Tell the streaming buffer which entries - * we want flushed. - */ - while(start < end) { - *sbuf_pflush = start; - start += PAGE_SIZE; - } - - /* 3) Initiate flush sequence. */ - sregs->sbuf_fsync = __pa(&(iommu->flushflag)); - - /* 4) Guarentee completion of all previous writes - * by reading SYSIO's SBUS control register. - */ - tmp = *sbctrl; - - /* 5) Wait for flush flag to get set. */ - while(iommu->flushflag == 0) - membar("#LoadLoad"); - - spin_unlock_irqrestore(&iommu->iommu_lock, flags); - } -} - -void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) -{ - struct iommu_struct *iommu = sbus->iommu; - struct sysio_regs *sregs = iommu->sysio_regs; - unsigned long flags, tmp; - volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; - - if (iommu->strbuf_enabled) { - volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; - - spin_lock_irqsave(&iommu->iommu_lock, flags); - iommu->flushflag = 0; - - while(sz >= 0) { - unsigned long start = (unsigned long)sg[sz].addr; - unsigned long end = PAGE_ALIGN(start + sg[sz].len); - - if (end > MAX_DMA_ADDRESS) { - printk("mmu_get_scsi_sgl: Bogus DMA buffer address " - "[%016lx:%d]\n", start, (int) sg[sz].len); - panic("DMA address too large, tell DaveM"); - } - - sg[sz--].dvma_addr = sbus_dvma_addr(start); - start &= PAGE_MASK; - while(start < end) { - *sbuf_pflush = start; - start += PAGE_SIZE; - } - } - - sregs->sbuf_fsync = __pa(&(iommu->flushflag)); - tmp = *sbctrl; - while(iommu->flushflag == 0) - membar("#LoadLoad"); - spin_unlock_irqrestore(&iommu->iommu_lock, flags); - } else { - /* Just verify the addresses and fill in the - * dvma_addr fields in this case. - */ - while(sz >= 0) { - unsigned long start = (unsigned long)sg[sz].addr; - unsigned long end = PAGE_ALIGN(start + sg[sz].len); - if (end > MAX_DMA_ADDRESS) { - printk("mmu_get_scsi_sgl: Bogus DMA buffer address " - "[%016lx:%d]\n", start, (int) sg[sz].len); - panic("DMA address too large, tell DaveM"); - } - sg[sz--].dvma_addr = sbus_dvma_addr(start); - } - } -} - -void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus) -{ - struct iommu_struct *iommu = sbus->iommu; - struct sysio_regs *sregs = iommu->sysio_regs; - volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control; - unsigned long flags, tmp; - - if (iommu->strbuf_enabled) { - volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush; - - spin_lock_irqsave(&iommu->iommu_lock, flags); - - /* 1) Clear the flush flag word */ - iommu->flushflag = 0; - - /* 2) Tell the streaming buffer which entries - * we want flushed. - */ - while(sz >= 0) { - unsigned long start = sg[sz].dvma_addr; - unsigned long end = PAGE_ALIGN(start + sg[sz].len); - - start &= PAGE_MASK; - while(start < end) { - *sbuf_pflush = start; - start += PAGE_SIZE; - } - sz--; - } - - /* 3) Initiate flush sequence. */ - sregs->sbuf_fsync = __pa(&(iommu->flushflag)); - - /* 4) Guarentee completion of previous writes - * by reading SYSIO's SBUS control register. - */ - tmp = *sbctrl; - - /* 5) Wait for flush flag to get set. */ - while(iommu->flushflag == 0) - membar("#LoadLoad"); - - spin_unlock_irqrestore(&iommu->iommu_lock, flags); - } -} - -void mmu_set_sbus64(struct linux_sbus_device *sdev, int bursts) -{ - struct linux_sbus *sbus = sdev->my_bus; - struct sysio_regs *sregs = sbus->iommu->sysio_regs; - int slot = sdev->slot; - volatile u64 *cfg; - u64 tmp; - - switch(slot) { - case 0: - cfg = &sregs->sbus_s0cfg; - break; - case 1: - cfg = &sregs->sbus_s1cfg; - break; - case 2: - cfg = &sregs->sbus_s2cfg; - break; - case 3: - cfg = &sregs->sbus_s3cfg; - break; - - case 13: - cfg = &sregs->sbus_s4cfg; - break; - case 14: - cfg = &sregs->sbus_s5cfg; - break; - case 15: - cfg = &sregs->sbus_s6cfg; - break; - - default: - return; - }; - - /* ETM already enabled? If so, we're done. */ - tmp = *cfg; - if ((tmp & SYSIO_SBSCFG_ETM) != 0) - return; - - /* Set burst bits. */ - if (bursts & DMA_BURST8) - tmp |= SYSIO_SBSCFG_BA8; - if (bursts & DMA_BURST16) - tmp |= SYSIO_SBSCFG_BA16; - if (bursts & DMA_BURST32) - tmp |= SYSIO_SBSCFG_BA32; - if (bursts & DMA_BURST64) - tmp |= SYSIO_SBSCFG_BA64; - - /* Finally turn on ETM and set register. */ - *cfg = (tmp | SYSIO_SBSCFG_ETM); -} - int mmu_info(char *buf) { /* We'll do the rest later to make it nice... -DaveM */ +#if 0 + if (this_is_cheetah) + sprintf(buf, "MMU Type\t: One bad ass cpu\n"); + else +#endif return sprintf(buf, "MMU Type\t: Spitfire\n"); } -static unsigned long mempool; - struct linux_prom_translation { unsigned long virt; unsigned long size; unsigned long data; }; -static inline void inherit_prom_mappings(void) +extern unsigned long prom_boot_page; +extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); +extern int prom_get_mmu_ihandle(void); +extern void register_prom_callbacks(void); + +/* Exported for SMP bootup purposes. */ +unsigned long kern_locked_tte_data; + +void __init early_pgtable_allocfail(char *type) +{ + prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type); + prom_halt(); +} + +static void inherit_prom_mappings(void) { struct linux_prom_translation *trans; + unsigned long phys_page, tte_vaddr, tte_data; + void (*remap_func)(unsigned long, unsigned long, int); pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int node, n, i; + int node, n, i, tsz; node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); @@ -665,11 +184,17 @@ prom_printf("Couldn't get translation property\n"); prom_halt(); } + n += 5 * sizeof(struct linux_prom_translation); + for (tsz = 1; tsz < n; tsz <<= 1) + /* empty */; + trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL); + if (trans == NULL) { + prom_printf("inherit_prom_mappings: Cannot alloc translations.\n"); + prom_halt(); + } + memset(trans, 0, tsz); - for (i = 1; i < n; i <<= 1) /* empty */; - trans = sparc_init_alloc(&mempool, i); - - if (prom_getproperty(node, "translations", (char *)trans, i) == -1) { + if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { prom_printf("Couldn't get translation property\n"); prom_halt(); } @@ -684,15 +209,22 @@ vaddr += PAGE_SIZE) { pgdp = pgd_offset(&init_mm, vaddr); if (pgd_none(*pgdp)) { - pmdp = sparc_init_alloc(&mempool, - PMD_TABLE_SIZE); - memset(pmdp, 0, PAGE_SIZE); + pmdp = __alloc_bootmem(PMD_TABLE_SIZE, + PMD_TABLE_SIZE, + 0UL); + if (pmdp == NULL) + early_pgtable_allocfail("pmd"); + memset(pmdp, 0, PMD_TABLE_SIZE); pgd_set(pgdp, pmdp); } pmdp = pmd_offset(pgdp, vaddr); if (pmd_none(*pmdp)) { - ptep = sparc_init_alloc(&mempool, - PTE_TABLE_SIZE); + ptep = __alloc_bootmem(PTE_TABLE_SIZE, + PTE_TABLE_SIZE, + 0UL); + if (ptep == NULL) + early_pgtable_allocfail("pte"); + memset(ptep, 0, PTE_TABLE_SIZE); pmd_set(pmdp, ptep); } ptep = pte_offset(pmdp, vaddr); @@ -701,6 +233,83 @@ } } } + + /* Now fixup OBP's idea about where we really are mapped. */ + prom_printf("Remapping the kernel... "); + phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR; + phys_page += ((unsigned long)&prom_boot_page - + (unsigned long)&empty_zero_page); + + /* Lock this into i/d tlb entry 59 */ + __asm__ __volatile__( + "stxa %%g0, [%2] %3\n\t" + "stxa %0, [%1] %4\n\t" + "membar #Sync\n\t" + "flush %%g6\n\t" + "stxa %%g0, [%2] %5\n\t" + "stxa %0, [%1] %6\n\t" + "membar #Sync\n\t" + "flush %%g6" + : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP | + _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), + "r" (59 << 3), "r" (TLB_TAG_ACCESS), + "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), + "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) + : "memory"); + + tte_vaddr = (unsigned long) &empty_zero_page; + kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63); + + remap_func = (void *) ((unsigned long) &prom_remap - + (unsigned long) &prom_boot_page); + + remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR, + (unsigned long) &empty_zero_page, + prom_get_mmu_ihandle()); + + /* Flush out that temporary mapping. */ + spitfire_flush_dtlb_nucleus_page(0x0); + spitfire_flush_itlb_nucleus_page(0x0); + + /* Now lock us back into the TLBs via OBP. */ + prom_dtlb_load(63, tte_data, tte_vaddr); + prom_itlb_load(63, tte_data, tte_vaddr); + + /* Re-read translations property. */ + if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { + prom_printf("Couldn't get translation property\n"); + prom_halt(); + } + n = n / sizeof(*trans); + + for (i = 0; i < n; i++) { + unsigned long vaddr = trans[i].virt; + unsigned long size = trans[i].size; + + if (vaddr < 0xf0000000UL) { + unsigned long avoid_start = (unsigned long) &empty_zero_page; + unsigned long avoid_end = avoid_start + (4 * 1024 * 1024); + + if (vaddr < avoid_start) { + unsigned long top = vaddr + size; + + if (top > avoid_start) + top = avoid_start; + prom_unmap(top - vaddr, vaddr); + } + if ((vaddr + size) > avoid_end) { + unsigned long bottom = vaddr; + + if (bottom < avoid_end) + bottom = avoid_end; + prom_unmap((vaddr + size) - bottom, bottom); + } + } + } + + prom_printf("done.\n"); + + register_prom_callbacks(); } /* The OBP specifications for sun4u mark 0xfffffffc00000000 and @@ -1020,6 +629,10 @@ struct pgtable_cache_struct pgt_quicklists; #endif +/* For PMDs we don't care about the color, writes are + * only done via Dcache which is write-thru, so non-Dcache + * reads will always see correct data. + */ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) { pmd_t *pmd; @@ -1033,79 +646,55 @@ return NULL; } -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) -{ - pte_t *pte; - - pte = (pte_t *) __get_free_page(GFP_KERNEL); - if(pte) { - memset(pte, 0, PAGE_SIZE); - pmd_set(pmd, pte); - return pte + offset; - } - return NULL; -} - -static void __init -allocate_ptable_skeleton(unsigned long start, unsigned long end) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - while (start < end) { - pgdp = pgd_offset(&init_mm, start); - if (pgd_none(*pgdp)) { - pmdp = sparc_init_alloc(&mempool, PAGE_SIZE); - memset(pmdp, 0, PAGE_SIZE); - pgd_set(pgdp, pmdp); - } - pmdp = pmd_offset(pgdp, start); - if (pmd_none(*pmdp)) { - ptep = sparc_init_alloc(&mempool, PAGE_SIZE); - memset(ptep, 0, PAGE_SIZE); - pmd_set(pmdp, ptep); - } - start = (start + PMD_SIZE) & PMD_MASK; - } -} - -/* - * Create a mapping for an I/O register. Have to make sure the side-effect - * bit is set. +/* OK, we have to color these pages because during DTLB + * protection faults we set the dirty bit via a non-Dcache + * enabled mapping in the VPTE area. The kernel can end + * up missing the dirty bit resulting in processes crashing + * _iff_ the VPTE mapping of the ptes have a virtual address + * bit 13 which is different from bit 13 of the physical address. + * + * The sequence is: + * 1) DTLB protection fault, write dirty bit into pte via VPTE + * mappings. + * 2) Swapper checks pte, does not see dirty bit, frees page. + * 3) Process faults back in the page, the old pre-dirtied copy + * is provided and here is the corruption. */ - -void sparc_ultra_mapioaddr(unsigned long physaddr, unsigned long virt_addr, - int bus, int rdonly) +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset, unsigned long color) { - pgd_t *pgdp = pgd_offset(&init_mm, virt_addr); - pmd_t *pmdp = pmd_offset(pgdp, virt_addr); - pte_t *ptep = pte_offset(pmdp, virt_addr); - pte_t pte; + unsigned long paddr = __get_free_pages(GFP_KERNEL, 1); - physaddr &= PAGE_MASK; + if (paddr) { + struct page *page2 = mem_map + MAP_NR(paddr + PAGE_SIZE); + unsigned long *to_free; + pte_t *pte; - if(rdonly) - pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __PRIV_BITS)); - else - pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS | __PRIV_BITS)); + /* Set count of second page, so we can free it + * seperately later on. + */ + atomic_set(&page2->count, 1); - set_pte(ptep, pte); -} + /* Clear out both pages now. */ + memset((char *)paddr, 0, (PAGE_SIZE << 1)); -/* XXX no longer used, remove me... -DaveM */ -void sparc_ultra_unmapioaddr(unsigned long virt_addr) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; + /* Determine which page we give to this request. */ + if (!color) { + pte = (pte_t *) paddr; + to_free = (unsigned long *) (paddr + PAGE_SIZE); + } else { + pte = (pte_t *) (paddr + PAGE_SIZE); + to_free = (unsigned long *) paddr; + } - pgdp = pgd_offset(&init_mm, virt_addr); - pmdp = pmd_offset(pgdp, virt_addr); - ptep = pte_offset(pmdp, virt_addr); + /* Now free the other one up, adjust cache size. */ + *to_free = (unsigned long) pte_quicklist[color ^ 0x1]; + pte_quicklist[color ^ 0x1] = to_free; + pgtable_cache_size++; - /* No need to flush uncacheable page. */ - pte_clear(ptep); + pmd_set(pmd, pte); + return pte + offset; + } + return NULL; } void sparc_ultra_dump_itlb(void) @@ -1139,21 +728,114 @@ } } +#undef DEBUG_BOOTMEM + +extern unsigned long cmdline_memory_size; + +unsigned long __init bootmem_init(void) +{ + unsigned long bootmap_size, start_pfn, end_pfn; + unsigned long end_of_phys_memory = 0UL; + int i; + + /* XXX It is a bit ambiguous here, whether we should + * XXX treat the user specified mem=xxx as total wanted + * XXX physical memory, or as a limit to the upper + * XXX physical address we allow. For now it is the + * XXX latter. -DaveM + */ +#ifdef DEBUG_BOOTMEM + prom_printf("bootmem_init: Scan sp_banks, "); +#endif + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + end_of_phys_memory = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + if (cmdline_memory_size) { + if (end_of_phys_memory > cmdline_memory_size) { + if (cmdline_memory_size > sp_banks[i].base_addr) { + end_of_phys_memory = + sp_banks[i-1].base_addr + + sp_banks[i-1].num_bytes; + sp_banks[i].base_addr = 0xdeadbeef; + sp_banks[i].num_bytes = 0; + } else { + sp_banks[i].num_bytes -= + (end_of_phys_memory - + cmdline_memory_size); + end_of_phys_memory = cmdline_memory_size; + sp_banks[++i].base_addr = 0xdeadbeef; + sp_banks[i].num_bytes = 0; + } + break; + } + } + } + + /* Start with page aligned address of last symbol in kernel + * image. The kernel is hard mapped below PAGE_OFFSET in a + * 4MB locked TLB translation. + */ + start_pfn = PAGE_ALIGN((unsigned long) &_end) - + ((unsigned long) &empty_zero_page); + + /* Adjust up to the physical address where the kernel begins. */ + start_pfn += phys_base; + + /* Now shift down to get the real physical page frame number. */ + start_pfn >>= PAGE_SHIFT; + + end_pfn = end_of_phys_memory >> PAGE_SHIFT; + + /* Initialize the boot-time allocator. */ +#ifdef DEBUG_BOOTMEM + prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n", + start_pfn, end_pfn); +#endif + bootmap_size = init_bootmem(start_pfn, end_pfn); + + /* Now register the available physical memory with the + * allocator. + */ + for (i = 0; sp_banks[i].num_bytes != 0; i++) { +#ifdef DEBUG_BOOTMEM + prom_printf("free_bootmem: base[%lx] size[%lx]\n", + sp_banks[i].base_addr, + sp_banks[i].num_bytes); +#endif + free_bootmem(sp_banks[i].base_addr, + sp_banks[i].num_bytes); + } + + /* Reserve the kernel text/data/bss and the bootmem bitmap. */ +#ifdef DEBUG_BOOTMEM + prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", + phys_base, + (((start_pfn << PAGE_SHIFT) + + bootmap_size) - phys_base)); +#endif + reserve_bootmem(phys_base, (((start_pfn << PAGE_SHIFT) + + bootmap_size) - phys_base)); + +#ifdef DEBUG_BOOTMEM + prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn); +#endif + return end_pfn; +} + /* paging_init() sets up the page tables */ -extern unsigned long free_area_init(unsigned long, unsigned long); -extern unsigned long sun_serial_setup(unsigned long); +extern void sun_serial_setup(void); + +static unsigned long last_valid_pfn; -unsigned long __init -paging_init(unsigned long start_mem, unsigned long end_mem) +void __init paging_init(void) { extern pmd_t swapper_pmd_dir[1024]; extern unsigned int sparc64_vpte_patchme1[1]; extern unsigned int sparc64_vpte_patchme2[1]; unsigned long alias_base = phys_base + PAGE_OFFSET; unsigned long second_alias_page = 0; - unsigned long pt; - unsigned long flags; + unsigned long pt, flags, end_pfn; unsigned long shift = alias_base - ((unsigned long)&empty_zero_page); set_bit(0, mmu_context_bmap); @@ -1176,7 +858,7 @@ : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt), "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3) : "memory"); - if (start_mem >= KERNBASE + 0x340000) { + if (((unsigned long)&_end) >= KERNBASE + 0x340000) { second_alias_page = alias_base + 0x400000; __asm__ __volatile__(" stxa %1, [%0] %3 @@ -1203,24 +885,22 @@ /* Now can init the kernel/bad page tables. */ pgd_set(&swapper_pg_dir[0], swapper_pmd_dir + (shift / sizeof(pgd_t))); - sparc64_vpte_patchme1[0] |= (init_mm.pgd[0] >> 10); - sparc64_vpte_patchme2[0] |= (init_mm.pgd[0] & 0x3ff); + sparc64_vpte_patchme1[0] |= (pgd_val(init_mm.pgd[0]) >> 10); + sparc64_vpte_patchme2[0] |= (pgd_val(init_mm.pgd[0]) & 0x3ff); flushi((long)&sparc64_vpte_patchme1[0]); - /* We use mempool to create page tables, therefore adjust it up - * such that __pa() macros etc. work. - */ - mempool = PAGE_ALIGN(start_mem) + shift; - + /* Setup bootmem... */ + last_valid_pfn = end_pfn = bootmem_init(); + #ifdef CONFIG_SUN_SERIAL - /* This does not logically belong here, but is the first place - we can initialize it at, so that we work in the PAGE_OFFSET+ - address space. */ - mempool = sun_serial_setup(mempool); + /* 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(); #endif - /* Allocate 64M for dynamic DVMA mapping area. */ - allocate_ptable_skeleton(DVMA_VADDR, DVMA_VADDR + 0x4000000); + /* Inherit non-locked OBP mappings. */ inherit_prom_mappings(); /* Ok, we can use our TLB miss and window trap handlers safely. @@ -1231,205 +911,314 @@ { extern void setup_tba(int); int is_starfire = prom_finddevice("/ssp-serial"); - if(is_starfire != 0 && is_starfire != -1) + if (is_starfire != 0 && is_starfire != -1) is_starfire = 1; else is_starfire = 0; setup_tba(is_starfire); } - /* Really paranoid. */ - flushi((long)&empty_zero_page); - membar("#Sync"); - - /* Cleanup the extra locked TLB entry we created since we have the - * nice TLB miss handlers of ours installed now. - */ + inherit_locked_prom_mappings(1); + /* We only created DTLB mapping of this stuff. */ spitfire_flush_dtlb_nucleus_page(alias_base); if (second_alias_page) spitfire_flush_dtlb_nucleus_page(second_alias_page); - membar("#Sync"); - /* Paranoid */ - flushi((long)&empty_zero_page); - membar("#Sync"); + flush_tlb_all(); - inherit_locked_prom_mappings(1); + { + unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0}; - flush_tlb_all(); + zones_size[ZONE_DMA] = end_pfn; + free_area_init(zones_size); + } - start_mem = free_area_init(PAGE_ALIGN(mempool), end_mem); + device_scan(); +} - return device_scan (PAGE_ALIGN (start_mem)); +/* Ok, it seems that the prom can allocate some more memory chunks + * as a side effect of some prom calls we perform during the + * boot sequence. My most likely theory is that it is from the + * prom_set_traptable() call, and OBP is allocating a scratchpad + * for saving client program register state etc. + */ +void __init sort_memlist(struct linux_mlist_p1275 *thislist) +{ + int swapi = 0; + int i, mitr; + unsigned long tmpaddr, tmpsize; + unsigned long lowest; + + for (i = 0; thislist[i].theres_more != 0; i++) { + lowest = thislist[i].start_adr; + for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++) + if (thislist[mitr].start_adr < lowest) { + lowest = thislist[mitr].start_adr; + swapi = mitr; + } + if (lowest == thislist[i].start_adr) + continue; + tmpaddr = thislist[swapi].start_adr; + tmpsize = thislist[swapi].num_bytes; + for (mitr = swapi; mitr > i; mitr--) { + thislist[mitr].start_adr = thislist[mitr-1].start_adr; + thislist[mitr].num_bytes = thislist[mitr-1].num_bytes; + } + thislist[i].start_adr = tmpaddr; + thislist[i].num_bytes = tmpsize; + } } -static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem) +void __init rescan_sp_banks(void) { - unsigned long tmp = 0, paddr, endaddr; - unsigned long end = __pa(end_mem); + struct linux_prom64_registers memlist[64]; + struct linux_mlist_p1275 avail[64], *mlist; + unsigned long bytes, base_paddr; + int num_regs, node = prom_finddevice("/memory"); + int i; - dvmaio_init(); - for (paddr = __pa(start_mem); paddr < end; ) { - for (; sp_banks[tmp].num_bytes != 0; tmp++) - if (sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes > paddr) - break; - if (!sp_banks[tmp].num_bytes) { - mem_map[paddr>>PAGE_SHIFT].flags |= (1<>PAGE_SHIFT].next_hash = mem_map + (phys_base >> PAGE_SHIFT); - mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<>PAGE_SHIFT)+1UL].next_hash = mem_map + (phys_base >> PAGE_SHIFT); - return; + num_regs = prom_getproperty(node, "available", + (char *) memlist, sizeof(memlist)); + num_regs = (num_regs / sizeof(struct linux_prom64_registers)); + for (i = 0; i < num_regs; i++) { + avail[i].start_adr = memlist[i].phys_addr; + avail[i].num_bytes = memlist[i].reg_size; + avail[i].theres_more = &avail[i + 1]; + } + avail[i - 1].theres_more = NULL; + sort_memlist(avail); + + mlist = &avail[0]; + i = 0; + bytes = mlist->num_bytes; + base_paddr = mlist->start_adr; + + sp_banks[0].base_addr = base_paddr; + sp_banks[0].num_bytes = bytes; + + while (mlist->theres_more != NULL){ + i++; + mlist = mlist->theres_more; + bytes = mlist->num_bytes; + if (i >= SPARC_PHYS_BANKS-1) { + printk ("The machine has more banks than " + "this kernel can support\n" + "Increase the SPARC_PHYS_BANKS " + "setting (currently %d)\n", + SPARC_PHYS_BANKS); + i = SPARC_PHYS_BANKS-1; + break; } - - if (sp_banks[tmp].base_addr > paddr) { - /* Making a one or two pages PG_skip holes - * is not necessary. We add one more because - * we must set the PG_skip flag on the first - * two mem_map[] entries for the hole. Go and - * see the mm/filemap.c:shrink_mmap() loop for - * details. -DaveM - */ - if (sp_banks[tmp].base_addr - paddr > 3 * PAGE_SIZE) { - mem_map[paddr>>PAGE_SHIFT].flags |= (1<>PAGE_SHIFT].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT); - mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<>PAGE_SHIFT)+1UL].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT); + + sp_banks[i].base_addr = mlist->start_adr; + sp_banks[i].num_bytes = mlist->num_bytes; + } + + i++; + sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; + sp_banks[i].num_bytes = 0; + + for (i = 0; sp_banks[i].num_bytes != 0; i++) + sp_banks[i].num_bytes &= PAGE_MASK; +} + +static void __init taint_real_pages(void) +{ + struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS]; + int i; + +#ifdef DEBUG_BOOTMEM + prom_printf("taint_real_pages: Rescan sp_banks[].\n"); +#endif + for (i = 0; i < SPARC_PHYS_BANKS; i++) { + saved_sp_banks[i].base_addr = + sp_banks[i].base_addr; + saved_sp_banks[i].num_bytes = + sp_banks[i].num_bytes; + } + + rescan_sp_banks(); + + /* Find changes discovered in the sp_bank rescan and + * reserve the lost portions in the bootmem maps. + */ + for (i = 0; saved_sp_banks[i].num_bytes; i++) { + unsigned long old_start, old_end; + + old_start = saved_sp_banks[i].base_addr; + old_end = old_start + + saved_sp_banks[i].num_bytes; + while (old_start < old_end) { + int n; + + for (n = 0; sp_banks[n].num_bytes; n++) { + unsigned long new_start, new_end; + + new_start = sp_banks[n].base_addr; + new_end = new_start + sp_banks[n].num_bytes; + + if (new_start <= old_start && + new_end >= (old_start + PAGE_SIZE)) { + set_bit (old_start >> 22, + sparc64_valid_addr_bitmap); + goto do_next_page; + } } - paddr = sp_banks[tmp].base_addr; +#ifdef DEBUG_BOOTMEM + prom_printf("taint: Page went away, reserve page %lx.\n", + old_start); +#endif + reserve_bootmem(old_start, PAGE_SIZE); + + do_next_page: + old_start += PAGE_SIZE; } - - endaddr = sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes; - while (paddr < endaddr) { - mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<> 22, sparc64_valid_addr_bitmap); - if (paddr >= (MAX_DMA_ADDRESS - PAGE_OFFSET)) - mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<> PAGE_SHIFT]; + free_mem_map_range(first, last); + } else { + struct page *first, *last; + unsigned long prev_end; + + prev_end = sp_banks[i-1].base_addr + + sp_banks[i-1].num_bytes; + prev_end = PAGE_ALIGN(prev_end); + first = &mem_map[prev_end >> PAGE_SHIFT]; + last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT]; + + free_mem_map_range(first, last); + + if (!sp_banks[i+1].num_bytes) { + prev_end = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + first = &mem_map[prev_end >> PAGE_SHIFT]; + last = &mem_map[last_valid_pfn]; + free_mem_map_range(first, last); + } } } +#ifdef DEBUG_BOOTMEM + prom_printf("\n"); +#endif } -void __init mem_init(unsigned long start_mem, unsigned long end_mem) +void __init mem_init(void) { - int codepages = 0; - int datapages = 0; - int initpages = 0; - unsigned long addr; - unsigned long alias_base = phys_base + PAGE_OFFSET - (long)(&empty_zero_page); - struct page *page, *end; + unsigned long codepages, datapages, initpages; + unsigned long addr, last; int i; - end_mem &= PAGE_MASK; - max_mapnr = MAP_NR(end_mem); - high_memory = (void *) end_mem; - - start_mem = ((start_mem + 7UL) & ~7UL); - sparc64_valid_addr_bitmap = (unsigned long *)start_mem; - i = max_mapnr >> ((22 - PAGE_SHIFT) + 6); + i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i += 1; - memset(sparc64_valid_addr_bitmap, 0, i << 3); - start_mem += i << 3; - - start_mem = PAGE_ALIGN(start_mem); - num_physpages = 0; - - if (phys_base) { - mem_map[0].flags |= (1<> PAGE_SHIFT); - mem_map[1].flags |= (1<> PAGE_SHIFT); + sparc64_valid_addr_bitmap = (unsigned long *) + __alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL); + if (sparc64_valid_addr_bitmap == NULL) { + prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); + prom_halt(); } + memset(sparc64_valid_addr_bitmap, 0, i << 3); addr = PAGE_OFFSET + phys_base; - while(addr < start_mem) { + last = PAGE_ALIGN((unsigned long)&_end) - + ((unsigned long) &empty_zero_page); + last += PAGE_OFFSET + phys_base; + while (addr < last) { #ifdef CONFIG_BLK_DEV_INITRD +// FIXME to use bootmem scheme... if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end) mem_map[MAP_NR(addr)].flags &= ~(1<> 22, sparc64_valid_addr_bitmap); addr += PAGE_SIZE; } - taint_real_pages(start_mem, end_mem); - -#ifdef FREE_UNUSED_MEM_MAP - end = mem_map + max_mapnr; - for (page = mem_map; page < end; page++) { - if (PageSkip(page)) { - unsigned long low, high; - - /* See taint_real_pages() for why this is done. -DaveM */ - page++; - - 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) { - mem_map[MAP_NR(low)].flags &= ~(1<= end_mem) - break; - addr = next; - } - num_physpages++; - if (PageReserved(mem_map + MAP_NR(addr))) { - if ((addr < ((unsigned long) &etext) + alias_base) && (addr >= alias_base)) - codepages++; - else if((addr >= ((unsigned long)&__init_begin) + alias_base) - && (addr < ((unsigned long)&__init_end) + alias_base)) - initpages++; - else if((addr < start_mem) && (addr >= alias_base)) - datapages++; - continue; - } - atomic_set(&mem_map[MAP_NR(addr)].count, 1); -#ifdef CONFIG_BLK_DEV_INITRD - if (!initrd_start || - (addr < initrd_start || addr >= initrd_end)) + num_physpages = totalram_pages = free_all_bootmem(); +#if 0 + free_unused_mem_map(); #endif - free_page(addr); - } - + codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); + codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; + datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); + datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT; + initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); + initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; + #ifndef __SMP__ { /* Put empty_pg_dir on pgd_quicklist */ extern pgd_t empty_pg_dir[1024]; unsigned long addr = (unsigned long)empty_pg_dir; + unsigned long alias_base = phys_base + PAGE_OFFSET - + (long)(&empty_zero_page); memset(empty_pg_dir, 0, sizeof(empty_pg_dir)); addr += alias_base; - mem_map[MAP_NR(addr)].pprev_hash = 0; free_pgd_fast((pgd_t *)addr); + totalram_pages++; + num_physpages++; } #endif - printk("Memory: %uk available (%dk kernel code, %dk data, %dk init) [%016lx,%016lx]\n", - nr_free_pages << (PAGE_SHIFT-10), + printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n", + nr_free_pages() << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10), - PAGE_OFFSET, end_mem); + PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); /* NOTE NOTE NOTE NOTE * Please keep track of things and make sure this * always matches the code in mm/page_alloc.c -DaveM */ - i = nr_free_pages >> 7; + i = nr_free_pages() >> 7; if (i < 48) i = 48; if (i > 256) @@ -1442,42 +1231,35 @@ void free_initmem (void) { unsigned long addr; - + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - unsigned long page = addr + (long)__va(phys_base) - - (long)(&empty_zero_page); + unsigned long page; + struct page *p; - mem_map[MAP_NR(page)].flags &= ~(1 << PG_reserved); - atomic_set(&mem_map[MAP_NR(page)].count, 1); - free_page(page); + page = (addr + + ((unsigned long) __va(phys_base)) - + ((unsigned long) &empty_zero_page)); + p = mem_map + MAP_NR(page); + + ClearPageReserved(p); + set_page_count(p, 1); + __free_page(p); + totalram_pages++; + num_physpages++; } } void si_meminfo(struct sysinfo *val) { - struct page *page, *end; - - val->totalram = 0; + val->totalram = totalram_pages; val->sharedram = 0; - val->freeram = ((unsigned long)nr_free_pages) << PAGE_SHIFT; - val->bufferram = atomic_read(&buffermem); - for (page = mem_map, end = mem_map + max_mapnr; - page < end; page++) { - if (PageSkip(page)) { - if (page->next_hash < page) - break; - page = page->next_hash; - } - if (PageReserved(page)) - continue; - val->totalram++; - if (!atomic_read(&page->count)) - continue; - val->sharedram += atomic_read(&page->count) - 1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - val->totalbig = 0; - val->freebig = 0; + val->freeram = nr_free_pages(); + val->bufferram = atomic_read(&buffermem_pages); + + /* These are always zero on Sparc64. */ + val->totalhigh = 0; + val->freehigh = 0; + + val->mem_unit = PAGE_SIZE; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.3.34/linux/arch/sparc64/mm/ultra.S Thu Nov 18 20:25:37 1999 +++ linux/arch/sparc64/mm/ultra.S Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.34 1999/09/10 10:40:51 davem Exp $ +/* $Id: ultra.S,v 1.36 1999/12/15 15:45:18 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -174,10 +174,10 @@ * * Register usage: * %g5 mm->context (all tlb flushes) - * %g6 address arg 1 (tlb page and range flushes) + * %g1 address arg 1 (tlb page and range flushes) * %g7 address arg 2 (tlb range flush only) * - * %g1 ivector table, don't touch + * %g6 ivector table, don't touch * %g2 scratch 1 * %g3 scratch 2 * %g4 scratch 3 @@ -188,7 +188,7 @@ .globl xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range xcall_flush_tlb_page: mov SECONDARY_CONTEXT, %g2 - or %g6, 0x10, %g4 + or %g1, 0x10, %g4 ldxa [%g2] ASI_DMMU, %g3 stxa %g5, [%g2] ASI_DMMU stxa %g0, [%g4] ASI_DMMU_DEMAP @@ -209,11 +209,11 @@ xcall_flush_tlb_range: sethi %hi(8192 - 1), %g2 or %g2, %lo(8192 - 1), %g2 - andn %g6, %g2, %g6 + andn %g1, %g2, %g1 andn %g7, %g2, %g7 - sub %g7, %g6, %g3 + sub %g7, %g1, %g3 add %g2, 1, %g2 - orcc %g6, 0x10, %g6 + orcc %g1, 0x10, %g1 srlx %g3, 13, %g4 cmp %g4, 96 @@ -225,8 +225,8 @@ nop nop -1: stxa %g0, [%g6 + %g3] ASI_DMMU_DEMAP - stxa %g0, [%g6 + %g3] ASI_IMMU_DEMAP +1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP + stxa %g0, [%g1 + %g3] ASI_IMMU_DEMAP brnz,pt %g3, 1b sub %g3, %g2, %g3 stxa %g7, [%g4] ASI_DMMU @@ -262,6 +262,22 @@ b,pt %xcc, rtrap clr %l6 + .globl xcall_promstop +xcall_promstop: + rdpr %pstate, %g2 + wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + flushw + call prom_stopself + nop + /* We should not return, just spin if we do... */ +1: b,a,pt %xcc, 1b + nop + .globl xcall_receive_signal xcall_receive_signal: rdpr %pstate, %g2 @@ -303,7 +319,7 @@ cmp %g2, 63 ble,pt %icc, 1b sll %g2, 3, %g3 - flush %g1 + flush %g6 retry .globl xcall_flush_cache_all @@ -316,6 +332,6 @@ cmp %g3, %g2 bleu,pt %xcc, 1b nop - flush %g1 + flush %g6 retry #endif /* __SMP__ */ diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/Makefile linux/arch/sparc64/prom/Makefile --- v2.3.34/linux/arch/sparc64/prom/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/sparc64/prom/Makefile Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1997/02/25 12:40:25 jj Exp $ +# $Id: Makefile,v 1.5 1999/12/21 04:02:26 davem Exp $ # Makefile for the Sun Boot PROM interface library under # Linux. # @@ -9,13 +9,19 @@ # Note 2! The CFLAGS definitions are now in the main makefile... OBJS = bootstr.o devops.o init.o memory.o misc.o \ - ranges.o tree.o console.o printf.o p1275.o + tree.o console.o printf.o p1275.o map.o all: promlib.a promlib.a: $(OBJS) $(AR) rcs promlib.a $(OBJS) sync + +.S.s: + $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o dep: $(CPP) $(CPPFLAGS) -M *.c > .depend diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/init.c linux/arch/sparc64/prom/init.c --- v2.3.34/linux/arch/sparc64/prom/init.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/prom/init.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.9 1999/08/31 06:55:03 davem Exp $ +/* $Id: init.c,v 1.10 1999/09/21 14:35:59 davem Exp $ * init.c: Initialize internal variables used by the PROM * library functions. * @@ -28,7 +28,6 @@ */ extern void prom_meminit(void); -extern void prom_ranges_init(void); extern void prom_cif_init(void *, void *); void __init prom_init(void *cif_handler, void *cif_stack) @@ -81,8 +80,6 @@ printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + 4); prom_meminit(); - - prom_ranges_init(); /* Initialization successful. */ return; diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/map.S linux/arch/sparc64/prom/map.S --- v2.3.34/linux/arch/sparc64/prom/map.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/prom/map.S Mon Dec 20 22:05:52 1999 @@ -0,0 +1,70 @@ +/* $Id: map.S,v 1.2 1999/11/19 05:53:02 davem Exp $ + * map.S: Tricky coding required to fixup the kernel OBP maps + * properly. + * + * Copyright (C) 1999 David S. Miller (davem@redhat.com) + */ + + .text + .align 8192 + .globl prom_boot_page +prom_boot_page: +call_method: + .asciz "call-method" + .align 8 +map: + .asciz "map" + .align 8 + + /* When we are invoked, our caller has remapped us to + * page zero, therefore we must use PC relative addressing + * for everything after we begin performing the unmap/map + * calls. + */ + .globl prom_remap +prom_remap: /* %o0 = physpage, %o1 = virtpage, %o2 = mmu_ihandle */ + rd %pc, %g1 + srl %o2, 0, %o2 ! kill sign extension + sethi %hi(p1275buf), %g2 + or %g2, %lo(p1275buf), %g2 + ldx [%g2 + 0x10], %g3 ! prom_cif_stack + save %g3, -(192 + 128), %sp + ldx [%g2 + 0x08], %l0 ! prom_cif_handler + mov %g6, %i3 + mov %g4, %i4 + flushw + + sethi %hi(prom_remap - call_method), %g7 + or %g7, %lo(prom_remap - call_method), %g7 + sub %g1, %g7, %l2 ! call-method string + sethi %hi(prom_remap - map), %g7 + or %g7, %lo(prom_remap - map), %g7 + sub %g1, %g7, %l4 ! map string + + /* OK, map the 4MB region we really live at. */ + stx %l2, [%sp + 2047 + 128 + 0x00] ! call-method + mov 7, %l5 + stx %l5, [%sp + 2047 + 128 + 0x08] ! num_args + mov 1, %l5 + stx %l5, [%sp + 2047 + 128 + 0x10] ! num_rets + stx %l4, [%sp + 2047 + 128 + 0x18] ! map + stx %i2, [%sp + 2047 + 128 + 0x20] ! mmu_ihandle + mov -1, %l5 + stx %l5, [%sp + 2047 + 128 + 0x28] ! mode == default + sethi %hi(4 * 1024 * 1024), %l5 + stx %l5, [%sp + 2047 + 128 + 0x30] ! size + stx %i1, [%sp + 2047 + 128 + 0x38] ! vaddr + stx %g0, [%sp + 2047 + 128 + 0x40] ! filler + stx %i0, [%sp + 2047 + 128 + 0x48] ! paddr + call %l0 + add %sp, (2047 + 128), %o0 ! argument array + + /* Restore hard-coded globals. */ + mov %i3, %g6 + mov %i4, %g4 + + /* Wheee.... we are done. */ + ret + restore + + .align 8192 diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c --- v2.3.34/linux/arch/sparc64/prom/misc.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/prom/misc.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.15 1999/08/31 19:25:41 davem Exp $ +/* $Id: misc.c,v 1.16 1999/11/19 05:53:04 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -37,6 +39,11 @@ extern int serial_console; #endif +#ifdef __SMP__ +extern void smp_capture(void); +extern void smp_release(void); +#endif + /* Drop into the prom, with the chance to continue with the 'go' * prom command. */ @@ -44,26 +51,57 @@ prom_cmdline(void) { unsigned long flags; - + + __save_and_cli(flags); + #ifdef CONFIG_SUN_CONSOLE if(!serial_console && prom_palette) prom_palette (1); #endif - __save_and_cli(flags); + + /* We always arrive here via a serial interrupt. + * So in order for everything to work reliably, even + * on SMP, we need to drop the IRQ locks we hold. + */ +#ifdef __SMP__ + hardirq_exit(smp_processor_id()); + smp_capture(); +#else + local_irq_count--; +#endif + p1275_cmd ("enter", P1275_INOUT(0,0)); - __restore_flags(flags); + +#ifdef __SMP__ + smp_release(); + hardirq_enter(smp_processor_id()); + spin_unlock_wait(&global_irq_lock); +#else + local_irq_count++; +#endif + #ifdef CONFIG_SUN_CONSOLE if(!serial_console && prom_palette) prom_palette (0); #endif + + __restore_flags(flags); } +#ifdef __SMP__ +extern void smp_promstop_others(void); +#endif + /* Drop into the prom, but completely terminate the program. * No chance of continuing. */ void prom_halt(void) { +#ifdef __SMP__ + smp_promstop_others(); + udelay(8000); +#endif again: p1275_cmd ("exit", P1275_INOUT(0,0)); goto again; /* PROM is out to get me -DaveM */ @@ -122,10 +160,10 @@ p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba); } -/* This is only used internally below. */ -static int prom_get_mmu_ihandle(void) +int mmu_ihandle_cache = 0; + +int prom_get_mmu_ihandle(void) { - static int mmu_ihandle_cache = 0; int node, ret; if (mmu_ihandle_cache != 0) @@ -165,7 +203,10 @@ unsigned long vaddr) { return p1275_cmd("call-method", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 1)), + (P1275_ARG(0, P1275_ARG_IN_STRING) | + P1275_ARG(2, P1275_ARG_IN_64B) | + P1275_ARG(3, P1275_ARG_IN_64B) | + P1275_INOUT(5, 1)), "SUNW,itlb-load", prom_get_mmu_ihandle(), /* And then our actual args are pushed backwards. */ @@ -179,7 +220,10 @@ unsigned long vaddr) { return p1275_cmd("call-method", - (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 1)), + (P1275_ARG(0, P1275_ARG_IN_STRING) | + P1275_ARG(2, P1275_ARG_IN_64B) | + P1275_ARG(3, P1275_ARG_IN_64B) | + P1275_INOUT(5, 1)), "SUNW,dtlb-load", prom_get_mmu_ihandle(), /* And then our actual args are pushed backwards. */ @@ -188,6 +232,41 @@ index); } +int prom_map(int mode, unsigned long size, + unsigned long vaddr, unsigned long paddr) +{ + int ret = p1275_cmd("call-method", + (P1275_ARG(0, P1275_ARG_IN_STRING) | + P1275_ARG(3, P1275_ARG_IN_64B) | + P1275_ARG(4, P1275_ARG_IN_64B) | + P1275_ARG(6, P1275_ARG_IN_64B) | + P1275_INOUT(7, 1)), + "map", + prom_get_mmu_ihandle(), + mode, + size, + vaddr, + 0, + paddr); + + if (ret == 0) + ret = -1; + return ret; +} + +void prom_unmap(unsigned long size, unsigned long vaddr) +{ + p1275_cmd("call-method", + (P1275_ARG(0, P1275_ARG_IN_STRING) | + P1275_ARG(2, P1275_ARG_IN_64B) | + P1275_ARG(3, P1275_ARG_IN_64B) | + P1275_INOUT(4, 0)), + "unmap", + prom_get_mmu_ihandle(), + size, + vaddr); +} + /* Set aside physical memory which is not touched or modified * across soft resets. */ @@ -226,7 +305,7 @@ return p1275_cmd("call-method", (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(3, P1275_ARG_OUT_BUF) | - P1275_ARG(5, P1275_ARG_IN_64B) | + P1275_ARG(6, P1275_ARG_IN_64B) | P1275_INOUT(8, 2)), "SUNW,get-unumber", prom_get_memory_ihandle(), buflen, buf, P1275_SIZE(buflen), diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c --- v2.3.34/linux/arch/sparc64/prom/p1275.c Fri Sep 10 23:57:28 1999 +++ linux/arch/sparc64/prom/p1275.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: p1275.c,v 1.18 1999/09/10 10:40:53 davem Exp $ +/* $Id: p1275.c,v 1.20 1999/11/23 23:47:56 davem Exp $ * p1275.c: Sun IEEE 1275 PROM low level interface routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -252,11 +252,7 @@ * the counter is needed. -DaveM */ static int prom_entry_depth = 0; -static spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED; -#ifdef __SMP__ -extern void smp_capture(void); -extern void smp_release(void); -#endif +spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED; static __inline__ unsigned long prom_get_lock(void) { @@ -270,9 +266,6 @@ if (prom_entry_depth != 0) panic("prom_get_lock"); #endif -#ifdef __SMP__ - smp_capture(); -#endif } prom_entry_depth++; @@ -281,12 +274,9 @@ static __inline__ void prom_release_lock(unsigned long flags) { - if (--prom_entry_depth == 0) { -#ifdef __SMP__ - smp_release(); -#endif + if (--prom_entry_depth == 0) spin_unlock(&prom_entry_lock); - } + __restore_flags(flags); } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/ranges.c linux/arch/sparc64/prom/ranges.c --- v2.3.34/linux/arch/sparc64/prom/ranges.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/prom/ranges.c Wed Dec 31 16:00:00 1969 @@ -1,192 +0,0 @@ -/* $Id: ranges.c,v 1.12 1999/08/31 06:55:05 davem Exp $ - * ranges.c: Handle ranges in newer proms for obio/sbus. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PCI -#include -#include -#endif - -struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; -int num_obio_ranges; - -/* Adjust register values based upon the ranges parameters. */ -inline void -prom_adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges) -{ - int regc, rngc; - - for(regc=0; regc < nregs; regc++) { - for(rngc=0; rngc < nranges; rngc++) - if(regp[regc].which_io == rangep[rngc].ot_child_space) - break; /* Fount it */ - if(rngc==nranges) /* oops */ - prom_printf("adjust_regs: Could not find range with matching bus type...\n"); - regp[regc].which_io = rangep[rngc].ot_parent_space; - regp[regc].phys_addr += rangep[rngc].ot_parent_base; - } -} - -inline void -prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, - struct linux_prom_ranges *ranges2, int nranges2) -{ - int rng1c, rng2c; - - for(rng1c=0; rng1c < nranges1; rng1c++) { - for(rng2c=0; rng2c < nranges2; rng2c++) - if(ranges1[rng1c].ot_child_space == - ranges2[rng2c].ot_child_space) break; - if(rng2c == nranges2) /* oops */ - prom_printf("adjust_ranges: Could not find matching bus type...\n"); - ranges1[rng1c].ot_parent_space = ranges2[rng2c].ot_parent_space; - ranges1[rng1c].ot_parent_base += ranges2[rng2c].ot_parent_base; - } -} - -/* Apply probed sbus ranges to registers passed, if no ranges return. */ -void prom_apply_sbus_ranges(struct linux_sbus *sbus, struct linux_prom_registers *regs, - int nregs, struct linux_sbus_device *sdev) -{ - if(sbus->num_sbus_ranges) { - if(sdev && (sdev->ranges_applied == 0)) { - sdev->ranges_applied = 1; - prom_adjust_regs(regs, nregs, sbus->sbus_ranges, - sbus->num_sbus_ranges); - } - } -} - -/* Apply probed fhc ranges to registers passed, if no ranges return. */ -void prom_apply_fhc_ranges(struct linux_fhc *fhc, - struct linux_prom_registers *regs, - int nregs) -{ - if(fhc->num_fhc_ranges) - prom_adjust_regs(regs, nregs, fhc->fhc_ranges, - fhc->num_fhc_ranges); -} - -/* Apply probed central ranges to registers passed, if no ranges return. */ -void prom_apply_central_ranges(struct linux_central *central, - struct linux_prom_registers *regs, int nregs) -{ - if(central->num_central_ranges) - prom_adjust_regs(regs, nregs, central->central_ranges, - central->num_central_ranges); -} - -void __init prom_ranges_init(void) -{ -} - -void __init prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus) -{ - int success; - - sbus->num_sbus_ranges = 0; - success = prom_getproperty(sbus->prom_node, "ranges", - (char *) sbus->sbus_ranges, - sizeof (sbus->sbus_ranges)); - if (success != -1) - sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges)); -} - -void __init prom_central_ranges_init(int cnode, struct linux_central *central) -{ - int success; - - central->num_central_ranges = 0; - success = prom_getproperty(central->prom_node, "ranges", - (char *) central->central_ranges, - sizeof (central->central_ranges)); - if (success != -1) - central->num_central_ranges = (success/sizeof(struct linux_prom_ranges)); -} - -void __init prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc) -{ - int success; - - fhc->num_fhc_ranges = 0; - success = prom_getproperty(fhc->prom_node, "ranges", - (char *) fhc->fhc_ranges, - sizeof (fhc->fhc_ranges)); - if (success != -1) - fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges)); -} - -#ifdef CONFIG_PCI -void __init prom_ebus_ranges_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_ranges = 0; - success = prom_getproperty(ebus->prom_node, "ranges", - (char *)ebus->ebus_ranges, - sizeof(ebus->ebus_ranges)); - if (success != -1) - ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); -} - -void __init prom_ebus_intmap_init(struct linux_ebus *ebus) -{ - int success; - - ebus->num_ebus_intmap = 0; - success = prom_getproperty(ebus->prom_node, "interrupt-map", - (char *)ebus->ebus_intmap, - sizeof(ebus->ebus_intmap)); - if (success == -1) - return; - - ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); - - success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", - (char *)&ebus->ebus_intmask, - sizeof(ebus->ebus_intmask)); - if (success == -1) { - prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); - prom_halt(); - } -} -#endif - -void -prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs) -{ - int success; - int num_ranges; - struct linux_prom_ranges ranges[PROMREG_MAX]; - - success = prom_getproperty(node, "ranges", - (char *) ranges, - sizeof (ranges)); - if (success != -1) { - num_ranges = (success/sizeof(struct linux_prom_ranges)); - if (parent) { - struct linux_prom_ranges parent_ranges[PROMREG_MAX]; - int num_parent_ranges; - - success = prom_getproperty(parent, "ranges", - (char *) parent_ranges, - sizeof (parent_ranges)); - if (success != -1) { - num_parent_ranges = (success/sizeof(struct linux_prom_ranges)); - prom_adjust_ranges (ranges, num_ranges, parent_ranges, num_parent_ranges); - } - } - prom_adjust_regs(regs, nregs, ranges, num_ranges); - } -} diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.3.34/linux/arch/sparc64/solaris/fs.c Sat May 15 11:12:09 1999 +++ linux/arch/sparc64/solaris/fs.c Mon Dec 20 22:05:52 1999 @@ -1,7 +1,10 @@ -/* $Id: fs.c,v 1.13 1999/05/14 07:24:37 davem Exp $ +/* $Id: fs.c,v 1.14 1999/09/22 09:28:49 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * 1999-08-19 Implemented solaris F_FREESP (truncate) + * fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu) */ #include @@ -661,7 +664,16 @@ __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT); return ret; } - } + case SOL_F_FREESP: + { + int length; + int (*sys_newftruncate)(unsigned int, unsigned long)= + (int (*)(unsigned int, unsigned long))SYS(ftruncate); + + get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, -EFAULT); + return sys_newftruncate(fd, length); + } + }; return -EINVAL; } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c --- v2.3.34/linux/arch/sparc64/solaris/ioctl.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc64/solaris/ioctl.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ioctl.c,v 1.13 1999/08/20 00:27:15 davem Exp $ +/* $Id: ioctl.c,v 1.14 1999/09/22 09:28:50 davem Exp $ * ioctl.c: Solaris ioctl emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -7,6 +7,9 @@ * Streams & timod emulation based on code * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) * + * 1999-08-19 Implemented solaris 'm' (mag tape) and + * 'O' (openprom) ioctls, by Jason Rappleye + * (rappleye@ccr.buffalo.edu) */ #include @@ -18,9 +21,12 @@ #include #include #include +#include +#include #include #include +#include #include "conv.h" #include "socksys.h" @@ -678,6 +684,90 @@ return -ENOSYS; } +static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg) +{ + int ret; + + switch (cmd & 0xff) { + case 1: /* MTIOCTOP */ + ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg); + break; + case 2: /* MTIOCGET */ + ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg); + break; + case 3: /* MTIOCGETDRIVETYPE */ + case 4: /* MTIOCPERSISTENT */ + case 5: /* MTIOCPERSISTENTSTATUS */ + case 6: /* MTIOCLRERR */ + case 7: /* MTIOCGUARANTEEDORDER */ + case 8: /* MTIOCRESERVE */ + case 9: /* MTIOCRELEASE */ + case 10: /* MTIOCFORCERESERVE */ + case 13: /* MTIOCSTATE */ + case 14: /* MTIOCREADIGNOREILI */ + case 15: /* MTIOCREADIGNOREEOFS */ + case 16: /* MTIOCSHORTFMK */ + default: + ret = -ENOSYS; /* linux doesn't support these */ + break; + }; + + return ret; +} + +static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg) +{ + int ret = -EINVAL; + + switch (cmd & 0xff) { + case 1: /* OPROMGETOPT */ + ret = sys_ioctl(fd, OPROMGETOPT, arg); + break; + case 2: /* OPROMSETOPT */ + ret = sys_ioctl(fd, OPROMSETOPT, arg); + break; + case 3: /* OPROMNXTOPT */ + ret = sys_ioctl(fd, OPROMNXTOPT, arg); + break; + case 4: /* OPROMSETOPT2 */ + ret = sys_ioctl(fd, OPROMSETOPT2, arg); + break; + case 5: /* OPROMNEXT */ + ret = sys_ioctl(fd, OPROMNEXT, arg); + break; + case 6: /* OPROMCHILD */ + ret = sys_ioctl(fd, OPROMCHILD, arg); + break; + case 7: /* OPROMGETPROP */ + ret = sys_ioctl(fd, OPROMGETPROP, arg); + break; + case 8: /* OPROMNXTPROP */ + ret = sys_ioctl(fd, OPROMNXTPROP, arg); + break; + case 9: /* OPROMU2P */ + ret = sys_ioctl(fd, OPROMU2P, arg); + break; + case 10: /* OPROMGETCONS */ + ret = sys_ioctl(fd, OPROMGETCONS, arg); + break; + case 11: /* OPROMGETFBNAME */ + ret = sys_ioctl(fd, OPROMGETFBNAME, arg); + break; + case 12: /* OPROMGETBOOTARGS */ + ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg); + break; + case 13: /* OPROMGETVERSION */ + case 14: /* OPROMPATH2DRV */ + case 15: /* OPROMDEV2PROMNAME */ + case 16: /* OPROMPROM2DEVNAME */ + case 17: /* OPROMGETPROPLEN */ + default: + ret = -EINVAL; + break; + }; + return ret; +} + /* }}} */ asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg) @@ -699,6 +789,8 @@ case 's': error = solaris_s(fd, cmd, arg); break; case 't': error = solaris_t(fd, cmd, arg); break; case 'f': error = sys_ioctl(fd, cmd, arg); break; + case 'm': error = solaris_m(fd, cmd, arg); break; + case 'O': error = solaris_O(fd, cmd, arg); break; default: error = -ENOSYS; break; diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/ipc.c linux/arch/sparc64/solaris/ipc.c --- v2.3.34/linux/arch/sparc64/solaris/ipc.c Sat May 15 11:12:09 1999 +++ linux/arch/sparc64/solaris/ipc.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: ipc.c,v 1.4 1999/05/13 07:11:37 jj Exp $ +/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $ * ipc.c: Solaris IPC emulation * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.3.34/linux/arch/sparc64/solaris/misc.c Tue Jun 29 09:22:08 1999 +++ linux/arch/sparc64/solaris/misc.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.14 1999/06/25 11:00:53 davem Exp $ +/* $Id: misc.c,v 1.19 1999/12/15 17:51:25 jj Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -476,8 +476,8 @@ #define RLIMIT_SOL_VMEM 6 struct rlimit32 { - s32 rlim_cur; - s32 rlim_max; + u32 rlim_cur; + u32 rlim_max; }; asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim) @@ -747,11 +747,7 @@ 1, 1, /* PER_SVR4 personality */ solaris_to_linux_signals, linux_to_solaris_signals, -#ifdef MODULE - &__this_module, -#else - NULL, -#endif + THIS_MODULE, NULL }; diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/socket.c linux/arch/sparc64/solaris/socket.c --- v2.3.34/linux/arch/sparc64/solaris/socket.c Mon Nov 16 10:37:28 1998 +++ linux/arch/sparc64/solaris/socket.c Mon Dec 20 22:05:52 1999 @@ -1,7 +1,10 @@ -/* $Id: socket.c,v 1.1 1998/10/28 08:12:11 jj Exp $ +/* $Id: socket.c,v 1.2 1999/09/22 09:28:50 davem Exp $ * socket.c: Socket syscall emulation for Solaris 2.6+ * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) + * + * 1999-08-19 Fixed socketpair code + * Jason Rappleye (rappleye@ccr.buffalo.edu) */ #include @@ -25,6 +28,18 @@ #define SOCK_SOL_RDM 5 #define SOCK_SOL_SEQPACKET 6 +#define SOL_SO_SNDLOWAT 0x1003 +#define SOL_SO_RCVLOWAT 0x1004 +#define SOL_SO_SNDTIMEO 0x1005 +#define SOL_SO_RCVTIMEO 0x1006 +#define SOL_SO_STATE 0x2000 + +#define SOL_SS_NDELAY 0x040 +#define SOL_SS_NONBLOCK 0x080 +#define SOL_SS_ASYNC 0x100 + +#define SO_STATE 0x000e + static int socket_check(int family, int type) { if (family != PF_UNIX && family != PF_INET) @@ -40,6 +55,19 @@ return type; } +static int solaris_to_linux_sockopt(int optname) +{ + switch (optname) { + case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break; + case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break; + case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; + case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break; + case SOL_SO_STATE: optname = SO_STATE; break; + }; + + return optname; +} + asmlinkage int solaris_socket(int family, int type, int protocol) { int (*sys_socket)(int, int, int) = @@ -50,14 +78,19 @@ return sys_socket(family, type, protocol); } -asmlinkage int solaris_socketpair(int family, int type, int protocol, int *usockvec) +asmlinkage int solaris_socketpair(int *usockvec) { int (*sys_socketpair)(int, int, int, int *) = (int (*)(int, int, int, int *))SYS(socketpair); - type = socket_check (family, type); - if (type < 0) return type; - return sys_socketpair(family, type, protocol, usockvec); + /* solaris socketpair really only takes one arg at the syscall + * level, int * usockvec. The libs apparently take care of + * making sure that family==AF_UNIX and type==SOCK_STREAM. The + * pointer we really want ends up residing in the first (and + * supposedly only) argument. + */ + + return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec); } asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen) @@ -73,6 +106,12 @@ int (*sunos_setsockopt)(int, int, int, u32, int) = (int (*)(int, int, int, u32, int))SUNOS(105); + optname = solaris_to_linux_sockopt(optname); + if (optname < 0) + return optname; + if (optname == SO_STATE) + return 0; + return sunos_setsockopt(fd, level, optname, optval, optlen); } @@ -80,6 +119,13 @@ { int (*sunos_getsockopt)(int, int, int, u32, u32) = (int (*)(int, int, int, u32, u32))SUNOS(118); + + optname = solaris_to_linux_sockopt(optname); + if (optname < 0) + return optname; + + if (optname == SO_STATE) + optname = SOL_SO_STATE; return sunos_getsockopt(fd, level, optname, optval, optlen); } diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- v2.3.34/linux/arch/sparc64/solaris/timod.c Mon Oct 11 15:38:14 1999 +++ linux/arch/sparc64/solaris/timod.c Mon Dec 20 22:05:52 1999 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.4 1999/09/01 08:07:47 davem Exp $ +/* $Id: timod.c,v 1.5 1999/11/23 08:55:24 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) diff -u --recursive --new-file v2.3.34/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.3.34/linux/drivers/block/ide-probe.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/ide-probe.c Tue Dec 21 21:56:42 1999 @@ -624,7 +624,7 @@ hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq); #elif defined(__sparc__) - printk("%s at 0x%03x-0x%03x,0x%03x on irq %s", hwif->name, + printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET]+7, hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq)); diff -u --recursive --new-file v2.3.34/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.3.34/linux/drivers/block/rd.c Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/rd.c Fri Dec 24 13:06:05 1999 @@ -185,6 +185,8 @@ { unsigned int minor; unsigned long offset, len; + struct buffer_head *rbh; + struct buffer_head *sbh; repeat: INIT_REQUEST; @@ -211,16 +213,66 @@ } /* - * If we're reading, fill the buffer with 0's. This is okay since - * we're using protected buffers which should never get freed... + * This has become somewhat more complicated with the addition of + * the page cache. The problem is that in some cases the furnished + * buffer is "real", i.e., part of the existing ramdisk, while in + * others it is "unreal", e.g., part of a page. In the first case + * not much needs to be done, while in the second, some kind of + * transfer is needed. + * + * The two cases are distinguished here by checking whether the + * real buffer is already in the buffer cache, and whether it is + * the same as the one supplied. * - * If we're writing, we protect the buffer. - */ - - if (CURRENT->cmd == READ) - memset(CURRENT->buffer, 0, len); - else - set_bit(BH_Protected, &CURRENT->bh->b_state); + * There are three cases with read/write to consider: + * + * 1. Supplied buffer matched one in the buffer cache: + * Read - Clear the buffer, as it wasn't already valid. + * Write - Mark the buffer as "Protected". + * + * 2. Supplied buffer mismatched one in the buffer cache: + * Read - Copy the data from the buffer cache entry. + * Write - Copy the data to the buffer cache entry. + * + * 3 No buffer cache entry existed: + * Read - Clear the supplied buffer, but do not create a real + * one. + * Write - Create a real buffer, copy the data to it, and mark + * it as "Protected". + * + * NOTE: There seems to be some schizophrenia here - the logic + * using "len" seems to assume arbitrary request lengths, while + * the "protect" logic assumes a single buffer cache entry. + * This seems to be left over from the ancient contiguous ramdisk + * logic. + */ + + sbh = CURRENT->bh; + rbh = get_hash_table(sbh->b_dev, sbh->b_blocknr, sbh->b_size); + if (sbh == rbh) { + if (CURRENT->cmd == READ) + memset(CURRENT->buffer, 1, len); + } else if (rbh) { + if (CURRENT->cmd == READ) + memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size); + else + memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size); + } else { /* !rbh */ + if (CURRENT->cmd == READ) + memset(sbh->b_data, 2, len); + else { + rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size); + if (rbh) + memcpy(rbh->b_data, CURRENT->buffer, + rbh->b_size); + else + BUG(); /* No buffer, what to do here? */ + } + } + if (rbh) { + set_bit(BH_Protected, &rbh->b_state); + brelse(rbh); + } end_request(1); goto repeat; diff -u --recursive --new-file v2.3.34/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c --- v2.3.34/linux/drivers/char/n_hdlc.c Thu Nov 11 20:11:34 1999 +++ linux/drivers/char/n_hdlc.c Tue Dec 21 10:13:00 1999 @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * ==FILEDATE 19990901== + * ==FILEDATE 19991217== * * This code is released under the GNU General Public License (GPL) * @@ -78,7 +78,7 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "1.11" +#define HDLC_VERSION "1.13" #include #include @@ -171,6 +171,7 @@ #if LINUX_VERSION_CODE < VERSION(2,1,0) #define __init typedef int spinlock_t; +#define spin_lock_init(a) #define spin_lock_irqsave(a,b) {save_flags((b));cli();} #define spin_unlock_irqrestore(a,b) {restore_flags((b));} #define spin_lock(a) @@ -659,8 +660,11 @@ /* wake up any blocked reads and perform async signalling */ wake_up_interruptible (&n_hdlc->read_wait); if (n_hdlc->tty->fasync != NULL) +#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); - +#endif } /* end of n_hdlc_tty_receive() */ /* n_hdlc_tty_read() @@ -1072,7 +1076,7 @@ void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list) { memset(list,0,sizeof(N_HDLC_BUF_LIST)); - + spin_lock_init(&list->spinlock); } /* end of n_hdlc_buf_list_init() */ /* n_hdlc_buf_put() diff -u --recursive --new-file v2.3.34/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.3.34/linux/drivers/char/pc_keyb.c Wed Dec 15 10:43:16 1999 +++ linux/drivers/char/pc_keyb.c Wed Dec 22 10:53:57 1999 @@ -746,6 +746,10 @@ int loops = 10; int retval = 0; + /* Check if the BIOS detected a device on the auxiliary port. */ + if (aux_device_present == 0xaa) + return 1; + spin_lock_irqsave(&kbd_controller_lock, flags); /* Put the value 0x5A in the output buffer using the "Write diff -u --recursive --new-file v2.3.34/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.3.34/linux/drivers/char/serial.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/char/serial.c Mon Dec 20 21:14:42 1999 @@ -74,6 +74,7 @@ #include #include +#include #undef SERIAL_PARANOIA_CHECK #define CONFIG_SERIAL_NOPAUSE_IO diff -u --recursive --new-file v2.3.34/linux/drivers/char/synclink.c linux/drivers/char/synclink.c --- v2.3.34/linux/drivers/char/synclink.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/char/synclink.c Tue Dec 21 10:13:06 1999 @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * ==FILEDATE 19991207== + * ==FILEDATE 19991217== * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -158,6 +158,7 @@ #define SERIAL_TYPE_NORMAL 1 #define SERIAL_TYPE_CALLOUT 2 typedef int spinlock_t; +#define spin_lock_init(a) #define spin_lock_irqsave(a,b) {save_flags((b));cli();} #define spin_unlock_irqrestore(a,b) {restore_flags((b));} #define spin_lock(a) @@ -925,7 +926,7 @@ #endif static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "1.15"; +static char *driver_version = "1.16"; static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -4456,7 +4457,7 @@ init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->status_event_wait_q); init_waitqueue_head(&info->event_wait_q); - + spin_lock_init(&info->irq_spinlock); memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); info->idle_mode = HDLC_TXIDLE_FLAGS; } diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c --- v2.3.34/linux/drivers/fc4/fc.c Wed May 12 08:41:15 1999 +++ linux/drivers/fc4/fc.c Mon Dec 20 22:06:42 1999 @@ -54,29 +54,29 @@ #endif #ifdef __sparc__ -static inline void *fc_dma_alloc(long size, char *name, dma_handle *dma) +static inline void *fc_dma_alloc(long size, dma_handle *dma, fc_channel *fc) { - return (void *) sparc_dvma_malloc (size, name, dma); + return sbus_alloc_consistant(fc->dev, size, dma); } -static inline dma_handle fc_sync_dma_entry(void *buf, int len, fc_channel *fc) +static inline dma_handle fc_sync_dma_entry(void *buf, long len, fc_channel *fc) { - return mmu_get_scsi_one (buf, len, fc->dev->my_bus); + return sbus_map_single(fc->dev, buf, len); } static inline void fc_sync_dma_exit(dma_handle dmh, long size, fc_channel *fc) { - mmu_release_scsi_one (dmh, size, fc->dev->my_bus); + sbus_unmap_single(fc->dev, dmh, size); } static inline void fc_sync_dma_entry_sg(struct scatterlist *list, int count, fc_channel *fc) { - mmu_get_scsi_sgl((struct mmu_sglist *)list, count - 1, fc->dev->my_bus); + sbus_map_sg(fc->dev, list, count); } static inline void fc_sync_dma_exit_sg(struct scatterlist *list, int count, fc_channel *fc) { - mmu_release_scsi_sgl ((struct mmu_sglist *)list, count - 1, fc->dev->my_bus); + sbus_unmap_sg(fc->dev, list, count); } #else #error Port this @@ -352,7 +352,7 @@ if (!unregister) { fc->scsi_cmd_pool = (fcp_cmd *) fc_dma_alloc (slots * (sizeof (fcp_cmd) + fc->rsp_size), - "FCP SCSI cmd & rsp queues", &fc->dma_scsi_cmd); + &fc->dma_scsi_cmd, fc); fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots); fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd); fc->scsi_bitmap_end = (slots + 63) & ~63; @@ -555,7 +555,7 @@ l->timer.function = fcp_login_timeout; l->timer.data = (unsigned long)l; atomic_set (&l->todo, count); - l->logi = kmalloc (count * 3 * sizeof(logi), GFP_DMA); + l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL); l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); if (!l->logi || !l->fcmds) { if (l->logi) kfree (l->logi); @@ -821,7 +821,7 @@ if (SCpnt->use_sg > 1) printk ("%s: SG for use_sg > 1 not handled yet\n", fc->name); fc_sync_dma_entry_sg (sg, SCpnt->use_sg, fc); fcmd->data = sg->dvma_address; - cmd->fcp_data_len = sg->length; + cmd->fcp_data_len = sg->dvma_length; } } memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -1103,7 +1103,7 @@ logi *l; int status; - l = (logi *)kmalloc(2 * sizeof(logi), GFP_DMA); + l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL); if (!l) return -ENOMEM; memset(l, 0, 2 * sizeof(logi)); l->code = LS_PLOGI; @@ -1138,7 +1138,7 @@ prli *p; int status; - p = (prli *)kmalloc(2 * sizeof(prli), GFP_DMA); + p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL); if (!p) return -ENOMEM; memset(p, 0, 2 * sizeof(prli)); p->code = LS_PRLI; diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/fcp_impl.h linux/drivers/fc4/fcp_impl.h --- v2.3.34/linux/drivers/fc4/fcp_impl.h Mon Mar 15 16:11:29 1999 +++ linux/drivers/fc4/fcp_impl.h Mon Dec 20 22:06:42 1999 @@ -84,7 +84,7 @@ common_svc_parm *common_svc; svc_parm *class_svcs; #ifdef __sparc__ - struct linux_sbus_device *dev; + struct sbus_dev *dev; #endif struct module *module; /* FCP SCSI stuff */ diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c --- v2.3.34/linux/drivers/fc4/soc.c Thu Aug 5 14:34:02 1999 +++ linux/drivers/fc4/soc.c Mon Dec 20 22:06:42 1999 @@ -66,16 +66,18 @@ static inline void soc_disable(struct soc *s) { - s->regs->imask = 0; s->regs->cmd = SOC_CMD_SOFT_RESET; + sbus_writel(0, s->regs + IMASK); + sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD); } static inline void soc_enable(struct soc *s) { SOD(("enable %08x\n", s->cfg)) - s->regs->sae = 0; s->regs->cfg = s->cfg; - s->regs->cmd = SOC_CMD_RSP_QALL; + sbus_writel(0, s->regs + SAE); + sbus_writel(s->cfg, s->regs + CFG); + sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD); SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK))); } static void soc_reset(fc_channel *fc) @@ -114,23 +116,29 @@ sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q]; if (sw_cq->pool == NULL) - sw_cq->pool = - (soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16))); + sw_cq->pool = (soc_req *) + (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address)); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - SOD (("soc_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) + SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last)) for (;;) { hwrsp = (soc_rsp *)sw_cq->pool + sw_cq->out; token = xram_get_32low ((xram_p)&hwrsp->shdr.token); status = xram_get_32low ((xram_p)&hwrsp->status); fc = (fc_channel *)(&s->port[(token >> 11) & 1]); - if (status == SOC_OK) - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL); - else { + if (status == SOC_OK) { + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + FC_STATUS_OK, NULL); + } else { xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr)); - /* We have intentionally defined FC_STATUS_* constants to match SOC_* constants, otherwise - we'd have to translate status */ - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr); + /* We have intentionally defined FC_STATUS_* constants + * to match SOC_* constants, otherwise we'd have to + * translate status. + */ + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + status, &fchdr); } if (++sw_cq->out > sw_cq->last) { @@ -142,9 +150,13 @@ sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)); + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) break; @@ -156,15 +168,18 @@ static void inline soc_request (struct soc *s, u32 cmd) { SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL)); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); - SOD(("Queues available %08x OUT %X %X\n", cmd, xram_get_8((xram_p)&s->req[0].hw_cq->out), xram_get_8((xram_p)&s->req[0].hw_cq->out))) + SOD(("Queues available %08x OUT %X %X\n", cmd, + xram_get_8((xram_p)&s->req[0].hw_cq->out), + xram_get_8((xram_p)&s->req[0].hw_cq->out))) if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else + } else { fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); + } if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) s->curr_port ^= 1; } @@ -180,8 +195,8 @@ sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q]; if (sw_cq->pool == NULL) - sw_cq->pool = - (soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16))); + sw_cq->pool = (soc_req *) + (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address))); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) @@ -193,27 +208,34 @@ flags = hwrsp->shdr.flags; count = xram_get_8 ((xram_p)&hwrsp->count); fc = (fc_channel *)&s->port[flags & SOC_PORT_B]; - SOD(("FC %08lx fcp_state_change %08lx\n", (long)fc, (long)fc->fcp_state_change)) + SOD(("FC %08lx fcp_state_change %08lx\n", + (long)fc, (long)fc->fcp_state_change)) if (count != 1) { /* Ugh, continuation entries */ u8 in; if (count != 2) { - printk("%s: Too many continuations entries %d\n", fc->name, count); + printk("%s: Too many continuations entries %d\n", + fc->name, count); goto update_out; } in = sw_cq->in; if (in < sw_cq->out) in += sw_cq->last + 1; if (in < sw_cq->out + 2) { - /* Ask the hardware about it if they haven't arrived yet */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)); + /* Ask the hardware if they haven't arrived yet. */ + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) /* Nothing came, let us wait */ return; } @@ -236,7 +258,8 @@ fcp_state_change(fc, FC_STATE_OFFLINE); break; default: - printk ("%s: Unknown STATUS no %d\n", fc->name, status); + printk ("%s: Unknown STATUS no %d\n", + fc->name, status); break; } break; @@ -248,29 +271,40 @@ if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt); - if (len < 4 || !hwrspc) - printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl); - else { - if (len > 60) len = 60; - xram_copy_from (buf, (xram_p)hwrspc, (len + 3) & ~3); + if (len < 4 || !hwrspc) { + printk ("%s: Invalid R_CTL %02x " + "continuation entries\n", + fc->name, r_ctl); + } else { + if (len > 60) + len = 60; + xram_copy_from (buf, (xram_p)hwrspc, + (len + 3) & ~3); if (*(u32 *)buf == LS_DISPLAY) { int i; for (i = 4; i < len; i++) - if (buf[i] == '\n') buf[i] = ' '; + if (buf[i] == '\n') + buf[i] = ' '; buf[len] = 0; - printk ("%s message: %s\n", fc->name, buf + 4); - } else - printk ("%s: Unknown LS_CMD %02x\n", fc->name, buf[0]); + printk ("%s message: %s\n", + fc->name, buf + 4); + } else { + printk ("%s: Unknown LS_CMD " + "%02x\n", fc->name, + buf[0]); + } } - } else - printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl); + } else { + printk ("%s: Unsolicited R_CTL %02x " + "not handled\n", fc->name, r_ctl); + } } break; default: printk ("%s: Unexpected flags %08x\n", fc->name, flags); break; - } + }; update_out: if (++sw_cq->out > sw_cq->last) { sw_cq->seqno++; @@ -288,9 +322,13 @@ sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)); + sbus_writel((sw_cq->out << 24) | + (SOC_CMD_RSP_QALL & + ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; + sbus_readl(s->regs + CMD); sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); } } @@ -304,8 +342,8 @@ register struct soc *s = (struct soc *)dev_id; spin_lock_irqsave(&io_request_lock, flags); - cmd = s->regs->cmd; - for (; (cmd = SOC_INTR (s, cmd)); cmd = s->regs->cmd) { + cmd = sbus_readl(s->regs + CMD); + for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s); if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s); if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd); @@ -338,11 +376,11 @@ sw_cq = s->req + qno; cq_next_in = (sw_cq->in + 1) & sw_cq->last; - if (cq_next_in == sw_cq->out - && cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) { + if (cq_next_in == sw_cq->out && + cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) { SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last)) SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno)); - SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask)); + SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); /* If queue is full, just say NO */ return -EBUSY; } @@ -363,7 +401,8 @@ request->shdr.bytecnt = i; request->data[2].base = fcmd->data; request->data[2].count = i; - request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? + request->type = + (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ; } else { request->shdr.segcnt = 2; @@ -374,7 +413,8 @@ } FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); + FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, + F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); fch->param = 0; @@ -388,7 +428,8 @@ request->type = SOC_CQTYPE_OFFLINE; FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); + FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, + F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); request->shdr.flags = port->flags; @@ -436,7 +477,9 @@ request->data[1].base = fcmd->rsp; request->data[0].count = fcmd->cmdlen; request->data[1].count = fcmd->rsplen; - request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE; + request->type = + (fcmd->class == FC_CLASS_IO_READ) ? + SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE; if (fcmd->data) { request->data[2].base = fcmd->data; request->data[2].count = fcmd->datalen; @@ -447,9 +490,9 @@ request->shdr.segcnt = 2; } break; - } + }; break; - } + }; request->count = 1; request->flags = 0; @@ -462,11 +505,14 @@ sw_cq->seqno++; } - SOD(("Putting %08x into cmd\n", SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno))) + SOD(("Putting %08x into cmd\n", + SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno))) - s->regs->cmd = SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno); - /* Read so that command is completed */ - s->regs->cmd; + sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno), + s->regs + CMD); + + /* Read so that command is completed. */ + sbus_readl(s->regs + CMD); return 0; } @@ -475,19 +521,19 @@ { #ifdef HAVE_SOC_UCODE xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode)); - xram_bzero (s->xram + (sizeof(soc_ucode)/sizeof(u16)), 32768 - sizeof(soc_ucode)); + xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode)); #endif } /* Check for what the best SBUS burst we can use happens * to be on this machine. */ -static inline void soc_init_bursts(struct soc *s, struct linux_sbus_device *sdev) +static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev) { int bsizes, bsizes_more; bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff); + bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); bsizes &= bsizes_more; if ((bsizes & 0x7f) == 0x7f) s->cfg = SOC_CFG_BURST_64; @@ -499,22 +545,24 @@ s->cfg = SOC_CFG_BURST_4; } -static inline void soc_init(struct linux_sbus_device *sdev, int no) +static inline void soc_init(struct sbus_dev *sdev, int no) { unsigned char tmp[60]; int propl; struct soc *s; - static unsigned version_printed = 0; + static int version_printed = 0; soc_hw_cq cq[8]; int size, i; int irq; s = kmalloc (sizeof (struct soc), GFP_KERNEL); - if (!s) return; + if (s == NULL) + return; memset (s, 0, sizeof(struct soc)); s->soc_no = no; - SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", (long)socs, (long)soc_intr, (long)soc_hw_enque)) + SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", + (long)socs, (long)soc_intr, (long)soc_hw_enque)) if (version_printed++ == 0) printk (version); #ifdef MODULE @@ -558,9 +606,9 @@ memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) s->port[0].fc.sid = 1; s->port[1].fc.sid = 17; @@ -570,26 +618,18 @@ s->port[0].fc.reset = soc_reset; s->port[1].fc.reset = soc_reset; - /* Setup the reg property for this device. */ - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev); - if (sdev->num_registers == 1) { /* Probably SunFire onboard SOC */ - s->xram = (xram_p) - sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, - sdev->reg_addrs [0].reg_size, "soc_xram", - sdev->reg_addrs [0].which_io, 0); - s->regs = (struct soc_regs *)((char *)s->xram + 0x10000); + s->xram = sbus_ioremap(&sdev->resource[0], 0, + 0x10000UL, "soc xram"); + s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL, + 0x10UL, "soc regs"); } else { /* Probably SOC sbus card */ - s->xram = (xram_p) - sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, - sdev->reg_addrs [1].reg_size, "soc_xram", - sdev->reg_addrs [1].which_io, 0); - s->regs = (struct soc_regs *) - sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, - sdev->reg_addrs [2].reg_size, "soc_regs", - sdev->reg_addrs [2].which_io, 0); + s->xram = sbus_ioremap(&sdev->resource[1], 0, + sdev->reg_addrs[1].reg_size, "soc xram"); + s->regs = sbus_ioremap(&sdev->resource[2], 0, + sdev->reg_addrs[2].reg_size, "soc regs"); } soc_init_bursts(s, sdev); @@ -628,13 +668,15 @@ memset (cq, 0, sizeof(cq)); size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req); - s->req[0].pool = (soc_req *) sparc_dvma_malloc (size, "SOC request queues", &cq[0].address); + s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma); + s->req[0].pool = s->req_cpu; + cq[0].address = s->req_dvma; s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE; s->req[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET); - s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq) / sizeof(u16)); + s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq)); s->rsp[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq) / sizeof(u16)); + s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq)); cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req)); cq[4].address = 1; @@ -677,13 +719,13 @@ int init_module(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; struct soc *s; int cards = 0; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { if(!strcmp(sdev->prom_name, "SUNW,soc")) { soc_init(sdev, cards); cards++; @@ -706,7 +748,7 @@ { struct soc *s; int irq; - struct linux_sbus_device *sdev; + struct sbus_dev *sdev; for_each_soc(s) { irq = s->port[0].fc.irq; @@ -716,13 +758,16 @@ fcp_release(&(s->port[0].fc), 2); sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) - sparc_free_io ((char *)s->xram, sdev->reg_addrs [0].reg_size); - else { - sparc_free_io ((char *)s->xram, sdev->reg_addrs [1].reg_size); - sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size); + if (sdev->num_registers == 1) { + sbus_iounmap(s->xram, 0x10000UL); + sbus_iounmap(s->regs, 0x10UL); + } else { + sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); + sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); } - /* FIXME: sparc_dvma_free() ??? */ + sbus_free_consistant(sdev, + (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req), + s->req_cpu, s->req_dvma); } } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/soc.h linux/drivers/fc4/soc.h --- v2.3.34/linux/drivers/fc4/soc.h Mon Mar 15 16:11:29 1999 +++ linux/drivers/fc4/soc.h Mon Dec 20 22:06:42 1999 @@ -10,14 +10,11 @@ #include "fcp.h" #include "fcp_impl.h" -/* Hardware structures and constants first {{{ */ - -struct soc_regs { - volatile u32 cfg; /* Config Register */ - volatile u32 sae; /* Slave Access Error Register */ - volatile u32 cmd; /* Command & Status Register */ - volatile u32 imask; /* Interrupt Mask Register */ -}; +/* Hardware register offsets and constants first {{{ */ +#define CFG 0x00UL /* Config Register */ +#define SAE 0x04UL /* Slave Access Error Register */ +#define CMD 0x08UL /* Command and Status Register */ +#define IMASK 0x0cUL /* Interrupt Mask Register */ /* Config Register */ #define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000 @@ -74,7 +71,9 @@ & s->imask) #define SOC_SETIMASK(s, i) \ - (s)->imask = (i); (s)->regs->imask = (i) +do { (s)->imask = (i); \ + sbus_writel((i), (s)->regs + IMASK); \ +} while(0) /* XRAM * @@ -82,56 +81,61 @@ * That's why here are the following inline functions... */ -typedef u16 *xram_p; +typedef unsigned long xram_p; /* Get 32bit number from XRAM */ static inline u32 xram_get_32 (xram_p x) { - return (((u32)*x) << 16) | (x[1]); + return ((sbus_readw(x + 0x00UL) << 16) | + (sbus_readw(x + 0x02UL))); } /* Like the above, but when we don't care about the high 16 bits */ static inline u32 xram_get_32low (xram_p x) { - return (u32)x[1]; + return (u32) sbus_readw(x + 0x02UL); } static inline u8 xram_get_8 (xram_p x) { - if (((long)x) & 1) { - x = (xram_p)((long)x - 1); - return (u8)*x; - } else - return (u8)(*x >> 8); + if (x & (xram_p)0x1) { + x = x - 1; + return (u8) sbus_readw(x); + } else { + return (u8) (sbus_readw(x) >> 8); + } } static inline void xram_copy_from (void *p, xram_p x, int len) { - for (len >>= 2; len > 0; len--, x += 2) { - *((u32 *)p)++ = (((u32)(*x)) << 16) | (x[1]); + for (len >>= 2; len > 0; len--, x += sizeof(u32)) { + u32 val; + + val = ((sbus_readw(x + 0x00UL) << 16) | + (sbus_readw(x + 0x02UL))); + *((u32 *)p)++ = val; } } static inline void xram_copy_to (xram_p x, void *p, int len) { - register u32 tmp; - for (len >>= 2; len > 0; len--, x += 2) { - tmp = *((u32 *)p)++; - *x = tmp >> 16; - x[1] = tmp; + for (len >>= 2; len > 0; len--, x += sizeof(u32)) { + u32 tmp = *((u32 *)p)++; + sbus_writew(tmp >> 16, x + 0x00UL); + sbus_writew(tmp, x + 0x02UL); } } static inline void xram_bzero (xram_p x, int len) { - for (len >>= 1; len > 0; len--) *x++ = 0; + for (len >>= 1; len > 0; len--, x += sizeof(u16)) + sbus_writew(0, x); } /* Circular Queue */ -/* These two are in sizeof(u16) units */ -#define SOC_CQ_REQ_OFFSET 0x100 -#define SOC_CQ_RSP_OFFSET 0x110 +#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16)) +#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16)) typedef struct { u32 address; @@ -260,7 +264,7 @@ soc_cq req[2]; /* Request CQs */ soc_cq rsp[2]; /* Response CQs */ int soc_no; - struct soc_regs *regs; + unsigned long regs; xram_p xram; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ @@ -268,6 +272,9 @@ char serv_params[80]; struct soc *next; int curr_port; /* Which port will have priority to fcp_queue_empty */ + + soc_req *req_cpu; + u32 req_dvma; }; /* }}} */ diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c --- v2.3.34/linux/drivers/fc4/socal.c Thu Aug 5 14:34:02 1999 +++ linux/drivers/fc4/socal.c Mon Dec 20 22:06:42 1999 @@ -61,23 +61,33 @@ #define for_each_socal(s) for (s = socals; s; s = s->next) struct socal *socals = NULL; -/* I don't think our VIS mem* routines will behave well - in IO... */ -static void socal_memcpy(void *d, void *s, int size) +static void socal_copy_from_xram(void *d, unsigned long xram, long size) { - u32 *dp = (u32 *)d, *sp = (u32 *)s; + u32 *dp = (u32 *) d; while (size) { - *dp++ = *sp++; + *dp++ = sbus_readl(xram); + xram += sizeof(u32); + size -= sizeof(u32); + } +} + +static void socal_copy_to_xram(unsigned long xram, void *s, long size) +{ + u32 *sp = (u32 *) s; + while (size) { + u32 val = *sp++; + sbus_writel(val, xram); + xram += sizeof(u32); size -= sizeof(u32); } } #ifdef HAVE_SOCAL_UCODE -static void socal_bzero(void *d, int size) +static void socal_bzero(unsigned long xram, int size) { - u32 *dp = (u32 *)d; while (size) { - *dp++ = 0; + sbus_writel(0, xram); + xram += sizeof(u32); size -= sizeof(u32); } } @@ -85,16 +95,18 @@ static inline void socal_disable(struct socal *s) { - s->regs->imask = 0; s->regs->cmd = SOCAL_CMD_SOFT_RESET; + sbus_writel(0, s->regs + IMASK); + sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD); } static inline void socal_enable(struct socal *s) { SOD(("enable %08x\n", s->cfg)) - s->regs->sae = 0; s->regs->cfg = s->cfg; - s->regs->cmd = SOCAL_CMD_RSP_QALL; + sbus_writel(0, s->regs + SAE); + sbus_writel(s->cfg, s->regs + CFG); + sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD); SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); } static void socal_reset(fc_channel *fc) @@ -121,7 +133,7 @@ socal_enable(s); } -static void inline socal_solicited (struct socal *s, int qno) +static void inline socal_solicited(struct socal *s, unsigned long qno) { fc_hdr fchdr; socal_rsp *hwrsp; @@ -138,8 +150,9 @@ (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe)); } /* Finally an improvement against old SOC :) */ - sw_cq->in = s->regs->respr[qno]; - SOD (("socal_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) + sw_cq->in = sbus_readb(s->regs + RESP + qno); + SOD (("socal_solicited, %d packets arrived\n", + (sw_cq->in - sw_cq->out) & sw_cq->last)) for (;;) { hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out)) @@ -147,16 +160,28 @@ #if defined(SOCALDEBUG) && 0 { u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u = (u32 *)s->xram; while (u < ((u32 *)s->regs)) { - if (u[0] == 0x00003000 || u[0] == 0x00003801) { - SOD(("Found at %04lx\n", (unsigned long)u - (unsigned long)s->xram)) - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + if (sbus_readl(&u[0]) == 0x00003000 || + sbus_readl(&u[0]) == 0x00003801) { + SOD(("Found at %04lx\n", + (unsigned long)u - (unsigned long)s->xram)) + SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + sbus_readl(&u[0]), sbus_readl(&u[1]), + sbus_readl(&u[2]), sbus_readl(&u[3]), + sbus_readl(&u[4]), sbus_readl(&u[5]), + sbus_readl(&u[6]), sbus_readl(&u[7]))) u += 8; - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + sbus_readl(&u[0]), sbus_readl(&u[1]), + sbus_readl(&u[2]), sbus_readl(&u[3]), + sbus_readl(&u[4]), sbus_readl(&u[5]), + sbus_readl(&u[6]), sbus_readl(&u[7]))) u -= 8; } u++; @@ -169,13 +194,18 @@ fc = (fc_channel *)(&s->port[(token >> 11) & 1]); SOD(("Solicited token %08x status %08x\n", token, status)) - if (status == SOCAL_OK) - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL); - else { - socal_memcpy(&fchdr, &hwrsp->fchdr, sizeof(fchdr)); - /* We have intentionally defined FC_STATUS_* constants to match SOCAL_* constants, otherwise - we'd have to translate status */ - fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr); + if (status == SOCAL_OK) { + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), + FC_STATUS_OK, NULL); + } else { + socal_copy_from_xram(&fchdr, &hwrsp->fchdr, sizeof(fchdr)); + /* We have intentionally defined FC_STATUS_* constants + * to match SOCAL_* constants, otherwise we'd have to + * translate status. + */ + fcp_receive_solicited(fc, token >> 12, + token & ((1 << 11) - 1), status, &fchdr); } if (++sw_cq->out > sw_cq->last) { @@ -184,13 +214,17 @@ } if (sw_cq->out == sw_cq->in) { - sw_cq->in = s->regs->respr[qno]; + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) break; } @@ -201,20 +235,21 @@ static void inline socal_request (struct socal *s, u32 cmd) { SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL)); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0])) if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else + } else { fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); + } if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) s->curr_port ^= 1; } -static void inline socal_unsolicited (struct socal *s, int qno) +static void inline socal_unsolicited (struct socal *s, unsigned long qno) { socal_rsp *hwrsp, *hwrspc; socal_cq *sw_cq; @@ -225,13 +260,14 @@ sw_cq = &s->rsp[qno]; if (sw_cq->pool == NULL) { - SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram)) + SOD(("address %08x xram %lx\n", sw_cq->hw_cq->address, s->xram)) sw_cq->pool = (socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe)); } - sw_cq->in = s->regs->respr[qno]; - SOD (("socal_unsolicited, %d packets arrived, in %d\n", (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in)) + sw_cq->in = sbus_readb(s->regs + RESP + qno); + SOD (("socal_unsolicited, %d packets arrived, in %d\n", + (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in)) while (sw_cq->in != sw_cq->out) { /* ...real work per entry here... */ hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; @@ -240,9 +276,11 @@ #if defined(SOCALDEBUG) && 0 { u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) + SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", + u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) } #endif @@ -257,20 +295,27 @@ u8 in; if (count != 2) { - printk("%s: Too many continuations entries %d\n", fc->name, count); + printk("%s: Too many continuations entries %d\n", + fc->name, count); goto update_out; } in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) { - /* Ask the hardware about it if they haven't arrived yet */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + /* Ask the hardware if they haven't arrived yet. */ + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; + if (in < sw_cq->out) + in += sw_cq->last + 1; if (in < sw_cq->out + 2) /* Nothing came, let us wait */ return; } @@ -297,9 +342,11 @@ fcp_state_change(fc, FC_STATE_OFFLINE); break; default: - printk ("%s: Unknown STATUS no %d\n", fc->name, status); + printk ("%s: Unknown STATUS no %d\n", + fc->name, status); break; - } + }; + break; case (SOCAL_UNSOLICITED|SOCAL_FC_HDR): { @@ -309,30 +356,40 @@ if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { len = hwrsp->shdr.bytecnt; - if (len < 4 || !hwrspc) - printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl); - else { - if (len > 60) len = 60; - socal_memcpy (buf, hwrspc, (len + 3) & ~3); + if (len < 4 || !hwrspc) { + printk ("%s: Invalid R_CTL %02x " + "continuation entries\n", + fc->name, r_ctl); + } else { + if (len > 60) + len = 60; + socal_copy_from_xram(buf, hwrspc, + (len + 3) & ~3); if (*(u32 *)buf == LS_DISPLAY) { int i; for (i = 4; i < len; i++) - if (buf[i] == '\n') buf[i] = ' '; + if (buf[i] == '\n') + buf[i] = ' '; buf[len] = 0; - printk ("%s message: %s\n", fc->name, buf + 4); + printk ("%s message: %s\n", + fc->name, buf + 4); } else { - printk ("%s: Unknown LS_CMD %08x\n", fc->name, *(u32 *)buf); + printk ("%s: Unknown LS_CMD " + "%08x\n", fc->name, + *(u32 *)buf); } } - } else - printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl); + } else { + printk ("%s: Unsolicited R_CTL %02x " + "not handled\n", fc->name, r_ctl); + } } break; default: printk ("%s: Unexpected flags %08x\n", fc->name, flags); break; - } + }; update_out: if (++sw_cq->out > sw_cq->last) { sw_cq->seqno++; @@ -347,13 +404,17 @@ } if (sw_cq->out == sw_cq->in) { - sw_cq->in = s->regs->respr[qno]; + sw_cq->in = sbus_readb(s->regs + RESP + qno); if (sw_cq->out == sw_cq->in) { /* Tell the hardware about it */ - s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno)); + sbus_writel((sw_cq->out << 24) | + (SOCAL_CMD_RSP_QALL & + ~(SOCAL_CMD_RSP_Q0 << qno)), + s->regs + CMD); + /* Read it, so that we're sure it has been updated */ - s->regs->cmd; - sw_cq->in = s->regs->respr[qno]; + sbus_readl(s->regs + CMD); + sw_cq->in = sbus_readb(s->regs + RESP + qno); } } } @@ -366,16 +427,21 @@ register struct socal *s = (struct socal *)dev_id; spin_lock_irqsave(&io_request_lock, flags); - cmd = s->regs->cmd; - for (; (cmd = SOCAL_INTR (s, cmd)); cmd = s->regs->cmd) { + cmd = sbus_readl(s->regs + CMD); + for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { #ifdef SOCALDEBUG static int cnt = 0; - if (cnt++ < 50) printk("soc_intr %08x\n", cmd); + if (cnt++ < 50) + printk("soc_intr %08x\n", cmd); #endif - if (cmd & SOCAL_CMD_RSP_Q2) socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q1) socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q0) socal_solicited (s, SOCAL_SOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_REQ_QALL) socal_request (s, cmd); + if (cmd & SOCAL_CMD_RSP_Q2) + socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q); + if (cmd & SOCAL_CMD_RSP_Q1) + socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q); + if (cmd & SOCAL_CMD_RSP_Q0) + socal_solicited (s, SOCAL_SOLICITED_RSP_Q); + if (cmd & SOCAL_CMD_REQ_QALL) + socal_request (s, cmd); } spin_unlock_irqrestore(&io_request_lock, flags); } @@ -386,7 +452,7 @@ { socal_port *port = (socal_port *)fc; struct socal *s = port->s; - int qno; + unsigned long qno; socal_cq *sw_cq; int cq_next_in; socal_req *request; @@ -405,12 +471,15 @@ sw_cq = s->req + qno; cq_next_in = (sw_cq->in + 1) & sw_cq->last; - if (cq_next_in == sw_cq->out - && cq_next_in == (sw_cq->out = s->regs->reqpr[qno])) { - SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last)) + if (cq_next_in == sw_cq->out && + cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) { + SOD(("%d IN %d OUT %d LAST %d\n", + qno, sw_cq->in, + sw_cq->out, sw_cq->last)) SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno)); - SOD(("imask %08x %08x\n", s->imask, s->regs->imask)); - /* If queue is full, just say NO */ + SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); + + /* If queue is full, just say NO. */ return -EBUSY; } @@ -540,9 +609,11 @@ SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno))) - s->regs->cmd = SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno); + sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno), + s->regs + CMD); + /* Read so that command is completed */ - s->regs->cmd; + sbus_readl(s->regs + CMD); return 0; } @@ -551,7 +622,7 @@ { #ifdef HAVE_SOCAL_UCODE SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram)) - socal_memcpy (s->xram, socal_ucode, sizeof(socal_ucode)); + socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode)); SOD(("Clearing the rest of memory\n")) socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode)); SOD(("Done\n")) @@ -561,13 +632,13 @@ /* Check for what the best SBUS burst we can use happens * to be on this machine. */ -static inline void socal_init_bursts(struct socal *s, struct linux_sbus_device *sdev) +static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev) { int bsizes, bsizes_more; u32 cfg; bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff); + bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); bsizes &= bsizes_more; #ifdef USE_64BIT_MODE #ifdef __sparc_v9__ @@ -598,7 +669,7 @@ s->cfg = cfg; } -static inline void socal_init(struct linux_sbus_device *sdev, int no) +static inline void socal_init(struct sbus_dev *sdev, int no) { unsigned char tmp[60]; int propl; @@ -613,7 +684,8 @@ memset (s, 0, sizeof(struct socal)); s->socal_no = no; - SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", (long)socals, (long)socal_intr, (long)socal_hw_enque)) + SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", + (long)socals, (long)socal_intr, (long)socal_hw_enque)) if (version_printed++ == 0) printk (version); #ifdef MODULE @@ -663,16 +735,17 @@ break; default: break; - } + }; + node = prom_getsibling(node); } memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) + *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo, + *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, + *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) s->port[0].fc.sid = 1; s->port[1].fc.sid = 17; @@ -682,29 +755,20 @@ s->port[0].fc.reset = socal_reset; s->port[1].fc.reset = socal_reset; - /* Setup the reg property for this device. */ - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev); - if (sdev->num_registers == 1) { - s->eeprom = (u8 *) - sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, - sdev->reg_addrs [0].reg_size, "socal_xram", - sdev->reg_addrs [0].which_io, 0); - if (sdev->reg_addrs [0].reg_size > 0x20000) - s->xram = s->eeprom + 0x10000; + s->eeprom = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, "socal xram"); + if (sdev->reg_addrs[0].reg_size > 0x20000) + s->xram = s->eeprom + 0x10000UL; else s->xram = s->eeprom; - s->regs = (struct socal_regs *)(s->xram + 0x10000); + s->regs = (s->xram + 0x10000UL); } else { /* E.g. starfire presents 3 registers for SOCAL */ - s->xram = (u8 *) - sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, - sdev->reg_addrs [1].reg_size, "socal_xram", - sdev->reg_addrs [1].which_io, 0); - s->regs = (struct socal_regs *) - sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, - sdev->reg_addrs [2].reg_size, "socal_regs", - sdev->reg_addrs [2].which_io, 0); + s->xram = sbus_ioremap(&sdev->resource[1], 0, + sdev->reg_addrs[1].reg_size, "socal xram"); + s->regs = sbus_ioremap(&sdev->resource[2], 0, + sdev->reg_addrs[2].reg_size, "socal regs"); } socal_init_bursts(s, sdev); @@ -742,8 +806,12 @@ /* Now setup xram circular queues */ memset (cq, 0, sizeof(cq)); - size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req); - s->req[0].pool = (socal_req *) sparc_dvma_malloc (size, "SOCAL request queues", &cq[0].address); + size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req); + s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma); + s->req[0].pool = s->req_cpu; + cq[0].address = s->req_dvma; s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE; s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE; s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE; @@ -780,12 +848,12 @@ s->rsp[1].seqno = 1; s->rsp[2].seqno = 1; - socal_memcpy (s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq)); + socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq)); SOD(("Setting up params\n")) /* Make our sw copy of SOCAL service parameters */ - socal_memcpy (s->serv_params, s->xram + 0x280, sizeof (s->serv_params)); + socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params)); s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params; s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); @@ -803,20 +871,21 @@ int init_module(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; struct socal *s; int cards = 0; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { if(!strcmp(sdev->prom_name, "SUNW,socal")) { socal_init(sdev, cards); cards++; } } } - if (!cards) return -EIO; + if (!cards) + return -EIO; for_each_socal(s) if (s->next) @@ -833,7 +902,7 @@ { struct socal *s; int irq; - struct linux_sbus_device *sdev; + struct sbus_dev *sdev; for_each_socal(s) { irq = s->port[0].fc.irq; @@ -843,13 +912,17 @@ fcp_release(&(s->port[0].fc), 2); sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) - sparc_free_io (s->eeprom, sdev->reg_addrs [0].reg_size); - else { - sparc_free_io (s->xram, sdev->reg_addrs [1].reg_size); - sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size); + if (sdev->num_registers == 1) { + sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size); + } else { + sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); + sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); } - /* FIXME: sparc_dvma_free() ??? */ + sbus_free_consistant(sdev, + (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req), + s->req_cpu, s->req_dvma); } } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/socal.h linux/drivers/fc4/socal.h --- v2.3.34/linux/drivers/fc4/socal.h Mon Mar 15 16:11:29 1999 +++ linux/drivers/fc4/socal.h Mon Dec 20 22:06:42 1999 @@ -10,24 +10,13 @@ #include "fcp.h" #include "fcp_impl.h" -/* Hardware structures and constants first {{{ */ - -union socal_rq_reg { - volatile u8 read[4]; - volatile u32 write; -}; -struct socal_regs { - volatile u32 cfg; /* Config Register */ - volatile u32 sae; /* Slave Access Error Register */ - volatile u32 cmd; /* Command & Status Register */ - volatile u32 imask; /* Interrupt Mask Register */ - union socal_rq_reg reqp; /* Request Queue Index Register */ - union socal_rq_reg resp; /* Response Queue Index Register */ -#define reqpr reqp.read -#define reqpw reqp.write -#define respr resp.read -#define respw resp.write -}; +/* Hardware register offsets and constants first {{{ */ +#define CFG 0x00UL +#define SAE 0x04UL +#define CMD 0x08UL +#define IMASK 0x0cUL +#define REQP 0x10UL +#define RESP 0x14UL /* Config Register */ #define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000 @@ -86,7 +75,9 @@ & s->imask) #define SOCAL_SETIMASK(s, i) \ - (s)->imask = (i); (s)->regs->imask = (i) +do { (s)->imask = (i); \ + sbus_writel((i), (s)->regs + IMASK); \ +} while (0) #define SOCAL_MAX_EXCHANGES 1024 @@ -303,15 +294,18 @@ socal_cq req[4]; /* Request CQs */ socal_cq rsp[4]; /* Response CQs */ int socal_no; - struct socal_regs *regs; - u8 *xram; - u8 *eeprom; + unsigned long regs; + unsigned long xram; + unsigned long eeprom; fc_wwn wwn; u32 imask; /* Our copy of regs->imask */ u32 cfg; /* Our copy of regs->cfg */ char serv_params[80]; struct socal *next; int curr_port; /* Which port will have priority to fcp_queue_empty */ + + socal_req * req_cpu; + u32 req_dvma; }; /* }}} */ diff -u --recursive --new-file v2.3.34/linux/drivers/misc/Config.in linux/drivers/misc/Config.in --- v2.3.34/linux/drivers/misc/Config.in Thu Nov 11 20:11:39 1999 +++ linux/drivers/misc/Config.in Sat Dec 25 15:04:56 1999 @@ -4,6 +4,4 @@ mainmenu_option next_comment comment 'Misc devices' -bool 'ACPI support' CONFIG_ACPI - endmenu diff -u --recursive --new-file v2.3.34/linux/drivers/misc/Makefile linux/drivers/misc/Makefile --- v2.3.34/linux/drivers/misc/Makefile Thu Nov 11 20:11:39 1999 +++ linux/drivers/misc/Makefile Sat Dec 25 15:05:05 1999 @@ -18,10 +18,6 @@ O_OBJS := OX_OBJS := -ifeq ($(CONFIG_ACPI),y) - OX_OBJS += acpi.o -endif - include $(TOPDIR)/Rules.make fastdep: diff -u --recursive --new-file v2.3.34/linux/drivers/misc/acpi.c linux/drivers/misc/acpi.c --- v2.3.34/linux/drivers/misc/acpi.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/misc/acpi.c Wed Dec 31 16:00:00 1969 @@ -1,1255 +0,0 @@ -/* - * acpi.c - Linux ACPI driver - * - * Copyright (C) 1999 Andrew Henroid - * - * 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 - */ - -/* - * See http://www.geocities.com/SiliconValley/Hardware/3165/ - * for the user-level ACPI stuff - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Defines for 2.2.x - */ -#ifndef __exit -#define __exit -#endif -#ifndef module_init -#define module_init(x) int init_module(void) {return x();} -#endif -#ifndef module_exit -#define module_exit(x) void cleanup_module(void) {x();} -#endif -#ifndef DECLARE_WAIT_QUEUE_HEAD -#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL -#endif - -/* - * Yes, it's unfortunate that we are relying on get_cmos_time - * because it is slow (> 1 sec.) and i386 only. It might be better - * to use some of the code from drivers/char/rtc.c in the near future - */ -extern unsigned long get_cmos_time(void); - -static int acpi_control_thread(void *context); -static int acpi_do_ulong(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len); -static int acpi_do_event_reg(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len); -static int acpi_do_event(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len); -static int acpi_do_sleep(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len); - -DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait); - -static struct ctl_table_header *acpi_sysctl = NULL; - -static struct acpi_facp *acpi_facp = NULL; -static int acpi_fake_facp = 0; -static struct acpi_facs *acpi_facs = NULL; -static unsigned long acpi_facp_addr = 0; -static unsigned long acpi_dsdt_addr = 0; - -// current system sleep state (S0 - S4) -static acpi_sstate_t acpi_sleep_state = ACPI_S0; -// time sleep began -static unsigned long acpi_sleep_start = 0; - -static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; -static volatile u32 acpi_pm1_status = 0; -static volatile u32 acpi_gpe_status = 0; -static volatile u32 acpi_gpe_level = 0; -static volatile acpi_sstate_t acpi_event_state = ACPI_S0; -static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); - -static spinlock_t acpi_devs_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(acpi_devs); - -/* Make it impossible to enter C2/C3 until after we've initialized */ -static unsigned long acpi_p_lvl2_lat = ACPI_INFINITE_LAT; -static unsigned long acpi_p_lvl3_lat = ACPI_INFINITE_LAT; - -static unsigned long acpi_p_blk = 0; - -static int acpi_p_lvl2_tested = 0; -static int acpi_p_lvl3_tested = 0; - -// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb -static unsigned long acpi_slp_typ[] = -{ - ACPI_SLP_TYP_DISABLED, /* S0 */ - ACPI_SLP_TYP_DISABLED, /* S1 */ - ACPI_SLP_TYP_DISABLED, /* S2 */ - ACPI_SLP_TYP_DISABLED, /* S3 */ - ACPI_SLP_TYP_DISABLED, /* S4 */ - ACPI_SLP_TYP_DISABLED /* S5 */ -}; - -static struct ctl_table acpi_table[] = -{ - {ACPI_FACP, "facp", - &acpi_facp_addr, sizeof(acpi_facp_addr), - 0400, NULL, &acpi_do_ulong}, - - {ACPI_DSDT, "dsdt", - &acpi_dsdt_addr, sizeof(acpi_dsdt_addr), - 0400, NULL, &acpi_do_ulong}, - - {ACPI_PM1_ENABLE, "pm1_enable", - NULL, 0, - 0600, NULL, &acpi_do_event_reg}, - - {ACPI_GPE_ENABLE, "gpe_enable", - NULL, 0, - 0600, NULL, &acpi_do_event_reg}, - - {ACPI_GPE_LEVEL, "gpe_level", - NULL, 0, - 0600, NULL, &acpi_do_event_reg}, - - {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, - - {ACPI_P_BLK, "p_blk", - &acpi_p_blk, sizeof(acpi_p_blk), - 0600, NULL, &acpi_do_ulong}, - - {ACPI_P_LVL2_LAT, "p_lvl2_lat", - &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_P_LVL3_LAT, "p_lvl3_lat", - &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat), - 0644, NULL, &acpi_do_ulong}, - - {ACPI_S0_SLP_TYP, "s0_slp_typ", - &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]), - 0600, NULL, &acpi_do_ulong}, - - {ACPI_S1_SLP_TYP, "s1_slp_typ", - &acpi_slp_typ[ACPI_S1], sizeof(acpi_slp_typ[ACPI_S1]), - 0600, NULL, &acpi_do_ulong}, - - {ACPI_S5_SLP_TYP, "s5_slp_typ", - &acpi_slp_typ[ACPI_S5], sizeof(acpi_slp_typ[ACPI_S5]), - 0600, NULL, &acpi_do_ulong}, - - {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep}, - - {0} -}; - -static struct ctl_table acpi_dir_table[] = -{ - {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table}, - {0} -}; - - -/* - * Get the value of the PM1 control register (SCI_EN, ...) - */ -static u32 acpi_read_pm1_control(struct acpi_facp *facp) -{ - u32 value = 0; - if (facp->pm1a_cnt) - value = inw(facp->pm1a_cnt); - if (facp->pm1b_cnt) - value |= inw(facp->pm1b_cnt); - return value; -} - -/* - * Set the value of the PM1 control register (BM_RLD, ...) - */ -static void acpi_write_pm1_control(struct acpi_facp *facp, u32 value) -{ - if (facp->pm1a_cnt) - outw(value, facp->pm1a_cnt); - if (facp->pm1b_cnt) - outw(value, facp->pm1b_cnt); -} - -/* - * Get the value of the fixed event status register - */ -static u32 acpi_read_pm1_status(struct acpi_facp *facp) -{ - u32 value = 0; - if (facp->pm1a_evt) - value = inw(facp->pm1a_evt); - if (facp->pm1b_evt) - value |= inw(facp->pm1b_evt); - return value; -} - -/* - * Set the value of the fixed event status register (clear events) - */ -static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value) -{ - if (facp->pm1a_evt) - outw(value, facp->pm1a_evt); - if (facp->pm1b_evt) - outw(value, facp->pm1b_evt); -} - -/* - * Get the value of the fixed event enable register - */ -static u32 acpi_read_pm1_enable(struct acpi_facp *facp) -{ - int offset = facp->pm1_evt_len >> 1; - u32 value = 0; - if (facp->pm1a_evt) - value = inw(facp->pm1a_evt + offset); - if (facp->pm1b_evt) - value |= inw(facp->pm1b_evt + offset); - return value; -} - -/* - * Set the value of the fixed event enable register (enable events) - */ -static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value) -{ - int offset = facp->pm1_evt_len >> 1; - if (facp->pm1a_evt) - outw(value, facp->pm1a_evt + offset); - if (facp->pm1b_evt) - outw(value, facp->pm1b_evt + offset); -} - -/* - * Get the value of the general-purpose event status register - */ -static u32 acpi_read_gpe_status(struct acpi_facp *facp) -{ - u32 value = 0; - int i, size; - - if (facp->gpe1) { - size = facp->gpe1_len >> 1; - for (i = size - 1; i >= 0; i--) - value = (value << 8) | inb(facp->gpe1 + i); - } - if (facp->gpe0) { - size = facp->gpe0_len >> 1; - for (i = size - 1; i >= 0; i--) - value = (value << 8) | inb(facp->gpe0 + i); - } - return value; -} - -/* - * Set the value of the general-purpose event status register (clear events) - */ -static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value) -{ - int i, size; - - if (facp->gpe0) { - size = facp->gpe0_len >> 1; - for (i = 0; i < size; i++) { - outb(value & 0xff, facp->gpe0 + i); - value >>= 8; - } - } - if (facp->gpe1) { - size = facp->gpe1_len >> 1; - for (i = 0; i < size; i++) { - outb(value & 0xff, facp->gpe1 + i); - value >>= 8; - } - } -} - -/* - * Get the value of the general-purpose event enable register - */ -static u32 acpi_read_gpe_enable(struct acpi_facp *facp) -{ - u32 value = 0; - int i, size, offset; - - offset = facp->gpe0_len >> 1; - if (facp->gpe1) { - size = facp->gpe1_len >> 1; - for (i = size - 1; i >= 0; i--) { - value = (value << 8) | inb(facp->gpe1 + offset + i); - } - } - if (facp->gpe0) { - size = facp->gpe0_len >> 1; - for (i = size - 1; i >= 0; i--) - value = (value << 8) | inb(facp->gpe0 + offset + i); - } - return value; -} - -/* - * Set the value of the general-purpose event enable register (enable events) - */ -static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value) -{ - int i, offset; - - offset = facp->gpe0_len >> 1; - if (facp->gpe0) { - for (i = 0; i < offset; i++) { - outb(value & 0xff, facp->gpe0 + offset + i); - value >>= 8; - } - } - if (facp->gpe1) { - offset = facp->gpe1_len >> 1; - for (i = 0; i < offset; i++) { - outb(value & 0xff, facp->gpe1 + offset + i); - value >>= 8; - } - } -} - -/* - * Map an ACPI table into virtual memory - */ -static struct acpi_table *__init acpi_map_table(u32 addr) -{ - struct acpi_table *table = NULL; - if (addr) { - // map table header to determine size - table = (struct acpi_table *) - ioremap((unsigned long) addr, - sizeof(struct acpi_table)); - if (table) { - unsigned long table_size = table->length; - iounmap(table); - // remap entire table - table = (struct acpi_table *) - ioremap((unsigned long) addr, table_size); - } - - if (!table) { - /* ioremap is a pain, it returns NULL if the - * table starts within mapped physical memory. - * Hopefully, no table straddles a mapped/unmapped - * physical memory boundary, ugh - */ - table = (struct acpi_table*) phys_to_virt(addr); - } - } - return table; -} - -/* - * Unmap an ACPI table from virtual memory - */ -static void acpi_unmap_table(struct acpi_table *table) -{ - // iounmap ignores addresses within physical memory - if (table) - iounmap(table); -} - -/* - * Locate and map ACPI tables - */ -static int __init acpi_find_tables(void) -{ - struct acpi_rsdp *rsdp; - struct acpi_table *rsdt; - u32 *rsdt_entry; - int rsdt_entry_count; - unsigned long i; - - // search BIOS memory for RSDP - for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) { - rsdp = (struct acpi_rsdp *) phys_to_virt(i); - if (rsdp->signature[0] == ACPI_RSDP1_SIG - && rsdp->signature[1] == ACPI_RSDP2_SIG) { - char oem[7]; - int j; - - // strip trailing space and print OEM identifier - memcpy(oem, rsdp->oem, 6); - oem[6] = '\0'; - for (j = 5; - j > 0 && (oem[j] == '\0' || oem[j] == ' '); - j--) { - oem[j] = '\0'; - } - printk(KERN_INFO "ACPI: \"%s\" found at 0x%p\n", - oem, (void *) i); - - break; - } - } - if (i >= ACPI_BIOS_ROM_END) - return -ENODEV; - - // fetch RSDT from RSDP - rsdt = acpi_map_table(rsdp->rsdt); - if (!rsdt) { - printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n", - (void*) rsdp->rsdt); - return -ENODEV; - } - else if (rsdt->signature != ACPI_RSDT_SIG) { - printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n", - (void*) rsdp->rsdt, (unsigned) rsdt->signature); - acpi_unmap_table(rsdt); - return -ENODEV; - } - // search RSDT for FACP - acpi_facp = NULL; - rsdt_entry = (u32 *) (rsdt + 1); - rsdt_entry_count = (int) ((rsdt->length - sizeof(*rsdt)) >> 2); - while (rsdt_entry_count) { - struct acpi_table *dt = acpi_map_table(*rsdt_entry); - if (dt && dt->signature == ACPI_FACP_SIG) { - acpi_facp = (struct acpi_facp*) dt; - acpi_facp_addr = *rsdt_entry; - acpi_dsdt_addr = acpi_facp->dsdt; - - // map FACS if it exists - if (acpi_facp->facs) { - dt = acpi_map_table(acpi_facp->facs); - if (dt && dt->signature == ACPI_FACS_SIG) { - acpi_facs = (struct acpi_facs*) dt; - } - else { - acpi_unmap_table(dt); - } - } - } - else { - acpi_unmap_table(dt); - } - rsdt_entry++; - rsdt_entry_count--; - } - - acpi_unmap_table(rsdt); - - if (!acpi_facp) { - printk(KERN_ERR "ACPI: missing FACP\n"); - return -ENODEV; - } - return 0; -} - -/* - * Unmap or destroy ACPI tables - */ -static void acpi_destroy_tables(void) -{ - if (!acpi_fake_facp) - acpi_unmap_table((struct acpi_table*) acpi_facp); - else - kfree(acpi_facp); - acpi_unmap_table((struct acpi_table*) acpi_facs); -} - -/* - * Locate PIIX4 device and create a fake FACP - */ -static int __init acpi_find_piix4(void) -{ - struct pci_dev *dev; - u32 base; - u16 cmd; - u8 pmregmisc; - - dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, - NULL); - if (!dev) - return -ENODEV; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_IO)) - return -ENODEV; - - pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc); - if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) - return -ENODEV; - - pci_read_config_dword(dev, 0x40, &base); - if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) - return -ENODEV; - - base &= PCI_BASE_ADDRESS_IO_MASK; - if (!base) - return -ENODEV; - - printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base); - - acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL); - if (!acpi_facp) - return -ENOMEM; - - acpi_fake_facp = 1; - memset(acpi_facp, 0, sizeof(struct acpi_facp)); - acpi_facp->int_model = ACPI_PIIX4_INT_MODEL; - acpi_facp->sci_int = ACPI_PIIX4_SCI_INT; - acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD; - acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE; - acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE; - acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ; - acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT; - acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT; - acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT; - acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR; - acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0; - acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN; - acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN; - acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN; - acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN; - acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN; - acpi_facp->p_lvl2_lat = (__u16) ACPI_INFINITE_LAT; - acpi_facp->p_lvl3_lat = (__u16) ACPI_INFINITE_LAT; - - acpi_facp_addr = virt_to_phys(acpi_facp); - acpi_dsdt_addr = 0; - - acpi_p_blk = base + ACPI_PIIX4_P_BLK; - - return 0; -} - -/* - * Handle an ACPI SCI (fixed or general purpose event) - */ -static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - u32 pm1_status, gpe_status, gpe_level, gpe_edge; - unsigned long flags; - - // detect and clear fixed events - pm1_status = (acpi_read_pm1_status(acpi_facp) - & acpi_read_pm1_enable(acpi_facp)); - acpi_write_pm1_status(acpi_facp, pm1_status); - - // detect and handle general-purpose events - gpe_status = (acpi_read_gpe_status(acpi_facp) - & acpi_read_gpe_enable(acpi_facp)); - gpe_level = gpe_status & acpi_gpe_level; - if (gpe_level) { - // disable level-triggered events (re-enabled after handling) - acpi_write_gpe_enable( - acpi_facp, - acpi_read_gpe_enable(acpi_facp) & ~gpe_level); - } - gpe_edge = gpe_status & ~gpe_level; - if (gpe_edge) { - // clear edge-triggered events - while (acpi_read_gpe_status(acpi_facp) & gpe_edge) - acpi_write_gpe_status(acpi_facp, gpe_edge); - } - - // notify process waiting on /dev/acpi - spin_lock_irqsave(&acpi_event_lock, flags); - acpi_pm1_status |= pm1_status; - acpi_gpe_status |= gpe_status; - spin_unlock_irqrestore(&acpi_event_lock, flags); - acpi_event_state = acpi_sleep_state; - wake_up_interruptible(&acpi_event_wait); -} - -/* - * Is ACPI enabled or not? - */ -static inline int acpi_is_enabled(struct acpi_facp *facp) -{ - return ((acpi_read_pm1_control(facp) & ACPI_SCI_EN) ? 1:0); -} - -/* - * Enable SCI - */ -static int acpi_enable(struct acpi_facp *facp) -{ - if (facp->smi_cmd) - outb(facp->acpi_enable, facp->smi_cmd); - return (acpi_is_enabled(facp) ? 0:-1); -} - -/* - * Disable SCI - */ -static int acpi_disable(struct acpi_facp *facp) -{ - // disable and clear any pending events - acpi_write_gpe_enable(facp, 0); - while (acpi_read_gpe_status(facp)) - acpi_write_gpe_status(facp, acpi_read_gpe_status(facp)); - acpi_write_pm1_enable(facp, 0); - acpi_write_pm1_status(facp, acpi_read_pm1_status(facp)); - - /* writing acpi_disable to smi_cmd would be appropriate - * here but this causes a nasty crash on many systems - */ - - return 0; -} - -/* - * Idle loop (uniprocessor only) - */ -static void acpi_idle_handler(void) -{ - static int sleep_level = 1; - u32 pm1_cnt, timer, pm2_cnt, bm_active; - unsigned long time, usec; - - // return to C0 on bus master request (necessary for C3 only) - pm1_cnt = acpi_read_pm1_control(acpi_facp); - if (sleep_level == 3) { - if (!(pm1_cnt & ACPI_BM_RLD)) { - pm1_cnt |= ACPI_BM_RLD; - acpi_write_pm1_control(acpi_facp, pm1_cnt); - } - } - else { - if (pm1_cnt & ACPI_BM_RLD) { - pm1_cnt &= ~ACPI_BM_RLD; - acpi_write_pm1_control(acpi_facp, pm1_cnt); - } - } - - // clear bus master activity flag - acpi_write_pm1_status(acpi_facp, ACPI_BM); - - // get current time (fallback to CPU cycles if no PM timer) - timer = acpi_facp->pm_tmr; - if (timer) - time = inl(timer); - else - time = get_cycles(); - - // sleep - switch (sleep_level) { - case 1: - __asm__ __volatile__("sti ; hlt": : :"memory"); - break; - case 2: - inb(acpi_p_blk + ACPI_P_LVL2); - break; - case 3: - pm2_cnt = acpi_facp->pm2_cnt; - if (pm2_cnt) { - /* Disable PCI arbitration while sleeping, - to avoid DMA corruption? */ - cli(); - outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt); - inb(acpi_p_blk + ACPI_P_LVL3); - outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt); - sti(); - } - else { - inb(acpi_p_blk + ACPI_P_LVL3); - } - break; - } - - // calculate time spent sleeping (fallback to CPU cycles) - if (timer) - time = (inl(timer) - time) & ACPI_TMR_MASK; - else - time = ACPI_CPU_TO_TMR_TICKS(get_cycles() - time); - - // check for bus master activity - bm_active = (acpi_read_pm1_status(acpi_facp) & ACPI_BM); - - // record working C2/C3 - if (sleep_level == 2 && !acpi_p_lvl2_tested) { - acpi_p_lvl2_tested = 1; - printk(KERN_INFO "ACPI: C2 works\n"); - } - else if (sleep_level == 3 && !acpi_p_lvl3_tested) { - acpi_p_lvl3_tested = 1; - printk(KERN_INFO "ACPI: C3 works\n"); - } - - // pick next C-state based on time spent sleeping, - // C-state latencies, and bus master activity - sleep_level = 1; - if (acpi_p_blk) { - usec = ACPI_TMR_TICKS_TO_uS(time); - if (usec > acpi_p_lvl3_lat && !bm_active) - sleep_level = 3; - else if (usec > acpi_p_lvl2_lat) - sleep_level = 2; - } -} - -/* - * Put all devices into specified D-state - */ -static int acpi_enter_dx(acpi_dstate_t state) -{ - int status = 0; - struct list_head *i = acpi_devs.next; - - while (i != &acpi_devs) { - struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry); - if (dev->state != state) { - int dev_status = 0; - if (dev->info.transition) - dev_status = dev->info.transition(dev, state); - if (!dev_status) { - // put hardware into D-state - dev->state = state; - } - if (dev_status) - status = dev_status; - } - - i = i->next; - } - - return status; -} - -/* - * Update system time from real-time clock - */ -static void acpi_update_clock(void) -{ - if (acpi_sleep_start) { - unsigned long delta; - struct timeval tv; - - delta = get_cmos_time() - acpi_sleep_start; - do_gettimeofday(&tv); - tv.tv_sec += delta; - do_settimeofday(&tv); - - acpi_sleep_start = 0; - } -} - - -/* - * Enter system sleep state - */ -static void acpi_enter_sx(acpi_sstate_t state) -{ - unsigned long slp_typ = acpi_slp_typ[(int) state]; - if (slp_typ != ACPI_SLP_TYP_DISABLED) { - u16 typa, typb, value; - - // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb - typa = (slp_typ >> 8) & 0xff; - typb = slp_typ & 0xff; - - typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); - typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK); - - if (state != ACPI_S0) { - acpi_sleep_start = get_cmos_time(); - acpi_enter_dx(ACPI_D3); - acpi_sleep_state = state; - } - - // clear wake status - acpi_write_pm1_status(acpi_facp, ACPI_WAK); - - // set SLP_TYPa/b and SLP_EN - if (acpi_facp->pm1a_cnt) { - value = inw(acpi_facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK; - outw(value | typa | ACPI_SLP_EN, acpi_facp->pm1a_cnt); - } - if (acpi_facp->pm1b_cnt) { - value = inw(acpi_facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK; - outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt); - } - - if (state == ACPI_S0) { - acpi_sleep_state = state; - acpi_enter_dx(ACPI_D0); - acpi_sleep_start = 0; - } - else if (state == ACPI_S1) { - // wait until S1 is entered - while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ; - // finished sleeping, update system time - acpi_update_clock(); - } - } -} - -/* - * Enter soft-off (S5) - */ -static void acpi_power_off_handler(void) -{ - acpi_enter_sx(ACPI_S5); -} - -/* - * Claim ACPI I/O ports - */ -static int acpi_claim_ioports(struct acpi_facp *facp) -{ - // we don't get a guarantee of contiguity for any of the ACPI registers - if (facp->pm1a_evt) - request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi"); - if (facp->pm1b_evt) - request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi"); - if (facp->pm1a_cnt) - request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi"); - if (facp->pm1b_cnt) - request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi"); - if (facp->pm_tmr) - request_region(facp->pm_tmr, facp->pm_tm_len, "acpi"); - if (facp->gpe0) - request_region(facp->gpe0, facp->gpe0_len, "acpi"); - if (facp->gpe1) - request_region(facp->gpe1, facp->gpe1_len, "acpi"); - - return 0; -} - -/* - * Free ACPI I/O ports - */ -static int acpi_release_ioports(struct acpi_facp *facp) -{ - // we don't get a guarantee of contiguity for any of the ACPI registers - if (facp->pm1a_evt) - release_region(facp->pm1a_evt, facp->pm1_evt_len); - if (facp->pm1b_evt) - release_region(facp->pm1b_evt, facp->pm1_evt_len); - if (facp->pm1a_cnt) - release_region(facp->pm1a_cnt, facp->pm1_cnt_len); - if (facp->pm1b_cnt) - release_region(facp->pm1b_cnt, facp->pm1_cnt_len); - if (facp->pm_tmr) - release_region(facp->pm_tmr, facp->pm_tm_len); - if (facp->gpe0) - release_region(facp->gpe0, facp->gpe0_len); - if (facp->gpe1) - release_region(facp->gpe1, facp->gpe1_len); - - return 0; -} - -/* - * Examine/modify value - */ -static int acpi_do_ulong(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len) -{ - char str[2 * sizeof(unsigned long) + 4], *strend; - unsigned long val; - int size; - - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - - val = *(unsigned long*) ctl->data; - size = sprintf(str, "0x%08lx\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - } - else { - size = sizeof(str) - 1; - if (size > *len) - size = *len; - copy_from_user(str, buffer, size); - str[size] = '\0'; - val = simple_strtoul(str, &strend, 0); - if (strend == str) - return -EINVAL; - *(unsigned long*) ctl->data = val; - } - - file->f_pos += *len; - return 0; -} - -/* - * Examine/modify event register - */ -static int acpi_do_event_reg(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len) -{ - char str[2 * sizeof(u32) + 4], *strend; - u32 val, enabling; - int size; - - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - - val = 0; - switch (ctl->ctl_name) { - case ACPI_PM1_ENABLE: - val = acpi_read_pm1_enable(acpi_facp); - break; - case ACPI_GPE_ENABLE: - val = acpi_read_gpe_enable(acpi_facp); - break; - case ACPI_GPE_LEVEL: - val = acpi_gpe_level; - break; - } - - size = sprintf(str, "0x%08x\n", val); - if (*len >= size) { - copy_to_user(buffer, str, size); - *len = size; - } - else - *len = 0; - } - else - { - // fetch user value - size = sizeof(str) - 1; - if (size > *len) - size = *len; - copy_from_user(str, buffer, size); - str[size] = '\0'; - val = (u32) simple_strtoul(str, &strend, 0); - if (strend == str) - return -EINVAL; - - // store value in register - switch (ctl->ctl_name) { - case ACPI_PM1_ENABLE: - // clear previously disabled events - enabling = (val - & ~acpi_read_pm1_enable(acpi_facp)); - acpi_write_pm1_status(acpi_facp, enabling); - - if (val) { - // enable ACPI unless it is already - if (!acpi_is_enabled(acpi_facp)) - acpi_enable(acpi_facp); - } - else if (!acpi_read_gpe_enable(acpi_facp)) { - // disable ACPI unless it is already - if (acpi_is_enabled(acpi_facp)) - acpi_disable(acpi_facp); - } - - acpi_write_pm1_enable(acpi_facp, val); - break; - case ACPI_GPE_ENABLE: - // clear previously disabled events - enabling = (val - & ~acpi_read_gpe_enable(acpi_facp)); - while (acpi_read_gpe_status(acpi_facp) & enabling) - acpi_write_gpe_status(acpi_facp, enabling); - - if (val) { - // enable ACPI unless it is already - if (!acpi_is_enabled(acpi_facp)) - acpi_enable(acpi_facp); - } - else if (!acpi_read_pm1_enable(acpi_facp)) { - // disable ACPI unless it is already - if (acpi_is_enabled(acpi_facp)) - acpi_disable(acpi_facp); - } - - acpi_write_gpe_enable(acpi_facp, val); - break; - case ACPI_GPE_LEVEL: - acpi_gpe_level = val; - break; - } - } - - file->f_pos += *len; - return 0; -} - -/* - * Wait for next event - */ -static int acpi_do_event(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len) -{ - u32 pm1_status = 0, gpe_status = 0; - acpi_sstate_t event_state = 0; - char str[27]; - int size; - - if (write) - return -EPERM; - if (*len < sizeof(str)) { - *len = 0; - return 0; - } - - for (;;) { - unsigned long flags; - - // we need an atomic exchange here - spin_lock_irqsave(&acpi_event_lock, flags); - pm1_status = acpi_pm1_status; - acpi_pm1_status = 0; - gpe_status = acpi_gpe_status; - acpi_gpe_status = 0; - spin_unlock_irqrestore(&acpi_event_lock, flags); - event_state = acpi_event_state; - - if (pm1_status || gpe_status) - break; - - // wait for an event to arrive - interruptible_sleep_on(&acpi_event_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - size = sprintf(str, "0x%08x 0x%08x 0x%01x\n", - pm1_status, - gpe_status, - event_state); - copy_to_user(buffer, str, size); - *len = size; - file->f_pos += size; - - return 0; -} - -/* - * Enter system sleep state - */ -static int acpi_do_sleep(ctl_table *ctl, - int write, - struct file *file, - void *buffer, - size_t *len) -{ - if (!write) { - if (file->f_pos) { - *len = 0; - return 0; - } - } - else - { - acpi_enter_sx(ACPI_S1); - acpi_enter_sx(ACPI_S0); - } - file->f_pos += *len; - return 0; -} - -/* - * Initialize and enable ACPI - */ -static int __init acpi_init(void) -{ - int pid; - - if (acpi_find_tables() && acpi_find_piix4()) { - // no ACPI tables and not PIIX4 - return -ENODEV; - } - - if (acpi_facp->p_lvl2_lat - && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) { - acpi_p_lvl2_lat = acpi_facp->p_lvl2_lat; - } - if (acpi_facp->p_lvl3_lat - && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) { - acpi_p_lvl3_lat = acpi_facp->p_lvl3_lat; - } - - if (acpi_facp->sci_int - && request_irq(acpi_facp->sci_int, - acpi_irq, - SA_INTERRUPT | SA_SHIRQ, - "acpi", - acpi_facp)) { - printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", - acpi_facp->sci_int); - acpi_destroy_tables(); - return -ENODEV; - } - - acpi_claim_ioports(acpi_facp); - acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); - - pid = kernel_thread(acpi_control_thread, - NULL, - CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - - acpi_power_off = acpi_power_off_handler; - - /* - * Set up the ACPI idle function. Note that we can't really - * do this with multiple CPU's, we'd need a per-CPU ACPI - * device.. - */ -#ifdef __SMP__ - if (smp_num_cpus > 1) - return 0; -#endif - - acpi_idle = acpi_idle_handler; - - return 0; -} - -/* - * Disable and deinitialize ACPI - */ -static void __exit acpi_exit(void) -{ - acpi_idle = NULL; - acpi_power_off = NULL; - - unregister_sysctl_table(acpi_sysctl); - acpi_disable(acpi_facp); - acpi_release_ioports(acpi_facp); - - if (acpi_facp->sci_int) - free_irq(acpi_facp->sci_int, acpi_facp); - - acpi_destroy_tables(); -} - -/* - * Register a device with the ACPI subsystem - */ -struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr) -{ - struct acpi_dev *dev = NULL; - if (info) { - dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL); - if (dev) { - unsigned long flags; - - memset(dev, 0, sizeof(*dev)); - memcpy(&dev->info, info, sizeof(dev->info)); - dev->adr = adr; - - spin_lock_irqsave(&acpi_devs_lock, flags); - list_add(&dev->entry, &acpi_devs); - spin_unlock_irqrestore(&acpi_devs_lock, flags); - } - } - return dev; -} - -/* - * Unregister a device with ACPI - */ -void acpi_unregister(struct acpi_dev *dev) -{ - if (dev) { - unsigned long flags; - - spin_lock_irqsave(&acpi_devs_lock, flags); - list_del(&dev->entry); - spin_unlock_irqrestore(&acpi_devs_lock, flags); - - kfree(dev); - } -} - -/* - * Wake up a device - */ -void acpi_wakeup(struct acpi_dev *dev) -{ - // run _PS0 or tell parent bus to wake device up -} - -/* - * Manage idle devices - */ -static int acpi_control_thread(void *context) -{ - exit_mm(current); - exit_files(current); - strcpy(current->comm, "acpi"); - - for(;;) { - interruptible_sleep_on(&acpi_control_wait); - if (signal_pending(current)) - break; - - // find all idle devices and set idle timer - } - - return 0; -} - -__initcall(acpi_init); - -/* - * Module visible symbols - */ -EXPORT_SYMBOL(acpi_control_wait); -EXPORT_SYMBOL(acpi_register); -EXPORT_SYMBOL(acpi_unregister); -EXPORT_SYMBOL(acpi_wakeup); diff -u --recursive --new-file v2.3.34/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v2.3.34/linux/drivers/net/3c503.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/net/3c503.c Tue Dec 21 10:17:31 1999 @@ -103,7 +103,7 @@ for (addr = addrs; *addr; addr++) { int i; - unsigned int base_bits = readb(*addr); + unsigned int base_bits = isa_readb(*addr); /* Find first set bit. */ for(i = 7; i >= 0; i--, base_bits >>= 1) if (base_bits & 0x1) @@ -251,18 +251,18 @@ { /* Check the card's memory. */ unsigned long mem_base = dev->mem_start; unsigned int test_val = 0xbbadf00d; - writel(0xba5eba5e, mem_base); + isa_writel(0xba5eba5e, mem_base); for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) { - writel(test_val, mem_base + i); - if (readl(mem_base) != 0xba5eba5e - || readl(mem_base + i) != test_val) { + isa_writel(test_val, mem_base + i); + if (isa_readl(mem_base) != 0xba5eba5e + || isa_readl(mem_base + i) != test_val) { printk("3c503: memory failure or memory address conflict.\n"); dev->mem_start = 0; ei_status.name = "3c503-PIO"; break; } test_val += 0x55555555; - writel(0, mem_base + i); + isa_writel(0, mem_base + i); } } #endif /* EL2MEMTEST */ diff -u --recursive --new-file v2.3.34/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.3.34/linux/drivers/net/Makefile Mon Dec 20 18:48:21 1999 +++ linux/drivers/net/Makefile Mon Dec 20 22:05:10 1999 @@ -178,7 +178,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o obj-$(CONFIG_SUNQE) += sunqe.o obj-$(CONFIG_SUNBMAC) += sunbmac.o -obj-$(CONFIG_SUNBMAC) += sunbmac.o obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o obj-$(CONFIG_AT1700) += at1700.o obj-$(CONFIG_FMV18X) += fmv18x.o diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in --- v2.3.34/linux/drivers/net/irda/Config.in Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/irda/Config.in Tue Dec 21 10:17:31 1999 @@ -20,6 +20,8 @@ dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA dep_tristate ' Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA + dep_tristate ' Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA + fi endmenu diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile --- v2.3.34/linux/drivers/net/irda/Makefile Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/Makefile Tue Dec 21 10:17:31 1999 @@ -52,6 +52,22 @@ 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 @@ -107,6 +123,14 @@ else ifeq ($(CONFIG_AIRPORT_DONGLE),m) M_OBJS += airport.o + endif +endif + +ifeq ($(CONFIG_OLD_BELKIN_DONGLE),y) +L_OBJS += old_belkin.o +else + ifeq ($(CONFIG_OLD_BELKIN_DONGLE),m) + M_OBJS += old_belkin.o endif endif diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c --- v2.3.34/linux/drivers/net/irda/actisys.c Wed Oct 27 16:34:12 1999 +++ linux/drivers/net/irda/actisys.c Tue Dec 21 10:17:31 1999 @@ -1,16 +1,18 @@ /********************************************************************* * * Filename: actisys.c - * Version: 0.8 + * Version: 1.0 * Description: Implementation for the ACTiSYS IR-220L and IR-220L+ * dongles - * Status: Experimental. - * Author: Dag Brattli + * Status: Beta. + * Authors: Dag Brattli (initially) + * Jean Tourrilhes (new version) * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Mon Oct 18 23:37:06 1999 + * Modified at: Fri Dec 17 09:16:09 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. + * Copyright (c) 1999 Jean Tourrilhes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,6 +25,16 @@ * ********************************************************************/ +/* + * Changelog + * + * 0.8 -> 0.9999 - Jean + * o New initialisation procedure : much safer and correct + * o New procedure the change speed : much faster and simpler + * o Other cleanups & comments + * Thanks to Lichen Wang @ Actisys for his excellent help... + */ + #include #include #include @@ -33,13 +45,25 @@ #include #include +/* + * Define the timing of the pulses we send to the dongle (to reset it, and + * to toggle speeds). Basically, the limit here is the propagation speed of + * the signals through the serial port, the dongle being much faster. Any + * serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can + * go through cleanly . If you are on the wild side, you can try to lower + * this value (Actisys recommended me 2 us, and 0 us work for me on a P233!) + */ +#define MIN_DELAY 10 /* 10 us to be on the conservative side */ + static int actisys_change_speed(struct irda_task *task); static int actisys_reset(struct irda_task *task); static void actisys_open(dongle_t *self, struct qos_info *qos); static void actisys_close(dongle_t *self); -/* These are the baudrates supported */ +/* These are the baudrates supported, in the order available */ +/* Note : the 220L doesn't support 38400, but we will fix that below */ static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 }; +#define MAX_SPEEDS 5 static struct dongle_reg dongle = { Q_NULL, @@ -59,13 +83,25 @@ actisys_change_speed, }; +/* + * Function actisys_change_speed (task) + * + * There is two model of Actisys dongle we are dealing with, + * the 220L and 220L+. At this point, only irattach knows with + * kind the user has requested (it was an argument on irattach + * command line). + * So, we register a dongle of each sort and let irattach + * pick the right one... + */ int __init actisys_init(void) { int ret; + /* First, register an Actisys 220L dongle */ ret = irda_device_register_dongle(&dongle); if (ret < 0) return ret; + /* Now, register an Actisys 220L+ dongle */ ret = irda_device_register_dongle(&dongle_plus); if (ret < 0) { irda_device_unregister_dongle(&dongle); @@ -76,125 +112,121 @@ void actisys_cleanup(void) { + /* We have to remove both dongles */ irda_device_unregister_dongle(&dongle); irda_device_unregister_dongle(&dongle_plus); } static void actisys_open(dongle_t *self, struct qos_info *qos) { + /* Power on the dongle */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + + /* Set the speeds we can accept */ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; /* Remove support for 38400 if this is not a 220L+ dongle */ if (self->issue->type == IRDA_ACTISYS_DONGLE) qos->baud_rate.bits &= ~IR_38400; - qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ + qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */ MOD_INC_USE_COUNT; } static void actisys_close(dongle_t *self) { - /* Power off dongle */ + /* Power off the dongle */ self->set_dtr_rts(self->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } /* - * Function actisys_change_speed (tty, baud) + * Function actisys_change_speed (task) * * Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles. - * To cycle through the available baud rates, pulse RTS low for a few - * ms. + * To cycle through the available baud rates, pulse RTS low for a few us. + * + * First, we reset the dongle to always start from a known state. + * Then, we cycle through the speeds by pulsing RTS low and then up. + * The dongle allow us to pulse quite fast, se we can set speed in one go, + * which is must faster ( < 100 us) and less complex than what is found + * in some other dongle drivers... + * Note that even if the new speed is the same as the current speed, + * we reassert the speed. This make sure that things are all right, + * and it's fast anyway... + * By the way, this function will work for both type of dongles, + * because the additional speed is at the end of the sequence... */ static int actisys_change_speed(struct irda_task *task) { dongle_t *self = (dongle_t *) task->instance; - __u32 speed = (__u32) task->param; - __u32 current_speed; - int index = 0; + __u32 speed = (__u32) task->param; /* Target speed */ int ret = 0; - - IRDA_DEBUG(4, __FUNCTION__ "()\n"); - - current_speed = self->speed; + int i = 0; - /* Find the correct baudrate index for the currently used baudrate */ - while (current_speed != baud_rates[index]) - index++; + IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed, + self->speed); - IRDA_DEBUG(4, __FUNCTION__ "(), index=%d\n", index); + /* Go to a known state by reseting the dongle */ - switch (task->state) { - case IRDA_TASK_INIT: - /* Lock dongle */ - if (irda_lock((void *) &self->busy) == FALSE) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); - ret = MSECS_TO_JIFFIES(100); + /* Reset the dongle : set DTR low for 10 us */ + self->set_dtr_rts(self->dev, FALSE, TRUE); + udelay(MIN_DELAY); + + /* Go back to normal mode (we are now at 9600 b/s) */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + + /* + * Now, we can set the speed requested. Send RTS pulses until we + * reach the target speed + */ + for (i=0; ispeed = baud_rates[i]; break; } - - IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", - baud_rates[index]); - - /* Set DTR, clear RTS */ + /* Make sure previous pulse is finished */ + udelay(MIN_DELAY); + + /* Set RTS low for 10 us */ self->set_dtr_rts(self->dev, TRUE, FALSE); - - irda_task_next_state(task, IRDA_TASK_WAIT1); + udelay(MIN_DELAY); - /* Wait at a few ms */ - ret = MSECS_TO_JIFFIES(20); - break; - case IRDA_TASK_WAIT1: - /* Set DTR, Set RTS */ + /* Set RTS high for 10 us */ self->set_dtr_rts(self->dev, TRUE, TRUE); - - irda_task_next_state(task, IRDA_TASK_WAIT2); - - /* Wait at a few ms again */ - ret = MSECS_TO_JIFFIES(20); - break; - case IRDA_TASK_WAIT2: - /* Go to next baudrate */ - if (self->issue->type == IRDA_ACTISYS_DONGLE) - index = (index+1) % 4; /* IR-220L */ - else - index = (index+1) % 5; /* IR-220L+ */ - - current_speed = baud_rates[index]; - - /* Check if we need to go some more rounds */ - if (current_speed != speed) - irda_task_next_state(task, IRDA_TASK_INIT); - else { - irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; - } - break; - default: - ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); - irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; - ret = -1; - break; - } + } - self->speed = speed; + /* Check if life is sweet... */ + if (i >= MAX_SPEEDS) + ret = -1; /* This should not happen */ - IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", - baud_rates[index]); + /* Basta lavoro, on se casse d'ici... */ + irda_task_next_state(task, IRDA_TASK_DONE); return ret; } /* - * Function actisys_reset (dev) + * Function actisys_reset (task) * * Reset the Actisys type dongle. Warning, this function must only be * called with a process context! * - * 1. Clear DTR for a few ms. + * We need to do two things in this function : + * o first make sure that the dongle is in a state where it can operate + * o second put the dongle in a know state + * + * The dongle is powered of the RTS and DTR lines. In the dongle, there + * is a big capacitor to accomodate the current spikes. This capacitor + * takes a least 50 ms to be charged. In theory, the Bios set those lines + * up, so by the time we arrive here we should be set. It doesn't hurt + * to be on the conservative side, so we will wait... + * Then, we set the speed to 9600 b/s to get in a known state (see in + * change_speed for details). It is needed because the IrDA stack + * has tried to set the speed immediately after our first return, + * so before we can be sure the dongle is up and running. */ static int actisys_reset(struct irda_task *task) { @@ -203,27 +235,34 @@ ASSERT(task != NULL, return -1;); + self->reset_task = task; + switch (task->state) { case IRDA_TASK_INIT: - /* Clear DTR */ - self->set_dtr_rts(self->dev, FALSE, TRUE); + /* Set both DTR & RTS to power up the dongle */ + /* In theory redundant with power up in actisys_open() */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + /* Sleep 50 ms to make sure capacitor is charged */ + ret = MSECS_TO_JIFFIES(50); irda_task_next_state(task, IRDA_TASK_WAIT); - - /* Sleep 10-20 ms*/ - ret = MSECS_TO_JIFFIES(20); break; case IRDA_TASK_WAIT: + /* Reset the dongle : set DTR low for 10 us */ + self->set_dtr_rts(self->dev, FALSE, TRUE); + udelay(MIN_DELAY); + /* Go back to normal mode */ self->set_dtr_rts(self->dev, TRUE, TRUE); irda_task_next_state(task, IRDA_TASK_DONE); - - self->speed = 9600; + self->reset_task = NULL; + self->speed = 9600; /* That's the default */ break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); + self->reset_task = NULL; ret = -1; break; } @@ -231,7 +270,7 @@ } #ifdef MODULE -MODULE_AUTHOR("Dag Brattli "); +MODULE_AUTHOR("Dag Brattli - Jean Tourrilhes "); MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver"); /* diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/airport.c linux/drivers/net/irda/airport.c --- v2.3.34/linux/drivers/net/irda/airport.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/irda/airport.c Tue Dec 21 10:17:31 1999 @@ -68,7 +68,7 @@ qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; /* May need 1ms */ - qos->min_turn_time.bits &= 0x07; + qos->min_turn_time.bits = 0x07; MOD_INC_USE_COUNT; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c --- v2.3.34/linux/drivers/net/irda/esi.c Wed Oct 27 16:34:12 1999 +++ linux/drivers/net/irda/esi.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Mon Oct 18 12:35:43 1999 + * Modified at: Fri Dec 17 09:17:05 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, , @@ -68,7 +68,7 @@ static void esi_open(dongle_t *self, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; - qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ + qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ MOD_INC_USE_COUNT; } @@ -93,12 +93,6 @@ __u32 speed = (__u32) task->param; int dtr, rts; - /* Lock dongle */ - if (irda_lock((void *) &self->busy) == FALSE) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); - return MSECS_TO_JIFFIES(100); - } - switch (speed) { case 19200: dtr = TRUE; @@ -120,9 +114,6 @@ irda_task_next_state(task, IRDA_TASK_DONE); - /* Unlock */ - self->busy = 0; - return 0; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c --- v2.3.34/linux/drivers/net/irda/girbil.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/irda/girbil.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Sat Oct 30 20:25:22 1999 + * Modified at: Fri Dec 17 09:16:52 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -87,7 +87,7 @@ static void girbil_open(dongle_t *self, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x03; + qos->min_turn_time.bits = 0x03; MOD_INC_USE_COUNT; } @@ -113,14 +113,10 @@ __u8 control[2]; int ret = 0; + self->speed_task = task; + switch (task->state) { case IRDA_TASK_INIT: - /* Lock dongle */ - if (irda_lock((void *) &self->busy) == FALSE) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); - return MSECS_TO_JIFFIES(100); - } - /* Need to reset the dongle and go to 9600 bps before programming */ if (irda_task_execute(self, girbil_reset, NULL, task, @@ -170,12 +166,12 @@ /* Go back to normal mode */ self->set_dtr_rts(self->dev, TRUE, TRUE); irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; + self->speed_task = NULL; break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; + self->speed_task = NULL; ret = -1; break; } @@ -197,6 +193,8 @@ __u8 control = GIRBIL_TXEN | GIRBIL_RXEN; int ret = 0; + self->reset_task = task; + switch (task->state) { case IRDA_TASK_INIT: /* Reset dongle */ @@ -221,10 +219,12 @@ /* Go back to normal mode */ self->set_dtr_rts(self->dev, TRUE, TRUE); irda_task_next_state(task, IRDA_TASK_DONE); + self->reset_task = NULL; break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); + self->reset_task = NULL; ret = -1; break; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- v2.3.34/linux/drivers/net/irda/irport.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/irport.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 3 13:49:59 1997 - * Modified at: Sat Nov 13 23:25:56 1999 + * Modified at: Thu Dec 16 00:47:08 1999 * Modified by: Dag Brattli * Sources: serial.c by Linus Torvalds * @@ -73,16 +73,11 @@ static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL}; static char *driver_name = "irport"; -static int irport_open(int i, unsigned int iobase, unsigned int irq); -static int irport_close(struct irport_cb *self); - static void irport_write_wakeup(struct irport_cb *self); static int irport_write(int iobase, int fifo_size, __u8 *buf, int len); static void irport_receive(struct irport_cb *self); static int irport_net_init(struct net_device *dev); -static int irport_net_open(struct net_device *dev); -static int irport_net_close(struct net_device *dev); static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int irport_is_receiving(struct irport_cb *self); @@ -91,7 +86,15 @@ static struct net_device_stats *irport_net_get_stats(struct net_device *dev); static int irport_change_speed_complete(struct irda_task *task); +EXPORT_SYMBOL(irport_open); +EXPORT_SYMBOL(irport_close); +EXPORT_SYMBOL(irport_start); +EXPORT_SYMBOL(irport_stop); +EXPORT_SYMBOL(irport_interrupt); +EXPORT_SYMBOL(irport_hard_xmit); EXPORT_SYMBOL(irport_change_speed); +EXPORT_SYMBOL(irport_net_open); +EXPORT_SYMBOL(irport_net_close); int __init irport_init(void) { @@ -101,7 +104,7 @@ int ioaddr = io[i]; if (check_region(ioaddr, IO_EXTENT)) continue; - if (irport_open(i, io[i], irq[i]) == 0) + if (irport_open(i, io[i], irq[i]) != NULL) return 0; } /* @@ -130,7 +133,8 @@ } #endif /* MODULE */ -static int irport_open(int i, unsigned int iobase, unsigned int irq) +struct irport_cb * +irport_open(int i, unsigned int iobase, unsigned int irq) { struct net_device *dev; struct irport_cb *self; @@ -146,7 +150,7 @@ if (!self) { ERROR(__FUNCTION__ "(), can't allocate memory for " "control block!\n"); - return -ENOMEM; + return NULL; } memset(self, 0, sizeof(struct irport_cb)); @@ -154,22 +158,23 @@ /* Need to store self somewhere */ dev_self[i] = self; + self->priv = self; /* Initialize IO */ - self->io.iobase2 = iobase; - self->io.irq2 = irq; + self->io.iobase = iobase; + self->io.irq = irq; self->io.io_ext = IO_EXTENT; self->io.fifo_size = 16; /* Lock the port that we need */ - ret = check_region(self->io.iobase2, self->io.io_ext); + ret = check_region(self->io.iobase, self->io.io_ext); if (ret < 0) { IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", - self->io.iobase2); + self->io.iobase); /* irport_cleanup(self->self); */ - return -ENODEV; + return NULL; } - request_region(self->io.iobase2, self->io.io_ext, driver_name); + request_region(self->io.iobase, self->io.io_ext, driver_name); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&self->qos); @@ -191,7 +196,7 @@ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, GFP_KERNEL); if (self->rx_buff.head == NULL) - return -ENOMEM; + return NULL; memset(self->rx_buff.head, 0, self->rx_buff.truesize); } if (self->tx_buff.truesize > 0) { @@ -199,7 +204,7 @@ GFP_KERNEL); if (self->tx_buff.head == NULL) { kfree(self->rx_buff.head); - return -ENOMEM; + return NULL; } memset(self->tx_buff.head, 0, self->tx_buff.truesize); } @@ -211,12 +216,18 @@ if (!(dev = dev_alloc("irda%d", &err))) { ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); - return -ENOMEM; + return NULL; } + /* dev_alloc doesn't clear the struct */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); - dev->priv = (void *) self; self->netdev = dev; + /* May be overridden by piggyback drivers */ + dev->priv = (void *) self; + self->interrupt = irport_interrupt; + self->change_speed = irport_change_speed; + /* Override the network functions we need to use */ dev->init = irport_net_init; dev->hard_start_xmit = irport_hard_xmit; @@ -234,14 +245,14 @@ rtnl_unlock(); if (err) { ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); - return -1; + return NULL; } MESSAGE("IrDA: Registered device %s\n", dev->name); - return 0; + return self; } -static int irport_close(struct irport_cb *self) +int irport_close(struct irport_cb *self) { ASSERT(self != NULL, return -1;); @@ -255,12 +266,14 @@ rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); + /* Must free the old-style 2.2.x device */ + kfree(self->netdev); } /* Release the IO-port that this driver is using */ IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", - self->io.iobase2); - release_region(self->io.iobase2, self->io.io_ext); + self->io.iobase); + release_region(self->io.iobase, self->io.io_ext); if (self->tx_buff.head) kfree(self->tx_buff.head); @@ -273,13 +286,16 @@ return 0; } -void irport_start(struct irport_cb *self, int iobase) +void irport_start(struct irport_cb *self) { unsigned long flags; + int iobase; + + iobase = self->io.iobase; spin_lock_irqsave(&self->lock, flags); - irport_stop(self, iobase); + irport_stop(self); /* Initialize UART */ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ @@ -291,9 +307,12 @@ spin_unlock_irqrestore(&self->lock, flags); } -void irport_stop(struct irport_cb *self, int iobase) +void irport_stop(struct irport_cb *self) { unsigned long flags; + int iobase; + + iobase = self->io.iobase; spin_lock_irqsave(&self->lock, flags); @@ -325,8 +344,9 @@ * Set speed of IrDA port to specified baudrate * */ -void __irport_change_speed(struct irport_cb *self, __u32 speed) +void irport_change_speed(void *priv, __u32 speed) { + struct irport_cb *self = (struct irport_cb *) priv; unsigned long flags; int iobase; int fcr; /* FIFO control reg */ @@ -337,7 +357,7 @@ ASSERT(self != NULL, return;); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Update accounting for new speed */ self->io.speed = speed; @@ -377,12 +397,12 @@ } /* - * Function irport_change_speed (instance, state, param) + * Function __irport_change_speed (instance, state, param) * * State machine for changing speed of the device. We do it this way since * we cannot use schedule_timeout() when we are in interrupt context */ -int irport_change_speed(struct irda_task *task) +int __irport_change_speed(struct irda_task *task) { struct irport_cb *self; __u32 speed = (__u32) task->param; @@ -413,7 +433,7 @@ break; case IRDA_TASK_CHILD_INIT: /* Go to default speed */ - __irport_change_speed(self, 9600); + irport_change_speed(self, 9600); /* Change speed of dongle */ if (irda_task_execute(self->dongle, @@ -436,7 +456,7 @@ break; case IRDA_TASK_CHILD_DONE: /* Finally we are ready to change the speed */ - __irport_change_speed(self, speed); + irport_change_speed(self, speed); irda_task_next_state(task, IRDA_TASK_DONE); break; @@ -466,7 +486,7 @@ IRDA_DEBUG(4, __FUNCTION__ "()\n"); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Finished with frame? */ if (self->tx_buff.len > 0) { @@ -484,7 +504,7 @@ */ if (self->new_speed) { IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n"); - irda_task_execute(self, irport_change_speed, + irda_task_execute(self, __irport_change_speed, irport_change_speed_complete, NULL, (void *) self->new_speed); self->new_speed = 0; @@ -529,7 +549,7 @@ /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n"); - return -1; + return 0; } /* Fill FIFO with current frame */ @@ -589,7 +609,7 @@ self = (struct irport_cb *) dev->priv; ASSERT(self != NULL, return 0;); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) { @@ -598,8 +618,8 @@ return -EBUSY; WARNING("%s: transmit timed out\n", dev->name); - irport_start(self, iobase); - __irport_change_speed(self, self->io.speed ); + irport_start(self); + irport_change_speed(self, self->io.speed ); dev->trans_start = jiffies; } @@ -643,7 +663,7 @@ ASSERT(self != NULL, return;); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* * Receive all characters in Rx FIFO, unwrap and unstuff them. @@ -684,7 +704,7 @@ dev->interrupt = 1; - iobase = self->io.iobase2; + iobase = self->io.iobase; iir = inb(iobase+UART_IIR) & UART_IIR_ID; while (iir) { @@ -739,7 +759,7 @@ * Network device is taken up. Usually this is done by "ifconfig irda0 up" * */ -static int irport_net_open(struct net_device *dev) +int irport_net_open(struct net_device *dev) { struct irport_cb *self; int iobase; @@ -747,13 +767,13 @@ ASSERT(dev != NULL, return -1;); self = (struct irport_cb *) dev->priv; - iobase = self->io.iobase2; + iobase = self->io.iobase; - if (request_irq(self->io.irq2, irport_interrupt, 0, dev->name, + if (request_irq(self->io.irq, self->interrupt, 0, dev->name, (void *) dev)) return -EAGAIN; - irport_start(self, iobase); + irport_start(self); /* Ready to play! */ dev->tbusy = 0; @@ -779,7 +799,7 @@ * Network device is taken down. Usually this is done by * "ifconfig irda0 down" */ -static int irport_net_close(struct net_device *dev) +int irport_net_close(struct net_device *dev) { struct irport_cb *self; int iobase; @@ -791,7 +811,7 @@ ASSERT(self != NULL, return -1;); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Stop device */ dev->tbusy = 1; @@ -802,9 +822,9 @@ irlap_close(self->irlap); self->irlap = NULL; - irport_stop(self, iobase); + irport_stop(self); - free_irq(self->io.irq2, dev); + free_irq(self->io.irq, dev); MOD_DEC_USE_COUNT; @@ -822,7 +842,7 @@ { int iobase; - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Wait until Tx FIFO is empty */ while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { @@ -857,7 +877,7 @@ ASSERT(self != NULL, return -1;); - iobase = self->io.iobase2; + iobase = self->io.iobase; if (dtr) dtr = UART_MCR_DTR; @@ -877,7 +897,7 @@ ASSERT(self != NULL, return -1;); - iobase = self->io.iobase2; + iobase = self->io.iobase; /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { @@ -923,7 +943,7 @@ switch (cmd) { case SIOCSBANDWIDTH: /* Set bandwidth */ - irda_task_execute(self, irport_change_speed, NULL, NULL, + irda_task_execute(self, __irport_change_speed, NULL, NULL, (void *) irq->ifr_baudrate); break; case SIOCSDONGLE: /* Set dongle */ diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.3.34/linux/drivers/net/irda/irtty.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/irtty.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Tue Nov 16 02:50:37 1999 + * Modified at: Thu Dec 16 09:37:47 1999 * Modified by: Dag Brattli * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, @@ -42,7 +42,6 @@ #include static hashbin_t *irtty = NULL; - static struct tty_ldisc irda_ldisc; static int qos_mtt_bits = 0x03; /* 5 ms or more */ @@ -186,7 +185,7 @@ tty->ldisc.flush_buffer(tty); self->magic = IRTTY_MAGIC; - self->rx_buff.state = OUTSIDE_FRAME; + self->mode = IRDA_IRLAP; /* * Initialize QoS capabilities, we fill in all the stuff that @@ -206,7 +205,7 @@ /* Specify how much memory we want */ self->rx_buff.truesize = 4000; self->tx_buff.truesize = 4000; - + /* Allocate memory if needed */ if (self->rx_buff.truesize > 0) { self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, @@ -225,8 +224,6 @@ memset(self->tx_buff.head, 0, self->tx_buff.truesize); } - self->magic = IRTTY_MAGIC; - self->rx_buff.in_frame = FALSE; self->rx_buff.state = OUTSIDE_FRAME; self->tx_buff.data = self->tx_buff.head; @@ -284,18 +281,24 @@ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); tty->disc_data = 0; - /* We are not using any dongle anymore! */ - if (self->dongle) - irda_device_dongle_cleanup(self->dongle); - self->dongle = NULL; - /* Remove netdevice */ if (self->netdev) { rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); + /* Must free the old-style 2.2.x device */ + kfree(self->netdev); } + /* We are not using any dongle anymore! */ + if (self->dongle) + irda_device_dongle_cleanup(self->dongle); + self->dongle = NULL; + + /* Remove speed changing task if any */ + if (self->task) + irda_task_delete(self->task); + self->tty = NULL; self->magic = 0; @@ -404,9 +407,15 @@ IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); self = (struct irtty_cb *) task->instance; - ASSERT(self != NULL, return -1;); + /* Check if busy */ + if (self->task && self->task != task) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(10); + } else + self->task = task; + switch (task->state) { case IRDA_TASK_INIT: /* @@ -459,10 +468,12 @@ __irtty_change_speed(self, speed); irda_task_next_state(task, IRDA_TASK_DONE); + self->task = NULL; break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); + self->task = NULL; ret = -1; break; } @@ -551,6 +562,11 @@ { struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; + if (!self || !self->netdev) { + IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n"); + return; + } + /* Read the characters out of the buffer */ while (count--) { /* @@ -631,7 +647,7 @@ /* Check if we need to change the speed */ if ((speed = irda_get_speed(skb)) != self->io.speed) self->new_speed = speed; - + /* Init tx buffer*/ self->tx_buff.data = self->tx_buff.head; @@ -768,7 +784,7 @@ set_fs(get_ds()); if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { - ERROR(__FUNCTION__ "(), error doing ioctl!\n"); + IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n"); } set_fs(fs); @@ -987,6 +1003,9 @@ break; case SIOCSDTRRTS: irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); + break; + case SIOCSMODE: + irtty_set_mode(dev, irq->ifr_mode); break; default: ret = -EOPNOTSUPP; diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c --- v2.3.34/linux/drivers/net/irda/litelink.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/irda/litelink.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Stable * Author: Dag Brattli * Created at: Fri May 7 12:50:33 1999 - * Modified at: Sat Oct 30 20:24:58 1999 + * Modified at: Fri Dec 17 09:16:23 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -71,7 +71,7 @@ static void litelink_open(dongle_t *self, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ + qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */ MOD_INC_USE_COUNT; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/old_belkin.c linux/drivers/net/irda/old_belkin.c --- v2.3.34/linux/drivers/net/irda/old_belkin.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/irda/old_belkin.c Tue Dec 21 10:17:31 1999 @@ -0,0 +1,178 @@ +/********************************************************************* + * + * Filename: old_belkin.c + * Version: 1.1 + * Description: Driver for the Belkin (old) SmartBeam dongle + * Status: Experimental... + * Author: Jean Tourrilhes + * Created at: 22/11/99 + * Modified at: Fri Dec 17 09:17:30 1999 + * Modified by: Dag Brattli + * + * Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Belkin is selling a dongle called the SmartBeam. + * In fact, there is two hardware version of this dongle, of course with + * the same name and looking the exactly same (grrr...). + * I guess that I've got the old one, because inside I don't have + * a jumper for IrDA/ASK... + * + * As far as I can make it from info on their web site, the old dongle + * support only 9600 b/s, which make our life much simpler as far as + * the driver is concerned, but you might not like it very much ;-) + * The new SmartBeam does 115 kb/s, and I've not tested it... + * + * Belkin claim that the correct driver for the old dongle (in Windows) + * is the generic Parallax 9500a driver, but the Linux LiteLink driver + * fails for me (probably because Linux-IrDA doesn't rate fallback), + * so I created this really dumb driver... + * + * In fact, this driver doesn't do much. The only thing it does is to + * prevent Linux-IrDA to use any other speed than 9600 b/s ;-) This + * driver is called "old_belkin" so that when the new SmartBeam is supported + * its driver can be called "belkin" instead of "new_belkin". + * + * Note : this driver was written without any info/help from Belkin, + * so a lot of info here might be totally wrong. Blame me ;-) + */ + +/* Let's guess */ +#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */ + +static void old_belkin_open(dongle_t *self, struct qos_info *qos); +static void old_belkin_close(dongle_t *self); +static int old_belkin_change_speed(struct irda_task *task); +static int old_belkin_reset(struct irda_task *task); + +/* These are the baudrates supported */ +/* static __u32 baud_rates[] = { 9600 }; */ + +static struct dongle_reg dongle = { + Q_NULL, + IRDA_OLD_BELKIN_DONGLE, + old_belkin_open, + old_belkin_close, + old_belkin_reset, + old_belkin_change_speed, +}; + +int __init old_belkin_init(void) +{ + return irda_device_register_dongle(&dongle); +} + +void old_belkin_cleanup(void) +{ + irda_device_unregister_dongle(&dongle); +} + +static void old_belkin_open(dongle_t *self, struct qos_info *qos) +{ + /* Not too fast, please... */ + qos->baud_rate.bits &= IR_9600; + /* Needs at least 10 ms (totally wild guess, can do probably better) */ + qos->min_turn_time.bits = 0x01; + + MOD_INC_USE_COUNT; +} + +static void old_belkin_close(dongle_t *self) +{ + /* Power off dongle */ + self->set_dtr_rts(self->dev, FALSE, FALSE); + + MOD_DEC_USE_COUNT; +} + +/* + * Function old_belkin_change_speed (task) + * + * With only one speed available, not much to do... + */ +static int old_belkin_change_speed(struct irda_task *task) +{ + irda_task_next_state(task, IRDA_TASK_DONE); + + return 0; +} + +/* + * Function old_belkin_reset (task) + * + * Reset the Old-Belkin type dongle. + * + */ +static int old_belkin_reset(struct irda_task *task) +{ + dongle_t *self = (dongle_t *) task->instance; + + /* Power on dongle */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(MIN_DELAY); + + /* This dongles speed "defaults" to 9600 bps ;-) */ + self->speed = 9600; + + irda_task_next_state(task, IRDA_TASK_DONE); + + return 0; +} + +#ifdef MODULE +MODULE_AUTHOR("Jean Tourrilhes "); +MODULE_DESCRIPTION("Belkin (old) SmartBeam dongle driver"); + +/* + * Function init_module (void) + * + * Initialize Old-Belkin module + * + */ +int init_module(void) +{ + return old_belkin_init(); +} + +/* + * Function cleanup_module (void) + * + * Cleanup Old-Belkin module + * + */ +void cleanup_module(void) +{ + old_belkin_cleanup(); +} +#endif /* MODULE */ + diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c --- v2.3.34/linux/drivers/net/irda/pc87108.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/pc87108.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Sat Nov 13 23:54:59 1999 + * Modified at: Thu Dec 16 00:54:27 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli @@ -36,7 +36,7 @@ * outb(bank, iobase+BSR); * * If you find bugs in this file, its very likely that the same bug - * will also be in w83977af_ir.c since the implementations is quite + * will also be in w83977af_ir.c since the implementations are quite * similar. * ********************************************************************/ @@ -121,6 +121,7 @@ static int pc87108_net_init(struct net_device *dev); static int pc87108_net_open(struct net_device *dev); static int pc87108_net_close(struct net_device *dev); +static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); /* * Function pc87108_init () @@ -267,6 +268,7 @@ dev->hard_start_xmit = pc87108_hard_xmit; dev->open = pc87108_net_open; dev->stop = pc87108_net_close; + dev->do_ioctl = pc87108_net_ioctl; rtnl_lock(); err = register_netdevice(dev); @@ -304,12 +306,15 @@ /* Remove netdevice */ if (self->netdev) { rtnl_lock(); - unregister_netdev(self->netdev); + unregister_netdevice(self->netdev); rtnl_unlock(); + /* Must free the old-style 2.2.x device */ + kfree(self->netdev); } /* Release the PORT that this driver is using */ - IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.iobase); + IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", + self->io.iobase); release_region(self->io.iobase, self->io.io_ext); if (self->tx_buff.head) @@ -389,7 +394,7 @@ dongle_id = pc87108_read_dongle_id(iobase); IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", - dongle_types[dongle_id]); + dongle_types[dongle_id]); /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ switch_bank(iobase, BANK0); @@ -550,7 +555,8 @@ outb(0x62, iobase+MCR); break; default: - IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id); + IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", + dongle_id); } /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ @@ -705,7 +711,8 @@ break; default: mcr = MCR_FIR; - IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", + speed); break; } @@ -856,7 +863,7 @@ /* Choose transmit DMA channel */ switch_bank(iobase, BANK2); outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, - iobase+ECR1); + iobase+ECR1); /* Enable DMA */ switch_bank(iobase, BANK0); @@ -885,10 +892,12 @@ switch_bank(iobase, BANK0); if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { - IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + IRDA_DEBUG(4, __FUNCTION__ + "(), warning, FIFO not empty yet!\n"); fifo_size -= 17; - IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + IRDA_DEBUG(4, __FUNCTION__ "(), %d bytes left in tx fifo\n", + fifo_size); } /* Fill FIFO with current frame */ @@ -898,8 +907,8 @@ } IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); - + fifo_size, actual, len); + /* Restore bank */ outb(bank, iobase+BSR); @@ -1189,6 +1198,14 @@ else { self->netdev->tbusy = 0; /* Unlock */ self->stats.tx_packets++; + + /* Check if we need to change the speed? */ + if (self->new_speed) { + IRDA_DEBUG(2, __FUNCTION__ + "(), Changing speed!\n"); + pc87108_change_speed(self, self->new_speed); + self->new_speed = 0; + } mark_bh(NET_BH); @@ -1420,7 +1437,8 @@ iobase = self->io.iobase; if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name, - (void *) dev)) { + (void *) dev)) + { return -EAGAIN; } /* @@ -1497,7 +1515,7 @@ switch_bank(iobase, BANK0); outb(0, iobase+IER); - free_irq(self->io.irq, self); + free_irq(self->io.irq, dev); free_dma(self->io.dma); /* Restore bank register */ @@ -1506,6 +1524,50 @@ MOD_DEC_USE_COUNT; return 0; +} + +/* + * Function pc87108_net_ioctl (dev, rq, cmd) + * + * Process IOCTL commands for this device + * + */ +static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct pc87108 *self; + unsigned long flags; + int ret = 0; + + ASSERT(dev != NULL, return -1;); + + self = dev->priv; + + ASSERT(self != NULL, return -1;); + + IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + pc87108_change_speed(self, irq->ifr_baudrate); + break; + case SIOCSMEDIABUSY: /* Set media busy */ + irda_device_set_media_busy(self->netdev, TRUE); + break; + case SIOCGRECEIVING: /* Check if we are receiving right now */ + irq->ifr_receiving = pc87108_is_receiving(self); + break; + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; } #ifdef MODULE diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c --- v2.3.34/linux/drivers/net/irda/smc-ircc.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/smc-ircc.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Thomas Davis (tadavis@jps.net) * Created at: - * Modified at: Fri Nov 12 21:08:09 1999 + * Modified at: Sat Dec 11 14:38:26 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved. @@ -68,12 +68,10 @@ static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase); static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev); static void ircc_dma_write(struct ircc_cb *self, int iobase); -static void ircc_change_speed(struct ircc_cb *self, __u32 speed); +static void ircc_change_speed(void *priv, __u32 speed); static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void ircc_wait_until_sent(struct ircc_cb *self); static int ircc_is_receiving(struct ircc_cb *self); -static int ircc_net_init(struct net_device *dev); static int ircc_net_open(struct net_device *dev); static int ircc_net_close(struct net_device *dev); @@ -149,11 +147,10 @@ */ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2) { - struct net_device *dev; struct ircc_cb *self; + struct irport_cb *irport; int config; int ret; - int err; IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); @@ -177,21 +174,30 @@ /* Need to store self somewhere */ dev_self[i] = self; + irport = irport_open(0, iobase2, config >> 4 & 0x0f); + if (!irport) + return -ENODEV; + + /* Steal the network device from irport */ + self->netdev = irport->netdev; + self->irport = irport; + irport->priv = self; + /* Initialize IO */ self->io.iobase = iobase; self->io.iobase2 = iobase2; /* Used by irport */ self->io.irq = config >> 4 & 0x0f; if (ircc_irq < 255) { - printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n", - self->io.irq, ircc_irq); + MESSAGE("smc_ircc: Overriding IRQ - chip says %d, using %d\n", + self->io.irq, ircc_irq); self->io.irq = ircc_irq; } self->io.io_ext = CHIP_IO_EXTENT; self->io.io_ext2 = 8; /* Used by irport */ self->io.dma = config & 0x0f; if (ircc_dma < 255) { - printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n", - self->io.dma, ircc_dma); + MESSAGE("smc: Overriding DMA - chip says %d, using %d\n", + self->io.dma, ircc_dma); self->io.dma = ircc_dma; } self->io.fifo_size = 16; @@ -204,15 +210,8 @@ /* ircc_cleanup(self->self); */ return -ENODEV; } - ret = check_region(self->io.iobase2, self->io.io_ext2); - if (ret < 0) { - IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n", - self->io.iobase2); - /* ircc_cleanup(self->self); */ - return -ENODEV; - } + request_region(self->io.iobase, self->io.io_ext, driver_name); - request_region(self->io.iobase2, self->io.io_ext2, driver_name); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&self->qos); @@ -227,10 +226,10 @@ IR_115200; #endif - self->qos.min_turn_time.bits = 0x07; - irda_qos_bits_to_value(&self->qos); + irport->qos.min_turn_time.bits = 0x07; + irda_qos_bits_to_value(&irport->qos); - self->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO; + irport->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO; /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ self->rx_buff.truesize = 4000; @@ -259,31 +258,12 @@ self->tx_buff.data = self->tx_buff.head; self->rx_buff.data = self->rx_buff.head; - if (!(dev = dev_alloc("irda%d", &err))) { - ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); - return -ENOMEM; - } + /* Override the speed change function, since we must control it now */ + irport->change_speed = &ircc_change_speed; + self->netdev->open = &ircc_net_open; + self->netdev->stop = &ircc_net_close; - dev->priv = (void *) self; - self->netdev = dev; - - /* Override the network functions we need to use */ - dev->init = ircc_net_init; - dev->hard_start_xmit = ircc_hard_xmit; - dev->open = ircc_net_open; - dev->stop = ircc_net_close; - - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - if (err) { - ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); - return -1; - } - - MESSAGE("IrDA: Registered device %s\n", dev->name); - - irport_start(&self->irport, iobase2); + irport_start(self->irport); IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n"); return 0; @@ -306,14 +286,7 @@ iobase = self->io.iobase; - irport_stop(&self->irport, self->io.iobase2); - - /* Remove netdevice */ - if (self->netdev) { - rtnl_lock(); - unregister_netdev(self->netdev); - rtnl_unlock(); - } + irport_close(self->irport); register_bank(iobase, 0); serial_out(iobase, UART_IER, 0); @@ -331,12 +304,6 @@ release_region(self->io.iobase, self->io.io_ext); - if (self->io.iobase2) { - IRDA_DEBUG(ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", - self->io.iobase2); - release_region(self->io.iobase2, self->io.io_ext2); - } - if (self->tx_buff.head) kfree(self->tx_buff.head); @@ -394,14 +361,17 @@ * Change the speed of the device * */ -static void ircc_change_speed(struct ircc_cb *self, __u32 speed) +static void ircc_change_speed(void *priv, __u32 speed) { int iobase, ir_mode, select, fast; + struct ircc_cb *self = (struct ircc_cb *) priv; + struct net_device *dev; IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); ASSERT(self != NULL, return;); + dev = self->netdev; iobase = self->io.iobase; /* Update accounting for new speed */ @@ -420,8 +390,14 @@ serial_out(iobase, UART_IER, 0); serial_out(iobase, UART_MASTER, UART_MASTER_RESET); serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN); - irport_start(&self->irport, self->io.iobase2); - __irport_change_speed(&self->irport, speed); + + dev->hard_start_xmit = &irport_hard_xmit; + + /* We must give the interrupt back to irport */ + self->irport->interrupt = irport_interrupt; + + irport_start(self->irport); + irport_change_speed(self->irport, speed); return; break; @@ -429,22 +405,26 @@ ir_mode = UART_CFGA_IRDA_HDLC; select = 0; fast = 0; - IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 576000\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ + "(), handling baud of 576000\n"); break; case 1152000: ir_mode = UART_CFGA_IRDA_HDLC; select = UART_1152; fast = 0; - IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ + "(), handling baud of 1152000\n"); break; case 4000000: ir_mode = UART_CFGA_IRDA_4PPM; select = 0; fast = UART_LCR_A_FAST; - IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ + "(), handling baud of 4000000\n"); break; default: - IRDA_DEBUG(0, __FUNCTION__ ": unknown baud rate of %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", + speed); return; } @@ -457,9 +437,15 @@ register_bank(iobase, 0); serial_out(iobase, UART_IER, 0); - irport_stop(&self->irport, self->io.iobase2); + irport_stop(self->irport); - self->netdev->tbusy = 0; + /* Install FIR transmit handler */ + dev->hard_start_xmit = &ircc_hard_xmit; + + /* Need to steal the interrupt as well */ + self->irport->interrupt = &ircc_interrupt; + + dev->tbusy = 0; register_bank(iobase, 1); @@ -493,13 +479,15 @@ */ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev) { + struct irport_cb *irport; struct ircc_cb *self; int iobase; int mtt; __u32 speed; IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); - self = (struct ircc_cb *) dev->priv; + irport = (struct irport_cb *) dev->priv; + self = (struct ircc_cb *) irport->priv; ASSERT(self != NULL, return 0;); @@ -510,14 +498,7 @@ /* Check if we need to change the speed */ if ((speed = irda_get_speed(skb)) != self->io.speed) - ircc_change_speed(self, speed); - - /* Use irport for SIR speeds */ - if (self->io.speed <= 115200) { - IRDA_DEBUG(ircc_debug+1, __FUNCTION__ - ": calling irport_hard_xmit\n"); - return irport_hard_xmit(skb, dev); - } + self->new_speed = speed; IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len); @@ -631,11 +612,17 @@ /* Check for underrrun! */ if (underrun) { - self->stats.tx_errors++; - self->stats.tx_fifo_errors++; + self->irport->stats.tx_errors++; + self->irport->stats.tx_fifo_errors++; } else { - self->stats.tx_packets++; - self->stats.tx_bytes += self->tx_buff.len; + self->irport->stats.tx_packets++; + self->irport->stats.tx_bytes += self->tx_buff.len; + } + + if (self->new_speed) { + ircc_change_speed(self, self->new_speed); + + self->new_speed = 0; } /* Unlock tx_buff and request another frame */ @@ -733,7 +720,7 @@ skb_put(skb, len); memcpy(skb->data, self->rx_buff.data, len); - self->stats.rx_packets++; + self->irport->stats.rx_packets++; skb->dev = self->netdev; skb->mac.raw = skb->data; @@ -771,12 +758,6 @@ self = (struct ircc_cb *) dev->priv; - if (self->io.speed <= 115200) { - IRDA_DEBUG(ircc_debug+1, __FUNCTION__ - ": routing interrupt to irport_interrupt\n"); - return irport_interrupt(irq, dev_id, regs); - } - iobase = self->io.iobase; dev->interrupt = 1; @@ -823,23 +804,6 @@ } /* - * Function ircc_wait_until_sent (self) - * - * This function should put the current thread to sleep until all data - * have been sent, so it is safe to change the speed. - */ -static void ircc_wait_until_sent(struct ircc_cb *self) -{ - IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); - - /* Just delay 60 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(60)); - - IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n"); -} - -/* * Function ircc_is_receiving (self) * * Return TRUE is we are currently receiving a frame @@ -865,26 +829,6 @@ } /* - * Function ircc_net_init (dev) - * - * Initialize network device - * - */ -static int ircc_net_init(struct net_device *dev) -{ - IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); - - /* Setup to be a normal IrDA network device driver */ - irda_device_setup(dev); - - /* Insert overrides below this line! */ - - IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n"); - return 0; -} - - -/* * Function ircc_net_open (dev) * * Start the device @@ -892,22 +836,22 @@ */ static int ircc_net_open(struct net_device *dev) { + struct irport_cb *irport; struct ircc_cb *self; int iobase; - + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT(dev != NULL, return -1;); - self = (struct ircc_cb *) dev->priv; - + irport = (struct irport_cb *) dev->priv; + self = (struct ircc_cb *) irport->priv; + ASSERT(self != NULL, return 0;); iobase = self->io.iobase; - if (request_irq(self->io.irq, ircc_interrupt, 0, dev->name, - (void *) dev)) { - return -EAGAIN; - } + irport_net_open(dev); + /* * Always allocate the DMA channel after the IRQ, * and clean up on failure. @@ -916,17 +860,6 @@ free_irq(self->io.irq, dev); return -EAGAIN; } - - /* Ready to play! */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos); MOD_INC_USE_COUNT; @@ -942,31 +875,24 @@ */ static int ircc_net_close(struct net_device *dev) { + struct irport_cb *irport; struct ircc_cb *self; int iobase; IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT(dev != NULL, return -1;); - self = (struct ircc_cb *) dev->priv; + irport = (struct irport_cb *) dev->priv; + self = (struct ircc_cb *) irport->priv; ASSERT(self != NULL, return 0;); iobase = self->io.iobase; - /* Stop device */ - dev->tbusy = 1; - dev->start = 0; - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; + irport_net_close(dev); disable_dma(self->io.dma); - /* Disable interrupts */ - free_irq(self->io.irq, dev); free_dma(self->io.dma); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c --- v2.3.34/linux/drivers/net/irda/tekram.c Wed Oct 27 16:34:12 1999 +++ linux/drivers/net/irda/tekram.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Mon Oct 18 23:25:44 1999 + * Modified at: Fri Dec 17 09:17:45 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. @@ -70,7 +70,7 @@ IRDA_DEBUG(2, __FUNCTION__ "()\n"); qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ + qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ irda_qos_bits_to_value(qos); MOD_INC_USE_COUNT; @@ -83,6 +83,11 @@ /* Power off dongle */ self->set_dtr_rts(self->dev, FALSE, FALSE); + if (self->reset_task) + irda_task_delete(self->reset_task); + if (self->speed_task) + irda_task_delete(self->speed_task); + MOD_DEC_USE_COUNT; } @@ -113,6 +118,12 @@ ASSERT(task != NULL, return -1;); + if (self->speed_task && self->speed_task != task) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(10); + } else + self->speed_task = task; + switch (speed) { default: case 9600: @@ -128,19 +139,12 @@ byte = TEKRAM_PW|TEKRAM_57600; break; case 115200: - byte = TEKRAM_PW|TEKRAM_115200; + byte = TEKRAM_115200; break; } switch (task->state) { case IRDA_TASK_INIT: - /* Lock dongle */ - if (irda_lock((void *) &self->busy) == FALSE) { - IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); - return MSECS_TO_JIFFIES(100); - } - irda_task_next_state(task, IRDA_TASK_CHILD_INIT); - break; case IRDA_TASK_CHILD_INIT: /* * Need to reset the dongle and go to 9600 bps before @@ -166,7 +170,7 @@ self->set_dtr_rts(self->dev, TRUE, FALSE); /* Wait at least 7us */ - udelay(10); + udelay(14); /* Write control byte */ self->write(self->dev, &byte, 1); @@ -174,19 +178,19 @@ irda_task_next_state(task, IRDA_TASK_WAIT); /* Wait at least 100 ms */ - ret = MSECS_TO_JIFFIES(100); + ret = MSECS_TO_JIFFIES(150); break; case IRDA_TASK_WAIT: /* Set DTR, Set RTS */ self->set_dtr_rts(self->dev, TRUE, TRUE); irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; + self->speed_task = NULL; break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); - self->busy = 0; + self->speed_task = NULL; ret = -1; break; } @@ -214,9 +218,16 @@ IRDA_DEBUG(2, __FUNCTION__ "()\n"); ASSERT(task != NULL, return -1;); + + if (self->reset_task && self->reset_task != task) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(10); + } else + self->reset_task = task; /* Power off dongle */ - self->set_dtr_rts(self->dev, FALSE, FALSE); + //self->set_dtr_rts(self->dev, FALSE, FALSE); + self->set_dtr_rts(self->dev, TRUE, TRUE); switch (task->state) { case IRDA_TASK_INIT: @@ -231,21 +242,23 @@ irda_task_next_state(task, IRDA_TASK_WAIT2); - /* Should sleep 1 ms, but 10 should not do any harm */ - ret = MSECS_TO_JIFFIES(10); + /* Should sleep 1 ms */ + ret = MSECS_TO_JIFFIES(1); break; case IRDA_TASK_WAIT2: /* Set DTR, Set RTS */ self->set_dtr_rts(self->dev, TRUE, TRUE); - udelay(50); + /* Wait at least 50 us */ + udelay(75); irda_task_next_state(task, IRDA_TASK_DONE); + self->reset_task = NULL; break; default: ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); irda_task_next_state(task, IRDA_TASK_DONE); - + self->reset_task = NULL; ret = -1; } return ret; diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.3.34/linux/drivers/net/irda/toshoboe.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/toshoboe.c Tue Dec 21 10:17:31 1999 @@ -7,6 +7,8 @@ * Status: Experimental. * Author: James McKenzie * Created at: Sat May 8 12:35:27 1999 + * Modified: Paul Bristow + * Modified: Mon Nov 11 19:10:05 1999 * * Copyright (c) 1999 James McKenzie, All Rights Reserved. * @@ -28,7 +30,7 @@ /* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */ /* an hp printer, this works fine at 4MBPS with my HP printer */ -static char *rcsid = "$Id: toshoboe.c,v 1.9 1999/06/29 14:21:06 root Exp $"; +static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $"; /* * $Log: toshoboe.c,v $ @@ -65,7 +67,7 @@ /* Toshiba's drivers do this, but it disables back to back tansfers */ /* I think that the chip may have some problems certainly, I have */ /* seen it jump over tasks in the taskfile->xmit with this turned on */ -#define ONETASK +#define ONETASK /* To adjust the number of tasks in use edit toshoboe.h */ @@ -84,7 +86,6 @@ /* No user servicable parts below here */ -#include #include #include @@ -147,7 +148,7 @@ unsigned long flags; IRDA_DEBUG (4, __FUNCTION__ "()\n"); - printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud); + printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud); save_flags (flags); cli (); @@ -206,6 +207,7 @@ outb_p (0x80, OBOE_RST); outb_p (0x01, OBOE_REG_9); + self->io.speed = baud; } /* Wake the chip up and get it looking at the taskfile */ @@ -407,6 +409,7 @@ if (self->new_speed) { toshoboe_setbaud(self, self->new_speed); + self->new_speed = 0; } self->netdev->tbusy = 0; /* Unlock */ @@ -450,8 +453,6 @@ "(), memory squeeze, dropping frame.\n"); } - - self->taskfile->recv[self->rxs].control = 0x83; self->taskfile->recv[self->rxs].len = 0x0; @@ -486,16 +487,6 @@ } static int -toshoboe_is_receiving (struct toshoboe_cb *self) -{ - IRDA_DEBUG (4, __FUNCTION__ "()\n"); - -/*FIXME Can't tell! */ - return (FALSE); -} - - -static int toshoboe_net_init (struct net_device *dev) { IRDA_DEBUG (4, __FUNCTION__ "()\n"); @@ -625,7 +616,51 @@ } +/* + * Function toshoboe_net_ioctl (dev, rq, cmd) + * + * Process IOCTL commands for this device + * + */ +static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct toshoboe_cb *self; + unsigned long flags; + int ret = 0; + + ASSERT(dev != NULL, return -1;); + + self = dev->priv; + + ASSERT(self != NULL, return -1;); + IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + /* toshoboe_setbaud(self, irq->ifr_baudrate); */ + /* Just change speed once - inserted by Paul Bristow */ + self->new_speed = irq->ifr_baudrate; + break; + case SIOCSMEDIABUSY: /* Set media busy */ + irda_device_set_media_busy(self->netdev, TRUE); + break; + case SIOCGRECEIVING: /* Check if we are receiving right now */ + irq->ifr_receiving = 0; /* Can't tell */ + break; + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; +} #ifdef MODULE @@ -667,6 +702,8 @@ rtnl_lock(); unregister_netdevice(self->netdev); rtnl_unlock(); + /* Must free the old-style 2.2.x device */ + kfree(self->netdev); } kfree (self->taskfilebuf); @@ -847,6 +884,7 @@ dev->hard_start_xmit = toshoboe_hard_xmit; dev->open = toshoboe_net_open; dev->stop = toshoboe_net_close; + dev->do_ioctl = toshoboe_net_ioctl; rtnl_lock(); err = register_netdevice(dev); diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- v2.3.34/linux/drivers/net/irda/w83977af_ir.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/irda/w83977af_ir.c Tue Dec 21 10:17:31 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Paul VanderSpek * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Mon Nov 8 10:05:48 1999 + * Modified at: Thu Dec 16 00:52:53 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli @@ -22,7 +22,7 @@ * and at no charge. * * If you find bugs in this file, its very likely that the same bug - * will also be in pc87108.c since the implementations is quite + * will also be in pc87108.c since the implementations are quite * similar. * * Notice that all functions that needs to access the chip in _any_ @@ -62,22 +62,28 @@ #include #include -#define CONFIG_NETWINDER /* Adjust to NetWinder differences */ -#undef CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */ -#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */ -#undef CONFIG_USE_INTERNAL_TIMER /* Just cannot make that timer work */ -#define CONFIG_USE_W977_PNP /* Currently needed */ +#ifdef CONFIG_ARCH_VNC /* Adjust to NetWinder differences */ +#undef CONFIG_VNC_TX_DMA_PROBLEMS /* Not needed */ +#define CONFIG_VNC_RX_DMA_PROBLEMS /* Must have this one! */ +#endif +#undef CONFIG_USE_INTERNAL_TIMER /* Just cannot make that timer work */ +#define CONFIG_USE_W977_PNP /* Currently needed */ #define PIO_MAX_SPEED 115200 static char *driver_name = "w83977af_ir"; -static int qos_mtt_bits = 0x07; /* 1 ms or more */ +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 static unsigned int io[] = { 0x180, ~0, ~0, ~0 }; +#ifdef CONFIG_ARCH_VNC /* Adjust to NetWinder differences */ static unsigned int irq[] = { 6, 0, 0, 0 }; -static unsigned int dma[] = -{ 1, 0, 0, 0 }; +#else +static unsigned int irq[] = { 11, 0, 0, 0 }; +#endif +static unsigned int dma[] = { 1, 0, 0, 0 }; +static unsigned int efbase[] = { W977_EFIO_BASE, W977_EFIO2_BASE }; +static unsigned int efio = W977_EFIO_BASE; static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; @@ -98,6 +104,7 @@ static int w83977af_net_init(struct net_device *dev); static int w83977af_net_open(struct net_device *dev); static int w83977af_net_close(struct net_device *dev); +static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); /* * Function w83977af_init () @@ -248,6 +255,7 @@ dev->hard_start_xmit = w83977af_hard_xmit; dev->open = w83977af_net_open; dev->stop = w83977af_net_close; + dev->do_ioctl = w83977af_net_ioctl; rtnl_lock(); err = register_netdev(dev); @@ -278,21 +286,23 @@ #ifdef CONFIG_USE_W977_PNP /* enter PnP configuration mode */ - w977_efm_enter(); + w977_efm_enter(efio); - w977_select_device(W977_DEVICE_IR); + w977_select_device(W977_DEVICE_IR, efio); /* Deactivate device */ - w977_write_reg(0x30, 0x00); + w977_write_reg(0x30, 0x00, efio); - w977_efm_exit(); + w977_efm_exit(efio); #endif /* CONFIG_USE_W977_PNP */ /* Remove netdevice */ if (self->netdev) { rtnl_lock(); - unregister_netdev(self->netdev); + unregister_netdevice(self->netdev); rtnl_unlock(); + /* Must free the old-style 2.2.x device */ + kfree(self->netdev); } /* Release the PORT that this driver is using */ @@ -311,100 +321,103 @@ return 0; } -/* - * Function w83977af_probe (iobase, irq, dma) - * - * Returns non-negative on success. - * - */ int w83977af_probe( int iobase, int irq, int dma) { - int version; - - IRDA_DEBUG( 0, __FUNCTION__ "()\n"); + int version; + int i; + + for (i=0; i < 2; i++) { + IRDA_DEBUG( 0, __FUNCTION__ "()\n"); #ifdef CONFIG_USE_W977_PNP - /* Enter PnP configuration mode */ - w977_efm_enter(); - - w977_select_device(W977_DEVICE_IR); - - /* Configure PnP port, IRQ, and DMA channel */ - w977_write_reg(0x60, (iobase >> 8) & 0xff); - w977_write_reg(0x61, (iobase) & 0xff); - - w977_write_reg(0x70, irq); -#ifdef CONFIG_NETWINDER - w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */ + /* Enter PnP configuration mode */ + w977_efm_enter(efbase[i]); + + w977_select_device(W977_DEVICE_IR, efbase[i]); + + /* Configure PnP port, IRQ, and DMA channel */ + w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]); + w977_write_reg(0x61, (iobase) & 0xff, efbase[i]); + + w977_write_reg(0x70, irq, efbase[i]); +#ifdef CONFIG_ARCH_VNC + /* Netwinder uses 1 higher than Linux */ + w977_write_reg(0x74, dma+1, efbase[i]); #else - w977_write_reg(0x74, dma); -#endif - w977_write_reg(0x75, 0x04); /* Disable Tx DMA */ - - /* Set append hardware CRC, enable IR bank selection */ - w977_write_reg(0xf0, APEDCRC|ENBNKSEL); - - /* Activate device */ - w977_write_reg(0x30, 0x01); - - w977_efm_exit(); -#endif - /* Disable Advanced mode */ - switch_bank(iobase, SET2); - outb(iobase+2, 0x00); - - /* Turn on UART (global) interrupts */ - switch_bank(iobase, SET0); - outb(HCR_EN_IRQ, iobase+HCR); - - /* Switch to advanced mode */ - switch_bank(iobase, SET2); - outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); - - /* Set default IR-mode */ - switch_bank(iobase, SET0); - outb(HCR_SIR, iobase+HCR); - - /* Read the Advanced IR ID */ - switch_bank(iobase, SET3); - version = inb(iobase+AUID); - - /* Should be 0x1? */ - if (0x10 != (version & 0xf0)) { - IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); - return -1; - } - - /* Set FIFO size to 32 */ - switch_bank(iobase, SET2); - outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); - - /* Set FIFO threshold to TX17, RX16 */ - switch_bank(iobase, SET0); - outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR); - - /* Receiver frame length */ - switch_bank(iobase, SET4); - outb(2048 & 0xff, iobase+6); - outb((2048 >> 8) & 0x1f, iobase+7); - - /* - * Init HP HSDL-1100 transceiver. - * - * Set IRX_MSL since we have 2 * receive paths IRRX, and - * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used - * for IRRXH - * - * IRRX pin 37 connected to receiver - * IRTX pin 38 connected to transmitter - * FIRRX pin 39 connected to receiver (IRSL0) - * CIRRX pin 40 connected to pin 37 - */ - switch_bank(iobase, SET7); - outb(0x40, iobase+7); - - IRDA_DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); - - return 0; + w977_write_reg(0x74, dma, efbase[i]); +#endif /*CONFIG_ARCH_VNC */ + w977_write_reg(0x75, 0x04, efbase[i]); /* Disable Tx DMA */ + + /* Set append hardware CRC, enable IR bank selection */ + w977_write_reg(0xf0, APEDCRC|ENBNKSEL, efbase[i]); + + /* Activate device */ + w977_write_reg(0x30, 0x01, efbase[i]); + + w977_efm_exit(efbase[i]); +#endif /* CONFIG_USE_W977_PNP */ + /* Disable Advanced mode */ + switch_bank(iobase, SET2); + outb(iobase+2, 0x00); + + /* Turn on UART (global) interrupts */ + switch_bank(iobase, SET0); + outb(HCR_EN_IRQ, iobase+HCR); + + /* Switch to advanced mode */ + switch_bank(iobase, SET2); + outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); + + /* Set default IR-mode */ + switch_bank(iobase, SET0); + outb(HCR_SIR, iobase+HCR); + + /* Read the Advanced IR ID */ + switch_bank(iobase, SET3); + version = inb(iobase+AUID); + + /* Should be 0x1? */ + if (0x10 == (version & 0xf0)) { + efio = efbase[i]; + + /* Set FIFO size to 32 */ + switch_bank(iobase, SET2); + outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + + /* Set FIFO threshold to TX17, RX16 */ + switch_bank(iobase, SET0); + outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST| + UFR_EN_FIFO,iobase+UFR); + + /* Receiver frame length */ + switch_bank(iobase, SET4); + outb(2048 & 0xff, iobase+6); + outb((2048 >> 8) & 0x1f, iobase+7); + + /* + * Init HP HSDL-1100 transceiver. + * + * Set IRX_MSL since we have 2 * receive paths IRRX, + * and IRRXH. Clear IRSL0D since we want IRSL0 * to + * be a input pin used for IRRXH + * + * IRRX pin 37 connected to receiver + * IRTX pin 38 connected to transmitter + * FIRRX pin 39 connected to receiver (IRSL0) + * CIRRX pin 40 connected to pin 37 + */ + switch_bank(iobase, SET7); + outb(0x40, iobase+7); + + MESSAGE("W83977AF (IR) driver loaded. " + "Version: 0x%02x\n", version); + + return 0; + } else { + /* Try next extented function register address */ + IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); + } + } + return -1; } void w83977af_change_speed(struct w83977af_ir *self, __u32 speed) @@ -576,7 +589,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase) { __u8 set; -#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS +#ifdef CONFIG_VNC_TX_DMA_PROBLEMS unsigned long flags; __u8 hcr; #endif @@ -592,7 +605,7 @@ /* Choose transmit DMA channel */ switch_bank(iobase, SET2); outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1); -#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS +#ifdef CONFIG_VNC_TX_DMA_PROBLEMS save_flags(flags); cli(); @@ -609,7 +622,7 @@ /* Enable DMA */ switch_bank(iobase, SET0); -#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS +#ifdef CONFIG_VNC_TX_DMA_PROBLEMS hcr = inb(iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR); enable_dma(self->io.dma); @@ -653,7 +666,7 @@ } IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); + fifo_size, actual, len); /* Restore bank */ outb(set, iobase+SSR); @@ -725,7 +738,7 @@ { int iobase; __u8 set; -#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS +#ifdef CONFIG_VNC_RX_DMA_PROBLEMS unsigned long flags; __u8 hcr; #endif @@ -751,7 +764,7 @@ self->io.direction = IO_RECV; self->rx_buff.data = self->rx_buff.head; -#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS +#ifdef CONFIG_VNC_RX_DMA_PROBLEMS save_flags(flags); cli(); @@ -775,7 +788,7 @@ /* Enable DMA */ switch_bank(iobase, SET0); -#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS +#ifdef CONFIG_VNC_RX_DMA_PROBLEMS hcr = inb(iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR); enable_dma(self->io.dma); @@ -985,6 +998,14 @@ self->netdev->tbusy = 0; /* Unlock */ self->stats.tx_packets++; + /* Check if we need to change the speed? */ + if (self->new_speed) { + IRDA_DEBUG(2, __FUNCTION__ + "(), Changing speed!\n"); + w83977af_change_speed(self, self->new_speed); + self->new_speed = 0; + } + /* Schedule network layer */ mark_bh(NET_BH); @@ -1207,7 +1228,7 @@ iobase = self->io.iobase; if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, - (void *) dev)) { + (void *) dev)) { return -EAGAIN; } /* @@ -1289,7 +1310,7 @@ switch_bank(iobase, SET0); outb(0, iobase+ICR); - free_irq(self->io.irq, self); + free_irq(self->io.irq, dev); free_dma(self->io.dma); /* Restore bank register */ @@ -1298,6 +1319,50 @@ MOD_DEC_USE_COUNT; return 0; +} + +/* + * Function w83977af_net_ioctl (dev, rq, cmd) + * + * Process IOCTL commands for this device + * + */ +static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct w83977af_ir *self; + unsigned long flags; + int ret = 0; + + ASSERT(dev != NULL, return -1;); + + self = dev->priv; + + ASSERT(self != NULL, return -1;); + + IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + w83977af_change_speed(self, irq->ifr_baudrate); + break; + case SIOCSMEDIABUSY: /* Set media busy */ + irda_device_set_media_busy(self->netdev, TRUE); + break; + case SIOCGRECEIVING: /* Check if we are receiving right now */ + irq->ifr_receiving = w83977af_is_receiving(self); + break; + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; } #ifdef MODULE diff -u --recursive --new-file v2.3.34/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c --- v2.3.34/linux/drivers/net/myri_sbus.c Thu Nov 11 20:11:41 1999 +++ linux/drivers/net/myri_sbus.c Mon Dec 20 22:06:42 1999 @@ -1,10 +1,10 @@ /* myri_sbus.h: MyriCOM MyriNET SBUS card driver. * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) */ static char *version = - "myri_sbus.c:v1.0 10/Dec/96 David S. Miller (davem@caipfs.rutgers.edu)\n"; + "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n"; #include @@ -92,73 +92,79 @@ static struct myri_eth *root_myri_dev = NULL; #endif -static inline void myri_reset_off(struct lanai_regs *lp, struct myri_control *cregs) +static void myri_reset_off(unsigned long lp, unsigned long cregs) { - lp->eimask = 0; /* Clear IRQ mask. */ - cregs->ctrl = CONTROL_ROFF; /* Turn RESET function off. */ + /* Clear IRQ mask. */ + sbus_writel(0, lp + LANAI_EIMASK); + + /* Turn RESET function off. */ + sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL); } -static inline void myri_reset_on(struct myri_control *cregs) +static void myri_reset_on(unsigned long cregs) { - cregs->ctrl = CONTROL_RON; /* Enable RESET function. */ - cregs->ctrl = CONTROL_DIRQ; /* Disable IRQ's. */ + /* Enable RESET function. */ + sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL); + + /* Disable IRQ's. */ + sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL); } -static inline void myri_disable_irq(struct lanai_regs *lp, struct myri_control *cregs) +static void myri_disable_irq(unsigned long lp, unsigned long cregs) { - cregs->ctrl = CONTROL_DIRQ; - lp->eimask = 0; - lp->istat = ISTAT_HOST; + sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL); + sbus_writel(0, lp + LANAI_EIMASK); + sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT); } -static inline void myri_enable_irq(struct lanai_regs *lp, struct myri_control *cregs) +static void myri_enable_irq(unsigned long lp, unsigned long cregs) { - cregs->ctrl = CONTROL_EIRQ; - lp->eimask = ISTAT_HOST; + sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL); + sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK); } static inline void bang_the_chip(struct myri_eth *mp) { struct myri_shmem *shmem = mp->shmem; - struct myri_control *cregs = mp->cregs; + unsigned long cregs = mp->cregs; - shmem->send = 1; - cregs->ctrl = CONTROL_WON; + sbus_writel(1, &shmem->send); + sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL); } -static inline int myri_do_handshake(struct myri_eth *mp) +static int myri_do_handshake(struct myri_eth *mp) { struct myri_shmem *shmem = mp->shmem; - struct myri_control *cregs = mp->cregs; + unsigned long cregs = mp->cregs; struct myri_channel *chan = &shmem->channel; int tick = 0; DET(("myri_do_handshake: ")); - if(chan->state == STATE_READY) { + if (sbus_readl(&chan->state) == STATE_READY) { DET(("Already STATE_READY, failed.\n")); return -1; /* We're hosed... */ } myri_disable_irq(mp->lregs, cregs); - while(tick++ <= 25) { - unsigned int softstate; + while (tick++ <= 25) { + u32 softstate; /* Wake it up. */ DET(("shakedown, CONTROL_WON, ")); - shmem->shakedown = 1; - cregs->ctrl = CONTROL_WON; + sbus_writel(1, &shmem->shakedown); + sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL); - softstate = chan->state; + softstate = sbus_readl(&chan->state); DET(("chanstate[%08x] ", softstate)); - if(softstate == STATE_READY) { + if (softstate == STATE_READY) { DET(("wakeup successful, ")); break; } - if(softstate != STATE_WFN) { + if (softstate != STATE_WFN) { DET(("not WFN setting that, ")); - chan->state = STATE_WFN; + sbus_writel(STATE_WFN, &chan->state); } udelay(20); @@ -166,7 +172,7 @@ myri_enable_irq(mp->lregs, cregs); - if(tick > 25) { + if (tick > 25) { DET(("25 ticks we lose, failure.\n")); return -1; } @@ -174,9 +180,9 @@ return 0; } -static inline int myri_load_lanai(struct myri_eth *mp) +static int myri_load_lanai(struct myri_eth *mp) { - struct net_device *dev = mp->dev; + struct net_device *dev = mp->dev; struct myri_shmem *shmem = mp->shmem; unsigned char *rptr; int i; @@ -185,28 +191,30 @@ myri_reset_on(mp->cregs); rptr = (unsigned char *) mp->lanai; - for(i = 0; i < mp->eeprom.ramsz; i++) - rptr[i] = 0; + for (i = 0; i < mp->eeprom.ramsz; i++) + sbus_writeb(0, &rptr[i]); - if(mp->eeprom.cpuvers >= CPUVERS_3_0) - mp->lregs->cval = mp->eeprom.cval; + if (mp->eeprom.cpuvers >= CPUVERS_3_0) + sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL); /* Load executable code. */ - for(i = 0; i < sizeof(lanai4_code); i++) - rptr[(lanai4_code_off * 2) + i] = lanai4_code[i]; + for (i = 0; i < sizeof(lanai4_code); i++) + sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]); /* Load data segment. */ - for(i = 0; i < sizeof(lanai4_data); i++) - rptr[(lanai4_data_off * 2) + i] = lanai4_data[i]; + for (i = 0; i < sizeof(lanai4_data); i++) + sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]); /* Set device address. */ - shmem->addr[0] = shmem->addr[1] = 0; - for(i = 0; i < 6; i++) - shmem->addr[i + 2] = dev->dev_addr[i]; + sbus_writeb(0, &shmem->addr[0]); + sbus_writeb(0, &shmem->addr[1]); + for (i = 0; i < 6; i++) + sbus_writeb(dev->dev_addr[i], + &shmem->addr[i + 2]); /* Set SBUS bursts and interrupt mask. */ - shmem->burst = ((mp->myri_bursts & 0xf8) >> 3); - shmem->imask = SHMEM_IMASK_RX; + sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst); + sbus_writel(SHMEM_IMASK_RX, &shmem->imask); /* Release the LANAI. */ myri_disable_irq(mp->lregs, mp->cregs); @@ -214,22 +222,22 @@ myri_disable_irq(mp->lregs, mp->cregs); /* Wait for the reset to complete. */ - for(i = 0; i < 5000; i++) { - if(shmem->channel.state != STATE_READY) + for (i = 0; i < 5000; i++) { + if (sbus_readl(&shmem->channel.state) != STATE_READY) break; else udelay(10); } - if(i == 5000) - printk("myricom: Chip would not reset after firmware load.\n"); + if (i == 5000) + printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n"); i = myri_do_handshake(mp); - if(i) - printk("myricom: Handshake with LANAI failed.\n"); + if (i) + printk(KERN_ERR "myricom: Handshake with LANAI failed.\n"); - if(mp->eeprom.cpuvers == CPUVERS_4_0) - mp->lregs->vers = 0; + if (mp->eeprom.cpuvers == CPUVERS_4_0) + sbus_writel(0, mp->lregs + LANAI_VERS); return i; } @@ -240,17 +248,31 @@ struct recvq *rq = mp->rq; int i; - rq->tail = rq->head = 0; - for(i = 0; i < (RX_RING_SIZE+1); i++) { - if(mp->rx_skbs[i] != NULL) { + sbus_writel(0, &rq->tail); + sbus_writel(0, &rq->head); + for (i = 0; i < (RX_RING_SIZE+1); i++) { + if (mp->rx_skbs[i] != NULL) { + struct myri_rxd *rxd = &rq->myri_rxd[i]; + u32 dma_addr; + + dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); + sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE); dev_kfree_skb(mp->rx_skbs[i]); mp->rx_skbs[i] = NULL; } } - mp->tx_old = sq->tail = sq->head = 0; - for(i = 0; i < TX_RING_SIZE; i++) { - if(mp->tx_skbs[i] != NULL) { + mp->tx_old = 0; + sbus_writel(0, &sq->tail); + sbus_writel(0, &sq->head); + for (i = 0; i < TX_RING_SIZE; i++) { + if (mp->tx_skbs[i] != NULL) { + struct sk_buff *skb = mp->tx_skbs[i]; + struct myri_txd *txd = &sq->myri_txd[i]; + u32 dma_addr; + + dma_addr = sbus_readl(&txd->myri_gathers[0].addr); + sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3); dev_kfree_skb(mp->tx_skbs[i]); mp->tx_skbs[i] = NULL; } @@ -265,25 +287,28 @@ int gfp_flags = GFP_KERNEL; int i; - if(from_irq || in_interrupt()) + if (from_irq || in_interrupt()) gfp_flags = GFP_ATOMIC; myri_clean_rings(mp); - for(i = 0; i < RX_RING_SIZE; i++) { + for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags); + u32 dma_addr; - if(!skb) + if (!skb) continue; mp->rx_skbs[i] = skb; skb->dev = dev; skb_put(skb, RX_ALLOC_SIZE); - rxd[i].myri_scatters[0].addr = sbus_dvma_addr(skb->data); - rxd[i].myri_scatters[0].len = RX_ALLOC_SIZE; - rxd[i].ctx = i; - rxd[i].num_sg = 1; + + dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE); + sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); + sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); + sbus_writel(i, &rxd[i].ctx); + sbus_writel(1, &rxd[i].num_sg); } - rq->head = 0; - rq->tail = RX_RING_SIZE; + sbus_writel(0, &rq->head); + sbus_writel(RX_RING_SIZE, &rq->tail); } static int myri_init(struct myri_eth *mp, int from_irq) @@ -323,19 +348,22 @@ } #endif -static inline void myri_tx(struct myri_eth *mp, struct net_device *dev) +static void myri_tx(struct myri_eth *mp, struct net_device *dev) { struct sendq *sq = mp->sq; int entry = mp->tx_old; - int limit = sq->head; + int limit = sbus_readl(&sq->head); DTX(("entry[%d] limit[%d] ", entry, limit)); - if(entry == limit) + if (entry == limit) return; - while(entry != limit) { + while (entry != limit) { struct sk_buff *skb = mp->tx_skbs[entry]; + u32 dma_addr; DTX(("SKB[%d] ", entry)); + dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); + sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len); dev_kfree_skb(skb); mp->tx_skbs[entry] = NULL; mp->enet_stats.tx_packets++; @@ -361,17 +389,17 @@ DHDR(("myri_type_trans: ")); dump_ehdr(eth); #endif - if(*eth->h_dest & 1) { - if(memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0) + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; - } else if(dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) { - if(memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) + } else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) { + if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) skb->pkt_type = PACKET_OTHERHOST; } - if(ntohs(eth->h_proto) >= 1536) + if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; rawp = skb->data; @@ -388,36 +416,39 @@ return htons(ETH_P_802_2); } -static inline void myri_rx(struct myri_eth *mp, struct net_device *dev) +static void myri_rx(struct myri_eth *mp, struct net_device *dev) { struct recvq *rq = mp->rq; struct recvq *rqa = mp->rqack; - int entry = rqa->head; - int limit = rqa->tail; + int entry = sbus_readl(&rqa->head); + int limit = sbus_readl(&rqa->tail); int drops; DRX(("entry[%d] limit[%d] ", entry, limit)); - if(entry == limit) + if (entry == limit) return; drops = 0; DRX(("\n")); - while(entry != limit) { + while (entry != limit) { struct myri_rxd *rxdack = &rqa->myri_rxd[entry]; - unsigned int csum = rxdack->csum; - int len = rxdack->myri_scatters[0].len; - int index = rxdack->ctx; + u32 csum = sbus_readl(&rxdack->csum); + int len = sbus_readl(&rxdack->myri_scatters[0].len); + int index = sbus_readl(&rxdack->ctx); struct myri_rxd *rxd = &rq->myri_rxd[rq->tail]; struct sk_buff *skb = mp->rx_skbs[index]; /* Ack it. */ - rqa->head = NEXT_RX(entry); + sbus_writel(NEXT_RX(entry), &rqa->head); /* Check for errors. */ DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum)); - if((len < (ETH_HLEN + MYRI_PAD_LEN)) || (skb->data[0] != MYRI_PAD_LEN)) { + sbus_dma_sync_single(mp->myri_sdev, + sbus_readl(&rxd->myri_scatters[0].addr), + RX_ALLOC_SIZE); + if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) { DRX(("ERROR[")); mp->enet_stats.rx_errors++; - if(len < (ETH_HLEN + MYRI_PAD_LEN)) { + if (len < (ETH_HLEN + MYRI_PAD_LEN)) { DRX(("BAD_LENGTH] ")); mp->enet_stats.rx_length_errors++; } else { @@ -430,37 +461,38 @@ drops++; DRX(("DROP ")); mp->enet_stats.rx_dropped++; - rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data); - rxd->myri_scatters[0].len = RX_ALLOC_SIZE; - rxd->ctx = index; - rxd->num_sg = 1; - rq->tail = NEXT_RX(rq->tail); + sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); + sbus_writel(index, &rxd->ctx); + sbus_writel(1, &rxd->num_sg); + sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail); goto next; } -#ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(sbus_dvma_addr(skb->data), - skb->len, mp->myri_sbus_dev->my_bus); -#endif - DRX(("len[%d] ", len)); - if(len > RX_COPY_THRESHOLD) { + if (len > RX_COPY_THRESHOLD) { struct sk_buff *new_skb; + u32 dma_addr; DRX(("BIGBUFF ")); new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC); - if(!new_skb) { + if (new_skb == NULL) { DRX(("skb_alloc(FAILED) ")); goto drop_it; } + sbus_unmap_single(mp->myri_sdev, + sbus_readl(&rxd->myri_scatters[0].addr), + RX_ALLOC_SIZE); mp->rx_skbs[index] = new_skb; new_skb->dev = dev; skb_put(new_skb, RX_ALLOC_SIZE); - rxd->myri_scatters[0].addr = sbus_dvma_addr(new_skb->data); - rxd->myri_scatters[0].len = RX_ALLOC_SIZE; - rxd->ctx = index; - rxd->num_sg = 1; - rq->tail = NEXT_RX(rq->tail); + dma_addr = sbus_map_single(mp->myri_sdev, + new_skb->data, + RX_ALLOC_SIZE); + sbus_writel(dma_addr, &rxd->myri_scatters[0].addr); + sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); + sbus_writel(index, &rxd->ctx); + sbus_writel(1, &rxd->num_sg); + sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail); /* Trim the original skb for the netif. */ DRX(("trim(%d) ", len)); @@ -469,10 +501,11 @@ struct sk_buff *copy_skb = dev_alloc_skb(len); DRX(("SMALLBUFF ")); - if(!copy_skb) { + if (copy_skb == NULL) { DRX(("dev_alloc_skb(FAILED) ")); goto drop_it; } + /* DMA sync already done above. */ copy_skb->dev = dev; DRX(("resv_and_put ")); skb_put(copy_skb, len); @@ -480,11 +513,10 @@ /* Reuse original ring buffer. */ DRX(("reuse ")); - rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data); - rxd->myri_scatters[0].len = RX_ALLOC_SIZE; - rxd->ctx = index; - rxd->num_sg = 1; - rq->tail = NEXT_RX(rq->tail); + sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); + sbus_writel(index, &rxd->ctx); + sbus_writel(1, &rxd->num_sg); + sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail); skb = copy_skb; } @@ -508,28 +540,28 @@ { struct net_device *dev = (struct net_device *) dev_id; struct myri_eth *mp = (struct myri_eth *) dev->priv; - struct lanai_regs *lregs = mp->lregs; + unsigned long lregs = mp->lregs; struct myri_channel *chan = &mp->shmem->channel; - unsigned int status; + u32 status; - status = lregs->istat; + status = sbus_readl(lregs + LANAI_ISTAT); DIRQ(("myri_interrupt: status[%08x] ", status)); - if(status & ISTAT_HOST) { - unsigned int softstate; + if (status & ISTAT_HOST) { + u32 softstate; DIRQ(("IRQ_DISAB ")); myri_disable_irq(lregs, mp->cregs); dev->interrupt = 1; - softstate = chan->state; + softstate = sbus_readl(&chan->state); DIRQ(("state[%08x] ", softstate)); - if(softstate != STATE_READY) { + if (softstate != STATE_READY) { DIRQ(("myri_not_so_happy ")); myri_is_not_so_happy(mp); } DIRQ(("\nmyri_rx: ")); myri_rx(mp, dev); DIRQ(("\nistat=ISTAT_HOST ")); - lregs->istat = ISTAT_HOST; + sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT); dev->interrupt = 0; DIRQ(("IRQ_ENAB ")); myri_enable_irq(lregs, mp->cregs); @@ -557,25 +589,25 @@ struct myri_eth *mp = (struct myri_eth *) dev->priv; struct sendq *sq = mp->sq; struct myri_txd *txd; - unsigned char *srcptr; unsigned long flags; unsigned int head, tail; int len, entry; + u32 dma_addr; DTX(("myri_start_xmit: ")); myri_tx(mp, dev); - if(dev->tbusy) { + if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; DTX(("tbusy tickssofar[%d] ", tickssofar)); - if(tickssofar < 40) { + if (tickssofar < 40) { DTX(("returning 1\n")); return 1; } else { DTX(("resetting, return 0\n")); - printk("%s: transmit timed out, resetting\n", dev->name); + printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); mp->enet_stats.tx_errors++; myri_init(mp, in_interrupt()); dev->tbusy = 0; @@ -584,23 +616,17 @@ } } - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { DTX(("tbusy, maybe a race? returning 1\n")); printk("%s: Transmitter access conflict.\n", dev->name); return 1; } - -#ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(sbus_dvma_addr(skb->data), - skb->len, mp->myri_sbus_dev->my_bus); -#endif - /* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */ - head = sq->head; - tail = sq->tail; + head = sbus_readl(&sq->head); + tail = sbus_readl(&sq->tail); - if(!TX_BUFFS_AVAIL(head, tail)) { + if (!TX_BUFFS_AVAIL(head, tail)) { DTX(("no buffs available, returning 1\n")); return 1; } @@ -614,34 +640,39 @@ /* XXX Maybe this can go as well. */ len = skb->len; - if(len & 3) { + if (len & 3) { DTX(("len&3 ")); len = (len + 4) & (~3); } - entry = sq->tail; + entry = sbus_readl(&sq->tail); txd = &sq->myri_txd[entry]; mp->tx_skbs[entry] = skb; - txd->myri_gathers[0].addr = sbus_dvma_addr(skb->data); - txd->myri_gathers[0].len = len; - txd->num_sg = 1; - txd->chan = KERNEL_CHANNEL; - txd->len = len; - txd->csum_off = ((unsigned int)-1); - txd->csum_field = 0; - - srcptr = (((unsigned char *) skb->data) + MYRI_PAD_LEN); - if(srcptr[0] & 0x1) { - txd->addr[0] = txd->addr[1] = txd->addr[2] = txd->addr[3] = 0xffff; + /* Must do this before we sbus map it. */ + if (skb->data[MYRI_PAD_LEN] & 0x1) { + sbus_writew(0xffff, &txd->addr[0]); + sbus_writew(0xffff, &txd->addr[1]); + sbus_writew(0xffff, &txd->addr[2]); + sbus_writew(0xffff, &txd->addr[3]); } else { - txd->addr[0] = 0; - txd->addr[1] = (srcptr[0] << 8) | srcptr[1]; - txd->addr[2] = (srcptr[2] << 8) | srcptr[3]; - txd->addr[3] = (srcptr[4] << 8) | srcptr[5]; - } - sq->tail = NEXT_TX(entry); + sbus_writew(0xffff, &txd->addr[0]); + sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]); + sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]); + sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); + } + + dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len); + sbus_writel(dma_addr, &txd->myri_gathers[0].addr); + sbus_writel(len, &txd->myri_gathers[0].len); + sbus_writel(1, &txd->num_sg); + sbus_writel(KERNEL_CHANNEL, &txd->chan); + sbus_writel(len, &txd->len); + sbus_writel((u32)-1, &txd->csum_off); + sbus_writel(0, &txd->csum_field); + + sbus_writel(NEXT_TX(entry), &sq->tail); DTX(("BangTheChip ")); bang_the_chip(mp); @@ -659,8 +690,8 @@ static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); - unsigned char *pad = (unsigned char *)skb_push(skb,MYRI_PAD_LEN); + struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); + unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN); #ifdef DEBUG_HEADER DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1])); @@ -674,13 +705,13 @@ /* Set the protocol type. For a packet of type ETH_P_802_3 we put the length * in here instead. It is up to the 802.2 layer to carry protocol information. */ - if(type != ETH_P_802_3) + if (type != ETH_P_802_3) eth->h_proto = htons(type); else eth->h_proto = htons(len); /* Set the source hardware address. */ - if(saddr) + if (saddr) memcpy(eth->h_source, saddr, dev->addr_len); else memcpy(eth->h_source, dev->dev_addr, dev->addr_len); @@ -688,12 +719,12 @@ /* Anyway, the loopback-device should never use this function... */ if (dev->flags & IFF_LOOPBACK) { int i; - for(i = 0; i < dev->addr_len; i++) + for (i = 0; i < dev->addr_len; i++) eth->h_dest[i] = 0; return(dev->hard_header_len); } - if(daddr) { + if (daddr) { memcpy(eth->h_dest, daddr, dev->addr_len); return dev->hard_header_len; } @@ -706,8 +737,8 @@ */ static int myri_rebuild_header(struct sk_buff *skb) { - unsigned char *pad = (unsigned char *)skb->data; - struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN); + unsigned char *pad = (unsigned char *) skb->data; + struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN); struct net_device *dev = skb->dev; #ifdef DEBUG_HEADER @@ -742,8 +773,8 @@ int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh) { unsigned short type = hh->hh_type; - unsigned char *pad = (unsigned char *)hh->hh_data; - struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN); + unsigned char *pad = (unsigned char *) hh->hh_data; + struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN); struct net_device *dev = neigh->dev; if (type == __constant_htons(ETH_P_802_3)) @@ -862,37 +893,36 @@ } #endif -static inline int myri_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int num) +static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num) { static unsigned version_printed = 0; struct myri_eth *mp; - unsigned char prop_buf[32]; + unsigned char prop_buf[32]; int i; DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num)); dev = init_etherdev(0, sizeof(struct myri_eth)); - if(version_printed++ == 0) + if (version_printed++ == 0) printk(version); printk("%s: MyriCOM MyriNET Ethernet ", dev->name); - dev->base_addr = (long) sdev; mp = (struct myri_eth *) dev->priv; - mp->myri_sbus_dev = sdev; + mp->myri_sdev = sdev; /* Clean out skb arrays. */ - for(i = 0; i < (RX_RING_SIZE + 1); i++) + for (i = 0; i < (RX_RING_SIZE + 1); i++) mp->rx_skbs[i] = NULL; - for(i = 0; i < TX_RING_SIZE; i++) + for (i = 0; i < TX_RING_SIZE; i++) mp->tx_skbs[i] = NULL; /* First check for EEPROM information. */ i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info", (char *)&mp->eeprom, sizeof(struct myri_eeprom)); DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i)); - if(i == 0 || i == -1) { + if (i == 0 || i == -1) { /* No eeprom property, must cook up the values ourselves. */ DET(("No EEPROM: ")); mp->eeprom.bus_type = BUS_TYPE_SBUS; @@ -901,38 +931,38 @@ mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0); DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers, mp->eeprom.cval, mp->eeprom.ramsz)); - if(mp->eeprom.cpuvers == 0) { + if (mp->eeprom.cpuvers == 0) { DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3)); mp->eeprom.cpuvers = CPUVERS_2_3; } - if(mp->eeprom.cpuvers < CPUVERS_3_0) { + if (mp->eeprom.cpuvers < CPUVERS_3_0) { DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n")); mp->eeprom.cval = 0; } - if(mp->eeprom.ramsz == 0) { + if (mp->eeprom.ramsz == 0) { DET(("EEPROM: ramsz == 0, setting to 128k\n")); mp->eeprom.ramsz = (128 * 1024); } i = prom_getproperty(sdev->prom_node, "myrinet-board-id", &prop_buf[0], 10); DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i)); - if((i != 0) && (i != -1)) + if ((i != 0) && (i != -1)) memcpy(&mp->eeprom.id[0], &prop_buf[0], 6); else set_boardid_from_idprom(mp, num); i = prom_getproperty(sdev->prom_node, "fpga_version", &mp->eeprom.fvers[0], 32); DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i)); - if(i == 0 || i == -1) + if (i == 0 || i == -1) memset(&mp->eeprom.fvers[0], 0, 32); - if(mp->eeprom.cpuvers == CPUVERS_4_1) { + if (mp->eeprom.cpuvers == CPUVERS_4_1) { DET(("EEPROM: cpuvers CPUVERS_4_1, ")); - if(mp->eeprom.ramsz == (128 * 1024)) { + if (mp->eeprom.ramsz == (128 * 1024)) { DET(("ramsize 128k, setting to 256k, ")); mp->eeprom.ramsz = (256 * 1024); } - if((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){ + if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){ DET(("changing cval from %08x to %08x ", mp->eeprom.cval, 0x50e450e4)); mp->eeprom.cval = 0x50e450e4; @@ -944,7 +974,7 @@ dump_eeprom(mp); #endif - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i] = mp->eeprom.id[i], i == 5 ? ' ' : ':'); @@ -953,45 +983,36 @@ determine_reg_space_size(mp); /* Map in the MyriCOM register/localram set. */ - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); - if(mp->eeprom.cpuvers < CPUVERS_4_0) { + if (mp->eeprom.cpuvers < CPUVERS_4_0) { /* XXX Makes no sense, if control reg is non-existant this * XXX driver cannot function at all... maybe pre-4.0 is * XXX only a valid version for PCI cards? Ask feldy... */ DET(("Mapping regs for cpuvers < CPUVERS_4_0\n")); - mp->regs = (struct myri_regs *) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - mp->reg_size, "MyriCOM Regs", - sdev->reg_addrs[0].which_io, 0); - if(!mp->regs) { + mp->regs = sbus_ioremap(&sdev->resource[0], 0, + mp->reg_size, "MyriCOM Regs"); + if (!mp->regs) { printk("MyriCOM: Cannot map MyriCOM registers.\n"); return ENODEV; } - mp->lanai = (unsigned short *) (((unsigned long)mp->regs) + (256*1024)); + mp->lanai = (unsigned short *) (mp->regs + (256 * 1024)); mp->lanai3 = (unsigned int *) mp->lanai; - mp->lregs = (struct lanai_regs *) &mp->lanai[0x10000]; + mp->lregs = (unsigned long) &mp->lanai[0x10000]; } else { DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); - mp->cregs = (struct myri_control *) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "MyriCOM Control Regs", - sdev->reg_addrs[0].which_io, 0); - mp->lregs = (struct lanai_regs *) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (256 * 1024), - 0, PAGE_SIZE, "MyriCOM LANAI Regs", - sdev->reg_addrs[0].which_io, 0); + mp->cregs = sbus_ioremap(&sdev->resource[0], 0, + PAGE_SIZE, "MyriCOM Control Regs"); + mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024), + PAGE_SIZE, "MyriCOM LANAI Regs"); mp->lanai = (unsigned short *) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (512 * 1024), - 0, mp->eeprom.ramsz, "MyriCOM SRAM", - sdev->reg_addrs[0].which_io, 0); + sbus_ioremap(&sdev->resource[0], (512 * 1024), + mp->eeprom.ramsz, "MyriCOM SRAM"); mp->lanai3 = (unsigned int *) mp->lanai; } - DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p] lanai3[%p]\n", + DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n", mp->cregs, mp->lregs, mp->lanai, mp->lanai3)); - if(mp->eeprom.cpuvers >= CPUVERS_4_0) + if (mp->eeprom.cpuvers >= CPUVERS_4_0) mp->shmem_base = 0xf000; else mp->shmem_base = 0x8000; @@ -1017,22 +1038,22 @@ myri_reset_on(mp->cregs); /* Get the supported DVMA burst sizes from our SBUS. */ - mp->myri_bursts = prom_getintdefault(mp->myri_sbus_dev->my_bus->prom_node, + mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node, "burst-sizes", 0x00); -#if 1 /* XXX Until sun4m SBUS burst workaround is written. */ - if(sparc_cpu_model == sun4m) + if (!sbus_can_burst64(sdev)) mp->myri_bursts &= ~(DMA_BURST64); -#endif + DET(("MYRI bursts %02x\n", mp->myri_bursts)); /* Encode SBUS interrupt level in second control register. */ i = prom_getint(sdev->prom_node, "interrupts"); - if(i == 0) + if (i == 0) i = 4; DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n", i, (1 << i))); - mp->cregs->irqlvl = (1 << i); + + sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL); mp->dev = dev; dev->open = &myri_open; @@ -1041,12 +1062,11 @@ dev->get_stats = &myri_get_stats; dev->set_multicast_list = &myri_set_multicast; dev->irq = sdev->irqs[0]; - dev->dma = 0; /* Register interrupt handler now. */ DET(("Requesting MYRIcom IRQ line.\n")); - if(request_irq(dev->irq, &myri_interrupt, - SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) { + if (request_irq(dev->irq, &myri_interrupt, + SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) { printk("MyriCOM: Cannot register interrupt handler.\n"); return ENODEV; } @@ -1074,31 +1094,42 @@ return 0; } +static int __init myri_sbus_match(struct sbus_dev *sdev) +{ + char *name = sdev->prom_name; + + if (!strcmp(name, "MYRICOM,mlanai") || + !strcmp(name, "myri")) + return 1; + + return 0; +} + int __init myri_sbus_probe(void) { struct net_device *dev = NULL; - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *bus; + struct sbus_dev *sdev = 0; static int called = 0; int cards = 0, v; - if(called) + if (called) return ENODEV; called++; for_each_sbus(bus) { for_each_sbusdev(sdev, bus) { - if(cards) dev = NULL; - if(!strcmp(sdev->prom_name, "MYRICOM,mlanai") || - !strcmp(sdev->prom_name, "myri")) { + if (cards) + dev = NULL; + if (myri_sbus_match(sdev)) { cards++; DET(("Found myricom myrinet as %s\n", sdev->prom_name)); - if((v = myri_ether_init(dev, sdev, (cards - 1)))) + if ((v = myri_ether_init(dev, sdev, (cards - 1)))) return v; } } } - if(!cards) + if (!cards) return ENODEV; return 0; } @@ -1115,15 +1146,13 @@ void cleanup_module(void) { - struct myri_eth *mp; - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_myri_dev) { - mp = root_myri_dev->next_module; + struct myri_eth *next = root_myri_dev->next_module; unregister_netdev(root_myri_dev->dev); kfree(root_myri_dev->dev); - root_myri_dev = mp; + root_myri_dev = next; } } diff -u --recursive --new-file v2.3.34/linux/drivers/net/myri_sbus.h linux/drivers/net/myri_sbus.h --- v2.3.34/linux/drivers/net/myri_sbus.h Wed Aug 18 11:36:45 1999 +++ linux/drivers/net/myri_sbus.h Mon Dec 20 22:06:42 1999 @@ -6,52 +6,52 @@ #ifndef _MYRI_SBUS_H #define _MYRI_SBUS_H -struct lanai_regs { - volatile unsigned int ipf0; /* Context zero state registers.*/ - volatile unsigned int cur0; - volatile unsigned int prev0; - volatile unsigned int data0; - volatile unsigned int dpf0; - volatile unsigned int ipf1; /* Context one state registers. */ - volatile unsigned int cur1; - volatile unsigned int prev1; - volatile unsigned int data1; - volatile unsigned int dpf1; - volatile unsigned int istat; /* Interrupt status. */ - volatile unsigned int eimask; /* External IRQ mask. */ - volatile unsigned int itimer; /* IRQ timer. */ - volatile unsigned int rtc; /* Real Time Clock */ - volatile unsigned int csum; /* Checksum. */ - volatile unsigned int dma_xaddr; /* SBUS DMA external address. */ - volatile unsigned int dma_laddr; /* SBUS DMA local address. */ - volatile unsigned int dma_ctr; /* SBUS DMA counter. */ - volatile unsigned int rx_dmaptr; /* Receive DMA pointer. */ - volatile unsigned int rx_dmalim; /* Receive DMA limit. */ - volatile unsigned int tx_dmaptr; /* Transmit DMA pointer. */ - volatile unsigned int tx_dmalim; /* Transmit DMA limit. */ - volatile unsigned int tx_dmalimt; /* Transmit DMA limit w/tail. */ - unsigned int _unused0; - volatile unsigned char rbyte; /* Receive byte. */ - unsigned char _unused1[3]; - volatile unsigned short rhalf; /* Receive half-word. */ - unsigned char _unused2[2]; - volatile unsigned int rword; /* Receive word. */ - volatile unsigned int salign; /* Send align. */ - volatile unsigned int ss_sendbyte; /* SingleSend send-byte. */ - volatile unsigned int ss_sendhalf; /* SingleSend send-halfword. */ - volatile unsigned int ss_sendword; /* SingleSend send-word. */ - volatile unsigned int ss_sendt; /* SingleSend special. */ - volatile unsigned int dma_dir; /* DMA direction. */ - volatile unsigned int dma_stat; /* DMA status. */ - volatile unsigned int timeo; /* Timeout register. */ - volatile unsigned int myrinet; /* XXX MAGIC myricom thing */ - volatile unsigned int hwdebug; /* Hardware debugging reg. */ - volatile unsigned int leds; /* LED control. */ - volatile unsigned int vers; /* Version register. */ - volatile unsigned int link_on; /* Link activation reg. */ - unsigned int _unused3[0x17]; - volatile unsigned int cval; /* Clock value register. */ -}; +/* LANAI Registers */ +#define LANAI_IPF0 0x00UL /* Context zero state registers.*/ +#define LANAI_CUR0 0x04UL +#define LANAI_PREV0 0x08UL +#define LANAI_DATA0 0x0cUL +#define LANAI_DPF0 0x10UL +#define LANAI_IPF1 0x14UL /* Context one state registers. */ +#define LANAI_CUR1 0x18UL +#define LANAI_PREV1 0x1cUL +#define LANAI_DATA1 0x20UL +#define LANAI_DPF1 0x24UL +#define LANAI_ISTAT 0x28UL /* Interrupt status. */ +#define LANAI_EIMASK 0x2cUL /* External IRQ mask. */ +#define LANAI_ITIMER 0x30UL /* IRQ timer. */ +#define LANAI_RTC 0x34UL /* Real Time Clock */ +#define LANAI_CSUM 0x38UL /* Checksum. */ +#define LANAI_DMAXADDR 0x3cUL /* SBUS DMA external address. */ +#define LANAI_DMALADDR 0x40UL /* SBUS DMA local address. */ +#define LANAI_DMACTR 0x44UL /* SBUS DMA counter. */ +#define LANAI_RXDMAPTR 0x48UL /* Receive DMA pointer. */ +#define LANAI_RXDMALIM 0x4cUL /* Receive DMA limit. */ +#define LANAI_TXDMAPTR 0x50UL /* Transmit DMA pointer. */ +#define LANAI_TXDMALIM 0x54UL /* Transmit DMA limit. */ +#define LANAI_TXDMALIMT 0x58UL /* Transmit DMA limit w/tail. */ + /* 0x5cUL, reserved */ +#define LANAI_RBYTE 0x60UL /* Receive byte. */ + /* 0x64-->0x6c, reserved */ +#define LANAI_RHALF 0x70UL /* Receive half-word. */ + /* 0x72UL, reserved */ +#define LANAI_RWORD 0x74UL /* Receive word. */ +#define LANAI_SALIGN 0x78UL /* Send align. */ +#define LANAI_SBYTE 0x7cUL /* SingleSend send-byte. */ +#define LANAI_SHALF 0x80UL /* SingleSend send-halfword. */ +#define LANAI_SWORD 0x84UL /* SingleSend send-word. */ +#define LANAI_SSENDT 0x88UL /* SingleSend special. */ +#define LANAI_DMADIR 0x8cUL /* DMA direction. */ +#define LANAI_DMASTAT 0x90UL /* DMA status. */ +#define LANAI_TIMEO 0x94UL /* Timeout register. */ +#define LANAI_MYRINET 0x98UL /* XXX MAGIC myricom thing */ +#define LANAI_HWDEBUG 0x9cUL /* Hardware debugging reg. */ +#define LANAI_LEDS 0xa0UL /* LED control. */ +#define LANAI_VERS 0xa4UL /* Version register. */ +#define LANAI_LINKON 0xa8UL /* Link activation reg. */ + /* 0xac-->0x104, reserved */ +#define LANAI_CVAL 0x108UL /* Clock value register. */ +#define LANAI_REG_SIZE 0x10cUL /* Interrupt status bits. */ #define ISTAT_DEBUG 0x80000000 @@ -82,17 +82,17 @@ #define ISTAT_RECV 0x00000002 #define ISTAT_BRDY 0x00000001 -struct myri_regs { - volatile unsigned int reset_off; - volatile unsigned int reset_on; - volatile unsigned int irq_off; - volatile unsigned int irq_on; - volatile unsigned int wakeup_off; - volatile unsigned int wakeup_on; - volatile unsigned int irq_read; - unsigned int _unused[0xfff9]; - volatile unsigned short local_mem[0x10800]; -}; +/* MYRI Registers */ +#define MYRI_RESETOFF 0x00UL +#define MYRI_RESETON 0x04UL +#define MYRI_IRQOFF 0x08UL +#define MYRI_IRQON 0x0cUL +#define MYRI_WAKEUPOFF 0x10UL +#define MYRI_WAKEUPON 0x14UL +#define MYRI_IRQREAD 0x18UL + /* 0x1c-->0x3ffc, reserved */ +#define MYRI_LOCALMEM 0x4000UL +#define MYRI_REG_SIZE 0x25000UL /* Shared memory interrupt mask. */ #define SHMEM_IMASK_RX 0x00000002 @@ -131,10 +131,10 @@ #define CPUVERS_4_2 0x0402 #define CPUVERS_5_0 0x0500 -struct myri_control { - volatile unsigned short ctrl; - volatile unsigned short irqlvl; -}; +/* MYRI Control Registers */ +#define MYRICTRL_CTRL 0x00UL +#define MYRICTRL_IRQLVL 0x02UL +#define MYRICTRL_REG_SIZE 0x04UL /* Global control register defines. */ #define CONTROL_ROFF 0x8000 /* Reset OFF. */ @@ -147,25 +147,25 @@ #define MYRI_GATHER_ENTRIES 16 struct myri_sglist { - unsigned int addr; - unsigned int len; + u32 addr; + u32 len; }; struct myri_rxd { struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES]; /* DMA scatter list.*/ - unsigned int csum; /* HW computed checksum. */ - unsigned int ctx; - unsigned int num_sg; /* Total scatter entries. */ + u32 csum; /* HW computed checksum. */ + u32 ctx; + u32 num_sg; /* Total scatter entries. */ }; struct myri_txd { struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list. */ - unsigned int num_sg; /* Total scatter entries. */ - unsigned short addr[4]; /* XXX address */ - unsigned int chan; - unsigned int len; /* Total length of packet. */ - unsigned int csum_off; /* Where data to csum is. */ - unsigned int csum_field; /* Where csum goes in pkt. */ + u32 num_sg; /* Total scatter entries. */ + u16 addr[4]; /* XXX address */ + u32 chan; + u32 len; /* Total length of packet. */ + u32 csum_off; /* Where data to csum is. */ + u32 csum_field; /* Where csum goes in pkt. */ }; #define MYRINET_MTU 8432 @@ -185,6 +185,7 @@ /* GRRR... */ static __inline__ int NEXT_RX(int num) { + /* XXX >=??? */ if(++num > RX_RING_SIZE) num = 0; return num; @@ -206,44 +207,44 @@ (head) - (tail) - 1) struct sendq { - unsigned int tail; - unsigned int head; - unsigned int hdebug; - unsigned int mdebug; + u32 tail; + u32 head; + u32 hdebug; + u32 mdebug; struct myri_txd myri_txd[TX_RING_MAXSIZE]; }; struct recvq { - unsigned int head; - unsigned int tail; - unsigned int hdebug; - unsigned int mdebug; + u32 head; + u32 tail; + u32 hdebug; + u32 mdebug; struct myri_rxd myri_rxd[RX_RING_MAXSIZE + 1]; }; #define MYRI_MLIST_SIZE 8 struct mclist { - unsigned int maxlen; - unsigned int len; - unsigned int cache; + u32 maxlen; + u32 len; + u32 cache; struct pair { - unsigned char addr[8]; - unsigned int val; + u8 addr[8]; + u32 val; } mc_pairs[MYRI_MLIST_SIZE]; - unsigned char bcast_addr[8]; + u8 bcast_addr[8]; }; struct myri_channel { - unsigned int state; /* State of the channel. */ - unsigned int busy; /* Channel is busy. */ + u32 state; /* State of the channel. */ + u32 busy; /* Channel is busy. */ struct sendq sendq; /* Device tx queue. */ struct recvq recvq; /* Device rx queue. */ struct recvq recvqa; /* Device rx queue acked. */ - unsigned int rbytes; /* Receive bytes. */ - unsigned int sbytes; /* Send bytes. */ - unsigned int rmsgs; /* Receive messages. */ - unsigned int smsgs; /* Send messages. */ + u32 rbytes; /* Receive bytes. */ + u32 sbytes; /* Send bytes. */ + u32 rmsgs; /* Receive messages. */ + u32 smsgs; /* Send messages. */ struct mclist mclist; /* Device multicast list. */ }; @@ -253,14 +254,14 @@ #define STATE_READY 2 /* Ready. */ struct myri_shmem { - unsigned char addr[8]; /* Board's address. */ - unsigned int nchan; /* Number of channels. */ - unsigned int burst; /* SBUS dma burst enable. */ - unsigned int shakedown; /* DarkkkkStarrr Crashesss... */ - unsigned int send; /* Send wanted. */ - unsigned int imask; /* Interrupt enable mask. */ - unsigned int mlevel; /* Map level. */ - unsigned int debug[4]; /* Misc. debug areas. */ + u8 addr[8]; /* Board's address. */ + u32 nchan; /* Number of channels. */ + u32 burst; /* SBUS dma burst enable. */ + u32 shakedown; /* DarkkkkStarrr Crashesss... */ + u32 send; /* Send wanted. */ + u32 imask; /* Interrupt enable mask. */ + u32 mlevel; /* Map level. */ + u32 debug[4]; /* Misc. debug areas. */ struct myri_channel channel; /* Only one channel on a host. */ }; @@ -269,26 +270,26 @@ * to obtain good cache hit rates. */ struct myri_shmem *shmem; /* Shared data structures. */ - struct myri_control *cregs; /* Control register space. */ + unsigned long cregs; /* Control register space. */ struct recvq *rqack; /* Where we ack rx's. */ struct recvq *rq; /* Where we put buffers. */ struct sendq *sq; /* Where we stuff tx's. */ - struct net_device *dev; /* Linux/NET dev struct. */ + struct net_device *dev; /* Linux/NET dev struct. */ int tx_old; /* To speed up tx cleaning. */ - struct lanai_regs *lregs; /* Quick ptr to LANAI regs. */ + unsigned long lregs; /* Quick ptr to LANAI regs. */ struct sk_buff *rx_skbs[RX_RING_SIZE+1];/* RX skb's */ struct sk_buff *tx_skbs[TX_RING_SIZE]; /* TX skb's */ struct net_device_stats enet_stats; /* Interface stats. */ /* These are less frequently accessed. */ - struct myri_regs *regs; /* MyriCOM register space. */ + unsigned long regs; /* MyriCOM register space. */ unsigned short *lanai; /* View 2 of register space. */ unsigned int *lanai3; /* View 3 of register space. */ unsigned int myri_bursts; /* SBUS bursts. */ struct myri_eeprom eeprom; /* Local copy of EEPROM. */ unsigned int reg_size; /* Size of register space. */ unsigned int shmem_base; /* Offset to shared ram. */ - struct linux_sbus_device *myri_sbus_dev; /* Our SBUS device struct. */ + struct sbus_dev *myri_sdev; /* Our SBUS device struct. */ struct myri_eth *next_module; /* Next in adapter chain. */ }; diff -u --recursive --new-file v2.3.34/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c --- v2.3.34/linux/drivers/net/ptifddi.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/net/ptifddi.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: ptifddi.c,v 1.9 1999/08/20 00:31:07 davem Exp $ +/* $Id: ptifddi.c,v 1.11 1999/10/25 01:50:16 zaitcev Exp $ * ptifddi.c: Network driver for Performance Technologies single-attach * and dual-attach FDDI sbus cards. * @@ -149,7 +149,7 @@ { } -static inline int pti_fddi_init(struct net_device *dev, struct linux_sbus_device *sdev, int num) +static inline int pti_fddi_init(struct net_device *dev, struct sbus_dev *sdev, int num) { static unsigned version_printed = 0; struct ptifddi *pp; @@ -160,34 +160,25 @@ if(version_printed++ == 0) printk(version); - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); - /* Register 0 mapping contains DPRAM. */ - pp->dpram = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, - "PTI FDDI DPRAM", - sdev->reg_addrs[0].which_io, 0); + pp->dpram = (struct dfddi_ram *) sbus_ioremap( + &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; } /* Next, register 1 contains reset byte. */ - pp->reset = sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0, - sdev->reg_addrs[1].reg_size, - "PTI FDDI RESET Byte", - sdev->reg_addrs[1].which_io, 0); + pp->reset = (unsigned char *) sbus_ioremap( + &sdep->resource[1], 0, 1, "PTI FDDI RESET Byte"); if(!pp->reset) { printk("ptiFDDI: Cannot map RESET byte.\n"); return ENODEV; } /* Register 2 contains unreset byte. */ - pp->unreset = sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0, - sdev->reg_addrs[2].reg_size, - "PTI FDDI UNRESET Byte", - sdev->reg_addrs[2].which_io, 0); + pp->unreset = (unsigned char *) sbus_ioremap( + &sdep->resource[2], 0, 1, "PTI FDDI UNRESET Byte"); if(!pp->unreset) { printk("ptiFDDI: Cannot map UNRESET byte.\n"); return ENODEV; @@ -215,8 +206,8 @@ int __init ptifddi_sbus_probe(struct net_device *dev) { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *bus; + struct sbus_dev *sdev = 0; static int called = 0; int cards = 0, v; diff -u --recursive --new-file v2.3.34/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.3.34/linux/drivers/net/sis900.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/sis900.c Sat Dec 25 11:21:15 1999 @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. - Silicon Integrated System Corporation - Revision: 1.05 Aug 7 1999 + Copyright 1999 Silicon Integrated System Corporation + Revision: 1.06.03 Dec 23 1999 Modified from the driver which is originally written by Donald Becker. @@ -18,6 +18,9 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + 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 + Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com) Rev 1.06 Nov. 4 1999 Ollie Lho (ollie@sis.com.tw) Second release Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx Chin-Shan Li (lcs@sis.com.tw) Added AMD Am79c901 HomePNA PHY support @@ -47,7 +50,7 @@ #include "sis900.h" static const char *version = -"sis900.c: v1.06 11/04/99\n"; +"sis900.c: v1.06.03 12/23/99\n"; static int max_interrupt_work = 20; #define sis900_debug debug @@ -221,6 +224,8 @@ if (did_version++ == 0) printk(KERN_INFO "%s", version); + if ((net_dev = init_etherdev(net_dev, 0)) == NULL) + return NULL; /* check to see if we have sane EEPROM */ signature = (u16) read_eeprom(ioaddr, EEPROMSignature); if (signature == 0xffff || signature == 0x0000) { @@ -229,9 +234,6 @@ return NULL; } - if ((net_dev = init_etherdev(net_dev, 0)) == NULL) - return NULL; - printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name, mac->name, ioaddr, irq); @@ -509,7 +511,7 @@ net_dev->start = 1; /* Enable all known interrupts by setting the interrupt mask. */ - outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxOK), ioaddr + imr); + outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr); outl(RxENA, ioaddr + cr); outl(IE, ioaddr + ier); @@ -787,6 +789,7 @@ { struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; long ioaddr = net_dev->base_addr; + int i; printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n", net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr)); @@ -794,14 +797,26 @@ /* Disable interrupts by clearing the interrupt mask. */ outl(0x0000, ioaddr + imr); - sis_priv->cur_rx = 0; + /* discard unsent packets, should this code section be protected by + cli(), sti() ?? */ + sis_priv->dirty_tx = sis_priv->cur_tx = 0; + for (i = 0; i < NUM_TX_DESC; i++) { + if (sis_priv->tx_skbuff[i] != NULL) { + dev_kfree_skb(sis_priv->tx_skbuff[i]); + sis_priv->tx_skbuff[i] = 0; + sis_priv->tx_ring[i].cmdsts = 0; + sis_priv->tx_ring[i].bufptr = 0; + sis_priv->stats.tx_dropped++; + } + } + net_dev->trans_start = jiffies; - sis_priv->stats.tx_errors++; + net_dev->tbusy = sis_priv->tx_full = 0; /* FIXME: Should we restart the transmission thread here ?? */ /* Enable all known interrupts by setting the interrupt mask. */ - outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxOK), ioaddr + imr); + outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr); return; } @@ -876,13 +891,7 @@ do { status = inl(ioaddr + isr); - if (sis900_debug > 3) - printk(KERN_INFO "%s: entering interrupt, " - "original status = %#8.8x, " - "new status = %#8.8x.\n", - net_dev->name, status, inl(ioaddr + isr)); - - if ((status & (HIBERR|TxURN|TxERR|TxOK|RxORN|RxERR|RxOK)) == 0) + if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0) /* nothing intresting happened */ break; @@ -891,7 +900,7 @@ /* Rx interrupt */ sis900_rx(net_dev); - if (status & (TxURN | TxERR | TxOK)) + if (status & (TxURN | TxERR | TxIDLE)) /* Tx interrupt */ sis900_finish_xmit(net_dev); @@ -961,6 +970,9 @@ } else { struct sk_buff * skb; + /* This situation should never happen, but due to + some unknow bugs, it is possible that + we are working on NULL sk_buff :-( */ if (sis_priv->rx_skbuff[entry] == NULL) { printk(KERN_INFO "%s: NULL pointer " "encountered in Rx ring, skipping\n", @@ -1033,7 +1045,9 @@ tx_status = sis_priv->tx_ring[entry].cmdsts; if (tx_status & OWN) { - /* The packet is not transmited yet (owned by hardware) ! */ + /* The packet is not transmited yet (owned by hardware) ! + Note: the interrupt is generated only when Tx Machine + is idle, so this is an almost impossible case */ break; } @@ -1054,8 +1068,6 @@ sis_priv->stats.tx_window_errors++; } else { /* packet successfully transmited */ - if (sis900_debug > 3) - printk(KERN_INFO "Tx Transmit OK\n"); sis_priv->stats.collisions += (tx_status & COLCNT) >> 16; sis_priv->stats.tx_bytes += tx_status & DSIZE; sis_priv->stats.tx_packets++; @@ -1069,8 +1081,8 @@ if (sis_priv->tx_full && net_dev->tbusy && sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) { - /* The ring is no longer full, clear tbusy, tx_full and schedule - more transmission by marking NET_BH */ + /* The ring is no longer full, clear tbusy, tx_full and + schedule more transmission by marking NET_BH */ sis_priv->tx_full = 0; clear_bit(0, (void *)&net_dev->tbusy); mark_bh(NET_BH); @@ -1153,11 +1165,13 @@ { /* what is the correct value of the POLYNOMIAL ?? - Donald Becker use 0x04C11DB7U */ -#define POLYNOMIAL 0x04C11DB6L + Donald Becker use 0x04C11DB7U + Joseph Zbiciak im14u2c@primenet.com gives me the + correct answer, thank you Joe !! */ +#define POLYNOMIAL 0x04C11DB7L u32 crc = 0xffffffff, msb; int i, j; - u8 byte; + u32 byte; for (i = 0; i < 6; i++) { byte = *addr++; @@ -1166,7 +1180,6 @@ crc <<= 1; if (msb ^ (byte & 1)) { crc ^= POLYNOMIAL; - crc |= 1; } byte >>= 1; } @@ -1208,7 +1221,7 @@ /* update Multicast Hash Table in Receive Filter */ for (i = 0; i < 8; i++) { - /* why plus 0x04 ??, I don't know, UNDOCUMENT FEATURE ?? */ ++ /* why plus 0x04 ??, That makes the correct value for hash table. */ outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr); outl(mc_filter[i], ioaddr + rfdr); } diff -u --recursive --new-file v2.3.34/linux/drivers/net/sis900.h linux/drivers/net/sis900.h --- v2.3.34/linux/drivers/net/sis900.h Sun Nov 7 16:37:34 1999 +++ linux/drivers/net/sis900.h Sat Dec 25 11:21:15 1999 @@ -92,8 +92,8 @@ /* recevie FIFO thresholds */ #define RxDRNT_shift 1 -#define RxDRNT_100 24 /* 3/4 FIFO size */ -#define RxDRNT_10 16 /* 1/2 FIFO size */ +#define RxDRNT_100 16 /* 1/2 FIFO size */ +#define RxDRNT_10 24 /* 3/4 FIFO size */ enum sis900_reveive_config_register_bits { RxAEP = 0x80000000, RxARP = 0x40000000, RxATX = 0x10000000, diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c --- v2.3.34/linux/drivers/net/sunbmac.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/sunbmac.c Mon Dec 20 22:06:42 1999 @@ -1,10 +1,11 @@ -/* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. +/* $Id: sunbmac.c,v 1.12 1999/12/15 14:07:58 davem Exp $ + * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. * - * Copyright (C) 1997, 1998 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) */ static char *version = - "sunbmac.c:v1.1 8/Dec/98 David S. Miller (davem@caipfs.rutgers.edu)\n"; + "sunbmac.c:v1.9 11/Sep/99 David S. Miller (davem@redhat.com)\n"; #include @@ -70,84 +71,87 @@ #define QEC_RESET_TRIES 200 -static inline int qec_global_reset(struct qe_globreg *gregs) +static int qec_global_reset(unsigned long gregs) { int tries = QEC_RESET_TRIES; - gregs->ctrl = GLOB_CTRL_RESET; - while(--tries) { - if(gregs->ctrl & GLOB_CTRL_RESET) { + sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL); + while (--tries) { + if (sbus_readl(gregs + GLOB_CTRL) & GLOB_CTRL_RESET) { udelay(20); continue; } break; } - if(tries) + if (tries) return 0; - printk("BigMAC: Cannot reset the QEC.\n"); + printk(KERN_ERR "BigMAC: Cannot reset the QEC.\n"); return -1; } static void qec_init(struct bigmac *bp) { - struct qe_globreg *gregs = bp->gregs; - struct linux_sbus_device *qec_sdev = bp->qec_sbus_dev; - unsigned char bsizes = bp->bigmac_bursts; - unsigned int regval; + unsigned long gregs = bp->gregs; + struct sbus_dev *qec_sdev = bp->qec_sdev; + u8 bsizes = bp->bigmac_bursts; + u32 regval; /* 64byte bursts do not work at the moment, do * not even try to enable them. -DaveM */ - if(bsizes & DMA_BURST32) + if (bsizes & DMA_BURST32) regval = GLOB_CTRL_B32; else regval = GLOB_CTRL_B16; - gregs->ctrl = regval | GLOB_CTRL_BMODE; - - gregs->psize = GLOB_PSIZE_2048; + sbus_writel(regval | GLOB_CTRL_BMODE, gregs + GLOB_CTRL); + sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE); /* All of memsize is given to bigmac. */ - gregs->msize = qec_sdev->reg_addrs[1].reg_size; + sbus_writel(qec_sdev->reg_addrs[1].reg_size, + gregs + GLOB_MSIZE); /* Half to the transmitter, half to the receiver. */ - gregs->rsize = gregs->tsize = qec_sdev->reg_addrs[1].reg_size >> 1; + sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, + gregs + GLOB_TSIZE); + sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, + gregs + GLOB_RSIZE); } -/* XXX auto negotiation on these things might not be pleasant... */ - #define TX_RESET_TRIES 32 #define RX_RESET_TRIES 32 -static inline void bigmac_tx_reset(struct BIG_MAC_regs *bregs) +static void bigmac_tx_reset(unsigned long bregs) { int tries = TX_RESET_TRIES; - bregs->tx_cfg = 0; + sbus_writel(0, bregs + BMAC_TXCFG); /* The fifo threshold bit is read-only and does * not clear. -DaveM */ - while((bregs->tx_cfg & ~(BIGMAC_TXCFG_FIFO)) != 0 && - --tries != 0) + while ((sbus_readl(bregs + BMAC_TXCFG) & ~(BIGMAC_TXCFG_FIFO)) != 0 && + --tries != 0) udelay(20); - if(!tries) { - printk("BIGMAC: Transmitter will not reset.\n"); - printk("BIGMAC: tx_cfg is %08x\n", bregs->tx_cfg); + if (!tries) { + printk(KERN_ERR "BIGMAC: Transmitter will not reset.\n"); + printk(KERN_ERR "BIGMAC: tx_cfg is %08x\n", + sbus_readl(bregs + BMAC_TXCFG)); } } -static inline void bigmac_rx_reset(struct BIG_MAC_regs *bregs) +static void bigmac_rx_reset(unsigned long bregs) { int tries = RX_RESET_TRIES; - bregs->rx_cfg = 0; - while((bregs->rx_cfg) && --tries) + sbus_writel(0, bregs + BMAC_RXCFG); + while (sbus_readl(bregs + BMAC_RXCFG) && --tries) udelay(20); - if(!tries) { - printk("BIGMAC: Receiver will not reset.\n"); - printk("BIGMAC: rx_cfg is %08x\n", bregs->rx_cfg); + if (!tries) { + printk(KERN_ERR "BIGMAC: Receiver will not reset.\n"); + printk(KERN_ERR "BIGMAC: rx_cfg is %08x\n", + sbus_readl(bregs + BMAC_RXCFG)); } } @@ -158,38 +162,41 @@ bigmac_rx_reset(bp->bregs); } -static void bigmac_get_counters(struct bigmac *bp, struct BIG_MAC_regs *bregs) +static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs) { struct enet_statistics *stats = &bp->enet_stats; - stats->rx_crc_errors += bregs->rcrce_ctr; - bregs->rcrce_ctr = 0; + stats->rx_crc_errors += sbus_readl(bregs + BMAC_RCRCECTR); + sbus_writel(0, bregs + BMAC_RCRCECTR); - stats->rx_frame_errors += bregs->unale_ctr; - bregs->unale_ctr = 0; + stats->rx_frame_errors += sbus_readl(bregs + BMAC_UNALECTR); + sbus_writel(0, bregs + BMAC_UNALECTR); - stats->rx_length_errors += bregs->gle_ctr; - bregs->gle_ctr = 0; + stats->rx_length_errors += sbus_readl(bregs + BMAC_GLECTR); + sbus_writel(0, bregs + BMAC_GLECTR); - stats->tx_aborted_errors += bregs->ex_ctr; + stats->tx_aborted_errors += sbus_readl(bregs + BMAC_EXCTR); - stats->collisions += (bregs->ex_ctr + bregs->lt_ctr); - bregs->ex_ctr = bregs->lt_ctr = 0; + stats->collisions += + (sbus_readl(bregs + BMAC_EXCTR) + + sbus_readl(bregs + BMAC_LTCTR)); + sbus_writel(0, bregs + BMAC_EXCTR); + sbus_writel(0, bregs + BMAC_LTCTR); } -static inline void bigmac_clean_rings(struct bigmac *bp) +static void bigmac_clean_rings(struct bigmac *bp) { int i; - for(i = 0; i < RX_RING_SIZE; i++) { - if(bp->rx_skbs[i] != NULL) { + for (i = 0; i < RX_RING_SIZE; i++) { + if (bp->rx_skbs[i] != NULL) { dev_kfree_skb(bp->rx_skbs[i]); bp->rx_skbs[i] = NULL; } } - for(i = 0; i < TX_RING_SIZE; i++) { - if(bp->tx_skbs[i] != NULL) { + for (i = 0; i < TX_RING_SIZE; i++) { + if (bp->tx_skbs[i] != NULL) { dev_kfree_skb(bp->tx_skbs[i]); bp->tx_skbs[i] = NULL; } @@ -202,7 +209,7 @@ struct net_device *dev = bp->dev; int i, gfp_flags = GFP_KERNEL; - if(from_irq || in_interrupt()) + if (from_irq || in_interrupt()) gfp_flags = GFP_ATOMIC; bp->rx_new = bp->rx_old = bp->tx_new = bp->tx_old = 0; @@ -210,12 +217,12 @@ /* Free any skippy bufs left around in the rings. */ bigmac_clean_rings(bp); - /* Now get new skippy bufs for the receive ring. */ - for(i = 0; i < RX_RING_SIZE; i++) { + /* Now get new skbufs for the receive ring. */ + for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; skb = big_mac_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags); - if(!skb) + if (!skb) continue; bp->rx_skbs[i] = skb; @@ -225,125 +232,103 @@ skb_put(skb, ETH_FRAME_LEN); skb_reserve(skb, 34); - bb->be_rxd[i].rx_addr = sbus_dvma_addr(skb->data); + bb->be_rxd[i].rx_addr = + sbus_map_single(bp->bigmac_sdev, skb->data, + RX_BUF_ALLOC_SIZE - 34); bb->be_rxd[i].rx_flags = (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); } - for(i = 0; i < TX_RING_SIZE; i++) + for (i = 0; i < TX_RING_SIZE; i++) bb->be_txd[i].tx_flags = bb->be_txd[i].tx_addr = 0; } -#ifndef __sparc_v9__ -static void sun4c_bigmac_init_rings(struct bigmac *bp) -{ - struct bmac_init_block *bb = bp->bmac_block; - __u32 bbufs_dvma = bp->s4c_buf_dvma; - int i; - - bp->rx_new = bp->rx_old = bp->tx_new = bp->tx_old = 0; - - for(i = 0; i < RX_RING_SIZE; i++) { - bb->be_rxd[i].rx_addr = bbufs_dvma + bbuf_offset(rx_buf, i); - bb->be_rxd[i].rx_flags = - (RXD_OWN | (SUN4C_RX_BUFF_SIZE & RXD_LENGTH)); - } - - for(i = 0; i < TX_RING_SIZE; i++) - bb->be_txd[i].tx_flags = bb->be_txd[i].tx_addr = 0; -} -#endif - #define MGMT_CLKON (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK) #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB) -static inline void idle_transceiver(struct bmac_tcvr *tregs) +static void idle_transceiver(unsigned long tregs) { - volatile unsigned int garbage; int i = 20; - while(i--) { - tregs->mgmt_pal = MGMT_CLKOFF; - garbage = tregs->mgmt_pal; - tregs->mgmt_pal = MGMT_CLKON; - garbage = tregs->mgmt_pal; + while (i--) { + sbus_writel(MGMT_CLKOFF, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + sbus_writel(MGMT_CLKON, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); } } -static void write_tcvr_bit(struct bigmac *bp, struct bmac_tcvr *tregs, int bit) +static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit) { - volatile unsigned int garbage; - - if(bp->tcvr_type == internal) { + if (bp->tcvr_type == internal) { bit = (bit & 1) << 3; - tregs->mgmt_pal = bit | (MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO); - garbage = tregs->mgmt_pal; - tregs->mgmt_pal = bit | (MGMT_PAL_OENAB | - MGMT_PAL_EXT_MDIO | - MGMT_PAL_DCLOCK); - garbage = tregs->mgmt_pal; - } else if(bp->tcvr_type == external) { + sbus_writel(bit | (MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO), + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + sbus_writel(bit | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + } else if (bp->tcvr_type == external) { bit = (bit & 1) << 2; - tregs->mgmt_pal = bit | (MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB); - garbage = tregs->mgmt_pal; - tregs->mgmt_pal = bit | (MGMT_PAL_INT_MDIO | - MGMT_PAL_OENAB | - MGMT_PAL_DCLOCK); - garbage = tregs->mgmt_pal; + sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB, + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB | MGMT_PAL_DCLOCK, + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); } else { - printk("write_tcvr_bit: No transceiver type known!\n"); + printk(KERN_ERR "write_tcvr_bit: No transceiver type known!\n"); } } -static int read_tcvr_bit(struct bigmac *bp, struct bmac_tcvr *tregs) +static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs) { - volatile unsigned int garbage; int retval = 0; - if(bp->tcvr_type == internal) { - tregs->mgmt_pal = MGMT_PAL_EXT_MDIO; - garbage = tregs->mgmt_pal; - tregs->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK; - garbage = tregs->mgmt_pal; - retval = (tregs->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3; - } else if(bp->tcvr_type == external) { - tregs->mgmt_pal = MGMT_PAL_INT_MDIO; - garbage = tregs->mgmt_pal; - tregs->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK; - garbage = tregs->mgmt_pal; - retval = (tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2; + if (bp->tcvr_type == internal) { + sbus_writel(MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + sbus_writel(MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_INT_MDIO) >> 3; + } else if (bp->tcvr_type == external) { + sbus_writel(MGMT_PAL_INT_MDIO, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_EXT_MDIO) >> 2; } else { - printk("read_tcvr_bit: No transceiver type known!\n"); + printk(KERN_ERR "read_tcvr_bit: No transceiver type known!\n"); } return retval; } -static int read_tcvr_bit2(struct bigmac *bp, struct bmac_tcvr *tregs) +static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs) { - volatile unsigned int garbage; int retval = 0; - if(bp->tcvr_type == internal) { - tregs->mgmt_pal = MGMT_PAL_EXT_MDIO; - garbage = tregs->mgmt_pal; - retval = (tregs->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3; - tregs->mgmt_pal = (MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK); - garbage = tregs->mgmt_pal; - } else if(bp->tcvr_type == external) { - tregs->mgmt_pal = MGMT_PAL_INT_MDIO; - garbage = tregs->mgmt_pal; - retval = (tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2; - tregs->mgmt_pal = (MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK); - garbage = tregs->mgmt_pal; + if (bp->tcvr_type == internal) { + sbus_writel(MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_INT_MDIO) >> 3; + sbus_writel(MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + } else if (bp->tcvr_type == external) { + sbus_writel(MGMT_PAL_INT_MDIO, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); + retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_EXT_MDIO) >> 2; + sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); } else { - printk("read_tcvr_bit2: No transceiver type known!\n"); + printk(KERN_ERR "read_tcvr_bit2: No transceiver type known!\n"); } return retval; } -static inline void put_tcvr_byte(struct bigmac *bp, - struct bmac_tcvr *tregs, - unsigned int byte) +static void put_tcvr_byte(struct bigmac *bp, + unsigned long tregs, + unsigned int byte) { int shift = 4; @@ -353,7 +338,7 @@ } while (shift >= 0); } -static void bigmac_tcvr_write(struct bigmac *bp, struct bmac_tcvr *tregs, +static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs, int reg, unsigned short val) { int shift; @@ -366,7 +351,7 @@ break; default: - printk("bigmac_tcvr_read: Whoops, no known transceiver type.\n"); + printk(KERN_ERR "bigmac_tcvr_read: Whoops, no known transceiver type.\n"); return; }; @@ -389,11 +374,11 @@ do { write_tcvr_bit(bp, tregs, (val >> shift) & 1); shift -= 1; - } while(shift >= 0); + } while (shift >= 0); } static unsigned short bigmac_tcvr_read(struct bigmac *bp, - struct bmac_tcvr *tregs, + unsigned long tregs, int reg) { unsigned short retval = 0; @@ -405,7 +390,7 @@ break; default: - printk("bigmac_tcvr_read: Whoops, no known transceiver type.\n"); + printk(KERN_ERR "bigmac_tcvr_read: Whoops, no known transceiver type.\n"); return 0xffff; }; @@ -421,7 +406,7 @@ put_tcvr_byte(bp, tregs, reg); - if(bp->tcvr_type == external) { + if (bp->tcvr_type == external) { int shift = 15; (void) read_tcvr_bit2(bp, tregs); @@ -433,7 +418,7 @@ tmp = read_tcvr_bit2(bp, tregs); retval |= ((tmp & 1) << shift); shift -= 1; - } while(shift >= 0); + } while (shift >= 0); (void) read_tcvr_bit2(bp, tregs); (void) read_tcvr_bit2(bp, tregs); @@ -450,7 +435,7 @@ tmp = read_tcvr_bit(bp, tregs); retval |= ((tmp & 1) << shift); shift -= 1; - } while(shift >= 0); + } while (shift >= 0); (void) read_tcvr_bit(bp, tregs); (void) read_tcvr_bit(bp, tregs); @@ -461,49 +446,47 @@ static void bigmac_tcvr_init(struct bigmac *bp) { - volatile unsigned int garbage; - struct bmac_tcvr *tregs = bp->tregs; + unsigned long tregs = bp->tregs; + u32 mpal; idle_transceiver(tregs); - tregs->mgmt_pal = (MGMT_PAL_INT_MDIO | - MGMT_PAL_EXT_MDIO | - MGMT_PAL_DCLOCK); - garbage = tregs->mgmt_pal; + sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, + tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); /* Only the bit for the present transceiver (internal or * external) will stick, set them both and see what stays. */ - tregs->mgmt_pal = (MGMT_PAL_INT_MDIO | - MGMT_PAL_EXT_MDIO); - garbage = tregs->mgmt_pal; + sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL); + sbus_readl(tregs + TCVR_MPAL); udelay(20); - if(tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) { + mpal = sbus_readl(tregs + TCVR_MPAL); + if (mpal & MGMT_PAL_EXT_MDIO) { bp->tcvr_type = external; - tregs->tcvr_pal = ~(TCVR_PAL_EXTLBACK | - TCVR_PAL_MSENSE | - TCVR_PAL_LTENABLE); - garbage = tregs->tcvr_pal; - } else if(tregs->mgmt_pal & MGMT_PAL_INT_MDIO) { + sbus_writel(~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE), + tregs + TCVR_TPAL); + sbus_readl(tregs + TCVR_TPAL); + } else if (mpal & MGMT_PAL_INT_MDIO) { bp->tcvr_type = internal; - tregs->tcvr_pal = ~(TCVR_PAL_SERIAL | - TCVR_PAL_EXTLBACK | - TCVR_PAL_MSENSE | - TCVR_PAL_LTENABLE); - garbage = tregs->tcvr_pal; + sbus_writel(~(TCVR_PAL_SERIAL | TCVR_PAL_EXTLBACK | + TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE), + tregs + TCVR_TPAL); + sbus_readl(tregs + TCVR_TPAL); } else { - printk("BIGMAC: AIEEE, neither internal nor " + printk(KERN_ERR "BIGMAC: AIEEE, neither internal nor " "external MDIO available!\n"); - printk("BIGMAC: mgmt_pal[%08x] tcvr_pal[%08x]\n", - tregs->mgmt_pal, tregs->tcvr_pal); + printk(KERN_ERR "BIGMAC: mgmt_pal[%08x] tcvr_pal[%08x]\n", + sbus_readl(tregs + TCVR_MPAL), + sbus_readl(tregs + TCVR_TPAL)); } } static int bigmac_init(struct bigmac *, int); -static int try_next_permutation(struct bigmac *bp, struct bmac_tcvr *tregs) +static int try_next_permutation(struct bigmac *bp, unsigned long tregs) { - if(bp->sw_bmcr & BMCR_SPEED100) { + if (bp->sw_bmcr & BMCR_SPEED100) { int timeout; /* Reset the PHY. */ @@ -513,14 +496,14 @@ bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr); timeout = 64; - while(--timeout) { + while (--timeout) { bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR); - if((bp->sw_bmcr & BMCR_RESET) == 0) + if ((bp->sw_bmcr & BMCR_RESET) == 0) break; udelay(20); } - if(timeout == 0) - printk("%s: PHY reset failed.\n", bp->dev->name); + if (timeout == 0) + printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name); bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR); @@ -537,31 +520,31 @@ static void bigmac_timer(unsigned long data) { struct bigmac *bp = (struct bigmac *) data; - struct bmac_tcvr *tregs = bp->tregs; + unsigned long tregs = bp->tregs; int restart_timer = 0; bp->timer_ticks++; - if(bp->timer_state == ltrywait) { + if (bp->timer_state == ltrywait) { bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR); bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR); - if(bp->sw_bmsr & BMSR_LSTATUS) { - printk("%s: Link is now up at %s.\n", + if (bp->sw_bmsr & BMSR_LSTATUS) { + printk(KERN_INFO "%s: Link is now up at %s.\n", bp->dev->name, (bp->sw_bmcr & BMCR_SPEED100) ? "100baseT" : "10baseT"); bp->timer_state = asleep; restart_timer = 0; } else { - if(bp->timer_ticks >= 4) { + if (bp->timer_ticks >= 4) { int ret; ret = try_next_permutation(bp, tregs); - if(ret == -1) { - printk("%s: Link down, cable problem?\n", + if (ret == -1) { + printk(KERN_ERR "%s: Link down, cable problem?\n", bp->dev->name); ret = bigmac_init(bp, 0); - if(ret) { - printk("%s: Error, cannot re-init the " + if (ret) { + printk(KERN_ERR "%s: Error, cannot re-init the " "BigMAC.\n", bp->dev->name); } return; @@ -574,14 +557,14 @@ } } else { /* Can't happens.... */ - printk("%s: Aieee, link timer is asleep but we got one anyways!\n", + printk(KERN_ERR "%s: Aieee, link timer is asleep but we got one anyways!\n", bp->dev->name); restart_timer = 0; bp->timer_ticks = 0; bp->timer_state = asleep; /* foo on you */ } - if(restart_timer != 0) { + if (restart_timer != 0) { bp->bigmac_timer.expires = jiffies + ((12 * HZ)/10); /* 1.2 sec. */ add_timer(&bp->bigmac_timer); } @@ -592,7 +575,7 @@ */ static void bigmac_begin_auto_negotiation(struct bigmac *bp) { - struct bmac_tcvr *tregs = bp->tregs; + unsigned long tregs = bp->tregs; int timeout; /* Grab new software copies of PHY registers. */ @@ -606,14 +589,14 @@ bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr); timeout = 64; - while(--timeout) { + while (--timeout) { bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR); - if((bp->sw_bmcr & BMCR_RESET) == 0) + if ((bp->sw_bmcr & BMCR_RESET) == 0) break; udelay(20); } - if(timeout == 0) - printk("%s: PHY reset failed.\n", bp->dev->name); + if (timeout == 0) + printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name); bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR); @@ -631,9 +614,9 @@ static int bigmac_init(struct bigmac *bp, int from_irq) { - struct qe_globreg *gregs = bp->gregs; - struct qe_creg *cregs = bp->creg; - struct BIG_MAC_regs *bregs = bp->bregs; + unsigned long gregs = bp->gregs; + unsigned long cregs = bp->creg; + unsigned long bregs = bp->bregs; unsigned char *e = &bp->dev->dev_addr[0]; /* Latch current counters into statistics. */ @@ -646,12 +629,7 @@ qec_init(bp); /* Alloc and reset the tx/rx descriptor chains. */ -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - sun4c_bigmac_init_rings(bp); - else -#endif - bigmac_init_rings(bp, from_irq); + bigmac_init_rings(bp, from_irq); /* Initialize the PHY. */ bigmac_tcvr_init(bp); @@ -660,56 +638,67 @@ bigmac_stop(bp); /* Set hardware ethernet address. */ - bregs->mac_addr2 = ((e[4] << 8) | e[5]); - bregs->mac_addr1 = ((e[2] << 8) | e[3]); - bregs->mac_addr0 = ((e[0] << 8) | e[1]); + sbus_writel(((e[4] << 8) | e[5]), bregs + BMAC_MACADDR2); + sbus_writel(((e[2] << 8) | e[3]), bregs + BMAC_MACADDR1); + sbus_writel(((e[0] << 8) | e[1]), bregs + BMAC_MACADDR0); /* Clear the hash table until mc upload occurs. */ - bregs->htable3 = 0; - bregs->htable2 = 0; - bregs->htable1 = 0; - bregs->htable0 = 0; + sbus_writel(0, bregs + BMAC_HTABLE3); + sbus_writel(0, bregs + BMAC_HTABLE2); + sbus_writel(0, bregs + BMAC_HTABLE1); + sbus_writel(0, bregs + BMAC_HTABLE0); /* Enable Big Mac hash table filter. */ - bregs->rx_cfg = (BIGMAC_RXCFG_HENABLE | BIGMAC_RXCFG_FIFO); - + sbus_writel(BIGMAC_RXCFG_HENABLE | BIGMAC_RXCFG_FIFO, + bregs + BMAC_RXCFG); udelay(20); /* Ok, configure the Big Mac transmitter. */ - bregs->tx_cfg = BIGMAC_TXCFG_FIFO; + sbus_writel(BIGMAC_TXCFG_FIFO, bregs + BMAC_TXCFG); /* The HME docs recommend to use the 10LSB of our MAC here. */ - bregs->rand_seed = ((e[5] | e[4] << 8) & 0x3ff); + sbus_writel(((e[5] | e[4] << 8) & 0x3ff), + bregs + BMAC_RSEED); /* Enable the output drivers no matter what. */ - bregs->xif_cfg = (BIGMAC_XCFG_ODENABLE | BIGMAC_XCFG_RESV); + sbus_writel(BIGMAC_XCFG_ODENABLE | BIGMAC_XCFG_RESV, + bregs + BMAC_XIFCFG); /* Tell the QEC where the ring descriptors are. */ - cregs->rxds = bp->bblock_dvma + bib_offset(be_rxd, 0); - cregs->txds = bp->bblock_dvma + bib_offset(be_txd, 0); + sbus_writel(bp->bblock_dvma + bib_offset(be_rxd, 0), + cregs + CREG_RXDS); + sbus_writel(bp->bblock_dvma + bib_offset(be_txd, 0), + cregs + CREG_TXDS); /* Setup the FIFO pointers into QEC local memory. */ - cregs->rxwbufptr = cregs->rxrbufptr = 0; - cregs->txwbufptr = cregs->txrbufptr = gregs->rsize; + sbus_writel(0, cregs + CREG_RXRBUFPTR); + sbus_writel(0, cregs + CREG_RXWBUFPTR); + sbus_writel(sbus_readl(gregs + GLOB_RSIZE), + cregs + CREG_TXRBUFPTR); + sbus_writel(sbus_readl(gregs + GLOB_RSIZE), + cregs + CREG_TXWBUFPTR); /* Tell bigmac what interrupts we don't want to hear about. */ - bregs->imask = (BIGMAC_IMASK_GOTFRAME | BIGMAC_IMASK_SENTFRAME); + sbus_writel(BIGMAC_IMASK_GOTFRAME | BIGMAC_IMASK_SENTFRAME, + bregs + BMAC_IMASK); /* Enable the various other irq's. */ - cregs->rimask = 0; - cregs->timask = 0; - cregs->qmask = 0; - cregs->bmask = 0; + sbus_writel(0, cregs + CREG_RIMASK); + sbus_writel(0, cregs + CREG_TIMASK); + sbus_writel(0, cregs + CREG_QMASK); + sbus_writel(0, cregs + CREG_BMASK); /* Set jam size to a reasonable default. */ - bregs->jsize = DEFAULT_JAMSIZE; + sbus_writel(DEFAULT_JAMSIZE, bregs + BMAC_JSIZE); /* Clear collision counter. */ - cregs->ccnt = 0; + sbus_writel(0, cregs + CREG_CCNT); /* Enable transmitter and receiver. */ - bregs->tx_cfg |= BIGMAC_TXCFG_ENABLE; - bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE; + sbus_writel(sbus_readl(bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE, + bregs + BMAC_TXCFG); + sbus_writel(sbus_readl(bregs + BMAC_RXCFG) | BIGMAC_RXCFG_ENABLE, + bregs + BMAC_RXCFG); /* Ok, start detecting link speed/duplex. */ bigmac_begin_auto_negotiation(bp); @@ -719,39 +708,37 @@ } /* Error interrupts get sent here. */ -static void bigmac_is_medium_rare(struct bigmac *bp, - unsigned int qec_status, - unsigned int bmac_status) -{ - printk("bigmac_is_medium_rare: "); - if(qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) { - if(qec_status & GLOB_STAT_ER) +static void bigmac_is_medium_rare(struct bigmac *bp, u32 qec_status, u32 bmac_status) +{ + printk(KERN_ERR "bigmac_is_medium_rare: "); + if (qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) { + if (qec_status & GLOB_STAT_ER) printk("QEC_ERROR, "); - if(qec_status & GLOB_STAT_BM) + if (qec_status & GLOB_STAT_BM) printk("QEC_BMAC_ERROR, "); } - if(bmac_status & CREG_STAT_ERRORS) { - if(bmac_status & CREG_STAT_BERROR) + if (bmac_status & CREG_STAT_ERRORS) { + if (bmac_status & CREG_STAT_BERROR) printk("BMAC_ERROR, "); - if(bmac_status & CREG_STAT_TXDERROR) + if (bmac_status & CREG_STAT_TXDERROR) printk("TXD_ERROR, "); - if(bmac_status & CREG_STAT_TXLERR) + if (bmac_status & CREG_STAT_TXLERR) printk("TX_LATE_ERROR, "); - if(bmac_status & CREG_STAT_TXPERR) + if (bmac_status & CREG_STAT_TXPERR) printk("TX_PARITY_ERROR, "); - if(bmac_status & CREG_STAT_TXSERR) + if (bmac_status & CREG_STAT_TXSERR) printk("TX_SBUS_ERROR, "); - if(bmac_status & CREG_STAT_RXDROP) + if (bmac_status & CREG_STAT_RXDROP) printk("RX_DROP_ERROR, "); - if(bmac_status & CREG_STAT_RXSMALL) + if (bmac_status & CREG_STAT_RXSMALL) printk("RX_SMALL_ERROR, "); - if(bmac_status & CREG_STAT_RXLERR) + if (bmac_status & CREG_STAT_RXLERR) printk("RX_LATE_ERROR, "); - if(bmac_status & CREG_STAT_RXPERR) + if (bmac_status & CREG_STAT_RXPERR) printk("RX_PARITY_ERROR, "); - if(bmac_status & CREG_STAT_RXSERR) + if (bmac_status & CREG_STAT_RXSERR) printk("RX_SBUS_ERROR, "); } @@ -760,106 +747,83 @@ } /* BigMAC transmit complete service routines. */ -static inline void bigmac_tx(struct bigmac *bp) +static void bigmac_tx(struct bigmac *bp) { struct be_txd *txbase = &bp->bmac_block->be_txd[0]; - struct be_txd *this; int elem = bp->tx_old; DTX(("bigmac_tx: tx_old[%d] ", elem)); - while(elem != bp->tx_new) { + while (elem != bp->tx_new) { struct sk_buff *skb; - - this = &txbase[elem]; + struct be_txd *this = &txbase[elem]; DTX(("this(%p) [flags(%08x)addr(%08x)]", this, this->tx_flags, this->tx_addr)); - if(this->tx_flags & TXD_OWN) + if (this->tx_flags & TXD_OWN) break; skb = bp->tx_skbs[elem]; + bp->enet_stats.tx_packets++; + bp->enet_stats.tx_bytes += skb->len; + sbus_unmap_single(bp->bigmac_sdev, + this->tx_addr, skb->len); + DTX(("skb(%p) ", skb)); bp->tx_skbs[elem] = NULL; dev_kfree_skb(skb); - bp->enet_stats.tx_packets++; elem = NEXT_TX(elem); } DTX((" DONE, tx_old=%d\n", elem)); bp->tx_old = elem; } -#ifndef __sparc_v9__ -static inline void sun4c_bigmac_tx(struct bigmac *bp) -{ - struct be_txd *txbase = &bp->bmac_block->be_txd[0]; - struct be_txd *this; - int elem = bp->tx_old; - - while(elem != bp->tx_new) { - this = &txbase[elem]; - if(this->tx_flags & TXD_OWN) - break; - bp->enet_stats.tx_packets++; - elem = NEXT_TX(elem); - } - bp->tx_old = elem; -} -#endif - /* BigMAC receive complete service routines. */ -static inline void bigmac_rx(struct bigmac *bp) +static void bigmac_rx(struct bigmac *bp) { struct be_rxd *rxbase = &bp->bmac_block->be_rxd[0]; struct be_rxd *this; int elem = bp->rx_new, drops = 0; + u32 flags; this = &rxbase[elem]; - while(!(this->rx_flags & RXD_OWN)) { + while (!((flags = this->rx_flags) & RXD_OWN)) { struct sk_buff *skb; - unsigned int flags = this->rx_flags; int len = (flags & RXD_LENGTH); /* FCS not included */ /* Check for errors. */ - if(len < ETH_ZLEN) { + if (len < ETH_ZLEN) { bp->enet_stats.rx_errors++; bp->enet_stats.rx_length_errors++; drop_it: /* Return it to the BigMAC. */ bp->enet_stats.rx_dropped++; - this->rx_addr = sbus_dvma_addr(bp->rx_skbs[elem]->data); this->rx_flags = - (RXD_OWN | (RX_BUF_ALLOC_SIZE & RXD_LENGTH)); + (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); goto next; } skb = bp->rx_skbs[elem]; -#ifdef NEED_DMA_SYNCHRONIZATION -#ifdef __sparc_v9__ - if ((unsigned long) (skb->data + skb->len) >= MAX_DMA_ADDRESS) { - printk("sunbmac: Bogus DMA buffer address " - "[%016lx]\n", ((unsigned long) skb->data)); - panic("DMA address too large, tell DaveM"); - } -#endif - mmu_sync_dma(sbus_dvma_addr(skb->data), - skb->len, bp->bigmac_sbus_dev->my_bus); -#endif - if(len > RX_COPY_THRESHOLD) { + if (len > RX_COPY_THRESHOLD) { struct sk_buff *new_skb; /* Now refill the entry, if we can. */ new_skb = big_mac_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); - if(!new_skb) { + if (new_skb == NULL) { drops++; goto drop_it; } + sbus_unmap_single(bp->bigmac_sdev, + this->rx_addr, + RX_BUF_ALLOC_SIZE - 34); bp->rx_skbs[elem] = new_skb; new_skb->dev = bp->dev; skb_put(new_skb, ETH_FRAME_LEN); skb_reserve(new_skb, 34); - rxbase[elem].rx_addr = sbus_dvma_addr(new_skb->data); - rxbase[elem].rx_flags = + this->rx_addr = sbus_map_single(bp->bigmac_sdev, + new_skb->data, + RX_BUF_ALLOC_SIZE - 34); + this->rx_flags = (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); /* Trim the original skb for the netif. */ @@ -867,18 +831,19 @@ } else { struct sk_buff *copy_skb = dev_alloc_skb(len + 2); - if(!copy_skb) { + if (copy_skb == NULL) { drops++; goto drop_it; } copy_skb->dev = bp->dev; skb_reserve(copy_skb, 2); skb_put(copy_skb, len); + sbus_dma_sync_single(bp->bigmac_sdev, + this->rx_addr, len); eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0); - /* Reuse otiginal ring buffer. */ - rxbase[elem].rx_addr = sbus_dvma_addr(skb->data); - rxbase[elem].rx_flags = + /* Reuse original ring buffer. */ + this->rx_flags = (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); skb = copy_skb; @@ -888,94 +853,41 @@ skb->protocol = eth_type_trans(skb, bp->dev); netif_rx(skb); bp->enet_stats.rx_packets++; + bp->enet_stats.rx_bytes += len; next: elem = NEXT_RX(elem); this = &rxbase[elem]; } bp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", bp->dev->name); -} - -#ifndef __sparc_v9__ -static inline void sun4c_bigmac_rx(struct bigmac *bp) -{ - struct be_rxd *rxbase = &bp->bmac_block->be_rxd[0]; - struct be_rxd *this; - struct bigmac_buffers *bbufs = bp->sun4c_buffers; - __u32 bbufs_dvma = bp->s4c_buf_dvma; - int elem = bp->rx_new, drops = 0; - - this = &rxbase[elem]; - while(!(this->rx_flags & RXD_OWN)) { - struct sk_buff *skb; - unsigned char *this_bbuf = - bbufs->rx_buf[elem & (SUN4C_RX_RING_SIZE - 1)]; - __u32 this_bbuf_dvma = bbufs_dvma + - bbuf_offset(rx_buf, (elem & (SUN4C_RX_RING_SIZE - 1))); - struct be_rxd *end_rxd = - &rxbase[(elem+SUN4C_RX_RING_SIZE)&(RX_RING_SIZE-1)]; - unsigned int flags = this->rx_flags; - int len = (flags & RXD_LENGTH) - 4; /* FCS not included */ - - /* Check for errors. */ - if(len < ETH_ZLEN) { - bp->enet_stats.rx_errors++; - bp->enet_stats.rx_length_errors++; - bp->enet_stats.rx_dropped++; - } else { - skb = dev_alloc_skb(len + 2); - if(skb == 0) { - drops++; - bp->enet_stats.rx_dropped++; - } else { - skb->dev = bp->dev; - skb_reserve(skb, 2); - skb_put(skb, len); - eth_copy_and_sum(skb, (unsigned char *)this_bbuf, - len, 0); - skb->protocol = eth_type_trans(skb, bp->dev); - netif_rx(skb); - bp->enet_stats.rx_packets++; - } - } - end_rxd->rx_addr = this_bbuf_dvma; - end_rxd->rx_flags = (RXD_OWN | (SUN4C_RX_BUFF_SIZE & RXD_LENGTH)); - - elem = NEXT_RX(elem); - this = &rxbase[elem]; - } - bp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", bp->dev->name); + if (drops) + printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", bp->dev->name); } -#endif static void bigmac_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct bigmac *bp = (struct bigmac *) dev_id; - unsigned int qec_status, bmac_status; + u32 qec_status, bmac_status; DIRQ(("bigmac_interrupt: ")); /* Latch status registers now. */ - bmac_status = bp->creg->stat; - qec_status = bp->gregs->stat; + bmac_status = sbus_readl(bp->creg + CREG_STAT); + qec_status = sbus_readl(bp->gregs + GLOB_STAT); bp->dev->interrupt = 1; DIRQ(("qec_status=%08x bmac_status=%08x\n", qec_status, bmac_status)); - if((qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) || + if ((qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) || (bmac_status & CREG_STAT_ERRORS)) bigmac_is_medium_rare(bp, qec_status, bmac_status); - if(bmac_status & CREG_STAT_TXIRQ) + if (bmac_status & CREG_STAT_TXIRQ) bigmac_tx(bp); - if(bmac_status & CREG_STAT_RXIRQ) + if (bmac_status & CREG_STAT_RXIRQ) bigmac_rx(bp); - if(bp->dev->tbusy && (TX_BUFFS_AVAIL(bp) >= 0)) { + if (bp->dev->tbusy && (TX_BUFFS_AVAIL(bp) > 0)) { bp->dev->tbusy = 0; mark_bh(NET_BH); } @@ -983,59 +895,19 @@ bp->dev->interrupt = 0; } -#ifndef __sparc_v9__ -static void sun4c_bigmac_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct bigmac *bp = (struct bigmac *) dev_id; - unsigned int qec_status, bmac_status; - - /* Latch status registers now. */ - bmac_status = bp->creg->stat; - qec_status = bp->gregs->stat; - - bp->dev->interrupt = 1; - - if(qec_status & (GLOB_STAT_ER | GLOB_STAT_BM) || - (bmac_status & CREG_STAT_ERRORS)) - bigmac_is_medium_rare(bp, qec_status, bmac_status); - - if(bmac_status & CREG_STAT_TXIRQ) - sun4c_bigmac_tx(bp); - - if(bmac_status & CREG_STAT_RXIRQ) - sun4c_bigmac_rx(bp); - - if(bp->dev->tbusy && (SUN4C_TX_BUFFS_AVAIL(bp) >= 0)) { - bp->dev->tbusy = 0; - mark_bh(NET_BH); - } - - bp->dev->interrupt = 0; -} -#endif - static int bigmac_open(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; int res; -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) { - if(request_irq(dev->irq, &sun4c_bigmac_interrupt, - SA_SHIRQ, "BIG MAC", (void *) bp)) { - printk("BIGMAC: Can't order irq %d to go.\n", dev->irq); - return -EAGAIN; - } - } else -#endif - if(request_irq(dev->irq, &bigmac_interrupt, - SA_SHIRQ, "BIG MAC", (void *) bp)) { - printk("BIGMAC: Can't order irq %d to go.\n", dev->irq); + if (request_irq(dev->irq, &bigmac_interrupt, + SA_SHIRQ, "BIG MAC", (void *) bp)) { + printk(KERN_ERR "BIGMAC: Can't order irq %d to go.\n", dev->irq); return -EAGAIN; } init_timer(&bp->bigmac_timer); res = bigmac_init(bp, 0); - if(!res) { + if (!res) { MOD_INC_USE_COUNT; } return res; @@ -1062,13 +934,13 @@ struct bigmac *bp = (struct bigmac *) dev->priv; int len, entry; - if(dev->tbusy) { + if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 40) { return 1; } else { - printk ("%s: transmit timed out, resetting\n", dev->name); + printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); bp->enet_stats.tx_errors++; bigmac_init(bp, 0); dev->tbusy = 0; @@ -1078,110 +950,37 @@ } } - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name); return 1; } - if(!TX_BUFFS_AVAIL(bp)) + if (!TX_BUFFS_AVAIL(bp)) return 1; -#ifdef NEED_DMA_SYNCHRONIZATION -#ifdef __sparc_v9__ - if ((unsigned long) (skb->data + skb->len) >= MAX_DMA_ADDRESS) { - struct sk_buff *new_skb = skb_copy(skb, GFP_DMA | GFP_ATOMIC); - if(!new_skb) - return 1; - dev_kfree_skb(skb); - skb = new_skb; - } -#endif - mmu_sync_dma(sbus_dvma_addr(skb->data), - skb->len, bp->bigmac_sbus_dev->my_bus); -#endif len = skb->len; entry = bp->tx_new; DTX(("bigmac_start_xmit: len(%d) entry(%d)\n", len, entry)); /* Avoid a race... */ bp->bmac_block->be_txd[entry].tx_flags = TXD_UPDATE; - bp->tx_skbs[entry] = skb; - bp->bmac_block->be_txd[entry].tx_addr = sbus_dvma_addr(skb->data); + bp->bmac_block->be_txd[entry].tx_addr = + sbus_map_single(bp->bigmac_sdev, skb->data, len); bp->bmac_block->be_txd[entry].tx_flags = (TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH)); dev->trans_start = jiffies; bp->tx_new = NEXT_TX(entry); /* Get it going. */ - bp->creg->ctrl = CREG_CTRL_TWAKEUP; + sbus_writel(CREG_CTRL_TWAKEUP, bp->creg + CREG_CTRL); - if(TX_BUFFS_AVAIL(bp)) + if (TX_BUFFS_AVAIL(bp)) dev->tbusy = 0; return 0; } -#ifndef __sparc_v9__ -static int sun4c_bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct bigmac *bp = (struct bigmac *) dev->priv; - struct bigmac_buffers *bbufs = bp->sun4c_buffers; - __u32 txbuf_dvma, bbufs_dvma = bp->s4c_buf_dvma; - unsigned char *txbuf; - int len, entry; - - if(dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 40) { - return 1; - } else { - printk ("%s: transmit timed out, resetting\n", dev->name); - bp->enet_stats.tx_errors++; - bigmac_init(bp, 0); - dev->tbusy = 0; - dev->trans_start = jiffies; - return 0; - } - } - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } - - if(!SUN4C_TX_BUFFS_AVAIL(bp)) - return 1; - - len = skb->len; - entry = bp->tx_new; - - txbuf = &bbufs->tx_buf[entry][0]; - txbuf_dvma = bbufs_dvma + bbuf_offset(tx_buf, entry); - memcpy(txbuf, skb->data, len); - - /* Avoid a race... */ - bp->bmac_block->be_txd[entry].tx_flags = TXD_UPDATE; - - bp->bmac_block->be_txd[entry].tx_addr = txbuf_dvma; - bp->bmac_block->be_txd[entry].tx_flags = - (TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH)); - bp->tx_new = NEXT_TX(entry); - - /* Get it going. */ - dev->trans_start = jiffies; - bp->creg->ctrl = CREG_CTRL_TWAKEUP; - - dev_kfree_skb(skb); - - if(SUN4C_TX_BUFFS_AVAIL(bp)) - dev->tbusy = 0; - - return 0; -} -#endif - static struct enet_statistics *bigmac_get_stats(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; @@ -1196,175 +995,140 @@ static void bigmac_set_multicast(struct net_device *dev) { struct bigmac *bp = (struct bigmac *) dev->priv; - struct BIG_MAC_regs *bregs = bp->bregs; + unsigned long bregs = bp->bregs; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; - u32 crc, poly = CRC_POLYNOMIAL_LE; + u32 tmp, crc, poly = CRC_POLYNOMIAL_LE; /* Disable the receiver. The bit self-clears when * the operation is complete. */ - bregs->rx_cfg &= ~(BIGMAC_RXCFG_ENABLE); - while((bregs->rx_cfg & BIGMAC_RXCFG_ENABLE) != 0) + tmp = sbus_readl(bregs + BMAC_RXCFG); + tmp &= ~(BIGMAC_RXCFG_ENABLE); + sbus_writel(tmp, bregs + BMAC_RXCFG); + while ((sbus_readl(bregs + BMAC_RXCFG) & BIGMAC_RXCFG_ENABLE) != 0) udelay(20); - if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { - bregs->htable0 = 0xffff; - bregs->htable1 = 0xffff; - bregs->htable2 = 0xffff; - bregs->htable3 = 0xffff; - } else if(dev->flags & IFF_PROMISC) { - bregs->rx_cfg |= BIGMAC_RXCFG_PMISC; + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + sbus_writel(0xffff, bregs + BMAC_HTABLE0); + sbus_writel(0xffff, bregs + BMAC_HTABLE1); + sbus_writel(0xffff, bregs + BMAC_HTABLE2); + sbus_writel(0xffff, bregs + BMAC_HTABLE3); + } else if (dev->flags & IFF_PROMISC) { + tmp = sbus_readl(bregs + BMAC_RXCFG); + tmp |= BIGMAC_RXCFG_PMISC; + sbus_writel(tmp, bregs + BMAC_RXCFG); } else { u16 hash_table[4]; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < dev->mc_count; i++) { + for (i = 0; i < dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - if(!(*addrs & 1)) + if (!(*addrs & 1)) continue; crc = 0xffffffffU; - for(byte = 0; byte < 6; byte++) { - for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + for (byte = 0; byte < 6; byte++) { + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { int test; test = ((bit ^ crc) & 0x01); crc >>= 1; - if(test) + if (test) crc = crc ^ poly; } } crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } - bregs->htable0 = hash_table[0]; - bregs->htable1 = hash_table[1]; - bregs->htable2 = hash_table[2]; - bregs->htable3 = hash_table[3]; + sbus_writel(hash_table[0], bregs + BMAC_HTABLE0); + sbus_writel(hash_table[1], bregs + BMAC_HTABLE1); + sbus_writel(hash_table[2], bregs + BMAC_HTABLE2); + sbus_writel(hash_table[3], bregs + BMAC_HTABLE3); } /* Re-enable the receiver. */ - bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE; + tmp = sbus_readl(bregs + BMAC_RXCFG); + tmp |= BIGMAC_RXCFG_ENABLE; + sbus_writel(tmp, bregs + BMAC_RXCFG); } -static int __init bigmac_ether_init(struct net_device *dev, struct linux_sbus_device *qec_sdev) +static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec_sdev) { - static unsigned version_printed = 0; + static int version_printed = 0; struct bigmac *bp = 0; - unsigned char bsizes, bsizes_more; - int i, j, num_qranges, res = ENOMEM; - struct linux_prom_ranges qranges[8]; + u8 bsizes, bsizes_more; + int i, res = ENOMEM; /* Get a new device struct for this interface. */ dev = init_etherdev(0, sizeof(struct bigmac)); - if(version_printed++ == 0) - printk(version); + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); /* Report what we have found to the user. */ - printk("%s: BigMAC 100baseT Ethernet ", dev->name); + printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name); dev->base_addr = (long) qec_sdev; - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], i == 5 ? ' ' : ':'); printk("\n"); /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ bp = (struct bigmac *) dev->priv; - bp->qec_sbus_dev = qec_sdev; - bp->bigmac_sbus_dev = qec_sdev->child; + bp->qec_sdev = qec_sdev; + bp->bigmac_sdev = qec_sdev->child; /* All further failures we find return this. */ res = ENODEV; /* Verify the registers we expect, are actually there. */ - if((bp->bigmac_sbus_dev->num_registers != 3) || - (bp->qec_sbus_dev->num_registers != 2)) { - printk("BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n", - bp->qec_sbus_dev->num_registers, - bp->bigmac_sbus_dev->num_registers); - printk("BIGMAC: Would you like that for here or to go?\n"); + if ((bp->bigmac_sdev->num_registers != 3) || + (bp->qec_sdev->num_registers != 2)) { + printk(KERN_ERR "BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n", + bp->qec_sdev->num_registers, + bp->bigmac_sdev->num_registers); + printk(KERN_ERR "BIGMAC: Would you like that for here or to go?\n"); goto fail_and_cleanup; } - /* Fun with QEC ranges... */ - if(bp->bigmac_sbus_dev->ranges_applied == 0) { - i = prom_getproperty(bp->qec_sbus_dev->prom_node, "ranges", - (char *)&qranges[0], sizeof(qranges)); - num_qranges = (i / sizeof(struct linux_prom_ranges)); - - /* Now, apply all the ranges for the BigMAC. */ - for(j = 0; j < bp->bigmac_sbus_dev->num_registers; j++) { - int k; - - for(k = 0; k < num_qranges; k++) - if(bp->bigmac_sbus_dev->reg_addrs[j].which_io == - qranges[k].ot_child_space) - break; - if(k >= num_qranges) { - printk("BigMAC: Aieee, bogus QEC range for space %08x\n", - bp->bigmac_sbus_dev->reg_addrs[j].which_io); - goto fail_and_cleanup; - } - bp->bigmac_sbus_dev->reg_addrs[j].which_io = qranges[k].ot_parent_space; - bp->bigmac_sbus_dev->reg_addrs[j].phys_addr += qranges[k].ot_parent_base; - } - - /* Next, apply SBUS ranges on top of what we just changed. */ - prom_apply_sbus_ranges(bp->bigmac_sbus_dev->my_bus, - &bp->bigmac_sbus_dev->reg_addrs[0], - bp->bigmac_sbus_dev->num_registers, - bp->bigmac_sbus_dev); - } - - /* Apply SBUS ranges for the QEC parent. */ - prom_apply_sbus_ranges(bp->qec_sbus_dev->my_bus, - &bp->qec_sbus_dev->reg_addrs[0], - bp->qec_sbus_dev->num_registers, - bp->qec_sbus_dev); - /* Map in QEC global control registers. */ - bp->gregs = sparc_alloc_io(bp->qec_sbus_dev->reg_addrs[0].phys_addr, - 0, - sizeof(struct qe_globreg), - "BigMAC QEC Global Regs", - bp->qec_sbus_dev->reg_addrs[0].which_io, - 0); - if(!bp->gregs) { - printk("BIGMAC: Cannot map QEC global registers.\n"); + bp->gregs = sbus_ioremap(&bp->qec_sdev->resource[0], 0, + GLOB_REG_SIZE, "BigMAC QEC GLobal Regs"); + if (!bp->gregs) { + printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n"); goto fail_and_cleanup; } /* Make sure QEC is in BigMAC mode. */ - if((bp->gregs->ctrl & 0xf0000000) != GLOB_CTRL_BMODE) { - printk("BigMAC: AIEEE, QEC is not in BigMAC mode!\n"); + if ((sbus_readl(bp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_BMODE) { + printk(KERN_ERR "BigMAC: AIEEE, QEC is not in BigMAC mode!\n"); goto fail_and_cleanup; } /* Reset the QEC. */ - if(qec_global_reset(bp->gregs)) + if (qec_global_reset(bp->gregs)) goto fail_and_cleanup; /* Get supported SBUS burst sizes. */ - bsizes = prom_getintdefault(bp->qec_sbus_dev->prom_node, + bsizes = prom_getintdefault(bp->qec_sdev->prom_node, "burst-sizes", 0xff); - bsizes_more = prom_getintdefault(bp->qec_sbus_dev->my_bus->prom_node, + bsizes_more = prom_getintdefault(bp->qec_sdev->bus->prom_node, "burst-sizes", 0xff); bsizes &= 0xff; - if(bsizes_more != 0xff) + if (bsizes_more != 0xff) bsizes &= bsizes_more; - if(bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || - (bsizes & DMA_BURST32) == 0) + if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || + (bsizes & DMA_BURST32) == 0) bsizes = (DMA_BURST32 - 1); bp->bigmac_bursts = bsizes; @@ -1372,40 +1136,28 @@ qec_init(bp); /* Map in the BigMAC channel registers. */ - bp->creg = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[0].phys_addr, - 0, - sizeof(struct qe_creg), - "BigMAC QEC Channel Regs", - bp->bigmac_sbus_dev->reg_addrs[0].which_io, - 0); - if(!bp->creg) { - printk("BIGMAC: Cannot map QEC channel registers.\n"); + bp->creg = sbus_ioremap(&bp->bigmac_sdev->resource[0], 0, + CREG_REG_SIZE, "BigMAC QEC Channel Regs"); + if (!bp->creg) { + printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n"); goto fail_and_cleanup; } /* Map in the BigMAC control registers. */ - bp->bregs = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[1].phys_addr, - 0, - sizeof(struct BIG_MAC_regs), - "BigMAC Primary Regs", - bp->bigmac_sbus_dev->reg_addrs[1].which_io, - 0); - if(!bp->bregs) { - printk("BIGMAC: Cannot map BigMAC primary registers.\n"); + bp->bregs = sbus_ioremap(&bp->bigmac_sdev->resource[1], 0, + BMAC_REG_SIZE, "BigMAC Primary Regs"); + if (!bp->bregs) { + printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n"); goto fail_and_cleanup; } /* Map in the BigMAC transceiver registers, this is how you poke at * the BigMAC's PHY. */ - bp->tregs = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[2].phys_addr, - 0, - sizeof(struct bmac_tcvr), - "BigMAC Transceiver Regs", - bp->bigmac_sbus_dev->reg_addrs[2].which_io, - 0); - if(!bp->tregs) { - printk("BIGMAC: Cannot map BigMAC transceiver registers.\n"); + bp->tregs = sbus_ioremap(&bp->bigmac_sdev->resource[2], 0, + TCVR_REG_SIZE, "BigMAC Transceiver Regs"); + if (!bp->tregs) { + printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n"); goto fail_and_cleanup; } @@ -1413,27 +1165,18 @@ bigmac_stop(bp); /* Allocate transmit/receive descriptor DVMA block. */ - bp->bmac_block = (struct bmac_init_block *) - sparc_dvma_malloc(PAGE_SIZE, "BigMAC Init Block", - &bp->bblock_dvma); + bp->bmac_block = sbus_alloc_consistant(bp->bigmac_sdev, + PAGE_SIZE, + &bp->bblock_dvma); + if (bp->bmac_block == NULL || bp->bblock_dvma == 0) { + printk(KERN_ERR "BIGMAC: Cannot allocate consistant DMA.\n"); + goto fail_and_cleanup; + } /* Get the board revision of this BigMAC. */ - bp->board_rev = prom_getintdefault(bp->bigmac_sbus_dev->prom_node, + bp->board_rev = prom_getintdefault(bp->bigmac_sdev->prom_node, "board-version", 1); - /* If on sun4c, we use a static buffer pool, on sun4m we DMA directly - * in and out of sk_buffs instead for speed and one copy to userspace. - */ -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - bp->sun4c_buffers = (struct bigmac_buffers *) - sparc_dvma_malloc(sizeof(struct bigmac_buffers), - "BigMAC Bufs", - &bp->s4c_buf_dvma); - else -#endif - bp->sun4c_buffers = 0; - /* Init auto-negotiation timer state. */ init_timer(&bp->bigmac_timer); bp->timer_state = asleep; @@ -1445,21 +1188,14 @@ /* Set links to our BigMAC open and close routines. */ dev->open = &bigmac_open; dev->stop = &bigmac_close; - - /* Choose transmit routine based upon buffering scheme. */ -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - dev->hard_start_xmit = &sun4c_bigmac_start_xmit; - else -#endif - dev->hard_start_xmit = &bigmac_start_xmit; + dev->hard_start_xmit = &bigmac_start_xmit; /* Set links to BigMAC statistic and multi-cast loading code. */ dev->get_stats = &bigmac_get_stats; dev->set_multicast_list = &bigmac_set_multicast; /* Finish net device registration. */ - dev->irq = bp->bigmac_sbus_dev->irqs[0]; + dev->irq = bp->bigmac_sdev->irqs[0]; dev->dma = 0; ether_setup(dev); @@ -1472,18 +1208,22 @@ fail_and_cleanup: /* Something went wrong, undo whatever we did so far. */ - if(bp) { + if (bp) { /* Free register mappings if any. */ - if(bp->gregs) - sparc_free_io(bp->gregs, sizeof(struct qe_globreg)); - if(bp->creg) - sparc_free_io(bp->creg, sizeof(struct qe_creg)); - if(bp->bregs) - sparc_free_io(bp->bregs, sizeof(struct BIG_MAC_regs)); - if(bp->tregs) - sparc_free_io(bp->tregs, sizeof(struct bmac_tcvr)); - - /* XXX todo, bmac_block and sun4c_buffers */ + if (bp->gregs) + sbus_iounmap(bp->gregs, GLOB_REG_SIZE); + if (bp->creg) + sbus_iounmap(bp->creg, CREG_REG_SIZE); + if (bp->bregs) + sbus_iounmap(bp->bregs, BMAC_REG_SIZE); + if (bp->tregs) + sbus_iounmap(bp->tregs, TCVR_REG_SIZE); + + if (bp->bmac_block) + sbus_free_consistant(bp->bigmac_sdev, + PAGE_SIZE, + bp->bmac_block, + bp->bblock_dvma); /* Free the BigMAC softc. */ kfree(bp); @@ -1492,34 +1232,50 @@ return res; /* Return error code. */ } +/* QEC can be the parent of either QuadEthernet or + * a BigMAC. We want the latter. + */ +static int __init bigmac_match(struct sbus_dev *sdev) +{ + struct sbus_dev *child = sdev->child; + + if (strcmp(sdev->prom_name, "qec") != 0) + return 0; + + if (child == NULL) + return 0; + + if (strcmp(child->prom_name, "be") != 0) + return 0; + + return 1; +} + int __init bigmac_probe(void) { struct net_device *dev = NULL; - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; static int called = 0; int cards = 0, v; - if(called) + if (called) return ENODEV; called++; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { - if(cards) dev = NULL; - - /* QEC can be the parent of either QuadEthernet or - * a BigMAC. We want the latter. - */ - if(!strcmp(sdev->prom_name, "qec") && sdev->child && - !strcmp(sdev->child->prom_name, "be")) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (cards) + dev = NULL; + + if (bigmac_match(sdev)) { cards++; - if((v = bigmac_ether_init(dev, sdev))) - return v; + if ((v = bigmac_ether_init(dev, sdev))) + return v; } } } - if(!cards) + if (!cards) return ENODEV; return 0; } @@ -1541,12 +1297,14 @@ struct bigmac *bp = root_bigmac_dev; struct bigmac *bp_nxt = root_bigmac_dev->next_module; - sparc_free_io(bp->gregs, sizeof(struct qe_globreg)); - sparc_free_io(bp->creg, sizeof(struct qe_creg)); - sparc_free_io(bp->bregs, sizeof(struct BIG_MAC_regs)); - sparc_free_io(bp->tregs, sizeof(struct bmac_tcvr)); - - /* XXX todo, bmac_block and sun4c_buffers */ + sbus_iounmap(bp->gregs, GLOB_REG_SIZE); + sbus_iounmap(bp->creg, CREG_REG_SIZE); + sbus_iounmap(bp->bregs, BMAC_REG_SIZE); + sbus_iounmap(bp->tregs, TCVR_REG_SIZE); + sbus_free_consistant(bp->bigmac_sdev, + PAGE_SIZE, + bp->bmac_block, + bp->bblock_dvma); unregister_netdev(bp->dev); kfree(bp->dev); diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunbmac.h linux/drivers/net/sunbmac.h --- v2.3.34/linux/drivers/net/sunbmac.h Wed Aug 18 11:36:45 1999 +++ linux/drivers/net/sunbmac.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,5 @@ -/* sunbmac.h: Defines for the Sun "Big MAC" 100baseT ethernet cards. +/* $Id: sunbmac.h,v 1.5 1999/09/21 14:36:26 davem Exp $ + * sunbmac.h: Defines for the Sun "Big MAC" 100baseT ethernet cards. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ @@ -7,14 +8,13 @@ #define _SUNBMAC_H /* QEC global registers. */ -struct qe_globreg { - volatile unsigned int ctrl; /* Control */ - volatile unsigned int stat; /* Status */ - volatile unsigned int psize; /* Packet Size */ - volatile unsigned int msize; /* Local-mem size (64K) */ - volatile unsigned int rsize; /* Receive partition size */ - volatile unsigned int tsize; /* Transmit partition size */ -}; +#define GLOB_CTRL 0x00UL /* Control */ +#define GLOB_STAT 0x04UL /* Status */ +#define GLOB_PSIZE 0x08UL /* Packet Size */ +#define GLOB_MSIZE 0x0cUL /* Local-mem size (64K) */ +#define GLOB_RSIZE 0x10UL /* Receive partition size */ +#define GLOB_TSIZE 0x14UL /* Transmit partition size */ +#define GLOB_REG_SIZE 0x18UL #define GLOB_CTRL_MMODE 0x40000000 /* MACE qec mode */ #define GLOB_CTRL_BMODE 0x10000000 /* BigMAC qec mode */ @@ -36,21 +36,20 @@ #define GLOB_PSIZE_8192 0x11 /* 8k packet size */ /* QEC BigMAC channel registers. */ -struct qe_creg { - volatile unsigned int ctrl; /* Control */ - volatile unsigned int stat; /* Status */ - volatile unsigned int rxds; /* RX descriptor ring ptr */ - volatile unsigned int txds; /* TX descriptor ring ptr */ - volatile unsigned int rimask; /* RX Interrupt Mask */ - volatile unsigned int timask; /* TX Interrupt Mask */ - volatile unsigned int qmask; /* QEC Error Interrupt Mask */ - volatile unsigned int bmask; /* BigMAC Error Interrupt Mask */ - volatile unsigned int rxwbufptr; /* Local memory rx write ptr */ - volatile unsigned int rxrbufptr; /* Local memory rx read ptr */ - volatile unsigned int txwbufptr; /* Local memory tx write ptr */ - volatile unsigned int txrbufptr; /* Local memory tx read ptr */ - volatile unsigned int ccnt; /* Collision Counter */ -}; +#define CREG_CTRL 0x00UL /* Control */ +#define CREG_STAT 0x04UL /* Status */ +#define CREG_RXDS 0x08UL /* RX descriptor ring ptr */ +#define CREG_TXDS 0x0cUL /* TX descriptor ring ptr */ +#define CREG_RIMASK 0x10UL /* RX Interrupt Mask */ +#define CREG_TIMASK 0x14UL /* TX Interrupt Mask */ +#define CREG_QMASK 0x18UL /* QEC Error Interrupt Mask */ +#define CREG_BMASK 0x1cUL /* BigMAC Error Interrupt Mask*/ +#define CREG_RXWBUFPTR 0x20UL /* Local memory rx write ptr */ +#define CREG_RXRBUFPTR 0x24UL /* Local memory rx read ptr */ +#define CREG_TXWBUFPTR 0x28UL /* Local memory tx write ptr */ +#define CREG_TXRBUFPTR 0x2cUL /* Local memory tx read ptr */ +#define CREG_CCNT 0x30UL /* Collision Counter */ +#define CREG_REG_SIZE 0x34UL #define CREG_CTRL_TWAKEUP 0x00000001 /* Transmitter Wakeup, 'go'. */ @@ -82,56 +81,56 @@ #define CREG_QMASK_RXPERR 0x00000002 /* RX parity error */ #define CREG_QMASK_RXSERR 0x00000001 /* RX sbus error ack */ -struct BIG_MAC_regs { - volatile unsigned int xif_cfg; /* XIF config register */ - volatile unsigned int _unused[63]; /* Reserved... */ - volatile unsigned int status; /* Status register, clear on read */ - volatile unsigned int imask; /* Interrupt mask register */ - volatile unsigned int _unused2[64]; /* Reserved... */ - volatile unsigned int tx_swreset; /* Transmitter software reset */ - volatile unsigned int tx_cfg; /* Transmitter config register */ - volatile unsigned int ipkt_gap1; /* Inter-packet gap 1 */ - volatile unsigned int ipkt_gap2; /* Inter-packet gap 2 */ - volatile unsigned int attempt_limit; /* Transmit attempt limit */ - volatile unsigned int stime; /* Transmit slot time */ - volatile unsigned int preamble_len; /* Size of transmit preamble */ - volatile unsigned int preamble_pattern; /* Pattern for transmit preamble */ - volatile unsigned int tx_sframe_delim; /* Transmit delimiter */ - volatile unsigned int jsize; /* Toe jam... */ - volatile unsigned int tx_pkt_max; /* Transmit max pkt size */ - volatile unsigned int tx_pkt_min; /* Transmit min pkt size */ - volatile unsigned int peak_attempt; /* Count of transmit peak attempts */ - volatile unsigned int dt_ctr; /* Transmit defer timer */ - volatile unsigned int nc_ctr; /* Transmit normal-collision counter */ - volatile unsigned int fc_ctr; /* Transmit first-collision counter */ - volatile unsigned int ex_ctr; /* Transmit excess-collision counter */ - volatile unsigned int lt_ctr; /* Transmit late-collision counter */ - volatile unsigned int rand_seed; /* Transmit random number seed */ - volatile unsigned int tx_smachine; /* Transmit state machine */ - volatile unsigned int _unused3[44]; /* Reserved */ - volatile unsigned int rx_swreset; /* Receiver software reset */ - volatile unsigned int rx_cfg; /* Receiver config register */ - volatile unsigned int rx_pkt_max; /* Receive max pkt size */ - volatile unsigned int rx_pkt_min; /* Receive min pkt size */ - volatile unsigned int mac_addr2; /* Ether address register 2 */ - volatile unsigned int mac_addr1; /* Ether address register 1 */ - volatile unsigned int mac_addr0; /* Ether address register 0 */ - volatile unsigned int fr_ctr; /* Receive frame receive counter */ - volatile unsigned int gle_ctr; /* Receive giant-length error counter */ - volatile unsigned int unale_ctr; /* Receive unaligned error counter */ - volatile unsigned int rcrce_ctr; /* Receive CRC error counter */ - volatile unsigned int rx_smachine; /* Receiver state machine */ - volatile unsigned int rx_cvalid; /* Receiver code violation */ - volatile unsigned int _unused4; /* Reserved... */ - volatile unsigned int htable3; /* Hash table 3 */ - volatile unsigned int htable2; /* Hash table 2 */ - volatile unsigned int htable1; /* Hash table 1 */ - volatile unsigned int htable0; /* Hash table 0 */ - volatile unsigned int afilter2; /* Address filter 2 */ - volatile unsigned int afilter1; /* Address filter 1 */ - volatile unsigned int afilter0; /* Address filter 0 */ - volatile unsigned int afilter_mask; /* Address filter mask */ -}; +/* BIGMAC core registers */ +#define BMAC_XIFCFG 0x000UL /* XIF config register */ + /* 0x004-->0x0fc, reserved */ +#define BMAC_STATUS 0x100UL /* Status register, clear on read */ +#define BMAC_IMASK 0x104UL /* Interrupt mask register */ + /* 0x108-->0x204, reserved */ +#define BMAC_TXSWRESET 0x208UL /* Transmitter software reset */ +#define BMAC_TXCFG 0x20cUL /* Transmitter config register */ +#define BMAC_IGAP1 0x210UL /* Inter-packet gap 1 */ +#define BMAC_IGAP2 0x214UL /* Inter-packet gap 2 */ +#define BMAC_ALIMIT 0x218UL /* Transmit attempt limit */ +#define BMAC_STIME 0x21cUL /* Transmit slot time */ +#define BMAC_PLEN 0x220UL /* Size of transmit preamble */ +#define BMAC_PPAT 0x224UL /* Pattern for transmit preamble */ +#define BMAC_TXDELIM 0x228UL /* Transmit delimiter */ +#define BMAC_JSIZE 0x22cUL /* Toe jam... */ +#define BMAC_TXPMAX 0x230UL /* Transmit max pkt size */ +#define BMAC_TXPMIN 0x234UL /* Transmit min pkt size */ +#define BMAC_PATTEMPT 0x238UL /* Count of transmit peak attempts */ +#define BMAC_DTCTR 0x23cUL /* Transmit defer timer */ +#define BMAC_NCCTR 0x240UL /* Transmit normal-collision counter */ +#define BMAC_FCCTR 0x244UL /* Transmit first-collision counter */ +#define BMAC_EXCTR 0x248UL /* Transmit excess-collision counter */ +#define BMAC_LTCTR 0x24cUL /* Transmit late-collision counter */ +#define BMAC_RSEED 0x250UL /* Transmit random number seed */ +#define BMAC_TXSMACHINE 0x254UL /* Transmit state machine */ + /* 0x258-->0x304, reserved */ +#define BMAC_RXSWRESET 0x308UL /* Receiver software reset */ +#define BMAC_RXCFG 0x30cUL /* Receiver config register */ +#define BMAC_RXPMAX 0x310UL /* Receive max pkt size */ +#define BMAC_RXPMIN 0x314UL /* Receive min pkt size */ +#define BMAC_MACADDR2 0x318UL /* Ether address register 2 */ +#define BMAC_MACADDR1 0x31cUL /* Ether address register 1 */ +#define BMAC_MACADDR0 0x320UL /* Ether address register 0 */ +#define BMAC_FRCTR 0x324UL /* Receive frame receive counter */ +#define BMAC_GLECTR 0x328UL /* Receive giant-length error counter */ +#define BMAC_UNALECTR 0x32cUL /* Receive unaligned error counter */ +#define BMAC_RCRCECTR 0x330UL /* Receive CRC error counter */ +#define BMAC_RXSMACHINE 0x334UL /* Receiver state machine */ +#define BMAC_RXCVALID 0x338UL /* Receiver code violation */ + /* 0x33c, reserved */ +#define BMAC_HTABLE3 0x340UL /* Hash table 3 */ +#define BMAC_HTABLE2 0x344UL /* Hash table 2 */ +#define BMAC_HTABLE1 0x348UL /* Hash table 1 */ +#define BMAC_HTABLE0 0x34cUL /* Hash table 0 */ +#define BMAC_AFILTER2 0x350UL /* Address filter 2 */ +#define BMAC_AFILTER1 0x354UL /* Address filter 1 */ +#define BMAC_AFILTER0 0x358UL /* Address filter 0 */ +#define BMAC_AFMASK 0x35cUL /* Address filter mask */ +#define BMAC_REG_SIZE 0x360UL /* BigMac XIF config register. */ #define BIGMAC_XCFG_ODENABLE 0x00000001 /* Output driver enable */ @@ -197,10 +196,9 @@ /* The BigMAC PHY transceiver. Not nearly as sophisticated as the happy meal * one. But it does have the "bit banger", oh baby. */ -struct bmac_tcvr { - unsigned int tcvr_pal; - unsigned int mgmt_pal; -}; +#define TCVR_TPAL 0x00UL +#define TCVR_MPAL 0x04UL +#define TCVR_REG_SIZE 0x08UL /* Frame commands. */ #define FRAME_WRITE 0x50020000 @@ -244,8 +242,8 @@ /* Ring descriptors and such, same as Quad Ethernet. */ struct be_rxd { - unsigned int rx_flags; - unsigned int rx_addr; + u32 rx_flags; + u32 rx_addr; }; #define RXD_OWN 0x80000000 /* Ownership. */ @@ -253,8 +251,8 @@ #define RXD_LENGTH 0x000007ff /* Packet Length. */ struct be_txd { - unsigned int tx_flags; - unsigned int tx_addr; + u32 tx_flags; + u32 tx_addr; }; #define TXD_OWN 0x80000000 /* Ownership. */ @@ -280,13 +278,7 @@ (bp)->tx_old - (bp)->tx_new - 1) -#define SUN4C_TX_BUFFS_AVAIL(bp) \ - (((bp)->tx_old <= (bp)->tx_new) ? \ - (bp)->tx_old + (SUN4C_TX_RING_SIZE - 1) - (bp)->tx_new : \ - (bp)->tx_old - (bp)->tx_new - (TX_RING_SIZE - SUN4C_TX_RING_SIZE)) - - -#define RX_COPY_THRESHOLD 128 +#define RX_COPY_THRESHOLD 256 #define RX_BUF_ALLOC_SIZE (ETH_FRAME_LEN + (64 * 3)) struct bmac_init_block { @@ -297,22 +289,6 @@ #define bib_offset(mem, elem) \ ((__u32)((unsigned long)(&(((struct bmac_init_block *)0)->mem[elem])))) -#define SUN4C_PKT_BUF_SZ 1546 -#define SUN4C_RX_BUFF_SIZE SUN4C_PKT_BUF_SZ -#define SUN4C_TX_BUFF_SIZE SUN4C_PKT_BUF_SZ - -#define SUN4C_RX_RING_SIZE 16 -#define SUN4C_TX_RING_SIZE 16 - -struct bigmac_buffers { - char tx_buf[SUN4C_TX_RING_SIZE][SUN4C_TX_BUFF_SIZE]; - char pad[2]; /* Align rx_buf for copy_and_sum(). */ - char rx_buf[SUN4C_RX_RING_SIZE][SUN4C_RX_BUFF_SIZE]; -}; - -#define bbuf_offset(mem, elem) \ -((__u32)((unsigned long)(&(((struct bigmac_buffers *)0)->mem[elem][0])))) - /* Now software state stuff. */ enum bigmac_transceiver { external = 0, @@ -327,21 +303,18 @@ }; struct bigmac { - struct qe_globreg *gregs; /* QEC Global Registers */ - struct qe_creg *creg; /* QEC BigMAC Channel Registers */ - struct BIG_MAC_regs *bregs; /* BigMAC Registers */ - struct bmac_tcvr *tregs; /* BigMAC Transceiver */ - struct bmac_init_block *bmac_block; /* RX and TX descriptors */ - __u32 bblock_dvma; /* RX and TX descriptors */ + unsigned long gregs; /* QEC Global Registers */ + unsigned long creg; /* QEC BigMAC Channel Registers */ + unsigned long bregs; /* BigMAC Registers */ + unsigned long tregs; /* BigMAC Transceiver */ + struct bmac_init_block *bmac_block; /* RX and TX descriptors */ + __u32 bblock_dvma; /* RX and TX descriptors */ struct sk_buff *rx_skbs[RX_RING_SIZE]; struct sk_buff *tx_skbs[TX_RING_SIZE]; int rx_new, tx_new, rx_old, tx_old; - struct bigmac_buffers *sun4c_buffers; - __u32 s4c_buf_dvma; - int board_rev; /* BigMAC board revision. */ enum bigmac_transceiver tcvr_type; @@ -353,11 +326,11 @@ enum bigmac_timer_state timer_state; unsigned int timer_ticks; - struct enet_statistics enet_stats; - struct linux_sbus_device *qec_sbus_dev; - struct linux_sbus_device *bigmac_sbus_dev; - struct net_device *dev; - struct bigmac *next_module; + struct enet_statistics enet_stats; + struct sbus_dev *qec_sdev; + struct sbus_dev *bigmac_sdev; + struct net_device *dev; + struct bigmac *next_module; }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.3.34/linux/drivers/net/sunhme.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/sunhme.c Mon Dec 20 22:06:42 1999 @@ -1,12 +1,13 @@ -/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, +/* $Id: sunhme.c,v 1.84 1999/12/15 14:08:03 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. * - * Copyright (C) 1996, 1998 David S. Miller (davem@caipfs.rutgers.edu) + * Copyright (C) 1996, 1998, 1999 David S. Miller (davem@redhat.com) */ static char *version = - "sunhme.c:v1.10 27/Jan/99 David S. Miller (davem@caipfs.rutgers.edu)\n"; + "sunhme.c:v1.99 12/Sep/99 David S. Miller (davem@redhat.com)\n"; #include @@ -103,7 +104,7 @@ int i, this; this = txlog_cur_entry; - for(i = 0; i < TX_LOG_LEN; i++) { + for (i = 0; i < TX_LOG_LEN; i++) { printk("TXLOG[%d]: j[%08x] tx[N(%d)O(%d)] action[%08x] stat[%08x]\n", i, tx_log[this].tstamp, tx_log[this].tx_new, tx_log[this].tx_old, @@ -117,7 +118,7 @@ struct happy_meal_txd *tp = &hb->happy_meal_txd[0]; int i; - for(i = 0; i < TX_RING_SIZE; i+=4) { + for (i = 0; i < TX_RING_SIZE; i+=4) { printk("TXD[%d..%d]: [%08x:%08x] [%08x:%08x] [%08x:%08x] [%08x:%08x]\n", i, i + 4, le32_to_cpu(tp[i].tx_flags), le32_to_cpu(tp[i].tx_addr), @@ -151,53 +152,225 @@ #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ -/* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ -#define BB_PUT_BIT(hp, tregs, bit) \ -do { hme_write32(hp, &(tregs)->bb_data, (bit)); \ - hme_write32(hp, &(tregs)->bb_clock, 0); \ - hme_write32(hp, &(tregs)->bb_clock, 1); \ +#if defined(CONFIG_SBUS) && defined(CONFIG_PCI) +static void sbus_hme_write32(unsigned long reg, u32 val) +{ + sbus_writel(val, reg); +} + +static u32 sbus_hme_read32(unsigned long reg) +{ + return sbus_readl(reg); +} + +static void sbus_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr) +{ + rxd->rx_addr = addr; + rxd->rx_flags = flags; +} + +static void sbus_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr) +{ + txd->tx_flags = flags; + txd->tx_addr = addr; +} + +static u32 sbus_hme_read_desc32(u32 *p) +{ + return *p; +} + +static void pci_hme_write32(unsigned long reg, u32 val) +{ + writel(val, reg); +} + +static u32 pci_hme_read32(unsigned long reg) +{ + return readl(reg); +} + +static void pci_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr) +{ + rxd->rx_addr = cpu_to_le32(addr); + rxd->rx_flags = cpu_to_le32(flags); +} + +static void pci_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr) +{ + txd->tx_flags = cpu_to_le32(flags); + txd->tx_addr = cpu_to_le32(addr); +} + +static u32 pci_hme_read_desc32(u32 *p) +{ + return cpu_to_le32(*p); +} + +/* XXX Convert these to direct function hookup once new + * XXX PCI dvma interfaces are propagated and in use everywhere. + */ +static u32 pci_hme_dma_map(void *device, void *ptr, long size) +{ +#if 1 + return virt_to_bus(ptr); +#else + struct pci_dev *pdev = device; + + return pci_map_single(pdev, ptr, size); +#endif +} + +static void pci_hme_dma_unmap(void *device, u32 dma_addr, long size) +{ +#if 1 + return; +#else + struct pci_dev *pdev = device; + + pci_unmap_single(pdev, dma_addr, size); +#endif +} + +static void pci_hme_dma_sync(void *device, u32 dma_addr, long size) +{ +#if 1 + return; +#else + struct pci_dev *pdev = device; + + pci_dma_sync_single(pdev, dma_addr, size); +#endif +} + +#define hme_write32(__hp, __reg, __val) \ + ((__hp)->write32((__reg), (__val))) +#define hme_read32(__hp, __reg) \ + ((__hp)->read32(__reg)) +#define hme_write_rxd(__hp, __rxd, __flags, __addr) \ + ((__hp)->write_rxd((__rxd), (__flags), (__addr))) +#define hme_write_txd(__hp, __txd, __flags, __addr) \ + ((__hp)->write_txd((__txd), (__flags), (__addr))) +#define hme_read_desc32(__hp, __p) \ + ((__hp)->read_desc32(__p)) +#define hme_dma_map(__hp, __ptr, __size) \ + ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size))) +#define hme_dma_unmap(__hp, __addr, __size) \ + ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size))) +#define hme_dma_sync(__hp, __addr, __size) \ + ((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size))) +#else +#ifdef CONFIG_SBUS +/* SBUS only compilation */ +#define hme_write32(__hp, __reg, __val) \ + sbus_writel((__val), (__reg)) +#define hme_read32(__hp, __reg) \ + sbus_readl(__reg) +#define hme_write_rxd(__hp, __rxd, __flags, __addr) \ +do { (__rxd)->rx_addr = (__addr); \ + (__rxd)->rx_flags = (__flags); \ +} while(0) +#define hme_write_txd(__hp, __txd, __flags, __addr) \ +do { (__txd)->tx_addr = (__addr); \ + (__txd)->tx_flags = (__flags); \ } while(0) +#define hme_read_desc32(__hp, __p) (*(__p)) +#define hme_dma_map(__hp, __ptr, __size) \ + sbus_map_single((__hp)->happy_dev, (__ptr), (__size)) +#define hme_dma_unmap(__hp, __addr, __size) \ + sbus_unmap_single((__hp)->happy_dev, (__addr), (__size)) +#define hme_dma_sync(__hp, __addr, __size) \ + sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size)) +#else +/* PCI only compilation */ +#define hme_write32(__hp, __reg, __val) \ + writel((__val), (__reg)) +#define hme_read32(__hp, __reg) \ + readl(__reg) +#define hme_write_rxd(__hp, __rxd, __flags, __addr) \ +do { (__rxd)->rx_addr = cpu_to_le32(__addr); \ + (__rxd)->rx_flags = cpu_to_le32(__flags); \ +} while(0) +#define hme_write_txd(__hp, __txd, __flags, __addr) \ +do { (__txd)->tx_addr = cpu_to_le32(__addr); \ + (__txd)->tx_flags = cpu_to_le32(__flags); \ +} while(0) +#define hme_read_desc32(__hp, __p) cpu_to_le32(*(__p)) +#if 0 /* XXX Once new PCI interfaces are in place... XXX */ +#define hme_dma_map(__hp, __ptr, __size) \ + pci_map_single((__hp)->happy_dev, (__ptr), (__size)) +#define hme_dma_unmap(__hp, __addr, __size) \ + pci_unmap_single((__hp)->happy_dev, (__addr), (__size)) +#define hme_dma_sync(__hp, __addr, __size) \ + pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size)) +#else +#define hme_dma_map(__hp, __ptr, __size) \ + (virt_to_bus(__ptr)) +#define hme_dma_unmap(__hp, __addr, __size) \ + do { } while(0) +#define hme_dma_sync(__hp, __addr, __size) \ + do { } while(0) +#endif +#endif +#endif + +/* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ +static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit) +{ + hme_write32(hp, tregs + TCVR_BBDATA, bit); + hme_write32(hp, tregs + TCVR_BBCLOCK, 0); + hme_write32(hp, tregs + TCVR_BBCLOCK, 1); +} + +#if 0 +static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal) +{ + u32 ret; + + hme_write32(hp, tregs + TCVR_BBCLOCK, 0); + hme_write32(hp, tregs + TCVR_BBCLOCK, 1); + ret = hme_read32(hp, tregs + TCVR_CFG); + if (internal) + ret &= TCV_CFG_MDIO0; + else + ret &= TCV_CFG_MDIO1; + + return ret; +} +#endif + +static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal) +{ + u32 retval; -#define BB_GET_BIT(hp, tregs, internal) \ -({ \ - hme_write32(hp, &(tregs)->bb_clock, 0); \ - hme_write32(hp, &(tregs)->bb_clock, 1); \ - if(internal) \ - hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0; \ - else \ - hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1; \ -}) - -#define BB_GET_BIT2(hp, tregs, internal) \ -({ \ - int retval; \ - hme_write32(hp, &(tregs)->bb_clock, 0); \ - udelay(1); \ - if(internal) \ - retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0; \ - else \ - retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1; \ - hme_write32(hp, &(tregs)->bb_clock, 1); \ - retval; \ -}) + hme_write32(hp, tregs + TCVR_BBCLOCK, 0); + udelay(1); + retval = hme_read32(hp, tregs + TCVR_CFG); + if (internal) + retval &= TCV_CFG_MDIO0; + else + retval &= TCV_CFG_MDIO1; + hme_write32(hp, tregs + TCVR_BBCLOCK, 1); + + return retval; +} #define TCVR_FAILURE 0x80000000 /* Impossible MIF read value */ -static inline int happy_meal_bb_read(struct happy_meal *hp, - struct hmeal_tcvregs *tregs, int reg) +static int happy_meal_bb_read(struct happy_meal *hp, + unsigned long tregs, int reg) { - volatile int unused; - unsigned long tmp; + u32 tmp; int retval = 0; int i; ASD(("happy_meal_bb_read: reg=%d ", reg)); /* Enable the MIF BitBang outputs. */ - hme_write32(hp, &tregs->bb_oenab, 1); + hme_write32(hp, tregs + TCVR_BBOENAB, 1); /* Force BitBang into the idle state. */ - for(i = 0; i < 32; i++) + for (i = 0; i < 32; i++) BB_PUT_BIT(hp, tregs, 1); /* Give it the read sequence. */ @@ -208,42 +381,42 @@ /* Give it the PHY address. */ tmp = hp->paddr & 0xff; - for(i = 4; i >= 0; i--) + for (i = 4; i >= 0; i--) BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1)); /* Tell it what register we want to read. */ tmp = (reg & 0xff); - for(i = 4; i >= 0; i--) + for (i = 4; i >= 0; i--) BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1)); /* Close down the MIF BitBang outputs. */ - hme_write32(hp, &tregs->bb_oenab, 0); + hme_write32(hp, tregs + TCVR_BBOENAB, 0); /* Now read in the value. */ - unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); - for(i = 15; i >= 0; i--) + (void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); + for (i = 15; i >= 0; i--) retval |= BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); - unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); - unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); - unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); + (void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); + (void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); + (void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal)); ASD(("value=%x\n", retval)); return retval; } -static inline void happy_meal_bb_write(struct happy_meal *hp, - struct hmeal_tcvregs *tregs, int reg, - unsigned short value) +static void happy_meal_bb_write(struct happy_meal *hp, + unsigned long tregs, int reg, + unsigned short value) { - unsigned long tmp; + u32 tmp; int i; ASD(("happy_meal_bb_write: reg=%d value=%x\n", reg, value)); /* Enable the MIF BitBang outputs. */ - hme_write32(hp, &tregs->bb_oenab, 1); + hme_write32(hp, tregs + TCVR_BBOENAB, 1); /* Force BitBang into the idle state. */ - for(i = 0; i < 32; i++) + for (i = 0; i < 32; i++) BB_PUT_BIT(hp, tregs, 1); /* Give it write sequence. */ @@ -254,81 +427,81 @@ /* Give it the PHY address. */ tmp = (hp->paddr & 0xff); - for(i = 4; i >= 0; i--) + for (i = 4; i >= 0; i--) BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1)); /* Tell it what register we will be writing. */ tmp = (reg & 0xff); - for(i = 4; i >= 0; i--) + for (i = 4; i >= 0; i--) BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1)); /* Tell it to become ready for the bits. */ BB_PUT_BIT(hp, tregs, 1); BB_PUT_BIT(hp, tregs, 0); - for(i = 15; i >= 0; i--) + for (i = 15; i >= 0; i--) BB_PUT_BIT(hp, tregs, ((value >> i) & 1)); /* Close down the MIF BitBang outputs. */ - hme_write32(hp, &tregs->bb_oenab, 0); + hme_write32(hp, tregs + TCVR_BBOENAB, 0); } #define TCVR_READ_TRIES 16 -static inline int happy_meal_tcvr_read(struct happy_meal *hp, - struct hmeal_tcvregs *tregs, int reg) +static int happy_meal_tcvr_read(struct happy_meal *hp, + unsigned long tregs, int reg) { int tries = TCVR_READ_TRIES; int retval; ASD(("happy_meal_tcvr_read: reg=0x%02x ", reg)); - if(hp->tcvr_type == none) { + if (hp->tcvr_type == none) { ASD(("no transceiver, value=TCVR_FAILURE\n")); return TCVR_FAILURE; } - if(!(hp->happy_flags & HFLAG_FENABLE)) { + if (!(hp->happy_flags & HFLAG_FENABLE)) { ASD(("doing bit bang\n")); return happy_meal_bb_read(hp, tregs, reg); } - hme_write32(hp, &tregs->frame, + hme_write32(hp, tregs + TCVR_FRAME, (FRAME_READ | (hp->paddr << 23) | ((reg & 0xff) << 18))); - while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries) + while (!(hme_read32(hp, tregs + TCVR_FRAME) & 0x10000) && --tries) udelay(20); - if(!tries) { - printk("happy meal: Aieee, transceiver MIF read bolixed\n"); + if (!tries) { + printk(KERN_ERR "happy meal: Aieee, transceiver MIF read bolixed\n"); return TCVR_FAILURE; } - retval = hme_read32(hp, &tregs->frame) & 0xffff; + retval = hme_read32(hp, tregs + TCVR_FRAME) & 0xffff; ASD(("value=%04x\n", retval)); return retval; } #define TCVR_WRITE_TRIES 16 -static inline void happy_meal_tcvr_write(struct happy_meal *hp, - struct hmeal_tcvregs *tregs, int reg, - unsigned short value) +static void happy_meal_tcvr_write(struct happy_meal *hp, + unsigned long tregs, int reg, + unsigned short value) { int tries = TCVR_WRITE_TRIES; ASD(("happy_meal_tcvr_write: reg=0x%02x value=%04x\n", reg, value)); /* Welcome to Sun Microsystems, can I take your order please? */ - if(!hp->happy_flags & HFLAG_FENABLE) + if (!hp->happy_flags & HFLAG_FENABLE) return happy_meal_bb_write(hp, tregs, reg, value); /* Would you like fries with that? */ - hme_write32(hp, &tregs->frame, + hme_write32(hp, tregs + TCVR_FRAME, (FRAME_WRITE | (hp->paddr << 23) | ((reg & 0xff) << 18) | (value & 0xffff))); - while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries) + while (!(hme_read32(hp, tregs + TCVR_FRAME) & 0x10000) && --tries) udelay(20); /* Anything else? */ - if(!tries) - printk("happy meal: Aieee, transceiver MIF write bolixed\n"); + if (!tries) + printk(KERN_ERR "happy meal: Aieee, transceiver MIF write bolixed\n"); /* Fifty-two cents is your change, have a nice day. */ } @@ -365,21 +538,21 @@ * service routine, and the chip is reset, or the link is ifconfig'd down * and then back up, this entire process repeats itself all over again. */ -static int try_next_permutation(struct happy_meal *hp, struct hmeal_tcvregs *tregs) +static int try_next_permutation(struct happy_meal *hp, unsigned long tregs) { hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); /* Downgrade from full to half duplex. Only possible * via ethtool. */ - if(hp->sw_bmcr & BMCR_FULLDPLX) { + if (hp->sw_bmcr & BMCR_FULLDPLX) { hp->sw_bmcr &= ~(BMCR_FULLDPLX); happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); return 0; } /* Downgrade from 100 to 10. */ - if(hp->sw_bmcr & BMCR_SPEED100) { + if (hp->sw_bmcr & BMCR_SPEED100) { hp->sw_bmcr &= ~(BMCR_SPEED100); happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); return 0; @@ -389,70 +562,70 @@ return -1; } -static void display_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs) +static void display_link_mode(struct happy_meal *hp, unsigned long tregs) { - printk("%s: Link is up using ", hp->dev->name); - if(hp->tcvr_type == external) + printk(KERN_INFO "%s: Link is up using ", hp->dev->name); + if (hp->tcvr_type == external) printk("external "); else printk("internal "); printk("transceiver at "); hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA); - if(hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) { - if(hp->sw_lpa & LPA_100FULL) + if (hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) { + if (hp->sw_lpa & LPA_100FULL) printk("100Mb/s, Full Duplex.\n"); else printk("100Mb/s, Half Duplex.\n"); } else { - if(hp->sw_lpa & LPA_10FULL) + if (hp->sw_lpa & LPA_10FULL) printk("10Mb/s, Full Duplex.\n"); else printk("10Mb/s, Half Duplex.\n"); } } -static void display_forced_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs) +static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs) { - printk("%s: Link has been forced up using ", hp->dev->name); - if(hp->tcvr_type == external) + printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name); + if (hp->tcvr_type == external) printk("external "); else printk("internal "); printk("transceiver at "); hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(hp->sw_bmcr & BMCR_SPEED100) + if (hp->sw_bmcr & BMCR_SPEED100) printk("100Mb/s, "); else printk("10Mb/s, "); - if(hp->sw_bmcr & BMCR_FULLDPLX) + if (hp->sw_bmcr & BMCR_FULLDPLX) printk("Full Duplex.\n"); else printk("Half Duplex.\n"); } -static int set_happy_link_modes(struct happy_meal *hp, struct hmeal_tcvregs *tregs) +static int set_happy_link_modes(struct happy_meal *hp, unsigned long tregs) { int full; /* All we care about is making sure the bigmac tx_cfg has a * proper duplex setting. */ - if(hp->timer_state == arbwait) { + if (hp->timer_state == arbwait) { hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA); - if(!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL))) + if (!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL))) goto no_response; - if(hp->sw_lpa & LPA_100FULL) + if (hp->sw_lpa & LPA_100FULL) full = 1; - else if(hp->sw_lpa & LPA_100HALF) + else if (hp->sw_lpa & LPA_100HALF) full = 0; - else if(hp->sw_lpa & LPA_10FULL) + else if (hp->sw_lpa & LPA_10FULL) full = 1; else full = 0; } else { /* Forcing a link mode. */ hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(hp->sw_bmcr & BMCR_FULLDPLX) + if (hp->sw_bmcr & BMCR_FULLDPLX) full = 1; else full = 0; @@ -466,24 +639,24 @@ * 3) Make TX configuration changes * 4) Set Enable once more */ - hme_write32(hp, &hp->bigmacregs->tx_cfg, - hme_read32(hp, &hp->bigmacregs->tx_cfg) & + hme_write32(hp, hp->bigmacregs + BMAC_TXCFG, + hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) & ~(BIGMAC_TXCFG_ENABLE)); - while(hme_read32(hp, &hp->bigmacregs->tx_cfg) & BIGMAC_TXCFG_ENABLE) + while (hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) & BIGMAC_TXCFG_ENABLE) barrier(); - if(full) { + if (full) { hp->happy_flags |= HFLAG_FULL; - hme_write32(hp, &hp->bigmacregs->tx_cfg, - hme_read32(hp, &hp->bigmacregs->tx_cfg) | + hme_write32(hp, hp->bigmacregs + BMAC_TXCFG, + hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) | BIGMAC_TXCFG_FULLDPLX); } else { hp->happy_flags &= ~(HFLAG_FULL); - hme_write32(hp, &hp->bigmacregs->tx_cfg, - hme_read32(hp, &hp->bigmacregs->tx_cfg) & + hme_write32(hp, hp->bigmacregs + BMAC_TXCFG, + hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) & ~(BIGMAC_TXCFG_FULLDPLX)); } - hme_write32(hp, &hp->bigmacregs->tx_cfg, - hme_read32(hp, &hp->bigmacregs->tx_cfg) | + hme_write32(hp, hp->bigmacregs + BMAC_TXCFG, + hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE); return 0; no_response: @@ -492,10 +665,29 @@ static int happy_meal_init(struct happy_meal *hp, int from_irq); +static int is_lucent_phy(struct happy_meal *hp) +{ + unsigned long tregs = hp->tcvregs; + unsigned short mr2, mr3; + int ret = 0; + + mr2 = happy_meal_tcvr_read(hp, tregs, 2); + mr3 = happy_meal_tcvr_read(hp, tregs, 3); + if ((mr2 & 0xffff) == 0x0180 && + ((mr3 & 0xffff) >> 10) == 0x1d) { +#if 0 + printk("HMEDEBUG: Lucent PHY detected.\n"); +#endif + ret = 1; + } + + return ret; +} + static void happy_meal_timer(unsigned long data) { struct happy_meal *hp = (struct happy_meal *) data; - struct hmeal_tcvregs *tregs = hp->tcvregs; + unsigned long tregs = hp->tcvregs; int restart_timer = 0; hp->timer_ticks++; @@ -504,35 +696,36 @@ /* Only allow for 5 ticks, thats 10 seconds and much too * long to wait for arbitration to complete. */ - if(hp->timer_ticks >= 10) { + if (hp->timer_ticks >= 10) { /* Enter force mode. */ do_force_mode: hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - printk("%s: Auto-Negotiation unsuccessful, trying force link mode\n", + printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful, trying force link mode\n", hp->dev->name); hp->sw_bmcr = BMCR_SPEED100; happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); - /* OK, seems we need do disable the transceiver for the first - * tick to make sure we get an accurate link state at the - * second tick. - */ - hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG); - hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig); - + if (!is_lucent_phy(hp)) { + /* OK, seems we need do disable the transceiver for the first + * tick to make sure we get an accurate link state at the + * second tick. + */ + hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG); + hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); + happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig); + } hp->timer_state = ltrywait; hp->timer_ticks = 0; restart_timer = 1; } else { /* Anything interesting happen? */ hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR); - if(hp->sw_bmsr & BMSR_ANEGCOMPLETE) { + if (hp->sw_bmsr & BMSR_ANEGCOMPLETE) { int ret; /* Just what we've been waiting for... */ ret = set_happy_link_modes(hp, tregs); - if(ret) { + if (ret) { /* Ooops, something bad happened, go to force * mode. * @@ -558,7 +751,7 @@ * a message to the user at 10 second intervals. */ hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR); - if(hp->sw_bmsr & BMSR_LSTATUS) { + if (hp->sw_bmsr & BMSR_LSTATUS) { /* Wheee, it's up, display the link mode in use and put * the timer to sleep. */ @@ -566,8 +759,8 @@ hp->timer_state = asleep; restart_timer = 0; } else { - if(hp->timer_ticks >= 10) { - printk("%s: Auto negotiation successful, link still " + if (hp->timer_ticks >= 10) { + printk(KERN_NOTICE "%s: Auto negotiation successful, link still " "not completely up.\n", hp->dev->name); hp->timer_ticks = 0; restart_timer = 1; @@ -585,51 +778,62 @@ */ hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR); hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG); - if(hp->timer_ticks == 1) { - /* Re-enable transceiver, we'll re-enable the transceiver next - * tick, then check link state on the following tick. */ - hp->sw_csconfig |= CSCONFIG_TCVDISAB; - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig); + if (hp->timer_ticks == 1) { + if (!is_lucent_phy(hp)) { + /* Re-enable transceiver, we'll re-enable the transceiver next + * tick, then check link state on the following tick. + */ + hp->sw_csconfig |= CSCONFIG_TCVDISAB; + happy_meal_tcvr_write(hp, tregs, + DP83840_CSCONFIG, hp->sw_csconfig); + } restart_timer = 1; break; } - if(hp->timer_ticks == 2) { - hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig); + if (hp->timer_ticks == 2) { + if (!is_lucent_phy(hp)) { + hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); + happy_meal_tcvr_write(hp, tregs, + DP83840_CSCONFIG, hp->sw_csconfig); + } restart_timer = 1; break; } - if(hp->sw_bmsr & BMSR_LSTATUS) { + if (hp->sw_bmsr & BMSR_LSTATUS) { /* Force mode selection success. */ display_forced_link_mode(hp, tregs); set_happy_link_modes(hp, tregs); /* XXX error? then what? */ hp->timer_state = asleep; restart_timer = 0; } else { - if(hp->timer_ticks >= 4) { /* 6 seconds or so... */ + if (hp->timer_ticks >= 4) { /* 6 seconds or so... */ int ret; ret = try_next_permutation(hp, tregs); - if(ret == -1) { + if (ret == -1) { /* Aieee, tried them all, reset the * chip and try all over again. */ /* Let the user know... */ - printk("%s: Link down, cable problem?\n", + printk(KERN_NOTICE "%s: Link down, cable problem?\n", hp->dev->name); ret = happy_meal_init(hp, 0); - if(ret) { + if (ret) { /* ho hum... */ - printk("%s: Error, cannot re-init the " + printk(KERN_ERR "%s: Error, cannot re-init the " "Happy Meal.\n", hp->dev->name); } return; } - hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG); - hp->sw_csconfig |= CSCONFIG_TCVDISAB; - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig); + if (!is_lucent_phy(hp)) { + hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, + DP83840_CSCONFIG); + hp->sw_csconfig |= CSCONFIG_TCVDISAB; + happy_meal_tcvr_write(hp, tregs, + DP83840_CSCONFIG, hp->sw_csconfig); + } hp->timer_ticks = 0; restart_timer = 1; } else { @@ -641,7 +845,7 @@ case asleep: default: /* Can't happens.... */ - printk("%s: Aieee, link timer is asleep but we got one anyways!\n", + printk(KERN_ERR "%s: Aieee, link timer is asleep but we got one anyways!\n", hp->dev->name); restart_timer = 0; hp->timer_ticks = 0; @@ -649,7 +853,7 @@ break; }; - if(restart_timer) { + if (restart_timer) { hp->happy_timer.expires = jiffies + ((12 * HZ)/10); /* 1.2 sec. */ add_timer(&hp->happy_timer); } @@ -658,41 +862,39 @@ #define TX_RESET_TRIES 32 #define RX_RESET_TRIES 32 -static inline void happy_meal_tx_reset(struct happy_meal *hp, - struct hmeal_bigmacregs *bregs) +static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs) { int tries = TX_RESET_TRIES; HMD(("happy_meal_tx_reset: reset, ")); /* Would you like to try our SMCC Delux? */ - hme_write32(hp, &bregs->tx_swreset, 0); - while((hme_read32(hp, &bregs->tx_swreset) & 1) && --tries) + hme_write32(hp, bregs + BMAC_TXSWRESET, 0); + while ((hme_read32(hp, bregs + BMAC_TXSWRESET) & 1) && --tries) udelay(20); /* Lettuce, tomato, buggy hardware (no extra charge)? */ - if(!tries) - printk("happy meal: Transceiver BigMac ATTACK!"); + if (!tries) + printk(KERN_ERR "happy meal: Transceiver BigMac ATTACK!"); /* Take care. */ HMD(("done\n")); } -static inline void happy_meal_rx_reset(struct happy_meal *hp, - struct hmeal_bigmacregs *bregs) +static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs) { int tries = RX_RESET_TRIES; HMD(("happy_meal_rx_reset: reset, ")); /* We have a special on GNU/Viking hardware bugs today. */ - hme_write32(hp, &bregs->rx_swreset, 0); - while((hme_read32(hp, &bregs->rx_swreset) & 1) && --tries) + hme_write32(hp, bregs + BMAC_RXSWRESET, 0); + while ((hme_read32(hp, bregs + BMAC_RXSWRESET) & 1) && --tries) udelay(20); /* Will that be all? */ - if(!tries) - printk("happy meal: Receiver BigMac ATTACK!"); + if (!tries) + printk(KERN_ERR "happy meal: Receiver BigMac ATTACK!"); /* Don't forget your vik_1137125_wa. Have a nice day. */ HMD(("done\n")); @@ -700,69 +902,67 @@ #define STOP_TRIES 16 -static inline void happy_meal_stop(struct happy_meal *hp, - struct hmeal_gregs *gregs) +static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs) { int tries = STOP_TRIES; HMD(("happy_meal_stop: reset, ")); /* We're consolidating our STB products, it's your lucky day. */ - hme_write32(hp, &gregs->sw_reset, GREG_RESET_ALL); - while(hme_read32(hp, &gregs->sw_reset) && --tries) + hme_write32(hp, gregs + GREG_SWRESET, GREG_RESET_ALL); + while (hme_read32(hp, gregs + GREG_SWRESET) && --tries) udelay(20); /* Come back next week when we are "Sun Microelectronics". */ - if(!tries) - printk("happy meal: Fry guys."); + if (!tries) + printk(KERN_ERR "happy meal: Fry guys."); /* Remember: "Different name, same old buggy as shit hardware." */ HMD(("done\n")); } -static void happy_meal_get_counters(struct happy_meal *hp, - struct hmeal_bigmacregs *bregs) +static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs) { struct net_device_stats *stats = &hp->net_stats; - stats->rx_crc_errors += hme_read32(hp, &bregs->rcrce_ctr); - hme_write32(hp, &bregs->rcrce_ctr, 0); + stats->rx_crc_errors += hme_read32(hp, bregs + BMAC_RCRCECTR); + hme_write32(hp, bregs + BMAC_RCRCECTR, 0); - stats->rx_frame_errors += hme_read32(hp, &bregs->unale_ctr); - hme_write32(hp, &bregs->unale_ctr, 0); + stats->rx_frame_errors += hme_read32(hp, bregs + BMAC_UNALECTR); + hme_write32(hp, bregs + BMAC_UNALECTR, 0); - stats->rx_length_errors += hme_read32(hp, &bregs->gle_ctr); - hme_write32(hp, &bregs->gle_ctr, 0); + stats->rx_length_errors += hme_read32(hp, bregs + BMAC_GLECTR); + hme_write32(hp, bregs + BMAC_GLECTR, 0); - stats->tx_aborted_errors += hme_read32(hp, &bregs->ex_ctr); + stats->tx_aborted_errors += hme_read32(hp, bregs + BMAC_EXCTR); stats->collisions += - (hme_read32(hp, &bregs->ex_ctr) + - hme_read32(hp, &bregs->lt_ctr)); - hme_write32(hp, &bregs->ex_ctr, 0); - hme_write32(hp, &bregs->lt_ctr, 0); + (hme_read32(hp, bregs + BMAC_EXCTR) + + hme_read32(hp, bregs + BMAC_LTCTR)); + hme_write32(hp, bregs + BMAC_EXCTR, 0); + hme_write32(hp, bregs + BMAC_LTCTR, 0); } -static inline void happy_meal_poll_start(struct happy_meal *hp, - struct hmeal_tcvregs *tregs) +#if 0 +static void happy_meal_poll_start(struct happy_meal *hp, unsigned long tregs) { - unsigned long tmp; + u32 tmp; int speed; ASD(("happy_meal_poll_start: ")); - if(!(hp->happy_flags & HFLAG_POLLENABLE)) { + if (!(hp->happy_flags & HFLAG_POLLENABLE)) { HMD(("polling disabled, return\n")); return; } /* Start the MIF polling on the external transceiver. */ ASD(("polling on, ")); - tmp = hme_read32(hp, &tregs->cfg); + tmp = hme_read32(hp, tregs + TCVR_CFG); tmp &= ~(TCV_CFG_PDADDR | TCV_CFG_PREGADDR); tmp |= ((hp->paddr & 0x1f) << 10); tmp |= (TCV_PADDR_ETX << 3); tmp |= TCV_CFG_PENABLE; - hme_write32(hp, &tregs->cfg, tmp); + hme_write32(hp, tregs + TCVR_CFG, tmp); /* Let the bits set. */ udelay(200); @@ -773,29 +973,29 @@ /* Clear the poll flags, get the basic status as of now. */ hp->poll_flag = 0; - hp->poll_data = tregs->status >> 16; + hp->poll_data = hme_read32(hp, tregs + TCVR_STATUS) >> 16; - if(hp->happy_flags & HFLAG_AUTO) + if (hp->happy_flags & HFLAG_AUTO) speed = hp->auto_speed; else speed = hp->forced_speed; /* Listen only for the MIF interrupts we want to hear. */ ASD(("mif ints on, ")); - if(speed == 100) - hme_write32(hp, &tregs->int_mask, 0xfffb); + if (speed == 100) + hme_write32(hp, tregs + TCVR_IMASK, 0xfffb); else - hme_write32(hp, &tregs->int_mask, 0xfff9); + hme_write32(hp, tregs + TCVR_IMASK, 0xfff9); ASD(("done\n")); } +#endif -static inline void happy_meal_poll_stop(struct happy_meal *hp, - struct hmeal_tcvregs *tregs) +static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs) { ASD(("happy_meal_poll_stop: ")); /* If polling disabled or not polling already, nothing to do. */ - if((hp->happy_flags & (HFLAG_POLLENABLE | HFLAG_POLL)) != + if ((hp->happy_flags & (HFLAG_POLLENABLE | HFLAG_POLL)) != (HFLAG_POLLENABLE | HFLAG_POLL)) { HMD(("not polling, return\n")); return; @@ -803,12 +1003,12 @@ /* Shut up the MIF. */ ASD(("were polling, mif ints off, ")); - hme_write32(hp, &tregs->int_mask, 0xffff); + hme_write32(hp, tregs + TCVR_IMASK, 0xffff); /* Turn off polling. */ ASD(("polling off, ")); - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_PENABLE)); + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_PENABLE)); /* We are no longer polling. */ hp->happy_flags &= ~(HFLAG_POLL); @@ -824,45 +1024,44 @@ #define TCVR_RESET_TRIES 16 /* It should reset quickly */ #define TCVR_UNISOLATE_TRIES 32 /* Dis-isolation can take longer. */ -static int happy_meal_tcvr_reset(struct happy_meal *hp, - struct hmeal_tcvregs *tregs) +static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs) { - unsigned long tconfig; + u32 tconfig; int result, tries = TCVR_RESET_TRIES; - tconfig = hme_read32(hp, &tregs->cfg); + tconfig = hme_read32(hp, tregs + TCVR_CFG); ASD(("happy_meal_tcvr_reset: tcfg<%08lx> ", tconfig)); - if(hp->tcvr_type == external) { + if (hp->tcvr_type == external) { ASD(("external<")); - hme_write32(hp, &tregs->cfg, tconfig & ~(TCV_CFG_PSELECT)); + hme_write32(hp, tregs + TCVR_CFG, tconfig & ~(TCV_CFG_PSELECT)); hp->tcvr_type = internal; hp->paddr = TCV_PADDR_ITX; ASD(("ISOLATE,")); happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE)); result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(result == TCVR_FAILURE) { + if (result == TCVR_FAILURE) { ASD(("phyread_fail>\n")); return -1; } ASD(("phyread_ok,PSELECT>")); - hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT); + hme_write32(hp, tregs + TCVR_CFG, tconfig | TCV_CFG_PSELECT); hp->tcvr_type = external; hp->paddr = TCV_PADDR_ETX; } else { - if(tconfig & TCV_CFG_MDIO1) { + if (tconfig & TCV_CFG_MDIO1) { ASD(("internalcfg, (tconfig | TCV_CFG_PSELECT)); + hme_write32(hp, tregs + TCVR_CFG, (tconfig | TCV_CFG_PSELECT)); ASD(("ISOLATE,")); happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE)); result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(result == TCVR_FAILURE) { + if (result == TCVR_FAILURE) { ASD(("phyread_fail>\n")); return -1; } ASD(("phyread_ok,~PSELECT>")); - hme_write32(hp, &tregs->cfg, (tconfig & ~(TCV_CFG_PSELECT))); + hme_write32(hp, tregs + TCVR_CFG, (tconfig & ~(TCV_CFG_PSELECT))); hp->tcvr_type = internal; hp->paddr = TCV_PADDR_ITX; } @@ -871,16 +1070,16 @@ ASD(("BMCR_RESET ")); happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, BMCR_RESET); - while(--tries) { + while (--tries) { result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(result == TCVR_FAILURE) + if (result == TCVR_FAILURE) return -1; hp->sw_bmcr = result; - if(!(result & BMCR_RESET)) + if (!(result & BMCR_RESET)) break; udelay(20); } - if(!tries) { + if (!tries) { ASD(("BMCR RESET FAILED!\n")); return -1; } @@ -897,36 +1096,39 @@ happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); tries = TCVR_UNISOLATE_TRIES; - while(--tries) { + while (--tries) { result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(result == TCVR_FAILURE) + if (result == TCVR_FAILURE) return -1; - if(!(result & BMCR_ISOLATE)) + if (!(result & BMCR_ISOLATE)) break; udelay(20); } - if(!tries) { + if (!tries) { ASD((" FAILED!\n")); return -1; } ASD((" SUCCESS and CSCONFIG_DFBYPASS\n")); - result = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG); - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, (result | CSCONFIG_DFBYPASS)); + if (!is_lucent_phy(hp)) { + result = happy_meal_tcvr_read(hp, tregs, + DP83840_CSCONFIG); + happy_meal_tcvr_write(hp, tregs, + DP83840_CSCONFIG, (result | CSCONFIG_DFBYPASS)); + } return 0; } /* Figure out whether we have an internal or external transceiver. */ -static void happy_meal_transceiver_check(struct happy_meal *hp, - struct hmeal_tcvregs *tregs) +static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs) { - unsigned long tconfig = hme_read32(hp, &tregs->cfg); + unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG); ASD(("happy_meal_transceiver_check: tcfg=%08lx ", tconfig)); - if(hp->happy_flags & HFLAG_POLL) { + if (hp->happy_flags & HFLAG_POLL) { /* If we are polling, we must stop to get the transceiver type. */ ASD((" ")); - if(hp->tcvr_type == internal) { - if(tconfig & TCV_CFG_MDIO1) { + if (hp->tcvr_type == internal) { + if (tconfig & TCV_CFG_MDIO1) { ASD((" ")); happy_meal_poll_stop(hp, tregs); hp->paddr = TCV_PADDR_ETX; @@ -934,19 +1136,19 @@ ASD(("\n")); tconfig &= ~(TCV_CFG_PENABLE); tconfig |= TCV_CFG_PSELECT; - hme_write32(hp, &tregs->cfg, tconfig); + hme_write32(hp, tregs + TCVR_CFG, tconfig); } } else { - if(hp->tcvr_type == external) { + if (hp->tcvr_type == external) { ASD((" ")); - if(!(hme_read32(hp, &tregs->status) >> 16)) { + if (!(hme_read32(hp, tregs + TCVR_STATUS) >> 16)) { ASD((" ")); happy_meal_poll_stop(hp, tregs); hp->paddr = TCV_PADDR_ITX; hp->tcvr_type = internal; ASD(("\n")); - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) & + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_PSELECT)); } ASD(("\n")); @@ -955,24 +1157,24 @@ } } } else { - unsigned long reread = hme_read32(hp, &tregs->cfg); + u32 reread = hme_read32(hp, tregs + TCVR_CFG); /* Else we can just work off of the MDIO bits. */ ASD((" ")); - if(reread & TCV_CFG_MDIO1) { - hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT); + if (reread & TCV_CFG_MDIO1) { + hme_write32(hp, tregs + TCVR_CFG, tconfig | TCV_CFG_PSELECT); hp->paddr = TCV_PADDR_ETX; hp->tcvr_type = external; ASD(("\n")); } else { - if(reread & TCV_CFG_MDIO0) { - hme_write32(hp, &tregs->cfg, + if (reread & TCV_CFG_MDIO0) { + hme_write32(hp, tregs + TCVR_CFG, tconfig & ~(TCV_CFG_PSELECT)); hp->paddr = TCV_PADDR_ITX; hp->tcvr_type = internal; ASD(("\n")); } else { - printk("happy meal: Transceiver and a coke please."); + printk(KERN_ERR "happy meal: Transceiver and a coke please."); hp->tcvr_type = none; /* Grrr... */ ASD(("\n")); } @@ -1024,20 +1226,34 @@ * * before sending off the skb to the protocols, and we are good as gold. */ -static inline void happy_meal_clean_rings(struct happy_meal *hp) +static void happy_meal_clean_rings(struct happy_meal *hp) { int i; - for(i = 0; i < RX_RING_SIZE; i++) { - if(hp->rx_skbs[i] != NULL) { - dev_kfree_skb(hp->rx_skbs[i]); + for (i = 0; i < RX_RING_SIZE; i++) { + if (hp->rx_skbs[i] != NULL) { + struct sk_buff *skb = hp->rx_skbs[i]; + struct happy_meal_rxd *rxd; + u32 dma_addr; + + rxd = &hp->happy_block->happy_meal_rxd[i]; + dma_addr = hme_read_desc32(hp, &rxd->rx_addr); + hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE); + dev_kfree_skb(skb); hp->rx_skbs[i] = NULL; } } - for(i = 0; i < TX_RING_SIZE; i++) { - if(hp->tx_skbs[i] != NULL) { - dev_kfree_skb(hp->tx_skbs[i]); + for (i = 0; i < TX_RING_SIZE; i++) { + if (hp->tx_skbs[i] != NULL) { + struct sk_buff *skb = hp->tx_skbs[i]; + struct happy_meal_txd *txd; + u32 dma_addr; + + txd = &hp->happy_block->happy_meal_txd[i]; + dma_addr = hme_read_desc32(hp, &txd->tx_addr); + hme_dma_unmap(hp, dma_addr, skb->len); + dev_kfree_skb(skb); hp->tx_skbs[i] = NULL; } } @@ -1049,7 +1265,7 @@ struct net_device *dev = hp->dev; int i, gfp_flags = GFP_KERNEL; - if(from_irq || in_interrupt()) + if (from_irq || in_interrupt()) gfp_flags = GFP_ATOMIC; HMD(("happy_meal_init_rings: counters to zero, ")); @@ -1061,76 +1277,34 @@ /* Now get new skippy bufs for the receive ring. */ HMD(("init rxring, ")); - for(i = 0; i < RX_RING_SIZE; i++) { + for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; - skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags | GFP_DMA); - if(!skb) + skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags); + if (!skb) { + hme_write_rxd(hp, &hb->happy_meal_rxd[i], 0, 0); continue; + } hp->rx_skbs[i] = skb; skb->dev = dev; /* Because we reserve afterwards. */ skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET)); - -#ifdef CONFIG_PCI - if(hp->happy_flags & HFLAG_PCI) { - pcihme_write_rxd(&hb->happy_meal_rxd[i], - (RXFLAG_OWN | - ((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), - (u32)virt_to_bus((volatile void *)skb->data)); - } else -#endif -#ifndef __sparc_v9__ - if (sparc_cpu_model == sun4d) { - __u32 va = (__u32)hp->sun4d_buffers + i * PAGE_SIZE; - - hb->happy_meal_rxd[i].rx_addr = - iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus); - hb->happy_meal_rxd[i].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); - } else -#endif - { - hb->happy_meal_rxd[i].rx_addr = sbus_dvma_addr(skb->data); - hb->happy_meal_rxd[i].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); - } + hme_write_rxd(hp, &hb->happy_meal_rxd[i], + (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), + hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE)); skb_reserve(skb, RX_OFFSET); } HMD(("init txring, ")); - for(i = 0; i < TX_RING_SIZE; i++) - hb->happy_meal_txd[i].tx_flags = 0; - HMD(("done\n")); -} - -#ifndef __sparc_v9__ -static void sun4c_happy_meal_init_rings(struct happy_meal *hp) -{ - struct hmeal_init_block *hb = hp->happy_block; - __u32 hbufs = hp->s4c_buf_dvma; - int i; - - HMD(("happy_meal_init_rings: counters to zero, ")); - hp->rx_new = hp->rx_old = hp->tx_new = hp->tx_old = 0; - - HMD(("init rxring, ")); - for(i = 0; i < RX_RING_SIZE; i++) { - hb->happy_meal_rxd[i].rx_addr = hbufs + hbuf_offset(rx_buf, i); - hb->happy_meal_rxd[i].rx_flags = - (RXFLAG_OWN | ((SUN4C_RX_BUFF_SIZE - RX_OFFSET) << 16)); - } + for (i = 0; i < TX_RING_SIZE; i++) + hme_write_txd(hp, &hb->happy_meal_txd[i], 0, 0); - HMD(("init txring, ")); - for(i = 0; i < TX_RING_SIZE; i++) - hb->happy_meal_txd[i].tx_flags = 0; HMD(("done\n")); } -#endif static void happy_meal_begin_auto_negotiation(struct happy_meal *hp, - struct hmeal_tcvregs *tregs, + unsigned long tregs, struct ethtool_cmd *ep) { int timeout; @@ -1144,22 +1318,22 @@ /* XXX Check BMSR_ANEGCAPABLE, should not be necessary though. */ hp->sw_advertise = happy_meal_tcvr_read(hp, tregs, DP83840_ADVERTISE); - if(ep == NULL || ep->autoneg == AUTONEG_ENABLE) { + if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) { /* Advertise everything we can support. */ - if(hp->sw_bmsr & BMSR_10HALF) + if (hp->sw_bmsr & BMSR_10HALF) hp->sw_advertise |= (ADVERTISE_10HALF); else hp->sw_advertise &= ~(ADVERTISE_10HALF); - if(hp->sw_bmsr & BMSR_10FULL) + if (hp->sw_bmsr & BMSR_10FULL) hp->sw_advertise |= (ADVERTISE_10FULL); else hp->sw_advertise &= ~(ADVERTISE_10FULL); - if(hp->sw_bmsr & BMSR_100HALF) + if (hp->sw_bmsr & BMSR_100HALF) hp->sw_advertise |= (ADVERTISE_100HALF); else hp->sw_advertise &= ~(ADVERTISE_100HALF); - if(hp->sw_bmsr & BMSR_100FULL) + if (hp->sw_bmsr & BMSR_100FULL) hp->sw_advertise |= (ADVERTISE_100FULL); else hp->sw_advertise &= ~(ADVERTISE_100FULL); @@ -1173,13 +1347,13 @@ #ifdef AUTO_SWITCH_DEBUG ASD(("%s: Advertising [ ", hp->dev->name)); - if(hp->sw_advertise & ADVERTISE_10HALF) + if (hp->sw_advertise & ADVERTISE_10HALF) ASD(("10H ")); - if(hp->sw_advertise & ADVERTISE_10FULL) + if (hp->sw_advertise & ADVERTISE_10FULL) ASD(("10F ")); - if(hp->sw_advertise & ADVERTISE_100HALF) + if (hp->sw_advertise & ADVERTISE_100HALF) ASD(("100H ")); - if(hp->sw_advertise & ADVERTISE_100FULL) + if (hp->sw_advertise & ADVERTISE_100FULL) ASD(("100F ")); #endif @@ -1194,16 +1368,16 @@ /* BMCR_ANRESTART self clears when the process has begun. */ timeout = 64; /* More than enough. */ - while(--timeout) { + while (--timeout) { hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); - if(!(hp->sw_bmcr & BMCR_ANRESTART)) + if (!(hp->sw_bmcr & BMCR_ANRESTART)) break; /* got it. */ udelay(10); } - if(!timeout) { - printk("%s: Happy Meal would not start auto negotiation " + if (!timeout) { + printk(KERN_ERR "%s: Happy Meal would not start auto negotiation " "BMCR=0x%04x\n", hp->dev->name, hp->sw_bmcr); - printk("%s: Performing force link detection.\n", + printk(KERN_NOTICE "%s: Performing force link detection.\n", hp->dev->name); goto force_link; } else { @@ -1219,28 +1393,29 @@ /* Disable auto-negotiation in BMCR, enable the duplex and * speed setting, init the timer state machine, and fire it off. */ - if(ep == NULL || ep->autoneg == AUTONEG_ENABLE) { + if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) { hp->sw_bmcr = BMCR_SPEED100; } else { - if(ep->speed == SPEED_100) + if (ep->speed == SPEED_100) hp->sw_bmcr = BMCR_SPEED100; else hp->sw_bmcr = 0; - if(ep->duplex == DUPLEX_FULL) + if (ep->duplex == DUPLEX_FULL) hp->sw_bmcr |= BMCR_FULLDPLX; } happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); - /* OK, seems we need do disable the transceiver for the first - * tick to make sure we get an accurate link state at the - * second tick. - */ - hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, - DP83840_CSCONFIG); - hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); - happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, - hp->sw_csconfig); - + if (!is_lucent_phy(hp)) { + /* OK, seems we need do disable the transceiver for the first + * tick to make sure we get an accurate link state at the + * second tick. + */ + hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, + DP83840_CSCONFIG); + hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB); + happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, + hp->sw_csconfig); + } hp->timer_state = ltrywait; } @@ -1256,12 +1431,12 @@ static int happy_meal_init(struct happy_meal *hp, int from_irq) { - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_etxregs *etxregs = hp->etxregs; - struct hmeal_erxregs *erxregs = hp->erxregs; - struct hmeal_bigmacregs *bregs = hp->bigmacregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned long regtmp, rxcfg; + unsigned long gregs = hp->gregs; + unsigned long etxregs = hp->etxregs; + unsigned long erxregs = hp->erxregs; + unsigned long bregs = hp->bigmacregs; + unsigned long tregs = hp->tcvregs; + u32 regtmp, rxcfg; unsigned char *e = &hp->dev->dev_addr[0]; /* If auto-negotiation timer is running, kill it. */ @@ -1269,7 +1444,7 @@ HMD(("happy_meal_init: happy_flags[%08x] ", hp->happy_flags)); - if(!(hp->happy_flags & HFLAG_INIT)) { + if (!(hp->happy_flags & HFLAG_INIT)) { HMD(("set HFLAG_INIT, ")); hp->happy_flags |= HFLAG_INIT; happy_meal_get_counters(hp, bregs); @@ -1285,29 +1460,24 @@ /* Alloc and reset the tx/rx descriptor chains. */ HMD(("happy_meal_init: to happy_meal_init_rings\n")); -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - sun4c_happy_meal_init_rings(hp); - else -#endif - happy_meal_init_rings(hp, from_irq); + happy_meal_init_rings(hp, from_irq); /* Shut up the MIF. */ HMD(("happy_meal_init: Disable all MIF irqs (old[%08x]), ", hme_read32(hp, &tregs->int_mask))); - hme_write32(hp, &tregs->int_mask, 0xffff); + hme_write32(hp, tregs + TCVR_IMASK, 0xffff); /* See if we can enable the MIF frame on this card to speak to the DP83840. */ - if(hp->happy_flags & HFLAG_FENABLE) { + if (hp->happy_flags & HFLAG_FENABLE) { HMD(("use frame old[%08x], ", hme_read32(hp, &tregs->cfg))); - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_BENABLE)); + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_BENABLE)); } else { HMD(("use bitbang old[%08x], ", hme_read32(hp, &tregs->cfg))); - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) | TCV_CFG_BENABLE); + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE); } /* Check the state of the transceiver. */ @@ -1325,17 +1495,17 @@ case internal: /* Using the MII buffers. */ HMD(("internal, using MII, ")); - hme_write32(hp, &bregs->xif_cfg, 0); + hme_write32(hp, bregs + BMAC_XIFCFG, 0); break; case external: /* Not using the MII, disable it. */ HMD(("external, disable MII, ")); - hme_write32(hp, &bregs->xif_cfg, BIGMAC_XCFG_MIIDISAB); + hme_write32(hp, bregs + BMAC_XIFCFG, BIGMAC_XCFG_MIIDISAB); break; }; - if(happy_meal_tcvr_reset(hp, tregs)) + if (happy_meal_tcvr_reset(hp, tregs)) return -EAGAIN; /* Reset the Happy Meal Big Mac transceiver and the receiver. */ @@ -1345,128 +1515,132 @@ /* Set jam size and inter-packet gaps to reasonable defaults. */ HMD(("jsize/ipg1/ipg2, ")); - hme_write32(hp, &bregs->jsize, DEFAULT_JAMSIZE); - hme_write32(hp, &bregs->ipkt_gap1, DEFAULT_IPG1); - hme_write32(hp, &bregs->ipkt_gap2, DEFAULT_IPG2); + hme_write32(hp, bregs + BMAC_JSIZE, DEFAULT_JAMSIZE); + hme_write32(hp, bregs + BMAC_IGAP1, DEFAULT_IPG1); + hme_write32(hp, bregs + BMAC_IGAP2, DEFAULT_IPG2); /* Load up the MAC address and random seed. */ HMD(("rseed/macaddr, ")); /* The docs recommend to use the 10LSB of our MAC here. */ - hme_write32(hp, &bregs->rand_seed, ((e[5] | e[4]<<8)&0x3ff)); + hme_write32(hp, bregs + BMAC_RSEED, ((e[5] | e[4]<<8)&0x3ff)); - hme_write32(hp, &bregs->mac_addr2, ((e[4] << 8) | e[5])); - hme_write32(hp, &bregs->mac_addr1, ((e[2] << 8) | e[3])); - hme_write32(hp, &bregs->mac_addr0, ((e[0] << 8) | e[1])); + hme_write32(hp, bregs + BMAC_MACADDR2, ((e[4] << 8) | e[5])); + hme_write32(hp, bregs + BMAC_MACADDR1, ((e[2] << 8) | e[3])); + hme_write32(hp, bregs + BMAC_MACADDR0, ((e[0] << 8) | e[1])); HMD(("htable, ")); - if((hp->dev->flags & IFF_ALLMULTI) || - (hp->dev->mc_count > 64)) { - hme_write32(hp, &bregs->htable0, 0xffff); - hme_write32(hp, &bregs->htable1, 0xffff); - hme_write32(hp, &bregs->htable2, 0xffff); - hme_write32(hp, &bregs->htable3, 0xffff); - } else if((hp->dev->flags & IFF_PROMISC) == 0) { + if ((hp->dev->flags & IFF_ALLMULTI) || + (hp->dev->mc_count > 64)) { + hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff); + } else if ((hp->dev->flags & IFF_PROMISC) == 0) { u16 hash_table[4]; struct dev_mc_list *dmi = hp->dev->mc_list; char *addrs; int i, j, bit, byte; u32 crc, poly = CRC_POLYNOMIAL_LE; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < hp->dev->mc_count; i++) { + for (i = 0; i < hp->dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - if(!(*addrs & 1)) + if (!(*addrs & 1)) continue; crc = 0xffffffffU; - for(byte = 0; byte < 6; byte++) { - for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + for (byte = 0; byte < 6; byte++) { + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { int test; test = ((bit ^ crc) & 0x01); crc >>= 1; - if(test) + if (test) crc = crc ^ poly; } } crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } - hme_write32(hp, &bregs->htable0, hash_table[0]); - hme_write32(hp, &bregs->htable1, hash_table[1]); - hme_write32(hp, &bregs->htable2, hash_table[2]); - hme_write32(hp, &bregs->htable3, hash_table[3]); + hme_write32(hp, bregs + BMAC_HTABLE0, hash_table[0]); + hme_write32(hp, bregs + BMAC_HTABLE1, hash_table[1]); + hme_write32(hp, bregs + BMAC_HTABLE2, hash_table[2]); + hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]); } else { - hme_write32(hp, &bregs->htable3, 0); - hme_write32(hp, &bregs->htable2, 0); - hme_write32(hp, &bregs->htable1, 0); - hme_write32(hp, &bregs->htable0, 0); + hme_write32(hp, bregs + BMAC_HTABLE3, 0); + hme_write32(hp, bregs + BMAC_HTABLE2, 0); + hme_write32(hp, bregs + BMAC_HTABLE1, 0); + hme_write32(hp, bregs + BMAC_HTABLE0, 0); } /* Set the RX and TX ring ptrs. */ HMD(("ring ptrs rxr[%08x] txr[%08x]\n", (hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0)), (hp->hblock_dvma + hblock_offset(happy_meal_txd, 0)))); - hme_write32(hp, &erxregs->rx_ring, + hme_write32(hp, erxregs + ERX_RING, (hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0))); - hme_write32(hp, &etxregs->tx_ring, + hme_write32(hp, etxregs + ETX_RING, (hp->hblock_dvma + hblock_offset(happy_meal_txd, 0))); /* Set the supported burst sizes. */ HMD(("happy_meal_init: old[%08x] bursts<", - hme_read32(hp, &gregs->cfg))); + hme_read32(hp, gregs + GREG_CFG))); -#ifdef __sparc_v9__ - /* XXX Can sun4d do these too? */ - if(hp->happy_bursts & DMA_BURST64) { + if ((hp->happy_bursts & DMA_BURST64) && + ((hp->happy_flags & HFLAG_PCI) != 0 +#ifdef CONFIG_SBUS + || sbus_can_burst64(hp->happy_dev) +#endif + || 0)) { u32 gcfg = GREG_CFG_BURST64; /* I have no idea if I should set the extended * transfer mode bit for Cheerio, so for now I * do not. -DaveM */ - if((hp->happy_flags & HFLAG_PCI) == 0) { - mmu_set_sbus64(hp->happy_sbus_dev, - hp->happy_bursts); +#ifdef CONFIG_SBUS + if ((hp->happy_flags & HFLAG_PCI) == 0 && + sbus_can_dma_64bit(hp->happy_dev)) { + sbus_set_sbus64(hp->happy_dev, + hp->happy_bursts); gcfg |= GREG_CFG_64BIT; } +#endif HMD(("64>")); - hme_write32(hp, &gregs->cfg, gcfg); - } else -#endif - if(hp->happy_bursts & DMA_BURST32) { + hme_write32(hp, gregs + GREG_CFG, gcfg); + } else if (hp->happy_bursts & DMA_BURST32) { HMD(("32>")); - hme_write32(hp, &gregs->cfg, GREG_CFG_BURST32); - } else if(hp->happy_bursts & DMA_BURST16) { + hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST32); + } else if (hp->happy_bursts & DMA_BURST16) { HMD(("16>")); - hme_write32(hp, &gregs->cfg, GREG_CFG_BURST16); + hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST16); } else { HMD(("XXX>")); - hme_write32(hp, &gregs->cfg, 0); + hme_write32(hp, gregs + GREG_CFG, 0); } /* Turn off interrupts we do not want to hear. */ HMD((", enable global interrupts, ")); - hme_write32(hp, &gregs->imask, + hme_write32(hp, gregs + GREG_IMASK, (GREG_IMASK_GOTFRAME | GREG_IMASK_RCNTEXP | GREG_IMASK_SENTFRAME | GREG_IMASK_TXPERR)); /* Set the transmit ring buffer size. */ HMD(("tx rsize=%d oreg[%08x], ", (int)TX_RING_SIZE, - hme_read32(hp, &etxregs->tx_rsize))); - hme_write32(hp, &etxregs->tx_rsize, (TX_RING_SIZE >> ETX_RSIZE_SHIFT) - 1); + hme_read32(hp, etxregs + ETX_RSIZE))); + hme_write32(hp, etxregs + ETX_RSIZE, (TX_RING_SIZE >> ETX_RSIZE_SHIFT) - 1); /* Enable transmitter DVMA. */ HMD(("tx dma enable old[%08x], ", - hme_read32(hp, &etxregs->cfg))); - hme_write32(hp, &etxregs->cfg, - hme_read32(hp, &etxregs->cfg) | ETX_CFG_DMAENABLE); + hme_read32(hp, etxregs + ETX_CFG))); + hme_write32(hp, etxregs + ETX_CFG, + hme_read32(hp, etxregs + ETX_CFG) | ETX_CFG_DMAENABLE); /* This chip really rots, for the receiver sometimes when you * write to it's control registers not all the bits get there @@ -1474,24 +1648,24 @@ * coverage for this hardware bug yet. */ HMD(("erx regs bug old[%08x]\n", - hme_read32(hp, &erxregs->cfg))); - hme_write32(hp, &erxregs->cfg, ERX_CFG_DEFAULT(RX_OFFSET)); - regtmp = hme_read32(hp, &erxregs->cfg); - hme_write32(hp, &erxregs->cfg, ERX_CFG_DEFAULT(RX_OFFSET)); - if(hme_read32(hp, &erxregs->cfg) != ERX_CFG_DEFAULT(RX_OFFSET)) { - printk("happy meal: Eieee, rx config register gets greasy fries.\n"); - printk("happy meal: Trying to set %08x, reread gives %08lx\n", + hme_read32(hp, erxregs + ERX_CFG))); + hme_write32(hp, erxregs + ERX_CFG, ERX_CFG_DEFAULT(RX_OFFSET)); + regtmp = hme_read32(hp, erxregs + ERX_CFG); + hme_write32(hp, erxregs + ERX_CFG, ERX_CFG_DEFAULT(RX_OFFSET)); + if (hme_read32(hp, erxregs + ERX_CFG) != ERX_CFG_DEFAULT(RX_OFFSET)) { + printk(KERN_ERR "happy meal: Eieee, rx config register gets greasy fries.\n"); + printk(KERN_ERR "happy meal: Trying to set %08x, reread gives %08x\n", ERX_CFG_DEFAULT(RX_OFFSET), regtmp); /* XXX Should return failure here... */ } /* Enable Big Mac hash table filter. */ HMD(("happy_meal_init: enable hash rx_cfg_old[%08x], ", - hme_read32(hp, &bregs->rx_cfg))); + hme_read32(hp, bregs + BMAC_RXCFG))); rxcfg = BIGMAC_RXCFG_HENABLE; - if(hp->dev->flags & IFF_PROMISC) + if (hp->dev->flags & IFF_PROMISC) rxcfg |= BIGMAC_RXCFG_PMISC; - hme_write32(hp, &bregs->rx_cfg, rxcfg); + hme_write32(hp, bregs + BMAC_RXCFG, rxcfg); /* Let the bits settle in the chip. */ udelay(10); @@ -1499,33 +1673,33 @@ /* Ok, configure the Big Mac transmitter. */ HMD(("BIGMAC init, ")); regtmp = 0; - if(hp->happy_flags & HFLAG_FULL) + if (hp->happy_flags & HFLAG_FULL) regtmp |= BIGMAC_TXCFG_FULLDPLX; - hme_write32(hp, &bregs->tx_cfg, regtmp | BIGMAC_TXCFG_DGIVEUP); + hme_write32(hp, bregs + BMAC_TXCFG, regtmp | BIGMAC_TXCFG_DGIVEUP); /* Enable the output drivers no matter what. */ regtmp = BIGMAC_XCFG_ODENABLE; /* If card can do lance mode, enable it. */ - if(hp->happy_flags & HFLAG_LANCE) + if (hp->happy_flags & HFLAG_LANCE) regtmp |= (DEFAULT_IPG0 << 5) | BIGMAC_XCFG_LANCE; /* Disable the MII buffers if using external transceiver. */ - if(hp->tcvr_type == external) + if (hp->tcvr_type == external) regtmp |= BIGMAC_XCFG_MIIDISAB; HMD(("XIF config old[%08x], ", - hme_read32(hp, &bregs->xif_cfg))); - hme_write32(hp, &bregs->xif_cfg, regtmp); + hme_read32(hp, bregs + BMAC_XIFCFG))); + hme_write32(hp, bregs + BMAC_XIFCFG, regtmp); /* Start things up. */ HMD(("tx old[%08x] and rx [%08x] ON!\n", - hme_read32(hp, &bregs->tx_cfg), - hme_read32(hp, &bregs->rx_cfg))); - hme_write32(hp, &bregs->tx_cfg, - hme_read32(hp, &bregs->tx_cfg) | BIGMAC_TXCFG_ENABLE); - hme_write32(hp, &bregs->rx_cfg, - hme_read32(hp, &bregs->rx_cfg) | BIGMAC_RXCFG_ENABLE); + hme_read32(hp, bregs + BMAC_TXCFG), + hme_read32(hp, bregs + BMAC_RXCFG))); + hme_write32(hp, bregs + BMAC_TXCFG, + hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE); + hme_write32(hp, bregs + BMAC_RXCFG, + hme_read32(hp, bregs + BMAC_RXCFG) | BIGMAC_RXCFG_ENABLE); /* Get the autonegotiation started, and the watch timer ticking. */ happy_meal_begin_auto_negotiation(hp, tregs, NULL); @@ -1536,30 +1710,30 @@ static void happy_meal_set_initial_advertisement(struct happy_meal *hp) { - struct hmeal_tcvregs *tregs = hp->tcvregs; - struct hmeal_bigmacregs *bregs = hp->bigmacregs; - struct hmeal_gregs *gregs = hp->gregs; + unsigned long tregs = hp->tcvregs; + unsigned long bregs = hp->bigmacregs; + unsigned long gregs = hp->gregs; happy_meal_stop(hp, gregs); - hme_write32(hp, &tregs->int_mask, 0xffff); - if(hp->happy_flags & HFLAG_FENABLE) - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_BENABLE)); + hme_write32(hp, tregs + TCVR_IMASK, 0xffff); + if (hp->happy_flags & HFLAG_FENABLE) + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_BENABLE)); else - hme_write32(hp, &tregs->cfg, - hme_read32(hp, &tregs->cfg) | TCV_CFG_BENABLE); + hme_write32(hp, tregs + TCVR_CFG, + hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE); happy_meal_transceiver_check(hp, tregs); switch(hp->tcvr_type) { case none: return; case internal: - hme_write32(hp, &bregs->xif_cfg, 0); + hme_write32(hp, bregs + BMAC_XIFCFG, 0); break; case external: - hme_write32(hp, &bregs->xif_cfg, BIGMAC_XCFG_MIIDISAB); + hme_write32(hp, bregs + BMAC_XIFCFG, BIGMAC_XCFG_MIIDISAB); break; }; - if(happy_meal_tcvr_reset(hp, tregs)) + if (happy_meal_tcvr_reset(hp, tregs)) return; /* Latch PHY registers as of now. */ @@ -1567,20 +1741,20 @@ hp->sw_advertise = happy_meal_tcvr_read(hp, tregs, DP83840_ADVERTISE); /* Advertise everything we can support. */ - if(hp->sw_bmsr & BMSR_10HALF) + if (hp->sw_bmsr & BMSR_10HALF) hp->sw_advertise |= (ADVERTISE_10HALF); else hp->sw_advertise &= ~(ADVERTISE_10HALF); - if(hp->sw_bmsr & BMSR_10FULL) + if (hp->sw_bmsr & BMSR_10FULL) hp->sw_advertise |= (ADVERTISE_10FULL); else hp->sw_advertise &= ~(ADVERTISE_10FULL); - if(hp->sw_bmsr & BMSR_100HALF) + if (hp->sw_bmsr & BMSR_100HALF) hp->sw_advertise |= (ADVERTISE_100HALF); else hp->sw_advertise &= ~(ADVERTISE_100HALF); - if(hp->sw_bmsr & BMSR_100FULL) + if (hp->sw_bmsr & BMSR_100FULL) hp->sw_advertise |= (ADVERTISE_100FULL); else hp->sw_advertise &= ~(ADVERTISE_100FULL); @@ -1592,50 +1766,48 @@ /* Once status is latched (by happy_meal_interrupt) it is cleared by * the hardware, so we cannot re-read it and get a correct value. */ -static int happy_meal_is_not_so_happy(struct happy_meal *hp, - struct hmeal_gregs *gregs, - unsigned long status) +static int happy_meal_is_not_so_happy(struct happy_meal *hp, u32 status) { int reset = 0; /* Only print messages for non-counter related interrupts. */ - if(status & (GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND | - GREG_STAT_MAXPKTERR | GREG_STAT_RXERR | - GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR | - GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR | - GREG_STAT_TXPERR | GREG_STAT_TXTERR | GREG_STAT_SLVERR | - GREG_STAT_SLVPERR)) - printk("%s: Error interrupt for happy meal, status = %08lx\n", + if (status & (GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND | + GREG_STAT_MAXPKTERR | GREG_STAT_RXERR | + GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR | + GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR | + GREG_STAT_TXPERR | GREG_STAT_TXTERR | GREG_STAT_SLVERR | + GREG_STAT_SLVPERR)) + printk(KERN_ERR "%s: Error interrupt for happy meal, status = %08x\n", hp->dev->name, status); - if(status & GREG_STAT_RFIFOVF) { + if (status & GREG_STAT_RFIFOVF) { /* Receive FIFO overflow is harmless and the hardware will take care of it, just some packets are lost. Who cares. */ printk(KERN_DEBUG "%s: Happy Meal receive FIFO overflow.\n", hp->dev->name); } - if(status & GREG_STAT_STSTERR) { + if (status & GREG_STAT_STSTERR) { /* BigMAC SQE link test failed. */ - printk("%s: Happy Meal BigMAC SQE test failed.\n", hp->dev->name); + printk(KERN_ERR "%s: Happy Meal BigMAC SQE test failed.\n", hp->dev->name); reset = 1; } - if(status & GREG_STAT_TFIFO_UND) { + if (status & GREG_STAT_TFIFO_UND) { /* Transmit FIFO underrun, again DMA error likely. */ - printk("%s: Happy Meal transmitter FIFO underrun, DMA error.\n", + printk(KERN_ERR "%s: Happy Meal transmitter FIFO underrun, DMA error.\n", hp->dev->name); reset = 1; } - if(status & GREG_STAT_MAXPKTERR) { + if (status & GREG_STAT_MAXPKTERR) { /* Driver error, tried to transmit something larger * than ethernet max mtu. */ - printk("%s: Happy Meal MAX Packet size error.\n", hp->dev->name); + printk(KERN_ERR "%s: Happy Meal MAX Packet size error.\n", hp->dev->name); reset = 1; } - if(status & GREG_STAT_NORXD) { + if (status & GREG_STAT_NORXD) { /* This is harmless, it just means the system is * quite loaded and the incomming packet rate was * faster than the interrupt handler could keep up @@ -1646,87 +1818,87 @@ hp->dev->name); } - if(status & (GREG_STAT_RXERR|GREG_STAT_RXPERR|GREG_STAT_RXTERR)) { + if (status & (GREG_STAT_RXERR|GREG_STAT_RXPERR|GREG_STAT_RXTERR)) { /* All sorts of DMA receive errors. */ - printk("%s: Happy Meal rx DMA errors [ ", hp->dev->name); - if(status & GREG_STAT_RXERR) + printk(KERN_ERR "%s: Happy Meal rx DMA errors [ ", hp->dev->name); + if (status & GREG_STAT_RXERR) printk("GenericError "); - if(status & GREG_STAT_RXPERR) + if (status & GREG_STAT_RXPERR) printk("ParityError "); - if(status & GREG_STAT_RXTERR) + if (status & GREG_STAT_RXTERR) printk("RxTagBotch "); printk("]\n"); reset = 1; } - if(status & GREG_STAT_EOPERR) { + if (status & GREG_STAT_EOPERR) { /* Driver bug, didn't set EOP bit in tx descriptor given * to the happy meal. */ - printk("%s: EOP not set in happy meal transmit descriptor!\n", + printk(KERN_ERR "%s: EOP not set in happy meal transmit descriptor!\n", hp->dev->name); reset = 1; } - if(status & GREG_STAT_MIFIRQ) { + if (status & GREG_STAT_MIFIRQ) { /* MIF signalled an interrupt, were we polling it? */ - printk("%s: Happy Meal MIF interrupt.\n", hp->dev->name); + printk(KERN_ERR "%s: Happy Meal MIF interrupt.\n", hp->dev->name); } - if(status & - (GREG_STAT_TXEACK|GREG_STAT_TXLERR|GREG_STAT_TXPERR|GREG_STAT_TXTERR)) { + if (status & + (GREG_STAT_TXEACK|GREG_STAT_TXLERR|GREG_STAT_TXPERR|GREG_STAT_TXTERR)) { /* All sorts of transmit DMA errors. */ - printk("%s: Happy Meal tx DMA errors [ ", hp->dev->name); - if(status & GREG_STAT_TXEACK) + printk(KERN_ERR "%s: Happy Meal tx DMA errors [ ", hp->dev->name); + if (status & GREG_STAT_TXEACK) printk("GenericError "); - if(status & GREG_STAT_TXLERR) + if (status & GREG_STAT_TXLERR) printk("LateError "); - if(status & GREG_STAT_TXPERR) + if (status & GREG_STAT_TXPERR) printk("ParityErro "); - if(status & GREG_STAT_TXTERR) + if (status & GREG_STAT_TXTERR) printk("TagBotch "); printk("]\n"); reset = 1; } - if(status & (GREG_STAT_SLVERR|GREG_STAT_SLVPERR)) { + if (status & (GREG_STAT_SLVERR|GREG_STAT_SLVPERR)) { /* Bus or parity error when cpu accessed happy meal registers * or it's internal FIFO's. Should never see this. */ - printk("%s: Happy Meal register access SBUS slave (%s) error.\n", + printk(KERN_ERR "%s: Happy Meal register access SBUS slave (%s) error.\n", hp->dev->name, (status & GREG_STAT_SLVPERR) ? "parity" : "generic"); reset = 1; } - if(reset) { - printk("%s: Resetting...\n", hp->dev->name); + if (reset) { + printk(KERN_NOTICE "%s: Resetting...\n", hp->dev->name); happy_meal_init(hp, 1); return 1; } return 0; } -static inline void happy_meal_mif_interrupt(struct happy_meal *hp, - struct hmeal_gregs *gregs, - struct hmeal_tcvregs *tregs) +static void happy_meal_mif_interrupt(struct happy_meal *hp) { - printk("%s: Link status change.\n", hp->dev->name); + unsigned long tregs = hp->tcvregs; + + printk(KERN_INFO "%s: Link status change.\n", hp->dev->name); hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR); hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA); /* Use the fastest transmission protocol possible. */ - if(hp->sw_lpa & LPA_100FULL) { - printk("%s: Switching to 100Mbps at full duplex.", hp->dev->name); + if (hp->sw_lpa & LPA_100FULL) { + printk(KERN_INFO "%s: Switching to 100Mbps at full duplex.", hp->dev->name); hp->sw_bmcr |= (BMCR_FULLDPLX | BMCR_SPEED100); - } else if(hp->sw_lpa & LPA_100HALF) { - printk("%s: Switching to 100MBps at half duplex.", hp->dev->name); + } else if (hp->sw_lpa & LPA_100HALF) { + printk(KERN_INFO "%s: Switching to 100MBps at half duplex.", hp->dev->name); hp->sw_bmcr |= BMCR_SPEED100; - } else if(hp->sw_lpa & LPA_10FULL) { - printk("%s: Switching to 10MBps at full duplex.", hp->dev->name); + } else if (hp->sw_lpa & LPA_10FULL) { + printk(KERN_INFO "%s: Switching to 10MBps at full duplex.", hp->dev->name); hp->sw_bmcr |= BMCR_FULLDPLX; } else { - printk("%s: Using 10Mbps at half duplex.", hp->dev->name); + printk(KERN_INFO "%s: Using 10Mbps at half duplex.", hp->dev->name); } happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr); @@ -1740,60 +1912,28 @@ #define TXD(x) #endif -static inline void happy_meal_tx(struct happy_meal *hp) +static void happy_meal_tx(struct happy_meal *hp) { struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0]; struct happy_meal_txd *this; int elem = hp->tx_old; TXD(("TX<")); - while(elem != hp->tx_new) { + while (elem != hp->tx_new) { struct sk_buff *skb; + u32 flags, dma_addr; TXD(("[%d]", elem)); this = &txbase[elem]; - if(this->tx_flags & TXFLAG_OWN) + flags = hme_read_desc32(hp, &this->tx_flags); + if (flags & TXFLAG_OWN) break; + dma_addr = hme_read_desc32(hp, &this->tx_addr); skb = hp->tx_skbs[elem]; + hme_dma_unmap(hp, dma_addr, skb->len); hp->tx_skbs[elem] = NULL; - hp->net_stats.tx_bytes+=skb->len; - - dev_kfree_skb(skb); - - hp->net_stats.tx_packets++; - elem = NEXT_TX(elem); - } - hp->tx_old = elem; - TXD((">")); -} - -#ifdef CONFIG_PCI -static inline void pci_happy_meal_tx(struct happy_meal *hp) -{ - struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0]; - struct happy_meal_txd *this; - int elem = hp->tx_old; + hp->net_stats.tx_bytes += skb->len; - TXD(("TX<")); - while(elem != hp->tx_new) { - struct sk_buff *skb; - unsigned int flags; - - TXD(("[%d]", elem)); - this = &txbase[elem]; -#ifdef __sparc_v9__ - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=r" (flags) - : "r" (&this->tx_flags), "i" (ASI_PL)); -#else - flags = flip_dword(this->tx_flags); -#endif - if(flags & TXFLAG_OWN) - break; - skb = hp->tx_skbs[elem]; - hp->tx_skbs[elem] = NULL; - hp->net_stats.tx_bytes+=skb->len; - dev_kfree_skb(skb); hp->net_stats.tx_packets++; @@ -1802,31 +1942,6 @@ hp->tx_old = elem; TXD((">")); } -#endif - -#ifndef __sparc_v9__ -static inline void sun4c_happy_meal_tx(struct happy_meal *hp) -{ - struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0]; - struct happy_meal_txd *this; - int elem = hp->tx_old; - - TXD(("TX<")); - while(elem != hp->tx_new) { - TXD(("[%d]", elem)); - - this = &txbase[elem]; - - if(this->tx_flags & TXFLAG_OWN) - break; - - hp->net_stats.tx_packets++; - elem = NEXT_TX(elem); - } - hp->tx_old = elem; - TXD((">")); -} -#endif #ifdef RXDEBUG #define RXD(x) printk x @@ -1841,30 +1956,30 @@ * ring when we cannot get a new skb and give them all back to the happy meal, * maybe things will be "happier" now. */ -static inline void happy_meal_rx(struct happy_meal *hp, struct net_device *dev, - struct hmeal_gregs *gregs) +static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) { struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0]; struct happy_meal_rxd *this; int elem = hp->rx_new, drops = 0; + u32 flags; RXD(("RX<")); this = &rxbase[elem]; - while(!(this->rx_flags & RXFLAG_OWN)) { + while (!((flags = hme_read_desc32(hp, &this->rx_flags)) & RXFLAG_OWN)) { struct sk_buff *skb; - unsigned int flags = this->rx_flags; int len = flags >> 16; u16 csum = flags & RXFLAG_CSUM; + u32 dma_addr = hme_read_desc32(hp, &this->rx_addr); RXD(("[%d ", elem)); /* Check for errors. */ - if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { + if ((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { RXD(("ERR(%08x)]", flags)); hp->net_stats.rx_errors++; - if(len < ETH_ZLEN) + if (len < ETH_ZLEN) hp->net_stats.rx_length_errors++; - if(len & (RXFLAG_OVERFLOW >> 16)) { + if (len & (RXFLAG_OVERFLOW >> 16)) { hp->net_stats.rx_over_errors++; hp->net_stats.rx_fifo_errors++; } @@ -1872,41 +1987,36 @@ /* Return it to the Happy meal. */ drop_it: hp->net_stats.rx_dropped++; - this->rx_addr = kva_to_hva(hp, hp->rx_skbs[elem]->data); - this->rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); + hme_write_rxd(hp, this, + (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), + dma_addr); goto next; } skb = hp->rx_skbs[elem]; -#ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(kva_to_hva(hp, skb->data), - skb->len, hp->happy_sbus_dev->my_bus); -#endif - if(len > RX_COPY_THRESHOLD) { + if (len > RX_COPY_THRESHOLD) { struct sk_buff *new_skb; /* Now refill the entry, if we can. */ - new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, - (GFP_DMA|GFP_ATOMIC)); - if(!new_skb) { + new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); + if (new_skb == NULL) { drops++; goto drop_it; } - + hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE); hp->rx_skbs[elem] = new_skb; new_skb->dev = dev; skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); - rxbase[elem].rx_addr = kva_to_hva(hp, new_skb->data); + hme_write_rxd(hp, this, + (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), + hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE)); skb_reserve(new_skb, RX_OFFSET); - rxbase[elem].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); /* Trim the original skb for the netif. */ skb_trim(skb, len); } else { struct sk_buff *copy_skb = dev_alloc_skb(len + 2); - if(!copy_skb) { + if (copy_skb == NULL) { drops++; goto drop_it; } @@ -1914,18 +2024,19 @@ copy_skb->dev = dev; skb_reserve(copy_skb, 2); skb_put(copy_skb, len); + hme_dma_sync(hp, dma_addr, len); memcpy(copy_skb->data, skb->data, len); /* Reuse original ring buffer. */ - rxbase[elem].rx_addr = kva_to_hva(hp, skb->data); - rxbase[elem].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); + hme_write_rxd(hp, this, + (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), + dma_addr); skb = copy_skb; } /* This card is _fucking_ hot... */ - if(!(csum ^ 0xffff)) + if (!(csum ^ 0xffff)) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; @@ -1935,535 +2046,107 @@ netif_rx(skb); hp->net_stats.rx_packets++; - hp->net_stats.rx_bytes+=len; + hp->net_stats.rx_bytes += len; next: elem = NEXT_RX(elem); this = &rxbase[elem]; } hp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name); + if (drops) + printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", hp->dev->name); RXD((">")); } -#ifdef CONFIG_PCI -static inline void pci_happy_meal_rx(struct happy_meal *hp, struct net_device *dev, - struct hmeal_gregs *gregs) +static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0]; - struct happy_meal_rxd *this; - unsigned int flags; - int elem = hp->rx_new, drops = 0; - - RXD(("RX<")); - this = &rxbase[elem]; -#ifdef __sparc_v9__ - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=r" (flags) - : "r" (&this->rx_flags), "i" (ASI_PL)); -#else - flags = flip_dword(this->rx_flags); /* FIXME */ -#endif - while(!(flags & RXFLAG_OWN)) { - struct sk_buff *skb; - int len; - u16 csum; - - RXD(("[%d ", elem)); + struct net_device *dev = (struct net_device *) dev_id; + struct happy_meal *hp = (struct happy_meal *) dev->priv; + u32 happy_status = hme_read32(hp, hp->gregs + GREG_STAT); - len = flags >> 16; - csum = flags & RXFLAG_CSUM; + HMD(("happy_meal_interrupt: status=%08x ", happy_status)); - /* Check for errors. */ - if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08x)]", flags)); - hp->net_stats.rx_errors++; - if(len < ETH_ZLEN) - hp->net_stats.rx_length_errors++; - if(len & (RXFLAG_OVERFLOW >> 16)) { - hp->net_stats.rx_over_errors++; - hp->net_stats.rx_fifo_errors++; - } + dev->interrupt = 1; - /* Return it to the Happy meal. */ - drop_it: - hp->net_stats.rx_dropped++; - pcihme_write_rxd(this, - (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), - (u32) virt_to_bus((volatile void *)hp->rx_skbs[elem]->data)); - goto next; + if (happy_status & GREG_STAT_ERRORS) { + HMD(("ERRORS ")); + if (happy_meal_is_not_so_happy(hp, /* un- */ happy_status)) { + dev->interrupt = 0; + return; } - skb = hp->rx_skbs[elem]; - if(len > RX_COPY_THRESHOLD) { - struct sk_buff *new_skb; - - /* Now refill the entry, if we can. */ - new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, - (GFP_DMA|GFP_ATOMIC)); - if(!new_skb) { - drops++; - goto drop_it; - } + } - hp->rx_skbs[elem] = new_skb; - new_skb->dev = dev; - skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); - pcihme_write_rxd(&rxbase[elem], - (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), - (u32)virt_to_bus((volatile void *)new_skb->data)); - skb_reserve(new_skb, RX_OFFSET); + if (happy_status & GREG_STAT_MIFIRQ) { + HMD(("MIFIRQ ")); + happy_meal_mif_interrupt(hp); + } - /* Trim the original skb for the netif. */ - skb_trim(skb, len); - } else { - struct sk_buff *copy_skb = dev_alloc_skb(len + 2); + if (happy_status & GREG_STAT_TXALL) { + HMD(("TXALL ")); + happy_meal_tx(hp); + } - if(!copy_skb) { - drops++; - goto drop_it; - } + if (happy_status & GREG_STAT_RXTOHOST) { + HMD(("RXTOHOST ")); + happy_meal_rx(hp, dev); + } - copy_skb->dev = dev; - skb_reserve(copy_skb, 2); - skb_put(copy_skb, len); - memcpy(copy_skb->data, skb->data, len); + if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) { + hp->dev->tbusy = 0; + mark_bh(NET_BH); + } - /* Reuse original ring buffer. */ - pcihme_write_rxd(&rxbase[elem], - (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), - (u32)virt_to_bus((volatile void *)skb->data)); - - skb = copy_skb; - } - - /* This card is _fucking_ hot... */ - if(!~(csum)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - - RXD(("len=%d csum=%4x]", len, csum)); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - - hp->net_stats.rx_packets++; - hp->net_stats.rx_bytes+=len; - next: - elem = NEXT_RX(elem); - this = &rxbase[elem]; -#ifdef __sparc_v9__ - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=r" (flags) - : "r" (&this->rx_flags), "i" (ASI_PL)); -#else - flags = flip_dword(this->rx_flags); /* FIXME */ -#endif - } - hp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name); - RXD((">")); -} -#endif - -#ifndef __sparc_v9__ -static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct net_device *dev, - struct hmeal_gregs *gregs) -{ - struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0]; - struct happy_meal_rxd *this; - struct hmeal_buffers *hbufs = hp->sun4c_buffers; - __u32 hbufs_dvma = hp->s4c_buf_dvma; - int elem = hp->rx_new, drops = 0; - - RXD(("RX<")); - this = &rxbase[elem]; - while(!(this->rx_flags & RXFLAG_OWN)) { - struct sk_buff *skb; - unsigned int flags = this->rx_flags; - unsigned char *thisbuf = &hbufs->rx_buf[elem][0]; - __u32 thisbuf_dvma = hbufs_dvma + hbuf_offset(rx_buf, elem); - int len = flags >> 16; - - RXD(("[%d ", elem)); - - /* Check for errors. */ - if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08x)]", flags)); - hp->net_stats.rx_errors++; - if(len < ETH_ZLEN) - hp->net_stats.rx_length_errors++; - if(len & (RXFLAG_OVERFLOW >> 16)) { - hp->net_stats.rx_over_errors++; - hp->net_stats.rx_fifo_errors++; - } - - hp->net_stats.rx_dropped++; - } else { - skb = dev_alloc_skb(len + 2); - if(skb == 0) { - drops++; - hp->net_stats.rx_dropped++; - } else { - RXD(("len=%d]", len)); - skb->dev = hp->dev; - skb_reserve(skb, 2); - skb_put(skb, len); - eth_copy_and_sum(skb, (thisbuf+2), len, 0); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - hp->net_stats.rx_packets++; - hp->net_stats.rx_bytes+=len; - } - } - /* Return the buffer to the Happy Meal. */ - this->rx_addr = thisbuf_dvma; - this->rx_flags = - (RXFLAG_OWN | ((SUN4C_RX_BUFF_SIZE - RX_OFFSET) << 16)); - - elem = NEXT_RX(elem); - this = &rxbase[elem]; - } - hp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name); - RXD((">")); -} - -static inline void sun4d_happy_meal_rx(struct happy_meal *hp, struct net_device *dev, - struct hmeal_gregs *gregs) -{ - struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0]; - struct happy_meal_rxd *this; - int elem = hp->rx_new, drops = 0; - __u32 va; - - RXD(("RX<")); - this = &rxbase[elem]; - while(!(this->rx_flags & RXFLAG_OWN)) { - struct sk_buff *skb; - unsigned int flags = this->rx_flags; - int len = flags >> 16; - u16 csum = flags & RXFLAG_CSUM; - - RXD(("[%d ", elem)); - - /* Check for errors. */ - if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) { - RXD(("ERR(%08x)]", flags)); - hp->net_stats.rx_errors++; - if(len < ETH_ZLEN) - hp->net_stats.rx_length_errors++; - if(len & (RXFLAG_OVERFLOW >> 16)) { - hp->net_stats.rx_over_errors++; - hp->net_stats.rx_fifo_errors++; - } - - /* Return it to the Happy meal. */ - drop_it: - hp->net_stats.rx_dropped++; - va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE; - this->rx_addr = iounit_map_dma_page(va, hp->rx_skbs[elem]->data, - hp->happy_sbus_dev->my_bus); - this->rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); - goto next; - } - skb = hp->rx_skbs[elem]; - if(len > RX_COPY_THRESHOLD) { - struct sk_buff *new_skb; - - /* Now refill the entry, if we can. */ - new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, - (GFP_DMA | GFP_ATOMIC)); - if(!new_skb) { - drops++; - goto drop_it; - } - - hp->rx_skbs[elem] = new_skb; - new_skb->dev = dev; - skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); - va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE; - rxbase[elem].rx_addr = iounit_map_dma_page(va, new_skb->data, - hp->happy_sbus_dev->my_bus); - - skb_reserve(new_skb, RX_OFFSET); - rxbase[elem].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); - - /* Trim the original skb for the netif. */ - skb_trim(skb, len); - } else { - struct sk_buff *copy_skb = dev_alloc_skb(len + 2); - - if(!copy_skb) { - drops++; - goto drop_it; - } - - copy_skb->dev = dev; - skb_reserve(copy_skb, 2); - skb_put(copy_skb, len); - memcpy(copy_skb->data, skb->data, len); - - /* Reuse original ring buffer. */ - va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE; - rxbase[elem].rx_addr = iounit_map_dma_page(va, skb->data, - hp->happy_sbus_dev->my_bus); - rxbase[elem].rx_flags = - (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)); - - skb = copy_skb; - } - - /* This card is _fucking_ hot... */ - if(!(csum ^ 0xffff)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - - RXD(("len=%d csum=%4x]", len, csum)); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - - hp->net_stats.rx_packets++; - hp->net_stats.rx_bytes+=len; - next: - elem = NEXT_RX(elem); - this = &rxbase[elem]; - } - hp->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name); - RXD((">")); -} -#endif - -static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned int happy_status = hme_read32(hp, &gregs->stat); - - HMD(("happy_meal_interrupt: status=%08x ", happy_status)); - - dev->interrupt = 1; - - if(happy_status & GREG_STAT_ERRORS) { - HMD(("ERRORS ")); - if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) { - dev->interrupt = 0; - return; - } - } - - if(happy_status & GREG_STAT_MIFIRQ) { - HMD(("MIFIRQ ")); - happy_meal_mif_interrupt(hp, gregs, tregs); - } - - if(happy_status & GREG_STAT_TXALL) { - HMD(("TXALL ")); - happy_meal_tx(hp); - } - - if(happy_status & GREG_STAT_RXTOHOST) { - HMD(("RXTOHOST ")); - happy_meal_rx(hp, dev, gregs); - } - - if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) { - hp->dev->tbusy = 0; - mark_bh(NET_BH); - } - - dev->interrupt = 0; - HMD(("done\n")); -} - -#ifdef CONFIG_PCI -static void pci_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned int happy_status = readl((unsigned long)&gregs->stat); - - HMD(("happy_meal_interrupt: status=%08x ", happy_status)); - - dev->interrupt = 1; - - if(happy_status & GREG_STAT_ERRORS) { - HMD(("ERRORS ")); - if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) { - dev->interrupt = 0; - return; - } - } - - if(happy_status & GREG_STAT_MIFIRQ) { - HMD(("MIFIRQ ")); - happy_meal_mif_interrupt(hp, gregs, tregs); - } - - if(happy_status & GREG_STAT_TXALL) { - HMD(("TXALL ")); - pci_happy_meal_tx(hp); - } - - if(happy_status & GREG_STAT_RXTOHOST) { - HMD(("RXTOHOST ")); - pci_happy_meal_rx(hp, dev, gregs); - } - - if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) { - hp->dev->tbusy = 0; - mark_bh(NET_BH); - } - tx_add_log(hp, TXLOG_ACTION_IRQ, happy_status); - dev->interrupt = 0; - HMD(("done\n")); -} -#endif - -#ifndef __sparc_v9__ -static void sun4c_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned int happy_status = hme_read32(hp, &gregs->stat); - - HMD(("happy_meal_interrupt: status=%08x ", happy_status)); - - dev->interrupt = 1; - - if(happy_status & GREG_STAT_ERRORS) { - HMD(("ERRORS ")); - if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) { - dev->interrupt = 0; - return; - } - } - - if(happy_status & GREG_STAT_MIFIRQ) { - HMD(("MIFIRQ ")); - happy_meal_mif_interrupt(hp, gregs, tregs); - } - - if(happy_status & GREG_STAT_TXALL) { - HMD(("TXALL ")); - sun4c_happy_meal_tx(hp); - } - - if(happy_status & GREG_STAT_RXTOHOST) { - HMD(("RXTOHOST ")); - sun4c_happy_meal_rx(hp, dev, gregs); - } - - if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) { - hp->dev->tbusy = 0; - mark_bh(NET_BH); - } - - dev->interrupt = 0; - HMD(("done\n")); -} - -static void sun4d_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned int happy_status = hme_read32(hp, &gregs->stat); - - HMD(("happy_meal_interrupt: status=%08x ", happy_status)); - - dev->interrupt = 1; - - if(happy_status & GREG_STAT_ERRORS) { - HMD(("ERRORS ")); - if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) { - dev->interrupt = 0; - return; - } - } - - if(happy_status & GREG_STAT_MIFIRQ) { - HMD(("MIFIRQ ")); - happy_meal_mif_interrupt(hp, gregs, tregs); - } - - if(happy_status & GREG_STAT_TXALL) { - HMD(("TXALL ")); - happy_meal_tx(hp); - } - - if(happy_status & GREG_STAT_RXTOHOST) { - HMD(("RXTOHOST ")); - sun4d_happy_meal_rx(hp, dev, gregs); - } - - if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) { - hp->dev->tbusy = 0; - mark_bh(NET_BH); - } - - dev->interrupt = 0; - HMD(("done\n")); -} -#endif + dev->interrupt = 0; + HMD(("done\n")); +} static void quattro_sbus_interrupt(int irq, void *cookie, struct pt_regs *ptregs) { - struct quattro *qp = (struct quattro *)cookie; + struct quattro *qp = (struct quattro *) cookie; int i; - for(i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { struct net_device *dev = qp->happy_meals[i]; - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_gregs *gregs = hp->gregs; - struct hmeal_tcvregs *tregs = hp->tcvregs; - unsigned int happy_status = hme_read32(hp, &gregs->stat); + struct happy_meal *hp = (struct happy_meal *) dev->priv; + u32 happy_status = hme_read32(hp, hp->gregs + GREG_STAT); - HMD(("quattro_interrupt: status=%08x ",happy_status)); + HMD(("quattro_interrupt: status=%08x ", happy_status)); - dev->interrupt=1; + if (!(happy_status & (GREG_STAT_ERRORS | + GREG_STAT_MIFIRQ | + GREG_STAT_TXALL | + GREG_STAT_RXTOHOST))) + continue; + + dev->interrupt = 1; - if(happy_status & GREG_STAT_ERRORS) { + if (happy_status & GREG_STAT_ERRORS) { HMD(("ERRORS ")); - if(happy_meal_is_not_so_happy(hp, gregs, happy_status)) { + if (happy_meal_is_not_so_happy(hp, happy_status)) { dev->interrupt=0; break; } } - if(happy_status & GREG_STAT_MIFIRQ) { + if (happy_status & GREG_STAT_MIFIRQ) { HMD(("MIFIRQ ")); - happy_meal_mif_interrupt(hp, gregs, tregs); + happy_meal_mif_interrupt(hp); } - if(happy_status & GREG_STAT_TXALL) { + if (happy_status & GREG_STAT_TXALL) { HMD(("TXALL ")); happy_meal_tx(hp); } - if(happy_status & GREG_STAT_RXTOHOST) { + if (happy_status & GREG_STAT_RXTOHOST) { HMD(("RXTOHOST ")); - happy_meal_rx(hp, dev, gregs); + happy_meal_rx(hp, dev); } - if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) { + if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) { hp->dev->tbusy = 0; mark_bh(NET_BH); } - dev->interrupt=0; + dev->interrupt = 0; } HMD(("done\n")); } @@ -2478,51 +2161,19 @@ /* On SBUS Quattro QFE cards, all hme interrupts are concentrated * into a single source which we register handling at probe time. */ - if((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) == HFLAG_QUATTRO) { - hp->qfe_parent->irq_status[hp->qfe_ent] = &hp->gregs->stat; - goto after_request_irq; - } -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) { - if(request_irq(dev->irq, &sun4c_happy_meal_interrupt, - SA_SHIRQ, "HAPPY MEAL", (void *) dev)) { + if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) { + if (request_irq(dev->irq, &happy_meal_interrupt, + SA_SHIRQ, "HAPPY MEAL", (void *)dev)) { HMD(("EAGAIN\n")); - printk("happy meal: Can't order irq %d to go.\n", dev->irq); - return -EAGAIN; - } - } else if (sparc_cpu_model == sun4d) { - if(request_irq(dev->irq, &sun4d_happy_meal_interrupt, - SA_SHIRQ, "HAPPY MEAL", (void *) dev)) { - HMD(("EAGAIN\n")); - printk("happy_meal(SBUS): Can't order irq %s to go.\n", + printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n", __irq_itoa(dev->irq)); return -EAGAIN; } - } else -#endif -#ifdef CONFIG_PCI - if(hp->happy_flags & HFLAG_PCI) { - if(request_irq(dev->irq, &pci_happy_meal_interrupt, - SA_SHIRQ, "HAPPY MEAL (PCI)", dev)) { - HMD(("EAGAIN\n")); - printk("happy_meal(PCI: Can't order irq %s to go.\n", - __irq_itoa(dev->irq)); - return -EAGAIN; - } - } else -#endif - if(request_irq(dev->irq, &happy_meal_interrupt, - SA_SHIRQ, "HAPPY MEAL", (void *)dev)) { - HMD(("EAGAIN\n")); - printk("happy_meal(SBUS): Can't order irq %s to go.\n", - __irq_itoa(dev->irq)); - return -EAGAIN; } -after_request_irq: HMD(("to happy_meal_init\n")); res = happy_meal_init(hp, 0); - if(!res) { + if (!res) { MOD_INC_USE_COUNT; } return res; @@ -2542,12 +2193,8 @@ * into a single source which we register handling at probe * time and never unregister. */ - if((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) { + if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) free_irq(dev->irq, (void *)dev); - } else { - /* Zap the status register pointer. */ - hp->qfe_parent->irq_status[hp->qfe_ent] = NULL; - } MOD_DEC_USE_COUNT; return 0; @@ -2564,83 +2211,17 @@ struct happy_meal *hp = (struct happy_meal *) dev->priv; int len, entry; - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { int tickssofar = jiffies - dev->trans_start; if (tickssofar >= 40) { - printk ("%s: transmit timed out, resetting\n", dev->name); + printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name); hp->net_stats.tx_errors++; tx_dump_log(); - printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name, - hme_read32(hp, &hp->gregs->stat), - hme_read32(hp, &hp->etxregs->cfg), - hme_read32(hp, &hp->bigmacregs->tx_cfg)); - happy_meal_init(hp, 0); - dev->tbusy = 0; - dev->trans_start = jiffies; - } else - tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0); - return 1; - } - - if(!TX_BUFFS_AVAIL(hp)) { - tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0); - return 1; - } -#ifdef __sparc_v9__ - if ((unsigned long)(skb->data + skb->len) >= MAX_DMA_ADDRESS) { - struct sk_buff *new_skb = skb_copy(skb, GFP_DMA | GFP_ATOMIC); - if (!new_skb) - return 1; - dev_kfree_skb(skb); - skb = new_skb; - } -#endif - len = skb->len; - entry = hp->tx_new; - - SXD(("SX", len, entry)); -#ifdef NEED_DMA_SYNCHRONIZATION - mmu_sync_dma(kva_to_hva(hp, skb->data), - skb->len, hp->happy_sbus_dev->my_bus); -#endif - hp->tx_skbs[entry] = skb; - hp->happy_block->happy_meal_txd[entry].tx_addr = kva_to_hva(hp, skb->data); - hp->happy_block->happy_meal_txd[entry].tx_flags = - (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)); - hp->tx_new = NEXT_TX(entry); - - /* Get it going. */ - dev->trans_start = jiffies; - hme_write32(hp, &hp->etxregs->tx_pnding, ETX_TP_DMAWAKEUP); - - if(TX_BUFFS_AVAIL(hp)) - dev->tbusy = 0; - - tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); - return 0; -} - -#ifdef CONFIG_PCI -static int pci_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct happy_meal *hp = (struct happy_meal *) dev->priv; - int len, entry; - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar >= 40) { - unsigned long flags; - - printk ("%s: transmit timed out, resetting\n", dev->name); - - save_and_cli(flags); - tx_dump_log(); - tx_dump_ring(hp); - restore_flags(flags); - - hp->net_stats.tx_errors++; + printk (KERN_ERR "%s: Happy Status %08x TX[%08x:%08x]\n", dev->name, + hme_read32(hp, hp->gregs + GREG_STAT), + hme_read32(hp, hp->etxregs + ETX_CFG), + hme_read32(hp, hp->bigmacregs + BMAC_TXCFG)); happy_meal_init(hp, 0); dev->tbusy = 0; dev->trans_start = jiffies; @@ -2649,7 +2230,7 @@ return 1; } - if(!TX_BUFFS_AVAIL(hp)) { + if (!TX_BUFFS_AVAIL(hp)) { tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0); return 1; } @@ -2658,132 +2239,21 @@ SXD(("SX", len, entry)); hp->tx_skbs[entry] = skb; - pcihme_write_txd(&hp->happy_block->happy_meal_txd[entry], - (TXFLAG_OWN|TXFLAG_SOP|TXFLAG_EOP|(len & TXFLAG_SIZE)), - (u32) virt_to_bus((volatile void *)skb->data)); + hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry], + (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)), + hme_dma_map(hp, skb->data, len)); hp->tx_new = NEXT_TX(entry); /* Get it going. */ dev->trans_start = jiffies; - writel(ETX_TP_DMAWAKEUP, (unsigned long)&hp->etxregs->tx_pnding); + hme_write32(hp, hp->etxregs + ETX_PENDING, ETX_TP_DMAWAKEUP); - if(TX_BUFFS_AVAIL(hp)) + if (TX_BUFFS_AVAIL(hp)) dev->tbusy = 0; tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); return 0; } -#endif - -#ifndef __sparc_v9__ -static int sun4c_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_buffers *hbufs = hp->sun4c_buffers; - __u32 txbuf_dvma, hbufs_dvma = hp->s4c_buf_dvma; - unsigned char *txbuf; - int len, entry; - - if(dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 40) { - return 1; - } else { - printk ("%s: transmit timed out, resetting\n", dev->name); - hp->net_stats.tx_errors++; - happy_meal_init(hp, 0); - dev->tbusy = 0; - dev->trans_start = jiffies; - return 0; - } - } - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("happy meal: Transmitter access conflict.\n"); - return 1; - } - - if(!TX_BUFFS_AVAIL(hp)) - return 1; - - len = skb->len; - entry = hp->tx_new; - - txbuf = &hbufs->tx_buf[entry][0]; - memcpy(txbuf, skb->data, len); - - SXD(("SX", len, entry)); - txbuf_dvma = hbufs_dvma + hbuf_offset(tx_buf, entry); - hp->happy_block->happy_meal_txd[entry].tx_addr = txbuf_dvma; - hp->happy_block->happy_meal_txd[entry].tx_flags = - (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)); - hp->tx_new = NEXT_TX(entry); - - /* Get it going. */ - dev->trans_start = jiffies; - hp->etxregs->tx_pnding = ETX_TP_DMAWAKEUP; - - dev_kfree_skb(skb); - - if(TX_BUFFS_AVAIL(hp)) - dev->tbusy = 0; - - return 0; -} - -static int sun4d_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct happy_meal *hp = (struct happy_meal *) dev->priv; - int len, entry; - __u32 va; - - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar >= 40) { - printk ("%s: transmit timed out, resetting\n", dev->name); - hp->net_stats.tx_errors++; - tx_dump_log(); - printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name, - hme_read32(hp, &hp->gregs->stat), - hme_read32(hp, &hp->etxregs->cfg), - hme_read32(hp, &hp->bigmacregs->tx_cfg)); - happy_meal_init(hp, 0); - dev->tbusy = 0; - dev->trans_start = jiffies; - } else - tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0); - return 1; - } - - if(!TX_BUFFS_AVAIL(hp)) { - tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0); - return 1; - } - len = skb->len; - entry = hp->tx_new; - - SXD(("SX", len, entry)); - hp->tx_skbs[entry] = skb; - va = (__u32)hp->sun4d_buffers + (RX_RING_SIZE + entry) * PAGE_SIZE; - hp->happy_block->happy_meal_txd[entry].tx_addr = - iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus); - hp->happy_block->happy_meal_txd[entry].tx_flags = - (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)); - hp->tx_new = NEXT_TX(entry); - - /* Get it going. */ - dev->trans_start = jiffies; - hme_write32(hp, &hp->etxregs->tx_pnding, ETX_TP_DMAWAKEUP); - - if(TX_BUFFS_AVAIL(hp)) - dev->tbusy = 0; - - tx_add_log(hp, TXLOG_ACTION_TXMIT, 0); - return 0; -} -#endif static struct net_device_stats *happy_meal_get_stats(struct net_device *dev) { @@ -2796,7 +2266,7 @@ static void happy_meal_set_multicast(struct net_device *dev) { struct happy_meal *hp = (struct happy_meal *) dev->priv; - struct hmeal_bigmacregs *bregs = hp->bigmacregs; + unsigned long bregs = hp->bigmacregs; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; @@ -2805,45 +2275,45 @@ /* Lock out others. */ set_bit(0, (void *) &dev->tbusy); - if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { - hme_write32(hp, &bregs->htable0, 0xffff); - hme_write32(hp, &bregs->htable1, 0xffff); - hme_write32(hp, &bregs->htable2, 0xffff); - hme_write32(hp, &bregs->htable3, 0xffff); - } else if(dev->flags & IFF_PROMISC) { - hme_write32(hp, &bregs->rx_cfg, - hme_read32(hp, &bregs->rx_cfg) | BIGMAC_RXCFG_PMISC); + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff); + hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff); + } else if (dev->flags & IFF_PROMISC) { + hme_write32(hp, bregs + BMAC_RXCFG, + hme_read32(hp, bregs + BMAC_RXCFG) | BIGMAC_RXCFG_PMISC); } else { u16 hash_table[4]; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < dev->mc_count; i++) { + for (i = 0; i < dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - if(!(*addrs & 1)) + if (!(*addrs & 1)) continue; crc = 0xffffffffU; - for(byte = 0; byte < 6; byte++) { - for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + for (byte = 0; byte < 6; byte++) { + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { int test; test = ((bit ^ crc) & 0x01); crc >>= 1; - if(test) + if (test) crc = crc ^ poly; } } crc >>= 26; hash_table[crc >> 4] |= 1 << (crc & 0xf); } - hme_write32(hp, &bregs->htable0, hash_table[0]); - hme_write32(hp, &bregs->htable1, hash_table[1]); - hme_write32(hp, &bregs->htable2, hash_table[2]); - hme_write32(hp, &bregs->htable3, hash_table[3]); + hme_write32(hp, bregs + BMAC_HTABLE0, hash_table[0]); + hme_write32(hp, bregs + BMAC_HTABLE1, hash_table[1]); + hme_write32(hp, bregs + BMAC_HTABLE2, hash_table[2]); + hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]); } /* Let us get going again. */ @@ -2858,12 +2328,12 @@ struct ethtool_cmd *ep_user = (struct ethtool_cmd *) rq->ifr_data; struct ethtool_cmd ecmd; - if(cmd != SIOCETHTOOL) + if (cmd != SIOCETHTOOL) return -EOPNOTSUPP; - if(copy_from_user(&ecmd, ep_user, sizeof(ecmd))) + if (copy_from_user(&ecmd, ep_user, sizeof(ecmd))) return -EFAULT; - if(ecmd.cmd == SPARC_ETH_GSET) { + if (ecmd.cmd == SPARC_ETH_GSET) { ecmd.supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | @@ -2877,12 +2347,12 @@ /* Record PHY settings. */ hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, DP83840_BMCR); hp->sw_lpa = happy_meal_tcvr_read(hp, hp->tcvregs, DP83840_LPA); - if(hp->sw_bmcr & BMCR_ANENABLE) { + if (hp->sw_bmcr & BMCR_ANENABLE) { ecmd.autoneg = AUTONEG_ENABLE; ecmd.speed = (hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ? SPEED_100 : SPEED_10; - if(ecmd.speed == SPEED_100) + if (ecmd.speed == SPEED_100) ecmd.duplex = (hp->sw_lpa & (LPA_100FULL)) ? DUPLEX_FULL : DUPLEX_HALF; @@ -2899,22 +2369,22 @@ (hp->sw_bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } - if(copy_to_user(ep_user, &ecmd, sizeof(ecmd))) + if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) return -EFAULT; return 0; - } else if(ecmd.cmd == SPARC_ETH_SSET) { - if(!capable(CAP_NET_ADMIN)) + } else if (ecmd.cmd == SPARC_ETH_SSET) { + if (!capable(CAP_NET_ADMIN)) return -EPERM; /* Verify the settings we care about. */ - if(ecmd.autoneg != AUTONEG_ENABLE && - ecmd.autoneg != AUTONEG_DISABLE) + if (ecmd.autoneg != AUTONEG_ENABLE && + ecmd.autoneg != AUTONEG_DISABLE) return -EINVAL; - if(ecmd.autoneg == AUTONEG_DISABLE && - ((ecmd.speed != SPEED_100 && - ecmd.speed != SPEED_10) || - (ecmd.duplex != DUPLEX_HALF && - ecmd.duplex != DUPLEX_FULL))) + if (ecmd.autoneg == AUTONEG_DISABLE && + ((ecmd.speed != SPEED_100 && + ecmd.speed != SPEED_10) || + (ecmd.duplex != DUPLEX_HALF && + ecmd.duplex != DUPLEX_FULL))) return -EINVAL; /* Ok, do it to it. */ @@ -2928,15 +2398,19 @@ return -EOPNOTSUPP; } +static int hme_version_printed = 0; + +#ifdef CONFIG_SBUS void __init quattro_get_ranges(struct quattro *qp) { + struct sbus_dev *sdev = qp->quattro_dev; int err; - err = prom_getproperty(qp->quattro_sbus_dev->prom_node, + err = prom_getproperty(sdev->prom_node, "ranges", (char *)&qp->ranges[0], sizeof(qp->ranges)); - if(err == 0 || err == -1) { + if (err == 0 || err == -1) { qp->nranges = 0; return; } @@ -2945,19 +2419,19 @@ static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp) { - struct linux_sbus_device *sdev = hp->happy_sbus_dev; + struct sbus_dev *sdev = hp->happy_dev; int rng; - for(rng = 0; rng < qp->nranges; rng++) { + for (rng = 0; rng < qp->nranges; rng++) { struct linux_prom_ranges *rngp = &qp->ranges[rng]; int reg; - for(reg = 0; reg < 5; reg++) { - if(sdev->reg_addrs[reg].which_io == - rngp->ot_child_space) + for (reg = 0; reg < 5; reg++) { + if (sdev->reg_addrs[reg].which_io == + rngp->ot_child_space) break; } - if(reg == 5) + if (reg == 5) continue; sdev->reg_addrs[reg].which_io = rngp->ot_parent_space; @@ -2970,30 +2444,30 @@ * * Return NULL on failure. */ -static struct quattro * __init quattro_sbus_find(struct linux_sbus_device *goal_sdev) +static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev) { - struct linux_sbus *sbus; - struct linux_sbus_device *sdev; + struct sbus_bus *sbus; + struct sbus_dev *sdev; struct quattro *qp; - if(qfe_sbus_list == NULL) + if (qfe_sbus_list == NULL) goto found; - for(qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - for(sdev = qp->quattro_sbus_dev; - sdev != NULL; - sdev = sdev->next) { - if(sdev == goal_sdev) + for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { + for (sdev = qp->quattro_dev; + sdev != NULL; + sdev = sdev->next) { + if (sdev == goal_sdev) return qp; } } for_each_sbus(sbus) { for_each_sbusdev(sdev, sbus) { - if(sdev->child != NULL) { - struct linux_sbus_device *p; + if (sdev->child != NULL) { + struct sbus_dev *p; - for(p = sdev->child; p != NULL; p = p->next) - if(p == goal_sdev) + for (p = sdev->child; p != NULL; p = p->next) + if (p == goal_sdev) goto found; } } @@ -3004,18 +2478,13 @@ found: qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); - if(qp != NULL) { + if (qp != NULL) { int i; - for(i = 0; i < 4; i++) { - qp->irq_status[i] = NULL; + for (i = 0; i < 4; i++) qp->happy_meals[i] = NULL; - } - qp->handler = NULL; - qp->quattro_sbus_dev = goal_sdev; -#ifdef CONFIG_PCI - qp->quattro_pci_dev = NULL; -#endif + + qp->quattro_dev = goal_sdev; qp->next = qfe_sbus_list; qfe_sbus_list = qp; quattro_get_ranges(qp); @@ -3023,6 +2492,29 @@ return qp; } +/* After all quattro cards have been probed, we call these functions + * to register the IRQ handlers. + */ +static void __init quattro_sbus_register_irqs(void) +{ + struct quattro *qp; + + for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { + struct sbus_dev *sdev = qp->quattro_dev; + int err; + + err = request_irq(sdev->irqs[0], + quattro_sbus_interrupt, + SA_SHIRQ, "Quattro", + qp); + if (err != 0) { + printk(KERN_ERR "Quattro: Fatal IRQ registery error %d.\n", err); + panic("QFE request irq"); + } + } +} +#endif /* CONFIG_SBUS */ + #ifdef CONFIG_PCI static struct quattro * __init quattro_pci_find(struct pci_dev *pdev) { @@ -3030,21 +2522,20 @@ struct quattro *qp; if (!bdev) return NULL; - for(qp = qfe_pci_list; qp != NULL; qp = qp->next) { - if(qp->quattro_pci_dev == bdev) + for (qp = qfe_pci_list; qp != NULL; qp = qp->next) { + struct pci_dev *qpdev = qp->quattro_dev; + + if (qpdev == bdev) return qp; } qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); - if(qp != NULL) { + if (qp != NULL) { int i; - for(i = 0; i < 4; i++) { - qp->irq_status[i] = NULL; + for (i = 0; i < 4; i++) qp->happy_meals[i] = NULL; - } - qp->handler = NULL; - qp->quattro_sbus_dev = NULL; - qp->quattro_pci_dev = bdev; + + qp->quattro_dev = bdev; qp->next = qfe_pci_list; qfe_pci_list = qp; @@ -3053,88 +2544,50 @@ } return qp; } -#endif - -/* After all quattro cards have been probed, we call these functions - * to register the IRQ handlers. - */ -static void __init quattro_sbus_register_irqs(void) -{ - struct quattro *qp; - - for(qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - int err; - - /* Set the handler. */ -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - qp->handler = sun4c_happy_meal_interrupt; - else if(sparc_cpu_model == sun4d) - qp->handler = sun4d_happy_meal_interrupt; - else -#endif -#ifdef CONFIG_PCI - if(qp->quattro_pci_dev != NULL) - panic("QFE: PCI qfe in sbus_register_irqs!"); - else -#endif - qp->handler = happy_meal_interrupt; - - err = request_irq(qp->quattro_sbus_dev->irqs[0], - quattro_sbus_interrupt, - SA_SHIRQ, "Quattro", - qp); - if(err != 0) { - printk("Quattro: Fatal IRQ registery error %d.\n", err); - panic("QFE request irq"); - } - } -} +#endif /* CONFIG_PCI */ -static unsigned hme_version_printed = 0; - -static int __init happy_meal_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int is_qfe) +#ifdef CONFIG_SBUS +static int __init happy_meal_sbus_init(struct net_device *dev, + struct sbus_dev *sdev, + int is_qfe) { struct quattro *qp = NULL; struct happy_meal *hp; int i, qfe_slot = -1; - if(is_qfe) { + if (is_qfe) { qp = quattro_sbus_find(sdev); - if(qp == NULL) + if (qp == NULL) return ENODEV; - for(qfe_slot = 0; qfe_slot < 4; qfe_slot++) - if(qp->happy_meals[qfe_slot] == NULL) + for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) + if (qp->happy_meals[qfe_slot] == NULL) break; - if(qfe_slot == 4) + if (qfe_slot == 4) return ENODEV; } - if(dev == NULL) { + if (dev == NULL) { dev = init_etherdev(0, sizeof(struct happy_meal)); } else { dev->priv = kmalloc(sizeof(struct happy_meal), GFP_KERNEL); - if(dev->priv == NULL) + if (dev->priv == NULL) return -ENOMEM; } - if(hme_version_printed++ == 0) - printk(version); + if (hme_version_printed++ == 0) + printk(KERN_INFO "%s", version); - if(qfe_slot != -1) - printk("%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", + if (qfe_slot != -1) + printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", dev->name, qfe_slot); else - printk("%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ", + printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ", dev->name); - dev->base_addr = (long) sdev; - - /* XXX Check for local-mac-address property on Quattro... -DaveM */ /* Quattro local-mac-address... */ - if(qfe_slot != -1 && prom_getproplen(sdev->prom_node,"local-mac-address")==6) + if (qfe_slot != -1 && prom_getproplen(sdev->prom_node,"local-mac-address")==6) prom_getproperty(sdev->prom_node,"local-mac-address",dev->dev_addr,6); else memcpy(dev->dev_addr,idprom->id_ethaddr,6); - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); @@ -3142,105 +2595,77 @@ hp = (struct happy_meal *) dev->priv; memset(hp, 0, sizeof(*hp)); - hp->happy_sbus_dev = sdev; -#ifdef CONFIG_PCI - hp->happy_pci_dev = NULL; -#endif + hp->happy_dev = sdev; - if(sdev->num_registers != 5) { - printk("happymeal: Device does not have 5 regs, it has %d.\n", + if (sdev->num_registers != 5) { + printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n", sdev->num_registers); - printk("happymeal: Would you like that for here or to go?\n"); + printk(KERN_ERR "happymeal: Would you like that for here or to go?\n"); return ENODEV; } - if(qp != NULL) { + if (qp != NULL) { hp->qfe_parent = qp; hp->qfe_ent = qfe_slot; qp->happy_meals[qfe_slot] = dev; quattro_apply_ranges(qp, hp); } - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); - hp->gregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sizeof(struct hmeal_gregs), - "Happy Meal Global Regs", - sdev->reg_addrs[0].which_io, 0); - if(!hp->gregs) { - printk("happymeal: Cannot map Happy Meal global registers.\n"); + hp->gregs = sbus_ioremap(&sdev->resource[0], 0, + GREG_REG_SIZE, "HME Global Regs"); + if (!hp->gregs) { + printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n"); return ENODEV; } - hp->etxregs = sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0, - sizeof(struct hmeal_etxregs), - "Happy Meal MAC TX Regs", - sdev->reg_addrs[1].which_io, 0); - if(!hp->etxregs) { - printk("happymeal: Cannot map Happy Meal MAC Transmit registers.\n"); + 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; } - hp->erxregs = sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0, - sizeof(struct hmeal_erxregs), - "Happy Meal MAC RX Regs", - sdev->reg_addrs[2].which_io, 0); - if(!hp->erxregs) { - printk("happymeal: Cannot map Happy Meal MAC Receive registers.\n"); + 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; } - hp->bigmacregs = sparc_alloc_io(sdev->reg_addrs[3].phys_addr, 0, - sizeof(struct hmeal_bigmacregs), - "Happy Meal BIGMAC Regs", - sdev->reg_addrs[3].which_io, 0); - if(!hp->bigmacregs) { - printk("happymeal: Cannot map Happy Meal BIGMAC registers.\n"); + 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; } - hp->tcvregs = sparc_alloc_io(sdev->reg_addrs[4].phys_addr, 0, - sizeof(struct hmeal_tcvregs), - "Happy Meal Tranceiver Regs", - sdev->reg_addrs[4].which_io, 0); - if(!hp->tcvregs) { - printk("happymeal: Cannot map Happy Meal Tranceiver registers.\n"); + 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; } hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff); - if(hp->hm_revision == 0xff) + if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; /* Now enable the feature flags we can. */ - if(hp->hm_revision == 0x20 || hp->hm_revision == 0x21) + if (hp->hm_revision == 0x20 || hp->hm_revision == 0x21) hp->happy_flags = HFLAG_20_21; - else if(hp->hm_revision != 0xa0) + else if (hp->hm_revision != 0xa0) hp->happy_flags = HFLAG_NOT_A0; - if(qp != NULL) + if (qp != NULL) hp->happy_flags |= HFLAG_QUATTRO; /* Get the supported DVMA burst sizes from our Happy SBUS. */ - hp->happy_bursts = prom_getintdefault(hp->happy_sbus_dev->my_bus->prom_node, + hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0x00); - hp->happy_block = (struct hmeal_init_block *) - sparc_dvma_malloc(PAGE_SIZE, "Happy Meal Init Block", - &hp->hblock_dvma); - -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - hp->sun4c_buffers = (struct hmeal_buffers *) - sparc_dvma_malloc(sizeof(struct hmeal_buffers), "Happy Meal Bufs", - &hp->s4c_buf_dvma); - else if (sparc_cpu_model == sun4d) - hp->sun4d_buffers = (struct hmeal_buffers *) - iounit_map_dma_init(hp->happy_sbus_dev->my_bus, - (RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE); - else -#endif - hp->sun4c_buffers = 0; + hp->happy_block = sbus_alloc_consistant(hp->happy_dev, + PAGE_SIZE, + &hp->hblock_dvma); /* Force check of the link first time we are brought up. */ hp->linkcheck = 0; @@ -3249,30 +2674,35 @@ hp->timer_state = asleep; hp->timer_ticks = 0; - /* Grrr, Happy Meal comes up by default not advertising - * full duplex 100baseT capabilities, fix this. - */ - happy_meal_set_initial_advertisement(hp); - init_timer(&hp->happy_timer); hp->dev = dev; dev->open = &happy_meal_open; dev->stop = &happy_meal_close; -#ifndef __sparc_v9__ - if(sparc_cpu_model == sun4c) - dev->hard_start_xmit = &sun4c_happy_meal_start_xmit; - else if (sparc_cpu_model == sun4d) - dev->hard_start_xmit = &sun4d_happy_meal_start_xmit; - else -#endif - dev->hard_start_xmit = &happy_meal_start_xmit; + dev->hard_start_xmit = &happy_meal_start_xmit; dev->get_stats = &happy_meal_get_stats; dev->set_multicast_list = &happy_meal_set_multicast; dev->do_ioctl = &happy_meal_ioctl; dev->irq = sdev->irqs[0]; - dev->dma = 0; + +#if defined(CONFIG_SBUS) && defined(CONFIG_PCI) + /* Hook up PCI register/dma accessors. */ + hp->read_desc32 = sbus_hme_read_desc32; + hp->write_txd = sbus_hme_write_txd; + hp->write_rxd = sbus_hme_write_rxd; + hp->dma_map = (u32 (*)(void *, void *, long))sbus_map_single; + hp->dma_unmap = (void (*)(void *, u32, long))sbus_unmap_single; + hp->dma_sync = (void (*)(void *, u32, long))sbus_dma_sync_single; + hp->read32 = sbus_hme_read32; + hp->write32 = sbus_hme_write32; +#endif + + /* Grrr, Happy Meal comes up by default not advertising + * full duplex 100baseT capabilities, fix this. + */ + happy_meal_set_initial_advertisement(hp); + ether_setup(dev); #ifdef MODULE /* We are home free at this point, link us in to the happy @@ -3284,6 +2714,7 @@ #endif return 0; } +#endif #ifdef CONFIG_PCI static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pdev) @@ -3298,8 +2729,8 @@ /* Now make sure pci_dev cookie is there. */ pcp = pdev->sysdata; - if(pcp == NULL || pcp->prom_node == -1) { - printk("happymeal(PCI): Some PCI device info missing\n"); + if (pcp == NULL || pcp->prom_node == -1) { + printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); return ENODEV; } node = pcp->prom_node; @@ -3307,43 +2738,45 @@ prom_getstring(node, "name", prom_name, sizeof(prom_name)); if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { qp = quattro_pci_find(pdev); - if(qp == NULL) + if (qp == NULL) return ENODEV; - for(qfe_slot = 0; qfe_slot < 4; qfe_slot++) - if(qp->happy_meals[qfe_slot] == NULL) + for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) + if (qp->happy_meals[qfe_slot] == NULL) break; - if(qfe_slot == 4) + if (qfe_slot == 4) return ENODEV; } - if(dev == NULL) { + if (dev == NULL) { dev = init_etherdev(0, sizeof(struct happy_meal)); } else { dev->priv = kmalloc(sizeof(struct happy_meal), GFP_KERNEL); - if(dev->priv == NULL) + if (dev->priv == NULL) return -ENOMEM; } - if(hme_version_printed++ == 0) - printk(version); + if (hme_version_printed++ == 0) + printk(KERN_INFO "%s", version); if (!qfe_slot) { + struct pci_dev *qpdev = qp->quattro_dev; + prom_name[0] = 0; if (!strncmp(dev->name, "eth", 3)) { int i = simple_strtoul(dev->name + 3, NULL, 10); sprintf(prom_name, "-%d", i + 3); } - printk("%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name); - if (qp->quattro_pci_dev->vendor == PCI_VENDOR_ID_DEC && - qp->quattro_pci_dev->device == PCI_DEVICE_ID_DEC_21153) + printk(KERN_INFO "%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name); + if (qpdev->vendor == PCI_VENDOR_ID_DEC && + qpdev->device == PCI_DEVICE_ID_DEC_21153) printk("DEC 21153 PCI Bridge\n"); else printk("unknown bridge %04x.%04x\n", - qp->quattro_pci_dev->vendor, qp->quattro_pci_dev->device); + qpdev->vendor, qpdev->device); } - if(qfe_slot != -1) - printk("%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ", + if (qfe_slot != -1) + printk(KERN_INFO "%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, qfe_slot); else - printk("%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ", + printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ", dev->name); dev->base_addr = (long) pdev; @@ -3351,10 +2784,9 @@ hp = (struct happy_meal *)dev->priv; memset(hp, 0, sizeof(*hp)); - hp->happy_sbus_dev = NULL; - hp->happy_pci_dev = pdev; + hp->happy_dev = pdev; - if(qp != NULL) { + if (qp != NULL) { hp->qfe_parent = qp; hp->qfe_ent = qfe_slot; qp->happy_meals[qfe_slot] = dev; @@ -3362,37 +2794,39 @@ hpreg_base = pdev->resource[0].start; if ((pdev->resource[0].flags & IORESOURCE_IO) != 0) { - printk("happymeal(PCI): Cannot find proper PCI device base address.\n"); + printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n"); 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) prom_getproperty(node, "local-mac-address", dev->dev_addr, 6); else memcpy(dev->dev_addr, idprom->id_ethaddr, 6); - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); /* Layout registers. */ - hp->gregs = (struct hmeal_gregs *) (hpreg_base + 0x0000); - hp->etxregs = (struct hmeal_etxregs *) (hpreg_base + 0x2000); - hp->erxregs = (struct hmeal_erxregs *) (hpreg_base + 0x4000); - hp->bigmacregs = (struct hmeal_bigmacregs *) (hpreg_base + 0x6000); - hp->tcvregs = (struct hmeal_tcvregs *) (hpreg_base + 0x7000); + hp->gregs = (hpreg_base + 0x0000UL); + hp->etxregs = (hpreg_base + 0x2000UL); + hp->erxregs = (hpreg_base + 0x4000UL); + hp->bigmacregs = (hpreg_base + 0x6000UL); + hp->tcvregs = (hpreg_base + 0x7000UL); hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); - if(hp->hm_revision == 0xff) + if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; /* Now enable the feature flags we can. */ - if(hp->hm_revision == 0x20 || hp->hm_revision == 0x21) + if (hp->hm_revision == 0x20 || hp->hm_revision == 0x21) hp->happy_flags = HFLAG_20_21; - else if(hp->hm_revision != 0xa0) + else if (hp->hm_revision != 0xa0) hp->happy_flags = HFLAG_NOT_A0; - if(qp != NULL) + if (qp != NULL) hp->happy_flags |= HFLAG_QUATTRO; /* And of course, indicate this is PCI. */ @@ -3401,36 +2835,53 @@ /* Assume PCI happy meals can handle all burst sizes. */ hp->happy_bursts = DMA_BURSTBITS; - hp->happy_block = (struct hmeal_init_block *) get_free_page(GFP_DMA); - if(!hp->happy_block) { - printk("happymeal(PCI): Cannot get hme init block.\n"); + hp->happy_block = (struct hmeal_init_block *) get_free_page(GFP_ATOMIC); + if (!hp->happy_block) { + printk(KERN_ERR "happymeal(PCI): Cannot get hme init block.\n"); return ENODEV; } hp->hblock_dvma = (u32) virt_to_bus(hp->happy_block); #ifndef __sparc_v9__ - /* This case we currently need to use 'sparc_alloc_io' */ - hp->happy_block = sparc_alloc_io (hp->hblock_dvma, NULL, - PAGE_SIZE, "sunhme", 0, 0); + /* + * P3: Dirty trick to get uncacheable memory as we have no dma_sync. + */ + hp->happy_block = ioremap(virt_to_phys(hp->happy_block), PAGE_SIZE); #endif - hp->sun4c_buffers = 0; hp->linkcheck = 0; hp->timer_state = asleep; hp->timer_ticks = 0; - happy_meal_set_initial_advertisement(hp); init_timer(&hp->happy_timer); hp->dev = dev; dev->open = &happy_meal_open; dev->stop = &happy_meal_close; - dev->hard_start_xmit = &pci_happy_meal_start_xmit; + dev->hard_start_xmit = &happy_meal_start_xmit; dev->get_stats = &happy_meal_get_stats; dev->set_multicast_list = &happy_meal_set_multicast; dev->do_ioctl = &happy_meal_ioctl; dev->irq = pdev->irq; dev->dma = 0; + +#if defined(CONFIG_SBUS) && defined(CONFIG_PCI) + /* Hook up PCI register/dma accessors. */ + hp->read_desc32 = pci_hme_read_desc32; + hp->write_txd = pci_hme_write_txd; + hp->write_rxd = pci_hme_write_rxd; + hp->dma_map = pci_hme_dma_map; + hp->dma_unmap = pci_hme_dma_unmap; + hp->dma_sync = pci_hme_dma_sync; + hp->read32 = pci_hme_read32; + hp->write32 = pci_hme_write32; +#endif + + /* Grrr, Happy Meal comes up by default not advertising + * full duplex 100baseT capabilities, fix this. + */ + happy_meal_set_initial_advertisement(hp); + ether_setup(dev); /* If we don't do this, nothing works. */ @@ -3459,55 +2910,79 @@ } #endif -int __init happy_meal_probe(void) +#ifdef CONFIG_SBUS +static int __init happy_meal_sbus_probe(struct net_device *dev) { - struct net_device *dev = NULL; - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; - static int called = 0; - int cards = 0, v; + struct sbus_bus *sbus; + struct sbus_dev *sdev; + int cards = 0; - if(called) - return ENODEV; - called++; + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + char *name = sdev->prom_name; - for_each_sbus(bus) { - for_each_sbusdev(sdev, bus) { - if(cards) + if (cards) dev = NULL; - if(!strcmp(sdev->prom_name, "SUNW,hme")) { + if (!strcmp(name, "SUNW,hme")) { cards++; - if((v = happy_meal_ether_init(dev, sdev, 0))) - return v; - } else if(!strcmp(sdev->prom_name, "qfe") || - !strcmp(sdev->prom_name, "SUNW,qfe")) { + happy_meal_sbus_init(dev, sdev, 0); + } else if (!strcmp(name, "qfe") || + !strcmp(name, "SUNW,qfe")) { cards++; - if((v = happy_meal_ether_init(dev, sdev, 1))) - return v; + happy_meal_sbus_init(dev, sdev, 1); } } } - if(cards != 0) + if (cards != 0) quattro_sbus_register_irqs(); + return cards; +} +#endif + #ifdef CONFIG_PCI - if(pci_present()) { +static int __init happy_meal_pci_probe(struct net_device *dev) +{ + int cards = 0; + + if (pci_present()) { struct pci_dev *pdev; pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL, 0); - while (pdev) { - if(cards) + while (pdev != NULL) { + if (cards) dev = NULL; cards++; - if((v = happy_meal_pci_init(dev, pdev))) - return v; + happy_meal_pci_init(dev, pdev); pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev); } } + return cards; +} #endif - if(!cards) + +int __init happy_meal_probe(void) +{ + struct net_device *dev = NULL; + static int called = 0; + int cards; + + if (called) + return ENODEV; + called++; + + cards = 0; +#ifdef CONFIG_SBUS + cards += happy_meal_sbus_probe(dev); + if (cards != 0) + dev = NULL; +#endif +#ifdef CONFIG_PCI + cards += happy_meal_pci_probe(dev); +#endif + if (!cards) return ENODEV; return 0; } @@ -3518,32 +2993,33 @@ init_module(void) { root_happy_dev = NULL; - return happy_meal_probe(NULL); + return happy_meal_probe(); } void cleanup_module(void) { - struct happy_meal *sunshine; - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_happy_dev) { struct happy_meal *hp = root_happy_dev; - sunshine = root_happy_dev->next_module; + struct happy_meal *next = root_happy_dev->next_module; - sparc_free_io(hp->gregs, sizeof(struct hmeal_gregs)); - sparc_free_io(hp->etxregs, sizeof(struct hmeal_etxregs)); - sparc_free_io(hp->erxregs, sizeof(struct hmeal_erxregs)); - sparc_free_io(hp->bigmacregs, sizeof(struct hmeal_bigmacregs)); - sparc_free_io(hp->tcvregs, sizeof(struct hmeal_tcvregs)); -#ifndef __sparc_v9__ - if (sparc_cpu_model == sun4d) - iounit_map_dma_finish(hp->happy_sbus_dev->my_bus, - (__u32)hp->sun4d_buffers, (RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE); -#endif +#ifdef CONFIG_SBUS + if (!(hp->happy_flags & HFLAG_PCI)) { + sbus_iounmap(hp->gregs, GREG_REG_SIZE); + sbus_iounmap(hp->etxregs, ETX_REG_SIZE); + sbus_iounmap(hp->erxregs, ERX_REG_SIZE); + sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); + sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); + sbus_free_consistant(hp->happy_dev, + PAGE_SIZE, + hp->happy_block, + hp->hblock_dvma); + } +#endif unregister_netdev(hp->dev); kfree(hp->dev); - root_happy_dev = sunshine; + root_happy_dev = next; } } diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h --- v2.3.34/linux/drivers/net/sunhme.h Wed Aug 18 11:36:45 1999 +++ linux/drivers/net/sunhme.h Mon Dec 20 22:06:42 1999 @@ -1,7 +1,8 @@ -/* sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver. +/* $Id: sunhme.h,v 1.28 1999/09/21 14:36:34 davem Exp $ + * sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver. * Also known as the "Happy Meal". * - * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) + * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) */ #ifndef _SUNHME_H @@ -10,13 +11,11 @@ #include /* Happy Meal global registers. */ -struct hmeal_gregs { - volatile unsigned int sw_reset; /* Software Reset */ - volatile unsigned int cfg; /* Config Register */ - volatile unsigned int _padding[62]; /* Unused */ - volatile unsigned int stat; /* Status */ - volatile unsigned int imask; /* Interrupt Mask */ -}; +#define GREG_SWRESET 0x000UL /* Software Reset */ +#define GREG_CFG 0x004UL /* Config Register */ +#define GREG_STAT 0x108UL /* Status */ +#define GREG_IMASK 0x10cUL /* Interrupt Mask */ +#define GREG_REG_SIZE 0x110UL /* Global reset register. */ #define GREG_RESET_ETX 0x01 @@ -104,21 +103,20 @@ #define GREG_IMASK_SLVPERR 0x80000000 /* PIO access got a parity error */ /* Happy Meal external transmitter registers. */ -struct hmeal_etxregs { - volatile unsigned int tx_pnding; /* Transmit pending/wakeup register */ - volatile unsigned int cfg; /* Transmit config register */ - volatile unsigned int tx_ring; /* Transmit ring pointer */ - volatile unsigned int tx_bbase; /* Transmit buffer base */ - volatile unsigned int tx_bdisp; /* Transmit buffer displacement */ - volatile unsigned int tx_fifo_wptr; /* FIFO write ptr */ - volatile unsigned int tx_fifo_swptr; /* FIFO write ptr (shadow register) */ - volatile unsigned int tx_fifo_rptr; /* FIFO read ptr */ - volatile unsigned int tx_fifo_srptr; /* FIFO read ptr (shadow register) */ - volatile unsigned int tx_fifo_pcnt; /* FIFO packet counter */ - volatile unsigned int smachine; /* Transmitter state machine */ - volatile unsigned int tx_rsize; /* Ring descriptor size */ - volatile unsigned int tx_bptr; /* Transmit data buffer ptr */ -}; +#define ETX_PENDING 0x00UL /* Transmit pending/wakeup register */ +#define ETX_CFG 0x04UL /* Transmit config register */ +#define ETX_RING 0x08UL /* Transmit ring pointer */ +#define ETX_BBASE 0x0cUL /* Transmit buffer base */ +#define ETX_BDISP 0x10UL /* Transmit buffer displacement */ +#define ETX_FIFOWPTR 0x14UL /* FIFO write ptr */ +#define ETX_FIFOSWPTR 0x18UL /* FIFO write ptr (shadow register) */ +#define ETX_FIFORPTR 0x1cUL /* FIFO read ptr */ +#define ETX_FIFOSRPTR 0x20UL /* FIFO read ptr (shadow register) */ +#define ETX_FIFOPCNT 0x24UL /* FIFO packet counter */ +#define ETX_SMACHINE 0x28UL /* Transmitter state machine */ +#define ETX_RSIZE 0x2cUL /* Ring descriptor size */ +#define ETX_BPTR 0x30UL /* Transmit data buffer ptr */ +#define ETX_REG_SIZE 0x34UL /* ETX transmit pending register. */ #define ETX_TP_DMAWAKEUP 0x00000001 /* Restart transmit dma */ @@ -132,16 +130,15 @@ #define ETX_RSIZE_SHIFT 4 /* Happy Meal external receiver registers. */ -struct hmeal_erxregs { - volatile unsigned int cfg; /* Receiver config register */ - volatile unsigned int rx_ring; /* Receiver ring ptr */ - volatile unsigned int rx_bptr; /* Receiver buffer ptr */ - volatile unsigned int rx_fifo_wptr; /* FIFO write ptr */ - volatile unsigned int rx_fifo_swptr; /* FIFO write ptr (shadow register) */ - volatile unsigned int rx_fifo_rptr; /* FIFO read ptr */ - volatile unsigned int rx_fifo_srptr; /* FIFO read ptr (shadow register) */ - volatile unsigned int smachine; /* Receiver state machine */ -}; +#define ERX_CFG 0x00UL /* Receiver config register */ +#define ERX_RING 0x04UL /* Receiver ring ptr */ +#define ERX_BPTR 0x08UL /* Receiver buffer ptr */ +#define ERX_FIFOWPTR 0x0cUL /* FIFO write ptr */ +#define ERX_FIFOSWPTR 0x10UL /* FIFO write ptr (shadow register) */ +#define ERX_FIFORPTR 0x14UL /* FIFO read ptr */ +#define ERX_FIFOSRPTR 0x18UL /* FIFO read ptr (shadow register) */ +#define ERX_SMACHINE 0x1cUL /* Receiver state machine */ +#define ERX_REG_SIZE 0x20UL /* ERX config register. */ #define ERX_CFG_DMAENABLE 0x00000001 /* Enable receive DMA */ @@ -156,54 +153,52 @@ #define ERX_CFG_CSUMSTART 0x007f0000 /* Offset of checksum start */ /* I'd like a Big Mac, small fries, small coke, and SparcLinux please. */ -struct hmeal_bigmacregs { - volatile unsigned int xif_cfg; /* XIF config register */ - volatile unsigned int _unused[129]; /* Reserved... */ - volatile unsigned int tx_swreset; /* Transmitter software reset */ - volatile unsigned int tx_cfg; /* Transmitter config register */ - volatile unsigned int ipkt_gap1; /* Inter-packet gap 1 */ - volatile unsigned int ipkt_gap2; /* Inter-packet gap 2 */ - volatile unsigned int attempt_limit; /* Transmit attempt limit */ - volatile unsigned int stime; /* Transmit slot time */ - volatile unsigned int preamble_len; /* Size of transmit preamble */ - volatile unsigned int preamble_pattern; /* Pattern for transmit preamble */ - volatile unsigned int tx_sframe_delim; /* Transmit delimiter */ - volatile unsigned int jsize; /* Jam size */ - volatile unsigned int tx_pkt_max; /* Transmit max pkt size */ - volatile unsigned int tx_pkt_min; /* Transmit min pkt size */ - volatile unsigned int peak_attempt; /* Count of transmit peak attempts */ - volatile unsigned int dt_ctr; /* Transmit defer timer */ - volatile unsigned int nc_ctr; /* Transmit normal-collision counter */ - volatile unsigned int fc_ctr; /* Transmit first-collision counter */ - volatile unsigned int ex_ctr; /* Transmit excess-collision counter */ - volatile unsigned int lt_ctr; /* Transmit late-collision counter */ - volatile unsigned int rand_seed; /* Transmit random number seed */ - volatile unsigned int tx_smachine; /* Transmit state machine */ - volatile unsigned int _unused2[44]; /* Reserved */ - volatile unsigned int rx_swreset; /* Receiver software reset */ - volatile unsigned int rx_cfg; /* Receiver config register */ - volatile unsigned int rx_pkt_max; /* Receive max pkt size */ - volatile unsigned int rx_pkt_min; /* Receive min pkt size */ - volatile unsigned int mac_addr2; /* Ether address register 2 */ - volatile unsigned int mac_addr1; /* Ether address register 1 */ - volatile unsigned int mac_addr0; /* Ether address register 0 */ - volatile unsigned int fr_ctr; /* Receive frame receive counter */ - volatile unsigned int gle_ctr; /* Receive giant-length error counter */ - volatile unsigned int unale_ctr; /* Receive unaligned error counter */ - volatile unsigned int rcrce_ctr; /* Receive CRC error counter */ - volatile unsigned int rx_smachine; /* Receiver state machine */ - volatile unsigned int rx_cvalid; /* Receiver code violation */ - volatile unsigned int _unused3; /* Reserved... */ - volatile unsigned int htable3; /* Hash table 3 */ - volatile unsigned int htable2; /* Hash table 2 */ - volatile unsigned int htable1; /* Hash table 1 */ - volatile unsigned int htable0; /* Hash table 0 */ - volatile unsigned int afilter2; /* Address filter 2 */ - volatile unsigned int afilter1; /* Address filter 1 */ - volatile unsigned int afilter0; /* Address filter 0 */ - volatile unsigned int afilter_mask; /* Address filter mask */ - -}; +#define BMAC_XIFCFG 0x0000UL /* XIF config register */ + /* 0x4-->0x204, reserved */ +#define BMAC_TXSWRESET 0x208UL /* Transmitter software reset */ +#define BMAC_TXCFG 0x20cUL /* Transmitter config register */ +#define BMAC_IGAP1 0x210UL /* Inter-packet gap 1 */ +#define BMAC_IGAP2 0x214UL /* Inter-packet gap 2 */ +#define BMAC_ALIMIT 0x218UL /* Transmit attempt limit */ +#define BMAC_STIME 0x21cUL /* Transmit slot time */ +#define BMAC_PLEN 0x220UL /* Size of transmit preamble */ +#define BMAC_PPAT 0x224UL /* Pattern for transmit preamble */ +#define BMAC_TXSDELIM 0x228UL /* Transmit delimiter */ +#define BMAC_JSIZE 0x22cUL /* Jam size */ +#define BMAC_TXMAX 0x230UL /* Transmit max pkt size */ +#define BMAC_TXMIN 0x234UL /* Transmit min pkt size */ +#define BMAC_PATTEMPT 0x238UL /* Count of transmit peak attempts */ +#define BMAC_DTCTR 0x23cUL /* Transmit defer timer */ +#define BMAC_NCCTR 0x240UL /* Transmit normal-collision counter */ +#define BMAC_FCCTR 0x244UL /* Transmit first-collision counter */ +#define BMAC_EXCTR 0x248UL /* Transmit excess-collision counter */ +#define BMAC_LTCTR 0x24cUL /* Transmit late-collision counter */ +#define BMAC_RSEED 0x250UL /* Transmit random number seed */ +#define BMAC_TXSMACHINE 0x254UL /* Transmit state machine */ + /* 0x258-->0x304, reserved */ +#define BMAC_RXSWRESET 0x308UL /* Receiver software reset */ +#define BMAC_RXCFG 0x30cUL /* Receiver config register */ +#define BMAC_RXMAX 0x310UL /* Receive max pkt size */ +#define BMAC_RXMIN 0x314UL /* Receive min pkt size */ +#define BMAC_MACADDR2 0x318UL /* Ether address register 2 */ +#define BMAC_MACADDR1 0x31cUL /* Ether address register 1 */ +#define BMAC_MACADDR0 0x320UL /* Ether address register 0 */ +#define BMAC_FRCTR 0x324UL /* Receive frame receive counter */ +#define BMAC_GLECTR 0x328UL /* Receive giant-length error counter */ +#define BMAC_UNALECTR 0x32cUL /* Receive unaligned error counter */ +#define BMAC_RCRCECTR 0x330UL /* Receive CRC error counter */ +#define BMAC_RXSMACHINE 0x334UL /* Receiver state machine */ +#define BMAC_RXCVALID 0x338UL /* Receiver code violation */ + /* 0x33c, reserved */ +#define BMAC_HTABLE3 0x340UL /* Hash table 3 */ +#define BMAC_HTABLE2 0x344UL /* Hash table 2 */ +#define BMAC_HTABLE1 0x348UL /* Hash table 1 */ +#define BMAC_HTABLE0 0x34cUL /* Hash table 0 */ +#define BMAC_AFILTER2 0x350UL /* Address filter 2 */ +#define BMAC_AFILTER1 0x354UL /* Address filter 1 */ +#define BMAC_AFILTER0 0x358UL /* Address filter 0 */ +#define BMAC_AFMASK 0x35cUL /* Address filter mask */ +#define BMAC_REG_SIZE 0x360UL /* BigMac XIF config register. */ #define BIGMAC_XCFG_ODENABLE 0x00000001 /* Output driver enable */ @@ -236,16 +231,15 @@ #define BIGMAC_RXCFG_AENABLE 0x00001000 /* Enable the address filter */ /* These are the "Management Interface" (ie. MIF) registers of the transceiver. */ -struct hmeal_tcvregs { - volatile unsigned int bb_clock; /* Bit bang clock register */ - volatile unsigned int bb_data; /* Bit bang data register */ - volatile unsigned int bb_oenab; /* Bit bang output enable */ - volatile unsigned int frame; /* Frame control/data register */ - volatile unsigned int cfg; /* MIF config register */ - volatile unsigned int int_mask; /* MIF interrupt mask */ - volatile unsigned int status; /* MIF status */ - volatile unsigned int smachine; /* MIF state machine */ -}; +#define TCVR_BBCLOCK 0x00UL /* Bit bang clock register */ +#define TCVR_BBDATA 0x04UL /* Bit bang data register */ +#define TCVR_BBOENAB 0x08UL /* Bit bang output enable */ +#define TCVR_FRAME 0x0cUL /* Frame control/data register */ +#define TCVR_CFG 0x10UL /* MIF config register */ +#define TCVR_IMASK 0x14UL /* MIF interrupt mask */ +#define TCVR_STATUS 0x18UL /* MIF status */ +#define TCVR_SMACHINE 0x1cUL /* MIF state machine */ +#define TCVR_REG_SIZE 0x20UL /* Frame commands. */ #define FRAME_WRITE 0x50020000 @@ -421,10 +415,12 @@ /* Happy Meal descriptor rings and such. * All descriptor rings must be aligned on a 2K boundry. * All receive buffers must be 64 byte aligned. + * Always write the address first before setting the ownership + * bits to avoid races with the hardware scanning the ring. */ struct happy_meal_rxd { - unsigned int rx_flags; - unsigned int rx_addr; + u32 rx_flags; + u32 rx_addr; }; #define RXFLAG_OWN 0x80000000 /* 1 = hardware, 0 = software */ @@ -433,8 +429,8 @@ #define RXFLAG_CSUM 0x0000ffff /* HW computed checksum */ struct happy_meal_txd { - unsigned int tx_flags; - unsigned int tx_addr; + u32 tx_flags; + u32 tx_addr; }; #define TXFLAG_OWN 0x80000000 /* 1 = hardware, 0 = software */ @@ -480,18 +476,6 @@ #define hblock_offset(mem, elem) \ ((__u32)((unsigned long)(&(((struct hmeal_init_block *)0)->mem[elem])))) -#define SUN4C_PKT_BUF_SZ 1546 -#define SUN4C_RX_BUFF_SIZE SUN4C_PKT_BUF_SZ -#define SUN4C_TX_BUFF_SIZE SUN4C_PKT_BUF_SZ - -struct hmeal_buffers { - char tx_buf[TX_RING_SIZE][SUN4C_TX_BUFF_SIZE]; - char rx_buf[RX_RING_SIZE][SUN4C_RX_BUFF_SIZE]; -}; - -#define hbuf_offset(mem, elem) \ -((__u32)((unsigned long)(&(((struct hmeal_buffers *)0)->mem[elem][0])))) - /* Now software state stuff. */ enum happy_transceiver { external = 0, @@ -511,25 +495,39 @@ /* Happy happy, joy joy! */ struct happy_meal { - struct hmeal_gregs *gregs; /* Happy meal global registers */ - struct hmeal_etxregs *etxregs; /* External transmitter regs */ - struct hmeal_erxregs *erxregs; /* External receiver regs */ - struct hmeal_bigmacregs *bigmacregs; /* I said NO SOLARIS with my bigmac! */ - struct hmeal_tcvregs *tcvregs; /* MIF transceiver regs */ + unsigned long gregs; /* Happy meal global registers */ + struct hmeal_init_block *happy_block; /* RX and TX descriptors (CPU addr) */ - struct hmeal_init_block *happy_block; /* RX and TX descriptors (CPU addr) */ - __u32 hblock_dvma; /* DVMA visible address happy block */ +#if defined(CONFIG_SBUS) && defined(CONFIG_PCI) + u32 (*read_desc32)(u32 *); + void (*write_txd)(struct happy_meal_txd *, u32, u32); + void (*write_rxd)(struct happy_meal_rxd *, u32, u32); + u32 (*dma_map)(void *, void *, long); + void (*dma_unmap)(void *, u32, long); + void (*dma_sync)(void *, u32, long); +#endif + + /* This is either a sbus_dev or a pci_dev. */ + void *happy_dev; struct sk_buff *rx_skbs[RX_RING_SIZE]; struct sk_buff *tx_skbs[TX_RING_SIZE]; int rx_new, tx_new, rx_old, tx_old; - /* We may use this for Ultra as well, will have to see, maybe not. */ - struct hmeal_buffers *sun4c_buffers; /* CPU visible address. */ -#define sun4d_buffers sun4c_buffers /* No need to make this a separate. */ - __u32 s4c_buf_dvma; /* DVMA visible address. */ + struct net_device_stats net_stats; /* Statistical counters */ + +#if defined(CONFIG_SBUS) && defined(CONFIG_PCI) + u32 (*read32)(unsigned long); + void (*write32)(unsigned long, u32); +#endif + + unsigned long etxregs; /* External transmitter regs */ + unsigned long erxregs; /* External receiver regs */ + unsigned long bigmacregs; /* BIGMAC core regs */ + unsigned long tcvregs; /* MIF transceiver regs */ + __u32 hblock_dvma; /* DVMA visible address happy block */ unsigned int happy_flags; /* Driver state flags */ enum happy_transceiver tcvr_type; /* Kind of transceiver in use */ unsigned int happy_bursts; /* Get your mind out of the gutter */ @@ -555,15 +553,10 @@ enum happy_timer_state timer_state; /* State of the auto-neg timer. */ unsigned int timer_ticks; /* Number of clicks at each state. */ - struct net_device_stats net_stats; /* Statistical counters */ - struct linux_sbus_device *happy_sbus_dev; /* ;-) */ -#ifdef CONFIG_PCI - struct pci_dev *happy_pci_dev; -#endif - struct net_device *dev; /* Backpointer */ - struct quattro *qfe_parent; /* For Quattro cards */ - int qfe_ent; /* Which instance on quattro */ - struct happy_meal *next_module; + struct net_device *dev; /* Backpointer */ + struct quattro *qfe_parent; /* For Quattro cards */ + int qfe_ent; /* Which instance on quattro */ + struct happy_meal *next_module; }; /* Here are the happy flags. */ @@ -586,15 +579,12 @@ /* Support for QFE/Quattro cards. */ struct quattro { - volatile u32 *irq_status[4]; - struct net_device *happy_meals[4]; - void (*handler)(int, void *, struct pt_regs *); - - struct linux_sbus_device *quattro_sbus_dev; -#ifdef CONFIG_PCI - struct pci_dev *quattro_pci_dev; -#endif - struct quattro *next; + struct net_device *happy_meals[4]; + + /* This is either a sbus_dev or a pci_dev. */ + void *quattro_dev; + + struct quattro *next; /* PROM ranges, if any. */ struct linux_prom_ranges ranges[8]; @@ -603,78 +593,16 @@ /* We use this to acquire receive skb's that we can DMA directly into. */ #define ALIGNED_RX_SKB_ADDR(addr) \ - ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr)) + ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) #define happy_meal_alloc_skb(__length, __gfp_flags) \ ({ struct sk_buff *__skb; \ __skb = alloc_skb((__length) + 64, (__gfp_flags)); \ if(__skb) { \ - int __offset = ALIGNED_RX_SKB_ADDR(__skb->data); \ + int __offset = (int) ALIGNED_RX_SKB_ADDR(__skb->data); \ if(__offset) \ skb_reserve(__skb, __offset); \ } \ __skb; \ }) - -/* Register/DMA access stuff, used to cope with differences between - * PCI and SBUS happy meals. - */ -#if defined(CONFIG_PCI) -#define kva_to_hva(__hp, __addr) \ -({ u32 __ret; \ - if ((__hp)->happy_flags & HFLAG_PCI) \ - (__ret) = (u32) virt_to_bus((volatile void *)(__addr)); \ - else \ - (__ret) = sbus_dvma_addr(__addr); \ - __ret; \ -}) -#define hme_read32(__hp, __reg) \ -({ unsigned int __ret; \ - if ((__hp)->happy_flags & HFLAG_PCI) \ - __ret = readl((unsigned long)(__reg)); \ - else \ - __ret = *(__reg); \ - __ret; \ -}) -#define hme_write32(__hp, __reg, __val) \ -do { if ((__hp)->happy_flags & HFLAG_PCI) \ - writel((__val), (unsigned long)(__reg)); \ - else \ - *(__reg) = (__val); \ -} while(0) -#else -#define kva_to_hva(__hp, __addr) ((u32)sbus_dvma_addr(__addr)) -#define hme_read32(__hp, __reg) (*(__reg)) -#define hme_write32(__hp, __reg, __val) ((*(__reg)) = (__val)) -#endif - -#ifdef CONFIG_PCI -#ifdef __sparc_v9__ -#define pcihme_write_rxd(__rp, __flags, __addr) \ - __asm__ __volatile__("stwa %3, [%0] %2\n\t" \ - "stwa %4, [%1] %2" \ - : /* no outputs */ \ - : "r" (&(__rp)->rx_addr), "r" (&(__rp)->rx_flags), \ - "i" (ASI_PL), "r" (__addr), "r" (__flags)) - -#define pcihme_write_txd(__tp, __flags, __addr) \ - __asm__ __volatile__("stwa %3, [%0] %2\n\t" \ - "stwa %4, [%1] %2" \ - : /* no outputs */ \ - : "r" (&(__tp)->tx_addr), "r" (&(__tp)->tx_flags), \ - "i" (ASI_PL), "r" (__addr), "r" (__flags)) -#else - -#define pcihme_write_rxd(__rp, __flags, __addr) \ -do { (__rp)->rx_addr = flip_dword(__addr); \ - (__rp)->rx_flags = flip_dword(__flags); \ -} while(0) - -#define pcihme_write_txd(__tp, __flags, __addr) \ -do { (__tp)->tx_addr = flip_dword(__addr); \ - (__tp)->tx_flags = flip_dword(__flags); \ -} while(0) - -#endif /* def __sparc_v9__ */ -#endif /* def CONFIG_PCI */ #endif /* !(_SUNHME_H) */ diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c --- v2.3.34/linux/drivers/net/sunlance.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/sunlance.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sunlance.c,v 1.88 1999/08/20 00:31:45 davem Exp $ +/* $Id: sunlance.c,v 1.92 1999/12/15 14:08:09 davem Exp $ * lance.c: Linux/Sparc/Lance driver * * Written 1995, 1996 by Miguel de Icaza @@ -60,15 +60,16 @@ * 1.12: * 11/3/99: Fixed SMP race in lance_start_xmit found by davem. * Anton Blanchard (anton@progsoc.uts.edu.au) + * 2.00: 11/9/99: Massive overhaul and port to new SBUS driver interfaces. + * David S. Miller (davem@redhat.com) */ #undef DEBUG_DRIVER static char *version = - "sunlance.c:v1.12 11/Mar/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n"; + "sunlance.c:v2.00 11/Sep/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n"; static char *lancestr = "LANCE"; -static char *lancedma = "LANCE DMA"; #include #include @@ -177,53 +178,55 @@ #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) #define TX_RING_MOD_MASK (TX_RING_SIZE - 1) #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) +#define TX_NEXT(__x) (((__x)+1) & TX_RING_MOD_MASK) #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) #define RX_RING_MOD_MASK (RX_RING_SIZE - 1) #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) +#define RX_NEXT(__x) (((__x)+1) & RX_RING_MOD_MASK) #define PKT_BUF_SZ 1544 #define RX_BUFF_SIZE PKT_BUF_SZ #define TX_BUFF_SIZE PKT_BUF_SZ struct lance_rx_desc { - unsigned short rmd0; /* low address of packet */ - unsigned char rmd1_bits; /* descriptor bits */ - unsigned char rmd1_hadr; /* high address of packet */ - short length; /* This length is 2s complement (negative)! - * Buffer length - */ - unsigned short mblength; /* This is the actual number of bytes received */ + u16 rmd0; /* low address of packet */ + u8 rmd1_bits; /* descriptor bits */ + u8 rmd1_hadr; /* high address of packet */ + s16 length; /* This length is 2s complement (negative)! + * Buffer length + */ + u16 mblength; /* This is the actual number of bytes received */ }; struct lance_tx_desc { - unsigned short tmd0; /* low address of packet */ - unsigned char tmd1_bits; /* descriptor bits */ - unsigned char tmd1_hadr; /* high address of packet */ - short length; /* Length is 2s complement (negative)! */ - unsigned short misc; + u16 tmd0; /* low address of packet */ + u8 tmd1_bits; /* descriptor bits */ + u8 tmd1_hadr; /* high address of packet */ + s16 length; /* Length is 2s complement (negative)! */ + u16 misc; }; /* The LANCE initialization block, described in databook. */ /* On the Sparc, this block should be on a DMA region */ struct lance_init_block { - unsigned short mode; /* Pre-set mode (reg. 15) */ - unsigned char phys_addr[6]; /* Physical ethernet address */ - unsigned filter[2]; /* Multicast filter. */ + u16 mode; /* Pre-set mode (reg. 15) */ + u8 phys_addr[6]; /* Physical ethernet address */ + u32 filter[2]; /* Multicast filter. */ /* Receive and transmit ring base, along with extra bits. */ - unsigned short rx_ptr; /* receive descriptor addr */ - unsigned short rx_len; /* receive len and high addr */ - unsigned short tx_ptr; /* transmit descriptor addr */ - unsigned short tx_len; /* transmit len and high addr */ + u16 rx_ptr; /* receive descriptor addr */ + u16 rx_len; /* receive len and high addr */ + u16 tx_ptr; /* transmit descriptor addr */ + u16 tx_len; /* transmit len and high addr */ /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */ struct lance_rx_desc brx_ring[RX_RING_SIZE]; struct lance_tx_desc btx_ring[TX_RING_SIZE]; - char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE]; - char pad[2]; /* align rx_buf for copy_and_sum(). */ - char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE]; + u8 tx_buf [TX_RING_SIZE][TX_BUFF_SIZE]; + u8 pad[2]; /* align rx_buf for copy_and_sum(). */ + u8 rx_buf [RX_RING_SIZE][RX_BUFF_SIZE]; }; #define libdesc_offset(rt, elem) \ @@ -233,40 +236,48 @@ ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0]))))) struct lance_private { - char *name; - volatile struct lance_regs *ll; + unsigned long lregs; /* Lance RAP/RDP regs. */ + unsigned long dregs; /* DMA controller regs. */ volatile struct lance_init_block *init_block; - __u32 init_block_dvma; - int rx_new, tx_new; - int rx_old, tx_old; + int rx_new, tx_new; + int rx_old, tx_old; struct net_device_stats stats; - struct Linux_SBus_DMA *ledma; /* If set this points to ledma */ - /* and arch = sun4m */ - - int tpe; /* cable-selection is TPE */ - int auto_select; /* cable-selection by carrier */ - int burst_sizes; /* ledma SBus burst sizes */ - - unsigned short busmaster_regval; - unsigned short pio_buffer; - - struct net_device *dev; /* Backpointer */ - struct lance_private *next_module; - struct linux_sbus *sbus; - struct timer_list multicast_timer; + struct sbus_dma *ledma; /* If set this points to ledma */ + char tpe; /* cable-selection is TPE */ + char auto_select; /* cable-selection by carrier */ + char burst_sizes; /* ledma SBus burst sizes */ + char pio_buffer; /* init block in PIO space? */ + + unsigned short busmaster_regval; + + void (*init_ring)(struct net_device *); + void (*rx)(struct net_device *); + void (*tx)(struct net_device *); + + char *name; + __u32 init_block_dvma; + struct net_device *dev; /* Backpointer */ + struct lance_private *next_module; + struct sbus_dev *sdev; + struct timer_list multicast_timer; }; #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\ lp->tx_old - lp->tx_new-1) -/* On the sparc, the lance control ports are memory mapped */ -struct lance_regs { - unsigned short rdp; /* register data port */ - unsigned short rap; /* register address port */ -}; +/* Lance registers. */ +#define RDP 0x00UL /* register data port */ +#define RAP 0x02UL /* register address port */ +#define LANCE_REG_SIZE 0x04UL + +#define STOP_LANCE(__lp) \ +do { unsigned long __base = (__lp)->lregs; \ + sbus_writew(LE_CSR0, __base + RAP); \ + sbus_writew(LE_C0_STOP, __base + RDP); \ +} while (0) int sparc_lance_debug = 2; @@ -275,7 +286,7 @@ /* On the Sun4m we have to instruct the ledma to provide them */ /* Even worse, on scsi/ether SBUS cards, the init block and the * transmit/receive buffers are addresses as offsets from absolute - * zero on the lebuffer PIO area. -davem + * zero on the lebuffer PIO area. -DaveM */ #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) @@ -285,46 +296,36 @@ #endif /* Load the CSR registers */ -static void load_csrs (struct lance_private *lp) +static void load_csrs(struct lance_private *lp) { - volatile struct lance_regs *ll = lp->ll; - __u32 ib_dvma = lp->init_block_dvma; - int leptr; + u32 leptr; - /* This is right now because when we are using a PIO buffered - * init block, init_block_dvma is set to zero. -DaveM - */ - leptr = LANCE_ADDR (ib_dvma); - - ll->rap = LE_CSR1; - ll->rdp = (leptr & 0xFFFF); - ll->rap = LE_CSR2; - ll->rdp = leptr >> 16; - ll->rap = LE_CSR3; - ll->rdp = lp->busmaster_regval; + if (lp->pio_buffer) + leptr = 0; + else + leptr = LANCE_ADDR(lp->init_block_dvma); + + sbus_writew(LE_CSR1, lp->lregs + RAP); + sbus_writew(leptr & 0xffff, lp->lregs + RDP); + sbus_writew(LE_CSR2, lp->lregs + RAP); + sbus_writew(leptr >> 16, lp->lregs + RDP); + sbus_writew(LE_CSR3, lp->lregs + RAP); + sbus_writew(lp->busmaster_regval, lp->lregs + RDP); /* Point back to csr0 */ - ll->rap = LE_CSR0; + sbus_writew(LE_CSR0, lp->lregs + RAP); } -#define ZERO 0 - /* Setup the Lance Rx and Tx rings */ /* Sets dev->tbusy */ -static void lance_init_ring (struct net_device *dev) +static void lance_init_ring_dvma(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; - __u32 ib_dvma = lp->init_block_dvma; - __u32 aib; /* for LANCE_ADDR computations */ - int leptr; + __u32 aib = lp->init_block_dvma; + __u32 leptr; int i; - /* This is right now because when we are using a PIO buffered - * init block, init_block_dvma is set to zero. -DaveM - */ - aib = ib_dvma; - /* Lock out other processes while setting up hardware */ dev->tbusy = 1; lp->rx_new = lp->tx_new = 0; @@ -332,7 +333,6 @@ /* Copy the ethernet address to the lance init block * Note that on the sparc you need to swap the ethernet address. - * Note also we want the CPU ptr of the init_block here. */ ib->phys_addr [0] = dev->dev_addr [1]; ib->phys_addr [1] = dev->dev_addr [0]; @@ -341,9 +341,6 @@ ib->phys_addr [4] = dev->dev_addr [5]; ib->phys_addr [5] = dev->dev_addr [4]; - if (ZERO) - printk ("TX rings:\n"); - /* Setup the Tx ring entries */ for (i = 0; i <= TX_RING_SIZE; i++) { leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i)); @@ -352,13 +349,9 @@ ib->btx_ring [i].tmd1_bits = 0; ib->btx_ring [i].length = 0xf000; /* The ones required by tmd2 */ ib->btx_ring [i].misc = 0; - if (i < 3) - if (ZERO) printk ("%d: 0x%8.8x\n", i, leptr); } /* Setup the Rx ring entries */ - if (ZERO) - printk ("RX rings:\n"); for (i = 0; i < RX_RING_SIZE; i++) { leptr = LANCE_ADDR(aib + libbuff_offset(rx_buf, i)); @@ -367,8 +360,6 @@ ib->brx_ring [i].rmd1_bits = LE_R1_OWN; ib->brx_ring [i].length = -RX_BUFF_SIZE | 0xf000; ib->brx_ring [i].mblength = 0; - if (i < 3 && ZERO) - printk ("%d: 0x%8.8x\n", i, leptr); } /* Setup the initialization block */ @@ -377,98 +368,155 @@ leptr = LANCE_ADDR(aib + libdesc_offset(brx_ring, 0)); ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16); ib->rx_ptr = leptr; - if (ZERO) - printk ("RX ptr: %8.8x\n", leptr); /* Setup tx descriptor pointer */ leptr = LANCE_ADDR(aib + libdesc_offset(btx_ring, 0)); ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16); ib->tx_ptr = leptr; - if (ZERO) - printk ("TX ptr: %8.8x\n", leptr); } -static int init_restart_lance (struct lance_private *lp) +static void lance_init_ring_pio(struct net_device *dev) { - volatile struct lance_regs *ll = lp->ll; + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + u32 leptr; int i; + + /* Lock out other processes while setting up hardware */ + dev->tbusy = 1; + lp->rx_new = lp->tx_new = 0; + lp->rx_old = lp->tx_old = 0; - if (lp->ledma) { - struct sparc_dma_registers *dregs = lp->ledma->regs; - unsigned long creg; - - if (!(dregs->cond_reg & DMA_HNDL_ERROR)) { - /* E-Cache draining */ - while (dregs->cond_reg & DMA_FIFO_ISDRAIN) - barrier(); - } + /* Copy the ethernet address to the lance init block + * Note that on the sparc you need to swap the ethernet address. + */ + sbus_writeb(dev->dev_addr[1], &ib->phys_addr[0]); + sbus_writeb(dev->dev_addr[0], &ib->phys_addr[1]); + sbus_writeb(dev->dev_addr[3], &ib->phys_addr[2]); + sbus_writeb(dev->dev_addr[2], &ib->phys_addr[3]); + sbus_writeb(dev->dev_addr[5], &ib->phys_addr[4]); + sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]); - creg = dregs->cond_reg; - if (lp->burst_sizes & DMA_BURST32) - creg |= DMA_E_BURST8; - else - creg &= ~DMA_E_BURST8; + /* Setup the Tx ring entries */ + for (i = 0; i <= TX_RING_SIZE; i++) { + leptr = libbuff_offset(tx_buf, i); + sbus_writew(leptr, &ib->btx_ring [i].tmd0); + sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr); + sbus_writeb(0, &ib->btx_ring [i].tmd1_bits); + + /* The ones required by tmd2 */ + sbus_writew(0xf000, &ib->btx_ring [i].length); + sbus_writew(0, &ib->btx_ring [i].misc); + } - creg |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV); + /* Setup the Rx ring entries */ + for (i = 0; i < RX_RING_SIZE; i++) { + leptr = libbuff_offset(rx_buf, i); - if (lp->tpe) - creg |= DMA_EN_ENETAUI; - else - creg &= ~DMA_EN_ENETAUI; - udelay(20); - dregs->cond_reg = creg; - udelay(200); + sbus_writew(leptr, &ib->brx_ring [i].rmd0); + sbus_writeb(leptr >> 16,&ib->brx_ring [i].rmd1_hadr); + sbus_writeb(LE_R1_OWN, &ib->brx_ring [i].rmd1_bits); + sbus_writew(-RX_BUFF_SIZE|0xf000, + &ib->brx_ring [i].length); + sbus_writew(0, &ib->brx_ring [i].mblength); } - ll->rap = LE_CSR0; - ll->rdp = LE_C0_INIT; + /* Setup the initialization block */ + + /* Setup rx descriptor pointer */ + leptr = libdesc_offset(brx_ring, 0); + sbus_writew((LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16), + &ib->rx_len); + sbus_writew(leptr, &ib->rx_ptr); + + /* Setup tx descriptor pointer */ + leptr = libdesc_offset(btx_ring, 0); + sbus_writew((LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16), + &ib->tx_len); + sbus_writew(leptr, &ib->tx_ptr); +} + +static void init_restart_ledma(struct lance_private *lp) +{ + u32 csr = sbus_readl(lp->dregs + DMA_CSR); + + if (!(csr & DMA_HNDL_ERROR)) { + /* E-Cache draining */ + while (sbus_readl(lp->dregs + DMA_CSR) & DMA_FIFO_ISDRAIN) + barrier(); + } + + csr = sbus_readl(lp->dregs + DMA_CSR); + csr &= ~DMA_E_BURSTS; + if (lp->burst_sizes & DMA_BURST32) + csr |= DMA_E_BURST32; + else + csr |= DMA_E_BURST16; + + csr |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV); + + if (lp->tpe) + csr |= DMA_EN_ENETAUI; + else + csr &= ~DMA_EN_ENETAUI; + udelay(20); + sbus_writel(csr, lp->dregs + DMA_CSR); + udelay(200); +} + +static int init_restart_lance(struct lance_private *lp) +{ + u16 regval = 0; + int i; + + if (lp->dregs) + init_restart_ledma(lp); + + sbus_writew(LE_CSR0, lp->lregs + RAP); + sbus_writew(LE_C0_INIT, lp->lregs + RDP); /* Wait for the lance to complete initialization */ - for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++) + for (i = 0; i < 100; i++) { + regval = sbus_readw(lp->lregs + RDP); + + if (regval & (LE_C0_ERR | LE_C0_IDON)) + break; barrier(); - if ((i == 100) || (ll->rdp & LE_C0_ERR)) { - printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); - if (lp->ledma) - printk ("dcsr=%8.8x\n", - (unsigned int) lp->ledma->regs->cond_reg); + } + if (i == 100 || (regval & LE_C0_ERR)) { + printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n", + i, regval); + if (lp->dregs) + printk("dcsr=%8.8x\n", sbus_readl(lp->dregs + DMA_CSR)); return -1; } /* Clear IDON by writing a "1", enable interrupts and start lance */ - ll->rdp = LE_C0_IDON; - ll->rdp = LE_C0_INEA | LE_C0_STRT; + sbus_writew(LE_C0_IDON, lp->lregs + RDP); + sbus_writew(LE_C0_INEA | LE_C0_STRT, lp->lregs + RDP); - if (lp->ledma) - lp->ledma->regs->cond_reg |= DMA_INT_ENAB; + if (lp->dregs) { + u32 csr = sbus_readl(lp->dregs + DMA_CSR); + + csr |= DMA_INT_ENAB; + sbus_writel(csr, lp->dregs + DMA_CSR); + } return 0; } -static int lance_rx (struct net_device *dev) +static void lance_rx_dvma(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; volatile struct lance_rx_desc *rd; - unsigned char bits; - int len; + u8 bits; + int len, entry = lp->rx_new; struct sk_buff *skb; -#ifdef TEST_HITS - printk ("["); - for (i = 0; i < RX_RING_SIZE; i++) { - if (i == lp->rx_new) - printk ("%s", - ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X"); - else - printk ("%s", - ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1"); - } - printk ("]"); -#endif - - for (rd = &ib->brx_ring [lp->rx_new]; + for (rd = &ib->brx_ring [entry]; !((bits = rd->rmd1_bits) & LE_R1_OWN); - rd = &ib->brx_ring [lp->rx_new]) { + rd = &ib->brx_ring [entry]) { /* We got an incomplete frame? */ if ((bits & LE_R1_POK) != LE_R1_POK) { @@ -485,58 +533,57 @@ if (bits & LE_R1_EOP) lp->stats.rx_errors++; } else { len = (rd->mblength & 0xfff) - 4; - skb = dev_alloc_skb (len+2); + skb = dev_alloc_skb(len + 2); - if (skb == 0) { - printk ("%s: Memory squeeze, deferring packet.\n", - dev->name); + if (skb == NULL) { + printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", + dev->name); lp->stats.rx_dropped++; rd->mblength = 0; rd->rmd1_bits = LE_R1_OWN; - lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; - return 0; + lp->rx_new = RX_NEXT(entry); + return; } lp->stats.rx_bytes += len; skb->dev = dev; - skb_reserve (skb, 2); /* 16 byte align */ - skb_put (skb, len); /* make room */ + skb_reserve(skb, 2); /* 16 byte align */ + skb_put(skb, len); /* make room */ eth_copy_and_sum(skb, - (unsigned char *)&(ib->rx_buf [lp->rx_new][0]), + (unsigned char *)&(ib->rx_buf [entry][0]), len, 0); - skb->protocol = eth_type_trans (skb, dev); - netif_rx (skb); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); lp->stats.rx_packets++; } /* Return the packet to the pool */ rd->mblength = 0; rd->rmd1_bits = LE_R1_OWN; - lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + entry = RX_NEXT(entry); } - return 0; + + lp->rx_new = entry; } -static int lance_tx (struct net_device *dev) +static void lance_tx_dvma(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; - volatile struct lance_regs *ll = lp->ll; - volatile struct lance_tx_desc *td; int i, j; - int status; j = lp->tx_old; for (i = j; i != lp->tx_new; i = j) { - td = &ib->btx_ring [i]; + volatile struct lance_tx_desc *td = &ib->btx_ring [i]; + u8 bits = td->tmd1_bits; /* If we hit a packet not owned by us, stop */ - if (td->tmd1_bits & LE_T1_OWN) + if (bits & LE_T1_OWN) break; - if (td->tmd1_bits & LE_T1_ERR) { - status = td->misc; + if (bits & LE_T1_ERR) { + u16 status = td->misc; lp->stats.tx_errors++; if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; @@ -546,15 +593,13 @@ lp->stats.tx_carrier_errors++; if (lp->auto_select) { lp->tpe = 1 - lp->tpe; - printk("%s: Carrier Lost, trying %s\n", + printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n", dev->name, lp->tpe?"TPE":"AUI"); - /* Stop the lance */ - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; - lance_init_ring (dev); - load_csrs (lp); - init_restart_lance (lp); - return 0; + STOP_LANCE(lp); + lp->init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return; } } @@ -564,72 +609,233 @@ if (status & (LE_T3_BUF|LE_T3_UFL)) { lp->stats.tx_fifo_errors++; - printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", - dev->name); - /* Stop the lance */ - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; - lance_init_ring (dev); - load_csrs (lp); - init_restart_lance (lp); - return 0; + printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n", + dev->name); + STOP_LANCE(lp); + lp->init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return; } - } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { + } else if ((bits & LE_T1_POK) == LE_T1_POK) { /* * So we don't count the packet more than once. */ - td->tmd1_bits &= ~(LE_T1_POK); + td->tmd1_bits = bits & ~(LE_T1_POK); /* One collision before packet was sent. */ - if (td->tmd1_bits & LE_T1_EONE) + if (bits & LE_T1_EONE) lp->stats.collisions++; /* More than one collision, be optimistic. */ - if (td->tmd1_bits & LE_T1_EMORE) + if (bits & LE_T1_EMORE) lp->stats.collisions += 2; lp->stats.tx_packets++; } - j = (j + 1) & TX_RING_MOD_MASK; + j = TX_NEXT(j); } lp->tx_old = j; - return 0; } -static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) +static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len) +{ + u16 *p16 = (u16 *) skb->data; + u32 *p32; + u8 *p8; + unsigned long pbuf = (unsigned long) piobuf; + + /* We know here that both src and dest are on a 16bit boundry. */ + *p16++ = sbus_readw(pbuf); + p32 = (u32 *) p16; + pbuf += 2; + len -= 2; + + while (len >= 4) { + *p32++ = sbus_readl(pbuf); + pbuf += 4; + len -= 4; + } + p8 = (u8 *) p32; + if (len >= 2) { + p16 = (u16 *) p32; + *p16++ = sbus_readw(pbuf); + pbuf += 2; + len -= 2; + p8 = (u8 *) p16; + } + if (len >= 1) + *p8 = sbus_readb(pbuf); +} + +static void lance_rx_pio(struct net_device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + volatile struct lance_rx_desc *rd; + unsigned char bits; + int len, entry; + struct sk_buff *skb; + + entry = lp->rx_new; + for (rd = &ib->brx_ring [entry]; + !((bits = sbus_readb(&rd->rmd1_bits)) & LE_R1_OWN); + rd = &ib->brx_ring [entry]) { + + /* We got an incomplete frame? */ + if ((bits & LE_R1_POK) != LE_R1_POK) { + lp->stats.rx_over_errors++; + lp->stats.rx_errors++; + } else if (bits & LE_R1_ERR) { + /* Count only the end frame as a rx error, + * not the beginning + */ + if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++; + if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++; + if (bits & LE_R1_OFL) lp->stats.rx_over_errors++; + if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++; + if (bits & LE_R1_EOP) lp->stats.rx_errors++; + } else { + len = (sbus_readw(&rd->mblength) & 0xfff) - 4; + skb = dev_alloc_skb(len + 2); + + if (skb == NULL) { + printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", + dev->name); + lp->stats.rx_dropped++; + sbus_writew(0, &rd->mblength); + sbus_writeb(LE_R1_OWN, &rd->rmd1_bits); + lp->rx_new = RX_NEXT(entry); + return; + } + + lp->stats.rx_bytes += len; + + skb->dev = dev; + skb_reserve (skb, 2); /* 16 byte align */ + skb_put(skb, len); /* make room */ + lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + } + + /* Return the packet to the pool */ + sbus_writew(0, &rd->mblength); + sbus_writeb(LE_R1_OWN, &rd->rmd1_bits); + entry = RX_NEXT(entry); + } + + lp->rx_new = entry; +} + +static void lance_tx_pio(struct net_device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_init_block *ib = lp->init_block; + int i, j; + + j = lp->tx_old; + for (i = j; i != lp->tx_new; i = j) { + volatile struct lance_tx_desc *td = &ib->btx_ring [i]; + u8 bits = sbus_readb(&td->tmd1_bits); + + /* If we hit a packet not owned by us, stop */ + if (bits & LE_T1_OWN) + break; + + if (bits & LE_T1_ERR) { + u16 status = sbus_readw(&td->misc); + + lp->stats.tx_errors++; + if (status & LE_T3_RTY) lp->stats.tx_aborted_errors++; + if (status & LE_T3_LCOL) lp->stats.tx_window_errors++; + + if (status & LE_T3_CLOS) { + lp->stats.tx_carrier_errors++; + if (lp->auto_select) { + lp->tpe = 1 - lp->tpe; + printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n", + dev->name, lp->tpe?"TPE":"AUI"); + STOP_LANCE(lp); + lp->init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return; + } + } + + /* Buffer errors and underflows turn off the + * transmitter, restart the adapter. + */ + if (status & (LE_T3_BUF|LE_T3_UFL)) { + lp->stats.tx_fifo_errors++; + + printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n", + dev->name); + STOP_LANCE(lp); + lp->init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); + return; + } + } else if ((bits & LE_T1_POK) == LE_T1_POK) { + /* + * So we don't count the packet more than once. + */ + sbus_writeb(bits & ~(LE_T1_POK), &td->tmd1_bits); + + /* One collision before packet was sent. */ + if (bits & LE_T1_EONE) + lp->stats.collisions++; + + /* More than one collision, be optimistic. */ + if (bits & LE_T1_EMORE) + lp->stats.collisions += 2; + + lp->stats.tx_packets++; + } + + j = TX_NEXT(j); + } + lp->tx_old = j; +} + +static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; struct lance_private *lp = (struct lance_private *)dev->priv; - volatile struct lance_regs *ll = lp->ll; int csr0; if (dev->interrupt) - printk ("%s: again", dev->name); + printk(KERN_ERR "%s: again", dev->name); dev->interrupt = 1; - ll->rap = LE_CSR0; - csr0 = ll->rdp; + sbus_writew(LE_CSR0, lp->lregs + RAP); + csr0 = sbus_readw(lp->lregs + RDP); /* Acknowledge all the interrupt sources ASAP */ - ll->rdp = csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT); + sbus_writew(csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT), + lp->lregs + RDP); - if ((csr0 & LE_C0_ERR)) { + if ((csr0 & LE_C0_ERR) != 0) { /* Clear the error condition */ - ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | - LE_C0_CERR | LE_C0_MERR; + sbus_writew((LE_C0_BABL | LE_C0_ERR | LE_C0_MISS | + LE_C0_CERR | LE_C0_MERR), + lp->lregs + RDP); } if (csr0 & LE_C0_RINT) - lance_rx (dev); + lp->rx(dev); if (csr0 & LE_C0_TINT) - lance_tx (dev); + lp->tx(dev); - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { + if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) { dev->tbusy = 0; - mark_bh (NET_BH); + mark_bh(NET_BH); } if (csr0 & LE_C0_BABL) @@ -639,103 +845,122 @@ lp->stats.rx_errors++; if (csr0 & LE_C0_MERR) { - struct sparc_dma_registers *dregs = lp->ledma->regs; - unsigned long tst = (unsigned long)dregs->st_addr; + if (lp->dregs) { + u32 addr = sbus_readl(lp->dregs + DMA_ADDR); + + printk(KERN_ERR "%s: Memory error, status %04x, addr %06x\n", + dev->name, csr0, addr & 0xffffff); + } else { + printk(KERN_ERR "%s: Memory error, status %04x\n", + dev->name, csr0); + } - printk ("%s: Memory error, status %04x, addr %06lx\n", - dev->name, csr0, tst & 0xffffff); + sbus_writew(LE_C0_STOP, lp->lregs + RDP); - ll->rdp = LE_C0_STOP; + if (lp->dregs) { + u32 dma_csr = sbus_readl(lp->dregs + DMA_CSR); - if (lp->ledma) - lp->ledma->regs->cond_reg |= DMA_FIFO_INV; + dma_csr |= DMA_FIFO_INV; + sbus_writel(dma_csr, lp->dregs + DMA_CSR); + } - lance_init_ring (dev); - load_csrs (lp); - init_restart_lance (lp); + lp->init_ring(dev); + load_csrs(lp); + init_restart_lance(lp); dev->tbusy = 0; } - ll->rdp = LE_C0_INEA; + sbus_writew(LE_C0_INEA, lp->lregs + RDP); dev->interrupt = 0; } +/* Build a fake network packet and send it to ourselves. */ +static void build_fake_packet(struct lance_private *lp) +{ + struct net_device *dev = lp->dev; + volatile struct lance_init_block *ib = lp->init_block; + u16 *packet; + struct ethhdr *eth; + int i, entry; + + entry = lp->tx_new & TX_RING_MOD_MASK; + packet = (u16 *) &(ib->tx_buf[entry][0]); + eth = (struct ethhdr *) packet; + if (lp->pio_buffer) { + for (i = 0; i < (ETH_ZLEN / sizeof(u16)); i++) + sbus_writew(0, &packet[i]); + for (i = 0; i < 6; i++) { + sbus_writeb(dev->dev_addr[i], ð->h_dest[i]); + sbus_writeb(dev->dev_addr[i], ð->h_source[i]); + } + sbus_writew((-ETH_ZLEN) | 0xf000, &ib->btx_ring[entry].length); + sbus_writew(0, &ib->btx_ring[entry].misc); + sbus_writeb(LE_T1_POK|LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits); + } else { + memset(packet, 0, ETH_ZLEN); + for (i = 0; i < 6; i++) { + eth->h_dest[i] = dev->dev_addr[i]; + eth->h_source[i] = dev->dev_addr[i]; + } + ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000; + ib->btx_ring[entry].misc = 0; + ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); + } + lp->tx_new = TX_NEXT(entry); +} + struct net_device *last_dev = 0; -static int lance_open (struct net_device *dev) +static int lance_open(struct net_device *dev) { struct lance_private *lp = (struct lance_private *)dev->priv; - volatile struct lance_regs *ll = lp->ll; volatile struct lance_init_block *ib = lp->init_block; int status = 0; last_dev = dev; - if (request_irq (dev->irq, &lance_interrupt, SA_SHIRQ, - lancestr, (void *) dev)) { - printk ("Lance: Can't get irq %s\n", __irq_itoa(dev->irq)); + if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ, + lancestr, (void *) dev)) { + printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq)); return -EAGAIN; } - /* Stop the Lance */ - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; + STOP_LANCE(lp); /* On the 4m, setup the ledma to provide the upper bits for buffers */ - if (lp->ledma) - lp->ledma->regs->dma_test = ((__u32) lp->init_block_dvma) & 0xff000000; + if (lp->dregs) { + u32 regval = lp->init_block_dvma & 0xff000000; - /* Set mode and clear multicast filter only at device open, - so that lance_init_ring() called at any error will not - forget multicast filters. + sbus_writel(regval, lp->dregs + DMA_TEST); + } - BTW it is common bug in all lance drivers! --ANK + /* Set mode and clear multicast filter only at device open, + * so that lance_init_ring() called at any error will not + * forget multicast filters. + * + * BTW it is common bug in all lance drivers! --ANK */ - ib->mode = 0; - ib->filter [0] = 0; - ib->filter [1] = 0; + if (lp->pio_buffer) { + sbus_writew(0, &ib->mode); + sbus_writel(0, &ib->filter[0]); + sbus_writel(0, &ib->filter[1]); + } else { + ib->mode = 0; + ib->filter [0] = 0; + ib->filter [1] = 0; + } - lance_init_ring (dev); - load_csrs (lp); + lp->init_ring(dev); + load_csrs(lp); dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; - status = init_restart_lance (lp); -#if 0 - /* To emulate SunOS, we add a route to the local network */ - rt_add (RTF_UP, - dev->pa_addr & ip_get_mask (dev->pa_addr), - ip_get_mask (dev->pa_addr), - 0, dev, dev->mtu, 0, 0); -#endif + status = init_restart_lance(lp); if (!status && lp->auto_select) { - /* - * Build a fake network packet and send it to ourselfs. - */ - volatile struct lance_init_block *ib = lp->init_block; - volatile unsigned long flush; - unsigned char packet[ETH_ZLEN]; - struct ethhdr *eth = (struct ethhdr *)packet; - int i, entry; - - memset(packet, 0, ETH_ZLEN); - for (i = 0; i < 6; i++) { - eth->h_dest[i] = dev->dev_addr[i]; - eth->h_source[i] = dev->dev_addr[i]; - } - - entry = lp->tx_new & TX_RING_MOD_MASK; - ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000; - ib->btx_ring[entry].misc = 0; - - memcpy((char *)&ib->tx_buf[entry][0], packet, ETH_ZLEN); - ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); - lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; - - ll->rdp = LE_C0_INEA | LE_C0_TDMD; - flush = ll->rdp; + build_fake_packet(lp); + sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP); } if (!status) @@ -744,74 +969,162 @@ return status; } -static int lance_close (struct net_device *dev) +static int lance_close(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; - volatile struct lance_regs *ll = lp->ll; dev->start = 0; dev->tbusy = 1; del_timer(&lp->multicast_timer); - /* Stop the card */ - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; + STOP_LANCE(lp); - free_irq (dev->irq, (void *) dev); + free_irq(dev->irq, (void *) dev); MOD_DEC_USE_COUNT; return 0; } -static inline int lance_reset (struct net_device *dev) +static int lance_reset(struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; - volatile struct lance_regs *ll = lp->ll; + struct lance_private *lp = (struct lance_private *) dev->priv; int status; - /* Stop the lance */ - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; + STOP_LANCE(lp); /* On the 4m, reset the dma too */ - if (lp->ledma) { - printk ("resetting ledma\n"); - lp->ledma->regs->cond_reg |= DMA_RST_ENET; - udelay (200); - lp->ledma->regs->cond_reg &= ~DMA_RST_ENET; - lp->ledma->regs->dma_test = ((__u32) lp->init_block_dvma) & 0xff000000; + if (lp->dregs) { + u32 csr, addr; + + printk(KERN_ERR "resetting ledma\n"); + csr = sbus_readl(lp->dregs + DMA_CSR); + sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); + udelay(200); + sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR); + + addr = lp->init_block_dvma & 0xff000000; + sbus_writel(addr, lp->dregs + DMA_TEST); } - lance_init_ring (dev); - load_csrs (lp); + lp->init_ring(dev); + load_csrs(lp); dev->trans_start = jiffies; dev->interrupt = 0; dev->start = 1; dev->tbusy = 0; - status = init_restart_lance (lp); -#ifdef DEBUG_DRIVER - printk ("Lance restart=%d\n", status); -#endif + status = init_restart_lance(lp); return status; } -static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) +static void lance_piocopy_from_skb(volatile void *dest, char *src, int len) { - struct lance_private *lp = (struct lance_private *)dev->priv; - volatile struct lance_regs *ll = lp->ll; + unsigned long piobuf = (unsigned long) dest; + u32 *p32; + u16 *p16; + u8 *p8; + + switch ((unsigned long)src & 0x3) { + case 0: + p32 = (u32 *) src; + while (len >= 4) { + sbus_writel(*p32, piobuf); + p32++; + piobuf += 4; + len -= 4; + } + src = (char *) p32; + break; + case 1: + case 3: + p8 = (u8 *) src; + while (len >= 4) { + u32 val; + + val = p8[0] << 24; + val |= p8[1] << 16; + val |= p8[2] << 8; + val |= p8[3]; + sbus_writel(val, piobuf); + p8 += 4; + piobuf += 4; + len -= 4; + } + src = (char *) p8; + break; + case 2: + p16 = (u16 *) src; + while (len >= 4) { + u32 val = p16[0]<<16 | p16[1]; + sbus_writel(val, piobuf); + p16 += 2; + piobuf += 4; + len -= 4; + } + src = (char *) p16; + break; + }; + if (len >= 2) { + u16 val = src[0] << 8 | src[1]; + sbus_writew(val, piobuf); + src += 2; + piobuf += 2; + len -= 2; + } + if (len >= 1) + sbus_writeb(src[0], piobuf); +} + +static void lance_piozero(volatile void *dest, int len) +{ + unsigned long piobuf = (unsigned long) dest; + + if (piobuf & 1) { + sbus_writeb(0, piobuf); + piobuf += 1; + len -= 1; + if (len == 0) + return; + } + if (len == 1) { + sbus_writeb(0, piobuf); + return; + } + if (piobuf & 2) { + sbus_writew(0, piobuf); + piobuf += 2; + len -= 2; + if (len == 0) + return; + } + while (len >= 4) { + sbus_writel(0, piobuf); + piobuf += 4; + len -= 4; + } + if (len >= 2) { + sbus_writew(0, piobuf); + piobuf += 2; + len -= 2; + } + if (len >= 1) + sbus_writeb(0, piobuf); +} + +static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; - volatile unsigned long flush; unsigned long flags; int entry, skblen, len; - if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) { + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 100) return 1; - printk ("%s: transmit timed out, status %04x, reset\n", - dev->name, ll->rdp); + printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n", + dev->name, sbus_readw(lp->lregs + RDP)); lp->stats.tx_errors++; - lance_reset (dev); + lance_reset(dev); return 1; } @@ -830,38 +1143,43 @@ lp->stats.tx_bytes += len; entry = lp->tx_new & TX_RING_MOD_MASK; - ib->btx_ring [entry].length = (-len) | 0xf000; - ib->btx_ring [entry].misc = 0; - - memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen); + if (lp->pio_buffer) { + sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length); + sbus_writew(0, &ib->btx_ring[entry].misc); + lance_piocopy_from_skb(&ib->tx_buf[entry][0], skb->data, skblen); + if (len != skblen) + lance_piozero(&ib->tx_buf[entry][skblen], len - skblen); + sbus_writeb(LE_T1_POK | LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits); + } else { + ib->btx_ring [entry].length = (-len) | 0xf000; + ib->btx_ring [entry].misc = 0; + memcpy((char *)&ib->tx_buf [entry][0], skb->data, skblen); + if (len != skblen) + memset((char *) &ib->tx_buf [entry][skblen], 0, len - skblen); + ib->btx_ring [entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); + } - /* Clear the slack of the packet, do I need this? */ - /* For a firewall its a good idea - AC */ - if (len != skblen) - memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen); - - /* Now, give the packet to the lance */ - ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); - lp->tx_new = (lp->tx_new+1) & TX_RING_MOD_MASK; + lp->tx_new = TX_NEXT(entry); /* Kick the lance: transmit now */ - ll->rdp = LE_C0_INEA | LE_C0_TDMD; + sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP); dev->trans_start = jiffies; - dev_kfree_skb (skb); + dev_kfree_skb(skb); if (TX_BUFFS_AVAIL) dev->tbusy = 0; /* Read back CSR to invalidate the E-Cache. - * This is needed, because DMA_DSBL_WR_INV is set. */ - if (lp->ledma) - flush = ll->rdp; + * This is needed, because DMA_DSBL_WR_INV is set. + */ + if (lp->dregs) + sbus_readw(lp->lregs + RDP); restore_flags(flags); return 0; } -static struct net_device_stats *lance_get_stats (struct net_device *dev) +static struct net_device_stats *lance_get_stats(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; @@ -869,25 +1187,35 @@ } /* taken from the depca driver */ -static void lance_load_multicast (struct net_device *dev) +static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; - volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi=dev->mc_list; + volatile u16 *mcast_table = (u16 *) &ib->filter; + struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i, j, bit, byte; u32 crc, poly = CRC_POLYNOMIAL_LE; /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { - ib->filter [0] = 0xffffffff; - ib->filter [1] = 0xffffffff; + if (lp->pio_buffer) { + sbus_writel(0xffffffff, &ib->filter[0]); + sbus_writel(0xffffffff, &ib->filter[1]); + } else { + ib->filter [0] = 0xffffffff; + ib->filter [1] = 0xffffffff; + } return; } /* clear the multicast filter */ - ib->filter [0] = 0; - ib->filter [1] = 0; + if (lp->pio_buffer) { + sbus_writel(0, &ib->filter[0]); + sbus_writel(0, &ib->filter[1]); + } else { + ib->filter [0] = 0; + ib->filter [1] = 0; + } /* Add addresses */ for (i = 0; i < dev->mc_count; i++) { @@ -911,37 +1239,29 @@ } } crc = crc >> 26; - mcast_table [crc >> 4] |= 1 << (crc & 0xf); + if (lp->pio_buffer) { + u16 tmp = sbus_readw(&mcast_table[crc>>4]); + tmp |= 1 << (crc & 0xf); + sbus_writew(tmp, &mcast_table[crc>>4]); + } else { + mcast_table [crc >> 4] |= 1 << (crc & 0xf); + } } } -static void lance_set_multicast (struct net_device *dev) +static void lance_set_multicast(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; - volatile struct lance_regs *ll = lp->ll; + u16 mode; if (!dev->start) return; - if (dev->tbusy) { + if (test_and_set_bit(0, (void *)&dev->tbusy)) { mod_timer(&lp->multicast_timer, jiffies + 2); return; } - /* This CANNOT be correct. Chip is running - and dev->tbusy may change any moment. - It is useless to set it. - - Generally, usage of dev->tbusy in this driver is completely - wrong. - - I protected calls to this function - with start_bh_atomic, so that set_multicast_list - and hard_start_xmit are serialized now by top level. --ANK - - The same is true about a2065. - */ - set_bit (0, (void *) &dev->tbusy); if (lp->tx_old != lp->tx_new) { mod_timer(&lp->multicast_timer, jiffies + 4); @@ -949,93 +1269,130 @@ return; } - ll->rap = LE_CSR0; - ll->rdp = LE_C0_STOP; - lance_init_ring (dev); + STOP_LANCE(lp); + lp->init_ring(dev); + if (lp->pio_buffer) + mode = sbus_readw(&ib->mode); + else + mode = ib->mode; if (dev->flags & IFF_PROMISC) { - ib->mode |= LE_MO_PROM; + mode |= LE_MO_PROM; + if (lp->pio_buffer) + sbus_writew(mode, &ib->mode); + else + ib->mode = mode; } else { - ib->mode &= ~LE_MO_PROM; - lance_load_multicast (dev); + mode &= ~LE_MO_PROM; + if (lp->pio_buffer) + sbus_writew(mode, &ib->mode); + else + ib->mode = mode; + lance_load_multicast(dev); } - load_csrs (lp); - init_restart_lance (lp); + load_csrs(lp); + init_restart_lance(lp); dev->tbusy = 0; mark_bh(NET_BH); } -static int __init -sparc_lance_init (struct net_device *dev, struct linux_sbus_device *sdev, - struct Linux_SBus_DMA *ledma, - struct linux_sbus_device *lebuffer) +static void lance_free_hwresources(struct lance_private *lp) +{ + if (lp->lregs) + sbus_iounmap(lp->lregs, LANCE_REG_SIZE); + if (lp->init_block != NULL) { + if (lp->pio_buffer) { + sbus_iounmap((unsigned long)lp->init_block, + sizeof(struct lance_init_block)); + } else { + sbus_free_consistant(lp->sdev, + sizeof(struct lance_init_block), + (void *)lp->init_block, + lp->init_block_dvma); + } + } +} + +static int __init sparc_lance_init(struct net_device *dev, + struct sbus_dev *sdev, + struct sbus_dma *ledma, + struct sbus_dev *lebuffer) { static unsigned version_printed = 0; + struct lance_private *lp = NULL; int i; - struct lance_private *lp; - volatile struct lance_regs *ll; if (dev == NULL) { dev = init_etherdev (0, sizeof (struct lance_private) + 8); } else { - dev->priv = kmalloc (sizeof (struct lance_private) + 8, - GFP_KERNEL); + dev->priv = kmalloc(sizeof (struct lance_private) + 8, + GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof (struct lance_private) + 8); } if (sparc_lance_debug && version_printed++ == 0) - printk (version); + printk (KERN_INFO "%s", version); + + printk(KERN_INFO "%s: LANCE ", dev->name); - printk ("%s: LANCE ", dev->name); - /* Fill the dev fields */ - dev->base_addr = (long) sdev; + /* Make certain the data structures used by the LANCE are aligned. */ + dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7); + lp = (struct lance_private *) dev->priv; /* Copy the IDPROM ethernet address to the device structure, later we * will copy the address in the device structure to the lance * initialization block. */ for (i = 0; i < 6; i++) - printk ("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], - i == 5 ? ' ': ':'); + printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], + i == 5 ? ' ': ':'); printk("\n"); /* Get the IO region */ - prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0], - sdev->num_registers, sdev); - ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, - sizeof (struct lance_regs), lancestr, - sdev->reg_addrs[0].which_io, 0x0); + lp->lregs = sbus_ioremap(&sdev->resource[0], 0, + LANCE_REG_SIZE, lancestr); + if (lp->lregs == 0UL) { + printk(KERN_ERR "%s: Cannot map SunLance registers.\n", + dev->name); + goto fail; + } - /* Make certain the data structures used by the LANCE are aligned. */ - dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7); - lp = (struct lance_private *) dev->priv; - lp->sbus = sdev->my_bus; - if (lebuffer){ - prom_apply_sbus_ranges (lebuffer->my_bus, - &lebuffer->reg_addrs [0], - lebuffer->num_registers, - lebuffer); - - lp->init_block = (void *) - sparc_alloc_io (lebuffer->reg_addrs [0].phys_addr, 0, - sizeof (struct lance_init_block), "lebuffer", - lebuffer->reg_addrs [0].which_io, 0); + lp->sdev = sdev; + if (lebuffer) { + lp->init_block = (volatile struct lance_init_block *) + sbus_ioremap(&lebuffer->resource[0], 0, + sizeof(struct lance_init_block), "lebuffer"); + if (lp->init_block == NULL) { + printk(KERN_ERR "%s: Cannot map SunLance PIO buffer.\n", + dev->name); + goto fail; + } lp->init_block_dvma = 0; - lp->pio_buffer = 1; + lp->init_ring = lance_init_ring_pio; + lp->rx = lance_rx_pio; + lp->tx = lance_tx_pio; } else { - lp->init_block = (void *) - sparc_dvma_malloc (sizeof (struct lance_init_block), - lancedma, &lp->init_block_dvma); + lp->init_block = (volatile struct lance_init_block *) + sbus_alloc_consistant(sdev, sizeof(struct lance_init_block), + &lp->init_block_dvma); + if (lp->init_block == NULL || + lp->init_block_dvma == 0) { + printk(KERN_ERR "%s: Cannot allocate consistant DMA memory.\n", + dev->name); + goto fail; + } lp->pio_buffer = 0; + lp->init_ring = lance_init_ring_dvma; + lp->rx = lance_rx_dvma; + lp->tx = lance_tx_dvma; } lp->busmaster_regval = prom_getintdefault(sdev->prom_node, "busmaster-regval", (LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON)); - lp->ll = ll; lp->name = lancestr; lp->ledma = ledma; @@ -1043,24 +1400,25 @@ if (lp->ledma) { char prop[6]; unsigned int sbmask; + u32 csr; /* Find burst-size property for ledma */ - lp->burst_sizes = prom_getintdefault(ledma->SBus_dev->prom_node, + lp->burst_sizes = prom_getintdefault(ledma->sdev->prom_node, "burst-sizes", 0); /* ledma may be capable of fast bursts, but sbus may not. */ - sbmask = prom_getintdefault(ledma->SBus_dev->my_bus->prom_node, + sbmask = prom_getintdefault(ledma->sdev->bus->prom_node, "burst-sizes", DMA_BURSTBITS); lp->burst_sizes &= sbmask; /* Get the cable-selection property */ memset(prop, 0, sizeof(prop)); - prom_getstring(ledma->SBus_dev->prom_node, "cable-selection", + prom_getstring(ledma->sdev->prom_node, "cable-selection", prop, sizeof(prop)); if (prop[0] == 0) { int topnd, nd; - printk("%s: using auto-carrier-detection.\n", + printk(KERN_INFO "%s: using auto-carrier-detection.\n", dev->name); /* Is this found at /options .attributes in all @@ -1080,9 +1438,9 @@ sizeof(prop)); if (strcmp(prop, "true")) { - printk("%s: warning: overriding option " + printk(KERN_NOTICE "%s: warning: overriding option " "'tpe-link-test?'\n", dev->name); - printk("%s: warning: mail any problems " + printk(KERN_NOTICE "%s: warning: mail any problems " "to ecd@skynet.be\n", dev->name); set_auxio(AUXIO_LINK_TEST, 0); } @@ -1097,17 +1455,21 @@ lp->tpe = 1; } + lp->dregs = ledma->regs; + /* Reset ledma */ - lp->ledma->regs->cond_reg |= DMA_RST_ENET; - udelay (200); - lp->ledma->regs->cond_reg &= ~DMA_RST_ENET; - } + csr = sbus_readl(lp->dregs + DMA_CSR); + sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); + udelay(200); + sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR); + } else + lp->dregs = 0; /* This should never happen. */ if ((unsigned long)(lp->init_block->brx_ring) & 0x07) { - printk("%s: ERROR: Rx and Tx rings not on even boundary.\n", + printk(KERN_ERR "%s: ERROR: Rx and Tx rings not on even boundary.\n", dev->name); - return ENODEV; + goto fail; } lp->dev = dev; @@ -1120,7 +1482,7 @@ dev->irq = sdev->irqs[0]; dev->dma = 0; - ether_setup (dev); + ether_setup(dev); /* We cannot sleep if the chip is busy during a * multicast list update event, because such events @@ -1138,18 +1500,23 @@ root_lance_dev = lp; #endif return 0; + +fail: + if (lp != NULL) + lance_free_hwresources(lp); + return ENODEV; } /* On 4m, find the associated dma for the lance chip */ -static inline struct Linux_SBus_DMA * -find_ledma (struct linux_sbus_device *dev) +static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev) { - struct Linux_SBus_DMA *p; + struct sbus_dma *p; - for_each_dvma(p) - if (p->SBus_dev == dev) + for_each_dvma(p) { + if (p->sdev == sdev) return p; - return 0; + } + return NULL; } #ifdef CONFIG_SUN4 @@ -1159,16 +1526,16 @@ /* Find all the lance cards on the system and initialize them */ int __init sparc_lance_probe(void) { - static struct linux_sbus_device sdev; + static struct sbus_dev sdev; static int called = 0; - if(called) + if (called) return ENODEV; called++; if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset (&sdev, 0, sizeof(sdev)); + memset(&sdev, 0, sizeof(sdev)); sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; sdev.irqs[0] = 6; return sparc_lance_init(NULL, &sdev, 0, 0); @@ -1179,37 +1546,38 @@ #else /* !CONFIG_SUN4 */ /* Find all the lance cards on the system and initialize them */ -int __init sparc_lance_probe (void) +int __init sparc_lance_probe(void) { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *bus; + struct sbus_dev *sdev = 0; struct net_device *dev = NULL; - struct Linux_SBus_DMA *ledma = 0; + struct sbus_dma *ledma = 0; static int called = 0; int cards = 0, v; - if(called) + if (called) return ENODEV; called++; for_each_sbus (bus) { for_each_sbusdev (sdev, bus) { - if (cards) dev = NULL; - if (strcmp (sdev->prom_name, "le") == 0) { + if (cards) + dev = NULL; + if (strcmp(sdev->prom_name, "le") == 0) { cards++; if ((v = sparc_lance_init(dev, sdev, 0, 0))) return v; continue; } - if (strcmp (sdev->prom_name, "ledma") == 0) { + if (strcmp(sdev->prom_name, "ledma") == 0) { cards++; - ledma = find_ledma (sdev); + ledma = find_ledma(sdev); if ((v = sparc_lance_init(dev, sdev->child, ledma, 0))) return v; continue; } - if (strcmp (sdev->prom_name, "lebuffer") == 0){ + if (strcmp(sdev->prom_name, "lebuffer") == 0){ cards++; if ((v = sparc_lance_init(dev, sdev->child, 0, sdev))) @@ -1242,6 +1610,7 @@ lp = root_lance_dev->next_module; unregister_netdev(root_lance_dev->dev); + lance_free_hwresources(root_lance_dev); kfree(root_lance_dev->dev); root_lance_dev = lp; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c --- v2.3.34/linux/drivers/net/sunqe.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/net/sunqe.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,5 @@ -/* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. +/* $Id: sunqe.c,v 1.40 1999/12/15 14:08:13 davem Exp $ + * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver. * Once again I am out to prove that every ethernet * controller out there can be most efficiently programmed * if you make it look like a LANCE. @@ -7,7 +8,7 @@ */ static char *version = - "sunqe.c:v2.0 9/9/99 David S. Miller (davem@redhat.com)\n"; + "sunqe.c:v2.9 9/11/99 David S. Miller (davem@redhat.com)\n"; #include @@ -53,21 +54,22 @@ #define QEC_RESET_TRIES 200 -static inline int qec_global_reset(struct qe_globreg *gregs) +static inline int qec_global_reset(unsigned long gregs) { int tries = QEC_RESET_TRIES; - gregs->ctrl = GLOB_CTRL_RESET; - while(--tries) { - if(gregs->ctrl & GLOB_CTRL_RESET) { + sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL); + while (--tries) { + u32 tmp = sbus_readl(gregs + GLOB_CTRL); + if (tmp & GLOB_CTRL_RESET) { udelay(20); continue; } break; } - if(tries) + if (tries) return 0; - printk("QuadEther: AIEEE cannot reset the QEC!\n"); + printk(KERN_ERR "QuadEther: AIEEE cannot reset the QEC!\n"); return -1; } @@ -76,36 +78,38 @@ static inline int qe_stop(struct sunqe *qep) { - struct qe_creg *cregs = qep->qcregs; - struct qe_mregs *mregs = qep->mregs; + unsigned long cregs = qep->qcregs; + unsigned long mregs = qep->mregs; int tries; /* Reset the MACE, then the QEC channel. */ - mregs->bconfig = MREGS_BCONFIG_RESET; + sbus_writeb(MREGS_BCONFIG_RESET, mregs + MREGS_BCONFIG); tries = MACE_RESET_RETRIES; - while(--tries) { - if(mregs->bconfig & MREGS_BCONFIG_RESET) { + while (--tries) { + u8 tmp = sbus_readb(mregs + MREGS_BCONFIG); + if (tmp & MREGS_BCONFIG_RESET) { udelay(20); continue; } break; } - if(!tries) { - printk("QuadEther: AIEEE cannot reset the MACE!\n"); + if (!tries) { + printk(KERN_ERR "QuadEther: AIEEE cannot reset the MACE!\n"); return -1; } - cregs->ctrl = CREG_CTRL_RESET; + sbus_writel(CREG_CTRL_RESET, cregs + CREG_CTRL); tries = QE_RESET_RETRIES; - while(--tries) { - if(cregs->ctrl & CREG_CTRL_RESET) { + while (--tries) { + u32 tmp = sbus_readl(cregs + CREG_CTRL); + if (tmp & CREG_CTRL_RESET) { udelay(20); continue; } break; } - if(!tries) { - printk("QuadEther: Cannot reset QE channel!\n"); + if (!tries) { + printk(KERN_ERR "QuadEther: Cannot reset QE channel!\n"); return -1; } return 0; @@ -121,7 +125,7 @@ qep->rx_new = qep->rx_old = qep->tx_new = qep->tx_old = 0; memset(qb, 0, sizeof(struct qe_init_block)); memset(qbufs, 0, sizeof(struct sunqe_buffers)); - for(i = 0; i < RX_RING_SIZE; i++) { + for (i = 0; i < RX_RING_SIZE; i++) { qb->qe_rxd[i].rx_addr = qbufs_dvma + qebuf_offset(rx_buf, i); qb->qe_rxd[i].rx_flags = (RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH)); @@ -131,99 +135,110 @@ static int qe_init(struct sunqe *qep, int from_irq) { struct sunqec *qecp = qep->parent; - struct qe_creg *cregs = qep->qcregs; - struct qe_mregs *mregs = qep->mregs; - struct qe_globreg *gregs = qecp->gregs; + unsigned long cregs = qep->qcregs; + unsigned long mregs = qep->mregs; + unsigned long gregs = qecp->gregs; unsigned char *e = &qep->dev->dev_addr[0]; - volatile unsigned char garbage; + u32 tmp; int i; /* Shut it up. */ - if(qe_stop(qep)) + if (qe_stop(qep)) return -EAGAIN; /* Setup initial rx/tx init block pointers. */ - cregs->rxds = qep->qblock_dvma + qib_offset(qe_rxd, 0); - cregs->txds = qep->qblock_dvma + qib_offset(qe_txd, 0); + sbus_writel(qep->qblock_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS); + sbus_writel(qep->qblock_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS); /* Enable/mask the various irq's. */ - cregs->rimask = 0; - cregs->timask = 1; + sbus_writel(0, cregs + CREG_RIMASK); + sbus_writel(1, cregs + CREG_TIMASK); - cregs->qmask = 0; - cregs->mmask = CREG_MMASK_RXCOLL; + sbus_writel(0, cregs + CREG_QMASK); + sbus_writel(CREG_MMASK_RXCOLL, cregs + CREG_MMASK); /* Setup the FIFO pointers into QEC local memory. */ - cregs->rxwbufptr = cregs->rxrbufptr = qep->channel * gregs->msize; - cregs->txwbufptr = cregs->txrbufptr = cregs->rxrbufptr + gregs->rsize; + tmp = qep->channel * sbus_readl(gregs + GLOB_MSIZE); + sbus_writel(tmp, cregs + CREG_RXRBUFPTR); + sbus_writel(tmp, cregs + CREG_RXWBUFPTR); + + tmp = sbus_readl(cregs + CREG_RXRBUFPTR) + + sbus_readl(gregs + GLOB_RSIZE); + sbus_writel(tmp, cregs + CREG_TXRBUFPTR); + sbus_writel(tmp, cregs + CREG_TXWBUFPTR); /* Clear the channel collision counter. */ - cregs->ccnt = 0; + sbus_writel(0, cregs + CREG_CCNT); /* For 10baseT, inter frame space nor throttle seems to be necessary. */ - cregs->pipg = 0; + sbus_writel(0, cregs + CREG_PIPG); /* Now dork with the AMD MACE. */ - mregs->phyconfig = MREGS_PHYCONFIG_AUTO; - mregs->txfcntl = MREGS_TXFCNTL_AUTOPAD; /* Save us some tx work. */ - mregs->rxfcntl = 0; + sbus_writeb(MREGS_PHYCONFIG_AUTO, mregs + MREGS_PHYCONFIG); + sbus_writeb(MREGS_TXFCNTL_AUTOPAD, mregs + MREGS_TXFCNTL); + sbus_writeb(0, mregs + MREGS_RXFCNTL); /* The QEC dma's the rx'd packets from local memory out to main memory, * and therefore it interrupts when the packet reception is "complete". * So don't listen for the MACE talking about it. */ - mregs->imask = (MREGS_IMASK_COLL | MREGS_IMASK_RXIRQ); - - mregs->bconfig = (MREGS_BCONFIG_BSWAP | MREGS_BCONFIG_64TS); - mregs->fconfig = (MREGS_FCONFIG_TXF16 | MREGS_FCONFIG_RXF32 | - MREGS_FCONFIG_RFWU | MREGS_FCONFIG_TFWU); + sbus_writeb(MREGS_IMASK_COLL | MREGS_IMASK_RXIRQ, mregs + MREGS_IMASK); + sbus_writeb(MREGS_BCONFIG_BSWAP | MREGS_BCONFIG_64TS, mregs + MREGS_BCONFIG); + sbus_writeb((MREGS_FCONFIG_TXF16 | MREGS_FCONFIG_RXF32 | + MREGS_FCONFIG_RFWU | MREGS_FCONFIG_TFWU), + mregs + MREGS_FCONFIG); /* Only usable interface on QuadEther is twisted pair. */ - mregs->plsconfig = (MREGS_PLSCONFIG_TP); + sbus_writeb(MREGS_PLSCONFIG_TP, mregs + MREGS_PLSCONFIG); /* Tell MACE we are changing the ether address. */ - mregs->iaconfig = (MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_PARESET); - while ((mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0) + sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_PARESET, + mregs + MREGS_IACONFIG); + while ((sbus_readb(mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0) barrier(); - mregs->ethaddr = e[0]; - mregs->ethaddr = e[1]; - mregs->ethaddr = e[2]; - mregs->ethaddr = e[3]; - mregs->ethaddr = e[4]; - mregs->ethaddr = e[5]; + sbus_writeb(e[0], mregs + MREGS_ETHADDR); + sbus_writeb(e[1], mregs + MREGS_ETHADDR); + sbus_writeb(e[2], mregs + MREGS_ETHADDR); + sbus_writeb(e[3], mregs + MREGS_ETHADDR); + sbus_writeb(e[4], mregs + MREGS_ETHADDR); + sbus_writeb(e[5], mregs + MREGS_ETHADDR); /* Clear out the address filter. */ - mregs->iaconfig = (MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET); - while ((mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0) + sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET, + mregs + MREGS_IACONFIG); + while ((sbus_readb(mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0) barrier(); - for(i = 0; i < 8; i++) - mregs->filter = 0; + for (i = 0; i < 8; i++) + sbus_writeb(0, mregs + MREGS_FILTER); /* Address changes are now complete. */ - mregs->iaconfig = 0; + sbus_writeb(0, mregs + MREGS_IACONFIG); qe_init_rings(qep); /* Wait a little bit for the link to come up... */ mdelay(5); - if(!(mregs->phyconfig & MREGS_PHYCONFIG_LTESTDIS)) { + if (!(sbus_readb(mregs + MREGS_PHYCONFIG) & MREGS_PHYCONFIG_LTESTDIS)) { int tries = 50; while (tries--) { + u8 tmp; + mdelay(5); barrier(); - if((mregs->phyconfig & MREGS_PHYCONFIG_LSTAT) != 0) + tmp = sbus_readb(mregs + MREGS_PHYCONFIG); + if ((tmp & MREGS_PHYCONFIG_LSTAT) != 0) break; } if (tries == 0) - printk("%s: Warning, link state is down.\n", qep->dev->name); + printk(KERN_NOTICE "%s: Warning, link state is down.\n", qep->dev->name); } /* Missed packet counter is cleared on a read. */ - garbage = mregs->mpcnt; + sbus_readb(mregs + MREGS_MPCNT); /* Reload multicast information, this will enable the receiver - * and transmitter. But set the base mconfig value right now. + * and transmitter. */ qe_set_multicast(qep->dev); @@ -234,152 +249,152 @@ /* Grrr, certain error conditions completely lock up the AMD MACE, * so when we get these we _must_ reset the chip. */ -static int qe_is_bolixed(struct sunqe *qep, unsigned int qe_status) +static int qe_is_bolixed(struct sunqe *qep, u32 qe_status) { struct net_device *dev = qep->dev; int mace_hwbug_workaround = 0; - if(qe_status & CREG_STAT_EDEFER) { - printk("%s: Excessive transmit defers.\n", dev->name); + if (qe_status & CREG_STAT_EDEFER) { + printk(KERN_ERR "%s: Excessive transmit defers.\n", dev->name); qep->net_stats.tx_errors++; } - if(qe_status & CREG_STAT_CLOSS) { - printk("%s: Carrier lost, link down?\n", dev->name); + if (qe_status & CREG_STAT_CLOSS) { + printk(KERN_ERR "%s: Carrier lost, link down?\n", dev->name); qep->net_stats.tx_errors++; qep->net_stats.tx_carrier_errors++; } - if(qe_status & CREG_STAT_ERETRIES) { - printk("%s: Excessive transmit retries (more than 16).\n", dev->name); + if (qe_status & CREG_STAT_ERETRIES) { + printk(KERN_ERR "%s: Excessive transmit retries (more than 16).\n", dev->name); qep->net_stats.tx_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_LCOLL) { - printk("%s: Late transmit collision.\n", dev->name); + if (qe_status & CREG_STAT_LCOLL) { + printk(KERN_ERR "%s: Late transmit collision.\n", dev->name); qep->net_stats.tx_errors++; qep->net_stats.collisions++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_FUFLOW) { - printk("%s: Transmit fifo underflow, driver bug.\n", dev->name); + if (qe_status & CREG_STAT_FUFLOW) { + printk(KERN_ERR "%s: Transmit fifo underflow, driver bug.\n", dev->name); qep->net_stats.tx_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_JERROR) { - printk("%s: Jabber error.\n", dev->name); + if (qe_status & CREG_STAT_JERROR) { + printk(KERN_ERR "%s: Jabber error.\n", dev->name); } - if(qe_status & CREG_STAT_BERROR) { - printk("%s: Babble error.\n", dev->name); + if (qe_status & CREG_STAT_BERROR) { + printk(KERN_ERR "%s: Babble error.\n", dev->name); } - if(qe_status & CREG_STAT_CCOFLOW) { + if (qe_status & CREG_STAT_CCOFLOW) { qep->net_stats.tx_errors += 256; qep->net_stats.collisions += 256; } - if(qe_status & CREG_STAT_TXDERROR) { - printk("%s: Transmit descriptor is bogus, driver bug.\n", dev->name); + if (qe_status & CREG_STAT_TXDERROR) { + printk(KERN_ERR "%s: Transmit descriptor is bogus, driver bug.\n", dev->name); qep->net_stats.tx_errors++; qep->net_stats.tx_aborted_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_TXLERR) { - printk("%s: Transmit late error.\n", dev->name); + if (qe_status & CREG_STAT_TXLERR) { + printk(KERN_ERR "%s: Transmit late error.\n", dev->name); qep->net_stats.tx_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_TXPERR) { - printk("%s: Transmit DMA parity error.\n", dev->name); + if (qe_status & CREG_STAT_TXPERR) { + printk(KERN_ERR "%s: Transmit DMA parity error.\n", dev->name); qep->net_stats.tx_errors++; qep->net_stats.tx_aborted_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_TXSERR) { - printk("%s: Transmit DMA sbus error ack.\n", dev->name); + if (qe_status & CREG_STAT_TXSERR) { + printk(KERN_ERR "%s: Transmit DMA sbus error ack.\n", dev->name); qep->net_stats.tx_errors++; qep->net_stats.tx_aborted_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_RCCOFLOW) { + if (qe_status & CREG_STAT_RCCOFLOW) { qep->net_stats.rx_errors += 256; qep->net_stats.collisions += 256; } - if(qe_status & CREG_STAT_RUOFLOW) { + if (qe_status & CREG_STAT_RUOFLOW) { qep->net_stats.rx_errors += 256; qep->net_stats.rx_over_errors += 256; } - if(qe_status & CREG_STAT_MCOFLOW) { + if (qe_status & CREG_STAT_MCOFLOW) { qep->net_stats.rx_errors += 256; qep->net_stats.rx_missed_errors += 256; } - if(qe_status & CREG_STAT_RXFOFLOW) { - printk("%s: Receive fifo overflow.\n", dev->name); + if (qe_status & CREG_STAT_RXFOFLOW) { + printk(KERN_ERR "%s: Receive fifo overflow.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.rx_over_errors++; } - if(qe_status & CREG_STAT_RLCOLL) { - printk("%s: Late receive collision.\n", dev->name); + if (qe_status & CREG_STAT_RLCOLL) { + printk(KERN_ERR "%s: Late receive collision.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.collisions++; } - if(qe_status & CREG_STAT_FCOFLOW) { + if (qe_status & CREG_STAT_FCOFLOW) { qep->net_stats.rx_errors += 256; qep->net_stats.rx_frame_errors += 256; } - if(qe_status & CREG_STAT_CECOFLOW) { + if (qe_status & CREG_STAT_CECOFLOW) { qep->net_stats.rx_errors += 256; qep->net_stats.rx_crc_errors += 256; } - if(qe_status & CREG_STAT_RXDROP) { - printk("%s: Receive packet dropped.\n", dev->name); + if (qe_status & CREG_STAT_RXDROP) { + printk(KERN_ERR "%s: Receive packet dropped.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.rx_dropped++; qep->net_stats.rx_missed_errors++; } - if(qe_status & CREG_STAT_RXSMALL) { - printk("%s: Receive buffer too small, driver bug.\n", dev->name); + if (qe_status & CREG_STAT_RXSMALL) { + printk(KERN_ERR "%s: Receive buffer too small, driver bug.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.rx_length_errors++; } - if(qe_status & CREG_STAT_RXLERR) { - printk("%s: Receive late error.\n", dev->name); + if (qe_status & CREG_STAT_RXLERR) { + printk(KERN_ERR "%s: Receive late error.\n", dev->name); qep->net_stats.rx_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_RXPERR) { - printk("%s: Receive DMA parity error.\n", dev->name); + if (qe_status & CREG_STAT_RXPERR) { + printk(KERN_ERR "%s: Receive DMA parity error.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.rx_missed_errors++; mace_hwbug_workaround = 1; } - if(qe_status & CREG_STAT_RXSERR) { - printk("%s: Receive DMA sbus error ack.\n", dev->name); + if (qe_status & CREG_STAT_RXSERR) { + printk(KERN_ERR "%s: Receive DMA sbus error ack.\n", dev->name); qep->net_stats.rx_errors++; qep->net_stats.rx_missed_errors++; mace_hwbug_workaround = 1; } - if(mace_hwbug_workaround) + if (mace_hwbug_workaround) qe_init(qep, 1); return mace_hwbug_workaround; } @@ -394,10 +409,10 @@ struct sunqe_buffers *qbufs = qep->buffers; __u32 qbufs_dvma = qep->buffers_dvma; int elem = qep->rx_new, drops = 0; - unsigned int flags; + u32 flags; this = &rxbase[elem]; - while(!((flags = this->rx_flags) & RXD_OWN)) { + while (!((flags = this->rx_flags) & RXD_OWN)) { struct sk_buff *skb; unsigned char *this_qbuf = &qbufs->rx_buf[elem & (RX_RING_SIZE - 1)][0]; @@ -408,25 +423,25 @@ int len = (flags & RXD_LENGTH) - 4; /* QE adds ether FCS size to len */ /* Check for errors. */ - if(len < ETH_ZLEN) { + if (len < ETH_ZLEN) { qep->net_stats.rx_errors++; qep->net_stats.rx_length_errors++; qep->net_stats.rx_dropped++; } else { skb = dev_alloc_skb(len + 2); - if(skb == 0) { + if (skb == NULL) { drops++; qep->net_stats.rx_dropped++; } else { skb->dev = qep->dev; skb_reserve(skb, 2); skb_put(skb, len); - eth_copy_and_sum(skb, (unsigned char *)this_qbuf, + eth_copy_and_sum(skb, (unsigned char *) this_qbuf, len, 0); skb->protocol = eth_type_trans(skb, qep->dev); netif_rx(skb); qep->net_stats.rx_packets++; - qep->net_stats.rx_bytes+=len; + qep->net_stats.rx_bytes += len; } } end_rxd->rx_addr = this_qbuf_dvma; @@ -436,8 +451,8 @@ this = &rxbase[elem]; } qep->rx_new = elem; - if(drops) - printk("%s: Memory squeeze, deferring packet.\n", qep->dev->name); + if (drops) + printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", qep->dev->name); } /* Interrupts for all QE's get filtered out via the QEC master controller, @@ -447,25 +462,25 @@ static void qec_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct sunqec *qecp = (struct sunqec *) dev_id; - unsigned int qec_status; + u32 qec_status; int channel = 0; /* Latch the status now. */ - qec_status = qecp->gregs->stat; - while(channel < 4) { - if(qec_status & 0xf) { + qec_status = sbus_readl(qecp->gregs + GLOB_STAT); + while (channel < 4) { + if (qec_status & 0xf) { struct sunqe *qep = qecp->qes[channel]; struct net_device *dev = qep->dev; - unsigned int qe_status; + u32 qe_status; dev->interrupt = 1; - qe_status = qep->qcregs->stat; - if(qe_status & CREG_STAT_ERRORS) - if(qe_is_bolixed(qep, qe_status)) + qe_status = sbus_readl(qep->qcregs + CREG_STAT); + if (qe_status & CREG_STAT_ERRORS) { + if (qe_is_bolixed(qep, qe_status)) goto next; - - if(qe_status & CREG_STAT_RXIRQ) + } + if (qe_status & CREG_STAT_RXIRQ) qe_rx(qep); next: dev->interrupt = 0; @@ -484,7 +499,7 @@ MREGS_MCONFIG_RXENAB | MREGS_MCONFIG_MBAENAB); res = qe_init(qep, 0); - if(!res) + if (!res) MOD_INC_USE_COUNT; return res; @@ -506,18 +521,16 @@ struct net_device *dev = qep->dev; int elem = qep->tx_old; - while(elem != qep->tx_new) { - unsigned int flags = txbase[elem].tx_flags; + while (elem != qep->tx_new) { + u32 flags = txbase[elem].tx_flags; if (flags & TXD_OWN) break; - qep->net_stats.tx_packets++; - qep->net_stats.tx_bytes+=(flags & TXD_LENGTH); elem = NEXT_TX(elem); } qep->tx_old = elem; - if(dev->tbusy && (TX_BUFFS_AVAIL(qep) > 0)) { + if (dev->tbusy && (TX_BUFFS_AVAIL(qep) > 0)) { dev->tbusy = 0; mark_bh(NET_BH); } @@ -534,11 +547,11 @@ qe_tx_reclaim(qep); - if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) { + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { long tickssofar = jiffies - dev->trans_start; if (tickssofar >= 40) { - printk("%s: transmit timed out, resetting\n", dev->name); + printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); qe_init(qep, 1); dev->tbusy = 0; dev->trans_start = jiffies; @@ -546,9 +559,6 @@ return 1; } - if(!TX_BUFFS_AVAIL(qep)) - return 1; - len = skb->len; entry = qep->tx_new; @@ -568,11 +578,14 @@ /* Get it going. */ dev->trans_start = jiffies; - qep->qcregs->ctrl = CREG_CTRL_TWAKEUP; + sbus_writel(CREG_CTRL_TWAKEUP, qep->qcregs + CREG_CTRL); + + qep->net_stats.tx_packets++; + qep->net_stats.tx_bytes += len; dev_kfree_skb(skb); - if(TX_BUFFS_AVAIL(qep)) + if (TX_BUFFS_AVAIL(qep)) dev->tbusy = 0; return 0; @@ -592,7 +605,7 @@ { struct sunqe *qep = (struct sunqe *) dev->priv; struct dev_mc_list *dmi = dev->mc_list; - unsigned char new_mconfig = qep->mconfig; + u8 new_mconfig = qep->mconfig; char *addrs; int i, j, bit, byte; u32 crc, poly = CRC_POLYNOMIAL_LE; @@ -600,37 +613,38 @@ /* Lock out others. */ set_bit(0, (void *) &dev->tbusy); - if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { - qep->mregs->iaconfig = MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET; - while ((qep->mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0) + if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET, + qep->mregs + MREGS_IACONFIG); + while ((sbus_readb(qep->mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0) barrier(); - for(i = 0; i < 8; i++) - qep->mregs->filter = 0xff; - qep->mregs->iaconfig = 0; - } else if(dev->flags & IFF_PROMISC) { + for (i = 0; i < 8; i++) + sbus_writeb(0xff, qep->mregs + MREGS_FILTER); + sbus_writeb(0, qep->mregs + MREGS_IACONFIG); + } else if (dev->flags & IFF_PROMISC) { new_mconfig |= MREGS_MCONFIG_PROMISC; } else { u16 hash_table[4]; - unsigned char *hbytes = (unsigned char *) &hash_table[0]; + u8 *hbytes = (unsigned char *) &hash_table[0]; - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < dev->mc_count; i++) { + for (i = 0; i < dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - if(!(*addrs & 1)) + if (!(*addrs & 1)) continue; crc = 0xffffffffU; - for(byte = 0; byte < 6; byte++) { - for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { + for (byte = 0; byte < 6; byte++) { + for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { int test; test = ((bit ^ crc) & 0x01); crc >>= 1; - if(test) + if (test) crc = crc ^ poly; } } @@ -638,12 +652,15 @@ hash_table[crc >> 4] |= 1 << (crc & 0xf); } /* Program the qe with the new filter value. */ - qep->mregs->iaconfig = MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET; - while ((qep->mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0) + sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET, + qep->mregs + MREGS_IACONFIG); + while ((sbus_readb(qep->mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0) barrier(); - for(i = 0; i < 8; i++) - qep->mregs->filter = *hbytes++; - qep->mregs->iaconfig = 0; + for (i = 0; i < 8; i++) { + u8 tmp = *hbytes++; + sbus_writeb(tmp, qep->mregs + MREGS_FILTER); + } + sbus_writeb(0, qep->mregs + MREGS_IACONFIG); } /* Any change of the logical address filter, the physical address, @@ -653,82 +670,80 @@ * me a day or two to find this bug. */ qep->mconfig = new_mconfig; - qep->mregs->mconfig = qep->mconfig; + sbus_writeb(qep->mconfig, qep->mregs + MREGS_MCONFIG); /* Let us get going again. */ dev->tbusy = 0; } /* This is only called once at boot time for each card probed. */ -static inline void qec_init_once(struct sunqec *qecp, struct linux_sbus_device *qsdev) +static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) { - unsigned char bsizes = qecp->qec_bursts; + u8 bsizes = qecp->qec_bursts; -#ifdef __sparc_v9__ - if (bsizes & DMA_BURST64) { - qecp->gregs->ctrl = GLOB_CTRL_B64; - } else -#endif - if(bsizes & DMA_BURST32) { - qecp->gregs->ctrl = GLOB_CTRL_B32; + if (sbus_can_burst64(qsdev) && (bsizes & DMA_BURST64)) { + sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL); + } else if (bsizes & DMA_BURST32) { + sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL); } else { - qecp->gregs->ctrl = GLOB_CTRL_B16; + sbus_writel(GLOB_CTRL_B16, qecp->gregs + GLOB_CTRL); } /* Packetsize only used in 100baseT BigMAC configurations, * set it to zero just to be on the safe side. */ - qecp->gregs->psize = 0; + sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE); /* Set the local memsize register, divided up to one piece per QE channel. */ - qecp->gregs->msize = (qsdev->reg_addrs[1].reg_size >> 2); + sbus_writel((qsdev->reg_addrs[1].reg_size >> 2), + qecp->gregs + GLOB_MSIZE); /* Divide up the local QEC memory amongst the 4 QE receiver and * transmitter FIFOs. Basically it is (total / 2 / num_channels). */ - qecp->gregs->rsize = qecp->gregs->tsize = - (qsdev->reg_addrs[1].reg_size >> 2) >> 1; - + sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, + qecp->gregs + GLOB_TSIZE); + sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, + qecp->gregs + GLOB_RSIZE); } /* Four QE's per QEC card. */ -static inline int qec_ether_init(struct net_device *dev, struct linux_sbus_device *sdev) +static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev) { static unsigned version_printed = 0; struct net_device *qe_devs[4]; struct sunqe *qeps[4]; - struct linux_sbus_device *qesdevs[4]; - struct sunqec *qecp; - struct linux_prom_ranges qranges[8]; - unsigned char bsizes, bsizes_more, num_qranges; + struct sbus_dev *qesdevs[4]; + struct sunqec *qecp = NULL; + u8 bsizes, bsizes_more; int i, j, res = ENOMEM; dev = init_etherdev(0, sizeof(struct sunqe)); qe_devs[0] = dev; qeps[0] = (struct sunqe *) dev->priv; qeps[0]->channel = 0; - for(j = 0; j < 6; j++) + for (j = 0; j < 6; j++) qe_devs[0]->dev_addr[j] = idprom->id_ethaddr[j]; - if(version_printed++ == 0) - printk(version); + if (version_printed++ == 0) + printk(KERN_INFO "%s", version); qe_devs[1] = qe_devs[2] = qe_devs[3] = NULL; - for(i = 1; i < 4; i++) { + for (i = 1; i < 4; i++) { qe_devs[i] = init_etherdev(0, sizeof(struct sunqe)); - if(qe_devs[i] == NULL || qe_devs[i]->priv == NULL) + if (qe_devs[i] == NULL || qe_devs[i]->priv == NULL) goto qec_free_devs; qeps[i] = (struct sunqe *) qe_devs[i]->priv; - for(j = 0; j < 6; j++) + for (j = 0; j < 6; j++) qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j]; qeps[i]->channel = i; } qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL); - if(qecp == NULL) + if (qecp == NULL) goto qec_free_devs; - qecp->qec_sbus_dev = sdev; + qecp->qec_sdev = sdev; - for(i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { qecp->qes[i] = qeps[i]; qeps[i]->dev = qe_devs[i]; qeps[i]->parent = qecp; @@ -736,80 +751,45 @@ /* Link in channel 0. */ i = prom_getintdefault(sdev->child->prom_node, "channel#", -1); - if(i == -1) { res=ENODEV; goto qec_free_devs; } + if (i == -1) { res=ENODEV; goto qec_free_devs; } qesdevs[i] = sdev->child; - qe_devs[i]->base_addr = (long) qesdevs[i]; /* Link in channel 1. */ i = prom_getintdefault(sdev->child->next->prom_node, "channel#", -1); - if(i == -1) { res=ENODEV; goto qec_free_devs; } + if (i == -1) { res=ENODEV; goto qec_free_devs; } qesdevs[i] = sdev->child->next; - qe_devs[i]->base_addr = (long) qesdevs[i]; /* Link in channel 2. */ i = prom_getintdefault(sdev->child->next->next->prom_node, "channel#", -1); - if(i == -1) { res=ENODEV; goto qec_free_devs; } + if (i == -1) { res=ENODEV; goto qec_free_devs; } qesdevs[i] = sdev->child->next->next; - qe_devs[i]->base_addr = (long) qesdevs[i]; /* Link in channel 3. */ i = prom_getintdefault(sdev->child->next->next->next->prom_node, "channel#", -1); - if(i == -1) { res=ENODEV; goto qec_free_devs; } + if (i == -1) { res=ENODEV; goto qec_free_devs; } qesdevs[i] = sdev->child->next->next->next; - qe_devs[i]->base_addr = (long) qesdevs[i]; - for(i = 0; i < 4; i++) - qeps[i]->qe_sbusdev = qesdevs[i]; - - /* This is a bit of fun, get QEC ranges. */ - i = prom_getproperty(sdev->prom_node, "ranges", - (char *) &qranges[0], sizeof(qranges)); - num_qranges = (i / sizeof(struct linux_prom_ranges)); - - /* Now, apply all the ranges, QEC ranges then the SBUS ones for each QE. */ - if (sdev->ranges_applied == 0) { - for(i = 0; i < 4; i++) { - for(j = 0; j < 2; j++) { - int k; - - for(k = 0; k < num_qranges; k++) - if(qesdevs[i]->reg_addrs[j].which_io == - qranges[k].ot_child_space) - break; - if(k >= num_qranges) - printk("QuadEther: Aieee, bogus QEC range for " - "space %08x\n",qesdevs[i]->reg_addrs[j].which_io); - qesdevs[i]->reg_addrs[j].which_io = qranges[k].ot_parent_space; - qesdevs[i]->reg_addrs[j].phys_addr += qranges[k].ot_parent_base; - } - - prom_apply_sbus_ranges(qesdevs[i]->my_bus, &qesdevs[i]->reg_addrs[0], - 2, qesdevs[i]); - } - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); - } + for (i = 0; i < 4; i++) + qeps[i]->qe_sdev = qesdevs[i]; /* Now map in the registers, QEC globals first. */ - qecp->gregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sizeof(struct qe_globreg), - "QEC Global Registers", - sdev->reg_addrs[0].which_io, 0); - if(!qecp->gregs) { - printk("QuadEther: Cannot map QEC global registers.\n"); + qecp->gregs = sbus_ioremap(&sdev->resource[0], 0, + GLOB_REG_SIZE, "QEC Global Registers"); + if (!qecp->gregs) { + printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n"); res = ENODEV; goto qec_free_devs; } /* Make sure the QEC is in MACE mode. */ - if((qecp->gregs->ctrl & 0xf0000000) != GLOB_CTRL_MMODE) { - printk("QuadEther: AIEEE, QEC is not in MACE mode!\n"); + if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) { + printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n"); res = ENODEV; goto qec_free_devs; } /* Reset the QEC. */ - if(qec_global_reset(qecp->gregs)) { + if (qec_global_reset(qecp->gregs)) { res = ENODEV; goto qec_free_devs; } @@ -819,11 +799,11 @@ */ bsizes = prom_getintdefault(sdev->prom_node, "burst-sizes", 0xff); bsizes &= 0xff; - bsizes_more = prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff); + bsizes_more = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff); - if(bsizes_more != 0xff) + if (bsizes_more != 0xff) bsizes &= bsizes_more; - if(bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || + if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 || (bsizes & DMA_BURST32)==0) bsizes = (DMA_BURST32 - 1); @@ -834,43 +814,44 @@ */ qec_init_once(qecp, sdev); - for(i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { /* Map in QEC per-channel control registers. */ - qeps[i]->qcregs = sparc_alloc_io(qesdevs[i]->reg_addrs[0].phys_addr, 0, - sizeof(struct qe_creg), - "QEC Per-Channel Registers", - qesdevs[i]->reg_addrs[0].which_io, 0); - if(!qeps[i]->qcregs) { - printk("QuadEther: Cannot map QE %d's channel registers.\n", i); + qeps[i]->qcregs = sbus_ioremap(&qesdevs[i]->resource[0], 0, + CREG_REG_SIZE, "QEC Channel Registers"); + if (!qeps[i]->qcregs) { + printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i); res = ENODEV; goto qec_free_devs; } /* Map in per-channel AMD MACE registers. */ - qeps[i]->mregs = sparc_alloc_io(qesdevs[i]->reg_addrs[1].phys_addr, 0, - sizeof(struct qe_mregs), - "QE MACE Registers", - qesdevs[i]->reg_addrs[1].which_io, 0); - if(!qeps[i]->mregs) { - printk("QuadEther: Cannot map QE %d's MACE registers.\n", i); + qeps[i]->mregs = sbus_ioremap(&qesdevs[i]->resource[1], 0, + MREGS_REG_SIZE, "QE MACE Registers"); + if (!qeps[i]->mregs) { + printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i); res = ENODEV; goto qec_free_devs; } - qeps[i]->qe_block = (struct qe_init_block *) - sparc_dvma_malloc(PAGE_SIZE, "QE Init Block", - &qeps[i]->qblock_dvma); - - qeps[i]->buffers = (struct sunqe_buffers *) - sparc_dvma_malloc(sizeof(struct sunqe_buffers), - "QE RX/TX Buffers", - &qeps[i]->buffers_dvma); + qeps[i]->qe_block = sbus_alloc_consistant(qesdevs[i], + PAGE_SIZE, + &qeps[i]->qblock_dvma); + qeps[i]->buffers = sbus_alloc_consistant(qesdevs[i], + sizeof(struct sunqe_buffers), + &qeps[i]->buffers_dvma); + if (qeps[i]->qe_block == NULL || + qeps[i]->qblock_dvma == 0 || + qeps[i]->buffers == NULL || + qeps[i]->buffers_dvma == 0) { + res = ENODEV; + goto qec_free_devs; + } /* Stop this QE. */ qe_stop(qeps[i]); } - for(i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { qe_devs[i]->open = qe_open; qe_devs[i]->stop = qe_close; qe_devs[i]->hard_start_xmit = qe_start_xmit; @@ -886,17 +867,17 @@ * interrupt for all QE channels we register the IRQ handler * for it now. */ - if(request_irq(sdev->irqs[0], &qec_interrupt, - SA_SHIRQ, "QuadEther", (void *) qecp)) { - printk("QuadEther: Can't register QEC master irq handler.\n"); + if (request_irq(sdev->irqs[0], &qec_interrupt, + SA_SHIRQ, "QuadEther", (void *) qecp)) { + printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n"); res = EAGAIN; goto qec_free_devs; } /* Report the QE channels. */ - for(i = 0; i < 4; i++) { - printk("%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i); - for(j = 0; j < 6; j++) + for (i = 0; i < 4; i++) { + printk(KERN_INFO "%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i); + for (j = 0; j < 6; j++) printk ("%2.2x%c", qe_devs[i]->dev_addr[j], j == 5 ? ' ': ':'); @@ -907,7 +888,7 @@ /* We are home free at this point, link the qe's into * the master list for later module unloading. */ - for(i = 0; i < 4; i++) + for (i = 0; i < 4; i++) qe_devs[i]->ifindex = dev_new_index(); qecp->next_module = root_qec_dev; root_qec_dev = qecp; @@ -916,50 +897,87 @@ return 0; qec_free_devs: - for(i = 0; i < 4; i++) { - if(qe_devs[i]) { - if(qe_devs[i]->priv) + for (i = 0; i < 4; i++) { + if (qe_devs[i] != NULL) { + if (qe_devs[i]->priv) { + struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv; + + if (qe->qcregs) + sbus_iounmap(qe->qcregs, CREG_REG_SIZE); + if (qe->mregs) + sbus_iounmap(qe->mregs, MREGS_REG_SIZE); + if (qe->qe_block != NULL) + sbus_free_consistant(qe->qe_sdev, + PAGE_SIZE, + qe->qe_block, + qe->qblock_dvma); + if (qe->buffers != NULL) + sbus_free_consistant(qe->qe_sdev, + sizeof(struct sunqe_buffers), + qe->buffers, + qe->buffers_dvma); kfree(qe_devs[i]->priv); + } kfree(qe_devs[i]); } } + if (qecp != NULL) { + if (qecp->gregs) + sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); + kfree(qecp); + } return res; } +static int __init qec_match(struct sbus_dev *sdev) +{ + struct sbus_dev *sibling; + int i; + + if (strcmp(sdev->prom_name, "qec") != 0) + return 0; + + /* QEC can be parent of either QuadEthernet or BigMAC + * children. Do not confuse this with qfe/SUNW,qfe + * which is a quad-happymeal card and handled by + * a different driver. + */ + sibling = sdev->child; + for (i = 0; i < 4; i++) { + if (sibling == NULL) + return 0; + if (strcmp(sibling->prom_name, "qe") != 0) + return 0; + sibling = sibling->next; + } + return 1; +} + int __init qec_probe(void) { struct net_device *dev = NULL; - struct linux_sbus *bus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *bus; + struct sbus_dev *sdev = 0; static int called = 0; int cards = 0, v; - if(called) + if (called) return ENODEV; called++; for_each_sbus(bus) { for_each_sbusdev(sdev, bus) { - if(cards) dev = NULL; + if (cards) + dev = NULL; - /* QEC can be parent of either QuadEthernet or BigMAC - * children. - */ - if(!strcmp(sdev->prom_name, "qec") && sdev->child && - !strcmp(sdev->child->prom_name, "qe") && - sdev->child->next && - !strcmp(sdev->child->next->prom_name, "qe") && - sdev->child->next->next && - !strcmp(sdev->child->next->next->prom_name, "qe") && - sdev->child->next->next->next && - !strcmp(sdev->child->next->next->next->prom_name, "qe")) { + if (qec_match(sdev)) { cards++; - if((v = qec_ether_init(dev, sdev))) + if ((v = qec_ether_init(dev, sdev))) return v; } } } - if(!cards) + if (!cards) return ENODEV; return 0; } @@ -984,14 +1002,22 @@ next_qec = root_qec_dev->next_module; /* Release all four QE channels, then the QEC itself. */ - for(i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { unregister_netdev(root_qec_dev->qes[i]->dev); - sparc_free_io(root_qec_dev->qes[i]->qcregs, sizeof(struct qe_creg)); - sparc_free_io(root_qec_dev->qes[i]->mregs, sizeof(struct qe_mregs)); + sbus_iounmap(root_qec_dev->qes[i]->qcregs, CREG_REG_SIZE); + sbus_iounmap(root_qec_dev->qes[i]->mregs, MREGS_REG_SIZE); + sbus_free_consistant(root_qec_dev->qes[i]->qe_sdev, + PAGE_SIZE, + root_qec_dev->qes[i]->qe_block, + root_qec_dev->qes[i]->qblock_dvma); + sbus_free_consistant(root_qec_dev->qes[i]->qe_sdev, + sizeof(struct sunqe_buffers), + root_qec_dev->qes[i]->buffers, + root_qec_dev->qes[i]->buffers_dvma); kfree(root_qec_dev->qes[i]->dev); } - free_irq(root_qec_dev->qec_sbus_dev->irqs[0], (void *)root_qec_dev); - sparc_free_io(root_qec_dev->gregs, sizeof(struct qe_globreg)); + free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev); + sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); kfree(root_qec_dev); root_qec_dev = next_qec; } diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h --- v2.3.34/linux/drivers/net/sunqe.h Fri Sep 10 23:57:30 1999 +++ linux/drivers/net/sunqe.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,5 @@ -/* sunqe.h: Definitions for the Sun QuadEthernet driver. +/* $Id: sunqe.h,v 1.12 1999/09/21 14:36:44 davem Exp $ + * sunqe.h: Definitions for the Sun QuadEthernet driver. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ @@ -7,14 +8,13 @@ #define _SUNQE_H /* QEC global registers. */ -struct qe_globreg { - volatile unsigned int ctrl; /* Control */ - volatile unsigned int stat; /* Status */ - volatile unsigned int psize; /* Packet Size */ - volatile unsigned int msize; /* Local-mem size (64K) */ - volatile unsigned int rsize; /* Receive partition size */ - volatile unsigned int tsize; /* Transmit partition size */ -}; +#define GLOB_CTRL 0x00UL /* Control */ +#define GLOB_STAT 0x04UL /* Status */ +#define GLOB_PSIZE 0x08UL /* Packet Size */ +#define GLOB_MSIZE 0x0cUL /* Local-memory Size */ +#define GLOB_RSIZE 0x10UL /* Receive partition size */ +#define GLOB_TSIZE 0x14UL /* Transmit partition size */ +#define GLOB_REG_SIZE 0x18UL #define GLOB_CTRL_MMODE 0x40000000 /* MACE qec mode */ #define GLOB_CTRL_BMODE 0x10000000 /* BigMAC qec mode */ @@ -42,22 +42,21 @@ #define GLOB_STAT_PER_QE(status, channel) (((status) >> ((channel) * 4)) & 0xf) /* The following registers are for per-qe channel information/status. */ -struct qe_creg { - volatile unsigned int ctrl; /* Control */ - volatile unsigned int stat; /* Status */ - volatile unsigned int rxds; /* RX descriptor ring ptr */ - volatile unsigned int txds; /* TX descriptor ring ptr */ - volatile unsigned int rimask; /* RX Interrupt Mask */ - volatile unsigned int timask; /* TX Interrupt Mask */ - volatile unsigned int qmask; /* QEC Error Interrupt Mask */ - volatile unsigned int mmask; /* MACE Error Interrupt Mask */ - volatile unsigned int rxwbufptr; /* Local memory rx write ptr */ - volatile unsigned int rxrbufptr; /* Local memory rx read ptr */ - volatile unsigned int txwbufptr; /* Local memory tx write ptr */ - volatile unsigned int txrbufptr; /* Local memory tx read ptr */ - volatile unsigned int ccnt; /* Collision Counter */ - volatile unsigned int pipg; /* Inter-Frame Gap */ -}; +#define CREG_CTRL 0x00UL /* Control */ +#define CREG_STAT 0x04UL /* Status */ +#define CREG_RXDS 0x08UL /* RX descriptor ring ptr */ +#define CREG_TXDS 0x0cUL /* TX descriptor ring ptr */ +#define CREG_RIMASK 0x10UL /* RX Interrupt Mask */ +#define CREG_TIMASK 0x14UL /* TX Interrupt Mask */ +#define CREG_QMASK 0x18UL /* QEC Error Interrupt Mask */ +#define CREG_MMASK 0x1cUL /* MACE Error Interrupt Mask */ +#define CREG_RXWBUFPTR 0x20UL /* Local memory rx write ptr */ +#define CREG_RXRBUFPTR 0x24UL /* Local memory rx read ptr */ +#define CREG_TXWBUFPTR 0x28UL /* Local memory tx write ptr */ +#define CREG_TXRBUFPTR 0x2cUL /* Local memory tx read ptr */ +#define CREG_CCNT 0x30UL /* Collision Counter */ +#define CREG_PIPG 0x34UL /* Inter-Frame Gap */ +#define CREG_REG_SIZE 0x38UL #define CREG_CTRL_RXOFF 0x00000004 /* Disable this qe's receiver*/ #define CREG_CTRL_RESET 0x00000002 /* Reset this qe channel */ @@ -127,40 +126,39 @@ #define CREG_PIPG_WMASK 0x0000000f /* SBUS Wait Mask */ /* Per-channel AMD 79C940 MACE registers. */ -struct qe_mregs { - volatile unsigned char rxfifo; /* Receive FIFO */ - volatile unsigned char txfifo; /* Transmit FIFO */ - volatile unsigned char txfcntl; /* Transmit Frame Control */ - volatile unsigned char txfstat; /* Transmit Frame Status */ - volatile unsigned char txrcnt; /* Transmit Retry Count */ - volatile unsigned char rxfcntl; /* Receive Frame Control */ - volatile unsigned char rxfstat; /* Receive Frame Status */ - volatile unsigned char ffcnt; /* FIFO Frame Count */ - volatile unsigned char ireg; /* Interrupt Register */ - volatile unsigned char imask; /* Interrupt Mask */ - volatile unsigned char poll; /* POLL Register */ - volatile unsigned char bconfig; /* BIU Config */ - volatile unsigned char fconfig; /* FIFO Config */ - volatile unsigned char mconfig; /* MAC Config */ - volatile unsigned char plsconfig;/* PLS Config */ - volatile unsigned char phyconfig;/* PHY Config */ - volatile unsigned char chipid1; /* Chip-ID, low bits */ - volatile unsigned char chipid2; /* Chip-ID, high bits */ - volatile unsigned char iaconfig; /* Internal Address Config */ - volatile unsigned char _unused0; /* Reserved... */ - volatile unsigned char filter; /* Logical Address Filter */ - volatile unsigned char ethaddr; /* Our Ethernet Address */ - volatile unsigned char _unused1; /* Reserved... */ - volatile unsigned char _unused2; /* Reserved... */ - volatile unsigned char mpcnt; /* Missed Packet Count */ - volatile unsigned char _unused3; /* Reserved... */ - volatile unsigned char rpcnt; /* Runt Packet Count */ - volatile unsigned char rccnt; /* RX Collision Count */ - volatile unsigned char _unused4; /* Reserved... */ - volatile unsigned char utest; /* User Test */ - volatile unsigned char rtest1; /* Reserved Test 1 */ - volatile unsigned char rtest2; /* Reserved Test 2 */ -}; +#define MREGS_RXFIFO 0x00UL /* Receive FIFO */ +#define MREGS_TXFIFO 0x01UL /* Transmit FIFO */ +#define MREGS_TXFCNTL 0x02UL /* Transmit Frame Control */ +#define MREGS_TXFSTAT 0x03UL /* Transmit Frame Status */ +#define MREGS_TXRCNT 0x04UL /* Transmit Retry Count */ +#define MREGS_RXFCNTL 0x05UL /* Receive Frame Control */ +#define MREGS_RXFSTAT 0x06UL /* Receive Frame Status */ +#define MREGS_FFCNT 0x07UL /* FIFO Frame Count */ +#define MREGS_IREG 0x08UL /* Interrupt Register */ +#define MREGS_IMASK 0x09UL /* Interrupt Mask */ +#define MREGS_POLL 0x0aUL /* POLL Register */ +#define MREGS_BCONFIG 0x0bUL /* BIU Config */ +#define MREGS_FCONFIG 0x0cUL /* FIFO Config */ +#define MREGS_MCONFIG 0x0dUL /* MAC Config */ +#define MREGS_PLSCONFIG 0x0eUL /* PLS Config */ +#define MREGS_PHYCONFIG 0x0fUL /* PHY Config */ +#define MREGS_CHIPID1 0x10UL /* Chip-ID, low bits */ +#define MREGS_CHIPID2 0x11UL /* Chip-ID, high bits */ +#define MREGS_IACONFIG 0x12UL /* Internal Address Config */ + /* 0x13UL, reserved */ +#define MREGS_FILTER 0x14UL /* Logical Address Filter */ +#define MREGS_ETHADDR 0x15UL /* Our Ethernet Address */ + /* 0x16UL, reserved */ + /* 0x17UL, reserved */ +#define MREGS_MPCNT 0x18UL /* Missed Packet Count */ + /* 0x19UL, reserved */ +#define MREGS_RPCNT 0x1aUL /* Runt Packet Count */ +#define MREGS_RCCNT 0x1bUL /* RX Collision Count */ + /* 0x1cUL, reserved */ +#define MREGS_UTEST 0x1dUL /* User Test */ +#define MREGS_RTEST1 0x1eUL /* Reserved Test 1 */ +#define MREGS_RTEST2 0x1fUL /* Reserved Test 2 */ +#define MREGS_REG_SIZE 0x20UL #define MREGS_TXFCNTL_DRETRY 0x80 /* Retry disable */ #define MREGS_TXFCNTL_DFCS 0x08 /* Disable TX FCS */ @@ -267,8 +265,8 @@ #define MREGS_UTEST_NOLOOP 0x00 /* No loopback */ struct qe_rxd { - unsigned int rx_flags; - unsigned int rx_addr; + u32 rx_flags; + u32 rx_addr; }; #define RXD_OWN 0x80000000 /* Ownership. */ @@ -276,8 +274,8 @@ #define RXD_LENGTH 0x000007ff /* Packet Length. */ struct qe_txd { - unsigned int tx_flags; - unsigned int tx_addr; + u32 tx_flags; + u32 tx_addr; }; #define TXD_OWN 0x80000000 /* Ownership. */ @@ -313,40 +311,40 @@ struct sunqe; struct sunqec { - struct qe_globreg *gregs; /* QEC Global Registers */ - struct sunqe *qes[4]; /* Each child MACE */ - unsigned int qec_bursts; /* Support burst sizes */ - struct linux_sbus_device *qec_sbus_dev; /* QEC's SBUS device */ - struct sunqec *next_module; /* List of all QECs in system */ + unsigned long gregs; /* QEC Global Registers */ + struct sunqe *qes[4]; /* Each child MACE */ + unsigned int qec_bursts; /* Support burst sizes */ + struct sbus_dev *qec_sdev; /* QEC's SBUS device */ + struct sunqec *next_module; /* List of all QECs in system */ }; #define PKT_BUF_SZ 1664 #define RXD_PKT_SZ 1664 struct sunqe_buffers { - char tx_buf[TX_RING_SIZE][PKT_BUF_SZ]; - char __pad[2]; - char rx_buf[RX_RING_SIZE][PKT_BUF_SZ]; + u8 tx_buf[TX_RING_SIZE][PKT_BUF_SZ]; + u8 __pad[2]; + u8 rx_buf[RX_RING_SIZE][PKT_BUF_SZ]; }; #define qebuf_offset(mem, elem) \ ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0])))) struct sunqe { - struct qe_creg *qcregs; /* QEC per-channel Registers */ - struct qe_mregs *mregs; /* Per-channel MACE Registers */ - struct qe_init_block *qe_block; /* RX and TX descriptors */ - __u32 qblock_dvma; /* RX and TX descriptors */ - int rx_new, rx_old; /* RX ring extents */ - int tx_new, tx_old; /* TX ring extents */ - struct sunqe_buffers *buffers; /* CPU visible address. */ - __u32 buffers_dvma; /* DVMA visible address. */ - struct sunqec *parent; - unsigned char mconfig; /* Base MACE mconfig value */ - struct net_device_stats net_stats; /* Statistical counters */ - struct linux_sbus_device *qe_sbusdev; /* QE's SBUS device struct */ - struct net_device *dev; /* QE's netdevice struct */ - int channel; /* Who am I? */ + unsigned long qcregs; /* QEC per-channel Registers */ + unsigned long mregs; /* Per-channel MACE Registers */ + struct qe_init_block *qe_block; /* RX and TX descriptors */ + __u32 qblock_dvma; /* RX and TX descriptors */ + int rx_new, rx_old; /* RX ring extents */ + int tx_new, tx_old; /* TX ring extents */ + struct sunqe_buffers *buffers; /* CPU visible address. */ + __u32 buffers_dvma; /* DVMA visible address. */ + struct sunqec *parent; + u8 mconfig; /* Base MACE mconfig value */ + struct net_device_stats net_stats; /* Statistical counters */ + struct sbus_dev *qe_sdev; /* QE's SBUS device struct */ + struct net_device *dev; /* QE's netdevice struct */ + int channel; /* Who am I? */ }; #endif /* !(_SUNQE_H) */ diff -u --recursive --new-file v2.3.34/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c --- v2.3.34/linux/drivers/parport/parport_sunbpp.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/parport/parport_sunbpp.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: parport_sunbpp.c,v 1.7 1999/09/02 11:59:31 davem Exp $ +/* $Id: parport_sunbpp.c,v 1.9 1999/10/14 05:59:43 ecd Exp $ * Parallel-port routines for Sun architecture * * Author: Derrick J. Brashear @@ -32,7 +32,7 @@ #include #include /* OpenProm Library */ -#include /* struct linux_sbus *SBus_chain */ +#include #include /* BPP uses LSI 64854 for DMA */ #include #include @@ -52,22 +52,28 @@ static void parport_sunbpp_disable_irq(struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; + u32 tmp; - regs->p_csr &= ~(DMA_INT_ENAB); + tmp = sbus_readl(®s->p_csr); + tmp &= ~DMA_INT_ENAB; + sbus_writel(tmp, ®s->p_csr); } static void parport_sunbpp_enable_irq(struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; + u32 tmp; - regs->p_csr |= DMA_INT_ENAB; + tmp = sbus_readl(®s->p_csr); + tmp |= DMA_INT_ENAB; + sbus_writel(tmp, ®s->p_csr); } static void parport_sunbpp_write_data(struct parport *p, unsigned char d) { struct bpp_regs *regs = (struct bpp_regs *)p->base; - regs->p_dr = d; + sbus_writeb(d, ®s->p_dr); dprintk(("wrote 0x%x\n", d)); } @@ -75,14 +81,15 @@ { struct bpp_regs *regs = (struct bpp_regs *)p->base; - return regs->p_dr; + return sbus_readb(®s->p_dr); } +#if 0 static void control_pc_to_sunbpp(struct parport *p, unsigned char status) { struct bpp_regs *regs = (struct bpp_regs *)p->base; - unsigned char value_tcr = regs->p_tcr; - unsigned char value_or = regs->p_or; + unsigned char value_tcr = sbus_readb(®s->p_tcr); + unsigned char value_or = sbus_readb(®s->p_or); if (status & PARPORT_CONTROL_STROBE) value_tcr |= P_TCR_DS; @@ -93,16 +100,17 @@ if (status & PARPORT_CONTROL_SELECT) value_or |= P_OR_SLCT_IN; - regs->p_or = value_or; - regs->p_tcr = value_tcr; + sbus_writeb(value_or, ®s->p_or); + sbus_writeb(value_tcr, ®s->p_tcr); } +#endif static unsigned char status_sunbpp_to_pc(struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; unsigned char bits = 0; - unsigned char value_tcr = regs->p_tcr; - unsigned char value_ir = regs->p_ir; + unsigned char value_tcr = sbus_readb(®s->p_tcr); + unsigned char value_ir = sbus_readb(®s->p_ir); if (!(value_ir & P_IR_ERR)) bits |= PARPORT_STATUS_ERROR; @@ -124,8 +132,8 @@ { struct bpp_regs *regs = (struct bpp_regs *)p->base; unsigned char bits = 0; - unsigned char value_tcr = regs->p_tcr; - unsigned char value_or = regs->p_or; + unsigned char value_tcr = sbus_readb(®s->p_tcr); + unsigned char value_or = sbus_readb(®s->p_or); if (!(value_tcr & P_TCR_DS)) bits |= PARPORT_CONTROL_STROBE; @@ -151,8 +159,8 @@ unsigned char val) { struct bpp_regs *regs = (struct bpp_regs *)p->base; - unsigned char value_tcr = regs->p_tcr; - unsigned char value_or = regs->p_or; + unsigned char value_tcr = sbus_readb(®s->p_tcr); + unsigned char value_or = sbus_readb(®s->p_or); dprintk(("frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); if (mask & PARPORT_CONTROL_STROBE) { @@ -184,8 +192,8 @@ } } - regs->p_or = value_or; - regs->p_tcr = value_tcr; + sbus_writeb(value_or, ®s->p_or); + sbus_writeb(value_tcr, ®s->p_tcr); dprintk(("frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or)); return parport_sunbpp_read_control(p); } @@ -208,20 +216,21 @@ static void parport_sunbpp_data_forward (struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; - unsigned char value_tcr = regs->p_tcr; + unsigned char value_tcr = sbus_readb(®s->p_tcr); dprintk(("forward\n")); - value_tcr = regs->p_tcr; value_tcr &= ~P_TCR_DIR; - regs->p_tcr = value_tcr; + sbus_writeb(value_tcr, ®s->p_tcr); } static void parport_sunbpp_data_reverse (struct parport *p) { struct bpp_regs *regs = (struct bpp_regs *)p->base; + u8 val = sbus_readb(®s->p_tcr); dprintk(("reverse\n")); - regs->p_tcr |= P_TCR_DIR; + val |= P_TCR_DIR; + sbus_writeb(val, ®s->p_tcr); } static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s) @@ -292,38 +301,37 @@ parport_ieee1284_read_byte, }; -static int __init init_one_port(struct linux_sbus_device *sdev) +static int __init init_one_port(struct sbus_dev *sdev) { struct parport *p; /* at least in theory there may be a "we don't dma" case */ struct parport_operations *ops; - char *base; + unsigned long base; int irq, dma, err, size; struct bpp_regs *regs; unsigned char value_tcr; dprintk(("init_one_port(%p): ranges, alloc_io, ", sdev)); irq = sdev->irqs[0]; - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, 1, sdev); - base = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, - "sunbpp", sdev->reg_addrs[0].which_io, 0); + base = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "sunbpp"); size = sdev->reg_addrs[0].reg_size; dma = PARPORT_DMA_NONE; dprintk(("alloc(ppops), ")); ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); if (!ops) { - sparc_free_io(base, size); + sbus_iounmap(base, size); return 0; } memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port, ")); - if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) { + if (!(p = parport_register_port(base, irq, dma, ops))) { kfree(ops); - sparc_free_io(base, size); + sbus_iounmap(base, size); return 0; } @@ -334,7 +342,7 @@ dprintk(("ERROR %d\n", err)); parport_unregister_port(p); kfree(ops); - sparc_free_io(base, size); + sbus_iounmap(base, size); return err; } else { dprintk(("OK\n")); @@ -343,9 +351,9 @@ regs = (struct bpp_regs *)p->base; dprintk(("forward\n")); - value_tcr = regs->p_tcr; + value_tcr = sbus_readb(®s->p_tcr); value_tcr &= ~P_TCR_DIR; - regs->p_tcr = value_tcr; + sbus_writeb(value_tcr, ®s->p_tcr); printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); parport_proc_register(p); @@ -362,8 +370,8 @@ int __init parport_sunbpp_init(void) #endif { - struct linux_sbus *sbus; - struct linux_sbus_device *sdev; + struct sbus_bus *sbus; + struct sbus_dev *sdev; int count = 0; for_each_sbus(sbus) { @@ -383,21 +391,24 @@ void cleanup_module(void) { - struct parport *p = parport_enumerate(), *tmp; + struct parport *p = parport_enumerate(); + while (p) { - tmp = p->next; + struct parport *next = p->next; + if (1/*p->modes & PARPORT_MODE_PCSPP*/) { - struct parport_operations *ops = p->ops; - if (p->irq != PARPORT_IRQ_NONE) { - parport_sunbpp_disable_irq(p); - free_irq(p->irq, p); - } - sparc_free_io((char *)p->base, p->size); - parport_proc_unregister(p); - parport_unregister_port(p); - kfree (ops); + struct parport_operations *ops = p->ops; + + if (p->irq != PARPORT_IRQ_NONE) { + parport_sunbpp_disable_irq(p); + free_irq(p->irq, p); + } + sbus_iounmap(p->base, p->size); + parport_proc_unregister(p); + parport_unregister_port(p); + kfree (ops); } - p = tmp; + p = next; } } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/pci/Makefile linux/drivers/pci/Makefile --- v2.3.34/linux/drivers/pci/Makefile Wed Dec 8 14:11:26 1999 +++ linux/drivers/pci/Makefile Tue Dec 21 10:12:53 1999 @@ -11,21 +11,20 @@ L_TARGET := pci.a -# Nasty trick as nobody references pcisyms.o, but we still want it linked. -ifeq ($(CONFIG_MODULES),y) -O_TARGET = pci_syms.o -OX_OBJS = pcisyms.o -O_OBJS = pci.o -L_OBJS := pci_syms.o -else -L_OBJS := pci.o +# Nasty trick as we need to link files with no references from the outside. +O_TARGET := pci_core.o +L_OBJS := pci_core.o +O_OBJS := pci.o quirks.o + +ifdef CONFIG_MODULES +OX_OBJS += pcisyms.o endif ifdef CONFIG_PROC_FS -L_OBJS += proc.o +O_OBJS += proc.o endif -L_OBJS += compat.o quirks.o names.o helper.o +L_OBJS += compat.o names.o helper.o ifndef CONFIG_X86 L_OBJS += syscall.o setup.o diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.3.34/linux/drivers/pci/pci.c Wed Dec 8 14:11:26 1999 +++ linux/drivers/pci/pci.c Mon Dec 27 11:08:29 1999 @@ -30,7 +30,6 @@ struct pci_bus *pci_root; struct pci_dev *pci_devices = NULL; static struct pci_dev **pci_last_dev_p = &pci_devices; -static int pci_reverse __initdata = 0; struct pci_dev * pci_find_slot(unsigned int bus, unsigned int devfn) @@ -270,7 +269,7 @@ return IORESOURCE_MEM; } -void __init pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) +static void __init pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) { unsigned int pos, reg, next; u32 l, sz, tmp; @@ -413,91 +412,264 @@ } } -static unsigned int __init pci_do_scan_bus(struct pci_bus *bus) +static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) { - unsigned int devfn, l, max, class; - unsigned char irq, hdr_type, is_multi = 0; - struct pci_dev *dev, **bus_last; struct pci_bus *child; - struct pci_dev *dev_cache = NULL; - DBG("pci_do_scan_bus for bus %d\n", bus->number); - bus_last = &bus->devices; - max = bus->secondary; - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) && !is_multi) { - /* not a multi-function device */ - continue; - } - if (!dev_cache) { - dev_cache = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev_cache) - continue; - } - dev = dev_cache; - memset(dev, 0, sizeof(*dev)); - dev->bus = bus; - dev->sysdata = bus->sysdata; - dev->devfn = devfn; + /* + * Allocate a new bus, and inherit stuff from the parent.. + */ + child = kmalloc(sizeof(*child), GFP_KERNEL); + memset(child, 0, sizeof(*child)); - if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) - continue; - if (!PCI_FUNC(devfn)) - is_multi = hdr_type & 0x80; + child->next = parent->children; + parent->children = child; + child->self = dev; + dev->subordinate = child; + child->parent = parent; + child->ops = parent->ops; + child->sysdata = parent->sysdata; + + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = busnr; + child->primary = parent->secondary; + child->subordinate = 0xff; + + return child; +} + +/* + * A CardBus bridge is basically the same as a regular PCI bridge, + * except we don't scan behind it because it will be changing. + */ +static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr) +{ + unsigned short cr; + unsigned int buses; + struct pci_bus *child; + + /* + * Insert it into the tree of buses. + */ + child = pci_add_new_bus(bus, dev, ++busnr); + child->subordinate = busnr; + sprintf(child->name, "PCI CardBus #%02x", child->number); + + /* + * Clear all status bits and turn off memory, + * I/O and master enables. + */ + pci_read_config_word(dev, PCI_COMMAND, &cr); + pci_write_config_word(dev, PCI_COMMAND, 0x0000); + pci_write_config_word(dev, PCI_STATUS, 0xffff); + + /* + * Read the existing primary/secondary/subordinate bus + * number configuration to determine if the bridge + * has already been configured by the system. If so, + * do not modify the configuration, merely note it. + */ + pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); + if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) { + child->primary = buses & 0xFF; + child->secondary = (buses >> 8) & 0xFF; + child->subordinate = (buses >> 16) & 0xFF; + child->number = child->secondary; + if (child->subordinate > busnr) + busnr = child->subordinate; + } else { + /* + * Configure the bus numbers for this bridge: + */ + buses &= 0xff000000; + buses |= + (((unsigned int)(child->primary) << 0) | + ((unsigned int)(child->secondary) << 8) | + ((unsigned int)(child->subordinate) << 16)); + pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); + } + pci_write_config_word(dev, PCI_COMMAND, cr); + return busnr; +} + +static unsigned int __init pci_do_scan_bus(struct pci_bus *bus); + +/* + * If it's a bridge, scan the bus behind it. + */ +static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max) +{ + unsigned int buses; + unsigned short cr; + struct pci_bus *child; + + /* + * Insert it into the tree of buses. + */ + child = pci_add_new_bus(bus, dev, ++max); + sprintf(child->name, "PCI Bus #%02x", child->number); + + /* + * Clear all status bits and turn off memory, + * I/O and master enables. + */ + pci_read_config_word(dev, PCI_COMMAND, &cr); + pci_write_config_word(dev, PCI_COMMAND, 0x0000); + pci_write_config_word(dev, PCI_STATUS, 0xffff); + + /* + * Read the existing primary/secondary/subordinate bus + * number configuration to determine if the PCI bridge + * has already been configured by the system. If so, + * do not modify the configuration, merely note it. + */ + pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); + if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) { + unsigned int cmax; + child->primary = buses & 0xFF; + child->secondary = (buses >> 8) & 0xFF; + child->subordinate = (buses >> 16) & 0xFF; + child->number = child->secondary; + cmax = pci_do_scan_bus(child); + if (cmax > max) max = cmax; + } else { + /* + * Configure the bus numbers for this bridge: + */ + buses &= 0xff000000; + buses |= + (((unsigned int)(child->primary) << 0) | + ((unsigned int)(child->secondary) << 8) | + ((unsigned int)(child->subordinate) << 16)); + pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); + /* + * Now we can scan all subordinate buses: + */ + max = pci_do_scan_bus(child); + /* + * Set the subordinate bus number to its real + * value: + */ + child->subordinate = max; + buses = (buses & 0xff00ffff) + | ((unsigned int)(child->subordinate) << 16); + pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); + } + pci_write_config_word(dev, PCI_COMMAND, cr); + return max; +} - if (pci_read_config_dword(dev, PCI_VENDOR_ID, &l) || - /* some broken boards return 0 if a slot is empty: */ - l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) +/* + * Read interrupt line and base address registers. + * The architecture-dependent code can tweak these, of course. + */ +static void __init pci_read_irq(struct pci_dev *dev) +{ + unsigned char irq; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); + if (irq) + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + dev->irq = irq; +} + +/* + * Read the config data for a PCI device, sanity-check it + * and fill in the dev structure... + */ +static struct pci_dev * __init pci_scan_device(struct pci_dev *temp) +{ + struct pci_dev *dev; + u32 l, class; + + if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l)) + return NULL; + + /* some broken boards return 0 or ~0 if a slot is empty: */ + if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) + return NULL; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + memcpy(dev, temp, sizeof(*dev)); + dev->vendor = l & 0xffff; + dev->device = (l >> 16) & 0xffff; + sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + pci_name_device(dev); + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); + class >>= 8; /* upper 3 bytes */ + dev->class = class; + class >>= 8; + + switch (dev->hdr_type) { /* header type */ + case PCI_HEADER_TYPE_NORMAL: /* standard header */ + if (class == PCI_CLASS_BRIDGE_PCI) + goto bad; + pci_read_irq(dev); + pci_read_bases(dev, 6, PCI_ROM_ADDRESS); + pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); + pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); + break; + + case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ + if (class != PCI_CLASS_BRIDGE_PCI) + goto bad; + pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); + break; + + case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ + if (class != PCI_CLASS_BRIDGE_CARDBUS) + goto bad; + pci_read_irq(dev); + pci_read_bases(dev, 1, 0); + pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); + pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device); + break; + + default: /* unknown header */ + printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n", + dev->slot_name, dev->hdr_type); + kfree(dev); + return NULL; + + bad: + printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n", + dev->slot_name, class, dev->hdr_type); + dev->class = PCI_CLASS_NOT_DEFINED; + } + + /* We found a fine healthy device, go go go... */ + return dev; +} + +struct pci_dev * __init pci_scan_slot(struct pci_dev *temp) +{ + struct pci_bus *bus = temp->bus; + struct pci_dev *dev; + struct pci_dev *first_dev = NULL; + int func = 0; + int is_multi = 0; + u8 hdr_type; + + for (func = 0; func < 8; func++, temp->devfn++) { + if (func && !is_multi) /* not a multi-function device */ + continue; + if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) continue; + temp->hdr_type = hdr_type & 0x7f; - dev_cache = NULL; - dev->vendor = l & 0xffff; - dev->device = (l >> 16) & 0xffff; - sprintf(dev->slot_name, "%02x:%02x.%d", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); - pci_name_device(dev); - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); - class >>= 8; /* upper 3 bytes */ - dev->class = class; - class >>= 8; - dev->hdr_type = hdr_type & 0x7f; - - switch (dev->hdr_type) { /* header type */ - case PCI_HEADER_TYPE_NORMAL: /* standard header */ - if (class == PCI_CLASS_BRIDGE_PCI) - goto bad; - /* - * Read interrupt line and base address registers. - * The architecture-dependent code can tweak these, of course. - */ - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); - if (irq) - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - dev->irq = irq; - pci_read_bases(dev, 6, PCI_ROM_ADDRESS); - pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); - pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); - break; - case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ - if (class != PCI_CLASS_BRIDGE_PCI) - goto bad; - pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); - break; - case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ - if (class != PCI_CLASS_BRIDGE_CARDBUS) - goto bad; - pci_read_bases(dev, 1, 0); - pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); - pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device); - break; - default: /* unknown header */ - printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n", - dev->slot_name, hdr_type); + dev = pci_scan_device(temp); + if (!dev) continue; - bad: - printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n", - dev->slot_name, class, hdr_type); - dev->class = PCI_CLASS_NOT_DEFINED; + if (!func) { + is_multi = hdr_type & 0x80; + first_dev = dev; } DBG("PCI: %02x:%02x [%04x/%04x] %06x %02x\n", bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type); @@ -506,122 +678,57 @@ * Put it into the global PCI device chain. It's used to * find devices once everything is set up. */ - if (!pci_reverse) { - *pci_last_dev_p = dev; - pci_last_dev_p = &dev->next; - } else { - dev->next = pci_devices; - pci_devices = dev; - } + *pci_last_dev_p = dev; + pci_last_dev_p = &dev->next; /* * Now insert it into the list of devices held * by the parent bus. */ - *bus_last = dev; - bus_last = &dev->sibling; + *bus->last_dev_p = dev; + bus->last_dev_p = &dev->sibling; /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); + } + return first_dev; +} -#if 0 - /* - * Setting of latency timer in case it was less than 32 was - * a great idea, but it confused several broken devices. Grrr. - */ - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp); - if (tmp < 32) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); -#endif +static unsigned int __init pci_do_scan_bus(struct pci_bus *bus) +{ + unsigned int devfn, max; + struct pci_dev *dev, dev0; + + DBG("pci_do_scan_bus for bus %d\n", bus->number); + bus->last_dev_p = &bus->devices; + max = bus->secondary; + + /* Create a device template */ + memset(&dev0, 0, sizeof(dev0)); + dev0.bus = bus; + dev0.sysdata = bus->sysdata; + + /* Go find them, Rover! */ + for (devfn = 0; devfn < 0x100; devfn += 8) { + dev0.devfn = devfn; + pci_scan_slot(&dev0); } - if (dev_cache) - kfree(dev_cache); /* * After performing arch-dependent fixup of the bus, look behind * all PCI-to-PCI bridges on this bus. */ pcibios_fixup_bus(bus); - for(dev=bus->devices; dev; dev=dev->sibling) - /* - * If it's a bridge, scan the bus behind it. - */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - unsigned int buses; - unsigned short cr; - - /* - * Insert it into the tree of buses. - */ - child = kmalloc(sizeof(*child), GFP_KERNEL); - memset(child, 0, sizeof(*child)); - child->next = bus->children; - bus->children = child; - child->self = dev; - child->parent = bus; - child->ops = bus->ops; - child->sysdata = bus->sysdata; - - /* - * Set up the primary, secondary and subordinate - * bus numbers. Read resource ranges behind the bridge. - */ - child->number = child->secondary = ++max; - child->primary = bus->secondary; - child->subordinate = 0xff; - sprintf(child->name, "PCI Bus #%02x", child->number); - /* - * Clear all status bits and turn off memory, - * I/O and master enables. - */ - pci_read_config_word(dev, PCI_COMMAND, &cr); - pci_write_config_word(dev, PCI_COMMAND, 0x0000); - pci_write_config_word(dev, PCI_STATUS, 0xffff); - /* - * Read the existing primary/secondary/subordinate bus - * number configuration to determine if the PCI bridge - * has already been configured by the system. If so, - * do not modify the configuration, merely note it. - */ - pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); - if ((buses & 0xFFFFFF) != 0 - && ! pcibios_assign_all_busses()) - { - unsigned int cmax; - - child->primary = buses & 0xFF; - child->secondary = (buses >> 8) & 0xFF; - child->subordinate = (buses >> 16) & 0xFF; - child->number = child->secondary; - cmax = pci_do_scan_bus(child); - if (cmax > max) max = cmax; - } - else - { - /* - * Configure the bus numbers for this bridge: - */ - buses &= 0xff000000; - buses |= - (((unsigned int)(child->primary) << 0) | - ((unsigned int)(child->secondary) << 8) | - ((unsigned int)(child->subordinate) << 16)); - pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); - /* - * Now we can scan all subordinate buses: - */ - max = pci_do_scan_bus(child); - /* - * Set the subordinate bus number to its real - * value: - */ - child->subordinate = max; - buses = (buses & 0xff00ffff) - | ((unsigned int)(child->subordinate) << 16); - pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); - } - pci_write_config_word(dev, PCI_COMMAND, cr); + for (dev = bus->devices; dev; dev = dev->sibling) { + switch (dev->class >> 8) { + case PCI_CLASS_BRIDGE_PCI: + max = pci_scan_bridge(bus, dev, max); + break; + case PCI_CLASS_BRIDGE_CARDBUS: + max = pci_scan_cardbus(bus, dev, max); + break; } + } /* * We've scanned the bus and so we know all about what's on @@ -646,7 +753,7 @@ return 0; } -struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata) +struct pci_bus * __init pci_alloc_primary_bus(int bus) { struct pci_bus *b, **r; @@ -666,11 +773,19 @@ *r = b; b->number = b->secondary = bus; - b->sysdata = sysdata; - b->ops = ops; b->resource[0] = &ioport_resource; b->resource[1] = &iomem_resource; - b->subordinate = pci_do_scan_bus(b); + return b; +} + +struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata) +{ + struct pci_bus *b = pci_alloc_primary_bus(bus); + if (b) { + b->sysdata = sysdata; + b->ops = ops; + b->subordinate = pci_do_scan_bus(b); + } return b; } @@ -691,9 +806,8 @@ if (k) *k++ = 0; if (*str && (str = pcibios_setup(str)) && *str) { - if (!strcmp(str, "reverse")) - pci_reverse = 1; - else printk(KERN_ERR "PCI: Unknown option `%s'\n", str); + /* PCI layer options should be handled here */ + printk(KERN_ERR "PCI: Unknown option `%s'\n", str); } str = k; } diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.3.34/linux/drivers/pci/pci.ids Mon Dec 20 18:48:21 1999 +++ linux/drivers/pci/pci.ids Sun Dec 26 19:34:04 1999 @@ -2150,7 +2150,7 @@ 1948 Solo? 1968 ES1968 Maestro 2 1969 ES1969 Solo-1 Audiodrive - 1978 ES1978 Maestro Audiodrive + 1978 ES1978 Maestro 2E 2808 ES336H Fax Modem (Later Model) 2898 ES2898 Modem 125e Specialvideo Engineering SRL @@ -2216,7 +2216,7 @@ e886 IT8330G 1284 Sahara Networks, Inc. 1285 Platform Technologies, Inc. - 0100 PT-201C-O-P AGOGO-XP sound chip + 0100 AGOGO sound chip (aka ESS Maestro 1) 1286 Mazet GmbH 1287 M-Pact, Inc. 001e LS220D DVD Decoder diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c --- v2.3.34/linux/drivers/pci/pcisyms.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/pci/pcisyms.c Sun Dec 26 10:39:19 1999 @@ -25,6 +25,8 @@ EXPORT_SYMBOL(pci_find_slot); EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_simple_probe); +EXPORT_SYMBOL(pci_set_power_state); +EXPORT_SYMBOL(pci_assign_resource); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(pci_proc_attach_device); EXPORT_SYMBOL(pci_proc_detach_device); diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/Config.in linux/drivers/pcmcia/Config.in --- v2.3.34/linux/drivers/pcmcia/Config.in Fri Oct 22 13:21:49 1999 +++ linux/drivers/pcmcia/Config.in Wed Dec 22 10:52:08 1999 @@ -8,8 +8,9 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then if [ "$CONFIG_PCI" != "n" ]; then bool ' CardBus support' CONFIG_CARDBUS + dep_tristate ' Yenta Cardbus support' CONFIG_YENTA $CONFIG_CARDBUS fi - bool ' i82365/Yenta compatible bridge support' CONFIG_I82365 + bool ' i82365 compatible bridge support' CONFIG_I82365 bool ' Databook TCIC host bridge support' CONFIG_TCIC fi diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile --- v2.3.34/linux/drivers/pcmcia/Makefile Fri Oct 22 13:21:49 1999 +++ linux/drivers/pcmcia/Makefile Wed Dec 22 10:54:26 1999 @@ -24,6 +24,9 @@ ifeq ($(CONFIG_TCIC),y) O_OBJS += tcic.o endif + ifeq ($(CONFIG_YENTA),y) + OX_OBJS += yenta.o pci_socket.o + endif ifeq ($(CONFIG_CARDBUS),y) O_OBJS += cardbus.o OX_OBJS += cb_enabler.o diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c --- v2.3.34/linux/drivers/pcmcia/bulkmem.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/pcmcia/bulkmem.c Tue Dec 21 11:41:41 1999 @@ -257,7 +257,7 @@ win->ctl.flags |= MAP_ATTRIB; win->ctl.speed = req->AccessSpeed; win->ctl.card_start = req->CardOffset; - win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl); + win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl); return CS_SUCCESS; } @@ -270,7 +270,7 @@ return CS_BAD_VPP; s = SOCKET(handle); s->socket.Vpp = req->Vpp1; - if (s->ss_entry(s->sock, SS_SetSocket, &s->socket)) + if (s->ss_entry->set_socket(s->sock, &s->socket)) return CS_BAD_VPP; return CS_SUCCESS; } @@ -285,7 +285,7 @@ s->socket.csc_mask |= SS_READY; else s->socket.csc_mask &= ~SS_READY; - if (s->ss_entry(s->sock, SS_SetSocket, &s->socket)) + if (s->ss_entry->set_socket(s->sock, &s->socket)) return CS_GENERAL_FAILURE; return CS_SUCCESS; } diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c --- v2.3.34/linux/drivers/pcmcia/cardbus.c Thu Nov 11 20:11:42 1999 +++ linux/drivers/pcmcia/cardbus.c Tue Dec 28 17:31:24 1999 @@ -203,7 +203,7 @@ pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, PCI_COMMAND_MEMORY); m->map = 0; m->flags = MAP_ACTIVE; m->start = base; m->stop = base+sz-1; - s->ss_entry(s->sock, SS_SetBridge, m); + s->ss_entry->set_bridge(s->sock, m); if ((space == 7) && (check_rom(s->cb_cis_virt, sz) == 0)) { printk(KERN_NOTICE "cs: no valid ROM images found!\n"); return CS_READ_FAILURE; @@ -227,7 +227,7 @@ br = (s->cb_cis_space == 7) ? CB_ROM_BASE : CB_BAR(s->cb_cis_space-1); m->map = 0; m->flags = 0; - s->ss_entry(s->sock, SS_SetBridge, m); + s->ss_entry->set_bridge(s->sock, m); pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, 0); pci_writel(s->cap.cardbus, 0, br, 0); release_mem_region(m->start, m->stop - m->start + 1); @@ -283,20 +283,21 @@ u_char i, hdr, fn, bus = s->cap.cardbus; cb_config_t *c; + memset(&tmp, 0, sizeof(tmp)); tmp.bus = s->cap.cb_bus; tmp.devfn = 0; - tmp.next = pci_devices; pci_devices = &tmp; - pci_readw(bus, 0, PCI_VENDOR_ID, &vend); - pci_readw(bus, 0, PCI_DEVICE_ID, &dev); + + pci_read_config_word(&tmp, PCI_VENDOR_ID, &vend); + pci_read_config_word(&tmp, PCI_DEVICE_ID, &dev); printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, " "device 0x%04x\n", bus, vend, dev); - pci_readb(bus, 0, PCI_HEADER_TYPE, &hdr); + pci_read_config_byte(&tmp, PCI_HEADER_TYPE, &hdr); if (hdr & 0x80) { /* Count functions */ for (fn = 0; fn < 8; fn++) { tmp.devfn = fn; - pci_readw(bus, fn, PCI_VENDOR_ID, &v); + pci_read_config_word(&tmp, PCI_VENDOR_ID, &v); if (v != vend) break; } } else fn = 1; @@ -307,7 +308,6 @@ memset(c, 0, fn * sizeof(struct cb_config_t)); s->cb_config = c; - pci_devices = tmp.next; for (i = 0; i < fn; i++) { c[i].dev.bus = s->cap.cb_bus; c[i].dev.devfn = i; @@ -317,7 +317,7 @@ } s->cap.cb_bus->devices = &c[0].dev; /* Link into PCI device chain */ - c[s->functions-1].dev.next = pci_devices; + c[fn-1].dev.next = pci_devices; pci_devices = &c[0].dev; for (i = 0; i < fn; i++) { c[i].dev.vendor = vend; @@ -338,17 +338,20 @@ cb_config_t *c = s->cb_config; if (c) { - struct pci_dev **p, *q; + struct pci_dev **p; /* Unlink from PCI device chain */ - for (p = &pci_devices; *p; p = &((*p)->next)) - if (*p == &c[0].dev) break; - for (q = *p; q; q = q->next) { - if (q->bus != (*p)->bus) break; + p = &pci_devices; + while (*p) { + struct pci_dev * dev = *p; + if (dev->bus != s->cap.cb_bus) { + p = &dev->next; + continue; + } + *p = dev->next; #ifdef CONFIG_PROC_FS - pci_proc_detach_device(q); + pci_proc_detach_device(dev); #endif } - if (*p) *p = q; s->cap.cb_bus->devices = NULL; kfree(s->cb_config); s->cb_config = NULL; @@ -584,7 +587,7 @@ DEBUG(0, " bridge %s map %d (flags 0x%x): 0x%x-0x%x\n", (m.flags & MAP_IOSPACE) ? "io" : "mem", m.map, m.flags, m.start, m.stop); - s->ss_entry(s->sock, SS_SetBridge, &m); + s->ss_entry->set_bridge(s->sock, &m); } /* Set up base address registers */ @@ -609,7 +612,7 @@ pci_writeb(bus, i, PCI_INTERRUPT_LINE, s->irq.AssignedIRQ); s->socket.io_irq = s->irq.AssignedIRQ; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + s->ss_entry->set_socket(s->sock, &s->socket); } } @@ -638,6 +641,6 @@ case B_M1: m.map = m.flags = 0; break; case B_M2: m.map = 1; m.flags = 0; break; } - s->ss_entry(s->sock, SS_SetBridge, &m); + s->ss_entry->set_bridge(s->sock, &m); } } diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c --- v2.3.34/linux/drivers/pcmcia/cistpl.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/pcmcia/cistpl.c Tue Dec 21 11:43:21 1999 @@ -101,7 +101,7 @@ mem->card_start = addr & ~(s->cap.map_size-1); for (; len > 0; sys = s->cis_virt) { - s->ss_entry(s->sock, SS_SetMemMap, mem); + s->ss_entry->set_mem_map(s->sock, mem); DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n", bus_readb(s->cap.bus, sys), bus_readb(s->cap.bus, sys+inc), @@ -131,7 +131,7 @@ mem->card_start = addr & ~(s->cap.map_size-1); for (; len > 0; sys = s->cis_virt) { - s->ss_entry(s->sock, SS_SetMemMap, mem); + s->ss_entry->set_mem_map(s->sock, mem); for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) { if (sys == s->cis_virt+s->cap.map_size) break; bus_writeb(s->cap.bus, *(u_char *)ptr, sys); @@ -181,7 +181,7 @@ vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size); vs->cis_mem.card_start = 0; vs->cis_mem.flags = MAP_ACTIVE; - vs->ss_entry(vs->sock, SS_SetMemMap, &vs->cis_mem); + vs->ss_entry->set_mem_map(vs->sock, &vs->cis_mem); /* Don't bother checking every word... */ a = 0; b = -1; for (i = 0; i < vs->cap.map_size; i += 44) { @@ -223,7 +223,7 @@ { if (s->cis_mem.sys_start != 0) { s->cis_mem.flags &= ~MAP_ACTIVE; - s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem); + s->ss_entry->set_mem_map(s->sock, &s->cis_mem); release_mem_region(s->cis_mem.sys_start, s->cap.map_size); bus_iounmap(s->cap.bus, s->cis_virt); s->cis_mem.sys_start = 0; diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.3.34/linux/drivers/pcmcia/cs.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/pcmcia/cs.c Tue Dec 21 21:18:54 1999 @@ -242,6 +242,42 @@ /*====================================================================== + These functions are just shorthand for the actual low-level drivers + +======================================================================*/ + +static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info) +{ + return s->ss_entry->register_callback(s->sock, handler, info); +} + +static int get_socket_status(socket_info_t *s, int *val) +{ + return s->ss_entry->get_status(s->sock, val); +} + +static int set_socket(socket_info_t *s, socket_state_t *state) +{ + return s->ss_entry->set_socket(s->sock, state); +} + +static int get_io_map(socket_info_t *s, struct pccard_io_map *io) +{ + return s->ss_entry->get_io_map(s->sock, io); +} + +static int set_io_map(socket_info_t *s, struct pccard_io_map *io) +{ + return s->ss_entry->set_io_map(s->sock, io); +} + +static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem) +{ + return s->ss_entry->set_mem_map(s->sock, mem); +} + +/*====================================================================== + Reset a socket to the default state ======================================================================*/ @@ -254,14 +290,14 @@ mem.sys_stop = s->cap.map_size; s->socket = dead_socket; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); for (i = 0; i < 2; i++) { io.map = i; - s->ss_entry(s->sock, SS_SetIOMap, &io); + set_io_map(s, &io); } for (i = 0; i < 5; i++) { mem.map = i; - s->ss_entry(s->sock, SS_SetMemMap, &mem); + set_mem_map(s, &mem); } } @@ -295,7 +331,7 @@ static void unreset_socket(u_long i); static void parse_events(void *info, u_int events); -int register_ss_entry(int nsock, ss_entry_t ss_entry) +int register_ss_entry(int nsock, struct pccard_operations * ss_entry) { int i, ns; socket_info_t *s; @@ -324,7 +360,7 @@ if (i == sockets) sockets++; init_socket(s); - ss_entry(ns, SS_InquireSocket, &s->cap); + ss_entry->inquire_socket(ns, &s->cap); #ifdef CONFIG_PROC_FS if (proc_pccard) { char name[3]; @@ -333,7 +369,7 @@ #ifdef PCMCIA_DEBUG create_proc_read_entry("clients",0,s->proc,proc_read_clients,s); #endif - ss_entry(ns, SS_ProcSetup, s->proc); + ss_entry->proc_setup(ns, s->proc); } #endif } @@ -343,7 +379,7 @@ /*====================================================================*/ -void unregister_ss_entry(ss_entry_t ss_entry) +void unregister_ss_entry(struct pccard_operations * ss_entry) { int i, j; socket_info_t *s = NULL; @@ -454,7 +490,7 @@ int val; socket_info_t *s = socket_table[i]; - s->ss_entry(s->sock, SS_GetStatus, &val); + get_socket_status(s, &val); if (val & SS_DETECT) { DEBUG(1, "cs: setup_socket(%ld): applying power\n", i); s->state |= SOCKET_PRESENT; @@ -474,7 +510,7 @@ printk(KERN_NOTICE "cs: unsupported card type detected!\n"); #endif } - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); s->setup.function = &reset_socket; s->setup.expires = jiffies + vcc_settle; add_timer(&s->setup); @@ -497,10 +533,10 @@ DEBUG(1, "cs: resetting socket %ld\n", i); s->socket.flags |= SS_OUTPUT_ENA | SS_RESET; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); udelay((long)reset_time); s->socket.flags &= ~SS_RESET; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); s->unreset_timeout = 0; s->setup.expires = jiffies + unreset_delay; s->setup.function = &unreset_socket; @@ -515,7 +551,7 @@ socket_info_t *s = socket_table[i]; int val; - s->ss_entry(s->sock, SS_GetStatus, &val); + get_socket_status(s, &val); if (val & SS_READY) { DEBUG(1, "cs: reset done on socket %ld\n", i); if (s->state & SOCKET_SUSPEND) { @@ -607,7 +643,7 @@ int status; u_long flags; spin_lock_irqsave(&s->lock, flags); - s->ss_entry(s->sock, SS_GetStatus, &status); + get_socket_status(s, &status); if ((s->state & SOCKET_PRESENT) && (!(s->state & SOCKET_SUSPEND) || !(status & SS_DETECT))) @@ -668,7 +704,7 @@ if ((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)){ send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); - s->ss_entry(s->sock, SS_SetSocket, &dead_socket); + set_socket(s, &dead_socket); s->state |= SOCKET_SUSPEND; } } @@ -685,7 +721,7 @@ s = socket_table[i]; /* Do this just to reinitialize the socket */ init_socket(s); - s->ss_entry(s->sock, SS_GetStatus, &stat); + get_socket_status(s, &stat); /* If there was or is a card here, we need to do something about it... but parse_events will sort it all out. */ if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT)) @@ -939,7 +975,7 @@ } if (--s->real_clients == 0) - s->ss_entry(sn, SS_RegisterCallback, NULL); + register_callback(s, NULL, NULL); return CS_SUCCESS; } /* deregister_client */ @@ -1134,7 +1170,7 @@ if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); - s->ss_entry(s->sock, SS_GetStatus, &val); + get_socket_status(s, &val); status->CardState = status->SocketState = 0; status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; @@ -1213,7 +1249,7 @@ return CS_BAD_PAGE; s = win->sock; win->ctl.card_start = req->CardOffset; - if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0) + if (set_mem_map(s, &win->ctl) != 0) return CS_BAD_OFFSET; return CS_SUCCESS; } /* map_mem_page */ @@ -1246,7 +1282,7 @@ c->Attributes &= ~CONF_ENABLE_IRQ; s->socket.io_irq = 0; } - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) @@ -1258,7 +1294,7 @@ if (mod->Vpp1 != mod->Vpp2) return CS_BAD_VPP; c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; - if (s->ss_entry(s->sock, SS_SetSocket, &s->socket)) + if (set_socket(s, &s->socket)) return CS_BAD_VPP; } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) @@ -1288,7 +1324,7 @@ if (req->Attributes & WIN_USE_WAIT) win->ctl.flags |= MAP_USE_WAIT; win->ctl.speed = req->AccessSpeed; - win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl); + set_mem_map(win->sock, &win->ctl); return CS_SUCCESS; } /* modify_window */ @@ -1324,12 +1360,9 @@ s = socket_table[ns]; if (++s->real_clients == 1) { - ss_callback_t call; int status; - call.handler = &parse_events; - call.info = s; - s->ss_entry(ns, SS_RegisterCallback, &call); - s->ss_entry(ns, SS_GetStatus, &status); + register_callback(s, &parse_events, s); + get_socket_status(s, &status); if ((status & SS_DETECT) && !(s->state & SOCKET_SETUP_PENDING)) { s->state |= SOCKET_SETUP_PENDING; @@ -1405,7 +1438,7 @@ s->socket.flags = SS_OUTPUT_ENA; s->socket.Vpp = 0; s->socket.io_irq = 0; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); } if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { @@ -1415,9 +1448,9 @@ if (s->io[i].Config != 0) continue; io.map = i; - s->ss_entry(s->sock, SS_GetIOMap, &io); + get_io_map(s, &io); io.flags &= ~MAP_ACTIVE; - s->ss_entry(s->sock, SS_SetIOMap, &io); + set_io_map(s, &io); } c->state &= ~CONFIG_LOCKED; } @@ -1520,7 +1553,7 @@ /* Shut down memory window */ win->ctl.flags &= ~MAP_ACTIVE; - s->ss_entry(s->sock, SS_SetMemMap, &win->ctl); + set_mem_map(s, &win->ctl); s->state &= ~SOCKET_WIN_REQ(win->index); /* Release system memory */ @@ -1574,7 +1607,7 @@ if (req->Vpp1 != req->Vpp2) return CS_BAD_VPP; s->socket.Vpp = req->Vpp1; - if (s->ss_entry(s->sock, SS_SetSocket, &s->socket)) + if (set_socket(s, &s->socket)) return CS_BAD_VPP; c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; @@ -1592,7 +1625,7 @@ s->socket.io_irq = s->irq.AssignedIRQ; else s->socket.io_irq = 0; - s->ss_entry(s->sock, SS_SetSocket, &s->socket); + set_socket(s, &s->socket); s->lock_count++; /* Set up CIS configuration registers */ @@ -1655,7 +1688,7 @@ } iomap.start = s->io[i].BasePort; iomap.stop = iomap.start + s->io[i].NumPorts - 1; - s->ss_entry(s->sock, SS_SetIOMap, &iomap); + set_io_map(s, &iomap); s->io[i].Config++; } } @@ -1871,7 +1904,7 @@ win->ctl.sys_start = req->Base; win->ctl.sys_stop = req->Base + req->Size-1; win->ctl.card_start = 0; - if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0) + if (set_mem_map(s, &win->ctl) != 0) return CS_BAD_ARGS; s->state |= SOCKET_WIN_REQ(w); @@ -1939,7 +1972,7 @@ DEBUG(1, "cs: suspending socket %d\n", i); send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); - s->ss_entry(s->sock, SS_SetSocket, &dead_socket); + set_socket(s, &dead_socket); s->state |= SOCKET_SUSPEND; return CS_SUCCESS; @@ -2014,7 +2047,7 @@ if (!(s->state & SOCKET_SETUP_PENDING)) { s->state |= SOCKET_SETUP_PENDING; spin_unlock_irqrestore(&s->lock, flags); - s->ss_entry(i, SS_GetStatus, &status); + get_socket_status(s, &status); if (status & SS_DETECT) setup_socket(i); else { diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h --- v2.3.34/linux/drivers/pcmcia/cs_internal.h Thu Nov 18 20:25:37 1999 +++ linux/drivers/pcmcia/cs_internal.h Tue Dec 28 17:43:36 1999 @@ -120,7 +120,7 @@ typedef struct socket_info_t { spinlock_t lock; - ss_entry_t ss_entry; + struct pccard_operations * ss_entry; u_int sock; socket_state_t socket; socket_cap_t cap; diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c --- v2.3.34/linux/drivers/pcmcia/i82365.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/pcmcia/i82365.c Sun Dec 26 12:33:09 1999 @@ -66,7 +66,7 @@ #include "o2micro.h" /* PCI-bus controllers */ -#include "yenta.h" +#include "old-yenta.h" #include "ti113x.h" #include "smc34c90.h" #include "topic.h" @@ -159,8 +159,6 @@ #ifdef CONFIG_PCI /* Scan PCI bus? */ static int do_pci_probe = 1; -/* Default memory base address for CardBus controllers */ -static u_int cb_mem_base[] = { 0x68000000, 0xf8000000 }; static int fast_pci = -1; static int hold_time = -1; /* Override BIOS interrupt routing mode? */ @@ -173,7 +171,6 @@ static int cb_bus_step = 2; static int cb_write_post = -1; MODULE_PARM(do_pci_probe, "i"); -MODULE_PARM(cb_mem_base, "i"); MODULE_PARM(fast_pci, "i"); MODULE_PARM(hold_time, "i"); MODULE_PARM(irq_mode, "i"); @@ -249,11 +246,11 @@ struct proc_dir_entry *proc; #endif #ifdef CONFIG_PCI - u_short vendor, device; - u_char revision, bus, devfn; + struct pci_dev *pdev; + u_char revision; u_short bcr; u_char pci_lat, cb_lat, sub_bus; - u_char cache, pmcs; + u_char cache; u_int cb_phys; char *cb_virt; #endif @@ -294,24 +291,10 @@ /*====================================================================*/ -#ifdef CONFIG_PCI - -#ifndef PCI_VENDOR_ID_INTEL -#define PCI_VENDOR_ID_INTEL 0x8086 -#endif -#ifndef PCI_VENDOR_ID_OMEGA -#define PCI_VENDOR_ID_OMEGA 0x119b -#endif -#ifndef PCI_DEVICE_ID_OMEGA_PCMCIA -#define PCI_DEVICE_ID_OMEGA_PCMCIA 0x1221 -#endif - /* Default settings for PCI command configuration register */ #define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \ PCI_COMMAND_MASTER|PCI_COMMAND_WAIT) -#endif - /* These definitions must match the pcic table! */ typedef enum pcic_id { #ifdef CONFIG_ISA @@ -379,9 +362,9 @@ { "O2Micro OZ6730", IS_O2MICRO|IS_PCI|IS_VG_PWR, PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6730 }, { "Intel 82092AA", IS_PCI, - PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_OMEGA_PCMCIA }, + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0 }, { "Omega Micro 82C092G", IS_PCI, - PCI_VENDOR_ID_OMEGA, PCI_DEVICE_ID_OMEGA_PCMCIA }, + PCI_VENDOR_ID_OMEGA, PCI_DEVICE_ID_OMEGA_82C092G }, { "Cirrus PD6832", IS_CIRRUS|IS_CARDBUS, PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832 }, { "O2Micro OZ6832/OZ6833", IS_O2MICRO|IS_CARDBUS|IS_VG_PWR, @@ -443,12 +426,12 @@ /* Some PCI shortcuts */ -#define pci_readb pcibios_read_config_byte -#define pci_writeb pcibios_write_config_byte -#define pci_readw pcibios_read_config_word -#define pci_writew pcibios_write_config_word -#define pci_readl pcibios_read_config_dword -#define pci_writel pcibios_write_config_dword +#define config_readb(sock, r, v) pci_read_config_byte((sock)->pdev, r, v) +#define config_readw(sock, r, v) pci_read_config_word((sock)->pdev, r, v) +#define config_readl(sock, r, v) pci_read_config_dword((sock)->pdev, r, v) +#define config_writeb(sock, r, v) pci_write_config_byte((sock)->pdev, r, v) +#define config_writew(sock, r, v) pci_write_config_word((sock)->pdev, r, v) +#define config_writel(sock, r, v) pci_write_config_dword((sock)->pdev, r, v) #define cb_readb(s, r) readb(socket[s].cb_virt + (r)) #define cb_readl(s, r) readl(socket[s].cb_virt + (r)) @@ -701,21 +684,21 @@ { socket_info_t *t = &socket[s]; ti113x_state_t *p = &socket[s].state.ti113x; - pci_readl(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, &p->sysctl); - pci_readb(t->bus, t->devfn, TI113X_CARD_CONTROL, &p->cardctl); - pci_readb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, &p->devctl); - pci_readb(t->bus, t->devfn, TI1250_DIAGNOSTIC, &p->diag); + config_readl(t, TI113X_SYSTEM_CONTROL, &p->sysctl); + config_readb(t, TI113X_CARD_CONTROL, &p->cardctl); + config_readb(t, TI113X_DEVICE_CONTROL, &p->devctl); + config_readb(t, TI1250_DIAGNOSTIC, &p->diag); } static void ti113x_set_state(u_short s) { socket_info_t *t = &socket[s]; ti113x_state_t *p = &socket[s].state.ti113x; - pci_writel(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, p->sysctl); - pci_writeb(t->bus, t->devfn, TI113X_CARD_CONTROL, p->cardctl); - pci_writeb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, p->devctl); - pci_writeb(t->bus, t->devfn, TI1250_MULTIMEDIA_CTL, 0); - pci_writeb(t->bus, t->devfn, TI1250_DIAGNOSTIC, p->diag); + config_writel(t, TI113X_SYSTEM_CONTROL, p->sysctl); + config_writeb(t, TI113X_CARD_CONTROL, p->cardctl); + config_writeb(t, TI113X_DEVICE_CONTROL, p->devctl); + config_writeb(t, TI1250_MULTIMEDIA_CTL, 0); + config_writeb(t, TI1250_DIAGNOSTIC, p->diag); i365_set_pair(s, TI113X_IO_OFFSET(0), 0); i365_set_pair(s, TI113X_IO_OFFSET(1), 0); } @@ -822,20 +805,20 @@ { socket_info_t *t = &socket[s]; rl5c4xx_state_t *p = &socket[s].state.rl5c4xx; - pci_readw(t->bus, t->devfn, RL5C4XX_MISC, &p->misc); - pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_CTL, &p->ctl); - pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, &p->io); - pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, &p->mem); + config_readw(t, RL5C4XX_MISC, &p->misc); + config_readw(t, RL5C4XX_16BIT_CTL, &p->ctl); + config_readw(t, RL5C4XX_16BIT_IO_0, &p->io); + config_readw(t, RL5C4XX_16BIT_MEM_0, &p->mem); } static void rl5c4xx_set_state(u_short s) { socket_info_t *t = &socket[s]; rl5c4xx_state_t *p = &socket[s].state.rl5c4xx; - pci_writew(t->bus, t->devfn, RL5C4XX_MISC, p->misc); - pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_CTL, p->ctl); - pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, p->io); - pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, p->mem); + config_writew(t, RL5C4XX_MISC, p->misc); + config_writew(t, RL5C4XX_16BIT_CTL, p->ctl); + config_writew(t, RL5C4XX_16BIT_IO_0, p->io); + config_writew(t, RL5C4XX_16BIT_MEM_0, p->mem); } static u_int __init rl5c4xx_set_opts(u_short s, char *buf) @@ -986,20 +969,20 @@ { socket_info_t *t = &socket[s]; topic_state_t *p = &socket[s].state.topic; - pci_readb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, &p->slot); - pci_readb(t->bus, t->devfn, TOPIC_CARD_CONTROL, &p->ccr); - pci_readb(t->bus, t->devfn, TOPIC_CARD_DETECT, &p->cdr); - pci_readl(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, &p->rcr); + config_readb(t, TOPIC_SLOT_CONTROL, &p->slot); + config_readb(t, TOPIC_CARD_CONTROL, &p->ccr); + config_readb(t, TOPIC_CARD_DETECT, &p->cdr); + config_readl(t, TOPIC_REGISTER_CONTROL, &p->rcr); } static void topic_set_state(u_short s) { socket_info_t *t = &socket[s]; topic_state_t *p = &socket[s].state.topic; - pci_writeb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, p->slot); - pci_writeb(t->bus, t->devfn, TOPIC_CARD_CONTROL, p->ccr); - pci_writeb(t->bus, t->devfn, TOPIC_CARD_DETECT, p->cdr); - pci_writel(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, p->rcr); + config_writeb(t, TOPIC_SLOT_CONTROL, p->slot); + config_writeb(t, TOPIC_CARD_CONTROL, p->ccr); + config_writeb(t, TOPIC_CARD_DETECT, p->cdr); + config_writel(t, TOPIC_REGISTER_CONTROL, p->rcr); } static int topic_set_irq_mode(u_short s, int pcsc, int pint) @@ -1040,33 +1023,28 @@ { socket_info_t *t = &socket[s]; - pci_readb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, &t->cache); - pci_readb(t->bus, t->devfn, PCI_LATENCY_TIMER, &t->pci_lat); - pci_readb(t->bus, t->devfn, CB_LATENCY_TIMER, &t->cb_lat); - pci_readb(t->bus, t->devfn, CB_CARDBUS_BUS, &t->cap.cardbus); - pci_readb(t->bus, t->devfn, CB_SUBORD_BUS, &t->sub_bus); - pci_readw(t->bus, t->devfn, CB_BRIDGE_CONTROL, &t->bcr); - { - struct pci_dev *pdev = pci_find_slot(t->bus, t->devfn); - t->cap.pci_irq = (pdev) ? pdev->irq : 0; - } - if (t->cap.pci_irq >= NR_IRQS) t->cap.pci_irq = 0; + config_readb(t, PCI_CACHE_LINE_SIZE, &t->cache); + config_readb(t, PCI_LATENCY_TIMER, &t->pci_lat); + config_readb(t, CB_LATENCY_TIMER, &t->cb_lat); + config_readb(t, CB_CARDBUS_BUS, &t->cap.cardbus); + config_readb(t, CB_SUBORD_BUS, &t->sub_bus); + config_readw(t, CB_BRIDGE_CONTROL, &t->bcr); + t->cap.pci_irq = t->pdev->irq; } static void cb_set_state(u_short s) { socket_info_t *t = &socket[s]; - if (t->pmcs) - pci_writew(t->bus, t->devfn, t->pmcs, PCI_PMCS_PWR_STATE_D0); - pci_writel(t->bus, t->devfn, CB_LEGACY_MODE_BASE, 0); - pci_writel(t->bus, t->devfn, PCI_BASE_ADDRESS_0, t->cb_phys); - pci_writew(t->bus, t->devfn, PCI_COMMAND, CMD_DFLT); - pci_writeb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, t->cache); - pci_writeb(t->bus, t->devfn, PCI_LATENCY_TIMER, t->pci_lat); - pci_writeb(t->bus, t->devfn, CB_LATENCY_TIMER, t->cb_lat); - pci_writeb(t->bus, t->devfn, CB_CARDBUS_BUS, t->cap.cardbus); - pci_writeb(t->bus, t->devfn, CB_SUBORD_BUS, t->sub_bus); - pci_writew(t->bus, t->devfn, CB_BRIDGE_CONTROL, t->bcr); + pci_set_power_state(t->pdev, 0); /* FIXME: Do we really need all of this? */ + config_writel(t, CB_LEGACY_MODE_BASE, 0); + config_writel(t, PCI_BASE_ADDRESS_0, t->cb_phys); + config_writew(t, PCI_COMMAND, CMD_DFLT); + config_writeb(t, PCI_CACHE_LINE_SIZE, t->cache); + config_writeb(t, PCI_LATENCY_TIMER, t->pci_lat); + config_writeb(t, CB_LATENCY_TIMER, t->cb_lat); + config_writeb(t, CB_CARDBUS_BUS, t->cap.cardbus); + config_writeb(t, CB_SUBORD_BUS, t->sub_bus); + config_writew(t, CB_BRIDGE_CONTROL, t->bcr); } static int cb_get_irq_mode(u_short s) @@ -1500,13 +1478,11 @@ printk(KERN_INFO " %s", pcic[type].name); #ifdef CONFIG_PCI if (t->flags & IS_UNKNOWN) - printk(" [0x%04x 0x%04x]", t->vendor, t->device); + printk(" [0x%04x 0x%04x]", t->pdev->vendor, t->pdev->device); if (t->flags & IS_CARDBUS) - printk(" PCI-to-CardBus at bus %d slot %d, mem 0x%08x", - t->bus, PCI_SLOT(t->devfn), t->cb_phys); + printk(" PCI-to-CardBus at %s, mem 0x%08x", t->pdev->slot_name, t->cb_phys); else if (t->flags & IS_PCI) - printk(" PCI-to-PCMCIA at bus %d slot %d, port %#x", - t->bus, PCI_SLOT(t->devfn), t->ioaddr); + printk(" PCI-to-PCMCIA at %s, port %#x", t->pdev->slot_name, t->ioaddr); else #endif printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x", @@ -1596,107 +1572,50 @@ #ifdef CONFIG_PCI -typedef struct pci_dev *pci_id_t; -static int __init pci_lookup(u_int class, pci_id_t *id, - u_char *bus, u_char *devfn) -{ - if ((*id = pci_find_class(class<<8, *id)) != NULL) { - *bus = (*id)->bus->number; - *devfn = (*id)->devfn; - return 0; - } else return -1; -} - -static void __init add_pci_bridge(int type, u_char bus, u_char devfn, - u_short v, u_short d) +static void __init add_pci_bridge(int type, struct pci_dev *dev) { socket_info_t *s = &socket[sockets]; u_short i, ns; - u_int addr; + u32 addr = dev->resource[0].start; if (type == PCIC_COUNT) type = IS_UNK_PCI; - pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &addr); - addr &= ~0x1; - pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT); + pci_write_config_word(dev, PCI_COMMAND, CMD_DFLT); for (i = ns = 0; i < ((type == IS_I82092AA) ? 4 : 2); i++) { - s->bus = bus; s->devfn = devfn; - s->vendor = v; s->device = d; + s->pdev = dev; add_socket(addr, i, type); ns++; s++; } add_pcic(ns, type); } -static void __init add_cb_bridge(int type, u_char bus, u_char devfn, - u_short v, u_short d0) +static void __init add_cb_bridge(int type, struct pci_dev *dev0) { socket_info_t *s = &socket[sockets]; - u_short d, ns, i; - u_char a, b, r, max; + u_short i, ns; + u_char a, b; - /* PCI bus enumeration is broken on some systems */ - for (ns = 0; ns < sockets; ns++) - if ((socket[ns].bus == bus) && (socket[ns].devfn == devfn)) - return; - - if (type == PCIC_COUNT) type = IS_UNK_CARDBUS; - pci_readb(bus, devfn, PCI_HEADER_TYPE, &a); - pci_readb(bus, devfn, PCI_CLASS_REVISION, &r); - max = (a & 0x80) ? 8 : 1; - for (ns = 0; ns < max; ns++, s++, devfn++) { - if (pci_readw(bus, devfn, PCI_DEVICE_ID, &d) || (d != d0)) - break; - s->bus = bus; s->devfn = devfn; - s->vendor = v; s->device = d; s->revision = r; - - /* Check for power management capabilities */ - pci_readb(bus, devfn, PCI_STATUS, &a); - if (a & PCI_STATUS_CAPLIST) { - pci_readb(bus, devfn, PCI_CB_CAPABILITY_POINTER, &b); - while (b != 0) { - pci_readb(bus, devfn, b+PCI_CAPABILITY_ID, &a); - if (a == PCI_CAPABILITY_PM) { - s->pmcs = b + PCI_PM_CONTROL_STATUS; - break; - } - pci_readb(bus, devfn, b+PCI_NEXT_CAPABILITY, &b); - } - } - /* If capability exists, make sure we're in D0 state */ - if (s->pmcs) - pci_writew(bus, devfn, s->pmcs, PCI_PMCS_PWR_STATE_D0); - - /* Map CardBus registers if they are not already mapped */ - pci_writel(bus, devfn, CB_LEGACY_MODE_BASE, 0); - pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &s->cb_phys); - if (s->cb_phys == 0) { - pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT); - for (i = 0; i < sizeof(cb_mem_base)/sizeof(u_int); i++) { - s->cb_phys = cb_mem_base[i]; - s->cb_virt = ioremap(s->cb_phys, 0x1000); - pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, s->cb_phys); - /* Simple sanity checks */ - if (!(readb(s->cb_virt+0x800+I365_IDENT) & 0x70) && - !(readb(s->cb_virt+0x800+I365_CSC) && - readb(s->cb_virt+0x800+I365_CSC) && - readb(s->cb_virt+0x800+I365_CSC))) - break; - iounmap(s->cb_virt); - } - if (i == sizeof(cb_mem_base)/sizeof(u_int)) { - pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, 0); - s->cb_phys = 0; s->cb_virt = NULL; - printk("\n"); - printk(KERN_NOTICE " Bridge register mapping failed:" - " check cb_mem_base setting\n"); + if (type == PCIC_COUNT) + type = IS_UNK_CARDBUS; + + for (ns = 0; ns < 8; ns++, s++) { + struct pci_dev *dev; + + dev = pci_find_slot(dev0->bus->number, dev0->devfn + ns); + if (!dev) break; - } - cb_mem_base[0] = cb_mem_base[i] + PAGE_SIZE; - } else { - s->cb_virt = ioremap(s->cb_phys, 0x1000); + s->pdev = dev; + pci_read_config_byte(dev, PCI_CLASS_REVISION, &s->revision); + + /* Map CardBus registers if they are not already mapped */ + pci_write_config_dword(dev, CB_LEGACY_MODE_BASE, 0); + s->cb_phys = dev->resource[0].start; + if (!s->cb_phys || !(s->cb_virt = ioremap(s->cb_phys, 0x1000))) { + printk("\n"); + printk(KERN_ERR " No control registers found!\n"); + break; } - request_mem_region(s->cb_phys, 0x1000, "i82365"); + s->cap.cb_bus = dev->subordinate; add_socket(0, 0, type); } if (ns == 0) return; @@ -1704,11 +1623,11 @@ s -= ns; if (ns == 2) { /* Nasty special check for bad bus mapping */ - pci_readb(bus, s[0].devfn, CB_CARDBUS_BUS, &a); - pci_readb(bus, s[1].devfn, CB_CARDBUS_BUS, &b); + config_readb(&s[0], CB_CARDBUS_BUS, &a); + config_readb(&s[1], CB_CARDBUS_BUS, &b); if (a == b) { - pci_writeb(bus, s[0].devfn, CB_CARDBUS_BUS, 0); - pci_writeb(bus, s[1].devfn, CB_CARDBUS_BUS, 0); + config_writeb(&s[0], CB_CARDBUS_BUS, 0); + config_writeb(&s[1], CB_CARDBUS_BUS, 0); } } add_pcic(ns, type); @@ -1728,43 +1647,19 @@ if (i == 200) printk(KERN_NOTICE "i82365: card voltage interrogation" " timed out!\n"); - - /* Set up PCI bus bridge structures if needed */ - for (a = 0; a < ns; a++) { - struct pci_dev *self = pci_find_slot(bus, s[a].devfn); - struct pci_bus *child, *parent = self->bus; - for (child = parent->children; child; child = child->next) - if (child->number == s[a].cap.cardbus) break; - if (!child) { - child = kmalloc(sizeof(struct pci_bus), GFP_KERNEL); - memset(child, 0, sizeof(struct pci_bus)); - child->self = self; - child->primary = bus; - child->number = child->secondary = s[a].cap.cardbus; - child->subordinate = s[a].sub_bus; - child->parent = parent; - child->ops = parent->ops; - child->next = parent->children; - } - s[a].cap.cb_bus = parent->children = child; - } } -static void __init pci_probe(u_int class, void (add_fn) - (int, u_char, u_char, u_short, u_short)) -{ - u_short i, v, d; - u_char bus, devfn; - pci_id_t id; - - id = 0; - while (pci_lookup(class, &id, &bus, &devfn) == 0) { - if (PCI_FUNC(devfn) != 0) continue; - pci_readw(bus, devfn, PCI_VENDOR_ID, &v); - pci_readw(bus, devfn, PCI_DEVICE_ID, &d); +static void __init pci_probe(u_int class, void (add_fn)(int, struct pci_dev *)) +{ + struct pci_dev *dev = NULL; + u_short i; + + while ((dev = pci_find_class(class << 8, dev))) { + pci_enable_device(dev); + if (PCI_FUNC(dev->devfn) != 0) continue; for (i = 0; i < PCIC_COUNT; i++) - if ((pcic[i].vendor == v) && (pcic[i].device == d)) break; - add_fn(i, bus, devfn, v, d); + if ((pcic[i].vendor == dev->vendor) && (pcic[i].device == dev->device)) break; + add_fn(i, dev); } } @@ -1887,22 +1782,21 @@ /*====================================================================*/ -static int pcic_register_callback(u_short sock, ss_callback_t *call) +static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info) { - if (call == NULL) { - socket[sock].handler = NULL; + socket[sock].handler = handler; + socket[sock].info = info; + if (handler == NULL) { MOD_DEC_USE_COUNT; } else { MOD_INC_USE_COUNT; - socket[sock].handler = call->handler; - socket[sock].info = call->info; } return 0; } /* pcic_register_callback */ /*====================================================================*/ -static int pcic_inquire_socket(u_short sock, socket_cap_t *cap) +static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap) { *cap = socket[sock].cap; return 0; @@ -2398,7 +2292,7 @@ u_short bcr; cb_get_power(sock, state); - pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr); + config_readw(s, CB_BRIDGE_CONTROL, &bcr); state->flags |= (bcr & CB_BCR_CB_RESET) ? SS_RESET : 0; if (cb_get_irq_mode(sock) != 0) state->io_irq = s->cap.pci_irq; @@ -2414,7 +2308,7 @@ { socket_info_t *s = &socket[sock]; u_int reg; - + DEBUG(1, "yenta: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, state->Vcc, state->Vpp, state->io_irq, state->csc_mask); @@ -2455,15 +2349,15 @@ if (map > 1) return -EINVAL; m->flags &= MAP_IOSPACE; map += (m->flags & MAP_IOSPACE) ? 2 : 0; - pci_readl(s->bus, s->devfn, CB_MEM_BASE(map), &m->start); - pci_readl(s->bus, s->devfn, CB_MEM_LIMIT(map), &m->stop); + config_readl(s, CB_MEM_BASE(map), &m->start); + config_readl(s, CB_MEM_LIMIT(map), &m->stop); if (m->start || m->stop) { m->flags |= MAP_ACTIVE; m->stop |= (map > 1) ? 3 : 0x0fff; } if (map > 1) { u_short bcr; - pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr); + config_readw(s, CB_BRIDGE_CONTROL, &bcr); m->flags |= (bcr & CB_BCR_PREFETCH(map)) ? MAP_PREFETCH : 0; } DEBUG(1, "yenta: GetBridge(%d, %d) = %#2.2x, %#4.4x-%#4.4x\n", @@ -2490,17 +2384,17 @@ u_short bcr; if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff)) return -EINVAL; - pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr); + config_readw(s, CB_BRIDGE_CONTROL, &bcr); bcr &= ~CB_BCR_PREFETCH(map); bcr |= (m->flags & MAP_PREFETCH) ? CB_BCR_PREFETCH(map) : 0; - pci_writew(s->bus, s->devfn, CB_BRIDGE_CONTROL, bcr); + config_writew(s, CB_BRIDGE_CONTROL, bcr); } if (m->flags & MAP_ACTIVE) { - pci_writel(s->bus, s->devfn, CB_MEM_BASE(map), m->start); - pci_writel(s->bus, s->devfn, CB_MEM_LIMIT(map), m->stop); + config_writel(s, CB_MEM_BASE(map), m->start); + config_writel(s, CB_MEM_LIMIT(map), m->stop); } else { - pci_writel(s->bus, s->devfn, CB_IO_BASE(map), 0); - pci_writel(s->bus, s->devfn, CB_IO_LIMIT(map), 0); + config_writel(s, CB_MEM_BASE(map), 0); + config_writel(s, CB_MEM_LIMIT(map), 0); } return 0; } @@ -2526,7 +2420,7 @@ #ifdef CONFIG_PCI if (s->flags & (IS_PCI|IS_CARDBUS)) p += sprintf(p, "bus: %02x\ndevfn: %02x.%1x\n", - s->bus, PCI_SLOT(s->devfn), PCI_FUNC(s->devfn)); + s->pdev->bus->number, PCI_SLOT(s->pdev->devfn), PCI_FUNC(s->pdev->devfn)); if (s->flags & IS_CARDBUS) p += sprintf(p, "cardbus: %02x\n", s->cap.cardbus); #endif @@ -2566,16 +2460,15 @@ int count, int *eof, void *data) { socket_info_t *s = data; - u_char bus = s->bus, devfn = s->devfn; char *p = buf; u_int a, b, c, d; int i; for (i = 0; i < 0xc0; i += 0x10) { - pci_readl(bus, devfn, i, &a); - pci_readl(bus, devfn, i+4, &b); - pci_readl(bus, devfn, i+8, &c); - pci_readl(bus, devfn, i+12, &d); + config_readl(s, i, &a); + config_readl(s, i+4, &b); + config_readl(s, i+8, &c); + config_readl(s, i+12, &d); p += sprintf(p, "%08x %08x %08x %08x\n", a, b, c, d); } return (p - buf); @@ -2599,9 +2492,14 @@ } #endif -static void pcic_proc_setup(u_short sock, struct proc_dir_entry *base) +static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base) { +#ifdef CONFIG_PROC_FS socket_info_t *s = &socket[sock]; + + if (s->flags & IS_ALIVE) + return; + create_proc_read_entry("info", 0, base, proc_read_info, s); create_proc_read_entry("exca", 0, base, proc_read_exca, s); #ifdef CONFIG_PCI @@ -2613,6 +2511,7 @@ create_proc_read_entry("cardbus", 0, base, proc_read_cardbus, s); #endif s->proc = base; +#endif } static void pcic_proc_remove(u_short sock) @@ -2635,68 +2534,150 @@ /*====================================================================*/ -typedef int (*subfn_t)(u_short, void *); +/* + * This looks like a lot of duplication, and it is. What we should REALLY + * have is separate functions for the separate cases, instead of having + * duplicate tests in them - and then have the test in the place that sets + * up the ss_entry function pointer table instead! + * + * For example, the IS_CARDBUS thing is something we know _statically_, + * and as such it is a waste of time and space to test it dynamically. + * + * Much of this goes away by splitting off the cases. One small step at a + * time.. + */ -static subfn_t pcic_service_table[] = { - (subfn_t)&pcic_register_callback, - (subfn_t)&pcic_inquire_socket, - (subfn_t)&i365_get_status, - (subfn_t)&i365_get_socket, - (subfn_t)&i365_set_socket, - (subfn_t)&i365_get_io_map, - (subfn_t)&i365_set_io_map, - (subfn_t)&i365_get_mem_map, - (subfn_t)&i365_set_mem_map, #ifdef CONFIG_CARDBUS - (subfn_t)&cb_get_bridge, - (subfn_t)&cb_set_bridge, +#define is_cardbus(sock) ((socket[(sock)].flags & IS_CARDBUS) && (cb_readl((sock), CB_SOCKET_STATE) & CB_SS_32BIT)) +#endif + +/* + * The locking is rather broken. Why do we only lock for ISA, not for + * all other cases? If there are reasons to lock, we should lock. Not + * this silly conditional. + * + * Plan: make it bug-for-bug compatible with the old stuff, and clean + * it up when the infrastructure is done. + */ +#ifdef CONFIG_ISA +#define LOCKED(x) do { \ + if (socket[(sock)].flags & IS_CARDBUS) return x; \ + do { \ + int retval; \ + unsigned long flags; \ + spin_lock_irqsave(&isa_lock, flags); \ + retval = x; \ + spin_unlock_irqrestore(&isa_lock, flags); \ + return retval; \ + } while (0); \ +} while (0) #else - NULL, NULL, +#define LOCKED(x) return x #endif -#ifdef CONFIG_PROC_FS - (subfn_t)&pcic_proc_setup + + +static int pcic_get_status(unsigned int sock, u_int *value) +{ + if (socket[sock].flags & IS_ALIVE) { + *value = 0; + return -EINVAL; + } + +#ifdef CONFIG_CARDBUS + if (is_cardbus(sock)) + return cb_get_status(sock, value); #endif -}; + LOCKED(i365_get_status(sock, value)); +} + +static int pcic_get_socket(unsigned int sock, socket_state_t *state) +{ + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; -#define NFUNC (sizeof(pcic_service_table)/sizeof(subfn_t)) +#ifdef CONFIG_CARDBUS + if (is_cardbus(sock)) + return cb_get_socket(sock, state); +#endif + LOCKED(i365_get_socket(sock, state)); +} -static int pcic_service(u_int sock, u_int cmd, void *arg) +static int pcic_set_socket(unsigned int sock, socket_state_t *state) { - subfn_t fn; - int ret; -#ifdef CONFIG_ISA - u_long flags = 0; + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; + +#ifdef CONFIG_CARDBUS + if (is_cardbus(sock)) + return cb_set_socket(sock, state); #endif - - DEBUG(2, "pcic_ioctl(%d, %d, 0x%p)\n", sock, cmd, arg); + LOCKED(i365_set_socket(sock, state)); +} - if (cmd >= NFUNC) - return -EINVAL; +static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io) +{ + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; + + LOCKED(i365_get_io_map(sock, io)); +} + +static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io) +{ + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; + + LOCKED(i365_set_io_map(sock, io)); +} + +static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) +{ + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; + + LOCKED(i365_get_mem_map(sock, mem)); +} + +static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) +{ + if (socket[sock].flags & IS_ALIVE) + return -EINVAL; + + LOCKED(i365_set_mem_map(sock, mem)); +} - if (socket[sock].flags & IS_ALIVE) { - if (cmd == SS_GetStatus) - *(u_int *)arg = 0; +static int pcic_get_bridge(unsigned int sock, struct cb_bridge_map *m) +{ +#ifdef CONFIG_CARDBUS + return cb_get_bridge(sock, m); +#else return -EINVAL; - } - - fn = pcic_service_table[cmd]; +#endif +} + +static int pcic_set_bridge(unsigned int sock, struct cb_bridge_map *m) +{ #ifdef CONFIG_CARDBUS - if ((socket[sock].flags & IS_CARDBUS) && - (cb_readl(sock, CB_SOCKET_STATE) & CB_SS_32BIT)) { - if (cmd == SS_GetStatus) - fn = (subfn_t)&cb_get_status; - else if (cmd == SS_GetSocket) - fn = (subfn_t)&cb_get_socket; - else if (cmd == SS_SetSocket) - fn = (subfn_t)&cb_set_socket; - } + return cb_set_bridge(sock, m); +#else + return -EINVAL; #endif +} - ISA_LOCK(sock, flags); - ret = (fn == NULL) ? -EINVAL : fn(sock, arg); - ISA_UNLOCK(sock, flags); - return ret; -} /* pcic_service */ +static struct pccard_operations pcic_operations = { + pcic_register_callback, + pcic_inquire_socket, + pcic_get_status, + pcic_get_socket, + pcic_set_socket, + pcic_get_io_map, + pcic_set_io_map, + pcic_get_mem_map, + pcic_set_mem_map, + pcic_get_bridge, + pcic_set_bridge, + pcic_proc_setup +}; /*====================================================================*/ @@ -2714,7 +2695,7 @@ sockets = 0; #ifdef CONFIG_PCI - if (do_pci_probe && pcibios_present()) { + if (do_pci_probe) { pci_probe(PCI_CLASS_BRIDGE_CARDBUS, add_cb_bridge); pci_probe(PCI_CLASS_BRIDGE_PCMCIA, add_pci_bridge); } @@ -2746,7 +2727,7 @@ } #endif - if (register_ss_entry(sockets, &pcic_service) != 0) + if (register_ss_entry(sockets, &pcic_operations) != 0) printk(KERN_NOTICE "i82365: register_ss_entry() failed\n"); /* Finally, schedule a polling interrupt */ @@ -2768,7 +2749,7 @@ #ifdef CONFIG_PROC_FS for (i = 0; i < sockets; i++) pcic_proc_remove(i); #endif - unregister_ss_entry(&pcic_service); + unregister_ss_entry(&pcic_operations); if (poll_interval != 0) del_timer(&poll_timer); #ifdef CONFIG_ISA @@ -2805,4 +2786,3 @@ module_exit(exit_i82365); /*====================================================================*/ - diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/old-yenta.h linux/drivers/pcmcia/old-yenta.h --- v2.3.34/linux/drivers/pcmcia/old-yenta.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/pcmcia/old-yenta.h Thu Nov 11 16:03:37 1999 @@ -0,0 +1,153 @@ +/* + * yenta.h 1.16 1999/10/25 20:03:34 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License version 2 (the "GPL"), in which + * case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + */ + +#ifndef _LINUX_YENTA_H +#define _LINUX_YENTA_H + +/* PCI Configuration Registers */ + +#define PCI_STATUS_CAPLIST 0x10 +#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */ +#define PCI_CAPABILITY_ID 0x00 /* 8 bit */ +#define PCI_CAPABILITY_PM 0x01 +#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */ +#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */ +#define PCI_PMCAP_PME_D3COLD 0x8000 +#define PCI_PMCAP_PME_D3HOT 0x4000 +#define PCI_PMCAP_PME_D2 0x2000 +#define PCI_PMCAP_PME_D1 0x1000 +#define PCI_PMCAP_PME_D0 0x0800 +#define PCI_PMCAP_D2_CAP 0x0400 +#define PCI_PMCAP_D1_CAP 0x0200 +#define PCI_PMCAP_DYN_DATA 0x0100 +#define PCI_PMCAP_DSI 0x0020 +#define PCI_PMCAP_AUX_PWR 0x0010 +#define PCI_PMCAP_PMECLK 0x0008 +#define PCI_PMCAP_VERSION_MASK 0x0007 +#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */ +#define PCI_PMCS_PME_STATUS 0x8000 +#define PCI_PMCS_DATASCALE_MASK 0x6000 +#define PCI_PMCS_DATASCALE_SHIFT 13 +#define PCI_PMCS_DATASEL_MASK 0x1e00 +#define PCI_PMCS_DATASEL_SHIFT 9 +#define PCI_PMCS_PME_ENABLE 0x0100 +#define PCI_PMCS_PWR_STATE_MASK 0x0003 +#define PCI_PMCS_PWR_STATE_D0 0x0000 +#define PCI_PMCS_PWR_STATE_D1 0x0001 +#define PCI_PMCS_PWR_STATE_D2 0x0002 +#define PCI_PMCS_PWR_STATE_D3 0x0003 +#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */ +#define PCI_PM_DATA 0x07 /* 8 bit */ + +#define CB_PRIMARY_BUS 0x18 /* 8 bit */ +#define CB_CARDBUS_BUS 0x19 /* 8 bit */ +#define CB_SUBORD_BUS 0x1a /* 8 bit */ +#define CB_LATENCY_TIMER 0x1b /* 8 bit */ + +#define CB_MEM_BASE(m) (0x1c + 8*(m)) +#define CB_MEM_LIMIT(m) (0x20 + 8*(m)) +#define CB_IO_BASE(m) (0x2c + 8*(m)) +#define CB_IO_LIMIT(m) (0x30 + 8*(m)) + +#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */ +#define CB_BCR_PARITY_ENA 0x0001 +#define CB_BCR_SERR_ENA 0x0002 +#define CB_BCR_ISA_ENA 0x0004 +#define CB_BCR_VGA_ENA 0x0008 +#define CB_BCR_MABORT 0x0020 +#define CB_BCR_CB_RESET 0x0040 +#define CB_BCR_ISA_IRQ 0x0080 +#define CB_BCR_PREFETCH(m) (0x0100 << (m)) +#define CB_BCR_WRITE_POST 0x0400 + +#define CB_LEGACY_MODE_BASE 0x44 + +/* Memory mapped registers */ + +#define CB_SOCKET_EVENT 0x0000 +#define CB_SE_CSTSCHG 0x00000001 +#define CB_SE_CCD1 0x00000002 +#define CB_SE_CCD2 0x00000004 +#define CB_SE_PWRCYCLE 0x00000008 + +#define CB_SOCKET_MASK 0x0004 +#define CB_SM_CSTSCHG 0x00000001 +#define CB_SM_CCD 0x00000006 +#define CB_SM_PWRCYCLE 0x00000008 + +#define CB_SOCKET_STATE 0x0008 +#define CB_SS_CSTSCHG 0x00000001 +#define CB_SS_CCD1 0x00000002 +#define CB_SS_CCD2 0x00000004 +#define CB_SS_PWRCYCLE 0x00000008 +#define CB_SS_16BIT 0x00000010 +#define CB_SS_32BIT 0x00000020 +#define CB_SS_CINT 0x00000040 +#define CB_SS_BADCARD 0x00000080 +#define CB_SS_DATALOST 0x00000100 +#define CB_SS_BADVCC 0x00000200 +#define CB_SS_5VCARD 0x00000400 +#define CB_SS_3VCARD 0x00000800 +#define CB_SS_XVCARD 0x00001000 +#define CB_SS_YVCARD 0x00002000 +#define CB_SS_5VSOCKET 0x10000000 +#define CB_SS_3VSOCKET 0x20000000 +#define CB_SS_XVSOCKET 0x40000000 +#define CB_SS_YVSOCKET 0x80000000 + +#define CB_SOCKET_FORCE 0x000c +#define CB_SF_CVSTEST 0x00004000 + +#define CB_SOCKET_CONTROL 0x0010 +#define CB_SC_VPP_MASK 0x00000007 +#define CB_SC_VPP_OFF 0x00000000 +#define CB_SC_VPP_12V 0x00000001 +#define CB_SC_VPP_5V 0x00000002 +#define CB_SC_VPP_3V 0x00000003 +#define CB_SC_VPP_XV 0x00000004 +#define CB_SC_VPP_YV 0x00000005 +#define CB_SC_VCC_MASK 0x00000070 +#define CB_SC_VCC_OFF 0x00000000 +#define CB_SC_VCC_5V 0x00000020 +#define CB_SC_VCC_3V 0x00000030 +#define CB_SC_VCC_XV 0x00000040 +#define CB_SC_VCC_YV 0x00000050 +#define CB_SC_CCLK_STOP 0x00000080 + +#define CB_SOCKET_POWER 0x0020 +#define CB_SP_CLK_CTRL 0x00000001 +#define CB_SP_CLK_CTRL_ENA 0x00010000 +#define CB_SP_CLK_MODE 0x01000000 +#define CB_SP_ACCESS 0x02000000 + +/* Address bits 31..24 for memory windows for 16-bit cards, + accessable only by memory mapping the 16-bit register set */ +#define CB_MEM_PAGE(map) (0x40 + (map)) + +#endif /* _LINUX_YENTA_H */ diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c --- v2.3.34/linux/drivers/pcmcia/pci_socket.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/pcmcia/pci_socket.c Thu Dec 23 00:07:09 1999 @@ -0,0 +1,212 @@ +/* + * Generic PCI pccard driver interface. + * + * (C) Copyright 1999 Linus Torvalds + * + * This implements the common parts of PCI pccard drivers, + * notably detection and infrastructure conversion (ie change + * from socket index to "struct pci_dev" etc) + * + * This does NOT implement the actual low-level driver details, + * and this has on purpose been left generic enough that it can + * be used to set up a PCI PCMCIA controller (ie non-cardbus), + * or to set up a controller. + * + * See for example the "yenta" driver for PCI cardbus controllers + * conforming to the yenta cardbus specifications. + */ +#include + +#include +#include +#include +#include + +#include + +#include + +#include "pci_socket.h" + +static struct pci_simple_probe_entry controller_list[] = { + { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, 0, 0, ¥ta_operations }, + { 0x1180, 0x0475, 0, 0, ¥ta_operations }, + { 0, 0, 0, 0, NULL } +}; + + +/* + * Arbitrary define. This is the array of active cardbus + * entries. + */ +#define MAX_SOCKETS (8) +static pci_socket_t pci_socket_array[MAX_SOCKETS]; + +/* + * Work in progress. I need to distill the _real_ differences in + * carbus drivers, and change the cardbus "op" list to match. This + * is just a direct 1:1 mapping of the pccard operations. + */ +static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info) +{ + pci_socket_t *socket = pci_socket_array + sock; + + socket->handler = handler; + socket->info = info; + if (handler) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; + return 0; +} + +static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->inquire) + return socket->op->inquire(socket, cap); + return -EINVAL; +} + +static int pci_get_status(unsigned int sock, unsigned int *value) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->get_status) + return socket->op->get_status(socket, value); + *value = 0; + return -EINVAL; +} + +static int pci_get_socket(unsigned int sock, socket_state_t *state) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->get_socket) + return socket->op->get_socket(socket, state); + return -EINVAL; +} + +static int pci_set_socket(unsigned int sock, socket_state_t *state) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->set_socket) + return socket->op->set_socket(socket, state); + return -EINVAL; +} + +static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->get_io_map) + return socket->op->get_io_map(socket, io); + return -EINVAL; +} + +static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->set_io_map) + return socket->op->set_io_map(socket, io); + return -EINVAL; +} + +static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->get_mem_map) + return socket->op->get_mem_map(socket, mem); + return -EINVAL; +} + +static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->set_mem_map) + return socket->op->set_mem_map(socket, mem); + return -EINVAL; +} + +static int pci_get_bridge(unsigned int sock, struct cb_bridge_map *m) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->get_bridge) + return socket->op->get_bridge(socket, m); + return -EINVAL; +} + +static int pci_set_bridge(unsigned int sock, struct cb_bridge_map *m) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->set_bridge) + return socket->op->set_bridge(socket, m); + return -EINVAL; +} + +static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base) +{ + pci_socket_t *socket = pci_socket_array + sock; + + if (socket->op && socket->op->proc_setup) + socket->op->proc_setup(socket, base); +} + +static struct pccard_operations pci_socket_operations = { + pci_register_callback, + pci_inquire_socket, + pci_get_status, + pci_get_socket, + pci_set_socket, + pci_get_io_map, + pci_set_io_map, + pci_get_mem_map, + pci_set_mem_map, + pci_get_bridge, + pci_set_bridge, + pci_proc_setup +}; + +static int __init pci_socket_probe(struct pci_dev *dev, int nr, const struct pci_simple_probe_entry * entry, void *data) +{ + pci_socket_t *socket = nr + pci_socket_array; + + printk("Found controller %d: %s\n", nr, dev->name); + socket->dev = dev; + socket->op = entry->dev_data; + socket->op->open(socket); + return 0; +} + +static int __init pci_socket_init(void) +{ + int sockets = pci_simple_probe(controller_list, MAX_SOCKETS, pci_socket_probe, NULL); + + if (sockets <= 0) + return -1; + register_ss_entry(sockets, &pci_socket_operations); + return 0; +} + +static void __exit pci_socket_exit(void) +{ + int i; + + unregister_ss_entry(&pci_socket_operations); + for (i = 0; i < MAX_SOCKETS; i++) { + pci_socket_t *socket = pci_socket_array + i; + + if (socket->op && socket->op->close) + socket->op->close(socket); + } +} + +module_init(pci_socket_init); +module_exit(pci_socket_exit); diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h --- v2.3.34/linux/drivers/pcmcia/pci_socket.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/pcmcia/pci_socket.h Thu Dec 23 14:55:39 1999 @@ -0,0 +1,36 @@ +/* + * drivers/pcmcia/pci_socket.h + * + * (C) Copyright 1999 Linus Torvalds + */ + +struct pci_socket_ops; + +typedef struct pci_socket { + struct pci_dev *dev; + int cb_irq, io_irq; + void *base; + void (*handler)(void *, unsigned int); + void *info; + struct pci_socket_ops *op; + socket_cap_t cap; +} pci_socket_t; + +struct pci_socket_ops { + int (*open)(struct pci_socket *); + void (*close)(struct pci_socket *); + + int (*inquire)(struct pci_socket *, socket_cap_t *cap); + int (*get_status)(struct pci_socket *, unsigned int *); + int (*get_socket)(struct pci_socket *, socket_state_t *); + int (*set_socket)(struct pci_socket *, socket_state_t *); + int (*get_io_map)(struct pci_socket *, struct pccard_io_map *); + int (*set_io_map)(struct pci_socket *, struct pccard_io_map *); + int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *); + int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *); + int (*get_bridge)(struct pci_socket *, struct cb_bridge_map *); + int (*set_bridge)(struct pci_socket *, struct cb_bridge_map *); + void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base); +}; + +extern struct pci_socket_ops yenta_operations; diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c --- v2.3.34/linux/drivers/pcmcia/tcic.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/pcmcia/tcic.c Tue Dec 21 22:02:15 1999 @@ -109,7 +109,7 @@ static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs); static void tcic_timer(u_long data); -static int tcic_service(u_int sock, u_int cmd, void *arg); +static struct pccard_operations tcic_operations; typedef struct socket_info_t { u_short psock; @@ -494,7 +494,7 @@ /* jump start interrupt handler, if needed */ tcic_interrupt(0, NULL, NULL); - if (register_ss_entry(sockets, &tcic_service) != 0) { + if (register_ss_entry(sockets, &tcic_operations) != 0) { printk(KERN_NOTICE "tcic: register_ss_entry() failed\n"); release_region(tcic_base, 16); if (cs_irq != 0) @@ -511,7 +511,7 @@ static void __exit exit_tcic(void) { u_long flags; - unregister_ss_entry(&tcic_service); + unregister_ss_entry(&tcic_operations); save_flags(flags); cli(); if (cs_irq != 0) { @@ -589,22 +589,21 @@ /*====================================================================*/ -static int tcic_register_callback(u_short lsock, ss_callback_t *call) +static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info) { - if (call == NULL) { - socket_table[lsock].handler = NULL; + socket_table[lsock].handler = handler; + socket_table[lsock].info = info; + if (handler == NULL) { MOD_DEC_USE_COUNT; } else { MOD_INC_USE_COUNT; - socket_table[lsock].handler = call->handler; - socket_table[lsock].info = call->info; } return 0; } /* tcic_register_callback */ /*====================================================================*/ -static int tcic_get_status(u_short lsock, u_int *value) +static int tcic_get_status(unsigned int lsock, u_int *value) { u_short psock = socket_table[lsock].psock; u_char reg; @@ -630,7 +629,7 @@ /*====================================================================*/ -static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap) +static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap) { *cap = tcic_cap; return 0; @@ -638,7 +637,7 @@ /*====================================================================*/ -static int tcic_get_socket(u_short lsock, socket_state_t *state) +static int tcic_get_socket(unsigned int lsock, socket_state_t *state) { u_short psock = socket_table[lsock].psock; u_char reg; @@ -691,7 +690,7 @@ /*====================================================================*/ -static int tcic_set_socket(u_short lsock, socket_state_t *state) +static int tcic_set_socket(unsigned int lsock, socket_state_t *state) { u_short psock = socket_table[lsock].psock; u_char reg; @@ -766,7 +765,7 @@ /*====================================================================*/ -static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io) +static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io) { u_short psock = socket_table[lsock].psock; u_short base, ioctl; @@ -804,7 +803,7 @@ /*====================================================================*/ -static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io) +static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io) { u_short psock = socket_table[lsock].psock; u_int addr; @@ -841,7 +840,7 @@ /*====================================================================*/ -static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem) +static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem) { u_short psock = socket_table[lsock].psock; u_short addr, ctl; @@ -886,7 +885,7 @@ /*====================================================================*/ -static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem) +static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem) { u_short psock = socket_table[lsock].psock; u_short addr, ctl; @@ -930,35 +929,31 @@ /*====================================================================*/ -typedef int (*subfn_t)(u_short, void *); - -static subfn_t service_table[] = { - (subfn_t)&tcic_register_callback, - (subfn_t)&tcic_inquire_socket, - (subfn_t)&tcic_get_status, - (subfn_t)&tcic_get_socket, - (subfn_t)&tcic_set_socket, - (subfn_t)&tcic_get_io_map, - (subfn_t)&tcic_set_io_map, - (subfn_t)&tcic_get_mem_map, - (subfn_t)&tcic_set_mem_map, -}; - -#define NFUNC (sizeof(service_table)/sizeof(subfn_t)) - -static int tcic_service(u_int lsock, u_int cmd, void *arg) +int tcic_get_bridge(unsigned int sock, struct cb_bridge_map *m) { - int err; + return -EINVAL; +} - DEBUG(2, "tcic_service(%d, %d, 0x%p)\n", lsock, cmd, arg); +#define tcic_set_bridge tcic_get_bridge - if (cmd < NFUNC) - err = service_table[cmd](lsock, arg); - else - err = -EINVAL; +void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base) +{ +} - return err; -} /* tcic_service */ +static struct pccard_operations tcic_operations = { + tcic_register_callback, + tcic_inquire_socket, + tcic_get_status, + tcic_get_socket, + tcic_set_socket, + tcic_get_io_map, + tcic_set_io_map, + tcic_get_mem_map, + tcic_set_mem_map, + tcic_get_bridge, + tcic_set_bridge, + tcic_proc_setup +}; /*====================================================================*/ diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.3.34/linux/drivers/pcmcia/yenta.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/pcmcia/yenta.c Tue Dec 28 16:11:31 1999 @@ -0,0 +1,534 @@ +/* + * Regular lowlevel cardbus driver ("yenta") + * + * (C) Copyright 1999 Linus Torvalds + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include "yenta.h" +#include "i82365.h" + +/* Don't ask.. */ +#define to_cycles(ns) ((ns)/120) +#define to_ns(cycles) ((cycles)*120) + +static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap) +{ + *cap = socket->cap; + return 0; +} + +/* + * Silly interface. We convert the cardbus status to a internal status, + * and we probably really should keep it in cardbus status form and + * only convert for old-style 16-bit PCMCIA cards.. + */ +static int yenta_get_status(pci_socket_t *socket, unsigned int *value) +{ + u32 state = cb_readl(socket, CB_SOCKET_STATE); + u8 status; + unsigned int val; + + /* Convert from Yenta status to old-style status */ + val = (state & CB_CARDSTS) ? SS_STSCHG : 0; + val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT; + val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0; + val |= (state & CB_CBCARD) ? SS_CARDBUS : 0; + val |= (state & CB_3VCARD) ? SS_3VCARD : 0; + val |= (state & CB_XVCARD) ? SS_XVCARD : 0; + + /* Get the old compatibility status too.. */ + status = exca_readb(socket, I365_STATUS); + val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; + val |= (status & I365_CS_READY) ? SS_READY : 0; + val |= (status & I365_CS_POWERON) ? SS_POWERON : 0; + +printk("yenta_get_status(%p)= %x\n", socket, val); + + *value = val; + return 0; +} + +static int yenta_Vcc_power(u32 control) +{ + switch ((control >> CB_VCCCTRL) & CB_PWRBITS) { + case CB_PWR5V: return 50; + case CB_PWR3V: return 33; + default: return 0; + } +} + +static int yenta_Vpp_power(u32 control) +{ + switch ((control >> CB_VPPCTRL) & CB_PWRBITS) { + case CB_PWR12V: return 120; + case CB_PWR5V: return 50; + case CB_PWR3V: return 33; + default: return 0; + } +} + +static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state) +{ + u32 control = cb_readl(socket, CB_SOCKET_CONTROL); + u8 reg; + + state->Vcc = yenta_Vcc_power(control); + state->Vpp = yenta_Vpp_power(control); + state->io_irq = socket->io_irq; + + reg = exca_readb(socket, I365_POWER); + state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0; + state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0; + + reg = exca_readb(socket, I365_INTCTL); + state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET; + state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0; + + reg = exca_readb(socket, I365_CSCINT); + state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0; + if (state->flags & SS_IOCARD) { + state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0; + } else { + state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0; + state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0; + state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0; + } + +printk("yenta_get_socket(%p) = %d, %d\n", socket, state->Vcc, state->Vpp); + + return 0; +} + +static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state) +{ + u8 reg; + u16 bridge; + u32 control; + +printk("yenta_set_socket(%p, %d, %d, %x)\n", socket, state->Vcc, state->Vpp, state->flags); + + bridge = config_readw(socket, CB_BRIDGE_CONTROL); + bridge &= ~CB_BRIDGE_CRST; + bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0; + config_writew(socket, CB_BRIDGE_CONTROL, bridge); + + /* Set the IO interrupt and socket state */ + reg = state->io_irq; + reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; + reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; + exca_writeb(socket, I365_INTCTL, reg); + + /* Set host interrupt and CSC mask state */ + reg = socket->cb_irq << 4; + reg |= (state->csc_mask & SS_DETECT) ? I365_CSC_DETECT : 0; + if (state->flags & SS_IOCARD) { + reg |= (state->csc_mask & SS_STSCHG) ? I365_CSC_STSCHG : 0; + } else { + reg |= (state->csc_mask & SS_BATDEAD) ? I365_CSC_BVD1 : 0; + reg |= (state->csc_mask & SS_BATWARN) ? I365_CSC_BVD2 : 0; + reg |= (state->csc_mask & SS_READY) ? I365_CSC_READY : 0; + } + exca_writeb(socket, I365_CSCINT, reg); + exca_readb(socket, I365_CSC); + + /* + * Set power state.. + * + * I wonder if we could do the Vcc/Vpp part through the + * CB interface only.. + */ + reg = I365_PWR_NORESET; + reg |= (state->flags & SS_PWR_AUTO) ? I365_PWR_AUTO : 0; + reg |= (state->flags & SS_OUTPUT_ENA) ? I365_PWR_OUT : 0; + + control = CB_STOPCLK; + switch (state->Vcc) { + case 33: + control |= CB_PWR3V << CB_VCCCTRL; + reg |= I365_VCC_5V; + break; + case 50: + control |= CB_PWR5V << CB_VCCCTRL; + reg |= I365_VCC_5V; + break; + } + switch (state->Vpp) { + case 33: + control |= CB_PWR3V << CB_VPPCTRL; + reg |= I365_VPP1_5V; + break; + case 50: + control |= CB_PWR5V << CB_VPPCTRL; + reg |= I365_VPP1_5V; + break; + case 120: + control |= CB_PWR12V << CB_VPPCTRL; + reg |= I365_VPP1_12V; + break; + } + exca_writeb(socket, I365_POWER, reg); + cb_writel(socket, CB_SOCKET_CONTROL, control); + + return 0; +} + +static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io) +{ + int map; + unsigned char ioctl, addr; + + map = io->map; + if (map > 1) + return -EINVAL; + + io->start = exca_readw(socket, I365_IO(map)+I365_W_START); + io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP); + + ioctl = exca_readb(socket, I365_IOCTL); + addr = exca_readb(socket, I365_ADDRWIN); + io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; + io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; + io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; + io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; + io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; + +printk("yenta_get_io_map(%d) = %x, %x, %x\n", map, io->start, io->stop, io->flags); + + return 0; +} + +static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io) +{ + int map; + unsigned char ioctl, addr, enable; + + map = io->map; + +printk("yenta_set_io_map(%d, %x, %x, %x)\n", map, io->start, io->stop, io->flags); + + if (map > 1) + return -EINVAL; + + enable = I365_ENA_IO(map); + addr = exca_readb(socket, I365_ADDRWIN); + + /* Disable the window before changing it.. */ + if (addr & enable) { + addr &= ~enable; + exca_writeb(socket, I365_ADDRWIN, addr); + } + + exca_writew(socket, I365_IO(map)+I365_W_START, io->start); + exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop); + + ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map); + if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); + if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); + if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); + exca_writeb(socket, I365_IOCTL, ioctl); + + if (io->flags & MAP_ACTIVE) + exca_writeb(socket, I365_ADDRWIN, addr | enable); + return 0; +} + +static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) +{ + int map; + unsigned char addr; + unsigned int start, stop, page, offset; + + map = mem->map; + if (map > 4) + return -EINVAL; + + addr = exca_readb(socket, I365_ADDRWIN); + mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0; + + start = exca_readw(socket, I365_MEM(map) + I365_W_START); + mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0; + mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0; + start = (start & 0x0fff) << 12; + + stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP); + mem->speed = (stop & I365_MEM_WS0) ? 1 : 0; + mem->speed += (stop & I365_MEM_WS1) ? 2 : 0; + mem->speed = to_ns(mem->speed); + stop = ((stop & 0x0fff) << 12) + 0x0fff; + + offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF); + mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0; + mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0; + offset = ((offset & 0x3fff) << 12) + start; + mem->card_start = offset & 0x3ffffff; + + page = exca_readb(socket, CB_MEM_PAGE(map)) << 24; + mem->sys_start = start + page; + mem->sys_stop = start + page; + +printk("yenta_get_map(%d) = %lx, %lx, %x\n", map, mem->sys_start, mem->sys_stop, mem->card_start); + + return 0; +} + +static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem) +{ + int map; + unsigned char addr, enable; + unsigned int start, stop, card_start; + unsigned short word; + + map = mem->map; + start = mem->sys_start; + stop = mem->sys_stop; + card_start = mem->card_start; + +printk("yenta_set_map(%d, %x, %x, %x)\n", map, start, stop, card_start); + + if (map > 4 || start > stop || ((start ^ stop) >> 24) || (card_start >> 26) || mem->speed > 1000) + return -EINVAL; + + enable = I365_ENA_MEM(map); + addr = exca_readb(socket, I365_ADDRWIN); + if (addr & enable) { + addr &= ~enable; + exca_writeb(socket, I365_ADDRWIN, addr); + } + + exca_writeb(socket, CB_MEM_PAGE(map), start >> 24); + + word = (start >> 12) & 0x0fff; + if (mem->flags & MAP_16BIT) + word |= I365_MEM_16BIT; + if (mem->flags & MAP_0WS) + word |= I365_MEM_0WS; + exca_writew(socket, I365_MEM(map) + I365_W_START, word); + + word = (stop >> 12) & 0x0fff; + switch (to_cycles(mem->speed)) { + case 0: break; + case 1: word |= I365_MEM_WS0; break; + case 2: word |= I365_MEM_WS1; break; + default: word |= I365_MEM_WS1 | I365_MEM_WS0; break; + } + exca_writew(socket, I365_MEM(map) + I365_W_STOP, word); + + word = ((card_start - start) >> 12) & 0x3fff; + if (mem->flags & MAP_WRPROT) + word |= I365_MEM_WRPROT; + if (mem->flags & MAP_ATTRIB) + word |= I365_MEM_REG; + exca_writew(socket, I365_MEM(map) + I365_W_OFF, word); + + if (mem->flags & MAP_ACTIVE) + exca_writeb(socket, I365_ADDRWIN, addr | enable); + return 0; +} + +static int yenta_get_bridge(pci_socket_t *socket, struct cb_bridge_map *m) +{ + unsigned map; + + map = m->map; + if (map > 1) + return -EINVAL; + + m->flags &= MAP_IOSPACE; + map += (m->flags & MAP_IOSPACE) ? 2 : 0; + m->start = config_readl(socket, CB_BRIDGE_BASE(map)); + m->stop = config_readl(socket, CB_BRIDGE_LIMIT(map)); + if (m->start || m->stop) { + m->flags |= MAP_ACTIVE; + m->stop |= (map > 1) ? 3 : 0x0fff; + } + + /* Get prefetch state for memory mappings */ + if (map < 2) { + u16 ctrl, prefetch_mask = CB_BRIDGE_PREFETCH0 << map; + + ctrl = config_readw(socket, CB_BRIDGE_CONTROL); + m->flags |= (ctrl & prefetch_mask) ? MAP_PREFETCH : 0; + } + return 0; +} + +static int yenta_set_bridge(pci_socket_t *socket, struct cb_bridge_map *m) +{ + unsigned map; + u32 start, end; + + map = m->map; + if (map > 1 || m->stop < m->start) + return -EINVAL; + + if (m->flags & MAP_IOSPACE) { + if ((m->stop > 0xffff) || (m->start & 3) || + ((m->stop & 3) != 3)) + return -EINVAL; + map += 2; + } else { + u16 ctrl, prefetch_mask = CB_BRIDGE_PREFETCH0 << map; + + if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff)) + return -EINVAL; + ctrl = config_readw(socket, CB_BRIDGE_CONTROL); + ctrl &= ~prefetch_mask; + ctrl |= (m->flags & MAP_PREFETCH) ? prefetch_mask : 0; + config_writew(socket, CB_BRIDGE_CONTROL, ctrl); + } + + start = 0; + end = 0; + if (m->flags & MAP_ACTIVE) { + start = m->start; + end = m->stop; + } + config_writel(socket, CB_BRIDGE_BASE(map), start); + config_writel(socket, CB_BRIDGE_LIMIT(map), end); + return 0; +} + +static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base) +{ + /* Not done yet */ +} + +static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + u8 csc; + u32 cb_event; + unsigned int events; + pci_socket_t *socket = (pci_socket_t *) dev_id; + + /* Clear interrupt status for the event */ + cb_event = cb_readl(socket, CB_SOCKET_EVENT); + cb_writel(socket, CB_SOCKET_EVENT, cb_event); + + csc = exca_readb(socket, I365_CSC); + + events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; + events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; + if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { + events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; + } else { + events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; + events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; + events |= (csc & I365_CSC_READY) ? SS_READY : 0; + } + + printk("Socket interrupt event %08x (%08x %02x)\n", events, cb_event, csc); + + if (events && socket->handler) + socket->handler(socket->info, events); +} + +static unsigned int yenta_probe_irq(pci_socket_t *socket) +{ + int i; + unsigned long val; + + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + val = probe_irq_on(); + for (i = 1; i < 16; i++) { + exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4)); + cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); + udelay(100); + cb_writel(socket, CB_SOCKET_EVENT, -1); + } + cb_writel(socket, CB_SOCKET_MASK, 0); + return probe_irq_mask(val); +} + +static void yenta_get_socket_capabilities(pci_socket_t *socket) +{ + socket->cap.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS; + socket->cap.irq_mask = yenta_probe_irq(socket); + if (socket->cb_irq && socket->cb_irq < 16) + socket->cap.irq_mask |= 1 << socket->cb_irq; + socket->cap.map_size = 0x1000; + socket->cap.pci_irq = socket->cb_irq; + socket->cap.cardbus = config_readb(socket, PCI_CB_CARD_BUS); + socket->cap.cb_bus = socket->dev->subordinate; + socket->cap.bus = NULL; + + printk("Yenta IRQ list %04x\n", socket->cap.irq_mask); +} + +/* + * Initialize a cardbus controller. Make sure we have a usable + * interrupt, and that we can map the cardbus area. Fill in the + * socket information structure.. + */ +static int yenta_open(pci_socket_t *socket) +{ + struct pci_dev *dev = socket->dev; + + /* + * Do some basic sanity checking.. + */ + if (pci_enable_device(dev)) { + printk("Unable to enable device\n"); + return -1; + } + if (!dev->resource[0].start) { + printk("No cardbus resource!\n"); + return -1; + } + + /* + * Ok, start setup.. Map the cardbus registers, + * and request the IRQ. + */ + socket->base = ioremap(dev->resource[0].start, 0x1000); + if (!socket->base) + return -1; + + if (dev->irq && !request_irq(dev->irq, yenta_interrupt, SA_SHIRQ, dev->name, socket)) + socket->cb_irq = dev->irq; + + /* Figure out what the dang thing can do.. */ + yenta_get_socket_capabilities(socket); + + /* Enable all events */ + writel(0x0f, socket->base + 4); + + printk("Socket status: %08x\n", readl(socket->base + 8)); + return 0; +} + +/* + * Close it down - release our resources and go home.. + */ +static void yenta_close(pci_socket_t *sock) +{ + if (sock->cb_irq) + free_irq(sock->cb_irq, sock); + if (sock->base) + iounmap(sock->base); +} + +struct pci_socket_ops yenta_operations = { + yenta_open, + yenta_close, + yenta_inquire, + yenta_get_status, + yenta_get_socket, + yenta_set_socket, + yenta_get_io_map, + yenta_set_io_map, + yenta_get_mem_map, + yenta_set_mem_map, + yenta_get_bridge, + yenta_set_bridge, + yenta_proc_setup +}; diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/yenta.h linux/drivers/pcmcia/yenta.h --- v2.3.34/linux/drivers/pcmcia/yenta.h Thu Nov 11 20:11:43 1999 +++ linux/drivers/pcmcia/yenta.h Tue Dec 28 17:43:37 1999 @@ -1,153 +1,124 @@ +#ifndef __YENTA_H +#define __YENTA_H + +#include +#include "pci_socket.h" + /* - * yenta.h 1.16 1999/10/25 20:03:34 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU Public License version 2 (the "GPL"), in which - * case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use - * your version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. + * Generate easy-to-use ways of reading a cardbus sockets + * regular memory space ("cb_xxx"), configuration space + * ("config_xxx") and compatibility space ("exca_xxxx") */ -#ifndef _LINUX_YENTA_H -#define _LINUX_YENTA_H +#define cb_readb(sock,reg) readb((sock)->base + (reg)) +#define cb_readw(sock,reg) readw((sock)->base + (reg)) +#define cb_readl(sock,reg) readl((sock)->base + (reg)) +#define cb_writeb(sock,reg,val) writeb((val), (sock)->base + (reg)) +#define cb_writew(sock,reg,val) writew((val), (sock)->base + (reg)) +#define cb_writel(sock,reg,val) writel((val), (sock)->base + (reg)) + +#define config_readb(sock,offset) ({ __u8 __val; pci_read_config_byte((sock)->dev, (offset), &__val); __val; }) +#define config_readw(sock,offset) ({ __u16 __val; pci_read_config_word((sock)->dev, (offset), &__val); __val; }) +#define config_readl(sock,offset) ({ __u32 __val; pci_read_config_dword((sock)->dev, (offset), &__val); __val; }) + +#define config_writeb(sock,offset,val) pci_write_config_byte((sock)->dev, (offset), (val)) +#define config_writew(sock,offset,val) pci_write_config_word((sock)->dev, (offset), (val)) +#define config_writel(sock,offset,val) pci_write_config_dword((sock)->dev, (offset), (val)) + +#define exca_readb(sock,reg) cb_readb((sock),(reg)+0x0800) +#define exca_readw(sock,reg) cb_readw((sock),(reg)+0x0800) +#define exca_readl(sock,reg) cb_readl((sock),(reg)+0x0800) + +#define exca_writeb(sock,reg,val) cb_writeb((sock),(reg)+0x0800,(val)) +#define exca_writew(sock,reg,val) cb_writew((sock),(reg)+0x0800,(val)) +#define exca_writel(sock,reg,val) cb_writel((sock),(reg)+0x0800,(val)) + +#define CB_SOCKET_EVENT 0x00 +#define CB_CSTSEVENT 0x00000001 /* Card status event */ +#define CB_CD1EVENT 0x00000002 /* Card detect 1 change event */ +#define CB_CD2EVENT 0x00000004 /* Card detect 2 change event */ +#define CB_PWREVENT 0x00000008 /* PWRCYCLE change event */ + +#define CB_SOCKET_MASK 0x04 +#define CB_CSTSMASK 0x00000001 /* Card status mask */ +#define CB_CDMASK 0x00000006 /* Card detect 1&2 mask */ +#define CB_PWRMASK 0x00000008 /* PWRCYCLE change mask */ + +#define CB_SOCKET_STATE 0x08 +#define CB_CARDSTS 0x00000001 /* CSTSCHG status */ +#define CB_CDETECT1 0x00000002 /* Card detect status 1 */ +#define CB_CDETECT2 0x00000004 /* Card detect status 2 */ +#define CB_PWRCYCLE 0x00000008 /* Socket powered */ +#define CB_16BITCARD 0x00000010 /* 16-bit card detected */ +#define CB_CBCARD 0x00000020 /* CardBus card detected */ +#define CB_IREQCINT 0x00000040 /* READY(xIRQ)/xCINT high */ +#define CB_NOTACARD 0x00000080 /* Unrecognizable PC card detected */ +#define CB_DATALOST 0x00000100 /* Potential data loss due to card removal */ +#define CB_BADVCCREQ 0x00000200 /* Invalid Vcc request by host software */ +#define CB_5VCARD 0x00000400 /* Card Vcc at 5.0 volts? */ +#define CB_3VCARD 0x00000800 /* Card Vcc at 3.3 volts? */ +#define CB_XVCARD 0x00001000 /* Card Vcc at X.X volts? */ +#define CB_YVCARD 0x00002000 /* Card Vcc at Y.Y volts? */ +#define CB_5VSOCKET 0x10000000 /* Socket Vcc at 5.0 volts? */ +#define CB_3VSOCKET 0x20000000 /* Socket Vcc at 3.3 volts? */ +#define CB_XVSOCKET 0x40000000 /* Socket Vcc at X.X volts? */ +#define CB_YVSOCKET 0x80000000 /* Socket Vcc at Y.Y volts? */ + +#define CB_SOCKET_FORCE 0x0C +#define CB_FCARDSTS 0x00000001 /* Force CSTSCHG */ +#define CB_FCDETECT1 0x00000002 /* Force CD1EVENT */ +#define CB_FCDETECT2 0x00000004 /* Force CD2EVENT */ +#define CB_FPWRCYCLE 0x00000008 /* Force PWREVENT */ +#define CB_F16BITCARD 0x00000010 /* Force 16-bit PCMCIA card */ +#define CB_FCBCARD 0x00000020 /* Force CardBus line */ +#define CB_FNOTACARD 0x00000080 /* Force NOTACARD */ +#define CB_FDATALOST 0x00000100 /* Force data lost */ +#define CB_FBADVCCREQ 0x00000200 /* Force bad Vcc request */ +#define CB_F5VCARD 0x00000400 /* Force 5.0 volt card */ +#define CB_F3VCARD 0x00000800 /* Force 3.3 volt card */ +#define CB_FXVCARD 0x00001000 /* Force X.X volt card */ +#define CB_FYVCARD 0x00002000 /* Force Y.Y volt card */ +#define CB_CVSTEST 0x00004000 /* Card VS test */ + +#define CB_SOCKET_CONTROL 0x10 +#define CB_VPPCTRL 0 /* Shift for Vpp */ +#define CB_VCCCTRL 4 /* Shift for Vcc */ +#define CB_STOPCLK 0x00000080 /* CLKRUN can slow CB clock when idle */ + +#define CB_PWRBITS 0x7 +#define CB_PWROFF 0x0 +#define CB_PWR12V 0x1 /* Only valid for Vpp */ +#define CB_PWR5V 0x2 +#define CB_PWR3V 0x3 +#define CB_PWRXV 0x4 +#define CB_PWRYV 0x5 + +#define CB_SOCKET_POWER 0x20 +#define CB_SKTACCES 0x02000000 /* A PC card access has occurred (clear on read) */ +#define CB_SKTMODE 0x01000000 /* Clock frequency has changed (clear on read) */ +#define CB_CLKCTRLEN 0x00010000 /* Clock control enabled (RW) */ +#define CB_CLKCTRL 0x00000001 /* Stop(0) or slow(1) CB clock (RW) */ -/* PCI Configuration Registers */ +/* + * Cardbus configuration space + */ +#define CB_BRIDGE_BASE(m) (0x1c + 8*(m)) +#define CB_BRIDGE_LIMIT(m) (0x20 + 8*(m)) +#define CB_BRIDGE_CONTROL 0x3e +#define CB_BRIDGE_CPERREN 0x00000001 +#define CB_BRIDGE_CSERREN 0x00000002 +#define CB_BRIDGE_ISAEN 0x00000004 +#define CB_BRIDGE_VGAEN 0x00000008 +#define CB_BRIDGE_MABTMODE 0x00000020 +#define CB_BRIDGE_CRST 0x00000040 +#define CB_BRIDGE_INTR 0x00000080 +#define CB_BRIDGE_PREFETCH0 0x00000100 +#define CB_BRIDGE_PREFETCH1 0x00000200 +#define CB_BRIDGE_POSTEN 0x00000400 -#define PCI_STATUS_CAPLIST 0x10 -#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */ -#define PCI_CAPABILITY_ID 0x00 /* 8 bit */ -#define PCI_CAPABILITY_PM 0x01 -#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */ -#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */ -#define PCI_PMCAP_PME_D3COLD 0x8000 -#define PCI_PMCAP_PME_D3HOT 0x4000 -#define PCI_PMCAP_PME_D2 0x2000 -#define PCI_PMCAP_PME_D1 0x1000 -#define PCI_PMCAP_PME_D0 0x0800 -#define PCI_PMCAP_D2_CAP 0x0400 -#define PCI_PMCAP_D1_CAP 0x0200 -#define PCI_PMCAP_DYN_DATA 0x0100 -#define PCI_PMCAP_DSI 0x0020 -#define PCI_PMCAP_AUX_PWR 0x0010 -#define PCI_PMCAP_PMECLK 0x0008 -#define PCI_PMCAP_VERSION_MASK 0x0007 -#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */ -#define PCI_PMCS_PME_STATUS 0x8000 -#define PCI_PMCS_DATASCALE_MASK 0x6000 -#define PCI_PMCS_DATASCALE_SHIFT 13 -#define PCI_PMCS_DATASEL_MASK 0x1e00 -#define PCI_PMCS_DATASEL_SHIFT 9 -#define PCI_PMCS_PME_ENABLE 0x0100 -#define PCI_PMCS_PWR_STATE_MASK 0x0003 -#define PCI_PMCS_PWR_STATE_D0 0x0000 -#define PCI_PMCS_PWR_STATE_D1 0x0001 -#define PCI_PMCS_PWR_STATE_D2 0x0002 -#define PCI_PMCS_PWR_STATE_D3 0x0003 -#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */ -#define PCI_PM_DATA 0x07 /* 8 bit */ - -#define CB_PRIMARY_BUS 0x18 /* 8 bit */ -#define CB_CARDBUS_BUS 0x19 /* 8 bit */ -#define CB_SUBORD_BUS 0x1a /* 8 bit */ -#define CB_LATENCY_TIMER 0x1b /* 8 bit */ - -#define CB_MEM_BASE(m) (0x1c + 8*(m)) -#define CB_MEM_LIMIT(m) (0x20 + 8*(m)) -#define CB_IO_BASE(m) (0x2c + 8*(m)) -#define CB_IO_LIMIT(m) (0x30 + 8*(m)) - -#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */ -#define CB_BCR_PARITY_ENA 0x0001 -#define CB_BCR_SERR_ENA 0x0002 -#define CB_BCR_ISA_ENA 0x0004 -#define CB_BCR_VGA_ENA 0x0008 -#define CB_BCR_MABORT 0x0020 -#define CB_BCR_CB_RESET 0x0040 -#define CB_BCR_ISA_IRQ 0x0080 -#define CB_BCR_PREFETCH(m) (0x0100 << (m)) -#define CB_BCR_WRITE_POST 0x0400 - -#define CB_LEGACY_MODE_BASE 0x44 - -/* Memory mapped registers */ - -#define CB_SOCKET_EVENT 0x0000 -#define CB_SE_CSTSCHG 0x00000001 -#define CB_SE_CCD1 0x00000002 -#define CB_SE_CCD2 0x00000004 -#define CB_SE_PWRCYCLE 0x00000008 - -#define CB_SOCKET_MASK 0x0004 -#define CB_SM_CSTSCHG 0x00000001 -#define CB_SM_CCD 0x00000006 -#define CB_SM_PWRCYCLE 0x00000008 - -#define CB_SOCKET_STATE 0x0008 -#define CB_SS_CSTSCHG 0x00000001 -#define CB_SS_CCD1 0x00000002 -#define CB_SS_CCD2 0x00000004 -#define CB_SS_PWRCYCLE 0x00000008 -#define CB_SS_16BIT 0x00000010 -#define CB_SS_32BIT 0x00000020 -#define CB_SS_CINT 0x00000040 -#define CB_SS_BADCARD 0x00000080 -#define CB_SS_DATALOST 0x00000100 -#define CB_SS_BADVCC 0x00000200 -#define CB_SS_5VCARD 0x00000400 -#define CB_SS_3VCARD 0x00000800 -#define CB_SS_XVCARD 0x00001000 -#define CB_SS_YVCARD 0x00002000 -#define CB_SS_5VSOCKET 0x10000000 -#define CB_SS_3VSOCKET 0x20000000 -#define CB_SS_XVSOCKET 0x40000000 -#define CB_SS_YVSOCKET 0x80000000 - -#define CB_SOCKET_FORCE 0x000c -#define CB_SF_CVSTEST 0x00004000 - -#define CB_SOCKET_CONTROL 0x0010 -#define CB_SC_VPP_MASK 0x00000007 -#define CB_SC_VPP_OFF 0x00000000 -#define CB_SC_VPP_12V 0x00000001 -#define CB_SC_VPP_5V 0x00000002 -#define CB_SC_VPP_3V 0x00000003 -#define CB_SC_VPP_XV 0x00000004 -#define CB_SC_VPP_YV 0x00000005 -#define CB_SC_VCC_MASK 0x00000070 -#define CB_SC_VCC_OFF 0x00000000 -#define CB_SC_VCC_5V 0x00000020 -#define CB_SC_VCC_3V 0x00000030 -#define CB_SC_VCC_XV 0x00000040 -#define CB_SC_VCC_YV 0x00000050 -#define CB_SC_CCLK_STOP 0x00000080 - -#define CB_SOCKET_POWER 0x0020 -#define CB_SP_CLK_CTRL 0x00000001 -#define CB_SP_CLK_CTRL_ENA 0x00010000 -#define CB_SP_CLK_MODE 0x01000000 -#define CB_SP_ACCESS 0x02000000 - -/* Address bits 31..24 for memory windows for 16-bit cards, - accessable only by memory mapping the 16-bit register set */ -#define CB_MEM_PAGE(map) (0x40 + (map)) +/* + * ExCA area extensions in Yenta + */ +#define CB_MEM_PAGE(map) (0x40 + (map)) -#endif /* _LINUX_YENTA_H */ +#endif diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c --- v2.3.34/linux/drivers/sbus/audio/amd7930.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/amd7930.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: amd7930.c,v 1.23 1999/11/19 09:55:58 davem Exp $ * drivers/sbus/audio/amd7930.c * * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -132,31 +132,30 @@ struct amd7930_channel { /* Channel status */ - unsigned char channel_status; + u8 channel_status; /* Current buffer that the driver is playing on channel */ volatile __u8 * output_ptr; - volatile unsigned long output_count; - unsigned char xmit_idle_char; + volatile u32 output_count; + u8 xmit_idle_char; /* Callback routine (and argument) when output is done on */ - void (*output_callback)(); + void (*output_callback)(void *, unsigned char); void * output_callback_arg; /* Current buffer that the driver is recording on channel */ volatile __u8 * input_ptr; - volatile unsigned long input_count; - volatile unsigned long input_limit; + volatile u32 input_count; + volatile u32 input_limit; /* Callback routine (and argument) when input is done on */ - void (*input_callback)(); + void (*input_callback)(void *, unsigned char, unsigned long); void * input_callback_arg; int input_format; int output_format; }; - /* Private information we store for each amd7930 chip. */ struct amd7930_info { struct amd7930_channel D; @@ -171,7 +170,7 @@ struct amd7930_channel *Bisdn[2]; /* Device registers information. */ - struct amd7930 *regs; + unsigned long regs; unsigned long regs_size; struct amd7930_map map; @@ -185,21 +184,20 @@ /* Format type */ int format_type; - /* Someone to signal when the ISDN LIU state changes */ int liu_state; void (*liu_callback)(void *); void *liu_callback_arg; }; - - /* Output a 16-bit quantity in the order that the amd7930 expects. */ -#define amd7930_out16(regs,v) ({ regs->dr = v & 0xFF; regs->dr = (v >> 8) & 0xFF; }) - +static __inline__ void amd7930_out16(unsigned long regs, u16 val) +{ + sbus_writeb(val & 0xff, regs + DR); + sbus_writeb(val >> 8, regs + DR); +} -/* - * gx, gr & stg gains. this table must contain 256 elements with +/* gx, gr & stg gains. this table must contain 256 elements with * the 0th being "infinity" (the magic value 9008). The remaining * elements match sun's gain curve (but with higher resolution): * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps. @@ -265,80 +263,76 @@ #define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0])) /* Enable amd7930 interrupts atomically. */ -static __inline__ void amd7930_enable_ints(struct amd7930_info *info) +static void amd7930_enable_ints(struct amd7930_info *info) { - register unsigned long flags; - - if (info->ints_on) - return; + unsigned long flags; save_and_cli(flags); - info->regs->cr = AMR_INIT; - info->regs->dr = AM_INIT_ACTIVE; + if (!info->ints_on) { + sbus_writeb(AMR_INIT, info->regs + CR); + sbus_writeb(AM_INIT_ACTIVE, info->regs + DR); + info->ints_on = 1; + } restore_flags(flags); - - info->ints_on = 1; } /* Disable amd7930 interrupts atomically. */ static __inline__ void amd7930_disable_ints(struct amd7930_info *info) { - register unsigned long flags; - - if (!info->ints_on) - return; + unsigned long flags; save_and_cli(flags); - info->regs->cr = AMR_INIT; - info->regs->dr = AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS; + if (info->ints_on) { + sbus_writeb(AMR_INIT, info->regs + CR); + sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS, + info->regs + DR); + info->ints_on = 0; + } restore_flags(flags); - info->ints_on = 0; } /* Idle amd7930 (no interrupts, no audio, no data) */ static __inline__ void amd7930_idle(struct amd7930_info *info) { - register unsigned long flags; - - if (!info->ints_on) - return; + unsigned long flags; save_and_cli(flags); - info->regs->cr = AMR_INIT; - info->regs->dr = 0; + if (info->ints_on) { + sbus_writeb(AMR_INIT, info->regs + CR); + sbus_writeb(0, info->regs + DR); + info->ints_on = 0; + } restore_flags(flags); - - info->ints_on = 0; } /* Commit the local copy of the MAP registers to the amd7930. */ static void amd7930_write_map(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; - struct amd7930 *regs = info->regs; + struct amd7930_info *info = (struct amd7930_info *) drv->private; + unsigned long regs = info->regs; struct amd7930_map *map = &info->map; unsigned long flags; save_and_cli(flags); - regs->cr = AMR_MAP_GX; + sbus_writeb(AMR_MAP_GX, regs + CR); amd7930_out16(regs, map->gx); - regs->cr = AMR_MAP_GR; + sbus_writeb(AMR_MAP_GR, regs + CR); amd7930_out16(regs, map->gr); - regs->cr = AMR_MAP_STGR; + sbus_writeb(AMR_MAP_STGR, regs + CR); amd7930_out16(regs, map->stgr); - regs->cr = AMR_MAP_GER; + sbus_writeb(AMR_MAP_GER, regs + CR); amd7930_out16(regs, map->ger); - regs->cr = AMR_MAP_MMR1; - regs->dr = map->mmr1; + sbus_writeb(AMR_MAP_MMR1, regs + CR); + sbus_writeb(map->mmr1, regs + DR); - regs->cr = AMR_MAP_MMR2; - regs->dr = map->mmr2; + sbus_writeb(AMR_MAP_MMR2, regs + CR); + sbus_writeb(map->mmr2, regs + DR); restore_flags(flags); } @@ -346,7 +340,7 @@ /* Update the MAP registers with new settings. */ static void amd7930_update_map(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; struct amd7930_map *map = &info->map; int level; @@ -380,14 +374,17 @@ #ifdef L2FRAME_DEBUG -inline void debug_info(struct amd7930_info *info, char c) { +inline void debug_info(struct amd7930_info *info, char c) +{ struct IsdnCardState *cs; - if (!info || !info->D.output_callback_arg) return; + if (!info || !info->D.output_callback_arg) + return; - cs = (struct IsdnCardState *)info->D.output_callback_arg; + cs = (struct IsdnCardState *) info->D.output_callback_arg; - if (!cs || !cs->status_write) return; + if (!cs || !cs->status_write) + return; if (cs->debug & L1_DEB_INTSTAT) { *(cs->status_write++) = c; @@ -402,15 +399,15 @@ #endif - static void fill_D_xmit_fifo(struct amd7930_info *info) { /* Send next byte(s) of outgoing data. */ while (info->D.output_ptr && info->D.output_count > 0 && - (info->regs->dsr2 & AMR_DSR2_TBE)) { + (sbus_readb(info->regs + DSR2) & AMR_DSR2_TBE)) { + u8 byte = *(info->D.output_ptr); /* Send the next byte and advance buffer pointer. */ - info->regs->dctb = *(info->D.output_ptr); + sbus_writeb(byte, info->regs + DCTB); info->D.output_ptr++; info->D.output_count--; @@ -437,51 +434,40 @@ if (info->D.output_callback) (*info->D.output_callback) (info->D.output_callback_arg, - info->regs->der); - /* info->regs->der & D_XMIT_ERRORS); */ + sbus_readb(info->regs + DER)); + /* sbus_readb(info->regs + DER) & D_XMIT_ERRORS); */ } /* Read the next byte(s) of incoming data. */ - while (info->regs->dsr2 & AMR_DSR2_RBA) { - + while (sbus_readb(info->regs + DSR2) & AMR_DSR2_RBA) { if (info->D.input_ptr && (info->D.input_count < info->D.input_limit)) { - /* Get the next byte and advance buffer pointer. */ - - *(info->D.input_ptr) = info->regs->dcrb; + *(info->D.input_ptr) = sbus_readb(info->regs + DCRB); info->D.input_ptr++; info->D.input_count++; - } else { - /* Overflow - should be detected by chip via RBLR * so we'll just consume data until we see LBRP */ - - dummy = info->regs->dcrb; - + dummy = sbus_readb(info->regs + DCRB); } debug_info(info, '<'); - if (info->regs->dsr2 & AMR_DSR2_LBRP) { - - /* End of recv packet? Notify the midlevel driver. */ - + if (sbus_readb(info->regs + DSR2) & AMR_DSR2_LBRP) { __u8 der; + /* End of recv packet? Notify the midlevel driver. */ debug_info(info, '!'); - info->D.input_ptr = NULL; - - der = info->regs->der & D_RECV_ERRORS; + der = sbus_readb(info->regs + DER) & D_RECV_ERRORS; /* Read receive byte count - advances FIFOs */ - info->regs->cr = AMR_DLC_DRCR; - dummy = info->regs->dr; - dummy = info->regs->dr; + sbus_writeb(AMR_DLC_DRCR, info->regs + CR); + dummy = sbus_readb(info->regs + DR); + dummy = sbus_readb(info->regs + DR); if (info->D.input_callback) (*info->D.input_callback) @@ -492,26 +478,33 @@ } } -long amd7930_xmit_idles=0; +long amd7930_xmit_idles = 0; static void transceive_Bchannel(struct amd7930_channel *channel, - __volatile__ __u8 *io_reg) + unsigned long reg) { /* Send the next byte of outgoing data. */ if (channel->output_ptr && channel->output_count > 0) { + u8 byte; /* Send the next byte and advance buffer pointer. */ switch(channel->output_format) { case AUDIO_ENCODING_ULAW: case AUDIO_ENCODING_ALAW: - *io_reg = *(channel->output_ptr); + byte = *(channel->output_ptr); + sbus_writeb(byte, reg); break; case AUDIO_ENCODING_LINEAR8: - *io_reg = bilinear2mulaw(*(channel->output_ptr)); + byte = bilinear2mulaw(*(channel->output_ptr)); + sbus_writeb(byte, reg); break; case AUDIO_ENCODING_LINEAR: if (channel->output_count >= 2) { - *io_reg = linear2mulaw(*((__u16*)(channel->output_ptr))); + u16 val = channel->output_ptr[0] << 8; + + val |= channel->output_ptr[1]; + byte = linear2mulaw(val); + sbus_writeb(byte, reg); channel->output_ptr++; channel->output_count--; }; @@ -529,28 +522,31 @@ (channel->output_callback_arg,1); } } else { - *io_reg = channel->xmit_idle_char; + sbus_writeb(channel->xmit_idle_char, reg); amd7930_xmit_idles++; } /* Read the next byte of incoming data. */ if (channel->input_ptr && channel->input_count > 0) { - /* Get the next byte and advance buffer pointer. */ switch(channel->input_format) { case AUDIO_ENCODING_ULAW: case AUDIO_ENCODING_ALAW: - *(channel->input_ptr) = *io_reg; + *(channel->input_ptr) = sbus_readb(reg); break; case AUDIO_ENCODING_LINEAR8: - *(channel->input_ptr) = mulaw2bilinear(*io_reg); + *(channel->input_ptr) = mulaw2bilinear(sbus_readb(reg)); break; case AUDIO_ENCODING_LINEAR: if (channel->input_count >= 2) { - *((__u16*)(channel->input_ptr)) = mulaw2linear(*io_reg); + u16 val = mulaw2linear(sbus_readb(reg)); + channel->input_ptr[0] = val >> 8; + channel->input_ptr[1] = val & 0xff; channel->input_ptr++; channel->input_count--; - } else *(channel->input_ptr) = 0; + } else { + *(channel->input_ptr) = 0; + } }; channel->input_ptr++; channel->input_count--; @@ -561,7 +557,7 @@ channel->input_count = 0; if (channel->input_callback) (*channel->input_callback) - (channel->input_callback_arg, 1); + (channel->input_callback_arg, 1, 0); } } } @@ -569,20 +565,19 @@ /* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */ static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; - struct amd7930_info *info = (struct amd7930_info *)drv->private; - struct amd7930 *regs = info->regs; + struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id; + struct amd7930_info *info = (struct amd7930_info *) drv->private; + unsigned long regs = info->regs; __u8 ir; - __u8 lsr; /* Clear the interrupt. */ - ir = regs->ir; + ir = sbus_readb(regs + IR); if (ir & AMR_IR_BBUF) { if (info->Bb.channel_status == CHANNEL_INUSE) - transceive_Bchannel(&info->Bb, &info->regs->bbtb); + transceive_Bchannel(&info->Bb, info->regs + BBTB); if (info->Bc.channel_status == CHANNEL_INUSE) - transceive_Bchannel(&info->Bc, &info->regs->bctb); + transceive_Bchannel(&info->Bc, info->regs + BCTB); } if (ir & (AMR_IR_DRTHRSH | AMR_IR_DTTHRSH | AMR_IR_DSRI)) { @@ -592,21 +587,22 @@ } if (ir & AMR_IR_LSRI) { - regs->cr = AMR_LIU_LSR; - lsr = regs->dr; + __u8 lsr; - info->liu_state = (lsr&0x7) + 2; + sbus_writeb(AMR_LIU_LSR, regs + CR); + lsr = sbus_readb(regs + DR); + + info->liu_state = (lsr & 0x7) + 2; if (info->liu_callback) (*info->liu_callback)(info->liu_callback_arg); } } - static int amd7930_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; switch(MINOR(inode->i_rdev) & 0xf) { case SPARCAUDIO_AUDIO_MINOR: @@ -634,31 +630,29 @@ static void request_Baudio(struct amd7930_info *info) { if (info->Bb.channel_status == CHANNEL_AVAILABLE) { - info->Bb.channel_status = CHANNEL_INUSE; info->Baudio = &info->Bb; /* Multiplexor map - audio (Ba) to Bb */ - info->regs->cr = AMR_MUX_MCR1; - info->regs->dr = AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4); + sbus_writeb(AMR_MUX_MCR1, info->regs + CR); + sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4), + info->regs + DR); /* Enable B channel interrupts */ - info->regs->cr = AMR_MUX_MCR4; - info->regs->dr = AM_MUX_MCR4_ENABLE_INTS; - + sbus_writeb(AMR_MUX_MCR4, info->regs + CR); + sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR); } else if (info->Bc.channel_status == CHANNEL_AVAILABLE) { - info->Bc.channel_status = CHANNEL_INUSE; info->Baudio = &info->Bc; /* Multiplexor map - audio (Ba) to Bc */ - info->regs->cr = AMR_MUX_MCR1; - info->regs->dr = AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4); + sbus_writeb(AMR_MUX_MCR1, info->regs + CR); + sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4), + info->regs + DR); /* Enable B channel interrupts */ - info->regs->cr = AMR_MUX_MCR4; - info->regs->dr = AM_MUX_MCR4_ENABLE_INTS; - + sbus_writeb(AMR_MUX_MCR4, info->regs + CR); + sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR); } } @@ -666,16 +660,15 @@ { if (info->Baudio) { info->Baudio->channel_status = CHANNEL_AVAILABLE; - info->regs->cr = AMR_MUX_MCR1; - info->regs->dr = 0; + sbus_writeb(AMR_MUX_MCR1, info->regs + CR); + sbus_writeb(0, info->regs + DR); info->Baudio = NULL; if (info->Bb.channel_status == CHANNEL_AVAILABLE && info->Bc.channel_status == CHANNEL_AVAILABLE) { - /* Disable B channel interrupts */ - info->regs->cr = AMR_MUX_MCR4; - info->regs->dr = 0; + sbus_writeb(AMR_MUX_MCR4, info->regs + CR); + sbus_writeb(0, info->regs + DR); } } } @@ -683,25 +676,24 @@ static void amd7930_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; - if (! info->Baudio) { + if (! info->Baudio) request_Baudio(info); - } if (info->Baudio) { info->Baudio->output_ptr = buffer; info->Baudio->output_count = count; info->Baudio->output_format = info->format_type; - info->Baudio->output_callback = (void *) &sparcaudio_output_done; - info->Baudio->output_callback_arg = (void *) drv; + info->Baudio->output_callback = (void *) &sparcaudio_output_done; + info->Baudio->output_callback_arg = (void *) drv; info->Baudio->xmit_idle_char = 0; } } static void amd7930_stop_output(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; if (info->Baudio) { info->Baudio->output_ptr = NULL; @@ -714,11 +706,10 @@ static void amd7930_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; - if (! info->Baudio) { + if (! info->Baudio) request_Baudio(info); - } if (info->Baudio) { info->Baudio->input_ptr = buffer; @@ -731,7 +722,7 @@ static void amd7930_stop_input(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; if (info->Baudio) { info->Baudio->input_ptr = NULL; @@ -772,7 +763,7 @@ static int amd7930_set_output_volume(struct sparcaudio_driver *drv, int vol) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; info->pgain = vol; amd7930_update_map(drv); @@ -781,14 +772,14 @@ static int amd7930_get_output_volume(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; return info->pgain; } static int amd7930_set_input_volume(struct sparcaudio_driver *drv, int vol) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; info->rgain = vol; amd7930_update_map(drv); @@ -797,14 +788,14 @@ static int amd7930_get_input_volume(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; return info->rgain; } static int amd7930_set_monitor_volume(struct sparcaudio_driver *drv, int vol) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; info->mgain = vol; amd7930_update_map(drv); @@ -813,7 +804,7 @@ static int amd7930_get_monitor_volume(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; return info->mgain; } @@ -848,7 +839,7 @@ static int amd7930_set_input_channels(struct sparcaudio_driver *drv, int value) { - return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL; + return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL; } static int amd7930_get_output_precision(struct sparcaudio_driver *drv) @@ -859,7 +850,7 @@ static int amd7930_set_output_precision(struct sparcaudio_driver *drv, int value) { - return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL; + return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL; } static int amd7930_get_input_precision(struct sparcaudio_driver *drv) @@ -870,32 +861,36 @@ static int amd7930_set_input_precision(struct sparcaudio_driver *drv, int value) { - return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL; + return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL; } static int amd7930_get_output_port(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; - if (info->map.mmr2 & AM_MAP_MMR2_LS) - return AUDIO_SPEAKER; - return AUDIO_HEADPHONE; + struct amd7930_info *info = (struct amd7930_info *) drv->private; + + if (info->map.mmr2 & AM_MAP_MMR2_LS) + return AUDIO_SPEAKER; + + return AUDIO_HEADPHONE; } static int amd7930_set_output_port(struct sparcaudio_driver *drv, int value) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; - switch (value) { - case AUDIO_HEADPHONE: - info->map.mmr2 &= ~AM_MAP_MMR2_LS; - break; - case AUDIO_SPEAKER: - info->map.mmr2 |= AM_MAP_MMR2_LS; - break; - default: - return -EINVAL; - } - amd7930_update_map(drv); - return 0; + struct amd7930_info *info = (struct amd7930_info *) drv->private; + + switch (value) { + case AUDIO_HEADPHONE: + info->map.mmr2 &= ~AM_MAP_MMR2_LS; + break; + case AUDIO_SPEAKER: + info->map.mmr2 |= AM_MAP_MMR2_LS; + break; + default: + return -EINVAL; + }; + + amd7930_update_map(drv); + return 0; } /* Only a microphone here, so no troubles */ @@ -906,36 +901,37 @@ static int amd7930_get_encoding(struct sparcaudio_driver *drv) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; - if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && - (info->format_type == AUDIO_ENCODING_ALAW)) - return AUDIO_ENCODING_ALAW; + struct amd7930_info *info = (struct amd7930_info *) drv->private; + + if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && + (info->format_type == AUDIO_ENCODING_ALAW)) + return AUDIO_ENCODING_ALAW; - return info->format_type; + return info->format_type; } static int amd7930_set_encoding(struct sparcaudio_driver *drv, int value) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; - switch (value) { - case AUDIO_ENCODING_ALAW: - info->map.mmr1 |= AM_MAP_MMR1_ALAW; - break; - case AUDIO_ENCODING_LINEAR8: - case AUDIO_ENCODING_LINEAR: - case AUDIO_ENCODING_ULAW: - info->map.mmr1 &= ~AM_MAP_MMR1_ALAW; - break; - default: - return -EINVAL; - }; + switch (value) { + case AUDIO_ENCODING_ALAW: + info->map.mmr1 |= AM_MAP_MMR1_ALAW; + break; + case AUDIO_ENCODING_LINEAR8: + case AUDIO_ENCODING_LINEAR: + case AUDIO_ENCODING_ULAW: + info->map.mmr1 &= ~AM_MAP_MMR1_ALAW; + break; + default: + return -EINVAL; + }; - info->format_type = value; + info->format_type = value; - amd7930_update_map(drv); - return 0; + amd7930_update_map(drv); + return 0; } /* This is what you get. Take it or leave it */ @@ -947,7 +943,7 @@ static int amd7930_set_output_rate(struct sparcaudio_driver *drv, int value) { - return (value == AMD7930_RATE) ? 0 : -EINVAL; + return (value == AMD7930_RATE) ? 0 : -EINVAL; } static int amd7930_get_input_rate(struct sparcaudio_driver *drv) @@ -958,7 +954,7 @@ static int amd7930_set_input_rate(struct sparcaudio_driver *drv, int value) { - return (value == AMD7930_RATE) ? 0 : -EINVAL; + return (value == AMD7930_RATE) ? 0 : -EINVAL; } static int amd7930_get_output_muted(struct sparcaudio_driver *drv) @@ -968,31 +964,30 @@ static void amd7930_loopback(struct sparcaudio_driver *drv, unsigned int value) { - struct amd7930_info *info = (struct amd7930_info *)drv->private; + struct amd7930_info *info = (struct amd7930_info *) drv->private; - if (value) - info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK; - else - info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK; - amd7930_update_map(drv); - return; + if (value) + info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK; + else + info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK; + amd7930_update_map(drv); } static int amd7930_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg, struct sparcaudio_driver *drv) { - int retval = 0; + int retval = 0; - switch (cmd) { - case AUDIO_DIAG_LOOPBACK: - amd7930_loopback(drv, (unsigned int)arg); - break; - default: - retval = -EINVAL; - } + switch (cmd) { + case AUDIO_DIAG_LOOPBACK: + amd7930_loopback(drv, (unsigned int)arg); + break; + default: + retval = -EINVAL; + }; - return retval; + return retval; } @@ -1141,9 +1136,8 @@ { struct amd7930_info *info; - if (dev > num_drivers) { + if (dev > num_drivers) return(0); - } info = (struct amd7930_info *) drivers[dev].private; @@ -1154,9 +1148,8 @@ { struct amd7930_info *info; - if (dev > num_drivers) { + if (dev > num_drivers) return(0); - } info = (struct amd7930_info *) drivers[dev].private; @@ -1166,11 +1159,10 @@ static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; @@ -1181,19 +1173,21 @@ info->liu_callback_arg = callback_arg; /* De-activate the ISDN Line Interface Unit (LIU) */ - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr = 0; + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + sbus_writeb(0, info->regs + DR); /* Request interrupt when LIU changes state from/to F3/F7/F8 */ - info->regs->cr = AMR_LIU_LMR2; - info->regs->dr = AM_LIU_LMR2_EN_F3_INT | - AM_LIU_LMR2_EN_F7_INT | AM_LIU_LMR2_EN_F8_INT; + sbus_writeb(AMR_LIU_LMR2, info->regs + CR); + sbus_writeb(AM_LIU_LMR2_EN_F3_INT | + AM_LIU_LMR2_EN_F7_INT | + AM_LIU_LMR2_EN_F8_INT, + info->regs + DR); /* amd7930_enable_ints(info); */ /* Activate the ISDN Line Interface Unit (LIU) */ - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr = AM_LIU_LMR1_LIU_ENABL; + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + sbus_writeb(AM_LIU_LMR1_LIU_ENABL, info->regs + DR); restore_flags(flags); } @@ -1201,11 +1195,10 @@ static void amd7930_liu_activate(int dev, int priority) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; @@ -1218,14 +1211,13 @@ * * Priority 0 is eight 1s; priority 1 is ten 1s; etc */ - - info->regs->cr = AMR_LIU_LPR; - info->regs->dr = priority & 0x0f; + sbus_writeb(AMR_LIU_LPR, info->regs + CR); + sbus_writeb(priority & 0x0f, info->regs + DR); /* request LIU activation */ - - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr = AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV; + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + sbus_writeb(AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV, + info->regs + DR); restore_flags(flags); } @@ -1233,20 +1225,18 @@ static void amd7930_liu_deactivate(int dev) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; save_and_cli(flags); /* deactivate LIU */ - - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr = 0; + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + sbus_writeb(0, info->regs + DR); restore_flags(flags); } @@ -1255,12 +1245,11 @@ void (*callback)(void *, int), void *callback_arg) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; __u8 dmr1; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; @@ -1278,16 +1267,16 @@ info->D.output_callback_arg = callback_arg; /* Enable D-channel Transmit Threshold interrupt; disable addressing */ - info->regs->cr = AMR_DLC_DMR1; - dmr1 = info->regs->dr; + sbus_writeb(AMR_DLC_DMR1, info->regs + CR); + dmr1 = sbus_readb(info->regs + DR); dmr1 |= AMR_DLC_DMR1_DTTHRSH_INT; dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS; - info->regs->dr = dmr1; + sbus_writeb(dmr1, info->regs + DR); /* Begin xmit by setting D-channel Transmit Byte Count Reg (DTCR) */ - info->regs->cr = AMR_DLC_DTCR; - info->regs->dr = count & 0xff; - info->regs->dr = (count >> 8) & 0xff; + sbus_writeb(AMR_DLC_DTCR, info->regs + CR); + sbus_writeb(count & 0xff, info->regs + DR); + sbus_writeb((count >> 8) & 0xff, info->regs + DR); /* Prime xmit FIFO */ /* fill_D_xmit_fifo(info); */ @@ -1301,12 +1290,11 @@ void *callback_arg) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; __u8 dmr1; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; @@ -1328,16 +1316,16 @@ * Enable D-channel End of Receive Packet interrupt; * Disable address recognition */ - info->regs->cr = AMR_DLC_DMR1; - dmr1 = info->regs->dr; + sbus_writeb(AMR_DLC_DMR1, info->regs + CR); + dmr1 = sbus_readb(info->regs + DR); dmr1 |= AMR_DLC_DMR1_DRTHRSH_INT | AMR_DLC_DMR1_EORP_INT; dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS; - info->regs->dr = dmr1; + sbus_writeb(dmr1, info->regs + DR); /* Set D-channel Receive Byte Count Limit Register */ - info->regs->cr = AMR_DLC_DRCR; - info->regs->dr = size & 0xff; - info->regs->dr = (size >> 8) & 0xff; + sbus_writeb(AMR_DLC_DRCR, info->regs + CR); + sbus_writeb(size & 0xff, info->regs + DR); + sbus_writeb((size >> 8) & 0xff, info->regs + DR); restore_flags(flags); } @@ -1346,54 +1334,56 @@ int mode, u_char xmit_idle_char) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; + u8 tmp; - if (dev > num_drivers || chan<0 || chan>1) { + if (dev > num_drivers || chan<0 || chan>1) return -1; - } - if (mode == L1_MODE_HDLC) { - return -1; - } + if (mode == L1_MODE_HDLC) + return -1; info = (struct amd7930_info *) drivers[dev].private; save_and_cli(flags); if (info->Bb.channel_status == CHANNEL_AVAILABLE) { - info->Bb.channel_status = CHANNEL_INUSE; info->Bb.xmit_idle_char = xmit_idle_char; info->Bisdn[chan] = &info->Bb; /* Multiplexor map - isdn (B1/2) to Bb */ - info->regs->cr = AMR_MUX_MCR2 + chan; - info->regs->dr = (AM_MUX_CHANNEL_B1 + chan) | - (AM_MUX_CHANNEL_Bb << 4); - + sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR); + sbus_writeb((AM_MUX_CHANNEL_B1 + chan) | + (AM_MUX_CHANNEL_Bb << 4), + info->regs + DR); } else if (info->Bc.channel_status == CHANNEL_AVAILABLE) { - info->Bc.channel_status = CHANNEL_INUSE; info->Bc.xmit_idle_char = xmit_idle_char; info->Bisdn[chan] = &info->Bc; /* Multiplexor map - isdn (B1/2) to Bc */ - info->regs->cr = AMR_MUX_MCR2 + chan; - info->regs->dr = (AM_MUX_CHANNEL_B1 + chan) | - (AM_MUX_CHANNEL_Bc << 4); - + sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR); + sbus_writeb((AM_MUX_CHANNEL_B1 + chan) | + (AM_MUX_CHANNEL_Bc << 4), + info->regs + DR); } else { restore_flags(flags); return (-1); } /* Enable B channel transmit */ - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr |= AM_LIU_LMR1_B1_ENABL + chan; + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + tmp = sbus_readb(info->regs + DR); + tmp |= AM_LIU_LMR1_B1_ENBL + chan; + sbus_writeb(tmp, info->regs + DR); /* Enable B channel interrupts */ - info->regs->cr = AMR_MUX_MCR4; - info->regs->dr = AM_MUX_MCR4_ENABLE_INTS | AM_MUX_MCR4_REVERSE_Bb | AM_MUX_MCR4_REVERSE_Bc; + sbus_writeb(AMR_MUX_MCR4, info->regs + CR); + sbus_writeb(AM_MUX_MCR4_ENABLE_INTS | + AM_MUX_MCR4_REVERSE_Bb | + AM_MUX_MCR4_REVERSE_Bc, + info->regs + DR); restore_flags(flags); return 0; @@ -1402,32 +1392,36 @@ static void amd7930_bclose(int dev, unsigned int chan) { struct amd7930_info *info; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers || chan<0 || chan>1) { + if (dev > num_drivers || chan<0 || chan>1) return; - } info = (struct amd7930_info *) drivers[dev].private; save_and_cli(flags); if (info->Bisdn[chan]) { + u8 tmp; + info->Bisdn[chan]->channel_status = CHANNEL_AVAILABLE; - info->regs->cr = AMR_MUX_MCR2 + chan; - info->regs->dr = 0; + + sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR); + sbus_writeb(0, info->regs + DR); + info->Bisdn[chan] = NULL; /* Disable B channel transmit */ - info->regs->cr = AMR_LIU_LMR1; - info->regs->dr &= ~(AM_LIU_LMR1_B1_ENABL + chan); + sbus_writeb(AMR_LIU_LMR1, info->regs + CR); + tmp = sbus_readb(info->regs + DR); + tmp &= ~(AM_LIU_LMR1_B1_ENABL + chan); + sbus_writeb(tmp, info->regs + DR); if (info->Bb.channel_status == CHANNEL_AVAILABLE && info->Bc.channel_status == CHANNEL_AVAILABLE) { - /* Disable B channel interrupts */ - info->regs->cr = AMR_MUX_MCR4; - info->regs->dr = 0; + sbus_writeb(AMR_MUX_MCR4, info->regs + CR); + sbus_writeb(0, info->regs + DR); } } @@ -1440,11 +1434,10 @@ { struct amd7930_info *info; struct amd7930_channel *Bchan; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; Bchan = info->Bisdn[chan]; @@ -1469,11 +1462,10 @@ { struct amd7930_info *info; struct amd7930_channel *Bchan; - register unsigned long flags; + unsigned long flags; - if (dev > num_drivers) { + if (dev > num_drivers) return; - } info = (struct amd7930_info *) drivers[dev].private; Bchan = info->Bisdn[chan]; @@ -1573,16 +1565,17 @@ /* Attach to an amd7930 chip given its PROM node. */ static int amd7930_attach(struct sparcaudio_driver *drv, int node, - struct linux_sbus *sbus, struct linux_sbus_device *sdev) + struct sbus_bus *sbus, struct sbus_dev *sdev) { struct linux_prom_registers regs; struct linux_prom_irqs irq; + struct resource res, *resp; struct amd7930_info *info; int err; /* Allocate our private information structure. */ drv->private = kmalloc(sizeof(struct amd7930_info), GFP_KERNEL); - if (!drv->private) + if (drv->private == NULL) return -ENOMEM; /* Point at the information structure and initialize it. */ @@ -1595,13 +1588,18 @@ /* Map the registers into memory. */ prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); - if (sbus && sdev) - prom_apply_sbus_ranges(sbus, ®s, 1, sdev); + if (sbus && sdev) { + resp = &sdev->resource[0]; + } else { + resp = &res; + res.start = regs.phys_addr; + res.end = res.start + regs.reg_size - 1; + res.flags = IORESOURCE_IO | (regs.which_io & 0xff); + } info->regs_size = regs.reg_size; - info->regs = sparc_alloc_io(regs.phys_addr, 0, regs.reg_size, - "amd7930", regs.which_io, 0); + info->regs = sbus_ioremap(resp, 0, regs.reg_size, "amd7930"); if (!info->regs) { - printk(KERN_ERR "amd7930: could not allocate registers\n"); + printk(KERN_ERR "amd7930: could not remap registers\n"); kfree(drv->private); return -EIO; } @@ -1610,10 +1608,11 @@ amd7930_idle(info); /* Enable extended FIFO operation on D-channel */ - info->regs->cr = AMR_DLC_EFCR; - info->regs->dr = AMR_DLC_EFCR_EXTEND_FIFO; - info->regs->cr = AMR_DLC_DMR4; - info->regs->dr = /* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14; + sbus_writeb(AMR_DLC_EFCR, info->regs + CR); + sbus_writeb(AMR_DLC_EFCR_EXTEND_FIFO, info->regs + DR); + sbus_writeb(AMR_DLC_DMR4, info->regs + CR); + sbus_writeb(/* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14, + info->regs + DR); /* Attach the interrupt handler to the audio interrupt. */ prom_getproperty(node, "intr", (char *)&irq, sizeof(irq)); @@ -1625,8 +1624,8 @@ /* Initalize the local copy of the MAP registers. */ memset(&info->map, 0, sizeof(info->map)); - info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER - | AM_MAP_MMR1_GR | AM_MAP_MMR1_STG; + info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER | + AM_MAP_MMR1_GR | AM_MAP_MMR1_STG; /* Start out with speaker, microphone */ info->map.mmr2 |= (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB); @@ -1647,14 +1646,14 @@ printk(KERN_ERR "amd7930: unable to register\n"); disable_irq(info->irq); free_irq(info->irq, drv); - sparc_free_io(info->regs, info->regs_size); + sbus_iounmap(info->regs, info->regs_size); kfree(drv->private); return -EIO; } /* Announce the hardware to the user. */ - printk(KERN_INFO "amd7930 at 0x%lx irq %d\n", - (unsigned long)info->regs, info->irq); + printk(KERN_INFO "amd7930 at %lx irq %d\n", + info->regs, info->irq); /* Success! */ return 0; @@ -1670,7 +1669,7 @@ amd7930_idle(info); disable_irq(info->irq); free_irq(info->irq, drv); - sparc_free_io(info->regs, info->regs_size); + sbus_iounmap(info->regs, info->regs_size); kfree(drv->private); } #endif @@ -1682,8 +1681,8 @@ int __init amd7930_init(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev; + struct sbus_bus *sbus; + struct sbus_dev *sdev; int node; /* Try to find the sun4c "audio" node first. */ @@ -1695,7 +1694,7 @@ num_drivers = 0; /* Probe each SBUS for amd7930 chips. */ - for_all_sbusdev(sdev,bus) { + for_all_sbusdev(sdev, sbus) { if (!strcmp(sdev->prom_name, "audio")) { /* Don't go over the max number of drivers. */ if (num_drivers >= MAX_DRIVERS) @@ -1769,7 +1768,6 @@ { return ulaw[data]; } - static unsigned char linear[] = { 0, 0, 0, 0, 0, 0, 0, 1, diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/amd7930.h linux/drivers/sbus/audio/amd7930.h --- v2.3.34/linux/drivers/sbus/audio/amd7930.h Wed Nov 18 09:06:05 1998 +++ linux/drivers/sbus/audio/amd7930.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: amd7930.h,v 1.8 1999/09/21 14:37:10 davem Exp $ * drivers/sbus/audio/amd7930.h * * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -17,22 +17,18 @@ #include /* Register interface presented to the CPU by the amd7930. */ -struct amd7930 -{ - __volatile__ __u8 cr; /* Command Register (W) */ -#define ir cr /* Interrupt Register (R) */ - __volatile__ __u8 dr; /* Data Register (R/W) */ - __volatile__ __u8 dsr1; /* D-channel Status Register 1 (R) */ - __volatile__ __u8 der; /* D-channel Error Register (R) */ - __volatile__ __u8 dctb; /* D-channel Transmit Buffer (W) */ -#define dcrb dctb /* D-channel Receive Buffer (R) */ - __volatile__ __u8 bbtb; /* Bb-channel Transmit Buffer (W) */ -#define bbrb bbtb /* Bb-channel Receive Buffer (R) */ - __volatile__ __u8 bctb; /* Bc-channel Transmit Buffer (W) */ -#define bcrb bctb /* Bc-channel Receive Buffer (R) */ - __volatile__ __u8 dsr2; /* D-channel Status Register 2 (R) */ -}; - +#define CR 0x00UL /* Command Register (W) */ +#define IR CR /* Interrupt Register (R) */ +#define DR 0x01UL /* Data Register (R/W) */ +#define DSR1 0x02UL /* D-channel Status Register 1 (R) */ +#define DER 0x03UL /* D-channel Error Register (R) */ +#define DCTB 0x04UL /* D-channel Transmit Buffer (W) */ +#define DCRB DCTB /* D-channel Receive Buffer (R) */ +#define BBTB 0x05UL /* Bb-channel Transmit Buffer (W) */ +#define BBRB BBTB /* Bb-channel Receive Buffer (R) */ +#define BCTB 0x06UL /* Bc-channel Transmit Buffer (W) */ +#define BCRB BCTB /* Bc-channel Receive Buffer (R) */ +#define DSR2 0x07UL /* D-channel Status Register 2 (R) */ /* Indirect registers in the Main Audio Processor. */ struct amd7930_map { @@ -270,4 +266,5 @@ /* Give this chip a "default" sample rate */ #define AMD7930_RATE (8000) -#endif + +#endif /* _AMD7930_H_ */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c --- v2.3.34/linux/drivers/sbus/audio/audio.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/audio.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: audio.c,v 1.47 1999/12/15 22:30:16 davem Exp $ * drivers/sbus/audio/audio.c * * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) @@ -97,14 +97,13 @@ /* If we've used up SPARCAUDIO_MAX_DEVICES, fail */ for (dev = 0; dev < SPARCAUDIO_MAX_DEVICES; dev++) { - if (drivers[dev] == NULL) { - break; - } - } - if (drivers[dev]) { - return -EIO; + if (drivers[dev] == NULL) + break; } + if (drivers[dev]) + return -EIO; + /* Ensure that the driver has a proper operations structure. */ if (!drv->ops || !drv->ops->start_output || !drv->ops->stop_output || !drv->ops->start_input || !drv->ops->stop_input) @@ -146,17 +145,18 @@ drv->output_notify = kmalloc(drv->num_output_buffers * sizeof(char), GFP_KERNEL); if (!drv->output_buffers || !drv->output_sizes || !drv->output_notify) - goto kmalloc_failed1; + goto kmalloc_failed1; drv->output_buffer = kmalloc((drv->output_buffer_size * - drv->num_output_buffers), - (GFP_DMA | GFP_KERNEL)); - if (!drv->output_buffer) goto kmalloc_failed2; + drv->num_output_buffers), + GFP_KERNEL); + if (!drv->output_buffer) + goto kmalloc_failed2; /* Allocate the pages for each output buffer. */ for (i = 0; i < drv->num_output_buffers; i++) { drv->output_buffers[i] = (void *)(drv->output_buffer + - (i * drv->output_buffer_size)); + (i * drv->output_buffer_size)); drv->output_sizes[i] = 0; drv->output_notify[i] = 0; } @@ -174,31 +174,32 @@ drv->input_buffers = kmalloc(drv->num_input_buffers * sizeof(__u8 *), GFP_KERNEL); drv->input_sizes = kmalloc(drv->num_input_buffers * - sizeof(size_t), GFP_KERNEL); - if (!drv->input_buffers || !drv->input_sizes) goto kmalloc_failed3; + sizeof(size_t), GFP_KERNEL); + if (!drv->input_buffers || !drv->input_sizes) + goto kmalloc_failed3; /* Allocate the pages for each input buffer. */ if (duplex == 1) { - drv->input_buffer = kmalloc((drv->input_buffer_size * - drv->num_input_buffers), - (GFP_DMA | GFP_KERNEL)); - if (!drv->input_buffer) goto kmalloc_failed4; - - for (i = 0; i < drv->num_input_buffers; i++) { - drv->input_buffers[i] = (void *)(drv->input_buffer + - (i * drv->input_buffer_size)); - } + drv->input_buffer = kmalloc((drv->input_buffer_size * + drv->num_input_buffers), + GFP_DMA); + if (!drv->input_buffer) + goto kmalloc_failed4; + + for (i = 0; i < drv->num_input_buffers; i++) + drv->input_buffers[i] = (void *)(drv->input_buffer + + (i * drv->input_buffer_size)); } else { - if (duplex == 2) { - drv->input_buffer = drv->output_buffer; - drv->input_buffer_size = drv->output_buffer_size; - drv->num_input_buffers = drv->num_output_buffers; - for (i = 0; i < drv->num_input_buffers; i++) - drv->input_buffers[i] = drv->output_buffers[i]; - } else { - for (i = 0; i < drv->num_input_buffers; i++) - drv->input_buffers[i] = NULL; - } + if (duplex == 2) { + drv->input_buffer = drv->output_buffer; + drv->input_buffer_size = drv->output_buffer_size; + drv->num_input_buffers = drv->num_output_buffers; + for (i = 0; i < drv->num_input_buffers; i++) + drv->input_buffers[i] = drv->output_buffers[i]; + } else { + for (i = 0; i < drv->num_input_buffers; i++) + drv->input_buffers[i] = NULL; + } } /* Take note of our duplexity */ @@ -253,13 +254,13 @@ /* Deallocate the queue of input buffers. */ if (duplex == 1) { - kfree(drv->input_buffer); - kfree(drv->input_sizes); + kfree(drv->input_buffer); + kfree(drv->input_sizes); } kfree(drv->input_buffers); if (&(drv->sd_siglist) != NULL) - lis_free_elist( &(drv->sd_siglist) ); + lis_free_elist( &(drv->sd_siglist) ); MOD_DEC_USE_COUNT; @@ -271,123 +272,122 @@ void sparcaudio_output_done(struct sparcaudio_driver * drv, int status) { - /* - * If !status, just restart current output. - * If status & 1, a buffer is finished; make it available again. - * If status & 2, a buffer was claimed for DMA and is still in use. - * - * The playing_count for non-DMA hardware should never be non-zero. - * Value of status for non-DMA hardware should always be 1. - */ - if (status & 1) { - if (drv->playing_count) - drv->playing_count--; - else { - drv->output_count--; - drv->output_size -= drv->output_sizes[drv->output_front]; - if (drv->output_notify[drv->output_front] == 1) { - drv->output_eof++; - drv->output_notify[drv->output_front] = 0; - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - } - drv->output_front = (drv->output_front + 1) % - drv->num_output_buffers; - } - } + /* If !status, just restart current output. + * If status & 1, a buffer is finished; make it available again. + * If status & 2, a buffer was claimed for DMA and is still in use. + * + * The playing_count for non-DMA hardware should never be non-zero. + * Value of status for non-DMA hardware should always be 1. + */ + if (status & 1) { + if (drv->playing_count) { + drv->playing_count--; + } else { + drv->output_count--; + drv->output_size -= drv->output_sizes[drv->output_front]; + if (drv->output_notify[drv->output_front] == 1) { + drv->output_eof++; + drv->output_notify[drv->output_front] = 0; + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + } + drv->output_front = (drv->output_front + 1) % + drv->num_output_buffers; + } + } - if (status & 2) { - drv->output_count--; - drv->playing_count++; - drv->output_size -= drv->output_sizes[drv->output_front]; - if (drv->output_notify[drv->output_front] == 1) { - drv->output_eof++; - drv->output_notify[drv->output_front] = 0; - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - } - drv->output_front = (drv->output_front + 1) % - drv->num_output_buffers; - } + if (status & 2) { + drv->output_count--; + drv->playing_count++; + drv->output_size -= drv->output_sizes[drv->output_front]; + if (drv->output_notify[drv->output_front] == 1) { + drv->output_eof++; + drv->output_notify[drv->output_front] = 0; + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + } + drv->output_front = (drv->output_front + 1) % + drv->num_output_buffers; + } - /* If we've played everything go inactive. */ - if ((drv->output_count < 1) && (drv->playing_count < 1)) - drv->output_active = 0; - - /* If we got back a buffer, see if anyone wants to write to it */ - if ((status & 1) || ((drv->output_count + drv->playing_count) - < drv->num_output_buffers)) { - wake_up_interruptible(&drv->output_write_wait); - } + /* If we've played everything go inactive. */ + if ((drv->output_count < 1) && (drv->playing_count < 1)) + drv->output_active = 0; + + /* If we got back a buffer, see if anyone wants to write to it */ + if ((status & 1) || ((drv->output_count + drv->playing_count) + < drv->num_output_buffers)) { + wake_up_interruptible(&drv->output_write_wait); + } - /* If the output queue is empty, shut down the driver. */ - if ((drv->output_count < 1) && (drv->playing_count < 1)) { - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - - /* Stop the lowlevel driver from outputing. */ - /* drv->ops->stop_output(drv); Should not be necessary -- DJB 5/25/98 */ - drv->output_active = 0; + /* If the output queue is empty, shut down the driver. */ + if ((drv->output_count < 1) && (drv->playing_count < 1)) { + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + + /* Stop the lowlevel driver from outputing. */ + /* drv->ops->stop_output(drv); Should not be necessary -- DJB 5/25/98 */ + drv->output_active = 0; - /* Wake up any waiting writers or syncers and return. */ - wake_up_interruptible(&drv->output_write_wait); - wake_up_interruptible(&drv->output_drain_wait); - return; - } + /* Wake up any waiting writers or syncers and return. */ + wake_up_interruptible(&drv->output_write_wait); + wake_up_interruptible(&drv->output_drain_wait); + return; + } - /* Start next block of output if we have it */ - if (drv->output_count > 0) { - drv->ops->start_output(drv, drv->output_buffers[drv->output_front], - drv->output_sizes[drv->output_front]); - drv->output_active = 1; - } else - drv->output_active = 0; + /* Start next block of output if we have it */ + if (drv->output_count > 0) { + drv->ops->start_output(drv, drv->output_buffers[drv->output_front], + drv->output_sizes[drv->output_front]); + drv->output_active = 1; + } else { + drv->output_active = 0; + } } void sparcaudio_input_done(struct sparcaudio_driver * drv, int status) { - /* Deal with the weird case here */ - if (drv->duplex == 2) { - if (drv->input_count < drv->num_input_buffers) - drv->input_count++; - drv->ops->start_input(drv, drv->input_buffers[drv->input_front], - drv->input_buffer_size); - wake_up_interruptible(&drv->input_read_wait); - return; - } - - /* - * If status % 2, they filled a buffer for us. - * If status & 2, they took a buffer from us. - */ - - if ((status % 2) == 1) { - drv->input_count++; - drv->recording_count--; - drv->input_size+=drv->input_buffer_size; - } + /* Deal with the weird case here */ + if (drv->duplex == 2) { + if (drv->input_count < drv->num_input_buffers) + drv->input_count++; + drv->ops->start_input(drv, drv->input_buffers[drv->input_front], + drv->input_buffer_size); + wake_up_interruptible(&drv->input_read_wait); + return; + } - if (status > 1) { - drv->recording_count++; - drv->input_front = (drv->input_front + 1) % drv->num_input_buffers; - } - - dprintk(("f%d r%d c%d u%d\n", drv->input_front, drv->input_rear, drv->input_count, drv->recording_count)); - /* If the input queue is full, shutdown the driver. */ - if ((drv->input_count + drv->recording_count) == drv->num_input_buffers) { - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - - /* Stop the lowlevel driver from inputing. */ - drv->ops->stop_input(drv); - drv->input_active = 0; - } else { - /* Otherwise, give the driver the next buffer. */ - drv->ops->start_input(drv, drv->input_buffers[drv->input_front], - drv->input_buffer_size); - } + /* If status % 2, they filled a buffer for us. + * If status & 2, they took a buffer from us. + */ + if ((status % 2) == 1) { + drv->input_count++; + drv->recording_count--; + drv->input_size+=drv->input_buffer_size; + } - /* Wake up any tasks that are waiting. */ - wake_up_interruptible(&drv->input_read_wait); -} + if (status > 1) { + drv->recording_count++; + drv->input_front = (drv->input_front + 1) % drv->num_input_buffers; + } + dprintk(("f%d r%d c%d u%d\n", + drv->input_front, drv->input_rear, + drv->input_count, drv->recording_count)); + + /* If the input queue is full, shutdown the driver. */ + if ((drv->input_count + drv->recording_count) == drv->num_input_buffers) { + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + + /* Stop the lowlevel driver from inputing. */ + drv->ops->stop_input(drv); + drv->input_active = 0; + } else { + /* Otherwise, give the driver the next buffer. */ + drv->ops->start_input(drv, drv->input_buffers[drv->input_front], + drv->input_buffer_size); + } + /* Wake up any tasks that are waiting. */ + wake_up_interruptible(&drv->input_read_wait); +} /* * VFS layer interface @@ -397,49 +397,50 @@ static int sparcaudio_select(struct inode * inode, struct file * file, int sel_type, select_table * wait) { - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; - switch (sel_type) { - case SEL_IN: - if (((!file->f_flags & O_NONBLOCK) && drv->input_count) || - (drv->input_size > drv->buffer_size)) { - dprintk(("read ready: c%d o%d\n", drv->input_count, drv->input_offset)); - return 1; - } - select_wait(&drv->input_read_wait, wait); - break; - case SEL_OUT: - dprintk(("sel out: c%d o%d p%d\n", drv->output_count, drv->output_offset, drv->playing_count)); - if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) { - return 1; - } - select_wait(&drv->output_write_wait, wait); - break; - case SEL_EX: - break; - } + switch (sel_type) { + case SEL_IN: + if (((!file->f_flags & O_NONBLOCK) && drv->input_count) || + (drv->input_size > drv->buffer_size)) { + dprintk(("read ready: c%d o%d\n", + drv->input_count, drv->input_offset)); + return 1; + } + select_wait(&drv->input_read_wait, wait); + break; + case SEL_OUT: + dprintk(("sel out: c%d o%d p%d\n", + drv->output_count, drv->output_offset, drv->playing_count)); + if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) + return 1; + select_wait(&drv->output_write_wait, wait); + break; + case SEL_EX: + break; + }; - return 0; + return 0; } #else static unsigned int sparcaudio_poll(struct file *file, poll_table * wait) { - unsigned int mask = 0; - struct inode *inode = file->f_dentry->d_inode; - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; - - poll_wait(file, &drv->input_read_wait, wait); - poll_wait(file, &drv->output_write_wait, wait); - if (((!file->f_flags & O_NONBLOCK) && drv->input_count) || - (drv->input_size > drv->buffer_size)) { - mask |= POLLIN | POLLRDNORM; - } - if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) { - mask |= POLLOUT | POLLWRNORM; - } - return mask; + unsigned int mask = 0; + struct inode *inode = file->f_dentry->d_inode; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; + + poll_wait(file, &drv->input_read_wait, wait); + poll_wait(file, &drv->output_write_wait, wait); + if (((!file->f_flags & O_NONBLOCK) && drv->input_count) || + (drv->input_size > drv->buffer_size)) { + mask |= POLLIN | POLLRDNORM; + } + if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) { + mask |= POLLOUT | POLLWRNORM; + } + return mask; } #endif @@ -462,78 +463,77 @@ #endif { #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; #endif - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; - int bytes_to_copy, bytes_read = 0, err; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; + int bytes_to_copy, bytes_read = 0, err; - if (! file->f_mode & FMODE_READ) - return -EINVAL; + if (! (file->f_mode & FMODE_READ)) + return -EINVAL; - if ((file->f_flags & O_NONBLOCK) && (drv->input_size < count)) - return -EAGAIN; + if ((file->f_flags & O_NONBLOCK) && (drv->input_size < count)) + return -EAGAIN; - while (count > 0) { - if (drv->input_count == 0) { - /* This *should* never happen. */ - if (file->f_flags & O_NONBLOCK) { - printk("Warning: audio input leak!\n"); - return -EAGAIN; - } - interruptible_sleep_on(&drv->input_read_wait); - if (signal_pending(current)) - return -EINTR; - } + while (count > 0) { + if (drv->input_count == 0) { + /* This *should* never happen. */ + if (file->f_flags & O_NONBLOCK) { + printk("Warning: audio input leak!\n"); + return -EAGAIN; + } + interruptible_sleep_on(&drv->input_read_wait); + if (signal_pending(current)) + return -EINTR; + } - bytes_to_copy = drv->input_buffer_size - drv->input_offset; - - if (bytes_to_copy > count) - bytes_to_copy = count; + bytes_to_copy = drv->input_buffer_size - drv->input_offset; + if (bytes_to_copy > count) + bytes_to_copy = count; + + err = verify_area(VERIFY_WRITE, buf, bytes_to_copy); + if (err) + return err; + + copy_to_user(buf, drv->input_buffers[drv->input_rear]+drv->input_offset, + bytes_to_copy); + + drv->input_offset += bytes_to_copy; + drv->input_size -= bytes_to_copy; + buf += bytes_to_copy; + count -= bytes_to_copy; + bytes_read += bytes_to_copy; + + if (drv->input_offset >= drv->input_buffer_size) { + drv->input_rear = (drv->input_rear + 1) % + drv->num_input_buffers; + drv->input_count--; + drv->input_offset = 0; + } - err = verify_area(VERIFY_WRITE, buf, bytes_to_copy); - if (err) - return err; - - copy_to_user(buf, drv->input_buffers[drv->input_rear]+drv->input_offset, - bytes_to_copy); - - drv->input_offset += bytes_to_copy; - drv->input_size -= bytes_to_copy; - buf += bytes_to_copy; - count -= bytes_to_copy; - bytes_read += bytes_to_copy; - - if (drv->input_offset >= drv->input_buffer_size) { - drv->input_rear = (drv->input_rear + 1) % - drv->num_input_buffers; - drv->input_count--; - drv->input_offset = 0; - } - /* If we're in "loop audio" mode, try waking up the other side - * in case they're waiting for us to eat a block. - */ - if (drv->duplex == 2) { - wake_up_interruptible(&drv->output_write_wait); - } - } + /* If we're in "loop audio" mode, try waking up the other side + * in case they're waiting for us to eat a block. + */ + if (drv->duplex == 2) + wake_up_interruptible(&drv->output_write_wait); + } - return bytes_read; + return bytes_read; } static void sparcaudio_sync_output(struct sparcaudio_driver * drv) { - unsigned long flags; + unsigned long flags; - /* If the low-level driver is not active, activate it. */ - save_and_cli(flags); - if ((!drv->output_active) && (drv->output_count > 0)) { - drv->ops->start_output(drv, - drv->output_buffers[drv->output_front], - drv->output_sizes[drv->output_front]); - drv->output_active = 1; - } - restore_flags(flags); + /* If the low-level driver is not active, activate it. */ + save_and_cli(flags); + if ((!drv->output_active) && (drv->output_count > 0)) { + drv->ops->start_output(drv, + drv->output_buffers[drv->output_front], + drv->output_sizes[drv->output_front]); + drv->output_active = 1; + } + restore_flags(flags); } #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 @@ -545,317 +545,319 @@ #endif { #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; #endif - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; - int bytes_written = 0, bytes_to_copy, err; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; + int bytes_written = 0, bytes_to_copy, err; - if (! file->f_mode & FMODE_WRITE) - return -EINVAL; + if (! (file->f_mode & FMODE_WRITE)) + return -EINVAL; - /* - * A signal they want notification when this is processed. Too bad - * sys_write doesn't tell us unless you patch it, in 2.0 kernels. - */ - if (count == 0) { + /* A signal they want notification when this is processed. Too bad + * sys_write doesn't tell us unless you patch it, in 2.0 kernels. + */ + if (count == 0) { #ifndef notdef - drv->output_eof++; - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + drv->output_eof++; + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); #else - /* Nice code, but the world isn't ready yet... */ - drv->output_notify[drv->output_rear] = 1; + /* Nice code, but the world isn't ready yet... */ + drv->output_notify[drv->output_rear] = 1; #endif - } + } - /* Loop until all output is written to device. */ - while (count > 0) { - /* Check to make sure that an output buffer is available. */ - if (drv->num_output_buffers == (drv->output_count + drv->playing_count)) { - /* We need buffers, so... */ - sparcaudio_sync_output(drv); - if (file->f_flags & O_NONBLOCK) { - return -EAGAIN; - } - interruptible_sleep_on(&drv->output_write_wait); - if (signal_pending(current)) - return bytes_written > 0 ? bytes_written : -EINTR; - } - - /* No buffers were freed. Go back to sleep */ - if (drv->num_output_buffers == (drv->output_count + drv->playing_count)) - continue; - - /* Deal with the weird case of a reader in the write area by trying to - * let them keep ahead of us... Go to sleep until they start servicing. - */ - if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) && - (drv->output_rear == drv->input_rear) && (drv->input_count > 0)) { - if (file->f_flags & O_NONBLOCK) { - return -EAGAIN; - } - interruptible_sleep_on(&drv->output_write_wait); - if (signal_pending(current)) - return bytes_written > 0 ? bytes_written : -EINTR; - } - - /* Determine how much we can copy in this iteration. */ - bytes_to_copy = count; - if (bytes_to_copy > drv->output_buffer_size - drv->output_offset) - bytes_to_copy = drv->output_buffer_size - drv->output_offset; + /* Loop until all output is written to device. */ + while (count > 0) { + /* Check to make sure that an output buffer is available. */ + if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) { + /* We need buffers, so... */ + sparcaudio_sync_output(drv); + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + interruptible_sleep_on(&drv->output_write_wait); + if (signal_pending(current)) + return bytes_written > 0 ? bytes_written : -EINTR; + } + + /* No buffers were freed. Go back to sleep */ + if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) + continue; + + /* Deal with the weird case of a reader in the write area by trying to + * let them keep ahead of us... Go to sleep until they start servicing. + */ + if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) && + (drv->output_rear == drv->input_rear) && (drv->input_count > 0)) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + interruptible_sleep_on(&drv->output_write_wait); + if (signal_pending(current)) + return bytes_written > 0 ? bytes_written : -EINTR; + } + + /* Determine how much we can copy in this iteration. */ + bytes_to_copy = count; + if (bytes_to_copy > drv->output_buffer_size - drv->output_offset) + bytes_to_copy = drv->output_buffer_size - drv->output_offset; - err = verify_area(VERIFY_READ, buf, bytes_to_copy); - if (err) - return err; + err = verify_area(VERIFY_READ, buf, bytes_to_copy); + if (err) + return err; - copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset, buf, bytes_to_copy); + copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset, + buf, bytes_to_copy); - /* Update the queue pointers. */ - buf += bytes_to_copy; - count -= bytes_to_copy; - bytes_written += bytes_to_copy; - - /* A block can get orphaned in a flush and not cleaned up. */ - if (drv->output_offset) - drv->output_sizes[drv->output_rear] += bytes_to_copy; - else - drv->output_sizes[drv->output_rear] = bytes_to_copy; - - drv->output_notify[drv->output_rear] = 0; - - if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) { - drv->output_rear = (drv->output_rear + 1) - % drv->num_output_buffers; - drv->output_count++; - drv->output_offset = 0; - } else - drv->output_offset += bytes_to_copy; + /* Update the queue pointers. */ + buf += bytes_to_copy; + count -= bytes_to_copy; + bytes_written += bytes_to_copy; + + /* A block can get orphaned in a flush and not cleaned up. */ + if (drv->output_offset) + drv->output_sizes[drv->output_rear] += bytes_to_copy; + else + drv->output_sizes[drv->output_rear] = bytes_to_copy; + + drv->output_notify[drv->output_rear] = 0; + + if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) { + drv->output_rear = (drv->output_rear + 1) + % drv->num_output_buffers; + drv->output_count++; + drv->output_offset = 0; + } else { + drv->output_offset += bytes_to_copy; + } - drv->output_size+=bytes_to_copy; - } + drv->output_size += bytes_to_copy; + } - sparcaudio_sync_output(drv); + sparcaudio_sync_output(drv); - /* Return the number of bytes written to the caller. */ - return bytes_written; + /* Return the number of bytes written to the caller. */ + return bytes_written; } /* Add these in as new devices are supported. Belongs in audioio.h, actually */ #define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC) static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned int *arg) + unsigned int cmd, unsigned int *arg) { - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; - unsigned long i = 0, j = 0, l = 0, m = 0; - unsigned int k = 0; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - drv->mixer_modify_counter++; - - if(cmd == SOUND_MIXER_INFO) { - audio_device_t tmp; - mixer_info info; - int retval = -EINVAL; - - if(drv->ops->sunaudio_getdev) { - drv->ops->sunaudio_getdev(drv, &tmp); - memset(&info, 0, sizeof(info)); - strncpy(info.id, tmp.name, sizeof(info.id)); - strncpy(info.name, "Sparc Audio", sizeof(info.name)); - info.modify_counter = drv->mixer_modify_counter; - - if(copy_to_user((char *)arg, &info, sizeof(info))) - retval = -EFAULT; - else - retval = 0; - } - return retval; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; + unsigned long i = 0, j = 0, l = 0, m = 0; + unsigned int k = 0; + + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + drv->mixer_modify_counter++; + + if(cmd == SOUND_MIXER_INFO) { + audio_device_t tmp; + mixer_info info; + int retval = -EINVAL; + + if(drv->ops->sunaudio_getdev) { + drv->ops->sunaudio_getdev(drv, &tmp); + memset(&info, 0, sizeof(info)); + strncpy(info.id, tmp.name, sizeof(info.id)); + strncpy(info.name, "Sparc Audio", sizeof(info.name)); + info.modify_counter = drv->mixer_modify_counter; + + if(copy_to_user((char *)arg, &info, sizeof(info))) + retval = -EFAULT; + else + retval = 0; + } + return retval; } - switch (cmd) { - case SOUND_MIXER_WRITE_RECLEV: - if(COPY_IN(arg, k)) - return -EFAULT; - iretry: - oprintk(("setting input volume (0x%x)", k)); - if (drv->ops->get_input_channels) - j = drv->ops->get_input_channels(drv); - if (drv->ops->get_input_volume) - l = drv->ops->get_input_volume(drv); - if (drv->ops->get_input_balance) - m = drv->ops->get_input_balance(drv); - i = OSS_TO_GAIN(k); - j = OSS_TO_BAL(k); - oprintk((" for stereo to to %d (bal %d):", i, j)); - if (drv->ops->set_input_volume) - drv->ops->set_input_volume(drv, i); - if (drv->ops->set_input_balance) - drv->ops->set_input_balance(drv, j); - case SOUND_MIXER_READ_RECLEV: - if (drv->ops->get_input_volume) - i = drv->ops->get_input_volume(drv); - if (drv->ops->get_input_balance) - j = drv->ops->get_input_balance(drv); - oprintk((" got (0x%x)\n", BAL_TO_OSS(i,j))); - i = BAL_TO_OSS(i,j); - /* Try to be reasonable about volume changes */ - if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) && - (i == BAL_TO_OSS(l,m))) - { - k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; - k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; - oprintk((" try 0x%x\n", k)); - goto iretry; - } - return COPY_OUT(arg, i); - case SOUND_MIXER_WRITE_VOLUME: - if(COPY_IN(arg, k)) - return -EFAULT; - if (drv->ops->get_output_muted && drv->ops->set_output_muted) { - i = drv->ops->get_output_muted(drv); - if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100))) - drv->ops->set_output_muted(drv, 1); - else - drv->ops->set_output_muted(drv, 0); - } - case SOUND_MIXER_READ_VOLUME: - if (drv->ops->get_output_muted) - i = drv->ops->get_output_muted(drv); - k = 0x6464 * (1 - i); - return COPY_OUT(arg, k); - case SOUND_MIXER_WRITE_PCM: - if(COPY_IN(arg, k)) - return -EFAULT; - oretry: - oprintk(("setting output volume (0x%x)\n", k)); - if (drv->ops->get_output_channels) - j = drv->ops->get_output_channels(drv); - if (drv->ops->get_output_volume) - l = drv->ops->get_output_volume(drv); - if (drv->ops->get_output_balance) - m = drv->ops->get_output_balance(drv); - oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m))); - i = OSS_TO_GAIN(k); - j = OSS_TO_BAL(k); - oprintk((" for stereo to %d (bal %d)\n", i, j)); - if (drv->ops->set_output_volume) - drv->ops->set_output_volume(drv, i); - if (drv->ops->set_output_balance) - drv->ops->set_output_balance(drv, j); - case SOUND_MIXER_READ_PCM: - if (drv->ops->get_output_volume) - i = drv->ops->get_output_volume(drv); - if (drv->ops->get_output_balance) - j = drv->ops->get_output_balance(drv); - oprintk((" got 0x%x\n", BAL_TO_OSS(i,j))); - i = BAL_TO_OSS(i,j); - /* Try to be reasonable about volume changes */ - if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) && - (i == BAL_TO_OSS(l,m))) - { - k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; - k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; - oprintk((" try 0x%x\n", k)); - goto oretry; - } - return COPY_OUT(arg, i); - case SOUND_MIXER_READ_SPEAKER: - k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_MIC: - k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_CD: - k = OSS_IPORT_AUDIO(drv, AUDIO_CD); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_LINE: - k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_LINE1: - k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_LINE2: - k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT); - return COPY_OUT(arg, k); - - case SOUND_MIXER_WRITE_MIC: - case SOUND_MIXER_WRITE_CD: - case SOUND_MIXER_WRITE_LINE: - case SOUND_MIXER_WRITE_LINE1: - case SOUND_MIXER_WRITE_LINE2: - case SOUND_MIXER_WRITE_SPEAKER: - if(COPY_IN(arg, k)) - return -EFAULT; - OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k); - OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k); - OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k); - - OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k); - OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k); - OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k); - return COPY_OUT(arg, k); - case SOUND_MIXER_READ_RECSRC: - if (drv->ops->get_input_port) - i = drv->ops->get_input_port(drv); - /* only one should ever be selected */ - if (i & AUDIO_CD) j = SOUND_MASK_CD; - if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE; - if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC; + switch (cmd) { + case SOUND_MIXER_WRITE_RECLEV: + if(COPY_IN(arg, k)) + return -EFAULT; + iretry: + oprintk(("setting input volume (0x%x)", k)); + if (drv->ops->get_input_channels) + j = drv->ops->get_input_channels(drv); + if (drv->ops->get_input_volume) + l = drv->ops->get_input_volume(drv); + if (drv->ops->get_input_balance) + m = drv->ops->get_input_balance(drv); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); + oprintk((" for stereo to to %d (bal %d):", i, j)); + if (drv->ops->set_input_volume) + drv->ops->set_input_volume(drv, i); + if (drv->ops->set_input_balance) + drv->ops->set_input_balance(drv, j); + case SOUND_MIXER_READ_RECLEV: + if (drv->ops->get_input_volume) + i = drv->ops->get_input_volume(drv); + if (drv->ops->get_input_balance) + j = drv->ops->get_input_balance(drv); + oprintk((" got (0x%x)\n", BAL_TO_OSS(i,j))); + i = BAL_TO_OSS(i,j); + /* Try to be reasonable about volume changes */ + if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) && + (i == BAL_TO_OSS(l,m))) { + k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; + k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; + oprintk((" try 0x%x\n", k)); + goto iretry; + } + return COPY_OUT(arg, i); + case SOUND_MIXER_WRITE_VOLUME: + if(COPY_IN(arg, k)) + return -EFAULT; + if (drv->ops->get_output_muted && drv->ops->set_output_muted) { + i = drv->ops->get_output_muted(drv); + if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100))) + drv->ops->set_output_muted(drv, 1); + else + drv->ops->set_output_muted(drv, 0); + } + case SOUND_MIXER_READ_VOLUME: + if (drv->ops->get_output_muted) + i = drv->ops->get_output_muted(drv); + k = 0x6464 * (1 - i); + return COPY_OUT(arg, k); + case SOUND_MIXER_WRITE_PCM: + if(COPY_IN(arg, k)) + return -EFAULT; + oretry: + oprintk(("setting output volume (0x%x)\n", k)); + if (drv->ops->get_output_channels) + j = drv->ops->get_output_channels(drv); + if (drv->ops->get_output_volume) + l = drv->ops->get_output_volume(drv); + if (drv->ops->get_output_balance) + m = drv->ops->get_output_balance(drv); + oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m))); + i = OSS_TO_GAIN(k); + j = OSS_TO_BAL(k); + oprintk((" for stereo to %d (bal %d)\n", i, j)); + if (drv->ops->set_output_volume) + drv->ops->set_output_volume(drv, i); + if (drv->ops->set_output_balance) + drv->ops->set_output_balance(drv, j); + case SOUND_MIXER_READ_PCM: + if (drv->ops->get_output_volume) + i = drv->ops->get_output_volume(drv); + if (drv->ops->get_output_balance) + j = drv->ops->get_output_balance(drv); + oprintk((" got 0x%x\n", BAL_TO_OSS(i,j))); + i = BAL_TO_OSS(i,j); + + /* Try to be reasonable about volume changes */ + if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) && + (i == BAL_TO_OSS(l,m))) { + k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256; + k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1; + oprintk((" try 0x%x\n", k)); + goto oretry; + } + return COPY_OUT(arg, i); + case SOUND_MIXER_READ_SPEAKER: + k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_MIC: + k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_CD: + k = OSS_IPORT_AUDIO(drv, AUDIO_CD); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE: + k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE1: + k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_LINE2: + k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT); + return COPY_OUT(arg, k); + + case SOUND_MIXER_WRITE_MIC: + case SOUND_MIXER_WRITE_CD: + case SOUND_MIXER_WRITE_LINE: + case SOUND_MIXER_WRITE_LINE1: + case SOUND_MIXER_WRITE_LINE2: + case SOUND_MIXER_WRITE_SPEAKER: + if(COPY_IN(arg, k)) + return -EFAULT; + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k); + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k); + OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k); + + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k); + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k); + OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k); + return COPY_OUT(arg, k); + case SOUND_MIXER_READ_RECSRC: + if (drv->ops->get_input_port) + i = drv->ops->get_input_port(drv); + + /* only one should ever be selected */ + if (i & AUDIO_CD) j = SOUND_MASK_CD; + if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE; + if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC; - return COPY_OUT(arg, j); + return COPY_OUT(arg, j); case SOUND_MIXER_WRITE_RECSRC: - if (!drv->ops->set_input_port) - return -EINVAL; - if(COPY_IN(arg, k)) - return -EFAULT; - /* only one should ever be selected */ - if (k & SOUND_MASK_CD) j = AUDIO_CD; - if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; - if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; - oprintk(("setting inport to %d\n", j)); - i = drv->ops->set_input_port(drv, j); + if (!drv->ops->set_input_port) + return -EINVAL; + if(COPY_IN(arg, k)) + return -EFAULT; + + /* only one should ever be selected */ + if (k & SOUND_MASK_CD) j = AUDIO_CD; + if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; + if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; + oprintk(("setting inport to %d\n", j)); + i = drv->ops->set_input_port(drv, j); - return COPY_OUT(arg, i); - case SOUND_MIXER_READ_RECMASK: - if (drv->ops->get_input_ports) - i = drv->ops->get_input_ports(drv); - /* what do we support? */ - if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; - if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; - if (i & AUDIO_CD) j |= SOUND_MASK_CD; + return COPY_OUT(arg, i); + case SOUND_MIXER_READ_RECMASK: + if (drv->ops->get_input_ports) + i = drv->ops->get_input_ports(drv); + /* what do we support? */ + if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; + if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; + if (i & AUDIO_CD) j |= SOUND_MASK_CD; - return COPY_OUT(arg, j); - case SOUND_MIXER_READ_CAPS: /* mixer capabilities */ - i = SOUND_CAP_EXCL_INPUT; - return COPY_OUT(arg, i); - - case SOUND_MIXER_READ_DEVMASK: /* all supported devices */ - if (drv->ops->get_input_ports) - i = drv->ops->get_input_ports(drv); - /* what do we support? */ - if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; - if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; - if (i & AUDIO_CD) j |= SOUND_MASK_CD; + return COPY_OUT(arg, j); + case SOUND_MIXER_READ_CAPS: /* mixer capabilities */ + i = SOUND_CAP_EXCL_INPUT; + return COPY_OUT(arg, i); + + case SOUND_MIXER_READ_DEVMASK: /* all supported devices */ + if (drv->ops->get_input_ports) + i = drv->ops->get_input_ports(drv); + /* what do we support? */ + if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC; + if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE; + if (i & AUDIO_CD) j |= SOUND_MASK_CD; - if (drv->ops->get_output_ports) - i = drv->ops->get_output_ports(drv); - if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER; - if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1; - if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2; - - j |= SOUND_MASK_VOLUME; - - case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */ - j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV; - - if (cmd == SOUND_MIXER_READ_STEREODEVS) - j &= ~(MONO_DEVICES); - return COPY_OUT(arg, j); - default: - return -EINVAL; - } + if (drv->ops->get_output_ports) + i = drv->ops->get_output_ports(drv); + if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER; + if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1; + if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2; + + j |= SOUND_MASK_VOLUME; + + case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */ + j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV; + + if (cmd == SOUND_MIXER_READ_STEREODEVS) + j &= ~(MONO_DEVICES); + return COPY_OUT(arg, j); + default: + return -EINVAL; + }; } /* AUDIO_SETINFO uses these to set values if possible. */ @@ -865,12 +867,12 @@ int (*get_function)(struct sparcaudio_driver *), unsigned int value) { - if (set_function && Modify(value)) - return (int)set_function(drv, value); - else if (get_function) - return (int)get_function(drv); - else - return 0; + if (set_function && Modify(value)) + return (int) set_function(drv, value); + else if (get_function) + return (int) get_function(drv); + else + return 0; } static __inline__ int @@ -879,12 +881,12 @@ int (*get_function)(struct sparcaudio_driver *), unsigned char value) { - if (set_function && Modifyc(value)) - return (char)set_function(drv, (int)value); - else if (get_function) - return (char)get_function(drv); - else - return 0; + if (set_function && Modifyc(value)) + return (char) set_function(drv, (int)value); + else if (get_function) + return (char) get_function(drv); + else + return 0; } /* I_FLUSH, I_{G,S}ETSIG, I_NREAD provided for SunOS compatibility @@ -892,7 +894,6 @@ * I must admit I'm quite ashamed of the state of the ioctl handling, * but I do have several optimizations which I'm planning. -- DJB */ - static int sparcaudio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { @@ -902,1043 +903,1081 @@ audio_buf_info binfo; count_info cinfo; struct sparcaudio_driver *drv = - drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)]; + drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)]; switch (minor & 0xf) { case SPARCAUDIO_MIXER_MINOR: - return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg); + return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg); case SPARCAUDIO_DSP16_MINOR: case SPARCAUDIO_DSP_MINOR: case SPARCAUDIO_AUDIO_MINOR: case SPARCAUDIO_AUDIOCTL_MINOR: - /* According to the OSS prog int, you can mixer ioctl /dev/dsp */ - if (_IOC_TYPE(cmd) == 'M') - return sparcaudio_mixer_ioctl(inode, - file, cmd, (unsigned int *)arg); - switch (cmd) { - case I_GETSIG: - case I_GETSIG_SOLARIS: - j = (int)lis_get_elist_ent(drv->sd_siglist,current->pid); - COPY_OUT(arg, j); - retval = drv->input_count; - break; - - case I_SETSIG: - case I_SETSIG_SOLARIS: - if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) { - if (!arg){ - if (lis_del_from_elist(&(drv->sd_siglist),current->pid,S_ALL)) - retval = -EINVAL; - else - if (!drv->sd_siglist) - drv->sd_sigflags=0; - } - else - if (lis_add_to_elist(&(drv->sd_siglist),current->pid, - (short)arg)) - retval = -EAGAIN; - else - ((drv->sd_sigflags) |= (arg)); - } - break; - case I_NREAD: - case I_NREAD_SOLARIS: - /* According to the Solaris man page, this copies out - * the size of the first streams buffer and returns - * the number of streams messages on the read queue as - * as its retval. (streamio(7I)) This should work. */ - - j = (drv->input_count > 0) ? drv->input_buffer_size : 0; - COPY_OUT(arg, j); - retval = drv->input_count; - break; - /* - * A poor substitute until we do true resizable buffers. - */ - case SNDCTL_DSP_GETISPACE: - binfo.fragstotal = drv->num_input_buffers; - binfo.fragments = drv->num_input_buffers - - (drv->input_count + drv->recording_count); - binfo.fragsize = drv->input_buffer_size; - binfo.bytes = binfo.fragments*binfo.fragsize; + /* According to the OSS prog int, you can mixer ioctl /dev/dsp */ + if (_IOC_TYPE(cmd) == 'M') + return sparcaudio_mixer_ioctl(inode, + file, cmd, (unsigned int *)arg); + switch (cmd) { + case I_GETSIG: + case I_GETSIG_SOLARIS: + j = (int) lis_get_elist_ent(drv->sd_siglist,current->pid); + COPY_OUT(arg, j); + retval = drv->input_count; + break; + + case I_SETSIG: + case I_SETSIG_SOLARIS: + if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) { + if (!arg) { + if (lis_del_from_elist(&(drv->sd_siglist), + current->pid,S_ALL)) { + retval = -EINVAL; + } else if (!drv->sd_siglist) { + drv->sd_sigflags=0; + } + } else if (lis_add_to_elist(&(drv->sd_siglist), + current->pid, + (short)arg)) { + retval = -EAGAIN; + } else { + ((drv->sd_sigflags) |= (arg)); + } + } + break; + case I_NREAD: + case I_NREAD_SOLARIS: + /* According to the Solaris man page, this copies out + * the size of the first streams buffer and returns + * the number of streams messages on the read queue as + * as its retval. (streamio(7I)) This should work. + */ + j = (drv->input_count > 0) ? drv->input_buffer_size : 0; + COPY_OUT(arg, j); + retval = drv->input_count; + break; + + /* A poor substitute until we do true resizable buffers. */ + case SNDCTL_DSP_GETISPACE: + binfo.fragstotal = drv->num_input_buffers; + binfo.fragments = drv->num_input_buffers - + (drv->input_count + drv->recording_count); + binfo.fragsize = drv->input_buffer_size; + binfo.bytes = binfo.fragments*binfo.fragsize; - retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo)); - if (retval) break; - copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo)); - break; - case SNDCTL_DSP_GETOSPACE: - binfo.fragstotal = drv->num_output_buffers; - binfo.fragments = drv->num_output_buffers - - (drv->output_count + drv->playing_count + - (drv->output_offset ? 1 : 0)); - binfo.fragsize = drv->output_buffer_size; - binfo.bytes = binfo.fragments*binfo.fragsize + - (drv->output_buffer_size - drv->output_offset); + retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo)); + if (retval) + break; + copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo)); + break; + case SNDCTL_DSP_GETOSPACE: + binfo.fragstotal = drv->num_output_buffers; + binfo.fragments = drv->num_output_buffers - + (drv->output_count + drv->playing_count + + (drv->output_offset ? 1 : 0)); + binfo.fragsize = drv->output_buffer_size; + binfo.bytes = binfo.fragments*binfo.fragsize + + (drv->output_buffer_size - drv->output_offset); - retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo)); - if (retval) break; - copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo)); - break; - case SNDCTL_DSP_GETIPTR: - case SNDCTL_DSP_GETOPTR: - /* - * int bytes (number of bytes read/written since last) - * int blocks (number of frags read/wrote since last call) - * int ptr (current position of dma in buffer) - */ - retval = 0; - cinfo.bytes = 0; - cinfo.ptr = 0; - cinfo.blocks = 0; - cinfo.bytes += cinfo.ptr; + retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo)); + if (retval) + break; + copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo)); + break; + case SNDCTL_DSP_GETIPTR: + case SNDCTL_DSP_GETOPTR: + /* int bytes (number of bytes read/written since last) + * int blocks (number of frags read/wrote since last call) + * int ptr (current position of dma in buffer) + */ + retval = 0; + cinfo.bytes = 0; + cinfo.ptr = 0; + cinfo.blocks = 0; + cinfo.bytes += cinfo.ptr; - retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo)); - if (retval) break; - copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo)); - break; - case SNDCTL_DSP_SETFRAGMENT: - /* XXX Small hack to get ESD/Enlightenment to work. --DaveM */ - retval = 0; - break; - - case SNDCTL_DSP_SUBDIVIDE: - /* - * I don't understand what I need to do yet. - */ - retval = -EINVAL; - break; - case SNDCTL_DSP_SETTRIGGER: - /* This may not be 100% correct */ - if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause && - drv->ops->set_input_pause) { - if (drv->ops->get_input_pause(drv)) - drv->ops->set_input_pause(drv, 0); - } else { - if (!drv->ops->get_input_pause(drv)) - drv->ops->set_input_pause(drv, 1); - } - if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause && - drv->ops->set_output_pause) { - if (drv->ops->get_output_pause(drv)) - drv->ops->set_output_pause(drv, 0); - } else { - if (!drv->ops->get_output_pause(drv)) - drv->ops->set_output_pause(drv, 1); - } - break; - case SNDCTL_DSP_GETTRIGGER: - j = 0; - if (drv->ops->get_input_pause) - if (drv->ops->get_input_pause(drv)) - j = PCM_ENABLE_INPUT; - if (drv->ops->get_output_pause) - if (drv->ops->get_output_pause(drv)) - j |= PCM_ENABLE_OUTPUT; - COPY_OUT(arg, j); - break; - case SNDCTL_DSP_GETBLKSIZE: - j = drv->input_buffer_size; - COPY_OUT(arg, j); - break; - case SNDCTL_DSP_SPEED: - if ((!drv->ops->set_output_rate) && - (!drv->ops->set_input_rate)) { - retval = -EINVAL; - break; - } - COPY_IN(arg, i); - tprintk(("setting speed to %d\n", i)); - drv->ops->set_input_rate(drv, i); - drv->ops->set_output_rate(drv, i); - j = drv->ops->get_output_rate(drv); - COPY_OUT(arg, j); - break; - case SNDCTL_DSP_GETCAPS: - /* - * All Sparc audio hardware is full duplex. - * 4231 supports DMA pointer reading, 7930 is byte at a time. - * Pause functionality emulates trigger - */ - j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME; - COPY_OUT(arg, j); - break; - case SNDCTL_DSP_GETFMTS: - if (drv->ops->get_formats) { - j = drv->ops->get_formats(drv); - COPY_OUT(arg, j); - } else - retval = -EINVAL; - break; - case SNDCTL_DSP_SETFMT: - /* need to decode into encoding, precision */ - COPY_IN(arg, i); + retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo)); + if (retval) + break; + copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo)); + break; + case SNDCTL_DSP_SETFRAGMENT: + /* XXX Small hack to get ESD/Enlightenment to work. --DaveM */ + retval = 0; + break; + + case SNDCTL_DSP_SUBDIVIDE: + /* I don't understand what I need to do yet. */ + retval = -EINVAL; + break; + case SNDCTL_DSP_SETTRIGGER: + /* This may not be 100% correct */ + if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause && + drv->ops->set_input_pause) { + if (drv->ops->get_input_pause(drv)) + drv->ops->set_input_pause(drv, 0); + } else { + if (!drv->ops->get_input_pause(drv)) + drv->ops->set_input_pause(drv, 1); + } + if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause && + drv->ops->set_output_pause) { + if (drv->ops->get_output_pause(drv)) + drv->ops->set_output_pause(drv, 0); + } else { + if (!drv->ops->get_output_pause(drv)) + drv->ops->set_output_pause(drv, 1); + } + break; + case SNDCTL_DSP_GETTRIGGER: + j = 0; + if (drv->ops->get_input_pause) { + if (drv->ops->get_input_pause(drv)) + j = PCM_ENABLE_INPUT; + } + if (drv->ops->get_output_pause) { + if (drv->ops->get_output_pause(drv)) + j |= PCM_ENABLE_OUTPUT; + } + COPY_OUT(arg, j); + break; + case SNDCTL_DSP_GETBLKSIZE: + j = drv->input_buffer_size; + COPY_OUT(arg, j); + break; + case SNDCTL_DSP_SPEED: + if ((!drv->ops->set_output_rate) && + (!drv->ops->set_input_rate)) { + retval = -EINVAL; + break; + } + COPY_IN(arg, i); + tprintk(("setting speed to %d\n", i)); + drv->ops->set_input_rate(drv, i); + drv->ops->set_output_rate(drv, i); + j = drv->ops->get_output_rate(drv); + COPY_OUT(arg, j); + break; + case SNDCTL_DSP_GETCAPS: + /* All Sparc audio hardware is full duplex. + * 4231 supports DMA pointer reading, 7930 is byte at a time. + * Pause functionality emulates trigger + */ + j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME; + COPY_OUT(arg, j); + break; + case SNDCTL_DSP_GETFMTS: + if (drv->ops->get_formats) { + j = drv->ops->get_formats(drv); + COPY_OUT(arg, j); + } else { + retval = -EINVAL; + } + break; + case SNDCTL_DSP_SETFMT: + /* need to decode into encoding, precision */ + COPY_IN(arg, i); - /* handle special case here */ - if (i == AFMT_QUERY) { - j = drv->ops->get_output_encoding(drv); - k = drv->ops->get_output_precision(drv); - if (j == AUDIO_ENCODING_DVI) - i = AFMT_IMA_ADPCM; - else if (k == 8) { - switch (j) { - case AUDIO_ENCODING_ULAW: - i = AFMT_MU_LAW; - break; - case AUDIO_ENCODING_ALAW: - i = AFMT_A_LAW; - break; - case AUDIO_ENCODING_LINEAR8: - i = AFMT_U8; - break; - } - } else if (k == 16) { - switch (j) { - case AUDIO_ENCODING_LINEAR: - i = AFMT_S16_BE; - break; - case AUDIO_ENCODING_LINEARLE: - i = AFMT_S16_LE; - break; - } - } - COPY_OUT(arg, i); - break; - } - - /* Without these there's no point in trying */ - if (!drv->ops->set_input_precision || - !drv->ops->set_input_encoding || - !drv->ops->set_output_precision || - !drv->ops->set_output_encoding) { - eprintk(("missing set routines: failed\n")); - retval = -EINVAL; - break; - } - - if (drv->ops->get_formats) - if (!(drv->ops->get_formats(drv) & i)) { - dprintk(("format not supported\n")); - return -EINVAL; - } - - switch (i) { - case AFMT_S16_LE: - ainfo.record.precision = ainfo.play.precision = 16; - ainfo.record.encoding = ainfo.play.encoding = - AUDIO_ENCODING_LINEARLE; - break; - case AFMT_S16_BE: - ainfo.record.precision = ainfo.play.precision = 16; - ainfo.record.encoding = ainfo.play.encoding = - AUDIO_ENCODING_LINEAR; - break; - case AFMT_MU_LAW: - ainfo.record.precision = ainfo.play.precision = 8; - ainfo.record.encoding = ainfo.play.encoding = - AUDIO_ENCODING_ULAW; - break; - case AFMT_A_LAW: - ainfo.record.precision = ainfo.play.precision = 8; - ainfo.record.encoding = ainfo.play.encoding = - AUDIO_ENCODING_ALAW; - break; - case AFMT_U8: - ainfo.record.precision = ainfo.play.precision = 8; - ainfo.record.encoding = ainfo.play.encoding = - AUDIO_ENCODING_LINEAR8; - break; - } - tprintk(("setting fmt to enc %d pr %d\n", ainfo.play.encoding, - ainfo.play.precision)); - if ((drv->ops->set_input_precision(drv, - ainfo.record.precision) - < 0) || - (drv->ops->set_output_precision(drv, - ainfo.play.precision) - < 0) || - (drv->ops->set_input_encoding(drv, - ainfo.record.encoding) - < 0) || - (drv->ops->set_output_encoding(drv, - ainfo.play.encoding) - < 0)) { - dprintk(("setting format: failed\n")); - return -EINVAL; - } - COPY_OUT(arg, i); - break; - case SNDCTL_DSP_CHANNELS: - if ((!drv->ops->set_output_channels) && - (!drv->ops->set_input_channels)) { - retval = -EINVAL; - break; - } - COPY_IN(arg, i); - drv->ops->set_input_channels(drv, i); - drv->ops->set_output_channels(drv, i); - i = drv->ops->get_output_channels(drv); - COPY_OUT(arg, i); - break; - case SNDCTL_DSP_STEREO: - if ((!drv->ops->set_output_channels) && - (!drv->ops->set_input_channels)) { - retval = -EINVAL; - break; - } - COPY_IN(arg, i); - drv->ops->set_input_channels(drv, (i + 1)); - drv->ops->set_output_channels(drv, (i + 1)); - i = ((drv->ops->get_output_channels(drv)) - 1); - COPY_OUT(arg, i); - break; - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SYNC: - case AUDIO_DRAIN: - /* Deal with weirdness so we can fill buffers */ - if (drv->output_offset) { - drv->output_offset = 0; - drv->output_rear = (drv->output_rear + 1) - % drv->num_output_buffers; - drv->output_count++; - } - if (drv->output_count > 0) { - sparcaudio_sync_output(drv); - /* Only pause for DRAIN/SYNC, not POST */ - if (cmd != SNDCTL_DSP_POST) { - interruptible_sleep_on(&drv->output_drain_wait); - retval = (signal_pending(current)) ? -EINTR : 0; - } - } - break; - case I_FLUSH: - case I_FLUSH_SOLARIS: - if (((unsigned int)arg == FLUSHW) || - ((unsigned int)arg == FLUSHRW)) { - if (file->f_mode & FMODE_WRITE) { - sparcaudio_sync_output(drv); - if (drv->output_active) { - wake_up_interruptible(&drv->output_write_wait); - drv->ops->stop_output(drv); - } - drv->output_offset = 0; - drv->output_active = 0; - drv->output_front = 0; - drv->output_rear = 0; - drv->output_count = 0; - drv->output_size = 0; - drv->playing_count = 0; - drv->output_eof = 0; - } - } - if (((unsigned int)arg == FLUSHR) || - ((unsigned int)arg == FLUSHRW)) { - if (drv->input_active && (file->f_mode & FMODE_READ)) { - wake_up_interruptible(&drv->input_read_wait); - drv->ops->stop_input(drv); - drv->input_active = 0; - drv->input_front = 0; - drv->input_rear = 0; - drv->input_count = 0; - drv->input_size = 0; - drv->input_offset = 0; - drv->recording_count = 0; - } - if ((file->f_mode & FMODE_READ) && - (drv->flags & SDF_OPEN_READ)) { - if (drv->duplex == 2) - drv->input_count = drv->output_count; - drv->ops->start_input(drv, - drv->input_buffers[drv->input_front], - drv->input_buffer_size); - drv->input_active = 1; - } - } - if (((unsigned int)arg == FLUSHW) || - ((unsigned int)arg == FLUSHRW)) { - if ((file->f_mode & FMODE_WRITE) && - !(drv->flags & SDF_OPEN_WRITE)) { - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - sparcaudio_sync_output(drv); - } - } - break; - case SNDCTL_DSP_RESET: - case AUDIO_FLUSH: - if (drv->output_active && (file->f_mode & FMODE_WRITE)) { - wake_up_interruptible(&drv->output_write_wait); - drv->ops->stop_output(drv); - drv->output_active = 0; - drv->output_front = 0; - drv->output_rear = 0; - drv->output_count = 0; - drv->output_size = 0; - drv->playing_count = 0; - drv->output_offset = 0; - drv->output_eof = 0; - } - if (drv->input_active && (file->f_mode & FMODE_READ)) { - wake_up_interruptible(&drv->input_read_wait); - drv->ops->stop_input(drv); - drv->input_active = 0; - drv->input_front = 0; - drv->input_rear = 0; - drv->input_count = 0; - drv->input_size = 0; - drv->input_offset = 0; - drv->recording_count = 0; - } - if ((file->f_mode & FMODE_READ) && - !(drv->flags & SDF_OPEN_READ)) { - drv->ops->start_input(drv, - drv->input_buffers[drv->input_front], - drv->input_buffer_size); - drv->input_active = 1; - } - if ((file->f_mode & FMODE_WRITE) && - !(drv->flags & SDF_OPEN_WRITE)) { - sparcaudio_sync_output(drv); - } - break; - case AUDIO_GETDEV: - if (drv->ops->sunaudio_getdev) { - audio_device_t tmp; + /* handle special case here */ + if (i == AFMT_QUERY) { + j = drv->ops->get_output_encoding(drv); + k = drv->ops->get_output_precision(drv); + if (j == AUDIO_ENCODING_DVI) { + i = AFMT_IMA_ADPCM; + } else if (k == 8) { + switch (j) { + case AUDIO_ENCODING_ULAW: + i = AFMT_MU_LAW; + break; + case AUDIO_ENCODING_ALAW: + i = AFMT_A_LAW; + break; + case AUDIO_ENCODING_LINEAR8: + i = AFMT_U8; + break; + }; + } else if (k == 16) { + switch (j) { + case AUDIO_ENCODING_LINEAR: + i = AFMT_S16_BE; + break; + case AUDIO_ENCODING_LINEARLE: + i = AFMT_S16_LE; + break; + }; + } + COPY_OUT(arg, i); + break; + } + + /* Without these there's no point in trying */ + if (!drv->ops->set_input_precision || + !drv->ops->set_input_encoding || + !drv->ops->set_output_precision || + !drv->ops->set_output_encoding) { + eprintk(("missing set routines: failed\n")); + retval = -EINVAL; + break; + } + + if (drv->ops->get_formats) { + if (!(drv->ops->get_formats(drv) & i)) { + dprintk(("format not supported\n")); + return -EINVAL; + } + } + switch (i) { + case AFMT_S16_LE: + ainfo.record.precision = ainfo.play.precision = 16; + ainfo.record.encoding = ainfo.play.encoding = + AUDIO_ENCODING_LINEARLE; + break; + case AFMT_S16_BE: + ainfo.record.precision = ainfo.play.precision = 16; + ainfo.record.encoding = ainfo.play.encoding = + AUDIO_ENCODING_LINEAR; + break; + case AFMT_MU_LAW: + ainfo.record.precision = ainfo.play.precision = 8; + ainfo.record.encoding = ainfo.play.encoding = + AUDIO_ENCODING_ULAW; + break; + case AFMT_A_LAW: + ainfo.record.precision = ainfo.play.precision = 8; + ainfo.record.encoding = ainfo.play.encoding = + AUDIO_ENCODING_ALAW; + break; + case AFMT_U8: + ainfo.record.precision = ainfo.play.precision = 8; + ainfo.record.encoding = ainfo.play.encoding = + AUDIO_ENCODING_LINEAR8; + break; + }; + tprintk(("setting fmt to enc %d pr %d\n", + ainfo.play.encoding, + ainfo.play.precision)); + if ((drv->ops->set_input_precision(drv, + ainfo.record.precision) + < 0) || + (drv->ops->set_output_precision(drv, + ainfo.play.precision) + < 0) || + (drv->ops->set_input_encoding(drv, + ainfo.record.encoding) + < 0) || + (drv->ops->set_output_encoding(drv, + ainfo.play.encoding) + < 0)) { + dprintk(("setting format: failed\n")); + return -EINVAL; + } + COPY_OUT(arg, i); + break; + case SNDCTL_DSP_CHANNELS: + if ((!drv->ops->set_output_channels) && + (!drv->ops->set_input_channels)) { + retval = -EINVAL; + break; + } + COPY_IN(arg, i); + drv->ops->set_input_channels(drv, i); + drv->ops->set_output_channels(drv, i); + i = drv->ops->get_output_channels(drv); + COPY_OUT(arg, i); + break; + case SNDCTL_DSP_STEREO: + if ((!drv->ops->set_output_channels) && + (!drv->ops->set_input_channels)) { + retval = -EINVAL; + break; + } + COPY_IN(arg, i); + drv->ops->set_input_channels(drv, (i + 1)); + drv->ops->set_output_channels(drv, (i + 1)); + i = ((drv->ops->get_output_channels(drv)) - 1); + COPY_OUT(arg, i); + break; + case SNDCTL_DSP_POST: + case SNDCTL_DSP_SYNC: + case AUDIO_DRAIN: + /* Deal with weirdness so we can fill buffers */ + if (drv->output_offset) { + drv->output_offset = 0; + drv->output_rear = (drv->output_rear + 1) + % drv->num_output_buffers; + drv->output_count++; + } + if (drv->output_count > 0) { + sparcaudio_sync_output(drv); + /* Only pause for DRAIN/SYNC, not POST */ + if (cmd != SNDCTL_DSP_POST) { + interruptible_sleep_on(&drv->output_drain_wait); + retval = (signal_pending(current)) ? -EINTR : 0; + } + } + break; + case I_FLUSH: + case I_FLUSH_SOLARIS: + if (((unsigned int)arg == FLUSHW) || + ((unsigned int)arg == FLUSHRW)) { + if (file->f_mode & FMODE_WRITE) { + sparcaudio_sync_output(drv); + if (drv->output_active) { + wake_up_interruptible(&drv->output_write_wait); + drv->ops->stop_output(drv); + } + drv->output_offset = 0; + drv->output_active = 0; + drv->output_front = 0; + drv->output_rear = 0; + drv->output_count = 0; + drv->output_size = 0; + drv->playing_count = 0; + drv->output_eof = 0; + } + } + if (((unsigned int)arg == FLUSHR) || + ((unsigned int)arg == FLUSHRW)) { + if (drv->input_active && (file->f_mode & FMODE_READ)) { + wake_up_interruptible(&drv->input_read_wait); + drv->ops->stop_input(drv); + drv->input_active = 0; + drv->input_front = 0; + drv->input_rear = 0; + drv->input_count = 0; + drv->input_size = 0; + drv->input_offset = 0; + drv->recording_count = 0; + } + if ((file->f_mode & FMODE_READ) && + (drv->flags & SDF_OPEN_READ)) { + if (drv->duplex == 2) + drv->input_count = drv->output_count; + drv->ops->start_input(drv, + drv->input_buffers[drv->input_front], + drv->input_buffer_size); + drv->input_active = 1; + } + } + if (((unsigned int)arg == FLUSHW) || + ((unsigned int)arg == FLUSHRW)) { + if ((file->f_mode & FMODE_WRITE) && + !(drv->flags & SDF_OPEN_WRITE)) { + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + sparcaudio_sync_output(drv); + } + } + break; + case SNDCTL_DSP_RESET: + case AUDIO_FLUSH: + if (drv->output_active && (file->f_mode & FMODE_WRITE)) { + wake_up_interruptible(&drv->output_write_wait); + drv->ops->stop_output(drv); + drv->output_active = 0; + drv->output_front = 0; + drv->output_rear = 0; + drv->output_count = 0; + drv->output_size = 0; + drv->playing_count = 0; + drv->output_offset = 0; + drv->output_eof = 0; + } + if (drv->input_active && (file->f_mode & FMODE_READ)) { + wake_up_interruptible(&drv->input_read_wait); + drv->ops->stop_input(drv); + drv->input_active = 0; + drv->input_front = 0; + drv->input_rear = 0; + drv->input_count = 0; + drv->input_size = 0; + drv->input_offset = 0; + drv->recording_count = 0; + } + if ((file->f_mode & FMODE_READ) && + !(drv->flags & SDF_OPEN_READ)) { + drv->ops->start_input(drv, + drv->input_buffers[drv->input_front], + drv->input_buffer_size); + drv->input_active = 1; + } + if ((file->f_mode & FMODE_WRITE) && + !(drv->flags & SDF_OPEN_WRITE)) { + sparcaudio_sync_output(drv); + } + break; + case AUDIO_GETDEV: + if (drv->ops->sunaudio_getdev) { + audio_device_t tmp; - retval = verify_area(VERIFY_WRITE, (void *)arg, - sizeof(audio_device_t)); - if (!retval) - drv->ops->sunaudio_getdev(drv, &tmp); - copy_to_user((audio_device_t *)arg, &tmp, sizeof(tmp)); - } else - retval = -EINVAL; - break; - case AUDIO_GETDEV_SUNOS: - if (drv->ops->sunaudio_getdev_sunos) { - int tmp = drv->ops->sunaudio_getdev_sunos(drv); - - retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); - if (!retval) - copy_to_user((int *)arg, &tmp, sizeof(tmp)); - } else - retval = -EINVAL; - break; - case AUDIO_GETINFO: - AUDIO_INITINFO(&ainfo); - - if (drv->ops->get_input_rate) - ainfo.record.sample_rate = - drv->ops->get_input_rate(drv); - else - ainfo.record.sample_rate = (8000); - if (drv->ops->get_input_channels) - ainfo.record.channels = - drv->ops->get_input_channels(drv); - else - ainfo.record.channels = (1); - if (drv->ops->get_input_precision) - ainfo.record.precision = - drv->ops->get_input_precision(drv); - else - ainfo.record.precision = (8); - if (drv->ops->get_input_encoding) - ainfo.record.encoding = - drv->ops->get_input_encoding(drv); - else - ainfo.record.encoding = (AUDIO_ENCODING_ULAW); - if (drv->ops->get_input_volume) - ainfo.record.gain = - drv->ops->get_input_volume(drv); - else - ainfo.record.gain = (0); - if (drv->ops->get_input_port) - ainfo.record.port = - drv->ops->get_input_port(drv); - else - ainfo.record.port = (0); - if (drv->ops->get_input_ports) - ainfo.record.avail_ports = - drv->ops->get_input_ports(drv); - else - ainfo.record.avail_ports = (0); - /* To make e.g. vat happy, we let them think they control this */ - ainfo.record.buffer_size = drv->buffer_size; - if (drv->ops->get_input_samples) - ainfo.record.samples = drv->ops->get_input_samples(drv); - else - ainfo.record.samples = 0; - /* This is undefined in the record context in Solaris */ - ainfo.record.eof = 0; - if (drv->ops->get_input_pause) - ainfo.record.pause = - drv->ops->get_input_pause(drv); - else - ainfo.record.pause = 0; - if (drv->ops->get_input_error) - ainfo.record.error = - (unsigned char)drv->ops->get_input_error(drv); - else - ainfo.record.error = 0; - ainfo.record.waiting = 0; - if (drv->ops->get_input_balance) - ainfo.record.balance = - (unsigned char)drv->ops->get_input_balance(drv); - else - ainfo.record.balance = (unsigned char)(AUDIO_MID_BALANCE); - ainfo.record.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT); - ainfo.record.open = (drv->flags & SDF_OPEN_READ); - ainfo.record.active = 0; - - if (drv->ops->get_output_rate) - ainfo.play.sample_rate = - drv->ops->get_output_rate(drv); - else - ainfo.play.sample_rate = (8000); - if (drv->ops->get_output_channels) - ainfo.play.channels = - drv->ops->get_output_channels(drv); - else - ainfo.play.channels = (1); - if (drv->ops->get_output_precision) - ainfo.play.precision = - drv->ops->get_output_precision(drv); - else - ainfo.play.precision = (8); - if (drv->ops->get_output_encoding) - ainfo.play.encoding = - drv->ops->get_output_encoding(drv); - else - ainfo.play.encoding = (AUDIO_ENCODING_ULAW); - if (drv->ops->get_output_volume) - ainfo.play.gain = - drv->ops->get_output_volume(drv); - else - ainfo.play.gain = (0); - if (drv->ops->get_output_port) - ainfo.play.port = - drv->ops->get_output_port(drv); - else - ainfo.play.port = (0); - if (drv->ops->get_output_ports) - ainfo.play.avail_ports = - drv->ops->get_output_ports(drv); - else - ainfo.play.avail_ports = (0); - /* This is not defined in the play context in Solaris */ - ainfo.play.buffer_size = 0; - if (drv->ops->get_output_samples) - ainfo.play.samples = drv->ops->get_output_samples(drv); - else - ainfo.play.samples = 0; - ainfo.play.eof = drv->output_eof; - if (drv->ops->get_output_pause) - ainfo.play.pause = - drv->ops->get_output_pause(drv); - else - ainfo.play.pause = 0; - if (drv->ops->get_output_error) - ainfo.play.error = - (unsigned char)drv->ops->get_output_error(drv); - else - ainfo.play.error = 0; - ainfo.play.waiting = waitqueue_active(&drv->open_wait); - if (drv->ops->get_output_balance) - ainfo.play.balance = - (unsigned char)drv->ops->get_output_balance(drv); - else - ainfo.play.balance = (unsigned char)(AUDIO_MID_BALANCE); - ainfo.play.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT); - ainfo.play.open = (drv->flags & SDF_OPEN_WRITE); - ainfo.play.active = drv->output_active; - - if (drv->ops->get_monitor_volume) - ainfo.monitor_gain = - drv->ops->get_monitor_volume(drv); - else - ainfo.monitor_gain = (0); - - if (drv->ops->get_output_muted) - ainfo.output_muted = - (unsigned char)drv->ops->get_output_muted(drv); - else - ainfo.output_muted = (unsigned char)(0); - - retval = verify_area(VERIFY_WRITE, (void *)arg, - sizeof(struct audio_info)); - if (retval < 0) - break; - - copy_to_user((struct audio_info *)arg, &ainfo, sizeof(ainfo)); + retval = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(audio_device_t)); + if (!retval) + drv->ops->sunaudio_getdev(drv, &tmp); + copy_to_user((audio_device_t *)arg, &tmp, sizeof(tmp)); + } else { + retval = -EINVAL; + } + break; + case AUDIO_GETDEV_SUNOS: + if (drv->ops->sunaudio_getdev_sunos) { + int tmp = drv->ops->sunaudio_getdev_sunos(drv); + + retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)); + if (!retval) + copy_to_user((int *)arg, &tmp, sizeof(tmp)); + } else { + retval = -EINVAL; + } + break; + case AUDIO_GETINFO: + AUDIO_INITINFO(&ainfo); + + if (drv->ops->get_input_rate) + ainfo.record.sample_rate = + drv->ops->get_input_rate(drv); + else + ainfo.record.sample_rate = (8000); + if (drv->ops->get_input_channels) + ainfo.record.channels = + drv->ops->get_input_channels(drv); + else + ainfo.record.channels = (1); + if (drv->ops->get_input_precision) + ainfo.record.precision = + drv->ops->get_input_precision(drv); + else + ainfo.record.precision = (8); + if (drv->ops->get_input_encoding) + ainfo.record.encoding = + drv->ops->get_input_encoding(drv); + else + ainfo.record.encoding = (AUDIO_ENCODING_ULAW); + if (drv->ops->get_input_volume) + ainfo.record.gain = + drv->ops->get_input_volume(drv); + else + ainfo.record.gain = (0); + if (drv->ops->get_input_port) + ainfo.record.port = + drv->ops->get_input_port(drv); + else + ainfo.record.port = (0); + if (drv->ops->get_input_ports) + ainfo.record.avail_ports = + drv->ops->get_input_ports(drv); + else + ainfo.record.avail_ports = (0); + + /* To make e.g. vat happy, we let them think they control this */ + ainfo.record.buffer_size = drv->buffer_size; + if (drv->ops->get_input_samples) + ainfo.record.samples = drv->ops->get_input_samples(drv); + else + ainfo.record.samples = 0; + + /* This is undefined in the record context in Solaris */ + ainfo.record.eof = 0; + if (drv->ops->get_input_pause) + ainfo.record.pause = + drv->ops->get_input_pause(drv); + else + ainfo.record.pause = 0; + if (drv->ops->get_input_error) + ainfo.record.error = + (unsigned char) drv->ops->get_input_error(drv); + else + ainfo.record.error = 0; + ainfo.record.waiting = 0; + if (drv->ops->get_input_balance) + ainfo.record.balance = + (unsigned char) drv->ops->get_input_balance(drv); + else + ainfo.record.balance = (unsigned char)(AUDIO_MID_BALANCE); + ainfo.record.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT); + ainfo.record.open = (drv->flags & SDF_OPEN_READ); + ainfo.record.active = 0; + + if (drv->ops->get_output_rate) + ainfo.play.sample_rate = + drv->ops->get_output_rate(drv); + else + ainfo.play.sample_rate = (8000); + if (drv->ops->get_output_channels) + ainfo.play.channels = + drv->ops->get_output_channels(drv); + else + ainfo.play.channels = (1); + if (drv->ops->get_output_precision) + ainfo.play.precision = + drv->ops->get_output_precision(drv); + else + ainfo.play.precision = (8); + if (drv->ops->get_output_encoding) + ainfo.play.encoding = + drv->ops->get_output_encoding(drv); + else + ainfo.play.encoding = (AUDIO_ENCODING_ULAW); + if (drv->ops->get_output_volume) + ainfo.play.gain = + drv->ops->get_output_volume(drv); + else + ainfo.play.gain = (0); + if (drv->ops->get_output_port) + ainfo.play.port = + drv->ops->get_output_port(drv); + else + ainfo.play.port = (0); + if (drv->ops->get_output_ports) + ainfo.play.avail_ports = + drv->ops->get_output_ports(drv); + else + ainfo.play.avail_ports = (0); + + /* This is not defined in the play context in Solaris */ + ainfo.play.buffer_size = 0; + if (drv->ops->get_output_samples) + ainfo.play.samples = drv->ops->get_output_samples(drv); + else + ainfo.play.samples = 0; + ainfo.play.eof = drv->output_eof; + if (drv->ops->get_output_pause) + ainfo.play.pause = + drv->ops->get_output_pause(drv); + else + ainfo.play.pause = 0; + if (drv->ops->get_output_error) + ainfo.play.error = + (unsigned char)drv->ops->get_output_error(drv); + else + ainfo.play.error = 0; + ainfo.play.waiting = waitqueue_active(&drv->open_wait); + if (drv->ops->get_output_balance) + ainfo.play.balance = + (unsigned char)drv->ops->get_output_balance(drv); + else + ainfo.play.balance = (unsigned char)(AUDIO_MID_BALANCE); + ainfo.play.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT); + ainfo.play.open = (drv->flags & SDF_OPEN_WRITE); + ainfo.play.active = drv->output_active; - break; - case AUDIO_SETINFO: - { - audio_info_t curinfo, newinfo; + if (drv->ops->get_monitor_volume) + ainfo.monitor_gain = + drv->ops->get_monitor_volume(drv); + else + ainfo.monitor_gain = (0); + + if (drv->ops->get_output_muted) + ainfo.output_muted = + (unsigned char)drv->ops->get_output_muted(drv); + else + ainfo.output_muted = (unsigned char)(0); + + retval = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(struct audio_info)); + if (retval < 0) + break; + + copy_to_user((struct audio_info *)arg, &ainfo, sizeof(ainfo)); + break; + case AUDIO_SETINFO: + { + audio_info_t curinfo, newinfo; - if (verify_area(VERIFY_READ, (audio_info_t *)arg, - sizeof(audio_info_t))) { - dprintk(("verify_area failed\n")); - return -EINVAL; - } - copy_from_user(&ainfo, (audio_info_t *)arg, sizeof(audio_info_t)); - - /* Without these there's no point in trying */ - if (!drv->ops->get_input_precision || - !drv->ops->get_input_channels || - !drv->ops->get_input_rate || - !drv->ops->get_input_encoding || - !drv->ops->get_output_precision || - !drv->ops->get_output_channels || - !drv->ops->get_output_rate || - !drv->ops->get_output_encoding) - { - eprintk(("missing get routines: failed\n")); - retval = -EINVAL; - break; - } - - /* Do bounds checking for things which always apply. - * Follow with enforcement of basic tenets of certain - * encodings. Everything over and above generic is - * enforced by the driver, which can assume that - * Martian cases are taken care of here. */ - if (Modify(ainfo.play.gain) && - ((ainfo.play.gain > AUDIO_MAX_GAIN) || - (ainfo.play.gain < AUDIO_MIN_GAIN))) { - /* Need to differentiate this from e.g. the above error */ - eprintk(("play gain bounds: failed %d\n", ainfo.play.gain)); - retval = -EINVAL; - break; - } - if (Modify(ainfo.record.gain) && - ((ainfo.record.gain > AUDIO_MAX_GAIN) || - (ainfo.record.gain < AUDIO_MIN_GAIN))) { - eprintk(("rec gain bounds: failed %d\n", ainfo.record.gain)); - retval = -EINVAL; - break; - } - if (Modify(ainfo.monitor_gain) && - ((ainfo.monitor_gain > AUDIO_MAX_GAIN) || - (ainfo.monitor_gain < AUDIO_MIN_GAIN))) { - eprintk(("monitor gain bounds: failed\n")); - retval = -EINVAL; - break; - } - /* Don't need to check less than zero on these */ - if (Modifyc(ainfo.play.balance) && - (ainfo.play.balance > AUDIO_RIGHT_BALANCE)) { - eprintk(("play balance bounds: %d failed\n", - (int)ainfo.play.balance)); - retval = -EINVAL; - break; - } - if (Modifyc(ainfo.record.balance) && - (ainfo.record.balance > AUDIO_RIGHT_BALANCE)) { - eprintk(("rec balance bounds: failed\n")); - retval = -EINVAL; - break; - } + if (verify_area(VERIFY_READ, (audio_info_t *)arg, + sizeof(audio_info_t))) { + dprintk(("verify_area failed\n")); + return -EINVAL; + } + copy_from_user(&ainfo, (audio_info_t *)arg, sizeof(audio_info_t)); + + /* Without these there's no point in trying */ + if (!drv->ops->get_input_precision || + !drv->ops->get_input_channels || + !drv->ops->get_input_rate || + !drv->ops->get_input_encoding || + !drv->ops->get_output_precision || + !drv->ops->get_output_channels || + !drv->ops->get_output_rate || + !drv->ops->get_output_encoding) { + eprintk(("missing get routines: failed\n")); + retval = -EINVAL; + break; + } + + /* Do bounds checking for things which always apply. + * Follow with enforcement of basic tenets of certain + * encodings. Everything over and above generic is + * enforced by the driver, which can assume that + * Martian cases are taken care of here. + */ + if (Modify(ainfo.play.gain) && + ((ainfo.play.gain > AUDIO_MAX_GAIN) || + (ainfo.play.gain < AUDIO_MIN_GAIN))) { + /* Need to differentiate this from e.g. the above error */ + eprintk(("play gain bounds: failed %d\n", ainfo.play.gain)); + retval = -EINVAL; + break; + } + if (Modify(ainfo.record.gain) && + ((ainfo.record.gain > AUDIO_MAX_GAIN) || + (ainfo.record.gain < AUDIO_MIN_GAIN))) { + eprintk(("rec gain bounds: failed %d\n", ainfo.record.gain)); + retval = -EINVAL; + break; + } + if (Modify(ainfo.monitor_gain) && + ((ainfo.monitor_gain > AUDIO_MAX_GAIN) || + (ainfo.monitor_gain < AUDIO_MIN_GAIN))) { + eprintk(("monitor gain bounds: failed\n")); + retval = -EINVAL; + break; + } + + /* Don't need to check less than zero on these */ + if (Modifyc(ainfo.play.balance) && + (ainfo.play.balance > AUDIO_RIGHT_BALANCE)) { + eprintk(("play balance bounds: %d failed\n", + (int)ainfo.play.balance)); + retval = -EINVAL; + break; + } + if (Modifyc(ainfo.record.balance) && + (ainfo.record.balance > AUDIO_RIGHT_BALANCE)) { + eprintk(("rec balance bounds: failed\n")); + retval = -EINVAL; + break; + } - /* If any of these changed, record them all, then make - * changes atomically. If something fails, back it all out. */ - if (Modify(ainfo.record.precision) || - Modify(ainfo.record.sample_rate) || - Modify(ainfo.record.channels) || - Modify(ainfo.record.encoding) || - Modify(ainfo.play.precision) || - Modify(ainfo.play.sample_rate) || - Modify(ainfo.play.channels) || - Modify(ainfo.play.encoding)) - { - /* If they're trying to change something we - * have no routine for, they lose */ - if ((!drv->ops->set_input_encoding && - Modify(ainfo.record.encoding)) || - (!drv->ops->set_input_rate && - Modify(ainfo.record.sample_rate)) || - (!drv->ops->set_input_precision && - Modify(ainfo.record.precision)) || - (!drv->ops->set_input_channels && - Modify(ainfo.record.channels))) { - eprintk(("rec set no routines: failed\n")); - retval = -EINVAL; - break; - } + /* If any of these changed, record them all, then make + * changes atomically. If something fails, back it all out. + */ + if (Modify(ainfo.record.precision) || + Modify(ainfo.record.sample_rate) || + Modify(ainfo.record.channels) || + Modify(ainfo.record.encoding) || + Modify(ainfo.play.precision) || + Modify(ainfo.play.sample_rate) || + Modify(ainfo.play.channels) || + Modify(ainfo.play.encoding)) { + /* If they're trying to change something we + * have no routine for, they lose. + */ + if ((!drv->ops->set_input_encoding && + Modify(ainfo.record.encoding)) || + (!drv->ops->set_input_rate && + Modify(ainfo.record.sample_rate)) || + (!drv->ops->set_input_precision && + Modify(ainfo.record.precision)) || + (!drv->ops->set_input_channels && + Modify(ainfo.record.channels))) { + eprintk(("rec set no routines: failed\n")); + retval = -EINVAL; + break; + } - curinfo.record.encoding = - drv->ops->get_input_encoding(drv); - curinfo.record.sample_rate = - drv->ops->get_input_rate(drv); - curinfo.record.precision = - drv->ops->get_input_precision(drv); - curinfo.record.channels = - drv->ops->get_input_channels(drv); - newinfo.record.encoding = Modify(ainfo.record.encoding) ? - ainfo.record.encoding : curinfo.record.encoding; - newinfo.record.sample_rate = - Modify(ainfo.record.sample_rate)? - ainfo.record.sample_rate : curinfo.record.sample_rate; - newinfo.record.precision = Modify(ainfo.record.precision) ? - ainfo.record.precision : curinfo.record.precision; - newinfo.record.channels = Modify(ainfo.record.channels) ? - ainfo.record.channels : curinfo.record.channels; + curinfo.record.encoding = + drv->ops->get_input_encoding(drv); + curinfo.record.sample_rate = + drv->ops->get_input_rate(drv); + curinfo.record.precision = + drv->ops->get_input_precision(drv); + curinfo.record.channels = + drv->ops->get_input_channels(drv); + newinfo.record.encoding = + Modify(ainfo.record.encoding) ? + ainfo.record.encoding : + curinfo.record.encoding; + newinfo.record.sample_rate = + Modify(ainfo.record.sample_rate) ? + ainfo.record.sample_rate : + curinfo.record.sample_rate; + newinfo.record.precision = + Modify(ainfo.record.precision) ? + ainfo.record.precision : + curinfo.record.precision; + newinfo.record.channels = + Modify(ainfo.record.channels) ? + ainfo.record.channels : + curinfo.record.channels; - switch (newinfo.record.encoding) { - case AUDIO_ENCODING_ALAW: - case AUDIO_ENCODING_ULAW: - if (newinfo.record.precision != 8) { - eprintk(("rec law precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.record.channels != 1) { - eprintk(("rec law channel bounds: failed\n")); - retval = -EINVAL; - break; - } - break; - case AUDIO_ENCODING_LINEAR: - case AUDIO_ENCODING_LINEARLE: - if (newinfo.record.precision != 16) { - eprintk(("rec lin precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.record.channels != 1 && - newinfo.record.channels != 2) - { - eprintk(("rec lin channel bounds: failed\n")); - retval = -EINVAL; - break; - } - break; - case AUDIO_ENCODING_LINEAR8: - if (newinfo.record.precision != 8) { - eprintk(("rec lin8 precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.record.channels != 1 && - newinfo.record.channels != 2) - { - eprintk(("rec lin8 channel bounds: failed\n")); - retval = -EINVAL; - break; - } - } + switch (newinfo.record.encoding) { + case AUDIO_ENCODING_ALAW: + case AUDIO_ENCODING_ULAW: + if (newinfo.record.precision != 8) { + eprintk(("rec law precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.record.channels != 1) { + eprintk(("rec law channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + break; + case AUDIO_ENCODING_LINEAR: + case AUDIO_ENCODING_LINEARLE: + if (newinfo.record.precision != 16) { + eprintk(("rec lin precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.record.channels != 1 && + newinfo.record.channels != 2) { + eprintk(("rec lin channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + break; + case AUDIO_ENCODING_LINEAR8: + if (newinfo.record.precision != 8) { + eprintk(("rec lin8 precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.record.channels != 1 && + newinfo.record.channels != 2) { + eprintk(("rec lin8 channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + }; - if (retval < 0) - break; + if (retval < 0) + break; - /* If they're trying to change something we - * have no routine for, they lose */ - if ((!drv->ops->set_output_encoding && - Modify(ainfo.play.encoding)) || - (!drv->ops->set_output_rate && - Modify(ainfo.play.sample_rate)) || - (!drv->ops->set_output_precision && - Modify(ainfo.play.precision)) || - (!drv->ops->set_output_channels && - Modify(ainfo.play.channels))) { - eprintk(("play set no routine: failed\n")); - retval = -EINVAL; - break; - } + /* If they're trying to change something we + * have no routine for, they lose. + */ + if ((!drv->ops->set_output_encoding && + Modify(ainfo.play.encoding)) || + (!drv->ops->set_output_rate && + Modify(ainfo.play.sample_rate)) || + (!drv->ops->set_output_precision && + Modify(ainfo.play.precision)) || + (!drv->ops->set_output_channels && + Modify(ainfo.play.channels))) { + eprintk(("play set no routine: failed\n")); + retval = -EINVAL; + break; + } - curinfo.play.encoding = - drv->ops->get_output_encoding(drv); - curinfo.play.sample_rate = - drv->ops->get_output_rate(drv); - curinfo.play.precision = - drv->ops->get_output_precision(drv); - curinfo.play.channels = - drv->ops->get_output_channels(drv); - newinfo.play.encoding = Modify(ainfo.play.encoding) ? - ainfo.play.encoding : curinfo.play.encoding; - newinfo.play.sample_rate = Modify(ainfo.play.sample_rate) ? - ainfo.play.sample_rate : curinfo.play.sample_rate; - newinfo.play.precision = Modify(ainfo.play.precision) ? - ainfo.play.precision : curinfo.play.precision; - newinfo.play.channels = Modify(ainfo.play.channels) ? - ainfo.play.channels : curinfo.play.channels; + curinfo.play.encoding = + drv->ops->get_output_encoding(drv); + curinfo.play.sample_rate = + drv->ops->get_output_rate(drv); + curinfo.play.precision = + drv->ops->get_output_precision(drv); + curinfo.play.channels = + drv->ops->get_output_channels(drv); + newinfo.play.encoding = + Modify(ainfo.play.encoding) ? + ainfo.play.encoding : + curinfo.play.encoding; + newinfo.play.sample_rate = + Modify(ainfo.play.sample_rate) ? + ainfo.play.sample_rate : + curinfo.play.sample_rate; + newinfo.play.precision = + Modify(ainfo.play.precision) ? + ainfo.play.precision : + curinfo.play.precision; + newinfo.play.channels = + Modify(ainfo.play.channels) ? + ainfo.play.channels : + curinfo.play.channels; - switch (newinfo.play.encoding) { - case AUDIO_ENCODING_ALAW: - case AUDIO_ENCODING_ULAW: - if (newinfo.play.precision != 8) { - eprintk(("play law precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.play.channels != 1) { - eprintk(("play law channel bounds: failed\n")); - retval = -EINVAL; - break; - } - break; - case AUDIO_ENCODING_LINEAR: - case AUDIO_ENCODING_LINEARLE: - if (newinfo.play.precision != 16) { - eprintk(("play lin precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.play.channels != 1 && - newinfo.play.channels != 2) - { - eprintk(("play lin channel bounds: failed\n")); - retval = -EINVAL; - break; - } - break; - case AUDIO_ENCODING_LINEAR8: - if (newinfo.play.precision != 8) { - eprintk(("play lin8 precision bounds: failed\n")); - retval = -EINVAL; - break; - } - if (newinfo.play.channels != 1 && - newinfo.play.channels != 2) - { - eprintk(("play lin8 channel bounds: failed\n")); - retval = -EINVAL; - break; - } - } + switch (newinfo.play.encoding) { + case AUDIO_ENCODING_ALAW: + case AUDIO_ENCODING_ULAW: + if (newinfo.play.precision != 8) { + eprintk(("play law precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.play.channels != 1) { + eprintk(("play law channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + break; + case AUDIO_ENCODING_LINEAR: + case AUDIO_ENCODING_LINEARLE: + if (newinfo.play.precision != 16) { + eprintk(("play lin precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.play.channels != 1 && + newinfo.play.channels != 2) { + eprintk(("play lin channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + break; + case AUDIO_ENCODING_LINEAR8: + if (newinfo.play.precision != 8) { + eprintk(("play lin8 precision bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + if (newinfo.play.channels != 1 && + newinfo.play.channels != 2) { + eprintk(("play lin8 channel bounds: " + "failed\n")); + retval = -EINVAL; + break; + } + }; - if (retval < 0) - break; + if (retval < 0) + break; - /* If we got this far, we're at least sane with - * respect to generics. Try the changes. */ - if ((drv->ops->set_input_channels && - (drv->ops->set_input_channels(drv, - newinfo.record.channels) - < 0)) || - (drv->ops->set_output_channels && - (drv->ops->set_output_channels(drv, - newinfo.play.channels) - < 0)) || - (drv->ops->set_input_rate && - (drv->ops->set_input_rate(drv, - newinfo.record.sample_rate) - < 0)) || - (drv->ops->set_output_rate && - (drv->ops->set_output_rate(drv, - newinfo.play.sample_rate) - < 0)) || - (drv->ops->set_input_precision && - (drv->ops->set_input_precision(drv, - newinfo.record.precision) - < 0)) || - (drv->ops->set_output_precision && - (drv->ops->set_output_precision(drv, - newinfo.play.precision) - < 0)) || - (drv->ops->set_input_encoding && - (drv->ops->set_input_encoding(drv, - newinfo.record.encoding) - < 0)) || - (drv->ops->set_output_encoding && - (drv->ops->set_output_encoding(drv, - newinfo.play.encoding) - < 0))) - { - dprintk(("setting format: failed\n")); - /* Pray we can set it all back. If not, uh... */ - if (drv->ops->set_input_channels) - drv->ops->set_input_channels(drv, + /* If we got this far, we're at least sane with + * respect to generics. Try the changes. + */ + if ((drv->ops->set_input_channels && + (drv->ops->set_input_channels(drv, + newinfo.record.channels) + < 0)) || + (drv->ops->set_output_channels && + (drv->ops->set_output_channels(drv, + newinfo.play.channels) + < 0)) || + (drv->ops->set_input_rate && + (drv->ops->set_input_rate(drv, + newinfo.record.sample_rate) + < 0)) || + (drv->ops->set_output_rate && + (drv->ops->set_output_rate(drv, + newinfo.play.sample_rate) + < 0)) || + (drv->ops->set_input_precision && + (drv->ops->set_input_precision(drv, + newinfo.record.precision) + < 0)) || + (drv->ops->set_output_precision && + (drv->ops->set_output_precision(drv, + newinfo.play.precision) + < 0)) || + (drv->ops->set_input_encoding && + (drv->ops->set_input_encoding(drv, + newinfo.record.encoding) + < 0)) || + (drv->ops->set_output_encoding && + (drv->ops->set_output_encoding(drv, + newinfo.play.encoding) + < 0))) + { + dprintk(("setting format: failed\n")); + /* Pray we can set it all back. If not, uh... */ + if (drv->ops->set_input_channels) + drv->ops->set_input_channels(drv, curinfo.record.channels); - if (drv->ops->set_output_channels) - drv->ops->set_output_channels(drv, - curinfo.play.channels); - if (drv->ops->set_input_rate) - drv->ops->set_input_rate(drv, - curinfo.record.sample_rate); - if (drv->ops->set_output_rate) - drv->ops->set_output_rate(drv, - curinfo.play.sample_rate); - if (drv->ops->set_input_precision) - drv->ops->set_input_precision(drv, - curinfo.record.precision); - if (drv->ops->set_output_precision) - drv->ops->set_output_precision(drv, - curinfo.play.precision); - if (drv->ops->set_input_encoding) - drv->ops->set_input_encoding(drv, - curinfo.record.encoding); - if (drv->ops->set_output_encoding) - drv->ops->set_output_encoding(drv, - curinfo.play.encoding); - retval = -EINVAL; - break; - } - } - - if (retval < 0) - break; + if (drv->ops->set_output_channels) + drv->ops->set_output_channels(drv, + curinfo.play.channels); + if (drv->ops->set_input_rate) + drv->ops->set_input_rate(drv, + curinfo.record.sample_rate); + if (drv->ops->set_output_rate) + drv->ops->set_output_rate(drv, + curinfo.play.sample_rate); + if (drv->ops->set_input_precision) + drv->ops->set_input_precision(drv, + curinfo.record.precision); + if (drv->ops->set_output_precision) + drv->ops->set_output_precision(drv, + curinfo.play.precision); + if (drv->ops->set_input_encoding) + drv->ops->set_input_encoding(drv, + curinfo.record.encoding); + if (drv->ops->set_output_encoding) + drv->ops->set_output_encoding(drv, + curinfo.play.encoding); + retval = -EINVAL; + break; + } + } + + if (retval < 0) + break; + + newinfo.record.balance = + __sparcaudio_if_setc_do(drv, + drv->ops->set_input_balance, + drv->ops->get_input_balance, + ainfo.record.balance); + newinfo.play.balance = + __sparcaudio_if_setc_do(drv, + drv->ops->set_output_balance, + drv->ops->get_output_balance, + ainfo.play.balance); + newinfo.record.error = + __sparcaudio_if_setc_do(drv, + drv->ops->set_input_error, + drv->ops->get_input_error, + ainfo.record.error); + newinfo.play.error = + __sparcaudio_if_setc_do(drv, + drv->ops->set_output_error, + drv->ops->get_output_error, + ainfo.play.error); + newinfo.output_muted = + __sparcaudio_if_setc_do(drv, + drv->ops->set_output_muted, + drv->ops->get_output_muted, + ainfo.output_muted); + newinfo.record.gain = + __sparcaudio_if_set_do(drv, + drv->ops->set_input_volume, + drv->ops->get_input_volume, + ainfo.record.gain); + newinfo.play.gain = + __sparcaudio_if_set_do(drv, + drv->ops->set_output_volume, + drv->ops->get_output_volume, + ainfo.play.gain); + newinfo.record.port = + __sparcaudio_if_set_do(drv, + drv->ops->set_input_port, + drv->ops->get_input_port, + ainfo.record.port); + newinfo.play.port = + __sparcaudio_if_set_do(drv, + drv->ops->set_output_port, + drv->ops->get_output_port, + ainfo.play.port); + newinfo.record.samples = + __sparcaudio_if_set_do(drv, + drv->ops->set_input_samples, + drv->ops->get_input_samples, + ainfo.record.samples); + newinfo.play.samples = + __sparcaudio_if_set_do(drv, + drv->ops->set_output_samples, + drv->ops->get_output_samples, + ainfo.play.samples); + newinfo.monitor_gain = + __sparcaudio_if_set_do(drv, + drv->ops->set_monitor_volume, + drv->ops->get_monitor_volume, + ainfo.monitor_gain); + + if (Modify(ainfo.record.buffer_size)) { + /* Should sanity check this */ + newinfo.record.buffer_size = ainfo.record.buffer_size; + drv->buffer_size = ainfo.record.buffer_size; + } else { + newinfo.record.buffer_size = drv->buffer_size; + } + + if (Modify(ainfo.play.eof)) { + ainfo.play.eof = newinfo.play.eof; + newinfo.play.eof = drv->output_eof; + drv->output_eof = ainfo.play.eof; + } else { + newinfo.play.eof = drv->output_eof; + } + + if (drv->flags & SDF_OPEN_READ) { + newinfo.record.pause = + __sparcaudio_if_setc_do(drv, + drv->ops->set_input_pause, + drv->ops->get_input_pause, + ainfo.record.pause); + } else if (drv->ops->get_input_pause) { + newinfo.record.pause = drv->ops->get_input_pause(drv); + } else { + newinfo.record.pause = 0; + } + + if (drv->flags & SDF_OPEN_WRITE) { + newinfo.play.pause = + __sparcaudio_if_setc_do(drv, + drv->ops->set_output_pause, + drv->ops->get_output_pause, + ainfo.play.pause); + } else if (drv->ops->get_output_pause) { + newinfo.play.pause = drv->ops->get_output_pause(drv); + } else { + newinfo.play.pause = 0; + } - newinfo.record.balance = - __sparcaudio_if_setc_do(drv, - drv->ops->set_input_balance, - drv->ops->get_input_balance, - ainfo.record.balance); - newinfo.play.balance = - __sparcaudio_if_setc_do(drv, - drv->ops->set_output_balance, - drv->ops->get_output_balance, - ainfo.play.balance); - newinfo.record.error = - __sparcaudio_if_setc_do(drv, - drv->ops->set_input_error, - drv->ops->get_input_error, - ainfo.record.error); - newinfo.play.error = - __sparcaudio_if_setc_do(drv, - drv->ops->set_output_error, - drv->ops->get_output_error, - ainfo.play.error); - newinfo.output_muted = - __sparcaudio_if_setc_do(drv, - drv->ops->set_output_muted, - drv->ops->get_output_muted, - ainfo.output_muted); - newinfo.record.gain = - __sparcaudio_if_set_do(drv, - drv->ops->set_input_volume, - drv->ops->get_input_volume, - ainfo.record.gain); - newinfo.play.gain = - __sparcaudio_if_set_do(drv, - drv->ops->set_output_volume, - drv->ops->get_output_volume, - ainfo.play.gain); - newinfo.record.port = - __sparcaudio_if_set_do(drv, - drv->ops->set_input_port, - drv->ops->get_input_port, - ainfo.record.port); - newinfo.play.port = - __sparcaudio_if_set_do(drv, - drv->ops->set_output_port, - drv->ops->get_output_port, - ainfo.play.port); - newinfo.record.samples = - __sparcaudio_if_set_do(drv, - drv->ops->set_input_samples, - drv->ops->get_input_samples, - ainfo.record.samples); - newinfo.play.samples = - __sparcaudio_if_set_do(drv, - drv->ops->set_output_samples, - drv->ops->get_output_samples, - ainfo.play.samples); - newinfo.monitor_gain = - __sparcaudio_if_set_do(drv, - drv->ops->set_monitor_volume, - drv->ops->get_monitor_volume, - ainfo.monitor_gain); - - if (Modify(ainfo.record.buffer_size)) { - /* Should sanity check this */ - newinfo.record.buffer_size = ainfo.record.buffer_size; - drv->buffer_size = ainfo.record.buffer_size; - } else - newinfo.record.buffer_size = drv->buffer_size; - - - if (Modify(ainfo.play.eof)) { - ainfo.play.eof = newinfo.play.eof; - newinfo.play.eof = drv->output_eof; - drv->output_eof = ainfo.play.eof; - } else - newinfo.play.eof = drv->output_eof; - - if (drv->flags & SDF_OPEN_READ) { - newinfo.record.pause = - __sparcaudio_if_setc_do(drv, - drv->ops->set_input_pause, - drv->ops->get_input_pause, - ainfo.record.pause); - } else if (drv->ops->get_input_pause) { - newinfo.record.pause = drv->ops->get_input_pause(drv); - } else newinfo.record.pause = 0; - - if (drv->flags & SDF_OPEN_WRITE) { - newinfo.play.pause = - __sparcaudio_if_setc_do(drv, - drv->ops->set_output_pause, - drv->ops->get_output_pause, - ainfo.play.pause); - } else if (drv->ops->get_output_pause) { - newinfo.play.pause = drv->ops->get_output_pause(drv); - } else newinfo.play.pause = 0; - - retval = verify_area(VERIFY_WRITE, (void *)arg, - sizeof(struct audio_info)); + retval = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(struct audio_info)); - /* Even if we fail, if we made changes let's try notification */ - if (!retval) - copy_to_user((struct audio_info *)arg, &newinfo, - sizeof(newinfo)); + /* Even if we fail, if we made changes let's try notification */ + if (!retval) + copy_to_user((struct audio_info *)arg, &newinfo, + sizeof(newinfo)); #ifdef REAL_AUDIO_SIGNALS - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); #endif - - break; - } + break; + } - default: - if (drv->ops->ioctl) - retval = drv->ops->ioctl(inode,file,cmd,arg,drv); - else - retval = -EINVAL; - } - break; + default: + if (drv->ops->ioctl) + retval = drv->ops->ioctl(inode,file,cmd,arg,drv); + else + retval = -EINVAL; + }; + break; case SPARCAUDIO_STATUS_MINOR: - eprintk(("status minor not yet implemented\n")); - retval = -EINVAL; + eprintk(("status minor not yet implemented\n")); + retval = -EINVAL; default: - eprintk(("unknown minor device number\n")); - retval = -EINVAL; - } + eprintk(("unknown minor device number\n")); + retval = -EINVAL; + }; return retval; } static int sparcaudioctl_release_ret(struct inode * inode, struct file * file) { - MOD_DEC_USE_COUNT; - return 0; + MOD_DEC_USE_COUNT; + return 0; } /* For 2.0 kernels */ #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 static void sparcaudioctl_release(struct inode * inode, struct file * file) { - sparcaudioctl_release_ret(inode, file); + sparcaudioctl_release_ret(inode, file); } #endif static struct file_operations sparcaudioctl_fops = { - NULL, - NULL, - NULL, - NULL, /* sparcaudio_readdir */ - sparcaudio_select, - sparcaudio_ioctl, - NULL, /* sparcaudio_mmap */ - NULL, + NULL, + NULL, + NULL, + NULL, /* sparcaudio_readdir */ + sparcaudio_select, + sparcaudio_ioctl, + NULL, /* sparcaudio_mmap */ + NULL, #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff - NULL, /* sparcaudio_flush */ + NULL, /* sparcaudio_flush */ #endif - sparcaudioctl_release, + sparcaudioctl_release, }; static int sparcaudio_open(struct inode * inode, struct file * file) { int minor = MINOR(inode->i_rdev); struct sparcaudio_driver *drv = - drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)]; + drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)]; int err; /* A low-level audio driver must exist. */ @@ -1952,84 +1991,87 @@ switch (minor & 0xf) { case SPARCAUDIO_AUDIOCTL_MINOR: - file->f_op = &sparcaudioctl_fops; - break; + file->f_op = &sparcaudioctl_fops; + break; case SPARCAUDIO_DSP16_MINOR: case SPARCAUDIO_DSP_MINOR: case SPARCAUDIO_AUDIO_MINOR: - /* If the driver is busy, then wait to get through. */ - retry_open: - if (file->f_mode & FMODE_READ && drv->flags & SDF_OPEN_READ) { - if (file->f_flags & O_NONBLOCK) - return -EBUSY; - - /* If something is now waiting, signal control device */ - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - - interruptible_sleep_on(&drv->open_wait); - if (signal_pending(current)) - return -EINTR; - goto retry_open; - } - if (file->f_mode & FMODE_WRITE && drv->flags & SDF_OPEN_WRITE) { - if (file->f_flags & O_NONBLOCK) - return -EBUSY; + /* If the driver is busy, then wait to get through. */ + retry_open: + if (file->f_mode & FMODE_READ && drv->flags & SDF_OPEN_READ) { + if (file->f_flags & O_NONBLOCK) + return -EBUSY; + + /* If something is now waiting, signal control device */ + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + + interruptible_sleep_on(&drv->open_wait); + if (signal_pending(current)) + return -EINTR; + goto retry_open; + } + if (file->f_mode & FMODE_WRITE && drv->flags & SDF_OPEN_WRITE) { + if (file->f_flags & O_NONBLOCK) + return -EBUSY; - /* If something is now waiting, signal control device */ - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + /* If something is now waiting, signal control device */ + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + + interruptible_sleep_on(&drv->open_wait); + if (signal_pending(current)) + return -EINTR; + goto retry_open; + } + + /* Allow the low-level driver to initialize itself. */ + if (drv->ops->open) { + err = drv->ops->open(inode,file,drv); + if (err < 0) + return err; + } - interruptible_sleep_on(&drv->open_wait); - if (signal_pending(current)) - return -EINTR; - goto retry_open; - } - - /* Allow the low-level driver to initialize itself. */ - if (drv->ops->open) { - err = drv->ops->open(inode,file,drv); - if (err < 0) - return err; - } - - /* Mark the driver as locked for read and/or write. */ - if (file->f_mode & FMODE_READ) { - drv->input_offset = 0; - drv->input_front = 0; - drv->input_rear = 0; - drv->input_count = 0; - drv->input_size = 0; - drv->recording_count = 0; - /* Clear pause */ - if (drv->ops->set_input_pause) - drv->ops->set_input_pause(drv, 0); - drv->ops->start_input(drv, drv->input_buffers[drv->input_front], - drv->input_buffer_size); - drv->input_active = 1; - drv->flags |= SDF_OPEN_READ; - } - if (file->f_mode & FMODE_WRITE) { - drv->output_offset = 0; - drv->output_eof = 0; - drv->playing_count = 0; - drv->output_size = 0; - drv->output_front = 0; - drv->output_rear = 0; - drv->output_count = 0; - drv->output_active = 0; - /* Clear pause */ - if (drv->ops->set_output_pause) - drv->ops->set_output_pause(drv, 0); - drv->flags |= SDF_OPEN_WRITE; - } + /* Mark the driver as locked for read and/or write. */ + if (file->f_mode & FMODE_READ) { + drv->input_offset = 0; + drv->input_front = 0; + drv->input_rear = 0; + drv->input_count = 0; + drv->input_size = 0; + drv->recording_count = 0; + + /* Clear pause */ + if (drv->ops->set_input_pause) + drv->ops->set_input_pause(drv, 0); + drv->ops->start_input(drv, drv->input_buffers[drv->input_front], + drv->input_buffer_size); + drv->input_active = 1; + drv->flags |= SDF_OPEN_READ; + } + + if (file->f_mode & FMODE_WRITE) { + drv->output_offset = 0; + drv->output_eof = 0; + drv->playing_count = 0; + drv->output_size = 0; + drv->output_front = 0; + drv->output_rear = 0; + drv->output_count = 0; + drv->output_active = 0; + + /* Clear pause */ + if (drv->ops->set_output_pause) + drv->ops->set_output_pause(drv, 0); + drv->flags |= SDF_OPEN_WRITE; + } - break; + break; case SPARCAUDIO_MIXER_MINOR: - file->f_op = &sparcaudioctl_fops; - break; + file->f_op = &sparcaudioctl_fops; + break; default: - return -ENXIO; - } + return -ENXIO; + }; /* From the dbri driver: * SunOS 5.5.1 audio(7I) man page says: @@ -2042,23 +2084,23 @@ */ if ((minor & 0xf) == SPARCAUDIO_AUDIO_MINOR) { - if (file->f_mode & FMODE_WRITE) { - if (drv->ops->set_output_channels) - drv->ops->set_output_channels(drv, 1); - if (drv->ops->set_output_encoding) - drv->ops->set_output_encoding(drv, AUDIO_ENCODING_ULAW); - if (drv->ops->set_output_rate) - drv->ops->set_output_rate(drv, 8000); - } - - if (file->f_mode & FMODE_READ) { - if (drv->ops->set_input_channels) - drv->ops->set_input_channels(drv, 1); - if (drv->ops->set_input_encoding) - drv->ops->set_input_encoding(drv, AUDIO_ENCODING_ULAW); - if (drv->ops->set_input_rate) - drv->ops->set_input_rate(drv, 8000); - } + if (file->f_mode & FMODE_WRITE) { + if (drv->ops->set_output_channels) + drv->ops->set_output_channels(drv, 1); + if (drv->ops->set_output_encoding) + drv->ops->set_output_encoding(drv, AUDIO_ENCODING_ULAW); + if (drv->ops->set_output_rate) + drv->ops->set_output_rate(drv, 8000); + } + + if (file->f_mode & FMODE_READ) { + if (drv->ops->set_input_channels) + drv->ops->set_input_channels(drv, 1); + if (drv->ops->set_input_encoding) + drv->ops->set_input_encoding(drv, AUDIO_ENCODING_ULAW); + if (drv->ops->set_input_rate) + drv->ops->set_input_rate(drv, 8000); + } } MOD_INC_USE_COUNT; @@ -2069,62 +2111,61 @@ static int sparcaudio_release_ret(struct inode * inode, struct file * file) { - struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> - SPARCAUDIO_DEVICE_SHIFT)]; + struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >> + SPARCAUDIO_DEVICE_SHIFT)]; - if (file->f_mode & FMODE_READ) { - /* Stop input */ - drv->ops->stop_input(drv); - drv->input_active = 0; - } + if (file->f_mode & FMODE_READ) { + /* Stop input */ + drv->ops->stop_input(drv); + drv->input_active = 0; + } - if (file->f_mode & FMODE_WRITE) { - /* Anything in the queue? */ - if (drv->output_offset) { - drv->output_offset = 0; - drv->output_rear = (drv->output_rear + 1) - % drv->num_output_buffers; - drv->output_count++; - } - sparcaudio_sync_output(drv); - - /* Wait for any output still in the queue to be played. */ - if ((drv->output_count > 0) || (drv->playing_count > 0)) - interruptible_sleep_on(&drv->output_drain_wait); - - /* Force any output to be stopped. */ - drv->ops->stop_output(drv); - drv->output_active = 0; - drv->playing_count = 0; - drv->output_eof = 0; + if (file->f_mode & FMODE_WRITE) { + /* Anything in the queue? */ + if (drv->output_offset) { + drv->output_offset = 0; + drv->output_rear = (drv->output_rear + 1) + % drv->num_output_buffers; + drv->output_count++; + } + sparcaudio_sync_output(drv); - } + /* Wait for any output still in the queue to be played. */ + if ((drv->output_count > 0) || (drv->playing_count > 0)) + interruptible_sleep_on(&drv->output_drain_wait); + + /* Force any output to be stopped. */ + drv->ops->stop_output(drv); + drv->output_active = 0; + drv->playing_count = 0; + drv->output_eof = 0; + } - /* Let the low-level driver do any release processing. */ - if (drv->ops->release) - drv->ops->release(inode,file,drv); + /* Let the low-level driver do any release processing. */ + if (drv->ops->release) + drv->ops->release(inode,file,drv); - if (file->f_mode & FMODE_READ) - drv->flags &= ~(SDF_OPEN_READ); + if (file->f_mode & FMODE_READ) + drv->flags &= ~(SDF_OPEN_READ); - if (file->f_mode & FMODE_WRITE) - drv->flags &= ~(SDF_OPEN_WRITE); + if (file->f_mode & FMODE_WRITE) + drv->flags &= ~(SDF_OPEN_WRITE); - /* Status changed. Signal control device */ - kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); + /* Status changed. Signal control device */ + kill_procs(drv->sd_siglist,SIGPOLL,S_MSG); - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; - wake_up_interruptible(&drv->open_wait); + wake_up_interruptible(&drv->open_wait); - return 0; + return 0; } /* For 2.0 kernels */ #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 static void sparcaudio_release(struct inode * inode, struct file * file) { - sparcaudio_release_ret(inode, file); + sparcaudio_release_ret(inode, file); } #endif @@ -2138,7 +2179,7 @@ NULL, /* sparcaudio_mmap */ sparcaudio_open, #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff - NULL, /* sparcaudio_flush */ + NULL, /* sparcaudio_flush */ #endif sparcaudio_release }; @@ -2207,136 +2248,139 @@ static int lis_add_to_elist( strevent_t **list, pid_t pid, short events ) { - strevent_t *ev = NULL; + strevent_t *ev = NULL; - if (*list != NULL) - { - for (ev=(*list)->se_next; - ev != *list && ev->se_pid < pid; - ev=ev->se_next - ); - } - - if (ev == NULL || ev == *list) /* no slot for pid in list */ - { - if ((ev = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL))==NULL) - return(-ENOMEM); - - if (!*list) /* create dummy head node */ - { - strevent_t *hd; - if ((hd = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL) - )==NULL) - { - kfree(ev); - return(-ENOMEM); - } - (*list=hd)->se_pid=0; - hd->se_next=hd->se_prev=hd; /* empty list */ - } - - /* link node last in the list */ - ev->se_prev=(*list)->se_prev; - (*list)->se_prev->se_next=ev; - ((*list)->se_prev=ev)->se_next=*list; - - ev->se_pid=pid; - ev->se_evs=0; - } - else if (ev->se_pid!=pid){ /* link node in the middle of the list */ - strevent_t *new; - if ((new = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL))==NULL){ - return(-ENOMEM); - } - new->se_prev=ev->se_prev; - new->se_next=ev; - ev->se_prev->se_next=new; - ev->se_prev=new; - ev = new ; /* use new element */ - ev->se_pid=pid; - ev->se_evs=0; - } - ev->se_evs|=events; - return(0); + if (*list != NULL) { + for (ev = (*list)->se_next; + ev != *list && ev->se_pid < pid; + ev = ev->se_next) + ; + } + + if (ev == NULL || ev == *list) { /* no slot for pid in list */ + ev = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL); + if (ev == NULL) + return(-ENOMEM); + + if (!*list) { /* create dummy head node */ + strevent_t *hd; + + hd = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL); + if (hd == NULL) { + kfree(ev); + return(-ENOMEM); + } + (*list = hd)->se_pid = 0; + hd->se_next = hd->se_prev = hd; /* empty list */ + } + + /* link node last in the list */ + ev->se_prev = (*list)->se_prev; + (*list)->se_prev->se_next = ev; + ((*list)->se_prev = ev)->se_next = *list; + + ev->se_pid = pid; + ev->se_evs = 0; + } else if (ev->se_pid != pid) { /* link node in the middle of the list */ + strevent_t *new; + + new = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL); + if (new == NULL) + return -ENOMEM; + + new->se_prev = ev->se_prev; + new->se_next = ev; + ev->se_prev->se_next = new; + ev->se_prev = new; + ev = new; /* use new element */ + ev->se_pid = pid; + ev->se_evs = 0; + } + + ev->se_evs |= events; + return 0; } static int lis_del_from_elist( strevent_t **list, pid_t pid, short events ) { - strevent_t *ev = NULL; + strevent_t *ev = NULL; + + if (*list != NULL) { + for (ev = (*list)->se_next; + ev != *list && ev->se_pid < pid; + ev = ev->se_next) + ; + } + + if (ev == NULL || ev == *list || ev->se_pid != pid) + return 1; - if (*list != NULL) - { - for (ev=(*list)->se_next; - ev != *list && ev->se_pid < pid; - ev=ev->se_next - ); - } - - if (ev == NULL || ev == *list || ev->se_pid != pid ) - return(1); - - if ( (ev->se_evs &= ~events) == 0 ){ /* unlink */ - if (ev->se_next) /* should always be true */ - ev->se_next->se_prev=ev->se_prev; - if (ev->se_prev) /* should always be true */ - ev->se_prev->se_next=ev->se_next; - kfree(ev); - } - return(0); + if ((ev->se_evs &= ~events) == 0) { /* unlink */ + if (ev->se_next) /* should always be true */ + ev->se_next->se_prev = ev->se_prev; + if (ev->se_prev) /* should always be true */ + ev->se_prev->se_next = ev->se_next; + kfree(ev); + } + return 0; } static void lis_free_elist( strevent_t **list ) { - strevent_t *ev; - strevent_t *nxt ; + strevent_t *ev; + strevent_t *nxt; - for (ev = *list; ev != NULL; ) - { - nxt = ev->se_next ; - kfree(ev) ; - ev = nxt ; - if (ev == *list) break ; /* all done */ - } + for (ev = *list; ev != NULL; ) { + nxt = ev->se_next; + kfree(ev); + ev = nxt; + if (ev == *list) + break; /* all done */ + } - *list = NULL ; + *list = NULL; } static short lis_get_elist_ent( strevent_t *list, pid_t pid ) { - strevent_t *ev = NULL; + strevent_t *ev = NULL; - if (list == NULL) return(0) ; + if (list == NULL) + return 0; - for(ev = list->se_next ; ev != list && ev->se_pid < pid; ev=ev->se_next ) - ; - if (ev != list && ev->se_pid == pid) - return(ev->se_evs); - else - return(0); + for(ev = list->se_next ; ev != list && ev->se_pid < pid; ev = ev->se_next) + ; + if (ev != list && ev->se_pid == pid) + return ev->se_evs; + else + return 0; } static void kill_procs( struct strevent *elist, int sig, short e) { - strevent_t *ev; - int res; + strevent_t *ev; + int res; - (void) sig ; - if (elist) { - for(ev = elist->se_next ; ev != elist; ev=ev->se_next ) - if ((ev->se_evs & e) != 0){ - if ((res=kill_proc(ev->se_pid,SIGPOLL,1))<0) { - if (res == -3) { - lis_del_from_elist(&elist, ev->se_pid, S_ALL); - continue; - } - dprintk(("kill_proc: errno %d\n",res)); - } - } - } + if (elist) { + for(ev = elist->se_next ; ev != elist; ev = ev->se_next) + if ((ev->se_evs & e) != 0) { + res = kill_proc(ev->se_pid, SIGPOLL, 1); + + if (res < 0) { + if (res == -3) { + lis_del_from_elist(&elist, + ev->se_pid, + S_ALL); + continue; + } + dprintk(("kill_proc: errno %d\n",res)); + } + } + } } /* diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4215.h linux/drivers/sbus/audio/cs4215.h --- v2.3.34/linux/drivers/sbus/audio/cs4215.h Thu Jun 17 01:08:50 1999 +++ linux/drivers/sbus/audio/cs4215.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: cs4215.h,v 1.7 1999/09/21 14:37:19 davem Exp $ * drivers/sbus/audio/cs4215.h * * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) @@ -117,4 +117,4 @@ #define CS4215_RG(v) v /* Right Gain Setting 0xf: 22.5 dB */ #define CS4215_MA(v) (v<<4) /* Monitor Path Attenuation 0xf: mute */ -#endif +#endif /* _CS4215_H_ */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c --- v2.3.34/linux/drivers/sbus/audio/cs4231.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/cs4231.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: cs4231.c,v 1.41 1999/12/19 23:28:03 davem Exp $ * drivers/sbus/audio/cs4231.c * * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu) @@ -84,418 +84,399 @@ static void eb4231_pollinput(struct sparcaudio_driver *drv); #endif -#define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000); +/* Serveral shorthands save typing... */ +#define CHIP_READY() \ +do { udelay(100); cs4231_ready(drv); udelay(1000); } while(0) +#define WRITE_IAR(__VAL) \ + CS4231_WRITE8(cs4231_chip, cs4231_chip->regs + IAR, __VAL) +#define WRITE_IDR(__VAL) \ + CS4231_WRITE8(cs4231_chip, cs4231_chip->regs + IDR, __VAL) +#define READ_IAR() \ + CS4231_READ8(cs4231_chip, cs4231_chip->regs + IAR) +#define READ_IDR() \ + CS4231_READ8(cs4231_chip, cs4231_chip->regs + IDR) /* Enable cs4231 interrupts atomically. */ -static __inline__ void cs4231_enable_interrupts(struct sparcaudio_driver *drv) +static void cs4231_enable_interrupts(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - if (cs4231_chip->status & CS_STATUS_INTS_ON) - return; - - tprintk(("enabling interrupts\n")); - save_flags(flags); - cli(); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_ON); - restore_flags(flags); - - cs4231_chip->status |= CS_STATUS_INTS_ON; + tprintk(("enabling interrupts\n")); + save_flags(flags); + cli(); + if ((cs4231_chip->status & CS_STATUS_INTS_ON) == 0) { + WRITE_IAR(0xa); + WRITE_IDR(INTR_ON); + cs4231_chip->status |= CS_STATUS_INTS_ON; + } + restore_flags(flags); } /* Disable cs4231 interrupts atomically. */ -static __inline__ void cs4231_disable_interrupts(struct sparcaudio_driver *drv) +static void cs4231_disable_interrupts(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; - - if (!(cs4231_chip->status & CS_STATUS_INTS_ON)) - return; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - tprintk(("disabling interrupts\n")); - save_flags(flags); - cli(); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_OFF); - restore_flags(flags); - - cs4231_chip->status &= ~CS_STATUS_INTS_ON; + tprintk(("disabling interrupts\n")); + save_flags(flags); + cli(); + if ((cs4231_chip->status & CS_STATUS_INTS_ON) != 0) { + WRITE_IAR(0xa); + WRITE_IDR(INTR_OFF); + cs4231_chip->status &= ~CS_STATUS_INTS_ON; + } + restore_flags(flags); } -static __inline__ void cs4231_enable_play(struct sparcaudio_driver *drv) +static void cs4231_enable_play(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - tprintk(("enabling play\n")); - save_flags(flags); - cli(); - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PEN_ENABLE)); - restore_flags(flags); + tprintk(("enabling play\n")); + save_flags(flags); + cli(); + WRITE_IAR(0x9); + WRITE_IDR(READ_IDR() | PEN_ENABLE); + restore_flags(flags); } -static __inline__ void cs4231_disable_play(struct sparcaudio_driver *drv) +static void cs4231_disable_play(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - tprintk(("disabling play\n")); - save_flags(flags); - cli(); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & PEN_DISABLE)); - restore_flags(flags); + tprintk(("disabling play\n")); + save_flags(flags); + cli(); + WRITE_IAR(0x9); + WRITE_IDR(READ_IDR() & PEN_DISABLE); + restore_flags(flags); } -static __inline__ void cs4231_enable_rec(struct sparcaudio_driver *drv) +static void cs4231_enable_rec(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - tprintk(("enabling rec\n")); - save_flags(flags); - cli(); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | CEN_ENABLE)); - restore_flags(flags); + tprintk(("enabling rec\n")); + save_flags(flags); + cli(); + WRITE_IAR(0x9); + WRITE_IDR(READ_IDR() | CEN_ENABLE); + restore_flags(flags); } -static __inline__ void cs4231_disable_rec(struct sparcaudio_driver *drv) +static void cs4231_disable_rec(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - register unsigned long flags; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned long flags; - tprintk(("disabling rec\n")); - save_flags(flags); - cli(); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & CEN_DISABLE)); - restore_flags(flags); + tprintk(("disabling rec\n")); + save_flags(flags); + cli(); + WRITE_IAR(0x9); + WRITE_IDR(READ_IDR() & CEN_DISABLE); + restore_flags(flags); } static struct cs4231_rates { - int speed, bits; + int speed, bits; } cs4231_rate_table[] = { - { 5512, CS4231_DFR_5512 }, - { 6615, CS4231_DFR_6615 }, - { 8000, CS4231_DFR_8000 }, - { 9600, CS4231_DFR_9600 }, - { 11025, CS4231_DFR_11025 }, - { 16000, CS4231_DFR_16000 }, - { 18900, CS4231_DFR_18900 }, - { 22050, CS4231_DFR_22050 }, - { 27429, CS4231_DFR_27429 }, - { 32000, CS4231_DFR_32000 }, - { 33075, CS4231_DFR_33075 }, - { 37800, CS4231_DFR_37800 }, - { 44100, CS4231_DFR_44100 }, - { 48000, CS4231_DFR_48000 } + { 5512, CS4231_DFR_5512 }, + { 6615, CS4231_DFR_6615 }, + { 8000, CS4231_DFR_8000 }, + { 9600, CS4231_DFR_9600 }, + { 11025, CS4231_DFR_11025 }, + { 16000, CS4231_DFR_16000 }, + { 18900, CS4231_DFR_18900 }, + { 22050, CS4231_DFR_22050 }, + { 27429, CS4231_DFR_27429 }, + { 32000, CS4231_DFR_32000 }, + { 33075, CS4231_DFR_33075 }, + { 37800, CS4231_DFR_37800 }, + { 44100, CS4231_DFR_44100 }, + { 48000, CS4231_DFR_48000 } }; #define NUM_RATES (sizeof(cs4231_rate_table) / sizeof(struct cs4231_rates)) -static int -cs4231_rate_to_bits(struct sparcaudio_driver *drv, int *value) -{ - struct cs4231_rates *p = &cs4231_rate_table[0]; - int i, wanted = *value; - - /* We try to be nice and approximate what the user asks for. */ - if(wanted < 5512) - wanted = 5512; - if(wanted > 48000) - wanted = 48000; - - for(i = 0; i < NUM_RATES; i++, p++) { - /* Exact match? */ - if(wanted == p->speed) - break; - - /* If we're inbetween two entries, and neither is exact, - * pick the closest one. - */ - if(wanted == p[1].speed) - continue; - if(wanted > p->speed && - wanted < p[1].speed) { - int diff1, diff2; - - diff1 = wanted - p->speed; - diff2 = p[1].speed - wanted; - if(diff2 < diff1) - p++; - break; - } - } - *value = p->speed; - return p->bits; -} - -static int -cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value) -{ - int set_bits; - - switch (value) { - case AUDIO_ENCODING_ULAW: - set_bits = CS4231_DFR_ULAW; - break; - case AUDIO_ENCODING_ALAW: - set_bits = CS4231_DFR_ALAW; - break; - case AUDIO_ENCODING_DVI: - set_bits = CS4231_DFR_ADPCM; - break; - case AUDIO_ENCODING_LINEARLE: - set_bits = CS4231_DFR_LINEARLE; - break; - case AUDIO_ENCODING_LINEAR: - set_bits = CS4231_DFR_LINEARBE; - break; - case AUDIO_ENCODING_LINEAR8: - set_bits = CS4231_DFR_LINEAR8; - break; - default: - set_bits = -(EINVAL); - break; - } - - return set_bits; -} - -static int -cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value) +static int cs4231_rate_to_bits(struct sparcaudio_driver *drv, int *value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits, set_bits; + struct cs4231_rates *p = &cs4231_rate_table[0]; + int i, wanted = *value; - tprintk(("output encoding %d\n", value)); - if (value != 0) { - set_bits = cs4231_encoding_to_bits(drv, value); - if (set_bits >= 0) { - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CHANGE_ENCODING(tmp_bits, set_bits)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - - CHIP_READY - - cs4231_chip->perchip_info.play.encoding = value; - return 0; - } - } - dprintk(("output enc failed\n")); - return -EINVAL; + /* We try to be nice and approximate what the user asks for. */ + if (wanted < 5512) + wanted = 5512; + if (wanted > 48000) + wanted = 48000; + + for (i = 0; i < NUM_RATES; i++, p++) { + /* Exact match? */ + if (wanted == p->speed) + break; + + /* If we're inbetween two entries, and neither is exact, + * pick the closest one. + */ + if (wanted == p[1].speed) + continue; + if (wanted > p->speed && wanted < p[1].speed) { + int diff1, diff2; + + diff1 = wanted - p->speed; + diff2 = p[1].speed - wanted; + if (diff2 < diff1) + p++; + break; + } + } + *value = p->speed; + return p->bits; +} + +static int cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value) +{ + int set_bits; + + switch (value) { + case AUDIO_ENCODING_ULAW: + set_bits = CS4231_DFR_ULAW; + break; + case AUDIO_ENCODING_ALAW: + set_bits = CS4231_DFR_ALAW; + break; + case AUDIO_ENCODING_DVI: + set_bits = CS4231_DFR_ADPCM; + break; + case AUDIO_ENCODING_LINEARLE: + set_bits = CS4231_DFR_LINEARLE; + break; + case AUDIO_ENCODING_LINEAR: + set_bits = CS4231_DFR_LINEARBE; + break; + case AUDIO_ENCODING_LINEAR8: + set_bits = CS4231_DFR_LINEAR8; + break; + default: + set_bits = -EINVAL; + break; + }; + + return set_bits; +} + +static int cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits, set_bits; + + tprintk(("output encoding %d\n", value)); + if (value != 0) { + set_bits = cs4231_encoding_to_bits(drv, value); + if (set_bits >= 0) { + READ_IDR(); + READ_IDR(); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = READ_IDR(); + WRITE_IDR(CHANGE_ENCODING(tmp_bits, set_bits)); + READ_IDR(); + READ_IDR(); + CHIP_READY(); + cs4231_chip->perchip_info.play.encoding = value; + return 0; + } + } + dprintk(("output enc failed\n")); + return -EINVAL; } static int cs4231_get_output_encoding(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.encoding; } -static int -cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value) +static int cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits, set_bits; - - tprintk(("input encoding %d\n", value)); - if (value != 0) { - set_bits = cs4231_encoding_to_bits(drv, value); - if (set_bits >= 0) { - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1c); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CHANGE_ENCODING(tmp_bits, set_bits)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits, set_bits; - CHIP_READY - - cs4231_chip->perchip_info.record.encoding = value; - return 0; - } - } - dprintk(("input enc failed\n")); - return -EINVAL; + tprintk(("input encoding %d\n", value)); + if (value != 0) { + set_bits = cs4231_encoding_to_bits(drv, value); + if (set_bits >= 0) { + READ_IDR(); + READ_IDR(); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c); + tmp_bits = READ_IDR(); + WRITE_IDR(CHANGE_ENCODING(tmp_bits, set_bits)); + READ_IDR(); + READ_IDR(); + CHIP_READY(); + + cs4231_chip->perchip_info.record.encoding = value; + return 0; + } + } + dprintk(("input enc failed\n")); + return -EINVAL; } static int cs4231_get_input_encoding(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.encoding; } -static int -cs4231_set_output_rate(struct sparcaudio_driver *drv, int value) +static int cs4231_set_output_rate(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits, set_bits; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits, set_bits; - tprintk(("output rate %d\n", value)); - if (value != 0) { - set_bits = cs4231_rate_to_bits(drv, &value); - if (set_bits >= 0) { - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CHANGE_DFR(tmp_bits, set_bits)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - - CHIP_READY - - cs4231_chip->perchip_info.play.sample_rate = value; - tprintk(("tmp_bits[%02x] set_bits[%02x] CHANGE_DFR[%02x]\n", - tmp_bits, set_bits, CHANGE_DFR(tmp_bits, set_bits))); - return 0; - } - } - dprintk(("output rate failed\n")); - return -EINVAL; + tprintk(("output rate %d\n", value)); + if (value != 0) { + set_bits = cs4231_rate_to_bits(drv, &value); + if (set_bits >= 0) { + READ_IDR(); + READ_IDR(); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = READ_IDR(); + WRITE_IDR(CHANGE_DFR(tmp_bits, set_bits)); + READ_IDR(); + READ_IDR(); + CHIP_READY(); + + cs4231_chip->perchip_info.play.sample_rate = value; + tprintk(("tmp_bits[%02x] set_bits[%02x] CHANGE_DFR[%02x]\n", + tmp_bits, set_bits, CHANGE_DFR(tmp_bits, set_bits))); + return 0; + } + } + dprintk(("output rate failed\n")); + return -EINVAL; } static int cs4231_get_output_rate(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.sample_rate; } -static int -cs4231_set_input_rate(struct sparcaudio_driver *drv, int value) +static int cs4231_set_input_rate(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits, set_bits; - - tprintk(("input rate %d\n", value)); - if (value != 0) { - set_bits = cs4231_rate_to_bits(drv, &value); - if (set_bits >= 0) { - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1c); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CHANGE_DFR(tmp_bits, set_bits)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - - CHIP_READY + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits, set_bits; - cs4231_chip->perchip_info.record.sample_rate = value; - return 0; - } - } - dprintk(("input rate failed\n")); - return -EINVAL; + tprintk(("input rate %d\n", value)); + if (value != 0) { + set_bits = cs4231_rate_to_bits(drv, &value); + if (set_bits >= 0) { + READ_IDR(); + READ_IDR(); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c); + tmp_bits = READ_IDR(); + WRITE_IDR(CHANGE_DFR(tmp_bits, set_bits)); + READ_IDR(); + READ_IDR(); + CHIP_READY(); + + cs4231_chip->perchip_info.record.sample_rate = value; + return 0; + } + } + dprintk(("input rate failed\n")); + return -EINVAL; } static int cs4231_get_input_rate(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.sample_rate; } /* Generically we support 4 channels. This hardware does 2 */ -static int -cs4231_set_input_channels(struct sparcaudio_driver *drv, int value) +static int cs4231_set_input_channels(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits; - tprintk(("input channels %d\n", value)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), (IAR_AUTOCAL_BEGIN | 0x1c)); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - switch (value) { - case 1: - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits)); - break; - case 2: - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits)); - break; - default: - dprintk(("input chan failed\n")); - return -(EINVAL); - } + tprintk(("input channels %d\n", value)); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c); + tmp_bits = READ_IDR(); + switch (value) { + case 1: + WRITE_IDR(CS4231_MONO_ON(tmp_bits)); + break; + case 2: + WRITE_IDR(CS4231_STEREO_ON(tmp_bits)); + break; + default: + dprintk(("input chan failed\n")); + return -EINVAL; + }; + CHIP_READY(); - CHIP_READY - - cs4231_chip->perchip_info.record.channels = value; - return 0; + cs4231_chip->perchip_info.record.channels = value; + return 0; } static int cs4231_get_input_channels(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.channels; } /* Generically we support 4 channels. This hardware does 2 */ -static int -cs4231_set_output_channels(struct sparcaudio_driver *drv, int value) +static int cs4231_set_output_channels(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp_bits; - - tprintk(("output channels %d\n", value)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8); - tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - switch (value) { - case 1: - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits)); - break; - case 2: - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits)); - break; - default: - dprintk(("output chan failed\n")); - return -(EINVAL); - } + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp_bits; - CHIP_READY + tprintk(("output channels %d\n", value)); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8); + tmp_bits = READ_IDR(); + switch (value) { + case 1: + WRITE_IDR(CS4231_MONO_ON(tmp_bits)); + break; + case 2: + WRITE_IDR(CS4231_STEREO_ON(tmp_bits)); + break; + default: + dprintk(("output chan failed\n")); + return -EINVAL; + }; + CHIP_READY(); - cs4231_chip->perchip_info.play.channels = value; - return 0; + cs4231_chip->perchip_info.play.channels = value; + return 0; } static int cs4231_get_output_channels(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.channels; } static int cs4231_get_input_precision(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.record.precision; } static int cs4231_get_output_precision(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.precision; } static int cs4231_set_input_precision(struct sparcaudio_driver *drv, int val) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.record.precision = val; @@ -504,7 +485,7 @@ static int cs4231_set_output_precision(struct sparcaudio_driver *drv, int val) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.play.precision = val; @@ -512,253 +493,238 @@ } /* Wait until the auto calibration process has finished */ -static void -cs4231_ready(struct sparcaudio_driver *drv) +static void cs4231_ready(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int x = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned int x; - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); - while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == IAR_NOT_READY && - x <= CS_TIMEOUT) { - x++; - } - - x = 0; - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0b); - while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == AUTOCAL_IN_PROGRESS && - x <= CS_TIMEOUT) { - x++; - } + WRITE_IAR(IAR_AUTOCAL_END); + x = 0; + do { + if (READ_IDR() != IAR_NOT_READY) + break; + x++; + } while (x <= CS_TIMEOUT); + + WRITE_IAR(0x0b); + x = 0; + do { + if (READ_IDR() != AUTOCAL_IN_PROGRESS) + break; + x++; + } while (x <= CS_TIMEOUT); } /* Set output mute */ static int cs4231_output_muted(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - tprintk(("in cs4231_output_muted: %d\n", value)); - if (!value) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE)); - cs4231_chip->perchip_info.output_muted = 0; - } else { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE)); - cs4231_chip->perchip_info.output_muted = 1; - } - return 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + tprintk(("in cs4231_output_muted: %d\n", value)); + if (!value) { + WRITE_IAR(0x7); + WRITE_IDR(READ_IDR() & OUTCR_UNMUTE); + WRITE_IAR(0x6); + WRITE_IDR(READ_IDR() & OUTCR_UNMUTE); + cs4231_chip->perchip_info.output_muted = 0; + } else { + WRITE_IAR(0x7); + WRITE_IDR(READ_IDR() | OUTCR_MUTE); + WRITE_IAR(0x6); + WRITE_IDR(READ_IDR() | OUTCR_MUTE); + cs4231_chip->perchip_info.output_muted = 1; + } + return 0; } static int cs4231_get_output_muted(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - return cs4231_chip->perchip_info.output_muted; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + return cs4231_chip->perchip_info.output_muted; } static int cs4231_get_formats(struct sparcaudio_driver *drv) { - return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_IMA_ADPCM | - AFMT_S16_LE | AFMT_S16_BE); + return (AFMT_MU_LAW | AFMT_A_LAW | + AFMT_U8 | AFMT_IMA_ADPCM | + AFMT_S16_LE | AFMT_S16_BE); } static int cs4231_get_output_ports(struct sparcaudio_driver *drv) { - return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE); + return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE); } static int cs4231_get_input_ports(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - /* This apparently applies only to APC ultras, not ebus ultras */ - if (cs4231_chip->status & CS_STATUS_IS_ULTRA) - return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK); - else - return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | AUDIO_MICROPHONE | - AUDIO_ANALOG_LOOPBACK); + /* This apparently applies only to APC ultras, not ebus ultras */ + if (cs4231_chip->status & CS_STATUS_IS_ULTRA) + return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK); + else + return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | + AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK); } /* Set chip "output" port */ static int cs4231_set_output_port(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int retval = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int retval = 0; - tprintk(("output port: %d\n", value)); - /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively - * enable things. - */ - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | MONO_IOCR_MUTE)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_LINE_MUTE)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_HDPH_MUTE)); - - if (value & AUDIO_SPEAKER) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~MONO_IOCR_MUTE)); - retval |= AUDIO_SPEAKER; - } - - if (value & AUDIO_HEADPHONE) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_HDPH_MUTE)); - retval |= AUDIO_HEADPHONE; - } - - if (value & AUDIO_LINE_OUT) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_LINE_MUTE)); - retval |= AUDIO_LINE_OUT; - } + tprintk(("output port: %d\n", value)); + /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively + * enable things. + */ + WRITE_IAR(0x1a); + WRITE_IDR(READ_IDR() | MONO_IOCR_MUTE); + WRITE_IAR(0x0a); + WRITE_IDR(READ_IDR() | PINCR_LINE_MUTE); + WRITE_IDR(READ_IDR() | PINCR_HDPH_MUTE); + + if (value & AUDIO_SPEAKER) { + WRITE_IAR(0x1a); + WRITE_IDR(READ_IDR() & ~MONO_IOCR_MUTE); + retval |= AUDIO_SPEAKER; + } + + if (value & AUDIO_HEADPHONE) { + WRITE_IAR(0x0a); + WRITE_IDR(READ_IDR() & ~PINCR_HDPH_MUTE); + retval |= AUDIO_HEADPHONE; + } + + if (value & AUDIO_LINE_OUT) { + WRITE_IAR(0x0a); + WRITE_IDR(READ_IDR() & ~PINCR_LINE_MUTE); + retval |= AUDIO_LINE_OUT; + } - cs4231_chip->perchip_info.play.port = retval; + cs4231_chip->perchip_info.play.port = retval; - return (retval); + return (retval); } static int cs4231_get_output_port(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - return cs4231_chip->perchip_info.play.port; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + return cs4231_chip->perchip_info.play.port; } /* Set chip "input" port */ static int cs4231_set_input_port(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int retval = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int retval = 0; - tprintk(("input port: %d\n", value)); + tprintk(("input port: %d\n", value)); - /* You can have one and only one. This is probably wrong, but - * appears to be how SunOS is doing it. Should be able to mix. - * More work to be done. CD input mixable, analog loopback may be. - */ - - /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */ - /* This apparently applies only to APC ultras, not ebus ultras */ - if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) { - if (value & AUDIO_INTERNAL_CD_IN) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - retval = AUDIO_INTERNAL_CD_IN; - } - } - if ((value & AUDIO_LINE_IN)) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - retval = AUDIO_LINE_IN; - } else if (value & AUDIO_MICROPHONE) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - retval = AUDIO_MICROPHONE; - } else if (value & AUDIO_ANALOG_LOOPBACK) { - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)))); - retval = AUDIO_ANALOG_LOOPBACK; - } + /* You can have one and only one. This is probably wrong, but + * appears to be how SunOS is doing it. Should be able to mix. + * More work to be done. CD input mixable, analog loopback may be. + */ + + /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */ + /* This apparently applies only to APC ultras, not ebus ultras */ + if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) { + if (value & AUDIO_INTERNAL_CD_IN) { + WRITE_IAR(0x1); + WRITE_IDR(CDROM_ENABLE(READ_IDR())); + WRITE_IAR(0x0); + WRITE_IDR(CDROM_ENABLE(READ_IDR())); + retval = AUDIO_INTERNAL_CD_IN; + } + } + if ((value & AUDIO_LINE_IN)) { + WRITE_IAR(0x1); + WRITE_IDR(LINE_ENABLE(READ_IDR())); + WRITE_IAR(0x0); + WRITE_IDR(LINE_ENABLE(READ_IDR())); + retval = AUDIO_LINE_IN; + } else if (value & AUDIO_MICROPHONE) { + WRITE_IAR(0x1); + WRITE_IDR(MIC_ENABLE(READ_IDR())); + WRITE_IAR(0x0); + WRITE_IDR(MIC_ENABLE(READ_IDR())); + retval = AUDIO_MICROPHONE; + } else if (value & AUDIO_ANALOG_LOOPBACK) { + WRITE_IAR(0x1); + WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR())); + WRITE_IAR(0x0); + WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR())); + retval = AUDIO_ANALOG_LOOPBACK; + } - cs4231_chip->perchip_info.record.port = retval; + cs4231_chip->perchip_info.record.port = retval; - return (retval); + return retval; } static int cs4231_get_input_port(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - return cs4231_chip->perchip_info.record.port; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + return cs4231_chip->perchip_info.record.port; } /* Set chip "monitor" gain */ static int cs4231_set_monitor_volume(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int a = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int a = 0; - tprintk(("monitor gain: %d\n", value)); + tprintk(("monitor gain: %d\n", value)); - /* This interpolation really sucks. The question is, be compatible - * with ScumOS/Sloaris or not? - */ - a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1)); - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d); - if (a >= CS4231_MON_MAX_ATEN) - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), LOOPB_OFF); - else - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), ((a << 2) | LOOPB_ON)); - - if (value == AUDIO_MAX_GAIN) - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain), AUDIO_MAX_GAIN); - else - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain), - ((CS4231_MAX_DEV_ATEN - a) * - (AUDIO_MAX_GAIN + 1) / - (CS4231_MAX_DEV_ATEN + 1))); + /* This interpolation really sucks. The question is, be compatible + * with ScumOS/Sloaris or not? + */ + a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1)); + + WRITE_IAR(0x0d); + if (a >= CS4231_MON_MAX_ATEN) + WRITE_IDR(LOOPB_OFF); + else + WRITE_IDR((a << 2) | LOOPB_ON); + + if (value == AUDIO_MAX_GAIN) + cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN; + else + cs4231_chip->perchip_info.monitor_gain = + ((CS4231_MAX_DEV_ATEN - a) * + (AUDIO_MAX_GAIN + 1) / + (CS4231_MAX_DEV_ATEN + 1)); - return 0; + return 0; } static int cs4231_get_monitor_volume(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.monitor_gain; + return (int) cs4231_chip->perchip_info.monitor_gain; } static int cs4231_get_output_error(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.play.error; + return (int) cs4231_chip->perchip_info.play.error; } static int cs4231_get_input_error(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.record.error; + return (int) cs4231_chip->perchip_info.record.error; } #ifdef EB4231_SUPPORT static int eb4231_get_output_samples(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int count = - cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, - readl(&cs4231_chip->eb2p->dbcr)); + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dbcr = readl(cs4231_chip->eb2p + EBDMA_COUNT); + int count = + cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dbcr); return (cs4231_chip->perchip_info.play.samples - ((count > cs4231_chip->perchip_info.play.samples) @@ -767,10 +733,10 @@ static int eb4231_get_input_samples(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int count = - cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, - readl(&cs4231_chip->eb2c->dbcr)); + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dbcr = readl(cs4231_chip->eb2c + EBDMA_COUNT); + int count = + cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, dbcr); return (cs4231_chip->perchip_info.record.samples - ((count > cs4231_chip->perchip_info.record.samples) ? @@ -780,10 +746,10 @@ static int cs4231_get_output_samples(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dmapc = sbus_readl(cs4231_chip->regs + APCPC); int count = - cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, - cs4231_chip->regs->dmapc); + cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dmapc); return (cs4231_chip->perchip_info.play.samples - ((count > cs4231_chip->perchip_info.play.samples) @@ -792,10 +758,10 @@ static int cs4231_get_input_samples(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dmacc = sbus_readl(cs4231_chip->regs + APCCC); int count = - cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, - cs4231_chip->regs->dmacc); + cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, dmacc); return (cs4231_chip->perchip_info.record.samples - ((count > cs4231_chip->perchip_info.record.samples) ? @@ -804,23 +770,24 @@ static int cs4231_get_output_pause(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.play.pause; + return (int) cs4231_chip->perchip_info.play.pause; } static int cs4231_get_input_pause(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.record.pause; + return (int) cs4231_chip->perchip_info.record.pause; } /* But for play/record we have these cheesy jacket routines because of - * how this crap gets set */ + * how this crap gets set. + */ static int cs4231_set_input_volume(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_record_gain(drv, value, cs4231_chip->perchip_info.record.balance); @@ -830,14 +797,14 @@ static int cs4231_get_input_volume(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.record.gain; + return (int) cs4231_chip->perchip_info.record.gain; } static int cs4231_set_output_volume(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_play_gain(drv, value, cs4231_chip->perchip_info.play.balance); @@ -846,7 +813,7 @@ static int cs4231_get_output_volume(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; return cs4231_chip->perchip_info.play.gain; } @@ -854,7 +821,7 @@ /* Likewise for balance */ static int cs4231_set_input_balance(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.record.balance = value; cs4231_record_gain(drv, cs4231_chip->perchip_info.record.gain, @@ -865,14 +832,14 @@ static int cs4231_get_input_balance(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.record.balance; + return (int) cs4231_chip->perchip_info.record.balance; } static int cs4231_set_output_balance(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.play.balance = value; cs4231_play_gain(drv, cs4231_chip->perchip_info.play.gain, @@ -883,561 +850,602 @@ static int cs4231_get_output_balance(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - return (int)cs4231_chip->perchip_info.play.balance; + return (int) cs4231_chip->perchip_info.play.balance; } /* Set chip record gain */ -static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) +static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, + unsigned char balance) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp = 0, r, l, r_adj, l_adj; - unsigned char old_gain; - - r = l = value; - - if (balance < AUDIO_MID_BALANCE) { - r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); - if (r < 0) r = 0; - } else if (balance > AUDIO_MID_BALANCE) { - l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); - if (l < 0) l = 0; - } - - l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); - r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0); - old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, l_adj)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1); - old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, r_adj)); - - if (l == value) { - (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / - (CS4231_MAX_GAIN + 1)); - } else if (r == value) { - (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / - (CS4231_MAX_GAIN + 1)); - } - cs4231_chip->perchip_info.record.gain = tmp; - return 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp = 0, r, l, r_adj, l_adj; + unsigned char old_gain; + + r = l = value; + + if (balance < AUDIO_MID_BALANCE) { + r = (int) (value - + ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); + + if (r < 0) + r = 0; + } else if (balance > AUDIO_MID_BALANCE) { + l = (int) (value - + ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); + + if (l < 0) + l = 0; + } + + l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); + r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1); + + WRITE_IAR(0x0); + old_gain = READ_IDR(); + WRITE_IDR(RECGAIN_SET(old_gain, l_adj)); + WRITE_IAR(0x1); + old_gain = READ_IDR(); + WRITE_IDR(RECGAIN_SET(old_gain, r_adj)); + + if (l == value) { + (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / + (CS4231_MAX_GAIN + 1)); + } else if (r == value) { + (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / + (CS4231_MAX_GAIN + 1)); + } + cs4231_chip->perchip_info.record.gain = tmp; + return 0; } /* Set chip play gain */ -static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) +static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, + unsigned char balance) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int tmp = 0, r, l, r_adj, l_adj; - unsigned char old_gain; - - tprintk(("in play_gain: %d %c\n", value, balance)); - r = l = value; - if (balance < AUDIO_MID_BALANCE) { - r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); - if (r < 0) r = 0; - } else if (balance > AUDIO_MID_BALANCE) { - l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); - if (l < 0) l = 0; - } - - (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - - (l * (CS4231_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN - - (r * (CS4231_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6); - old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, l_adj)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7); - old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, r_adj)); - - if ((value == 0) || (value == AUDIO_MAX_GAIN)) { - tmp = value; - } else { - if (value == l) - tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / - (CS4231_MAX_ATEN + 1)); - else if (value == r) - tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / - (CS4231_MAX_ATEN + 1)); - } - cs4231_chip->perchip_info.play.gain = tmp; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int tmp = 0, r, l, r_adj, l_adj; + unsigned char old_gain; + + tprintk(("in play_gain: %d %c\n", value, balance)); + r = l = value; + if (balance < AUDIO_MID_BALANCE) { + r = (int) (value - + ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); + + if (r < 0) + r = 0; + } else if (balance > AUDIO_MID_BALANCE) { + l = (int) (value - + ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); + + if (l < 0) + l = 0; + } + + (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - + (l * (CS4231_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN - + (r * (CS4231_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + + WRITE_IAR(0x6); + old_gain = READ_IDR(); + WRITE_IDR(GAIN_SET(old_gain, l_adj)); + WRITE_IAR(0x7); + old_gain = READ_IDR(); + WRITE_IDR(GAIN_SET(old_gain, r_adj)); + + if ((value == 0) || (value == AUDIO_MAX_GAIN)) { + tmp = value; + } else { + if (value == l) { + tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / + (CS4231_MAX_ATEN + 1)); + } else if (value == r) { + tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / + (CS4231_MAX_ATEN + 1)); + } + } + cs4231_chip->perchip_info.play.gain = tmp; - return 0; + return 0; } /* Reset the audio chip to a sane state. */ static void cs4231_chip_reset(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned char vers; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + unsigned char vers; - tprintk(("in cs4231_chip_reset\n")); + tprintk(("in cs4231_chip_reset\n")); - if (cs4231_chip->status & CS_STATUS_IS_EBUS) { + if (cs4231_chip->status & CS_STATUS_IS_EBUS) { #ifdef EB4231_SUPPORT - writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr)); - writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr)); - writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr)); - writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr)); + writel(EBUS_DCSR_RESET, cs4231_chip->eb2p + EBDMA_CSR); + writel(EBUS_DCSR_RESET, cs4231_chip->eb2c + EBDMA_CSR); + writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2p + EBDMA_CSR); + writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2c + EBDMA_CSR); #endif - } else { - cs4231_chip->regs->dmacsr = APC_CHIP_RESET; - cs4231_chip->regs->dmacsr = 0x00; - cs4231_chip->regs->dmacsr |= APC_CDC_RESET; - - udelay(20); - - cs4231_chip->regs->dmacsr &= ~(APC_CDC_RESET); - } - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->iar)) | IAR_AUTOCAL_BEGIN)); - - CHIP_READY - - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x0c); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), MISC_IR_MODE2); - - /* This is the equivalent of DEFAULT_DATA_FMAT */ - cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW); - cs4231_set_input_rate(drv, CS4231_RATE); - cs4231_set_input_channels(drv, CS4231_CHANNELS); - cs4231_set_input_precision(drv, CS4231_PRECISION); + } else { + u32 tmp; - cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW); - cs4231_set_output_rate(drv, CS4231_RATE); - cs4231_set_output_channels(drv, CS4231_CHANNELS); - cs4231_set_output_precision(drv, CS4231_PRECISION); + sbus_writel(APC_CHIP_RESET, cs4231_chip->regs + APCCSR); + sbus_writel(0x00, cs4231_chip->regs + APCCSR); + tmp = sbus_readl(cs4231_chip->regs + APCCSR); + tmp |= APC_CDC_RESET; + sbus_writel(tmp, cs4231_chip->regs + APCCSR); + + udelay(20); + + tmp = sbus_readl(cs4231_chip->regs + APCCSR); + tmp &= ~(APC_CDC_RESET); + sbus_writel(tmp, cs4231_chip->regs + APCCSR); + } - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x19); + WRITE_IAR(READ_IAR() | IAR_AUTOCAL_BEGIN); + CHIP_READY(); + + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x0c); + WRITE_IDR(MISC_IR_MODE2); - /* see what we can turn on */ - vers = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)); - if (vers & CS4231A) { - tprintk(("This is a CS4231A\n")); - cs4231_chip->status |= CS_STATUS_REV_A; - } else - cs4231_chip->status &= ~CS_STATUS_REV_A; + /* This is the equivalent of DEFAULT_DATA_FMAT */ + cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW); + cs4231_set_input_rate(drv, CS4231_RATE); + cs4231_set_input_channels(drv, CS4231_CHANNELS); + cs4231_set_input_precision(drv, CS4231_PRECISION); + + cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW); + cs4231_set_output_rate(drv, CS4231_RATE); + cs4231_set_output_channels(drv, CS4231_CHANNELS); + cs4231_set_output_precision(drv, CS4231_PRECISION); + + WRITE_IAR(0x19); + + /* see what we can turn on */ + vers = READ_IDR(); + if (vers & CS4231A) { + tprintk(("This is a CS4231A\n")); + cs4231_chip->status |= CS_STATUS_REV_A; + } else { + cs4231_chip->status &= ~CS_STATUS_REV_A; + } - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x10); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), OLB_ENABLE); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x10); + WRITE_IDR(OLB_ENABLE); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x11); - if (cs4231_chip->status & CS_STATUS_REV_A) - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (HPF_ON | XTALE_ON)); - else - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), HPF_ON); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x11); + if (cs4231_chip->status & CS_STATUS_REV_A) + WRITE_IDR(HPF_ON | XTALE_ON); + else + WRITE_IDR(HPF_ON); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1a); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), 0x00); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1a); + WRITE_IDR(0x00); - /* Now set things up for defaults */ - cs4231_set_input_balance(drv, AUDIO_MID_BALANCE); - cs4231_set_output_balance(drv, AUDIO_MID_BALANCE); + /* Now set things up for defaults */ + cs4231_set_input_balance(drv, AUDIO_MID_BALANCE); + cs4231_set_output_balance(drv, AUDIO_MID_BALANCE); - cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN); - cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN); + cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN); + cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN); - cs4231_set_input_port(drv, AUDIO_MICROPHONE); - cs4231_set_output_port(drv, AUDIO_SPEAKER); + cs4231_set_input_port(drv, AUDIO_MICROPHONE); + cs4231_set_output_port(drv, AUDIO_SPEAKER); - cs4231_set_monitor_volume(drv, LOOPB_OFF); + cs4231_set_monitor_volume(drv, LOOPB_OFF); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); + WRITE_IAR(IAR_AUTOCAL_END); - cs4231_ready(drv); + cs4231_ready(drv); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x09); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), - (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ACAL_DISABLE)); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END); + WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x09); + WRITE_IDR(READ_IDR() & ACAL_DISABLE); + WRITE_IAR(IAR_AUTOCAL_END); - cs4231_ready(drv); + cs4231_ready(drv); - cs4231_output_muted(drv, 0); + cs4231_output_muted(drv, 0); - cs4231_chip->recording_count = 0; - cs4231_chip->input_next_dma_handle = 0; - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_next_dma_size = 0; - cs4231_chip->input_dma_size = 0; + cs4231_chip->recording_count = 0; + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + cs4231_chip->input_dma_size = 0; - cs4231_chip->playing_count = 0; - cs4231_chip->output_next_dma_handle = 0; - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_next_dma_size = 0; - cs4231_chip->output_dma_size = 0; + cs4231_chip->playing_count = 0; + cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; + cs4231_chip->output_dma_size = 0; } -static int +static int cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length) { - unsigned int count; + unsigned int count; - if (thisdir->channels == 2) - count = (length/2); - else - count = length; - - if (thisdir->encoding == AUDIO_ENCODING_LINEAR) - count = (count/2); - else if (thisdir->encoding == AUDIO_ENCODING_DVI) - count = (count/4); + if (thisdir->channels == 2) + count = (length / 2); + else + count = length; + + if (thisdir->encoding == AUDIO_ENCODING_LINEAR) + count = (count / 2); + else if (thisdir->encoding == AUDIO_ENCODING_DVI) + count = (count / 4); - return count; + return count; } #ifdef EB4231_SUPPORT -static void eb4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction) -{ - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - struct audio_prinfo *thisdir; - unsigned int count, curcount, nextcount, dbcr; - - if(direction == 1) { - thisdir = &cs4231_chip->perchip_info.record; - dbcr = readl(&(cs4231_chip->eb2c->dbcr)); - nextcount = cs4231_chip->input_next_dma_size; - } else { - thisdir = &cs4231_chip->perchip_info.play; - dbcr = readl(&(cs4231_chip->eb2p->dbcr)); - nextcount = cs4231_chip->output_next_dma_size; - } - curcount = cs4231_length_to_samplecount(thisdir, dbcr); - count = thisdir->samples; - length = cs4231_length_to_samplecount(thisdir, length); - /* normalize for where we are. */ - thisdir->samples = ((count - nextcount) + (length - curcount)); +static void eb4231_getsamplecount(struct sparcaudio_driver *drv, + unsigned int length, + unsigned int direction) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + struct audio_prinfo *thisdir; + unsigned int count, curcount, nextcount, dbcr; + + if(direction == 1) { + thisdir = &cs4231_chip->perchip_info.record; + dbcr = readl(cs4231_chip->eb2c + EBDMA_COUNT); + nextcount = cs4231_chip->input_next_dma_size; + } else { + thisdir = &cs4231_chip->perchip_info.play; + dbcr = readl(cs4231_chip->eb2p + EBDMA_COUNT); + nextcount = cs4231_chip->output_next_dma_size; + } + curcount = cs4231_length_to_samplecount(thisdir, dbcr); + count = thisdir->samples; + length = cs4231_length_to_samplecount(thisdir, length); + /* normalize for where we are. */ + thisdir->samples = ((count - nextcount) + (length - curcount)); } #endif -static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction) -{ - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - struct audio_prinfo *thisdir; - unsigned int count, nextcount, curcount; - - if (direction == 1) /* record */ - { - thisdir = &cs4231_chip->perchip_info.record; - curcount = - cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacc); - nextcount = - cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacnc); - } - else /* play */ - { - thisdir = &cs4231_chip->perchip_info.play; - curcount = - cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapc); - nextcount = - cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapnc); - } - count = thisdir->samples; - length = cs4231_length_to_samplecount(thisdir, length); - /* normalize for where we are. */ - thisdir->samples = ((count - nextcount) + (length - curcount)); +static void cs4231_getsamplecount(struct sparcaudio_driver *drv, + unsigned int length, + unsigned int direction) +{ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + struct audio_prinfo *thisdir; + unsigned int count, nextcount, curcount; + u32 tmp; + + if (direction == 1) { + /* record */ + thisdir = &cs4231_chip->perchip_info.record; + tmp = sbus_readl(cs4231_chip->regs + APCCC); + curcount = cs4231_length_to_samplecount(thisdir, tmp); + tmp = sbus_readl(cs4231_chip->regs + APCCNC); + nextcount = cs4231_length_to_samplecount(thisdir, tmp); + } else { + /* play */ + thisdir = &cs4231_chip->perchip_info.play; + tmp = sbus_readl(cs4231_chip->regs + APCPC); + curcount = cs4231_length_to_samplecount(thisdir, tmp); + tmp = sbus_readl(cs4231_chip->regs + APCPNC); + nextcount = cs4231_length_to_samplecount(thisdir, tmp); + } + count = thisdir->samples; + length = cs4231_length_to_samplecount(thisdir, length); + + /* normalize for where we are. */ + thisdir->samples = ((count - nextcount) + (length - curcount)); } static int cs4231_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - /* Set the default audio parameters if not already in use. */ - if (file->f_mode & FMODE_WRITE) { - if (!(drv->flags & SDF_OPEN_WRITE) && - (cs4231_chip->perchip_info.play.active == 0)) { - cs4231_chip->perchip_info.play.open = 1; - cs4231_chip->perchip_info.play.samples = - cs4231_chip->perchip_info.play.error = 0; - } - } - - if (file->f_mode & FMODE_READ) { - if (!(drv->flags & SDF_OPEN_READ) && - (cs4231_chip->perchip_info.record.active == 0)) { - cs4231_chip->perchip_info.record.open = 1; - cs4231_chip->perchip_info.record.samples = - cs4231_chip->perchip_info.record.error = 0; - } - } + /* Set the default audio parameters if not already in use. */ + if (file->f_mode & FMODE_WRITE) { + if (!(drv->flags & SDF_OPEN_WRITE) && + (cs4231_chip->perchip_info.play.active == 0)) { + cs4231_chip->perchip_info.play.open = 1; + cs4231_chip->perchip_info.play.samples = + cs4231_chip->perchip_info.play.error = 0; + } + } + + if (file->f_mode & FMODE_READ) { + if (!(drv->flags & SDF_OPEN_READ) && + (cs4231_chip->perchip_info.record.active == 0)) { + cs4231_chip->perchip_info.record.open = 1; + cs4231_chip->perchip_info.record.samples = + cs4231_chip->perchip_info.record.error = 0; + } + } - cs4231_ready(drv); - - CHIP_READY + cs4231_ready(drv); + CHIP_READY(); - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - return 0; + return 0; } static void cs4231_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - - /* zero out any info about what data we have as well */ + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - if (file->f_mode & FMODE_READ) { - /* stop capture here or midlevel? */ - cs4231_chip->perchip_info.record.open = 0; - if (cs4231_chip->input_dma_handle) { - if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) - mmu_release_scsi_one(cs4231_chip->input_dma_handle, - cs4231_chip->input_dma_size, drv->dev->my_bus); - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_dma_size = 0; - } - if (cs4231_chip->input_next_dma_handle) { - if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) - mmu_release_scsi_one(cs4231_chip->input_next_dma_handle, - cs4231_chip->input_next_dma_size, drv->dev->my_bus); - cs4231_chip->input_next_dma_handle = 0; - cs4231_chip->input_next_dma_size = 0; - } - } - - if (file->f_mode & FMODE_WRITE) { - cs4231_chip->perchip_info.play.active = - cs4231_chip->perchip_info.play.open = 0; - if (cs4231_chip->output_dma_handle) { - if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) - mmu_release_scsi_one(cs4231_chip->output_dma_handle, - cs4231_chip->output_dma_size, drv->dev->my_bus); - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_dma_size = 0; - } - if (cs4231_chip->output_next_dma_handle) { - if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) - mmu_release_scsi_one(cs4231_chip->output_next_dma_handle, - cs4231_chip->output_next_dma_size, - drv->dev->my_bus); - cs4231_chip->output_next_dma_handle = 0; - cs4231_chip->output_next_dma_size = 0; - } - } - - if (!cs4231_chip->perchip_info.play.open && - !cs4231_chip->perchip_info.record.open && - (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) { - cs4231_chip_reset(drv); - cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE; - } + /* zero out any info about what data we have as well */ + if (file->f_mode & FMODE_READ) { + /* stop capture here or midlevel? */ + cs4231_chip->perchip_info.record.open = 0; + if (cs4231_chip->input_dma_handle) { + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + sbus_unmap_single(drv->dev, + cs4231_chip->input_dma_handle, + cs4231_chip->input_dma_size); + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + } + if (cs4231_chip->input_next_dma_handle) { + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + sbus_unmap_single(drv->dev, + cs4231_chip->input_next_dma_handle, + cs4231_chip->input_next_dma_size); + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + } + } + + if (file->f_mode & FMODE_WRITE) { + cs4231_chip->perchip_info.play.active = + cs4231_chip->perchip_info.play.open = 0; + if (cs4231_chip->output_dma_handle) { + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + sbus_unmap_single(drv->dev, + cs4231_chip->output_dma_handle, + cs4231_chip->output_dma_size); + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_dma_size = 0; + } + if (cs4231_chip->output_next_dma_handle) { + if(!(cs4231_chip->status & CS_STATUS_IS_EBUS)) + sbus_unmap_single(drv->dev, + cs4231_chip->output_next_dma_handle, + cs4231_chip->output_next_dma_size); + cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; + } + } + + if (!cs4231_chip->perchip_info.play.open && + !cs4231_chip->perchip_info.record.open && + (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) { + cs4231_chip_reset(drv); + cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE; + } - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; } static void cs4231_playintr(struct sparcaudio_driver *drv, int push) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int status = 0; - - if (!push) { - if (!cs4231_chip->perchip_info.play.active) { - cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle; - cs4231_chip->regs->dmapnc = cs4231_chip->output_next_dma_size; - } - sparcaudio_output_done(drv, 0); - return; - } - - if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) - cs4231_chip->playlen = cs4231_chip->output_size; - - if (cs4231_chip->output_dma_handle) { - mmu_release_scsi_one(cs4231_chip->output_dma_handle, - cs4231_chip->output_dma_size, drv->dev->my_bus); - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_dma_size = 0; - cs4231_chip->playing_count--; - status++; - } - if (cs4231_chip->output_next_dma_handle) { - cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle; - cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size; - cs4231_chip->output_next_dma_size = 0; - cs4231_chip->output_next_dma_handle = 0; - } - - if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && - !(cs4231_chip->perchip_info.play.pause)) { - cs4231_chip->output_next_dma_handle = - mmu_get_scsi_one((char *) cs4231_chip->output_ptr, - cs4231_chip->output_size, drv->dev->my_bus); - cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle; - cs4231_chip->output_next_dma_size = cs4231_chip->regs->dmapnc = - cs4231_chip->output_size; - cs4231_chip->output_size = 0; - cs4231_chip->output_ptr = NULL; - cs4231_chip->playing_count++; - status += 2; - } else { - cs4231_chip->regs->dmapnva = 0; - cs4231_chip->regs->dmapnc = 0; - } + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int status = 0; - sparcaudio_output_done(drv, status); + if (!push) { + if (!cs4231_chip->perchip_info.play.active) { + sbus_writel(cs4231_chip->output_next_dma_handle, + cs4231_chip->regs + APCPNVA); + sbus_writel(cs4231_chip->output_next_dma_size, + cs4231_chip->regs + APCPNC); + } + sparcaudio_output_done(drv, 0); + return; + } + + if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) + cs4231_chip->playlen = cs4231_chip->output_size; + + if (cs4231_chip->output_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->output_dma_handle, + cs4231_chip->output_dma_size); + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_dma_size = 0; + cs4231_chip->playing_count--; + status++; + } + + if (cs4231_chip->output_next_dma_handle) { + cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle; + cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size; + cs4231_chip->output_next_dma_size = 0; + cs4231_chip->output_next_dma_handle = 0; + } + + if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && + !(cs4231_chip->perchip_info.play.pause)) { + cs4231_chip->output_next_dma_handle = + sbus_map_single(drv->dev, + (char *)cs4231_chip->output_ptr, + cs4231_chip->output_size); + cs4231_chip->output_next_dma_size = cs4231_chip->output_size; + sbus_writel(cs4231_chip->output_next_dma_handle, + cs4231_chip->regs + APCPNVA); + sbus_writel(cs4231_chip->output_next_dma_size, + cs4231_chip->regs + APCPNC); + cs4231_chip->output_size = 0; + cs4231_chip->output_ptr = NULL; + cs4231_chip->playing_count++; + status += 2; + } else { + sbus_writel(0, cs4231_chip->regs + APCPNVA); + sbus_writel(0, cs4231_chip->regs + APCPNC); + } - return; + sparcaudio_output_done(drv, status); } #ifdef EB4231_SUPPORT static void eb4231_playintr(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int status = 0; - - if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) - cs4231_chip->playlen = cs4231_chip->output_size; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int status = 0; - if (cs4231_chip->output_dma_handle) { - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_dma_size = 0; - cs4231_chip->playing_count--; - status++; - } - if(cs4231_chip->output_next_dma_handle) { - cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle; - cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size; - cs4231_chip->output_next_dma_handle = 0; - cs4231_chip->output_next_dma_size = 0; - } - - if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && - !(cs4231_chip->perchip_info.play.pause)) { - cs4231_chip->output_next_dma_handle = virt_to_bus(cs4231_chip->output_ptr); - cs4231_chip->output_next_dma_size = cs4231_chip->output_size; - - writel(cs4231_chip->output_next_dma_size, &(cs4231_chip->eb2p->dbcr)); - writel(cs4231_chip->output_next_dma_handle, &(cs4231_chip->eb2p->dacr)); - cs4231_chip->output_size = 0; - cs4231_chip->output_ptr = NULL; - cs4231_chip->playing_count++; - status += 2; - } + if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) + cs4231_chip->playlen = cs4231_chip->output_size; - sparcaudio_output_done(drv, status); + if (cs4231_chip->output_dma_handle) { + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_dma_size = 0; + cs4231_chip->playing_count--; + status++; + } + + if(cs4231_chip->output_next_dma_handle) { + cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle; + cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size; + cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; + } + + if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && + !(cs4231_chip->perchip_info.play.pause)) { + cs4231_chip->output_next_dma_handle = + virt_to_bus(cs4231_chip->output_ptr); + cs4231_chip->output_next_dma_size = cs4231_chip->output_size; + + writel(cs4231_chip->output_next_dma_size, + cs4231_chip->eb2p + EBDMA_COUNT); + writel(cs4231_chip->output_next_dma_handle, + cs4231_chip->eb2p + EBDMA_ADDR); + cs4231_chip->output_size = 0; + cs4231_chip->output_ptr = NULL; + cs4231_chip->playing_count++; + status += 2; + } - return; + sparcaudio_output_done(drv, status); } #endif static void cs4231_recclear(int fmt, char *dmabuf, int length) { - switch (fmt) { - case AUDIO_ENCODING_LINEAR: - memset(dmabuf, 0x00, length); - break; - case AUDIO_ENCODING_ALAW: - memset(dmabuf, 0xd5, length); - break; - case AUDIO_ENCODING_ULAW: - memset(dmabuf, 0xff, length); - break; - } + switch (fmt) { + case AUDIO_ENCODING_LINEAR: + memset(dmabuf, 0x00, length); + break; + case AUDIO_ENCODING_ALAW: + memset(dmabuf, 0xd5, length); + break; + case AUDIO_ENCODING_ULAW: + memset(dmabuf, 0xff, length); + break; + } } static int cs4231_recintr(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int status = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int status = 0; - if (cs4231_chip->perchip_info.record.active == 0) { - dprintk(("going inactive\n")); - cs4231_pollinput(drv); - cs4231_disable_rec(drv); - } - - if (cs4231_chip->input_dma_handle) { - mmu_release_scsi_one(cs4231_chip->input_dma_handle, - cs4231_chip->input_dma_size, drv->dev->my_bus); - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_dma_size = 0; - cs4231_chip->recording_count--; - status++; - } - if (cs4231_chip->input_next_dma_handle) { - cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle; - cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size; - cs4231_chip->input_next_dma_size = 0; - cs4231_chip->input_next_dma_handle = 0; - } - - if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && - !(cs4231_chip->perchip_info.record.pause)) { - cs4231_recclear(cs4231_chip->perchip_info.record.encoding, - (char *)cs4231_chip->input_ptr, cs4231_chip->input_size); - cs4231_chip->input_next_dma_handle = - mmu_get_scsi_one((char *) cs4231_chip->input_ptr, - cs4231_chip->input_size, drv->dev->my_bus); - cs4231_chip->regs->dmacnva = cs4231_chip->input_next_dma_handle; - cs4231_chip->input_next_dma_size = cs4231_chip->regs->dmacnc = - cs4231_chip->input_size; - cs4231_chip->input_size = 0; - cs4231_chip->input_ptr = NULL; - cs4231_chip->recording_count++; - status += 2; - } else { - cs4231_chip->regs->dmacnva = 0; - cs4231_chip->regs->dmacnc = 0; - } - - sparcaudio_input_done(drv, status); + if (cs4231_chip->perchip_info.record.active == 0) { + dprintk(("going inactive\n")); + cs4231_pollinput(drv); + cs4231_disable_rec(drv); + } + + if (cs4231_chip->input_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->input_dma_handle, + cs4231_chip->input_dma_size); + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + cs4231_chip->recording_count--; + status++; + } + + if (cs4231_chip->input_next_dma_handle) { + cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle; + cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size; + cs4231_chip->input_next_dma_size = 0; + cs4231_chip->input_next_dma_handle = 0; + } + + if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && + !(cs4231_chip->perchip_info.record.pause)) { + cs4231_recclear(cs4231_chip->perchip_info.record.encoding, + (char *)cs4231_chip->input_ptr, + cs4231_chip->input_size); + cs4231_chip->input_next_dma_handle = + sbus_map_single(drv->dev, + (char *)cs4231_chip->input_ptr, + cs4231_chip->input_size); + cs4231_chip->input_next_dma_size = cs4231_chip->input_size; + sbus_writel(cs4231_chip->input_next_dma_handle, + cs4231_chip->regs + APCCNVA); + sbus_writel(cs4231_chip->input_next_dma_size, + cs4231_chip->regs + APCCNC); + cs4231_chip->input_size = 0; + cs4231_chip->input_ptr = NULL; + cs4231_chip->recording_count++; + status += 2; + } else { + sbus_writel(0, cs4231_chip->regs + APCCNVA); + sbus_writel(0, cs4231_chip->regs + APCCNC); + } - return 1; + sparcaudio_input_done(drv, status); + return 1; } #ifdef EB4231_SUPPORT static int eb4231_recintr(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int status = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int status = 0; - if (cs4231_chip->perchip_info.record.active == 0) { - dprintk(("going inactive\n")); - eb4231_pollinput(drv); - cs4231_disable_rec(drv); - } - - if (cs4231_chip->input_dma_handle) { - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_dma_size = 0; - cs4231_chip->recording_count--; - status++; - } - if (cs4231_chip->input_next_dma_handle) { - cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle; - cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size; - cs4231_chip->input_next_dma_size = 0; - cs4231_chip->input_next_dma_handle = 0; - } - - if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && - !(cs4231_chip->perchip_info.record.pause)) { - cs4231_recclear(cs4231_chip->perchip_info.record.encoding, - (char *)cs4231_chip->input_ptr, cs4231_chip->input_size); - - cs4231_chip->input_next_dma_handle = virt_to_bus(cs4231_chip->input_ptr); - cs4231_chip->input_next_dma_size = cs4231_chip->input_size; - - writel(cs4231_chip->input_next_dma_size, &(cs4231_chip->eb2c->dbcr)); - writel(cs4231_chip->input_next_dma_handle, &(cs4231_chip->eb2c->dacr)); - - cs4231_chip->input_size = 0; - cs4231_chip->input_ptr = NULL; - cs4231_chip->recording_count++; - status += 2; - } + if (cs4231_chip->perchip_info.record.active == 0) { + dprintk(("going inactive\n")); + eb4231_pollinput(drv); + cs4231_disable_rec(drv); + } + + if (cs4231_chip->input_dma_handle) { + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + cs4231_chip->recording_count--; + status++; + } + + if (cs4231_chip->input_next_dma_handle) { + cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle; + cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size; + cs4231_chip->input_next_dma_size = 0; + cs4231_chip->input_next_dma_handle = 0; + } + + if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && + !(cs4231_chip->perchip_info.record.pause)) { + cs4231_recclear(cs4231_chip->perchip_info.record.encoding, + (char *)cs4231_chip->input_ptr, + cs4231_chip->input_size); + + cs4231_chip->input_next_dma_handle = + virt_to_bus(cs4231_chip->input_ptr); + cs4231_chip->input_next_dma_size = cs4231_chip->input_size; + + writel(cs4231_chip->input_next_dma_size, + cs4231_chip->eb2c + EBDMA_COUNT); + writel(cs4231_chip->input_next_dma_handle, + cs4231_chip->eb2c + EBDMA_ADDR); + + cs4231_chip->input_size = 0; + cs4231_chip->input_ptr = NULL; + cs4231_chip->recording_count++; + status += 2; + } - sparcaudio_input_done(drv, status); - - return 1; + sparcaudio_input_done(drv, status); + return 1; } #endif @@ -1445,335 +1453,380 @@ static void eb4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int dcsr; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dcsr; - cs4231_chip->output_ptr = buffer; - cs4231_chip->output_size = count; + cs4231_chip->output_ptr = buffer; + cs4231_chip->output_size = count; - if (cs4231_chip->perchip_info.play.active || - (cs4231_chip->perchip_info.play.pause)) - return; + if (cs4231_chip->perchip_info.play.active || + (cs4231_chip->perchip_info.play.pause)) + return; - cs4231_ready(drv); + cs4231_ready(drv); - cs4231_chip->perchip_info.play.active = 1; - cs4231_chip->playing_count = 0; + cs4231_chip->perchip_info.play.active = 1; + cs4231_chip->playing_count = 0; - dcsr = readl(&cs4231_chip->eb2p->dcsr); - if (!(dcsr & EBUS_DCSR_EN_DMA)) { - writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr)); - writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr)); + dcsr = readl(cs4231_chip->eb2p + EBDMA_CSR); + if (!(dcsr & EBUS_DCSR_EN_DMA)) { + writel(EBUS_DCSR_RESET, cs4231_chip->eb2p + EBDMA_CSR); + writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2p + EBDMA_CSR); - eb4231_playintr(drv); + eb4231_playintr(drv); - writel(EBUS_DCSR_BURST_SZ_16 | - (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), - &(cs4231_chip->eb2p->dcsr)); + writel(EBUS_DCSR_BURST_SZ_16 | + (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | + EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), + cs4231_chip->eb2p + EBDMA_CSR); - cs4231_enable_play(drv); + cs4231_enable_play(drv); - cs4231_ready(drv); - } else { - eb4231_playintr(drv); - } + cs4231_ready(drv); + } else { + eb4231_playintr(drv); + } } #endif static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - - tprintk(("in 4231 start output\n")); - cs4231_chip->output_ptr = buffer; - cs4231_chip->output_size = count; - - if (cs4231_chip->perchip_info.play.active || - (cs4231_chip->perchip_info.play.pause)) - return; - - cs4231_ready(drv); - - cs4231_chip->perchip_info.play.active = 1; - cs4231_chip->playing_count = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 csr; - if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) || - !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) { - cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY; - cs4231_chip->regs->dmacsr &= ~APC_PPAUSE; + tprintk(("in 4231 start output\n")); + cs4231_chip->output_ptr = buffer; + cs4231_chip->output_size = count; + + if (cs4231_chip->perchip_info.play.active || + (cs4231_chip->perchip_info.play.pause)) + return; + + cs4231_ready(drv); + + cs4231_chip->perchip_info.play.active = 1; + cs4231_chip->playing_count = 0; + + csr = sbus_readl(cs4231_chip->regs + APCCSR); + if ((csr & APC_PPAUSE) || !(csr & APC_PDMA_READY)) { + u32 pnva; + + csr &= ~APC_XINT_PLAY; + sbus_writel(csr, cs4231_chip->regs + APCCSR); + csr &= ~APC_PPAUSE; + sbus_writel(csr, cs4231_chip->regs + APCCSR); - cs4231_playintr(drv, cs4231_chip->regs->dmapnva == 0 ? 1 : 0); + pnva = sbus_readl(cs4231_chip->regs + APCPNVA); + cs4231_playintr(drv, (pnva == 0) ? 1 : 0); - cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP; - cs4231_enable_play(drv); + csr |= APC_PLAY_SETUP; + sbus_writel(csr, cs4231_chip->regs + APCCSR); + cs4231_enable_play(drv); - cs4231_ready(drv); - } + cs4231_ready(drv); + } } #ifdef EB4231_SUPPORT static void eb4231_stop_output(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int dcsr; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dcsr; - dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n", - readl(&cs4231_chip->eb2p->dcsr), - readl(&cs4231_chip->eb2p->dacr), - readl(&cs4231_chip->eb2p->dbcr))); - cs4231_chip->output_ptr = NULL; - cs4231_chip->output_size = 0; - if (cs4231_chip->output_dma_handle) { - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_dma_size = 0; - } - if (cs4231_chip->output_next_dma_handle) { - cs4231_chip->output_next_dma_handle = 0; - cs4231_chip->output_next_dma_size = 0; - } - dcsr = readl(&(cs4231_chip->eb2p->dcsr)); - if(dcsr & EBUS_DCSR_EN_DMA) - writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2p->dcsr)); + dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n", + readl(cs4231_chip->eb2p + EBDMA_CSR), + readl(cs4231_chip->eb2p + EBDMA_ADDR), + readl(cs4231_chip->eb2p + EBDMA_COUNT))); + + cs4231_chip->output_ptr = NULL; + cs4231_chip->output_size = 0; + + if (cs4231_chip->output_dma_handle) { + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_dma_size = 0; + } + + if (cs4231_chip->output_next_dma_handle) { + cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; + } + dcsr = readl(cs4231_chip->eb2p + EBDMA_CSR); + if(dcsr & EBUS_DCSR_EN_DMA) + writel(dcsr & ~EBUS_DCSR_EN_DMA, + cs4231_chip->eb2p + EBDMA_CSR); - /* Else subsequent speed setting changes are ignored by the chip. */ - cs4231_disable_play(drv); + /* Else subsequent speed setting changes are ignored by the chip. */ + cs4231_disable_play(drv); } #endif static void cs4231_stop_output(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - tprintk(("in cs4231_stop_output\n")); - cs4231_chip->output_ptr = NULL; - cs4231_chip->output_size = 0; - if (cs4231_chip->output_dma_handle) { - mmu_release_scsi_one(cs4231_chip->output_dma_handle, - cs4231_chip->output_dma_size, drv->dev->my_bus); - cs4231_chip->output_dma_handle = 0; - cs4231_chip->output_dma_size = 0; - } - if (cs4231_chip->output_next_dma_handle) { - mmu_release_scsi_one(cs4231_chip->output_next_dma_handle, - cs4231_chip->output_next_dma_size, drv->dev->my_bus); - cs4231_chip->output_next_dma_handle = 0; - cs4231_chip->output_next_dma_size = 0; - } + tprintk(("in cs4231_stop_output\n")); + cs4231_chip->output_ptr = NULL; + cs4231_chip->output_size = 0; + + if (cs4231_chip->output_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->output_dma_handle, + cs4231_chip->output_dma_size); + cs4231_chip->output_dma_handle = 0; + cs4231_chip->output_dma_size = 0; + } + + if (cs4231_chip->output_next_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->output_next_dma_handle, + cs4231_chip->output_next_dma_size); + cs4231_chip->output_next_dma_handle = 0; + cs4231_chip->output_next_dma_size = 0; + } #if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */ - /* Else subsequent speed setting changes are ignored by the chip. */ - cs4231_disable_play(drv); + /* Else subsequent speed setting changes are ignored by the chip. */ + cs4231_disable_play(drv); #endif } #ifdef EB4231_SUPPORT static void eb4231_pollinput(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int x = 0, dcsr; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int x; + u32 dcsr; + + x = 0; + do { + dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR); + if (dcsr & EBUS_DCSR_TC) + break; + x++; + } while (x <= CS_TIMEOUT); - while (!((dcsr = readl(&(cs4231_chip->eb2c->dcsr))) & EBUS_DCSR_TC) && - x <= CS_TIMEOUT) { - x++; - } - - writel(dcsr | EBUS_DCSR_TC, &(cs4231_chip->eb2c->dcsr)); + writel(dcsr | EBUS_DCSR_TC, + cs4231_chip->eb2c + EBDMA_CSR); } #endif static void cs4231_pollinput(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int x = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int x; + u32 csr; + + x = 0; + do { + csr = sbus_readl(cs4231_chip->regs + APCCSR); + if (csr & APC_XINT_COVF) + break; + x++; + } while (x <= CS_TIMEOUT); - while (!(cs4231_chip->regs->dmacsr & APC_XINT_COVF) && x <= CS_TIMEOUT) { - x++; - } - cs4231_chip->regs->dmacsr |= APC_XINT_CEMP; + sbus_writel(csr | APC_XINT_CEMP, + cs4231_chip->regs + APCCSR); } static void cs4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 csr; - cs4231_chip->input_ptr = buffer; - cs4231_chip->input_size = count; + cs4231_chip->input_ptr = buffer; + cs4231_chip->input_size = count; - if (cs4231_chip->perchip_info.record.active || - (cs4231_chip->perchip_info.record.pause)) - return; + if (cs4231_chip->perchip_info.record.active || + (cs4231_chip->perchip_info.record.pause)) + return; - cs4231_ready(drv); + cs4231_ready(drv); - cs4231_chip->perchip_info.record.active = 1; - cs4231_chip->recording_count = 0; + cs4231_chip->perchip_info.record.active = 1; + cs4231_chip->recording_count = 0; - if ((cs4231_chip->regs->dmacsr & APC_CPAUSE) || - !(cs4231_chip->regs->dmacsr & APC_CDMA_READY)) { - cs4231_chip->regs->dmacsr &= ~APC_XINT_CAPT; - cs4231_chip->regs->dmacsr &= ~APC_CPAUSE; + csr = sbus_readl(cs4231_chip->regs + APCCSR); + if ((csr & APC_CPAUSE) || !(csr & APC_CDMA_READY)) { + csr &= ~APC_XINT_CAPT; + sbus_writel(csr, cs4231_chip->regs + APCCSR); + csr &= ~APC_CPAUSE; + sbus_writel(csr, cs4231_chip->regs + APCCSR); - cs4231_recintr(drv); + cs4231_recintr(drv); - cs4231_chip->regs->dmacsr |= APC_CAPT_SETUP; - cs4231_enable_rec(drv); + csr |= APC_CAPT_SETUP; + sbus_writel(csr, cs4231_chip->regs + APCCSR); - cs4231_ready(drv); - } else - cs4231_recintr(drv); + cs4231_enable_rec(drv); + cs4231_ready(drv); + } else { + cs4231_recintr(drv); + } } static void cs4231_stop_input(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 csr; + + cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->regs->dmacsr |= (APC_CPAUSE); + csr = sbus_readl(cs4231_chip->regs + APCCSR); + csr |= APC_CPAUSE; + sbus_writel(csr, cs4231_chip->regs + APCCSR); + + cs4231_chip->input_ptr = NULL; + cs4231_chip->input_size = 0; + + if (cs4231_chip->input_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->input_dma_handle, + cs4231_chip->input_dma_size); + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + } + + if (cs4231_chip->input_next_dma_handle) { + sbus_unmap_single(drv->dev, + cs4231_chip->input_next_dma_handle, + cs4231_chip->input_next_dma_size); + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + } - cs4231_chip->input_ptr = NULL; - cs4231_chip->input_size = 0; - if (cs4231_chip->input_dma_handle) { - mmu_release_scsi_one(cs4231_chip->input_dma_handle, - cs4231_chip->input_dma_size, drv->dev->my_bus); - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_dma_size = 0; - } - if (cs4231_chip->input_next_dma_handle) { - mmu_release_scsi_one(cs4231_chip->input_next_dma_handle, - cs4231_chip->input_next_dma_size, drv->dev->my_bus); - cs4231_chip->input_next_dma_handle = 0; - cs4231_chip->input_next_dma_size = 0; - } - cs4231_pollinput(drv); + cs4231_pollinput(drv); } #ifdef EB4231_SUPPORT static void eb4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int dcsr; - - cs4231_chip->input_ptr = buffer; - cs4231_chip->input_size = count; - - if (cs4231_chip->perchip_info.record.active || - (cs4231_chip->perchip_info.record.pause)) - return; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dcsr; - cs4231_ready(drv); + cs4231_chip->input_ptr = buffer; + cs4231_chip->input_size = count; - cs4231_chip->perchip_info.record.active = 1; - cs4231_chip->recording_count = 0; + if (cs4231_chip->perchip_info.record.active || + (cs4231_chip->perchip_info.record.pause)) + return; + + cs4231_ready(drv); + cs4231_chip->perchip_info.record.active = 1; + cs4231_chip->recording_count = 0; + + dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR); + if (!(dcsr & EBUS_DCSR_EN_DMA)) { + writel(EBUS_DCSR_RESET, cs4231_chip->eb2c + EBDMA_CSR); + writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2c + EBDMA_CSR); + + eb4231_recintr(drv); + + writel(EBUS_DCSR_BURST_SZ_16 | + (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | + EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), + cs4231_chip->eb2c + EBDMA_CSR); - dcsr = readl(&cs4231_chip->eb2c->dcsr); - if (!(dcsr & EBUS_DCSR_EN_DMA)) { - writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr)); - writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr)); - - eb4231_recintr(drv); - - writel(EBUS_DCSR_BURST_SZ_16 | - (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT), - &(cs4231_chip->eb2c->dcsr)); - - cs4231_enable_rec(drv); - cs4231_ready(drv); - } else - eb4231_recintr(drv); + cs4231_enable_rec(drv); + cs4231_ready(drv); + } else { + eb4231_recintr(drv); + } } static void eb4231_stop_input(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int dcsr; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dcsr; - cs4231_chip->perchip_info.record.active = 0; + cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->input_ptr = NULL; - cs4231_chip->input_size = 0; - if (cs4231_chip->input_dma_handle) { - cs4231_chip->input_dma_handle = 0; - cs4231_chip->input_dma_size = 0; - } - if (cs4231_chip->input_next_dma_handle) { - cs4231_chip->input_next_dma_handle = 0; - cs4231_chip->input_next_dma_size = 0; - } - - dcsr = readl(&(cs4231_chip->eb2c->dcsr)); - if (dcsr & EBUS_DCSR_EN_DMA) - writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2c->dcsr)); + cs4231_chip->input_ptr = NULL; + cs4231_chip->input_size = 0; - cs4231_disable_rec(drv); + if (cs4231_chip->input_dma_handle) { + cs4231_chip->input_dma_handle = 0; + cs4231_chip->input_dma_size = 0; + } + + if (cs4231_chip->input_next_dma_handle) { + cs4231_chip->input_next_dma_handle = 0; + cs4231_chip->input_next_dma_size = 0; + } + + dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR); + if (dcsr & EBUS_DCSR_EN_DMA) + writel(dcsr & ~EBUS_DCSR_EN_DMA, cs4231_chip->eb2c + EBDMA_CSR); + + cs4231_disable_rec(drv); } #endif static int cs4231_set_output_pause(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.play.pause = value; if (!value) - sparcaudio_output_done(drv, 0); + sparcaudio_output_done(drv, 0); return value; } static int cs4231_set_output_error(struct sparcaudio_driver *drv, int value) { - int i; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int i; - i = cs4231_chip->perchip_info.play.error; - cs4231_chip->perchip_info.play.error = value; + i = cs4231_chip->perchip_info.play.error; + cs4231_chip->perchip_info.play.error = value; - return i; + return i; } static int cs4231_set_input_error(struct sparcaudio_driver *drv, int value) { - int i; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int i; - i = cs4231_chip->perchip_info.record.error; - cs4231_chip->perchip_info.record.error = value; + i = cs4231_chip->perchip_info.record.error; + cs4231_chip->perchip_info.record.error = value; - return i; + return i; } static int cs4231_set_output_samples(struct sparcaudio_driver *drv, int value) { - int i; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + int i; - i = cs4231_chip->perchip_info.play.samples; - cs4231_chip->perchip_info.play.samples = value; + i = cs4231_chip->perchip_info.play.samples; + cs4231_chip->perchip_info.play.samples = value; - return i; + return i; } static int cs4231_set_input_samples(struct sparcaudio_driver *drv, int value) { - int i; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - - i = cs4231_chip->perchip_info.record.samples; - cs4231_chip->perchip_info.record.samples = value; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int i; - return i; + i = cs4231_chip->perchip_info.record.samples; + cs4231_chip->perchip_info.record.samples = value; + + return i; } static int cs4231_set_input_pause(struct sparcaudio_driver *drv, int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_chip->perchip_info.record.pause = value; if (value) - cs4231_stop_input(drv); + cs4231_stop_input(drv); return value; } @@ -1781,182 +1834,181 @@ static void cs4231_audio_getdev(struct sparcaudio_driver *drv, audio_device_t * audinfo) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1); - /* versions */ - /* a: SPARCstation 4/5 b: Ultra 1/2 (electron) */ - /* c: Ultra 1/2 PCI? (positron) d: ppc */ - /* e: x86 f: Ultra Enterprise? (tazmo) */ - /* g: Ultra 30? (quark) h: Ultra 5/10? (darwin) */ - /* apparently Ultra 1, Ultra 2 don't have internal CD input */ - if (cs4231_chip->status & CS_STATUS_IS_ULTRA) - strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1); - else - strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); - strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); + strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1); + /* versions */ + /* a: SPARCstation 4/5 b: Ultra 1/2 (electron) */ + /* c: Ultra 1/2 PCI? (positron) d: ppc */ + /* e: x86 f: Ultra Enterprise? (tazmo) */ + /* g: Ultra 30? (quark) h: Ultra 5/10? (darwin) */ + /* apparently Ultra 1, Ultra 2 don't have internal CD input */ + if (cs4231_chip->status & CS_STATUS_IS_ULTRA) + strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1); + else + strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); + strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); } static int cs4231_audio_getdev_sunos(struct sparcaudio_driver *drv) { - return AUDIO_DEV_CS4231; + return AUDIO_DEV_CS4231; } static void cs4231_loopback(struct sparcaudio_driver *drv, unsigned int value) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d); - CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (value ? LOOPB_ON : 0)); + WRITE_IAR(0x0d); + WRITE_IDR(value ? LOOPB_ON : 0); } static int cs4231_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg, struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int retval = 0; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + int retval = 0; - switch (cmd) { - case AUDIO_DIAG_LOOPBACK: - cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE; - cs4231_loopback(drv, (unsigned int)arg); - break; - default: - retval = -EINVAL; - } + switch (cmd) { + case AUDIO_DIAG_LOOPBACK: + cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE; + cs4231_loopback(drv, (unsigned int)arg); + break; + default: + retval = -EINVAL; + }; - return retval; + return retval; } #ifdef EB4231_SUPPORT /* ebus audio capture interrupt handler. */ void eb4231_cinterrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - int dummy; - - /* Clear the interrupt. */ - dummy = readl(&(cs4231_chip->eb2c->dcsr)); - writel(dummy, &(cs4231_chip->eb2c->dcsr)); - - if ((dummy & EBUS_DCSR_TC) != 0 - /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { - cs4231_chip->perchip_info.record.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), - cs4231_chip->reclen); - eb4231_recintr(drv); - } - - if ((dummy & EBUS_DCSR_A_LOADED) == 0) { - cs4231_chip->perchip_info.record.active = 0; - eb4231_recintr(drv); -#if 1 - eb4231_getsamplecount(drv, cs4231_chip->reclen, 1); -#endif - } + struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dummy; + + /* Clear the interrupt. */ + dummy = readl(cs4231_chip->eb2c + EBDMA_CSR); + writel(dummy, cs4231_chip->eb2c + EBDMA_CSR); + + if ((dummy & EBUS_DCSR_TC) != 0 + /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + eb4231_recintr(drv); + } + + if ((dummy & EBUS_DCSR_A_LOADED) == 0) { + cs4231_chip->perchip_info.record.active = 0; + eb4231_recintr(drv); + eb4231_getsamplecount(drv, cs4231_chip->reclen, 1); + } } /* ebus audio play interrupt handler. */ void eb4231_pinterrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - unsigned int dummy; - - /* Clear the interrupt. Bleh, when not using the next-address - * feature, TC can only be cleared by a reset. - */ - dummy = readl(&(cs4231_chip->eb2p->dcsr)); - writel(dummy, &(cs4231_chip->eb2p->dcsr)); - - /* If we get a terminal count and address loaded condition, - * this means the DNAR was copied into DACR. - */ - if((dummy & EBUS_DCSR_TC) != 0 - /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { - cs4231_chip->perchip_info.play.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), - cs4231_chip->playlen); - eb4231_playintr(drv); - } - - if((dummy & EBUS_DCSR_A_LOADED) == 0) { - cs4231_chip->perchip_info.play.active = 0; - eb4231_playintr(drv); - - eb4231_getsamplecount(drv, cs4231_chip->playlen, 0); - } + struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + u32 dummy; + + /* Clear the interrupt. Bleh, when not using the next-address + * feature, TC can only be cleared by a reset. + */ + dummy = readl(cs4231_chip->eb2p + EBDMA_CSR); + writel(dummy, cs4231_chip->eb2p + EBDMA_CSR); + + /* If we get a terminal count and address loaded condition, + * this means the DNAR was copied into DACR. + */ + if((dummy & EBUS_DCSR_TC) != 0 + /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) { + cs4231_chip->perchip_info.play.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), + cs4231_chip->playlen); + eb4231_playintr(drv); + } + + if((dummy & EBUS_DCSR_A_LOADED) == 0) { + cs4231_chip->perchip_info.play.active = 0; + eb4231_playintr(drv); + eb4231_getsamplecount(drv, cs4231_chip->playlen, 0); + } } #endif /* Audio interrupt handler. */ void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id; - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; - __u32 dummy; - - dprintk(("in cs4231_interrupt\n")); - - /* Clear the interrupt. */ - dummy = cs4231_chip->regs->dmacsr; - cs4231_chip->regs->dmacsr = dummy; - - /* now go through and figure out what gets to claim the interrupt - * if anything since we may be doing shared interrupts - */ - - if (dummy & APC_PLAY_INT) { - if (dummy & APC_XINT_PNVA) { - cs4231_chip->perchip_info.play.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), - cs4231_chip->playlen); - if (!(dummy & APC_XINT_EMPT)) - cs4231_playintr(drv, 1); - } - /* Any other conditions we need worry about? */ - } - - if (dummy & APC_CAPT_INT) { - if (dummy & APC_XINT_CNVA) { - cs4231_chip->perchip_info.record.samples += - cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), - cs4231_chip->reclen); - cs4231_recintr(drv); - } - /* Any other conditions we need worry about? */ - } - - - if (dummy & APC_XINT_CEMP) { - if (cs4231_chip->perchip_info.record.active == 0) { - /* Fix me */ - cs4231_chip->perchip_info.record.active = 0; - cs4231_chip->perchip_info.record.error = 1; - cs4231_recintr(drv); - } - } - - if (dummy & APC_XINT_EMPT) { - if (!cs4231_chip->output_next_dma_handle) { - cs4231_chip->regs->dmacsr |= (APC_PPAUSE); - cs4231_disable_play(drv); - cs4231_chip->perchip_info.play.error = 1; - } - cs4231_chip->perchip_info.play.active = 0; - cs4231_playintr(drv, 0); - - cs4231_getsamplecount(drv, cs4231_chip->playlen, 0); - } - - if (dummy & APC_GENL_INT) { - /* If we get here we must be sharing an interrupt, but I haven't code - to handle this right now */ - } - + struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; + __u32 dummy; + + dprintk(("in cs4231_interrupt\n")); + + /* Clear the interrupt. */ + dummy = sbus_readl(cs4231_chip->regs + APCCSR); + sbus_writel(dummy, cs4231_chip->regs + APCCSR); + + /* now go through and figure out what gets to claim the interrupt + * if anything since we may be doing shared interrupts + */ + if (dummy & APC_PLAY_INT) { + if (dummy & APC_XINT_PNVA) { + cs4231_chip->perchip_info.play.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), + cs4231_chip->playlen); + if (!(dummy & APC_XINT_EMPT)) + cs4231_playintr(drv, 1); + } + /* Any other conditions we need worry about? */ + } + + if (dummy & APC_CAPT_INT) { + if (dummy & APC_XINT_CNVA) { + cs4231_chip->perchip_info.record.samples += + cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), + cs4231_chip->reclen); + cs4231_recintr(drv); + } + /* Any other conditions we need worry about? */ + } + + + if (dummy & APC_XINT_CEMP) { + if (cs4231_chip->perchip_info.record.active == 0) { + /* Fix me */ + cs4231_chip->perchip_info.record.active = 0; + cs4231_chip->perchip_info.record.error = 1; + cs4231_recintr(drv); + } + } + + if (dummy & APC_XINT_EMPT) { + if (!cs4231_chip->output_next_dma_handle) { + u32 csr = sbus_readl(cs4231_chip->regs + APCCSR); + + csr |= APC_PPAUSE; + sbus_writel(csr, cs4231_chip->regs + APCCSR); + cs4231_disable_play(drv); + cs4231_chip->perchip_info.play.error = 1; + } + cs4231_chip->perchip_info.play.active = 0; + cs4231_playintr(drv, 0); + + cs4231_getsamplecount(drv, cs4231_chip->playlen, 0); + } + + if (dummy & APC_GENL_INT) { + /* If we get here we must be sharing an interrupt, but I haven't code + * to handle this right now. + */ + } } static struct sparcaudio_operations cs4231_ops = { @@ -2081,118 +2133,86 @@ /* Attach to an cs4231 chip given its PROM node. */ static int cs4231_attach(struct sparcaudio_driver *drv, - struct linux_sbus_device *sdev) + struct sbus_dev *sdev) { #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - struct linux_prom_irqs irq; -#endif - struct linux_sbus *sbus = sdev->my_bus; - struct cs4231_chip *cs4231_chip; - int err; - - /* Allocate our private information structure. */ - drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL); - if (!drv->private) - return -ENOMEM; - - /* Point at the information structure and initialize it. */ - drv->ops = &cs4231_ops; - cs4231_chip = (struct cs4231_chip *)drv->private; - cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL; - cs4231_chip->input_size = cs4231_chip->output_size = 0; - cs4231_chip->status = 0; - - drv->dev = sdev; - - /* Map the registers into memory. */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - prom_apply_sbus_ranges(sbus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); -#else - prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev); -#endif - - cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size; - - cs4231_chip->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, - "cs4231", sdev->reg_addrs[0].which_io, - 0); - - if (!cs4231_chip->regs) { - printk(KERN_ERR "cs4231: could not allocate registers\n"); - kfree(drv->private); - return -EIO; - } - - /* Attach the interrupt handler to the audio interrupt. */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - prom_getproperty(sdev->prom_node, "intr", (char *)&irq, sizeof(irq)); - - if (irq.pri < 0) { - sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size); - kfree(drv->private); - return -EIO; - } - - cs4231_chip->irq = irq.pri; - -#else - cs4231_chip->irq = sdev->irqs[0]; + struct linux_prom_irqs irq; #endif + struct cs4231_chip *cs4231_chip; + int err; - request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv); - - enable_irq(cs4231_chip->irq); - - cs4231_chip->nirqs = 1; - - cs4231_enable_interrupts(drv); - - /* Reset the audio chip. */ - cs4231_chip_reset(drv); - - /* Register ourselves with the midlevel audio driver. */ - err = register_sparcaudio_driver(drv, 1); - - if (err < 0) { - printk(KERN_ERR "cs4231: unable to register\n"); - cs4231_disable_interrupts(drv); - disable_irq(cs4231_chip->irq); - free_irq(cs4231_chip->irq, drv); - sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size); - kfree(drv->private); - return -EIO; - } - - cs4231_chip->perchip_info.play.active = - cs4231_chip->perchip_info.play.pause = 0; - - cs4231_chip->perchip_info.record.active = - cs4231_chip->perchip_info.record.pause = 0; - - cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | - AUDIO_SPEAKER | - AUDIO_LINE_OUT); - - cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN | - AUDIO_LINE_IN | - AUDIO_MICROPHONE | - AUDIO_ANALOG_LOOPBACK); - - /* Announce the hardware to the user. */ -#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100 - printk(KERN_INFO "audio%d: cs4231%c at 0x%x irq %d\n", - drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', - (unsigned long)cs4231_chip->regs, cs4231_chip->irq); -#else - printk(KERN_INFO "audio%d: cs4231%c at %p irq %s\n", - drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', - cs4231_chip->regs, __irq_itoa(cs4231_chip->irq)); -#endif + /* Allocate our private information structure. */ + drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL); + if (drv->private == NULL) + return -ENOMEM; + + /* Point at the information structure and initialize it. */ + drv->ops = &cs4231_ops; + cs4231_chip = (struct cs4231_chip *) drv->private; + cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL; + cs4231_chip->input_size = cs4231_chip->output_size = 0; + cs4231_chip->status = 0; + + drv->dev = sdev; + + /* Map the registers into memory. */ + cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size; + cs4231_chip->regs = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "cs4231"); + + if (!cs4231_chip->regs) { + printk(KERN_ERR "cs4231: could not remap registers\n"); + kfree(drv->private); + return -EIO; + } + + /* Attach the interrupt handler to the audio interrupt. */ + cs4231_chip->irq = sdev->irqs[0]; + request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv); + enable_irq(cs4231_chip->irq); + + cs4231_chip->nirqs = 1; + cs4231_enable_interrupts(drv); + + /* Reset the audio chip. */ + cs4231_chip_reset(drv); + + /* Register ourselves with the midlevel audio driver. */ + err = register_sparcaudio_driver(drv, 1); + + if (err < 0) { + printk(KERN_ERR "cs4231: unable to register\n"); + cs4231_disable_interrupts(drv); + disable_irq(cs4231_chip->irq); + free_irq(cs4231_chip->irq, drv); + sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size); + kfree(drv->private); + return -EIO; + } + + cs4231_chip->perchip_info.play.active = + cs4231_chip->perchip_info.play.pause = 0; + + cs4231_chip->perchip_info.record.active = + cs4231_chip->perchip_info.record.pause = 0; + + cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | + AUDIO_SPEAKER | + AUDIO_LINE_OUT); + + cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN | + AUDIO_LINE_IN | + AUDIO_MICROPHONE | + AUDIO_ANALOG_LOOPBACK); + + /* Announce the hardware to the user. */ + printk(KERN_INFO "audio%d: cs4231%c at %lx irq %s\n", + drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', + cs4231_chip->regs, __irq_itoa(cs4231_chip->irq)); - /* Success! */ - return 0; + /* Success! */ + return 0; } #ifdef EB4231_SUPPORT @@ -2200,89 +2220,86 @@ static int eb4231_attach(struct sparcaudio_driver *drv, struct linux_ebus_device *edev) { - struct cs4231_chip *cs4231_chip; - int len, err, nregs; - struct linux_prom_registers regs[4]; - - /* Allocate our private information structure. */ - drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL); - if (!drv->private) - return -ENOMEM; - - /* Point at the information structure and initialize it. */ - drv->ops = &eb4231_ops; - cs4231_chip = (struct cs4231_chip *)drv->private; - cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL; - cs4231_chip->input_size = cs4231_chip->output_size = 0; - cs4231_chip->status = 0; - - len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs)); - - if ((len % sizeof(regs[0])) != 0) { - printk("eb4231: Strange reg property size %d\n", len); - return -ENODEV; - } - - nregs = len / sizeof(regs[0]); - - cs4231_chip->regs = (struct cs4231_regs *)edev->resource[0].start; - cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->resource[1].start; - cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->resource[2].start; - - cs4231_chip->status |= CS_STATUS_IS_EBUS; - - /* Attach the interrupt handler to the audio interrupt. */ - cs4231_chip->irq = edev->irqs[0]; - cs4231_chip->irq2 = edev->irqs[1]; - - if(request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv) || - request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv)) - goto bail; - - cs4231_chip->nirqs = 2; - - cs4231_enable_interrupts(drv); - - /* Reset the audio chip. */ - cs4231_chip_reset(drv); - - /* Register ourselves with the midlevel audio driver. */ - err = register_sparcaudio_driver(drv, 1); - - if (err < 0) { - bail: - printk(KERN_ERR "cs4231: unable to register\n"); - cs4231_disable_interrupts(drv); - disable_irq(cs4231_chip->irq); - free_irq(cs4231_chip->irq, drv); - disable_irq(cs4231_chip->irq2); - free_irq(cs4231_chip->irq2, drv); - kfree(drv->private); - return -EIO; - } - - cs4231_chip->perchip_info.play.active = - cs4231_chip->perchip_info.play.pause = 0; - - cs4231_chip->perchip_info.record.active = - cs4231_chip->perchip_info.record.pause = 0; - - cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | - AUDIO_SPEAKER | - AUDIO_LINE_OUT); - - cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN | - AUDIO_LINE_IN | - AUDIO_MICROPHONE | - AUDIO_ANALOG_LOOPBACK); - - /* Announce the hardware to the user. */ - printk(KERN_INFO "audio%d: cs4231%c(eb2) at %p irq %s\n", - drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', - cs4231_chip->regs, __irq_itoa(cs4231_chip->irq)); + struct cs4231_chip *cs4231_chip; + int len, err, nregs; + struct linux_prom_registers regs[4]; + + /* Allocate our private information structure. */ + drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL); + if (drv->private == NULL) + return -ENOMEM; + + /* Point at the information structure and initialize it. */ + drv->ops = &eb4231_ops; + cs4231_chip = (struct cs4231_chip *) drv->private; + cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL; + cs4231_chip->input_size = cs4231_chip->output_size = 0; + cs4231_chip->status = 0; + + len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs)); + if ((len % sizeof(regs[0])) != 0) { + printk("eb4231: Strange reg property size %d\n", len); + return -ENODEV; + } + + nregs = len / sizeof(regs[0]); + cs4231_chip->regs = (unsigned long)ioremap(edev->resource[0].start, 0x10); + cs4231_chip->eb2p = (unsigned long)ioremap(edev->resource[1].start, 0x10); + cs4231_chip->eb2c = (unsigned long)ioremap(edev->resource[2].start, 0x10); + + cs4231_chip->status |= CS_STATUS_IS_EBUS; + + /* Attach the interrupt handler to the audio interrupt. */ + cs4231_chip->irq = edev->irqs[0]; + cs4231_chip->irq2 = edev->irqs[1]; + + if(request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv) || + request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv)) + goto bail; + + cs4231_chip->nirqs = 2; + cs4231_enable_interrupts(drv); + + /* Reset the audio chip. */ + cs4231_chip_reset(drv); + + /* Register ourselves with the midlevel audio driver. */ + err = register_sparcaudio_driver(drv, 1); + + if (err < 0) { + bail: + printk(KERN_ERR "cs4231: unable to register\n"); + cs4231_disable_interrupts(drv); + disable_irq(cs4231_chip->irq); + free_irq(cs4231_chip->irq, drv); + disable_irq(cs4231_chip->irq2); + free_irq(cs4231_chip->irq2, drv); + kfree(drv->private); + return -EIO; + } + + cs4231_chip->perchip_info.play.active = + cs4231_chip->perchip_info.play.pause = 0; + + cs4231_chip->perchip_info.record.active = + cs4231_chip->perchip_info.record.pause = 0; + + cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | + AUDIO_SPEAKER | + AUDIO_LINE_OUT); + + cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN | + AUDIO_LINE_IN | + AUDIO_MICROPHONE | + AUDIO_ANALOG_LOOPBACK); + + /* Announce the hardware to the user. */ + printk(KERN_INFO "audio%d: cs4231%c(eb2) at %lx irq %s\n", + drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', + cs4231_chip->regs, __irq_itoa(cs4231_chip->irq)); - /* Success! */ - return 0; + /* Success! */ + return 0; } #endif @@ -2293,62 +2310,65 @@ int __init cs4231_init(void) #endif { - struct linux_sbus *sbus; - struct linux_sbus_device *sdev; + struct sbus_bus *sbus; + struct sbus_dev *sdev; #ifdef EB4231_SUPPORT - struct linux_ebus *ebus; - struct linux_ebus_device *edev; + struct linux_ebus *ebus; + struct linux_ebus_device *edev; #endif - num_drivers = 0; + num_drivers = 0; - /* Probe each SBUS for cs4231 chips. */ - for_all_sbusdev(sdev,sbus) { - if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { - /* Don't go over the max number of drivers. */ - if (num_drivers >= MAX_DRIVERS) - continue; + /* Probe each SBUS for cs4231 chips. */ + for_all_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { + /* Don't go over the max number of drivers. */ + if (num_drivers >= MAX_DRIVERS) + continue; - if (cs4231_attach(&drivers[num_drivers], sdev) == 0) - num_drivers++; - } - } + if (cs4231_attach(&drivers[num_drivers], sdev) == 0) + num_drivers++; + } + } #ifdef EB4231_SUPPORT - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "SUNW,CS4231")) { - /* Don't go over the max number of drivers. */ - if (num_drivers >= MAX_DRIVERS) - continue; + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "SUNW,CS4231")) { + /* Don't go over the max number of drivers. */ + if (num_drivers >= MAX_DRIVERS) + continue; - if (eb4231_attach(&drivers[num_drivers], edev) == 0) - num_drivers++; - } - } - } + if (eb4231_attach(&drivers[num_drivers], edev) == 0) + num_drivers++; + } + } + } #endif - /* Only return success if we found some cs4231 chips. */ - return (num_drivers > 0) ? 0 : -EIO; + /* Only return success if we found some cs4231 chips. */ + return (num_drivers > 0) ? 0 : -EIO; } #ifdef MODULE /* Detach from an cs4231 chip given the device structure. */ static void cs4231_detach(struct sparcaudio_driver *drv) { - struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; + struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; cs4231_disable_interrupts(drv); unregister_sparcaudio_driver(drv, 1); disable_irq(cs4231_chip->irq); free_irq(cs4231_chip->irq, drv); if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) { - sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size); + sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size); } else { #ifdef EB4231_SUPPORT - disable_irq(cs4231_chip->irq2); - free_irq(cs4231_chip->irq2, drv); + iounmap(cs4231_chip->regs); + iounmap(cs4231_chip->eb2p); + iounmap(cs4231_chip->eb2c); + disable_irq(cs4231_chip->irq2); + free_irq(cs4231_chip->irq2, drv); #endif } kfree(drv->private); diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h --- v2.3.34/linux/drivers/sbus/audio/cs4231.h Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/cs4231.h Mon Dec 20 22:06:42 1999 @@ -1,8 +1,9 @@ -/* +/* $Id: cs4231.h,v 1.13 1999/09/21 14:37:27 davem Exp $ * drivers/sbus/audio/cs4231.h * * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu) * Copyright (C) 1997 Derrick J. Brashear (shadow@dementia.org) + * Copyright (C) 1999 David S. Miller (davem@redhat.com) */ #ifndef _CS4231_H_ @@ -11,78 +12,78 @@ #include /* According to the CS4231A data provided on CS web site and sun's includes */ - -struct cs4231_regs { - __volatile__ __u8 iar; /* Index Address Register */ - __volatile__ __u8 pad0[3]; - __volatile__ __u8 idr; /* Indexed Data Register */ - __volatile__ __u8 pad1[3]; - __volatile__ __u8 statr; /* Status Register */ - __volatile__ __u8 pad2[3]; - __volatile__ __u8 piodr; /* PIO Data Register */ - __volatile__ __u8 pad3[3]; - __volatile__ __u32 dmacsr; /* APC CSR */ - __volatile__ __u32 dmapad[3]; - __volatile__ __u32 dmacva; /* Capture Virtual Address */ - __volatile__ __u32 dmacc; /* Capture Count */ - __volatile__ __u32 dmacnva; /* Capture Next Virtual Address */ - __volatile__ __u32 dmacnc; /* Capture Next Count */ - __volatile__ __u32 dmapva; /* Playback Virtual Address */ - __volatile__ __u32 dmapc; /* Playback Count */ - __volatile__ __u32 dmapnva; /* Playback Next Virtual Address */ - __volatile__ __u32 dmapnc; /* Playback Next Count */ -}; +#define IAR 0x00UL /* Index Address Register */ +#define IDR 0x04UL /* Index Data Register */ +#define STAT 0x08UL /* Status Register */ +#define PIOD 0x0cUL /* PIO Data Register */ +#define APCCSR 0x10UL /* APC DMA CSR */ +#define APCCVA 0x20UL /* APC Capture DMA Address */ +#define APCCC 0x24UL /* APC Capture Count */ +#define APCCNVA 0x28UL /* APC Capture DMA Next Address */ +#define APCCNC 0x2cUL /* APC Capture Next Count */ +#define APCPVA 0x30UL /* APC Play DMA Address */ +#define APCPC 0x34UL /* APC Play Count */ +#define APCPNVA 0x38UL /* APC Play DMA Next Address */ +#define APCPNC 0x3cUL /* APC Play Next Count */ + +/* EBUS DMA Registers */ +#define EBDMA_CSR 0x00UL /* Control/Status */ +#define EBDMA_ADDR 0x04UL /* DMA Address */ +#define EBDMA_COUNT 0x08UL /* DMA Count */ /* Our structure for each chip */ - struct cs4231_chip { - struct cs4231_regs *regs; - struct linux_ebus_dma *eb2c; - struct linux_ebus_dma *eb2p; - struct audio_info perchip_info; - unsigned int playlen, reclen; - int irq, irq2, nirqs; - unsigned long regs_size; + unsigned long regs; + unsigned long eb2c; + unsigned long eb2p; + struct audio_info perchip_info; + unsigned int playlen, reclen; + int irq, irq2, nirqs; + unsigned long regs_size; - /* Keep track of various info */ - volatile unsigned int status; + /* Keep track of various info */ + volatile unsigned int status; - /* Current buffer that the driver is playing. */ - volatile __u8 * output_ptr; - volatile unsigned long output_size; - volatile __u32 output_dma_handle, output_next_dma_handle; - volatile unsigned long output_dma_size, output_next_dma_size; - - /* Current record buffer. */ - volatile __u8 * input_ptr; - volatile unsigned long input_size; - volatile __u32 input_dma_handle, input_next_dma_handle; - volatile unsigned long input_dma_size, input_next_dma_size; - - /* Number of buffers in the pipe. */ - volatile unsigned long playing_count; - volatile unsigned long recording_count; + /* Current buffer that the driver is playing. */ + volatile __u8 * output_ptr; + volatile __u32 output_size; + volatile __u32 output_dma_handle, output_next_dma_handle; + volatile __u32 output_dma_size, output_next_dma_size; + + /* Current record buffer. */ + volatile __u8 * input_ptr; + volatile __u32 input_size; + volatile __u32 input_dma_handle, input_next_dma_handle; + volatile __u32 input_dma_size, input_next_dma_size; + + /* Number of buffers in the pipe. */ + volatile __u32 playing_count; + volatile __u32 recording_count; }; #ifdef EB4231_SUPPORT -#define CS4231_READ32(__C, __REG) \ - (((__C)->status & CS_STATUS_IS_EBUS) ? readl((unsigned long)(__REG)) : (*(__REG))) +#define CS4231_READ32(__C, __REG) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + readl((__REG)) : \ + sbus_readl((__REG))) #define CS4231_READ8(__C, __REG) \ - (((__C)->status & CS_STATUS_IS_EBUS) ? readb((unsigned long)(__REG)) : (*(__REG))) -#define CS4231_WRITE32(__C, __REG, __VAL) \ - (((__C)->status & CS_STATUS_IS_EBUS) ? \ - writel((__VAL), (unsigned long)(__REG)) : \ - (*(__REG) = (__VAL))) -#define CS4231_WRITE8(__C, __REG, __VAL) \ - (((__C)->status & CS_STATUS_IS_EBUS) ? \ - writeb((__VAL), (unsigned long)(__REG)) : \ - (*(__REG) = (__VAL))) + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + readb((__REG)) : \ + sbus_readb((__REG))) +#define CS4231_WRITE32(__C, __REG, __VAL) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + writel((__VAL), (__REG)) : \ + sbus_writel((__VAL), (__REG))) +#define CS4231_WRITE8(__C, __REG, __VAL) \ + (((__C)->status & CS_STATUS_IS_EBUS) ? \ + writeb((__VAL), (__REG)) : \ + sbus_writeb((__VAL), (__REG))) #else /* We can assume all is SBUS in this case. */ -#define CS4231_READ32(__C, __REG) (*(__REG)) -#define CS4231_READ8(__C, __REG) (*(__REG)) -#define CS4231_WRITE32(__C, __REG, __VAL) (*(__REG) = (__VAL)) -#define CS4231_WRITE8(__C, __REG, __VAL) (*(__REG) = (__VAL)) +#define CS4231_READ32(__C, __REG) sbus_readl((__REG)) +#define CS4231_READ8(__C, __REG) sbus_readb((__REG)) +#define CS4231_WRITE32(__C, __REG, __VAL) sbus_writel((__VAL), (__REG)) +#define CS4231_WRITE8(__C, __REG, __VAL) sbus_writeb((__VAL), (__REG)) #endif /* Local status bits */ @@ -270,18 +271,26 @@ #define APC_CDMA_READY 0x04 /* Capture DMA Go */ #define APC_CHIP_RESET 0x01 /* Reset the chip */ -#define APC_INIT_SETUP (APC_CDMA_READY | APC_PDMA_READY | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_GENL | APC_INT_PENDING | APC_PLAY_INT | APC_CAPT_INT | APC_GENL_INT) - -#define APC_PLAY_SETUP (APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | APC_XINT_PENA | APC_PDMA_READY) - -#define APC_CAPT_SETUP (APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | APC_CDMA_READY) +#define APC_INIT_SETUP (APC_CDMA_READY | APC_PDMA_READY | APC_XINT_ENA | \ + APC_XINT_PLAY | APC_XINT_GENL | APC_INT_PENDING | \ + APC_PLAY_INT | APC_CAPT_INT | APC_GENL_INT) + +#define APC_PLAY_SETUP (APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | \ + APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | \ + APC_XINT_PENA | APC_PDMA_READY) + +#define APC_CAPT_SETUP (APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | \ + APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | \ + APC_CDMA_READY) /* Following are EB2 CSR register definitions for the Sparc */ /* asm/ebus.h has the base settings */ -#define EB2_PLAY_SETUP (EBUS_DCSR_BURST_SZ_8|EBUS_DCSR_INT_EN|EBUS_DCSR_EN_DMA|EBUS_DCSR_EN_CNT|EBUS_DCSR_TC) -#define EB2_CAPT_SETUP (EBUS_DCSR_BURST_SZ_8|EBUS_DCSR_INT_EN|EBUS_DCSR_EN_DMA|EBUS_DCSR_EN_CNT|EBUS_DCSR_TC|EBUS_DCSR_WRITE) +#define EB2_PLAY_SETUP (EBUS_DCSR_BURST_SZ_8 | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_DMA | \ + EBUS_DCSR_EN_CNT | EBUS_DCSR_TC) +#define EB2_CAPT_SETUP (EBUS_DCSR_BURST_SZ_8 | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_DMA| \ + EBUS_DCSR_EN_CNT | EBUS_DCSR_TC | EBUS_DCSR_WRITE) #define CS4231_MIN_ATEN (0) #define CS4231_MAX_ATEN (31) @@ -301,4 +310,4 @@ #define CS4231_RATE (8000) /* default sample rate */ -#endif +#endif /* _CS4231_H_ */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c --- v2.3.34/linux/drivers/sbus/audio/dbri.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/dbri.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: dbri.c,v 1.16 1999/11/19 09:56:05 davem Exp $ * drivers/sbus/audio/dbri.c * * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) @@ -42,8 +42,6 @@ * connected. */ - - #include #include #include @@ -151,42 +149,44 @@ static int dbri_locked = 0; -static volatile int * dbri_cmdlock(struct dbri *dbri) +static volatile s32 *dbri_cmdlock(struct dbri *dbri) { - if (dbri_locked) { + if (dbri_locked) printk("DBRI: Command buffer locked! (bug in driver)\n"); - } - dbri_locked ++; - return dbri->dma->cmd; + + dbri_locked++; + return &dbri->dma->cmd[0]; } static void dbri_process_interrupt_buffer(struct dbri *); -static void dbri_cmdsend(struct dbri *dbri, volatile int * cmd) +static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd) { int MAXLOOPS = 1000000; int maxloops = MAXLOOPS; - unsigned int flags; - volatile int * ptr; + unsigned long flags; + volatile s32 *ptr; - for (ptr = dbri->dma->cmd; ptr < cmd; ptr ++) { - dprintk(D_CMD, ("DBRI cmd: %08x:%08x\n", - (unsigned int) ptr, *ptr)); + for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) { + dprintk(D_CMD, ("DBRI cmd: %lx:%08x\n", + (unsigned long) ptr, *ptr)); } save_and_cli(flags); - dbri_locked --; + dbri_locked--; if (dbri_locked != 0) { printk("DBRI: Command buffer improperly locked! (bug in driver)\n"); - } else if ((cmd - dbri->dma->cmd) >= DBRI_NO_CMDS-1) { + } else if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS-1) { printk("DBRI: Command buffer overflow! (bug in driver)\n"); } else { *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); dbri->wait_seen = 0; - dbri->regs->reg8 = (int)dbri->dma_dvma->cmd; - while ((--maxloops) > 0 && (dbri->regs->reg0 & D_P)); + sbus_writel(dbri->dma_dvma, dbri->regs + REG8); + while ((--maxloops) > 0 && + (sbus_readl(dbri->regs + REG0) & D_P)) + barrier(); if (maxloops == 0) { printk("DBRI: Chip never completed command buffer\n"); } else { @@ -195,7 +195,8 @@ if (maxloops == 0) { printk("DBRI: Chip never acked WAIT\n"); } else { - dprintk(D_INT, ("DBRI: Chip completed command buffer (%d)\n", + dprintk(D_INT, ("DBRI: Chip completed command " + "buffer (%d)\n", MAXLOOPS - maxloops)); } } @@ -209,11 +210,13 @@ int i; dprintk(D_GEN, ("DBRI: reset 0:%x 2:%x 8:%x 9:%x\n", - dbri->regs->reg0, dbri->regs->reg2, - dbri->regs->reg8, dbri->regs->reg9)); + sbus_readl(dbri->regs + REG0), + sbus_readl(dbri->regs + REG2), + sbus_readl(dbri->regs + REG8), + sbus_readl(dbri->regs + REG9))); - dbri->regs->reg0 = D_R; /* Soft Reset */ - for(i = 0; (dbri->regs->reg0 & D_R) && i < 10; i++) + sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */ + for(i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++) udelay(10); } @@ -221,42 +224,48 @@ { dbri_reset(dbri); free_irq(dbri->irq, dbri); - sparc_free_io(dbri->regs, dbri->regs_size); - release_region((unsigned long) dbri->dma, sizeof(struct dbri_dma)); + sbus_iounmap(dbri->regs, dbri->regs_size); + sbus_free_consistant(dbri->sdev, sizeof(struct dbri_dma), + dbri->dma, dbry->dma_dvma); kfree(dbri); } - static void dbri_initialize(struct dbri *dbri) { + volatile s32 *cmd; + u32 dma_addr, tmp; int n; - volatile int *cmd; dbri_reset(dbri); - dprintk(D_GEN, ("DBRI: init: cmd: %x, int: %x\n", - (int)dbri->dma->cmd, (int)dbri->dma->intr)); + dprintk(D_GEN, ("DBRI: init: cmd: %p, int: %p\n", + &dbri->dma->cmd[0], &dbri->dma->intr[0])); /* * Initialize the interrupt ringbuffer. */ - for(n = 0; n < DBRI_NO_INTS-1; n++) - dbri->dma->intr[n * DBRI_INT_BLK] = - (int)(&dbri->dma_dvma->intr[(n+1)*DBRI_INT_BLK]); - dbri->dma->intr[n * DBRI_INT_BLK] = (int)(dbri->dma_dvma->intr); + for(n = 0; n < DBRI_NO_INTS-1; n++) { + dma_addr = dbri->dma_dvma; + dma_addr += dbri_dma_off(intr, ((n+1) & DBRI_INT_BLK)); + dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; + } + dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); + dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; dbri->dbri_irqp = 1; /* We should query the openprom to see what burst sizes this * SBus supports. For now, just disable all SBus bursts */ - dbri->regs->reg0 &= ~(D_G|D_S|D_E); + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~(D_G | D_S | D_E); + sbus_writel(tmp, dbri->regs + REG0); /* * Set up the interrupt queue */ cmd = dbri_cmdlock(dbri); - + dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); - *(cmd++) = (int)(dbri->dma_dvma->intr); + *(cmd++) = dma_addr; dbri_cmdsend(dbri, cmd); } @@ -302,7 +311,8 @@ break; default: printk("DBRI reverse_bytes: unsupported length\n"); - } + }; + return b; } @@ -329,7 +339,6 @@ td = dbri->pipes[pipe].desc; while (td >= 0) { - if (td >= DBRI_NO_DESCS) { printk("DBRI: invalid td on pipe %d\n", pipe); return; @@ -344,11 +353,10 @@ dprintk(D_INT, ("DBRI: TD %d, status 0x%02x\n", td, status)); buffer = dbri->descs[td].buffer; - if (buffer) { - mmu_release_scsi_one(sbus_dvma_addr(buffer), - dbri->descs[td].len, - dbri->sdev->my_bus); - } + if (buffer) + sbus_unmap_single(dbri->sdev, + dbri->descs[td].buffer_dvma, + dbri->descs[td].len); callback = dbri->descs[td].output_callback; callback_arg = dbri->descs[td].output_callback_arg; @@ -358,16 +366,15 @@ td = dbri->descs[td].next; dbri->pipes[pipe].desc = td; - if (callback != NULL) { + if (callback != NULL) callback(callback_arg, status & 0xe); - } } } static void reception_complete_intr(struct dbri *dbri, int pipe) { int rd = dbri->pipes[pipe].desc; - int status; + s32 status; void *buffer; void (*callback)(void *, int, unsigned int); @@ -381,18 +388,16 @@ status = dbri->dma->desc[rd].word1; buffer = dbri->descs[rd].buffer; - if (buffer) { - mmu_release_scsi_one(sbus_dvma_addr(buffer), - dbri->descs[rd].len, - dbri->sdev->my_bus); - } + if (buffer) + sbus_unmap_single(dbri->sdev, + dbri->descs[rd].buffer_dvma, + dbri->descs[rd].len); callback = dbri->descs[rd].input_callback; - if (callback != NULL) { + if (callback != NULL) callback(dbri->descs[rd].input_callback_arg, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)-2); - } dprintk(D_INT, ("DBRI: Recv RD %d, status 0x%02x, len %d\n", rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status))); @@ -414,35 +419,29 @@ channel, code, rval)); } - if (channel == D_INTR_CMD && command == D_WAIT) { - dbri->wait_seen ++; - } + if (channel == D_INTR_CMD && command == D_WAIT) + dbri->wait_seen++; if (code == D_INTR_SBRI) { - /* SBRI - BRI status change */ + const int liu_states[] = {1, 0, 8, 3, 4, 5, 6, 7}; - int liu_states[] = {1, 0, 8, 3, 4, 5, 6, 7}; dbri->liu_state = liu_states[val & 0x7]; if (dbri->liu_callback) dbri->liu_callback(dbri->liu_callback_arg); } - if (code == D_INTR_BRDY) { + if (code == D_INTR_BRDY) reception_complete_intr(dbri, channel); - } - if (code == D_INTR_XCMP) { + if (code == D_INTR_XCMP) transmission_complete_intr(dbri, channel); - } if (code == D_INTR_UNDR) { - /* UNDR - Transmission underrun * resend SDP command with clear pipe bit (C) set */ - - volatile int *cmd; + volatile s32 *cmd; int pipe = channel; int td = dbri->pipes[pipe].desc; @@ -452,21 +451,17 @@ *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C | D_SDP_2SAME); - *(cmd++) = (int) & dbri->dma_dvma->desc[td]; + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); dbri_cmdsend(dbri, cmd); } if (code == D_INTR_FXDT) { - /* FXDT - Fixed data change */ - - if (dbri->pipes[channel].sdp & D_SDP_MSB) { + if (dbri->pipes[channel].sdp & D_SDP_MSB) val = reverse_bytes(val, dbri->pipes[channel].length); - } - if (dbri->pipes[channel].recv_fixed_ptr) { - * dbri->pipes[channel].recv_fixed_ptr = val; - } + if (dbri->pipes[channel].recv_fixed_ptr) + *(dbri->pipes[channel].recv_fixed_ptr) = val; } } @@ -477,15 +472,12 @@ * order is important since we might recurse back into this function * and need to make sure the pointer has been advanced first. */ - static void dbri_process_interrupt_buffer(struct dbri *dbri) { - int x; + s32 x; while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) { - dbri->dma->intr[dbri->dbri_irqp] = 0; - dbri->dbri_irqp++; if (dbri->dbri_irqp == (DBRI_NO_INTS * DBRI_INT_BLK)) dbri->dbri_irqp = 1; @@ -498,17 +490,18 @@ static void dbri_intr(int irq, void *opaque, struct pt_regs *regs) { - struct dbri *dbri = (struct dbri *)opaque; + struct dbri *dbri = (struct dbri *) opaque; int x; /* * Read it, so the interrupt goes away. */ - x = dbri->regs->reg1; + x = sbus_readl(dbri->regs + REG1); dprintk(D_INT, ("DBRI: Interrupt! (reg1=0x%08x)\n", x)); - if ( x & (D_MRR|D_MLE|D_LBG|D_MBE) ) { + if (x & (D_MRR|D_MLE|D_LBG|D_MBE)) { + u32 tmp; if(x & D_MRR) printk("DBRI: Multiple Error Ack on SBus\n"); if(x & D_MLE) printk("DBRI: Multiple Late Error on SBus\n"); @@ -524,8 +517,9 @@ * If these things persist, we should probably reset * and re-init the chip. */ - - dbri->regs->reg0 &= ~D_D; + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~(D_D); + sbus_writel(tmp, dbri->regs + REG0); } #if 0 @@ -551,7 +545,6 @@ here interface closely with the transmit and receive interrupt code. */ - static int pipe_active(struct dbri *dbri, int pipe) { return (dbri->pipes[pipe].desc != -1); @@ -562,7 +555,6 @@ * * Called on an in-use pipe to clear anything being transmitted or received */ - static void reset_pipe(struct dbri *dbri, int pipe) { int sdp; @@ -597,21 +589,19 @@ void *input_callback_arg = dbri->descs[desc].input_callback_arg; - if (buffer) { - mmu_release_scsi_one(sbus_dvma_addr(buffer), - dbri->descs[desc].len, - dbri->sdev->my_bus); - } + if (buffer) + sbus_unmap_single(dbri->sdev, + dbri->descs[desc].buffer_dvma, + dbri->descs[desc].len); dbri->descs[desc].inuse = 0; desc = dbri->descs[desc].next; - if (output_callback) { + if (output_callback) output_callback(output_callback_arg, -1); - } - if (input_callback) { + + if (input_callback) input_callback(input_callback_arg, -1, 0); - } } dbri->pipes[pipe].desc = -1; @@ -632,10 +622,8 @@ /* If this is a fixed receive pipe, arrange for an interrupt * every time its data changes */ - - if (D_SDP_MODE(sdp) == D_SDP_FIXED && ! (sdp & D_SDP_TO_SER)) { + if (D_SDP_MODE(sdp) == D_SDP_FIXED && ! (sdp & D_SDP_TO_SER)) sdp |= D_SDP_CHANGE; - } sdp |= D_PIPE(pipe); dbri->pipes[pipe].sdp = sdp; @@ -648,7 +636,7 @@ enum in_or_out direction, int basepipe, int length, int cycle) { - volatile int *cmd; + volatile s32 *cmd; int val; int prevpipe; int nextpipe; @@ -668,23 +656,19 @@ * (where n = # of bit times per frame...) must be used." * - DBRI data sheet, page 11 */ - - if (basepipe == 16 && direction == PIPEoutput && cycle == 0) { + if (basepipe == 16 && direction == PIPEoutput && cycle == 0) cycle = dbri->chi_bpf; - } if (basepipe == pipe) { prevpipe = pipe; nextpipe = pipe; } else { - /* We're not initializing a new linked list (basepipe != pipe), * so run through the linked list and find where this pipe * should be sloted in, based on its cycle. CHI confuses * things a bit, since it has a single anchor for both its * transmit and receive lists. */ - if (basepipe == 16) { if (direction == PIPEinput) { prevpipe = dbri->chi_in_pipe; @@ -736,12 +720,11 @@ } /* I don't use this function, so it's basically untested. */ - static void unlink_time_slot(struct dbri *dbri, int pipe, enum in_or_out direction, int prevpipe, int nextpipe) { - volatile int *cmd; + volatile s32 *cmd; int val; if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) { @@ -780,10 +763,9 @@ * in the low-order 8 bits, filled either MSB-first or LSB-first, * depending on the settings passed to setup_pipe() */ - static void xmit_fixed(struct dbri *dbri, int pipe, unsigned int data) { - volatile int *cmd; + volatile s32 *cmd; if (pipe < 16 || pipe > 31) { printk("DBRI: xmit_fixed: Illegal pipe number\n"); @@ -800,16 +782,15 @@ return; } - if (! dbri->pipes[pipe].sdp & D_SDP_TO_SER) { + if (! (dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); return; } /* DBRI short pipes always transmit LSB first */ - if (dbri->pipes[pipe].sdp & D_SDP_MSB) { + if (dbri->pipes[pipe].sdp & D_SDP_MSB) data = reverse_bytes(data, dbri->pipes[pipe].length); - } cmd = dbri_cmdlock(dbri); @@ -855,17 +836,16 @@ * data buffers. Buffers too large for a single descriptor will * be spread across multiple descriptors. */ - static void xmit_on_pipe(struct dbri *dbri, int pipe, void * buffer, unsigned int len, void (*callback)(void *, int), void * callback_arg) { - volatile int *cmd; - register unsigned int flags; + volatile s32 *cmd; + unsigned long flags; int td = 0; int first_td = -1; int last_td = -1; - __u32 dvma_buffer; + __u32 dvma_buffer, dvma_buffer_base; if (pipe < 0 || pipe > 15) { printk("DBRI: xmit_on_pipe: Illegal pipe number\n"); @@ -877,26 +857,26 @@ return; } - if (! dbri->pipes[pipe].sdp & D_SDP_TO_SER) { + if (! (dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { printk("DBRI: xmit_on_pipe: Called on receive pipe %d\n", pipe); return; } - dvma_buffer = mmu_get_scsi_one(buffer, len, dbri->sdev->my_bus); - + dvma_buffer_base = dvma_buffer = sbus_map_single(dbri->sdev, buffer, len); while (len > 0) { int mylen; for (; td < DBRI_NO_DESCS; td ++) { - if (! dbri->descs[td].inuse) break; + if (! dbri->descs[td].inuse) + break; } if (td == DBRI_NO_DESCS) { printk("DBRI: xmit_on_pipe: No descriptors\n"); break; } - if (len > (1 << 13) - 1) { + if (len > ((1 << 13) - 1)) { mylen = (1 << 13) - 1; } else { mylen = len; @@ -918,7 +898,7 @@ } else { dbri->descs[last_td].next = td; dbri->dma->desc[last_td].nda = - (int) & dbri->dma_dvma->desc[td]; + dbri->dma_dvma + dbri_dma_off(desc, td); } last_td = td; @@ -933,6 +913,7 @@ dbri->dma->desc[last_td].word1 |= DBRI_TD_I | DBRI_TD_F | DBRI_TD_B; dbri->descs[last_td].buffer = buffer; + dbri->descs[last_td].buffer_dvma = dvma_buffer_base; dbri->descs[last_td].len = len; dbri->descs[last_td].output_callback = callback; dbri->descs[last_td].output_callback_arg = callback_arg; @@ -949,39 +930,32 @@ save_and_cli(flags); if (pipe_active(dbri, pipe)) { - /* Pipe is already active - find last TD in use * and link our first TD onto its end. Then issue * a CDP command to let the DBRI know there's more data. */ - last_td = dbri->pipes[pipe].desc; while (dbri->descs[last_td].next != -1) last_td = dbri->descs[last_td].next; dbri->descs[last_td].next = first_td; dbri->dma->desc[last_td].nda = - (int) & dbri->dma_dvma->desc[first_td]; + dbri->dma_dvma + dbri_dma_off(desc, first_td); cmd = dbri_cmdlock(dbri); *(cmd++) = DBRI_CMD(D_CDP, 0, pipe); dbri_cmdsend(dbri,cmd); - } else { - /* Pipe isn't active - issue an SDP command to start * our chain of TDs running. */ - dbri->pipes[pipe].desc = first_td; - cmd = dbri_cmdlock(dbri); *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = (int) & dbri->dma_dvma->desc[first_td]; + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); dbri_cmdsend(dbri, cmd); - } restore_flags(flags); @@ -992,11 +966,11 @@ void (*callback)(void *, int, unsigned int), void * callback_arg) { - volatile int *cmd; + volatile s32 *cmd; int first_rd = -1; int last_rd = -1; int rd; - __u32 bus_buffer; + __u32 bus_buffer, bus_buffer_base; if (pipe < 0 || pipe > 15) { printk("DBRI: recv_on_pipe: Illegal pipe number\n"); @@ -1017,7 +991,6 @@ /* XXX Fix this XXX * Should be able to queue multiple buffers to receive on a pipe */ - if (dbri->pipes[pipe].desc != -1) { printk("DBRI: recv_on_pipe: Called on active pipe %d\n", pipe); return; @@ -1026,20 +999,20 @@ /* Make sure buffer size is multiple of four */ len &= ~3; - bus_buffer = mmu_get_scsi_one(buffer, len, dbri->sdev->my_bus); + buf_buffer_base = buf_buffer = sbus_map_single(dbri->sdev, buffer, len); while (len > 0) { - int rd; - int mylen; + int rd, mylen; - if (len > (1 << 13) - 4) { + if (len > ((1 << 13) - 4)) { mylen = (1 << 13) - 4; } else { mylen = len; } for (rd = 0; rd < DBRI_NO_DESCS; rd ++) { - if (! dbri->descs[rd].inuse) break; + if (! dbri->descs[rd].inuse) + break; } if (rd == DBRI_NO_DESCS) { printk("DBRI recv_on_pipe: No descriptors\n"); @@ -1061,7 +1034,7 @@ if (first_rd == -1) first_rd = rd; if (last_rd != -1) { dbri->dma->desc[last_rd].nda = - (int) & dbri->dma_dvma->desc[rd]; + dbri->dma_dvma + dbri_dma_off(desc, rd); dbri->descs[last_rd].next = rd; } last_rd = rd; @@ -1070,9 +1043,8 @@ len -= mylen; } - if (last_rd == -1 || first_rd == -1) { + if (last_rd == -1 || first_rd == -1) return; - } for (rd=first_rd; rd != -1; rd = dbri->descs[rd].next) { dprintk(D_DESC, ("DBRI RD %d: %08x %08x %08x %08x\n", @@ -1084,6 +1056,7 @@ } dbri->descs[last_rd].buffer = buffer; + dbri->descs[last_rd].buffer_dvma = bus_buffer_base; dbri->descs[last_rd].len = len; dbri->descs[last_rd].input_callback = callback; dbri->descs[last_rd].input_callback_arg = callback_arg; @@ -1093,7 +1066,7 @@ cmd = dbri_cmdlock(dbri); *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C); - *(cmd++) = (int) & dbri->dma_dvma->desc[first_rd]; + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_rd); dbri_cmdsend(dbri, cmd); } @@ -1115,9 +1088,9 @@ static void reset_chi(struct dbri *dbri, enum master_or_slave master_or_slave, int bits_per_frame) { - volatile int *cmd; + volatile s32 *cmd; int val; - static int chi_initialized=0; + static int chi_initialized = 0; if (!chi_initialized) { @@ -1163,7 +1136,6 @@ dbri->chi_out_pipe = 16; cmd = dbri_cmdlock(dbri); - } if (master_or_slave == CHIslave) { @@ -1181,13 +1153,11 @@ * 12.288 MHz / CHICM_divisor = clock rate * FD = 1 - drive CHIFS on rising edge of CHICK */ - int clockrate = bits_per_frame * 8; int divisor = 12288 / clockrate; - if (divisor > 255 || divisor * clockrate != 12288) { + if (divisor > 255 || divisor * clockrate != 12288) printk("DBRI: illegal bits_per_frame in setup_chi\n"); - } *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | D_CHI_BPF(bits_per_frame)); @@ -1204,7 +1174,6 @@ */ *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN); dbri_cmdsend(dbri, cmd); @@ -1219,8 +1188,6 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. */ - - static void mmcodec_default(struct cs4215 *mm) { /* @@ -1312,6 +1279,7 @@ static void mmcodec_init_data(struct dbri *dbri) { int data_width; + u32 tmp; /* * Data mode: @@ -1326,13 +1294,14 @@ * bits. The CS4215, it seems, observes TSIN (the delayed signal) * even if it's the CHI master. Don't ask me... */ - - - dbri->regs->reg0 &= ~D_C; /* Disable CHI */ + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~(D_C); /* Disable CHI */ + sbus_writel(tmp, dbri->regs + REG0); /* Switch CS4215 to data mode - set PIO3 to 1 */ - dbri->regs->reg2 = D_ENPIO | D_PIO1 | D_PIO3 | - (dbri->mm.onboard ? D_PIO0 : D_PIO2); + sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 | + (dbri->mm.onboard ? D_PIO0 : D_PIO2), + dbri->regs + REG2); reset_chi(dbri, CHIslave, 128); @@ -1357,16 +1326,18 @@ mmcodec_setgain(dbri, 0); - dbri->regs->reg0 |= D_C; /* Enable CHI */ + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_C; /* Enable CHI */ + sbus_writel(tmp, dbri->regs + REG0); } - /* * Send the control information (i.e. audio format) */ static int mmcodec_setctrl(struct dbri *dbri) { int i, val; + u32 tmp; /* XXX - let the CPU do something useful during these delays */ @@ -1382,7 +1353,7 @@ * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec */ val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2); - dbri->regs->reg2 = val; + sbus_writel(val, dbri->regs + REG2); udelay(34); /* In Control mode, the CS4215 is a slave device, so the DBRI must @@ -1403,8 +1374,9 @@ * done in hardware by a TI 248 that delays the DBRI->4215 * frame sync signal by eight clock cycles. Anybody know why? */ - - dbri->regs->reg0 &= ~D_C; /* Disable CHI */ + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~D_C; /* Disable CHI */ + sbus_writel(tmp, dbri->regs + REG0); reset_chi(dbri, CHImaster, 128); @@ -1427,10 +1399,13 @@ dbri->mm.ctrl[0] &= ~CS4215_CLB; xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); - dbri->regs->reg0 |= D_C; /* Enable CHI */ - - i = 10; - while (((dbri->mm.status & 0xe4) != 0x20) && --i) udelay(125); + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_C; /* Enable CHI */ + sbus_writel(tmp, dbri->regs + REG0); + + i = 64; + while (((dbri->mm.status & 0xe4) != 0x20) && --i) + udelay(125); if (i == 0) { dprintk(D_MM, ("DBRI: CS4215 didn't respond to CLB (0x%02x)\n", dbri->mm.status)); @@ -1440,7 +1415,6 @@ /* Terminate CS4215 control mode - data sheet says * "Set CLB=1 and send two more frames of valid control info" */ - dbri->mm.ctrl[0] |= CS4215_CLB; xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); @@ -1454,9 +1428,8 @@ static int mmcodec_init(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; - int reg2 = dbri->regs->reg2; - + struct dbri *dbri = (struct dbri *) drv->private; + u32 reg2 = sbus_readl(dbri->regs + REG2); /* Look for the cs4215 chips */ if(reg2 & D_PIO2) { @@ -1472,10 +1445,11 @@ /* Using the Speakerbox, if both are attached. */ if((reg2 & D_PIO2) && (reg2 & D_PIO0)) { printk("DBRI: Using speakerbox / ignoring onboard mmcodec.\n"); - dbri->regs->reg2 = D_ENPIO2; + sbus_writel(D_ENPIO2, dbri->regs + REG2); dbri->mm.onboard = 0; } - if( !(reg2 & (D_PIO0|D_PIO2)) ) { + + if(!(reg2 & (D_PIO0|D_PIO2))) { printk("DBRI: no mmcodec found.\n"); return -EIO; } @@ -1519,27 +1493,23 @@ */ /******************* sparcaudio midlevel - audio output *******************/ - - static void dbri_audio_output_callback(void * callback_arg, int status) { struct sparcaudio_driver *drv = callback_arg; - if (status != -1) { + if (status != -1) sparcaudio_output_done(drv, 1); - } } static void dbri_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; - dprintk(D_USR, ("DBRI: start audio output buf=%lx/%ld\n", - (unsigned long) buffer, count)); + dprintk(D_USR, ("DBRI: start audio output buf=%p/%ld\n", + buffer, count)); /* Pipe 4 is audio transmit */ - xmit_on_pipe(dbri, 4, buffer, count, &dbri_audio_output_callback, drv); @@ -1559,12 +1529,11 @@ sparcaudio_output_done(drv, 2); #endif - } static void dbri_stop_output(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; reset_pipe(dbri, 4); } @@ -1577,26 +1546,25 @@ struct sparcaudio_driver * drv = (struct sparcaudio_driver *) callback_arg; - if (status != -1) { + if (status != -1) sparcaudio_input_done(drv, 3); - } } static void dbri_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long len) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; /* Pipe 6 is audio receive */ recv_on_pipe(dbri, 6, buffer, len, &dbri_audio_input_callback, (void *)drv); - dprintk(D_USR, ("DBRI: start audio input buf=%lx/%ld\n", - (unsigned long) buffer, len)); + dprintk(D_USR, ("DBRI: start audio input buf=%p/%ld\n", + buffer, len)); } static void dbri_stop_input(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; reset_pipe(dbri, 6); } @@ -1605,7 +1573,7 @@ static int dbri_set_output_volume(struct sparcaudio_driver *drv, int volume) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; dbri->perchip_info.play.gain = volume; mmcodec_setgain(dbri, 0); @@ -1615,7 +1583,7 @@ static int dbri_get_output_volume(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.gain; } @@ -1642,7 +1610,7 @@ static int dbri_set_output_balance(struct sparcaudio_driver *drv, int balance) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; dbri->perchip_info.play.balance = balance; mmcodec_setgain(dbri, 0); @@ -1652,7 +1620,7 @@ static int dbri_get_output_balance(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.balance; } @@ -1669,7 +1637,7 @@ static int dbri_set_output_muted(struct sparcaudio_driver *drv, int mute) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; dbri->perchip_info.output_muted = mute; @@ -1678,7 +1646,7 @@ static int dbri_get_output_muted(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.output_muted; } @@ -1687,7 +1655,7 @@ static int dbri_set_output_channels(struct sparcaudio_driver *drv, int chan) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; switch (chan) { case 0: @@ -1710,7 +1678,7 @@ static int dbri_get_output_channels(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.channels; } @@ -1732,7 +1700,7 @@ static int dbri_get_output_precision(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.precision; } @@ -1744,14 +1712,14 @@ static int dbri_get_input_precision(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.precision; } static int dbri_set_output_encoding(struct sparcaudio_driver *drv, int enc) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; /* For ULAW and ALAW, audio.c enforces precision = 8, * for LINEAR, precision must be 16 @@ -1780,7 +1748,8 @@ break; default: return -1; - } + }; + mmcodec_setctrl(dbri); mmcodec_init_data(dbri); return 0; @@ -1788,7 +1757,7 @@ static int dbri_get_output_encoding(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.encoding; } @@ -1805,19 +1774,19 @@ static int dbri_set_output_rate(struct sparcaudio_driver *drv, int rate) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; int i; - if (rate == 0) { + if (rate == 0) return 0; - } for (i=0; CS4215_FREQ[i].freq; i++) { - if (CS4215_FREQ[i].freq == rate) break; + if (CS4215_FREQ[i].freq == rate) + break; } - if (CS4215_FREQ[i].freq == 0) { + + if (CS4215_FREQ[i].freq == 0) return -1; - } dbri->mm.ctrl[1] &= ~ 0x38; dbri->mm.ctrl[1] |= CS4215_FREQ[i].csval; @@ -1833,7 +1802,7 @@ static int dbri_get_output_rate(struct sparcaudio_driver *drv) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; return dbri->perchip_info.play.sample_rate; } @@ -1885,7 +1854,7 @@ static void dbri_audio_getdev(struct sparcaudio_driver *drv, audio_device_t *audinfo) { - struct dbri *dbri = (struct dbri *)drv->private; + struct dbri *dbri = (struct dbri *) drv->private; strncpy(audinfo->name, "SUNW,DBRI", sizeof(audinfo->name) - 1); @@ -1907,13 +1876,11 @@ { MOD_INC_USE_COUNT; - /* - * I've taken the liberty of setting half gain and + /* I've taken the liberty of setting half gain and * mid balance, to put the codec in a known state. */ - dbri_set_output_balance(drv, AUDIO_MID_BALANCE); - dbri_set_output_volume(drv, AUDIO_MAX_GAIN/2); + dbri_set_output_volume(drv, AUDIO_MAX_GAIN / 2); return 0; } @@ -1985,8 +1952,6 @@ ************************** ISDN (Hisax) Interface ************************** **************************************************************************** */ - - void dbri_isdn_init(struct dbri *dbri) { /* Pipe 0: Receive D channel @@ -2018,9 +1983,8 @@ { struct dbri *dbri; - if (dev >= num_drivers) { + if (dev >= num_drivers) return(0); - } dbri = (struct dbri *) drivers[dev].private; @@ -2034,9 +1998,8 @@ { struct dbri *dbri; - if (dev >= num_drivers) { + if (dev >= num_drivers) return(0); - } dbri = (struct dbri *) drivers[dev].private; @@ -2051,9 +2014,8 @@ { struct dbri *dbri; - if (dev >= num_drivers) { + if (dev >= num_drivers) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2071,17 +2033,17 @@ { struct dbri *dbri; int val; - volatile int *cmd; + volatile s32 *cmd; - if (dev >= num_drivers) { + if (dev >= num_drivers) return; - } dbri = (struct dbri *) drivers[dev].private; tprintk(("dbri_liu_activate()\n")); if (dbri->liu_state <= 3) { + u32 tmp; cmd = dbri_cmdlock(dbri); @@ -2095,38 +2057,41 @@ dbri_cmdsend(dbri, cmd); /* Activate the interface */ - dbri->regs->reg0 |= D_T; + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_T; + sbus_writel(tmp, dbri->regs + REG0); } } void dbri_liu_deactivate(int dev) { struct dbri *dbri; + u32 tmp; - if (dev >= num_drivers) { + if (dev >= num_drivers) return; - } dbri = (struct dbri *) drivers[dev].private; tprintk(("dbri_liu_deactivate()\n")); #if 0 - /* Turn off the ISDN TE interface */ - dbri->regs->reg0 &= ~D_T; + /* Turn off the ISDN TE interface */ + tmp = sbus_readl(dbri->regs + REG0); + tmp &= ~D_T; + sbus_writel(tmp, dbri->regs + REG0); - dbri->liu_state = 0; + dbri->liu_state = 0; #endif } void dbri_dxmit(int dev, __u8 *buffer, unsigned int count, - void (*callback)(void *, int), void *callback_arg) + void (*callback)(void *, int), void *callback_arg) { struct dbri *dbri; - if (dev >= num_drivers) { + if (dev >= num_drivers) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2135,14 +2100,13 @@ } void dbri_drecv(int dev, __u8 *buffer, unsigned int size, - void (*callback)(void *, int, unsigned int), - void *callback_arg) + void (*callback)(void *, int, unsigned int), + void *callback_arg) { struct dbri *dbri; - if (dev >= num_drivers) { + if (dev >= num_drivers) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2155,14 +2119,12 @@ { struct dbri *dbri; - if (dev >= num_drivers || chan > 1) { + if (dev >= num_drivers || chan > 1) return -1; - } dbri = (struct dbri *) drivers[dev].private; if (hdlcmode) { - /* return -1; */ /* Pipe 8/9: receive B1/B2 channel */ @@ -2170,15 +2132,12 @@ /* Pipe 10/11: transmit B1/B2 channel */ setup_pipe(dbri,10+chan, D_SDP_HDLC | D_SDP_TO_SER | D_SDP_LSB); - } else { /* !hdlcmode means transparent */ - /* Pipe 8/9: receive B1/B2 channel */ setup_pipe(dbri, 8+chan, D_SDP_MEM | D_SDP_FROM_SER|D_SDP_LSB); /* Pipe 10/11: transmit B1/B2 channel */ setup_pipe(dbri,10+chan, D_SDP_MEM | D_SDP_TO_SER | D_SDP_LSB); - } return 0; } @@ -2187,9 +2146,8 @@ { struct dbri *dbri; - if (dev >= num_drivers || chan > 1) { + if (dev >= num_drivers || chan > 1) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2198,15 +2156,14 @@ } void dbri_bxmit(int dev, unsigned int chan, - __u8 *buffer, unsigned long count, - void (*callback)(void *, int), - void *callback_arg) + __u8 *buffer, unsigned long count, + void (*callback)(void *, int), + void *callback_arg) { struct dbri *dbri; - if (dev >= num_drivers || chan > 1) { + if (dev >= num_drivers || chan > 1) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2215,15 +2172,14 @@ } void dbri_brecv(int dev, unsigned int chan, - __u8 *buffer, unsigned long size, - void (*callback)(void *, int, unsigned int), - void *callback_arg) + __u8 *buffer, unsigned long size, + void (*callback)(void *, int, unsigned int), + void *callback_arg) { struct dbri *dbri; - if (dev >= num_drivers || chan > 1) { + if (dev >= num_drivers || chan > 1) return; - } dbri = (struct dbri *) drivers[dev].private; @@ -2255,7 +2211,7 @@ */ static int dbri_attach(struct sparcaudio_driver *drv, - struct linux_sbus_device *sdev) + struct sbus_dev *sdev) { struct dbri *dbri; struct linux_prom_irqs irq; @@ -2270,36 +2226,33 @@ drv->ops = &dbri_ops; drv->private = kmalloc(sizeof(struct dbri), GFP_KERNEL); - if (!drv->private) + if (drv->private == NULL) return -ENOMEM; - dbri = (struct dbri *)drv->private; + dbri = (struct dbri *) drv->private; memset(dbri, 0, sizeof(*dbri)); - /* sparc_dvma_malloc() will halt the kernel if the malloc fails */ - dbri->dma = sparc_dvma_malloc (sizeof (struct dbri_dma), - "DBRI DMA Cmd Block", &dma_dvma); - dbri->dma_dvma = (struct dbri_dma *) dma_dvma; + dbri->dma = sbus_alloc_consistant(sdev, + sizeof(struct dbri_dma), + &dbri->dma_dvma); memset((void *) dbri->dma, 0, sizeof(struct dbri_dma)); - dprintk(D_GEN, ("DBRI: DMA Cmd Block 0x%08x (0x%08x)\n", - (int)dbri->dma, (int)dbri->dma_dvma)); + dprintk(D_GEN, ("DBRI: DMA Cmd Block 0x%p (0x%08x)\n", + dbri->dma, dbri->dma_dvma)); dbri->dbri_version = sdev->prom_name[9]; dbri->sdev = sdev; /* Map the registers into memory. */ - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); dbri->regs_size = sdev->reg_addrs[0].reg_size; - dbri->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, - "DBRI Registers", sdev->reg_addrs[0].which_io, 0); + dbri->regs = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "DBRI Registers"); if (!dbri->regs) { printk(KERN_ERR "DBRI: could not allocate registers\n"); - release_region((unsigned long) dbri->dma, - sizeof(struct dbri_dma)); + sbus_free_consistant(sdev, sizeof(struct dbri_dma), + dbri->dma, dbri->dma_dvma); kfree(drv->private); return -EIO; } @@ -2311,9 +2264,9 @@ "DBRI audio/ISDN", dbri); if (err) { printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); - sparc_free_io(dbri->regs, dbri->regs_size); - release_region((unsigned long) dbri->dma, - sizeof(struct dbri_dma)); + sbus_iounmap(dbri->regs, dbri->regs_size); + sbus_free_consistant(sdev, sizeof(struct dbri_dma), + dbri->dma, dbri->dma_dvma); kfree(drv->private); return err; } @@ -2337,7 +2290,7 @@ dbri->perchip_info.record.active = dbri->perchip_info.record.pause = 0; printk(KERN_INFO "audio%d at 0x%lx (irq %d) is DBRI(%c)+CS4215(%d)\n", - num_drivers, (unsigned long)dbri->regs, + num_drivers, dbri->regs, dbri->irq, dbri->dbri_version, dbri->mm.version); return 0; @@ -2350,13 +2303,13 @@ int __init dbri_init(void) #endif { - struct linux_sbus *bus; - struct linux_sbus_device *sdev; + struct sbus_bus *sbus; + struct sbus_dev *sdev; num_drivers = 0; /* Probe each SBUS for the DBRI chip(s). */ - for_all_sbusdev(sdev,bus) { + for_all_sbusdev(sdev, sbus) { /* * The version is coded in the last character */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h --- v2.3.34/linux/drivers/sbus/audio/dbri.h Thu Jun 17 01:08:50 1999 +++ linux/drivers/sbus/audio/dbri.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: dbri.h,v 1.12 1999/09/21 14:37:34 davem Exp $ * drivers/sbus/audio/cs4231.h * * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) @@ -9,15 +9,13 @@ #include -struct dbri_regs { - __volatile__ __u32 reg0; /* Status & Control */ - __volatile__ __u32 reg1; /* Mode & Interrupt */ - __volatile__ __u32 reg2; /* Parallel IO */ - __volatile__ __u32 reg3; /* Test */ - __volatile__ __u32 unused[4]; - __volatile__ __u32 reg8; /* Command Queue Pointer */ - __volatile__ __u32 reg9; /* Interrupt Queue Pointer */ -}; +/* DBRI main registers */ +#define REG0 0x00UL /* Status and Control */ +#define REG1 0x04UL /* Mode and Interrupt */ +#define REG2 0x08UL /* Parallel IO */ +#define REG3 0x0cUL /* Test */ +#define REG8 0x20UL /* Command Queue Pointer */ +#define REG9 0x24UL /* Interrupt Queue Pointer */ #define DBRI_NO_CMDS 64 #define DBRI_NO_INTS 2 @@ -28,10 +26,10 @@ #define DBRI_MM_SB 2 struct dbri_mem { - __u32 word1; - __u32 ba; /* Transmit/Receive Buffer Address */ - __u32 nda; /* Next Descriptor Address */ - __u32 word4; + volatile __u32 word1; + volatile __u32 ba; /* Transmit/Receive Buffer Address */ + volatile __u32 nda; /* Next Descriptor Address */ + volatile __u32 word4; }; #include "cs4215.h" @@ -39,13 +37,16 @@ /* This structure is in a DMA region where it can accessed by both * the CPU and the DBRI */ - struct dbri_dma { - int cmd[DBRI_NO_CMDS]; /* Place for commands */ - int intr[DBRI_NO_INTS * DBRI_INT_BLK]; /* Interrupt field */ - struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */ + volatile s32 cmd[DBRI_NO_CMDS]; /* Place for commands */ + volatile s32 intr[DBRI_NO_INTS * DBRI_INT_BLK]; /* Interrupt field */ + struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */ }; +#define dbri_dma_off(member, elem) \ + ((u32)(unsigned long) \ + (&(((struct dbri_dma *)0)->member[elem]))) + enum in_or_out { PIPEinput, PIPEoutput }; enum direction { in, out }; @@ -64,7 +65,8 @@ struct dbri_desc { int inuse; /* Boolean flag */ int next; /* Index of next desc, or -1 */ - void *buffer; + void *buffer; /* CPU view of buffer */ + u32 buffer_dvma; /* Device view */ unsigned int len; void (*output_callback)(void *, int); void *output_callback_arg; @@ -75,37 +77,37 @@ /* This structure holds the information for both chips (DBRI & CS4215) */ struct dbri { - int regs_size, irq; /* Needed for unload */ - struct linux_sbus_device *sdev; + int regs_size, irq; /* Needed for unload */ + struct sbus_dev *sdev; /* SBUS device info */ - volatile struct dbri_dma *dma; /* Pointer to our DMA block */ - struct dbri_dma *dma_dvma; /* DBRI visible DMA address */ + volatile struct dbri_dma *dma; /* Pointer to our DMA block */ + u32 dma_dvma; /* DBRI visible DMA address */ - struct dbri_regs *regs; /* dbri HW regs */ - int dbri_version; /* 'e' and up is OK */ - int dbri_irqp; /* intr queue pointer */ - int wait_seen; + unsigned long regs; /* dbri HW regs */ + int dbri_version; /* 'e' and up is OK */ + int dbri_irqp; /* intr queue pointer */ + int wait_seen; - struct dbri_pipe pipes[32]; /* DBRI's 32 data pipes */ - struct dbri_desc descs[DBRI_NO_DESCS]; + struct dbri_pipe pipes[32]; /* DBRI's 32 data pipes */ + struct dbri_desc descs[DBRI_NO_DESCS]; - int chi_in_pipe; - int chi_out_pipe; - int chi_bpf; + int chi_in_pipe; + int chi_out_pipe; + int chi_bpf; - struct cs4215 mm; /* mmcodec special info */ + struct cs4215 mm; /* mmcodec special info */ #if 0 - wait_queue_head_t wait, int_wait; /* Where to sleep if busy */ + /* Where to sleep if busy */ + wait_queue_head_t wait, int_wait; #endif - struct audio_info perchip_info; + struct audio_info perchip_info; - /* Track ISDN LIU and notify changes */ - int liu_state; - void (*liu_callback)(void *); - void *liu_callback_arg; + /* Track ISDN LIU and notify changes */ + int liu_state; + void (*liu_callback)(void *); + void *liu_callback_arg; }; - /* DBRI Reg0 - Status Control Register - defines. (Page 17) */ #define D_P (1<<15) /* Program command & queue pointer valid */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c --- v2.3.34/linux/drivers/sbus/audio/dmy.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/audio/dmy.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: dmy.c,v 1.5 1999/09/21 14:37:37 davem Exp $ * drivers/sbus/audio/dummy.c * * Copyright 1998 Derrick J Brashear (shadow@andrew.cmu.edu) @@ -41,543 +41,614 @@ static int dummy_set_output_encoding(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (value != 0) { - dummy_chip->perchip_info.play.encoding = value; - return 0; - } - return -EINVAL; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (value != 0) { + dummy_chip->perchip_info.play.encoding = value; + return 0; + } + return -EINVAL; } static int dummy_set_input_encoding(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (value != 0) { - dummy_chip->perchip_info.record.encoding = value; - return 0; - } - return -EINVAL; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (value != 0) { + dummy_chip->perchip_info.record.encoding = value; + return 0; + } + return -EINVAL; } static int dummy_get_output_encoding(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.encoding; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.encoding; } static int dummy_get_input_encoding(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.encoding; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.encoding; } static int dummy_set_output_rate(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (value != 0) { - dummy_chip->perchip_info.play.sample_rate = value; - return 0; - } - return -EINVAL; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (value != 0) { + dummy_chip->perchip_info.play.sample_rate = value; + return 0; + } + return -EINVAL; } static int dummy_set_input_rate(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (value != 0) { - dummy_chip->perchip_info.record.sample_rate = value; - return 0; - } - return -EINVAL; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (value != 0) { + dummy_chip->perchip_info.record.sample_rate = value; + return 0; + } + return -EINVAL; } static int dummy_get_output_rate(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.sample_rate; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.sample_rate; } static int dummy_get_input_rate(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.sample_rate; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.sample_rate; } /* Generically we support 4 channels. This does 2 */ static int dummy_set_output_channels(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - switch (value) { - case 1: - case 2: - break; - default: - return -(EINVAL); - } - dummy_chip->perchip_info.play.channels = value; - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + switch (value) { + case 1: + case 2: + break; + default: + return -(EINVAL); + }; + + dummy_chip->perchip_info.play.channels = value; + return 0; } /* Generically we support 4 channels. This does 2 */ static int dummy_set_input_channels(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - switch (value) { - case 1: - case 2: - break; - default: - return -(EINVAL); - } - dummy_chip->perchip_info.record.channels = value; - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + switch (value) { + case 1: + case 2: + break; + default: + return -(EINVAL); + }; + + dummy_chip->perchip_info.record.channels = value; + return 0; } static int dummy_get_input_channels(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.channels; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.channels; } static int dummy_get_output_channels(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.channels; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.channels; } static int dummy_get_output_precision(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.precision; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.precision; } static int dummy_get_input_precision(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.precision; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.precision; } static int dummy_set_output_precision(struct sparcaudio_driver *drv, int val) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.play.precision = val; - return dummy_chip->perchip_info.play.precision; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.play.precision = val; + return dummy_chip->perchip_info.play.precision; } static int dummy_set_input_precision(struct sparcaudio_driver *drv, int val) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.precision = val; - return dummy_chip->perchip_info.record.precision; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.precision = val; + return dummy_chip->perchip_info.record.precision; } /* Set output mute */ static int dummy_output_muted(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (!value) - dummy_chip->perchip_info.output_muted = 0; - else - dummy_chip->perchip_info.output_muted = 1; - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (!value) + dummy_chip->perchip_info.output_muted = 0; + else + dummy_chip->perchip_info.output_muted = 1; + + return 0; } static int dummy_get_output_muted(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.output_muted; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.output_muted; } static int dummy_get_formats(struct sparcaudio_driver *drv) { - return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_IMA_ADPCM | - AFMT_S16_LE | AFMT_S16_BE); + return (AFMT_MU_LAW | AFMT_A_LAW | + AFMT_U8 | AFMT_IMA_ADPCM | + AFMT_S16_LE | AFMT_S16_BE); } static int dummy_get_output_ports(struct sparcaudio_driver *drv) { - return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE); + return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE); } static int dummy_get_input_ports(struct sparcaudio_driver *drv) { - return (AUDIO_ANALOG_LOOPBACK); + return (AUDIO_ANALOG_LOOPBACK); } /* Set chip "output" port */ static int dummy_set_output_port(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.play.port = value; - return (value); + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.play.port = value; + return value; } static int dummy_set_input_port(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.port = value; - return (value); + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.port = value; + return value; } static int dummy_get_output_port(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.port; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.port; } static int dummy_get_input_port(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.port; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.port; } static int dummy_get_output_error(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.play.error; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.play.error; } static int dummy_get_input_error(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.record.error; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.record.error; } static int dummy_get_output_samples(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.samples; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.samples; } static int dummy_get_output_pause(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.play.pause; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.play.pause; } static int dummy_set_output_volume(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_play_gain(drv, value, dummy_chip->perchip_info.play.balance); - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_play_gain(drv, value, dummy_chip->perchip_info.play.balance); + return 0; } static int dummy_get_output_volume(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.play.gain; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.play.gain; } static int dummy_set_output_balance(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.play.balance = value; - dummy_play_gain(drv, dummy_chip->perchip_info.play.gain, - dummy_chip->perchip_info.play.balance); - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.play.balance = value; + dummy_play_gain(drv, dummy_chip->perchip_info.play.gain, + dummy_chip->perchip_info.play.balance); + return 0; } static int dummy_get_output_balance(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.play.balance; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.play.balance; } /* Set chip play gain */ -static int dummy_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) +static int dummy_play_gain(struct sparcaudio_driver *drv, + int value, unsigned char balance) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - int tmp = 0, r, l, r_adj, l_adj; - r = l = value; - if (balance < AUDIO_MID_BALANCE) { - r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); - if (r < 0) r = 0; - } else if (balance > AUDIO_MID_BALANCE) { - l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); - if (l < 0) l = 0; - } - (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - - (l * (DUMMY_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN - - (r * (DUMMY_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - if ((value == 0) || (value == AUDIO_MAX_GAIN)) { - tmp = value; - } else { - if (value == l) - tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / - (DUMMY_MAX_ATEN + 1)); - else if (value == r) - tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / - (DUMMY_MAX_ATEN + 1)); - } - dummy_chip->perchip_info.play.gain = tmp; - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + int tmp = 0, r, l, r_adj, l_adj; + + r = l = value; + if (balance < AUDIO_MID_BALANCE) { + r = (int) (value - + ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); + + if (r < 0) + r = 0; + } else if (balance > AUDIO_MID_BALANCE) { + l = (int) (value - + ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); + + if (l < 0) + l = 0; + } + (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - + (l * (DUMMY_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN - + (r * (DUMMY_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + if ((value == 0) || (value == AUDIO_MAX_GAIN)) { + tmp = value; + } else { + if (value == l) { + tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / + (DUMMY_MAX_ATEN + 1)); + } else if (value == r) { + tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / + (DUMMY_MAX_ATEN + 1)); + } + } + dummy_chip->perchip_info.play.gain = tmp; + return 0; } static int dummy_get_input_samples(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.samples; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.samples; } static int dummy_get_input_pause(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.record.pause; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.record.pause; } static int dummy_set_monitor_volume(struct sparcaudio_driver *drv, int value) { - return 0; + return 0; } static int dummy_get_monitor_volume(struct sparcaudio_driver *drv) { - return 0; + return 0; } static int dummy_set_input_volume(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_record_gain(drv, value, dummy_chip->perchip_info.record.balance); - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_record_gain(drv, value, dummy_chip->perchip_info.record.balance); + return 0; } static int dummy_get_input_volume(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return dummy_chip->perchip_info.record.gain; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return dummy_chip->perchip_info.record.gain; } static int dummy_set_input_balance(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.balance = value; - dummy_record_gain(drv, dummy_chip->perchip_info.record.gain, - dummy_chip->perchip_info.play.balance); - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.balance = value; + dummy_record_gain(drv, dummy_chip->perchip_info.record.gain, + dummy_chip->perchip_info.play.balance); + return 0; } static int dummy_get_input_balance(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - return (int)dummy_chip->perchip_info.record.balance; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + return (int) dummy_chip->perchip_info.record.balance; } -static int dummy_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance) +static int dummy_record_gain(struct sparcaudio_driver *drv, + int value, unsigned char balance) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - int tmp = 0, r, l, r_adj, l_adj; - r = l = value; - if (balance < AUDIO_MID_BALANCE) { - r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); - if (r < 0) r = 0; - } else if (balance > AUDIO_MID_BALANCE) { - l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); - if (l < 0) l = 0; - } - (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - - (l * (DUMMY_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN - - (r * (DUMMY_MAX_ATEN + 1) / - (AUDIO_MAX_GAIN + 1))); - if ((value == 0) || (value == AUDIO_MAX_GAIN)) { - tmp = value; - } else { - if (value == l) - tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / - (DUMMY_MAX_ATEN + 1)); - else if (value == r) - tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / - (DUMMY_MAX_ATEN + 1)); - } - dummy_chip->perchip_info.record.gain = tmp; - return 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + int tmp = 0, r, l, r_adj, l_adj; + + r = l = value; + if (balance < AUDIO_MID_BALANCE) { + r = (int) (value - + ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)); + + if (r < 0) + r = 0; + } else if (balance > AUDIO_MID_BALANCE) { + l = (int) (value - + ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)); + + if (l < 0) + l = 0; + } + (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - + (l * (DUMMY_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN - + (r * (DUMMY_MAX_ATEN + 1) / + (AUDIO_MAX_GAIN + 1))); + if ((value == 0) || (value == AUDIO_MAX_GAIN)) { + tmp = value; + } else { + if (value == l) { + tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / + (DUMMY_MAX_ATEN + 1)); + } else if (value == r) { + tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / + (DUMMY_MAX_ATEN + 1)); + } + } + dummy_chip->perchip_info.record.gain = tmp; + return 0; } /* Reset the audio chip to a sane state. */ static void dummy_chip_reset(struct sparcaudio_driver *drv) { - dummy_set_output_encoding(drv, AUDIO_ENCODING_ULAW); - dummy_set_output_rate(drv, DUMMY_RATE); - dummy_set_output_channels(drv, DUMMY_CHANNELS); - dummy_set_output_precision(drv, DUMMY_PRECISION); - dummy_set_output_balance(drv, AUDIO_MID_BALANCE); - dummy_set_output_volume(drv, DUMMY_DEFAULT_PLAYGAIN); - dummy_set_output_port(drv, AUDIO_SPEAKER); - dummy_output_muted(drv, 0); - dummy_set_input_encoding(drv, AUDIO_ENCODING_ULAW); - dummy_set_input_rate(drv, DUMMY_RATE); - dummy_set_input_channels(drv, DUMMY_CHANNELS); - dummy_set_input_precision(drv, DUMMY_PRECISION); - dummy_set_input_balance(drv, AUDIO_MID_BALANCE); - dummy_set_input_volume(drv, DUMMY_DEFAULT_PLAYGAIN); - dummy_set_input_port(drv, AUDIO_SPEAKER); + dummy_set_output_encoding(drv, AUDIO_ENCODING_ULAW); + dummy_set_output_rate(drv, DUMMY_RATE); + dummy_set_output_channels(drv, DUMMY_CHANNELS); + dummy_set_output_precision(drv, DUMMY_PRECISION); + dummy_set_output_balance(drv, AUDIO_MID_BALANCE); + dummy_set_output_volume(drv, DUMMY_DEFAULT_PLAYGAIN); + dummy_set_output_port(drv, AUDIO_SPEAKER); + dummy_output_muted(drv, 0); + dummy_set_input_encoding(drv, AUDIO_ENCODING_ULAW); + dummy_set_input_rate(drv, DUMMY_RATE); + dummy_set_input_channels(drv, DUMMY_CHANNELS); + dummy_set_input_precision(drv, DUMMY_PRECISION); + dummy_set_input_balance(drv, AUDIO_MID_BALANCE); + dummy_set_input_volume(drv, DUMMY_DEFAULT_PLAYGAIN); + dummy_set_input_port(drv, AUDIO_SPEAKER); } static int dummy_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - /* Set the default audio parameters if not already in use. */ - if (file->f_mode & FMODE_WRITE) { - if (!(drv->flags & SDF_OPEN_WRITE) && - (dummy_chip->perchip_info.play.active == 0)) { - dummy_chip->perchip_info.play.open = 1; - dummy_chip->perchip_info.play.samples = - dummy_chip->perchip_info.play.error = 0; - } - } - if (file->f_mode & FMODE_READ) { - if (!(drv->flags & SDF_OPEN_READ) && - (dummy_chip->perchip_info.record.active == 0)) { - dummy_chip->perchip_info.record.open = 1; - dummy_chip->perchip_info.record.samples = - dummy_chip->perchip_info.record.error = 0; - } - } + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + /* Set the default audio parameters if not already in use. */ + if (file->f_mode & FMODE_WRITE) { + if (!(drv->flags & SDF_OPEN_WRITE) && + (dummy_chip->perchip_info.play.active == 0)) { + dummy_chip->perchip_info.play.open = 1; + dummy_chip->perchip_info.play.samples = + dummy_chip->perchip_info.play.error = 0; + } + } + + if (file->f_mode & FMODE_READ) { + if (!(drv->flags & SDF_OPEN_READ) && + (dummy_chip->perchip_info.record.active == 0)) { + dummy_chip->perchip_info.record.open = 1; + dummy_chip->perchip_info.record.samples = + dummy_chip->perchip_info.record.error = 0; + } + } - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - return 0; + return 0; } static void dummy_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - if (file->f_mode & FMODE_WRITE) { - dummy_chip->perchip_info.play.active = - dummy_chip->perchip_info.play.open = 0; - } - if (file->f_mode & FMODE_READ) { - dummy_chip->perchip_info.record.active = - dummy_chip->perchip_info.record.open = 0; - } - MOD_DEC_USE_COUNT; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + if (file->f_mode & FMODE_WRITE) { + dummy_chip->perchip_info.play.active = + dummy_chip->perchip_info.play.open = 0; + } + + if (file->f_mode & FMODE_READ) { + dummy_chip->perchip_info.record.active = + dummy_chip->perchip_info.record.open = 0; + } + + MOD_DEC_USE_COUNT; } static void dummy_output_done_task(void * arg) { - struct sparcaudio_driver *drv = (struct sparcaudio_driver *)arg; - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; + struct sparcaudio_driver *drv = (struct sparcaudio_driver *) arg; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; - sparcaudio_output_done(drv, 1); - if (dummy_chip->perchip_info.record.active) - sparcaudio_input_done(drv, 1); + sparcaudio_output_done(drv, 1); + if (dummy_chip->perchip_info.record.active) + sparcaudio_input_done(drv, 1); } static void dummy_start_output(struct sparcaudio_driver *drv, __u8 * buffer, - unsigned long count) + unsigned long count) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; - if (dummy_chip->perchip_info.play.pause || !count) - return; + if (dummy_chip->perchip_info.play.pause || !count) + return; - dummy_chip->perchip_info.play.active = 1; + dummy_chip->perchip_info.play.active = 1; - /* fake an "interrupt" to deal with this block */ - dummy_chip->tqueue.next = NULL; - dummy_chip->tqueue.sync = 0; - dummy_chip->tqueue.routine = dummy_output_done_task; - dummy_chip->tqueue.data = drv; + /* fake an "interrupt" to deal with this block */ + dummy_chip->tqueue.next = NULL; + dummy_chip->tqueue.sync = 0; + dummy_chip->tqueue.routine = dummy_output_done_task; + dummy_chip->tqueue.data = drv; - queue_task(&dummy_chip->tqueue, &tq_immediate); - mark_bh(IMMEDIATE_BH); + queue_task(&dummy_chip->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); } static void dummy_start_input(struct sparcaudio_driver *drv, __u8 * buffer, - unsigned long count) + unsigned long count) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.active = 1; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.active = 1; } static void dummy_stop_output(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.play.active = 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.play.active = 0; } static void dummy_stop_input(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.active = 0; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.active = 0; } static int dummy_set_output_pause(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.play.pause = value; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.play.pause = value; - if (!value) - sparcaudio_output_done(drv, 0); + if (!value) + sparcaudio_output_done(drv, 0); - return value; + return value; } static int dummy_set_input_pause(struct sparcaudio_driver *drv, int value) { - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - dummy_chip->perchip_info.record.pause = value; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + + dummy_chip->perchip_info.record.pause = value; - /* This should probably cause play pause. */ + /* This should probably cause play pause. */ - return value; + return value; } static int dummy_set_input_error(struct sparcaudio_driver *drv, int value) { - return 0; + return 0; } static int dummy_set_output_error(struct sparcaudio_driver *drv, int value) { - int i; - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - i = dummy_chip->perchip_info.play.error; - dummy_chip->perchip_info.play.error = value; - return i; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + int i; + + i = dummy_chip->perchip_info.play.error; + dummy_chip->perchip_info.play.error = value; + return i; } static int dummy_set_output_samples(struct sparcaudio_driver *drv, int value) { - int i; - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - i = dummy_chip->perchip_info.play.samples; - dummy_chip->perchip_info.play.samples = value; - return i; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + int i; + + i = dummy_chip->perchip_info.play.samples; + dummy_chip->perchip_info.play.samples = value; + return i; } static int dummy_set_input_samples(struct sparcaudio_driver *drv, int value) { - int i; - struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; - i = dummy_chip->perchip_info.play.samples; - dummy_chip->perchip_info.record.samples = value; - return i; + struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; + int i; + + i = dummy_chip->perchip_info.play.samples; + dummy_chip->perchip_info.record.samples = value; + return i; } /* In order to fake things which care out, play we're a 4231 */ static void dummy_audio_getdev(struct sparcaudio_driver *drv, - audio_device_t * audinfo) + audio_device_t * audinfo) { - strncpy(audinfo->name, "SUNW,cs4231", sizeof(audinfo->name) - 1); - strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); - strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); + strncpy(audinfo->name, "SUNW,cs4231", sizeof(audinfo->name) - 1); + strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1); + strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1); } static int dummy_audio_getdev_sunos(struct sparcaudio_driver *drv) { - return (5); + return 5; } static struct sparcaudio_operations dummy_ops = { @@ -646,73 +717,73 @@ int __init dummy_init(void) #endif { - num_drivers = 0; + num_drivers = 0; - /* Add support here for specifying multiple dummies to attach at once. */ - if (dummy_attach(&drivers[num_drivers]) == 0) - num_drivers++; + /* Add support here for specifying multiple dummies to attach at once. */ + if (dummy_attach(&drivers[num_drivers]) == 0) + num_drivers++; - /* Only return success if we found some dummy chips. */ - return (num_drivers > 0) ? 0 : -EIO; + /* Only return success if we found some dummy chips. */ + return (num_drivers > 0) ? 0 : -EIO; } /* Attach to an dummy chip given its PROM node. */ static int dummy_attach(struct sparcaudio_driver *drv) { - struct dummy_chip *dummy_chip; - int err; + struct dummy_chip *dummy_chip; + int err; - /* Allocate our private information structure. */ - drv->private = kmalloc(sizeof(struct dummy_chip), GFP_KERNEL); - if (!drv->private) - return -ENOMEM; - - /* Point at the information structure and initialize it. */ - drv->ops = &dummy_ops; - dummy_chip = (struct dummy_chip *)drv->private; - - /* Reset parameters. */ - dummy_chip_reset(drv); - - /* Register ourselves with the midlevel audio driver. */ - err = register_sparcaudio_driver(drv, 2); - - if (err < 0) { - printk(KERN_ERR "dummy: unable to register\n"); - kfree(drv->private); - return -EIO; - } - - dummy_chip->perchip_info.play.active = - dummy_chip->perchip_info.play.pause = 0; - - dummy_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | - AUDIO_SPEAKER | - AUDIO_LINE_OUT); + /* Allocate our private information structure. */ + drv->private = kmalloc(sizeof(struct dummy_chip), GFP_KERNEL); + if (drv->private == NULL) + return -ENOMEM; + + /* Point at the information structure and initialize it. */ + drv->ops = &dummy_ops; + dummy_chip = (struct dummy_chip *) drv->private; + + /* Reset parameters. */ + dummy_chip_reset(drv); + + /* Register ourselves with the midlevel audio driver. */ + err = register_sparcaudio_driver(drv, 2); + + if (err < 0) { + printk(KERN_ERR "dummy: unable to register\n"); + kfree(drv->private); + return -EIO; + } + + dummy_chip->perchip_info.play.active = + dummy_chip->perchip_info.play.pause = 0; + + dummy_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE | + AUDIO_SPEAKER | + AUDIO_LINE_OUT); - /* Announce the hardware to the user. */ - printk(KERN_INFO "audio%d: dummy at 0x0 irq 0\n", drv->index); + /* Announce the hardware to the user. */ + printk(KERN_INFO "audio%d: dummy at 0x0 irq 0\n", drv->index); - /* Success! */ - return 0; + /* Success! */ + return 0; } #ifdef MODULE /* Detach from an dummy chip given the device structure. */ static void dummy_detach(struct sparcaudio_driver *drv) { - unregister_sparcaudio_driver(drv, 2); - kfree(drv->private); + unregister_sparcaudio_driver(drv, 2); + kfree(drv->private); } void cleanup_module(void) { - register int i; + int i; - for (i = 0; i < num_drivers; i++) { - dummy_detach(&drivers[i]); - num_drivers--; - } + for (i = 0; i < num_drivers; i++) { + dummy_detach(&drivers[i]); + num_drivers--; + } } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dummy.h linux/drivers/sbus/audio/dummy.h --- v2.3.34/linux/drivers/sbus/audio/dummy.h Mon Mar 15 16:11:30 1999 +++ linux/drivers/sbus/audio/dummy.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: dummy.h,v 1.3 1999/09/21 14:37:41 davem Exp $ * drivers/sbus/audio/dummy.h * * Copyright (C) 1998 Derrick J. Brashear (shadow@dementia.org) @@ -15,9 +15,9 @@ /* Our structure for each chip */ struct dummy_chip { - struct audio_info perchip_info; - unsigned int playlen; - struct tq_struct tqueue; + struct audio_info perchip_info; + unsigned int playlen; + struct tq_struct tqueue; }; #define DUMMY_MIN_ATEN (0) @@ -38,4 +38,4 @@ #define DUMMY_RATE (8000) /* default sample rate */ -#endif +#endif /* _DUMMY_H_ */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in --- v2.3.34/linux/drivers/sbus/char/Config.in Mon Nov 1 13:56:26 1999 +++ linux/drivers/sbus/char/Config.in Mon Dec 20 22:06:42 1999 @@ -14,6 +14,7 @@ tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA tristate 'Tadpole TS102 Microcontroller support (EXPERIMENTAL)' CONFIG_TADPOLE_TS102_UCTRL + tristate 'JavaStation OS Flash SIMM (EXPERIMENTAL)' CONFIG_SUN_JSFLASH # XXX Why don't we do "source drivers/char/Config.in" somewhere? if [ "$CONFIG_PCI" = "y" ]; then define_bool CONFIG_APM_RTC_IS_GMT y # no shit diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c --- v2.3.34/linux/drivers/sbus/char/aurora.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/char/aurora.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* +/* $Id: aurora.c,v 1.7 1999/09/21 14:37:46 davem Exp $ * linux/drivers/sbus/char/aurora.c -- Aurora multiport driver * * Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro) @@ -69,7 +69,7 @@ unsigned char irqs[4] = { 0, 0, 0, 0 - }; +}; #ifdef AURORA_INT_DEBUG int irqhit=0; @@ -108,7 +108,7 @@ static unsigned long baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 0, - }; +}; static inline int aurora_paranoia_check(struct Aurora_port const * port, kdev_t device, const char *routine) @@ -165,7 +165,7 @@ #endif /* FIXME: need something more descriptive than 100000 :) */ for (delay = 100000; delay; delay--) - if (!r->r[CD180_CCR]) + if (!sbus_readb(&r->r[CD180_CCR])) return; printk(KERN_DEBUG "aurora: Timeout waiting for CCR.\n"); } @@ -178,12 +178,13 @@ extern inline void aurora_long_delay(unsigned long delay) { unsigned long i; + #ifdef AURORA_DEBUG -printk("aurora_long_delay: start\n"); + printk("aurora_long_delay: start\n"); #endif for (i = jiffies + delay; i > jiffies; ) ; #ifdef AURORA_DEBUG -printk("aurora_long_delay: end\n"); + printk("aurora_long_delay: end\n"); #endif } @@ -194,51 +195,68 @@ int id; #ifdef AURORA_DEBUG -printk("aurora_init_CD180: start %d:%d\n",board_No(bp),chip); + printk("aurora_init_CD180: start %d:%d\n", + board_No(bp), chip); #endif save_flags(flags); cli(); - bp->r[chip]->r[CD180_CAR]=0; - bp->r[chip]->r[CD180_GSVR]=0; - aurora_wait_CCR(bp->r[chip]); /* Wait for CCR ready */ - bp->r[chip]->r[CD180_CCR]=CCR_HARDRESET; /* Reset CD180 chip */ + sbus_writeb(0, &bp->r[chip]->r[CD180_CAR]); + sbus_writeb(0, &bp->r[chip]->r[CD180_GSVR]); + + /* Wait for CCR ready */ + aurora_wait_CCR(bp->r[chip]); + + /* Reset CD180 chip */ + sbus_writeb(CCR_HARDRESET, &bp->r[chip]->r[CD180_CCR]); udelay(1); sti(); id=1000; - while((--id)&&(bp->r[chip]->r[CD180_GSVR]!=0xff))udelay(100); + while((--id) && + (sbus_readb(&bp->r[chip]->r[CD180_GSVR])!=0xff))udelay(100); if(!id) { - printk(KERN_ERR "aurora%d: Chip %d failed init.\n",board_No(bp),chip); + printk(KERN_ERR "aurora%d: Chip %d failed init.\n", + board_No(bp), chip); restore_flags(flags); return(-1); - } + } cli(); - bp->r[chip]->r[CD180_GSVR]=(board_No(bp)<<5)|((chip+1)<<3); /* Set ID for this chip */ - bp->r[chip]->r[CD180_MSMR]=0x80|bp->ACK_MINT; /* Prio for modem intr */ - bp->r[chip]->r[CD180_TSMR]=0x80|bp->ACK_TINT; /* Prio for transmitter intr */ - bp->r[chip]->r[CD180_RSMR]=0x80|bp->ACK_RINT; /* Prio for receiver intr */ + sbus_writeb((board_No(bp)<<5)|((chip+1)<<3), + &bp->r[chip]->r[CD180_GSVR]); /* Set ID for this chip */ + sbus_writeb(0x80|bp->ACK_MINT, + &bp->r[chip]->r[CD180_MSMR]); /* Prio for modem intr */ + sbus_writeb(0x80|bp->ACK_TINT, + &bp->r[chip]->r[CD180_TSMR]); /* Prio for transmitter intr */ + sbus_writeb(0x80|bp->ACK_RINT, + &bp->r[chip]->r[CD180_RSMR]); /* Prio for receiver intr */ /* Setting up prescaler. We need 4 tick per 1 ms */ - bp->r[chip]->r[CD180_PPRH]=(bp->oscfreq/(1000000/AURORA_TPS)) >> 8; - bp->r[chip]->r[CD180_PPRL]=(bp->oscfreq/(1000000/AURORA_TPS)) & 0xff; - - bp->r[chip]->r[CD180_SRCR]=SRCR_AUTOPRI|SRCR_GLOBPRI; - - id=bp->r[chip]->r[CD180_GFRCR]; - printk(KERN_INFO "aurora%d: Chip %d id %02x: ",board_No(bp),chip,id); - if(bp->r[chip]->r[CD180_SRCR]&128) - switch(id){ + sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) >> 8, + &bp->r[chip]->r[CD180_PPRH]); + sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) & 0xff, + &bp->r[chip]->r[CD180_PPRL]); + + sbus_writeb(SRCR_AUTOPRI|SRCR_GLOBPRI, + &bp->r[chip]->r[CD180_SRCR]); + + id = sbus_readb(&bp->r[chip]->r[CD180_GFRCR]); + printk(KERN_INFO "aurora%d: Chip %d id %02x: ", + board_No(bp), chip,id); + if(sbus_readb(&bp->r[chip]->r[CD180_SRCR]) & 128) { + switch (id) { case 0x82:printk("CL-CD1864 rev A\n");break; case 0x83:printk("CL-CD1865 rev A\n");break; case 0x84:printk("CL-CD1865 rev B\n");break; case 0x85:printk("CL-CD1865 rev C\n");break; default:printk("Unknown.\n"); - }else - switch(id){ + }; + } else { + switch (id) { case 0x81:printk("CL-CD180 rev B\n");break; case 0x82:printk("CL-CD180 rev C\n");break; default:printk("Unknown.\n"); }; + } restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_init_CD180: end\n"); + printk("aurora_init_CD180: end\n"); #endif return 0; } @@ -254,70 +272,85 @@ static void aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs); /* Main probing routine, also sets irq. */ -static int aurora_probe(void) { - struct linux_sbus *sbus; - struct linux_sbus_device *sdev; +static int aurora_probe(void) +{ + struct sbus_bus *sbus; + struct sbus_dev *sdev; int grrr; char buf[30]; - int bn=0; + int bn = 0; struct Aurora_board *bp; for_each_sbus(sbus) { for_each_sbusdev(sdev, sbus) { /* printk("Try: %x %s\n",sdev,sdev->prom_name);*/ if (!strcmp(sdev->prom_name, "sio16")) { - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk(KERN_INFO "aurora: sio16 at %p\n",sdev); - #endif - prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev); - if((sdev->reg_addrs[0].reg_size!=1)&&(sdev->reg_addrs[1].reg_size!=128)&& - (sdev->reg_addrs[2].reg_size!=128)&&(sdev->reg_addrs[3].reg_size!=4)){ - printk(KERN_ERR "aurora%d: registers' sizes do not match.\n",bn); +#endif + if((sdev->reg_addrs[0].reg_size!=1) && + (sdev->reg_addrs[1].reg_size!=128) && + (sdev->reg_addrs[2].reg_size!=128) && + (sdev->reg_addrs[3].reg_size!=4)) { + printk(KERN_ERR "aurora%d: registers' sizes " + "do not match.\n", bn); break; - } - bp=&aurora_board[bn]; - bp->r0 = (struct aurora_reg1 *) sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sdev->reg_addrs[0].reg_size, "sio16",sdev->reg_addrs[0].which_io, 0x0); - if (!bp->r0) { - printk(KERN_ERR "aurora%d: can't map reg_addrs[0]\n",bn); + } + bp = &aurora_board[bn]; + bp->r0 = (struct aurora_reg1 *) + sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "sio16"); + if (bp->r0 == NULL) { + printk(KERN_ERR "aurora%d: can't map " + "reg_addrs[0]\n", bn); break; } - #ifdef AURORA_DEBUG - printk("Map reg 0: %x\n",bp->r0); - #endif - bp->r[0] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0, - sdev->reg_addrs[1].reg_size, "sio16", sdev->reg_addrs[1].which_io, 0x0); - if (!bp->r[0]) { - printk(KERN_ERR "aurora%d: can't map reg_addrs[1]\n",bn); +#ifdef AURORA_DEBUG + printk("Map reg 0: %p\n", bp->r0); +#endif + bp->r[0] = (struct aurora_reg128 *) + sbus_ioremap(&sdev->resource[1], 0, + sdev->reg_addrs[1].reg_size, + "sio16"); + if (bp->r[0] == NULL) { + printk(KERN_ERR "aurora%d: can't map " + "reg_addrs[1]\n", bn); break; } - #ifdef AURORA_DEBUG - printk("Map reg 1: %x\n",bp->r[0]); - #endif - bp->r[1] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0, - sdev->reg_addrs[2].reg_size, "sio16", sdev->reg_addrs[2].which_io, 0x0); - if (!bp->r[1]) { - printk(KERN_ERR "aurora%d: can't map reg_addrs[2]\n",bn); +#ifdef AURORA_DEBUG + printk("Map reg 1: %p\n", bp->r[0]); +#endif + bp->r[1] = (struct aurora_reg128 *) + sbus_ioremap(&sdev->resource[2], 0, + sdev->reg_addrs[2].reg_size, + "sio16"); + if (bp->r[1] == NULL) { + printk(KERN_ERR "aurora%d: can't map " + "reg_addrs[2]\n", bn); break; } - #ifdef AURORA_DEBUG - printk("Map reg 2: %x\n",bp->r[1]); - #endif - bp->r3 = (struct aurora_reg4 *) sparc_alloc_io(sdev->reg_addrs[3].phys_addr, 0, - sdev->reg_addrs[3].reg_size, "sio16", sdev->reg_addrs[3].which_io, 0x0); - if (!bp->r3) { - printk(KERN_ERR "aurora%d: can't map reg_addrs[3]\n",bn); +#ifdef AURORA_DEBUG + printk("Map reg 2: %p\n", bp->r[1]); +#endif + bp->r3 = (struct aurora_reg4 *) + sbus_ioremap(&sdev->resource[3], 0, + sdev->reg_addrs[3].reg_size, + "sio16"); + if (bp->r3 == NULL) { + printk(KERN_ERR "aurora%d: can't map " + "reg_addrs[3]\n", bn); break; } - #ifdef AURORA_DEBUG - printk("Map reg 3: %x\n",bp->r3); - #endif +#ifdef AURORA_DEBUG + printk("Map reg 3: %p\n", bp->r3); +#endif /* Variables setup */ bp->flags = 0; - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG grrr=prom_getint(sdev->prom_node,"intr"); - printk("intr pri %d\n",grrr); - #endif + printk("intr pri %d\n", grrr); +#endif if ((bp->irq=irqs[bn]) && valid_irq(bp->irq) && !request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) { free_irq(bp->irq|0x30, bp); @@ -395,42 +428,44 @@ static void aurora_release_io_range(struct Aurora_board *bp) { -sparc_free_io(bp->r0,1); -sparc_free_io(bp->r[0],128); -sparc_free_io(bp->r[1],128); -sparc_free_io(bp->r3,4); + sbus_iounmap((unsigned long)bp->r0, 1); + sbus_iounmap((unsigned long)bp->r[0], 128); + sbus_iounmap((unsigned long)bp->r[1], 128); + sbus_iounmap((unsigned long)bp->r3, 4); } extern inline void aurora_mark_event(struct Aurora_port * port, int event) { #ifdef AURORA_DEBUG -printk("aurora_mark_event: start\n"); + printk("aurora_mark_event: start\n"); #endif set_bit(event, &port->event); queue_task(&port->tqueue, &tq_aurora); mark_bh(AURORA_BH); #ifdef AURORA_DEBUG -printk("aurora_mark_event: end\n"); + printk("aurora_mark_event: end\n"); #endif } -extern inline struct Aurora_port * aurora_get_port(struct Aurora_board const * bp, - int chip, unsigned char const * what) +static __inline__ struct Aurora_port * aurora_get_port(struct Aurora_board const * bp, + int chip, + unsigned char const *what) { unsigned char channel; struct Aurora_port * port; - channel = (chip<<3)|((bp->r[chip]->r[CD180_GSCR]&GSCR_CHAN)>>GSCR_CHAN_OFF); + channel = ((chip << 3) | + ((sbus_readb(&bp->r[chip]->r[CD180_GSCR]) & GSCR_CHAN) >> GSCR_CHAN_OFF)); port = &aurora_port[board_No(bp) * AURORA_NPORT * AURORA_NCD180 + channel]; - if (port->flags & ASYNC_INITIALIZED) { + if (port->flags & ASYNC_INITIALIZED) return port; - } + printk(KERN_DEBUG "aurora%d: %s interrupt from invalid port %d\n", board_No(bp), what, channel); return NULL; } -extern inline void aurora_receive_exc(struct Aurora_board const * bp, int chip) +static void aurora_receive_exc(struct Aurora_board const * bp, int chip) { struct Aurora_port *port; struct tty_struct *tty; @@ -442,15 +477,15 @@ tty = port->tty; if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - #ifdef AURORA_INTNORM +#ifdef AURORA_INTNORM printk("aurora%d: port %d: Working around flip buffer overflow.\n", board_No(bp), port_No(port)); - #endif +#endif return; } #ifdef AURORA_REPORT_OVERRUN - status = bp->r[chip]->r[CD180_RCSR]; + status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]); if (status & RCSR_OE) { port->overrun++; #if 1 @@ -460,12 +495,12 @@ } status &= port->mark_mask; #else - status = bp->r[chip]->r[CD180_RCSR] & port->mark_mask; + status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]) & port->mark_mask; #endif - ch = bp->r[chip]->r[CD180_RDR]; - if (!status) { + ch = sbus_readb(&bp->r[chip]->r[CD180_RDR]); + if (!status) return; - } + if (status & RCSR_TOUT) { /* printk("aurora%d: port %d: Receiver timeout. Hardware problems ?\n", board_No(bp), port_No(port));*/ @@ -495,7 +530,7 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -extern inline void aurora_receive(struct Aurora_board const * bp, int chip) +static void aurora_receive(struct Aurora_board const * bp, int chip) { struct Aurora_port *port; struct tty_struct *tty; @@ -506,7 +541,7 @@ tty = port->tty; - count = bp->r[chip]->r[CD180_RDCR]; + count = sbus_readb(&bp->r[chip]->r[CD180_RDCR]); #ifdef AURORA_REPORT_FIFO port->hits[count > 8 ? 9 : count]++; @@ -514,13 +549,13 @@ while (count--) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - #ifdef AURORA_INTNORM +#ifdef AURORA_INTNORM printk("aurora%d: port %d: Working around flip buffer overflow.\n", board_No(bp), port_No(port)); - #endif +#endif break; } - cnt=bp->r[chip]->r[CD180_RDR]; + cnt = sbus_readb(&bp->r[chip]->r[CD180_RDR]); *tty->flip.char_buf_ptr++ = cnt; *tty->flip.flag_buf_ptr++ = 0; tty->flip.count++; @@ -528,13 +563,12 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -extern inline void aurora_transmit(struct Aurora_board const * bp, int chip) +static void aurora_transmit(struct Aurora_board const * bp, int chip) { struct Aurora_port *port; struct tty_struct *tty; unsigned char count; - if (!(port = aurora_get_port(bp, chip, "Transmit"))) return; @@ -542,41 +576,53 @@ if (port->SRER & SRER_TXEMPTY) { /* FIFO drained */ - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); port->SRER &= ~SRER_TXEMPTY; - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); return; } if ((port->xmit_cnt <= 0 && !port->break_length) || tty->stopped || tty->hw_stopped) { - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); port->SRER &= ~SRER_TXRDY; - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, + &bp->r[chip]->r[CD180_SRER]); return; } if (port->break_length) { if (port->break_length > 0) { if (port->COR2 & COR2_ETC) { - bp->r[chip]->r[CD180_TDR]=CD180_C_ESC; - bp->r[chip]->r[CD180_TDR]=CD180_C_SBRK; + sbus_writeb(CD180_C_ESC, + &bp->r[chip]->r[CD180_TDR]); + sbus_writeb(CD180_C_SBRK, + &bp->r[chip]->r[CD180_TDR]); port->COR2 &= ~COR2_ETC; } count = MIN(port->break_length, 0xff); - bp->r[chip]->r[CD180_TDR]=CD180_C_ESC; - bp->r[chip]->r[CD180_TDR]=CD180_C_DELAY; - bp->r[chip]->r[CD180_TDR]=count; + sbus_writeb(CD180_C_ESC, + &bp->r[chip]->r[CD180_TDR]); + sbus_writeb(CD180_C_DELAY, + &bp->r[chip]->r[CD180_TDR]); + sbus_writeb(count, + &bp->r[chip]->r[CD180_TDR]); if (!(port->break_length -= count)) port->break_length--; } else { - bp->r[chip]->r[CD180_TDR]=CD180_C_ESC; - bp->r[chip]->r[CD180_TDR]=CD180_C_EBRK; - bp->r[chip]->r[CD180_COR2]=port->COR2; + sbus_writeb(CD180_C_ESC, + &bp->r[chip]->r[CD180_TDR]); + sbus_writeb(CD180_C_EBRK, + &bp->r[chip]->r[CD180_TDR]); + sbus_writeb(port->COR2, + &bp->r[chip]->r[CD180_COR2]); aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_CORCHG2; + sbus_writeb(CCR_CORCHG2, + &bp->r[chip]->r[CD180_CCR]); port->break_length = 0; } return; @@ -584,23 +630,27 @@ count = CD180_NFIFO; do { - bp->r[chip]->r[CD180_TDR]=port->xmit_buf[port->xmit_tail++]; + u8 byte = port->xmit_buf[port->xmit_tail++]; + + sbus_writeb(byte, &bp->r[chip]->r[CD180_TDR]); port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); if (--port->xmit_cnt <= 0) break; } while (--count > 0); if (port->xmit_cnt <= 0) { - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); port->SRER &= ~SRER_TXRDY; - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, + &bp->r[chip]->r[CD180_SRER]); } if (port->xmit_cnt <= port->wakeup_chars) aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); } -extern inline void aurora_check_modem(struct Aurora_board const * bp, int chip) +static void aurora_check_modem(struct Aurora_board const * bp, int chip) { struct Aurora_port *port; struct tty_struct *tty; @@ -611,9 +661,9 @@ tty = port->tty; - mcr = bp->r[chip]->r[CD180_MCR]; + mcr = sbus_readb(&bp->r[chip]->r[CD180_MCR]); if (mcr & MCR_CDCHG) { - if (bp->r[chip]->r[CD180_MSVR] & MSVR_CD) + if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD) wake_up_interruptible(&port->open_wait); else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && (port->flags & ASYNC_CALLOUT_NOHUP))) @@ -635,7 +685,7 @@ tty->hw_stopped = 1; port->SRER &= ~SRER_TXRDY; } - bp->r[chip]->r[CD180_SRER, port->SRER); + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } if (mcr & MCR_DSRCHG) { if (aurora_in(bp, CD180_MSVR) & MSVR_DSR) { @@ -647,12 +697,12 @@ tty->hw_stopped = 1; port->SRER &= ~SRER_TXRDY; } - bp->r[chip]->r[CD180_SRER, port->SRER); + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } #endif AURORA_BRAIN_DAMAGED_CTS */ /* Clear change bits */ - bp->r[chip]->r[CD180_MCR]=0; + sbus_writeb(0, &bp->r[chip]->r[CD180_MCR]); } /* The main interrupt processing routine */ @@ -661,178 +711,177 @@ unsigned char status; unsigned char ack,chip/*,chip_id*/; struct Aurora_board * bp = (struct Aurora_board *) dev_id; - unsigned long loop=0; + unsigned long loop = 0; - #ifdef AURORA_INT_DEBUG +#ifdef AURORA_INT_DEBUG printk("IRQ%d %d\n",irq,++irqhit); - #ifdef AURORA_FLOODPRO +#ifdef AURORA_FLOODPRO if (irqhit>=AURORA_FLOODPRO) - bp->r0->r=8; - #endif - #endif + sbus_writeb(8, &bp->r0->r); +#endif +#endif /* old bp = IRQ_to_board[irq&0x0f];*/ - if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE)) { + if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE)) return; - } /* The while() below takes care of this. - status=bp->r[0]->r[CD180_SRSR]; - #ifdef AURORA_INT_DEBUG - printk("mumu: %02x\n",status); - #endif - if (!(status&SRSR_ANYINT)) return; * Nobody has anything to say, so exit * + status = sbus_readb(&bp->r[0]->r[CD180_SRSR]); +#ifdef AURORA_INT_DEBUG + printk("mumu: %02x\n", status); +#endif + if (!(status&SRSR_ANYINT)) + return; * Nobody has anything to say, so exit * */ - while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){ - #ifdef AURORA_INT_DEBUG - printk("SRSR: %02x\n",status); - #endif - if (status&SRSR_REXT) { - ack=bp->r3->r[bp->ACK_RINT]; - #ifdef AURORA_INT_DEBUG - printk("R-ACK %02x\n",ack); - #endif - if ((ack>>5)==board_No(bp)) { + while ((loop++ < 48) && + (status = sbus_readb(&bp->r[0]->r[CD180_SRSR]) & SRSR_ANYINT)){ +#ifdef AURORA_INT_DEBUG + printk("SRSR: %02x\n", status); +#endif + if (status & SRSR_REXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]); +#ifdef AURORA_INT_DEBUG + printk("R-ACK %02x\n", ack); +#endif + if ((ack >> 5) == board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_RGD) { aurora_receive(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; - } else - if ((ack&GSVR_ITMASK)==GSVR_IT_REXC) { + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); + } else if ((ack & GSVR_ITMASK) == GSVR_IT_REXC) { aurora_receive_exc(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); } } } - } else - if (status&SRSR_TEXT) { - ack=bp->r3->r[bp->ACK_TINT]; - #ifdef AURORA_INT_DEBUG - printk("T-ACK %02x\n",ack); - #endif - if ((ack>>5)==board_No(bp)) { + } else if (status & SRSR_TEXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]); +#ifdef AURORA_INT_DEBUG + printk("T-ACK %02x\n", ack); +#endif + if ((ack >> 5) == board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_TX) { aurora_transmit(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); } } } - } else - if (status&SRSR_MEXT) { - ack=bp->r3->r[bp->ACK_MINT]; - #ifdef AURORA_INT_DEBUG - printk("M-ACK %02x\n",ack); - #endif - if ((ack>>5)==board_No(bp)) { - if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { + } else if (status & SRSR_MEXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]); +#ifdef AURORA_INT_DEBUG + printk("M-ACK %02x\n", ack); +#endif + if ((ack >> 5) == board_No(bp)) { + if ((chip = ((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_MDM) { aurora_check_modem(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); } } } } } -/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. +/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. */ +#if 0 while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){ - #ifdef AURORA_INT_DEBUG +#ifdef AURORA_INT_DEBUG printk("SRSR: %02x\n",status); - #endif - ack=bp->r3->r[0]; - #ifdef AURORA_INT_DEBUG +#endif + ack = sbus_readb(&bp->r3->r[0]); +#ifdef AURORA_INT_DEBUG printk("ACK: %02x\n",ack); - #endif +#endif if ((ack>>5)==board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { ack&=GSVR_ITMASK; if (ack==GSVR_IT_RGD) { aurora_receive(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; - } else - if (ack==GSVR_IT_REXC) { + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); + } else if (ack==GSVR_IT_REXC) { aurora_receive_exc(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; - } else - if (ack==GSVR_IT_TX) { + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); + } else if (ack==GSVR_IT_TX) { aurora_transmit(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; - } else - if (ack==GSVR_IT_MDM) { + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); + } else if (ack==GSVR_IT_MDM) { aurora_check_modem(bp,chip); - bp->r[chip]->r[CD180_EOSRR]=0; + sbus_writeb(0, + &bp->r[chip]->r[CD180_EOSRR]); } } } } -*/ -/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. -for(chip=0;chipr[chip]->r[CD180_SRSR]) & - (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) { +#endif - if (status & SRSR_REXT) { - ack = bp->r3->r[bp->ACK_RINT]; - if (ack == (chip_id | GSVR_IT_RGD)){ - #ifdef AURORA_INTMSG - printk("RX ACK\n"); - #endif - aurora_receive(bp,chip); - } - else if (ack == (chip_id | GSVR_IT_REXC)){ - #ifdef AURORA_INTMSG - printk("RXC ACK\n"); - #endif - aurora_receive_exc(bp,chip); +/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. */ +#if 0 + for(chip=0;chipr[chip]->r[CD180_SRSR])) & + (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) { + + if (status & SRSR_REXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]); + if (ack == (chip_id | GSVR_IT_RGD)) { +#ifdef AURORA_INTMSG + printk("RX ACK\n"); +#endif + aurora_receive(bp,chip); + } else if (ack == (chip_id | GSVR_IT_REXC)) { +#ifdef AURORA_INTMSG + printk("RXC ACK\n"); +#endif + aurora_receive_exc(bp,chip); + } else { +#ifdef AURORA_INTNORM + printk("aurora%d-%d: Bad receive ack 0x%02x.\n", + board_No(bp), chip, ack); +#endif } - else - #ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad receive ack 0x%02x.\n", - board_No(bp), chip, ack) - #endif - ; - - } else if (status & SRSR_TEXT) { - ack = bp->r3->r[bp->ACK_TINT]; - if (ack == (chip_id | GSVR_IT_TX)){ - #ifdef AURORA_INTMSG - printk("TX ACK\n"); - #endif - aurora_transmit(bp,chip); + } else if (status & SRSR_TEXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]); + if (ack == (chip_id | GSVR_IT_TX)){ +#ifdef AURORA_INTMSG + printk("TX ACK\n"); +#endif + aurora_transmit(bp,chip); + } else { +#ifdef AURORA_INTNORM + printk("aurora%d-%d: Bad transmit ack 0x%02x.\n", + board_No(bp), chip, ack); +#endif } - else{ - #ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad transmit ack 0x%02x.\n", - board_No(bp), chip, ack); - #endif - } - - } else if (status & SRSR_MEXT) { - ack = bp->r3->r[bp->ACK_MINT]; - if (ack == (chip_id | GSVR_IT_MDM)){ - #ifdef AURORA_INTMSG - printk("MDM ACK\n"); - #endif - aurora_check_modem(bp,chip); + } else if (status & SRSR_MEXT) { + ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]); + if (ack == (chip_id | GSVR_IT_MDM)){ +#ifdef AURORA_INTMSG + printk("MDM ACK\n"); +#endif + aurora_check_modem(bp,chip); + } else { +#ifdef AURORA_INTNORM + printk("aurora%d-%d: Bad modem ack 0x%02x.\n", + board_No(bp), chip, ack); +#endif } - else - #ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad modem ack 0x%02x.\n", - board_No(bp), chip, ack) - #endif - ; - + } + sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } - bp->r[chip]->r[CD180_EOSRR]=0; } - } -*/ +#endif } - #ifdef AURORA_INT_DEBUG static void aurora_timer (unsigned long ignored); @@ -847,12 +896,15 @@ save_flags(flags); cli(); -printk("SRSR: %02x,%02x - ",aurora_board[0].r[0]->r[CD180_SRSR],aurora_board[0].r[1]->r[CD180_SRSR]); -for(i=0;i<4;i++){ - udelay(1); - printk("%02x ",aurora_board[0].r3->r[i]); + printk("SRSR: %02x,%02x - ", + sbus_readb(&aurora_board[0].r[0]->r[CD180_SRSR]), + sbus_readb(&aurora_board[0].r[1]->r[CD180_SRSR])); + for (i = 0; i < 4; i++) { + udelay(1); + printk("%02x ", + sbus_readb(&aurora_board[0].r3->r[i])); } -printk("\n"); + printk("\n"); aurora_poll_timer.expires = jiffies + 300; add_timer (&aurora_poll_timer); @@ -866,59 +918,63 @@ */ /* Called with disabled interrupts */ -extern inline int aurora_setup_board(struct Aurora_board * bp) +static int aurora_setup_board(struct Aurora_board * bp) { int error; #ifdef AURORA_ALLIRQ int i; - for(i=0;iirq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp); - if (error){ - printk(KERN_ERR "IRQ request error %d\n",error); + error = request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, + "sio16", bp); + if (error) { + printk(KERN_ERR "IRQ request error %d\n", error); return error; } #endif /* Board reset */ - bp->r0->r=0; + sbus_writeb(0, &bp->r0->r); udelay(1); - if(bp->flags&AURORA_BOARD_TYPE_2){ + if (bp->flags & AURORA_BOARD_TYPE_2) { /* unknown yet */ } else { - bp->r0->r=AURORA_CFG_ENABLE_IO|AURORA_CFG_ENABLE_IRQ|(((bp->irq)&0x0f)>>2); + sbus_writeb((AURORA_CFG_ENABLE_IO | AURORA_CFG_ENABLE_IRQ | + (((bp->irq)&0x0f)>>2)), + &bp->r0->r); } udelay(10000); if (aurora_init_CD180(bp,0))error=1;error=0; if (aurora_init_CD180(bp,1))error++; - if (error==AURORA_NCD180) { + if (error == AURORA_NCD180) { printk(KERN_ERR "Both chips failed initialisation.\n"); return -EIO; - } + } #ifdef AURORA_INT_DEBUG - aurora_poll_timer.expires=jiffies+1; + aurora_poll_timer.expires= jiffies + 1; add_timer(&aurora_poll_timer); #endif #ifdef AURORA_DEBUG -printk("aurora_setup_board: end\n"); + printk("aurora_setup_board: end\n"); #endif return 0; } /* Called with disabled interrupts */ -extern inline void aurora_shutdown_board(struct Aurora_board *bp) +static void aurora_shutdown_board(struct Aurora_board *bp) { int i; #ifdef AURORA_DEBUG -printk("aurora_shutdown_board: start\n"); + printk("aurora_shutdown_board: start\n"); #endif #ifdef AURORA_INT_DEBUG @@ -926,9 +982,9 @@ #endif #ifdef AURORA_ALLIRQ -for(i=0;iirq|0x30, bp); @@ -936,21 +992,20 @@ #endif /* Drop all DTR's */ for(i=0;i<16;i++){ - bp->r[i>>3]->r[CD180_CAR]=i&7; + sbus_writeb(i & 7, &bp->r[i>>3]->r[CD180_CAR]); udelay(1); - bp->r[i>>3]->r[CD180_MSVR]=0; + sbus_writeb(0, &bp->r[i>>3]->r[CD180_MSVR]); udelay(1); - } + } /* Board shutdown */ - bp->r0->r=0; + sbus_writeb(0, &bp->r0->r); #ifdef AURORA_DEBUG -printk("aurora_shutdown_board: end\n"); + printk("aurora_shutdown_board: end\n"); #endif } -/* - * Setting up port characteristics. +/* Setting up port characteristics. * Must be called with disabled interrupts */ static void aurora_change_speed(struct Aurora_board *bp, struct Aurora_port *port) @@ -962,12 +1017,12 @@ unsigned char mcor1 = 0, mcor2 = 0,chip; #ifdef AURORA_DEBUG -printk("aurora_change_speed: start\n"); + printk("aurora_change_speed: start\n"); #endif if (!(tty = port->tty) || !tty->termios) return; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); port->SRER = 0; port->COR2 = 0; @@ -990,25 +1045,26 @@ } /* Select port on the board */ - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); if (!baud_table[baud]) { /* Drop DTR & exit */ port->MSVR &= ~(bp->DTR|bp->RTS); - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, + &bp->r[chip]->r[CD180_MSVR]); return; } else { /* Set DTR on */ port->MSVR |= bp->DTR; - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, + &bp->r[chip]->r[CD180_MSVR]); } - /* - * Now we must calculate some speed depended things - */ + /* Now we must calculate some speed dependant things. */ - /* Set baud rate for port */ + /* Set baud rate for port. */ tmp = (((bp->oscfreq + baud_table[baud]/2) / baud_table[baud] + CD180_TPC/2) / CD180_TPC); @@ -1016,10 +1072,12 @@ if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/ /* printk("Prescaler period: %d\n",tmp);*/ - bp->r[chip]->r[CD180_RBPRH]=(tmp >> 8) & 0xff; - bp->r[chip]->r[CD180_TBPRH]=(tmp >> 8) & 0xff; - bp->r[chip]->r[CD180_RBPRL]=tmp & 0xff; - bp->r[chip]->r[CD180_TBPRL]=tmp & 0xff; + sbus_writeb((tmp >> 8) & 0xff, + &bp->r[chip]->r[CD180_RBPRH]); + sbus_writeb((tmp >> 8) & 0xff, + &bp->r[chip]->r[CD180_TBPRH]); + sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]); + sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]); baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ @@ -1031,7 +1089,7 @@ /* Receiver timeout will be transmission time for 1.5 chars */ tmp = (AURORA_TPS + AURORA_TPS/2 + baud/2) / baud; tmp = (tmp > 0xff) ? 0xff : tmp; - bp->r[chip]->r[CD180_RTPR]=tmp; + sbus_writeb(tmp, &bp->r[chip]->r[CD180_RTPR]); switch (C_CSIZE(tty)) { case CS5: @@ -1094,10 +1152,14 @@ cor3 |= (COR3_FCT | COR3_SCDE); if (I_IXANY(tty)) port->COR2 |= COR2_IXM; - bp->r[chip]->r[CD180_SCHR1]=START_CHAR(tty); - bp->r[chip]->r[CD180_SCHR2]=STOP_CHAR(tty); - bp->r[chip]->r[CD180_SCHR3]=START_CHAR(tty); - bp->r[chip]->r[CD180_SCHR4]=STOP_CHAR(tty); + sbus_writeb(START_CHAR(tty), + &bp->r[chip]->r[CD180_SCHR1]); + sbus_writeb(STOP_CHAR(tty), + &bp->r[chip]->r[CD180_SCHR2]); + sbus_writeb(START_CHAR(tty), + &bp->r[chip]->r[CD180_SCHR3]); + sbus_writeb(STOP_CHAR(tty), + &bp->r[chip]->r[CD180_SCHR4]); } if (!C_CLOCAL(tty)) { /* Enable CD check */ @@ -1113,24 +1175,25 @@ /* Set input FIFO size (1-8 bytes) */ cor3 |= AURORA_RXFIFO; /* Setting up CD180 channel registers */ - bp->r[chip]->r[CD180_COR1]=cor1; - bp->r[chip]->r[CD180_COR2]=port->COR2; - bp->r[chip]->r[CD180_COR3]=cor3; + sbus_writeb(cor1, &bp->r[chip]->r[CD180_COR1]); + sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); + sbus_writeb(cor3, &bp->r[chip]->r[CD180_COR3]); /* Make CD180 know about registers change */ aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3; + sbus_writeb(CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3, + &bp->r[chip]->r[CD180_CCR]); /* Setting up modem option registers */ - bp->r[chip]->r[CD180_MCOR1]=mcor1; - bp->r[chip]->r[CD180_MCOR2]=mcor2; + sbus_writeb(mcor1, &bp->r[chip]->r[CD180_MCOR1]); + sbus_writeb(mcor2, &bp->r[chip]->r[CD180_MCOR2]); /* Enable CD180 transmitter & receiver */ aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_TXEN | CCR_RXEN; + sbus_writeb(CCR_TXEN | CCR_RXEN, &bp->r[chip]->r[CD180_CCR]); /* Enable interrupts */ - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); /* And finally set RTS on */ - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); #ifdef AURORA_DEBUG -printk("aurora_change_speed: end\n"); + printk("aurora_change_speed: end\n"); #endif } @@ -1140,7 +1203,7 @@ unsigned long flags; #ifdef AURORA_DEBUG -printk("aurora_setup_port: start %d\n",port_No(port)); + printk("aurora_setup_port: start %d\n",port_No(port)); #endif if (port->flags & ASYNC_INITIALIZED) return 0; @@ -1167,8 +1230,8 @@ #ifdef MODULE if (port->count == 1) { MOD_INC_USE_COUNT; - if((++bp->count)==1) - bp->flags|=AURORA_BOARD_ACTIVE; + if((++bp->count) == 1) + bp->flags |= AURORA_BOARD_ACTIVE; } #endif @@ -1178,7 +1241,7 @@ restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_setup_port: end\n"); + printk("aurora_setup_port: end\n"); #endif return 0; } @@ -1190,12 +1253,12 @@ unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_shutdown_port: start\n"); + printk("aurora_shutdown_port: start\n"); #endif if (!(port->flags & ASYNC_INITIALIZED)) return; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); #ifdef AURORA_REPORT_OVERRUN printk("aurora%d: port %d: Total %ld overruns were detected.\n", @@ -1221,18 +1284,22 @@ if (!(tty = port->tty) || C_HUPCL(tty)) { /* Drop DTR */ port->MSVR &= ~(bp->DTR|bp->RTS); - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, + &bp->r[chip]->r[CD180_MSVR]); } /* Select port */ - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); + /* Reset port */ aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_SOFTRESET; + sbus_writeb(CCR_SOFTRESET, &bp->r[chip]->r[CD180_CCR]); + /* Disable all interrupts from this port */ port->SRER = 0; - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); if (tty) set_bit(TTY_IO_ERROR, &tty->flags); @@ -1240,18 +1307,19 @@ #ifdef MODULE if (--bp->count < 0) { - printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: bad board count: %d\n", + printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: " + "bad board count: %d\n", board_No(bp), bp->count); bp->count = 0; } MOD_DEC_USE_COUNT; if (!bp->count) - bp->flags&=~AURORA_BOARD_ACTIVE; + bp->flags &= ~AURORA_BOARD_ACTIVE; #endif #ifdef AURORA_DEBUG -printk("aurora_shutdown_port: end\n"); + printk("aurora_shutdown_port: end\n"); #endif } @@ -1267,12 +1335,11 @@ unsigned char chip; #ifdef AURORA_DEBUG -printk("block_til_ready: start\n"); + printk("block_til_ready: start\n"); #endif - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); - /* - * If the device is in the middle of being closed, then block + /* If the device is in the middle of being closed, then block * until it's done, and then try again. */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { @@ -1283,8 +1350,7 @@ return -ERESTARTSYS; } - /* - * If non-blocking mode is set, or the port is not enabled, + /* If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ if ((filp->f_flags & O_NONBLOCK) || @@ -1302,9 +1368,8 @@ if (C_CLOCAL(tty)) do_clocal = 1; } - - /* - * Block waiting for the carrier detect and the line to become + + /* Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in * this loop, info->count is dropped by one, so that * rs_close() knows when to free things. We restore it upon @@ -1319,12 +1384,16 @@ port->blocked_open++; while (1) { cli(); - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); - CD = bp->r[chip]->r[CD180_MSVR] & MSVR_CD; + CD = sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD; if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) { port->MSVR=bp->RTS; - bp->r[chip]->r[CD180_MSVR]=port->MSVR;/* auto drops DTR */ + + /* auto drops DTR */ + sbus_writeb(port->MSVR, + &bp->r[chip]->r[CD180_MSVR]); } sti(); set_current_state(TASK_INTERRUPTIBLE); @@ -1356,7 +1425,7 @@ port->flags |= ASYNC_NORMAL_ACTIVE; #ifdef AURORA_DEBUG -printk("block_til_ready: end\n"); + printk("block_til_ready: end\n"); #endif return 0; } @@ -1369,44 +1438,46 @@ struct Aurora_board * bp; unsigned long flags; - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_open: start\n"); - #endif +#endif board = AURORA_BOARD(MINOR(tty->device)); - if (board > AURORA_NBOARD || !(aurora_board[board].flags & AURORA_BOARD_PRESENT)){ - #ifdef AURORA_DEBUG - printk("aurora_open: error board %d present %d\n",board,aurora_board[board].flags &AURORA_BOARD_PRESENT); - #endif + if (board > AURORA_NBOARD || + !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) { +#ifdef AURORA_DEBUG + printk("aurora_open: error board %d present %d\n", + board, aurora_board[board].flags & AURORA_BOARD_PRESENT); +#endif return -ENODEV; - } + } bp = &aurora_board[board]; port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(MINOR(tty->device)); - if (aurora_paranoia_check(port, tty->device, "aurora_open")){ - #ifdef AURORA_DEBUG + if (aurora_paranoia_check(port, tty->device, "aurora_open")) { +#ifdef AURORA_DEBUG printk("aurora_open: error paranoia check\n"); - #endif +#endif return -ENODEV; - } + } port->count++; tty->driver_data = port; port->tty = tty; if ((error = aurora_setup_port(bp, port))) { - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_open: error aurora_setup_port ret %d\n",error); - #endif +#endif return error; - } + } - if ((error = block_til_ready(tty, filp, port))){ - #ifdef AURORA_DEBUG + if ((error = block_til_ready(tty, filp, port))) { +#ifdef AURORA_DEBUG printk("aurora_open: error block_til_ready ret %d\n",error); - #endif +#endif return error; - } + } if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) { *tty->termios = port->normal_termios; @@ -1417,9 +1488,9 @@ port->session = current->session; port->pgrp = current->pgrp; - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_open: end\n"); - #endif +#endif return 0; } @@ -1431,14 +1502,14 @@ unsigned long timeout; unsigned char chip; - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_close: start\n"); - #endif +#endif if (!port || aurora_paranoia_check(port, tty->device, "close")) return; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); if (tty_hung_up_p(filp)) { @@ -1448,12 +1519,14 @@ bp = port_Board(port); if ((tty->count == 1) && (port->count != 1)) { - printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; tty->count is 1, port count is %d\n", + printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; " + "tty->count is 1, port count is %d\n", board_No(bp), port->count); port->count = 1; } if (--port->count < 0) { - printk(KERN_DEBUG "aurora%d: aurora_close: bad port count for tty%d: %d\n", + printk(KERN_DEBUG "aurora%d: aurora_close: bad port " + "count for tty%d: %d\n", board_No(bp), port_No(port), port->count); port->count = 0; } @@ -1462,27 +1535,27 @@ return; } port->flags |= ASYNC_CLOSING; - /* - * Save the termios structure, since this port may have + + /* Save the termios structure, since this port may have * separate termios for callout and dialin. */ if (port->flags & ASYNC_NORMAL_ACTIVE) port->normal_termios = *tty->termios; /* if (port->flags & ASYNC_CALLOUT_ACTIVE) port->callout_termios = *tty->termios;*/ - /* - * Now we wait for the transmit buffer to clear; and we notify + + /* Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE){ - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_close: waiting to flush...\n"); - #endif +#endif tty_wait_until_sent(tty, port->closing_wait); - } - /* - * At this point we stop accepting input. To do this, we + } + + /* At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the * line status register. @@ -1491,9 +1564,10 @@ if (port->flags & ASYNC_INITIALIZED) { port->SRER &= ~SRER_TXRDY; port->SRER |= SRER_TXEMPTY; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1507,9 +1581,9 @@ break; } } - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_close: shutdown_port\n"); - #endif +#endif aurora_shutdown_port(bp, port); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -1529,27 +1603,27 @@ ASYNC_CLOSING); wake_up_interruptible(&port->close_wait); restore_flags(flags); - #ifdef AURORA_DEBUG +#ifdef AURORA_DEBUG printk("aurora_close: end\n"); - #endif +#endif } static int aurora_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) + const unsigned char *buf, int count) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; int c, total = 0; unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_write: start %d\n",count); + printk("aurora_write: start %d\n",count); #endif if (aurora_paranoia_check(port, tty->device, "aurora_write")) return 0; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); bp = port_Board(port); @@ -1586,24 +1660,25 @@ if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && !(port->SRER & SRER_TXRDY)) { port->SRER |= SRER_TXRDY; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_write: end %d\n",total); + printk("aurora_write: end %d\n",total); #endif return total; } static void aurora_put_char(struct tty_struct * tty, unsigned char ch) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned long flags; #ifdef AURORA_DEBUG -printk("aurora_put_char: start %c\n",ch); + printk("aurora_put_char: start %c\n",ch); #endif if (aurora_paranoia_check(port, tty->device, "aurora_put_char")) return; @@ -1623,23 +1698,23 @@ port->xmit_cnt++; restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_put_char: end\n"); + printk("aurora_put_char: end\n"); #endif } static void aurora_flush_chars(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned long flags; unsigned char chip; /*#ifdef AURORA_DEBUG -printk("aurora_flush_chars: start\n"); + printk("aurora_flush_chars: start\n"); #endif*/ if (aurora_paranoia_check(port, tty->device, "aurora_flush_chars")) return; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf) @@ -1647,22 +1722,24 @@ save_flags(flags); cli(); port->SRER |= SRER_TXRDY; - port_Board(port)->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &port_Board(port)->r[chip]->r[CD180_CAR]); udelay(1); - port_Board(port)->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, + &port_Board(port)->r[chip]->r[CD180_SRER]); restore_flags(flags); /*#ifdef AURORA_DEBUG -printk("aurora_flush_chars: end\n"); + printk("aurora_flush_chars: end\n"); #endif*/ } static int aurora_write_room(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; int ret; #ifdef AURORA_DEBUG -printk("aurora_write_room: start\n"); + printk("aurora_write_room: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_write_room")) return 0; @@ -1671,14 +1748,14 @@ if (ret < 0) ret = 0; #ifdef AURORA_DEBUG -printk("aurora_write_room: end\n"); + printk("aurora_write_room: end\n"); #endif return ret; } static int aurora_chars_in_buffer(struct tty_struct *tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; if (aurora_paranoia_check(port, tty->device, "aurora_chars_in_buffer")) return 0; @@ -1688,11 +1765,11 @@ static void aurora_flush_buffer(struct tty_struct *tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned long flags; #ifdef AURORA_DEBUG -printk("aurora_flush_buffer: start\n"); + printk("aurora_flush_buffer: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_flush_buffer")) return; @@ -1706,7 +1783,7 @@ tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); #ifdef AURORA_DEBUG -printk("aurora_flush_buffer: end\n"); + printk("aurora_flush_buffer: end\n"); #endif } @@ -1718,31 +1795,37 @@ unsigned long flags; #ifdef AURORA_DEBUG -printk("aurora_get_modem_info: start\n"); + printk("aurora_get_modem_info: start\n"); #endif - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); bp = port_Board(port); + save_flags(flags); cli(); - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + + sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); - status = bp->r[chip]->r[CD180_MSVR]; + + status = sbus_readb(&bp->r[chip]->r[CD180_MSVR]); result = 0/*bp->r[chip]->r[AURORA_RI] & (1u << port_No(port)) ? 0 : TIOCM_RNG*/; + restore_flags(flags); + result |= ((status & bp->RTS) ? TIOCM_RTS : 0) | ((status & bp->DTR) ? TIOCM_DTR : 0) | ((status & MSVR_CD) ? TIOCM_CAR : 0) | ((status & MSVR_DSR) ? TIOCM_DSR : 0) | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + put_user(result,(unsigned long *) value); #ifdef AURORA_DEBUG -printk("aurora_get_modem_info: end\n"); + printk("aurora_get_modem_info: end\n"); #endif return 0; } static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd, - unsigned int *value) + unsigned int *value) { int error; unsigned int arg; @@ -1751,12 +1834,12 @@ unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_set_modem_info: start\n"); + printk("aurora_set_modem_info: start\n"); #endif error = get_user(arg, value); if (error) return error; - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) @@ -1778,48 +1861,56 @@ break; default: return -EINVAL; - } + }; + save_flags(flags); cli(); - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + + sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + + sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); + restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_set_modem_info: end\n"); + printk("aurora_set_modem_info: end\n"); #endif return 0; } -extern inline void aurora_send_break(struct Aurora_port * port, unsigned long length) +static void aurora_send_break(struct Aurora_port * port, unsigned long length) { struct Aurora_board *bp = port_Board(port); unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_send_break: start\n"); + printk("aurora_send_break: start\n"); #endif - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); + port->break_length = AURORA_TPS / HZ * length; port->COR2 |= COR2_ETC; port->SRER |= SRER_TXRDY; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_COR2]=port->COR2; - bp->r[chip]->r[CD180_SRER]=port->SRER; + + sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); + sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_CORCHG2; + + sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); + restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_send_break: end\n"); + printk("aurora_send_break: end\n"); #endif } -extern inline int aurora_set_serial_info(struct Aurora_port * port, - struct serial_struct * newinfo) +static int aurora_set_serial_info(struct Aurora_port * port, + struct serial_struct * newinfo) { struct serial_struct tmp; struct Aurora_board *bp = port_Board(port); @@ -1828,7 +1919,7 @@ int error; #ifdef AURORA_DEBUG -printk("aurora_set_serial_info: start\n"); + printk("aurora_set_serial_info: start\n"); #endif error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp)); if (error) @@ -1869,20 +1960,20 @@ restore_flags(flags); } #ifdef AURORA_DEBUG -printk("aurora_set_serial_info: end\n"); + printk("aurora_set_serial_info: end\n"); #endif return 0; } -extern inline int aurora_get_serial_info(struct Aurora_port * port, - struct serial_struct * retinfo) +extern int aurora_get_serial_info(struct Aurora_port * port, + struct serial_struct * retinfo) { struct serial_struct tmp; struct Aurora_board *bp = port_Board(port); int error; #ifdef AURORA_DEBUG -printk("aurora_get_serial_info: start\n"); + printk("aurora_get_serial_info: start\n"); #endif error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)); if (error) @@ -1909,18 +2000,18 @@ unsigned int cmd, unsigned long arg) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; int error; int retval; #ifdef AURORA_DEBUG -printk("aurora_ioctl: start\n"); + printk("aurora_ioctl: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_ioctl")) return -ENODEV; switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ + case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; @@ -1928,171 +2019,177 @@ if (!arg) aurora_send_break(port, HZ/4); /* 1/4 second */ return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ + case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4); return 0; - case TIOCGSOFTCAR: + case TIOCGSOFTCAR: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long)); if (error) return error; put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); + (unsigned long *) arg); return 0; - case TIOCSSOFTCAR: + case TIOCSSOFTCAR: retval = get_user(arg,(unsigned long *) arg); if (retval) return retval; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); + (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: + case TIOCMGET: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)); if (error) return error; return aurora_get_modem_info(port, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: return aurora_set_modem_info(port, cmd, (unsigned int *) arg); - case TIOCGSERIAL: + case TIOCGSERIAL: return aurora_get_serial_info(port, (struct serial_struct *) arg); - case TIOCSSERIAL: + case TIOCSSERIAL: return aurora_set_serial_info(port, (struct serial_struct *) arg); - default: + default: return -ENOIOCTLCMD; - } + }; #ifdef AURORA_DEBUG -printk("aurora_ioctl: end\n"); + printk("aurora_ioctl: end\n"); #endif return 0; } static void aurora_throttle(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_throttle: start\n"); + printk("aurora_throttle: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_throttle")) return; bp = port_Board(port); - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->MSVR &= ~bp->RTS; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); if (I_IXOFF(tty)) { aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_SSCH2; + sbus_writeb(CCR_SSCH2, &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); } - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_throttle: end\n"); + printk("aurora_throttle: end\n"); #endif } static void aurora_unthrottle(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_unthrottle: start\n"); + printk("aurora_unthrottle: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_unthrottle")) return; bp = port_Board(port); - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->MSVR |= bp->RTS; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); if (I_IXOFF(tty)) { aurora_wait_CCR(bp->r[chip]); - bp->r[chip]->r[CD180_CCR]=CCR_SSCH1; + sbus_writeb(CCR_SSCH1, + &bp->r[chip]->r[CD180_CCR]); aurora_wait_CCR(bp->r[chip]); } - bp->r[chip]->r[CD180_MSVR]=port->MSVR; + sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_unthrottle: end\n"); + printk("aurora_unthrottle: end\n"); #endif } static void aurora_stop(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_stop: start\n"); + printk("aurora_stop: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_stop")) return; bp = port_Board(port); - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); port->SRER &= ~SRER_TXRDY; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, + &bp->r[chip]->r[CD180_SRER]); restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_stop: end\n"); + printk("aurora_stop: end\n"); #endif } static void aurora_start(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; unsigned long flags; unsigned char chip; #ifdef AURORA_DEBUG -printk("aurora_start: start\n"); + printk("aurora_start: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_start")) return; bp = port_Board(port); - chip=AURORA_CD180(port_No(port)); + chip = AURORA_CD180(port_No(port)); save_flags(flags); cli(); if (port->xmit_cnt && port->xmit_buf && !(port->SRER & SRER_TXRDY)) { port->SRER |= SRER_TXRDY; - bp->r[chip]->r[CD180_CAR]=port_No(port)&7; + sbus_writeb(port_No(port) & 7, + &bp->r[chip]->r[CD180_CAR]); udelay(1); - bp->r[chip]->r[CD180_SRER]=port->SRER; + sbus_writeb(port->SRER, + &bp->r[chip]->r[CD180_SRER]); } restore_flags(flags); #ifdef AURORA_DEBUG -printk("aurora_start: end\n"); + printk("aurora_start: end\n"); #endif } @@ -2111,25 +2208,25 @@ struct tty_struct *tty; #ifdef AURORA_DEBUG -printk("do_aurora_hangup: start\n"); + printk("do_aurora_hangup: start\n"); #endif tty = port->tty; - if (!tty) + if (tty == NULL) return; tty_hangup(tty); #ifdef AURORA_DEBUG -printk("do_aurora_hangup: end\n"); + printk("do_aurora_hangup: end\n"); #endif } static void aurora_hangup(struct tty_struct * tty) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board *bp; #ifdef AURORA_DEBUG -printk("aurora_hangup: start\n"); + printk("aurora_hangup: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_hangup")) return; @@ -2143,17 +2240,17 @@ port->tty = 0; wake_up_interruptible(&port->open_wait); #ifdef AURORA_DEBUG -printk("aurora_hangup: end\n"); + printk("aurora_hangup: end\n"); #endif } static void aurora_set_termios(struct tty_struct * tty, struct termios * old_termios) { - struct Aurora_port *port = (struct Aurora_port *)tty->driver_data; + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned long flags; #ifdef AURORA_DEBUG -printk("aurora_set_termios: start\n"); + printk("aurora_set_termios: start\n"); #endif if (aurora_paranoia_check(port, tty->device, "aurora_set_termios")) return; @@ -2172,7 +2269,7 @@ aurora_start(tty); } #ifdef AURORA_DEBUG -printk("aurora_set_termios: end\n"); + printk("aurora_set_termios: end\n"); #endif } @@ -2187,9 +2284,10 @@ struct tty_struct *tty; #ifdef AURORA_DEBUG -printk("do_softint: start\n"); + printk("do_softint: start\n"); #endif - if(!(tty = port->tty)) + tty = port->tty; + if (tty == NULL) return; if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { @@ -2199,7 +2297,7 @@ wake_up_interruptible(&tty->write_wait); } #ifdef AURORA_DEBUG -printk("do_softint: end\n"); + printk("do_softint: end\n"); #endif } @@ -2209,9 +2307,10 @@ int i; #ifdef AURORA_DEBUG -printk("aurora_init_drivers: start\n"); + printk("aurora_init_drivers: start\n"); #endif - if (!(tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL))) { + tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); + if (tmp_buf == NULL) { printk(KERN_ERR "aurora: Couldn't get free page.\n"); return 1; } @@ -2249,8 +2348,9 @@ aurora_driver.start = aurora_start; aurora_driver.hangup = aurora_hangup; - if ((error = tty_register_driver(&aurora_driver))) { - free_page((unsigned long)tmp_buf); + error = tty_register_driver(&aurora_driver); + if (error) { + free_page((unsigned long) tmp_buf); printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n", error); return 1; @@ -2270,7 +2370,7 @@ init_waitqueue_head(&aurora_port[i].close_wait); } #ifdef AURORA_DEBUG -printk("aurora_init_drivers: end\n"); + printk("aurora_init_drivers: end\n"); #endif return 0; } @@ -2278,12 +2378,12 @@ static void aurora_release_drivers(void) { #ifdef AURORA_DEBUG -printk("aurora_release_drivers: start\n"); + printk("aurora_release_drivers: start\n"); #endif free_page((unsigned long)tmp_buf); tty_unregister_driver(&aurora_driver); #ifdef AURORA_DEBUG -printk("aurora_release_drivers: end\n"); + printk("aurora_release_drivers: end\n"); #endif } @@ -2297,7 +2397,7 @@ * addresses in this case. * */ -__init_func(void aurora_setup(char *str, int *ints)) +void __init aurora_setup(char *str, int *ints) { int i; @@ -2306,33 +2406,37 @@ } } -__init_func(int aurora_init(void)) +int __init aurora_init(void) #else int aurora_init(void) #endif { -int found; -int grrr,i; + int found; + int i; -printk(KERN_INFO "aurora: Driver starting.\n"); -if(aurora_init_drivers())return -EIO; -found=aurora_probe(); -if(!found){ - aurora_release_drivers(); - printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n"); - return -EIO; - } else { - printk(KERN_INFO "aurora: %d boards found.\n",found); - } -for(i=0;i +#include #ifdef __KERNEL__ @@ -88,7 +89,7 @@ #define TYPE_1_IRQS 4 unsigned char type_1_irq[TYPE_1_IRQS] = { 3, 5, 9, 13 - }; +}; /* I know something about another method of interrupt setting, but not enough. * Also, this is for another type of board, so I first have to learn how to * detect it. @@ -166,15 +167,15 @@ struct aurora_reg1 { __volatile__ unsigned char r; - }; +}; struct aurora_reg128 { __volatile__ unsigned char r[128]; - }; +}; struct aurora_reg4 { __volatile__ unsigned char r[4]; - }; +}; struct Aurora_board { unsigned long flags; @@ -197,7 +198,7 @@ unsigned char MSVDTR; unsigned char MSVRTS; /* Values for hardware acknowledge. */ - unsigned char ACK_MINT,ACK_TINT,ACK_RINT; + unsigned char ACK_MINT, ACK_TINT, ACK_RINT; }; /* Board configuration register */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c --- v2.3.34/linux/drivers/sbus/char/bpp.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/char/bpp.c Mon Dec 20 22:06:42 1999 @@ -33,7 +33,7 @@ # include /* udelay() */ # include /* OpenProm Library */ -# include /* struct linux_sbus *SBus_chain */ +# include #endif #include @@ -146,23 +146,22 @@ /* * Register block */ -struct bpp_regs { /* DMA registers */ - __volatile__ __u32 p_csr; /* DMA Control/Status Register */ - __volatile__ __u32 p_addr; /* Address Register */ - __volatile__ __u32 p_bcnt; /* Byte Count Register */ - __volatile__ __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */ +#define BPP_CSR 0x00 +#define BPP_ADDR 0x04 +#define BPP_BCNT 0x08 +#define BPP_TST_CSR 0x0C /* Parallel Port registers */ - __volatile__ __u16 p_hcr; /* Hardware Configuration Register */ - __volatile__ __u16 p_ocr; /* Operation Configuration Register */ - __volatile__ __u8 p_dr; /* Parallel Data Register */ - __volatile__ __u8 p_tcr; /* Transfer Control Register */ - __volatile__ __u8 p_or; /* Output Register */ - __volatile__ __u8 p_ir; /* Input Register */ - __volatile__ __u16 p_icr; /* Interrupt Control Register */ -}; +#define BPP_HCR 0x10 +#define BPP_OCR 0x12 +#define BPP_DR 0x14 +#define BPP_TCR 0x15 +#define BPP_OR 0x16 +#define BPP_IR 0x17 +#define BPP_ICR 0x18 +#define BPP_SIZE 0x1A -/* P_CSR. Bits of type RW1 are cleared with writting '1'. */ +/* BPP_CSR. Bits of type RW1 are cleared with writting '1'. */ #define P_DEV_ID_MASK 0xf0000000 /* R */ #define P_DEV_ID_ZEBRA 0x40000000 #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ @@ -190,12 +189,12 @@ #define P_ERR_PEND 0x00000002 /* R */ #define P_INT_PEND 0x00000001 /* R */ -/* P_HCR. Time is in increments of SBus clock. */ +/* BPP_HCR. Time is in increments of SBus clock. */ #define P_HCR_TEST 0x8000 /* Allows buried counters to be read */ #define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */ #define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */ -/* P_OCR. */ +/* BPP_OCR. */ #define P_OCR_MEM_CLR 0x8000 #define P_OCR_DATA_SRC 0x4000 /* ) */ #define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */ @@ -209,13 +208,13 @@ #define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */ #define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */ -/* P_TCR */ +/* BPP_TCR */ #define P_TCR_DIR 0x08 #define P_TCR_BUSY 0x04 #define P_TCR_ACK 0x02 #define P_TCR_DS 0x01 /* Strobe */ -/* P_OR */ +/* BPP_OR */ #define P_OR_V3 0x20 /* ) */ #define P_OR_V2 0x10 /* ) on Zebra only */ #define P_OR_V1 0x08 /* ) */ @@ -223,12 +222,12 @@ #define P_OR_AFXN 0x02 /* Auto Feed */ #define P_OR_SLCT_IN 0x01 -/* P_IR */ +/* BPP_IR */ #define P_IR_PE 0x04 #define P_IR_SLCT 0x02 #define P_IR_ERR 0x01 -/* P_ICR */ +/* BPP_ICR */ #define P_DS_IRQ 0x8000 /* RW1 */ #define P_ACK_IRQ 0x4000 /* RW1 */ #define P_BUSY_IRQ 0x2000 /* RW1 */ @@ -246,22 +245,15 @@ #define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ #define P_ERR_IRQ_EN 0x0001 /* RW */ -volatile struct bpp_regs *base_addrs[BPP_NO]; - -static inline void bpp_outb_p(__u8 data, volatile struct bpp_regs *base){ - base->p_dr = data; -} - -#define bpp_inb_p(base) bpp_inb(base) - -static inline __u8 bpp_inb(volatile struct bpp_regs *base){ - return base->p_dr; -} +unsigned long base_addrs[BPP_NO]; +#define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) +#define bpp_inb_p(base) sbus_readb((base) + BPP_DR) +#define bpp_inb(base) sbus_readb((base) + BPP_DR) static void set_pins(unsigned short pins, unsigned minor) { - volatile struct bpp_regs *base = base_addrs[minor]; + unsigned long base = base_addrs[minor]; unsigned char bits_tcr = 0, bits_or = 0; if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; @@ -271,8 +263,8 @@ if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT; if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN; - base->p_or = bits_or; - base->p_tcr = bits_tcr; + sbus_writeb(bits_or, base + BPP_OR); + sbus_writeb(bits_tcr, base + BPP_TCR); } /* @@ -282,11 +274,11 @@ */ static unsigned short get_pins(unsigned minor) { - volatile struct bpp_regs *base = base_addrs[minor]; + unsigned long base = base_addrs[minor]; unsigned short bits = 0; - unsigned value_tcr = base->p_tcr; - unsigned value_ir = base->p_ir; - unsigned value_or = base->p_or; + unsigned value_tcr = sbus_readb(base + BPP_TCR); + unsigned value_ir = sbus_readb(base + BPP_IR); + unsigned value_or = sbus_readb(base + BPP_OR); if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe; if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd; @@ -302,15 +294,6 @@ return bits; } -#if 0 -/* P3 */ -static inline void bpp_snap(const char *msg, unsigned minor) -{ - volatile struct bpp_regs *r = base_addrs[minor]; - printk("bpp.%s: c=%02x o=%02x i=%02x\n", msg, r->p_tcr, r->p_or, r->p_ir); -} -#endif - #endif /* __sparc__ */ static void bpp_wake_up(unsigned long val) @@ -940,34 +923,15 @@ #if defined(__sparc__) -static volatile struct bpp_regs *map_bpp(struct linux_sbus_device *dev, int idx) +static unsigned long map_bpp(struct sbus_dev *dev, int idx) { - volatile struct bpp_regs *regs; - - /* - * PROM reports different numbers on Zebra and on DMA2. - * We need to figure out when to apply parent ranges. - * printk will show this on different machines. - */ - - /* IPC Zebra 1.fa200000[1c] i=2 */ - prom_apply_sbus_ranges(dev->my_bus, &dev->reg_addrs[0], - dev->num_registers, dev); - - regs = sparc_alloc_io(dev->reg_addrs[0].phys_addr, 0, - dev->reg_addrs[0].reg_size, "bpp", - dev->reg_addrs[0].which_io, 0x0); - printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx, - dev->reg_addrs[0].which_io, dev->reg_addrs[0].phys_addr, - dev->reg_addrs[0].reg_size, dev->irqs[0]); - - return regs; + return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); } static int collectLptPorts(void) { - struct linux_sbus *bus; - struct linux_sbus_device *dev; + struct sbus_bus *bus; + struct sbus_dev *dev; int count; count = 0; @@ -988,7 +952,7 @@ static void probeLptPort(unsigned idx) { - volatile struct bpp_regs *rp = base_addrs[idx]; + unsigned long rp = base_addrs[idx]; __u32 csr; char *brand; @@ -1007,20 +971,23 @@ instances[idx].present = 1; instances[idx].enhanced = 1; /* Sure */ - if (((csr = rp->p_csr) & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { + csr = sbus_readl(rp + BPP_CSR); + if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { udelay(20); - csr = rp->p_csr; + csr = sbus_readl(rp + BPP_CSR); if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); } } printk("bpp%d: reset with 0x%08x ..", idx, csr); - rp->p_csr = (csr | P_RESET) & ~P_INT_EN; + sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); udelay(500); - rp->p_csr &= ~P_RESET; - printk(" done with csr=0x%08x ocr=0x%04x\n", rp->p_csr, rp->p_ocr); + sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); + csr = sbus_readl(rp + BPP_CSR); + printk(" done with csr=0x%08x ocr=0x%04x\n", + csr, sbus_readw(rp + BPP_OCR)); - switch (rp->p_csr & P_DEV_ID_MASK) { + switch (csr & P_DEV_ID_MASK) { case P_DEV_ID_ZEBRA: brand = "Zebra"; break; @@ -1030,7 +997,7 @@ default: brand = "Unknown"; } - printk("bpp%d: %s at 0x%p\n", idx, brand, rp); + printk("bpp%d: %s at 0x%lx\n", idx, brand, rp); /* * Leave the port in compat idle mode. @@ -1042,7 +1009,7 @@ static inline void freeLptPort(int idx) { - sparc_free_io ((void *)base_addrs[idx], sizeof(struct bpp_regs)); + sbus_iounmap(base_addrs[idx], BPP_SIZE); } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c --- v2.3.34/linux/drivers/sbus/char/envctrl.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/char/envctrl.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: envctrl.c,v 1.12 1999/08/31 06:58:04 davem Exp $ +/* $Id: envctrl.c,v 1.13 1999/12/19 23:28:07 davem Exp $ * envctrl.c: Temperature and Fan monitoring on Machines providing it. * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) @@ -78,6 +78,7 @@ /* PCF8584 register offsets */ #define I2C_DATA 0x00UL #define I2C_CSR 0x01UL +#define I2C_REG_SIZE 0x02UL struct i2c_device { unsigned char addr; @@ -1565,7 +1566,7 @@ return -ENODEV; } - i2c_regs = edev->resource[0].start; + i2c_regs = (unsigned long) ioremap(edev->resource[0].start, I2C_REG_SIZE); writeb(CONTROL_PIN, i2c_regs + I2C_CSR); writeb(PCF8584_ADDRESS >> 1, i2c_regs + I2C_DATA); writeb(CONTROL_PIN | CONTROL_ES1, i2c_regs + I2C_CSR); @@ -1625,6 +1626,7 @@ { envctrl_stop(); i2c_free_devices(); + iounmap(i2c_regs); misc_deregister(&envctrl_dev); } #endif diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c --- v2.3.34/linux/drivers/sbus/char/flash.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/sbus/char/flash.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.13 1999/08/31 06:58:06 davem Exp $ +/* $Id: flash.c,v 1.15 1999/12/09 00:44:22 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -55,13 +55,12 @@ return -ENXIO; } - if (vma->vm_pgoff > (size >> PAGE_SHIFT)) + if ((vma->vm_pgoff << PAGE_SHIFT) > size) return -ENXIO; - off = vma->vm_pgoff << PAGE_SHIFT; - addr += off; + addr += (vma->vm_pgoff << PAGE_SHIFT); - if (vma->vm_end - (vma->vm_start + off) > size) - size = vma->vm_end - (vma->vm_start + off); + if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size) + size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)); pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE); pgprot_val(vma->vm_page_prot) |= _PAGE_E; @@ -153,8 +152,8 @@ int __init flash_init(void) #endif { - struct linux_sbus *sbus; - struct linux_sbus_device *sdev = 0; + struct sbus_bus *sbus; + struct sbus_dev *sdev = 0; struct linux_ebus *ebus; struct linux_ebus_device *edev = 0; struct linux_prom_registers regs[2]; @@ -162,8 +161,6 @@ for_all_sbusdev(sdev, sbus) { if (!strcmp(sdev->prom_name, "flashprom")) { - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], - sdev->num_registers, sdev); if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c --- v2.3.34/linux/drivers/sbus/char/jsflash.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sbus/char/jsflash.c Mon Dec 20 22:06:42 1999 @@ -0,0 +1,415 @@ +/* + * drivers/sbus/char/jsflash.c + * + * Copyright (C) 1991, 1992 Linus Torvalds (drivers/char/mem.c) + * Copyright (C) 1997 Eddie C. Dost (drivers/sbus/char/flash.c) + * Copyright (C) 1999 Pete Zaitcev + * + * This driver is used to program OS into a Flash SIMM on + * Krups and Espresso platforms. + * + * It is anticipated that programming an OS Flash will be a routine + * procedure. In the same time it is exeedingly dangerous because + * a user can program its OBP flash with OS image and effectively + * kill the machine. + * + * This driver uses an interface different from Eddie's flash.c + * as a silly safeguard. + * + * XXX The flash.c manipulates page caching characteristics in a certain + * dubious way; also it assumes that remap_page_range() can remap + * PCI bus locations, which may be false. ioremap() must be used + * instead. We should discuss this. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if 0 /* P3 from mem.c */ +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#if 0 /* P3 from mem.c */ +#include +#include +#include +#endif + +#include /* ioctl arguments. ?? */ +#define JSFIDSZ (sizeof(struct jsflash_ident_arg)) +#define JSFPRGSZ (sizeof(struct jsflash_program_arg)) + +/* + * Our device numbers have no business in system headers. + * The only thing a user knows is the device name /dev/jsflash. + */ +#define JSF_MINOR 178 + +/* + * Access functions. + * We could ioremap(), but it's easier this way. + */ +static unsigned int jsf_inl(unsigned long addr) +{ + unsigned long retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (addr), "i" (ASI_M_BYPASS)); + return retval; +} + +static void jsf_outl(unsigned long addr, __u32 data) +{ + + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (data), "r" (addr), "i" (ASI_M_BYPASS) : + "memory"); +} + +/* + * soft carrier + */ +struct jsflash { + unsigned long base; + unsigned long size; + unsigned long busy; /* In use? */ + struct jsflash_ident_arg id; +}; + +/* + * We do not map normal memory or obio as a safety precaution. + * But offsets are real, for ease of userland programming. + */ +#define JSF_BASE_TOP 0x30000000 +#define JSF_BASE_ALL 0x20000000 + +#define JSF_BASE_JK 0x20400000 + +/* + * Let's pretend we may have several of these... + */ +static struct jsflash jsf0; + +/* + * Wait for AMD to finish its embedded algorithm. + * We use the Toggle bit DQ6 (0x40) because it does not + * depend on the data value as /DATA bit DQ7 does. + * + * XXX Do we need any timeout here? + */ +static void jsf_wait(unsigned long p) { + unsigned int x1, x2; + + for (;;) { + x1 = jsf_inl(p); + x2 = jsf_inl(p); + if ((x1 & 0x40404040) == (x2 & 0x40404040)) return; + } +} + +/* + * Programming will only work if Flash is clean, + * we leave it to the programmer application. + * + * AMD must be programmed one byte at a time; + * thus, Simple Tech SIMM must be written 4 bytes at a time. + * + * Write waits for the chip to become ready after the write + * was finished. This is done so that application would read + * consistent data after the write is done. + */ +static void jsf_write4(unsigned long fa, u32 data) { + + jsf_outl(fa, 0xAAAAAAAA); /* Unlock 1 Write 1 */ + jsf_outl(fa, 0x55555555); /* Unlock 1 Write 2 */ + jsf_outl(fa, 0xA0A0A0A0); /* Byte Program */ + jsf_outl(fa, data); + + jsf_wait(fa); +} + +/* + * The memory devices use the full 32/64 bits of the offset, and so we cannot + * check against negative addresses: they are ok. The return value is weird, + * though, in that case (0). + * + * also note that seeking relative to the "end of file" isn't supported: + * it has no meaning, so it returns -EINVAL. + */ +static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) +{ + switch (orig) { + case 0: + file->f_pos = offset; + return file->f_pos; + case 1: + file->f_pos += offset; + return file->f_pos; + default: + return -EINVAL; + } +} + +/* + * P3: OS SIMM Cannot be read in other size but a 32bits word. + */ +static ssize_t jsf_read(struct file * file, char * buf, + size_t togo, loff_t *ppos) +{ + unsigned long p = *ppos; + char *tmp = buf; + + union byte4 { + char s[4]; + unsigned int n; + } b; + + if (verify_area(VERIFY_WRITE, buf, togo)) + return -EFAULT; + + if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) { + return 0; + } + + if ((p + togo) < p /* wrap */ + || (p + togo) >= JSF_BASE_TOP) { + togo = JSF_BASE_TOP - p; + } + + if (p < JSF_BASE_ALL && togo != 0) { + size_t x = JSF_BASE_ALL - p; + if (x > togo) x = togo; + clear_user(tmp, x); + tmp += x; + p += x; + togo -= x; + } + + while (togo >= 4) { + togo -= 4; + b.n = jsf_inl(p); + copy_to_user(tmp, b.s, 4); + tmp += 4; + p += 4; + } + + /* + * XXX Small togo may remain if 1 byte is ordered. + * It would be nice if we did a word size read and unpacked it. + */ + + *ppos = p; + return tmp-buf; +} + +static ssize_t jsf_write(struct file * file, const char * buf, + size_t count, loff_t *ppos) +{ + return -ENOSPC; +} + +/* + */ +static int jsf_ioctl_erase(unsigned long arg) +{ + unsigned long p; + + /* p = jsf0.base; hits wrong bank */ + p = 0x20400000; + + jsf_outl(p, 0xAAAAAAAA); /* Unlock 1 Write 1 */ + jsf_outl(p, 0x55555555); /* Unlock 1 Write 2 */ + jsf_outl(p, 0x80808080); /* Erase setup */ + jsf_outl(p, 0xAAAAAAAA); /* Unlock 2 Write 1 */ + jsf_outl(p, 0x55555555); /* Unlock 2 Write 2 */ + jsf_outl(p, 0x10101010); /* Chip erase */ + +#if 0 + /* + * This code is ok, except that counter based timeout + * has no place in this world. Let's just drop timeouts... + */ + { + int i; + __u32 x; + for (i = 0; i < 1000000; i++) { + x = jsf_inl(p); + if ((x & 0x80808080) == 0x80808080) break; + } + if ((x & 0x80808080) != 0x80808080) { + printk("jsf0: erase timeout with 0x%08x\n", x); + } else { + printk("jsf0: erase done with 0x%08x\n", x); + } + } +#else + jsf_wait(p); +#endif + + return 0; +} + +/* + * Program a block of flash. + * Very simple because we can do it byte by byte anyway. + */ +static int jsf_ioctl_program(unsigned long arg) +{ + struct jsflash_program_arg abuf; + char *uptr; + unsigned long p; + unsigned int togo; + union { + unsigned int n; + char s[4]; + } b; + + if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ)) + return -EFAULT; + copy_from_user(&abuf, (char *)arg, JSFPRGSZ); + p = abuf.off; + togo = abuf.size; + if ((togo & 3) || (p & 3)) return -EINVAL; + + uptr = (char *) abuf.data; + if (verify_area(VERIFY_READ, uptr, togo)) + return -EFAULT; + while (togo != 0) { + --togo; + copy_from_user(&b.s[0], uptr, 4); + jsf_write4(p, b.n); + p += 4; + uptr += 4; + } + + return 0; +} + +static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd, + unsigned long arg) +{ + int error = -ENOTTY; + + switch (cmd) { + case JSFLASH_IDENT: + if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ)) + return -EFAULT; + copy_to_user(arg, &jsf0.id, JSFIDSZ); + error = 0; + break; + case JSFLASH_ERASE: + error = jsf_ioctl_erase(arg); + break; + case JSFLASH_PROGRAM: + error = jsf_ioctl_program(arg); + break; + } + + return error; +} + +static int jsf_mmap(struct file * file, struct vm_area_struct * vma) +{ + return -ENXIO; +} + +static int jsf_open(struct inode * inode, struct file * filp) +{ + + if (jsf0.base == 0) return -ENXIO; + if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) + return -EBUSY; + + MOD_INC_USE_COUNT; + return 0; /* XXX What security? */ +} + +static int jsf_release(struct inode *inode, struct file *file) +{ + + MOD_DEC_USE_COUNT; + + jsf0.busy = 0; + return 0; +} + +static struct file_operations jsf_fops = { + jsf_lseek, + jsf_read, + jsf_write, + NULL, /* readdir */ + NULL, /* poll */ + jsf_ioctl, + jsf_mmap, + jsf_open, + NULL, /* flush */ + jsf_release, + NULL /* fsync */ +}; + +static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops }; + +EXPORT_NO_SYMBOLS; + +#ifdef MODULE +int init_module(void) +#else +int /* __init */ jsflash_init(void) +#endif +{ + int rc; + + /* extern enum sparc_cpu sparc_cpu_model; */ /* in */ + if (sparc_cpu_model == sun4m && jsf0.base == 0) { + /* XXX Autodetect */ + /* + * We do not want to use PROM properties; + * They are faked by PROLL anyways. + */ + jsf0.base = JSF_BASE_JK; + jsf0.size = 0x00800000; /* 8M */ + + jsf0.id.off = JSF_BASE_ALL; + jsf0.id.size = 0x01000000; /* 16M - all segments */ + strcpy(jsf0.id.name, "Krups_all"); + + printk("Espresso Flash @0x%lx\n", jsf0.base); + } + + if ((rc = misc_register(&jsf_dev)) != 0) { + printk(KERN_ERR "jsf: unable to get misc minor %d\n", + JSF_MINOR); + jsf0.base = 0; + return rc; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + + /* for (all probed units) { } */ + if (jsf0.busy) + printk("jsf0: cleaning busy unit\n"); + jsf0.base = 0; + jsf0.busy = 0; + + misc_deregister(&jsf_dev); +} +#endif diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c --- v2.3.34/linux/drivers/sbus/char/openprom.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/char/openprom.c Mon Dec 20 22:06:42 1999 @@ -31,6 +31,7 @@ #define PROMLIB_INTERNAL +#include #include #include #include @@ -43,7 +44,10 @@ #include #include #include - +#ifdef CONFIG_PCI +#include +#include +#endif /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data @@ -71,9 +75,15 @@ get_user_ret(bufsize, &info->oprom_size, -EFAULT); - if (bufsize == 0 || bufsize > OPROMMAXPARAM) + if (bufsize == 0) return -EINVAL; + /* If the bufsize is too large, just limit it. + * Fix from Jason Rappleye. + */ + if (bufsize > OPROMMAXPARAM) + bufsize = OPROMMAXPARAM; + if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL))) return -ENOMEM; memset(*opp_p, 0, sizeof(int) + bufsize + 1); @@ -138,6 +148,7 @@ unsigned long flags; int bufsize, len, error = 0; extern char saved_command_line[]; + static int cnt; if (cmd == OPROMSETOPT) bufsize = getstrings((void *)arg, &opp); @@ -194,20 +205,18 @@ buf = opp->oprom_array + strlen(opp->oprom_array) + 1; len = opp->oprom_array + bufsize - buf; - printk(KERN_DEBUG "OPROMSETOPT%s %s='%s'\n", - (cmd == OPROMSETOPT) ? "" : "2", opp->oprom_array, buf); - save_and_cli(flags); error = prom_setprop(options_node, opp->oprom_array, buf, len); restore_flags(flags); - if (error <= 0) + if (error < 0) error = -EINVAL; break; case OPROMNEXT: case OPROMCHILD: + case OPROMSETCUR: if (bufsize < sizeof(int)) { error = -EINVAL; break; @@ -216,10 +225,11 @@ node = *((int *) opp->oprom_array); save_and_cli(flags); - if (cmd == OPROMNEXT) - node = __prom_getsibling(node); - else - node = __prom_getchild(node); + switch (cmd) { + case OPROMNEXT: node = __prom_getsibling(node); break; + case OPROMCHILD: node = __prom_getchild(node); break; + case OPROMSETCUR: break; + } restore_flags(flags); data->current_node = node; @@ -229,6 +239,39 @@ error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; + case OPROMPCI2NODE: + error = -EINVAL; + + if (bufsize >= 2*sizeof(int)) { +#ifdef CONFIG_PCI + struct pci_dev *pdev; + struct pcidev_cookie *pcp; + pdev = pci_find_slot (((int *) opp->oprom_array)[0], + ((int *) opp->oprom_array)[1]); + + pcp = pdev->sysdata; + if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) { + node = pcp->prom_node; + data->current_node = node; + *((int *)opp->oprom_array) = node; + opp->oprom_size = sizeof(int); + error = copyout((void *)arg, opp, bufsize + sizeof(int)); + } +#endif + } + break; + + case OPROMPATH2NODE: + save_and_cli(flags); + node = prom_finddevice(opp->oprom_array); + restore_flags(flags); + data->current_node = node; + *((int *)opp->oprom_array) = node; + opp->oprom_size = sizeof(int); + + error = copyout((void *)arg, opp, bufsize + sizeof(int)); + break; + case OPROMGETBOOTARGS: buf = saved_command_line; @@ -248,11 +291,13 @@ case OPROMU2P: case OPROMGETCONS: case OPROMGETFBNAME: - printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n"); + if (cnt++ < 10) + printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n"); error = -EINVAL; break; default: - printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); + if (cnt++ < 10) + printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); error = -EINVAL; break; } @@ -315,6 +360,7 @@ int error, node, len; char *str, *tmp; char buffer[64]; + static int cnt; switch (cmd) { case OPIOCGET: @@ -459,7 +505,8 @@ return 0; default: - printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd); + if (cnt++ < 10) + printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd); return -EINVAL; } @@ -473,6 +520,7 @@ unsigned int cmd, unsigned long arg) { DATA *data = (DATA *) file->private_data; + static int cnt; switch (cmd) { case OPROMGETOPT: @@ -502,6 +550,9 @@ case OPROMGETCONS: case OPROMGETFBNAME: case OPROMGETBOOTARGS: + case OPROMSETCUR: + case OPROMPCI2NODE: + case OPROMPATH2NODE: if ((file->f_mode & FMODE_READ) == 0) return -EPERM; return openprom_sunos_ioctl(inode, file, cmd, arg, 0); @@ -521,7 +572,8 @@ return openprom_bsd_ioctl(inode,file,cmd,arg); default: - printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); + if (cnt++ < 10) + printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); return -EINVAL; } } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.3.34/linux/drivers/sbus/char/pcikbd.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/sbus/char/pcikbd.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.35 1999/09/01 08:09:26 davem Exp $ +/* $Id: pcikbd.c,v 1.40 1999/12/01 10:45:53 davem Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -67,8 +67,10 @@ extern void pci_setledstate(struct kbd_struct *, unsigned int); extern unsigned char pci_getledstate(void); -#ifdef __sparc_v9__ +#define pcikbd_inb(x) inb(x) +#define pcikbd_outb(v,x) outb(v,x) +#if 0 /* deadwood */ static __inline__ unsigned char pcikbd_inb(unsigned long port) { return inb(port); @@ -78,19 +80,6 @@ { outb(val, port); } - -#else - -static __inline__ unsigned char pcikbd_inb(unsigned long port) -{ - return *(volatile unsigned char *)port; -} - -static __inline__ void pcikbd_outb(unsigned char val, unsigned long port) -{ - *(volatile unsigned char *)port = val; -} - #endif static inline void kb_wait(void) @@ -487,8 +476,7 @@ char *msg; if (pcikbd_mrcoffee) { - if ((pcikbd_iobase = (unsigned long) sparc_alloc_io(0x71300060, - 0, 8, "ps2kbd-regs", 0x0, 0)) == 0) { + if ((pcikbd_iobase = (unsigned long) ioremap(0x71300060, 8)) == 0) { prom_printf("pcikbd_init_hw: cannot map\n"); return; } @@ -498,7 +486,7 @@ printk("8042: cannot register IRQ %x\n", pcikbd_irq); return; } - printk("8042(kbd): iobase[%08x] irq[%x]\n", + printk("8042(kbd): iobase[%x] irq[%x]\n", (unsigned)pcikbd_iobase, pcikbd_irq); } else { for_each_ebus(ebus) { @@ -588,7 +576,10 @@ static int aux_count = 0; static int aux_present = 0; -#ifdef __sparc_v9__ +#define pcimouse_inb(x) inb(x) +#define pcimouse_outb(v,x) outb(v,x) + +#if 0 static __inline__ unsigned char pcimouse_inb(unsigned long port) { @@ -600,18 +591,6 @@ outb(val, port); } -#else - -static __inline__ unsigned char pcimouse_inb(unsigned long port) -{ - return *(volatile unsigned char *)port; -} - -static __inline__ void pcimouse_outb(unsigned char val, unsigned long port) -{ - *(volatile unsigned char *)port = val; -} - #endif /* @@ -924,10 +903,34 @@ aux_fasync, }; +static int aux_no_open(struct inode *inode, struct file *file) +{ + return -ENODEV; +} + +struct file_operations psaux_no_fops = { + NULL, /* seek */ + NULL, + NULL, + NULL, /* readdir */ + NULL, + NULL, /* ioctl */ + NULL, /* mmap */ + aux_no_open, + NULL, /* flush */ + NULL, + NULL, + NULL, +}; + static struct miscdevice psaux_mouse = { PSMOUSE_MINOR, "ps2aux", &psaux_fops }; +static struct miscdevice psaux_no_mouse = { + PSMOUSE_MINOR, "ps2aux", &psaux_no_fops +}; + int __init pcimouse_init(void) { struct linux_ebus *ebus; @@ -937,7 +940,7 @@ if (pcikbd_mrcoffee) { if ((pcimouse_iobase = pcikbd_iobase) == 0) { printk("pcimouse_init: no 8042 given\n"); - return -ENODEV; + goto do_enodev; } pcimouse_irq = pcikbd_irq; } else { @@ -953,7 +956,7 @@ } } printk("pcimouse_init: no 8042 found\n"); - return -ENODEV; + goto do_enodev; found: pcimouse_iobase = child->resource[0].start; @@ -973,7 +976,7 @@ SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) { printk("8042: Cannot register IRQ %s\n", __irq_itoa(pcimouse_irq)); - return -ENODEV; + goto do_enodev; } printk("8042(mouse) at %lx (irq %s)\n", pcimouse_iobase, @@ -1002,10 +1005,19 @@ aux_end_atomic(); return 0; + +do_enodev: + misc_register(&psaux_no_mouse); + return -ENODEV; } +int __init pcimouse_no_init(void) +{ + misc_register(&psaux_no_mouse); + return -ENODEV; +} -int __init ps2kbd_probe(unsigned long *memory_start) +int __init ps2kbd_probe(void) { int pnode, enode, node, dnode, xnode; int kbnode = 0, msnode = 0, bnode = 0; @@ -1020,7 +1032,7 @@ len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); if (len < 0) { printk("ps2kbd_probe: no name of root node\n"); - return -ENODEV; + goto do_enodev; } if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) { pcikbd_mrcoffee = 1; /* Brain damage detected */ @@ -1033,7 +1045,7 @@ node = prom_getchild(prom_root_node); node = prom_searchsiblings(node, "aliases"); if (!node) - return -ENODEV; + goto do_enodev; len = prom_getproperty(node, "keyboard", prop, sizeof(prop)); if (len > 0) { @@ -1041,7 +1053,7 @@ kbnode = prom_finddevice(prop); } if (!kbnode) - return -ENODEV; + goto do_enodev; len = prom_getproperty(node, "mouse", prop, sizeof(prop)); if (len > 0) { @@ -1049,7 +1061,7 @@ msnode = prom_finddevice(prop); } if (!msnode) - return -ENODEV; + goto do_enodev; /* * Find matching EBus nodes... @@ -1119,11 +1131,13 @@ pnode = prom_getsibling(pnode); pnode = prom_searchsiblings(pnode, "pci"); } +do_enodev: + sunkbd_setinitfunc(pcimouse_no_init); return -ENODEV; found: - sunkbd_setinitfunc(memory_start, pcimouse_init); - sunkbd_setinitfunc(memory_start, pcikbd_init); + sunkbd_setinitfunc(pcimouse_init); + sunkbd_setinitfunc(pcikbd_init); kbd_ops.compute_shiftstate = pci_compute_shiftstate; kbd_ops.setledstate = pci_setledstate; kbd_ops.getledstate = pci_getledstate; diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.3.34/linux/drivers/sbus/char/sab82532.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/sbus/char/sab82532.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.35 1999/09/01 08:09:29 davem Exp $ +/* $Id: sab82532.c,v 1.40 1999/12/19 23:28:08 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,12 @@ static DECLARE_TASK_QUEUE(tq_serial); +/* This is (one of many) a special gross hack to allow SU and + * SAB serials to co-exist on the same machine. -DaveM + */ +#undef SERIAL_BH +#define SERIAL_BH AURORA_BH + static struct tty_driver serial_driver, callout_driver; static int sab82532_refcount; @@ -252,6 +259,9 @@ { unsigned char saved_rfc, tmp; + if (!stop_a_enabled) + return; + /* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. * Note that we must flush the user windows @@ -2129,7 +2139,7 @@ } memset(sab, 0, sizeof(struct sab82532)); - sab->regs = (union sab82532_async_regs *)(regs + offset); + sab->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs)); sab->irq = edev->irqs[0]; sab->line = 1 - i; sab->xmit_fifo_size = 32; @@ -2153,7 +2163,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.35 $"; + char *revision = "$Revision: 1.40 $"; char *version, *p; version = strchr(revision, ' '); @@ -2163,6 +2173,8 @@ printk("SAB82532 serial driver version %s\n", serial_version); } +extern int su_num_ports; + /* * The serial driver boot-time initialization code! */ @@ -2186,7 +2198,7 @@ serial_driver.driver_name = "serial"; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; - serial_driver.minor_start = 64; + serial_driver.minor_start = 64 + su_num_ports; serial_driver.num = NR_PORTS; serial_driver.type = TTY_DRIVER_TYPE_SERIAL; serial_driver.subtype = SERIAL_TYPE_NORMAL; @@ -2284,7 +2296,7 @@ printk(KERN_INFO "ttyS%02d at 0x%lx (irq = %s) is a SAB82532 %s\n", - info->line, (unsigned long)info->regs, + info->line + su_num_ports, (unsigned long)info->regs, __irq_itoa(info->irq), sab82532_version[info->type]); } @@ -2294,7 +2306,7 @@ return 0; } -int __init sab82532_probe(unsigned long *memory_start) +int __init sab82532_probe(void) { int node, enode, snode; char model[32]; @@ -2338,9 +2350,9 @@ found: #ifdef CONFIG_SERIAL_CONSOLE - sunserial_setinitfunc(memory_start, sab82532_console_init); + sunserial_setinitfunc(sab82532_console_init); #endif - sunserial_setinitfunc(memory_start, sab82532_init); + sunserial_setinitfunc(sab82532_init); rs_ops.rs_kgdb_hook = sab82532_kgdb_hook; return 0; } @@ -2356,6 +2368,7 @@ void cleanup_module(void) { + struct sab82532 *sab; unsigned long flags; int e1, e2; @@ -2378,6 +2391,8 @@ free_page((unsigned long) tmp_buf); tmp_buf = NULL; } + for (sab = sab82532_chain; sab; sab = sab->next) + iounmap(sab->regs); } #endif /* MODULE */ @@ -2575,8 +2590,9 @@ int __init sab82532_console_init(void) { extern int con_is_present(void); + extern int su_console_registered; - if (con_is_present()) + if (con_is_present() || su_console_registered) return 0; if (!sab82532_chain) { diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c --- v2.3.34/linux/drivers/sbus/char/su.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/sbus/char/su.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.28 1999/09/01 08:09:32 davem Exp $ +/* $Id: su.c,v 1.34 1999/12/02 09:55:21 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ #include #include #include +#include #include #ifdef CONFIG_SERIAL_CONSOLE #include @@ -113,6 +115,7 @@ int cflag; enum su_type port_type; /* Hookup type: e.g. mouse */ + int is_console; int port_node; char name[16]; @@ -341,7 +344,7 @@ } static __inline__ void -receive_kbd_ms_chars(struct su_struct *info, struct pt_regs *regs) +receive_kbd_ms_chars(struct su_struct *info, struct pt_regs *regs, int is_brk) { unsigned char status = 0; unsigned char ch; @@ -368,7 +371,7 @@ } sunkbd_inchar(ch, regs); } else { - sun_mouse_inbyte(ch); + sun_mouse_inbyte(ch, is_brk); } status = su_inb(info, UART_LSR); @@ -380,12 +383,15 @@ { struct tty_struct *tty = info->tty; unsigned char ch; - int ignored = 0; + int ignored = 0, saw_console_brk = 0; struct async_icount *icount; icount = &info->icount; do { ch = serial_inp(info, UART_RX); + if (info->is_console && + (ch == 0 || (*status &UART_LSR_BI))) + saw_console_brk = 1; if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; *tty->flip.char_buf_ptr = ch; @@ -461,6 +467,8 @@ printk("E%02x.R%d", *status, tty->flip.count); #endif tty_flip_buffer_push(tty); + if (saw_console_brk != 0) + batten_down_hatches(); } static __inline__ void @@ -598,8 +606,9 @@ #ifdef SERIAL_DEBUG_INTR printk("status = %x...", status); #endif - if (status & UART_LSR_DR) - receive_kbd_ms_chars(info, regs); + if ((status & UART_LSR_DR) || (status & UART_LSR_BI)) + receive_kbd_ms_chars(info, regs, + (status & UART_LSR_BI) != 0); #ifdef SERIAL_DEBUG_INTR printk("end.\n"); @@ -2214,7 +2223,7 @@ */ static __inline__ void __init show_su_version(void) { - char *revision = "$Revision: 1.28 $"; + char *revision = "$Revision: 1.34 $"; char *version, *p; version = strchr(revision, ' '); @@ -2273,8 +2282,13 @@ return; } prom_apply_obio_ranges(®0, 1); - if ((info->port = (unsigned long) sparc_alloc_io(reg0.phys_addr, - 0, reg0.reg_size, "su-regs", reg0.which_io, 0)) == 0) { + if (reg0.which_io != 0) { /* Just in case... */ + prom_printf("su: bus number nonzero: 0x%x:%x\n", + reg0.which_io, reg0.phys_addr); + return; + } + if ((info->port = (unsigned long) ioremap(reg0.phys_addr, + reg0.reg_size)) == 0) { prom_printf("su: cannot map\n"); return; } @@ -2407,6 +2421,11 @@ restore_flags(flags); } +/* This is used by the SAB driver to adjust where its minor + * numbers start, we always are probed for first. + */ +int su_num_ports = 0; + /* * The serial driver boot-time initialization code! */ @@ -2505,6 +2524,13 @@ uart_config[info->type].name); } + for (i = 0, info = su_table; i < NR_PORTS; i++, info++) + if (info->type == PORT_UNKNOWN) + break; + + su_num_ports = i; + serial_driver.num = callout_driver.num = i; + return 0; } @@ -2574,6 +2600,7 @@ } else { info->port_type = SU_PORT_PORT; } + info->is_console = 0; info->port_node = sunode; ++t->devices; } else { @@ -2582,7 +2609,7 @@ } } -int __init su_probe (unsigned long *memory_start) +int __init su_probe(void) { int node; int len; @@ -2630,20 +2657,22 @@ */ if (scan.msx != -1 && scan.kbx != -1) { su_table[0].port_type = SU_PORT_MS; + su_table[0].is_console = 0; su_table[0].port_node = scan.msnode; su_table[1].port_type = SU_PORT_KBD; + su_table[1].is_console = 0; su_table[1].port_node = scan.kbnode; - sunserial_setinitfunc(memory_start, su_kbd_ms_init); + sunserial_setinitfunc(su_kbd_ms_init); rs_ops.rs_change_mouse_baud = su_change_mouse_baud; - sunkbd_setinitfunc(memory_start, sun_kbd_init); + sunkbd_setinitfunc(sun_kbd_init); kbd_ops.compute_shiftstate = sun_compute_shiftstate; kbd_ops.setledstate = sun_setledstate; kbd_ops.getledstate = sun_getledstate; kbd_ops.setkeycode = sun_setkeycode; kbd_ops.getkeycode = sun_getkeycode; #ifdef CONFIG_PCI - sunkbd_install_keymaps(memory_start, sun_key_maps, + sunkbd_install_keymaps(sun_key_maps, sun_keymap_count, sun_func_buf, sun_func_table, sun_funcbufsize, sun_funcbufleft, sun_accent_table, sun_accent_table_size); @@ -2663,9 +2692,9 @@ * Console must be initiated after the generic initialization. * sunserial_setinitfunc inverts order, so call this before next one. */ - sunserial_setinitfunc(memory_start, su_serial_console_init); + sunserial_setinitfunc(su_serial_console_init); #endif - sunserial_setinitfunc(memory_start, su_serial_init); + sunserial_setinitfunc(su_serial_init); return 0; } @@ -2887,6 +2916,8 @@ if (su_inb(info, UART_LSR) == 0xff) return -1; + info->is_console = 1; + return 0; } @@ -2904,6 +2935,8 @@ NULL }; +int su_console_registered = 0; + /* * Register console. */ @@ -2919,6 +2952,7 @@ return 0; sercons.index = 0; register_console(&sercons); + su_console_registered = 1; return 0; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.3.34/linux/drivers/sbus/char/sunkbd.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/sbus/char/sunkbd.c Mon Dec 20 22:06:42 1999 @@ -172,6 +172,9 @@ static struct pt_regs * pt_regs; #ifdef CONFIG_MAGIC_SYSRQ +#ifndef CONFIG_PCI +int sysrq_enabled = 1; +#endif unsigned char sun_sysrq_xlate[128] = "\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0" /* 0x00 - 0x0f */ "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312" /* 0x10 - 0x1f */ @@ -545,7 +548,7 @@ #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq hack */ if (l1a_state.l1_down) { - if (!up_flag) + if (!up_flag && sysrq_enabled) handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty); goto out; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkeymap.c linux/drivers/sbus/char/sunkeymap.c --- v2.3.34/linux/drivers/sbus/char/sunkeymap.c Mon Jan 27 00:42:54 1997 +++ linux/drivers/sbus/char/sunkeymap.c Mon Dec 20 22:06:42 1999 @@ -1,3 +1,4 @@ + /* Do not edit this file! It was automatically generated by */ /* loadkeys --mktable defkeymap.map > defkeymap.c */ @@ -30,7 +31,7 @@ 0xf110, 0xf111, 0xf112, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf203, 0xf601, 0xf200, 0xf200, 0xf600, 0xf602, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026, 0xf02a, 0xf028, 0xf029, - 0xf05f, 0xf02b, 0xf07e, 0xf07f, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf05f, 0xf02b, 0xf07e, 0xf07f, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf310, 0xf200, 0xf114, 0xf009, 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf07f, 0xf20e, 0xf307, 0xf308, 0xf309, 0xf30b, @@ -38,7 +39,7 @@ 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, 0xf022, 0xf07c, 0xf201, 0xf30e, 0xf304, 0xf305, 0xf306, 0xf300, 0xf200, 0xf20b, 0xf200, 0xf208, 0xf700, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, - 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf200, + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf00a, 0xf301, 0xf302, 0xf303, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf020, 0xf200, 0xf20a, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -49,7 +50,7 @@ 0xf512, 0xf513, 0xf514, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf202, 0xf601, 0xf200, 0xf200, 0xf600, 0xf602, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, 0xf07b, 0xf05b, 0xf05d, 0xf07d, - 0xf05c, 0xf200, 0xf200, 0xf200, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf05c, 0xf200, 0xf200, 0xf200, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf310, 0xf200, 0xf114, 0xf200, 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf200, 0xf20e, 0xf911, 0xf912, 0xf913, 0xf30b, @@ -57,7 +58,7 @@ 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, 0xf200, 0xf200, 0xf201, 0xf30e, 0xf90e, 0xf90f, 0xf910, 0xf90a, 0xf200, 0xf118, 0xf200, 0xf208, 0xf700, 0xfb7a, 0xfb78, 0xf916, 0xfb76, - 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200, + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf00a, 0xf90b, 0xf90c, 0xf90d, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf200, 0xf200, 0xf119, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -68,7 +69,7 @@ 0xf106, 0xf107, 0xf108, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf204, 0xf601, 0xf200, 0xf200, 0xf600, 0xf602, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf07f, 0xf200, 0xf200, - 0xf01f, 0xf200, 0xf000, 0xf008, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf01f, 0xf200, 0xf000, 0xf008, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf310, 0xf200, 0xf114, 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf008, 0xf20e, 0xf307, 0xf308, 0xf309, 0xf30b, @@ -76,7 +77,7 @@ 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf007, 0xf01c, 0xf201, 0xf30e, 0xf304, 0xf305, 0xf306, 0xf300, 0xf200, 0xf118, 0xf200, 0xf208, 0xf700, 0xf01a, 0xf018, 0xf003, 0xf016, - 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf200, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf00a, 0xf301, 0xf302, 0xf303, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf000, 0xf200, 0xf119, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -87,7 +88,7 @@ 0xf200, 0xf200, 0xf200, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf200, 0xf601, 0xf200, 0xf200, 0xf600, 0xf602, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf01f, 0xf200, 0xf200, 0xf200, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf01f, 0xf200, 0xf200, 0xf200, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf310, 0xf200, 0xf114, 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf200, 0xf200, 0xf200, 0xf20e, 0xf307, 0xf308, 0xf309, 0xf30b, @@ -95,7 +96,7 @@ 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, 0xf200, 0xf200, 0xf201, 0xf30e, 0xf304, 0xf305, 0xf306, 0xf300, 0xf200, 0xf118, 0xf200, 0xf208, 0xf700, 0xf01a, 0xf018, 0xf003, 0xf016, - 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf00a, 0xf301, 0xf302, 0xf303, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf200, 0xf200, 0xf119, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -106,15 +107,15 @@ 0xf506, 0xf507, 0xf508, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf209, 0xf210, 0xf200, 0xf200, 0xf600, 0xf211, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, 0xf837, 0xf838, 0xf839, 0xf830, - 0xf82d, 0xf83d, 0xf860, 0xf87f, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf82d, 0xf83d, 0xf860, 0xf87f, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf310, 0xf200, 0xf114, 0xf809, 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, 0xf86f, 0xf870, - 0xf85b, 0xf85d, 0xf200, 0xf87f, 0xf907, 0xf908, 0xf909, 0xf30b, + 0xf85b, 0xf85d, 0xf87f, 0xf20e, 0xf907, 0xf908, 0xf909, 0xf30b, 0xf200, 0xf200, 0xf117, 0xf200, 0xf702, 0xf861, 0xf873, 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b, 0xf827, 0xf85c, 0xf80d, 0xf30e, 0xf904, 0xf905, 0xf906, 0xf900, 0xf200, 0xf118, 0xf200, 0xf208, 0xf700, 0xf87a, 0xf878, 0xf863, 0xf876, - 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf200, + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf00a, 0xf901, 0xf902, 0xf903, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf820, 0xf200, 0xf119, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -125,7 +126,7 @@ 0xf506, 0xf507, 0xf508, 0xf703, 0xf603, 0xf11d, 0xf200, 0xf200, 0xf601, 0xf200, 0xf200, 0xf600, 0xf602, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf115, 0xf200, 0xf30d, 0xf30c, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf115, 0xf03d, 0xf30d, 0xf30c, 0xf200, 0xf200, 0xf20c, 0xf200, 0xf114, 0xf200, 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, 0xf80f, 0xf810, 0xf200, 0xf200, 0xf20c, 0xf20e, 0xf307, 0xf308, 0xf309, 0xf30b, @@ -133,7 +134,7 @@ 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, 0xf200, 0xf200, 0xf201, 0xf30e, 0xf304, 0xf305, 0xf306, 0xf300, 0xf200, 0xf118, 0xf200, 0xf208, 0xf700, 0xf81a, 0xf818, 0xf803, 0xf816, - 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf00a, 0xf301, 0xf302, 0xf303, 0xf200, 0xf200, 0xf200, 0xf11b, 0xf207, 0xf200, 0xf200, 0xf200, 0xf119, 0xf200, 0xf30a, 0xf200, 0xf200, }; @@ -147,6 +148,7 @@ unsigned int keymap_count = 7; + /* * Philosophy: most people do not define more strings, but they who do * often want quite a lot of string space. So, we statically allocate @@ -183,6 +185,7 @@ '\033', '[', 'M', 0, '\033', '[', 'P', 0, }; + char *funcbufptr = func_buf; int funcbufsize = sizeof(func_buf); diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkeymap.map linux/drivers/sbus/char/sunkeymap.map --- v2.3.34/linux/drivers/sbus/char/sunkeymap.map Mon Jan 27 00:42:54 1997 +++ linux/drivers/sbus/char/sunkeymap.map Mon Dec 20 22:06:42 1999 @@ -160,7 +160,7 @@ alt keycode 0x41 = Meta_bracketright keycode 0x42 = Delete Delete control keycode 0x42 = BackSpace - alt keycode 0x43 = Meta_Delete + alt keycode 0x42 = Meta_Delete control alt keycode 0x42 = Boot keycode 0x43 = Compose keycode 0x44 = KP_7 diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c --- v2.3.34/linux/drivers/sbus/char/sunmouse.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/sbus/char/sunmouse.c Mon Dec 20 22:06:42 1999 @@ -81,7 +81,7 @@ unsigned int tail; union { char stream [STREAM_SIZE]; - Firm_event ev [0]; + Firm_event ev [EV_SIZE]; } queue; }; @@ -142,8 +142,6 @@ } /* Auto baud rate "detection". ;-) */ -static int mouse_bogon_bytes = 0; -static int mouse_baud_changing = 0; /* For reporting things to the user. */ static int mouse_baud = 4800; /* Initial rate set by zilog driver. */ /* Change the baud rate after receiving too many "bogon bytes". */ @@ -161,81 +159,112 @@ mouse_baud = 1200; rs_change_mouse_baud(mouse_baud); - mouse_baud_changing = 1; } -void mouse_baud_detection(unsigned char c) +/* This tries to monitor the mouse state so that it + * can automatically adjust to the correct baud rate. + * The mouse spits out BRKs when the baud rate is + * incorrect. + * + * It returns non-zero if we should ignore this byte. + */ +int mouse_baud_detection(unsigned char c, int is_break) { - static int wait_for_synchron = 1; + static int mouse_got_break = 0; static int ctr = 0; - if(wait_for_synchron) { - if((c & ~0x0f) != 0x80) - mouse_bogon_bytes++; - else { - if (c & 8) { - ctr = 2; - wait_for_synchron = 0; - } else { - ctr = 0; - wait_for_synchron = 0; - } - } - } else { + if (is_break) { + /* Let a few normal bytes go by before + * we jump the gun and say we need to + * try another baud rate. + */ + if (mouse_got_break && ctr < 8) + return 1; + + /* OK, we need to try another baud rate. */ + sun_mouse_change_baud(); + ctr = 0; + mouse_got_break = 1; + return 1; + } + if (mouse_got_break) { ctr++; - if(ctr >= 4) { - ctr = 0; - wait_for_synchron = 1; - if(mouse_baud_changing == 1) { - printk(KERN_DEBUG "sunmouse: Successfully adjusted to %d baud.\n", - mouse_baud); - mouse_baud_changing = 0; - } + if (c == 0x87) { + printk(KERN_INFO "sunmouse: Successfully " + "adjusted to %d baud.\n", mouse_baud); + mouse_got_break = 0; } + return 1; } - if(mouse_bogon_bytes > 12) { - sun_mouse_change_baud(); - mouse_bogon_bytes = 0; - wait_for_synchron = 1; - } + + return 0; } -/* The following is called from the zs driver when bytes are received on - * the Mouse zs8530 channel. +/* You ask me, why does this cap the lower bound at -127 and not + * -128? Because the xf86 mouse code is crap and treats -128 + * as an illegal value and resets it's protocol state machine + * when it sees this value. + */ +#define CLIP(__X) (((__X) > 127) ? 127 : (((__X) < -127) ? -127 : (__X))) + +/* The following is called from the serial driver when bytes/breaks + * are received on the Mouse line. */ void -sun_mouse_inbyte(unsigned char byte) +sun_mouse_inbyte(unsigned char byte, int is_break) { signed char mvalue; int d, pushed = 0; Firm_event ev; add_mouse_randomness (byte); +#if 0 + { + static int xxx = 0; + printk("mouse(%02x:%d) ", + byte, is_break); + if (byte == 0x87) { + xxx = 0; + printk("\n"); + } + } +#endif + if (mouse_baud_detection(byte, is_break)) + return; + if(!sunmouse.active) return; - mouse_baud_detection(byte); + /* Ignore this if it is garbage. */ + if (sunmouse.byte == 69) { + if (byte != 0x87) + return; - if (!gen_events){ - if (((byte & ~0x0f) == 0x80) && (byte & 0x8)) { - /* Push dummy 4th and 5th byte for last txn */ - push_char(0x0); - push_char(0x0); - } - push_char (byte); - return; + /* Ok, we've begun the state machine. */ + sunmouse.byte = 0; } - +#if 0 /* If the mouse sends us a byte from 0x80 to 0x87 * we are starting at byte zero in the transaction * protocol. */ if((byte & ~0x0f) == 0x80) sunmouse.byte = 0; +#endif mvalue = (signed char) byte; switch(sunmouse.byte) { case 0: + /* If we get a bogus button byte, just skip it. + * When we get here the baud detection code has + * passed, so the only other things which can + * cause this are dropped serial characters and + * confused mouse. We check this because otherwise + * begin posting erroneous mouse events. + */ + if ((byte & 0xf0) != 0x80) + return; + /* Button state */ sunmouse.button_state = (~byte) & 0x7; #ifdef SMOUSE_DEBUG @@ -274,6 +303,7 @@ printk("DX2<%d>", mvalue); #endif sunmouse.delta_x += mvalue; + sunmouse.delta_x = CLIP(sunmouse.delta_x); sunmouse.byte++; return; case 4: @@ -282,7 +312,8 @@ printk("DY2<%d>", mvalue); #endif sunmouse.delta_y += mvalue; - sunmouse.byte = 69; /* Some ridiculous value */ + sunmouse.delta_y = CLIP(sunmouse.delta_y); + sunmouse.byte = 0; /* Back to button state */ break; case 69: /* Until we get the (0x80 -> 0x87) value we aren't @@ -295,6 +326,12 @@ sunmouse.byte = 69; /* What could cause this? */ return; }; + if (!gen_events){ + push_char (~sunmouse.button_state & 0x87); + push_char (sunmouse.delta_x); + push_char (sunmouse.delta_y); + return; + } d = bstate ^ pstate; pstate = bstate; if (d){ @@ -405,6 +442,10 @@ if (current->thread.flags & SPARC_FLAG_32BIT) { Firm_event *q = get_from_queue(); + if ((end - p) < + ((sizeof(Firm_event) - sizeof(struct timeval) + + (sizeof(u32) * 2)))) + break; copy_to_user_ret((Firm_event *)p, q, sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); @@ -416,6 +457,8 @@ } else #endif { + if ((end - p) < sizeof(Firm_event)) + break; copy_to_user_ret((Firm_event *)p, get_from_queue(), sizeof(Firm_event), -EFAULT); p += sizeof (Firm_event); @@ -425,16 +468,25 @@ file->f_dentry->d_inode->i_atime = CURRENT_TIME; return p-buffer; } else { - int c; - - for (c = count; !queue_empty() && c; c--){ - put_user_ret(sunmouse.queue.stream[sunmouse.tail], buffer, -EFAULT); + int c, limit = 3; + + if (count < limit) + limit = count; + for (c = 0; c < limit; c++) { + put_user(sunmouse.queue.stream[sunmouse.tail], buffer); buffer++; sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE; } + while (c < count) { + if (c >= 5) + break; + put_user(0, buffer); + buffer++; + c++; + } sunmouse.ready = !queue_empty(); file->f_dentry->d_inode->i_atime = CURRENT_TIME; - return count-c; + return c; } /* Only called if nothing was sent */ if (signal_pending(current)) diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunmouse.h linux/drivers/sbus/char/sunmouse.h --- v2.3.34/linux/drivers/sbus/char/sunmouse.h Thu Sep 4 12:54:49 1997 +++ linux/drivers/sbus/char/sunmouse.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sunmouse.h,v 1.1 1997/08/28 02:23:38 ecd Exp $ +/* $Id: sunmouse.h,v 1.2 1999/11/19 09:56:34 davem Exp $ * sunmouse.h: Interface to the SUN mouse driver. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -8,6 +8,6 @@ #define _SPARC_SUNMOUSE_H 1 extern void sun_mouse_zsinit(void); -extern void sun_mouse_inbyte(unsigned char); +extern void sun_mouse_inbyte(unsigned char, int); #endif /* !(_SPARC_SUNMOUSE_H) */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c --- v2.3.34/linux/drivers/sbus/char/sunserial.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/sbus/char/sunserial.c Mon Dec 20 22:06:42 1999 @@ -1,24 +1,29 @@ -/* $Id: sunserial.c,v 1.70 1999/09/04 20:28:17 davem Exp $ +/* $Id: sunserial.c,v 1.74 1999/12/15 22:30:23 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) */ #include +#include +#include #include #include #include #include +#include #include #include #include #include +#include #include #include "sunserial.h" int serial_console; +int stop_a_enabled = 1; int __init con_is_present(void) { @@ -67,9 +72,9 @@ rs_ops.rs_kgdb_hook(channel); } -long __init serial_console_init(long kmem_start, long kmem_end) +void __init serial_console_init(void) { - return kmem_start; + return; } void rs_change_mouse_baud(int baud) @@ -168,14 +173,27 @@ return kbd_ops.getkeycode(scancode); } +void * __init sunserial_alloc_bootmem(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + void -sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void)) +sunserial_setinitfunc(int (*init) (void)) { struct initfunc *rs_init; - *memory_start = (*memory_start + 7) & ~(7); - rs_init = (struct initfunc *) *memory_start; - *memory_start += sizeof(struct initfunc); + rs_init = sunserial_alloc_bootmem(sizeof(struct initfunc)); + if (rs_init == NULL) { + prom_printf("sunserial_setinitfunc: Cannot alloc initfunc.\n"); + prom_halt(); + } rs_init->init = init; rs_init->next = rs_ops.rs_init; @@ -291,13 +309,15 @@ } void -sunkbd_setinitfunc(unsigned long *memory_start, int (*init) (void)) +sunkbd_setinitfunc(int (*init) (void)) { struct initfunc *kbd_init; - *memory_start = (*memory_start + 7) & ~(7); - kbd_init = (struct initfunc *) *memory_start; - *memory_start += sizeof(struct initfunc); + kbd_init = sunserial_alloc_bootmem(sizeof(struct initfunc)); + if (kbd_init == NULL) { + prom_printf("sunkbd_setinitfunc: Cannot alloc initfunc.\n"); + prom_halt(); + } kbd_init->init = init; kbd_init->next = kbd_ops.kbd_init; @@ -306,8 +326,7 @@ #ifdef CONFIG_PCI void -sunkbd_install_keymaps(unsigned long *memory_start, - ushort **src_key_maps, unsigned int src_keymap_count, +sunkbd_install_keymaps(ushort **src_key_maps, unsigned int src_keymap_count, char *src_func_buf, char **src_func_table, int src_funcbufsize, int src_funcbufleft, struct kbdiacr *src_accent_table, @@ -319,8 +338,13 @@ for (i = 0; i < MAX_NR_KEYMAPS; i++) { if (src_key_maps[i]) { if (!key_maps[i]) { - key_maps[i] = (ushort *)*memory_start; - *memory_start += NR_KEYS * sizeof(ushort); + key_maps[i] = (ushort *) + sunserial_alloc_bootmem(NR_KEYS * sizeof(ushort)); + if (key_maps[i] == NULL) { + prom_printf("sunkbd_install_keymaps: " + "Cannot alloc key_map(%d).\n", i); + prom_halt(); + } } for (j = 0; j < NR_KEYS; j++) key_maps[i][j] = src_key_maps[i][j]; @@ -341,16 +365,16 @@ } #endif -extern int su_probe(unsigned long *); -extern int zs_probe(unsigned long *); +extern int su_probe(void); +extern int zs_probe(void); #ifdef CONFIG_SAB82532 -extern int sab82532_probe(unsigned long *); +extern int sab82532_probe(void); #endif #ifdef CONFIG_PCI -extern int ps2kbd_probe(unsigned long *); +extern int ps2kbd_probe(void); #endif -unsigned long __init sun_serial_setup(unsigned long memory_start) +void __init sun_serial_setup(void) { int ret = 1; @@ -362,16 +386,16 @@ * get console on MrCoffee with fine but disconnected zs. */ if (!serial_console) - ps2kbd_probe(&memory_start); - if (su_probe(&memory_start) == 0) - return memory_start; + ps2kbd_probe(); + if (su_probe() == 0) + return; #endif - if (zs_probe(&memory_start) == 0) - return memory_start; + if (zs_probe() == 0) + return; #ifdef CONFIG_SAB82532 - ret = sab82532_probe(&memory_start); + ret = sab82532_probe(); #endif #if defined(CONFIG_PCI) && defined(__sparc_v9__) @@ -387,23 +411,22 @@ * serial console. */ if (!serial_console) - ps2kbd_probe(&memory_start); - if (su_probe(&memory_start) == 0) - return memory_start; + ps2kbd_probe(); + if (su_probe() == 0) + return; #endif if (!ret) - return memory_start; + return; #ifdef __sparc_v9__ { extern int this_is_starfire; /* Hello, Starfire. Pleased to meet you :) */ if(this_is_starfire != 0) - return memory_start; + return; } #endif prom_printf("No serial devices found, bailing out.\n"); prom_halt(); - return memory_start; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunserial.h linux/drivers/sbus/char/sunserial.h --- v2.3.34/linux/drivers/sbus/char/sunserial.h Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/char/sunserial.h Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sunserial.h,v 1.17 1997/12/19 07:33:12 ecd Exp $ +/* $Id: sunserial.h,v 1.19 1999/12/01 10:45:59 davem Exp $ * sunserial.h: SUN serial driver infrastructure (including keyboards). * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -37,15 +37,17 @@ extern struct sunserial_operations rs_ops; extern struct sunkbd_operations kbd_ops; -extern void sunserial_setinitfunc(unsigned long *, int (*) (void)); -extern void sunkbd_setinitfunc(unsigned long *, int (*) (void)); +extern void sunserial_setinitfunc(int (*) (void)); +extern void sunkbd_setinitfunc(int (*) (void)); extern int serial_console; +extern int stop_a_enabled; extern void sunserial_console_termios(struct console *); #ifdef CONFIG_PCI -extern void sunkbd_install_keymaps(unsigned long *, ushort **, unsigned int, char *, - char **, int, int, struct kbdiacr *, unsigned int); +extern void sunkbd_install_keymaps(ushort **, unsigned int, char *, + char **, int, int, struct kbdiacr *, + unsigned int); #endif #endif /* !(_SPARC_SUNSERIAL_H) */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c --- v2.3.34/linux/drivers/sbus/char/uctrl.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/sbus/char/uctrl.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: uctrl.c,v 1.2 1999/09/07 23:11:08 shadow Exp $ +/* $Id: uctrl.c,v 1.5 1999/12/15 15:48:24 davem Exp $ * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 * * Copyright 1999 Derrick J Brashear (shadow@dementia.org) @@ -25,13 +25,179 @@ #define UCTRL_MINOR 174 +#define DEBUG 1 +#ifdef DEBUG +#define dprintk(x) printk x +#else +#define dprintk(x) +#endif + +struct uctrl_regs { + volatile u32 uctrl_intr; + volatile u32 uctrl_data; + volatile u32 uctrl_stat; + volatile u32 uctrl_xxx[5]; +}; + +struct ts102_regs { + volatile u32 card_a_intr; + volatile u32 card_a_stat; + volatile u32 card_a_ctrl; + volatile u32 card_a_xxx; + volatile u32 card_b_intr; + volatile u32 card_b_stat; + volatile u32 card_b_ctrl; + volatile u32 card_b_xxx; + volatile u32 uctrl_intr; + volatile u32 uctrl_data; + volatile u32 uctrl_stat; + volatile u32 uctrl_xxx; + volatile u32 ts102_xxx[4]; +}; + +/* Bits for uctrl_intr register */ +#define UCTRL_INTR_TXE_REQ 0x01 /* transmit FIFO empty int req */ +#define UCTRL_INTR_TXNF_REQ 0x02 /* transmit FIFO not full int req */ +#define UCTRL_INTR_RXNE_REQ 0x04 /* receive FIFO not empty int req */ +#define UCTRL_INTR_RXO_REQ 0x08 /* receive FIFO overflow int req */ +#define UCTRL_INTR_TXE_MSK 0x10 /* transmit FIFO empty mask */ +#define UCTRL_INTR_TXNF_MSK 0x20 /* transmit FIFO not full mask */ +#define UCTRL_INTR_RXNE_MSK 0x40 /* receive FIFO not empty mask */ +#define UCTRL_INTR_RXO_MSK 0x80 /* receive FIFO overflow mask */ + +/* Bits for uctrl_stat register */ +#define UCTRL_STAT_TXE_STA 0x01 /* transmit FIFO empty status */ +#define UCTRL_STAT_TXNF_STA 0x02 /* transmit FIFO not full status */ +#define UCTRL_STAT_RXNE_STA 0x04 /* receive FIFO not empty status */ +#define UCTRL_STAT_RXO_STA 0x08 /* receive FIFO overflow status */ + +static const char *uctrl_extstatus[16] = { + "main power available", + "internal battery attached", + "external battery attached", + "external VGA attached", + "external keyboard attached", + "external mouse attached", + "lid down", + "internal battery currently charging", + "external battery currently charging", + "internal battery currently discharging", + "external battery currently discharging", +}; + +/* Everything required for one transaction with the uctrl */ +struct uctrl_txn { + u8 opcode; + u8 inbits; + u8 outbits; + u8 *inbuf; + u8 *outbuf; +}; + +struct uctrl_status { + u8 current_temp; /* 0x07 */ + u8 reset_status; /* 0x0b */ + u16 event_status; /* 0x0c */ + u16 error_status; /* 0x10 */ + u16 external_status; /* 0x11, 0x1b */ + u8 internal_charge; /* 0x18 */ + u8 external_charge; /* 0x19 */ + u16 control_lcd; /* 0x20 */ + u8 control_bitport; /* 0x21 */ + u8 speaker_volume; /* 0x23 */ + u8 control_tft_brightness; /* 0x24 */ + u8 control_kbd_repeat_delay; /* 0x28 */ + u8 control_kbd_repeat_rate; /* 0x29 */ + u8 control_screen_contrast; /* 0x2F */ +}; + +enum uctrl_opcode { + READ_SERIAL_NUMBER=0x1, + READ_ETHERNET_ADDRESS=0x2, + READ_HARDWARE_VERSION=0x3, + READ_MICROCONTROLLER_VERSION=0x4, + READ_MAX_TEMPERATURE=0x5, + READ_MIN_TEMPERATURE=0x6, + READ_CURRENT_TEMPERATURE=0x7, + READ_SYSTEM_VARIANT=0x8, + READ_POWERON_CYCLES=0x9, + READ_POWERON_SECONDS=0xA, + READ_RESET_STATUS=0xB, + READ_EVENT_STATUS=0xC, + READ_REAL_TIME_CLOCK=0xD, + READ_EXTERNAL_VGA_PORT=0xE, + READ_MICROCONTROLLER_ROM_CHECKSUM=0xF, + READ_ERROR_STATUS=0x10, + READ_EXTERNAL_STATUS=0x11, + READ_USER_CONFIGURATION_AREA=0x12, + READ_MICROCONTROLLER_VOLTAGE=0x13, + READ_INTERNAL_BATTERY_VOLTAGE=0x14, + READ_DCIN_VOLTAGE=0x15, + READ_HORIZONTAL_POINTER_VOLTAGE=0x16, + READ_VERTICAL_POINTER_VOLTAGE=0x17, + READ_INTERNAL_BATTERY_CHARGE_LEVEL=0x18, + READ_EXTERNAL_BATTERY_CHARGE_LEVEL=0x19, + READ_REAL_TIME_CLOCK_ALARM=0x1A, + READ_EVENT_STATUS_NO_RESET=0x1B, + READ_INTERNAL_KEYBOARD_LAYOUT=0x1C, + READ_EXTERNAL_KEYBOARD_LAYOUT=0x1D, + READ_EEPROM_STATUS=0x1E, + CONTROL_LCD=0x20, + CONTROL_BITPORT=0x21, + SPEAKER_VOLUME=0x23, + CONTROL_TFT_BRIGHTNESS=0x24, + CONTROL_WATCHDOG=0x25, + CONTROL_FACTORY_EEPROM_AREA=0x26, + CONTROL_KBD_TIME_UNTIL_REPEAT=0x28, + CONTROL_KBD_TIME_BETWEEN_REPEATS=0x29, + CONTROL_TIMEZONE=0x2A, + CONTROL_MARK_SPACE_RATIO=0x2B, + CONTROL_DIAGNOSTIC_MODE=0x2E, + CONTROL_SCREEN_CONTRAST=0x2F, + RING_BELL=0x30, + SET_DIAGNOSTIC_STATUS=0x32, + CLEAR_KEY_COMBINATION_TABLE=0x33, + PERFORM_SOFTWARE_RESET=0x34, + SET_REAL_TIME_CLOCK=0x35, + RECALIBRATE_POINTING_STICK=0x36, + SET_BELL_FREQUENCY=0x37, + SET_INTERNAL_BATTERY_CHARGE_RATE=0x39, + SET_EXTERNAL_BATTERY_CHARGE_RATE=0x3A, + SET_REAL_TIME_CLOCK_ALARM=0x3B, + READ_EEPROM=0x40, + WRITE_EEPROM=0x41, + WRITE_TO_STATUS_DISPLAY=0x42, + DEFINE_SPECIAL_CHARACTER=0x43, + DEFINE_KEY_COMBINATION_ENTRY=0x50, + DEFINE_STRING_TABLE_ENTRY=0x51, + DEFINE_STATUS_SCREEN_DISPLAY=0x52, + PERFORM_EMU_COMMANDS=0x64, + READ_EMU_REGISTER=0x65, + WRITE_EMU_REGISTER=0x66, + READ_EMU_RAM=0x67, + WRITE_EMU_RAM=0x68, + READ_BQ_REGISTER=0x69, + WRITE_BQ_REGISTER=0x6A, + SET_USER_PASSWORD=0x70, + VERIFY_USER_PASSWORD=0x71, + GET_SYSTEM_PASSWORD_KEY=0x72, + VERIFY_SYSTEM_PASSWORD=0x73, + POWER_OFF=0x82, + POWER_RESTART=0x83, +}; + struct uctrl_driver { - volatile u32 *regs; + struct uctrl_regs *regs; int irq; + int pending; + struct uctrl_status status; }; static struct uctrl_driver drv; +void uctrl_get_event_status(void); +void uctrl_get_external_status(void); + static loff_t uctrl_llseek(struct file *file, loff_t offset, int type) { @@ -53,6 +219,8 @@ uctrl_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; + uctrl_get_event_status(); + uctrl_get_external_status(); return 0; } @@ -88,6 +256,127 @@ &uctrl_fops }; +/* Wait for space to write, then write to it */ +#define WRITEUCTLDATA(value) \ +{ \ + unsigned int i; \ + for (i = 0; i < 10000; i++) { \ + if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \ + break; \ + } \ + dprintk(("write data 0x%02x\n", value)); \ + driver->regs->uctrl_data = value; \ +} + +/* Wait for something to read, read it, then clear the bit */ +#define READUCTLDATA(value) \ +{ \ + unsigned int i; \ + value = 0; \ + for (i = 0; i < 10000; i++) { \ + if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \ + break; \ + udelay(1); \ + } \ + value = driver->regs->uctrl_data; \ + dprintk(("read data 0x%02x\n", value)); \ + driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \ +} + +void uctrl_set_video(int status) +{ + struct uctrl_driver *driver = &drv; + +} + +static void uctrl_do_txn(struct uctrl_txn *txn) +{ + struct uctrl_driver *driver = &drv; + int stat, incnt, outcnt, bytecnt, intr; + u32 byte; + + stat = driver->regs->uctrl_stat; + intr = driver->regs->uctrl_intr; + driver->regs->uctrl_stat = stat; + + dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); + + incnt = txn->inbits; + outcnt = txn->outbits; + byte = (txn->opcode << 8); + WRITEUCTLDATA(byte); + + bytecnt = 0; + while (incnt > 0) { + byte = (txn->inbuf[bytecnt] << 8); + WRITEUCTLDATA(byte); + incnt--; + bytecnt++; + } + + /* Get the ack */ + READUCTLDATA(byte); + dprintk(("ack was %x\n", (byte >> 8))); + + bytecnt = 0; + while (outcnt > 0) { + READUCTLDATA(byte); + txn->outbuf[bytecnt] = (byte >> 8); + dprintk(("set byte to %02x\n", byte)); + outcnt--; + bytecnt++; + } +} + +void uctrl_get_event_status() +{ + struct uctrl_driver *driver = &drv; + struct uctrl_txn txn; + u8 outbits[2]; + + txn.opcode = READ_EVENT_STATUS; + txn.inbits = 0; + txn.outbits = 2; + txn.inbuf = 0; + txn.outbuf = outbits; + + uctrl_do_txn(&txn); + + dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); + driver->status.event_status = + ((outbits[0] & 0xff) << 8) | (outbits[1] & 0xff); + dprintk(("ev is %x\n", driver->status.event_status)); +} + +void uctrl_get_external_status() +{ + struct uctrl_driver *driver = &drv; + struct uctrl_txn txn; + u8 outbits[2]; + int i, v; + + txn.opcode = READ_EXTERNAL_STATUS; + txn.inbits = 0; + txn.outbits = 2; + txn.inbuf = 0; + txn.outbuf = outbits; + + uctrl_do_txn(&txn); + + dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); + driver->status.external_status = + ((outbits[0] * 256) + (outbits[1])); + dprintk(("ex is %x\n", driver->status.external_status)); + v = driver->status.external_status; + for (i = 0; v != 0; i++, v >>= 1) { + if (v & 1) { + dprintk(("%s%s", " ", uctrl_extstatus[i])); + } + } + dprintk(("\n")); + +} + #ifdef MODULE int init_module(void) #else @@ -95,7 +384,7 @@ #endif { struct uctrl_driver *driver = &drv; - int len; + int len, i; struct linux_prom_irqs tmp_irq[2]; unsigned int vaddr[2] = { 0, 0 }; int tmpnode, uctrlnode = prom_getchild(prom_root_node); @@ -113,10 +402,14 @@ /* the prom mapped it for us */ len = prom_getproperty(uctrlnode, "address", (void *) vaddr, sizeof(vaddr)); - driver->regs = vaddr[0]; + driver->regs = (struct uctrl_regs *)vaddr[0]; len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq, sizeof(tmp_irq)); + + /* Flush device */ + READUCTLDATA(len); + if(!driver->irq) driver->irq = tmp_irq[0].pri; @@ -133,7 +426,10 @@ return -ENODEV; } - printk(KERN_INFO, "uctrl: 0x%x (irq %d)\n", driver->regs, __irq_itoa(driver->irq)); + driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; + printk("uctrl: 0x%x (irq %s)\n", driver->regs, __irq_itoa(driver->irq)); + uctrl_get_event_status(); + uctrl_get_external_status(); return 0; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c --- v2.3.34/linux/drivers/sbus/char/vfc_dev.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/sbus/char/vfc_dev.c Mon Dec 20 22:06:42 1999 @@ -43,17 +43,20 @@ struct vfc_dev **vfc_dev_lst; static char vfcstr[]="vfc"; -static unsigned char saa9051_init_array[VFC_SAA9051_NR]= -{ 0x00, 0x64, 0x72, 0x52, - 0x36, 0x18, 0xff, 0x20, - 0xfc, 0x77, 0xe3, 0x50, - 0x3e}; +static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { + 0x00, 0x64, 0x72, 0x52, + 0x36, 0x18, 0xff, 0x20, + 0xfc, 0x77, 0xe3, 0x50, + 0x3e +}; -void vfc_lock_device(struct vfc_dev *dev) { +void vfc_lock_device(struct vfc_dev *dev) +{ down(&dev->device_lock_sem); } -void vfc_unlock_device(struct vfc_dev *dev) { +void vfc_unlock_device(struct vfc_dev *dev) +{ up(&dev->device_lock_sem); } @@ -61,41 +64,39 @@ void vfc_captstat_reset(struct vfc_dev *dev) { dev->control_reg |= VFC_CONTROL_CAPTRESET; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg &= ~VFC_CONTROL_CAPTRESET; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg |= VFC_CONTROL_CAPTRESET; - dev->regs->control=dev->control_reg; - return; + sbus_writel(dev->control_reg, &dev->regs->control); } void vfc_memptr_reset(struct vfc_dev *dev) { dev->control_reg |= VFC_CONTROL_MEMPTR; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg &= ~VFC_CONTROL_MEMPTR; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg |= VFC_CONTROL_MEMPTR; - dev->regs->control = dev->control_reg; - return; + sbus_writel(dev->control_reg, &dev->regs->control); } int vfc_csr_init(struct vfc_dev *dev) { dev->control_reg = 0x80000000; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); udelay(200); dev->control_reg &= ~0x80000000; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); udelay(100); - dev->regs->i2c_magic2 = 0x0f000000; + sbus_writel(0x0f000000, &dev->regs->i2c_magic2); vfc_memptr_reset(dev); dev->control_reg &= ~VFC_CONTROL_DIAGMODE; dev->control_reg &= ~VFC_CONTROL_CAPTURE; dev->control_reg |= 0x40000000; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); vfc_captstat_reset(dev); @@ -105,9 +106,10 @@ int vfc_saa9051_init(struct vfc_dev *dev) { int i; - for(i=0;isaa9051_state_array[i]=saa9051_init_array[i]; - } + + for (i = 0; i < VFC_SAA9051_NR; i++) + dev->saa9051_state_array[i] = saa9051_init_array[i]; + vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR, dev->saa9051_state_array, VFC_SAA9051_NR); return 0; @@ -136,27 +138,29 @@ return 0; } -int init_vfc_device(struct linux_sbus_device *sdev,struct vfc_dev *dev, - int instance) { - if(!dev) { +int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance) +{ + if(dev == NULL) { printk(KERN_ERR "VFC: Bogus pointer passed\n"); return -ENOMEM; } printk("Initializing vfc%d\n",instance); - dev->regs=NULL; - prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev); - dev->regs=sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - sizeof(struct vfc_regs), vfcstr, - sdev->reg_addrs[0].which_io, 0x0); - dev->which_io=sdev->reg_addrs[0].which_io; - dev->phys_regs=(struct vfc_regs *)sdev->reg_addrs[0].phys_addr; - if(!dev->regs) return -EIO; + dev->regs = NULL; + dev->regs = (volatile struct vfc_regs *) + sbus_ioremap(&sdev->resource[0], 0, + sizeof(struct vfc_regs), vfcstr); + dev->which_io = sdev->reg_addrs[0].which_io; + dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr; + if (dev->regs == NULL) + return -EIO; printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); - if(init_vfc_devstruct(dev,instance)) return -EINVAL; - if(init_vfc_hw(dev)) return -EIO; + if (init_vfc_devstruct(dev, instance)) + return -EINVAL; + if (init_vfc_hw(dev)) + return -EIO; return 0; } @@ -170,10 +174,14 @@ static int vfc_open(struct inode *inode, struct file *file) { struct vfc_dev *dev; - dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return -ENODEV; - if(dev->busy) return -EBUSY; - dev->busy=1; + + dev = vfc_get_dev_ptr(MINOR(inode->i_rdev)); + if (dev == NULL) + return -ENODEV; + if (dev->busy) + return -EBUSY; + + dev->busy = 1; MOD_INC_USE_COUNT; vfc_lock_device(dev); @@ -191,12 +199,14 @@ static void vfc_release(struct inode *inode,struct file *file) { struct vfc_dev *dev; - dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return; - if(!dev->busy) return; - dev->busy=0; + + dev = vfc_get_dev_ptr(MINOR(inode->i_rdev)); + if (dev == NULL) + return; + if (!dev->busy) + return; + dev->busy = 0; MOD_DEC_USE_COUNT; - return; } static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) @@ -204,21 +214,21 @@ struct vfc_debug_inout inout; unsigned char *buffer; - if(!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; switch(cmd) { case VFC_I2C_SEND: - if(copy_from_user(&inout, (void *)arg, sizeof(inout))) { + if(copy_from_user(&inout, (void *)arg, sizeof(inout))) return -EFAULT; - } buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL); - if (!buffer) + if (buffer == NULL) return -ENOMEM; if(copy_from_user(buffer, inout.buffer, inout.len*sizeof(char))) { - kfree_s(buffer,inout.len*sizeof(char)); + kfree_s(buffer, inout.len * sizeof(char)); return -EFAULT; } @@ -236,13 +246,13 @@ break; case VFC_I2C_RECV: - if (copy_from_user(&inout, (void *)arg, sizeof(inout))) { + if (copy_from_user(&inout, (void *)arg, sizeof(inout))) return -EFAULT; - } buffer = kmalloc(inout.len, GFP_KERNEL); - if (!buffer) + if (buffer == NULL) return -ENOMEM; + memset(buffer,0,inout.len*sizeof(char)); vfc_lock_device(dev); inout.ret= @@ -262,14 +272,15 @@ break; default: return -EINVAL; - } + }; + return 0; } int vfc_capture_start(struct vfc_dev *dev) { vfc_captstat_reset(dev); - dev->control_reg=dev->regs->control; + dev->control_reg = sbus_readl(&dev->regs->control); if((dev->control_reg & VFC_STATUS_CAPTURE)) { printk(KERN_ERR "vfc%d: vfc capture status not reset\n", dev->instance); @@ -278,11 +289,11 @@ vfc_lock_device(dev); dev->control_reg &= ~VFC_CONTROL_CAPTURE; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg |= VFC_CONTROL_CAPTURE; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); dev->control_reg &= ~VFC_CONTROL_CAPTURE; - dev->regs->control=dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); vfc_unlock_device(dev); return 0; @@ -290,13 +301,16 @@ int vfc_capture_poll(struct vfc_dev *dev) { - int timeout=1000; - while(!timeout--) { - if((dev->regs->control & VFC_STATUS_CAPTURE)) break; - vfc_i2c_delay_no_busy(dev,100); + int timeout = 1000; + + while (!timeout--) { + if (dev->regs->control & VFC_STATUS_CAPTURE) + break; + vfc_i2c_delay_no_busy(dev, 100); } if(!timeout) { - printk(KERN_WARNING "vfc%d: capture timed out\n", dev->instance); + printk(KERN_WARNING "vfc%d: capture timed out\n", + dev->instance); return -ETIMEDOUT; } return 0; @@ -307,11 +321,14 @@ static int vfc_set_control_ioctl(struct inode *inode, struct file *file, struct vfc_dev *dev, unsigned long arg) { - int setcmd,ret=0; + int setcmd, ret = 0; + if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int))) return -EFAULT; + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", dev->instance,setcmd)); + switch(setcmd) { case MEMPRST: vfc_lock_device(dev); @@ -327,29 +344,33 @@ if(suser()) { vfc_lock_device(dev); dev->control_reg |= VFC_CONTROL_DIAGMODE; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); vfc_unlock_device(dev); - ret=0; - } else ret=-EPERM; + ret = 0; + } else { + ret = -EPERM; + } break; case NORMMODE: vfc_lock_device(dev); dev->control_reg &= ~VFC_CONTROL_DIAGMODE; - dev->regs->control = dev->control_reg; + sbus_writel(dev->control_reg, &dev->regs->control); vfc_unlock_device(dev); - ret=0; + ret = 0; break; case CAPTRSTR: vfc_capture_start(dev); - ret=0; + ret = 0; break; case CAPTRWAIT: vfc_capture_poll(dev); - ret=0; + ret = 0; break; default: - ret=-EINVAL; - } + ret = -EINVAL; + break; + }; + return ret; } @@ -357,17 +378,18 @@ int vfc_port_change_ioctl(struct inode *inode, struct file *file, struct vfc_dev *dev, unsigned long arg) { - int ret=0; + int ret = 0; int cmd; if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_port_change_ioctl\n",dev->instance)); + "vfc_port_change_ioctl\n", + dev->instance)); return -EFAULT; } VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", - dev->instance,cmd)); + dev->instance, cmd)); switch(cmd) { case 1: @@ -385,29 +407,33 @@ VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17; VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa; VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde; - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; + VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = + VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC; VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0; - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); + VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= + ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); break; default: - ret=-EINVAL; + ret = -EINVAL; return ret; break; } switch(cmd) { case 1: - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0 | VFC_SAA9051_SS1; + VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= + (VFC_SAA9051_SS0 | VFC_SAA9051_SS1); break; case 2: - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); + VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= + ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; break; case 3: break; default: - ret=-EINVAL; + ret = -EINVAL; return ret; break; } @@ -422,23 +448,24 @@ int vfc_set_video_ioctl(struct inode *inode, struct file *file, struct vfc_dev *dev, unsigned long arg) { - int ret=0; + int ret = 0; int cmd; + if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) { VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_set_video_ioctl\n",dev->instance)); + "vfc_set_video_ioctl\n", + dev->instance)); return ret; } VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", - dev->instance,cmd)); + dev->instance, cmd)); switch(cmd) { - case STD_NTSC: VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT; VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS; - ret=vfc_update_saa9051(dev); + ret = vfc_update_saa9051(dev); break; case STD_PAL: VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | @@ -446,35 +473,39 @@ VFC_SAA9051_CCFR0 | VFC_SAA9051_FS); VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT; - ret=vfc_update_saa9051(dev); + ret = vfc_update_saa9051(dev); break; case COLOR_ON: VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO; - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= ~(VFC_SAA9051_BY | VFC_SAA9051_PF); - ret=vfc_update_saa9051(dev); + VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= + ~(VFC_SAA9051_BY | VFC_SAA9051_PF); + ret = vfc_update_saa9051(dev); break; case MONO: VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO); - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= VFC_SAA9051_BY | VFC_SAA9051_PF; - ret=vfc_update_saa9051(dev); + VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= + (VFC_SAA9051_BY | VFC_SAA9051_PF); + ret = vfc_update_saa9051(dev); break; default: - ret=-EINVAL; + ret = -EINVAL; break; - } + }; + return ret; } int vfc_get_video_ioctl(struct inode *inode, struct file *file, struct vfc_dev *dev, unsigned long arg) { - int ret=0; - unsigned int status=NO_LOCK; + int ret = 0; + unsigned int status = NO_LOCK; unsigned char buf[1]; - if(vfc_i2c_recvbuf(dev,VFC_SAA9051_ADDR,buf,1)) { - printk(KERN_ERR "vfc%d: Unable to get status\n",dev->instance); + if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) { + printk(KERN_ERR "vfc%d: Unable to get status\n", + dev->instance); return -EIO; } @@ -482,20 +513,22 @@ status = NO_LOCK; } else if(buf[0] & VFC_SAA9051_FD) { if(buf[0] & VFC_SAA9051_CD) - status=NTSC_COLOR; + status = NTSC_COLOR; else - status=NTSC_NOCOLOR; + status = NTSC_NOCOLOR; } else { if(buf[0] & VFC_SAA9051_CD) - status=PAL_COLOR; + status = PAL_COLOR; else - status=PAL_NOCOLOR; + status = PAL_NOCOLOR; } - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance, - status,buf[0])); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; " + "buf[0]=%x\n", dev->instance, status, buf[0])); + if (copy_to_user((void *)arg,&status,sizeof(unsigned int))) { VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_get_video_ioctl\n",dev->instance)); + "vfc_get_video_ioctl\n", + dev->instance)); return ret; } return ret; @@ -504,77 +537,81 @@ static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int ret=0; + int ret = 0; unsigned int tmp; struct vfc_dev *dev; - dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return -ENODEV; + dev = vfc_get_dev_ptr(MINOR(inode->i_rdev)); + if(dev == NULL) + return -ENODEV; switch(cmd & 0x0000ffff) { case VFCGCTRL: #if 0 - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance)); #endif - tmp=dev->regs->control; - if(copy_to_user((void *)arg,&tmp, sizeof(unsigned int))) { - ret=-EFAULT; + tmp = sbus_readl(&dev->regs->control); + if(copy_to_user((void *)arg, &tmp, sizeof(unsigned int))) { + ret = -EFAULT; break; } - ret=0; + ret = 0; break; case VFCSCTRL: - ret=vfc_set_control_ioctl(inode, file, dev, arg); + ret = vfc_set_control_ioctl(inode, file, dev, arg); break; case VFCGVID: - ret=vfc_get_video_ioctl(inode,file,dev,arg); + ret = vfc_get_video_ioctl(inode, file, dev, arg); break; case VFCSVID: - ret=vfc_set_video_ioctl(inode,file,dev,arg); + ret = vfc_set_video_ioctl(inode, file, dev, arg); break; case VFCHUE: - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance)); + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance)); if(copy_from_user(&tmp,(void *)arg,sizeof(unsigned int))) { VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " - "to IOCTL(VFCHUE)",dev->instance)); - ret=-EFAULT; + "to IOCTL(VFCHUE)", dev->instance)); + ret = -EFAULT; } else { - VFC_SAA9051_SA(dev,VFC_SAA9051_HUE)=tmp; + VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp; vfc_update_saa9051(dev); - ret=0; + ret = 0; } break; case VFCPORTCHG: - ret=vfc_port_change_ioctl(inode, file, dev, arg); + ret = vfc_port_change_ioctl(inode, file, dev, arg); break; case VFCRDINFO: - ret=-EINVAL; - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance)); + ret = -EINVAL; + VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance)); break; default: - ret=vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)), - cmd,arg); + ret = vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)), + cmd, arg); break; - } + }; + return ret; } static int vfc_mmap(struct inode *inode, struct file *file, - struct vm_area_struct *vma) + struct vm_area_struct *vma) { - unsigned int map_size,ret,map_offset; + unsigned int map_size, ret, map_offset; struct vfc_dev *dev; - dev=vfc_get_dev_ptr(MINOR(inode->i_rdev)); - if(!dev) return -ENODEV; + dev = vfc_get_dev_ptr(MINOR(inode->i_rdev)); + if(dev == NULL) + return -ENODEV; - map_size=vma->vm_end - vma->vm_start; + map_size = vma->vm_end - vma->vm_start; if(map_size > sizeof(struct vfc_regs)) - map_size=sizeof(struct vfc_regs); + map_size = sizeof(struct vfc_regs); - vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE; - map_offset=(unsigned int)dev->phys_regs; - ret = io_remap_page_range(vma->vm_start,map_offset,map_size, + vma->vm_flags |= + (VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); + map_offset = (unsigned int) (long)dev->phys_regs; + ret = io_remap_page_range(vma->vm_start, map_offset, map_size, vma->vm_page_prot, dev->which_io); if(ret) return -EAGAIN; @@ -584,13 +621,13 @@ static int vfc_lseek(struct inode *inode, struct file *file, - off_t offset, int origin) + off_t offset, int origin) { return -ESPIPE; } static struct file_operations vfc_fops = { - vfc_lseek, /* vfc_lseek */ + vfc_lseek, /* vfc_lseek */ NULL, /* vfc_write */ NULL, /* vfc_read */ NULL, /* vfc_readdir */ @@ -598,19 +635,19 @@ vfc_ioctl, vfc_mmap, vfc_open, - NULL, /* flush */ + NULL, /* flush */ vfc_release, }; static int vfc_probe(void) { - struct linux_sbus *bus; - struct linux_sbus_device *sdev = NULL; + struct sbus_bus *sbus; + struct sbus_dev *sdev = NULL; int ret; - int instance=0,cards=0; + int instance = 0, cards = 0; - for_all_sbusdev(sdev,bus) { - if (strcmp(sdev->prom_name,"vfc") == 0) { + for_all_sbusdev(sdev, sbus) { + if (strcmp(sdev->prom_name, "vfc") == 0) { cards++; continue; } @@ -619,33 +656,35 @@ if (!cards) return -ENODEV; - vfc_dev_lst=(struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *)* - (cards+1), - GFP_KERNEL); - if(!vfc_dev_lst) + vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) * + (cards+1), + GFP_KERNEL); + if (vfc_dev_lst == NULL) return -ENOMEM; - memset(vfc_dev_lst,0,sizeof(struct vfc_dev *)*(cards+1)); - vfc_dev_lst[cards]=NULL; + memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1)); + vfc_dev_lst[cards] = NULL; - ret=register_chrdev(VFC_MAJOR,vfcstr,&vfc_fops); + ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); if(ret) { - printk(KERN_ERR "Unable to get major number %d\n",VFC_MAJOR); + printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); kfree(vfc_dev_lst); return -EIO; } - instance=0; - for_all_sbusdev(sdev,bus) { - if (strcmp(sdev->prom_name,"vfc") == 0) { + instance = 0; + for_all_sbusdev(sdev, sbus) { + if (strcmp(sdev->prom_name, "vfc") == 0) { vfc_dev_lst[instance]=(struct vfc_dev *) kmalloc(sizeof(struct vfc_dev), GFP_KERNEL); - if(vfc_dev_lst[instance] == NULL) return -ENOMEM; - ret=init_vfc_device(sdev, - vfc_dev_lst[instance], - instance); + if (vfc_dev_lst[instance] == NULL) + return -ENOMEM; + ret = init_vfc_device(sdev, + vfc_dev_lst[instance], + instance); if(ret) { printk(KERN_ERR "Unable to initialize" - " vfc%d device\n",instance); + " vfc%d device\n", + instance); } else { } @@ -669,18 +708,21 @@ #ifdef MODULE static void deinit_vfc_device(struct vfc_dev *dev) { - if(!dev) return; - sparc_free_io((void *)dev->regs,sizeof(struct vfc_regs)); + if(dev == NULL) + return; + sbus_iounmap((unsigned long)dev->regs, sizeof(struct vfc_regs)); kfree(dev); } void cleanup_module(void) { struct vfc_dev **devp; + unregister_chrdev(VFC_MAJOR,vfcstr); - for(devp=vfc_dev_lst;*devp;devp++) { + + for (devp = vfc_dev_lst; *devp; devp++) deinit_vfc_device(*devp); - } + kfree(vfc_dev_lst); return; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/vfc_i2c.c linux/drivers/sbus/char/vfc_i2c.c --- v2.3.34/linux/drivers/sbus/char/vfc_i2c.c Thu Jan 7 09:21:53 1999 +++ linux/drivers/sbus/char/vfc_i2c.c Mon Dec 20 22:06:42 1999 @@ -38,6 +38,11 @@ #include "vfc.h" #include "vfc_i2c.h" +#define WRITE_S1(__val) \ + sbus_writel(__val, &dev->regs->i2c_s1) +#define WRITE_REG(__val) \ + sbus_writel(__val, &dev->regs->i2c_reg) + #define VFC_I2C_READ (0x1) #define VFC_I2C_WRITE (0x0) @@ -52,20 +57,24 @@ int vfc_pcf8584_init(struct vfc_dev *dev) { - dev->regs->i2c_s1=RESET; /* This will also choose - register S0_OWN so we can set it*/ + /* This will also choose register S0_OWN so we can set it. */ + WRITE_S1(RESET); - dev->regs->i2c_reg=0x55000000; /* the pcf8584 shifts this - value left one bit and uses - it as its i2c bus address */ - dev->regs->i2c_s1=SELECT(S2); - dev->regs->i2c_reg=0x14000000; /* this will set the i2c bus at - the same speed sun uses, - and set another magic bit */ + /* The pcf8584 shifts this value left one bit and uses + * it as its i2c bus address. + */ + WRITE_REG(0x55000000); + + /* This will set the i2c bus at the same speed sun uses, + * and set another magic bit. + */ + WRITE_S1(SELECT(S2)); + WRITE_REG(0x14000000); - dev->regs->i2c_s1=CLEAR_I2C_BUS; /* enable the serial port, - idle the i2c bus and set - the data reg to s0 */ + /* Enable the serial port, idle the i2c bus and set + * the data reg to s0. + */ + WRITE_S1(CLEAR_I2C_BUS); udelay(100); return 0; } @@ -73,11 +82,11 @@ void vfc_i2c_delay_wakeup(struct vfc_dev *dev) { /* Used to profile code and eliminate too many delays */ - VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n",dev->instance)); + VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance)); wake_up(&dev->poll_wait); } -void vfc_i2c_delay_no_busy(struct vfc_dev *dev,unsigned long usecs) +void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) { dev->poll_timer.next = NULL; dev->poll_timer.prev = NULL; @@ -92,12 +101,12 @@ void inline vfc_i2c_delay(struct vfc_dev *dev) { - vfc_i2c_delay_no_busy(dev,100); + vfc_i2c_delay_no_busy(dev, 100); } int vfc_init_i2c_bus(struct vfc_dev *dev) { - dev->regs->i2c_s1= ENABLE_SERIAL | SELECT(S0) | ACK; + WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); vfc_i2c_reset_bus(dev); return 0; } @@ -105,24 +114,28 @@ int vfc_i2c_reset_bus(struct vfc_dev *dev) { VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", - dev->instance)); - if(!dev) return -EINVAL; - if(!dev->regs) return -EINVAL; - dev->regs->i2c_s1=SEND_I2C_STOP; - dev->regs->i2c_s1=SEND_I2C_STOP | ACK; + dev->instance)); + if(dev == NULl) + return -EINVAL; + if(dev->regs == NULL) + return -EINVAL; + WRITE_S1(SEND_I2C_STOP); + WRITE_S1(SEND_I2C_STOP | ACK); vfc_i2c_delay(dev); - dev->regs->i2c_s1=CLEAR_I2C_BUS; + WRITE_S1(CLEAR_I2C_BUS); VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", - dev->instance, dev->regs->i2c_s1)); + dev->instance, + sbus_readl(&dev->regs->i2c_s1))); return 0; } int vfc_i2c_wait_for_bus(struct vfc_dev *dev) { - int timeout=1000; + int timeout = 1000; - while(!(dev->regs->i2c_s1 & BB)) { - if(!(timeout--)) return -ETIMEDOUT; + while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { + if(!(timeout--)) + return -ETIMEDOUT; vfc_i2c_delay(dev); } return 0; @@ -130,15 +143,17 @@ int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) { - int timeout=1000; + int timeout = 1000; int s1; - while((s1=dev->regs->i2c_s1) & PIN) { - if(!(timeout--)) return -ETIMEDOUT; + while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { + if (!(timeout--)) + return -ETIMEDOUT; vfc_i2c_delay(dev); } - if(ack==VFC_I2C_ACK_CHECK) { - if(s1 & LRB) return -EIO; + if (ack == VFC_I2C_ACK_CHECK) { + if(s1 & LRB) + return -EIO; } return 0; } @@ -146,47 +161,50 @@ #define SHIFT(a) ((a) << 24) int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) { - int ret,raddr; + int ret, raddr; #if 1 - dev->regs->i2c_s1=SEND_I2C_STOP | ACK; - dev->regs->i2c_s1=SELECT(S0) | ENABLE_SERIAL; + WRITE_S1(SEND_I2C_STOP | ACK); + WRITE_S1(SELECT(S0) | ENABLE_SERIAL); vfc_i2c_delay(dev); #endif switch(mode) { case VFC_I2C_READ: - dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1); + raddr = SHIFT(((unsigned int)addr | 0x1)); + WRITE_REG(raddr); VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", - dev->instance,addr | 0x1)); + dev->instance, addr | 0x1)); break; case VFC_I2C_WRITE: - dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr & ~0x1); + raddr = SHIFT((unsigned int)addr & ~0x1); + WRITE_REG(raddr); VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", - dev->instance,addr & ~0x1)); + dev->instance, addr & ~0x1)); break; default: return -EINVAL; - } - dev->regs->i2c_s1 = SEND_I2C_START; + }; + + WRITE_S1(SEND_I2C_START); vfc_i2c_delay(dev); - ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait - for the - i2c send - to finish - here but - Sun - doesn't, - hmm */ - if(ret) { + ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait + for the + i2c send + to finish + here but + Sun + doesn't, + hmm */ + if (ret) { printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", dev->instance); return ret; - } else if(mode == VFC_I2C_READ) { - if((ret=dev->regs->i2c_reg & 0xff000000) != raddr) { + } else if (mode == VFC_I2C_READ) { + if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { printk(KERN_WARNING "vfc%d: returned slave address " "mismatch(%x,%x)\n", - dev->instance,raddr,ret); + dev->instance, raddr, ret); } } return 0; @@ -195,75 +213,81 @@ int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) { int ret; - dev->regs->i2c_reg=SHIFT((unsigned int)*byte); + u32 val = SHIFT((unsigned int)*byte); + + WRITE_REG(val); - ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); + ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); switch(ret) { case -ETIMEDOUT: printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", dev->instance); break; case -EIO: - ret=XMIT_LAST_BYTE; + ret = XMIT_LAST_BYTE; break; default: break; - } + }; + return ret; } int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) { int ret; - if(last) { - dev->regs->i2c_reg=NEGATIVE_ACK; + + if (last) { + WRITE_REG(NEGATIVE_ACK); VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", - dev->instance)); + dev->instance)); } else { - dev->regs->i2c_s1=ACK; + WRITE_S1(ACK); } - ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_NO_ACK_CHECK); + ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); if(ret) { printk(KERN_ERR "vfc%d: " - "VFC recv byte timed out\n",dev->instance); + "VFC recv byte timed out\n", + dev->instance); } - *byte=(dev->regs->i2c_reg) >> 24; + *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; return ret; } int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, char *buf, int count) { - int ret,last; + int ret, last; - if(!(count && buf && dev && dev->regs) ) return -EINVAL; + if(!(count && buf && dev && dev->regs) ) + return -EINVAL; - if((ret=vfc_i2c_wait_for_bus(dev))) { - printk(KERN_ERR "vfc%d: VFC I2C bus busy\n",dev->instance); + if ((ret = vfc_i2c_wait_for_bus(dev))) { + printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); return ret; } - if((ret=vfc_i2c_xmit_addr(dev,addr,VFC_I2C_READ))) { - dev->regs->i2c_s1=SEND_I2C_STOP; + if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { + WRITE_S1(SEND_I2C_STOP); vfc_i2c_delay(dev); return ret; } - last=0; - while(count--) { - if(!count) last=1; - if((ret=vfc_i2c_recv_byte(dev,buf,last))) { + last = 0; + while (count--) { + if (!count) + last = 1; + if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { printk(KERN_ERR "vfc%d: " "VFC error while receiving byte\n", dev->instance); - dev->regs->i2c_s1=SEND_I2C_STOP; - ret=-EINVAL; + WRITE_S1(SEND_I2C_STOP); + ret = -EINVAL; } buf++; } - - dev->regs->i2c_s1=SEND_I2C_STOP | ACK; + WRITE_S1(SEND_I2C_STOP | ACK); vfc_i2c_delay(dev); return ret; } @@ -273,42 +297,43 @@ { int ret; - if(!(buf && dev && dev->regs) ) return -EINVAL; + if (!(buf && dev && dev->regs)) + return -EINVAL; - if((ret=vfc_i2c_wait_for_bus(dev))) { - printk(KERN_ERR "vfc%d: VFC I2C bus busy\n",dev->instance); + if ((ret = vfc_i2c_wait_for_bus(dev))) { + printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); return ret; } - if((ret=vfc_i2c_xmit_addr(dev,addr,VFC_I2C_WRITE))) { - dev->regs->i2c_s1=SEND_I2C_STOP; + if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { + WRITE_S1(SEND_I2C_STOP); vfc_i2c_delay(dev); return ret; } while(count--) { - ret=vfc_i2c_xmit_byte(dev,buf); + ret = vfc_i2c_xmit_byte(dev, buf); switch(ret) { case XMIT_LAST_BYTE: VFC_I2C_DEBUG_PRINTK(("vfc%d: " - "Reciever ended transmission with " - " %d bytes remaining\n", - dev->instance,count)); - ret=0; + "Reciever ended transmission with " + " %d bytes remaining\n", + dev->instance, count)); + ret = 0; goto done; break; case 0: break; default: printk(KERN_ERR "vfc%d: " - "VFC error while sending byte\n",dev->instance); + "VFC error while sending byte\n", dev->instance); break; - } + }; + buf++; } done: - dev->regs->i2c_s1=SEND_I2C_STOP | ACK; - + WRITE_S1(SEND_I2C_STOP | ACK); vfc_i2c_delay(dev); return ret; } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c --- v2.3.34/linux/drivers/sbus/char/zs.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/sbus/char/zs.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.45 1999/09/01 08:09:35 davem Exp $ +/* $Id: zs.c,v 1.52 1999/12/15 14:29:20 davem Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,8 @@ #include #include #include +#include +#include #include #ifdef __sparc_v9__ @@ -65,8 +68,8 @@ #else #define ZSDELAY() #define ZSDELAY_LONG() -#define ZS_WSYNC(channel) \ - ((void) *((volatile unsigned char *)(&((channel)->control)))) +#define ZS_WSYNC(__channel) \ + sbus_readb(&((__channel)->control)) #endif struct sun_zslayout **zs_chips; @@ -164,6 +167,47 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#undef ZS_LOG +#ifdef ZS_LOG +struct zs_logent { + u8 reg, val; + u8 write, __pad; +#define REGIRQ 0xff +#define REGDATA 0xfe +#define REGCTRL 0xfd +}; +struct zs_logent zslog[32]; +int zs_curlog = 0; +#define ZSLOG(__reg, __val, __write) \ +do{ int index = zs_curlog; \ + zslog[index].reg = (__reg); \ + zslog[index].val = (__val); \ + zslog[index].write = (__write); \ + zs_curlog = (index + 1) & (32 - 1); \ +}while(0) +int zs_dumplog(char *buffer) +{ + int len = 0; + int i; + + for (i = 0; i < 32; i++) { + u8 reg, val, write; + + reg = zslog[i].reg; + val = zslog[i].val; + write = zslog[i].write; + len += sprintf(buffer + len, + "ZSLOG[%2d]: reg %2x val %2x %s\n", + i, reg, val, write ? "write" : "read"); + } + len += sprintf(buffer + len, "ZS current log index %d\n", + zs_curlog); + return len; +} +#else +#define ZSLOG(x,y,z) do { } while (0) +#endif + /* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the memcpy_fromfs blocks while swapping in a page, @@ -197,15 +241,13 @@ return 0; } -/* - * This is used to figure out the divisor speeds and the timeouts - */ +/* This is used to figure out the divisor speeds and the timeouts. */ static int baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 76800, 0 }; + 9600, 19200, 38400, 76800, 0 +}; -/* - * Reading and writing Zilog8530 registers. The delays are to make this +/* Reading and writing Zilog8530 registers. The delays are to make this * driver work on the Sun4 which needs a settling delay after each chip * register access, other machines handle this in hardware via auxiliary * flip-flops which implement the settle time we do in software. @@ -215,26 +257,28 @@ { unsigned char retval; - channel->control = reg; + sbus_writeb(reg, &channel->control); ZSDELAY(); - retval = channel->control; + retval = sbus_readb(&channel->control); ZSDELAY(); + ZSLOG(reg, retval, 0); return retval; } static inline void write_zsreg(struct sun_zschannel *channel, unsigned char reg, unsigned char value) { - channel->control = reg; + ZSLOG(reg, value, 1); + sbus_writeb(reg, &channel->control); ZSDELAY(); - channel->control = value; + sbus_writeb(value, &channel->control); ZSDELAY(); } static inline void load_zsregs(struct sun_serial *info, unsigned char *regs) { - unsigned long flags; struct sun_zschannel *channel = info->zs_channel; + unsigned long flags; unsigned char stat; int i; @@ -287,12 +331,18 @@ * a timed polling loop and on sparc64 ZSDELAY * is a nop. -DaveM */ - while((channel->control & Tx_BUF_EMP) == 0 && --loops) + do { + u8 val = sbus_readb(&channel->control); + ZSLOG(REGCTRL, val, 0); + if (val & Tx_BUF_EMP) + break; udelay(5); + } while (--loops); - channel->data = ch; + sbus_writeb(ch, &channel->data); ZSDELAY(); ZS_WSYNC(channel); + ZSLOG(REGDATA, ch, 1); } /* Sets or clears DTR/RTS on the requested line */ @@ -339,7 +389,7 @@ */ static void zs_stop(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->device, "zs_stop")) @@ -355,7 +405,7 @@ static void zs_start(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->device, "zs_start")) @@ -374,6 +424,8 @@ */ void batten_down_hatches(void) { + if (!stop_a_enabled) + return; /* If we are doing kadb, we call the debugger * else we just drop into the boot monitor. * Note that we must flush the user windows @@ -424,7 +476,7 @@ * processing in the software interrupt portion of the driver. */ static _INLINE_ void zs_sched_event(struct sun_serial *info, - int event) + int event) { info->event |= 1 << event; queue_task(&info->tqueue, &tq_serial); @@ -439,9 +491,12 @@ { struct tty_struct *tty = info->tty; unsigned char ch, stat; + int do_queue_task = 1; do { - ch = (info->zs_channel->data) & info->parity_mask; + ch = sbus_readb(&info->zs_channel->data); + ZSLOG(REGDATA, ch, 0); + ch &= info->parity_mask; ZSDELAY(); /* If this is the console keyboard, we need to handle @@ -466,14 +521,16 @@ return; } sunkbd_inchar(ch, regs); - return; + do_queue_task = 0; + goto next_char; } if(info->cons_mouse) { - sun_mouse_inbyte(ch); - return; + sun_mouse_inbyte(ch, 0); + do_queue_task = 0; + goto next_char; } if(info->is_cons) { - if(ch==0) { + if(ch == 0) { /* whee, break received */ batten_down_hatches(); /* Continue execution... */ @@ -502,9 +559,11 @@ *tty->flip.flag_buf_ptr++ = 0; *tty->flip.char_buf_ptr++ = ch; + next_char: /* Check if we have another character... */ - stat = info->zs_channel->control; + stat = sbus_readb(&info->zs_channel->control); ZSDELAY(); + ZSLOG(REGCTRL, stat, 0); if (!(stat & Rx_CH_AV)) break; @@ -512,7 +571,8 @@ stat = read_zsreg(info->zs_channel, R1); } while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR))); - queue_task(&tty->flip.tqueue, &tq_timer); + if (do_queue_task != 0) + queue_task(&tty->flip.tqueue, &tq_timer); } static _INLINE_ void transmit_chars(struct sun_serial *info) @@ -528,9 +588,10 @@ if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) { /* That's peculiar... */ - info->zs_channel->control = RES_Tx_P; + sbus_writeb(RES_Tx_P, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_Tx_P, 1); return; } @@ -543,9 +604,10 @@ zs_sched_event(info, RS_EVENT_WRITE_WAKEUP); if(info->xmit_cnt <= 0) { - info->zs_channel->control = RES_Tx_P; + sbus_writeb(RES_Tx_P, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_Tx_P, 1); } } @@ -554,13 +616,14 @@ unsigned char status; /* Get status from Read Register 0 */ - status = info->zs_channel->control; + status = sbus_readb(&info->zs_channel->control); ZSDELAY(); + ZSLOG(REGCTRL, status, 0); /* Clear status condition... */ - info->zs_channel->control = RES_EXT_INT; + sbus_writeb(RES_EXT_INT, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); - + ZSLOG(REGCTRL, RES_EXT_INT, 1); #if 0 if(status & DCD) { if((info->tty->termios->c_cflag & CRTSCTS) && @@ -579,8 +642,12 @@ * 'break asserted' status change interrupt, call * the boot prom. */ - if((status & BRK_ABRT) && info->break_abort) - batten_down_hatches(); + if(status & BRK_ABRT) { + if (info->break_abort) + batten_down_hatches(); + if (info->cons_mouse) + sun_mouse_inbyte(0, 1); + } /* XXX Whee, put in a buffer somewhere, the status information * XXX whee whee whee... Where does the information go... @@ -595,8 +662,9 @@ stat = read_zsreg(info->zs_channel, R1); if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) { - ch = info->zs_channel->data; + ch = sbus_readb(&info->zs_channel->data); ZSDELAY(); + ZSLOG(REGDATA, ch, 0); } if (!tty) @@ -616,9 +684,10 @@ done: queue_task(&tty->flip.tqueue, &tq_timer); clear: - info->zs_channel->control = ERR_RES; + sbus_writeb(ERR_RES, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, ERR_RES, 1); } @@ -632,6 +701,7 @@ int i; info = (struct sun_serial *)dev_id; + ZSLOG(REGIRQ, 0, 0); for (i = 0; i < NUM_SERIAL; i++) { zs_intreg = read_zsreg(info->zs_next->zs_channel, 2); zs_intreg &= STATUS_MASK; @@ -797,13 +867,15 @@ /* * Clear the interrupt registers. */ - info->zs_channel->control = ERR_RES; + sbus_writeb(ERR_RES, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, ERR_RES, 1); - info->zs_channel->control = RES_H_IUS; + sbus_writeb(RES_H_IUS, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); /* * Now, initialize the Zilog @@ -826,13 +898,15 @@ /* * And clear the interrupt registers again for luck. */ - info->zs_channel->control = ERR_RES; + sbus_writeb(ERR_RES, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, ERR_RES, 1); - info->zs_channel->control = RES_H_IUS; + sbus_writeb(RES_H_IUS, &info->zs_channel->control); ZSDELAY(); ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -1035,24 +1109,32 @@ { struct sun_zschannel *chan = zs_kgdbchan; - while((chan->control & Tx_BUF_EMP)==0) + while((sbus_readb(&chan->control) & Tx_BUF_EMP)==0) udelay(5); - chan->data = kgdb_char; + sbus_writeb(kgdb_char, &chan->data); ZS_WSYNC(chan); + ZSLOG(REGDATA, kgdb_char, 1); } char getDebugChar(void) { struct sun_zschannel *chan = zs_kgdbchan; + u8 val; - while((chan->control & Rx_CH_AV)==0) + do { + val = sbus_readb(&chan->control); + ZSLOG(REGCTRL, val, 0); udelay(5); - return chan->data; + } while ((val & Rx_CH_AV) == 0); + + val = sbus_readb(&chan->data); + ZSLOG(REGDATA, val, 0); + return val; } static void zs_flush_chars(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->device, "zs_flush_chars")) @@ -1087,9 +1169,9 @@ static int zs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { - int c, total = 0; - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; unsigned long flags; + int c, total = 0; if (serial_paranoia_check(info, tty->device, "zs_write")) return 0; @@ -1143,8 +1225,8 @@ static int zs_write_room(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; - int ret; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; + int ret; if (serial_paranoia_check(info, tty->device, "zs_write_room")) return 0; @@ -1156,7 +1238,7 @@ static int zs_chars_in_buffer(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; if (serial_paranoia_check(info, tty->device, "zs_chars_in_buffer")) return 0; @@ -1165,7 +1247,7 @@ static void zs_flush_buffer(struct tty_struct *tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; if (serial_paranoia_check(info, tty->device, "zs_flush_buffer")) return; @@ -1188,7 +1270,7 @@ */ static void zs_throttle(struct tty_struct * tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; @@ -1211,7 +1293,7 @@ static void zs_unthrottle(struct tty_struct * tty) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; @@ -1268,7 +1350,7 @@ { struct serial_struct new_serial; struct sun_serial old_info; - int retval = 0; + int retval = 0; if (!new_info || copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; @@ -1326,10 +1408,11 @@ unsigned char status; cli(); - status = info->zs_channel->control; + status = sbus_readb(&info->zs_channel->control); ZSDELAY(); + ZSLOG(REGCTRL, status, 0); sti(); - put_user_ret(status,value, -EFAULT); + put_user_ret(status, value, -EFAULT); return 0; } @@ -1339,8 +1422,9 @@ unsigned int result; cli(); - status = info->zs_channel->control; + status = sbus_readb(&info->zs_channel->control); ZSDELAY(); + ZSLOG(REGCTRL, status, 0); sti(); result = ((info->curregs[5] & RTS) ? TIOCM_RTS : 0) | ((info->curregs[5] & DTR) ? TIOCM_DTR : 0) @@ -1402,7 +1486,7 @@ static int zs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - struct sun_serial * info = (struct sun_serial *)tty->driver_data; + struct sun_serial * info = (struct sun_serial *) tty->driver_data; int retval; if (serial_paranoia_check(info, tty->device, "zs_ioctl")) @@ -1469,7 +1553,7 @@ static void zs_set_termios(struct tty_struct *tty, struct termios *old_termios) { - struct sun_serial *info = (struct sun_serial *)tty->driver_data; + struct sun_serial *info = (struct sun_serial *) tty->driver_data; if (tty->termios->c_cflag == old_termios->c_cflag) return; @@ -1495,7 +1579,7 @@ */ static void zs_close(struct tty_struct *tty, struct file * filp) { - struct sun_serial * info = (struct sun_serial *)tty->driver_data; + struct sun_serial * info = (struct sun_serial *) tty->driver_data; unsigned long flags; if (!info || serial_paranoia_check(info, tty->device, "zs_close")) @@ -1598,7 +1682,7 @@ */ void zs_hangup(struct tty_struct *tty) { - struct sun_serial * info = (struct sun_serial *)tty->driver_data; + struct sun_serial * info = (struct sun_serial *) tty->driver_data; if (serial_paranoia_check(info, tty->device, "zs_hangup")) return; @@ -1629,9 +1713,8 @@ struct sun_serial *info) { DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - unsigned char r0; + int retval, do_clocal = 0; + unsigned char r0; /* * If the device is in the middle of being closed, then block @@ -1769,10 +1852,11 @@ */ int zs_open(struct tty_struct *tty, struct file * filp) { - struct sun_serial *info; - int retval, line; + struct sun_serial *info; + int retval, line; line = MINOR(tty->device) - tty->driver.minor_start; + /* The zilog lines for the mouse/keyboard must be * opened using their respective drivers. */ @@ -1844,7 +1928,7 @@ static void show_serial_version(void) { - char *revision = "$Revision: 1.45 $"; + char *revision = "$Revision: 1.52 $"; char *version, *p; version = strchr(revision, ' '); @@ -1869,16 +1953,19 @@ int busnode, seen, zsnode, sun4u_ino; static int irq = 0; - if(chip < 0 || chip >= NUM_SERIAL) - panic("get_zs bogon zs chip number"); + if(chip < 0 || chip >= NUM_SERIAL) { + prom_printf("get_zs bogon zs chip number"); + prom_halt(); + } if(central_bus) busnode = central_bus->child->prom_node; else busnode = prom_searchsiblings(prom_getchild(prom_root_node), "sbus"); - if(busnode == 0 || busnode == -1) - panic("get_zs: no zs bus to search"); - + if(busnode == 0 || busnode == -1) { + prom_printf("get_zs: no zs bus to search"); + prom_halt(); + } zsnode = prom_getchild(busnode); seen = 0; while(zsnode) { @@ -1891,8 +1978,8 @@ (void *) vaddr, sizeof(vaddr)); if(len == -1 || central_bus != NULL) { - struct linux_sbus *sbus = NULL; - struct linux_sbus_device *sdev = NULL; + struct sbus_bus *sbus = NULL; + struct sbus_dev *sdev = NULL; /* "address" property is not guarenteed, * everything in I/O is implicitly mapped @@ -1911,11 +1998,9 @@ if (sdev == NULL && central_bus == NULL) prom_halt(); if (central_bus == NULL) { - prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev); - mapped_addr = (unsigned long) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "Zilog Registers", - sdev->reg_addrs[0].which_io, 0x0); + mapped_addr = + sbus_ioremap(&sdev->resource[0], 0, + PAGE_SIZE, "Zilog Registers"); } else { struct linux_prom_registers zsregs[1]; int err; @@ -1927,11 +2012,11 @@ prom_printf("ZS: Cannot map Zilog regs.\n"); prom_halt(); } - prom_apply_fhc_ranges(central_bus->child, &zsregs[0], 1); - prom_apply_central_ranges(central_bus, &zsregs[0], 1); - mapped_addr = (unsigned long) - __va((((unsigned long)zsregs[0].which_io)<<32) | - (((unsigned long)zsregs[0].phys_addr))); + apply_fhc_ranges(central_bus->child, &zsregs[0], 1); + apply_central_ranges(central_bus, &zsregs[0], 1); + mapped_addr = + ((((u64)zsregs[0].which_io)<<32UL)| + ((u64)zsregs[0].phys_addr)); } } else if(len % sizeof(unsigned int)) { prom_printf("WHOOPS: proplen for %s " @@ -1946,13 +2031,14 @@ (sizeof(sun4u_ino))); if(!irq) { if (central_bus) { - irq = zilog_irq = - build_irq(12, 0, - ¢ral_bus->child->fhc_regs.uregs->fhc_uart_iclr, - ¢ral_bus->child->fhc_regs.uregs->fhc_uart_imap); + unsigned long iclr, imap; + + iclr = central_bus->child->fhc_regs.uregs + FHC_UREGS_ICLR; + imap = central_bus->child->fhc_regs.uregs + FHC_UREGS_IMAP; + irq = zilog_irq = build_irq(12, 0, iclr, imap); } else { irq = zilog_irq = - sbus_build_irq(SBus_chain, sun4u_ino); + sbus_build_irq(sbus_root, sun4u_ino); } } break; @@ -1964,10 +2050,20 @@ panic("get_zs: whee chip not found"); if(!vaddr[0] && !mapped_addr) panic("get_zs: whee no serial chip mappable"); - if (mapped_addr != 0) + if (mapped_addr != 0) { return (struct sun_zslayout *) mapped_addr; - else - return (struct sun_zslayout *) (unsigned long) vaddr[0]; + } else { + pgd_t *pgd = pgd_offset_k((unsigned long)vaddr[0]); + pmd_t *pmd = pmd_offset(pgd, (unsigned long)vaddr[0]); + pte_t *pte = pte_offset(pmd, (unsigned long)vaddr[0]); + unsigned long base = pte_val(*pte) & _PAGE_PADDR; + + /* Translate PROM's mapping we captured at boot + * time into physical address. + */ + base += ((unsigned long)vaddr[0] & ~PAGE_MASK); + return (struct sun_zslayout *) base; + } } #else /* !(__sparc_v9__) */ static struct sun_zslayout * __init get_zs(int chip) @@ -1990,6 +2086,8 @@ panic("get_zs bogon zs chip number"); if(sparc_cpu_model == sun4) { + struct resource dummy_resource; + /* Grrr, these have to be hardcoded aieee */ switch(chip) { case 0: @@ -2003,9 +2101,11 @@ zs_nodes[chip] = 0; if(!irq) zilog_irq = irq = 12; - vaddr[0] = (unsigned long) - sparc_alloc_io(paddr, 0, 8, - "Zilog Serial", iospace, 0); + dummy_resource.start = paddr; + dummy_resource.end = paddr + 8 - 1; + dummy_resource.flags = IORESOURCE_IO; + vaddr[0] = sbus_ioremap(&dummy_resource, 0, + 8, "Zilog Serial"); } else { /* Can use the prom for other machine types */ zsnode = prom_getchild(prom_root_node); @@ -2056,15 +2156,18 @@ } else { /* On sun4d don't have address property :( */ struct linux_prom_registers zsreg[4]; + struct resource res; if (prom_getproperty(zsnode, "reg", (char *)zsreg, sizeof(zsreg)) == -1) { prom_printf ("Cannot map zs regs\n"); prom_halt(); } prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1); - vaddr[0] = (unsigned long) - sparc_alloc_io(zsreg[0].phys_addr, 0, 8, - "Zilog Serial", zsreg[0].which_io, 0); + res.start = zsreg[0].phys_addr; + res.end = res.start + 8 - 1; + res.flags = zsreg[0].which_io | IORESOURCE_IO; + vaddr[0] = sbus_ioremap(&res, 0, + 8, "Zilog Serial"); } zs_nodes[chip] = zsnode; len = prom_getproperty(zsnode, "intr", @@ -2074,9 +2177,9 @@ prom_printf( "WHOOPS: proplen for %s " "was %d, need multiple of " - "%d\n", "address", len, + "%d\n", "intr", len, sizeof(struct linux_prom_irqs)); - panic("zilog: address property"); + panic("zilog: intr property"); } if(!irq) { irq = zilog_irq = tmp_irq[0].pri; @@ -2110,11 +2213,62 @@ write_zsreg(zs_soft[channel].zs_channel, R13, ((brg >> 8) & 0xff)); } -int __init zs_probe (unsigned long *memory_start) +void __init zs_init_alloc_failure(const char *table_name) +{ + prom_printf("zs_probe: Cannot alloc %s.\n", table_name); + prom_halt(); +} + +void * __init zs_alloc_bootmem(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + +void __init zs_alloc_tables(void) +{ + zs_chips = (struct sun_zslayout **) + zs_alloc_bootmem(NUM_SERIAL * sizeof(struct sun_zslayout *)); + if (zs_chips == NULL) + zs_init_alloc_failure("zs_chips"); + zs_channels = (struct sun_zschannel **) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_zschannel *)); + if (zs_channels == NULL) + zs_init_alloc_failure("zs_channels"); + zs_nodes = (int *) + zs_alloc_bootmem(NUM_SERIAL * sizeof(int)); + if (zs_nodes == NULL) + zs_init_alloc_failure("zs_nodes"); + zs_soft = (struct sun_serial *) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_serial)); + if (zs_soft == NULL) + zs_init_alloc_failure("zs_soft"); + zs_ttys = (struct tty_struct *) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct)); + if (zs_ttys == NULL) + zs_init_alloc_failure("zs_ttys"); + serial_table = (struct tty_struct **) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct *)); + if (serial_table == NULL) + zs_init_alloc_failure("serial_table"); + serial_termios = (struct termios **) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *)); + if (serial_termios == NULL) + zs_init_alloc_failure("serial_termios"); + serial_termios_locked = (struct termios **) + zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *)); + if (serial_termios_locked == NULL) + zs_init_alloc_failure("serial_termios_locked"); +} + +int __init zs_probe(void) { - char *p; int node; - int i; if(sparc_cpu_model == sun4) goto no_probe; @@ -2166,42 +2320,24 @@ NUM_SERIAL = 2; no_probe: - p = (char *)((*memory_start + 7) & ~7); - zs_chips = (struct sun_zslayout **)(p); - i = NUM_SERIAL * sizeof (struct sun_zslayout *); - zs_channels = (struct sun_zschannel **)(p + i); - i += NUM_CHANNELS * sizeof (struct sun_zschannel *); - zs_nodes = (int *)(p + i); - i += NUM_SERIAL * sizeof (int); - zs_soft = (struct sun_serial *)(p + i); - i += NUM_CHANNELS * sizeof (struct sun_serial); - zs_ttys = (struct tty_struct *)(p + i); - i += NUM_CHANNELS * sizeof (struct tty_struct); - serial_table = (struct tty_struct **)(p + i); - i += NUM_CHANNELS * sizeof (struct tty_struct *); - serial_termios = (struct termios **)(p + i); - i += NUM_CHANNELS * sizeof (struct termios *); - serial_termios_locked = (struct termios **)(p + i); - i += NUM_CHANNELS * sizeof (struct termios *); - memset (p, 0, i); - *memory_start = (((unsigned long)p) + i + 7) & ~7; + zs_alloc_tables(); /* Fill in rs_ops struct... */ #ifdef CONFIG_SERIAL_CONSOLE - sunserial_setinitfunc(memory_start, zs_console_init); + sunserial_setinitfunc(zs_console_init); #endif - sunserial_setinitfunc(memory_start, zs_init); + sunserial_setinitfunc(zs_init); rs_ops.rs_kgdb_hook = zs_kgdb_hook; rs_ops.rs_change_mouse_baud = zs_change_mouse_baud; - sunkbd_setinitfunc(memory_start, sun_kbd_init); + sunkbd_setinitfunc(sun_kbd_init); kbd_ops.compute_shiftstate = sun_compute_shiftstate; kbd_ops.setledstate = sun_setledstate; kbd_ops.getledstate = sun_getledstate; kbd_ops.setkeycode = sun_setkeycode; kbd_ops.getkeycode = sun_getkeycode; #if defined(__sparc_v9__) && defined(CONFIG_PCI) - sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count, + sunkbd_install_keymaps(sun_key_maps, sun_keymap_count, sun_func_buf, sun_func_table, sun_funcbufsize, sun_funcbufleft, sun_accent_table, sun_accent_table_size); @@ -2214,7 +2350,8 @@ int channel, chip; unsigned long flags; - if (!NUM_SERIAL) return; + if (!NUM_SERIAL) + return; save_and_cli(flags); @@ -2346,12 +2483,13 @@ */ if (request_irq(zilog_irq, zs_interrupt, (SA_INTERRUPT | SA_STATIC_ALLOC), - "Zilog8530", zs_chain)) - panic("Unable to attach zs intr\n"); + "Zilog8530", zs_chain)) { + prom_printf("Unable to attach zs intr\n"); + prom_halt(); + } /* Initialize Hardware */ for(channel = 0; channel < NUM_CHANNELS; channel++) { - /* Hardware reset each chip */ if (!(channel & 1)) { write_zsreg(zs_soft[channel].zs_channel, R9, FHWRES); @@ -2580,12 +2718,14 @@ */ static void zs_fair_output(struct sun_serial *info) { - int left; /* Output no more than that */ unsigned long flags; + int left; /* Output no more than that */ char c; - if (info == 0) return; - if (info->xmit_buf == 0) return; + if (info == NULL) + return; + if (info->xmit_buf == NULL) + return; save_flags(flags); cli(); left = info->xmit_cnt; @@ -2602,8 +2742,9 @@ } /* Last character is being transmitted now (hopefully). */ - info->zs_channel->control = RES_Tx_P; + sbus_writeb(RES_Tx_P, &info->zs_channel->control); ZSDELAY(); + ZSLOG(REGCTRL, RES_Tx_P, 1); restore_flags(flags); return; diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/zs.h linux/drivers/sbus/char/zs.h --- v2.3.34/linux/drivers/sbus/char/zs.h Wed May 12 08:41:15 1999 +++ linux/drivers/sbus/char/zs.h Mon Dec 20 22:06:42 1999 @@ -1,11 +1,11 @@ -/* $Id: zs.h,v 1.2 1999/05/12 11:15:31 davem Exp $ +/* $Id: zs.h,v 1.3 1999/09/21 14:38:18 davem Exp $ * zs.h: Definitions for the Sparc Zilog serial driver. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) */ -#ifndef _SPARC_SERIAL_H -#define _SPARC_SERIAL_H +#ifndef _ZS_H +#define _ZS_H /* Just one channel */ struct sun_zschannel { @@ -411,18 +411,17 @@ /* Read Register 15 (value of WR 15) */ /* Misc macros */ -#define ZS_CLEARERR(channel) do { channel->control = ERR_RES; \ +#define ZS_CLEARERR(channel) do { sbus_writeb(ERR_RES, &channel->control); \ udelay(5); } while(0) -#define ZS_CLEARSTAT(channel) do { channel->control = RES_EXT_INT; \ +#define ZS_CLEARSTAT(channel) do { sbus_writeb(RES_EXT_INT, &channel->control); \ udelay(5); } while(0) -#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ - garbage = channel->data; \ +#define ZS_CLEARFIFO(channel) do { sbus_readb(&channel->data); \ udelay(2); \ - garbage = channel->data; \ + sbus_readb(&channel->data); \ udelay(2); \ - garbage = channel->data; \ + sbus_readb(&channel->data); \ udelay(2); } while(0) -#endif /* !(_SPARC_SERIAL_H) */ +#endif /* !(_ZS_H) */ diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c --- v2.3.34/linux/drivers/sbus/dvma.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/sbus/dvma.c Mon Dec 20 22:06:42 1999 @@ -15,55 +15,51 @@ #include #include -struct Linux_SBus_DMA *dma_chain; +struct sbus_dma *dma_chain; /* Print out the current values in the DMA control registers */ -extern __inline__ void -dump_dma_regs(struct sparc_dma_registers *dregs) +extern __inline__ void dump_dma_regs(unsigned long dregs) { - printk("DMA CONTROL<%08lx> ADDR<%08lx> CNT<%08lx> TEST<%08lx>\n", - (unsigned long) dregs->cond_reg, - (unsigned long) dregs->st_addr, - (unsigned long) dregs->cnt, - (unsigned long) dregs->dma_test); - return; + printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n", + sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR), + sbus_readl(dregs + DMA_COUNT), sbus_readl(dregs + DMA_TEST)); } -void __init init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma) +void __init init_one_dvma(struct sbus_dma *dma, int num_dma) { printk("dma%d: ", num_dma); dma->next = 0; - dma->running=0; /* No transfers going on as of yet */ - dma->allocated=0; /* No one has allocated us yet */ - switch((dma->regs->cond_reg)&DMA_DEVICE_ID) { + dma->running = 0; /* No transfers going on as of yet */ + dma->allocated = 0; /* No one has allocated us yet */ + switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) { case DMA_VERS0: - dma->revision=dvmarev0; + dma->revision = dvmarev0; printk("Revision 0 "); break; case DMA_ESCV1: - dma->revision=dvmaesc1; + dma->revision = dvmaesc1; printk("ESC Revision 1 "); break; case DMA_VERS1: - dma->revision=dvmarev1; + dma->revision = dvmarev1; printk("Revision 1 "); break; case DMA_VERS2: - dma->revision=dvmarev2; + dma->revision = dvmarev2; printk("Revision 2 "); break; case DMA_VERHME: - dma->revision=dvmahme; + dma->revision = dvmahme; printk("HME DVMA gate array "); break; case DMA_VERSPLUS: - dma->revision=dvmarevplus; + dma->revision = dvmarevplus; printk("Revision 1 PLUS "); break; default: - printk("unknown dma version %x", - (dma->regs->cond_reg)&DMA_DEVICE_ID); + printk("unknown dma version %08x", + sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID); dma->allocated = 1; break; } @@ -74,57 +70,47 @@ } /* Probe this SBus DMA module(s) */ -void __init dvma_init(struct linux_sbus *sbus) +void __init dvma_init(struct sbus_bus *sbus) { - struct linux_sbus_device *this_dev; - struct Linux_SBus_DMA *dma; - struct Linux_SBus_DMA *dchain; - static int num_dma=0; + struct sbus_dev *this_dev; + struct sbus_dma *dma; + struct sbus_dma *dchain; + static int num_dma = 0; for_each_sbusdev(this_dev, sbus) { + char *name = this_dev->prom_name; int hme = 0; - if(!strcmp(this_dev->prom_name, "SUNW,fas")) + if(!strcmp(name, "SUNW,fas")) hme = 1; - else if(strcmp(this_dev->prom_name, "dma") && - strcmp(this_dev->prom_name, "ledma") && - strcmp(this_dev->prom_name, "espdma")) + else if(strcmp(name, "dma") && + strcmp(name, "ledma") && + strcmp(name, "espdma")) continue; /* Found one... */ - dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); + dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); - dma->SBus_dev = this_dev; + dma->sdev = this_dev; /* Put at end of dma chain */ dchain = dma_chain; if(dchain) { - while(dchain->next) dchain=dchain->next; - dchain->next=dma; + while(dchain->next) + dchain = dchain->next; + dchain->next = dma; } else { /* We're the first in line */ - dma_chain=dma; + dma_chain = dma; } - /* The constant PAGE_SIZE that is passed to sparc_alloc_io makes the - * routine only alloc 1 page, that was what the original code did - */ - if(hme) /* On HME cards, dvma lives with esp, 2 reg sets. */ - prom_apply_sbus_ranges(sbus, dma->SBus_dev->reg_addrs, - 0x2, dma->SBus_dev); - else /* All others have only 1 reg set. */ - prom_apply_sbus_ranges(sbus, dma->SBus_dev->reg_addrs, - 0x1, dma->SBus_dev); - dma->regs = (struct sparc_dma_registers *) - sparc_alloc_io (dma->SBus_dev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "dma", - dma->SBus_dev->reg_addrs[0].which_io, 0x0); + dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0, + PAGE_SIZE, "dma"); - dma->node = dma->SBus_dev->prom_node; + dma->node = dma->sdev->prom_node; init_one_dvma(dma, num_dma++); - - }; /* while(this_dev) */ + } } #ifdef CONFIG_SUN4 @@ -133,28 +119,29 @@ void __init sun4_dvma_init(void) { - struct Linux_SBus_DMA *dma; - struct Linux_SBus_DMA *dchain; + struct sbus_dma *dma; + struct sbus_dma *dchain; + struct resource r; if(sun4_dma_physaddr) { - dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC); + dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); /* No SBUS */ - dma->SBus_dev = 0x0; + dma->sdev = NULL; /* Only one DMA device */ - dma_chain=dma; + dma_chain = dma; - dma->regs = (struct sparc_dma_registers *) - sparc_alloc_io (sun4_dma_physaddr, 0, - PAGE_SIZE, "dma", 0x0, 0x0); + memset(&r, 0, sizeof(r)); + r.start = sun4_dma_physaddr; + dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma"); /* No prom node */ dma->node = 0x0; init_one_dvma(dma, 0); } else { - dma_chain=0x0; + dma_chain = NULL; } } diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- v2.3.34/linux/drivers/sbus/sbus.c Fri Sep 10 23:57:30 1999 +++ linux/drivers/sbus/sbus.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.80 1999/09/02 05:44:33 shadow Exp $ +/* $Id: sbus.c,v 1.83 1999/10/18 01:47:01 zaitcev Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -17,17 +17,10 @@ #include #include -/* This file has been written to be more dynamic and a bit cleaner, - * but it still needs some spring cleaning. - */ +struct sbus_bus *sbus_root = NULL; -struct linux_sbus *SBus_chain; static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; -static char lbuf[128]; - -extern void prom_sbus_ranges_init (int, struct linux_sbus *); - /* Perhaps when I figure out more about the iommu we'll put a * device registration routine here that probe_sbus() calls to * setup the iommu for each Sbus. @@ -40,151 +33,127 @@ /* #define DEBUG_FILL */ -static void __init fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev) +static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) { - int grrr, len; - unsigned long dev_base_addr, base; + unsigned long address, base; + int len; - sbus_dev->prom_node = nd; - prom_getstring(nd, "name", lbuf, sizeof(lbuf)); - strcpy(sbus_dev->prom_name, lbuf); - - dev_base_addr = prom_getint(nd, "address"); - if(dev_base_addr != -1) - sbus_dev->sbus_addr = dev_base_addr; - - len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs, - sizeof(sbus_dev->reg_addrs)); - if(len == -1) + sdev->prom_node = prom_node; + prom_getstring(prom_node, "name", + sdev->prom_name, sizeof(sdev->prom_name)); + address = prom_getint(prom_node, "address"); + len = prom_getproperty(prom_node, "reg", + (char *) sdev->reg_addrs, + sizeof(sdev->reg_addrs)); + if (len == -1) { + sdev->num_registers = 0; goto no_regs; - if(len%sizeof(struct linux_prom_registers)) { - prom_printf("WHOOPS: proplen for %s was %d, need multiple of %d\n", - sbus_dev->prom_name, len, - (int) sizeof(struct linux_prom_registers)); - panic("fill_sbus_device"); - } - sbus_dev->num_registers = (len/sizeof(struct linux_prom_registers)); - sbus_dev->ranges_applied = 0; - - base = (unsigned long) sbus_dev->reg_addrs[0].phys_addr; - if(base>=SUN_SBUS_BVADDR || - (sparc_cpu_model != sun4c && - sparc_cpu_model != sun4)) { - /* Ahh, we can determine the slot and offset */ - if(sparc_cpu_model == sun4u) { - /* A bit tricky on the SYSIO. */ - sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; - sbus_dev->offset = sbus_dev_offset(base); - } else if (sparc_cpu_model == sun4d) { - sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; - sbus_dev->offset = base; - } else { - sbus_dev->slot = sbus_dev_slot(base); - sbus_dev->offset = sbus_dev_offset(base); + } + + if (len % sizeof(struct linux_prom_registers)) { + prom_printf("fill_sbus_device: proplen for regs of %s " + " was %d, need multiple of %d\n", + sdev->prom_name, len, + (int) sizeof(struct linux_prom_registers)); + prom_halt(); + } + if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { + prom_printf("fill_sbus_device: Too many register properties " + "for device %s, len=%d\n", + sdev->prom_name, len); + prom_halt(); + } + sdev->num_registers = len / sizeof(struct linux_prom_registers); + sdev->ranges_applied = 0; + + base = (unsigned long) sdev->reg_addrs[0].phys_addr; + if (base >= SUN_SBUS_BVADDR || + (sparc_cpu_model != sun4c && sparc_cpu_model != sun4)) { + /* OK, we can compute the slot number in a + * straightforward manner. + */ + if (sparc_cpu_model == sun4u || + sparc_cpu_model == sun4d) + sdev->slot = sdev->reg_addrs[0].which_io; + else + sdev->slot = sbus_dev_slot(base); + } else { + int rnum; + + /* Fixups are needed to compute the slot number. */ + sdev->slot = sdev->reg_addrs[0].which_io; + sdev->reg_addrs[0].phys_addr = + sbus_devaddr(sdev->slot, base); + for (rnum = 1; rnum < sdev->num_registers; rnum++) { + base = (unsigned long) + sdev->reg_addrs[rnum].phys_addr; + sdev->reg_addrs[rnum].phys_addr = + sbus_devaddr(sdev->slot, base); } - } else { /* Grrr, gotta do calculations to fix things up */ - sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; - sbus_dev->offset = base; - sbus_dev->reg_addrs[0].phys_addr = - sbus_devaddr(sbus_dev->slot, base); - for(grrr=1; grrrnum_registers; grrr++) { - base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr; - sbus_dev->reg_addrs[grrr].phys_addr = - sbus_devaddr(sbus_dev->slot, base); - } - /* That surely sucked */ - } - sbus_dev->sbus_addr = (unsigned long) sbus_dev->reg_addrs[0].phys_addr; - if(len>(sizeof(struct linux_prom_registers)*PROMREG_MAX)) { - prom_printf("WHOOPS: I got too many register addresses for %s len=%d\n", - sbus_dev->prom_name, len); - panic("sbus device register overflow"); } no_regs: - len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs, - sizeof(sbus_dev->sbus_vaddrs)); - if(len == -1) len=0; - if(len&3) { - prom_printf("Grrr, I didn't get a multiple of 4 proplen " - "for device %s got %d\n", sbus_dev->prom_name, len); - len=0; - } - sbus_dev->num_vaddrs = (len/4); - -#ifdef __sparc_v9__ - len = prom_getproperty(nd, "interrupts", (void *)irqs, sizeof(irqs)); - if((len == -1) || (len == 0)) { - sbus_dev->irqs[0] = 0; - sbus_dev->num_irqs = 0; - } else { - sbus_dev->num_irqs = 1; - if (irqs[0].pri < 0x20) - sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, - irqs[0].pri + (sbus_dev->slot * 8)); - else - sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, - irqs[0].pri); + len = prom_getproperty(prom_node, "ranges", + (char *)sdev->device_ranges, + sizeof(sdev->device_ranges)); + if (len == -1) { + sdev->num_device_ranges = 0; + goto no_ranges; } -#else - len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs)); - if (len == -1) len=0; - if (len&7) { - prom_printf("Grrr, I didn't get a multiple of 8 proplen for " - "device %s got %d\n", sbus_dev->prom_name, len); - len=0; - } - if (len > 4 * 8) { - prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name); - len = 4 * 8; - } - sbus_dev->num_irqs=(len/8); - if(sbus_dev->num_irqs == 0) - sbus_dev->irqs[0]=0; - else if (sparc_cpu_model != sun4d) - for (len = 0; len < sbus_dev->num_irqs; len++) - sbus_dev->irqs[len] = irqs[len].pri; - else { - extern unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq); - - for (len = 0; len < sbus_dev->num_irqs; len++) - sbus_dev->irqs[len] = sun4d_build_irq(sbus_dev, irqs[len].pri); + if (len % sizeof(struct linux_prom_ranges)) { + prom_printf("fill_sbus_device: proplen for ranges of %s " + " was %d, need multiple of %d\n", + sdev->prom_name, len, + (int) sizeof(struct linux_prom_ranges)); + prom_halt(); } -#endif + if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { + prom_printf("fill_sbus_device: Too many range properties " + "for device %s, len=%d\n", + sdev->prom_name, len); + prom_halt(); + } + sdev->num_device_ranges = + len / sizeof(struct linux_prom_ranges); -#ifdef DEBUG_FILL -#ifdef __sparc_v9__ - prom_printf("Found %s at SBUS slot %x offset %016lx ", - sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset); - if (sbus_dev->irqs[0]) - prom_printf("irq %s\n", __irq_itoa(sbus_dev->irqs[0])); - else - prom_printf("\n"); - prom_printf("Base address %016lx\n", sbus_dev->sbus_addr); -#else - prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n", - sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset, - sbus_dev->irqs[0]); - prom_printf("Base address %08lx\n", sbus_dev->sbus_addr); -#endif - prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers); - for(len=0; lennum_registers; len++) +no_ranges: + /* XXX Unfortunately, IRQ issues are very arch specific. + * XXX Pull this crud out into an arch specific area + * XXX at some point. -DaveM + */ #ifdef __sparc_v9__ - prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d " - "bytes, %d words>\n", (int) len, - (unsigned long) sbus_dev->reg_addrs[len].phys_addr, - sbus_dev->reg_addrs[len].which_io, - sbus_dev->reg_addrs[len].reg_size, - (sbus_dev->reg_addrs[len].reg_size/4)); + len = prom_getproperty(prom_node, "interrupts", + (char *) irqs, sizeof(irqs)); + if (len == -1 || len == 0) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + unsigned int pri = irqs[0].pri; + + sdev->num_irqs = 1; + if (pri < 0x20) + pri += sdev->slot * 8; + + sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); + } #else - prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d " - "bytes, %d words>\n", (int) len, - (unsigned long) sbus_dev->reg_addrs[len].phys_addr, - sbus_dev->reg_addrs[len].which_io, - sbus_dev->reg_addrs[len].reg_size, - (sbus_dev->reg_addrs[len].reg_size/4)); -#endif -#endif + len = prom_getproperty(prom_node, "intr", + (char *)irqs, sizeof(irqs)); + if (len == -1) + len = 0; + sdev->num_irqs = len / 8; + if (sdev->num_irqs == 0) { + sdev->irqs[0] = 0; + } else if (sparc_cpu_model == sun4d) { + extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); + + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); + } else { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = irqs[len].pri; + } +#endif /* !__sparc_v9__ */ } /* This routine gets called from whoever needs the sbus first, to scan @@ -193,8 +162,8 @@ * devices. */ -extern void iommu_init(int iommu_node, struct linux_sbus *sbus); -extern void iounit_init(int sbi_node, int iounit_node, struct linux_sbus *sbus); +extern void iommu_init(int iommu_node, struct sbus_bus *sbus); +extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus); void sun4_init(void); #ifdef CONFIG_SUN_OPENPROMIO extern int openprom_init(void); @@ -213,41 +182,133 @@ #endif static void __init sbus_do_child_siblings(int start_node, - struct linux_sbus_device *child, - struct linux_sbus *sbus) + struct sbus_dev *child, + struct sbus_dev *parent, + struct sbus_bus *sbus) { - struct linux_sbus_device *this_dev = child; + struct sbus_dev *this_dev = child; int this_node = start_node; /* Child already filled in, just need to traverse siblings. */ - child->child = 0; + child->child = NULL; + child->parent = parent; while((this_node = prom_getsibling(this_node)) != 0) { - this_dev->next = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC); + this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); this_dev = this_dev->next; this_dev->next = 0; + this_dev->parent = parent; - this_dev->my_bus = sbus; + this_dev->bus = sbus; fill_sbus_device(this_node, this_dev); if(prom_getchild(this_node)) { - this_dev->child = kmalloc(sizeof(struct linux_sbus_device), + this_dev->child = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - this_dev->child->my_bus = sbus; + this_dev->child->bus = sbus; fill_sbus_device(prom_getchild(this_node), this_dev->child); sbus_do_child_siblings(prom_getchild(this_node), - this_dev->child, sbus); + this_dev->child, this_dev, sbus); } else { - this_dev->child = 0; + this_dev->child = NULL; } } } +/* + * XXX This functions appears to be a distorted version of + * prom_sbus_ranges_init(), with all sun4d stuff cut away. + * Ask DaveM what is going on here, how is sun4d supposed to work... XXX + */ +static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus) +{ + int len; + + len = prom_getproperty(sbus->prom_node, "ranges", + (char *) sbus->sbus_ranges, + sizeof(sbus->sbus_ranges)); + if (len == -1 || len == 0) { + sbus->num_sbus_ranges = 0; + return; + } + sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges); +} + +static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, + int num_ranges, + struct linux_prom_registers *regs, + int num_regs) +{ + if (num_ranges) { + int regnum; + + for (regnum = 0; regnum < num_regs; regnum++) { + int rngnum; + + for (rngnum = 0; rngnum < num_ranges; rngnum++) { + if (regs[regnum].which_io == ranges[rngnum].ot_child_space) + break; + } + if (rngnum == num_ranges) { + prom_printf("sbus_apply_ranges: Cannot find matching " + "range nregs[%d] nranges[%d].\n", + num_regs, num_ranges); + prom_halt(); + } + regs[regnum].which_io = ranges[rngnum].ot_parent_space; + regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; + } + } +} + +static void __init __fixup_regs_sdev(struct sbus_dev *sdev) +{ + if (sdev->num_registers != 0) { + struct sbus_dev *parent = sdev->parent; + int i; + + while (parent != NULL) { + __apply_ranges_to_regs(parent->device_ranges, + parent->num_device_ranges, + sdev->reg_addrs, + sdev->num_registers); + + parent = parent->parent; + } + + __apply_ranges_to_regs(sdev->bus->sbus_ranges, + sdev->bus->num_sbus_ranges, + sdev->reg_addrs, + sdev->num_registers); + + for (i = 0; i < sdev->num_registers; i++) { + struct resource *res = &sdev->resource[i]; + + res->start = sdev->reg_addrs[i].phys_addr; + res->end = (res->start + + (unsigned long)sdev->reg_addrs[i].reg_size - 1UL); + res->flags = IORESOURCE_IO | + (sdev->reg_addrs[i].which_io & 0xff); + } + } +} + +static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) +{ + struct sbus_dev *sdev; + + for (sdev = first_sdev; sdev; sdev = sdev->next) { + if (sdev->child) + sbus_fixup_all_regs(sdev->child); + __fixup_regs_sdev(sdev); + } +} + void __init sbus_init(void) { - register int nd, this_sbus, sbus_devs, topnd, iommund; + int nd, this_sbus, sbus_devs, topnd, iommund; unsigned int sbus_clock; - struct linux_sbus *sbus; - struct linux_sbus_device *this_dev; + struct sbus_bus *sbus; + struct sbus_dev *this_dev; int num_sbus = 0; /* How many did we find? */ #ifdef CONFIG_SUN4 @@ -303,33 +364,38 @@ /* Ok, we've found the first one, allocate first SBus struct * and place in chain. */ - sbus = SBus_chain = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC); - sbus->next = 0; + sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); + sbus->next = NULL; sbus->prom_node = nd; - this_sbus=nd; + this_sbus = nd; if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) iommu_init(iommund, sbus); /* Loop until we find no more SBUS's */ while(this_sbus) { +#ifdef __sparc_v9__ /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ - if(sparc_cpu_model == sun4u) - iommu_init(this_sbus, sbus); + if(sparc_cpu_model == sun4u) { + extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus); + + sbus_iommu_init(this_sbus, sbus); + } +#endif #ifndef __sparc_v9__ - else if (sparc_cpu_model == sun4d) + if (sparc_cpu_model == sun4d) iounit_init(this_sbus, iommund, sbus); #endif printk("sbus%d: ", num_sbus); sbus_clock = prom_getint(this_sbus, "clock-frequency"); - if(sbus_clock==-1) sbus_clock = (25*1000*1000); + if(sbus_clock == -1) + sbus_clock = (25*1000*1000); printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), (int) (((sbus_clock/1000)%1000 != 0) ? (((sbus_clock/1000)%1000) + 1000) : 0)); - prom_getstring(this_sbus, "name", lbuf, sizeof(lbuf)); - lbuf[sizeof(sbus->prom_name) - 1] = 0; - strcpy(sbus->prom_name, lbuf); + prom_getstring(this_sbus, "name", + sbus->prom_name, sizeof(sbus->prom_name)); sbus->clock_freq = sbus_clock; #ifndef __sparc_v9__ if (sparc_cpu_model == sun4d) { @@ -338,60 +404,69 @@ } #endif - prom_sbus_ranges_init (iommund, sbus); + sbus_bus_ranges_init(iommund, sbus); sbus_devs = prom_getchild(this_sbus); - sbus->devices = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC); + sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); this_dev = sbus->devices; - this_dev->next = 0; + this_dev->next = NULL; - this_dev->my_bus = sbus; + this_dev->bus = sbus; + this_dev->parent = NULL; fill_sbus_device(sbus_devs, this_dev); /* Should we traverse for children? */ if(prom_getchild(sbus_devs)) { /* Allocate device node */ - this_dev->child = kmalloc(sizeof(struct linux_sbus_device), + this_dev->child = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); /* Fill it */ - this_dev->child->my_bus = sbus; - fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); + this_dev->child->bus = sbus; + fill_sbus_device(prom_getchild(sbus_devs), + this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), - this_dev->child, sbus); + this_dev->child, + this_dev, + sbus); } else { - this_dev->child = 0; + this_dev->child = NULL; } while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { /* Allocate device node */ - this_dev->next = kmalloc(sizeof(struct linux_sbus_device), + this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - this_dev=this_dev->next; - this_dev->next=0; + this_dev = this_dev->next; + this_dev->next = NULL; /* Fill it */ - this_dev->my_bus = sbus; + this_dev->bus = sbus; + this_dev->parent = NULL; fill_sbus_device(sbus_devs, this_dev); /* Is there a child node hanging off of us? */ if(prom_getchild(sbus_devs)) { /* Get new device struct */ - this_dev->child = - kmalloc(sizeof(struct linux_sbus_device), - GFP_ATOMIC); + this_dev->child = kmalloc(sizeof(struct sbus_dev), + GFP_ATOMIC); /* Fill it */ - this_dev->child->my_bus = sbus; + this_dev->child->bus = sbus; fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), - this_dev->child, sbus); + this_dev->child, + this_dev, + sbus); } else { - this_dev->child = 0; + this_dev->child = NULL; } } + /* Walk all devices and apply parent ranges. */ + sbus_fixup_all_regs(sbus->devices); + dvma_init(sbus); num_sbus++; @@ -402,24 +477,28 @@ this_sbus = prom_searchsiblings(this_sbus, "sbus"); } else if(sparc_cpu_model == sun4d) { iommund = prom_getsibling(iommund); - if(!iommund) break; + if(!iommund) + break; iommund = prom_searchsiblings(iommund, "io-unit"); - if(!iommund) break; + if(!iommund) + break; this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi"); } else { this_sbus = prom_getsibling(this_sbus); - if(!this_sbus) break; + if(!this_sbus) + break; this_sbus = prom_searchsiblings(this_sbus, "sbus"); } if(this_sbus) { - sbus->next = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC); + sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); sbus = sbus->next; - sbus->next = 0; + sbus->next = NULL; sbus->prom_node = this_sbus; } else { break; } } /* while(this_sbus) */ + if (sparc_cpu_model == sun4d) { extern void sun4d_init_sbi_irq(void); sun4d_init_sbi_irq(); diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.3.34/linux/drivers/scsi/BusLogic.c Thu Nov 11 20:11:43 1999 +++ linux/drivers/scsi/BusLogic.c Tue Dec 21 10:17:32 1999 @@ -75,13 +75,13 @@ /* - BusLogic_Options can be assigned a string by the Loadable Kernel Module - Installation Facility to be parsed for BusLogic Driver Options - specifications. + BusLogic can be assigned a string by insmod. */ -static char - *BusLogic_Options = NULL; +#ifdef MODULE +static char *BusLogic = NULL; +MODULE_PARM(BusLogic, "s"); +#endif /* @@ -2724,8 +2724,10 @@ return 0; } memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T)); - if (BusLogic_Options != NULL) - BusLogic_ParseDriverOptions(BusLogic_Options); +#ifdef MODULE + if (BusLogic != NULL) + BusLogic_Setup(BusLogic); +#endif BusLogic_InitializeProbeInfoList(PrototypeHostAdapter); for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) { @@ -4655,14 +4657,14 @@ INSMOD Loadable Kernel Module Installation Facility: insmod BusLogic.o \ - 'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' + 'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"' NOTE: Module Utilities 2.1.71 or later is required for correct parsing of driver options containing commas. */ -static void BusLogic_ParseDriverOptions(char *OptionsString) +static int __init BusLogic_ParseDriverOptions(char *OptionsString) { while (true) { @@ -4705,7 +4707,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(illegal I/O Address 0x%X)\n", NULL, IO_Address); - return; + return 0; } } else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA")) @@ -4735,7 +4737,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(illegal Queue Depth %d)\n", NULL, QueueDepth); - return; + return 0; } DriverOptions->QueueDepth[TargetID] = QueueDepth; if (*OptionsString == ',') @@ -4747,7 +4749,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString); - return; + return 0; } } if (*OptionsString != ']') @@ -4755,7 +4757,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString); - return; + return 0; } else OptionsString++; } @@ -4769,7 +4771,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(illegal Queue Depth %d)\n", NULL, QueueDepth); - return; + return 0; } DriverOptions->CommonQueueDepth = QueueDepth; for (TargetID = 0; @@ -4887,7 +4889,7 @@ BusLogic_Error("BusLogic: Invalid Driver Options " "(illegal Bus Settle Time %d)\n", NULL, BusSettleTime); - return; + return 0; } DriverOptions->BusSettleTime = BusSettleTime; } @@ -4925,7 +4927,7 @@ { BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL); - return; + return 0; } /* Tagged Queuing is disabled when the Queue Depth is 1 since queuing @@ -4939,8 +4941,9 @@ DriverOptions->TaggedQueuingPermittedMask |= TargetBit; } if (*OptionsString == ';') OptionsString++; - if (*OptionsString == '\0') return; + if (*OptionsString == '\0') return 0; } + return 1; } @@ -4948,26 +4951,30 @@ BusLogic_Setup handles processing of Kernel Command Line Arguments. */ -void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers) +static int __init +BusLogic_Setup(char *str) { - if (CommandLineIntegers[0] != 0) - { - BusLogic_Error("BusLogic: Obsolete Command Line Entry " - "Format Ignored\n", NULL); - return; - } - if (CommandLineString == NULL || *CommandLineString == '\0') return; - BusLogic_ParseDriverOptions(CommandLineString); + int ints[3]; + + (void)get_options(str, ARRAY_SIZE(ints), ints); + + if (ints[0] != 0) { + BusLogic_Error("BusLogic: Obsolete Command Line Entry " + "Format Ignored\n", NULL); + return 0; + } + if (str == NULL || *str == '\0') + return 0; + return BusLogic_ParseDriverOptions(str); } +__setup("BusLogic=", BusLogic_Setup); /* Include Module support if requested. */ #ifdef MODULE - -MODULE_PARM(BusLogic_Options, "s"); SCSI_Host_Template_T driver_template = BUSLOGIC; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h --- v2.3.34/linux/drivers/scsi/BusLogic.h Tue Nov 23 22:42:21 1999 +++ linux/drivers/scsi/BusLogic.h Tue Dec 28 17:44:24 1999 @@ -1767,8 +1767,6 @@ SCSI_Command_T *, unsigned int); static void BusLogic_Message(BusLogic_MessageLevel_T, char *, BusLogic_HostAdapter_T *, ...); -static void BusLogic_ParseDriverOptions(char *); - /* Declare the Initialization Functions. @@ -1803,8 +1801,8 @@ int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *) __init; int BusLogic_ReleaseHostAdapter(SCSI_Host_T *) __init; static boolean BusLogic_ParseKeyword(char **, char *) __init; -static void BusLogic_ParseDriverOptions(char *) __init; -void BusLogic_Setup(char *, int *) __init; +static int BusLogic_ParseDriverOptions(char *) __init; +static int BusLogic_Setup(char *) __init; #endif /* BusLogic_DriverVersion */ diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c --- v2.3.34/linux/drivers/scsi/esp.c Thu Nov 11 20:11:46 1999 +++ linux/drivers/scsi/esp.c Wed Dec 22 19:55:38 1999 @@ -1,4 +1,5 @@ -/* esp.c: EnhancedScsiProcessor Sun SCSI driver code. +/* $Id: esp.c,v 1.89 1999/12/23 01:46:14 davem Exp $ + * esp.c: EnhancedScsiProcessor Sun SCSI driver code. * * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) */ @@ -39,6 +40,8 @@ #include #include +#include + #define DEBUG_ESP /* #define DEBUG_ESP_HME */ /* #define DEBUG_ESP_DATA */ @@ -174,18 +177,16 @@ }; /* The master ring of all esp hosts we are managing in this driver. */ -static struct Sparc_ESP *espchain; +static struct esp *espchain; +static spinlock_t espchain_lock = SPIN_LOCK_UNLOCKED; static int esps_running = 0; /* Forward declarations. */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs); -#ifndef __sparc_v9__ -static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs); -#endif /* Debugging routines */ struct esp_cmdstrings { - unchar cmdchar; + u8 cmdchar; char *text; } esp_cmd_strings[] = { /* Miscellaneous */ @@ -225,16 +226,16 @@ #define NUM_ESP_COMMANDS ((sizeof(esp_cmd_strings)) / (sizeof(struct esp_cmdstrings))) /* Print textual representation of an ESP command */ -static inline void esp_print_cmd(unchar espcmd) +static inline void esp_print_cmd(u8 espcmd) { - unchar dma_bit = espcmd & ESP_CMD_DMA; + u8 dma_bit = espcmd & ESP_CMD_DMA; int i; espcmd &= ~dma_bit; - for(i=0; i"); } /* Print the interrupt register's value */ -static inline void esp_print_ireg(unchar intreg) +static inline void esp_print_ireg(u8 intreg) { printk("INTREG< "); - if(intreg & ESP_INTR_S) + if (intreg & ESP_INTR_S) printk("SLCT_NATN "); - if(intreg & ESP_INTR_SATN) + if (intreg & ESP_INTR_SATN) printk("SLCT_ATN "); - if(intreg & ESP_INTR_RSEL) + if (intreg & ESP_INTR_RSEL) printk("RSLCT "); - if(intreg & ESP_INTR_FDONE) + if (intreg & ESP_INTR_FDONE) printk("FDONE "); - if(intreg & ESP_INTR_BSERV) + if (intreg & ESP_INTR_BSERV) printk("BSERV "); - if(intreg & ESP_INTR_DC) + if (intreg & ESP_INTR_DC) printk("DISCNCT "); - if(intreg & ESP_INTR_IC) + if (intreg & ESP_INTR_IC) printk("ILL_CMD "); - if(intreg & ESP_INTR_SR) + if (intreg & ESP_INTR_SR) printk("SCSI_BUS_RESET "); printk(">"); } /* Print the sequence step registers contents */ -static inline void esp_print_seqreg(unchar stepreg) +static inline void esp_print_seqreg(u8 stepreg) { stepreg &= ESP_STEP_VBITS; printk("STEP<%s>", @@ -306,7 +307,7 @@ static char *phase_string(int phase) { - switch(phase) { + switch (phase) { case not_issued: return "UNISSUED"; case in_slct_norm: @@ -374,17 +375,24 @@ #endif #ifdef DEBUG_ESP_CMDS -extern inline void esp_cmd(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - unchar cmd) +extern inline void esp_cmd(struct esp *esp, u8 cmd) { esp->espcmdlog[esp->espcmdent] = cmd; esp->espcmdent = (esp->espcmdent + 1) & 31; - eregs->esp_cmd = cmd; + sbus_writeb(cmd, esp->eregs + ESP_CMD); } #else -#define esp_cmd(__esp, __eregs, __cmd) (__eregs)->esp_cmd = (__cmd) +#define esp_cmd(__esp, __cmd) \ + sbus_writeb((__cmd), ((__esp)->eregs) + ESP_CMD) #endif +#define ESP_INTSOFF(__dregs) \ + sbus_writel(sbus_readl((__dregs)+DMA_CSR)&~(DMA_INT_ENAB), (__dregs)+DMA_CSR) +#define ESP_INTSON(__dregs) \ + sbus_writel(sbus_readl((__dregs)+DMA_CSR)|DMA_INT_ENAB, (__dregs)+DMA_CSR) +#define ESP_IRQ_P(__dregs) \ + (sbus_readl((__dregs)+DMA_CSR) & (DMA_HNDL_INTR|DMA_HNDL_ERROR)) + /* How we use the various Linux SCSI data structures for operation. * * struct scsi_cmnd: @@ -412,10 +420,10 @@ Scsi_Cmnd *end; new_SC->host_scribble = (unsigned char *) NULL; - if(!*SC) + if (!*SC) *SC = new_SC; else { - for(end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble) + for (end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble) ; end->host_scribble = (unsigned char *) new_SC; } @@ -431,7 +439,7 @@ { Scsi_Cmnd *ptr; ptr = *SC; - if(ptr) + if (ptr) *SC = (Scsi_Cmnd *) (*SC)->host_scribble; return ptr; } @@ -440,12 +448,12 @@ { Scsi_Cmnd *ptr, *prev; - for(ptr = *SC, prev = NULL; - ptr && ((ptr->target != target) || (ptr->lun != lun)); - prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) + for (ptr = *SC, prev = NULL; + ptr && ((ptr->target != target) || (ptr->lun != lun)); + prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) ; - if(ptr) { - if(prev) + if (ptr) { + if (prev) prev->host_scribble=ptr->host_scribble; else *SC=(Scsi_Cmnd *)ptr->host_scribble; @@ -454,61 +462,61 @@ } /* Resetting various pieces of the ESP scsi driver chipset/buses. */ -static void esp_reset_dma(struct Sparc_ESP *esp) +static void esp_reset_dma(struct esp *esp) { - struct sparc_dma_registers *dregs = esp->dregs; unsigned long flags; int can_do_burst16, can_do_burst32, can_do_burst64; int can_do_sbus64; + u32 tmp; - can_do_burst16 = esp->bursts & DMA_BURST16; - can_do_burst32 = esp->bursts & DMA_BURST32; + can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; + can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; can_do_burst64 = 0; can_do_sbus64 = 0; -#ifdef __sparc_v9__ - /* XXX Can sun4d do these too? */ - can_do_burst64 = esp->bursts & DMA_BURST64; - can_do_sbus64 = 1; - mmu_set_sbus64(esp->edev, esp->bursts); -#endif + if (sbus_can_dma_64bit(esp->sdev)) + can_do_sbus64 = 1; + if (sbus_can_burst64(esp->sdev)) + can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; /* Punt the DVMA into a known state. */ - if(esp->dma->revision != dvmahme) { - dregs->cond_reg |= DMA_RST_SCSI; - dregs->cond_reg &= ~(DMA_RST_SCSI); + if (esp->dma->revision != dvmahme) { + tmp = sbus_readl(esp->dregs + DMA_CSR); + sbus_writel(tmp | DMA_RST_SCSI, esp->dregs + DMA_CSR); + sbus_writel(tmp & ~DMA_RST_SCSI, esp->dregs + DMA_CSR); } - switch(esp->dma->revision) { + switch (esp->dma->revision) { case dvmahme: /* This is the HME DVMA gate array. */ save_flags(flags); cli(); /* I really hate this chip. */ - dregs->cond_reg = DMA_RESET_FAS366; /* Reset interface to FAS */ - dregs->cond_reg = DMA_RST_SCSI; /* Reset DVMA itself */ + sbus_writel(DMA_RESET_FAS366, esp->dregs + DMA_CSR); + sbus_writel(DMA_RST_SCSI, esp->dregs + DMA_CSR); esp->prev_hme_dmacsr = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB); esp->prev_hme_dmacsr &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ); - if(can_do_burst32) - esp->prev_hme_dmacsr |= DMA_BRST32; - else if(can_do_burst64) + if (can_do_burst64) esp->prev_hme_dmacsr |= DMA_BRST64; + else if (can_do_burst32) + esp->prev_hme_dmacsr |= DMA_BRST32; - if(can_do_sbus64) + if (can_do_sbus64) { esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; + sbus_set_sbus64(esp->sdev, esp->bursts); + } /* This chip is horrible. */ - while(dregs->cond_reg & DMA_PEND_READ) + while (sbus_readl(esp->dregs + DMA_CSR) & DMA_PEND_READ) udelay(1); - dregs->cond_reg = 0; - - dregs->cond_reg = esp->prev_hme_dmacsr; + sbus_writel(0, esp->dregs + DMA_CSR); + sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR); /* This is necessary to avoid having the SCSI channel * engine lock up on us. */ - dregs->st_addr = 0; + sbus_writel(0, esp->dregs + DMA_ADDR); restore_flags(flags); break; @@ -516,60 +524,68 @@ /* This is the gate array found in the sun4m * NCR SBUS I/O subsystem. */ - if(esp->erev != esp100) - dregs->cond_reg |= DMA_3CLKS; + if (esp->erev != esp100) { + tmp = sbus_readl(esp->dregs + DMA_CSR); + sbus_writel(tmp | DMA_3CLKS, esp->dregs + DMA_CSR); + } break; case dvmarev3: - dregs->cond_reg &= ~(DMA_3CLKS); - dregs->cond_reg |= DMA_2CLKS; - if(can_do_burst32) { - dregs->cond_reg &= ~(DMA_BRST_SZ); - dregs->cond_reg |= DMA_BRST32; + tmp = sbus_readl(esp->dregs + DMA_CSR); + tmp &= ~DMA_3CLKS; + tmp |= DMA_2CLKS; + if (can_do_burst32) { + tmp &= ~DMA_BRST_SZ; + tmp |= DMA_BRST32; } + sbus_writel(tmp, esp->dregs + DMA_CSR); break; case dvmaesc1: /* This is the DMA unit found on SCSI/Ether cards. */ - dregs->cond_reg |= DMA_ADD_ENABLE; - dregs->cond_reg &= ~DMA_BCNT_ENAB; - if(!can_do_burst32 && can_do_burst16) { - dregs->cond_reg |= DMA_ESC_BURST; + tmp = sbus_readl(esp->dregs + DMA_CSR); + tmp |= DMA_ADD_ENABLE; + tmp &= ~DMA_BCNT_ENAB; + if (!can_do_burst32 && can_do_burst16) { + tmp |= DMA_ESC_BURST; } else { - dregs->cond_reg &= ~(DMA_ESC_BURST); + tmp &= ~(DMA_ESC_BURST); } + sbus_writel(tmp, esp->dregs + DMA_CSR); break; default: break; }; - DMA_INTSON(dregs); + ESP_INTSON(esp->dregs); } /* Reset the ESP chip, _not_ the SCSI bus. */ -static void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs) +static void __init esp_reset_esp(struct esp *esp) { - int family_code, version, i; - volatile int trash; + u8 family_code, version; + int i; /* Now reset the ESP chip */ - esp_cmd(esp, eregs, ESP_CMD_RC); - esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA); - esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA); + esp_cmd(esp, ESP_CMD_RC); + esp_cmd(esp, ESP_CMD_NULL | ESP_CMD_DMA); + esp_cmd(esp, ESP_CMD_NULL | ESP_CMD_DMA); /* Reload the configuration registers */ - eregs->esp_cfact = esp->cfact; - eregs->esp_stp = esp->prev_stp = 0; - eregs->esp_soff = esp->prev_soff = 0; - eregs->esp_timeo = esp->neg_defp; + sbus_writeb(esp->cfact, esp->eregs + ESP_CFACT); + esp->prev_stp = 0; + sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP); + esp->prev_soff = 0; + sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF); + sbus_writeb(esp->neg_defp, esp->eregs + ESP_TIMEO); /* This is the only point at which it is reliable to read * the ID-code for a fast ESP chip variants. */ esp->max_period = ((35 * esp->ccycle) / 1000); - if(esp->erev == fast) { - version = eregs->esp_uid; + if (esp->erev == fast) { + version = sbus_readb(esp->eregs + ESP_UID); family_code = (version & 0xf8) >> 3; - if(family_code == 0x02) + if (family_code == 0x02) esp->erev = fas236; - else if(family_code == 0x0a) + else if (family_code == 0x0a) esp->erev = fashme; /* Version is usually '5'. */ else esp->erev = fas100a; @@ -586,28 +602,29 @@ esp->max_period = (esp->max_period + 3)>>2; esp->min_period = (esp->min_period + 3)>>2; - eregs->esp_cfg1 = esp->config1; - switch(esp->erev) { + sbus_writeb(esp->config1, esp->eregs + ESP_CFG1); + switch (esp->erev) { case esp100: /* nothing to do */ break; case esp100a: - eregs->esp_cfg2 = esp->config2; + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); break; case esp236: /* Slow 236 */ - eregs->esp_cfg2 = esp->config2; - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0]; + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); + esp->prev_cfg3 = esp->config3[0]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); break; case fashme: esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB); /* fallthrough... */ case fas236: /* Fast 236 or HME */ - eregs->esp_cfg2 = esp->config2; - for(i=0; i<8; i++) { - if(esp->erev == fashme) { - unsigned char cfg3; + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); + for (i = 0; i < 16; i++) { + if (esp->erev == fashme) { + u8 cfg3; cfg3 = ESP_CONFIG3_FCLOCK | ESP_CONFIG3_OBPUSH; if (esp->scsi_id >= 8) @@ -617,11 +634,12 @@ esp->config3[i] |= ESP_CONFIG3_FCLK; } } - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0]; - if(esp->erev == fashme) { + esp->prev_cfg3 = esp->config3[0]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); + if (esp->erev == fashme) { esp->radelay = 80; } else { - if(esp->diff) + if (esp->diff) esp->radelay = 0; else esp->radelay = 96; @@ -629,10 +647,11 @@ break; case fas100a: /* Fast 100a */ - eregs->esp_cfg2 = esp->config2; - for(i=0; i<8; i++) + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); + for (i = 0; i < 16; i++) esp->config3[i] |= ESP_CONFIG3_FCLOCK; - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0]; + esp->prev_cfg3 = esp->config3[0]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); esp->radelay = 32; break; default: @@ -641,202 +660,201 @@ }; /* Eat any bitrot in the chip */ - trash = eregs->esp_intrpt; + sbus_readb(esp->eregs + ESP_INTRPT); udelay(100); } /* This places the ESP into a known state at boot time. */ -static void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs) +static void __init esp_bootup_reset(struct esp *esp) { - volatile unchar trash; + u8 tmp; /* Reset the DMA */ esp_reset_dma(esp); /* Reset the ESP */ - esp_reset_esp(esp, eregs); + esp_reset_esp(esp); /* Reset the SCSI bus, but tell ESP not to generate an irq */ - eregs->esp_cfg1 |= ESP_CONFIG1_SRRDISAB; - esp_cmd(esp, eregs, ESP_CMD_RS); + tmp = sbus_readb(esp->eregs + ESP_CFG1); + tmp |= ESP_CONFIG1_SRRDISAB; + sbus_writeb(tmp, esp->eregs + ESP_CFG1); + + esp_cmd(esp, ESP_CMD_RS); udelay(400); - eregs->esp_cfg1 = esp->config1; + + sbus_writeb(esp->config1, esp->eregs + ESP_CFG1); /* Eat any bitrot in the chip and we are done... */ - trash = eregs->esp_intrpt; + sbus_readb(esp->eregs + ESP_INTRPT); } -int __init detect_one_esp -(Scsi_Host_Template *tpnt, struct linux_sbus_device *esp_dev, struct linux_sbus_device *espdma, - struct linux_sbus *sbus, int id, int hme) -{ - struct Sparc_ESP *esp, *elink; - struct Scsi_Host *esp_host; - struct Sparc_ESP_regs *eregs; - struct sparc_dma_registers *dregs; - struct Linux_SBus_DMA *dma, *dlink; - unsigned int fmhz; - unchar ccf, bsizes, bsizes_more; - int esp_node, i; - - esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP)); - if(!esp_host) - panic("Cannot register ESP SCSI host"); - if(hme) - esp_host->max_id = 16; - esp = (struct Sparc_ESP *) esp_host->hostdata; - if(!esp) - panic("No esp in hostdata"); - esp->ehost = esp_host; - esp->edev = esp_dev; - esp->esp_id = id; - -#ifdef __sparc_v9__ - esp_host->unchecked_isa_dma = 1; -#endif - - /* Put into the chain of esp chips detected */ - if(espchain) { - elink = espchain; - while(elink->next) elink = elink->next; +static void esp_chain_add(struct esp *esp) +{ + spin_lock_irq(&espchain_lock); + if (espchain) { + struct esp *elink = espchain; + while (elink->next) + elink = elink->next; elink->next = esp; } else { espchain = esp; } - esp->next = 0; + esp->next = NULL; + spin_unlock_irq(&espchain_lock); +} + +static void esp_chain_del(struct esp *esp) +{ + spin_lock_irq(&espchain_lock); + if (espchain == esp) { + espchain = esp->next; + } else { + struct esp *elink = espchain; + while (elink->next != esp) + elink = elink->next; + elink->next = esp->next; + } + esp->next = NULL; + spin_unlock_irq(&espchain_lock); +} - /* Get misc. prom information */ -#define ESP_IS_MY_DVMA(esp, dma) \ - (!dma->SBus_dev || \ - ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \ - (esp->edev->slot == dma->SBus_dev->slot) && \ - (!strcmp(dma->SBus_dev->prom_name, "dma") || \ - !strcmp(dma->SBus_dev->prom_name, "espdma")))) +static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev) +{ + struct sbus_dev *sdev = esp->sdev; + struct sbus_dma *dma; - esp_node = esp_dev->prom_node; - prom_getstring(esp_node, "name", esp->prom_name, - sizeof(esp->prom_name)); - esp->prom_node = esp_node; - if(espdma) { - for_each_dvma(dlink) { - if(dlink->SBus_dev == espdma) + if (dma_sdev != NULL) { + for_each_dvma(dma) { + if (dma->sdev == dma_sdev) break; } } else { - for_each_dvma(dlink) { - if(ESP_IS_MY_DVMA(esp, dlink) && - !dlink->allocated) + for_each_dvma(dma) { + /* If allocated already, can't use it. */ + if (dma->allocated) + continue; + + if (dma->sdev == NULL) + break; + + /* If bus + slot are the same and it has the + * correct OBP name, it's ours. + */ + if (sdev->bus == dma->sdev->bus && + sdev->slot == dma->sdev->slot && + (!strcmp(dma->sdev->prom_name, "dma") || + !strcmp(dma->sdev->prom_name, "espdma"))) break; } } -#undef ESP_IS_MY_DVMA + /* If we don't know how to handle the dvma, * do not use this device. */ - if(!dlink){ - printk ("Cannot find dvma for ESP%d's SCSI\n", - esp->esp_id); - scsi_unregister (esp_host); + if (dma == NULL) { + printk("Cannot find dvma for ESP%d's SCSI\n", esp->esp_id); return -1; } - if (dlink->allocated){ - printk ("esp%d: can't use my espdma\n", - esp->esp_id); - scsi_unregister (esp_host); + if (dma->allocated) { + printk("esp%d: can't use my espdma\n", esp->esp_id); return -1; } - dlink->allocated = 1; - dma = dlink; + dma->allocated = 1; esp->dma = dma; - esp->dregs = dregs = dma->regs; + esp->dregs = dma->regs; - /* Map in the ESP registers from I/O space */ - if(!hme) { - prom_apply_sbus_ranges(esp->edev->my_bus, - esp->edev->reg_addrs, - 1, esp->edev); - - esp->eregs = eregs = (struct Sparc_ESP_regs *) - sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "ESP Registers", - esp->edev->reg_addrs[0].which_io, 0x0); - } else { - /* On HME, two reg sets exist, first is DVMA, - * second is ESP registers. - */ - esp->eregs = eregs = (struct Sparc_ESP_regs *) - sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0, - PAGE_SIZE, "ESP Registers", - esp->edev->reg_addrs[1].which_io, 0x0); - } - if(!eregs) - panic("ESP registers unmappable"); - esp->esp_command = - sparc_dvma_malloc(16, "ESP DVMA Cmd Block", - &esp->esp_command_dvma); - if(!esp->esp_command || !esp->esp_command_dvma) - panic("ESP DVMA transport area unmappable"); - - /* Set up the irq's etc. */ - esp->ehost->base = (unsigned char *) esp->eregs; - esp->ehost->io_port = - esp->edev->reg_addrs[0].phys_addr; - esp->ehost->n_io_port = (unsigned char) - esp->edev->reg_addrs[0].reg_size; - esp->ehost->irq = esp->irq = esp->edev->irqs[0]; - -#ifndef __sparc_v9__ - if (sparc_cpu_model != sun4d) { - /* Allocate the irq only if necessary */ - for_each_esp(elink) { - if((elink != esp) && (esp->irq == elink->irq)) { - goto esp_irq_acquired; /* BASIC rulez */ - } - } - if(request_irq(esp->ehost->irq, esp_intr, SA_SHIRQ, - "Sparc ESP SCSI", NULL)) - panic("Cannot acquire ESP irq line"); -esp_irq_acquired: - printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq); - } else { - if (request_irq(esp->ehost->irq, esp_intr_4d, - SA_SHIRQ, "Sparc ESP SCSI", esp)) - panic("Cannot acquire ESP irq line"); - printk("esp%d: IRQ %s ", esp->esp_id, __irq_itoa(esp->ehost->irq)); - } -#else - /* On Ultra we must always call request_irq for each - * esp, so that imap registers get setup etc. + return 0; +} + +static int __init esp_map_regs(struct esp *esp, int hme) +{ + struct sbus_dev *sdev = esp->sdev; + struct resource *res; + + /* On HME, two reg sets exist, first is DVMA, + * second is ESP registers. */ - if(request_irq(esp->ehost->irq, esp_intr, - SA_SHIRQ, "Sparc ESP SCSI", esp)) - panic("Cannot acquire ESP irq line"); - printk("esp%d: IRQ %s ", - esp->esp_id, __irq_itoa(esp->ehost->irq)); -#endif + if (hme) + res = &sdev->resource[1]; + else + res = &sdev->resource[0]; + + esp->eregs = sbus_ioremap(res, 0, ESP_REG_SIZE, "ESP Registers"); + + if (esp->eregs == 0) + return -1; + return 0; +} + +static int __init esp_map_cmdarea(struct esp *esp) +{ + struct sbus_dev *sdev = esp->sdev; + + esp->esp_command = sbus_alloc_consistant(sdev, 16, + &esp->esp_command_dvma); + if (esp->esp_command == NULL || + esp->esp_command_dvma == 0) + return -1; + return 0; +} + +static int __init esp_register_irq(struct esp *esp) +{ + esp->ehost->irq = esp->irq = esp->sdev->irqs[0]; + + /* We used to try various overly-clever things to + * reduce the interrupt processing overhead on + * sun4c/sun4m when multiple ESP's shared the + * same IRQ. It was too complex and messy to + * sanely maintain. + */ + if (request_irq(esp->ehost->irq, esp_intr, + SA_SHIRQ, "ESP SCSI", esp)) { + printk("esp%d: Cannot acquire irq line\n", + esp->esp_id); + return -1; + } + + printk("esp%d: IRQ %s ", esp->esp_id, + __irq_itoa(esp->ehost->irq)); + + return 0; +} + +static void __init esp_get_scsi_id(struct esp *esp) +{ + struct sbus_dev *sdev = esp->sdev; - /* Figure out our scsi ID on the bus */ esp->scsi_id = prom_getintdefault(esp->prom_node, "initiator-id", -1); - if(esp->scsi_id == -1) + if (esp->scsi_id == -1) esp->scsi_id = prom_getintdefault(esp->prom_node, "scsi-initiator-id", -1); - if(esp->scsi_id == -1) - esp->scsi_id = (!esp->edev->my_bus) ? 7 : - prom_getintdefault(esp->edev->my_bus->prom_node, + if (esp->scsi_id == -1) + esp->scsi_id = (sdev->bus == NULL) ? 7 : + prom_getintdefault(sdev->bus->prom_node, "scsi-initiator-id", 7); esp->ehost->this_id = esp->scsi_id; esp->scsi_id_mask = (1 << esp->scsi_id); - /* Check for differential SCSI-bus */ - esp->diff = prom_getbool(esp->prom_node, "differential"); - if(esp->diff) - printk("Differential "); +} - /* Check out the clock properties of the chip. */ +static void __init esp_get_clock_params(struct esp *esp) +{ + struct sbus_dev *sdev = esp->sdev; + int prom_node = esp->prom_node; + int sbus_prom_node; + unsigned int fmhz; + u8 ccf; + + if (sdev != NULL && sdev->bus != NULL) + sbus_prom_node = sdev->bus->prom_node; + else + sbus_prom_node = 0; /* This is getting messy but it has to be done * correctly or else you get weird behavior all @@ -884,19 +902,17 @@ * period we could ever handle on this ESP. */ - fmhz = prom_getintdefault(esp->prom_node, - "clock-frequency", - -1); - if(fmhz==-1) - fmhz = (!esp->edev->my_bus) ? 0 : - prom_getintdefault(esp->edev->my_bus->prom_node, - "clock-frequency", - -1); - if(fmhz <= (5000000)) + fmhz = prom_getintdefault(prom_node, "clock-frequency", -1); + if (fmhz == -1) + fmhz = (!sbus_prom_node) ? 0 : + prom_getintdefault(sbus_prom_node, "clock-frequency", -1); + + if (fmhz <= (5000000)) ccf = 0; else ccf = (((5000000 - 1) + (fmhz))/(5000000)); - if(!ccf || ccf > 8) { + + if (!ccf || ccf > 8) { /* If we can't find anything reasonable, * just assume 20MHZ. This is the clock * frequency of the older sun4c's where I've @@ -907,91 +923,134 @@ ccf = ESP_CCF_F4; fmhz = (20000000); } - if(ccf==(ESP_CCF_F7+1)) + + if (ccf == (ESP_CCF_F7 + 1)) esp->cfact = ESP_CCF_F0; - else if(ccf == ESP_CCF_NEVER) + else if (ccf == ESP_CCF_NEVER) esp->cfact = ESP_CCF_F2; else esp->cfact = ccf; + esp->raw_cfact = ccf; + esp->cfreq = fmhz; esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz); esp->ctick = ESP_TICK(ccf, esp->ccycle); esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf); esp->sync_defp = SYNC_DEFP_SLOW; - printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ", + + printk("SCSI ID %d Clk %dMHz CCYC=%d CCF=%d TOut %d ", esp->scsi_id, (fmhz / 1000000), - ccf, (int) esp->neg_defp); + (int)esp->ccycle, (int)ccf, (int) esp->neg_defp); +} + +static void __init esp_get_bursts(struct esp *esp, struct sbus_dev *dma) +{ + struct sbus_dev *sdev = esp->sdev; + u8 bursts; - /* Find the burst sizes this dma/sbus/esp supports. */ - bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff); - bsizes &= 0xff; - if(espdma) { - bsizes_more = prom_getintdefault( - espdma->prom_node, - "burst-sizes", 0xff); - if(bsizes_more != 0xff) - bsizes &= bsizes_more; - } - if (esp->edev->my_bus) { - bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node, - "burst-sizes", 0xff); - if(bsizes_more != 0xff) - bsizes &= bsizes_more; - } - - if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 || - (bsizes & DMA_BURST32)==0) - bsizes = (DMA_BURST32 - 1); + bursts = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff); + + if (dma) { + u8 tmp = prom_getintdefault(dma->prom_node, + "burst-sizes", 0xff); + if (tmp != 0xff) + bursts &= tmp; + } + + if (sdev->bus) { + u8 tmp = prom_getintdefault(sdev->bus->prom_node, + "burst-sizes", 0xff); + if (tmp != 0xff) + bursts &= tmp; + } + + if (bursts == 0xff || + (bursts & DMA_BURST16) == 0 || + (bursts & DMA_BURST32) == 0) + bursts = (DMA_BURST32 - 1); + + esp->bursts = bursts; +} - esp->bursts = bsizes; +static void __init esp_get_revision(struct esp *esp) +{ + u8 tmp; - /* Probe the revision of this esp */ esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY); - eregs->esp_cfg2 = esp->config2; - if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) != - (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { - printk("NCR53C90(esp100)\n"); + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); + + tmp = sbus_readb(esp->eregs + ESP_CFG2); + tmp &= ~ESP_CONFIG2_MAGIC; + if (tmp != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) { + /* If what we write to cfg2 does not come back, cfg2 + * is not implemented, therefore this must be a plain + * esp100. + */ esp->erev = esp100; + printk("NCR53C90(esp100)\n"); } else { - eregs->esp_cfg2 = esp->config2 = 0; - eregs->esp_cfg3 = 0; - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0] = 5; - if(eregs->esp_cfg3 != 5) { - printk("NCR53C90A(esp100a)\n"); + esp->config2 = 0; + esp->prev_cfg3 = esp->config3[0] = 5; + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); + sbus_writeb(0, esp->eregs + ESP_CFG3); + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); + + tmp = sbus_readb(esp->eregs + ESP_CFG3); + if (tmp != 5) { + /* The cfg2 register is implemented, however + * cfg3 is not, must be esp100a. + */ esp->erev = esp100a; + printk("NCR53C90A(esp100a)\n"); } else { int target; - for(target=0; target<8; target++) + for (target = 0; target < 16; target++) esp->config3[target] = 0; - eregs->esp_cfg3 = esp->prev_cfg3 = 0; - if(ccf > ESP_CCF_F5) { - printk("NCR53C9XF(espfast)\n"); + esp->prev_cfg3 = 0; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); + + /* All of cfg{1,2,3} implemented, must be one of + * the fas variants, figure out which one. + */ + if (esp->raw_cfact > ESP_CCF_F5) { esp->erev = fast; - eregs->esp_cfg2 = esp->config2 = 0; esp->sync_defp = SYNC_DEFP_FAST; + printk("NCR53C9XF(espfast)\n"); } else { - printk("NCR53C9x(esp236)\n"); esp->erev = esp236; - eregs->esp_cfg2 = esp->config2 = 0; + printk("NCR53C9x(esp236)\n"); } + esp->config2 = 0; + sbus_writeb(esp->config2, esp->eregs + ESP_CFG2); } - } + } +} - /* Initialize the command queues */ - esp->current_SC = 0; - esp->disconnected_SC = 0; - esp->issue_SC = 0; +static void __init esp_init_swstate(struct esp *esp) +{ + int i; + + /* Driver spinlock... */ + spin_lock_init(&esp->lock); - /* Clear the state machines. */ + /* Command queues... */ + esp->current_SC = NULL; + esp->disconnected_SC = NULL; + esp->issue_SC = NULL; + + /* Target and current command state... */ esp->targets_present = 0; esp->resetting_bus = 0; esp->snip = 0; - esp->targets_present = 0; + + /* Debugging... */ for(i = 0; i < 32; i++) esp->espcmdlog[i] = 0; esp->espcmdent = 0; + + /* MSG phase state... */ for(i = 0; i < 16; i++) { esp->cur_msgout[i] = 0; esp->cur_msgin[i] = 0; @@ -1002,11 +1061,73 @@ /* Clear the one behind caches to hold unmatchable values. */ esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff; esp->prev_hme_dmacsr = 0xffffffff; +} + +static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev, + struct sbus_dev *espdma, struct sbus_bus *sbus, + int id, int hme) +{ + struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp)); + struct esp *esp; + + if (!esp_host) { + printk("ESP: Cannot register SCSI host\n"); + return -1; + } + if (hme) + esp_host->max_id = 16; + esp = (struct esp *) esp_host->hostdata; + esp->ehost = esp_host; + esp->sdev = esp_dev; + esp->esp_id = id; + esp->prom_node = esp_dev->prom_node; + prom_getstring(esp->prom_node, "name", esp->prom_name, + sizeof(esp->prom_name)); + + esp_chain_add(esp); + if (esp_find_dvma(esp, espdma) < 0) + goto fail_unlink; + if (esp_map_regs(esp, hme) < 0) { + printk("ESP registers unmappable"); + goto fail_dvma_release; + } + if (esp_map_cmdarea(esp) < 0) { + printk("ESP DVMA transport area unmappable"); + goto fail_unmap_regs; + } + if (esp_register_irq(esp) < 0) + goto fail_unmap_cmdarea; + + esp_get_scsi_id(esp); + + esp->diff = prom_getbool(esp->prom_node, "differential"); + if (esp->diff) + printk("Differential "); + + esp_get_clock_params(esp); + esp_get_bursts(esp, espdma); + esp_get_revision(esp); + esp_init_swstate(esp); - /* Reset the thing before we try anything... */ - esp_bootup_reset(esp, eregs); + esp_bootup_reset(esp); return 0; + +fail_unmap_cmdarea: + sbus_free_consistant(esp->sdev, 16, + (void *) esp->esp_command, + esp->esp_command_dvma); + +fail_unmap_regs: + sbus_iounmap(esp->eregs, ESP_REG_SIZE); + +fail_dvma_release: + esp->dma->allocated = 0; + +fail_unlink: + esp_chain_del(esp); + scsi_unregister(esp_host); + return -1; } /* Detecting ESP chips on the machine. This is the simple and easy @@ -1019,20 +1140,23 @@ int __init esp_detect(Scsi_Host_Template *tpnt) { - static struct linux_sbus_device esp_dev; + static struct sbus_dev esp_dev; int esps_in_use = 0; espchain = 0; - if(sun4_esp_physaddr) { + if (sun4_esp_physaddr) { memset (&esp_dev, 0, sizeof(esp_dev)); esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; esp_dev.irqs[0] = 4; + esp_dev.resource[0].start = sun4_esp_physaddr; + esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1; + esp_dev.resource[0].flags = IORESOURCE_IO; if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) esps_in_use++; printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); - esps_running = esps_in_use; + esps_running = esps_in_use; } return esps_in_use; } @@ -1041,12 +1165,12 @@ int __init esp_detect(Scsi_Host_Template *tpnt) { - struct linux_sbus *sbus; - struct linux_sbus_device *esp_dev, *sbdev_iter; + struct sbus_bus *sbus; + struct sbus_dev *esp_dev, *sbdev_iter; int nesps = 0, esps_in_use = 0; espchain = 0; - if(!SBus_chain) { + if (!sbus_root) { #ifdef CONFIG_PCI return 0; #else @@ -1055,25 +1179,25 @@ } for_each_sbus(sbus) { for_each_sbusdev(sbdev_iter, sbus) { - struct linux_sbus_device *espdma = 0; + struct sbus_dev *espdma = NULL; int hme = 0; /* Is it an esp sbus device? */ esp_dev = sbdev_iter; - if(strcmp(esp_dev->prom_name, "esp") && - strcmp(esp_dev->prom_name, "SUNW,esp")) { - if(!strcmp(esp_dev->prom_name, "SUNW,fas")) { + if (strcmp(esp_dev->prom_name, "esp") && + strcmp(esp_dev->prom_name, "SUNW,esp")) { + if (!strcmp(esp_dev->prom_name, "SUNW,fas")) { hme = 1; espdma = esp_dev; } else { - if(!esp_dev->child || - (strcmp(esp_dev->prom_name, "espdma") && - strcmp(esp_dev->prom_name, "dma"))) + if (!esp_dev->child || + (strcmp(esp_dev->prom_name, "espdma") && + strcmp(esp_dev->prom_name, "dma"))) continue; /* nope... */ espdma = esp_dev; esp_dev = esp_dev->child; - if(strcmp(esp_dev->prom_name, "esp") && - strcmp(esp_dev->prom_name, "SUNW,esp")) + if (strcmp(esp_dev->prom_name, "esp") && + strcmp(esp_dev->prom_name, "SUNW,esp")) continue; /* how can this happen? */ } } @@ -1098,10 +1222,10 @@ */ const char *esp_info(struct Scsi_Host *host) { - struct Sparc_ESP *esp; + struct esp *esp; - esp = (struct Sparc_ESP *) host->hostdata; - switch(esp->erev) { + esp = (struct esp *) host->hostdata; + switch (esp->erev) { case esp100: return "Sparc ESP100 (NCR53C90)"; case esp100a: @@ -1115,7 +1239,7 @@ case fas100a: return "Sparc ESP100A-FAST"; default: - panic("Bogon ESP revision"); + return "Bogon ESP revision"; }; } @@ -1162,7 +1286,7 @@ return len; } -static int esp_host_info(struct Sparc_ESP *esp, char *ptr, off_t offset, int len) +static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len) { struct info_str info; int i; @@ -1173,10 +1297,10 @@ info.pos = 0; copy_info(&info, "Sparc ESP Host Adapter:\n"); - copy_info(&info, "\tPROM node\t\t%08lx\n", (unsigned long) esp->prom_node); + copy_info(&info, "\tPROM node\t\t%08x\n", (unsigned int) esp->prom_node); copy_info(&info, "\tPROM name\t\t%s\n", esp->prom_name); copy_info(&info, "\tESP Model\t\t"); - switch(esp->erev) { + switch (esp->erev) { case esp100: copy_info(&info, "ESP100\n"); break; @@ -1204,7 +1328,7 @@ break; }; copy_info(&info, "\tDMA Revision\t\t"); - switch(esp->dma->revision) { + switch (esp->dma->revision) { case dvmarev0: copy_info(&info, "Rev 0\n"); break; @@ -1231,21 +1355,21 @@ break; }; copy_info(&info, "\tLive Targets\t\t[ "); - for(i = 0; i < 15; i++) { - if(esp->targets_present & (1 << i)) + for (i = 0; i < 15; i++) { + if (esp->targets_present & (1 << i)) copy_info(&info, "%d ", i); } copy_info(&info, "]\n\n"); /* Now describe the state of each existing target. */ copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n"); - for(i = 0; i < 15; i++) { - if(esp->targets_present & (1 << i)) { + for (i = 0; i < 15; i++) { + if (esp->targets_present & (1 << i)) { Scsi_Device *SDptr = esp->ehost->host_queue; - while((SDptr->host != esp->ehost) && - (SDptr->id != i) && - (SDptr->next)) + while ((SDptr->host != esp->ehost) && + (SDptr->id != i) && + (SDptr->next)) SDptr = SDptr->next; copy_info(&info, "%d\t\t", i); @@ -1257,7 +1381,6 @@ (esp->config3[i] & ESP_CONFIG3_EWIDE) ? "yes" : "no"); } } - return info.pos > info.offset? info.pos - info.offset : 0; } @@ -1265,58 +1388,55 @@ int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { - struct Sparc_ESP *esp; + struct esp *esp; - if(inout) + if (inout) return -EINVAL; /* not yet */ for_each_esp(esp) { - if(esp->ehost->host_no == hostno) + if (esp->ehost->host_no == hostno) break; } - if(!esp) + if (!esp) return -EINVAL; - if(start) + if (start) *start = buffer; return esp_host_info(esp, buffer, offset, length); } -static void esp_get_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp) { - if(sp->use_sg == 0) { + if (sp->use_sg == 0) { sp->SCp.this_residual = sp->request_bufflen; sp->SCp.buffer = (struct scatterlist *) sp->request_buffer; sp->SCp.buffers_residual = 0; - sp->SCp.have_data_in = mmu_get_scsi_one((char *)sp->SCp.buffer, - sp->SCp.this_residual, - esp->edev->my_bus); + sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer, + sp->SCp.this_residual); sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in); } else { sp->SCp.buffer = (struct scatterlist *) sp->buffer; - sp->SCp.buffers_residual = sp->use_sg - 1; - sp->SCp.this_residual = sp->SCp.buffer->length; - mmu_get_scsi_sgl((struct mmu_sglist *) sp->SCp.buffer, - sp->SCp.buffers_residual, - esp->edev->my_bus); + sp->SCp.buffers_residual = sbus_map_sg(esp->sdev, + sp->SCp.buffer, + sp->use_sg); + sp->SCp.this_residual = sp->SCp.buffer->dvma_length; sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.buffer->dvma_address); } } -static void esp_release_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp) { - if(sp->use_sg == 0) - mmu_release_scsi_one(sp->SCp.have_data_in, - sp->request_bufflen, - esp->edev->my_bus); - else - mmu_release_scsi_sgl((struct mmu_sglist *) - sp->buffer, sp->use_sg - 1, - esp->edev->my_bus); + if (sp->use_sg == 0) { + sbus_unmap_single(esp->sdev, + sp->SCp.have_data_in, + sp->request_bufflen); + } else { + sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg); + } } -static void esp_restore_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp) { struct esp_pointers *ep = &esp->data_pointers[sp->target]; @@ -1326,7 +1446,7 @@ sp->SCp.buffers_residual = ep->saved_buffers_residual; } -static void esp_save_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static void esp_save_pointers(struct esp *esp, Scsi_Cmnd *sp) { struct esp_pointers *ep = &esp->data_pointers[sp->target]; @@ -1356,9 +1476,9 @@ * case where we could see an interrupt is where we have disconnected * commands active and they are trying to reselect us. */ -static inline void esp_check_cmd(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static inline void esp_check_cmd(struct esp *esp, Scsi_Cmnd *sp) { - switch(sp->cmd_len) { + switch (sp->cmd_len) { case 6: case 10: case 12: @@ -1373,7 +1493,7 @@ }; } -static inline void build_sync_nego_msg(struct Sparc_ESP *esp, int period, int offset) +static inline void build_sync_nego_msg(struct esp *esp, int period, int offset) { esp->cur_msgout[0] = EXTENDED_MESSAGE; esp->cur_msgout[1] = 3; @@ -1384,12 +1504,12 @@ } /* SIZE is in bits, currently HME only supports 16 bit wide transfers. */ -static inline void build_wide_nego_msg(struct Sparc_ESP *esp, int size) +static inline void build_wide_nego_msg(struct esp *esp, int size) { esp->cur_msgout[0] = EXTENDED_MESSAGE; esp->cur_msgout[1] = 2; esp->cur_msgout[2] = EXTENDED_WDTR; - switch(size) { + switch (size) { case 32: esp->cur_msgout[3] = 2; break; @@ -1405,28 +1525,26 @@ esp->msgout_len = 4; } -static void esp_exec_cmd(struct Sparc_ESP *esp) +static void esp_exec_cmd(struct esp *esp) { - struct sparc_dma_registers *dregs = esp->dregs; - struct Sparc_ESP_regs *eregs = esp->eregs; Scsi_Cmnd *SCptr; Scsi_Device *SDptr; - volatile unchar *cmdp = esp->esp_command; - unsigned char the_esp_command; + volatile u8 *cmdp = esp->esp_command; + u8 the_esp_command; int lun, target; int i; /* Hold off if we have disconnected commands and * an IRQ is showing... */ - if(esp->disconnected_SC && DMA_IRQ_P(dregs)) + if (esp->disconnected_SC && ESP_IRQ_P(esp->dregs)) return; /* Grab first member of the issue queue. */ SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC); /* Safe to panic here because current_SC is null. */ - if(!SCptr) + if (!SCptr) panic("esp: esp_exec_cmd and issue queue is NULL"); SDptr = SCptr->device; @@ -1468,22 +1586,22 @@ * selections should not confuse SCSI-1 we hope. */ - if(SDptr->sync) { + if (SDptr->sync) { /* this targets sync is known */ do_sync_known: - if(SDptr->disconnect) + if (SDptr->disconnect) *cmdp++ = IDENTIFY(1, lun); else *cmdp++ = IDENTIFY(0, lun); - if(esp->esp_slowcmd) { + if (esp->esp_slowcmd) { the_esp_command = (ESP_CMD_SELAS | ESP_CMD_DMA); esp_advance_phase(SCptr, in_slct_stop); } else { the_esp_command = (ESP_CMD_SELA | ESP_CMD_DMA); esp_advance_phase(SCptr, in_slct_norm); } - } else if(!(esp->targets_present & (1<disconnect)) { + } else if (!(esp->targets_present & (1<disconnect)) { /* After the bootup SCSI code sends both the * TEST_UNIT_READY and INQUIRY commands we want * to at least attempt allowing the device to @@ -1491,7 +1609,7 @@ */ ESPMISC(("esp: Selecting device for first time. target=%d " "lun=%d\n", target, SCptr->lun)); - if(!SDptr->borken && !SDptr->disconnect) + if (!SDptr->borken && !SDptr->disconnect) SDptr->disconnect = 1; *cmdp++ = IDENTIFY(0, lun); @@ -1512,10 +1630,13 @@ * SparcStation1 and SparcStation1+. Allowing those * to be enabled seems to lockup the machine completely. */ - if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || - (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { - /* But we are nice and allow tapes to disconnect. */ - if(SDptr->type == TYPE_TAPE) + if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || + (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { + /* But we are nice and allow tapes and removable + * disks (but not CDROMs) to disconnect. + */ + if(SDptr->type == TYPE_TAPE || + (SDptr->type != TYPE_ROM && SDptr->removable)) SDptr->disconnect = 1; else SDptr->disconnect = 0; @@ -1531,9 +1652,10 @@ * need to attempt WIDE first, before * sync nego, as per SCSI 2 standard. */ - if(esp->erev == fashme && !SDptr->wide) { - if(!SDptr->borken && - SDptr->type != TYPE_ROM) { + if (esp->erev == fashme && !SDptr->wide) { + if (!SDptr->borken && + SDptr->type != TYPE_ROM && + SDptr->removable == 0) { build_wide_nego_msg(esp, 16); SDptr->wide = 1; esp->wnip = 1; @@ -1544,13 +1666,18 @@ } } - if(!SDptr->borken) { - if((SDptr->type == TYPE_ROM)) { + if (!SDptr->borken) { + if ((SDptr->type == TYPE_ROM)) { /* Nice try sucker... */ ESPMISC(("esp%d: Disabling sync for buggy " "CDROM.\n", esp->esp_id)); cdrom_hwbug_wkaround = 1; build_sync_nego_msg(esp, 0, 0); + } else if (SDptr->removable != 0) { + ESPMISC(("esp%d: Not negotiating sync/wide but " + "allowing disconnect for removable media.\n", + esp->esp_id)); + build_sync_nego_msg(esp, 0, 0); } else { build_sync_nego_msg(esp, esp->sync_defp, 15); } @@ -1584,8 +1711,10 @@ * Therefore _no_ disconnects for SCSI1 targets * thank you very much. ;-) */ - if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) || - cdrom_hwbug_wkaround || SDptr->borken) { + if(((SDptr->scsi_level < 3) && + (SDptr->type != TYPE_TAPE) && + SDptr->removable == 0) || + cdrom_hwbug_wkaround || SDptr->borken) { ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d " "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun)); SDptr->disconnect = 0; @@ -1605,79 +1734,84 @@ esp_advance_phase(SCptr, in_slct_msg); } - if(!esp->esp_slowcmd) - for(i = 0; i < SCptr->cmd_len; i++) + if (!esp->esp_slowcmd) + for (i = 0; i < SCptr->cmd_len; i++) *cmdp++ = SCptr->cmnd[i]; /* HME sucks... */ - if(esp->erev == fashme) - eregs->esp_busid = (target & 0xf) | - (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT); + if (esp->erev == fashme) + sbus_writeb((target & 0xf) | (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT), + esp->eregs + ESP_BUSID); else - eregs->esp_busid = (target & 7); + sbus_writeb(target & 7, esp->eregs + ESP_BUSID); if (esp->prev_soff != SDptr->sync_max_offset || esp->prev_stp != SDptr->sync_min_period || (esp->erev > esp100a && esp->prev_cfg3 != esp->config3[target])) { - eregs->esp_soff = esp->prev_soff = SDptr->sync_max_offset; - eregs->esp_stp = esp->prev_stp = SDptr->sync_min_period; - if(esp->erev > esp100a) - eregs->esp_cfg3 = - esp->prev_cfg3 = - esp->config3[target]; + esp->prev_soff = SDptr->sync_max_offset; + esp->prev_stp = SDptr->sync_min_period; + sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF); + sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP); + if (esp->erev > esp100a) { + esp->prev_cfg3 = esp->config3[target]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); + } } i = (cmdp - esp->esp_command); - if(esp->erev == fashme) { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */ + if (esp->erev == fashme) { + esp_cmd(esp, ESP_CMD_FLUSH); /* Grrr! */ /* Set up the DMA and HME counters */ - eregs->esp_tclow = i; - eregs->esp_tcmed = 0; - eregs->fas_rlo = 0; - eregs->fas_rhi = 0; - esp_cmd(esp, eregs, the_esp_command); + sbus_writeb(i, esp->eregs + ESP_TCLOW); + sbus_writeb(0, esp->eregs + ESP_TCMED); + sbus_writeb(0, esp->eregs + FAS_RLO); + sbus_writeb(0, esp->eregs + FAS_RHI); + esp_cmd(esp, the_esp_command); /* Talk about touchy hardware... */ esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | (DMA_SCSI_DISAB | DMA_ENABLE)) & ~(DMA_ST_WRITE)); - dregs->cnt = 16; - dregs->st_addr = esp->esp_command_dvma; - dregs->cond_reg = esp->prev_hme_dmacsr; + sbus_writel(16, esp->dregs + DMA_COUNT); + sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR); + sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR); } else { + u32 tmp; + /* Set up the DMA and ESP counters */ - eregs->esp_tclow = i; - eregs->esp_tcmed = 0; - dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE); - if(esp->dma->revision == dvmaesc1) { - if(i) /* Workaround ESC gate array SBUS rerun bug. */ - dregs->cnt = (PAGE_SIZE); + sbus_writeb(i, esp->eregs + ESP_TCLOW); + sbus_writeb(0, esp->eregs + ESP_TCMED); + tmp = sbus_readl(esp->dregs + DMA_CSR); + tmp &= ~DMA_ST_WRITE; + tmp |= DMA_ENABLE; + sbus_writel(tmp, esp->dregs + DMA_CSR); + if (esp->dma->revision == dvmaesc1) { + if (i) /* Workaround ESC gate array SBUS rerun bug. */ + sbus_writel(PAGE_SIZE, esp->dregs + DMA_COUNT); } - dregs->st_addr = esp->esp_command_dvma; + sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR); /* Tell ESP to "go". */ - esp_cmd(esp, eregs, the_esp_command); + esp_cmd(esp, the_esp_command); } } /* Queue a SCSI command delivered from the mid-level Linux SCSI code. */ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - struct Sparc_ESP *esp; - struct sparc_dma_registers *dregs; + struct esp *esp; + unsigned long flags; /* Set up func ptr and initial driver cmd-phase. */ SCpnt->scsi_done = done; SCpnt->SCp.phase = not_issued; - esp = (struct Sparc_ESP *) SCpnt->host->hostdata; - dregs = esp->dregs; - /* We use the scratch area. */ ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun)); ESPDISC(("N<%02x,%02x>", SCpnt->target, SCpnt->lun)); + esp = (struct esp *) SCpnt->host->hostdata; esp_get_dmabufs(esp, SCpnt); esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */ @@ -1685,8 +1819,10 @@ SCpnt->SCp.Message = 0xff; SCpnt->SCp.sent_command = 0; + spin_lock_irqsave(&esp->lock, flags); + /* Place into our queue. */ - if(SCpnt->cmnd[0] == REQUEST_SENSE) { + if (SCpnt->cmnd[0] == REQUEST_SENSE) { ESPQUEUE(("RQSENSE\n")); prepend_SC(&esp->issue_SC, SCpnt); } else { @@ -1695,16 +1831,18 @@ } /* Run it now if we can. */ - if(!esp->current_SC && !esp->resetting_bus) + if (!esp->current_SC && !esp->resetting_bus) esp_exec_cmd(esp); + spin_unlock_irqrestore(&esp->lock, flags); + return 0; } /* Only queuing supported in this ESP driver. */ int esp_command(Scsi_Cmnd *SCpnt) { - struct Sparc_ESP *esp = (struct Sparc_ESP *) SCpnt->host->hostdata; + struct esp *esp = (struct esp *) SCpnt->host->hostdata; ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id)); return -1; @@ -1720,8 +1858,7 @@ phase_string(SCptr->SCp.phase))); } -static void esp_dump_state(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static void esp_dump_state(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; #ifdef DEBUG_ESP_CMDS @@ -1730,40 +1867,37 @@ ESPLOG(("esp%d: dumping state\n", esp->esp_id)); ESPLOG(("esp%d: dma -- cond_reg<%08x> addr<%08x>\n", - esp->esp_id, dregs->cond_reg, dregs->st_addr)); + esp->esp_id, + sbus_readl(esp->dregs + DMA_CSR), + sbus_readl(esp->dregs + DMA_ADDR))); ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n", esp->esp_id, esp->sreg, esp->seqreg, esp->ireg)); ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n", - esp->esp_id, eregs->esp_status, eregs->esp_sstep, eregs->esp_intrpt)); + esp->esp_id, + sbus_readb(esp->eregs + ESP_STATUS), + sbus_readb(esp->eregs + ESP_SSTEP), + sbus_readb(esp->eregs + ESP_INTRPT))); #ifdef DEBUG_ESP_CMDS printk("esp%d: last ESP cmds [", esp->esp_id); i = (esp->espcmdent - 1) & 31; - printk("<"); - esp_print_cmd(esp->espcmdlog[i]); - printk(">"); + printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">"); i = (i - 1) & 31; - printk("<"); - esp_print_cmd(esp->espcmdlog[i]); - printk(">"); + printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">"); i = (i - 1) & 31; - printk("<"); - esp_print_cmd(esp->espcmdlog[i]); - printk(">"); + printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">"); i = (i - 1) & 31; - printk("<"); - esp_print_cmd(esp->espcmdlog[i]); - printk(">"); + printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">"); printk("]\n"); #endif /* (DEBUG_ESP_CMDS) */ - if(SCptr) { + if (SCptr) { ESPLOG(("esp%d: current command ", esp->esp_id)); esp_dump_cmd(SCptr); } ESPLOG(("\n")); SCptr = esp->disconnected_SC; ESPLOG(("esp%d: disconnected ", esp->esp_id)); - while(SCptr) { + while (SCptr) { esp_dump_cmd(SCptr); SCptr = (Scsi_Cmnd *) SCptr->host_scribble; } @@ -1773,13 +1907,14 @@ /* Abort a command. */ int esp_abort(Scsi_Cmnd *SCptr) { - struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata; - struct Sparc_ESP_regs *eregs = esp->eregs; - struct sparc_dma_registers *dregs = esp->dregs; + struct esp *esp = (struct esp *) SCptr->host->hostdata; + unsigned long flags; int don; + spin_lock_irqsave(&esp->lock, flags); + ESPLOG(("esp%d: Aborting command\n", esp->esp_id)); - esp_dump_state(esp, eregs, dregs); + esp_dump_state(esp); /* Wheee, if this is the current command on the bus, the * best we can do is assert ATN and wait for msgout phase. @@ -1787,36 +1922,41 @@ * in the driver and timeout because the eventual phase change * will cause the ESP to (eventually) give an interrupt. */ - if(esp->current_SC == SCptr) { + if (esp->current_SC == SCptr) { esp->cur_msgout[0] = ABORT; esp->msgout_len = 1; esp->msgout_ctr = 0; - esp_cmd(esp, eregs, ESP_CMD_SATN); + esp_cmd(esp, ESP_CMD_SATN); + spin_unlock_irqrestore(&esp->lock, flags); return SCSI_ABORT_PENDING; } /* If it is still in the issue queue then we can safely * call the completion routine and report abort success. */ - don = (dregs->cond_reg & DMA_INT_ENAB); - if(don) { - DMA_INTSOFF(dregs); - synchronize_irq(); + don = (sbus_readl(esp->dregs + DMA_CSR) & DMA_INT_ENAB); + if (don) { + ESP_INTSOFF(esp->dregs); } - if(esp->issue_SC) { + if (esp->issue_SC) { Scsi_Cmnd **prev, *this; - for(prev = (&esp->issue_SC), this = esp->issue_SC; - this; - prev = (Scsi_Cmnd **) &(this->host_scribble), - this = (Scsi_Cmnd *) this->host_scribble) { - if(this == SCptr) { + for (prev = (&esp->issue_SC), this = esp->issue_SC; + this != NULL; + prev = (Scsi_Cmnd **) &(this->host_scribble), + this = (Scsi_Cmnd *) this->host_scribble) { + + if (this == SCptr) { *prev = (Scsi_Cmnd *) this->host_scribble; this->host_scribble = NULL; + + spin_unlock_irqrestore(&esp->lock, flags); + esp_release_dmabufs(esp, this); this->result = DID_ABORT << 16; - this->done(this); - if(don) - DMA_INTSON(dregs); + this->scsi_done(this); + if (don) + ESP_INTSON(esp->dregs); + return SCSI_ABORT_SUCCESS; } } @@ -1827,9 +1967,10 @@ * on the bus at this time. So, we let the SCSI code wait * a little bit and try again later. */ - if(esp->current_SC) { - if(don) - DMA_INTSON(dregs); + if (esp->current_SC) { + if (don) + ESP_INTSON(esp->dregs); + spin_unlock_irqrestore(&esp->lock, flags); return SCSI_ABORT_BUSY; } @@ -1840,8 +1981,9 @@ * happens, we are really hung so reset the bus. */ - if(don) - DMA_INTSON(dregs); + if (don) + ESP_INTSON(esp->dregs); + spin_unlock_irqrestore(&esp->lock, flags); return SCSI_ABORT_SNOOZE; } @@ -1850,28 +1992,40 @@ * is to clean out the command queues and begin re-execution * of SCSI commands once more. */ -static int esp_finish_reset(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_finish_reset(struct esp *esp) { Scsi_Cmnd *sp = esp->current_SC; /* Clean up currently executing command, if any. */ if (sp != NULL) { + esp->current_SC = NULL; + spin_unlock(&esp->lock); + esp_release_dmabufs(esp, sp); sp->result = (DID_RESET << 16); + + spin_lock(&io_request_lock); sp->scsi_done(sp); - esp->current_SC = NULL; + spin_unlock(&io_request_lock); + + spin_lock(&esp->lock); } /* Clean up disconnected queue, they have been invalidated * by the bus reset. */ if (esp->disconnected_SC) { - while((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) { + while ((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) { + spin_unlock(&esp->lock); + esp_release_dmabufs(esp, sp); sp->result = (DID_RESET << 16); + + spin_lock(&io_request_lock); sp->scsi_done(sp); + spin_unlock(&io_request_lock); + + spin_lock(&esp->lock); } } @@ -1879,19 +2033,17 @@ esp->resetting_bus = 0; /* Ok, now it is safe to get commands going once more. */ - if(esp->issue_SC) + if (esp->issue_SC) esp_exec_cmd(esp); return do_intr_end; } -static int esp_do_resetbus(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_resetbus(struct esp *esp) { ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id)); esp->resetting_bus = 1; - esp_cmd(esp, eregs, ESP_CMD_RS); + esp_cmd(esp, ESP_CMD_RS); return do_intr_end; } @@ -1901,55 +2053,49 @@ */ int esp_reset(Scsi_Cmnd *SCptr, unsigned int how) { - struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata; + struct esp *esp = (struct esp *) SCptr->host->hostdata; + unsigned long flags; + + spin_lock_irqsave(&esp->lock, flags); + (void) esp_do_resetbus(esp); + spin_unlock_irqrestore(&esp->lock, flags); - (void) esp_do_resetbus(esp, esp->eregs, esp->dregs); return SCSI_RESET_PENDING; } /* Internal ESP done function. */ -static void esp_done(struct Sparc_ESP *esp, int error) +static void esp_done(struct esp *esp, int error) { - Scsi_Cmnd *done_SC; + Scsi_Cmnd *done_SC = esp->current_SC; - if(esp->current_SC) { - done_SC = esp->current_SC; - esp->current_SC = NULL; - esp_release_dmabufs(esp, done_SC); - done_SC->result = error; - done_SC->scsi_done(done_SC); + esp->current_SC = NULL; + + spin_unlock(&esp->lock); + esp_release_dmabufs(esp, done_SC); + done_SC->result = error; + + spin_lock(&io_request_lock); + done_SC->scsi_done(done_SC); + spin_unlock(&io_request_lock); + + /* Bus is free, issue any commands in the queue. */ + spin_lock(&esp->lock); + if (esp->issue_SC && !esp->current_SC) + esp_exec_cmd(esp); - /* Bus is free, issue any commands in the queue. */ - if(esp->issue_SC && !esp->current_SC) - esp_exec_cmd(esp); - } else { - /* Panic is safe as current_SC is null so we may still - * be able to accept more commands to sync disk buffers. - */ - ESPLOG(("panicing\n")); - panic("esp: done() called with NULL esp->current_SC"); - } } /* Wheee, ESP interrupt engine. */ /* Forward declarations. */ -static int esp_do_phase_determine(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_data_finale(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); -static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs); +static int esp_do_phase_determine(struct esp *esp); +static int esp_do_data_finale(struct esp *esp); +static int esp_select_complete(struct esp *esp); +static int esp_do_status(struct esp *esp); +static int esp_do_msgin(struct esp *esp); +static int esp_do_msgindone(struct esp *esp); +static int esp_do_msgout(struct esp *esp); +static int esp_do_cmdbegin(struct esp *esp); #define sreg_datainp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DIP) #define sreg_dataoutp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DOP) @@ -1957,40 +2103,42 @@ /* Read any bytes found in the FAS366 fifo, storing them into * the ESP driver software state structure. */ -static void hme_fifo_read(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs) +static void hme_fifo_read(struct esp *esp) { - unsigned long count = 0; - unchar status = esp->sreg; + u8 count = 0; + u8 status = esp->sreg; /* Cannot safely frob the fifo for these following cases, but * we must always read the fifo when the reselect interrupt * is pending. */ - if(((esp->ireg & ESP_INTR_RSEL) == 0) && - (sreg_datainp(status) || - sreg_dataoutp(status) || - (esp->current_SC && - esp->current_SC->SCp.phase == in_data_done))) { + if (((esp->ireg & ESP_INTR_RSEL) == 0) && + (sreg_datainp(status) || + sreg_dataoutp(status) || + (esp->current_SC && + esp->current_SC->SCp.phase == in_data_done))) { ESPHME(("")); } else { - unsigned long fcnt = eregs->esp_fflags & ESP_FF_FBYTES; + unsigned long fcnt = sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES; /* The HME stores bytes in multiples of 2 in the fifo. */ ESPHME(("hme_fifo[fcnt=%d", (int)fcnt)); - while(fcnt) { - esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata; - esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata; + while (fcnt) { + esp->hme_fifo_workaround_buffer[count++] = + sbus_readb(esp->eregs + ESP_FDATA); + esp->hme_fifo_workaround_buffer[count++] = + sbus_readb(esp->eregs + ESP_FDATA); ESPHME(("<%02x,%02x>", esp->hme_fifo_workaround_buffer[count-2], esp->hme_fifo_workaround_buffer[count-1])); fcnt--; } - if(eregs->esp_status2 & ESP_STAT2_F1BYTE) { + if (sbus_readb(esp->eregs + ESP_STATUS2) & ESP_STAT2_F1BYTE) { ESPHME(("")); - eregs->esp_fdata = 0; - esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata; + sbus_writeb(0, esp->eregs + ESP_FDATA); + esp->hme_fifo_workaround_buffer[count++] = + sbus_readb(esp->eregs + ESP_FDATA); ESPHME(("<%02x,0x00>", esp->hme_fifo_workaround_buffer[count-1])); ESPHME(("CMD_FLUSH")); - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, ESP_CMD_FLUSH); } else { ESPHME(("no_xtra_byte")); } @@ -1999,13 +2147,13 @@ esp->hme_fifo_workaround_count = count; } -static inline void hme_fifo_push(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - unchar *bytes, unchar count) +static inline void hme_fifo_push(struct esp *esp, u8 *bytes, u8 count) { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - while(count) { - eregs->esp_fdata = *bytes++; - eregs->esp_fdata = 0; + esp_cmd(esp, ESP_CMD_FLUSH); + while (count) { + u8 tmp = *bytes++; + sbus_writeb(tmp, esp->eregs + ESP_FDATA); + sbus_writeb(0, esp->eregs + ESP_FDATA); count--; } } @@ -2013,19 +2161,18 @@ /* We try to avoid some interrupts by jumping ahead and see if the ESP * has gotten far enough yet. Hence the following. */ -static inline int skipahead1(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs, - Scsi_Cmnd *scp, int prev_phase, int new_phase) +static inline int skipahead1(struct esp *esp, Scsi_Cmnd *scp, + int prev_phase, int new_phase) { - if(scp->SCp.sent_command != prev_phase) + if (scp->SCp.sent_command != prev_phase) return 0; - if(DMA_IRQ_P(dregs)) { + if (ESP_IRQ_P(esp->dregs)) { /* Yes, we are able to save an interrupt. */ if (esp->erev == fashme) - esp->sreg2 = eregs->esp_status2; - esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR)); - esp->ireg = eregs->esp_intrpt; - if(esp->erev == fashme) { + esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2); + esp->sreg = (sbus_readb(esp->eregs + ESP_STATUS) & ~(ESP_STAT_INTR)); + esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT); + if (esp->erev == fashme) { /* This chip is really losing. */ ESPHME(("HME[")); /* Must latch fifo before reading the interrupt @@ -2034,11 +2181,11 @@ * Happy Meal indeed.... */ ESPHME(("fifo_workaround]")); - if(!(esp->sreg2 & ESP_STAT2_FEMPTY) || - (esp->sreg2 & ESP_STAT2_F1BYTE)) - hme_fifo_read(esp, eregs); + if (!(esp->sreg2 & ESP_STAT2_FEMPTY) || + (esp->sreg2 & ESP_STAT2_F1BYTE)) + hme_fifo_read(esp); } - if(!(esp->ireg & ESP_INTR_SR)) + if (!(esp->ireg & ESP_INTR_SR)) return 0; else return do_reset_complete; @@ -2048,21 +2195,19 @@ return do_intr_end; } -static inline int skipahead2(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs, - Scsi_Cmnd *scp, int prev_phase1, int prev_phase2, - int new_phase) +static inline int skipahead2(struct esp *esp, Scsi_Cmnd *scp, + int prev_phase1, int prev_phase2, int new_phase) { - if(scp->SCp.sent_command != prev_phase1 && - scp->SCp.sent_command != prev_phase2) + if (scp->SCp.sent_command != prev_phase1 && + scp->SCp.sent_command != prev_phase2) return 0; - if(DMA_IRQ_P(dregs)) { + if (ESP_IRQ_P(esp->dregs)) { /* Yes, we are able to save an interrupt. */ if (esp->erev == fashme) - esp->sreg2 = eregs->esp_status2; - esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR)); - esp->ireg = eregs->esp_intrpt; - if(esp->erev == fashme) { + esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2); + esp->sreg = (sbus_readb(esp->eregs + ESP_STATUS) & ~(ESP_STAT_INTR)); + esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT); + if (esp->erev == fashme) { /* This chip is really losing. */ ESPHME(("HME[")); @@ -2072,11 +2217,11 @@ * Happy Meal indeed.... */ ESPHME(("fifo_workaround]")); - if(!(esp->sreg2 & ESP_STAT2_FEMPTY) || - (esp->sreg2 & ESP_STAT2_F1BYTE)) - hme_fifo_read(esp, eregs); + if (!(esp->sreg2 & ESP_STAT2_FEMPTY) || + (esp->sreg2 & ESP_STAT2_F1BYTE)) + hme_fifo_read(esp); } - if(!(esp->ireg & ESP_INTR_SR)) + if (!(esp->ireg & ESP_INTR_SR)) return 0; else return do_reset_complete; @@ -2087,99 +2232,98 @@ } /* Now some dma helpers. */ -static inline void dma_setup(struct sparc_dma_registers *dregs, enum dvma_rev drev, - __u32 addr, int count, int write) +static void dma_setup(struct esp *esp, __u32 addr, int count, int write) { - unsigned long nreg = dregs->cond_reg; - if(write) + u32 nreg = sbus_readl(esp->dregs + DMA_CSR); + + if (write) nreg |= DMA_ST_WRITE; else nreg &= ~(DMA_ST_WRITE); nreg |= DMA_ENABLE; - dregs->cond_reg = nreg; - if(drev == dvmaesc1) { + sbus_writel(nreg, esp->dregs + DMA_CSR); + if (esp->dma->revision == dvmaesc1) { /* This ESC gate array sucks! */ __u32 src = addr; __u32 dest = src + count; - if(dest & (PAGE_SIZE - 1)) + if (dest & (PAGE_SIZE - 1)) count = PAGE_ALIGN(count); - dregs->cnt = count; + sbus_writel(count, esp->dregs + DMA_COUNT); } - dregs->st_addr = addr; + sbus_writel(addr, esp->dregs + DMA_ADDR); } -static inline void dma_drain(struct sparc_dma_registers *dregs, enum dvma_rev drev) +static void dma_drain(struct esp *esp) { - if(drev == dvmahme) + u32 tmp; + + if (esp->dma->revision == dvmahme) return; - if(dregs->cond_reg & DMA_FIFO_ISDRAIN) { - switch(drev) { + if ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_FIFO_ISDRAIN) { + switch (esp->dma->revision) { default: - dregs->cond_reg |= DMA_FIFO_STDRAIN; + tmp |= DMA_FIFO_STDRAIN; + sbus_writel(tmp, esp->dregs + DMA_CSR); case dvmarev3: case dvmaesc1: - while(dregs->cond_reg & DMA_FIFO_ISDRAIN) + while (sbus_readl(esp->dregs + DMA_CSR) & DMA_FIFO_ISDRAIN) udelay(1); }; } } -static inline void dma_invalidate(struct Sparc_ESP *esp, - struct sparc_dma_registers *dregs, - enum dvma_rev drev) +static void dma_invalidate(struct esp *esp) { - unsigned int tmp; + u32 tmp; - if(drev == dvmahme) { - dregs->cond_reg = DMA_RST_SCSI; + if (esp->dma->revision == dvmahme) { + sbus_writel(DMA_RST_SCSI, esp->dregs + DMA_CSR); esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | (DMA_PARITY_OFF | DMA_2CLKS | DMA_SCSI_DISAB | DMA_INT_ENAB)) & ~(DMA_ST_WRITE | DMA_ENABLE)); - dregs->cond_reg = 0; - dregs->cond_reg = esp->prev_hme_dmacsr; + sbus_writel(0, esp->dregs + DMA_CSR); + sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR); /* This is necessary to avoid having the SCSI channel * engine lock up on us. */ - dregs->st_addr = 0; + sbus_writel(0, esp->dregs + DMA_ADDR); } else { - while(dregs->cond_reg & DMA_PEND_READ) + while ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_PEND_READ) udelay(1); - tmp = dregs->cond_reg; tmp &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB); tmp |= DMA_FIFO_INV; - dregs->cond_reg = tmp; - dregs->cond_reg = (tmp & ~(DMA_FIFO_INV)); + sbus_writel(tmp, esp->dregs + DMA_CSR); + tmp &= ~DMA_FIFO_INV; + sbus_writel(tmp, esp->dregs + DMA_CSR); } } -static inline void dma_flashclear(struct Sparc_ESP *esp, - struct sparc_dma_registers *dregs, - enum dvma_rev drev) +static inline void dma_flashclear(struct esp *esp) { - dma_drain(dregs, drev); - dma_invalidate(esp, dregs, drev); + dma_drain(esp); + dma_invalidate(esp); } -static inline int dma_can_transfer(Scsi_Cmnd *sp, enum dvma_rev drev) +static int dma_can_transfer(struct esp *esp, Scsi_Cmnd *sp) { __u32 base, end, sz; - if(drev == dvmarev3) { + if (esp->dma->revision == dvmarev3) { sz = sp->SCp.this_residual; - if(sz > 0x1000000) + if (sz > 0x1000000) sz = 0x1000000; } else { base = ((__u32)((unsigned long)sp->SCp.ptr)); base &= (0x1000000 - 1); end = (base + sp->SCp.this_residual); - if(end > 0x1000000) + if (end > 0x1000000) end = 0x1000000; sz = (end - base); } @@ -2188,33 +2332,34 @@ /* Misc. esp helper macros. */ #define esp_setcount(__eregs, __cnt, __hme) \ - (__eregs)->esp_tclow = ((__cnt) & 0xff); \ - (__eregs)->esp_tcmed = (((__cnt) >> 8) & 0xff); \ - if(__hme) { \ - (__eregs)->fas_rlo = 0; \ - (__eregs)->fas_rhi = 0; \ + sbus_writeb(((__cnt)&0xff), (__eregs) + ESP_TCLOW); \ + sbus_writeb((((__cnt)>>8)&0xff), (__eregs) + ESP_TCMED); \ + if (__hme) { \ + sbus_writeb((((__cnt)>>16)&0xff), (__eregs) + FAS_RLO); \ + sbus_writeb(0, (__eregs) + FAS_RHI); \ } -#define esp_getcount(__eregs) \ - ((((__eregs)->esp_tclow)&0xff) | \ - ((((__eregs)->esp_tcmed)&0xff) << 8)) +#define esp_getcount(__eregs, __hme) \ + ((sbus_readb((__eregs) + ESP_TCLOW)&0xff) | \ + ((sbus_readb((__eregs) + ESP_TCMED)&0xff) << 8) | \ + ((__hme) ? sbus_readb((__eregs) + FAS_RLO) << 16 : 0)) -#define fcount(__esp, __eregs) \ +#define fcount(__esp) \ (((__esp)->erev == fashme) ? \ (__esp)->hme_fifo_workaround_count : \ - (__eregs)->esp_fflags & ESP_FF_FBYTES) + sbus_readb(((__esp)->eregs) + ESP_FFLAGS) & ESP_FF_FBYTES) -#define fnzero(__esp, __eregs) \ +#define fnzero(__esp) \ (((__esp)->erev == fashme) ? 0 : \ - (__eregs)->esp_fflags & ESP_FF_ONOTZERO) + sbus_readb(((__esp)->eregs) + ESP_FFLAGS) & ESP_FF_ONOTZERO) /* XXX speculative nops unnecessary when continuing amidst a data phase * XXX even on esp100!!! another case of flooding the bus with I/O reg * XXX writes... */ -#define esp_maybe_nop(__esp, __eregs) \ - if((__esp)->erev == esp100) \ - esp_cmd((__esp), (__eregs), ESP_CMD_NULL) +#define esp_maybe_nop(__esp) \ + if ((__esp)->erev == esp100) \ + esp_cmd((__esp), ESP_CMD_NULL) #define sreg_to_dataphase(__sreg) \ ((((__sreg) & ESP_STAT_PMASK) == ESP_DOP) ? in_dataout : in_datain) @@ -2227,23 +2372,23 @@ * tell the ESP to eat the extraneous byte so that we can proceed * to the next phase. */ -static inline int esp100_sync_hwbug(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - Scsi_Cmnd *sp, int fifocnt) +static int esp100_sync_hwbug(struct esp *esp, Scsi_Cmnd *sp, int fifocnt) { /* Do not touch this piece of code. */ - if((!(esp->erev == esp100)) || - (!(sreg_datainp((esp->sreg = eregs->esp_status)) && !fifocnt) && - !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) { - if(sp->SCp.phase == in_dataout) - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + if ((!(esp->erev == esp100)) || + (!(sreg_datainp((esp->sreg = sbus_readb(esp->eregs + ESP_STATUS))) && + !fifocnt) && + !(sreg_dataoutp(esp->sreg) && !fnzero(esp)))) { + if (sp->SCp.phase == in_dataout) + esp_cmd(esp, ESP_CMD_FLUSH); return 0; } else { /* Async mode for this guy. */ build_sync_nego_msg(esp, 0, 0); /* Ack the bogus byte, but set ATN first. */ - esp_cmd(esp, eregs, ESP_CMD_SATN); - esp_cmd(esp, eregs, ESP_CMD_MOK); + esp_cmd(esp, ESP_CMD_SATN); + esp_cmd(esp, ESP_CMD_MOK); return 1; } } @@ -2253,15 +2398,14 @@ * contents if we get reselected during this process. So we just need to * ack the possible illegal cmd interrupt pending on the esp100. */ -static inline int esp100_reconnect_hwbug(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs) +static inline int esp100_reconnect_hwbug(struct esp *esp) { - volatile unchar junk; + u8 tmp; - if(esp->erev != esp100) + if (esp->erev != esp100) return 0; - junk = eregs->esp_intrpt; - if(junk & ESP_INTR_SR) + tmp = sbus_readb(esp->eregs + ESP_INTRPT); + if (tmp & ESP_INTR_SR) return 1; return 0; } @@ -2269,13 +2413,13 @@ /* This verifies the BUSID bits during a reselection so that we know which * target is talking to us. */ -static inline int reconnect_target(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs) +static inline int reconnect_target(struct esp *esp) { int it, me = esp->scsi_id_mask, targ = 0; - if(2 != fcount(esp, eregs)) + if (2 != fcount(esp)) return -1; - if(esp->erev == fashme) { + if (esp->erev == fashme) { /* HME does not latch it's own BUS ID bits during * a reselection. Also the target number is given * as an unsigned char, not as a sole bit number @@ -2284,13 +2428,13 @@ */ targ = esp->hme_fifo_workaround_buffer[0]; } else { - it = eregs->esp_fdata; - if(!(it & me)) + it = sbus_readb(esp->eregs + ESP_FDATA); + if (!(it & me)) return -1; it &= ~me; - if(it & (it - 1)) + if (it & (it - 1)) return -1; - while(!(it & 1)) + while (!(it & 1)) targ++, it >>= 1; } return targ; @@ -2299,27 +2443,27 @@ /* This verifies the identify from the target so that we know which lun is * being reconnected. */ -static inline int reconnect_lun(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs) +static inline int reconnect_lun(struct esp *esp) { int lun; - if((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) + if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) return -1; - if(esp->erev == fashme) + if (esp->erev == fashme) lun = esp->hme_fifo_workaround_buffer[1]; else - lun = eregs->esp_fdata; + lun = sbus_readb(esp->eregs + ESP_FDATA); /* Yes, you read this correctly. We report lun of zero * if we see parity error. ESP reports parity error for * the lun byte, and this is the only way to hope to recover * because the target is connected. */ - if(esp->sreg & ESP_STAT_PERR) + if (esp->sreg & ESP_STAT_PERR) return 0; /* Check for illegal bits being set in the lun. */ - if((lun & 0x40) || !(lun & 0x80)) + if ((lun & 0x40) || !(lun & 0x80)) return -1; return lun & 7; @@ -2328,21 +2472,22 @@ /* This puts the driver in a state where it can revitalize a command that * is being continued due to reselection. */ -static inline void esp_connect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - Scsi_Cmnd *sp) +static inline void esp_connect(struct esp *esp, Scsi_Cmnd *sp) { Scsi_Device *dp = sp->device; - if(esp->prev_soff != dp->sync_max_offset || - esp->prev_stp != dp->sync_min_period || - (esp->erev > esp100a && - esp->prev_cfg3 != esp->config3[sp->target])) { - eregs->esp_soff = esp->prev_soff = dp->sync_max_offset; - eregs->esp_stp = esp->prev_stp = dp->sync_min_period; - if(esp->erev > esp100a) - eregs->esp_cfg3 = - esp->prev_cfg3 = - esp->config3[sp->target]; + if (esp->prev_soff != dp->sync_max_offset || + esp->prev_stp != dp->sync_min_period || + (esp->erev > esp100a && + esp->prev_cfg3 != esp->config3[sp->target])) { + esp->prev_soff = dp->sync_max_offset; + esp->prev_stp = dp->sync_min_period; + sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF); + sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP); + if (esp->erev > esp100a) { + esp->prev_cfg3 = esp->config3[sp->target]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); + } } esp->current_SC = sp; } @@ -2350,9 +2495,9 @@ /* This will place the current working command back into the issue queue * if we are to receive a reselection amidst a selection attempt. */ -static inline void esp_reconnect(struct Sparc_ESP *esp, Scsi_Cmnd *sp) +static inline void esp_reconnect(struct esp *esp, Scsi_Cmnd *sp) { - if(!esp->disconnected_SC) + if (!esp->disconnected_SC) ESPLOG(("esp%d: Weird, being reselected but disconnected " "command queue is empty.\n", esp->esp_id)); esp->snip = 0; @@ -2362,14 +2507,14 @@ } /* Begin message in phase. */ -static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_msgin(struct esp *esp) { /* Must be very careful with the fifo on the HME */ - if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY)) - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - esp_maybe_nop(esp, eregs); - esp_cmd(esp, eregs, ESP_CMD_TI); + if ((esp->erev != fashme) || + !(sbus_readb(esp->eregs + ESP_STATUS2) & ESP_STAT2_FEMPTY)) + esp_cmd(esp, ESP_CMD_FLUSH); + esp_maybe_nop(esp); + esp_cmd(esp, ESP_CMD_TI); esp->msgin_len = 1; esp->msgin_ctr = 0; esp_advance_phase(esp->current_SC, in_msgindone); @@ -2379,14 +2524,12 @@ /* This uses various DMA csr fields and the fifo flags count value to * determine how many bytes were successfully sent/received by the ESP. */ -static inline int esp_bytes_sent(struct Sparc_ESP *esp, - struct sparc_dma_registers *dregs, - int fifo_count) +static inline int esp_bytes_sent(struct esp *esp, int fifo_count) { - int rval = dregs->st_addr - esp->esp_command_dvma; + int rval = sbus_readl(esp->dregs + DMA_ADDR) - esp->esp_command_dvma; - if(esp->dma->revision == dvmarev1) - rval -= (4 - ((dregs->cond_reg & DMA_READ_AHEAD)>>11)); + if (esp->dma->revision == dvmarev1) + rval -= (4 - ((sbus_readl(esp->dregs + DMA_CSR) & DMA_READ_AHEAD)>>11)); return rval - fifo_count; } @@ -2394,7 +2537,7 @@ { ++sp->SCp.buffer; --sp->SCp.buffers_residual; - sp->SCp.this_residual = sp->SCp.buffer->length; + sp->SCp.this_residual = sp->SCp.buffer->dvma_length; sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); } @@ -2416,25 +2559,25 @@ * within a buffer or sub-buffer should not upset us at all no matter * how bad the target and/or ESP fucks things up. */ -static int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_data(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; int thisphase, hmuch; ESPDATA(("esp_do_data: ")); - esp_maybe_nop(esp, eregs); + esp_maybe_nop(esp); thisphase = sreg_to_dataphase(esp->sreg); esp_advance_phase(SCptr, thisphase); ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT")); - hmuch = dma_can_transfer(SCptr, esp->dma->revision); + hmuch = dma_can_transfer(esp, SCptr); ESPDATA(("hmuch<%d> ", hmuch)); esp->current_transfer_size = hmuch; - if(esp->erev == fashme) { - unsigned long tmp = esp->prev_hme_dmacsr; + + if (esp->erev == fashme) { + u32 tmp = esp->prev_hme_dmacsr; /* Always set the ESP count registers first. */ - esp_setcount(eregs, hmuch, 1); + esp_setcount(esp->eregs, hmuch, 1); /* Get the DMA csr computed. */ tmp |= (DMA_SCSI_DISAB | DMA_ENABLE); @@ -2444,38 +2587,36 @@ tmp &= ~(DMA_ST_WRITE); esp->prev_hme_dmacsr = tmp; + ESPDATA(("DMA|TI --> do_intr_end\n")); if (thisphase == in_datain) { - dregs->cnt = hmuch; - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + sbus_writel(hmuch, esp->dregs + DMA_COUNT); + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); } else { - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); - dregs->cnt = hmuch; + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); + sbus_writel(hmuch, esp->dregs + DMA_COUNT); } - dregs->st_addr = ((__u32)((unsigned long)SCptr->SCp.ptr)); - dregs->cond_reg = esp->prev_hme_dmacsr; + sbus_writel((__u32)((unsigned long)SCptr->SCp.ptr), esp->dregs+DMA_ADDR); + sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR); } else { - esp_setcount(eregs, hmuch, 0); - dma_setup(dregs, esp->dma->revision, - ((__u32)((unsigned long)SCptr->SCp.ptr)), + esp_setcount(esp->eregs, hmuch, 0); + dma_setup(esp, ((__u32)((unsigned long)SCptr->SCp.ptr)), hmuch, (thisphase == in_datain)); ESPDATA(("DMA|TI --> do_intr_end\n")); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); } return do_intr_end; } /* See how successful the data transfer was. */ -static int esp_do_data_finale(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_data_finale(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0; ESPDATA(("esp_do_data_finale: ")); - if(SCptr->SCp.phase == in_datain) { - if(esp->sreg & ESP_STAT_PERR) { + if (SCptr->SCp.phase == in_datain) { + if (esp->sreg & ESP_STAT_PERR) { /* Yuck, parity error. The ESP asserts ATN * so that we can go to message out phase * immediately and inform the target that @@ -2486,16 +2627,16 @@ esp->cur_msgout[0] = INITIATOR_ERROR; esp->msgout_len = 1; } - dma_drain(dregs, esp->dma->revision); + dma_drain(esp); } - dma_invalidate(esp, dregs, esp->dma->revision); + dma_invalidate(esp); /* This could happen for the above parity error case. */ - if(!(esp->ireg == ESP_INTR_BSERV)) { + if (esp->ireg != ESP_INTR_BSERV) { /* Please go to msgout phase, please please please... */ ESPLOG(("esp%d: !BSERV after data, probably to msgout\n", esp->esp_id)); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } /* Check for partial transfers and other horrible events. @@ -2509,22 +2650,22 @@ * will move and count 16-bit quantities during wide data. * SMCC _and_ Qlogic can both bite me. */ - fifocnt = eregs->esp_fflags & ESP_FF_FBYTES; - if(esp->erev != fashme) - ecount = esp_getcount(eregs); + fifocnt = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES); + if (esp->erev != fashme) + ecount = esp_getcount(esp->eregs, 0); bytes_sent = esp->current_transfer_size; - ESPDATA(("trans_sz=%d, ", bytes_sent)); - if(esp->erev == fashme) { - if(!(esp->sreg & ESP_STAT_TCNT)) { - ecount = esp_getcount(eregs); + ESPDATA(("trans_sz(%d), ", bytes_sent)); + if (esp->erev == fashme) { + if (!(esp->sreg & ESP_STAT_TCNT)) { + ecount = esp_getcount(esp->eregs, 1); bytes_sent -= ecount; } /* Always subtract any cruft remaining in the FIFO. */ - if(esp->prev_cfg3 & ESP_CONFIG3_EWIDE) + if (esp->prev_cfg3 & ESP_CONFIG3_EWIDE) fifocnt <<= 1; - if(SCptr->SCp.phase == in_dataout) + if (SCptr->SCp.phase == in_dataout) bytes_sent -= fifocnt; /* I have an IBM disk which exhibits the following @@ -2546,34 +2687,34 @@ SCptr->SCp.phase == in_dataout) { int mask = (64 - 1); - if((esp->prev_cfg3 & ESP_CONFIG3_EWIDE) == 0) + if ((esp->prev_cfg3 & ESP_CONFIG3_EWIDE) == 0) mask >>= 1; if (bytes_sent & mask) bytes_sent -= (bytes_sent & mask); } } else { - if(!(esp->sreg & ESP_STAT_TCNT)) + if (!(esp->sreg & ESP_STAT_TCNT)) bytes_sent -= ecount; - if(SCptr->SCp.phase == in_dataout) + if (SCptr->SCp.phase == in_dataout) bytes_sent -= fifocnt; } - ESPDATA(("bytes_sent=%d, ", bytes_sent)); + ESPDATA(("bytes_sent(%d), ", bytes_sent)); /* If we were in synchronous mode, check for peculiarities. */ - if(esp->erev == fashme) { - if(SCptr->device->sync_max_offset) { - if(SCptr->SCp.phase == in_dataout) - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + if (esp->erev == fashme) { + if (SCptr->device->sync_max_offset) { + if (SCptr->SCp.phase == in_dataout) + esp_cmd(esp, ESP_CMD_FLUSH); } else { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, ESP_CMD_FLUSH); } } else { - if(SCptr->device->sync_max_offset) - bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt); + if (SCptr->device->sync_max_offset) + bogus_data = esp100_sync_hwbug(esp, SCptr, fifocnt); else - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, ESP_CMD_FLUSH); } /* Until we are sure of what has happened, we are certainly @@ -2581,7 +2722,7 @@ */ esp_advance_phase(SCptr, in_the_dark); - if(bytes_sent < 0) { + if (bytes_sent < 0) { /* I've seen this happen due to lost state in this * driver. No idea why it happened, but allowing * this value to be negative caused things to @@ -2606,15 +2747,16 @@ /* Update the state of our transfer. */ SCptr->SCp.ptr += bytes_sent; SCptr->SCp.this_residual -= bytes_sent; - if(SCptr->SCp.this_residual < 0) { + if (SCptr->SCp.this_residual < 0) { /* shit */ ESPLOG(("esp%d: Data transfer overrun.\n", esp->esp_id)); SCptr->SCp.this_residual = 0; } /* Maybe continue. */ - if(!bogus_data) { + if (!bogus_data) { ESPDATA(("!bogus_data, ")); + /* NO MATTER WHAT, we advance the scatterlist, * if the target should decide to disconnect * in between scatter chunks (which is common) @@ -2624,14 +2766,14 @@ * imagine the hell I went through trying to * figure this out. */ - if(SCptr->use_sg && !SCptr->SCp.this_residual) + if (SCptr->use_sg && !SCptr->SCp.this_residual) advance_sg(SCptr); - if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) { + if (sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) { ESPDATA(("to more data\n")); - return esp_do_data(esp, eregs, dregs); + return esp_do_data(esp); } ESPDATA(("to new phase\n")); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } /* Bogus data, just wait for next interrupt. */ ESPLOG(("esp%d: bogus_data during end of data phase\n", @@ -2650,27 +2792,27 @@ */ static int esp_should_clear_sync(Scsi_Cmnd *sp) { - unchar cmd1 = sp->cmnd[0]; - unchar cmd2 = sp->data_cmnd[0]; + u8 cmd1 = sp->cmnd[0]; + u8 cmd2 = sp->data_cmnd[0]; /* These cases are for spinning up a disk and * waiting for that spinup to complete. */ - if(cmd1 == START_STOP || - cmd2 == START_STOP) + if (cmd1 == START_STOP || + cmd2 == START_STOP) return 0; - if(cmd1 == TEST_UNIT_READY || - cmd2 == TEST_UNIT_READY) + if (cmd1 == TEST_UNIT_READY || + cmd2 == TEST_UNIT_READY) return 0; /* One more special case for SCSI tape drives, * this is what is used to probe the device for * completion of a rewind or tape load operation. */ - if(sp->device->type == TYPE_TAPE) { - if(cmd1 == MODE_SENSE || - cmd2 == MODE_SENSE) + if (sp->device->type == TYPE_TAPE) { + if (cmd1 == MODE_SENSE || + cmd2 == MODE_SENSE) return 0; } @@ -2680,31 +2822,30 @@ /* Either a command is completing or a target is dropping off the bus * to continue the command in the background so we can do other work. */ -static int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_freebus(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; int rval; - rval = skipahead2(esp, eregs, dregs, SCptr, in_status, in_msgindone, in_freeing); - if(rval) + rval = skipahead2(esp, SCptr, in_status, in_msgindone, in_freeing); + if (rval) return rval; - if(esp->ireg != ESP_INTR_DC) { + if (esp->ireg != ESP_INTR_DC) { ESPLOG(("esp%d: Target will not disconnect\n", esp->esp_id)); return do_reset_bus; /* target will not drop BSY... */ } esp->msgout_len = 0; esp->prevmsgout = NOP; - if(esp->prevmsgin == COMMAND_COMPLETE) { + if (esp->prevmsgin == COMMAND_COMPLETE) { /* Normal end of nexus. */ - if(esp->disconnected_SC || (esp->erev == fashme)) - esp_cmd(esp, eregs, ESP_CMD_ESEL); + if (esp->disconnected_SC || (esp->erev == fashme)) + esp_cmd(esp, ESP_CMD_ESEL); - if(SCptr->SCp.Status != GOOD && - SCptr->SCp.Status != CONDITION_GOOD && - ((1<target) & esp->targets_present) && - SCptr->device->sync && - SCptr->device->sync_max_offset) { + if (SCptr->SCp.Status != GOOD && + SCptr->SCp.Status != CONDITION_GOOD && + ((1<target) & esp->targets_present) && + SCptr->device->sync && + SCptr->device->sync_max_offset) { /* SCSI standard says that the synchronous capabilities * should be renegotiated at this point. Most likely * we are about to request sense from this target @@ -2721,20 +2862,20 @@ * can report not ready many times right after * loading up a tape. */ - if(esp_should_clear_sync(SCptr) != 0) + if (esp_should_clear_sync(SCptr) != 0) SCptr->device->sync = 0; } ESPDISC(("F<%02x,%02x>", SCptr->target, SCptr->lun)); esp_done(esp, ((SCptr->SCp.Status & 0xff) | ((SCptr->SCp.Message & 0xff)<<8) | (DID_OK << 16))); - } else if(esp->prevmsgin == DISCONNECT) { + } else if (esp->prevmsgin == DISCONNECT) { /* Normal disconnect. */ - esp_cmd(esp, eregs, ESP_CMD_ESEL); + esp_cmd(esp, ESP_CMD_ESEL); ESPDISC(("D<%02x,%02x>", SCptr->target, SCptr->lun)); append_SC(&esp->disconnected_SC, SCptr); esp->current_SC = NULL; - if(esp->issue_SC) + if (esp->issue_SC) esp_exec_cmd(esp); } else { /* Driver bug, we do not expect a disconnect here @@ -2751,7 +2892,7 @@ /* When a reselect occurs, and we cannot find the command to * reconnect to in our queues, we do this. */ -static int esp_bad_reconnect(struct Sparc_ESP *esp) +static int esp_bad_reconnect(struct esp *esp) { Scsi_Cmnd *sp; @@ -2760,21 +2901,21 @@ ESPLOG(("QUEUE DUMP\n")); sp = esp->issue_SC; ESPLOG(("esp%d: issue_SC[", esp->esp_id)); - while(sp) { + while (sp) { ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); sp = (Scsi_Cmnd *) sp->host_scribble; } ESPLOG(("]\n")); sp = esp->current_SC; ESPLOG(("esp%d: current_SC[", esp->esp_id)); - while(sp) { + if (sp) ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); - sp = (Scsi_Cmnd *) sp->host_scribble; - } + else + ESPLOG(("")); ESPLOG(("]\n")); sp = esp->disconnected_SC; ESPLOG(("esp%d: disconnected_SC[", esp->esp_id)); - while(sp) { + while (sp) { ESPLOG(("<%02x,%02x>", sp->target, sp->lun)); sp = (Scsi_Cmnd *) sp->host_scribble; } @@ -2783,20 +2924,19 @@ } /* Do the needy when a target tries to reconnect to us. */ -static int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_reconnect(struct esp *esp) { int lun, target; Scsi_Cmnd *SCptr; /* Check for all bogus conditions first. */ - target = reconnect_target(esp, eregs); - if(target < 0) { + target = reconnect_target(esp); + if (target < 0) { ESPDISC(("bad bus bits\n")); return do_reset_bus; } - lun = reconnect_lun(esp, eregs); - if(lun < 0) { + lun = reconnect_lun(esp); + if (lun < 0) { ESPDISC(("target=%2x, bad identify msg\n", target)); return do_reset_bus; } @@ -2805,23 +2945,24 @@ ESPDISC(("R<%02x,%02x>", target, lun)); /* Must not flush FIFO or DVMA on HME. */ - if(esp->erev != fashme) { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - if(esp100_reconnect_hwbug(esp, eregs)) + if (esp->erev != fashme) { + esp_cmd(esp, ESP_CMD_FLUSH); + if (esp100_reconnect_hwbug(esp)) return do_reset_bus; - esp_cmd(esp, eregs, ESP_CMD_NULL); + esp_cmd(esp, ESP_CMD_NULL); } - SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun); - if(!SCptr) + SCptr = remove_SC(&esp->disconnected_SC, (u8) target, (u8) lun); + if (!SCptr) return esp_bad_reconnect(esp); - esp_connect(esp, eregs, SCptr); - esp_cmd(esp, eregs, ESP_CMD_MOK); + esp_connect(esp, SCptr); + esp_cmd(esp, ESP_CMD_MOK); - if(esp->erev == fashme) - eregs->esp_busid = (SCptr->target & 0xf) | - (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT); + if (esp->erev == fashme) + sbus_writeb(((SCptr->target & 0xf) | + (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT)), + esp->eregs + ESP_BUSID); /* Reconnect implies a restore pointers operation. */ esp_restore_pointers(esp, SCptr); @@ -2834,29 +2975,28 @@ /* End of NEXUS (hopefully), pick up status + message byte then leave if * all goes well. */ -static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_status(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; int intr, rval; - rval = skipahead1(esp, eregs, dregs, SCptr, in_the_dark, in_status); - if(rval) + rval = skipahead1(esp, SCptr, in_the_dark, in_status); + if (rval) return rval; intr = esp->ireg; ESPSTAT(("esp_do_status: ")); - if(intr != ESP_INTR_DC) { + if (intr != ESP_INTR_DC) { int message_out = 0; /* for parity problems */ /* Ack the message. */ ESPSTAT(("ack msg, ")); - esp_cmd(esp, eregs, ESP_CMD_MOK); + esp_cmd(esp, ESP_CMD_MOK); - if(esp->erev != fashme) { - dma_flashclear(esp, dregs, esp->dma->revision); + if (esp->erev != fashme) { + dma_flashclear(esp); /* Wait till the first bits settle. */ - while(esp->esp_command[0] == 0xff) + while (esp->esp_command[0] == 0xff) udelay(1); } else { esp->esp_command[0] = esp->hme_fifo_workaround_buffer[0]; @@ -2883,24 +3023,24 @@ * and we must therefore wait for the * next phase change. */ - if(intr & ESP_INTR_FDONE) { + if (intr & ESP_INTR_FDONE) { /* We got it all, hallejulia. */ ESPSTAT(("got both, ")); SCptr->SCp.Status = esp->esp_command[0]; SCptr->SCp.Message = esp->esp_command[1]; esp->prevmsgin = SCptr->SCp.Message; esp->cur_msgin[0] = SCptr->SCp.Message; - if(esp->sreg & ESP_STAT_PERR) { + if (esp->sreg & ESP_STAT_PERR) { /* There was bad parity for the * message byte, the status byte * was ok. */ message_out = MSG_PARITY_ERROR; } - } else if(intr == ESP_INTR_BSERV) { + } else if (intr == ESP_INTR_BSERV) { /* Only got status byte. */ ESPLOG(("esp%d: got status only, ", esp->esp_id)); - if(!(esp->sreg & ESP_STAT_PERR)) { + if (!(esp->sreg & ESP_STAT_PERR)) { SCptr->SCp.Status = esp->esp_command[0]; SCptr->SCp.Message = 0xff; } else { @@ -2915,22 +3055,22 @@ /* This shouldn't happen ever. */ ESPSTAT(("got bolixed\n")); esp_advance_phase(SCptr, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } - if(!message_out) { + if (!message_out) { ESPSTAT(("status=%2x msg=%2x, ", SCptr->SCp.Status, SCptr->SCp.Message)); - if(SCptr->SCp.Message == COMMAND_COMPLETE) { + if (SCptr->SCp.Message == COMMAND_COMPLETE) { ESPSTAT(("and was COMMAND_COMPLETE\n")); esp_advance_phase(SCptr, in_freeing); - return esp_do_freebus(esp, eregs, dregs); + return esp_do_freebus(esp); } else { ESPLOG(("esp%d: and _not_ COMMAND_COMPLETE\n", esp->esp_id)); esp->msgin_len = esp->msgin_ctr = 1; esp_advance_phase(SCptr, in_msgindone); - return esp_do_msgindone(esp, eregs, dregs); + return esp_do_msgindone(esp); } } else { /* With luck we'll be able to let the target @@ -2945,42 +3085,42 @@ esp->cur_msgout[0] = message_out; esp->msgout_len = esp->msgout_ctr = 1; esp_advance_phase(SCptr, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } } else { /* If we disconnect now, all hell breaks loose. */ ESPLOG(("esp%d: whoops, disconnect\n", esp->esp_id)); esp_advance_phase(SCptr, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } } -static int esp_enter_status(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_enter_status(struct esp *esp) { - unchar thecmd = ESP_CMD_ICCSEQ; + u8 thecmd = ESP_CMD_ICCSEQ; + + esp_cmd(esp, ESP_CMD_FLUSH); + if (esp->erev != fashme) { + u32 tmp; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - if(esp->erev != fashme) { esp->esp_command[0] = esp->esp_command[1] = 0xff; - eregs->esp_tclow = 2; - eregs->esp_tcmed = 0; - dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE); - if(esp->dma->revision == dvmaesc1) - dregs->cnt = 0x100; - dregs->st_addr = esp->esp_command_dvma; + sbus_writeb(2, esp->eregs + ESP_TCLOW); + sbus_writeb(0, esp->eregs + ESP_TCMED); + tmp = sbus_readl(esp->dregs + DMA_CSR); + tmp |= (DMA_ST_WRITE | DMA_ENABLE); + sbus_writel(tmp, esp->dregs + DMA_CSR); + if (esp->dma->revision == dvmaesc1) + sbus_writel(0x100, esp->dregs + DMA_COUNT); + sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR); thecmd |= ESP_CMD_DMA; } - esp_cmd(esp, eregs, thecmd); + esp_cmd(esp, thecmd); esp_advance_phase(esp->current_SC, in_status); - return esp_do_status(esp, eregs, dregs); + return esp_do_status(esp); } -static int esp_disconnect_amidst_phases(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_disconnect_amidst_phases(struct esp *esp) { Scsi_Cmnd *sp = esp->current_SC; Scsi_Device *dp = sp->device; @@ -2994,10 +3134,10 @@ phase_string(sp->SCp.phase), phase_string(sp->SCp.sent_command))); - if(esp->disconnected_SC || (esp->erev == fashme)) - esp_cmd(esp, eregs, ESP_CMD_ESEL); + if (esp->disconnected_SC != NULL || (esp->erev == fashme)) + esp_cmd(esp, ESP_CMD_ESEL); - switch(esp->cur_msgout[0]) { + switch (esp->cur_msgout[0]) { default: /* We didn't expect this to happen at all. */ ESPLOG(("device is bolixed\n")); @@ -3024,42 +3164,32 @@ return do_intr_end; } -static int esp_enter_msgout(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_enter_msgout(struct esp *esp) { esp_advance_phase(esp->current_SC, in_msgout); - return esp_do_msgout(esp, eregs, dregs); + return esp_do_msgout(esp); } -static int esp_enter_msgin(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_enter_msgin(struct esp *esp) { esp_advance_phase(esp->current_SC, in_msgin); - return esp_do_msgin(esp, eregs, dregs); + return esp_do_msgin(esp); } -static int esp_enter_cmd(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_enter_cmd(struct esp *esp) { esp_advance_phase(esp->current_SC, in_cmdbegin); - return esp_do_cmdbegin(esp, eregs, dregs); + return esp_do_cmdbegin(esp); } -static int esp_enter_badphase(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_enter_badphase(struct esp *esp) { ESPLOG(("esp%d: Bizarre bus phase %2x.\n", esp->esp_id, esp->sreg & ESP_STAT_PMASK)); return do_reset_bus; } -typedef int (*espfunc_t)(struct Sparc_ESP *, - struct Sparc_ESP_regs *, - struct sparc_dma_registers *); +typedef int (*espfunc_t)(struct esp *); static espfunc_t phase_vector[] = { esp_do_data, /* ESP_DOP */ @@ -3075,39 +3205,38 @@ /* The target has control of the bus and we have to see where it has * taken us. */ -static int esp_do_phase_determine(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_phase_determine(struct esp *esp) { if ((esp->ireg & ESP_INTR_DC) != 0) - return esp_disconnect_amidst_phases(esp, eregs, dregs); - return phase_vector[esp->sreg & ESP_STAT_PMASK](esp, eregs, dregs); + return esp_disconnect_amidst_phases(esp); + return phase_vector[esp->sreg & ESP_STAT_PMASK](esp); } /* First interrupt after exec'ing a cmd comes here. */ -static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_select_complete(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; Scsi_Device *SDptr = SCptr->device; int cmd_bytes_sent, fcnt; - if(esp->erev != fashme) - esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS); - if(esp->erev == fashme) + if (esp->erev != fashme) + esp->seqreg = (sbus_readb(esp->eregs + ESP_SSTEP) & ESP_STEP_VBITS); + + if (esp->erev == fashme) fcnt = esp->hme_fifo_workaround_count; else - fcnt = (eregs->esp_fflags & ESP_FF_FBYTES); - cmd_bytes_sent = esp_bytes_sent(esp, dregs, fcnt); - dma_invalidate(esp, dregs, esp->dma->revision); + fcnt = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES); + + cmd_bytes_sent = esp_bytes_sent(esp, fcnt); + dma_invalidate(esp); /* Let's check to see if a reselect happened * while we we're trying to select. This must * be checked first. */ - if(esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) { + if (esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) { esp_reconnect(esp, SCptr); - return esp_do_reconnect(esp, eregs, dregs); + return esp_do_reconnect(esp); } /* Looks like things worked, we should see a bus service & @@ -3116,18 +3245,18 @@ * be fooled into thinking selection was successful if * ESP_INTR_DC is set, see below. */ - if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) { + if (esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) { /* target speaks... */ esp->targets_present |= (1<target); /* What if the target ignores the sdtr? */ - if(esp->snip) + if (esp->snip) SDptr->sync = 1; /* See how far, if at all, we got in getting * the information out to the target. */ - switch(esp->seqreg) { + switch (esp->seqreg) { default: case ESP_STEP_ASEL: @@ -3201,28 +3330,29 @@ case ESP_STEP_FINI6: case ESP_STEP_FINI7: /* Account for the identify message */ - if(SCptr->SCp.phase == in_slct_norm) + if (SCptr->SCp.phase == in_slct_norm) cmd_bytes_sent -= 1; }; - if(esp->erev != fashme) - esp_cmd(esp, eregs, ESP_CMD_NULL); + + if (esp->erev != fashme) + esp_cmd(esp, ESP_CMD_NULL); /* Be careful, we could really get fucked during synchronous * data transfers if we try to flush the fifo now. */ - if((esp->erev != fashme) && /* not a Happy Meal and... */ - !fcnt && /* Fifo is empty and... */ - /* either we are not doing synchronous transfers or... */ - (!SDptr->sync_max_offset || - /* We are not going into data in phase. */ - ((esp->sreg & ESP_STAT_PMASK) != ESP_DIP))) - esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* flush is safe */ + if ((esp->erev != fashme) && /* not a Happy Meal and... */ + !fcnt && /* Fifo is empty and... */ + /* either we are not doing synchronous transfers or... */ + (!SDptr->sync_max_offset || + /* We are not going into data in phase. */ + ((esp->sreg & ESP_STAT_PMASK) != ESP_DIP))) + esp_cmd(esp, ESP_CMD_FLUSH); /* flush is safe */ /* See how far we got if this is not a slow command. */ - if(!esp->esp_slowcmd) { - if(cmd_bytes_sent < 0) + if (!esp->esp_slowcmd) { + if (cmd_bytes_sent < 0) cmd_bytes_sent = 0; - if(cmd_bytes_sent != SCptr->cmd_len) { + if (cmd_bytes_sent != SCptr->cmd_len) { /* Crapola, mark it as a slowcmd * so that we have some chance of * keeping the command alive with @@ -3250,11 +3380,11 @@ /* Now figure out where we went. */ esp_advance_phase(SCptr, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } /* Did the target even make it? */ - if(esp->ireg == ESP_INTR_DC) { + if (esp->ireg == ESP_INTR_DC) { /* wheee... nobody there or they didn't like * what we told it to do, clean up. */ @@ -3263,13 +3393,14 @@ * a command in the background for us, tell * the ESP to listen for them. */ - if(esp->disconnected_SC) - esp_cmd(esp, eregs, ESP_CMD_ESEL); + if (esp->disconnected_SC) + esp_cmd(esp, ESP_CMD_ESEL); - if(((1<target) & esp->targets_present) && - esp->seqreg && esp->cur_msgout[0] == EXTENDED_MESSAGE && - (SCptr->SCp.phase == in_slct_msg || - SCptr->SCp.phase == in_slct_stop)) { + if (((1<target) & esp->targets_present) && + esp->seqreg != 0 && + (esp->cur_msgout[0] == EXTENDED_MESSAGE) && + (SCptr->SCp.phase == in_slct_msg || + SCptr->SCp.phase == in_slct_stop)) { /* shit */ esp->snip = 0; ESPLOG(("esp%d: Failed synchronous negotiation for target %d " @@ -3299,7 +3430,7 @@ * or whenever when we are scanning the bus for targets. * But first make sure that is really what is happening. */ - if(((1<target) & esp->targets_present)) { + if (((1<target) & esp->targets_present)) { ESPLOG(("esp%d: Warning, live target %d not responding to " "selection.\n", esp->esp_id, SCptr->target)); @@ -3320,38 +3451,30 @@ return do_intr_end; } - ESPLOG(("esp%d: Selection failure.\n", esp->esp_id)); printk("esp%d: Currently -- ", esp->esp_id); - esp_print_ireg(esp->ireg); - printk(" "); - esp_print_statreg(esp->sreg); - printk(" "); - esp_print_seqreg(esp->seqreg); - printk("\n"); + esp_print_ireg(esp->ireg); printk(" "); + esp_print_statreg(esp->sreg); printk(" "); + esp_print_seqreg(esp->seqreg); printk("\n"); printk("esp%d: New -- ", esp->esp_id); - esp->sreg = eregs->esp_status; - esp->seqreg = eregs->esp_sstep; - esp->ireg = eregs->esp_intrpt; - esp_print_ireg(esp->ireg); - printk(" "); - esp_print_statreg(esp->sreg); - printk(" "); - esp_print_seqreg(esp->seqreg); - printk("\n"); + esp->sreg = sbus_readb(esp->eregs + ESP_STATUS); + esp->seqreg = sbus_readb(esp->eregs + ESP_SSTEP); + esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT); + esp_print_ireg(esp->ireg); printk(" "); + esp_print_statreg(esp->sreg); printk(" "); + esp_print_seqreg(esp->seqreg); printk("\n"); ESPLOG(("esp%d: resetting bus\n", esp->esp_id)); return do_reset_bus; /* ugh... */ } /* Continue reading bytes for msgin phase. */ -static int esp_do_msgincont(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_msgincont(struct esp *esp) { - if(esp->ireg & ESP_INTR_BSERV) { + if (esp->ireg & ESP_INTR_BSERV) { /* in the right phase too? */ - if((esp->sreg & ESP_STAT_PMASK) == ESP_MIP) { + if ((esp->sreg & ESP_STAT_PMASK) == ESP_MIP) { /* phew... */ - esp_cmd(esp, eregs, ESP_CMD_TI); + esp_cmd(esp, ESP_CMD_TI); esp_advance_phase(esp->current_SC, in_msgindone); return do_intr_end; } @@ -3370,25 +3493,23 @@ return do_phase_determine; } -static int check_singlebyte_msg(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int check_singlebyte_msg(struct esp *esp) { esp->prevmsgin = esp->cur_msgin[0]; - if(esp->cur_msgin[0] & 0x80) { + if (esp->cur_msgin[0] & 0x80) { /* wheee... */ ESPLOG(("esp%d: target sends identify amidst phases\n", esp->esp_id)); esp_advance_phase(esp->current_SC, in_the_dark); return 0; - } else if(((esp->cur_msgin[0] & 0xf0) == 0x20) || - (esp->cur_msgin[0] == EXTENDED_MESSAGE)) { + } else if (((esp->cur_msgin[0] & 0xf0) == 0x20) || + (esp->cur_msgin[0] == EXTENDED_MESSAGE)) { esp->msgin_len = 2; esp_advance_phase(esp->current_SC, in_msgincont); return 0; } esp_advance_phase(esp->current_SC, in_the_dark); - switch(esp->cur_msgin[0]) { + switch (esp->cur_msgin[0]) { default: /* We don't want to hear about it. */ ESPLOG(("esp%d: msg %02x which we don't know about\n", esp->esp_id, @@ -3406,7 +3527,7 @@ * a save/restore pointer sequence so early in the * bus transition sequences, but cover it. */ - if(esp->esp_slowcmd) { + if (esp->esp_slowcmd) { esp->esp_scmdleft = esp->current_SC->cmd_len; esp->esp_scmdp = &esp->current_SC->cmnd[0]; } @@ -3425,7 +3546,7 @@ case MESSAGE_REJECT: ESPMISC(("msg reject, ")); - if(esp->prevmsgout == EXTENDED_MESSAGE) { + if (esp->prevmsgout == EXTENDED_MESSAGE) { Scsi_Device *SDptr = esp->current_SC->device; /* Doesn't look like this target can @@ -3449,11 +3570,11 @@ * the SCSI2 standard specifically recommends against targets doing * this because so many initiators cannot cope with this occuring. */ -static int target_with_ants_in_pants(struct Sparc_ESP *esp, +static int target_with_ants_in_pants(struct esp *esp, Scsi_Cmnd *SCptr, Scsi_Device *SDptr) { - if(SDptr->sync || SDptr->borken) { + if (SDptr->sync || SDptr->borken) { /* sorry, no can do */ ESPSDTR(("forcing to async, ")); build_sync_nego_msg(esp, 0, 0); @@ -3468,23 +3589,23 @@ return 0; } -static void sync_report(struct Sparc_ESP *esp) +static void sync_report(struct esp *esp) { int msg3, msg4; char *type; msg3 = esp->cur_msgin[3]; msg4 = esp->cur_msgin[4]; - if(msg4) { + if (msg4) { int hz = 1000000000 / (msg3 * 4); int integer = hz / 1000000; int fraction = (hz - (integer * 1000000)) / 10000; - if((esp->erev == fashme) && - (esp->config3[esp->current_SC->target] & ESP_CONFIG3_EWIDE)) { + if ((esp->erev == fashme) && + (esp->config3[esp->current_SC->target] & ESP_CONFIG3_EWIDE)) { type = "FAST-WIDE"; integer <<= 1; fraction <<= 1; - } else if((msg3 * 4) < 200) { + } else if ((msg3 * 4) < 200) { type = "FAST"; } else { type = "synchronous"; @@ -3507,36 +3628,34 @@ } } -static int check_multibyte_msg(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int check_multibyte_msg(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; Scsi_Device *SDptr = SCptr->device; - unchar regval = 0; + u8 regval = 0; int message_out = 0; ESPSDTR(("chk multibyte msg: ")); - if(esp->cur_msgin[2] == EXTENDED_SDTR) { + if (esp->cur_msgin[2] == EXTENDED_SDTR) { int period = esp->cur_msgin[3]; int offset = esp->cur_msgin[4]; ESPSDTR(("is sync nego response, ")); - if(!esp->snip) { + if (!esp->snip) { int rval; /* Target negotiates first! */ ESPSDTR(("target jumps the gun, ")); message_out = EXTENDED_MESSAGE; /* we must respond */ rval = target_with_ants_in_pants(esp, SCptr, SDptr); - if(rval) + if (rval) return rval; } ESPSDTR(("examining sdtr, ")); /* Offset cannot be larger than ESP fifo size. */ - if(offset > 15) { + if (offset > 15) { ESPSDTR(("offset too big %2x, ", offset)); offset = 15; ESPSDTR(("sending back new offset\n")); @@ -3544,7 +3663,7 @@ return EXTENDED_MESSAGE; } - if(offset && period > esp->max_period) { + if (offset && period > esp->max_period) { /* Yeee, async for this slow device. */ ESPSDTR(("period too long %2x, ", period)); build_sync_nego_msg(esp, 0, 0); @@ -3554,65 +3673,77 @@ } else if (offset && period < esp->min_period) { ESPSDTR(("period too short %2x, ", period)); period = esp->min_period; - if(esp->erev > esp236) + if (esp->erev > esp236) regval = 4; else regval = 5; - } else if(offset) { + } else if (offset) { int tmp; ESPSDTR(("period is ok, ")); tmp = esp->ccycle / 1000; regval = (((period << 2) + tmp - 1) / tmp); - if(regval && ((esp->erev == fas100a || - esp->erev == fas236 || - esp->erev == fashme))) { - if(period >= 50) + if (regval && ((esp->erev == fas100a || + esp->erev == fas236 || + esp->erev == fashme))) { + if (period >= 50) regval--; } } - if(offset) { - unchar bit; + if (offset) { + u8 bit; SDptr->sync_min_period = (regval & 0x1f); SDptr->sync_max_offset = (offset | esp->radelay); - if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) { - if((esp->erev == fas100a) || (esp->erev == fashme)) + if (esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme) { + if ((esp->erev == fas100a) || (esp->erev == fashme)) bit = ESP_CONFIG3_FAST; else bit = ESP_CONFIG3_FSCSI; - if(period < 50) + if (period < 50) { + /* On FAS366, if using fast-20 synchronous transfers + * we need to make sure the REQ/ACK assert/deassert + * control bits are clear. + */ + if (esp->erev == fashme) + SDptr->sync_max_offset &= ~esp->radelay; esp->config3[SCptr->target] |= bit; - else + } else { esp->config3[SCptr->target] &= ~bit; - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target]; + } + esp->prev_cfg3 = esp->config3[SCptr->target]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); } - eregs->esp_soff = esp->prev_soff = SDptr->sync_min_period; - eregs->esp_stp = esp->prev_stp = SDptr->sync_max_offset; - + esp->prev_soff = SDptr->sync_max_offset; + esp->prev_stp = SDptr->sync_min_period; + sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF); + sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP); ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n", - SDptr->sync_max_offset, - SDptr->sync_min_period, - esp->config3[SCptr->target])); + SDptr->sync_max_offset, + SDptr->sync_min_period, + esp->config3[SCptr->target])); esp->snip = 0; - } else if(SDptr->sync_max_offset) { - unchar bit; + } else if (SDptr->sync_max_offset) { + u8 bit; /* back to async mode */ ESPSDTR(("unaccaptable sync nego, forcing async\n")); SDptr->sync_max_offset = 0; SDptr->sync_min_period = 0; - eregs->esp_soff = esp->prev_soff = 0; - eregs->esp_stp = esp->prev_stp = 0; - if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) { - if((esp->erev == fas100a) || (esp->erev == fashme)) + esp->prev_soff = 0; + esp->prev_stp = 0; + sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF); + sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP); + if (esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme) { + if ((esp->erev == fas100a) || (esp->erev == fashme)) bit = ESP_CONFIG3_FAST; else bit = ESP_CONFIG3_FSCSI; esp->config3[SCptr->target] &= ~bit; - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target]; + esp->prev_cfg3 = esp->config3[SCptr->target]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); } } @@ -3621,7 +3752,7 @@ ESPSDTR(("chk multibyte msg: sync is known, ")); SDptr->sync = 1; - if(message_out) { + if (message_out) { ESPLOG(("esp%d: sending sdtr back, hoping for msgout\n", esp->esp_id)); build_sync_nego_msg(esp, period, offset); @@ -3632,26 +3763,26 @@ ESPSDTR(("returning zero\n")); esp_advance_phase(SCptr, in_the_dark); /* ...or else! */ return 0; - } else if(esp->cur_msgin[2] == EXTENDED_WDTR) { + } else if (esp->cur_msgin[2] == EXTENDED_WDTR) { int size = 8 << esp->cur_msgin[3]; esp->wnip = 0; - if(esp->erev != fashme) { + if (esp->erev != fashme) { ESPLOG(("esp%d: AIEEE wide msg received and not HME.\n", esp->esp_id)); message_out = MESSAGE_REJECT; - } else if(size > 16) { + } else if (size > 16) { ESPLOG(("esp%d: AIEEE wide transfer for %d size " "not supported.\n", esp->esp_id, size)); message_out = MESSAGE_REJECT; } else { /* Things look good; let's see what we got. */ - if(size == 16) { + if (size == 16) { /* Set config 3 register for this target. */ esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE; } else { /* Just make sure it was one byte sized. */ - if(size != 8) { + if (size != 8) { ESPLOG(("esp%d: Aieee, wide nego of %d size.\n", esp->esp_id, size)); message_out = MESSAGE_REJECT; @@ -3660,7 +3791,8 @@ /* Pure paranoia. */ esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE); } - eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target]; + esp->prev_cfg3 = esp->config3[SCptr->target]; + sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3); /* Regardless, next try for sync transfers. */ build_sync_nego_msg(esp, esp->sync_defp, 15); @@ -3668,7 +3800,7 @@ esp->snip = 1; message_out = EXTENDED_MESSAGE; } - } else if(esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) { + } else if (esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) { ESPLOG(("esp%d: rejecting modify data ptr msg\n", esp->esp_id)); message_out = MESSAGE_REJECT; } @@ -3677,39 +3809,38 @@ return message_out; } -static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_msgindone(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; int message_out = 0, it = 0, rval; - rval = skipahead1(esp, eregs, dregs, SCptr, in_msgin, in_msgindone); - if(rval) + rval = skipahead1(esp, SCptr, in_msgin, in_msgindone); + if (rval) return rval; - if(SCptr->SCp.sent_command != in_status) { - if(!(esp->ireg & ESP_INTR_DC)) { - if(esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) { + if (SCptr->SCp.sent_command != in_status) { + if (!(esp->ireg & ESP_INTR_DC)) { + if (esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) { message_out = MSG_PARITY_ERROR; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - } else if(esp->erev != fashme && - (it = (eregs->esp_fflags & ESP_FF_FBYTES))!=1) { + esp_cmd(esp, ESP_CMD_FLUSH); + } else if (esp->erev != fashme && + (it = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES)) != 1) { /* We certainly dropped the ball somewhere. */ message_out = INITIATOR_ERROR; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - } else if(!esp->msgin_len) { - if(esp->erev == fashme) + esp_cmd(esp, ESP_CMD_FLUSH); + } else if (!esp->msgin_len) { + if (esp->erev == fashme) it = esp->hme_fifo_workaround_buffer[0]; else - it = eregs->esp_fdata; + it = sbus_readb(esp->eregs + ESP_FDATA); esp_advance_phase(SCptr, in_msgincont); } else { /* it is ok and we want it */ - if(esp->erev == fashme) + if (esp->erev == fashme) it = esp->cur_msgin[esp->msgin_ctr] = esp->hme_fifo_workaround_buffer[0]; else it = esp->cur_msgin[esp->msgin_ctr] = - eregs->esp_fdata; + sbus_readb(esp->eregs + ESP_FDATA); esp->msgin_ctr++; } } else { @@ -3719,14 +3850,14 @@ } else { it = esp->cur_msgin[0]; } - if(!message_out && esp->msgin_len) { - if(esp->msgin_ctr < esp->msgin_len) { + if (!message_out && esp->msgin_len) { + if (esp->msgin_ctr < esp->msgin_len) { esp_advance_phase(SCptr, in_msgincont); - } else if(esp->msgin_len == 1) { - message_out = check_singlebyte_msg(esp, eregs, dregs); - } else if(esp->msgin_len == 2) { - if(esp->cur_msgin[0] == EXTENDED_MESSAGE) { - if((it+2) >= 15) { + } else if (esp->msgin_len == 1) { + message_out = check_singlebyte_msg(esp); + } else if (esp->msgin_len == 2) { + if (esp->cur_msgin[0] == EXTENDED_MESSAGE) { + if ((it + 2) >= 15) { message_out = MESSAGE_REJECT; } else { esp->msgin_len = (it + 2); @@ -3736,102 +3867,103 @@ message_out = MESSAGE_REJECT; /* foo on you */ } } else { - message_out = check_multibyte_msg(esp, eregs, dregs); + message_out = check_multibyte_msg(esp); } } - if(message_out < 0) { + if (message_out < 0) { return -message_out; - } else if(message_out) { - if(((message_out != 1) && - ((message_out < 0x20) || (message_out & 0x80)))) + } else if (message_out) { + if (((message_out != 1) && + ((message_out < 0x20) || (message_out & 0x80)))) esp->msgout_len = 1; esp->cur_msgout[0] = message_out; - esp_cmd(esp, eregs, ESP_CMD_SATN); + esp_cmd(esp, ESP_CMD_SATN); esp_advance_phase(SCptr, in_the_dark); esp->msgin_len = 0; } - esp->sreg = eregs->esp_status; + esp->sreg = sbus_readb(esp->eregs + ESP_STATUS); esp->sreg &= ~(ESP_STAT_INTR); - if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD)) - esp_cmd(esp, eregs, ESP_CMD_MOK); - if((SCptr->SCp.sent_command == in_msgindone) && + if ((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD)) + esp_cmd(esp, ESP_CMD_MOK); + if ((SCptr->SCp.sent_command == in_msgindone) && (SCptr->SCp.phase == in_freeing)) - return esp_do_freebus(esp, eregs, dregs); + return esp_do_freebus(esp); return do_intr_end; } -static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_cmdbegin(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; esp_advance_phase(SCptr, in_cmdend); - if(esp->erev == fashme) { - unsigned long tmp = dregs->cond_reg; + if (esp->erev == fashme) { + u32 tmp = sbus_readl(esp->dregs + DMA_CSR); int i; - for(i = 0; i < esp->esp_scmdleft; i++) + for (i = 0; i < esp->esp_scmdleft; i++) esp->esp_command[i] = *esp->esp_scmdp++; esp->esp_scmdleft = 0; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - esp_setcount(eregs, i, 1); - esp_cmd(esp, eregs, (ESP_CMD_DMA | ESP_CMD_TI)); + esp_cmd(esp, ESP_CMD_FLUSH); + esp_setcount(esp->eregs, i, 1); + esp_cmd(esp, (ESP_CMD_DMA | ESP_CMD_TI)); tmp |= (DMA_SCSI_DISAB | DMA_ENABLE); tmp &= ~(DMA_ST_WRITE); - dregs->cnt = i; - dregs->st_addr = esp->esp_command_dvma; - dregs->cond_reg = tmp; + sbus_writel(i, esp->dregs + DMA_COUNT); + sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR); + sbus_writel(tmp, esp->dregs + DMA_CSR); } else { - unsigned char tmp; - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + u8 tmp; + + esp_cmd(esp, ESP_CMD_FLUSH); tmp = *esp->esp_scmdp++; esp->esp_scmdleft--; - eregs->esp_fdata = tmp; - esp_cmd(esp, eregs, ESP_CMD_TI); + sbus_writeb(tmp, esp->eregs + ESP_FDATA); + esp_cmd(esp, ESP_CMD_TI); } return do_intr_end; } -static int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_cmddone(struct esp *esp) { - if(esp->erev == fashme) - dma_invalidate(esp, dregs, dvmahme); + if (esp->erev == fashme) + dma_invalidate(esp); else - esp_cmd(esp, eregs, ESP_CMD_NULL); - if(esp->ireg & ESP_INTR_BSERV) { + esp_cmd(esp, ESP_CMD_NULL); + + if (esp->ireg & ESP_INTR_BSERV) { esp_advance_phase(esp->current_SC, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } + ESPLOG(("esp%d: in do_cmddone() but didn't get BSERV interrupt.\n", esp->esp_id)); return do_reset_bus; } -static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_msgout(struct esp *esp) { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); - switch(esp->msgout_len) { + esp_cmd(esp, ESP_CMD_FLUSH); + switch (esp->msgout_len) { case 1: - if(esp->erev == fashme) - hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1); + if (esp->erev == fashme) + hme_fifo_push(esp, &esp->cur_msgout[0], 1); else - eregs->esp_fdata = esp->cur_msgout[0]; - esp_cmd(esp, eregs, ESP_CMD_TI); + sbus_writeb(esp->cur_msgout[0], esp->eregs + ESP_FDATA); + + esp_cmd(esp, ESP_CMD_TI); break; case 2: esp->esp_command[0] = esp->cur_msgout[0]; esp->esp_command[1] = esp->cur_msgout[1]; - if(esp->erev == fashme) { - hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 2); - esp_cmd(esp, eregs, ESP_CMD_TI); + + if (esp->erev == fashme) { + hme_fifo_push(esp, &esp->cur_msgout[0], 2); + esp_cmd(esp, ESP_CMD_TI); } else { - dma_setup(dregs, esp->dma->revision, - esp->esp_command_dvma, 2, 0); - esp_setcount(eregs, 2, 0); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + dma_setup(esp, esp->esp_command_dvma, 2, 0); + esp_setcount(esp->eregs, 2, 0); + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); } break; @@ -3841,14 +3973,14 @@ esp->esp_command[2] = esp->cur_msgout[2]; esp->esp_command[3] = esp->cur_msgout[3]; esp->snip = 1; - if(esp->erev == fashme) { - hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 4); - esp_cmd(esp, eregs, ESP_CMD_TI); + + if (esp->erev == fashme) { + hme_fifo_push(esp, &esp->cur_msgout[0], 4); + esp_cmd(esp, ESP_CMD_TI); } else { - dma_setup(dregs, esp->dma->revision, - esp->esp_command_dvma, 4, 0); - esp_setcount(eregs, 4, 0); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + dma_setup(esp, esp->esp_command_dvma, 4, 0); + esp_setcount(esp->eregs, 4, 0); + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); } break; @@ -3859,14 +3991,14 @@ esp->esp_command[3] = esp->cur_msgout[3]; esp->esp_command[4] = esp->cur_msgout[4]; esp->snip = 1; - if(esp->erev == fashme) { - hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5); - esp_cmd(esp, eregs, ESP_CMD_TI); + + if (esp->erev == fashme) { + hme_fifo_push(esp, &esp->cur_msgout[0], 5); + esp_cmd(esp, ESP_CMD_TI); } else { - dma_setup(dregs, esp->dma->revision, - esp->esp_command_dvma, 5, 0); - esp_setcount(eregs, 5, 0); - esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI); + dma_setup(esp, esp->esp_command_dvma, 5, 0); + esp_setcount(esp->eregs, 5, 0); + esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI); } break; @@ -3874,46 +4006,51 @@ /* whoops */ ESPMISC(("bogus msgout sending NOP\n")); esp->cur_msgout[0] = NOP; - if(esp->erev == fashme) { - hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1); + + if (esp->erev == fashme) { + hme_fifo_push(esp, &esp->cur_msgout[0], 1); } else { - eregs->esp_fdata = esp->cur_msgout[0]; + sbus_writeb(esp->cur_msgout[0], esp->eregs + ESP_FDATA); } + esp->msgout_len = 1; - esp_cmd(esp, eregs, ESP_CMD_TI); + esp_cmd(esp, ESP_CMD_TI); break; - } + }; + esp_advance_phase(esp->current_SC, in_msgoutdone); return do_intr_end; } -static int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_do_msgoutdone(struct esp *esp) { - if(esp->msgout_len > 1) { + if (esp->msgout_len > 1) { /* XXX HME/FAS ATN deassert workaround required, * XXX no DMA flushing, only possible ESP_CMD_FLUSH * XXX to kill the fifo. */ - if(esp->erev != fashme) { - while(dregs->cond_reg & DMA_PEND_READ) + if (esp->erev != fashme) { + u32 tmp; + + while ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_PEND_READ) udelay(1); - dregs->cond_reg &= ~(DMA_ENABLE); - dma_invalidate(esp, dregs, esp->dma->revision); + tmp &= ~DMA_ENABLE; + sbus_writel(tmp, esp->dregs + DMA_CSR); + dma_invalidate(esp); } else { - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + esp_cmd(esp, ESP_CMD_FLUSH); } } - if(!(esp->ireg & ESP_INTR_DC)) { - if(esp->erev != fashme) - esp_cmd(esp, eregs, ESP_CMD_NULL); - switch(esp->sreg & ESP_STAT_PMASK) { + if (!(esp->ireg & ESP_INTR_DC)) { + if (esp->erev != fashme) + esp_cmd(esp, ESP_CMD_NULL); + switch (esp->sreg & ESP_STAT_PMASK) { case ESP_MOP: /* whoops, parity error */ ESPLOG(("esp%d: still in msgout, parity error assumed\n", esp->esp_id)); - if(esp->msgout_len > 1) - esp_cmd(esp, eregs, ESP_CMD_SATN); + if (esp->msgout_len > 1) + esp_cmd(esp, ESP_CMD_SATN); esp_advance_phase(esp->current_SC, in_msgout); return do_work_bus; @@ -3922,10 +4059,10 @@ default: /* Happy Meal fifo is touchy... */ - if((esp->erev != fashme) && - !fcount(esp, eregs) && - !(esp->current_SC->device->sync_max_offset)) - esp_cmd(esp, eregs, ESP_CMD_FLUSH); + if ((esp->erev != fashme) && + !fcount(esp) && + !(esp->current_SC->device->sync_max_offset)) + esp_cmd(esp, ESP_CMD_FLUSH); break; }; @@ -3937,19 +4074,18 @@ /* If we sent out a synchronous negotiation message, update * our state. */ - if(esp->cur_msgout[2] == EXTENDED_MESSAGE && - esp->cur_msgout[4] == EXTENDED_SDTR) { + if (esp->cur_msgout[2] == EXTENDED_MESSAGE && + esp->cur_msgout[4] == EXTENDED_SDTR) { esp->snip = 1; /* anal retentiveness... */ } esp->prevmsgout = esp->cur_msgout[0]; esp->msgout_len = 0; esp_advance_phase(esp->current_SC, in_the_dark); - return esp_do_phase_determine(esp, eregs, dregs); + return esp_do_phase_determine(esp); } -static int esp_bus_unexpected(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_bus_unexpected(struct esp *esp) { ESPLOG(("esp%d: command in weird state %2x\n", esp->esp_id, esp->current_SC->SCp.phase)); @@ -3976,25 +4112,23 @@ }; /* This is the second tier in our dual-level SCSI state machine. */ -static int esp_work_bus(struct Sparc_ESP *esp, - struct Sparc_ESP_regs *eregs, - struct sparc_dma_registers *dregs) +static int esp_work_bus(struct esp *esp) { Scsi_Cmnd *SCptr = esp->current_SC; unsigned int phase; ESPBUS(("esp_work_bus: ")); - if(!SCptr) { + if (!SCptr) { ESPBUS(("reconnect\n")); - return esp_do_reconnect(esp, eregs, dregs); + return esp_do_reconnect(esp); } phase = SCptr->SCp.phase; if ((phase & 0xf0) == in_phases_mask) - return bus_vector[(phase & 0x0f)](esp, eregs, dregs); - else if((phase & 0xf0) == in_slct_mask) - return esp_select_complete(esp, eregs, dregs); + return bus_vector[(phase & 0x0f)](esp); + else if ((phase & 0xf0) == in_slct_mask) + return esp_select_complete(esp); else - return esp_bus_unexpected(esp, eregs, dregs); + return esp_bus_unexpected(esp); } static espfunc_t isvc_vector[] = { @@ -4006,25 +4140,22 @@ }; /* Main interrupt handler for an esp adapter. */ -static void esp_handle(struct Sparc_ESP *esp) +static void esp_handle(struct esp *esp) { - struct sparc_dma_registers *dregs; - struct Sparc_ESP_regs *eregs; Scsi_Cmnd *SCptr; int what_next = do_intr_end; - eregs = esp->eregs; - dregs = esp->dregs; SCptr = esp->current_SC; /* Check for errors. */ - esp->sreg = eregs->esp_status; + esp->sreg = sbus_readb(esp->eregs + ESP_STATUS); esp->sreg &= (~ESP_STAT_INTR); - if(esp->erev == fashme) { - esp->sreg2 = eregs->esp_status2; - esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS); + if (esp->erev == fashme) { + esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2); + esp->seqreg = (sbus_readb(esp->eregs + ESP_SSTEP) & ESP_STEP_VBITS); } - if(esp->sreg & (ESP_STAT_SPAM)) { + + if (esp->sreg & (ESP_STAT_SPAM)) { /* Gross error, could be due to one of: * * - top of fifo overwritten, could be because @@ -4047,7 +4178,7 @@ * target will be able to cleanly go away soon * so we can safely reset things. */ - if(!SCptr) { + if (!SCptr) { ESPLOG(("esp%d: No current cmd during gross error, " "resetting bus\n", esp->esp_id)); what_next = do_reset_bus; @@ -4055,7 +4186,7 @@ } } - if(dregs->cond_reg & DMA_HNDL_ERROR) { + if (sbus_readl(esp->dregs + DMA_CSR) & DMA_HNDL_ERROR) { /* A DMA gate array error. Here we must * be seeing one of two things. Either the * virtual to physical address translation @@ -4064,7 +4195,7 @@ * page. Ho hum... */ ESPLOG(("esp%d: DMA error %08x\n", esp->esp_id, - dregs->cond_reg)); + sbus_readl(esp->dregs + DMA_CSR))); /* DMA gate array itself must be reset to clear the * error condition. @@ -4075,9 +4206,9 @@ goto state_machine; } - esp->ireg = eregs->esp_intrpt; /* Unlatch intr and stat regs */ + esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT); /* Unlatch intr reg */ - if(esp->erev == fashme) { + if (esp->erev == fashme) { /* This chip is really losing. */ ESPHME(("HME[")); @@ -4086,10 +4217,10 @@ * register else garbage ends up in the FIFO * which confuses the driver utterly. */ - if(!(esp->sreg2 & ESP_STAT2_FEMPTY) || - (esp->sreg2 & ESP_STAT2_F1BYTE)) { + if (!(esp->sreg2 & ESP_STAT2_FEMPTY) || + (esp->sreg2 & ESP_STAT2_F1BYTE)) { ESPHME(("fifo_workaround]")); - hme_fifo_read(esp, eregs); + hme_fifo_read(esp); } else { ESPHME(("no_fifo_workaround]")); } @@ -4098,13 +4229,13 @@ /* No current cmd is only valid at this point when there are * commands off the bus or we are trying a reset. */ - if(!SCptr && !esp->disconnected_SC && !(esp->ireg & ESP_INTR_SR)) { + if (!SCptr && !esp->disconnected_SC && !(esp->ireg & ESP_INTR_SR)) { /* Panic is safe, since current_SC is null. */ ESPLOG(("esp%d: no command in esp_handle()\n", esp->esp_id)); panic("esp_handle: current_SC == penguin within interrupt!"); } - if(esp->ireg & (ESP_INTR_IC)) { + if (esp->ireg & (ESP_INTR_IC)) { /* Illegal command fed to ESP. Outside of obvious * software bugs that could cause this, there is * a condition with esp100 where we can confuse the @@ -4115,9 +4246,9 @@ */ ESPLOG(("esp%d: illegal command\n", esp->esp_id)); - esp_dump_state(esp, eregs, dregs); + esp_dump_state(esp); - if(SCptr) { + if (SCptr != NULL) { /* Devices with very buggy firmware can drop BSY * during a scatter list interrupt when using sync * mode transfers. We continue the transfer as @@ -4133,15 +4264,14 @@ } what_next = do_reset_bus; - } else if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) { - int phase; - - if(SCptr) { - phase = SCptr->SCp.phase; - if(phase & in_phases_mask) { - what_next = esp_work_bus(esp, eregs, dregs); - } else if(phase & in_slct_mask) { - what_next = esp_select_complete(esp, eregs, dregs); + } else if (!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) { + if (SCptr) { + unsigned int phase = SCptr->SCp.phase; + + if (phase & in_phases_mask) { + what_next = esp_work_bus(esp); + } else if (phase & in_slct_mask) { + what_next = esp_select_complete(esp); } else { ESPLOG(("esp%d: interrupt for no good reason...\n", esp->esp_id)); @@ -4152,23 +4282,23 @@ esp->esp_id)); what_next = do_reset_bus; } - } else if(esp->ireg & ESP_INTR_SR) { + } else if (esp->ireg & ESP_INTR_SR) { ESPLOG(("esp%d: SCSI bus reset interrupt\n", esp->esp_id)); what_next = do_reset_complete; - } else if(esp->ireg & (ESP_INTR_S | ESP_INTR_SATN)) { + } else if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN)) { ESPLOG(("esp%d: AIEEE we have been selected by another initiator!\n", esp->esp_id)); what_next = do_reset_bus; - } else if(esp->ireg & ESP_INTR_RSEL) { - if(!SCptr) { + } else if (esp->ireg & ESP_INTR_RSEL) { + if (SCptr == NULL) { /* This is ok. */ - what_next = esp_do_reconnect(esp, eregs, dregs); - } else if(SCptr->SCp.phase & in_slct_mask) { + what_next = esp_do_reconnect(esp); + } else if (SCptr->SCp.phase & in_slct_mask) { /* Only selection code knows how to clean * up properly. */ ESPDISC(("Reselected during selection attempt\n")); - what_next = esp_select_complete(esp, eregs, dregs); + what_next = esp_select_complete(esp); } else { ESPLOG(("esp%d: Reselected while bus is busy\n", esp->esp_id)); @@ -4178,11 +4308,11 @@ /* This is tier-one in our dual level SCSI state machine. */ state_machine: - while(what_next != do_intr_end) { + while (what_next != do_intr_end) { if (what_next >= do_phase_determine && - what_next < do_intr_end) - what_next = isvc_vector[what_next](esp, eregs, dregs); - else { + what_next < do_intr_end) { + what_next = isvc_vector[what_next](esp); + } else { /* state is completely lost ;-( */ ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n", esp->esp_id)); @@ -4191,102 +4321,29 @@ } } -#ifndef __sparc_v9__ - -#ifndef __SMP__ -static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) -{ - struct Sparc_ESP *esp; - unsigned long flags; - int again; - - /* Handle all ESP interrupts showing at this IRQ level. */ - spin_lock_irqsave(&io_request_lock, flags); -repeat: - again = 0; - for_each_esp(esp) { - if((esp->irq & 0xf) == irq) { - if(DMA_IRQ_P(esp->dregs)) { - again = 1; - - DMA_INTSOFF(esp->dregs); - - ESPIRQ(("I%d(", esp->esp_id)); - esp_handle(esp); - ESPIRQ((")")); - - DMA_INTSON(esp->dregs); - } - } - } - if(again) - goto repeat; - spin_unlock_irqrestore(&io_request_lock, flags); -} -#else -/* For SMP we only service one ESP on the list list at our IRQ level! */ +/* Service only the ESP described by dev_id. */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { - struct Sparc_ESP *esp; + struct esp *esp = dev_id; unsigned long flags; - /* Handle all ESP interrupts showing at this IRQ level. */ - spin_lock_irqsave(&io_request_lock, flags); - for_each_esp(esp) { - if(((esp)->irq & 0xf) == irq) { - if(DMA_IRQ_P(esp->dregs)) { - DMA_INTSOFF(esp->dregs); - - ESPIRQ(("I[%d:%d](", - smp_processor_id(), esp->esp_id)); - esp_handle(esp); - ESPIRQ((")")); - - DMA_INTSON(esp->dregs); - goto out; - } - } - } -out: - spin_unlock_irqrestore(&io_request_lock, flags); -} -#endif - -static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs) -{ - struct Sparc_ESP *esp = dev_id; - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - if(DMA_IRQ_P(esp->dregs)) { - DMA_INTSOFF(esp->dregs); + spin_lock_irqsave(&esp->lock, flags); + if (ESP_IRQ_P(esp->dregs)) { + ESP_INTSOFF(esp->dregs); ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id)); esp_handle(esp); ESPIRQ((")")); - DMA_INTSON(esp->dregs); + ESP_INTSON(esp->dregs); } - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irqrestore(&esp->lock, flags); } -#else /* __sparc_v9__ */ - -static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) -{ - struct Sparc_ESP *esp = dev_id; - unsigned long flags; +#ifdef MODULE +Scsi_Host_Template driver_template = SCSI_SPARC_ESP; - spin_lock_irqsave(&io_request_lock, flags); - if(DMA_IRQ_P(esp->dregs)) { - DMA_INTSOFF(esp->dregs); +#include "scsi_module.c" - ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id)); - esp_handle(esp); - ESPIRQ((")")); - - DMA_INTSON(esp->dregs); - } - spin_unlock_irqrestore(&io_request_lock, flags); -} -#endif +EXPORT_NO_SYMBOLS; +#endif /* MODULE */ diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/esp.h linux/drivers/scsi/esp.h --- v2.3.34/linux/drivers/scsi/esp.h Thu Nov 11 20:11:46 1999 +++ linux/drivers/scsi/esp.h Tue Dec 28 17:44:28 1999 @@ -1,4 +1,5 @@ -/* esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI +/* $Id: esp.h,v 1.27 1999/12/15 14:12:52 davem Exp $ + * esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI * Processor) driver under Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -23,182 +24,166 @@ /* All the ESP registers are one byte each and are accessed longwords * apart with a big-endian ordering to the bytes. */ - -struct Sparc_ESP_regs { - /* Access Description Offset */ - volatile unchar esp_tclow; /* rw Low bits of the transfer count 0x00 */ - unchar tlpad1[3]; - volatile unchar esp_tcmed; /* rw Mid bits of the transfer count 0x04 */ - unchar fdpad[3]; - volatile unchar esp_fdata; /* rw FIFO data bits 0x08 */ - unchar cbpad[3]; - volatile unchar esp_cmd; /* rw SCSI command bits 0x0c */ - unchar stpad[3]; - volatile unchar esp_status; /* ro ESP status register 0x10 */ -#define esp_busid esp_status /* wo Bus ID for select/reselect 0x10 */ - unchar irqpd[3]; - volatile unchar esp_intrpt; /* ro Kind of interrupt 0x14 */ -#define esp_timeo esp_intrpt /* wo Timeout value for select/resel 0x14 */ - unchar sspad[3]; - volatile unchar esp_sstep; /* ro Sequence step register 0x18 */ -#define esp_stp esp_sstep /* wo Transfer period per sync 0x18 */ - unchar ffpad[3]; - volatile unchar esp_fflags; /* ro Bits of current FIFO info 0x1c */ -#define esp_soff esp_fflags /* wo Sync offset 0x1c */ - unchar cf1pd[3]; - volatile unchar esp_cfg1; /* rw First configuration register 0x20 */ - unchar cfpad[3]; - volatile unchar esp_cfact; /* wo Clock conversion factor 0x24 */ -#define esp_status2 esp_cfact /* ro HME status2 register 0x24 */ - unchar ctpad[3]; - volatile unchar esp_ctest; /* wo Chip test register 0x28 */ - unchar cf2pd[3]; - volatile unchar esp_cfg2; /* rw Second configuration register 0x2c */ - unchar cf3pd[3]; - - /* The following is only found on the 53C9X series SCSI chips */ - volatile unchar esp_cfg3; /* rw Third configuration register 0x30 */ - unchar thpd[7]; - - /* The following is found on all chips except the NCR53C90 (ESP100) */ - volatile unchar esp_tchi; /* rw High bits of transfer count 0x38 */ -#define esp_uid esp_tchi /* ro Unique ID code 0x38 */ -#define fas_rlo esp_tchi /* rw HME extended counter 0x38 */ - unchar fgpad[3]; - volatile unchar esp_fgrnd; /* rw Data base for fifo 0x3c */ -#define fas_rhi esp_fgrnd /* rw HME extended counter 0x3c */ -}; + /* Access Description Offset */ +#define ESP_TCLOW 0x00UL /* rw Low bits of the transfer count 0x00 */ +#define ESP_TCMED 0x04UL /* rw Mid bits of the transfer count 0x04 */ +#define ESP_FDATA 0x08UL /* rw FIFO data bits 0x08 */ +#define ESP_CMD 0x0cUL /* rw SCSI command bits 0x0c */ +#define ESP_STATUS 0x10UL /* ro ESP status register 0x10 */ +#define ESP_BUSID ESP_STATUS /* wo Bus ID for select/reselect 0x10 */ +#define ESP_INTRPT 0x14UL /* ro Kind of interrupt 0x14 */ +#define ESP_TIMEO ESP_INTRPT /* wo Timeout value for select/resel 0x14 */ +#define ESP_SSTEP 0x18UL /* ro Sequence step register 0x18 */ +#define ESP_STP ESP_SSTEP /* wo Transfer period per sync 0x18 */ +#define ESP_FFLAGS 0x1cUL /* ro Bits of current FIFO info 0x1c */ +#define ESP_SOFF ESP_FFLAGS /* wo Sync offset 0x1c */ +#define ESP_CFG1 0x20UL /* rw First configuration register 0x20 */ +#define ESP_CFACT 0x24UL /* wo Clock conversion factor 0x24 */ +#define ESP_STATUS2 ESP_CFACT /* ro HME status2 register 0x24 */ +#define ESP_CTEST 0x28UL /* wo Chip test register 0x28 */ +#define ESP_CFG2 0x2cUL /* rw Second configuration register 0x2c */ +#define ESP_CFG3 0x30UL /* rw Third configuration register 0x30 */ +#define ESP_TCHI 0x38UL /* rw High bits of transfer count 0x38 */ +#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */ +#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */ +#define ESP_FGRND 0x3cUL /* rw Data base for fifo 0x3c */ +#define FAS_RHI ESP_FGRND /* rw HME extended counter 0x3c */ +#define ESP_REG_SIZE 0x40UL /* Various revisions of the ESP board. */ enum esp_rev { - esp100 = 0x00, /* NCR53C90 - very broken */ - esp100a = 0x01, /* NCR53C90A */ - esp236 = 0x02, - fas236 = 0x03, - fas100a = 0x04, - fast = 0x05, - fashme = 0x06, - espunknown = 0x07 + esp100 = 0x00, /* NCR53C90 - very broken */ + esp100a = 0x01, /* NCR53C90A */ + esp236 = 0x02, + fas236 = 0x03, + fas100a = 0x04, + fast = 0x05, + fashme = 0x06, + espunknown = 0x07 }; /* We get one of these for each ESP probed. */ -struct Sparc_ESP { - struct Sparc_ESP *next; /* Next ESP on probed or NULL */ - struct Sparc_ESP_regs *eregs; /* All esp registers */ - struct Linux_SBus_DMA *dma; /* Who I do transfers with. */ - struct sparc_dma_registers *dregs; /* And his registers. */ - struct Scsi_Host *ehost; /* Backpointer to SCSI Host */ - - struct linux_sbus_device *edev; /* Pointer to SBus entry */ - char prom_name[64]; /* Name of ESP device from prom */ - int prom_node; /* Prom node where ESP found */ - int esp_id; /* Unique per-ESP ID number */ - - /* ESP Configuration Registers */ - unsigned char config1; /* Copy of the 1st config register */ - unsigned char config2; /* Copy of the 2nd config register */ - unsigned char config3[16]; /* Copy of the 3rd config register */ - - /* The current command we are sending to the ESP chip. This esp_command - * ptr needs to be mapped in DVMA area so we can send commands and read - * from the ESP fifo without burning precious CPU cycles. Programmed I/O - * sucks when we have the DVMA to do it for us. The ESP is stupid and will - * only send out 6, 10, and 12 byte SCSI commands, others we need to send - * one byte at a time. esp_slowcmd being set says that we are doing one - * of the command types ESP doesn't understand, esp_scmdp keeps track of - * which byte we are sending, esp_scmdleft says how many bytes to go. - */ - volatile unchar *esp_command; /* Location of command (CPU view) */ - __u32 esp_command_dvma; /* Location of command (DVMA view) */ - unsigned char esp_clen; /* Length of this command */ - unsigned char esp_slowcmd; - unsigned char *esp_scmdp; - unsigned char esp_scmdleft; - - /* The following are used to determine the cause of an IRQ. Upon every - * IRQ entry we synchronize these with the hardware registers. - */ - unchar ireg; /* Copy of ESP interrupt register */ - unchar sreg; /* Same for ESP status register */ - unchar seqreg; /* The ESP sequence register */ - unchar sreg2; /* Copy of HME status2 register */ - - /* To save register writes to the ESP, which can be expensive, we - * keep track of the previous value that various registers had for - * the last target we connected to. If they are the same for the - * current target, we skip the register writes as they are not needed. - */ - unchar prev_soff, prev_stp, prev_cfg3, __cache_pad; - - /* We also keep a cache of the previous FAS/HME DMA CSR register value. */ - unsigned int prev_hme_dmacsr; - - /* The HME is the biggest piece of shit I have ever seen. */ - unchar hme_fifo_workaround_buffer[16 * 2]; /* 16-bit/entry fifo for wide scsi */ - unchar hme_fifo_workaround_count; - - /* For each target we keep track of save/restore data - * pointer information. This needs to be updated majorly - * when we add support for tagged queueing. -DaveM - */ - struct esp_pointers { - char *saved_ptr; - struct scatterlist *saved_buffer; - int saved_this_residual; - int saved_buffers_residual; - } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/; - - /* Clock periods, frequencies, synchronization, etc. */ - unsigned int cfreq; /* Clock frequency in HZ */ - unsigned int cfact; /* Clock conversion factor */ - unsigned int ccycle; /* One ESP clock cycle */ - unsigned int ctick; /* One ESP clock time */ - unsigned int radelay; /* FAST chip req/ack delay */ - unsigned int neg_defp; /* Default negotiation period */ - unsigned int sync_defp; /* Default sync transfer period */ - unsigned int max_period; /* longest our period can be */ - unsigned int min_period; /* shortest period we can withstand */ - /* For slow to medium speed input clock rates we shoot for 5mb/s, - * but for high input clock rates we try to do 10mb/s although I - * don't think a transfer can even run that fast with an ESP even - * with DMA2 scatter gather pipelining. - */ +struct esp { + spinlock_t lock; + unsigned long eregs; /* ESP controller registers */ + unsigned long dregs; /* DMA controller registers */ + struct sbus_dma *dma; /* DMA controller sw state */ + struct Scsi_Host *ehost; /* Backpointer to SCSI Host */ + struct sbus_dev *sdev; /* Pointer to SBus entry */ + + /* ESP Configuration Registers */ + u8 config1; /* Copy of the 1st config register */ + u8 config2; /* Copy of the 2nd config register */ + u8 config3[16]; /* Copy of the 3rd config register */ + + /* The current command we are sending to the ESP chip. This esp_command + * ptr needs to be mapped in DVMA area so we can send commands and read + * from the ESP fifo without burning precious CPU cycles. Programmed I/O + * sucks when we have the DVMA to do it for us. The ESP is stupid and will + * only send out 6, 10, and 12 byte SCSI commands, others we need to send + * one byte at a time. esp_slowcmd being set says that we are doing one + * of the command types ESP doesn't understand, esp_scmdp keeps track of + * which byte we are sending, esp_scmdleft says how many bytes to go. + */ + volatile u8 *esp_command; /* Location of command (CPU view) */ + __u32 esp_command_dvma;/* Location of command (DVMA view) */ + unsigned char esp_clen; /* Length of this command */ + unsigned char esp_slowcmd; + unsigned char *esp_scmdp; + unsigned char esp_scmdleft; + + /* The following are used to determine the cause of an IRQ. Upon every + * IRQ entry we synchronize these with the hardware registers. + */ + u8 ireg; /* Copy of ESP interrupt register */ + u8 sreg; /* Copy of ESP status register */ + u8 seqreg; /* Copy of ESP sequence step register */ + u8 sreg2; /* Copy of HME status2 register */ + + /* To save register writes to the ESP, which can be expensive, we + * keep track of the previous value that various registers had for + * the last target we connected to. If they are the same for the + * current target, we skip the register writes as they are not needed. + */ + u8 prev_soff, prev_stp; + u8 prev_cfg3, __cache_pad; + + /* We also keep a cache of the previous FAS/HME DMA CSR register value. */ + u32 prev_hme_dmacsr; + + /* The HME is the biggest piece of shit I have ever seen. */ + u8 hme_fifo_workaround_buffer[16 * 2]; + u8 hme_fifo_workaround_count; + + /* For each target we keep track of save/restore data + * pointer information. This needs to be updated majorly + * when we add support for tagged queueing. -DaveM + */ + struct esp_pointers { + char *saved_ptr; + struct scatterlist *saved_buffer; + int saved_this_residual; + int saved_buffers_residual; + } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/; + + /* Clock periods, frequencies, synchronization, etc. */ + unsigned int cfreq; /* Clock frequency in HZ */ + unsigned int cfact; /* Clock conversion factor */ + unsigned int raw_cfact; /* Raw copy from probing */ + unsigned int ccycle; /* One ESP clock cycle */ + unsigned int ctick; /* One ESP clock time */ + unsigned int radelay; /* FAST chip req/ack delay */ + unsigned int neg_defp; /* Default negotiation period */ + unsigned int sync_defp; /* Default sync transfer period */ + unsigned int max_period; /* longest our period can be */ + unsigned int min_period; /* shortest period we can withstand */ + + struct esp *next; /* Next ESP we probed or NULL */ + char prom_name[64]; /* Name of ESP device from prom */ + int prom_node; /* Prom node where ESP found */ + int esp_id; /* Unique per-ESP ID number */ + + /* For slow to medium speed input clock rates we shoot for 5mb/s, + * but for high input clock rates we try to do 10mb/s although I + * don't think a transfer can even run that fast with an ESP even + * with DMA2 scatter gather pipelining. + */ #define SYNC_DEFP_SLOW 0x32 /* 5mb/s */ #define SYNC_DEFP_FAST 0x19 /* 10mb/s */ - unsigned int snip; /* Sync. negotiation in progress */ - unsigned int wnip; /* WIDE negotiation in progress */ - unsigned int targets_present; /* targets spoken to before */ - - int current_transfer_size; /* Set at beginning of data dma */ - - unchar espcmdlog[32]; /* Log of current esp cmds sent. */ - unchar espcmdent; /* Current entry in esp cmd log. */ - - /* Misc. info about this ESP */ - enum esp_rev erev; /* ESP revision */ - int irq; /* SBus IRQ for this ESP */ - int scsi_id; /* Who am I as initiator? */ - int scsi_id_mask; /* Bitmask of 'me'. */ - int diff; /* Differential SCSI bus? */ - int bursts; /* Burst sizes our DVMA supports */ - - /* Our command queues, only one cmd lives in the current_SC queue. */ - Scsi_Cmnd *issue_SC; /* Commands to be issued */ - Scsi_Cmnd *current_SC; /* Who is currently working the bus */ - Scsi_Cmnd *disconnected_SC; /* Commands disconnected from the bus */ - - /* Message goo */ - unchar cur_msgout[16]; - unchar cur_msgin[16]; - unchar prevmsgout, prevmsgin; - unchar msgout_len, msgin_len; - unchar msgout_ctr, msgin_ctr; - - /* States that we cannot keep in the per cmd structure because they - * cannot be assosciated with any specific command. - */ - unchar resetting_bus; + unsigned int snip; /* Sync. negotiation in progress */ + unsigned int wnip; /* WIDE negotiation in progress */ + unsigned int targets_present;/* targets spoken to before */ + + int current_transfer_size; /* Set at beginning of data dma */ + + u8 espcmdlog[32]; /* Log of current esp cmds sent. */ + u8 espcmdent; /* Current entry in esp cmd log. */ + + /* Misc. info about this ESP */ + enum esp_rev erev; /* ESP revision */ + int irq; /* SBus IRQ for this ESP */ + int scsi_id; /* Who am I as initiator? */ + int scsi_id_mask; /* Bitmask of 'me'. */ + int diff; /* Differential SCSI bus? */ + int bursts; /* Burst sizes our DVMA supports */ + + /* Our command queues, only one cmd lives in the current_SC queue. */ + Scsi_Cmnd *issue_SC; /* Commands to be issued */ + Scsi_Cmnd *current_SC; /* Who is currently working the bus */ + Scsi_Cmnd *disconnected_SC;/* Commands disconnected from the bus */ + + /* Message goo */ + u8 cur_msgout[16]; + u8 cur_msgin[16]; + u8 prevmsgout, prevmsgin; + u8 msgout_len, msgin_len; + u8 msgout_ctr, msgin_ctr; + + /* States that we cannot keep in the per cmd structure because they + * cannot be assosciated with any specific command. + */ + u8 resetting_bus; }; /* Bitfield meanings for the above registers. */ @@ -428,7 +413,7 @@ this_id: 7, \ sg_tablesize: SG_ALL, \ cmd_per_lun: 1, \ - use_clustering: DISABLE_CLUSTERING, \ + use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0 \ } diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c --- v2.3.34/linux/drivers/scsi/fcal.c Thu Nov 11 20:11:46 1999 +++ linux/drivers/scsi/fcal.c Mon Dec 20 22:06:42 1999 @@ -218,7 +218,7 @@ fc = fcal->fc; #ifdef __sparc__ - SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s\n", fc->name); + SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node); #else SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name); #endif diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.3.34/linux/drivers/scsi/fdomain.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/scsi/fdomain.c Tue Dec 21 10:17:32 1999 @@ -280,6 +280,7 @@ #undef MODULE #endif +#include #include #include #include @@ -427,8 +428,8 @@ parameters. For example: insmod fdomain fdomain=0x140,11 */ -static int fdomain[]={ 0, 0, 0 }; -MODULE_PARM(fdomain, "2-3i"); +static char * fdomain = NULL; +MODULE_PARM(fdomain, "s"); #endif static unsigned long addresses[] = { @@ -563,21 +564,30 @@ printk( "\n" ); } -void fdomain_setup( char *str, int *ints ) +static int __init fdomain_setup( char *str ) { - if (setup_called++ || ints[0] < 2 || ints[0] > 3) { - printk( "scsi: " - " Usage: fdomain=,[,]\n" ); - printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - } + int ints[4]; + + (void)get_options(str, ARRAY_SIZE(ints), ints); - port_base = ints[0] >= 1 ? ints[1] : 0; - interrupt_level = ints[0] >= 2 ? ints[2] : 0; - this_id = ints[0] >= 3 ? ints[3] : 0; + if (setup_called++ || ints[0] < 2 || ints[0] > 3) { + printk( "scsi: " + " Usage: fdomain=,[,]\n" ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); + return 0; + } + + port_base = ints[0] >= 1 ? ints[1] : 0; + interrupt_level = ints[0] >= 2 ? ints[2] : 0; + this_id = ints[0] >= 3 ? ints[3] : 0; - bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ + bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ + ++setup_called; + return 1; } +__setup("fdomain=", fdomain_setup); + static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */ { @@ -694,6 +704,7 @@ printk( "scsi: fdomain_isa_detect:" ); #endif + for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { #if DEBUG_DETECT printk( " %lx(%lx),", addresses[i], bios_base ); @@ -880,13 +891,8 @@ tpnt->proc_name = "fdomain"; #ifdef MODULE - if (fdomain[0] || fdomain[1] || fdomain[2]) { - port_base = fdomain[0]; - interrupt_level = fdomain[1]; - this_id = fdomain[2]; - bios_major = bios_minor = -1; - ++setup_called; - } + if (fdomain) + fdomain_setup(fdomain); #endif if (setup_called) { diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- v2.3.34/linux/drivers/scsi/hosts.h Tue Dec 14 01:27:24 1999 +++ linux/drivers/scsi/hosts.h Tue Dec 28 17:44:21 1999 @@ -437,6 +437,8 @@ struct module * module; /* Used for loadable modules */ unsigned char scsi_type; unsigned char major; + unsigned char min_major; /* Minimum major in range. */ + unsigned char max_major; /* Maximum major in range. */ unsigned char nr_dev; /* Number currently attached */ unsigned char dev_noticed; /* Number of devices detected. */ unsigned char dev_max; /* Current size of arrays */ @@ -447,7 +449,8 @@ void (*finish)(void); /* Perform initialization after attachment */ int (*attach)(Scsi_Device *); /* Attach devices to arrays */ void (*detach)(Scsi_Device *); - int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code. */ + int (*init_command)(Scsi_Cmnd *); /* Used by new queueing code. + Selects command for blkdevs */ }; extern struct Scsi_Device_Template sd_template; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c --- v2.3.34/linux/drivers/scsi/pluto.c Thu Nov 11 20:11:48 1999 +++ linux/drivers/scsi/pluto.c Mon Dec 20 22:06:42 1999 @@ -287,12 +287,16 @@ const char *pluto_info(struct Scsi_Host *host) { - static char buf[80]; + static char buf[128], *p; struct pluto *pluto = (struct pluto *) host->hostdata; sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id, pluto->fc->name); +#ifdef __sparc__ + p = strchr(buf, 0); + sprintf(p, " PROM node %x", pluto->fc->dev->prom_node); +#endif return buf; } diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.3.34/linux/drivers/scsi/qlogicisp.c Wed Dec 15 10:43:16 1999 +++ linux/drivers/scsi/qlogicisp.c Mon Dec 20 22:06:42 1999 @@ -1241,8 +1241,6 @@ } #ifdef __sparc__ - if (mem_base) - mem_base = __pa(mem_base); command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY| PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR); pci_write_config_word(pdev, PCI_COMMAND, command); diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c --- v2.3.34/linux/drivers/scsi/qlogicpti.c Thu Nov 11 20:11:48 1999 +++ linux/drivers/scsi/qlogicpti.c Mon Dec 20 22:06:42 1999 @@ -43,13 +43,14 @@ #include #define MAX_TARGETS 16 -#define MAX_LUNS 8 +#define MAX_LUNS 8 /* 32 for 1.31 F/W */ -#define DEFAULT_LOOP_COUNT 1000000 +#define DEFAULT_LOOP_COUNT 10000 #include "qlogicpti_asm.c" -static struct qlogicpti *qptichain; +static struct qlogicpti *qptichain = NULL; +static spinlock_t qptichain_lock = SPIN_LOCK_UNLOCKED; static int qptis_running = 0; #define PACKB(a, b) (((a)<<4)|(b)) @@ -129,144 +130,240 @@ /* queue length's _must_ be power of two: */ #define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql)) #define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \ - QLOGICISP_REQ_QUEUE_LEN) + QLOGICPTI_REQ_QUEUE_LEN) #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN) -static inline void qlogicpti_enable_irqs(struct qlogicpti_regs *qregs) +static inline void qlogicpti_enable_irqs(struct qlogicpti *qpti) { - qregs->sbus_ctrl = SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB; + sbus_writew(SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB, + qpti->qregs + SBUS_CTRL); } - -static inline void qlogicpti_disable_irqs(struct qlogicpti_regs *qregs) +static inline void qlogicpti_disable_irqs(struct qlogicpti *qpti) { - qregs->sbus_ctrl = 0; + sbus_writew(0, qpti->qregs + SBUS_CTRL); } -static inline void set_sbus_cfg1(struct qlogicpti_regs *qregs, unsigned char bursts) +static inline void set_sbus_cfg1(struct qlogicpti *qpti) { - if(bursts & DMA_BURST32) { - qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B32); - } else if(bursts & DMA_BURST16) { - qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B16); - } else if(bursts & DMA_BURST8) { - qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B8); + u16 val; + u8 bursts = qpti->bursts; + +#if 0 /* It appears that at least PTI cards do not support + * 64-byte bursts and that setting the B64 bit actually + * is a nop and the chip ends up using the smallest burst + * size. -DaveM + */ + if (sbus_can_burst64(qpti->sdev) && (bursts & DMA_BURST64)) { + val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); + } else +#endif + if (bursts & DMA_BURST32) { + val = (SBUS_CFG1_BENAB | SBUS_CFG1_B32); + } else if (bursts & DMA_BURST16) { + val = (SBUS_CFG1_BENAB | SBUS_CFG1_B16); + } else if (bursts & DMA_BURST8) { + val = (SBUS_CFG1_BENAB | SBUS_CFG1_B8); } else { - qregs->sbus_cfg1 = 0; /* No sbus bursts for you... */ + val = 0; /* No sbus bursts for you... */ } + sbus_writew(val, qpti->qregs + SBUS_CFG1); } static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int force) { - struct qlogicpti_regs *qregs = qpti->qregs; int loop_count; + u16 tmp; - if(mbox_param[param[0]] == 0) + if (mbox_param[param[0]] == 0) return 1; + /* Set SBUS semaphore. */ + tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE); + tmp |= SBUS_SEMAPHORE_LCK; + sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE); + + /* Wait for host IRQ bit to clear. */ loop_count = DEFAULT_LOOP_COUNT; - while(--loop_count && (qregs->hcctrl & HCCTRL_HIRQ)) + while (--loop_count && (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_HIRQ)) barrier(); - if(!loop_count) + if (!loop_count) printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #1\n"); - switch(mbox_param[param[0]] >> 4) { - case 6: qregs->mbox5 = param[5]; - case 5: qregs->mbox4 = param[4]; - case 4: qregs->mbox3 = param[3]; - case 3: qregs->mbox2 = param[2]; - case 2: qregs->mbox1 = param[1]; - case 1: qregs->mbox0 = param[0]; - } - - qregs->hcctrl |= HCCTRL_SHIRQ; + /* Write mailbox command registers. */ + switch (mbox_param[param[0]] >> 4) { + case 6: sbus_writew(param[5], qpti->qregs + MBOX5); + case 5: sbus_writew(param[4], qpti->qregs + MBOX4); + case 4: sbus_writew(param[3], qpti->qregs + MBOX3); + case 3: sbus_writew(param[2], qpti->qregs + MBOX2); + case 2: sbus_writew(param[1], qpti->qregs + MBOX1); + case 1: sbus_writew(param[0], qpti->qregs + MBOX0); + } + + /* Clear RISC interrupt. */ + tmp = sbus_readw(qpti->qregs + HCCTRL); + tmp |= HCCTRL_CRIRQ; + sbus_writew(tmp, qpti->qregs + HCCTRL); + + /* Clear SBUS semaphore. */ + sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); + + /* Set HOST interrupt. */ + tmp = sbus_readw(qpti->qregs + HCCTRL); + tmp |= HCCTRL_SHIRQ; + sbus_writew(tmp, qpti->qregs + HCCTRL); + /* Wait for HOST interrupt clears. */ loop_count = DEFAULT_LOOP_COUNT; - while(--loop_count && !(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK)) + while (--loop_count && + (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_CRIRQ)) udelay(20); - if(!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #2\n"); + if (!loop_count) + printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #2\n", + param[0]); + /* Wait for SBUS semaphore to get set. */ loop_count = DEFAULT_LOOP_COUNT; - while(--loop_count && (qregs->mbox0 == 0x04)) + while (--loop_count && + !(sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK)) { udelay(20); - if(!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #3\n"); - if(force) { - qregs->hcctrl = HCCTRL_CRIRQ; - } else { - if((qregs->mbox5 - qpti->res_out_ptr) == 0) - qregs->hcctrl = HCCTRL_CRIRQ; + /* Workaround for some buggy chips. */ + if (sbus_readw(qpti->qregs + MBOX0) & 0x4000) + break; } + if (!loop_count) + printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #3\n", + param[0]); - switch(mbox_param[param[0]] & 0xf) { - case 6: param[5] = qregs->mbox5; - case 5: param[4] = qregs->mbox4; - case 4: param[3] = qregs->mbox3; - case 3: param[2] = qregs->mbox2; - case 2: param[1] = qregs->mbox1; - case 1: param[0] = qregs->mbox0; - } + /* Wait for MBOX busy condition to go away. */ + loop_count = DEFAULT_LOOP_COUNT; + while (--loop_count && (sbus_readw(qpti->qregs + MBOX0) == 0x04)) + udelay(20); + if (!loop_count) + printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #4\n", + param[0]); + + /* Read back output parameters. */ + switch (mbox_param[param[0]] & 0xf) { + case 6: param[5] = sbus_readw(qpti->qregs + MBOX5); + case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); + case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); + case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); + case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); + case 1: param[0] = sbus_readw(qpti->qregs + MBOX0); + } + + /* Clear RISC interrupt. */ + tmp = sbus_readw(qpti->qregs + HCCTRL); + tmp |= HCCTRL_CRIRQ; + sbus_writew(tmp, qpti->qregs + HCCTRL); + + /* Release SBUS semaphore. */ + tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE); + tmp &= ~(SBUS_SEMAPHORE_LCK); + sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE); - qregs->sbus_semaphore &= ~(SBUS_SEMAPHORE_LCK); + /* We're done. */ return 0; } +static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti) +{ + int i; + + qpti->host_param.initiator_scsi_id = qpti->scsi_id; + qpti->host_param.bus_reset_delay = 3; + qpti->host_param.retry_count = 0; + qpti->host_param.retry_delay = 5; + qpti->host_param.async_data_setup_time = 3; + qpti->host_param.req_ack_active_negation = 1; + qpti->host_param.data_line_active_negation = 1; + qpti->host_param.data_dma_burst_enable = 1; + qpti->host_param.command_dma_burst_enable = 1; + qpti->host_param.tag_aging = 8; + qpti->host_param.selection_timeout = 250; + qpti->host_param.max_queue_depth = 256; + + for(i = 0; i < MAX_TARGETS; i++) { + /* + * disconnect, parity, arq, reneg on reset, and, oddly enough + * tags...the midlayer's notion of tagged support has to match + * our device settings, and since we base whether we enable a + * tag on a per-cmnd basis upon what the midlayer sez, we + * actually enable the capability here. + */ + qpti->dev_param[i].device_flags = 0xcd; + qpti->dev_param[i].execution_throttle = 16; + if (qpti->ultra) { + qpti->dev_param[i].synchronous_period = 12; + qpti->dev_param[i].synchronous_offset = 8; + } else { + qpti->dev_param[i].synchronous_period = 25; + qpti->dev_param[i].synchronous_offset = 12; + } + qpti->dev_param[i].device_enable = 1; + } + /* this is very important to set! */ + qpti->sbits = 1 << qpti->scsi_id; +} + static int qlogicpti_reset_hardware(struct Scsi_Host *host) { struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - struct qlogicpti_regs *qregs = qpti->qregs; u_short param[6]; unsigned short risc_code_addr; int loop_count, i; unsigned long flags; - if(qpti->is_pti != 0) - risc_code_addr = pti_risc_code_addr01; - else - risc_code_addr = sbus_risc_code_addr01; + risc_code_addr = 0x1000; /* all load addresses are at 0x1000 */ save_flags(flags); cli(); - qregs->hcctrl = HCCTRL_PAUSE; + sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); /* Only reset the scsi bus if it is not free. */ - if(qregs->cpu_pctrl & CPU_PCTRL_BSY) { - qregs->cpu_oride = CPU_ORIDE_RMOD; - qregs->cpu_cmd = CPU_CMD_BRESET; + if (sbus_readw(qpti->qregs + CPU_PCTRL) & CPU_PCTRL_BSY) { + sbus_writew(CPU_ORIDE_RMOD, qpti->qregs + CPU_ORIDE); + sbus_writew(CPU_CMD_BRESET, qpti->qregs + CPU_CMD); udelay(400); } - qregs->sbus_ctrl = SBUS_CTRL_RESET; - qregs->cmd_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ); - qregs->data_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ); + sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); + sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); + sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL); loop_count = DEFAULT_LOOP_COUNT; - while(--loop_count && ((qregs->mbox0 & 0xff) == 0x04)) + while (--loop_count && ((sbus_readw(qpti->qregs + MBOX0) & 0xff) == 0x04)) udelay(20); - if(!loop_count) + if (!loop_count) printk(KERN_EMERG "qlogicpti: reset_hardware loop timeout\n"); - qregs->hcctrl = HCCTRL_PAUSE; - set_sbus_cfg1(qregs, qpti->bursts); - qlogicpti_enable_irqs(qregs); + sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); + set_sbus_cfg1(qpti); + qlogicpti_enable_irqs(qpti); - if(qregs->risc_psr & RISC_PSR_ULTRA) { + if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) { qpti->ultra = 1; - qregs->risc_mtreg = (RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA); + sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA), + qpti->qregs + RISC_MTREG); } else { qpti->ultra = 0; - qregs->risc_mtreg = (RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT); + sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT), + qpti->qregs + RISC_MTREG); } + /* reset adapter and per-device default values. */ + /* do it after finding out whether we're ultra mode capable */ + qlogicpti_set_hostdev_defaults(qpti); + /* Release the RISC processor. */ - qregs->hcctrl = HCCTRL_REL; + sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* Get RISC to start executing the firmware code. */ param[0] = MBOX_EXEC_FIRMWARE; param[1] = risc_code_addr; - if(qlogicpti_mbox_command(qpti, param, 1)) { + if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n", qpti->qpti_id); restore_flags(flags); @@ -276,7 +373,7 @@ /* Set initiator scsi ID. */ param[0] = MBOX_SET_INIT_SCSI_ID; param[1] = qpti->host_param.initiator_scsi_id; - if(qlogicpti_mbox_command(qpti, param, 1) || + if (qlogicpti_mbox_command(qpti, param, 1) || (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: Cannot set initiator SCSI ID.\n", qpti->qpti_id); @@ -292,7 +389,7 @@ param[2] = (u_short) (qpti->res_dvma >> 16); param[3] = (u_short) (qpti->res_dvma & 0xffff); param[4] = param[5] = 0; - if(qlogicpti_mbox_command(qpti, param, 1)) { + if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot init response queue.\n", qpti->qpti_id); restore_flags(flags); @@ -300,11 +397,11 @@ } param[0] = MBOX_INIT_REQ_QUEUE; - param[1] = QLOGICISP_REQ_QUEUE_LEN + 1; + param[1] = QLOGICPTI_REQ_QUEUE_LEN + 1; param[2] = (u_short) (qpti->req_dvma >> 16); param[3] = (u_short) (qpti->req_dvma & 0xffff); param[4] = param[5] = 0; - if(qlogicpti_mbox_command(qpti, param, 1)) { + if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot init request queue.\n", qpti->qpti_id); restore_flags(flags); @@ -320,7 +417,7 @@ param[1] = qpti->host_param.tag_aging; qlogicpti_mbox_command(qpti, param, 0); - for(i = 0; i < MAX_TARGETS; i++) { + for (i = 0; i < MAX_TARGETS; i++) { param[0] = MBOX_GET_DEV_QUEUE_PARAMS; param[1] = (i << 8); qlogicpti_mbox_command(qpti, param, 0); @@ -333,15 +430,26 @@ param[1] = qpti->host_param.selection_timeout; qlogicpti_mbox_command(qpti, param, 0); - for(i = 0; i < MAX_TARGETS; i++) { + for (i = 0; i < MAX_TARGETS; i++) { param[0] = MBOX_SET_TARGET_PARAMS; param[1] = (i << 8); param[2] = (qpti->dev_param[i].device_flags << 8); - param[3] = (qpti->dev_param[i].synchronous_offset << 8) | - qpti->dev_param[i].synchronous_period; + /* + * Since we're now loading 1.31 f/w, force narrow/async. + */ + param[2] |= 0xc0; + param[3] = 0; /* no offset, we do not have sync mode yet */ qlogicpti_mbox_command(qpti, param, 0); } + /* + * Always (sigh) do an initial bus reset (kicks f/w). + */ + param[0] = MBOX_BUS_RESET; + param[1] = qpti->host_param.bus_reset_delay; + qlogicpti_mbox_command(qpti, param, 0); + qpti->send_marker = 1; + restore_flags(flags); return 0; } @@ -350,130 +458,107 @@ static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) { - struct qlogicpti_regs *qregs = qpti->qregs; unsigned short csum = 0; unsigned short param[6]; unsigned short *risc_code, risc_code_addr, risc_code_length; unsigned long flags; -#if !defined(MODULE) && !defined(__sparc_v9__) - unsigned long dvma_addr; -#endif int i, timeout; - if(qpti->is_pti != 0) { - risc_code = &pti_risc_code01[0]; - risc_code_addr = pti_risc_code_addr01; - risc_code_length = pti_risc_code_length01; - } else { - risc_code = &sbus_risc_code01[0]; - risc_code_addr = sbus_risc_code_addr01; - risc_code_length = sbus_risc_code_length01; - } + risc_code = &sbus_risc_code01[0]; + risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */ + risc_code_length = sbus_risc_code_length01; save_flags(flags); cli(); /* Verify the checksum twice, one before loading it, and once * afterwards via the mailbox commands. */ - for(i = 0; i < risc_code_length; i++) + for (i = 0; i < risc_code_length; i++) csum += risc_code[i]; - if(csum) { + if (csum) { + restore_flags(flags); printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!", qpti->qpti_id); return 1; } - qregs->sbus_ctrl = SBUS_CTRL_RESET; - qregs->cmd_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ); - qregs->data_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ); + sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); + sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); + sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL); timeout = PTI_RESET_LIMIT; - while(--timeout && (qregs->sbus_ctrl & SBUS_CTRL_RESET)) + while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET)) udelay(20); - if(!timeout) { + if (!timeout) { + restore_flags(flags); printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id); return 1; } - qregs->hcctrl = HCCTRL_RESET; + sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL); mdelay(1); - qregs->sbus_ctrl = (SBUS_CTRL_GENAB | SBUS_CTRL_ERIRQ); - set_sbus_cfg1(qregs, qpti->bursts); - qregs->sbus_semaphore = 0; + sbus_writew((SBUS_CTRL_GENAB | SBUS_CTRL_ERIRQ), qpti->qregs + SBUS_CTRL); + set_sbus_cfg1(qpti); + sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); - if(qregs->risc_psr & RISC_PSR_ULTRA) { + if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) { qpti->ultra = 1; - qregs->risc_mtreg = (RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA); + sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA), + qpti->qregs + RISC_MTREG); } else { qpti->ultra = 0; - qregs->risc_mtreg = (RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT); + sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT), + qpti->qregs + RISC_MTREG); } - qregs->hcctrl = HCCTRL_REL; + sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* Pin lines are only stable while RISC is paused. */ - qregs->hcctrl = HCCTRL_PAUSE; - if(qregs->cpu_pdiff & CPU_PDIFF_MODE) + sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); + if (sbus_readw(qpti->qregs + CPU_PDIFF) & CPU_PDIFF_MODE) qpti->differential = 1; else qpti->differential = 0; - qregs->hcctrl = HCCTRL_REL; + sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); + + /* This shouldn't be necessary- we've reset things so we should be + running from the ROM now.. */ param[0] = MBOX_STOP_FIRMWARE; param[1] = param[2] = param[3] = param[4] = param[5] = 0; - if(qlogicpti_mbox_command(qpti, param, 1)) { + if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n", qpti->qpti_id); restore_flags(flags); return 1; } - /* Load the firmware. */ -#if !defined(MODULE) && !defined(__sparc_v9__) - if (sparc_cpu_model != sun4d) { - dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code[0], - (sizeof(u_short) * risc_code_length)); - param[0] = MBOX_LOAD_RAM; - param[1] = risc_code_addr; - param[2] = (dvma_addr >> 16); - param[3] = (dvma_addr & 0xffff); - param[4] = (sizeof(u_short) * risc_code_length); - if(qlogicpti_mbox_command(qpti, param, 1) || - (param[0] != MBOX_COMMAND_COMPLETE)) { - printk(KERN_EMERG "qlogicpti%d: Firmware dload failed, I'm bolixed!\n", + /* Load it up.. */ + for (i = 0; i < risc_code_length; i++) { + param[0] = MBOX_WRITE_RAM_WORD; + param[1] = risc_code_addr + i; + param[2] = risc_code[i]; + if (qlogicpti_mbox_command(qpti, param, 1) || + param[0] != MBOX_COMMAND_COMPLETE) { + printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", qpti->qpti_id); restore_flags(flags); return 1; } - mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length)); - } else -#endif - /* We need to do it this slow way always on Ultra, SS[12]000. */ - for(i = 0; i < risc_code_length; i++) { - param[0] = MBOX_WRITE_RAM_WORD; - param[1] = risc_code_addr + i; - param[2] = risc_code[i]; - if(qlogicpti_mbox_command(qpti, param, 1) || - param[0] != MBOX_COMMAND_COMPLETE) { - printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", - qpti->qpti_id); - restore_flags(flags); - return 1; - } - } + } /* Reset the ISP again. */ - qregs->hcctrl = HCCTRL_RESET; + sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL); mdelay(1); - qlogicpti_enable_irqs(qregs); - qregs->sbus_semaphore = 0; - qregs->hcctrl = HCCTRL_REL; + qlogicpti_enable_irqs(qpti); + sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); + sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* Ask ISP to verify the checksum of the new code. */ param[0] = MBOX_VERIFY_CHECKSUM; param[1] = risc_code_addr; - if(qlogicpti_mbox_command(qpti, param, 1) || - (param[0] != MBOX_COMMAND_COMPLETE)) { + if (qlogicpti_mbox_command(qpti, param, 1) || + (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n", qpti->qpti_id); restore_flags(flags); @@ -486,8 +571,8 @@ qlogicpti_mbox_command(qpti, param, 1); param[0] = MBOX_ABOUT_FIRMWARE; - if(qlogicpti_mbox_command(qpti, param, 1) || - (param[0] != MBOX_COMMAND_COMPLETE)) { + if (qlogicpti_mbox_command(qpti, param, 1) || + (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n", qpti->qpti_id); restore_flags(flags); @@ -497,8 +582,20 @@ /* Snag the major and minor revisions from the result. */ qpti->fware_majrev = param[1]; qpti->fware_minrev = param[2]; + qpti->fware_micrev = param[3]; + + /* Set the clock rate */ + param[0] = MBOX_SET_CLOCK_RATE; + param[1] = qpti->clock; + if (qlogicpti_mbox_command(qpti, param, 1) || + (param[0] != MBOX_COMMAND_COMPLETE)) { + printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n", + qpti->qpti_id); + restore_flags(flags); + return 1; + } - if(qpti->is_pti != 0) { + if (qpti->is_pti != 0) { /* Load scsi initiator ID and interrupt level into sbus static ram. */ param[0] = MBOX_WRITE_RAM_WORD; param[1] = 0xff80; @@ -517,25 +614,25 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti) { - int curstat = *qpti->sreg; + int curstat = sbus_readb(qpti->sreg); curstat &= 0xf0; - if(!(curstat & SREG_FUSE) && (qpti->swsreg & SREG_FUSE)) + if (!(curstat & SREG_FUSE) && (qpti->swsreg & SREG_FUSE)) printk("qlogicpti%d: Fuse returned to normal state.\n", qpti->qpti_id); - if(!(curstat & SREG_TPOWER) && (qpti->swsreg & SREG_TPOWER)) + if (!(curstat & SREG_TPOWER) && (qpti->swsreg & SREG_TPOWER)) printk("qlogicpti%d: termpwr back to normal state.\n", qpti->qpti_id); - if(curstat != qpti->swsreg) { + if (curstat != qpti->swsreg) { int error = 0; - if(curstat & SREG_FUSE) { + if (curstat & SREG_FUSE) { error++; printk("qlogicpti%d: Fuse is open!\n", qpti->qpti_id); } - if(curstat & SREG_TPOWER) { + if (curstat & SREG_TPOWER) { error++; printk("qlogicpti%d: termpwr failure\n", qpti->qpti_id); } - if(qpti->differential && - (curstat & SREG_DSENSE) != SREG_DSENSE) { + if (qpti->differential && + (curstat & SREG_DSENSE) != SREG_DSENSE) { error++; printk("qlogicpti%d: You have a single ended device on a " "differential bus! Please fix!\n", qpti->qpti_id); @@ -546,70 +643,191 @@ return 0; } -static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti) +static void qpti_intr(int irq, void *dev_id, struct pt_regs *regs); + +static void __init qpti_chain_add(struct qlogicpti *qpti) { - int i; + spin_lock_irq(&qptichain_lock); + if (qptichain != NULL) { + struct qlogicpti *qlink = qptichain; - qpti->host_param.initiator_scsi_id = qpti->scsi_id; - qpti->host_param.bus_reset_delay = 3; - qpti->host_param.retry_count = 0; - qpti->host_param.retry_delay = 5; - qpti->host_param.async_data_setup_time = 3; - qpti->host_param.req_ack_active_negation = 1; - qpti->host_param.data_line_active_negation = 1; - qpti->host_param.data_dma_burst_enable = 1; - qpti->host_param.command_dma_burst_enable = 1; - qpti->host_param.tag_aging = 8; - qpti->host_param.selection_timeout = 250; - qpti->host_param.max_queue_depth = 256; + while(qlink->next) + qlink = qlink->next; + qlink->next = qpti; + } else { + qptichain = qpti; + } + qpti->next = NULL; + spin_unlock_irq(&qptichain_lock); +} - for(i = 0; i < MAX_TARGETS; i++) { - qpti->dev_param[i].device_flags = 0xf9; - qpti->dev_param[i].execution_throttle = 16; - qpti->dev_param[i].synchronous_period = 16; - qpti->dev_param[i].synchronous_offset = 12; - qpti->dev_param[i].device_enable = 1; +static void __init qpti_chain_del(struct qlogicpti *qpti) +{ + spin_lock_irq(&qptichain_lock); + if (qptichain == qpti) { + qptichain = qpti->next; + } else { + struct qlogicpti *qlink = qptichain; + while(qlink->next != qpti) + qlink = qlink->next; + qlink->next = qpti->next; + } + qpti->next = NULL; + spin_unlock_irq(&qptichain_lock); +} + +static int __init qpti_map_regs(struct qlogicpti *qpti) +{ + struct sbus_dev *sdev = qpti->sdev; + + qpti->qregs = sbus_ioremap(&sdev->resource[0], 0, + sdev->reg_addrs[0].reg_size, + "PTI Qlogic/ISP"); + if (!qpti->qregs) { + printk("PTI: Qlogic/ISP registers are unmappable\n"); + return -1; + } + if (qpti->is_pti) { + qpti->sreg = sbus_ioremap(&sdev->resource[0], (16 * 4096), + sizeof(unsigned char), + "PTI Qlogic/ISP statreg"); + if (!qpti->sreg) { + printk("PTI: Qlogic/ISP status register is unmappable\n"); + return -1; + } } + return 0; } -static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs); -#ifndef __sparc_v9__ -static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs); -#endif +static int __init qpti_register_irq(struct qlogicpti *qpti) +{ + struct sbus_dev *sdev = qpti->sdev; + + qpti->qhost->irq = qpti->irq = sdev->irqs[0]; + + /* We used to try various overly-clever things to + * reduce the interrupt processing overhead on + * sun4c/sun4m when multiple PTI's shared the + * same IRQ. It was too complex and messy to + * sanely maintain. + */ + if (request_irq(qpti->irq, qpti_intr, + SA_SHIRQ, "Qlogic/PTI", qpti)) + goto fail; + + printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->irq)); + + return 0; + +fail: + printk("qpti%d: Cannot acquire irq line\n", qpti->qpti_id); + return -1; +} + +static void __init qpti_get_scsi_id(struct qlogicpti *qpti) +{ + qpti->scsi_id = prom_getintdefault(qpti->prom_node, + "initiator-id", + -1); + if (qpti->scsi_id == -1) + qpti->scsi_id = prom_getintdefault(qpti->prom_node, + "scsi-initiator-id", + -1); + if (qpti->scsi_id == -1) + qpti->scsi_id = + prom_getintdefault(qpti->sdev->bus->prom_node, + "scsi-initiator-id", 7); + qpti->qhost->this_id = qpti->scsi_id; + + printk("SCSI ID %d ", qpti->scsi_id); +} + +static void qpti_get_bursts(struct qlogicpti *qpti) +{ + struct sbus_dev *sdev = qpti->sdev; + u8 bursts, bmask; + + bursts = prom_getintdefault(qpti->prom_node, "burst-sizes", 0xff); + bmask = prom_getintdefault(sdev->bus->prom_node, + "burst-sizes", 0xff); + if (bmask != 0xff) + bursts &= bmask; + if (bursts == 0xff || + (bursts & DMA_BURST16) == 0 || + (bursts & DMA_BURST32) == 0) + bursts = (DMA_BURST32 - 1); + + qpti->bursts = bursts; +} + +static void qpti_get_clock(struct qlogicpti *qpti) +{ + unsigned int cfreq; + + /* Check for what the clock input to this card is. + * Default to 40Mhz. + */ + cfreq = prom_getintdefault(qpti->prom_node,"clock-frequency",40000000); + qpti->clock = (cfreq + 500000)/1000000; + if (qpti->clock == 0) /* bullshit */ + qpti->clock = 40; +} + +/* The request and response queues must each be aligned + * on a page boundry. + */ +static int __init qpti_map_queues(struct qlogicpti *qpti) +{ + struct sbus_dev *sdev = qpti->sdev; + +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + qpti->res_cpu = sbus_alloc_consistant(sdev, + QSIZE(RES_QUEUE_LEN), + &qpti->res_dvma); + if (qpti->res_cpu == NULL || + qpti->res_dvma == 0) { + printk("QPTI: Cannot map response queue.\n"); + return -1; + } + + qpti->req_cpu = sbus_alloc_consistant(sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + &qpti->req_dvma); + if (qpti->req_cpu == NULL || + qpti->req_dvma == 0) { + sbus_free_consistant(sdev, QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + printk("QPTI: Cannot map request queue.\n"); + return -1; + } + memset(qpti->res_cpu, 0, QSIZE(RES_QUEUE_LEN)); + memset(qpti->req_cpu, 0, QSIZE(QLOGICPTI_REQ_QUEUE_LEN)); + return 0; +} /* Detect all PTI Qlogic ISP's in the machine. */ int __init qlogicpti_detect(Scsi_Host_Template *tpnt) { - struct qlogicpti *qpti, *qlink; + struct qlogicpti *qpti; struct Scsi_Host *qpti_host; - struct linux_sbus *sbus; - struct linux_sbus_device *qpti_dev, *sbdev_iter; - struct qlogicpti_regs *qregs; - volatile unsigned char *sreg; - unsigned char bsizes, bsizes_more; + struct sbus_bus *sbus; + struct sbus_dev *sdev; int nqptis = 0, nqptis_in_use = 0; - int qpti_node; - int is_pti; tpnt->proc_name = "qlogicpti"; - qptichain = 0; - if(!SBus_chain) - return 0; for_each_sbus(sbus) { - for_each_sbusdev(sbdev_iter, sbus) { - qpti_dev = sbdev_iter; - + for_each_sbusdev(sdev, sbus) { /* Is this a red snapper? */ - if(strcmp(qpti_dev->prom_name, "ptisp") && - strcmp(qpti_dev->prom_name, "PTI,ptisp") && - strcmp(qpti_dev->prom_name, "QLGC,isp")) + if (strcmp(sdev->prom_name, "ptisp") && + strcmp(sdev->prom_name, "PTI,ptisp") && + strcmp(sdev->prom_name, "QLGC,isp")) continue; /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. * Skip over them in such cases so we survive. */ - if(qpti_dev->irqs[0] == 0) { + if (sdev->irqs[0] == 0) { printk("qpti%d: Adapter reports no interrupt, " "skipping over this card.", nqptis); continue; @@ -617,179 +835,76 @@ /* Yep, register and allocate software state. */ qpti_host = scsi_register(tpnt, sizeof(struct qlogicpti)); - if(!qpti_host) - panic("Cannot register PTI Qlogic ISP SCSI host"); + if (!qpti_host) { + printk("QPTI: Cannot register PTI Qlogic ISP SCSI host"); + continue; + } qpti = (struct qlogicpti *) qpti_host->hostdata; - if(!qpti) - panic("No qpti in hostdata"); + + spin_lock_init(&qpti->lock); /* We are wide capable, 16 targets. */ qpti_host->max_id = MAX_TARGETS; -#ifdef __sparc_v9__ - qpti_host->unchecked_isa_dma = 1; -#endif - /* Setup back pointers and misc. state. */ qpti->qhost = qpti_host; - qpti->qdev = qpti_dev; + qpti->sdev = sdev; qpti->qpti_id = nqptis++; - - /* Insert this one into the global interrupt service chain. */ - if(qptichain) { - qlink = qptichain; - while(qlink->next) qlink = qlink->next; - qlink->next = qpti; - } else { - qptichain = qpti; - } - qpti->next = 0; - - /* More misc. prom information. */ - qpti_node = qpti_dev->prom_node; - prom_getstring(qpti_node, "name", qpti->prom_name, + qpti->prom_node = sdev->prom_node; + prom_getstring(qpti->prom_node, "name", + qpti->prom_name, sizeof(qpti->prom_name)); - qpti->prom_node = qpti_node; - - qpti->is_pti = is_pti = - (strcmp (qpti->prom_name, "QLGC,isp") != 0); - /* Setup the reg property for this device. */ - prom_apply_sbus_ranges(qpti->qdev->my_bus, - qpti->qdev->reg_addrs, - 1, qpti->qdev); - - /* Map in Qlogic,ISP regs and the PTI status reg. */ - qpti->qregs = qregs = (struct qlogicpti_regs *) - sparc_alloc_io(qpti->qdev->reg_addrs[0].phys_addr, 0, - qpti->qdev->reg_addrs[0].reg_size, - "PTI Qlogic/ISP Registers", - qpti->qdev->reg_addrs[0].which_io, 0x0); - if(!qregs) - panic("PTI Qlogic/ISP registers unmappable"); - - if(is_pti) { - /* Map this one read only. */ - qpti->sreg = sreg = (volatile unsigned char *) - sparc_alloc_io((qpti->qdev->reg_addrs[0].phys_addr + - (16 * 4096)), 0, - sizeof(unsigned char), - "PTI Qlogic/ISP Status Reg", - qpti->qdev->reg_addrs[0].which_io, 1); - if(!sreg) - panic("PTI Qlogic/ISP status reg unmappable"); - qpti->swsreg = 0; - } - - qpti_host->base = (unsigned char *)qregs; - qpti_host->io_port = (unsigned int) ((unsigned long)qregs); - qpti_host->n_io_port = (unsigned char) - qpti->qdev->reg_addrs[0].reg_size; - - qpti_host->irq = qpti->irq = qpti->qdev->irqs[0]; - - /* On Ultra and S{S1,C2}000 we must always call request_irq for each - * qpti, so that imap registers get setup etc. - * But irq values are different in that case anyway... - * Otherwise allocate the irq only if necessary. + /* This is not correct, actually. There's a switch + * on the PTI cards that put them into "emulation" + * mode- i.e., report themselves as QLGC,isp + * instead of PTI,ptisp. The only real substantive + * difference between non-pti and pti cards is + * the tmon register. Which is possibly even + * there for Qlogic cards, but non-functional. */ - for_each_qlogicpti(qlink) { - if((qlink != qpti) && (qpti->irq == qlink->irq)) { - goto qpti_irq_acquired; /* BASIC rulez */ - } - } - if(request_irq(qpti->qhost->irq, -#ifndef __sparc_v9__ - (sparc_cpu_model == sun4m || sparc_cpu_model == sun4c) ? - do_qlogicpti_intr_handler_sun4m : -#endif - do_qlogicpti_intr_handler, - SA_SHIRQ, "PTI Qlogic/ISP SCSI", qpti)) { - printk("Cannot acquire PTI Qlogic/ISP irq line\n"); - /* XXX Unmap regs, unregister scsi host, free things. */ - continue; - } -qpti_irq_acquired: - printk("qpti%d: IRQ %s ", - qpti->qpti_id, __irq_itoa(qpti->qhost->irq)); - - /* Figure out our scsi ID on the bus */ - qpti->scsi_id = prom_getintdefault(qpti->prom_node, - "initiator-id", - -1); - if(qpti->scsi_id == -1) - qpti->scsi_id = prom_getintdefault(qpti->prom_node, - "scsi-initiator-id", - -1); - if(qpti->scsi_id == -1) - qpti->scsi_id = - prom_getintdefault(qpti->qdev->my_bus->prom_node, - "scsi-initiator-id", 7); - qpti->qhost->this_id = qpti->scsi_id; - printk("SCSI ID %d ", qpti->scsi_id); + qpti->is_pti = (strcmp (qpti->prom_name, "QLGC,isp") != 0); - /* Check for what the best SBUS burst we can use happens - * to be on this machine. - */ - bsizes = prom_getintdefault(qpti->prom_node,"burst-sizes",0xff); - bsizes &= 0xff; - bsizes_more = prom_getintdefault(qpti->qdev->my_bus->prom_node, - "burst-sizes", 0xff); - if(bsizes_more != 0xff) - bsizes &= bsizes_more; - if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 || - (bsizes & DMA_BURST32) == 0) - bsizes = (DMA_BURST32 - 1); - qpti->bursts = bsizes; + qpti_chain_add(qpti); + if (qpti_map_regs(qpti) < 0) + goto fail_unlink; + + if (qpti_register_irq(qpti) < 0) + goto fail_unmap_regs; + + qpti_get_scsi_id(qpti); + qpti_get_bursts(qpti); + qpti_get_clock(qpti); /* Clear out Scsi_Cmnd array. */ memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots)); - /* The request and response queues must each be aligned - * on a page boundry. - */ - -#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) - - qpti->res_cpu = sparc_dvma_malloc(QSIZE(RES_QUEUE_LEN), - "PTISP Response Queue", - &qpti->res_dvma); - qpti->req_cpu = sparc_dvma_malloc(QSIZE(QLOGICISP_REQ_QUEUE_LEN), - "PTISP Request Queue", - &qpti->req_dvma); + if (qpti_map_queues(qpti) < 0) + goto fail_free_irq; -#undef QSIZE - - - /* Set adapter and per-device default values. */ - qlogicpti_set_hostdev_defaults(qpti); - /* Load the firmware. */ - /* XXX Find out where is it possible to download - our sbus_risc_code on non-PTI ISP1000. */ - if(is_pti && qlogicpti_load_firmware(qpti)) - panic("SBUS Qlogic/ISP firmware load failed"); - - if (is_pti) { + if (qlogicpti_load_firmware(qpti)) + goto fail_unmap_queues; + if (qpti->is_pti) { /* Check the PTI status reg. */ - if(qlogicpti_verify_tmon(qpti)) - panic("PTI Qlogic/ISP tmon verification failed"); + if (qlogicpti_verify_tmon(qpti)) + goto fail_unmap_queues; } /* Reset the ISP and init res/req queues. */ - if(qlogicpti_reset_hardware(qpti_host)) - panic("PTI Qlogic/ISP cannot be reset"); + if (qlogicpti_reset_hardware(qpti_host)) + goto fail_unmap_queues; - if (is_pti) { - printk("(Firmware v%d.%d)", - qpti->fware_majrev, qpti->fware_minrev); - } else { + printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, + qpti->fware_minrev, qpti->fware_micrev); + { char buffer[60]; - prom_getstring (qpti_node, "isp-fcode", buffer, 60); + prom_getstring (qpti->prom_node, + "isp-fcode", buffer, 60); if (buffer[0]) printk("(Firmware %s)", buffer); - if (prom_getbool(qpti_node, "differential")) + if (prom_getbool(qpti->prom_node, "differential")) qpti->differential = 1; } @@ -798,6 +913,28 @@ (qpti->differential ? "differential" : "single ended")); nqptis_in_use++; + continue; + + fail_unmap_queues: +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistant(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistant(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + fail_free_irq: + free_irq(qpti->irq, qpti); + + fail_unmap_regs: + sbus_iounmap(qpti->qregs, + qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); + fail_unlink: + qpti_chain_del(qpti); + scsi_unregister(qpti->qhost); } } if (nqptis) @@ -810,17 +947,28 @@ int qlogicpti_release(struct Scsi_Host *host) { struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - struct qlogicpti_regs *qregs = qpti->qregs; + + /* Remove visibility from IRQ handlers. */ + qpti_chain_del(qpti); /* Shut up the card. */ - qregs->sbus_ctrl = 0; + sbus_writew(0, qpti->qregs + SBUS_CTRL); /* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */ - free_irq(host->irq, NULL); - unmapioaddr((unsigned long)qregs); - /* QLGC,isp doesn't have status reg */ - if (strcmp (qpti->prom_name, "QLGC,isp")) - unmapioaddr((unsigned long)qpti->sreg); + free_irq(qpti->irq, qpti); + +#define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) + sbus_free_consistant(qpti->sdev, + QSIZE(RES_QUEUE_LEN), + qpti->res_cpu, qpti->res_dvma); + sbus_free_consistant(qpti->sdev, + QSIZE(QLOGICPTI_REQ_QUEUE_LEN), + qpti->req_cpu, qpti->req_dvma); +#undef QSIZE + + sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); + if (qpti->is_pti) + sbus_iounmap(qpti->sreg, sizeof(unsigned char)); return 0; } @@ -830,8 +978,8 @@ static char buf[80]; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %08lx", - __irq_itoa(qpti->qhost->irq), (unsigned long) qpti->qregs); + sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %lx", + __irq_itoa(qpti->qhost->irq), qpti->qregs); return buf; } @@ -857,18 +1005,18 @@ cmd->target_lun = Cmnd->lun; cmd->cdb_length = Cmnd->cmd_len; cmd->control_flags = 0; - if(Cmnd->device->tagged_supported) { - if(qpti->cmd_count[Cmnd->target] == 0) + if (Cmnd->device->tagged_supported) { + if (qpti->cmd_count[Cmnd->target] == 0) qpti->tag_ages[Cmnd->target] = jiffies; - if((jiffies - qpti->tag_ages[Cmnd->target]) > (5*HZ)) { + if ((jiffies - qpti->tag_ages[Cmnd->target]) > (5*HZ)) { cmd->control_flags = CFLAG_ORDERED_TAG; qpti->tag_ages[Cmnd->target] = jiffies; } else cmd->control_flags = CFLAG_SIMPLE_TAG; } - if((Cmnd->cmnd[0] == WRITE_6) || - (Cmnd->cmnd[0] == WRITE_10) || - (Cmnd->cmnd[0] == WRITE_12)) + if ((Cmnd->cmnd[0] == WRITE_6) || + (Cmnd->cmnd[0] == WRITE_10) || + (Cmnd->cmnd[0] == WRITE_12)) cmd->control_flags |= CFLAG_WRITE; else cmd->control_flags |= CFLAG_READ; @@ -877,42 +1025,40 @@ } /* Do it to it baby. */ -static inline u_int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd, - struct qlogicpti *qpti, struct qlogicpti_regs *qregs, - u_int in_ptr, u_int out_ptr) +static inline int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd, + struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr) { - struct dataseg * ds; + struct dataseg *ds; struct scatterlist *sg; - int sg_count = Cmnd->use_sg; int i, n; - if(sg_count) { - mmu_get_scsi_sgl((struct mmu_sglist *)Cmnd->buffer, (Cmnd->use_sg - 1), - qpti->qdev->my_bus); + if (Cmnd->use_sg) { + int sg_count; + + sg = (struct scatterlist *) Cmnd->buffer; + sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg); - cmd->segment_cnt = sg_count; - sg = (struct scatterlist *) Cmnd->request_buffer; ds = cmd->dataseg; + cmd->segment_cnt = sg_count; /* Fill in first four sg entries: */ n = sg_count; - if(n > 4) + if (n > 4) n = 4; - for(i = 0; i < n; i++, sg++) { - ds[i].d_base = (u_int) sg->dvma_address; - ds[i].d_count = (u_int) sg->length; + for (i = 0; i < n; i++, sg++) { + ds[i].d_base = sg->dvma_address; + ds[i].d_count = sg->dvma_length; } sg_count -= 4; - while(sg_count > 0) { + while (sg_count > 0) { struct Continuation_Entry *cont; ++cmd->hdr.entry_cnt; cont = (struct Continuation_Entry *) &qpti->req_cpu[in_ptr]; in_ptr = NEXT_REQ_PTR(in_ptr); - if(in_ptr == out_ptr) { - printk(KERN_EMERG "qlogicpti: Unexpected request queue overflow\n"); + if (in_ptr == out_ptr) return -1; - } + cont->hdr.entry_type = ENTRY_CONTINUATION; cont->hdr.entry_cnt = 0; cont->hdr.sys_def_1 = 0; @@ -920,24 +1066,21 @@ cont->reserved = 0; ds = cont->dataseg; n = sg_count; - if(n > 7) + if (n > 7) n = 7; - for(i = 0; i < n; i++, sg++) { - ds[i].d_base = (u_int) sg->dvma_address; - ds[i].d_count = (u_int) sg->length; + for (i = 0; i < n; i++, sg++) { + ds[i].d_base = sg->dvma_address; + ds[i].d_count = sg->dvma_length; } sg_count -= n; } } else { - /* XXX Casts are extremely gross, but with 64-bit cpu addresses - * XXX and 32-bit SBUS DVMA addresses what am I to do? -DaveM - */ - Cmnd->SCp.ptr = (char *)((unsigned long) - mmu_get_scsi_one((char *)Cmnd->request_buffer, - Cmnd->request_bufflen, - qpti->qdev->my_bus)); + Cmnd->SCp.ptr = (char *)(unsigned long) + sbus_map_single(qpti->sdev, + Cmnd->request_buffer, + Cmnd->request_bufflen); - cmd->dataseg[0].d_base = (u_int) ((unsigned long)Cmnd->SCp.ptr); + cmd->dataseg[0].d_base = (u32) ((unsigned long)Cmnd->SCp.ptr); cmd->dataseg[0].d_count = Cmnd->request_bufflen; cmd->segment_cnt = 1; } @@ -947,7 +1090,7 @@ qpti->cmd_slots[in_ptr] = Cmnd; qpti->cmd_count[Cmnd->target]++; - qregs->mbox4 = in_ptr; + sbus_writew(in_ptr, qpti->qregs + MBOX4); qpti->req_in_ptr = in_ptr; return in_ptr; @@ -957,9 +1100,126 @@ { /* Temporary workaround until bug is found and fixed (one bug has been found already, but fixing it makes things even worse) -jj */ - int num_free = QLOGICISP_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64; + int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64; host->can_queue = host->host_busy + num_free; - host->sg_tablesize = QLOGICISP_MAX_SG(num_free); + host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); +} + +/* + * Until we scan the entire bus with inquiries, go throught this fella... + */ +static void ourdone(Scsi_Cmnd *Cmnd) +{ + struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata; + int tgt = Cmnd->target; + void (*done) (Scsi_Cmnd *); + + /* This grot added by DaveM, blame him for ugliness. + * The issue is that in the 2.3.x driver we use the + * host_scribble portion of the scsi command as a + * completion linked list at interrupt service time, + * so we have to store the done function pointer elsewhere. + */ + done = (void (*)(Scsi_Cmnd *)) + (((unsigned long) Cmnd->SCp.Message) +#ifdef __sparc_v9__ + | ((unsigned long) Cmnd->SCp.Status << 32UL) +#endif + ); + + if ((qpti->sbits & (1 << tgt)) == 0) { + int ok = host_byte(Cmnd->result) == DID_OK; + if (Cmnd->cmnd[0] == 0x12 && ok) { + unsigned char *iqd; + if (Cmnd->use_sg == 0) { + iqd = ((unsigned char *)Cmnd->buffer); + } else { + iqd = ((struct scatterlist *) Cmnd->request_buffer)->address; + } + /* tags handled in midlayer */ + /* enable sync mode? */ + if (iqd[7] & 0x10) { + qpti->dev_param[tgt].device_flags |= 0x10; + } else { + qpti->dev_param[tgt].synchronous_offset = 0; + qpti->dev_param[tgt].synchronous_period = 0; + } + /* are we wide capable? */ + if (iqd[7] & 0x20) { + qpti->dev_param[tgt].device_flags |= 0x20; + } + qpti->sbits |= (1 << tgt); + } else if (!ok) { + qpti->sbits |= (1 << tgt); + } + } + done(Cmnd); +} + +int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)) +{ + unsigned long flags; + struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata; + + /* + * done checking this host adapter? + * If not, then rewrite the command + * to finish through ourdone so we + * can peek at Inquiry data results. + */ + if (qpti->sbits && qpti->sbits != 0xffff) { + /* See above about in ourdone this ugliness... */ + Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff; +#ifdef __sparc_v9__ + Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff; +#endif + return qlogicpti_queuecommand(Cmnd, ourdone); + } + save_flags(flags); cli(); + + /* + * We've peeked at all targets for this bus- time + * to set parameters for devices for real now. + */ + if (qpti->sbits == 0xffff) { + int i; + for(i = 0; i < MAX_TARGETS; i++) { + u_short param[6]; + param[0] = MBOX_SET_TARGET_PARAMS; + param[1] = (i << 8); + param[2] = (qpti->dev_param[i].device_flags << 8); + if (qpti->dev_param[i].device_flags & 0x10) { + param[3] = (qpti->dev_param[i].synchronous_offset << 8) | + qpti->dev_param[i].synchronous_period; + } else { + param[3] = 0; + } + (void) qlogicpti_mbox_command(qpti, param, 0); + } + /* + * set to zero so any traverse through ourdone + * doesn't start the whole process again, + */ + qpti->sbits = 0; + } + + /* check to see if we're done with all adapters... */ + for (qpti = qptichain; qpti != NULL; qpti = qpti->next) { + if (qpti->sbits) { + break; + } + } + + /* + * if we hit the end of the chain w/o finding adapters still + * capability-configuring, then we're done with all adapters + * and can rock on.. + */ + if (qpti == NULL) + Cmnd->host->hostt->queuecommand = qlogicpti_queuecommand; + + restore_flags(flags); + return qlogicpti_queuecommand(Cmnd, done); } /* @@ -974,63 +1234,62 @@ { struct Scsi_Host *host = Cmnd->host; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; - struct qlogicpti_regs *qregs = qpti->qregs; - u_int in_ptr = qpti->req_in_ptr; - u_int out_ptr = qregs->mbox4; - struct Command_Entry *cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr]; + struct Command_Entry *cmd; + unsigned long flags; + u_int out_ptr; + int in_ptr; Cmnd->scsi_done = done; + + spin_lock_irqsave(&qpti->lock, flags); + + in_ptr = qpti->req_in_ptr; + cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr]; + out_ptr = sbus_readw(qpti->qregs + MBOX4); in_ptr = NEXT_REQ_PTR(in_ptr); - if(in_ptr == out_ptr) { - printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",qpti->qpti_id); + if (in_ptr == out_ptr) + goto toss_command; - /* Unfortunately, unless you use the new EH code, which - * we don't, the midlayer will ignore the return value, - * which is insane. We pick up the pieces like this. - */ - Cmnd->result = DID_BUS_BUSY; - done(Cmnd); - return 1; - } - if(qpti->send_marker) { + if (qpti->send_marker) { marker_frob(cmd); qpti->send_marker = 0; - if(NEXT_REQ_PTR(in_ptr) == out_ptr) { - qregs->mbox4 = in_ptr; + if (NEXT_REQ_PTR(in_ptr) == out_ptr) { + sbus_writew(in_ptr, qpti->qregs + MBOX4); qpti->req_in_ptr = in_ptr; - printk(KERN_EMERG "qlogicpti%d: request queue overflow\n", - qpti->qpti_id); - - /* Unfortunately, unless you use the new EH code, which - * we don't, the midlayer will ignore the return value, - * which is insane. We pick up the pieces like this. - */ - Cmnd->result = DID_BUS_BUSY; - done(Cmnd); - return 1; + goto toss_command; } cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr]; in_ptr = NEXT_REQ_PTR(in_ptr); } cmd_frob(cmd, Cmnd, qpti); - if((in_ptr = load_cmd(Cmnd, cmd, qpti, qregs, in_ptr, out_ptr)) == -1) { - /* Unfortunately, unless you use the new EH code, which - * we don't, the midlayer will ignore the return value, - * which is insane. We pick up the pieces like this. - */ - Cmnd->result = DID_BUS_BUSY; - done(Cmnd); - return 1; - } + if ((in_ptr = load_cmd(Cmnd, cmd, qpti, in_ptr, out_ptr)) == -1) + goto toss_command; + update_can_queue(host, in_ptr, out_ptr); + + spin_unlock_irqrestore(&qpti->lock, flags); return 0; + +toss_command: + printk(KERN_EMERG "qlogicpti%d: request queue overflow\n", + qpti->qpti_id); + + spin_unlock_irqrestore(&qpti->lock, flags); + + /* Unfortunately, unless you use the new EH code, which + * we don't, the midlayer will ignore the return value, + * which is insane. We pick up the pieces like this. + */ + Cmnd->result = DID_BUS_BUSY; + done(Cmnd); + return 1; } -static int qlogicpti_return_status(struct Status_Entry *sts) +static int qlogicpti_return_status(struct Status_Entry *sts, int id) { int host_status = DID_ERROR; - switch(sts->completion_status) { + switch (sts->completion_status) { case CS_COMPLETE: host_status = DID_OK; break; @@ -1081,8 +1340,8 @@ host_status = DID_OK; break; default: - printk(KERN_EMERG "qlogicpti : unknown completion status 0x%04x\n", - sts->completion_status); + printk(KERN_EMERG "qpti%d: unknown completion status 0x%04x\n", + id, sts->completion_status); host_status = DID_ERROR; break; } @@ -1090,22 +1349,19 @@ return (sts->scsi_status & STATUS_MASK) | (host_status << 16); } -static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti) +static Scsi_Cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) { - Scsi_Cmnd *Cmnd; + Scsi_Cmnd *Cmnd, *done_queue = NULL; struct Status_Entry *sts; u_int in_ptr, out_ptr; - struct qlogicpti_regs *qregs; - if(!(qpti->qregs->sbus_stat & SBUS_STAT_RINT)) - return 0; + if (!(sbus_readw(qpti->qregs + SBUS_STAT) & SBUS_STAT_RINT)) + return NULL; - qregs = qpti->qregs; - - in_ptr = qregs->mbox5; - qregs->hcctrl = HCCTRL_CRIRQ; - if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) { - switch(qregs->mbox0) { + in_ptr = sbus_readw(qpti->qregs + MBOX5); + sbus_writew(HCCTRL_CRIRQ, qpti->qregs + HCCTRL); + if (sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK) { + switch (sbus_readw(qpti->qregs + MBOX0)) { case ASYNC_SCSI_BUS_RESET: case EXECUTION_TIMEOUT_RESET: qpti->send_marker = 1; @@ -1115,13 +1371,13 @@ case COMMAND_ERROR: case COMMAND_PARAM_ERROR: break; - } - qregs->sbus_semaphore = 0; + }; + sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); } /* This looks like a network driver! */ out_ptr = qpti->res_out_ptr; - while(out_ptr != in_ptr) { + while (out_ptr != in_ptr) { u_int cmd_slot; sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr]; @@ -1135,64 +1391,62 @@ Cmnd = qpti->cmd_slots[cmd_slot]; qpti->cmd_slots[cmd_slot] = NULL; - if(sts->completion_status == CS_RESET_OCCURRED || - sts->completion_status == CS_ABORTED || - (sts->status_flags & STF_BUS_RESET)) + if (sts->completion_status == CS_RESET_OCCURRED || + sts->completion_status == CS_ABORTED || + (sts->status_flags & STF_BUS_RESET)) qpti->send_marker = 1; - if(sts->state_flags & SF_GOT_SENSE) + if (sts->state_flags & SF_GOT_SENSE) memcpy(Cmnd->sense_buffer, sts->req_sense_data, sizeof(Cmnd->sense_buffer)); - if(sts->hdr.entry_type == ENTRY_STATUS) - Cmnd->result = qlogicpti_return_status(sts); + if (sts->hdr.entry_type == ENTRY_STATUS) + Cmnd->result = + qlogicpti_return_status(sts, qpti->qpti_id); else Cmnd->result = DID_ERROR << 16; - if(Cmnd->use_sg) - mmu_release_scsi_sgl((struct mmu_sglist *) - Cmnd->buffer, - Cmnd->use_sg - 1, - qpti->qdev->my_bus); - else - mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr), - Cmnd->request_bufflen, - qpti->qdev->my_bus); - + if (Cmnd->use_sg) { + sbus_unmap_sg(qpti->sdev, + (struct scatterlist *)Cmnd->buffer, + Cmnd->use_sg); + } else { + sbus_unmap_single(qpti->sdev, + (__u32)((unsigned long)Cmnd->SCp.ptr), + Cmnd->request_bufflen); + } qpti->cmd_count[Cmnd->target]--; - qregs->mbox5 = out_ptr; - Cmnd->scsi_done(Cmnd); + sbus_writew(out_ptr, qpti->qregs + MBOX5); + Cmnd->host_scribble = (unsigned char *) done_queue; + done_queue = Cmnd; } qpti->res_out_ptr = out_ptr; - return 1; -} - -#ifndef __sparc_v9__ - -static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct qlogicpti *qpti; - int again; - spin_lock_irqsave(&io_request_lock, flags); - do { - again = 0; - for_each_qlogicpti(qpti) - again |= qlogicpti_intr_handler(qpti); - } while (again); - spin_unlock_irqrestore(&io_request_lock, flags); + return done_queue; } -#endif - -static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +static void qpti_intr(int irq, void *dev_id, struct pt_regs *regs) { + struct qlogicpti *qpti = dev_id; unsigned long flags; + Scsi_Cmnd *dq; - spin_lock_irqsave(&io_request_lock, flags); - qlogicpti_intr_handler((struct qlogicpti *)dev_id); - spin_unlock_irqrestore(&io_request_lock, flags); + spin_lock_irqsave(&qpti->lock, flags); + dq = qlogicpti_intr_handler(qpti); + spin_unlock(&qpti->lock); + + if (dq != NULL) { + spin_lock(&io_request_lock); + do { + Scsi_Cmnd *next; + + next = (Scsi_Cmnd *) dq->host_scribble; + dq->scsi_done(dq); + dq = next; + } while (dq != NULL); + spin_unlock(&io_request_lock); + } + __restore_flags(flags); } int qlogicpti_abort(Scsi_Cmnd *Cmnd) @@ -1201,20 +1455,39 @@ struct Scsi_Host *host = Cmnd->host; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; int return_status = SCSI_ABORT_SUCCESS; + unsigned long flags; + u32 cmd_cookie; + int i; printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n", (int)Cmnd->target, (int)Cmnd->lun); - qlogicpti_disable_irqs(qpti->qregs); + + spin_lock_irqsave(&qpti->lock, flags); + + qlogicpti_disable_irqs(qpti); + + /* Find the 32-bit cookie we gave to the firmware for + * this command. + */ + for (i = 0; i < QLOGICPTI_REQ_QUEUE_LEN + 1; i++) + if (qpti->cmd_slots[i] == Cmnd) + break; + cmd_cookie = i; + param[0] = MBOX_ABORT; param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun; - param[2] = ((unsigned int)((unsigned long)Cmnd)) >> 16; - param[3] = ((unsigned int)((unsigned long)Cmnd)) & 0xffff; - if(qlogicpti_mbox_command(qpti, param, 0) || - (param[0] != MBOX_COMMAND_COMPLETE)) { + param[2] = cmd_cookie >> 16; + param[3] = cmd_cookie & 0xffff; + if (qlogicpti_mbox_command(qpti, param, 0) || + (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti : scsi abort failure: %x\n", param[0]); return_status = SCSI_ABORT_ERROR; } - qlogicpti_enable_irqs(qpti->qregs); + + qlogicpti_enable_irqs(qpti); + + spin_unlock_irqrestore(&qpti->lock, flags); + return return_status; } @@ -1224,17 +1497,26 @@ struct Scsi_Host *host = Cmnd->host; struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; int return_status = SCSI_RESET_SUCCESS; + unsigned long flags; printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n"); - qlogicpti_disable_irqs(qpti->qregs); + + spin_lock_irqsave(&qpti->lock, flags); + + qlogicpti_disable_irqs(qpti); + param[0] = MBOX_BUS_RESET; param[1] = qpti->host_param.bus_reset_delay; - if(qlogicpti_mbox_command(qpti, param, 0) || + if (qlogicpti_mbox_command(qpti, param, 0) || (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicisp : scsi bus reset failure: %x\n", param[0]); return_status = SCSI_RESET_ERROR; } - qlogicpti_enable_irqs(qpti->qregs); + + qlogicpti_enable_irqs(qpti); + + spin_unlock_irqrestore(&qpti->lock, flags); + return return_status; } diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti.h linux/drivers/scsi/qlogicpti.h --- v2.3.34/linux/drivers/scsi/qlogicpti.h Thu Nov 18 20:25:37 1999 +++ linux/drivers/scsi/qlogicpti.h Mon Dec 20 22:06:42 1999 @@ -6,135 +6,28 @@ #ifndef _QLOGICPTI_H #define _QLOGICPTI_H -struct qlogicpti_regs { - /* SBUS control registers. */ - volatile unsigned short sbus_idlow; /* SBUS ID, low bytes */ - volatile unsigned short sbus_idhi; /* SBUS ID, high bytes */ - volatile unsigned short sbus_cfg0; /* SBUS Config reg zero */ - volatile unsigned short sbus_cfg1; /* SBUS Config reg one */ - volatile unsigned short sbus_ctrl; /* SBUS Control reg */ - volatile unsigned short sbus_stat; /* SBUS Status reg */ - volatile unsigned short sbus_semaphore; /* SBUS Semaphore, p/v this... */ - unsigned char _unused0[18]; /* Reserved... */ - - /* Command DVMA control registers. */ - volatile unsigned short cmd_dma_cfg; /* CMD DVMA Config reg */ - volatile unsigned short cmd_dma_ctrl; /* CMD DVMA Control reg */ - volatile unsigned short cmd_dma_stat; /* CMD DVMA Status reg */ - volatile unsigned short cmd_dma_fstat; /* CMD DVMA FIFO Status reg */ - volatile unsigned short cmd_dma_cnt; /* CMD DVMA Counter reg */ - unsigned short _unused1; /* Reserved... */ - volatile unsigned short cmd_dma_alow; /* CMD DVMA Address low bytes */ - volatile unsigned short cmd_dma_ahi; /* CMD DVMA Address high bytes */ - unsigned char _unused2[16]; /* Reserved... */ - - /* Data DVMA control registers. */ - volatile unsigned short data_dma_cfg; /* DATA DVMA Config reg */ - volatile unsigned short data_dma_ctrl; /* DATA DVMA Control reg */ - volatile unsigned short data_dma_stat; /* DATA DVMA Status reg */ - volatile unsigned short data_dma_fstat; /* DATA DVMA FIFO Status reg */ - volatile unsigned short data_dma_clo; /* DATA DVMA Counter low bytes */ - volatile unsigned short data_dma_chi; /* DATA DVMA Counter high bytes */ - volatile unsigned short data_dma_alow; /* DATA DVMA Address low bytes */ - volatile unsigned short data_dma_ahi; /* DATA DVMA Address high bytes */ - unsigned char _unused3[16]; /* Reserved... */ - - /* Data FIFO registers. */ - volatile unsigned short fcmd; /* FIFO Command port */ - volatile unsigned short fdata; /* FIFO Data port */ - unsigned char _unused4[28]; /* Reserved... */ - - /* Mailboxen. */ - volatile unsigned short mbox0; /* MailBOX 0 */ - volatile unsigned short mbox1; /* MailBOX 1 */ - volatile unsigned short mbox2; /* MailBOX 2 */ - volatile unsigned short mbox3; /* MailBOX 3 */ - volatile unsigned short mbox4; /* MailBOX 4 */ - volatile unsigned short mbox5; /* MailBOX 5 */ - unsigned char _unused5[372]; /* Reserved... */ - - /* Scsi processor registers. */ - volatile unsigned short cpu_id; /* PART ID */ - volatile unsigned short cpu_cfg1; /* Config reg 1 */ - volatile unsigned short cpu_cfg2; /* Config reg 2 */ - volatile unsigned short cpu_cfg3; /* Config reg 3 */ - unsigned char _unused6[4]; /* Reserved... */ - volatile unsigned short cpu_pc; /* Program Counter */ - unsigned short _unused7; /* Reserved... */ - volatile unsigned short cpu_rpc; /* Return Program Counter */ - unsigned short _unused8; /* Reserved... */ - volatile unsigned short cpu_cmd; /* Command */ - unsigned short _unused9; /* Reserved... */ - volatile unsigned short cpu_irq; /* IRQ status */ - unsigned short _unused10; /* Reserved... */ - volatile unsigned short cpu_seq; /* Sequence reg */ - volatile unsigned short cpu_gerr; /* Gross Error reg (ESP lineage?) */ - volatile unsigned short cpu_exc; /* Enable Exception reg */ - unsigned short _unused11; /* Reserved... */ - volatile unsigned short cpu_oride; /* Override reg */ - unsigned short _unused12; /* Reserved... */ - volatile unsigned short cpu_lbase; /* Literal Base reg */ - unsigned short _unused13; /* Reserved... */ - volatile unsigned short cpu_uflags; /* User Flags reg */ - unsigned short _unused14; /* Reserved... */ - volatile unsigned short cpu_uexc; /* User Exception reg */ - unsigned short _unused15; /* Reserved... */ - volatile unsigned short cpu_bkpt; /* Breakpoint reg */ - unsigned short _unused16[5]; /* Reserved... */ - volatile unsigned short cpu_sid; /* SCSI ID reg */ - volatile unsigned short cpu_dcfg1; /* Device Config 1 */ - volatile unsigned short cpu_dcfg2; /* Device Config 2 */ - unsigned short _unused17; /* Reserved... */ - volatile unsigned short cpu_pptr; /* Phase Pointer */ - unsigned short _unused18; /* Reserved... */ - volatile unsigned short cpu_bptr; /* Buffer Pointer */ - unsigned short _unused19; /* Reserved... */ - volatile unsigned short cpu_bcnt; /* Buffer Counter */ - volatile unsigned short cpu_buf; /* Buffer itself */ - volatile unsigned short cpu_bbyte; /* Buffer Byte */ - volatile unsigned short cpu_bword; /* Buffer Word */ - unsigned short _unused20; /* Reserved... */ - volatile unsigned short cpu_fifo; /* FIFO */ - volatile unsigned short cpu_fstat; /* FIFO Status */ - volatile unsigned short cpu_ftop; /* Top of FIFO */ - volatile unsigned short cpu_fbottom; /* Bottom of FIFO */ - unsigned short _unused21; /* Reserved... */ - volatile unsigned short cpu_treg; /* Transfer reg */ - unsigned short _unused22; /* Reserved... */ - volatile unsigned short cpu_clo; /* Transfer Count low bytes */ - volatile unsigned short cpu_chi; /* Transfer Count high bytes */ - volatile unsigned short cpu_cntlo; /* Transfer Counter low bytes */ - volatile unsigned short cpu_cnthi; /* Transfer Counter low bytes */ - volatile unsigned short cpu_adata; /* Arbitration Data */ - volatile unsigned short cpu_pctrl; /* Pin Control */ - volatile unsigned short cpu_pdata; /* Pin Data */ - volatile unsigned short cpu_pdiff; /* Differential Pins */ - unsigned char _unused23[392]; /* Reserved... */ - - /* RISC processor registers. */ - volatile unsigned short risc_a; /* Accumulator */ - volatile unsigned short risc_r[15]; /* General Purpose Registers */ - volatile unsigned short risc_psr; /* Processor Status Register */ - volatile unsigned short risc_ivec; /* Interrupt Vector */ - volatile unsigned short risc_pcr; /* Processor Control Register */ - volatile unsigned short risc_raddr0; /* RAM Addr reg 0 */ - volatile unsigned short risc_raddr1; /* RAM Addr reg 1 */ - volatile unsigned short risc_lcr; /* Loop Counter reg */ - volatile unsigned short risc_pc; /* Program Counter */ - volatile unsigned short risc_mtreg; /* Memory Timing reg */ - volatile unsigned short risc_embreg; /* External Memory Boundry reg */ - volatile unsigned short risc_sp; /* Stack Pointer */ - volatile unsigned short risc_hrev; /* Hardware Revision */ - unsigned char _unused24[10]; /* Reserved... */ - - /* Generic control/command registers. */ - volatile unsigned short hcctrl; /* Host cmd/control reg */ - volatile unsigned short pbkpt0; /* Processor Breakpoint 0 */ - volatile unsigned short pbkpt1; /* Processor Breakpoint 1 */ - volatile unsigned short tcntrl; /* Test Control reg */ - volatile unsigned short tmreg; /* Test Mode reg */ -}; +/* Qlogic/SBUS controller registers. */ +#define SBUS_CFG1 0x006UL +#define SBUS_CTRL 0x008UL +#define SBUS_STAT 0x00aUL +#define SBUS_SEMAPHORE 0x00cUL +#define CMD_DMA_CTRL 0x022UL +#define DATA_DMA_CTRL 0x042UL +#define MBOX0 0x080UL +#define MBOX1 0x082UL +#define MBOX2 0x084UL +#define MBOX3 0x086UL +#define MBOX4 0x088UL +#define MBOX5 0x08aUL +#define CPU_CMD 0x214UL +#define CPU_ORIDE 0x224UL +#define CPU_PCTRL 0x272UL +#define CPU_PDIFF 0x276UL +#define RISC_PSR 0x420UL +#define RISC_MTREG 0x42EUL +#define HCCTRL 0x440UL +/* SCSI parameters for this driver. */ #define MAX_TARGETS 16 #define MAX_LUNS 8 @@ -149,8 +42,8 @@ * requests are queued serially and the scatter/gather limit is * determined for each queue request anew. */ -#define QLOGICISP_REQ_QUEUE_LEN 255 /* must be power of two - 1 */ -#define QLOGICISP_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0) +#define QLOGICPTI_REQ_QUEUE_LEN 255 /* must be power of two - 1 */ +#define QLOGICPTI_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0) #ifndef NULL #define NULL (0) @@ -160,6 +53,7 @@ int qlogicpti_release(struct Scsi_Host *); const char * qlogicpti_info(struct Scsi_Host *); int qlogicpti_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); +int qlogicpti_queuecommand_slow(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int qlogicpti_abort(Scsi_Cmnd *); int qlogicpti_reset(Scsi_Cmnd *, unsigned int); @@ -182,15 +76,15 @@ /* Am I fucking pedantic or what? */ struct Entry_header { #ifdef __BIG_ENDIAN - u_char entry_cnt; - u_char entry_type; - u_char flags; - u_char sys_def_1; + u8 entry_cnt; + u8 entry_type; + u8 flags; + u8 sys_def_1; #else /* __LITTLE_ENDIAN */ - u_char entry_type; - u_char entry_cnt; - u_char sys_def_1; - u_char flags; + u8 entry_type; + u8 entry_cnt; + u8 sys_def_1; + u8 flags; #endif }; @@ -208,26 +102,26 @@ #define EFLAG_BAD_PAYLOAD 8 struct dataseg { - u_int d_base; - u_int d_count; + u32 d_base; + u32 d_count; }; struct Command_Entry { struct Entry_header hdr; - u_int handle; + u32 handle; #ifdef __BIG_ENDIAN - u_char target_id; - u_char target_lun; + u8 target_id; + u8 target_lun; #else /* __LITTLE_ENDIAN */ - u_char target_lun; - u_char target_id; + u8 target_lun; + u8 target_id; #endif - u_short cdb_length; - u_short control_flags; - u_short rsvd; - u_short time_out; - u_short segment_cnt; - u_char cdb[12]; + u16 cdb_length; + u16 control_flags; + u16 rsvd; + u16 time_out; + u16 segment_cnt; + u8 cdb[12]; struct dataseg dataseg[4]; }; @@ -242,46 +136,46 @@ struct Ext_Command_Entry { struct Entry_header hdr; - u_int handle; + u32 handle; #ifdef __BIG_ENDIAN - u_char target_id; - u_char target_lun; + u8 target_id; + u8 target_lun; #else /* __LITTLE_ENDIAN */ - u_char target_lun; - u_char target_id; + u8 target_lun; + u8 target_id; #endif - u_short cdb_length; - u_short control_flags; - u_short rsvd; - u_short time_out; - u_short segment_cnt; - u_char cdb[44]; + u16 cdb_length; + u16 control_flags; + u16 rsvd; + u16 time_out; + u16 segment_cnt; + u8 cdb[44]; }; struct Continuation_Entry { struct Entry_header hdr; - u_int reserved; + u32 reserved; struct dataseg dataseg[7]; }; struct Marker_Entry { struct Entry_header hdr; - u_int reserved; + u32 reserved; #ifdef __BIG_ENDIAN - u_char target_id; - u_char target_lun; + u8 target_id; + u8 target_lun; #else /* __LITTLE_ENDIAN */ - u_char target_lun; - u_char target_id; + u8 target_lun; + u8 target_id; #endif #ifdef __BIG_ENDIAN - u_char rsvd; - u_char modifier; + u8 rsvd; + u8 modifier; #else /* __LITTLE_ENDIAN */ - u_char modifier; - u_char rsvd; + u8 modifier; + u8 rsvd; #endif - u_char rsvds[52]; + u8 rsvds[52]; }; /* marker entry modifier definitions */ @@ -291,16 +185,16 @@ struct Status_Entry { struct Entry_header hdr; - u_int handle; - u_short scsi_status; - u_short completion_status; - u_short state_flags; - u_short status_flags; - u_short time; - u_short req_sense_len; - u_int residual; - u_char rsvd[8]; - u_char req_sense_data[32]; + u32 handle; + u16 scsi_status; + u16 completion_status; + u16 state_flags; + u16 status_flags; + u16 time; + u16 req_sense_len; + u32 residual; + u8 rsvd[8]; + u8 req_sense_data[32]; }; /* status entry completion status definitions */ @@ -439,9 +333,9 @@ #define RES_QUEUE_LEN 255 /* Must be power of two - 1 */ #define QUEUE_ENTRY_LEN 64 -#define NEXT_REQ_PTR(wheee) (((wheee) + 1) & QLOGICISP_REQ_QUEUE_LEN) +#define NEXT_REQ_PTR(wheee) (((wheee) + 1) & QLOGICPTI_REQ_QUEUE_LEN) #define NEXT_RES_PTR(wheee) (((wheee) + 1) & RES_QUEUE_LEN) -#define PREV_REQ_PTR(wheee) (((wheee) - 1) & QLOGICISP_REQ_QUEUE_LEN) +#define PREV_REQ_PTR(wheee) (((wheee) - 1) & QLOGICPTI_REQ_QUEUE_LEN) #define PREV_RES_PTR(wheee) (((wheee) - 1) & RES_QUEUE_LEN) struct pti_queue_entry { @@ -451,41 +345,43 @@ /* Software state for the driver. */ struct qlogicpti { /* These are the hot elements in the cache, so they come first. */ - struct qlogicpti *next; /* Next active adapter */ - struct qlogicpti_regs *qregs; /* Adapter registers */ + spinlock_t lock; /* Driver mutex */ + unsigned long qregs; /* Adapter registers */ struct pti_queue_entry *res_cpu; /* Ptr to RESPONSE bufs (CPU) */ struct pti_queue_entry *req_cpu; /* Ptr to REQUEST bufs (CPU) */ - __u32 res_dvma; /* Ptr to RESPONSE bufs (DVMA)*/ - __u32 req_dvma; /* Ptr to REQUEST bufs (DVMA) */ u_int req_in_ptr; /* index of next request slot */ u_int res_out_ptr; /* index of next result slot */ + long send_marker; /* must we send a marker? */ + struct sbus_dev *sdev; + unsigned long __pad; int cmd_count[MAX_TARGETS]; unsigned long tag_ages[MAX_TARGETS]; - long send_marker; /* must we send a marker? */ /* The cmd->handler is only 32-bits, so that things work even on monster * Ex000 sparc64 machines with >4GB of ram we just keep track of the * scsi command pointers here. This is essentially what Matt Jacob does. -DaveM */ - Scsi_Cmnd *cmd_slots[QLOGICISP_REQ_QUEUE_LEN + 1]; + Scsi_Cmnd *cmd_slots[QLOGICPTI_REQ_QUEUE_LEN + 1]; /* The rest of the elements are unimportant for performance. */ - u_char fware_majrev, fware_minrev; + struct qlogicpti *next; + __u32 res_dvma; /* Ptr to RESPONSE bufs (DVMA)*/ + __u32 req_dvma; /* Ptr to REQUEST bufs (DVMA) */ + u_char fware_majrev, fware_minrev, fware_micrev; struct Scsi_Host *qhost; - struct linux_sbus_device *qdev; int qpti_id; int scsi_id; int prom_node; char prom_name[64]; int irq; - char differential, ultra; + char differential, ultra, clock; unsigned char bursts; struct host_param host_param; struct dev_param dev_param[MAX_TARGETS]; - volatile unsigned char *sreg; + unsigned long sreg; #define SREG_TPOWER 0x80 /* State of termpwr */ #define SREG_FUSE 0x40 /* State of on board fuse */ #define SREG_PDISAB 0x20 /* Disable state for power on */ @@ -493,14 +389,14 @@ #define SREG_IMASK 0x0c /* Interrupt level */ #define SREG_SPMASK 0x03 /* Mask for switch pack */ unsigned char swsreg; - unsigned char is_pti; /* Non-zero if this is a PTI board. */ + unsigned int + gotirq : 1, /* this instance got an irq */ + is_pti : 1, /* Non-zero if this is a PTI board. */ + sbits : 16; /* syncmode known bits */ }; /* How to twiddle them bits... */ -/* SBUS config register zero. */ -#define SBUS_CFG0_HREVMASK 0x000f /* To get the revision */ - /* SBUS config register one. */ #define SBUS_CFG1_EPAR 0x0100 /* Enable parity checking */ #define SBUS_CFG1_FMASK 0x00f0 /* Forth code cycle mask */ @@ -529,12 +425,6 @@ #define SBUS_SEMAPHORE_STAT 0x0002 /* Semaphore status bit */ #define SBUS_SEMAPHORE_LCK 0x0001 /* Semaphore lock bit */ -/* DVMA config register */ -#define DMA_CFG_DVMAENAB 0x0008 /* Enable scsi cpu --> dma data */ -#define DMA_CFG_EIRQ 0x0004 /* Enable interrupts to risc cpu */ -#define DMA_CFG_EBURST 0x0002 /* Enable sbus dvma bursts */ -#define DMA_CFG_DIRECTION 0x0001 /* DMA direction (0=fifo->ram) */ - /* DVMA control register */ #define DMA_CTRL_CSUSPEND 0x0010 /* DMA channel suspend */ #define DMA_CTRL_CCLEAR 0x0008 /* DMA channel clear and reset */ @@ -542,72 +432,6 @@ #define DMA_CTRL_CIRQ 0x0002 /* DMA irq clear */ #define DMA_CTRL_DMASTART 0x0001 /* DMA transfer start */ -/* DVMA status register */ -#define DMA_STAT_PFULL 0x00c0 /* Pipe full */ -#define DMA_STAT_PORUN 0x0080 /* Pipe overrun */ -#define DMA_STAT_PSTG1 0x0040 /* Pipe has stage 1 loaded */ -#define DMA_STAT_PEMPTY 0x0000 /* Pipe is empty */ -#define DMA_STAT_CSUSP 0x0030 /* Channel suspended */ -#define DMA_STAT_CTRAN 0x0020 /* Channel transfer in progress */ -#define DMA_STAT_CACTIVE 0x0010 /* Channel active */ -#define DMA_STAT_CIDLE 0x0000 /* Channel idle */ -#define DMA_STAT_SPAR 0x0008 /* SBUS parity error */ -#define DMA_STAT_SERR 0x0004 /* SBUS dma error */ -#define DMA_STAT_TCNT 0x0002 /* Terminal count expired */ -#define DMA_STAT_IRQ 0x0001 /* DMA interrupt */ - -/* DVMA FIFO status register */ -#define DMA_FSTAT_ORUN 0x0200 /* FIFO overrun */ -#define DMA_FSTAT_URUN 0x0100 /* FIFO underrun */ -#define DMA_FSTAT_CMASK 0x007f /* FIFO count mask */ - -/* SCSI processor config 1 register */ -#define CPU_CFG1_ASTIME 0xf000 /* Asynchronous setup time mask */ -#define CPU_CFG1_STUNIT 0x0000 /* Selection time unit */ -#define CPU_CFG1_STIMEO 0x0600 /* Selection timeout value */ -#define CPU_CFG1_CFACT 0x00e0 /* Clock factor */ -#define CPU_CFG1_SID 0x000f /* SCSI ID */ - -/* SCSI processor config 2 register */ -#define CPU_CFG2_FDISAB 0x0040 /* SCSI filter disable */ -#define CPU_CFG2_ERAPUPS 0x0020 /* Req/Ack pullup enable */ -#define CPU_CFG2_EDPUPS 0x0010 /* Data active pullup enable */ -#define CPU_CFG2_ECAUTO 0x0008 /* Autoload device config enable */ -#define CPU_CFG2_ERESEL 0x0002 /* Enable reselections */ -#define CPU_CFG2_ESEL 0x0001 /* Enable selections */ - -/* SCSI processor interrupt register */ -#define CPU_IRQ_PERR 0x8000 /* Parity error */ -#define CPU_IRQ_GERR 0x4000 /* Gross error */ -#define CPU_IRQ_FABORT 0x2000 /* Function abort */ -#define CPU_IRQ_CFAIL 0x1000 /* Condition failed */ -#define CPU_IRQ_FEMPTY 0x0800 /* FIFO empty */ -#define CPU_IRQ_BCZ 0x0400 /* Byte counter is zero */ -#define CPU_IRQ_XZ 0x0200 /* Transfer counter is zero */ -#define CPU_IRQ_IRQ 0x0080 /* SCSI processor interrupt pending */ -#define CPU_IRQ_CRUN 0x0040 /* Command is running */ -#define CPU_IRQ_RCODE 0x000f /* Return code for interrupt */ - -/* SCSI processor gross error register */ -#define CPU_GERR_ONZ 0x0040 /* Offset not zero */ -#define CPU_GERR_OUF 0x0020 /* Offset underflowed */ -#define CPU_GERR_OOF 0x0010 /* Offset overflowed */ -#define CPU_GERR_FUF 0x0008 /* FIFO underflowed */ -#define CPU_GERR_FOF 0x0004 /* FIFO overflowed */ -#define CPU_GERR_WERR 0x0002 /* Error on write */ -#define CPU_GERR_ILL 0x0001 /* Instruction was illegal */ - -/* SCSI processor exception register */ -#define CPU_EXC_UZERO 0x8000 /* User exception zero */ -#define CPU_EXC_UONE 0x4000 /* User exception one */ -#define CPU_EXC_BFREE 0x0200 /* Bus free */ -#define CPU_EXC_TATN 0x0100 /* ATN in target mode */ -#define CPU_EXC_RESEL 0x0080 /* Reselect exception */ -#define CPU_EXC_SEL 0x0040 /* Selection exception */ -#define CPU_EXC_ARB 0x0020 /* Arbitration exception */ -#define CPU_EXC_GERR 0x0010 /* Gross error exception */ -#define CPU_EXC_RESET 0x0008 /* Bus reset exception */ - /* SCSI processor override register */ #define CPU_ORIDE_ETRIG 0x8000 /* External trigger enable */ #define CPU_ORIDE_STEP 0x4000 /* Single step mode enable */ @@ -626,38 +450,6 @@ /* SCSI processor commands */ #define CPU_CMD_BRESET 0x300b /* Reset SCSI bus */ -/* SCSI processor user exception register */ -#define CPU_UEXC_ONE 0x0002 /* User exception one */ -#define CPU_UEXC_ZERO 0x0001 /* User exception zero */ - -/* SCSI processor SCSI id register */ -#define CPU_SID_RSEID 0x0f00 /* Who is sel/resel'ing us */ -#define CPU_SID_SID 0x000f /* Selection ID */ - -/* SCSI processor device config 1 */ -#define CPU_DCFG1_SHOLD 0x7000 /* Sync data hold */ -#define CPU_DCFG1_SSETUP 0x0f00 /* Sync data setup */ -#define CPU_DCFG1_SOFF 0x000f /* Sync data offset */ - -/* SCSI processor device config 2 */ -#define CPU_DCFG2_FMASK 0xf000 /* Device flags */ -#define CPU_DCFG2_EWIDE 0x0400 /* WIDE enable */ -#define CPU_DCFG2_EPAR 0x0200 /* Parity enable */ -#define CPU_DCFG2_EBLK 0x0100 /* Block mode transfer enable */ -#define CPU_DCFG2_AMASK 0x0007 /* Assertion period mask */ - -/* SCSI processor phase pointer register */ -#define CPU_PPTR_STAT 0x1000 /* Status buf offset */ -#define CPU_PPTR_MSGIN 0x0700 /* Msg-in buf offset */ -#define CPU_PPTR_COM 0x00f0 /* Cmd buf offset */ -#define CPU_PPTR_MSGOUT 0x0007 /* Msg-out buf offset */ - -/* SCSI processor fifo status register */ -#define CPU_FSTAT_TFULL 0x8000 /* Top residue full */ -#define CPU_FSTAT_ARES 0x4000 /* Odd residue for wide transfer */ -#define CPU_FSTAT_CMSK 0x001c /* FIFO count mask */ -#define CPU_FSTAT_BRES 0x0001 /* Bottom residue full */ - /* SCSI processor pin control register */ #define CPU_PCTRL_PVALID 0x8000 /* Phase bits are valid */ #define CPU_PCTRL_PHI 0x0400 /* Parity bit high */ @@ -724,14 +516,14 @@ detect: qlogicpti_detect, \ release: qlogicpti_release, \ info: qlogicpti_info, \ - queuecommand: qlogicpti_queuecommand, \ + queuecommand: qlogicpti_queuecommand_slow, \ abort: qlogicpti_abort, \ reset: qlogicpti_reset, \ - can_queue: QLOGICISP_REQ_QUEUE_LEN, \ + can_queue: QLOGICPTI_REQ_QUEUE_LEN, \ this_id: 7, \ - sg_tablesize: QLOGICISP_MAX_SG(QLOGICISP_REQ_QUEUE_LEN), \ + sg_tablesize: QLOGICPTI_MAX_SG(QLOGICPTI_REQ_QUEUE_LEN), \ cmd_per_lun: 1, \ - use_clustering: DISABLE_CLUSTERING, \ + use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0 \ } diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti_asm.c linux/drivers/scsi/qlogicpti_asm.c --- v2.3.34/linux/drivers/scsi/qlogicpti_asm.c Mon Mar 15 16:11:31 1999 +++ linux/drivers/scsi/qlogicpti_asm.c Mon Dec 20 22:06:42 1999 @@ -1,2298 +1,1160 @@ -/* Version 1.24 Initiator Firmware (Aug 8, 1996) */ - -unsigned short pti_risc_code_addr01 = 0x1000; - -unsigned short pti_risc_code01[] __initdata = { - 0x0078, 0x1030, 0x0000, 0x231f, 0x0000, 0x12ff, 0x2043, 0x4f50, +/* Version 1.31.00 ISP1000 Initiator RISC firmware */ +unsigned short sbus_risc_code01[] __initdata = { + 0x0078, 0x1030, 0x0000, 0x2419, 0x0000, 0x12ff, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, - 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3234, 0x2020, + 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020, 0x20b9, 0x1212, 0x20c1, 0x0008, 0x2071, 0x0010, 0x70c3, 0x0004, - 0x20c9, 0x3eff, 0x2089, 0x10c5, 0x70c7, 0x4953, 0x70cb, 0x5020, + 0x20c9, 0x3fff, 0x2089, 0x10c8, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2031, 0x0030, - 0x2079, 0x3400, 0x7863, 0x0000, 0x2fa0, 0x2009, 0x032b, 0x2011, + 0x2079, 0x3500, 0x7863, 0x0000, 0x2fa0, 0x2009, 0x0327, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109, 0x00c0, 0x1051, 0x789b, 0x0101, 0x780b, 0x0002, 0x780f, 0x0002, 0x784f, 0x0bb8, 0x2069, - 0x3440, 0x00a8, 0x1067, 0x681b, 0x003c, 0x0078, 0x1069, 0x681b, - 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008, 0x6813, - 0x0005, 0x681f, 0x0000, 0x6823, 0x0006, 0x6817, 0x0008, 0x6827, - 0x0000, 0x2069, 0x3500, 0x2011, 0x0020, 0x2009, 0x0010, 0x680b, - 0x0c19, 0x680f, 0x0019, 0x6803, 0xdd00, 0x6807, 0x001a, 0x6a1a, - 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, 0x00c0, 0x107f, - 0x2069, 0x3580, 0x20a9, 0x0080, 0x6837, 0x0000, 0x680b, 0x0040, - 0x6817, 0x0100, 0x681f, 0x0064, 0xade8, 0x0010, 0x0070, 0x10a2, - 0x0078, 0x1094, 0x1078, 0x1a17, 0x1078, 0x2e4c, 0x1078, 0x1670, - 0x1078, 0x32c0, 0x3200, 0xa085, 0x000d, 0x2090, 0x70c3, 0x0000, - 0x0090, 0x10b9, 0x70c0, 0xa086, 0x0002, 0x00c0, 0x10b9, 0x1078, - 0x11b8, 0x1078, 0x10e9, 0x1078, 0x17f8, 0x1078, 0x1989, 0x1078, - 0x3187, 0x1078, 0x1766, 0x0078, 0x10b9, 0x10cd, 0x10cf, 0x1b6c, - 0x1b6c, 0x2ea6, 0x2ea6, 0x1b6c, 0x1b6c, 0x0078, 0x10cd, 0x0078, - 0x10cf, 0x0078, 0x10d1, 0x0078, 0x10d3, 0x7008, 0x800c, 0x00c8, - 0x10e4, 0x7007, 0x0002, 0xa08c, 0x000c, 0x00c0, 0x10e5, 0x8004, - 0x8004, 0x00c8, 0x10e4, 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, - 0x11bb, 0x0068, 0x1135, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, - 0x00c0, 0x1135, 0x7814, 0xa005, 0x00c0, 0x10fa, 0x0010, 0x1136, - 0x0078, 0x1135, 0x2009, 0x3468, 0x2104, 0xa005, 0x00c0, 0x1135, - 0x7814, 0xa086, 0x0001, 0x00c0, 0x1107, 0x1078, 0x1529, 0x7817, - 0x0000, 0x2009, 0x346f, 0x2104, 0xa065, 0x0040, 0x1123, 0x2009, - 0x346a, 0x211c, 0x8108, 0x2114, 0x8108, 0x2104, 0xa210, 0xa399, - 0x0000, 0x2009, 0x001c, 0x6083, 0x0103, 0x1078, 0x1600, 0x00c0, - 0x112f, 0x1078, 0x1667, 0x2009, 0x346f, 0x200b, 0x0000, 0x2009, - 0x3469, 0x2104, 0x200b, 0x0000, 0xa005, 0x0040, 0x1133, 0x2001, - 0x4005, 0x0078, 0x11ba, 0x0078, 0x11b8, 0x007c, 0x70c3, 0x0000, - 0x70c7, 0x0000, 0x70cb, 0x0000, 0x70cf, 0x0000, 0x70c0, 0xa0bc, - 0xffc0, 0x00c0, 0x1186, 0x2038, 0x0079, 0x1146, 0x11b8, 0x1203, - 0x11d1, 0x1203, 0x1254, 0x1254, 0x11c8, 0x157f, 0x125f, 0x11c4, - 0x11d5, 0x11d7, 0x11d9, 0x11db, 0x1584, 0x11c4, 0x1265, 0x1281, - 0x1537, 0x1579, 0x11dd, 0x1468, 0x148a, 0x14a2, 0x14c5, 0x1421, - 0x142f, 0x1443, 0x1457, 0x12ed, 0x11c4, 0x129d, 0x12a4, 0x12a9, - 0x12ae, 0x12b4, 0x12b9, 0x12be, 0x12c3, 0x12c8, 0x12cc, 0x12e1, - 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x12f9, 0x1302, 0x1311, - 0x1337, 0x1341, 0x1348, 0x136e, 0x137d, 0x138c, 0x139e, 0x1406, - 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x1416, 0xa0bc, 0xffa0, - 0x00c0, 0x11c4, 0x2038, 0xa084, 0x001f, 0x0079, 0x118f, 0x11c4, - 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, - 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, - 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, - 0x11c4, 0x15dc, 0x15e6, 0x15ea, 0x15f8, 0x11c4, 0x11c4, 0x72ca, - 0x71c6, 0x2001, 0x4006, 0x0078, 0x11ba, 0x73ce, 0x72ca, 0x71c6, - 0x2001, 0x4000, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, - 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x11bb, - 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, - 0x11b8, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x11b8, 0x0078, - 0x11b8, 0x0078, 0x11b8, 0x0078, 0x11b8, 0x2091, 0x8000, 0x70c3, - 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, - 0x0001, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, - 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061, - 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091, - 0x4080, 0x0078, 0x0455, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, - 0x2098, 0x2031, 0x0030, 0x81ff, 0x0040, 0x11b8, 0x7007, 0x0004, - 0x731a, 0x721e, 0x2051, 0x0012, 0x2049, 0x1232, 0x2041, 0x11b8, - 0x7003, 0x0002, 0xa786, 0x0001, 0x00c0, 0x1224, 0x2049, 0x1240, - 0x2041, 0x124c, 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, - 0x00c8, 0x122c, 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, - 0x0040, 0x1240, 0x700c, 0xa084, 0x007f, 0x8004, 0x2009, 0x0020, - 0xa102, 0x0942, 0x094a, 0x20a8, 0x26a0, 0x53a6, 0x0078, 0x10d5, - 0x700c, 0xa084, 0x007f, 0x0040, 0x1240, 0x80ac, 0x0048, 0x1240, - 0x2698, 0x53a5, 0x0078, 0x10d5, 0x700c, 0xa084, 0x007f, 0x80ac, - 0x2698, 0x53a5, 0x0078, 0x11b8, 0x71c4, 0x70c8, 0x2114, 0xa79e, - 0x0004, 0x00c0, 0x125c, 0x200a, 0x72ca, 0x0078, 0x11b7, 0x70c7, - 0x0001, 0x70cb, 0x0018, 0x0078, 0x11b8, 0x70c4, 0x72c8, 0x73cc, - 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x127b, - 0x8001, 0x7872, 0x7a7a, 0x7b7e, 0x7c76, 0x7898, 0xa084, 0xfffc, - 0x789a, 0x0078, 0x127f, 0x7898, 0xa085, 0x0001, 0x789a, 0x0078, - 0x11b8, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, - 0x74d6, 0xa005, 0x0040, 0x1297, 0x8001, 0x7886, 0x7a8e, 0x7b92, - 0x7c8a, 0x7898, 0xa084, 0xfcff, 0x789a, 0x0078, 0x129b, 0x7898, - 0xa085, 0x0100, 0x789a, 0x0078, 0x11b8, 0x2009, 0x3459, 0x210c, - 0x2011, 0x042c, 0x0078, 0x11b6, 0x2009, 0x3441, 0x210c, 0x0078, - 0x11b7, 0x2009, 0x3442, 0x210c, 0x0078, 0x11b7, 0x2061, 0x3440, - 0x610c, 0x6210, 0x0078, 0x11b6, 0x2009, 0x3445, 0x210c, 0x0078, - 0x11b7, 0x2009, 0x3446, 0x210c, 0x0078, 0x11b7, 0x2009, 0x3447, - 0x210c, 0x0078, 0x11b7, 0x2009, 0x3448, 0x210c, 0x0078, 0x11b7, - 0x7908, 0x7a0c, 0x0078, 0x11b6, 0x71c4, 0x8107, 0xa084, 0x000f, - 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3500, 0x6a00, 0x6804, 0xa084, - 0x0008, 0x0040, 0x12de, 0x6b08, 0x0078, 0x12df, 0x6b0c, 0x0078, - 0x11b5, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000, 0x6b1c, 0x6a14, - 0x2091, 0x8001, 0x2708, 0x0078, 0x11b5, 0x77c4, 0x1078, 0x1681, - 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, - 0x11b5, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x1078, 0x1a9b, - 0x0078, 0x11b5, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x2011, - 0x3441, 0x2204, 0x007e, 0x2112, 0x1078, 0x1a54, 0x017f, 0x0078, - 0x11b7, 0x71c4, 0x2011, 0x132f, 0x20a9, 0x0008, 0x2204, 0xa106, - 0x0040, 0x1321, 0x8210, 0x0070, 0x131f, 0x0078, 0x1316, 0x0078, - 0x11b0, 0xa292, 0x132f, 0x027e, 0x2011, 0x3442, 0x2204, 0x2112, - 0x017f, 0x007e, 0x1078, 0x1a60, 0x017f, 0x0078, 0x11b7, 0x03e8, - 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, - 0x3440, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, - 0x11b6, 0x2061, 0x3440, 0x6114, 0x70c4, 0x6016, 0x0078, 0x11b7, - 0x71c4, 0x2011, 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, - 0x1361, 0x2011, 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, - 0x1361, 0x2011, 0x0006, 0x2019, 0x2323, 0xa186, 0x003c, 0x00c0, - 0x11b0, 0x2061, 0x3440, 0x6018, 0x007e, 0x611a, 0x23b8, 0x1078, - 0x1a71, 0x1078, 0x32c0, 0x017f, 0x0078, 0x11b7, 0x71c4, 0xa184, - 0xffcf, 0x00c0, 0x11b0, 0x2011, 0x3447, 0x2204, 0x2112, 0x007e, - 0x1078, 0x1a93, 0x017f, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, - 0x00c8, 0x11b0, 0x2011, 0x3448, 0x2204, 0x007e, 0x2112, 0x1078, - 0x1a82, 0x017f, 0x0078, 0x11b7, 0x71c4, 0x72c8, 0xa184, 0xfffd, - 0x00c0, 0x11af, 0xa284, 0xfffd, 0x00c0, 0x11af, 0x2100, 0x7908, - 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x11b6, 0x71c4, 0x8107, - 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3500, 0x2019, - 0x0000, 0x72c8, 0x6800, 0x007e, 0xa226, 0x0040, 0x13cd, 0x6a02, - 0xa484, 0x2000, 0x0040, 0x13b6, 0xa39d, 0x0010, 0xa484, 0x1000, - 0x0040, 0x13bc, 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x13cd, - 0x810f, 0xa284, 0x4000, 0x0040, 0x13c9, 0x1078, 0x1ab5, 0x0078, - 0x13cd, 0x1078, 0x1aa7, 0x0078, 0x13cd, 0x72cc, 0x82ff, 0x0040, - 0x13ff, 0x6808, 0xa206, 0x0040, 0x13ff, 0xa2a4, 0x00ff, 0x2061, - 0x3440, 0x6118, 0xa186, 0x0028, 0x0040, 0x13e6, 0xa186, 0x0032, - 0x0040, 0x13ec, 0xa186, 0x003c, 0x0040, 0x13f2, 0xa482, 0x0064, - 0x0048, 0x13fc, 0x0078, 0x13f6, 0xa482, 0x0050, 0x0048, 0x13fc, - 0x0078, 0x13f6, 0xa482, 0x0043, 0x0048, 0x13fc, 0x71c4, 0x71c6, - 0x027f, 0x72ca, 0x0078, 0x11b1, 0x6a0a, 0xa39d, 0x000a, 0x6804, - 0xa305, 0x6806, 0x027f, 0x6b0c, 0x0078, 0x11b5, 0x77c4, 0x1078, - 0x1681, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, - 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x11b5, 0x71c4, 0x72c8, - 0x73cc, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x1078, 0x1ac3, 0x0078, - 0x11b5, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000, 0x6a08, 0xa295, - 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b6, 0x77c4, - 0x1078, 0x1681, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, - 0x6804, 0xa005, 0x0040, 0x143e, 0x1078, 0x19f8, 0x2091, 0x8001, - 0x2708, 0x0078, 0x11b6, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000, - 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1452, - 0x1078, 0x19f8, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b6, 0x77c4, - 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, - 0x1078, 0x168e, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x11b6, - 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1707, - 0x00c0, 0x1486, 0x6818, 0xa005, 0x0040, 0x1480, 0x2708, 0x1078, - 0x1ad3, 0x00c0, 0x1480, 0x7817, 0xffff, 0x2091, 0x8001, 0x007c, - 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x11ba, 0x2091, 0x8001, - 0x0078, 0x11b8, 0x77c4, 0x77c6, 0x2061, 0x3440, 0x60a3, 0x0003, - 0x67b6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, - 0x8000, 0x1078, 0x168e, 0x2091, 0x8001, 0x7817, 0xffff, 0x1078, - 0x19f8, 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, - 0x2061, 0x3440, 0x60a3, 0x0002, 0x67b6, 0x7817, 0xffff, 0x1078, - 0x19f8, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, - 0x8000, 0x1078, 0x168e, 0x70c8, 0x6836, 0x8738, 0xa784, 0x0007, - 0x00c0, 0x14b9, 0x2091, 0x8001, 0x007c, 0x7898, 0xa084, 0x0003, - 0x00c0, 0x14e9, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, - 0x2051, 0x0008, 0x1078, 0x1681, 0x2091, 0x8000, 0x6808, 0xa80d, - 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x0007, 0x00c0, 0x14d2, - 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, - 0x14d2, 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, - 0x0040, 0x1512, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, - 0x0004, 0x0040, 0x14ff, 0x0070, 0x14ff, 0x0078, 0x14f6, 0x684b, - 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x150c, - 0x0070, 0x150c, 0x0078, 0x1503, 0x20a9, 0x00fa, 0x0070, 0x1512, - 0x0078, 0x150e, 0x2079, 0x3400, 0x7817, 0x0001, 0x2061, 0x3440, - 0x60a3, 0x0001, 0x60c3, 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, - 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, - 0x007c, 0x7898, 0xa084, 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, - 0x1533, 0x1078, 0x1749, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, - 0x73c8, 0x72cc, 0x74c6, 0x73ca, 0x72ce, 0x2079, 0x3400, 0x2009, - 0x0040, 0x1078, 0x165e, 0x0040, 0x1575, 0x1078, 0x162e, 0x0040, - 0x154d, 0x1078, 0x1667, 0x0078, 0x1575, 0x6010, 0x7817, 0xffff, - 0x2009, 0x3468, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, 0x8108, - 0x230a, 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, 0x8108, - 0x200b, 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, 0x1078, - 0x2e25, 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, - 0x60af, 0x0000, 0x1078, 0x19f8, 0x007c, 0x70c3, 0x4005, 0x0078, - 0x11bb, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x11b8, 0x71c4, - 0x71c6, 0x2168, 0x0078, 0x1586, 0x2069, 0x1000, 0x690c, 0xa016, - 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1588, 0xa285, 0x0000, - 0x00c0, 0x1596, 0x70c3, 0x4000, 0x0078, 0x1598, 0x70c3, 0x4003, - 0x70ca, 0x0078, 0x11bb, 0x71c4, 0x72c8, 0x73cc, 0x2100, 0xa184, - 0xfffc, 0x00c0, 0x11c4, 0x2100, 0x0079, 0x15a6, 0x15bd, 0x15d2, - 0x15d4, 0x15d6, 0x70c3, 0x4003, 0x71ce, 0x72d2, 0x73d6, 0x0078, - 0x15b9, 0x70c3, 0x4000, 0x70cf, 0x0000, 0x70d3, 0x0000, 0x70d7, - 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11b8, 0x2031, 0x15d8, 0x2624, - 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, 0x15aa, 0xa484, 0xffff, - 0x00c0, 0x15bf, 0x2031, 0x15d8, 0x8210, 0x8319, 0xa384, 0xffff, - 0x00c0, 0x15bf, 0x0078, 0x15b1, 0x0078, 0x15b1, 0x0078, 0x15b1, - 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, 0x71c6, 0x71c4, 0xa182, - 0x0003, 0x00c8, 0x11b0, 0x7962, 0x0078, 0x11b8, 0x7960, 0x71c6, - 0x0078, 0x11b8, 0x7954, 0x71c6, 0x71c4, 0x7956, 0x7958, 0x71ca, - 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, 0x795e, 0x0078, 0x11b8, - 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, 0x71ce, 0x0078, 0x11b8, - 0x700c, 0xa084, 0x007f, 0x0040, 0x160c, 0x7007, 0x0004, 0x7004, - 0xa084, 0x0004, 0x00c0, 0x1607, 0x7017, 0x0000, 0x7112, 0x721a, - 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, 0x20a1, 0x0030, 0x6080, - 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007, 0x0001, - 0x7108, 0x8104, 0x00c8, 0x1620, 0x7007, 0x0002, 0xa184, 0x000c, - 0x710c, 0xa184, 0x0300, 0x7003, 0x0000, 0x007c, 0x700c, 0xa084, - 0x007f, 0x0040, 0x163a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x1635, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e, 0x2099, - 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007, - 0x0001, 0x7008, 0x800c, 0x00c8, 0x1649, 0x7007, 0x0002, 0xa08c, - 0x000c, 0x00c0, 0x165b, 0x710c, 0xa184, 0x0300, 0x00c0, 0x165b, - 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850, 0xa065, - 0x0040, 0x1666, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e, - 0x2079, 0x3400, 0x7850, 0x2062, 0x2c00, 0x7852, 0x0f7f, 0x007c, - 0x2011, 0x3f00, 0x7a52, 0x2019, 0x042c, 0x8319, 0x0040, 0x167e, - 0xa280, 0x002e, 0x2012, 0x2010, 0x0078, 0x1675, 0x2013, 0x0000, - 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003, - 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3580, 0x007c, 0x1078, 0x1681, - 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xffef, 0xa80d, - 0x690a, 0x2009, 0x344f, 0x210c, 0x6804, 0xa005, 0x0040, 0x16ab, - 0xa116, 0x00c0, 0x16ab, 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, - 0x0000, 0x0078, 0x16ae, 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, - 0x0040, 0x16bd, 0x6000, 0x6806, 0x1078, 0x16ce, 0x1078, 0x17ac, - 0x6810, 0x8001, 0x6812, 0x00c0, 0x16ae, 0x017f, 0x6902, 0x6906, - 0x007c, 0xa065, 0x0040, 0x16cd, 0x6098, 0x609b, 0x0000, 0x2008, - 0x1078, 0x1667, 0x2100, 0x0078, 0x16c1, 0x007c, 0x6003, 0x0103, - 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, 0x2001, 0x0000, 0x40a4, - 0x6828, 0x6016, 0x682c, 0x601e, 0x007c, 0x0e7e, 0x2071, 0x3440, - 0x7040, 0xa08c, 0x0080, 0x00c0, 0x16eb, 0xa088, 0x3480, 0x2d0a, - 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x3440, - 0x2009, 0x3480, 0x7240, 0x8221, 0x8211, 0x0048, 0x1705, 0x2104, - 0x8108, 0xad06, 0x00c0, 0x16f4, 0x8119, 0x211e, 0x8108, 0x8318, - 0x8211, 0x00c8, 0x16fd, 0x7442, 0xa006, 0x0e7f, 0x007c, 0x1078, - 0x1681, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065, 0x0040, 0x1748, - 0x0078, 0x1718, 0x2c00, 0x781e, 0x6000, 0xa065, 0x0040, 0x1748, - 0x600c, 0xa306, 0x00c0, 0x1712, 0x6008, 0xa206, 0x00c0, 0x1712, - 0x2c28, 0x6804, 0xac06, 0x00c0, 0x172f, 0x6000, 0x2060, 0x6806, - 0xa005, 0x00c0, 0x172f, 0x6803, 0x0000, 0x0078, 0x1739, 0x6400, - 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1739, 0x2c00, - 0x6802, 0x2560, 0x1078, 0x16ce, 0x6017, 0x0005, 0x601f, 0x0020, - 0x1078, 0x17ac, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, - 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, - 0x0008, 0x2091, 0x8000, 0x1078, 0x168e, 0x8738, 0xa784, 0x0007, - 0x00c0, 0x1753, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, - 0x0f00, 0x00c0, 0x1753, 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, - 0x6018, 0xa084, 0x0001, 0x00c0, 0x1773, 0x78ac, 0x78af, 0x0000, - 0xa005, 0x00c0, 0x1774, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x177a, - 0x1078, 0x1b4e, 0x0079, 0x177c, 0x178c, 0x178e, 0x1794, 0x1798, - 0x178c, 0x179c, 0x178c, 0x178c, 0x178c, 0x178c, 0x17a2, 0x17a6, - 0x178c, 0x178c, 0x178c, 0x178c, 0x1078, 0x1b4e, 0x1078, 0x1749, - 0x2001, 0x8001, 0x0078, 0x11ba, 0x2001, 0x8003, 0x0078, 0x11ba, - 0x2001, 0x8004, 0x0078, 0x11ba, 0x1078, 0x1749, 0x2001, 0x8006, - 0x0078, 0x11ba, 0x2001, 0x800c, 0x0078, 0x11ba, 0x1078, 0x1749, - 0x2001, 0x800d, 0x0078, 0x11ba, 0x2c04, 0x6082, 0x2c08, 0x2063, - 0x0000, 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, 0x0040, - 0x17bc, 0x2c02, 0x0078, 0x17bd, 0x796e, 0x007c, 0x0c7e, 0x2061, - 0x3400, 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, 0x8000, - 0x6066, 0x6068, 0xa005, 0x616a, 0x0040, 0x17d1, 0x2d02, 0x0078, - 0x17d2, 0x616e, 0x0c7f, 0x007c, 0x1078, 0x17e5, 0x0040, 0x17e4, - 0x0c7e, 0x6098, 0xa065, 0x0040, 0x17df, 0x1078, 0x16c1, 0x0c7f, - 0x609b, 0x0000, 0x1078, 0x1667, 0x007c, 0x786c, 0xa065, 0x0040, - 0x17f7, 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, 0x786e, - 0xa005, 0x00c0, 0x17f5, 0x786a, 0x8000, 0x2091, 0x8001, 0x007c, - 0x7898, 0xa005, 0x00c0, 0x1846, 0x7974, 0x70d0, 0x0005, 0x0005, - 0x72d0, 0xa206, 0x00c0, 0x17fd, 0x2200, 0xa106, 0x00c0, 0x1814, - 0x7804, 0xa005, 0x0040, 0x1846, 0x7807, 0x0000, 0x0068, 0x1846, - 0x2091, 0x4080, 0x0078, 0x1846, 0x1078, 0x165e, 0x0040, 0x1846, - 0x7a7c, 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, - 0x2009, 0x0040, 0x1078, 0x162e, 0x0040, 0x183d, 0x1078, 0x1667, - 0x7880, 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x1846, 0x2091, - 0x8000, 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, 0x0003, - 0x789a, 0x2091, 0x8001, 0x0078, 0x1846, 0x7883, 0x0000, 0x1078, - 0x1973, 0x6000, 0xa084, 0x0007, 0x0079, 0x1847, 0x007c, 0x184f, - 0x185e, 0x187e, 0x184f, 0x1890, 0x184f, 0x184f, 0x184f, 0x2039, - 0x0400, 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, 0x1078, - 0x18ce, 0x6018, 0x78a6, 0x1078, 0x195b, 0x007c, 0x78a8, 0xa084, - 0x0100, 0x0040, 0x1865, 0x0078, 0x184f, 0x78ab, 0x0000, 0x6000, - 0x8007, 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, 0x0040, - 0x187b, 0x1078, 0x18ce, 0x0040, 0x187b, 0x78a8, 0xa085, 0x0100, - 0x78aa, 0x0078, 0x187d, 0x1078, 0x18f2, 0x007c, 0x78a8, 0xa08c, - 0x0e00, 0x00c0, 0x1887, 0xa084, 0x0100, 0x00c0, 0x1889, 0x0078, - 0x184f, 0x1078, 0x18ce, 0x00c0, 0x188f, 0x1078, 0x18f2, 0x007c, - 0x78a8, 0xa084, 0x0100, 0x0040, 0x1897, 0x0078, 0x184f, 0x78ab, - 0x0000, 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, 0xa005, - 0x0040, 0x18b4, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, - 0x0040, 0x18b4, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, - 0x0040, 0x18b4, 0x0078, 0x18cb, 0x1078, 0x1681, 0x2d00, 0x2091, - 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, - 0x680a, 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, 0x0070, - 0x18cb, 0x0078, 0x18b7, 0x1078, 0x1667, 0x007c, 0x78a0, 0xa06d, - 0x00c0, 0x18d9, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, 0x0078, - 0x18e5, 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, 0x6002, - 0x78a4, 0xad06, 0x00c0, 0x18e5, 0x6002, 0x789c, 0x8001, 0x789e, - 0x00c0, 0x18f1, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, 0x2060, - 0xa006, 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, 0x619e, - 0x0040, 0x18fe, 0x0e7e, 0x1078, 0x2e25, 0x0e7f, 0x6592, 0x65a2, - 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, 0x1078, - 0x1681, 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, 0x1920, - 0x2091, 0x8001, 0x1078, 0x16ce, 0x2091, 0x8000, 0x1078, 0x17ac, - 0x2091, 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, 0x195a, - 0x6020, 0xa096, 0x0001, 0x00c0, 0x1927, 0x8000, 0x6022, 0x6a10, - 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x1936, 0x0040, 0x1936, - 0x2039, 0x0200, 0x1078, 0x195b, 0x0078, 0x195a, 0x2c08, 0x2091, - 0x8000, 0x6800, 0xa065, 0x0040, 0x193e, 0x6102, 0x6902, 0x00c0, - 0x1942, 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, - 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x1954, 0xa086, - 0x0040, 0x680a, 0x1078, 0x16dd, 0x1078, 0x19f8, 0x78a7, 0x0000, - 0x78a3, 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, 0x8000, - 0x1078, 0x17ac, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, 0x196e, - 0x6098, 0x78a6, 0x609b, 0x0000, 0x0078, 0x195e, 0x78a3, 0x0000, - 0x78a7, 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, 0x00c8, - 0x197a, 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, 0x1988, - 0x8001, 0x7806, 0x00c0, 0x1988, 0x0068, 0x1988, 0x2091, 0x4080, - 0x007c, 0x0068, 0x19a1, 0x2029, 0x0000, 0x786c, 0xa065, 0x0040, - 0x199c, 0x1078, 0x19a2, 0x0040, 0x199c, 0x1078, 0x19b8, 0x00c0, - 0x199c, 0x8528, 0x0078, 0x198d, 0x85ff, 0x0040, 0x19a1, 0x2091, - 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, 0x0005, 0x0005, 0x70d4, - 0xa206, 0x00c0, 0x19a4, 0x2200, 0xa102, 0x00c0, 0x19b2, 0x2300, - 0xa005, 0x007c, 0x0048, 0x19b6, 0xa302, 0x007c, 0x8002, 0x007c, - 0x1078, 0x19ea, 0x2009, 0x001c, 0x6024, 0xa005, 0x0040, 0x19c2, - 0x2009, 0x0040, 0x1078, 0x1600, 0x0040, 0x19db, 0x7894, 0x8000, - 0x7896, 0xa086, 0x0002, 0x00c0, 0x19e9, 0x2091, 0x8000, 0x78af, - 0x0003, 0x7897, 0x0000, 0x7898, 0xa085, 0x0300, 0x789a, 0x2091, - 0x8001, 0x0078, 0x19e9, 0x7897, 0x0000, 0x1078, 0x17d4, 0x7984, - 0x7888, 0x8000, 0xa10a, 0x00c8, 0x19e6, 0xa006, 0x788a, 0x70d6, - 0xa006, 0x007c, 0x8107, 0x8004, 0x8004, 0x7a90, 0x7b8c, 0xa210, - 0xa399, 0x0000, 0x007c, 0x2009, 0x3468, 0x2091, 0x8000, 0x200a, - 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3440, 0x2091, 0x8000, 0x2104, - 0xa086, 0x0000, 0x00c0, 0x1a13, 0x2009, 0x3412, 0x2104, 0xa005, - 0x00c0, 0x1a13, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1a13, 0x0018, - 0x1a13, 0x781b, 0x0044, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x127e, - 0x2091, 0x2300, 0x2071, 0x3440, 0x2079, 0x0100, 0x2019, 0x2d1f, - 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1a2f, 0x789a, 0x8318, - 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1a22, 0x789b, - 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0220, 0x0070, - 0x1a3b, 0x0078, 0x1a33, 0x7003, 0x0000, 0x1078, 0x1b3a, 0x7004, - 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200, 0x7843, - 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x347f, 0x7043, - 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, - 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1b3a, 0x007c, - 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1a69, 0x0078, - 0x1a64, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, - 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x1a7a, - 0x0078, 0x1a75, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, - 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, - 0x1a8b, 0x0078, 0x1a86, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, - 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, - 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, - 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, - 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, - 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, - 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, - 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, - 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, - 0x2018, 0x0c7f, 0x007c, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, - 0x1b16, 0x2061, 0x3e80, 0x1078, 0x1b1c, 0x0040, 0x1b04, 0x20a9, - 0x0000, 0x2061, 0x3d80, 0x0c7e, 0x1078, 0x1b1c, 0x0040, 0x1af0, - 0x0c7f, 0x8c60, 0x0070, 0x1aee, 0x0078, 0x1ae3, 0x0078, 0x1b16, - 0x007f, 0xa082, 0x3d80, 0x2071, 0x3440, 0x70ba, 0x601c, 0xa085, - 0x0800, 0x601e, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0004, 0x70a2, - 0x1078, 0x19f3, 0x0078, 0x1b12, 0x2071, 0x3440, 0x601c, 0xa085, - 0x0800, 0x601e, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0006, 0x70a2, - 0x1078, 0x19f3, 0x2001, 0x0000, 0x0078, 0x1b18, 0x2001, 0x0001, - 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04, 0xa005, - 0x0040, 0x1b35, 0x2060, 0x600c, 0xa306, 0x00c0, 0x1b32, 0x6008, - 0xa206, 0x00c0, 0x1b32, 0x6010, 0xa106, 0x00c0, 0x1b32, 0xa006, - 0x0078, 0x1b39, 0x6000, 0x0078, 0x1b1f, 0xa085, 0x0001, 0x2091, - 0x8001, 0x007c, 0x2011, 0x3441, 0x220c, 0xa18c, 0x000f, 0x2011, - 0x013b, 0x2204, 0xa084, 0x0100, 0x0040, 0x1b4d, 0x2019, 0x0112, - 0x201b, 0x1000, 0x2021, 0xff80, 0x2122, 0x007c, 0x0068, 0x1b4e, - 0x007e, 0x2071, 0x0000, 0x7018, 0xa084, 0x0001, 0x00c0, 0x1b53, - 0x007f, 0x2e08, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, - 0x8002, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x007f, - 0x2070, 0x007f, 0x0078, 0x1b6a, 0x107e, 0x007e, 0x127e, 0x2091, - 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0xa594, 0x003f, 0xa484, - 0x4000, 0x0040, 0x1b81, 0xa784, 0x007c, 0x00c0, 0x2ceb, 0x1078, - 0x1b4e, 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x1b89, 0x1078, - 0x1b4e, 0x8507, 0xa084, 0x000f, 0x0079, 0x1b8e, 0x1f8e, 0x202f, - 0x2055, 0x226e, 0x24d4, 0x251c, 0x2555, 0x25d0, 0x262a, 0x26ae, - 0x1bb4, 0x1b9e, 0x1df7, 0x1ec1, 0x24b3, 0x1b9e, 0x1078, 0x1b4e, - 0x0018, 0x1b71, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, - 0x7003, 0x0000, 0x703f, 0x0000, 0x7030, 0xa005, 0x0040, 0x1bb2, - 0x7033, 0x0000, 0x0018, 0x1b71, 0x705c, 0xa005, 0x00c0, 0x1c5b, - 0x70a0, 0xa084, 0x0007, 0x0079, 0x1bbd, 0x1c7a, 0x1bc5, 0x1bd3, - 0x1bf4, 0x1c1a, 0x1c46, 0x1c44, 0x1bc5, 0x7808, 0xa084, 0xfffd, - 0x780a, 0x2009, 0x0046, 0x1078, 0x2393, 0x00c0, 0x1bd1, 0x7003, - 0x0004, 0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1bf2, 0x70b4, - 0x8007, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0x78ab, 0x000c, - 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00f7, - 0x1078, 0x2391, 0x00c0, 0x1bf2, 0x7003, 0x0004, 0x70c3, 0x000f, - 0x7033, 0x3470, 0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1c18, - 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, - 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, - 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, 0x2391, - 0x00c0, 0x1c18, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, 0x3470, - 0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1c42, 0x71b4, 0x8107, - 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, - 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, - 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00f7, - 0x1078, 0x2391, 0x00c0, 0x1c42, 0x7003, 0x0004, 0x70c3, 0x000f, - 0x7033, 0x3470, 0x0078, 0x1ba0, 0x0078, 0x1bf4, 0x1078, 0x2cad, - 0x00c0, 0x1ba0, 0x70bc, 0x2068, 0x789b, 0x0010, 0x6810, 0xa084, - 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, 0x2041, 0x0001, 0x2001, - 0x0004, 0x0078, 0x1d82, 0x1078, 0x2cad, 0x00c0, 0x1ba0, 0x789b, - 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, 0x2bfc, 0x6008, 0xa085, - 0x0010, 0x600a, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, - 0x2031, 0x0020, 0x2041, 0x0001, 0x1078, 0x2d0c, 0x2001, 0x0003, - 0x0078, 0x1d6d, 0x0018, 0x1b71, 0x7440, 0xa485, 0x0000, 0x0040, - 0x1c94, 0xa080, 0x3480, 0x2030, 0x7144, 0x8108, 0xa12a, 0x0048, - 0x1c8b, 0x2009, 0x3480, 0x2164, 0x6504, 0x85ff, 0x00c0, 0x1ca1, - 0x8421, 0x00c0, 0x1c85, 0x7146, 0x7003, 0x0000, 0x703f, 0x0000, - 0x0078, 0x1ba0, 0x7640, 0xa6b0, 0x3480, 0x7144, 0x2600, 0x0078, - 0x1c90, 0x7146, 0x2568, 0x2558, 0x753e, 0x2c50, 0x6034, 0xa085, - 0x0000, 0x00c0, 0x1c9e, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, - 0x1cd3, 0xa784, 0x0021, 0x00c0, 0x1c9e, 0xa784, 0x0002, 0x0040, - 0x1cc0, 0xa784, 0x0004, 0x0040, 0x1c9e, 0xa7bc, 0xfffb, 0x670a, - 0xa784, 0x0008, 0x00c0, 0x1c9e, 0xa784, 0x0010, 0x00c0, 0x1c9e, - 0xa784, 0x0100, 0x0040, 0x1cd3, 0x6018, 0xa005, 0x00c0, 0x1c9e, - 0xa7bc, 0xfeff, 0x670a, 0x681f, 0x0000, 0x6e18, 0xa684, 0x000e, - 0x6118, 0x0040, 0x1ce3, 0x601c, 0xa102, 0x0048, 0x1ce6, 0x0040, - 0x1ce6, 0x0078, 0x1c9a, 0x81ff, 0x00c0, 0x1c9a, 0xa784, 0x0080, - 0x00c0, 0x1cec, 0x700c, 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x6b10, - 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3500, - 0x2060, 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x2a60, - 0x0018, 0x1b71, 0x789b, 0x0010, 0xa046, 0x1078, 0x2cad, 0x00c0, - 0x1ba0, 0x6b10, 0xa39c, 0x0007, 0xa39d, 0x00c0, 0x704c, 0xa084, - 0x8000, 0x0040, 0x1d17, 0xa684, 0x0001, 0x0040, 0x1d19, 0xa39c, - 0xffbf, 0xa684, 0x0010, 0x0040, 0x1d1f, 0xa39d, 0x0020, 0x7baa, - 0x8840, 0xa684, 0x000e, 0x00c0, 0x1d2a, 0xa7bd, 0x0010, 0x670a, - 0x0078, 0x1d6b, 0x714c, 0xa18c, 0x0800, 0x0040, 0x2870, 0x2011, - 0x0021, 0x8004, 0x8004, 0x0048, 0x1d41, 0x2011, 0x0022, 0x8004, - 0x0048, 0x1d41, 0x2011, 0x0020, 0x8004, 0x0048, 0x1d41, 0x0040, - 0x1d6b, 0x7aaa, 0x8840, 0x1078, 0x2cc6, 0x6a10, 0x610c, 0x8108, - 0xa18c, 0x00ff, 0xa1e0, 0x3d80, 0x2c64, 0x8cff, 0x0040, 0x1d62, - 0x6010, 0xa206, 0x00c0, 0x1d4c, 0x60b4, 0x8001, 0x60b6, 0x00c0, - 0x1d47, 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, - 0x0078, 0x1c7a, 0x1078, 0x2cad, 0x00c0, 0x1ba0, 0x2a60, 0x610e, - 0x79aa, 0x8840, 0x712e, 0x2001, 0x0001, 0x007e, 0x7150, 0xa184, - 0x0018, 0x0040, 0x1d81, 0xa184, 0x0010, 0x0040, 0x1d7b, 0x1078, - 0x2a33, 0x00c0, 0x1d81, 0xa184, 0x0008, 0x0040, 0x1d81, 0x1078, - 0x294d, 0x007f, 0x7002, 0xa68c, 0x0060, 0x88ff, 0x0040, 0x1d8a, - 0xa18d, 0x0004, 0x795a, 0x69b2, 0x789b, 0x0060, 0x2800, 0x78aa, - 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, - 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, - 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, - 0x8007, 0x789b, 0x007e, 0x78aa, 0x6d90, 0x7dd6, 0x7dde, 0x6e94, - 0x7ed2, 0x7eda, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1db9, 0x0098, - 0x1dc1, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2cc6, 0x0078, - 0x1ba8, 0x7200, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1dce, - 0x781b, 0x0049, 0x1078, 0x2cc6, 0x0078, 0x1ddf, 0x6ab0, 0xa295, - 0x2000, 0x7a5a, 0x781b, 0x0049, 0x1078, 0x2cc6, 0x7200, 0x2500, - 0xa605, 0x0040, 0x1ddf, 0xa284, 0x0007, 0x1079, 0x1ded, 0xad80, - 0x0008, 0x7032, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1deb, - 0x6018, 0x8000, 0x601a, 0x0078, 0x1ba0, 0x1df5, 0x2ffc, 0x2ffc, - 0x2feb, 0x2ffc, 0x1df5, 0x1df5, 0x1df5, 0x1078, 0x1b4e, 0x7808, - 0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079, 0x3400, 0x7898, 0x0f7f, - 0xa084, 0x0001, 0x0040, 0x1e1d, 0x70a0, 0xa086, 0x0001, 0x00c0, - 0x1e0c, 0x70a2, 0x0078, 0x1ea5, 0x70a0, 0xa086, 0x0005, 0x00c0, - 0x1e1b, 0x70bc, 0x2068, 0x6817, 0x0004, 0x6813, 0x0000, 0x681c, - 0xa085, 0x0008, 0x681e, 0x70a3, 0x0000, 0x157e, 0x2011, 0x0004, - 0x71a0, 0xa186, 0x0001, 0x0040, 0x1e3f, 0xa186, 0x0007, 0x00c0, - 0x1e2f, 0x2009, 0x342b, 0x200b, 0x0005, 0x0078, 0x1e3f, 0x2009, - 0x3413, 0x2104, 0x2009, 0x3412, 0x200a, 0x2009, 0x342b, 0x200b, - 0x0001, 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1e41, 0x70a3, - 0x0000, 0x1078, 0x2e0e, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, - 0x2b01, 0xa7b8, 0x0100, 0x0070, 0x1e4f, 0x0078, 0x1e47, 0x7000, - 0x2020, 0x0079, 0x1e53, 0x1e81, 0x1e6a, 0x1e6a, 0x1e5d, 0x1e81, - 0x1e81, 0x1e5b, 0x1e5b, 0x1078, 0x1b4e, 0x2021, 0x3457, 0x2404, - 0xa005, 0x0040, 0x1e6a, 0xad06, 0x00c0, 0x1e6a, 0x6800, 0x2022, - 0x0078, 0x1e7a, 0x681c, 0xa084, 0x0001, 0x00c0, 0x1e76, 0x6f10, - 0x1078, 0x2bfc, 0x1078, 0x283d, 0x0078, 0x1e7a, 0x7054, 0x2060, - 0x6800, 0x6002, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, - 0x17be, 0x2021, 0x3e80, 0x1078, 0x1eab, 0x2021, 0x3457, 0x1078, - 0x1eab, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x1078, 0x1eab, 0x8420, - 0x0070, 0x1e94, 0x0078, 0x1e8d, 0x20a9, 0x0080, 0x2061, 0x3580, - 0x6018, 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, - 0x0070, 0x1ea4, 0x0078, 0x1e98, 0x157f, 0x7003, 0x0000, 0x703f, - 0x0000, 0x0078, 0x1ba0, 0x047e, 0x2404, 0xa005, 0x0040, 0x1ebd, - 0x2068, 0x6800, 0x007e, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, - 0x1078, 0x17be, 0x007f, 0x0078, 0x1ead, 0x047f, 0x2023, 0x0000, - 0x007c, 0xa282, 0x0003, 0x0050, 0x1ec7, 0x1078, 0x1b4e, 0x2300, - 0x0079, 0x1eca, 0x1ecd, 0x1f40, 0x1f4e, 0xa282, 0x0002, 0x0040, - 0x1ed3, 0x1078, 0x1b4e, 0x70a0, 0x70a3, 0x0000, 0x70c3, 0x0000, - 0x0079, 0x1eda, 0x1ee2, 0x1ee2, 0x1ee4, 0x1f18, 0x287b, 0x1ee2, - 0x1f18, 0x1ee2, 0x1078, 0x1b4e, 0x77b4, 0x1078, 0x2b01, 0x77b4, - 0xa7bc, 0x0f00, 0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x1f0f, - 0x2021, 0x3e80, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1f69, - 0x0040, 0x1f0f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x047e, - 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1f69, 0x047f, 0x0040, - 0x1f0e, 0x8420, 0x0070, 0x1f0e, 0x0078, 0x1eff, 0x157f, 0x8738, - 0xa784, 0x0007, 0x00c0, 0x1eea, 0x0078, 0x1ba8, 0x0078, 0x1ba8, - 0x77b4, 0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x1f3e, 0x2021, - 0x3e80, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x1f69, 0x0040, - 0x1f3e, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x047e, 0x2009, - 0x0005, 0x2011, 0x0020, 0x1078, 0x1f69, 0x047f, 0x0040, 0x1f3d, - 0x8420, 0x0070, 0x1f3d, 0x0078, 0x1f2e, 0x157f, 0x0078, 0x1ba8, - 0x2200, 0x0079, 0x1f43, 0x1f46, 0x1f48, 0x1f48, 0x1078, 0x1b4e, - 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1ba0, 0x2200, 0x0079, - 0x1f51, 0x1f56, 0x1f48, 0x1f54, 0x1078, 0x1b4e, 0x1078, 0x23a0, - 0x7000, 0xa086, 0x0001, 0x00c0, 0x2813, 0x1078, 0x2853, 0x6008, - 0xa084, 0xffef, 0x600a, 0x1078, 0x2806, 0x0040, 0x2813, 0x0078, - 0x1c7a, 0x2404, 0xa005, 0x0040, 0x1f8a, 0x2068, 0x2d04, 0x007e, - 0x6810, 0xa706, 0x0040, 0x1f78, 0x2d20, 0x007f, 0x0078, 0x1f6a, - 0x007f, 0x2022, 0x6916, 0x681c, 0xa205, 0x681e, 0x1078, 0x17be, - 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, - 0x2853, 0x007c, 0xa085, 0x0001, 0x0078, 0x1f89, 0x2300, 0x0079, - 0x1f91, 0x1f96, 0x1f94, 0x1fd5, 0x1078, 0x1b4e, 0x78e4, 0xa005, - 0x00d0, 0x1fb9, 0x0018, 0x1fb9, 0x2008, 0xa084, 0x0030, 0x00c0, - 0x1fa5, 0x781b, 0x0049, 0x0078, 0x1ba0, 0x78ec, 0xa084, 0x0003, - 0x0040, 0x1fa1, 0x2100, 0xa084, 0x0007, 0x0079, 0x1faf, 0x1fc3, - 0x1fc9, 0x1fbd, 0x1fb7, 0x2ca7, 0x2ca7, 0x1fb7, 0x1fcf, 0x1078, - 0x1b4e, 0x2001, 0x0003, 0x0078, 0x2282, 0x1078, 0x2ae4, 0x781b, - 0x0055, 0x0078, 0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x00dc, 0x0078, - 0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x00e3, 0x0078, 0x1ba0, 0x1078, - 0x2ae4, 0x781b, 0x009d, 0x0078, 0x1ba0, 0xa584, 0x000f, 0x00c0, - 0x1ff4, 0x1078, 0x23a0, 0x7000, 0x0079, 0x1fde, 0x1fe6, 0x1fe8, - 0x1fe6, 0x2813, 0x2813, 0x2813, 0x1fe6, 0x1fe6, 0x1078, 0x1b4e, - 0x1078, 0x2853, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2806, - 0x0040, 0x2813, 0x0078, 0x1c7a, 0x78e4, 0xa005, 0x00d0, 0x1fb9, - 0x0018, 0x1fb9, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2003, 0x781b, - 0x0049, 0x0078, 0x1ba0, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1fff, - 0x2100, 0xa184, 0x0007, 0x0079, 0x200d, 0x201d, 0x2023, 0x2017, - 0x2015, 0x2ca7, 0x2ca7, 0x2015, 0x2c9f, 0x1078, 0x1b4e, 0x1078, - 0x2aec, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x1078, 0x2aec, 0x781b, - 0x00dc, 0x0078, 0x1ba0, 0x1078, 0x2aec, 0x781b, 0x00e3, 0x0078, - 0x1ba0, 0x1078, 0x2aec, 0x781b, 0x009d, 0x0078, 0x1ba0, 0x2300, - 0x0079, 0x2032, 0x2037, 0x2035, 0x2039, 0x1078, 0x1b4e, 0x0078, - 0x25d0, 0x6817, 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, - 0x0040, 0x25d0, 0x78ec, 0xa084, 0x0003, 0x0040, 0x25d0, 0xa184, - 0x0007, 0x0079, 0x204b, 0x1fc3, 0x1fc9, 0x1fbd, 0x2c7f, 0x2ca7, - 0x2ca7, 0x2053, 0x2c9f, 0x1078, 0x1b4e, 0xa282, 0x0005, 0x0050, - 0x205b, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x205e, 0x2061, 0x2256, - 0x2262, 0x2200, 0x0079, 0x2064, 0x2069, 0x206b, 0x207e, 0x2069, - 0x223b, 0x1078, 0x1b4e, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, - 0xa082, 0x0020, 0x0048, 0x2ac5, 0xa08a, 0x0004, 0x00c8, 0x2ac5, - 0x0079, 0x207a, 0x2ac5, 0x2ac5, 0x2ac5, 0x2a73, 0x789b, 0x0018, - 0x79a8, 0xa184, 0x0080, 0x0040, 0x2093, 0xa184, 0x0018, 0x0040, - 0x208f, 0x0078, 0x2ac5, 0x7000, 0xa005, 0x00c0, 0x2089, 0x2011, - 0x0003, 0x0078, 0x26bc, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, - 0x2ac5, 0x0079, 0x209b, 0x20ad, 0x20ab, 0x20c3, 0x20c5, 0x214a, - 0x2ac5, 0x2ac5, 0x214c, 0x2ac5, 0x2ac5, 0x2237, 0x2237, 0x2ac5, - 0x2ac5, 0x2ac5, 0x2239, 0x1078, 0x1b4e, 0xa684, 0x1000, 0x0040, - 0x20ba, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x009a, - 0x0078, 0x1ba0, 0x6814, 0xa084, 0x8000, 0x0040, 0x20c1, 0x6817, - 0x0003, 0x0078, 0x2c7f, 0x1078, 0x1b4e, 0x691c, 0x691e, 0xa684, - 0x1800, 0x00c0, 0x20df, 0x681c, 0xa084, 0x0001, 0x00c0, 0x20e7, - 0x6814, 0xa086, 0x0008, 0x00c0, 0x20d7, 0x6817, 0x0000, 0xa684, - 0x0400, 0x0040, 0x2146, 0x781b, 0x0058, 0x0078, 0x1ba0, 0xa684, - 0x1000, 0x0040, 0x20e7, 0x781b, 0x0058, 0x0078, 0x1ba0, 0xa684, - 0x0060, 0x0040, 0x2142, 0xa684, 0x0800, 0x0040, 0x2142, 0xa684, - 0x8000, 0x00c0, 0x20f5, 0x0078, 0x210f, 0xa6b4, 0x7fff, 0x7e5a, - 0x6eb2, 0x789b, 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, - 0x2102, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b94, - 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, 0xa684, - 0x4000, 0x0040, 0x2117, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb2, 0xa006, - 0x1078, 0x30a0, 0x6aac, 0x69a8, 0x6c94, 0x6b90, 0x2200, 0xa105, - 0x0040, 0x2126, 0x2200, 0xa422, 0x2100, 0xa31b, 0x7cd2, 0x7bd6, - 0x2300, 0xa405, 0x00c0, 0x2134, 0xa6b5, 0x4000, 0x7e5a, 0x6eb2, - 0x781b, 0x0067, 0x0078, 0x1ba0, 0x781b, 0x0067, 0x2200, 0xa115, - 0x00c0, 0x213e, 0x1078, 0x2ffc, 0x0078, 0x1ba0, 0x1078, 0x3029, - 0x0078, 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x781b, 0x0058, - 0x0078, 0x1ba0, 0x1078, 0x1b4e, 0x0078, 0x21a9, 0x691c, 0xa184, - 0x0100, 0x0040, 0x2164, 0xa18c, 0xfeff, 0x691e, 0x0c7e, 0x7048, + 0x3540, 0x00a8, 0x106a, 0x681b, 0x003c, 0x2009, 0x1313, 0x21b8, + 0x0078, 0x106c, 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, + 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, 0x6823, 0x0006, + 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600, 0x2011, 0x0020, + 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, 0x6803, 0xdd00, + 0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, + 0x8109, 0x00c0, 0x1082, 0x2069, 0x3680, 0x20a9, 0x0080, 0x6837, + 0x0000, 0x680b, 0x0040, 0x6817, 0x0100, 0x681f, 0x0064, 0xade8, + 0x0010, 0x0070, 0x10a5, 0x0078, 0x1097, 0x1078, 0x1a38, 0x1078, + 0x2f3a, 0x1078, 0x1681, 0x1078, 0x33ba, 0x3200, 0xa085, 0x000d, + 0x2090, 0x70c3, 0x0000, 0x0090, 0x10bc, 0x70c0, 0xa086, 0x0002, + 0x00c0, 0x10bc, 0x1078, 0x11ba, 0x1078, 0x10ec, 0x1078, 0x1817, + 0x1078, 0x19a8, 0x1078, 0x327d, 0x1078, 0x177d, 0x0078, 0x10bc, + 0x10d0, 0x10d2, 0x1bc3, 0x1bc3, 0x2f98, 0x2f98, 0x1bc3, 0x1bc3, + 0x0078, 0x10d0, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6, + 0x7008, 0x800c, 0x00c8, 0x10e7, 0x7007, 0x0002, 0xa08c, 0x000c, + 0x00c0, 0x10e8, 0x8004, 0x8004, 0x00c8, 0x10e7, 0x087a, 0x097a, + 0x70c3, 0x4002, 0x0078, 0x11bd, 0x7814, 0xa005, 0x00c0, 0x10f4, + 0x0010, 0x1130, 0x0078, 0x112f, 0x2009, 0x3568, 0x2104, 0xa005, + 0x00c0, 0x112f, 0x7814, 0xa086, 0x0001, 0x00c0, 0x1101, 0x1078, + 0x1536, 0x7817, 0x0000, 0x2009, 0x356f, 0x2104, 0xa065, 0x0040, + 0x111d, 0x2009, 0x356a, 0x211c, 0x8108, 0x2114, 0x8108, 0x2104, + 0xa210, 0xa399, 0x0000, 0x2009, 0x001c, 0x6083, 0x0103, 0x1078, + 0x1611, 0x00c0, 0x1129, 0x1078, 0x1678, 0x2009, 0x356f, 0x200b, + 0x0000, 0x2009, 0x3569, 0x2104, 0x200b, 0x0000, 0xa005, 0x0040, + 0x112d, 0x2001, 0x4005, 0x0078, 0x11bc, 0x0078, 0x11ba, 0x007c, + 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x0040, 0x1138, 0x007c, + 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000, 0x70cf, 0x0000, + 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1188, 0x2038, 0x0079, 0x1148, + 0x11ba, 0x1205, 0x11d3, 0x1205, 0x1256, 0x1256, 0x11ca, 0x1590, + 0x1261, 0x11c6, 0x11d7, 0x11d9, 0x11db, 0x11dd, 0x1595, 0x11c6, + 0x1267, 0x1283, 0x1544, 0x158a, 0x11df, 0x146b, 0x148d, 0x14a7, + 0x14d0, 0x1424, 0x1432, 0x1446, 0x145a, 0x12ef, 0x11c6, 0x129f, + 0x12a6, 0x12ab, 0x12b0, 0x12b6, 0x12bb, 0x12c0, 0x12c5, 0x12ca, + 0x12ce, 0x12e3, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x12fb, + 0x1304, 0x1313, 0x1339, 0x1343, 0x134a, 0x1370, 0x137f, 0x138e, + 0x13a0, 0x1409, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x1419, + 0xa0bc, 0xffa0, 0x00c0, 0x11c6, 0x2038, 0xa084, 0x001f, 0x0079, + 0x1191, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, + 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, + 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, + 0x11c6, 0x11c6, 0x11c6, 0x15ed, 0x15f7, 0x15fb, 0x1609, 0x11c6, + 0x11c6, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x11bc, 0x73ce, + 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x2061, 0x0000, 0x601b, + 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, + 0x0078, 0x11bd, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, + 0x53a3, 0x0078, 0x11ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, + 0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x2091, + 0x8000, 0x70c3, 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, + 0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, + 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, + 0x0470, 0x2061, 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, + 0x5000, 0x2091, 0x4080, 0x0078, 0x0455, 0x71d0, 0x72c8, 0x73cc, + 0x70c4, 0x20a0, 0x2098, 0x2031, 0x0030, 0x81ff, 0x0040, 0x11ba, + 0x7007, 0x0004, 0x731a, 0x721e, 0x2051, 0x0012, 0x2049, 0x1234, + 0x2041, 0x11ba, 0x7003, 0x0002, 0xa786, 0x0001, 0x00c0, 0x1226, + 0x2049, 0x1242, 0x2041, 0x124e, 0x7003, 0x0003, 0x7017, 0x0000, + 0x810b, 0x7112, 0x00c8, 0x122e, 0x7017, 0x0001, 0x7007, 0x0001, + 0xa786, 0x0001, 0x0040, 0x1242, 0x700c, 0xa084, 0x007f, 0x8004, + 0x2009, 0x0020, 0xa102, 0x0942, 0x094a, 0x20a8, 0x26a0, 0x53a6, + 0x0078, 0x10d8, 0x700c, 0xa084, 0x007f, 0x0040, 0x1242, 0x80ac, + 0x0048, 0x1242, 0x2698, 0x53a5, 0x0078, 0x10d8, 0x700c, 0xa084, + 0x007f, 0x80ac, 0x2698, 0x53a5, 0x0078, 0x11ba, 0x71c4, 0x70c8, + 0x2114, 0xa79e, 0x0004, 0x00c0, 0x125e, 0x200a, 0x72ca, 0x0078, + 0x11b9, 0x70c7, 0x0001, 0x70cb, 0x001f, 0x0078, 0x11ba, 0x70c4, + 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, + 0x0040, 0x127d, 0x8001, 0x7872, 0x7a7a, 0x7b7e, 0x7c76, 0x7898, + 0xa084, 0xfffc, 0x789a, 0x0078, 0x1281, 0x7898, 0xa085, 0x0001, + 0x789a, 0x0078, 0x11ba, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, + 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1299, 0x8001, 0x7886, + 0x7a8e, 0x7b92, 0x7c8a, 0x7898, 0xa084, 0xfcff, 0x789a, 0x0078, + 0x129d, 0x7898, 0xa085, 0x0100, 0x789a, 0x0078, 0x11ba, 0x2009, + 0x3559, 0x210c, 0x2011, 0x0410, 0x0078, 0x11b8, 0x2009, 0x3541, + 0x210c, 0x0078, 0x11b9, 0x2009, 0x3542, 0x210c, 0x0078, 0x11b9, + 0x2061, 0x3540, 0x610c, 0x6210, 0x0078, 0x11b8, 0x2009, 0x3545, + 0x210c, 0x0078, 0x11b9, 0x2009, 0x3546, 0x210c, 0x0078, 0x11b9, + 0x2009, 0x3547, 0x210c, 0x0078, 0x11b9, 0x2009, 0x3548, 0x210c, + 0x0078, 0x11b9, 0x7908, 0x7a0c, 0x0078, 0x11b8, 0x71c4, 0x8107, + 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3600, 0x6a00, + 0x6804, 0xa084, 0x0008, 0x0040, 0x12e0, 0x6b08, 0x0078, 0x12e1, + 0x6b0c, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, + 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b7, 0x77c4, + 0x1078, 0x1692, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091, + 0x8001, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b2, + 0x1078, 0x1abc, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8, + 0x11b2, 0x2011, 0x3541, 0x2204, 0x007e, 0x2112, 0x1078, 0x1a75, + 0x017f, 0x0078, 0x11b9, 0x71c4, 0x2011, 0x1331, 0x20a9, 0x0008, + 0x2204, 0xa106, 0x0040, 0x1323, 0x8210, 0x0070, 0x1321, 0x0078, + 0x1318, 0x0078, 0x11b2, 0xa292, 0x1331, 0x027e, 0x2011, 0x3542, + 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x1a81, 0x017f, 0x0078, + 0x11b9, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, + 0x004b, 0x2061, 0x3540, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8, + 0x6012, 0x0078, 0x11b8, 0x2061, 0x3540, 0x6114, 0x70c4, 0x6016, + 0x0078, 0x11b9, 0x71c4, 0x2011, 0x0004, 0x2019, 0x1212, 0xa186, + 0x0028, 0x0040, 0x1363, 0x2011, 0x0005, 0x2019, 0x1212, 0xa186, + 0x0032, 0x0040, 0x1363, 0x2011, 0x0006, 0x2019, 0x1313, 0xa186, + 0x003c, 0x00c0, 0x11b2, 0x2061, 0x3540, 0x6018, 0x007e, 0x611a, + 0x23b8, 0x1078, 0x1a92, 0x1078, 0x33ba, 0x017f, 0x0078, 0x11b9, + 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b2, 0x2011, 0x3547, 0x2204, + 0x2112, 0x007e, 0x1078, 0x1ab4, 0x017f, 0x0078, 0x11b9, 0x71c4, + 0xa182, 0x0010, 0x00c8, 0x11b2, 0x2011, 0x3548, 0x2204, 0x007e, + 0x2112, 0x1078, 0x1aa3, 0x017f, 0x0078, 0x11b9, 0x71c4, 0x72c8, + 0xa184, 0xfffd, 0x00c0, 0x11b1, 0xa284, 0xfffd, 0x00c0, 0x11b1, + 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x11b8, + 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, + 0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e, 0xa226, 0x0040, + 0x13cf, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13b8, 0xa39d, 0x0010, + 0xa484, 0x1000, 0x0040, 0x13be, 0xa39d, 0x0008, 0xa484, 0x4000, + 0x0040, 0x13cf, 0x810f, 0xa284, 0x4000, 0x0040, 0x13cb, 0x1078, + 0x1ad6, 0x0078, 0x13cf, 0x1078, 0x1ac8, 0x0078, 0x13cf, 0x72cc, + 0x82ff, 0x0040, 0x1401, 0x6808, 0xa206, 0x0040, 0x1401, 0xa2a4, + 0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028, 0x0040, 0x13e8, + 0xa186, 0x0032, 0x0040, 0x13ee, 0xa186, 0x003c, 0x0040, 0x13f4, + 0xa482, 0x0064, 0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0050, + 0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0043, 0x0048, 0x13fe, + 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b3, 0x6a0a, 0xa39d, + 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078, + 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a14, 0x6b1c, + 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, + 0x11b7, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x11b2, + 0x1078, 0x1ae4, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, + 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, + 0x0078, 0x11b8, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a08, + 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1441, 0x1078, + 0x1a19, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b8, 0x77c4, 0x1078, + 0x1692, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, + 0xa005, 0x0040, 0x1455, 0x1078, 0x1a19, 0x2091, 0x8001, 0x2708, + 0x0078, 0x11b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, + 0x0020, 0x2091, 0x8000, 0x1078, 0x169f, 0x2091, 0x8001, 0x2708, + 0x6a08, 0x0078, 0x11b8, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, + 0x73ce, 0x1078, 0x1718, 0x00c0, 0x1489, 0x6818, 0xa005, 0x0040, + 0x1483, 0x2708, 0x1078, 0x1af4, 0x00c0, 0x1483, 0x7817, 0xffff, + 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, + 0x11bc, 0x2091, 0x8001, 0x0078, 0x11ba, 0x77c4, 0x77c6, 0x2041, + 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, + 0x169f, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6, 0x60a7, 0x0000, + 0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x77c8, + 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061, + 0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6, 0x7817, 0xffff, + 0x1078, 0x1a19, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0004, + 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x169f, 0x70c8, 0x6836, + 0x8738, 0xa784, 0x0007, 0x00c0, 0x14c4, 0x2091, 0x8001, 0x007c, + 0x7898, 0xa084, 0x0003, 0x00c0, 0x14f4, 0x2039, 0x0000, 0x2041, + 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, 0x1692, 0x2091, + 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, + 0x0007, 0x00c0, 0x14dd, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, + 0xa784, 0x0f00, 0x00c0, 0x14dd, 0x2091, 0x8000, 0x2069, 0x0100, + 0x6830, 0xa084, 0x0040, 0x0040, 0x151d, 0x684b, 0x0004, 0x20a9, + 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x150a, 0x0070, 0x150a, + 0x0078, 0x1501, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, + 0x0001, 0x0040, 0x1517, 0x0070, 0x1517, 0x0078, 0x150e, 0x20a9, + 0x00fa, 0x0070, 0x151d, 0x0078, 0x1519, 0x2079, 0x3500, 0x7817, + 0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7, 0x0000, 0x60c3, + 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808, 0xa084, 0xfffd, + 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c, 0x7898, 0xa084, + 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x1540, 0x1078, 0x1760, + 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8, 0x72cc, 0x74c6, + 0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040, 0x1078, 0x166f, + 0x0040, 0x1586, 0x1078, 0x163f, 0x0040, 0x155a, 0x1078, 0x1678, + 0x0078, 0x1586, 0x6010, 0x2091, 0x8001, 0x7817, 0xffff, 0x2009, + 0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, 0x8108, 0x230a, + 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, 0x8108, 0x200b, + 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, 0x1078, 0x2f13, + 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, + 0x0000, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x70c3, 0x4005, + 0x0078, 0x11bd, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x11ba, + 0x71c4, 0x71c6, 0x2168, 0x0078, 0x1597, 0x2069, 0x1000, 0x690c, + 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1599, 0xa285, + 0x0000, 0x00c0, 0x15a7, 0x70c3, 0x4000, 0x0078, 0x15a9, 0x70c3, + 0x4003, 0x70ca, 0x0078, 0x11bd, 0x71c4, 0x72c8, 0x73cc, 0x2100, + 0xa184, 0xfffc, 0x00c0, 0x11c6, 0x2100, 0x0079, 0x15b7, 0x15ce, + 0x15e3, 0x15e5, 0x15e7, 0x70c3, 0x4003, 0x71ce, 0x72d2, 0x73d6, + 0x0078, 0x15ca, 0x70c3, 0x4000, 0x70cf, 0x0000, 0x70d3, 0x0000, + 0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11ba, 0x2031, 0x15e9, + 0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, 0x15bb, 0xa484, + 0xffff, 0x00c0, 0x15d0, 0x2031, 0x15e9, 0x8210, 0x8319, 0xa384, + 0xffff, 0x00c0, 0x15d0, 0x0078, 0x15c2, 0x0078, 0x15c2, 0x0078, + 0x15c2, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, 0x71c6, 0x71c4, + 0xa182, 0x0003, 0x00c8, 0x11b2, 0x7962, 0x0078, 0x11ba, 0x7960, + 0x71c6, 0x0078, 0x11ba, 0x7954, 0x71c6, 0x71c4, 0x7956, 0x7958, + 0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, 0x795e, 0x0078, + 0x11ba, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, 0x71ce, 0x0078, + 0x11ba, 0x700c, 0xa084, 0x007f, 0x0040, 0x161d, 0x7007, 0x0004, + 0x7004, 0xa084, 0x0004, 0x00c0, 0x1618, 0x7017, 0x0000, 0x7112, + 0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, 0x20a1, 0x0030, + 0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007, + 0x0001, 0x7108, 0x8104, 0x00c8, 0x1631, 0x7007, 0x0002, 0xa184, + 0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000, 0x007c, 0x700c, + 0xa084, 0x007f, 0x0040, 0x164b, 0x7007, 0x0004, 0x7004, 0xa084, + 0x0004, 0x00c0, 0x1646, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e, + 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, 0x0001, 0x7002, + 0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x165a, 0x7007, 0x0002, + 0xa08c, 0x000c, 0x00c0, 0x166c, 0x710c, 0xa184, 0x0300, 0x00c0, + 0x166c, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850, + 0xa065, 0x0040, 0x1677, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, + 0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00, 0x7852, 0x0f7f, + 0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x0410, 0x8319, 0x0040, + 0x168f, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078, 0x1686, 0x2013, + 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, + 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680, 0x007c, 0x1078, + 0x1692, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xffef, + 0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804, 0xa005, 0x0040, + 0x16bc, 0xa116, 0x00c0, 0x16bc, 0x2060, 0x6000, 0x6806, 0x017e, + 0x200b, 0x0000, 0x0078, 0x16bf, 0x2009, 0x0000, 0x017e, 0x6804, + 0xa065, 0x0040, 0x16ce, 0x6000, 0x6806, 0x1078, 0x16df, 0x1078, + 0x17cb, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16bf, 0x017f, 0x6902, + 0x6906, 0x007c, 0xa065, 0x0040, 0x16de, 0x6098, 0x609b, 0x0000, + 0x2008, 0x1078, 0x1678, 0x2100, 0x0078, 0x16d2, 0x007c, 0x6003, + 0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, 0x2001, 0x0000, + 0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c, 0x0e7e, 0x2071, + 0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x16fc, 0xa088, 0x3580, + 0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x2071, + 0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211, 0x0048, 0x1716, + 0x2104, 0x8108, 0xad06, 0x00c0, 0x1705, 0x8119, 0x211e, 0x8108, + 0x8318, 0x8211, 0x00c8, 0x170e, 0x7442, 0xa006, 0x0e7f, 0x007c, + 0x1078, 0x1692, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065, 0x0040, + 0x175f, 0x0078, 0x1729, 0x2c00, 0x781e, 0x6000, 0xa065, 0x0040, + 0x175f, 0x600c, 0xa306, 0x00c0, 0x1723, 0x6008, 0xa206, 0x00c0, + 0x1723, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06, 0x0040, 0x175f, + 0x6804, 0xac06, 0x00c0, 0x1746, 0x6000, 0x2060, 0x6806, 0xa005, + 0x00c0, 0x1746, 0x6803, 0x0000, 0x0078, 0x1750, 0x6400, 0x781c, + 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1750, 0x2c00, 0x6802, + 0x2560, 0x1078, 0x16df, 0x6017, 0x0005, 0x601f, 0x0020, 0x1078, + 0x17cb, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, 0x007c, + 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, + 0x2091, 0x8000, 0x1078, 0x169f, 0x8738, 0xa784, 0x0007, 0x00c0, + 0x176a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, + 0x00c0, 0x176a, 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, 0x6018, + 0xa084, 0x0001, 0x00c0, 0x178a, 0x78ac, 0x78af, 0x0000, 0xa005, + 0x00c0, 0x178b, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1791, 0x1078, + 0x1ba5, 0x0079, 0x1793, 0x17a3, 0x17a5, 0x17ab, 0x17af, 0x17a3, + 0x17b3, 0x17a3, 0x17a3, 0x17a3, 0x17a3, 0x17b9, 0x17bd, 0x17a3, + 0x17a3, 0x17a3, 0x17a3, 0x1078, 0x1ba5, 0x1078, 0x1760, 0x2001, + 0x8001, 0x0078, 0x17c3, 0x2001, 0x8003, 0x0078, 0x17c3, 0x2001, + 0x8004, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001, 0x8006, 0x0078, + 0x17c3, 0x2001, 0x800c, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001, + 0x800d, 0x0078, 0x17c3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, + 0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08, 0x2063, 0x0000, + 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, 0x0040, 0x17db, + 0x2c02, 0x0078, 0x17dc, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x3500, + 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, 0x8000, 0x6066, + 0x6068, 0xa005, 0x616a, 0x0040, 0x17f0, 0x2d02, 0x0078, 0x17f1, + 0x616e, 0x0c7f, 0x007c, 0x1078, 0x1804, 0x0040, 0x1803, 0x0c7e, + 0x6098, 0xa065, 0x0040, 0x17fe, 0x1078, 0x16d2, 0x0c7f, 0x609b, + 0x0000, 0x1078, 0x1678, 0x007c, 0x786c, 0xa065, 0x0040, 0x1816, + 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, 0x786e, 0xa005, + 0x00c0, 0x1814, 0x786a, 0x8000, 0x2091, 0x8001, 0x007c, 0x7898, + 0xa005, 0x00c0, 0x1865, 0x7974, 0x70d0, 0x0005, 0x0005, 0x72d0, + 0xa206, 0x00c0, 0x181c, 0x2200, 0xa106, 0x00c0, 0x1833, 0x7804, + 0xa005, 0x0040, 0x1865, 0x7807, 0x0000, 0x0068, 0x1865, 0x2091, + 0x4080, 0x0078, 0x1865, 0x1078, 0x166f, 0x0040, 0x1865, 0x7a7c, + 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, 0x2009, + 0x0040, 0x1078, 0x163f, 0x0040, 0x185c, 0x1078, 0x1678, 0x7880, + 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x1865, 0x2091, 0x8000, + 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, 0x0003, 0x789a, + 0x2091, 0x8001, 0x0078, 0x1865, 0x7883, 0x0000, 0x1078, 0x1992, + 0x6000, 0xa084, 0x0007, 0x0079, 0x1866, 0x007c, 0x186e, 0x187d, + 0x189d, 0x186e, 0x18af, 0x186e, 0x186e, 0x186e, 0x2039, 0x0400, + 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, 0x1078, 0x18ed, + 0x6018, 0x78a6, 0x1078, 0x197a, 0x007c, 0x78a8, 0xa084, 0x0100, + 0x0040, 0x1884, 0x0078, 0x186e, 0x78ab, 0x0000, 0x6000, 0x8007, + 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, 0x0040, 0x189a, + 0x1078, 0x18ed, 0x0040, 0x189a, 0x78a8, 0xa085, 0x0100, 0x78aa, + 0x0078, 0x189c, 0x1078, 0x1911, 0x007c, 0x78a8, 0xa08c, 0x0e00, + 0x00c0, 0x18a6, 0xa084, 0x0100, 0x00c0, 0x18a8, 0x0078, 0x186e, + 0x1078, 0x18ed, 0x00c0, 0x18ae, 0x1078, 0x1911, 0x007c, 0x78a8, + 0xa084, 0x0100, 0x0040, 0x18b6, 0x0078, 0x186e, 0x78ab, 0x0000, + 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, 0xa005, 0x0040, + 0x18d3, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, 0x0040, + 0x18d3, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, 0x0040, + 0x18d3, 0x0078, 0x18ea, 0x1078, 0x1692, 0x2d00, 0x2091, 0x8000, + 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, + 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, 0x0070, 0x18ea, + 0x0078, 0x18d6, 0x1078, 0x1678, 0x007c, 0x78a0, 0xa06d, 0x00c0, + 0x18f8, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1904, + 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, 0x6002, 0x78a4, + 0xad06, 0x00c0, 0x1904, 0x6002, 0x789c, 0x8001, 0x789e, 0x00c0, + 0x1910, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, 0x2060, 0xa006, + 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, 0x619e, 0x0040, + 0x191d, 0x0e7e, 0x1078, 0x2f13, 0x0e7f, 0x6592, 0x65a2, 0x6696, + 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, 0x1078, 0x1692, + 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, 0x193f, 0x2091, + 0x8001, 0x1078, 0x16df, 0x2091, 0x8000, 0x1078, 0x17cb, 0x2091, + 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, 0x1979, 0x6020, + 0xa096, 0x0001, 0x00c0, 0x1946, 0x8000, 0x6022, 0x6a10, 0x6814, + 0x2091, 0x8001, 0xa202, 0x0048, 0x1955, 0x0040, 0x1955, 0x2039, + 0x0200, 0x1078, 0x197a, 0x0078, 0x1979, 0x2c08, 0x2091, 0x8000, + 0x6800, 0xa065, 0x0040, 0x195d, 0x6102, 0x6902, 0x00c0, 0x1961, + 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, 0x2091, + 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x1973, 0xa086, 0x0040, + 0x680a, 0x1078, 0x16ee, 0x1078, 0x1a19, 0x78a7, 0x0000, 0x78a3, + 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, 0x8000, 0x1078, + 0x17cb, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, 0x198d, 0x6098, + 0x78a6, 0x609b, 0x0000, 0x0078, 0x197d, 0x78a3, 0x0000, 0x78a7, + 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, 0x00c8, 0x1999, + 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, 0x19a7, 0x8001, + 0x7806, 0x00c0, 0x19a7, 0x0068, 0x19a7, 0x2091, 0x4080, 0x007c, + 0x0068, 0x19c2, 0x2029, 0x0000, 0x786c, 0xa065, 0x0040, 0x19bd, + 0x1078, 0x19c3, 0x0040, 0x19bd, 0x057e, 0x1078, 0x19d9, 0x057f, + 0x00c0, 0x19bd, 0x8528, 0x0078, 0x19ac, 0x85ff, 0x0040, 0x19c2, + 0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, 0x0005, 0x0005, + 0x70d4, 0xa206, 0x00c0, 0x19c5, 0x2200, 0xa102, 0x00c0, 0x19d3, + 0x2300, 0xa005, 0x007c, 0x0048, 0x19d7, 0xa302, 0x007c, 0x8002, + 0x007c, 0x1078, 0x1a0b, 0x2009, 0x001c, 0x6024, 0xa005, 0x0040, + 0x19e3, 0x2009, 0x0040, 0x1078, 0x1611, 0x0040, 0x19fc, 0x7894, + 0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a0a, 0x2091, 0x8000, + 0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085, 0x0300, 0x789a, + 0x2091, 0x8001, 0x0078, 0x1a0a, 0x7897, 0x0000, 0x1078, 0x17f3, + 0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a07, 0xa006, 0x788a, + 0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004, 0x7a90, 0x7b8c, + 0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568, 0x2091, 0x8000, + 0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540, 0x2091, 0x8000, + 0x2104, 0xa086, 0x0000, 0x00c0, 0x1a34, 0x2009, 0x3512, 0x2104, + 0xa005, 0x00c0, 0x1a34, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1a34, + 0x0018, 0x1a34, 0x781b, 0x0044, 0x2091, 0x8001, 0x0f7f, 0x007c, + 0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079, 0x0100, 0x2019, + 0x2dd8, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1a50, 0x789a, + 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1a43, + 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0220, + 0x0070, 0x1a5c, 0x0078, 0x1a54, 0x7003, 0x0000, 0x1078, 0x1b5b, + 0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200, + 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0038, 0x7047, 0x357f, + 0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011, + 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1b5b, + 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1a8a, + 0x0078, 0x1a85, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, + 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, + 0x1a9b, 0x0078, 0x1a96, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, + 0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, + 0x0070, 0x1aac, 0x0078, 0x1aa7, 0xa18c, 0xf000, 0x2204, 0xa084, + 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, + 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, + 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, + 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, + 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, + 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, + 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, + 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, + 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, + 0x6818, 0xa005, 0x0040, 0x1b39, 0x2061, 0x3f80, 0x1078, 0x1b41, + 0x0040, 0x1b27, 0x20a9, 0x0000, 0x2061, 0x3e80, 0x0c7e, 0x1078, + 0x1b41, 0x0040, 0x1b13, 0x0c7f, 0x8c60, 0x0070, 0x1b11, 0x0078, + 0x1b06, 0x0078, 0x1b39, 0x007f, 0xa082, 0x3e80, 0x2071, 0x3540, + 0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000, + 0x2001, 0x0004, 0x70a2, 0x1078, 0x1a14, 0x0078, 0x1b35, 0x2071, + 0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000, + 0x2001, 0x0006, 0x70a2, 0x1078, 0x1a14, 0x2001, 0x0000, 0x0078, + 0x1b3b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, + 0x007c, 0x2c04, 0xa005, 0x0040, 0x1b58, 0x2060, 0x600c, 0xa306, + 0x00c0, 0x1b55, 0x6008, 0xa206, 0x00c0, 0x1b55, 0x6010, 0xa106, + 0x00c0, 0x1b55, 0xa006, 0x0078, 0x1b5a, 0x6000, 0x0078, 0x1b42, + 0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c, 0xa18c, 0x000f, + 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040, 0x1b6a, 0x2021, + 0xff80, 0x2122, 0x007c, 0x0e7e, 0x68e4, 0xa08c, 0x0020, 0x0040, + 0x1ba3, 0xa084, 0x0006, 0x00c0, 0x1ba3, 0x6010, 0x8007, 0xa084, + 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0, 0x3600, 0x7004, 0xa084, + 0x000a, 0x00c0, 0x1ba3, 0x7108, 0xa194, 0xff00, 0x0040, 0x1ba3, + 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x1b96, 0x2001, + 0x0032, 0xa106, 0x0040, 0x1b9a, 0x0078, 0x1b9e, 0x2009, 0x0020, + 0x0078, 0x1ba0, 0x2009, 0x003f, 0x0078, 0x1ba0, 0x2011, 0x0000, + 0x2100, 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x1ba5, 0x007e, + 0x2071, 0x0000, 0x7018, 0xa084, 0x0001, 0x00c0, 0x1baa, 0x007f, + 0x2e08, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, + 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x007f, 0x2070, + 0x007f, 0x0078, 0x1bc1, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300, + 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0xa594, 0x003f, 0xa484, 0x4000, + 0x0040, 0x1bd8, 0xa784, 0x007c, 0x00c0, 0x2d9c, 0x1078, 0x1ba5, + 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x1be0, 0x1078, 0x1ba5, + 0x8507, 0xa084, 0x000f, 0x0079, 0x1be5, 0x1fea, 0x209a, 0x20c0, + 0x22e6, 0x256b, 0x25b3, 0x25ea, 0x2665, 0x26bf, 0x2744, 0x1c0b, + 0x1bf5, 0x1e53, 0x1f1d, 0x254a, 0x1bf5, 0x1078, 0x1ba5, 0x0018, + 0x1bc8, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7003, + 0x0000, 0x703f, 0x0000, 0x7030, 0xa005, 0x0040, 0x1c09, 0x7033, + 0x0000, 0x0018, 0x1bc8, 0x705c, 0xa005, 0x00c0, 0x1cb6, 0x70a0, + 0xa084, 0x0007, 0x0079, 0x1c14, 0x1cd6, 0x1c1c, 0x1c2a, 0x1c4b, + 0x1c71, 0x1c9d, 0x1c9b, 0x1c1c, 0x7808, 0xa084, 0xfffd, 0x780a, + 0x2009, 0x0046, 0x1078, 0x2412, 0x00c0, 0x1c28, 0x7003, 0x0004, + 0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c49, 0x70b4, 0x8007, + 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0x78ab, 0x000c, 0x789b, + 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, + 0x2410, 0x00c0, 0x1c49, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, + 0x3570, 0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c6f, 0x71b4, + 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, + 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, + 0x0002, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, 0x2410, 0x00c0, + 0x1c6f, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, + 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c99, 0x71b4, 0x8107, 0x789b, + 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, + 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, 0x789b, + 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, + 0x2410, 0x00c0, 0x1c99, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, + 0x3570, 0x0078, 0x1bf7, 0x0078, 0x1c4b, 0x1078, 0x2d5e, 0x00c0, + 0x1bf7, 0x70bc, 0x2068, 0x789b, 0x0010, 0x6f10, 0x1078, 0x2ca1, + 0x2c50, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, + 0x2041, 0x0001, 0x2001, 0x0004, 0x0078, 0x1dde, 0x1078, 0x2d5e, + 0x00c0, 0x1bf7, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, + 0x2ca1, 0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6810, 0xa084, + 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, + 0x1078, 0x2dc5, 0x2001, 0x0003, 0x0078, 0x1dc9, 0x0018, 0x1bc8, + 0x7440, 0xa485, 0x0000, 0x0040, 0x1cf0, 0xa080, 0x3580, 0x2030, + 0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce7, 0x2009, 0x3580, 0x2164, + 0x6504, 0x85ff, 0x00c0, 0x1cfd, 0x8421, 0x00c0, 0x1ce1, 0x7146, + 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x7640, 0xa6b0, + 0x3580, 0x7144, 0x2600, 0x0078, 0x1cec, 0x7146, 0x2568, 0x2558, + 0x753e, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0, 0x1cfa, 0x6708, + 0x7736, 0xa784, 0x013f, 0x0040, 0x1d2f, 0xa784, 0x0021, 0x00c0, + 0x1cfa, 0xa784, 0x0002, 0x0040, 0x1d1c, 0xa784, 0x0004, 0x0040, + 0x1cfa, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, 0x00c0, 0x1cfa, + 0xa784, 0x0010, 0x00c0, 0x1cfa, 0xa784, 0x0100, 0x0040, 0x1d2f, + 0x6018, 0xa005, 0x00c0, 0x1cfa, 0xa7bc, 0xfeff, 0x670a, 0x681f, + 0x0000, 0x6e18, 0xa684, 0x000e, 0x6118, 0x0040, 0x1d3f, 0x601c, + 0xa102, 0x0048, 0x1d42, 0x0040, 0x1d42, 0x0078, 0x1cf6, 0x81ff, + 0x00c0, 0x1cf6, 0xa784, 0x0080, 0x00c0, 0x1d48, 0x700c, 0x6022, + 0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307, 0xa084, 0x000f, 0x8003, + 0x8003, 0x8003, 0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000, + 0x704e, 0x6004, 0x7052, 0x2a60, 0x0018, 0x1bc8, 0x789b, 0x0010, + 0xa046, 0x1078, 0x2d5e, 0x00c0, 0x1bf7, 0x6b10, 0xa39c, 0x0007, + 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, 0x0040, 0x1d73, 0xa684, + 0x0001, 0x0040, 0x1d75, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040, + 0x1d7b, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0, + 0x1d86, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x1dc7, 0x714c, 0xa18c, + 0x0800, 0x0040, 0x2902, 0x2011, 0x0021, 0x8004, 0x8004, 0x0048, + 0x1d9d, 0x2011, 0x0022, 0x8004, 0x0048, 0x1d9d, 0x2011, 0x0020, + 0x8004, 0x0048, 0x1d9d, 0x0040, 0x1dc7, 0x7aaa, 0x8840, 0x1078, + 0x2d77, 0x6a10, 0x610c, 0x8108, 0xa18c, 0x00ff, 0xa1e0, 0x3e80, + 0x2c64, 0x8cff, 0x0040, 0x1dbe, 0x6010, 0xa206, 0x00c0, 0x1da8, + 0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da3, 0x0c7e, 0x2a60, 0x6008, + 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x1cd6, 0x1078, 0x2d5e, + 0x00c0, 0x1bf7, 0x2a60, 0x610e, 0x79aa, 0x8840, 0x712e, 0x2001, + 0x0001, 0x007e, 0x7150, 0xa184, 0x0018, 0x0040, 0x1ddd, 0xa184, + 0x0010, 0x0040, 0x1dd7, 0x1078, 0x2acc, 0x00c0, 0x1ddd, 0xa184, + 0x0008, 0x0040, 0x1ddd, 0x1078, 0x29e6, 0x007f, 0x7002, 0xa68c, + 0x0060, 0x88ff, 0x0040, 0x1de6, 0xa18d, 0x0004, 0x795a, 0x69b2, + 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6814, 0xa085, + 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, + 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, + 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, + 0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2, 0x7eda, 0x7830, 0xa084, + 0x00c0, 0x00c0, 0x1e15, 0x0098, 0x1e1d, 0x6008, 0xa084, 0xffef, + 0x600a, 0x1078, 0x2d77, 0x0078, 0x1bff, 0x7200, 0xa284, 0x0007, + 0xa086, 0x0001, 0x00c0, 0x1e2a, 0x781b, 0x0049, 0x1078, 0x2d77, + 0x0078, 0x1e3b, 0x6ab0, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x0049, + 0x1078, 0x2d77, 0x7200, 0x2500, 0xa605, 0x0040, 0x1e3b, 0xa284, + 0x0007, 0x1079, 0x1e49, 0xad80, 0x0008, 0x7032, 0xa284, 0x0007, + 0xa086, 0x0001, 0x00c0, 0x1e47, 0x6018, 0x8000, 0x601a, 0x0078, + 0x1bf7, 0x1e51, 0x30f0, 0x30f0, 0x30df, 0x30f0, 0x1e51, 0x1e51, + 0x1e51, 0x1078, 0x1ba5, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, + 0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x1e79, + 0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e68, 0x70a2, 0x0078, 0x1f01, + 0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e77, 0x70bc, 0x2068, 0x6817, + 0x0004, 0x6813, 0x0000, 0x681c, 0xa085, 0x0008, 0x681e, 0x70a3, + 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, 0xa186, 0x0001, 0x0040, + 0x1e9b, 0xa186, 0x0007, 0x00c0, 0x1e8b, 0x2009, 0x352b, 0x200b, + 0x0005, 0x0078, 0x1e9b, 0x2009, 0x3513, 0x2104, 0x2009, 0x3512, + 0x200a, 0x2009, 0x352b, 0x200b, 0x0001, 0x70a3, 0x0000, 0x70a7, + 0x0001, 0x0078, 0x1e9d, 0x70a3, 0x0000, 0x1078, 0x2ec7, 0x20a9, + 0x0010, 0x2039, 0x0000, 0x1078, 0x2ba6, 0xa7b8, 0x0100, 0x0070, + 0x1eab, 0x0078, 0x1ea3, 0x7000, 0x2020, 0x0079, 0x1eaf, 0x1edd, + 0x1ec6, 0x1ec6, 0x1eb9, 0x1edd, 0x1edd, 0x1eb7, 0x1eb7, 0x1078, + 0x1ba5, 0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x1ec6, 0xad06, + 0x00c0, 0x1ec6, 0x6800, 0x2022, 0x0078, 0x1ed6, 0x681c, 0xa084, + 0x0001, 0x00c0, 0x1ed2, 0x6f10, 0x1078, 0x2ca1, 0x1078, 0x28d9, + 0x0078, 0x1ed6, 0x7054, 0x2060, 0x6800, 0x6002, 0x6a16, 0x681c, + 0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x2021, 0x3f80, 0x1078, + 0x1f07, 0x2021, 0x3557, 0x1078, 0x1f07, 0x20a9, 0x0000, 0x2021, + 0x3e80, 0x1078, 0x1f07, 0x8420, 0x0070, 0x1ef0, 0x0078, 0x1ee9, + 0x20a9, 0x0080, 0x2061, 0x3680, 0x6018, 0x6110, 0xa102, 0x6012, + 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x1f00, 0x0078, 0x1ef4, + 0x157f, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x047e, + 0x2404, 0xa005, 0x0040, 0x1f19, 0x2068, 0x6800, 0x007e, 0x6a16, + 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x007f, 0x0078, + 0x1f09, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, + 0x1f23, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x1f26, 0x1f29, 0x1f9c, + 0x1faa, 0xa282, 0x0002, 0x0040, 0x1f2f, 0x1078, 0x1ba5, 0x70a0, + 0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079, 0x1f36, 0x1f3e, 0x1f3e, + 0x1f40, 0x1f74, 0x2908, 0x1f3e, 0x1f74, 0x1f3e, 0x1078, 0x1ba5, + 0x77b4, 0x1078, 0x2ba6, 0x77b4, 0xa7bc, 0x0f00, 0x1078, 0x2ca1, + 0x6018, 0xa005, 0x0040, 0x1f6b, 0x2021, 0x3f80, 0x2009, 0x0004, + 0x2011, 0x0010, 0x1078, 0x1fc5, 0x0040, 0x1f6b, 0x157e, 0x20a9, + 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, + 0x1078, 0x1fc5, 0x047f, 0x0040, 0x1f6a, 0x8420, 0x0070, 0x1f6a, + 0x0078, 0x1f5b, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x1f46, + 0x0078, 0x1bff, 0x0078, 0x1bff, 0x77b4, 0x1078, 0x2ca1, 0x6018, + 0xa005, 0x0040, 0x1f9a, 0x2021, 0x3f80, 0x2009, 0x0005, 0x2011, + 0x0020, 0x1078, 0x1fc5, 0x0040, 0x1f9a, 0x157e, 0x20a9, 0x0000, + 0x2021, 0x3e80, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, + 0x1fc5, 0x047f, 0x0040, 0x1f99, 0x8420, 0x0070, 0x1f99, 0x0078, + 0x1f8a, 0x157f, 0x0078, 0x1bff, 0x2200, 0x0079, 0x1f9f, 0x1fa2, + 0x1fa4, 0x1fa4, 0x1078, 0x1ba5, 0x70a3, 0x0000, 0x70a7, 0x0001, + 0x0078, 0x1bf7, 0x2200, 0x0079, 0x1fad, 0x1fb2, 0x1fa4, 0x1fb0, + 0x1078, 0x1ba5, 0x1078, 0x241f, 0x7000, 0xa086, 0x0001, 0x00c0, + 0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, + 0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x2404, 0xa005, 0x0040, + 0x1fe6, 0x2068, 0x2d04, 0x007e, 0x6810, 0xa706, 0x0040, 0x1fd4, + 0x2d20, 0x007f, 0x0078, 0x1fc6, 0x007f, 0x2022, 0x6916, 0x681c, + 0xa205, 0x681e, 0x1078, 0x17dd, 0x6010, 0x8001, 0x6012, 0x6008, + 0xa084, 0xffef, 0x600a, 0x1078, 0x28ef, 0x007c, 0xa085, 0x0001, + 0x0078, 0x1fe5, 0x2300, 0x0079, 0x1fed, 0x1ff2, 0x1ff0, 0x2035, + 0x1078, 0x1ba5, 0x78e4, 0xa005, 0x00d0, 0x2015, 0x0018, 0x2015, + 0x2008, 0xa084, 0x0030, 0x00c0, 0x2001, 0x781b, 0x0049, 0x0078, + 0x1bf7, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1ffd, 0x2100, 0xa084, + 0x0007, 0x0079, 0x200b, 0x2023, 0x2029, 0x201d, 0x2013, 0x2d58, + 0x2d58, 0x2013, 0x202f, 0x1078, 0x1ba5, 0x7000, 0xa005, 0x0040, + 0x1bff, 0x2001, 0x0003, 0x0078, 0x22fa, 0x1078, 0x2b89, 0x781b, + 0x0055, 0x0078, 0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00dc, 0x0078, + 0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078, + 0x2b89, 0x781b, 0x009d, 0x0078, 0x1bf7, 0xa584, 0x000f, 0x00c0, + 0x205f, 0x1078, 0x241f, 0x7000, 0x0079, 0x203e, 0x2046, 0x2053, + 0x2046, 0x28af, 0x2048, 0x28af, 0x2046, 0x2046, 0x1078, 0x1ba5, + 0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004, 0x00c0, 0x2051, 0x0078, + 0x2908, 0x0078, 0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, + 0x600a, 0x1078, 0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x78e4, + 0xa005, 0x00d0, 0x2015, 0x0018, 0x2015, 0x2008, 0xa084, 0x0030, + 0x00c0, 0x206e, 0x781b, 0x0049, 0x0078, 0x1bf7, 0x78ec, 0xa084, + 0x0003, 0x0040, 0x206a, 0x2100, 0xa184, 0x0007, 0x0079, 0x2078, + 0x2088, 0x208e, 0x2082, 0x2080, 0x2d58, 0x2d58, 0x2080, 0x2d50, + 0x1078, 0x1ba5, 0x1078, 0x2b91, 0x781b, 0x0055, 0x0078, 0x1bf7, + 0x1078, 0x2b91, 0x781b, 0x00dc, 0x0078, 0x1bf7, 0x1078, 0x2b91, + 0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078, 0x2b91, 0x781b, 0x009d, + 0x0078, 0x1bf7, 0x2300, 0x0079, 0x209d, 0x20a2, 0x20a0, 0x20a4, + 0x1078, 0x1ba5, 0x0078, 0x2665, 0x6817, 0x0008, 0x78a3, 0x0000, + 0x79e4, 0xa184, 0x0030, 0x0040, 0x2665, 0x78ec, 0xa084, 0x0003, + 0x0040, 0x2665, 0xa184, 0x0007, 0x0079, 0x20b6, 0x2023, 0x2029, + 0x201d, 0x2d30, 0x2d58, 0x2d58, 0x20be, 0x2d50, 0x1078, 0x1ba5, + 0xa282, 0x0005, 0x0050, 0x20c6, 0x1078, 0x1ba5, 0x2300, 0x0079, + 0x20c9, 0x20cc, 0x22ce, 0x22da, 0x2200, 0x0079, 0x20cf, 0x20d4, + 0x20d6, 0x20e9, 0x20d4, 0x22b3, 0x1078, 0x1ba5, 0x789b, 0x0018, + 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x2b6a, 0xa08a, + 0x0004, 0x00c8, 0x2b6a, 0x0079, 0x20e5, 0x2b6a, 0x2b6a, 0x2b6a, + 0x2b0c, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x20fe, + 0xa184, 0x0018, 0x0040, 0x20fa, 0x0078, 0x2b6a, 0x7000, 0xa005, + 0x00c0, 0x20f4, 0x2011, 0x0003, 0x0078, 0x2752, 0xa184, 0x00ff, + 0xa08a, 0x0010, 0x00c8, 0x2b6a, 0x0079, 0x2106, 0x2118, 0x2116, + 0x212e, 0x2130, 0x21c2, 0x2b6a, 0x2b6a, 0x21c4, 0x2b6a, 0x2b6a, + 0x22af, 0x22af, 0x2b6a, 0x2b6a, 0x2b6a, 0x22b1, 0x1078, 0x1ba5, + 0xa684, 0x1000, 0x0040, 0x2125, 0x2001, 0x0300, 0x8000, 0x8000, + 0x783a, 0x781b, 0x009a, 0x0078, 0x1bf7, 0x6814, 0xa084, 0x8000, + 0x0040, 0x212c, 0x6817, 0x0003, 0x0078, 0x2d30, 0x1078, 0x1ba5, + 0x691c, 0x691e, 0xa684, 0x1800, 0x00c0, 0x214a, 0x681c, 0xa084, + 0x0001, 0x00c0, 0x2152, 0x6814, 0xa086, 0x0008, 0x00c0, 0x2142, + 0x6817, 0x0000, 0xa684, 0x0400, 0x0040, 0x21be, 0x781b, 0x0058, + 0x0078, 0x1bf7, 0xa684, 0x1000, 0x0040, 0x2152, 0x781b, 0x0058, + 0x0078, 0x1bf7, 0xa684, 0x0060, 0x0040, 0x21ba, 0xa684, 0x0800, + 0x0040, 0x21ba, 0xa684, 0x8000, 0x00c0, 0x2160, 0x0078, 0x217a, + 0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b, 0x0074, 0x7aac, 0x79ac, + 0x78ac, 0x801b, 0x00c8, 0x216d, 0x8000, 0xa084, 0x003f, 0xa108, + 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, + 0xa303, 0x68aa, 0xa684, 0x4000, 0x0040, 0x2182, 0xa6b4, 0xbfff, + 0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003, 0x00c0, 0x218f, 0x1078, + 0x2f3a, 0x1078, 0x30df, 0x781b, 0x0067, 0x0078, 0x1bf7, 0xa006, + 0x1078, 0x3194, 0x6aac, 0x69a8, 0x6c94, 0x6b90, 0x2200, 0xa105, + 0x0040, 0x219e, 0x2200, 0xa422, 0x2100, 0xa31b, 0x7cd2, 0x7bd6, + 0x2300, 0xa405, 0x00c0, 0x21ac, 0xa6b5, 0x4000, 0x7e5a, 0x6eb2, + 0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x0067, 0x2200, 0xa115, + 0x00c0, 0x21b6, 0x1078, 0x30f0, 0x0078, 0x1bf7, 0x1078, 0x311d, + 0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0058, + 0x0078, 0x1bf7, 0x1078, 0x1ba5, 0x0078, 0x2221, 0x691c, 0xa184, + 0x0100, 0x0040, 0x21dc, 0xa18c, 0xfeff, 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, - 0x6006, 0x0c7f, 0x0078, 0x2198, 0xa184, 0x0200, 0x0040, 0x2198, + 0x6006, 0x0c7f, 0x0078, 0x2210, 0xa184, 0x0200, 0x0040, 0x2210, 0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, - 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2198, 0x1078, 0x2bf8, 0x1078, - 0x294d, 0x88ff, 0x0040, 0x2198, 0x789b, 0x0060, 0x2800, 0x78aa, - 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2194, - 0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, - 0x7e58, 0xa684, 0x0400, 0x00c0, 0x21a1, 0x781b, 0x0058, 0x0078, - 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x0078, 0x2acb, 0x0078, - 0x2acb, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x21a7, + 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078, + 0x29e6, 0x88ff, 0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa, + 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x220c, + 0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, + 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2219, 0x781b, 0x0058, 0x0078, + 0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x0078, 0x2b70, 0x0078, + 0x2b70, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x221f, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0, - 0x21cc, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x21c4, - 0x0048, 0x21c4, 0x0078, 0x21c6, 0x0078, 0x214e, 0x24a8, 0x7aa8, - 0x00f0, 0x21c6, 0x0078, 0x21b2, 0xa284, 0x00f0, 0xa086, 0x0020, - 0x00c0, 0x2228, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x21dc, - 0x0048, 0x21dc, 0x0078, 0x2225, 0xa286, 0x0023, 0x0040, 0x21a7, + 0x2244, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x223c, + 0x0048, 0x223c, 0x0078, 0x223e, 0x0078, 0x21c6, 0x24a8, 0x7aa8, + 0x00f0, 0x223e, 0x0078, 0x222a, 0xa284, 0x00f0, 0xa086, 0x0020, + 0x00c0, 0x22a0, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x2254, + 0x0048, 0x2254, 0x0078, 0x229d, 0xa286, 0x0023, 0x0040, 0x221f, 0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58, 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, 0x600a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0010, - 0x0040, 0x2200, 0x1078, 0x2bf8, 0x1078, 0x2a33, 0x0078, 0x220f, + 0x0040, 0x2278, 0x1078, 0x2c9d, 0x1078, 0x2acc, 0x0078, 0x2287, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, - 0x0008, 0x0040, 0x2198, 0x1078, 0x2bf8, 0x1078, 0x294d, 0x88ff, - 0x0040, 0x2198, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004, - 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2221, 0x781b, 0x0055, 0x0078, - 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7aa8, 0x0078, 0x21b2, - 0x8318, 0x2300, 0xa102, 0x0040, 0x2231, 0x0048, 0x2231, 0x0078, - 0x21b2, 0xa284, 0x0080, 0x00c0, 0x2ad1, 0x0078, 0x2acb, 0x0078, - 0x2ad1, 0x0078, 0x2ac5, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, - 0xa08e, 0x0001, 0x0040, 0x2246, 0x1078, 0x1b4e, 0x7aa8, 0xa294, - 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2ac5, - 0x0079, 0x2252, 0x2ac5, 0x28a0, 0x2ac5, 0x29ce, 0xa282, 0x0000, - 0x00c0, 0x225c, 0x1078, 0x1b4e, 0x1078, 0x2ae4, 0x781b, 0x0069, - 0x0078, 0x1ba0, 0xa282, 0x0003, 0x00c0, 0x2268, 0x1078, 0x1b4e, - 0x1078, 0x2af4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0xa282, 0x0004, - 0x0050, 0x2274, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x2277, 0x227a, - 0x2351, 0x237b, 0xa286, 0x0003, 0x0040, 0x2280, 0x1078, 0x1b4e, - 0x2001, 0x0000, 0x703a, 0x7000, 0xa084, 0x0007, 0x0079, 0x2288, - 0x2290, 0x2292, 0x2292, 0x2471, 0x2499, 0x243b, 0x2290, 0x2290, - 0x1078, 0x1b4e, 0xa684, 0x1000, 0x00c0, 0x229a, 0x1078, 0x2e0e, - 0x0040, 0x232b, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x22e2, 0xa186, - 0x0008, 0x00c0, 0x22b1, 0x1078, 0x2853, 0x6008, 0xa084, 0xffef, - 0x600a, 0x1078, 0x2806, 0x0040, 0x22e2, 0x1078, 0x2e0e, 0x0078, - 0x22c9, 0xa186, 0x0028, 0x00c0, 0x22e2, 0x1078, 0x2e0e, 0x6008, - 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x22c9, 0x8001, - 0x601a, 0xa005, 0x0040, 0x22c9, 0x8001, 0xa005, 0x0040, 0x22c9, - 0x601e, 0x681c, 0xa084, 0x0001, 0x0040, 0x1ba8, 0x681c, 0xa084, + 0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078, 0x29e6, 0x88ff, + 0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004, + 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2299, 0x781b, 0x0055, 0x0078, + 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7aa8, 0x0078, 0x222a, + 0x8318, 0x2300, 0xa102, 0x0040, 0x22a9, 0x0048, 0x22a9, 0x0078, + 0x222a, 0xa284, 0x0080, 0x00c0, 0x2b76, 0x0078, 0x2b70, 0x0078, + 0x2b76, 0x0078, 0x2b6a, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, + 0xa08e, 0x0001, 0x0040, 0x22be, 0x1078, 0x1ba5, 0x7aa8, 0xa294, + 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2b6a, + 0x0079, 0x22ca, 0x2b6a, 0x2939, 0x2b6a, 0x2a67, 0xa282, 0x0000, + 0x00c0, 0x22d4, 0x1078, 0x1ba5, 0x1078, 0x2b89, 0x781b, 0x0069, + 0x0078, 0x1bf7, 0xa282, 0x0003, 0x00c0, 0x22e0, 0x1078, 0x1ba5, + 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7, 0xa282, 0x0004, + 0x0050, 0x22ec, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x22ef, 0x22f2, + 0x23c9, 0x23fa, 0xa286, 0x0003, 0x0040, 0x22f8, 0x1078, 0x1ba5, + 0x2001, 0x0000, 0x703a, 0x7000, 0xa084, 0x0007, 0x0079, 0x2300, + 0x2308, 0x230a, 0x230a, 0x2508, 0x2530, 0x24d2, 0x2308, 0x2308, + 0x1078, 0x1ba5, 0xa684, 0x1000, 0x00c0, 0x2312, 0x1078, 0x2ec7, + 0x0040, 0x23a3, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x235a, 0xa186, + 0x0008, 0x00c0, 0x2329, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, + 0x600a, 0x1078, 0x28a2, 0x0040, 0x235a, 0x1078, 0x2ec7, 0x0078, + 0x2341, 0xa186, 0x0028, 0x00c0, 0x235a, 0x1078, 0x2ec7, 0x6008, + 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2341, 0x8001, + 0x601a, 0xa005, 0x0040, 0x2341, 0x8001, 0xa005, 0x0040, 0x2341, + 0x601e, 0x681c, 0xa084, 0x0001, 0x0040, 0x1bff, 0x681c, 0xa084, 0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, - 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x22df, 0x6002, 0x6006, - 0x0078, 0x1ba8, 0x017e, 0x1078, 0x23a0, 0x017f, 0xa684, 0xdf00, - 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, 0x0040, 0x232b, 0xa186, - 0x0002, 0x00c0, 0x2323, 0xa684, 0x0800, 0x00c0, 0x22ff, 0xa684, - 0x0060, 0x0040, 0x22ff, 0x78d8, 0x7adc, 0x682e, 0x6a2a, 0x8717, - 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3500, 0xa290, - 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, 0x2310, 0x0078, 0x2316, + 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2357, 0x6002, 0x6006, + 0x0078, 0x1bff, 0x017e, 0x1078, 0x241f, 0x017f, 0xa684, 0xdf00, + 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, 0x0040, 0x23a3, 0xa186, + 0x0002, 0x00c0, 0x239b, 0xa684, 0x0800, 0x00c0, 0x2377, 0xa684, + 0x0060, 0x0040, 0x2377, 0x78d8, 0x7adc, 0x682e, 0x6a2a, 0x8717, + 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3600, 0xa290, + 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, 0x2388, 0x0078, 0x238e, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, 0x8211, 0xa384, 0x0400, - 0x0040, 0x2323, 0x689c, 0xa084, 0x0100, 0x00c0, 0x2323, 0x1078, - 0x23fa, 0x0078, 0x1ba8, 0xa186, 0x0018, 0x0040, 0x232b, 0xa186, - 0x0014, 0x0040, 0x1ba8, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040, - 0x2333, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, 0x2844, - 0x1078, 0x2853, 0x00c0, 0x2340, 0x6008, 0xa084, 0xffef, 0x600a, - 0x681c, 0xa084, 0x0001, 0x00c0, 0x2349, 0x1078, 0x283d, 0x0078, - 0x234d, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17be, 0x0078, - 0x1ba8, 0xa282, 0x0004, 0x0048, 0x2357, 0x1078, 0x1b4e, 0x2200, - 0x0079, 0x235a, 0x235e, 0x2360, 0x2366, 0x2360, 0x1078, 0x1b4e, - 0x1078, 0x2ae4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7890, 0x8007, - 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, - 0x00ff, 0xa186, 0x0003, 0x0040, 0x2377, 0x0078, 0x2ac5, 0x781b, - 0x006a, 0x0078, 0x1ba0, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff, - 0x00c0, 0x2386, 0x1078, 0x2ae4, 0x0078, 0x238d, 0x8211, 0x0040, - 0x238b, 0x1078, 0x1b4e, 0x1078, 0x2af4, 0x781b, 0x0069, 0x0078, - 0x1ba0, 0x1078, 0x2cc6, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x239d, - 0x0018, 0x239d, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, - 0xa684, 0x0060, 0x00c0, 0x23aa, 0x682f, 0x0000, 0x682b, 0x0000, - 0x0078, 0x23f9, 0xa684, 0x0800, 0x00c0, 0x23b1, 0x1078, 0x2e0e, - 0x007c, 0xa684, 0x0020, 0x0040, 0x23d3, 0x78d0, 0x8003, 0x00c8, - 0x23bf, 0xa006, 0x1078, 0x30a0, 0x78d4, 0x1078, 0x3103, 0xa684, - 0x4000, 0x0040, 0x23c9, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, - 0x23ae, 0x7038, 0xa005, 0x00c0, 0x23cd, 0x79d8, 0x7adc, 0x692e, - 0x6a2a, 0x0078, 0x23ae, 0xa684, 0x4000, 0x0040, 0x23dd, 0x682f, - 0x0000, 0x682b, 0x0000, 0x0078, 0x23ae, 0x7038, 0xa005, 0x00c0, - 0x23e3, 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, 0x80f3, 0x00c8, - 0x23ea, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, - 0x6a2a, 0x2100, 0xa205, 0x00c0, 0x23f7, 0x0078, 0x23ae, 0x1078, - 0x30a0, 0x007c, 0xa384, 0x0200, 0x0040, 0x2402, 0x6008, 0xa085, - 0x0002, 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, 0x6a3a, 0x693e, - 0x682b, 0x0300, 0x682f, 0x0000, 0x6833, 0x2000, 0x6893, 0x0000, - 0x6897, 0x0020, 0x7000, 0x0079, 0x2415, 0x241d, 0x241f, 0x2428, - 0x241d, 0x241d, 0x241d, 0x241d, 0x241d, 0x1078, 0x1b4e, 0x681c, - 0xa084, 0x0001, 0x00c0, 0x2428, 0x1078, 0x283d, 0x0078, 0x242e, - 0x7054, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3457, - 0x2404, 0xa005, 0x0040, 0x2437, 0x2020, 0x0078, 0x2430, 0x2d22, - 0x206b, 0x0000, 0x007c, 0x77b4, 0x1078, 0x2b01, 0xa7bc, 0x0f00, - 0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x246a, 0x0d7e, 0x2001, - 0x3e90, 0x2068, 0x0d7f, 0x2021, 0x3e80, 0x2009, 0x0004, 0x2011, - 0x0010, 0x1078, 0x1f69, 0x0040, 0x246a, 0x157e, 0x20a9, 0x0000, - 0x2021, 0x3d80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, - 0x1f69, 0x047f, 0x0040, 0x2469, 0x8420, 0x0070, 0x2469, 0x0078, - 0x245a, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x2440, 0x0078, - 0x1ba8, 0x1078, 0x2844, 0x1078, 0x2853, 0x6827, 0x0000, 0x789b, - 0x000e, 0x6f10, 0x6813, 0x0002, 0x1078, 0x30d4, 0xa684, 0x0800, - 0x0040, 0x2486, 0x6918, 0xa18d, 0x2000, 0x691a, 0x6814, 0xa084, - 0x8000, 0x0040, 0x248d, 0x6817, 0x0000, 0x2021, 0x3457, 0x6800, - 0x2022, 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, 0x17be, 0x0078, - 0x1ba8, 0x1078, 0x23a0, 0x6827, 0x0000, 0x789b, 0x000e, 0x6f10, - 0x1078, 0x2ccb, 0xa08c, 0x00ff, 0x6912, 0x6814, 0xa084, 0x8000, - 0x0040, 0x24ac, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x70a3, - 0x0000, 0x0078, 0x1ba8, 0xa006, 0x1078, 0x2e0e, 0x6813, 0x0000, - 0x6817, 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, 0x0000, 0x7000, - 0x0079, 0x24c2, 0x24ca, 0x24cc, 0x24cc, 0x24ce, 0x24ce, 0x24ce, - 0x24ca, 0x24ca, 0x1078, 0x1b4e, 0x1078, 0x2853, 0x6008, 0xa084, - 0xffef, 0x600a, 0x0078, 0x281e, 0x2300, 0x0079, 0x24d7, 0x24da, - 0x24dc, 0x251a, 0x1078, 0x1b4e, 0x7000, 0x0079, 0x24df, 0x24e7, - 0x24e9, 0x24e9, 0x24f4, 0x24e9, 0x24fb, 0x24e7, 0x24e7, 0x1078, - 0x1b4e, 0xa684, 0x2000, 0x00c0, 0x24f4, 0xa6b5, 0x2000, 0x7e5a, - 0x1078, 0x2ffc, 0x0078, 0x2c7f, 0x6814, 0xa084, 0x8000, 0x0040, - 0x24fb, 0x6817, 0x0007, 0x2009, 0x3418, 0x210c, 0xa186, 0x0000, - 0x0040, 0x2510, 0xa186, 0x0001, 0x0040, 0x2514, 0x2009, 0x342b, - 0x200b, 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1ba0, - 0x781b, 0x00dd, 0x0078, 0x1ba0, 0x2009, 0x342b, 0x200b, 0x000a, - 0x0078, 0x1ba0, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x251f, 0x2522, - 0x2524, 0x2547, 0x1078, 0x1b4e, 0x7000, 0x0079, 0x2527, 0x252f, - 0x2531, 0x2531, 0x253c, 0x2531, 0x2543, 0x252f, 0x252f, 0x1078, - 0x1b4e, 0xa684, 0x2000, 0x00c0, 0x253c, 0xa6b5, 0x2000, 0x7e5a, - 0x1078, 0x2ffc, 0x0078, 0x2c7f, 0x6814, 0xa084, 0x8000, 0x0040, - 0x2543, 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, 0x1ba0, 0x681c, - 0xa085, 0x0004, 0x681e, 0x1078, 0x2c4a, 0xa6b5, 0x0800, 0x1078, - 0x2ae4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x2300, 0x0079, 0x2558, - 0x255b, 0x255d, 0x255f, 0x1078, 0x1b4e, 0x1078, 0x1b4e, 0xa684, - 0x0400, 0x00c0, 0x257e, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, - 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040, - 0x2576, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x257a, 0x2001, 0x0014, - 0x0078, 0x2282, 0xa184, 0x0007, 0x0079, 0x25b6, 0x7a90, 0xa294, - 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x25b4, 0x789b, - 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x25a5, 0x7ba8, 0x7ba8, - 0xa386, 0x0001, 0x00c0, 0x2598, 0x2009, 0xfff7, 0x0078, 0x259e, - 0xa386, 0x0003, 0x00c0, 0x25a5, 0x2009, 0xffef, 0x0c7e, 0x7048, - 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, - 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c, - 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c7f, 0x1fc3, 0x1fc9, - 0x25c0, 0x25c8, 0x25be, 0x25be, 0x25be, 0x2c7f, 0x1078, 0x1b4e, - 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c87, - 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c7f, - 0x79e4, 0xa184, 0x0030, 0x0040, 0x25da, 0x78ec, 0xa084, 0x0003, - 0x00c0, 0x25e2, 0x6814, 0xa085, 0x8000, 0x6816, 0x2001, 0x0014, - 0x0078, 0x2282, 0xa184, 0x0007, 0x0079, 0x25e6, 0x2c7f, 0x2c7f, - 0x25ee, 0x2c7f, 0x2ca7, 0x2ca7, 0x2c7f, 0x2c7f, 0xa684, 0x0400, - 0x00c0, 0x261f, 0x681c, 0xa084, 0x0001, 0x0040, 0x2c87, 0xa68c, - 0x2060, 0xa18c, 0xfffb, 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab, - 0x0000, 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, - 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, - 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, - 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, 0x0078, 0x2c87, 0x6814, - 0xa084, 0x8000, 0x0040, 0x2626, 0x6817, 0x0008, 0x781b, 0x00d8, - 0x0078, 0x1ba0, 0x2300, 0x0079, 0x262d, 0x2632, 0x26ac, 0x2630, - 0x1078, 0x1b4e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2637, 0x263f, - 0x2641, 0x265d, 0x263f, 0x263f, 0x243b, 0x263f, 0x263f, 0x1078, - 0x1b4e, 0x691c, 0xa18d, 0x0001, 0x691e, 0x6800, 0x6006, 0xa005, - 0x00c0, 0x264b, 0x6002, 0x6818, 0xa084, 0x000e, 0x0040, 0x2657, - 0x7014, 0x68b6, 0x712c, 0xa188, 0x3d80, 0x0078, 0x2659, 0x2009, - 0x3e80, 0x2104, 0x6802, 0x2d0a, 0x7156, 0x691c, 0x691e, 0x6eb2, - 0xa684, 0x0060, 0x0040, 0x26aa, 0xa684, 0x0800, 0x00c0, 0x266e, - 0x6890, 0x6894, 0x1078, 0x2e0e, 0x0078, 0x26aa, 0xa684, 0x0020, - 0x0040, 0x2680, 0xa006, 0x1078, 0x30a0, 0x78d0, 0x8003, 0x00c8, - 0x267c, 0x78d4, 0x1078, 0x3103, 0x79d8, 0x7adc, 0x0078, 0x2684, - 0x1078, 0x2c09, 0x1078, 0x30a0, 0xa684, 0x8000, 0x0040, 0x26aa, - 0xa684, 0x7fff, 0x68b2, 0x789b, 0x0074, 0x1078, 0x2ccb, 0x2010, - 0x1078, 0x2ccb, 0x2008, 0xa684, 0x0020, 0x00c0, 0x26a2, 0x1078, - 0x2ccb, 0x801b, 0x00c8, 0x269d, 0x8000, 0xa084, 0x003f, 0xa108, - 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, - 0xa303, 0x68aa, 0x0078, 0x1ba8, 0x0078, 0x2ad1, 0x7033, 0x0000, - 0xa282, 0x0005, 0x0050, 0x26b6, 0x1078, 0x1b4e, 0x2300, 0x0079, - 0x26b9, 0x26bc, 0x26c6, 0x26e9, 0x2200, 0x0079, 0x26bf, 0x26c4, - 0x2ad1, 0x26c4, 0x2712, 0x2763, 0x1078, 0x1b4e, 0x7000, 0xa086, - 0x0001, 0x00c0, 0x26d3, 0x1078, 0x2853, 0x1078, 0x2e0e, 0x7034, - 0x600a, 0x0078, 0x26d8, 0x7000, 0xa086, 0x0003, 0x0040, 0x26cd, - 0x7003, 0x0005, 0x2001, 0x3e90, 0x2068, 0x703e, 0x7032, 0x2200, - 0x0079, 0x26e2, 0x2ad1, 0x26e7, 0x2712, 0x26e7, 0x2ad1, 0x1078, - 0x1b4e, 0x7000, 0xa086, 0x0001, 0x00c0, 0x26f6, 0x1078, 0x2853, - 0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x26fb, 0x7000, 0xa086, - 0x0003, 0x0040, 0x26f0, 0x7003, 0x0005, 0x2001, 0x3e90, 0x2068, - 0x703e, 0x7032, 0x2200, 0x0079, 0x2705, 0x270c, 0x270a, 0x270c, - 0x270a, 0x270c, 0x1078, 0x1b4e, 0x1078, 0x2af4, 0x781b, 0x0069, - 0x0078, 0x1ba0, 0x7000, 0xa086, 0x0001, 0x00c0, 0x271f, 0x1078, - 0x2853, 0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x2724, 0x7000, - 0xa086, 0x0003, 0x0040, 0x2719, 0x7003, 0x0002, 0x7a80, 0xa294, - 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x2069, - 0x3e80, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x273f, - 0x6810, 0xa206, 0x0040, 0x2758, 0x6800, 0x0078, 0x2732, 0x7003, - 0x0005, 0x2001, 0x3e90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, - 0x002e, 0x2003, 0x0000, 0x8000, 0x0070, 0x2750, 0x0078, 0x2749, - 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, - 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, 0x0040, 0x27b9, 0x1078, - 0x2aec, 0x0078, 0x27b9, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2770, - 0x1078, 0x2853, 0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x2775, - 0x7000, 0xa086, 0x0003, 0x0040, 0x276a, 0x7003, 0x0002, 0x7a80, - 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, - 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x3d80, 0x2d04, 0x2d08, - 0x7156, 0x2068, 0xa005, 0x0040, 0x2794, 0x6810, 0xa206, 0x0040, - 0x27ad, 0x6800, 0x0078, 0x2787, 0x7003, 0x0005, 0x2001, 0x3e90, - 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002e, 0x2003, 0x0000, - 0x8000, 0x0070, 0x27a5, 0x0078, 0x279e, 0x157f, 0x6a12, 0x68b3, - 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, 0x681c, - 0xa084, 0x0c00, 0x0040, 0x27b9, 0x1078, 0x2ae8, 0x7e58, 0x0078, - 0x27b9, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xa080, 0x3500, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, - 0xa684, 0x0060, 0x0040, 0x27ea, 0x6b94, 0x6c90, 0x69a8, 0x68ac, - 0xa105, 0x00c0, 0x27db, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x1078, - 0x2ffc, 0x0078, 0x27ea, 0x68ac, 0xa31a, 0x2100, 0xa423, 0x2400, - 0xa305, 0x0040, 0x27ea, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68ac, - 0x1078, 0x3029, 0x077f, 0x1078, 0x2bfc, 0x2009, 0x006a, 0xa684, - 0x0008, 0x0040, 0x27f5, 0x2009, 0x0069, 0xa6b5, 0x2000, 0x7e5a, - 0x791a, 0x2d00, 0x703e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa080, 0x3500, 0x2048, 0x0078, 0x1ba0, 0x6020, 0xa005, - 0x0040, 0x2812, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, - 0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x2e0e, 0x6813, 0x0000, - 0x6817, 0x0001, 0x681f, 0x0040, 0x681b, 0x0100, 0x7000, 0xa084, - 0x0007, 0x0079, 0x2823, 0x282b, 0x282d, 0x282d, 0x2839, 0x2835, - 0x282b, 0x282b, 0x282b, 0x1078, 0x1b4e, 0x1078, 0x2844, 0x1078, - 0x283d, 0x1078, 0x17be, 0x0078, 0x1ba8, 0x70a3, 0x0000, 0x0078, - 0x1ba8, 0x6817, 0x0000, 0x0078, 0x2471, 0x6800, 0xa005, 0x00c0, - 0x2842, 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, 0x284d, - 0x8001, 0x00d0, 0x284d, 0x1078, 0x1b4e, 0x6012, 0x6008, 0xa084, - 0xffef, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x2859, 0x8001, - 0x601a, 0x007c, 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, - 0x2863, 0x6817, 0x0018, 0x0078, 0x2894, 0x1078, 0x2cc6, 0x6814, - 0xa084, 0x8000, 0x0040, 0x286e, 0x6817, 0x0019, 0x0078, 0x2894, - 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, 0x2879, 0x6817, - 0x001a, 0x0078, 0x2894, 0x71b8, 0xa18c, 0x00ff, 0xa1e8, 0x3d80, - 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2888, 0x0078, 0x1ba8, - 0x6810, 0x72b4, 0xa206, 0x0040, 0x2890, 0x6800, 0x0078, 0x2881, - 0x6800, 0x200a, 0x6817, 0x0005, 0x681b, 0x0000, 0x681f, 0x0020, - 0x1078, 0x2844, 0x1078, 0x283d, 0x1078, 0x17be, 0x0078, 0x1ba8, - 0xa282, 0x0003, 0x00c0, 0x2ac5, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, - 0xa6b4, 0x00ff, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184, 0x0100, - 0x0040, 0x2900, 0xa18c, 0xfeff, 0x691e, 0xa6b4, 0x00ff, 0x0040, - 0x28ea, 0xa682, 0x000f, 0x0048, 0x28c1, 0x0040, 0x28c1, 0x2031, - 0x000f, 0x852b, 0x852b, 0x1078, 0x2b7f, 0x0040, 0x28cb, 0x1078, - 0x299a, 0x0078, 0x28f3, 0x1078, 0x2b3a, 0x0c7e, 0x2960, 0x6004, - 0xa084, 0xfff5, 0x6006, 0x1078, 0x29be, 0x0c7f, 0x691c, 0xa18d, - 0x0100, 0x691e, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, - 0x00c0, 0x28e6, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b, 0x0069, - 0x0078, 0x1ba0, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, - 0x1078, 0x29be, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x28fc, - 0x781b, 0x0058, 0x0078, 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, - 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040, 0x2940, - 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000f, 0x0048, 0x2914, - 0x0040, 0x2914, 0x2011, 0x000f, 0x2600, 0xa202, 0x00c8, 0x2919, - 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, - 0x2929, 0xa282, 0x0019, 0x00c8, 0x292f, 0x2011, 0x0019, 0x0078, - 0x292f, 0xa282, 0x000c, 0x00c8, 0x292f, 0x2011, 0x000c, 0x2200, - 0xa502, 0x00c8, 0x2934, 0x2228, 0x1078, 0x2b3e, 0x852b, 0x852b, - 0x1078, 0x2b7f, 0x0040, 0x2940, 0x1078, 0x299a, 0x0078, 0x2944, - 0x1078, 0x2b3a, 0x1078, 0x29be, 0x7858, 0xa085, 0x0004, 0x785a, - 0x0c7f, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x0c7e, 0x2960, 0x6000, - 0xa084, 0x1000, 0x00c0, 0x2968, 0x6010, 0xa084, 0x000f, 0x00c0, - 0x2962, 0xa18c, 0x0002, 0x00c0, 0x2962, 0xa18c, 0xfff5, 0x6106, - 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x298a, - 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x2978, - 0xa282, 0x0019, 0x00c8, 0x297e, 0x2011, 0x0019, 0x0078, 0x297e, - 0xa282, 0x000c, 0x00c8, 0x297e, 0x2011, 0x000c, 0x6308, 0x831f, - 0xa39c, 0x00ff, 0xa382, 0x000f, 0x0048, 0x298a, 0x0040, 0x298a, - 0x2019, 0x000f, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, - 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x681c, 0xa085, 0x0100, 0x681e, - 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084, 0xfff0, - 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, - 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a, 0xa6b4, - 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, - 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7048, - 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, - 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282, 0x0002, - 0x00c0, 0x2ac5, 0x7aa8, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184, - 0x0200, 0x0040, 0x2a13, 0xa18c, 0xfdff, 0x691e, 0xa294, 0x00ff, - 0xa282, 0x0002, 0x00c8, 0x2ac5, 0x1078, 0x2a5a, 0x1078, 0x29be, - 0xa980, 0x0001, 0x200c, 0x1078, 0x2bf8, 0x1078, 0x294d, 0x88ff, - 0x0040, 0x2a06, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, - 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2a02, 0x781b, 0x0055, - 0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7e58, 0xa684, - 0x0400, 0x00c0, 0x2a0f, 0x781b, 0x0058, 0x0078, 0x1ba0, 0x781b, - 0x006a, 0x0078, 0x1ba0, 0xa282, 0x0002, 0x00c8, 0x2a1b, 0xa284, - 0x0001, 0x0040, 0x2a25, 0x7148, 0xa188, 0x0000, 0x210c, 0xa18c, - 0x2000, 0x00c0, 0x2a25, 0x2011, 0x0000, 0x1078, 0x2b2c, 0x1078, - 0x2a5a, 0x1078, 0x29be, 0x7858, 0xa085, 0x0004, 0x785a, 0x781b, - 0x0069, 0x0078, 0x1ba0, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, - 0x0001, 0xa084, 0x2000, 0x00c0, 0x2a4a, 0x6014, 0xa084, 0x0040, - 0x00c0, 0x2a48, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x2a57, - 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, - 0x7aaa, 0xa8c0, 0x0004, 0x681c, 0xa085, 0x0200, 0x681e, 0x027f, - 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040, 0x2a62, - 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, - 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef, - 0x6006, 0x0c7f, 0x007c, 0xa684, 0x0020, 0x0040, 0x2ac1, 0x7888, - 0xa084, 0x0040, 0x0040, 0x2ac1, 0x78a8, 0x8001, 0x0040, 0x2a80, - 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x2a87, 0x8000, 0xa005, - 0x0040, 0x2aa8, 0x831b, 0x00c8, 0x2a90, 0x8001, 0x0040, 0x2abd, - 0xa006, 0x1078, 0x30a0, 0x78b4, 0x1078, 0x3103, 0x0078, 0x2ac1, - 0xa684, 0x4000, 0x0040, 0x2aa8, 0x78b8, 0x801b, 0x00c8, 0x2aa1, - 0x8000, 0xa084, 0x003f, 0x00c0, 0x2abd, 0xa6b4, 0xbfff, 0x7e5a, - 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x2ab1, 0xa291, - 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x30a0, 0x781b, - 0x0067, 0x1078, 0x2f6a, 0x0078, 0x1ba0, 0x781b, 0x0067, 0x0078, - 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x1078, 0x2af8, 0x781b, - 0x0069, 0x0078, 0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x0069, 0x0078, - 0x1ba0, 0x6823, 0x0002, 0x1078, 0x2aec, 0x691c, 0xa18d, 0x0020, - 0x691e, 0x6814, 0xa084, 0x8000, 0x0040, 0x2ae0, 0x6817, 0x0005, - 0x781b, 0x0069, 0x0078, 0x1ba0, 0x2001, 0x0005, 0x0078, 0x2afa, - 0x2001, 0x000c, 0x0078, 0x2afa, 0x2001, 0x0006, 0x0078, 0x2afa, - 0x2001, 0x000d, 0x0078, 0x2afa, 0x2001, 0x0009, 0x0078, 0x2afa, - 0x2001, 0x0007, 0x789b, 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a, - 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, - 0xa0e0, 0x3500, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, - 0x0040, 0x2b1a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, - 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, - 0x0040, 0x2b2a, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, - 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, - 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, - 0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, - 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, - 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, - 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, - 0xfff0, 0x2001, 0x3446, 0x2004, 0xa082, 0x0028, 0x0040, 0x2b68, - 0x2021, 0x2bdf, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2b6e, - 0x2021, 0x2beb, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, - 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x2b7d, 0x8420, 0x2300, - 0xa210, 0x0070, 0x2b7d, 0x0078, 0x2b70, 0x157f, 0x007c, 0x157e, - 0x2011, 0x3446, 0x2214, 0xa282, 0x0032, 0x0048, 0x2b93, 0x0040, - 0x2b97, 0x2021, 0x2bd1, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, - 0x0032, 0x0078, 0x2ba7, 0xa282, 0x0028, 0x0040, 0x2b9f, 0x2021, - 0x2bdf, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2ba5, 0x2021, - 0x2beb, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200, - 0xa502, 0x0040, 0x2bb7, 0x0048, 0x2bb7, 0x8420, 0x2300, 0xa210, - 0x0070, 0x2bb4, 0x0078, 0x2ba7, 0x157f, 0xa006, 0x007c, 0x157f, - 0xa582, 0x0064, 0x00c8, 0x2bc0, 0x7808, 0xa085, 0x0040, 0x780a, - 0x78ec, 0xa084, 0x0300, 0x0040, 0x2bce, 0x2404, 0xa09e, 0x2002, - 0x00c0, 0x2bce, 0x2001, 0x2101, 0x0078, 0x2bcf, 0x2404, 0xa005, - 0x007c, 0x2002, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, - 0x6605, 0x6805, 0x7806, 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, - 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, - 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, - 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, - 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, - 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3580, - 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x2c10, 0x8000, - 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, - 0x0100, 0x2009, 0x3440, 0x2091, 0x8000, 0x2104, 0x0079, 0x2c20, - 0x2c46, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c28, 0x2c28, - 0x1078, 0x1b4e, 0x784b, 0x0004, 0x68b0, 0xa085, 0x4000, 0x68b2, - 0x7858, 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, - 0x2c46, 0x0018, 0x2c46, 0x6818, 0xa084, 0x0020, 0x00c0, 0x2c44, - 0x781b, 0x00dd, 0x0078, 0x2c46, 0x781b, 0x00e4, 0x2091, 0x8001, - 0x0f7f, 0x007c, 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, 0x8003, - 0x8003, 0x8003, 0xa0e0, 0x3500, 0x6004, 0xa084, 0x000a, 0x00c0, - 0x2c7d, 0x6108, 0xa194, 0xff00, 0x0040, 0x2c7d, 0xa18c, 0x00ff, - 0x2001, 0x0019, 0xa106, 0x0040, 0x2c6c, 0x2001, 0x0032, 0xa106, - 0x0040, 0x2c70, 0x0078, 0x2c74, 0x2009, 0x0020, 0x0078, 0x2c76, - 0x2009, 0x003f, 0x0078, 0x2c76, 0x2011, 0x0000, 0x2100, 0xa205, - 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, - 0x006a, 0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x781b, - 0x0058, 0x0078, 0x1ba0, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b, - 0x00dd, 0x0078, 0x1ba0, 0x781b, 0x00dc, 0x0078, 0x1ba0, 0x781b, - 0x00e4, 0x0078, 0x1ba0, 0x781b, 0x00e3, 0x0078, 0x1ba0, 0x781b, - 0x009e, 0x0078, 0x1ba0, 0x781b, 0x009d, 0x0078, 0x1ba0, 0x70a3, - 0x0001, 0x781b, 0x0046, 0x0078, 0x1ba0, 0x007e, 0x7830, 0xa084, - 0x00c0, 0x00c0, 0x2cc4, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, - 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x2cc4, - 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0x7808, 0xa085, - 0x0002, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0, 0x2ccb, - 0x0098, 0x2cd4, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, + 0x0040, 0x239b, 0x689c, 0xa084, 0x0100, 0x00c0, 0x239b, 0x1078, + 0x2491, 0x0078, 0x1bff, 0xa186, 0x0018, 0x0040, 0x23a3, 0xa186, + 0x0014, 0x0040, 0x1bff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040, + 0x23ab, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, 0x28e0, + 0x1078, 0x28ef, 0x00c0, 0x23b8, 0x6008, 0xa084, 0xffef, 0x600a, + 0x681c, 0xa084, 0x0001, 0x00c0, 0x23c1, 0x1078, 0x28d9, 0x0078, + 0x23c5, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17dd, 0x0078, + 0x1bff, 0xa282, 0x0004, 0x0048, 0x23cf, 0x1078, 0x1ba5, 0x2200, + 0x0079, 0x23d2, 0x23d6, 0x23d8, 0x23e5, 0x23d8, 0x1078, 0x1ba5, + 0x7000, 0xa086, 0x0005, 0x0040, 0x23e1, 0x1078, 0x2b89, 0x781b, + 0x0069, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x7890, 0x8007, 0x8001, + 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, + 0xa186, 0x0003, 0x0040, 0x23f6, 0x0078, 0x2b6a, 0x781b, 0x006a, + 0x0078, 0x1bf7, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff, 0x00c0, + 0x2405, 0x1078, 0x2b89, 0x0078, 0x240c, 0x8211, 0x0040, 0x240a, + 0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7, + 0x1078, 0x2d77, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x241c, 0x0018, + 0x241c, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, + 0x0060, 0x00c0, 0x2429, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, + 0x2490, 0xa684, 0x0800, 0x00c0, 0x2438, 0x68b0, 0xa084, 0x4800, + 0xa635, 0xa684, 0x0800, 0x00c0, 0x2438, 0x1078, 0x2ec7, 0x007c, + 0xa684, 0x0020, 0x0040, 0x2462, 0x78d0, 0x8003, 0x00c8, 0x2446, + 0xa006, 0x1078, 0x3194, 0x78d4, 0x1078, 0x31f9, 0xa684, 0x4000, + 0x0040, 0x2450, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x2435, + 0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x244a, + 0x7038, 0xa005, 0x00c0, 0x245c, 0x79d8, 0x7adc, 0x692e, 0x6a2a, + 0x0078, 0x2435, 0xa684, 0x4000, 0x0040, 0x246c, 0x682f, 0x0000, + 0x682b, 0x0000, 0x0078, 0x2435, 0x68b0, 0xa084, 0x4800, 0xa635, + 0xa684, 0x4000, 0x00c0, 0x2466, 0x7038, 0xa005, 0x00c0, 0x247a, + 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, 0x80f3, 0x00c8, 0x2481, + 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a2a, + 0x2100, 0xa205, 0x00c0, 0x248e, 0x0078, 0x2435, 0x1078, 0x3194, + 0x007c, 0xa384, 0x0200, 0x0040, 0x2499, 0x6008, 0xa085, 0x0002, + 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, 0x6a3a, 0x693e, 0x682b, + 0x0300, 0x682f, 0x0000, 0x6833, 0x2000, 0x6893, 0x0000, 0x6897, + 0x0020, 0x7000, 0x0079, 0x24ac, 0x24b4, 0x24b6, 0x24bf, 0x24b4, + 0x24b4, 0x24b4, 0x24b4, 0x24b4, 0x1078, 0x1ba5, 0x681c, 0xa084, + 0x0001, 0x00c0, 0x24bf, 0x1078, 0x28d9, 0x0078, 0x24c5, 0x7054, + 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3557, 0x2404, + 0xa005, 0x0040, 0x24ce, 0x2020, 0x0078, 0x24c7, 0x2d22, 0x206b, + 0x0000, 0x007c, 0x77b4, 0x1078, 0x2ba6, 0xa7bc, 0x0f00, 0x1078, + 0x2ca1, 0x6018, 0xa005, 0x0040, 0x2501, 0x0d7e, 0x2001, 0x3f90, + 0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009, 0x0004, 0x2011, 0x0010, + 0x1078, 0x1fc5, 0x0040, 0x2501, 0x157e, 0x20a9, 0x0000, 0x2021, + 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc5, + 0x047f, 0x0040, 0x2500, 0x8420, 0x0070, 0x2500, 0x0078, 0x24f1, + 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x24d7, 0x0078, 0x1bff, + 0x1078, 0x28e0, 0x1078, 0x28ef, 0x6827, 0x0000, 0x789b, 0x000e, + 0x6f10, 0x6813, 0x0002, 0x1078, 0x31ca, 0xa684, 0x0800, 0x0040, + 0x251d, 0x6918, 0xa18d, 0x2000, 0x691a, 0x6814, 0xa084, 0x8000, + 0x0040, 0x2524, 0x6817, 0x0000, 0x2021, 0x3557, 0x6800, 0x2022, + 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, 0x17dd, 0x0078, 0x1bff, + 0x1078, 0x241f, 0x6827, 0x0000, 0x789b, 0x000e, 0x6f10, 0x1078, + 0x2d7c, 0xa08c, 0x00ff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040, + 0x2543, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x70a3, 0x0000, + 0x0078, 0x1bff, 0xa006, 0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817, + 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, 0x0000, 0x7000, 0x0079, + 0x2559, 0x2561, 0x2563, 0x2563, 0x2565, 0x2565, 0x2565, 0x2561, + 0x2561, 0x1078, 0x1ba5, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, + 0x600a, 0x0078, 0x28ba, 0x2300, 0x0079, 0x256e, 0x2571, 0x2573, + 0x25b1, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x2576, 0x257e, 0x2580, + 0x2580, 0x258b, 0x2580, 0x2592, 0x257e, 0x257e, 0x1078, 0x1ba5, + 0xa684, 0x2000, 0x00c0, 0x258b, 0xa6b5, 0x2000, 0x7e5a, 0x1078, + 0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x2592, + 0x6817, 0x0007, 0x2009, 0x3518, 0x210c, 0xa186, 0x0000, 0x0040, + 0x25a7, 0xa186, 0x0001, 0x0040, 0x25ab, 0x2009, 0x352b, 0x200b, + 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x781b, + 0x00dd, 0x0078, 0x1bf7, 0x2009, 0x352b, 0x200b, 0x000a, 0x0078, + 0x1bf7, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x25b6, 0x25b9, 0x25bb, + 0x25de, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x25be, 0x25c6, 0x25c8, + 0x25c8, 0x25d3, 0x25c8, 0x25da, 0x25c6, 0x25c6, 0x1078, 0x1ba5, + 0xa684, 0x2000, 0x00c0, 0x25d3, 0xa6b5, 0x2000, 0x7e5a, 0x1078, + 0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x25da, + 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, 0x1bf7, 0x681c, 0xa085, + 0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078, 0x2b89, 0x781b, 0x0069, + 0x0078, 0x1bf7, 0x2300, 0x0079, 0x25ed, 0x25f0, 0x25f2, 0x25f4, + 0x1078, 0x1ba5, 0x1078, 0x1ba5, 0xa684, 0x0400, 0x00c0, 0x2613, + 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, + 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040, 0x260b, 0x78ec, 0xa084, + 0x0003, 0x00c0, 0x260f, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184, + 0x0007, 0x0079, 0x264b, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, + 0x79a8, 0x81ff, 0x0040, 0x2649, 0x789b, 0x0010, 0x7ba8, 0xa384, + 0x0001, 0x00c0, 0x263a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, + 0x262d, 0x2009, 0xfff7, 0x0078, 0x2633, 0xa386, 0x0003, 0x00c0, + 0x263a, 0x2009, 0xffef, 0x0c7e, 0x7048, 0x2060, 0x6004, 0xa104, + 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, + 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, + 0x691e, 0x0078, 0x2d30, 0x2023, 0x2029, 0x2655, 0x265d, 0x2653, + 0x2653, 0x2653, 0x2d30, 0x1078, 0x1ba5, 0x691c, 0xa18c, 0xfdff, + 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d38, 0x691c, 0xa18c, 0xfdff, + 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d30, 0x79e4, 0xa184, 0x0030, + 0x0040, 0x266f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x2677, 0x6814, + 0xa085, 0x8000, 0x6816, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184, + 0x0007, 0x0079, 0x267b, 0x2d30, 0x2d30, 0x2683, 0x2d30, 0x2d58, + 0x2d58, 0x2d30, 0x2d30, 0xa684, 0x0400, 0x00c0, 0x26b4, 0x681c, + 0xa084, 0x0001, 0x0040, 0x2d38, 0xa68c, 0x2060, 0xa18c, 0xfffb, + 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, + 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e, + 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a, + 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b, + 0x007e, 0x78aa, 0x0078, 0x2d38, 0x6814, 0xa084, 0x8000, 0x0040, + 0x26bb, 0x6817, 0x0008, 0x781b, 0x00d8, 0x0078, 0x1bf7, 0x2300, + 0x0079, 0x26c2, 0x26c7, 0x2742, 0x26c5, 0x1078, 0x1ba5, 0x7000, + 0xa084, 0x0007, 0x0079, 0x26cc, 0x26d4, 0x26d6, 0x26f2, 0x26d4, + 0x26d4, 0x24d2, 0x26d4, 0x26d4, 0x1078, 0x1ba5, 0x691c, 0xa18d, + 0x0001, 0x691e, 0x6800, 0x6006, 0xa005, 0x00c0, 0x26e0, 0x6002, + 0x6818, 0xa084, 0x000e, 0x0040, 0x26ec, 0x7014, 0x68b6, 0x712c, + 0xa188, 0x3e80, 0x0078, 0x26ee, 0x2009, 0x3f80, 0x2104, 0x6802, + 0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060, 0x0040, 0x2740, 0xa684, + 0x0800, 0x00c0, 0x2704, 0xa684, 0x7fff, 0x68b2, 0x6890, 0x6894, + 0x1078, 0x2ec7, 0x0078, 0x2740, 0xa684, 0x0020, 0x0040, 0x2716, + 0xa006, 0x1078, 0x3194, 0x78d0, 0x8003, 0x00c8, 0x2712, 0x78d4, + 0x1078, 0x31f9, 0x79d8, 0x7adc, 0x0078, 0x271a, 0x1078, 0x2cae, + 0x1078, 0x3194, 0xa684, 0x8000, 0x0040, 0x2740, 0xa684, 0x7fff, + 0x68b2, 0x789b, 0x0074, 0x1078, 0x2d7c, 0x2010, 0x1078, 0x2d7c, + 0x2008, 0xa684, 0x0020, 0x00c0, 0x2738, 0x1078, 0x2d7c, 0x801b, + 0x00c8, 0x2733, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, + 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, + 0x0078, 0x1bff, 0x0078, 0x2b76, 0x7033, 0x0000, 0xa282, 0x0005, + 0x0050, 0x274c, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x274f, 0x2752, + 0x275c, 0x277f, 0x2200, 0x0079, 0x2755, 0x275a, 0x2b76, 0x275a, + 0x27a8, 0x27f9, 0x1078, 0x1ba5, 0x7000, 0xa086, 0x0001, 0x00c0, + 0x2769, 0x1078, 0x28ef, 0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078, + 0x276e, 0x7000, 0xa086, 0x0003, 0x0040, 0x2763, 0x7003, 0x0005, + 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x2778, + 0x2b76, 0x277d, 0x27a8, 0x277d, 0x2b76, 0x1078, 0x1ba5, 0x7000, + 0xa086, 0x0001, 0x00c0, 0x278c, 0x1078, 0x28ef, 0x1078, 0x2ec7, + 0x7034, 0x600a, 0x0078, 0x2791, 0x7000, 0xa086, 0x0003, 0x0040, + 0x2786, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, + 0x2200, 0x0079, 0x279b, 0x27a2, 0x27a0, 0x27a2, 0x27a0, 0x27a2, + 0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7, + 0x7000, 0xa086, 0x0001, 0x00c0, 0x27b5, 0x1078, 0x28ef, 0x1078, + 0x2ec7, 0x7034, 0x600a, 0x0078, 0x27ba, 0x7000, 0xa086, 0x0003, + 0x0040, 0x27af, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, + 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x2069, 0x3f80, 0x2d04, + 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x27d5, 0x6810, 0xa206, + 0x0040, 0x27ee, 0x6800, 0x0078, 0x27c8, 0x7003, 0x0005, 0x2001, + 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003, + 0x0000, 0x8000, 0x0070, 0x27e6, 0x0078, 0x27df, 0x157f, 0x6a12, + 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, + 0x681c, 0xa084, 0x0c00, 0x0040, 0x284f, 0x1078, 0x2b91, 0x0078, + 0x284f, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2806, 0x1078, 0x28ef, + 0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078, 0x280b, 0x7000, 0xa086, + 0x0003, 0x0040, 0x2800, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, + 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x79a8, 0x79a8, + 0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x7156, 0x2068, + 0xa005, 0x0040, 0x282a, 0x6810, 0xa206, 0x0040, 0x2843, 0x6800, + 0x0078, 0x281d, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, + 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, + 0x283b, 0x0078, 0x2834, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, + 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, + 0x0040, 0x284f, 0x1078, 0x2b8d, 0x7e58, 0x0078, 0x284f, 0x027e, + 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, + 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0xa684, 0x0060, + 0x0040, 0x2886, 0x6b94, 0x6c90, 0x69a8, 0x68ac, 0xa105, 0x00c0, + 0x2874, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a, + 0x1078, 0x30f0, 0x0078, 0x2886, 0x68ac, 0xa31a, 0x2100, 0xa423, + 0x2400, 0xa305, 0x0040, 0x2886, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, + 0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078, 0x311d, 0x077f, 0x1078, + 0x2ca1, 0x2009, 0x006a, 0xa684, 0x0008, 0x0040, 0x2891, 0x2009, + 0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a, 0x2d00, 0x703e, 0x8207, + 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048, + 0x0078, 0x1bf7, 0x6020, 0xa005, 0x0040, 0x28ae, 0x8001, 0x6022, + 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006, + 0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817, 0x0001, 0x681f, 0x0040, + 0x681b, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x28bf, 0x28c7, + 0x28c9, 0x28c9, 0x28d5, 0x28d1, 0x28c7, 0x28c7, 0x28c7, 0x1078, + 0x1ba5, 0x1078, 0x28e0, 0x1078, 0x28d9, 0x1078, 0x17dd, 0x0078, + 0x1bff, 0x70a3, 0x0000, 0x0078, 0x1bff, 0x6817, 0x0000, 0x0078, + 0x2508, 0x6800, 0xa005, 0x00c0, 0x28de, 0x6002, 0x6006, 0x007c, + 0x6010, 0xa005, 0x0040, 0x28e9, 0x8001, 0x00d0, 0x28e9, 0x1078, + 0x1ba5, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, + 0xa005, 0x0040, 0x28f5, 0x8001, 0x601a, 0x007c, 0x1078, 0x2d77, + 0x6817, 0x0018, 0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x0019, + 0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x001a, 0x0078, 0x2926, + 0x77b4, 0x1078, 0x2ca1, 0x71b8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80, + 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2918, 0x0078, 0x1bff, + 0x6810, 0x72b4, 0xa206, 0x0040, 0x2920, 0x6800, 0x0078, 0x2911, + 0x6800, 0x200a, 0x6817, 0x0005, 0x70bf, 0x0000, 0x1078, 0x28e0, + 0x681c, 0xa084, 0x0001, 0x00c0, 0x292f, 0x1078, 0x28d9, 0x1078, + 0x28ef, 0x681b, 0x0000, 0x681f, 0x0020, 0x1078, 0x17dd, 0x0078, + 0x1bff, 0xa282, 0x0003, 0x00c0, 0x2b6a, 0x7da8, 0xa5ac, 0x00ff, + 0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184, + 0x0100, 0x0040, 0x2999, 0xa18c, 0xfeff, 0x691e, 0xa6b4, 0x00ff, + 0x0040, 0x2983, 0xa682, 0x000f, 0x0048, 0x295a, 0x0040, 0x295a, + 0x2031, 0x000f, 0x852b, 0x852b, 0x1078, 0x2c24, 0x0040, 0x2964, + 0x1078, 0x2a33, 0x0078, 0x298c, 0x1078, 0x2bdf, 0x0c7e, 0x2960, + 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a57, 0x0c7f, 0x691c, + 0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, + 0x0400, 0x00c0, 0x297f, 0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b, + 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, + 0x6006, 0x1078, 0x2a57, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0, + 0x2995, 0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078, + 0x1bf7, 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040, + 0x29d9, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000f, 0x0048, + 0x29ad, 0x0040, 0x29ad, 0x2011, 0x000f, 0x2600, 0xa202, 0x00c8, + 0x29b2, 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, + 0x00c0, 0x29c2, 0xa282, 0x0019, 0x00c8, 0x29c8, 0x2011, 0x0019, + 0x0078, 0x29c8, 0xa282, 0x000c, 0x00c8, 0x29c8, 0x2011, 0x000c, + 0x2200, 0xa502, 0x00c8, 0x29cd, 0x2228, 0x1078, 0x2be3, 0x852b, + 0x852b, 0x1078, 0x2c24, 0x0040, 0x29d9, 0x1078, 0x2a33, 0x0078, + 0x29dd, 0x1078, 0x2bdf, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004, + 0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960, + 0x6000, 0xa084, 0x1000, 0x00c0, 0x2a01, 0x6010, 0xa084, 0x000f, + 0x00c0, 0x29fb, 0xa18c, 0x0002, 0x00c0, 0x29fb, 0xa18c, 0xfff5, + 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, + 0x2a23, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, + 0x2a11, 0xa282, 0x0019, 0x00c8, 0x2a17, 0x2011, 0x0019, 0x0078, + 0x2a17, 0xa282, 0x000c, 0x00c8, 0x2a17, 0x2011, 0x000c, 0x6308, + 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f, 0x0048, 0x2a23, 0x0040, + 0x2a23, 0x2019, 0x000f, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, + 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x681c, 0xa085, 0x0100, + 0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084, + 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, + 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a, + 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, + 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, + 0x7048, 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, + 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282, + 0x0002, 0x00c0, 0x2b6a, 0x7aa8, 0x691c, 0xa18d, 0x0080, 0x691e, + 0xa184, 0x0200, 0x0040, 0x2aac, 0xa18c, 0xfdff, 0x691e, 0xa294, + 0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b6a, 0x1078, 0x2af3, 0x1078, + 0x2a57, 0xa980, 0x0001, 0x200c, 0x1078, 0x2c9d, 0x1078, 0x29e6, + 0x88ff, 0x0040, 0x2a9f, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, + 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2a9b, 0x781b, + 0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7e58, + 0xa684, 0x0400, 0x00c0, 0x2aa8, 0x781b, 0x0058, 0x0078, 0x1bf7, + 0x781b, 0x006a, 0x0078, 0x1bf7, 0xa282, 0x0002, 0x00c8, 0x2ab4, + 0xa284, 0x0001, 0x0040, 0x2abe, 0x7148, 0xa188, 0x0000, 0x210c, + 0xa18c, 0x2000, 0x00c0, 0x2abe, 0x2011, 0x0000, 0x1078, 0x2bd1, + 0x1078, 0x2af3, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004, 0x785a, + 0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x027e, 0x2960, 0x6000, + 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x2ae3, 0x6014, 0xa084, + 0x0040, 0x00c0, 0x2ae1, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, + 0x2af0, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, + 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c, 0xa085, 0x0200, 0x681e, + 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040, + 0x2afb, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, + 0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, + 0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, + 0x0040, 0x2b15, 0x007f, 0x0078, 0x2b18, 0x007f, 0x0078, 0x2b66, + 0xa684, 0x0020, 0x0040, 0x2b66, 0x7888, 0xa084, 0x0040, 0x0040, + 0x2b66, 0x78a8, 0x8001, 0x0040, 0x2b25, 0x7bb8, 0xa384, 0x003f, + 0x831b, 0x00c8, 0x2b2c, 0x8000, 0xa005, 0x0040, 0x2b4d, 0x831b, + 0x00c8, 0x2b35, 0x8001, 0x0040, 0x2b62, 0xa006, 0x1078, 0x3194, + 0x78b4, 0x1078, 0x31f9, 0x0078, 0x2b66, 0xa684, 0x4000, 0x0040, + 0x2b4d, 0x78b8, 0x801b, 0x00c8, 0x2b46, 0x8000, 0xa084, 0x003f, + 0x00c0, 0x2b62, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, 0x2001, + 0x0001, 0xa108, 0x00c8, 0x2b56, 0xa291, 0x0000, 0x79d2, 0x79da, + 0x7ad6, 0x7ade, 0x1078, 0x3194, 0x781b, 0x0067, 0x1078, 0x305e, + 0x0078, 0x1bf7, 0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x006a, + 0x0078, 0x1bf7, 0x1078, 0x2b9d, 0x781b, 0x0069, 0x0078, 0x1bf7, + 0x1078, 0x2b89, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x6823, 0x0002, + 0x1078, 0x2b91, 0x691c, 0xa18d, 0x0020, 0x691e, 0x6814, 0xa084, + 0x8000, 0x0040, 0x2b85, 0x6817, 0x0005, 0x781b, 0x0069, 0x0078, + 0x1bf7, 0x2001, 0x0005, 0x0078, 0x2b9f, 0x2001, 0x000c, 0x0078, + 0x2b9f, 0x2001, 0x0006, 0x0078, 0x2b9f, 0x2001, 0x000d, 0x0078, + 0x2b9f, 0x2001, 0x0009, 0x0078, 0x2b9f, 0x2001, 0x0007, 0x789b, + 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a, 0x007c, 0x077e, 0x873f, + 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x3600, 0xa7b8, + 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x2bbf, 0xa184, + 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008, 0x6006, 0x8738, + 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040, 0x2bcf, 0xa184, + 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010, 0x6006, 0x077f, + 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, + 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004, 0x007c, 0x2031, + 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, + 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, + 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, + 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2001, 0x3546, + 0x2004, 0xa082, 0x0028, 0x0040, 0x2c0d, 0x2021, 0x2c84, 0x2019, + 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c13, 0x2021, 0x2c90, 0x2019, + 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404, 0xa084, 0xfff0, + 0xa106, 0x0040, 0x2c22, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c22, + 0x0078, 0x2c15, 0x157f, 0x007c, 0x157e, 0x2011, 0x3546, 0x2214, + 0xa282, 0x0032, 0x0048, 0x2c38, 0x0040, 0x2c3c, 0x2021, 0x2c76, + 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x0078, 0x2c4c, + 0xa282, 0x0028, 0x0040, 0x2c44, 0x2021, 0x2c84, 0x2019, 0x0014, + 0x20a9, 0x000c, 0x0078, 0x2c4a, 0x2021, 0x2c90, 0x2019, 0x0019, + 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x2c5c, + 0x0048, 0x2c5c, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c59, 0x0078, + 0x2c4c, 0x157f, 0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, + 0x2c65, 0x7808, 0xa085, 0x0070, 0x780a, 0x78ec, 0xa084, 0x0300, + 0x0040, 0x2c73, 0x2404, 0xa09e, 0x1201, 0x00c0, 0x2c73, 0x2001, + 0x2101, 0x0078, 0x2c74, 0x2404, 0xa005, 0x007c, 0x1201, 0x3002, + 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, + 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202, + 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05, + 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604, + 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046, + 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003, + 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680, 0x007c, 0x79d8, 0x7adc, + 0x78d0, 0x801b, 0x00c8, 0x2cb5, 0x8000, 0xa084, 0x003f, 0xa108, + 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540, + 0x2091, 0x8000, 0x2104, 0x0079, 0x2cc5, 0x2cf7, 0x2ccf, 0x2ccf, + 0x2ccf, 0x2ccf, 0x2ccf, 0x2ccd, 0x2ccd, 0x1078, 0x1ba5, 0x784b, + 0x0004, 0x7848, 0xa084, 0x0004, 0x00c0, 0x2cd1, 0x784b, 0x0008, + 0x7848, 0xa084, 0x0008, 0x00c0, 0x2cd8, 0x68b0, 0xa085, 0x4000, + 0x68b2, 0x7858, 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080, + 0x00c0, 0x2cf7, 0x0018, 0x2cf7, 0x6818, 0xa084, 0x0020, 0x00c0, + 0x2cf5, 0x781b, 0x00dd, 0x0078, 0x2cf7, 0x781b, 0x00e4, 0x2091, + 0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, + 0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600, 0x6004, 0xa084, 0x000a, + 0x00c0, 0x2d2e, 0x6108, 0xa194, 0xff00, 0x0040, 0x2d2e, 0xa18c, + 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x2d1d, 0x2001, 0x0032, + 0xa106, 0x0040, 0x2d21, 0x0078, 0x2d25, 0x2009, 0x0020, 0x0078, + 0x2d27, 0x2009, 0x003f, 0x0078, 0x2d27, 0x2011, 0x0000, 0x2100, + 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, + 0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, + 0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x0055, 0x0078, 0x1bf7, + 0x781b, 0x00dd, 0x0078, 0x1bf7, 0x781b, 0x00dc, 0x0078, 0x1bf7, + 0x781b, 0x00e4, 0x0078, 0x1bf7, 0x781b, 0x00e3, 0x0078, 0x1bf7, + 0x781b, 0x009e, 0x0078, 0x1bf7, 0x781b, 0x009d, 0x0078, 0x1bf7, + 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x007e, 0x7830, + 0xa084, 0x00c0, 0x00c0, 0x2d75, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, - 0x2ce3, 0x0098, 0x2ce1, 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002, - 0x780a, 0x007f, 0x007c, 0xa784, 0x0070, 0x0040, 0x2cef, 0x6817, - 0x0003, 0x7858, 0xa084, 0x3f00, 0x681a, 0x682f, 0x0000, 0x682b, - 0x0000, 0x784b, 0x0008, 0x78e4, 0xa005, 0x00d0, 0x1fb9, 0xa084, - 0x0020, 0x0040, 0x1fb9, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1fb9, - 0x0018, 0x1fb9, 0x0078, 0x2acb, 0x0c7e, 0x6810, 0x8007, 0xa084, - 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3500, 0x2060, 0x2048, - 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, 0x007c, 0x0020, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9847, 0x0014, 0x0014, - 0x98f5, 0x98e7, 0x0014, 0x0014, 0x0080, 0x00bf, 0x0100, 0x0402, - 0x2008, 0xf880, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0xa200, - 0x8838, 0x817e, 0x842a, 0x84a0, 0x3806, 0x8839, 0x28c2, 0x9cc3, - 0xa805, 0x0864, 0xa83b, 0x3008, 0x28c1, 0x9cc3, 0xa201, 0x300c, - 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, - 0x28e2, 0x9ca0, 0xa8f3, 0x0864, 0xa829, 0x300c, 0xa801, 0x3008, - 0x28e1, 0x9ca0, 0x280d, 0xa204, 0x64c0, 0x67a0, 0x6fc0, 0x1814, - 0x883b, 0x7023, 0x8576, 0x8677, 0xa80f, 0x786e, 0x883e, 0xa80c, - 0x282b, 0xa205, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, - 0x8576, 0x8677, 0xa801, 0x883e, 0x2069, 0x28c1, 0x9cc3, 0x2044, - 0x2103, 0x20a2, 0x2081, 0xa8dc, 0xa207, 0x0014, 0xa203, 0x8000, - 0x84a8, 0x85a4, 0x1872, 0x849a, 0x883c, 0x1fe2, 0xf601, 0xa208, - 0x856e, 0x866f, 0x0704, 0x3008, 0x9ca0, 0x0014, 0xa202, 0x8000, - 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf848, 0x8174, 0x86eb, 0x85eb, - 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f1, 0xf861, 0xa8e8, 0xf801, - 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, - 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, - 0x0014, 0xa206, 0x6865, 0x817f, 0x842a, 0x1dc1, 0x8823, 0x0016, - 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021, - 0x3008, 0x84a8, 0x1dc6, 0x20d7, 0x8822, 0x0016, 0x8000, 0x2848, - 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd, - 0xa887, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017, 0x300c, - 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x26e0, 0x873a, 0xfaa2, - 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x817e, 0x842a, - 0x84a0, 0x3806, 0x0210, 0x9ccd, 0x0704, 0x0000, 0x127e, 0x2091, - 0x2200, 0x2049, 0x2e0e, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215, - 0x7008, 0xa084, 0xfffd, 0xa205, 0x0040, 0x2e20, 0x1078, 0x2e68, - 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, 0x0040, - 0x2e42, 0x2c70, 0x2039, 0x2e47, 0x2704, 0xae68, 0x680c, 0xa630, - 0x6808, 0xa529, 0x8421, 0x0040, 0x2e42, 0x8738, 0x2704, 0xa005, - 0x00c0, 0x2e2d, 0x7098, 0xa075, 0x0040, 0x2e42, 0x2039, 0x2e44, - 0x0078, 0x2e2c, 0x007c, 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, - 0x0014, 0x0018, 0x001c, 0x0000, 0x127e, 0x2091, 0x2200, 0x2079, - 0x3400, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, - 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, - 0x0000, 0x2049, 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, 0x007c, - 0x2049, 0x2e68, 0x7004, 0x8004, 0x00c8, 0x2e90, 0x7007, 0x0012, - 0x7108, 0x7008, 0xa106, 0x00c0, 0x2e70, 0xa184, 0x0030, 0x0040, - 0x2e7d, 0xa086, 0x0030, 0x00c0, 0x2e70, 0x7000, 0xa084, 0x0001, - 0x00c0, 0x2e90, 0x7008, 0xa084, 0x000c, 0x00c0, 0x2e90, 0x710c, - 0xa184, 0x0300, 0x00c0, 0x2e90, 0xa184, 0x007f, 0x00c0, 0x2e68, - 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, - 0x2e94, 0x7007, 0x0012, 0x7108, 0x8104, 0x0048, 0x2e99, 0x78b3, - 0x0000, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e, - 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x2eb6, 0x157f, - 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x2118, - 0x7108, 0x700c, 0xa084, 0x0300, 0x00c0, 0x2ef8, 0xa184, 0x000c, - 0x00c0, 0x2ef8, 0x8213, 0x8213, 0x8213, 0x8213, 0xa284, 0x0100, - 0xa10d, 0x810b, 0x810b, 0x810f, 0xa184, 0x0007, 0x0079, 0x2ed0, - 0x2eda, 0x2eea, 0x2ef8, 0x2eea, 0x2f0c, 0x2f0c, 0x2ef8, 0x2f0a, - 0x1078, 0x1b4e, 0x7007, 0x0002, 0x8aff, 0x00c0, 0x2ee3, 0x2049, - 0x0000, 0x0078, 0x2ee7, 0x1078, 0x3077, 0x00c0, 0x2ee3, 0x78b3, - 0x0000, 0x007c, 0x7007, 0x0002, 0x8aff, 0x00c0, 0x2ef1, 0x0078, - 0x2ef5, 0x1078, 0x3077, 0x00c0, 0x2ef1, 0x78b3, 0x0000, 0x007c, - 0x7007, 0x0002, 0x1078, 0x2e68, 0x1078, 0x2c16, 0x6814, 0xa084, - 0x8000, 0x0040, 0x2f05, 0x6817, 0x0002, 0x007c, 0x1078, 0x1b4e, - 0x1078, 0x1b4e, 0x1078, 0x2f5c, 0x7210, 0x7114, 0x700c, 0xa09c, - 0x007f, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x78b0, 0xa005, - 0x0040, 0x2f1e, 0x78b3, 0x0000, 0x0078, 0x2f41, 0x1078, 0x2f5c, - 0x2704, 0x2c58, 0xac60, 0x630c, 0x2200, 0xa322, 0x6308, 0x2100, - 0xa31b, 0x2400, 0xa305, 0x0040, 0x2f37, 0x00c8, 0x2f37, 0x8412, - 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x2f1e, 0x2b60, - 0x8a07, 0xa7ba, 0x2e44, 0xa73d, 0x2c00, 0x6882, 0x6f86, 0x6c8e, - 0x6b8a, 0x1078, 0x2e68, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, - 0x2f50, 0x6098, 0xa005, 0x0040, 0x2f59, 0x2060, 0x2039, 0x2e44, - 0x8a51, 0x0040, 0x2f58, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0, - 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, - 0x00c0, 0x2f69, 0x2039, 0x2e4a, 0x6000, 0xa064, 0x00c0, 0x2f69, - 0x2d60, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6880, - 0x2060, 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, - 0x00ff, 0xa0b8, 0x2e44, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, - 0x0040, 0x0040, 0x2f85, 0xa6b5, 0x0001, 0x0f7e, 0x2079, 0x0100, - 0x7858, 0x0f7f, 0xa084, 0x0040, 0x0040, 0x2f94, 0xa684, 0x0001, - 0x00c0, 0x2f94, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084, - 0x0004, 0x00c0, 0x2f96, 0x7000, 0xa005, 0x0040, 0x2fa1, 0x1078, - 0x1b4e, 0x2400, 0xa305, 0x00c0, 0x2fa7, 0x0078, 0x2fe4, 0x2c58, - 0x2704, 0xac60, 0x6004, 0xa400, 0x007e, 0x701a, 0x6000, 0xa301, - 0x701e, 0x2009, 0x04fd, 0x2104, 0xa086, 0x04fd, 0x007f, 0x00c0, - 0x2fd4, 0xa084, 0x0001, 0x0040, 0x2fd4, 0xa684, 0x0001, 0x00c0, - 0x2fd4, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, - 0x78b3, 0x0001, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6004, 0xa400, - 0x701a, 0x6000, 0xa301, 0x701e, 0x620c, 0x2400, 0xa202, 0x7012, - 0x6208, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, - 0x1078, 0x2f44, 0x0078, 0x2fe6, 0x1078, 0x3077, 0x00c0, 0x2fe4, - 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, - 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x2ff2, 0x7003, - 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, - 0x0d7f, 0x2049, 0x2ffc, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x3005, 0x7000, 0xa005, 0x0040, 0x3010, 0x1078, 0x1b4e, - 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x301a, - 0xa6b5, 0x0001, 0x6824, 0xa005, 0x0040, 0x3026, 0x2050, 0x2039, - 0x2e47, 0x2d60, 0x1078, 0x3077, 0x00c0, 0x3022, 0x127f, 0x2000, - 0x007c, 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, - 0x037f, 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, - 0x0040, 0x303c, 0xa6b5, 0x0001, 0x2049, 0x3029, 0x6824, 0xa055, - 0x0040, 0x3074, 0x2d70, 0x2e60, 0x2039, 0x2e47, 0x2704, 0xae68, - 0x680c, 0xa422, 0x6808, 0xa31b, 0x0048, 0x3061, 0x8a51, 0x00c0, - 0x3053, 0x1078, 0x1b4e, 0x8738, 0x2704, 0xa005, 0x00c0, 0x3047, - 0x7098, 0xa075, 0x2060, 0x0040, 0x3074, 0x2039, 0x2e44, 0x0078, - 0x3046, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x690c, 0x2400, - 0xa122, 0x6908, 0x2300, 0xa11b, 0x00c8, 0x3070, 0x1078, 0x1b4e, - 0x2071, 0x0020, 0x0078, 0x2f94, 0x127f, 0x2000, 0x007c, 0x7008, - 0xa084, 0x00c0, 0xa086, 0x00c0, 0x0040, 0x309f, 0x2704, 0xac08, - 0x2104, 0x701e, 0x8108, 0x2104, 0x701a, 0x8108, 0x2104, 0x7016, - 0x8108, 0x2104, 0x7012, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, - 0xa084, 0x0040, 0x0040, 0x309a, 0xa684, 0x0001, 0x00c0, 0x309a, - 0xa6b5, 0x0001, 0x7602, 0x7007, 0x0001, 0x1078, 0x2f44, 0x007c, - 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x30a0, 0x0d7f, - 0x087f, 0x7108, 0xa184, 0x00c0, 0x00c0, 0x30b6, 0x6824, 0xa005, - 0x0040, 0x30c6, 0x1078, 0x2f0c, 0x0078, 0x30c6, 0x7108, 0x8104, - 0x00c8, 0x30be, 0x1078, 0x2eb6, 0x0078, 0x30a9, 0x7007, 0x0010, - 0x7108, 0x8104, 0x00c8, 0x30c0, 0x1078, 0x2eb6, 0x7008, 0xa086, - 0x0002, 0x00c0, 0x30a9, 0x7000, 0xa005, 0x00c0, 0x30a9, 0x2049, - 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, - 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x30d4, 0xad80, 0x0010, - 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x007f, 0x6826, 0x7007, - 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x30f2, 0x8000, - 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, - 0x30f4, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, - 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, - 0x0d7f, 0x2049, 0x3103, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c, - 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2e44, 0x7e08, - 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, - 0x311c, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, 0x701a, 0x6000, - 0xa301, 0x701e, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, - 0x0001, 0x007f, 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, 0x3136, - 0x7108, 0x7007, 0x0002, 0x810c, 0x00c8, 0x3136, 0x810c, 0x0048, - 0x3143, 0x0078, 0x2ef8, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6b8a, - 0x6c8e, 0x7007, 0x0004, 0x2049, 0x0000, 0x7003, 0x0000, 0x127f, - 0x2000, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, - 0x00c8, 0x315b, 0xa200, 0x00f0, 0x3156, 0x8086, 0x818e, 0x007c, - 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x3181, 0xa11a, 0x00c8, - 0x3181, 0x8213, 0x818d, 0x0048, 0x3174, 0xa11a, 0x00c8, 0x3175, - 0x00f0, 0x3169, 0x0078, 0x3179, 0xa11a, 0x2308, 0x8210, 0x00f0, - 0x3169, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, - 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x317d, 0x00e0, - 0x31c1, 0x2091, 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, 0x31bb, - 0x7824, 0x7822, 0x2091, 0x8000, 0x2069, 0x3440, 0x6800, 0xa084, - 0x0007, 0x0040, 0x31ab, 0xa086, 0x0002, 0x0040, 0x31ab, 0x6830, - 0xa00d, 0x0040, 0x31ab, 0x2104, 0xa005, 0x0040, 0x31ab, 0x8001, - 0x200a, 0x0040, 0x3277, 0x2061, 0x3580, 0x20a9, 0x0080, 0x6034, - 0xa005, 0x0040, 0x31b5, 0x8001, 0x6036, 0xace0, 0x0010, 0x0070, - 0x31bb, 0x0078, 0x31af, 0x1078, 0x31dc, 0x1078, 0x31c4, 0x1078, - 0x3201, 0x2091, 0x8001, 0x007c, 0x783c, 0x8001, 0x783e, 0x00c0, - 0x31db, 0x7840, 0x783e, 0x7848, 0xa005, 0x0040, 0x31db, 0x8001, - 0x784a, 0x00c0, 0x31db, 0x0f7e, 0x2079, 0x0100, 0x1078, 0x2cc6, - 0x0f7f, 0x1078, 0x19f8, 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0, - 0x3200, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0, - 0x31eb, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x3d80, 0x2040, - 0x2004, 0xa065, 0x0040, 0x3200, 0x6020, 0xa005, 0x0040, 0x31fc, - 0x8001, 0x6022, 0x0040, 0x3230, 0x6000, 0x2c40, 0x0078, 0x31f1, - 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x322f, 0x782c, 0x782a, - 0x7830, 0xa005, 0x00c0, 0x320e, 0x2001, 0x0080, 0x8001, 0x7832, - 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3580, 0xa298, 0x0002, - 0x2304, 0xa084, 0x0008, 0x0040, 0x322f, 0xa290, 0x0009, 0x2204, - 0xa005, 0x0040, 0x3227, 0x8001, 0x2012, 0x00c0, 0x322f, 0x2304, - 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x19f8, 0x007c, - 0x2069, 0x3440, 0x6800, 0xa005, 0x0040, 0x323a, 0x683c, 0xac06, - 0x0040, 0x3277, 0x6017, 0x0006, 0x60b0, 0xa084, 0x3f00, 0x601a, + 0x2d75, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0x7808, + 0xa085, 0x0002, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0, + 0x2d7c, 0x0098, 0x2d85, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, + 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, + 0x0040, 0x2d94, 0x0098, 0x2d92, 0x78ac, 0x007e, 0x7808, 0xa085, + 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0070, 0x0040, 0x2da8, + 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x1b6b, 0x2d78, 0x2c68, 0x0c7f, + 0x6817, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681a, 0x682f, 0x0000, + 0x682b, 0x0000, 0x784b, 0x0008, 0x78e4, 0xa005, 0x00d0, 0x2015, + 0xa084, 0x0020, 0x0040, 0x2015, 0x78ec, 0xa084, 0x0003, 0x0040, + 0x2015, 0x0018, 0x2015, 0x0078, 0x2b70, 0x0c7e, 0x6810, 0x8007, + 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060, + 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, 0x007c, + 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, + 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9847, 0x0014, + 0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014, 0x0080, 0x00bf, 0x0100, + 0x0402, 0x2008, 0xf880, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, + 0xa200, 0x8838, 0x817e, 0x842a, 0x84a0, 0x3806, 0x8839, 0x28c2, + 0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008, 0x28c1, 0x9cc3, 0xa201, + 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, + 0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864, 0xa829, 0x300c, 0xa801, + 0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204, 0x64c0, 0x67a0, 0x6fc0, + 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa80f, 0x786e, 0x883e, + 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, + 0x7023, 0x8576, 0x8677, 0xa801, 0x883e, 0x2069, 0x28c1, 0x9cc3, + 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc, 0xa207, 0x0014, 0xa203, + 0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a, 0x883c, 0x1fe2, 0xf601, + 0xa208, 0x856e, 0x866f, 0x0704, 0x3008, 0x9ca0, 0x0014, 0xa202, + 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf848, 0x8174, 0x86eb, + 0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f1, 0xf861, 0xa8e8, + 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, + 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, + 0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f, 0x842a, 0x1dc1, 0x8823, + 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, + 0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7, 0x8822, 0x0016, 0x8000, + 0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011, + 0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017, + 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x26e0, 0x873a, + 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x817e, + 0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd, 0x0704, 0x0000, 0x127e, + 0x2091, 0x2200, 0x2049, 0x2ec7, 0x7000, 0x7204, 0xa205, 0x720c, + 0xa215, 0x7008, 0xa084, 0xfffd, 0xa205, 0x0040, 0x2ed9, 0x0078, + 0x2ede, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084, + 0x0001, 0x00c0, 0x2f0c, 0x7108, 0x8104, 0x00c8, 0x2eeb, 0x1078, + 0x2fa8, 0x0078, 0x2ee3, 0x700c, 0xa08c, 0x007f, 0x0040, 0x2f0c, + 0x7004, 0x8004, 0x00c8, 0x2f03, 0x7014, 0xa005, 0x00c0, 0x2eff, + 0x7010, 0xa005, 0x0040, 0x2f03, 0xa102, 0x00c8, 0x2ee3, 0x7007, + 0x0010, 0x0078, 0x2f0c, 0x8aff, 0x0040, 0x2f0c, 0x1078, 0x316b, + 0x00c0, 0x2f06, 0x0040, 0x2ee3, 0x1078, 0x2f56, 0x7003, 0x0000, + 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, 0x0040, 0x2f30, 0x2c70, + 0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa630, 0x6808, 0xa529, + 0x8421, 0x0040, 0x2f30, 0x8738, 0x2704, 0xa005, 0x00c0, 0x2f1b, + 0x7098, 0xa075, 0x0040, 0x2f30, 0x2039, 0x2f32, 0x0078, 0x2f1a, + 0x007c, 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, + 0x001c, 0x0000, 0x127e, 0x2091, 0x2200, 0x2079, 0x3500, 0x2071, + 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2071, + 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2049, + 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049, 0x2f56, + 0x7004, 0x8004, 0x00c8, 0x2f82, 0x7007, 0x0012, 0x7108, 0x7008, + 0xa106, 0x00c0, 0x2f5e, 0xa184, 0x0030, 0x0040, 0x2f6b, 0xa086, + 0x0030, 0x00c0, 0x2f5e, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f82, + 0x7008, 0xa084, 0x000c, 0x00c0, 0x2f80, 0x710c, 0xa184, 0x0300, + 0x00c0, 0x2f80, 0xa184, 0x007f, 0x00c0, 0x2f56, 0x0078, 0x2f82, + 0x6817, 0x0003, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, + 0x0008, 0x00c0, 0x2f86, 0x7007, 0x0012, 0x7108, 0x8104, 0x0048, + 0x2f8b, 0x78b3, 0x0000, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, + 0x107e, 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, + 0x2fa8, 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, + 0x7204, 0x2118, 0x7108, 0x700c, 0xa084, 0x0300, 0x00c0, 0x2fea, + 0xa184, 0x000c, 0x00c0, 0x2fea, 0x8213, 0x8213, 0x8213, 0x8213, + 0xa284, 0x0100, 0xa10d, 0x810b, 0x810b, 0x810f, 0xa184, 0x0007, + 0x0079, 0x2fc2, 0x2fcc, 0x2fdc, 0x2fea, 0x2fdc, 0x2ffe, 0x2ffe, + 0x2fea, 0x2ffc, 0x1078, 0x1ba5, 0x7007, 0x0002, 0x8aff, 0x00c0, + 0x2fd5, 0x2049, 0x0000, 0x0078, 0x2fd9, 0x1078, 0x316b, 0x00c0, + 0x2fd5, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x8aff, 0x00c0, + 0x2fe3, 0x0078, 0x2fe7, 0x1078, 0x316b, 0x00c0, 0x2fe3, 0x78b3, + 0x0000, 0x007c, 0x7007, 0x0002, 0x1078, 0x2f56, 0x1078, 0x2cbb, + 0x6814, 0xa084, 0x8000, 0x0040, 0x2ff7, 0x6817, 0x0002, 0x007c, + 0x1078, 0x1ba5, 0x1078, 0x1ba5, 0x1078, 0x3050, 0x7210, 0x7114, + 0x700c, 0xa09c, 0x007f, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, + 0x78b0, 0xa005, 0x0040, 0x3010, 0x78b3, 0x0000, 0x0078, 0x3033, + 0x1078, 0x3050, 0x2704, 0x2c58, 0xac60, 0x630c, 0x2200, 0xa322, + 0x6308, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x3029, 0x00c8, + 0x3029, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, + 0x3010, 0x2b60, 0x8a07, 0xa7ba, 0x2f32, 0xa73d, 0x2c00, 0x6882, + 0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012, 0x1078, 0x2f56, 0x007c, + 0x8738, 0x2704, 0xa005, 0x00c0, 0x3044, 0x6098, 0xa005, 0x0040, + 0x304d, 0x2060, 0x2039, 0x2f32, 0x8a51, 0x0040, 0x304c, 0x7008, + 0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c, 0x2051, 0x0000, 0x007c, + 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x305d, 0x2039, 0x2f38, + 0x6000, 0xa064, 0x00c0, 0x305d, 0x2d60, 0x007c, 0x127e, 0x0d7e, + 0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c, + 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08, + 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3079, 0xa6b5, + 0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040, + 0x0040, 0x3088, 0xa684, 0x0001, 0x00c0, 0x3088, 0xa6b5, 0x0001, + 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x308a, 0x7000, + 0xa005, 0x0040, 0x3095, 0x1078, 0x1ba5, 0x2400, 0xa305, 0x00c0, + 0x309b, 0x0078, 0x30d8, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, + 0x007e, 0x701a, 0x6000, 0xa301, 0x701e, 0x2009, 0x04fd, 0x2104, + 0xa086, 0x04fd, 0x007f, 0x00c0, 0x30c8, 0xa084, 0x0001, 0x0040, + 0x30c8, 0xa684, 0x0001, 0x00c0, 0x30c8, 0x7013, 0x0001, 0x7017, + 0x0000, 0x7602, 0x7007, 0x0001, 0x78b3, 0x0001, 0xa4a0, 0x0001, + 0xa399, 0x0000, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e, + 0x620c, 0x2400, 0xa202, 0x7012, 0x6208, 0x2300, 0xa203, 0x7016, + 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x3038, 0x0078, 0x30da, + 0x1078, 0x316b, 0x00c0, 0x30d8, 0x127f, 0x2000, 0x007c, 0x127e, + 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xa084, + 0x0004, 0x00c0, 0x30e6, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, + 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x30f0, 0x7007, + 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30f9, 0x7000, 0xa005, + 0x0040, 0x3104, 0x1078, 0x1ba5, 0x7e08, 0xa6b5, 0x000c, 0x6818, + 0xa084, 0x0040, 0x0040, 0x310e, 0xa6b5, 0x0001, 0x6824, 0xa005, + 0x0040, 0x311a, 0x2050, 0x2039, 0x2f35, 0x2d60, 0x1078, 0x316b, + 0x00c0, 0x3116, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e, + 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5, + 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3130, 0xa6b5, 0x0001, + 0x2049, 0x311d, 0x6824, 0xa055, 0x0040, 0x3168, 0x2d70, 0x2e60, + 0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa422, 0x6808, 0xa31b, + 0x0048, 0x3155, 0x8a51, 0x00c0, 0x3147, 0x1078, 0x1ba5, 0x8738, + 0x2704, 0xa005, 0x00c0, 0x313b, 0x7098, 0xa075, 0x2060, 0x0040, + 0x3168, 0x2039, 0x2f32, 0x0078, 0x313a, 0x8422, 0x8420, 0x831a, + 0xa399, 0x0000, 0x690c, 0x2400, 0xa122, 0x6908, 0x2300, 0xa11b, + 0x00c8, 0x3164, 0x1078, 0x1ba5, 0x2071, 0x0020, 0x0078, 0x3088, + 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0, + 0x0040, 0x3193, 0x2704, 0xac08, 0x2104, 0x701e, 0x8108, 0x2104, + 0x701a, 0x8108, 0x2104, 0x7016, 0x8108, 0x2104, 0x7012, 0x0f7e, + 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040, 0x0040, 0x318e, + 0xa684, 0x0001, 0x00c0, 0x318e, 0xa6b5, 0x0001, 0x7602, 0x7007, + 0x0001, 0x1078, 0x3038, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, + 0x2200, 0x2049, 0x3194, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x00c0, + 0x00c0, 0x31aa, 0x6824, 0xa005, 0x0040, 0x31ba, 0x0078, 0x2ede, + 0x0078, 0x31ba, 0x7108, 0x8104, 0x00c8, 0x31b2, 0x1078, 0x2fa8, + 0x0078, 0x319d, 0x7007, 0x0010, 0x7108, 0x8104, 0x00c8, 0x31b4, + 0x1078, 0x2fa8, 0x7008, 0xa086, 0x0002, 0x00c0, 0x319d, 0x7000, + 0xa005, 0x00c0, 0x319d, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, + 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0d7e, 0x2091, + 0x2200, 0x0d7f, 0x2049, 0x31ca, 0xad80, 0x0010, 0x20a0, 0x2099, + 0x0031, 0x700c, 0xa084, 0x007f, 0x6826, 0x7007, 0x0008, 0x7007, + 0x0002, 0x7003, 0x0001, 0x0040, 0x31e8, 0x8000, 0x80ac, 0x53a5, + 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x31ea, 0x2049, + 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, 0x2000, + 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, + 0x31f9, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, + 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08, 0xa6b5, 0x0004, + 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x3212, 0x2c58, + 0x2704, 0xac60, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e, + 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x007f, + 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, 0x322c, 0x7108, 0x7007, + 0x0002, 0x810c, 0x00c8, 0x322c, 0x810c, 0x0048, 0x3239, 0x0078, + 0x2fea, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6b8a, 0x6c8e, 0x7007, + 0x0004, 0x2049, 0x0000, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, + 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x3251, + 0xa200, 0x00f0, 0x324c, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, + 0x0010, 0xa005, 0x0040, 0x3277, 0xa11a, 0x00c8, 0x3277, 0x8213, + 0x818d, 0x0048, 0x326a, 0xa11a, 0x00c8, 0x326b, 0x00f0, 0x325f, + 0x0078, 0x326f, 0xa11a, 0x2308, 0x8210, 0x00f0, 0x325f, 0x007e, + 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, + 0x3200, 0xa085, 0x0800, 0x0078, 0x3273, 0x00e0, 0x32bf, 0x2091, + 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, 0x32b9, 0x7824, 0x7822, + 0x2091, 0x8000, 0x2069, 0x3540, 0x6800, 0xa084, 0x0007, 0x0040, + 0x32a1, 0xa086, 0x0002, 0x0040, 0x32a1, 0x6830, 0xa00d, 0x0040, + 0x32a1, 0x2104, 0xa005, 0x0040, 0x32a1, 0x8001, 0x200a, 0x0040, + 0x336f, 0x2061, 0x3680, 0x20a9, 0x0080, 0x6034, 0xa005, 0x0040, + 0x32b3, 0x8001, 0x6036, 0x00c0, 0x32b3, 0x6010, 0xa005, 0x0040, + 0x32b3, 0x1078, 0x1a19, 0xace0, 0x0010, 0x0070, 0x32b9, 0x0078, + 0x32a5, 0x1078, 0x32d4, 0x1078, 0x32c2, 0x1078, 0x32f9, 0x2091, + 0x8001, 0x007c, 0x783c, 0x8001, 0x783e, 0x00c0, 0x32d3, 0x7840, + 0x783e, 0x7848, 0xa005, 0x0040, 0x32d3, 0x8001, 0x784a, 0x00c0, + 0x32d3, 0x1078, 0x1a19, 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0, + 0x32f8, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0, + 0x32e3, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x3e80, 0x2040, + 0x2004, 0xa065, 0x0040, 0x32f8, 0x6020, 0xa005, 0x0040, 0x32f4, + 0x8001, 0x6022, 0x0040, 0x3328, 0x6000, 0x2c40, 0x0078, 0x32e9, + 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x3327, 0x782c, 0x782a, + 0x7830, 0xa005, 0x00c0, 0x3306, 0x2001, 0x0080, 0x8001, 0x7832, + 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3680, 0xa298, 0x0002, + 0x2304, 0xa084, 0x0008, 0x0040, 0x3327, 0xa290, 0x0009, 0x2204, + 0xa005, 0x0040, 0x331f, 0x8001, 0x2012, 0x00c0, 0x3327, 0x2304, + 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x1a19, 0x007c, + 0x2069, 0x3540, 0x6800, 0xa005, 0x0040, 0x3332, 0x683c, 0xac06, + 0x0040, 0x336f, 0x6017, 0x0006, 0x60b0, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0060, 0x601e, 0x6000, 0x2042, - 0x6710, 0x6fb6, 0x1078, 0x1681, 0x6818, 0xa005, 0x0040, 0x3252, + 0x6710, 0x6fb6, 0x1078, 0x1692, 0x6818, 0xa005, 0x0040, 0x334a, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, 0x6810, 0x8001, - 0x00d0, 0x325c, 0x1078, 0x1b4e, 0x6812, 0x602f, 0x0000, 0x602b, - 0x0000, 0x2c68, 0x1078, 0x17be, 0x2069, 0x3440, 0x2001, 0x0006, - 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x3272, 0x69ba, 0x2001, - 0x0004, 0x68a2, 0x1078, 0x19f3, 0x2091, 0x8001, 0x007c, 0x2009, - 0x344f, 0x2164, 0x2069, 0x0100, 0x6017, 0x0006, 0x6858, 0xa084, - 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0048, 0x601e, - 0x602f, 0x0000, 0x602b, 0x0000, 0x6830, 0xa084, 0x0040, 0x0040, - 0x32b1, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, - 0x0040, 0x329e, 0x0070, 0x329e, 0x0078, 0x3295, 0x684b, 0x0009, - 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x32ab, 0x0070, - 0x32ab, 0x0078, 0x32a2, 0x20a9, 0x00fa, 0x0070, 0x32b1, 0x0078, - 0x32ad, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2009, - 0x3468, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091, 0x8001, 0x007c, - 0x2079, 0x3400, 0x1078, 0x3309, 0x1078, 0x32d1, 0x1078, 0x32e6, - 0x1078, 0x32fb, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000, - 0x007c, 0x2019, 0x000a, 0x2011, 0x3446, 0x2204, 0xa086, 0x0032, - 0x0040, 0x32e3, 0x2019, 0x000c, 0x2204, 0xa086, 0x003c, 0x0040, - 0x32e3, 0x2019, 0x0008, 0x7b2a, 0x7b2e, 0x007c, 0x2019, 0x0030, - 0x2011, 0x3446, 0x2204, 0xa086, 0x0032, 0x0040, 0x32f8, 0x2019, - 0x0039, 0x2204, 0xa086, 0x003c, 0x0040, 0x32f8, 0x2019, 0x0027, - 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, 0x2011, 0x3446, 0x2204, - 0xa086, 0x003c, 0x0040, 0x3306, 0x2019, 0x000a, 0x7b3e, 0x7b42, - 0x007c, 0x2019, 0x2faf, 0x2011, 0x3446, 0x2204, 0xa086, 0x0032, - 0x0040, 0x331b, 0x2019, 0x3971, 0x2204, 0xa086, 0x003c, 0x0040, - 0x331b, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c, 0xae5b -}; - -unsigned short pti_risc_code_length01 = 0x231f; - -/* Version 1.31.00 ISP1000 Initiator RISC firmware - * We use this for all non-PTI SBUS boards. - */ -unsigned short sbus_risc_code_addr01 = 0x1000; - -unsigned short sbus_risc_code01[] __initdata = { - 0x0078, 0x1030, 0xa5e3, 0x241a, 0x0001, 0x12ff, 0x2043, 0x4f50, - 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, - 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, - 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, - 0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, - 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020, - 0x2071, 0x0010, 0x70c3, 0x0004, 0x20c9, 0x3fff, 0x2089, 0x10ca, - 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001, - 0x3f00, 0x70d6, 0x2031, 0x0030, 0x2079, 0x3500, 0x7863, 0x0000, - 0x2fa0, 0x2009, 0x012b, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, - 0x8109, 0x00c0, 0x104d, 0x789b, 0x0101, 0x780b, 0x0002, 0x780f, - 0x0002, 0x784f, 0x0bb8, 0x2069, 0x3540, 0x00a8, 0x106c, 0x681b, - 0x003c, 0x2009, 0x1313, 0xa18c, 0xff00, 0x3700, 0xa084, 0x00ff, - 0xa105, 0x20b8, 0x0078, 0x106e, 0x681b, 0x0028, 0x6807, 0x0007, - 0x680b, 0x00fa, 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, - 0x6823, 0x0006, 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600, - 0x2011, 0x0020, 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, - 0x6803, 0xdd00, 0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, - 0xa290, 0x0004, 0x8109, 0x00c0, 0x1084, 0x2069, 0x3680, 0x20a9, - 0x0080, 0x6837, 0x0000, 0x680b, 0x0040, 0x6817, 0x0064, 0x681f, - 0x0002, 0xade8, 0x0010, 0x0070, 0x10a7, 0x0078, 0x1099, 0x1078, - 0x1a42, 0x1078, 0x2f3d, 0x1078, 0x168b, 0x1078, 0x33bb, 0x3200, - 0xa085, 0x000d, 0x2090, 0x70c3, 0x0000, 0x0090, 0x10be, 0x70c0, - 0xa086, 0x0002, 0x00c0, 0x10be, 0x1078, 0x11be, 0x1078, 0x10ee, - 0x1078, 0x1821, 0x1078, 0x19b2, 0x1078, 0x3280, 0x1078, 0x1787, - 0x0078, 0x10be, 0x10d2, 0x10d4, 0x1b9f, 0x1b9f, 0x2f9b, 0x2f9b, - 0x1b9f, 0x1b9f, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6, - 0x0078, 0x10d8, 0x7008, 0x800c, 0x00c8, 0x10e9, 0x7007, 0x0002, - 0xa08c, 0x000c, 0x00c0, 0x10ea, 0x8004, 0x8004, 0x00c8, 0x10e9, - 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x11c1, 0x0068, 0x1133, - 0x7814, 0xa005, 0x00c0, 0x10f8, 0x0010, 0x1134, 0x0078, 0x1133, - 0x2009, 0x3568, 0x2104, 0xa005, 0x00c0, 0x1133, 0x7814, 0xa086, - 0x0001, 0x00c0, 0x1105, 0x1078, 0x1540, 0x7817, 0x0000, 0x2009, - 0x356f, 0x2104, 0xa065, 0x0040, 0x1121, 0x2009, 0x356a, 0x211c, - 0x8108, 0x2114, 0x8108, 0x2104, 0xa210, 0xa399, 0x0000, 0x2009, - 0x001c, 0x6083, 0x0103, 0x1078, 0x161b, 0x00c0, 0x112d, 0x1078, - 0x1682, 0x2009, 0x356f, 0x200b, 0x0000, 0x2009, 0x3569, 0x2104, - 0x200b, 0x0000, 0xa005, 0x0040, 0x1131, 0x2001, 0x4005, 0x0078, - 0x11c0, 0x0078, 0x11be, 0x007c, 0x2061, 0x0000, 0x6018, 0xa084, - 0x0001, 0x0040, 0x113c, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, - 0x70cb, 0x0000, 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, - 0x118c, 0x2038, 0x0079, 0x114c, 0x11be, 0x1209, 0x11d7, 0x1209, - 0x125a, 0x125a, 0x11ce, 0x159a, 0x1265, 0x11ca, 0x11db, 0x11dd, - 0x11df, 0x11e1, 0x159f, 0x11ca, 0x126b, 0x1287, 0x154e, 0x1594, - 0x11e3, 0x1475, 0x1497, 0x14b1, 0x14da, 0x142e, 0x143c, 0x1450, - 0x1464, 0x12f3, 0x11ca, 0x12a3, 0x12aa, 0x12af, 0x12b4, 0x12ba, - 0x12bf, 0x12c4, 0x12c9, 0x12ce, 0x12d2, 0x12e7, 0x11ca, 0x11ca, - 0x11ca, 0x11ca, 0x11ca, 0x12ff, 0x1308, 0x1317, 0x133d, 0x1347, - 0x134e, 0x137a, 0x1389, 0x1398, 0x13aa, 0x1413, 0x11ca, 0x11ca, - 0x11ca, 0x11ca, 0x11ca, 0x1423, 0xa0bc, 0xffa0, 0x00c0, 0x11ca, - 0x2038, 0xa084, 0x001f, 0x0079, 0x1195, 0x11ca, 0x11ca, 0x11ca, - 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, - 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, - 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x15f7, - 0x1601, 0x1605, 0x1613, 0x11ca, 0x11ca, 0x72ca, 0x71c6, 0x2001, - 0x4006, 0x0078, 0x11c0, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, - 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, - 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x11c1, 0x2099, 0x0041, - 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x11be, 0x70c4, - 0x70c3, 0x0004, 0x007a, 0x0078, 0x11be, 0x0078, 0x11be, 0x0078, - 0x11be, 0x0078, 0x11be, 0x2091, 0x8000, 0x70c3, 0x0000, 0x70c7, - 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00, - 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059, - 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061, 0x0472, 0x20b9, - 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078, - 0x0455, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2098, 0x2031, - 0x0030, 0x81ff, 0x0040, 0x11be, 0x7007, 0x0004, 0x731a, 0x721e, - 0x2051, 0x0012, 0x2049, 0x1238, 0x2041, 0x11be, 0x7003, 0x0002, - 0xa786, 0x0001, 0x00c0, 0x122a, 0x2049, 0x1246, 0x2041, 0x1252, - 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, 0x00c8, 0x1232, - 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, 0x0040, 0x1246, - 0x700c, 0xa084, 0x007f, 0x8004, 0x2009, 0x0020, 0xa102, 0x0942, - 0x094a, 0x20a8, 0x26a0, 0x53a6, 0x0078, 0x10da, 0x700c, 0xa084, - 0x007f, 0x0040, 0x1246, 0x80ac, 0x0048, 0x1246, 0x2698, 0x53a5, - 0x0078, 0x10da, 0x700c, 0xa084, 0x007f, 0x80ac, 0x2698, 0x53a5, - 0x0078, 0x11be, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, - 0x1262, 0x200a, 0x72ca, 0x0078, 0x11bd, 0x70c7, 0x0001, 0x70cb, - 0x001f, 0x0078, 0x11be, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, - 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1281, 0x8001, 0x7872, - 0x7a7a, 0x7b7e, 0x7c76, 0x7898, 0xa084, 0xfffc, 0x789a, 0x0078, - 0x1285, 0x7898, 0xa085, 0x0001, 0x789a, 0x0078, 0x11be, 0x70c4, - 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005, - 0x0040, 0x129d, 0x8001, 0x7886, 0x7a8e, 0x7b92, 0x7c8a, 0x7898, - 0xa084, 0xfcff, 0x789a, 0x0078, 0x12a1, 0x7898, 0xa085, 0x0100, - 0x789a, 0x0078, 0x11be, 0x2009, 0x3559, 0x210c, 0x2011, 0x015c, - 0x0078, 0x11bc, 0x2009, 0x3541, 0x210c, 0x0078, 0x11bd, 0x2009, - 0x3542, 0x210c, 0x0078, 0x11bd, 0x2061, 0x3540, 0x610c, 0x6210, - 0x0078, 0x11bc, 0x2009, 0x3545, 0x210c, 0x0078, 0x11bd, 0x2009, - 0x3546, 0x210c, 0x0078, 0x11bd, 0x2009, 0x3547, 0x210c, 0x0078, - 0x11bd, 0x2009, 0x3548, 0x210c, 0x0078, 0x11bd, 0x7908, 0x7a0c, - 0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa0e8, 0x3600, 0x6a00, 0x6804, 0xa084, 0x0008, 0x0040, - 0x12e4, 0x6b08, 0x0078, 0x12e5, 0x6b0c, 0x0078, 0x11bb, 0x77c4, - 0x1078, 0x169c, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, - 0x2708, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000, - 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, 0x11bb, 0x71c4, - 0xa182, 0x0010, 0x00c8, 0x11b6, 0x1078, 0x1ac6, 0x0078, 0x11bb, - 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3541, 0x2204, - 0x007e, 0x2112, 0x1078, 0x1a7f, 0x017f, 0x0078, 0x11bd, 0x71c4, - 0x2011, 0x1335, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x1327, - 0x8210, 0x0070, 0x1325, 0x0078, 0x131c, 0x0078, 0x11b6, 0xa292, - 0x1335, 0x027e, 0x2011, 0x3542, 0x2204, 0x2112, 0x017f, 0x007e, - 0x1078, 0x1a8b, 0x017f, 0x0078, 0x11bd, 0x03e8, 0x00fa, 0x01f4, - 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x3540, 0x610c, - 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, 0x11bc, 0x2061, - 0x3540, 0x6114, 0x70c4, 0x6016, 0x0078, 0x11bd, 0x71c4, 0x2011, - 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1367, 0x2011, - 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, 0x1367, 0x2011, - 0x0006, 0x2019, 0x1313, 0xa186, 0x003c, 0x00c0, 0x11b6, 0x2061, - 0x3540, 0x6018, 0x007e, 0x611a, 0xa39c, 0xff00, 0x3700, 0xa084, - 0x00ff, 0xa305, 0x20b8, 0x1078, 0x1a9c, 0x1078, 0x33bb, 0x017f, - 0x0078, 0x11bd, 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b6, 0x2011, - 0x3547, 0x2204, 0x2112, 0x007e, 0x1078, 0x1abe, 0x017f, 0x0078, - 0x11bd, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3548, - 0x2204, 0x007e, 0x2112, 0x1078, 0x1aad, 0x017f, 0x0078, 0x11bd, - 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x11b5, 0xa284, 0xfffd, - 0x00c0, 0x11b5, 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, - 0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa0e8, 0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e, - 0xa226, 0x0040, 0x13d9, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13c2, - 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x13c8, 0xa39d, 0x0008, - 0xa484, 0x4000, 0x0040, 0x13d9, 0x810f, 0xa284, 0x4000, 0x0040, - 0x13d5, 0x1078, 0x1ae0, 0x0078, 0x13d9, 0x1078, 0x1ad2, 0x0078, - 0x13d9, 0x72cc, 0x82ff, 0x0040, 0x140b, 0x6808, 0xa206, 0x0040, - 0x140b, 0xa2a4, 0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028, - 0x0040, 0x13f2, 0xa186, 0x0032, 0x0040, 0x13f8, 0xa186, 0x003c, - 0x0040, 0x13fe, 0xa482, 0x0064, 0x0048, 0x1408, 0x0078, 0x1402, - 0xa482, 0x0050, 0x0048, 0x1408, 0x0078, 0x1402, 0xa482, 0x0043, - 0x0048, 0x1408, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b7, - 0x6a0a, 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, - 0x71c4, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000, - 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, - 0x2708, 0x0078, 0x11bb, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, - 0x00c8, 0x11b6, 0x1078, 0x1aee, 0x0078, 0x11bb, 0x77c4, 0x1078, - 0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091, - 0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x1078, 0x169c, 0x2091, - 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, - 0x144b, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2708, 0x0078, 0x11bc, - 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004, - 0x6a0a, 0x6804, 0xa005, 0x0040, 0x145f, 0x1078, 0x1a23, 0x2091, - 0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x2041, 0x0001, 0x2049, - 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x16a9, 0x2091, - 0x8001, 0x2708, 0x6a08, 0x0078, 0x11bc, 0x77c4, 0x72c8, 0x73cc, - 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1722, 0x00c0, 0x1493, 0x6818, - 0xa005, 0x0040, 0x148d, 0x2708, 0x1078, 0x1afe, 0x00c0, 0x148d, - 0x7817, 0xffff, 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, - 0x4005, 0x0078, 0x11c0, 0x2091, 0x8001, 0x0078, 0x11be, 0x77c4, - 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, - 0x8000, 0x1078, 0x16a9, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6, - 0x60a7, 0x0000, 0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a23, - 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, - 0x8000, 0x2061, 0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6, - 0x7817, 0xffff, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2041, 0x0021, - 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x16a9, - 0x70c8, 0x6836, 0x8738, 0xa784, 0x0007, 0x00c0, 0x14ce, 0x2091, - 0x8001, 0x007c, 0x7898, 0xa084, 0x0003, 0x00c0, 0x14fe, 0x2039, - 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, - 0x169c, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001, - 0x8738, 0xa784, 0x0007, 0x00c0, 0x14e7, 0xa7bc, 0xff00, 0x873f, - 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x14e7, 0x2091, 0x8000, - 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x1527, 0x684b, - 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x1514, - 0x0070, 0x1514, 0x0078, 0x150b, 0x684b, 0x0009, 0x20a9, 0x0014, - 0x6848, 0xa084, 0x0001, 0x0040, 0x1521, 0x0070, 0x1521, 0x0078, - 0x1518, 0x20a9, 0x00fa, 0x0070, 0x1527, 0x0078, 0x1523, 0x2079, - 0x3500, 0x7817, 0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7, - 0x0000, 0x60c3, 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808, - 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c, - 0x7898, 0xa084, 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x154a, - 0x1078, 0x176a, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8, - 0x72cc, 0x74c6, 0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040, - 0x1078, 0x1679, 0x0040, 0x1590, 0x1078, 0x1649, 0x0040, 0x1564, - 0x1078, 0x1682, 0x0078, 0x1590, 0x6010, 0x2091, 0x8001, 0x7817, - 0xffff, 0x2009, 0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, - 0x8108, 0x230a, 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, - 0x8108, 0x200b, 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, - 0x1078, 0x2f16, 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, - 0x0000, 0x60af, 0x0000, 0x2091, 0x8001, 0x1078, 0x1a23, 0x007c, - 0x70c3, 0x4005, 0x0078, 0x11c1, 0x71c4, 0x70c7, 0x0000, 0x7906, - 0x0078, 0x11be, 0x71c4, 0x71c6, 0x2168, 0x0078, 0x15a1, 0x2069, - 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, - 0x15a3, 0xa285, 0x0000, 0x00c0, 0x15b1, 0x70c3, 0x4000, 0x0078, - 0x15b3, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x11c1, 0x71c4, 0x72c8, - 0x73cc, 0x2100, 0xa184, 0xfffc, 0x00c0, 0x11ca, 0x2100, 0x0079, - 0x15c1, 0x15d8, 0x15ed, 0x15ef, 0x15f1, 0x70c3, 0x4003, 0x71ce, - 0x72d2, 0x73d6, 0x0078, 0x15d4, 0x70c3, 0x4000, 0x70cf, 0x0000, - 0x70d3, 0x0000, 0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11be, - 0x2031, 0x15f3, 0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, - 0x15c5, 0xa484, 0xffff, 0x00c0, 0x15da, 0x2031, 0x15f3, 0x8210, - 0x8319, 0xa384, 0xffff, 0x00c0, 0x15da, 0x0078, 0x15cc, 0x0078, - 0x15cc, 0x0078, 0x15cc, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, - 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x11b6, 0x7962, 0x0078, - 0x11be, 0x7960, 0x71c6, 0x0078, 0x11be, 0x7954, 0x71c6, 0x71c4, - 0x7956, 0x7958, 0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, - 0x795e, 0x0078, 0x11be, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, - 0x71ce, 0x0078, 0x11be, 0x700c, 0xa084, 0x007f, 0x0040, 0x1627, - 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x1622, 0x7017, - 0x0000, 0x7112, 0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, - 0x20a1, 0x0030, 0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, - 0x7002, 0x7007, 0x0001, 0x7108, 0x8104, 0x00c8, 0x163b, 0x7007, - 0x0002, 0xa184, 0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000, - 0x007c, 0x700c, 0xa084, 0x007f, 0x0040, 0x1655, 0x7007, 0x0004, - 0x7004, 0xa084, 0x0004, 0x00c0, 0x1650, 0x7017, 0x0000, 0x7112, - 0x721a, 0x731e, 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, - 0x0001, 0x7002, 0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x1664, - 0x7007, 0x0002, 0xa08c, 0x000c, 0x00c0, 0x1676, 0x710c, 0xa184, - 0x0300, 0x00c0, 0x1676, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, - 0x007c, 0x7850, 0xa065, 0x0040, 0x1681, 0x2c04, 0x7852, 0x2063, - 0x0000, 0x007c, 0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00, - 0x7852, 0x0f7f, 0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x015c, - 0x8319, 0x0040, 0x1699, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078, - 0x1690, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, - 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680, - 0x007c, 0x1078, 0x169c, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, - 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804, - 0xa005, 0x0040, 0x16c6, 0xa116, 0x00c0, 0x16c6, 0x2060, 0x6000, - 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x16c9, 0x2009, 0x0000, - 0x017e, 0x6804, 0xa065, 0x0040, 0x16d8, 0x6000, 0x6806, 0x1078, - 0x16e9, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16c9, - 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x16e8, 0x6098, - 0x609b, 0x0000, 0x2008, 0x1078, 0x1682, 0x2100, 0x0078, 0x16dc, - 0x007c, 0x6003, 0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, - 0x2001, 0x0000, 0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c, - 0x0e7e, 0x2071, 0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x1706, - 0xa088, 0x3580, 0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, - 0x0e7e, 0x2071, 0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211, - 0x0048, 0x1720, 0x2104, 0x8108, 0xad06, 0x00c0, 0x170f, 0x8119, - 0x211e, 0x8108, 0x8318, 0x8211, 0x00c8, 0x1718, 0x7442, 0xa006, - 0x0e7f, 0x007c, 0x1078, 0x169c, 0x2091, 0x8000, 0x6804, 0x781e, - 0xa065, 0x0040, 0x1769, 0x0078, 0x1733, 0x2c00, 0x781e, 0x6000, - 0xa065, 0x0040, 0x1769, 0x600c, 0xa306, 0x00c0, 0x172d, 0x6008, - 0xa206, 0x00c0, 0x172d, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06, - 0x0040, 0x1769, 0x6804, 0xac06, 0x00c0, 0x1750, 0x6000, 0x2060, - 0x6806, 0xa005, 0x00c0, 0x1750, 0x6803, 0x0000, 0x0078, 0x175a, - 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x175a, - 0x2c00, 0x6802, 0x2560, 0x1078, 0x16e9, 0x6017, 0x0005, 0x601f, - 0x0020, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, - 0xa005, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, - 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x16a9, 0x8738, 0xa784, - 0x0007, 0x00c0, 0x1774, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, - 0xa784, 0x0f00, 0x00c0, 0x1774, 0x2091, 0x8001, 0x007c, 0x2061, - 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1794, 0x78ac, 0x78af, - 0x0000, 0xa005, 0x00c0, 0x1795, 0x007c, 0xa08c, 0xfff0, 0x0040, - 0x179b, 0x1078, 0x1b81, 0x0079, 0x179d, 0x17ad, 0x17af, 0x17b5, - 0x17b9, 0x17ad, 0x17bd, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x17c3, - 0x17c7, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x1b81, 0x1078, - 0x176a, 0x2001, 0x8001, 0x0078, 0x17cd, 0x2001, 0x8003, 0x0078, - 0x17cd, 0x2001, 0x8004, 0x0078, 0x17cd, 0x1078, 0x176a, 0x2001, - 0x8006, 0x0078, 0x17cd, 0x2001, 0x800c, 0x0078, 0x17cd, 0x1078, - 0x176a, 0x2001, 0x800d, 0x0078, 0x17cd, 0x70c2, 0x2061, 0x0000, - 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08, - 0x2063, 0x0000, 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, - 0x0040, 0x17e5, 0x2c02, 0x0078, 0x17e6, 0x796e, 0x007c, 0x0c7e, - 0x2061, 0x3500, 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, - 0x8000, 0x6066, 0x6068, 0xa005, 0x616a, 0x0040, 0x17fa, 0x2d02, - 0x0078, 0x17fb, 0x616e, 0x0c7f, 0x007c, 0x1078, 0x180e, 0x0040, - 0x180d, 0x0c7e, 0x6098, 0xa065, 0x0040, 0x1808, 0x1078, 0x16dc, - 0x0c7f, 0x609b, 0x0000, 0x1078, 0x1682, 0x007c, 0x786c, 0xa065, - 0x0040, 0x1820, 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, - 0x786e, 0xa005, 0x00c0, 0x181e, 0x786a, 0x8000, 0x2091, 0x8001, - 0x007c, 0x7898, 0xa005, 0x00c0, 0x186f, 0x7974, 0x70d0, 0x0005, - 0x0005, 0x72d0, 0xa206, 0x00c0, 0x1826, 0x2200, 0xa106, 0x00c0, - 0x183d, 0x7804, 0xa005, 0x0040, 0x186f, 0x7807, 0x0000, 0x0068, - 0x186f, 0x2091, 0x4080, 0x0078, 0x186f, 0x1078, 0x1679, 0x0040, - 0x186f, 0x7a7c, 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, - 0x0000, 0x2009, 0x0040, 0x1078, 0x1649, 0x0040, 0x1866, 0x1078, - 0x1682, 0x7880, 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x186f, - 0x2091, 0x8000, 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, - 0x0003, 0x789a, 0x2091, 0x8001, 0x0078, 0x186f, 0x7883, 0x0000, - 0x1078, 0x199c, 0x6000, 0xa084, 0x0007, 0x0079, 0x1870, 0x007c, - 0x1878, 0x1887, 0x18a7, 0x1878, 0x18b9, 0x1878, 0x1878, 0x1878, - 0x2039, 0x0400, 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, - 0x1078, 0x18f7, 0x6018, 0x78a6, 0x1078, 0x1984, 0x007c, 0x78a8, - 0xa084, 0x0100, 0x0040, 0x188e, 0x0078, 0x1878, 0x78ab, 0x0000, - 0x6000, 0x8007, 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, - 0x0040, 0x18a4, 0x1078, 0x18f7, 0x0040, 0x18a4, 0x78a8, 0xa085, - 0x0100, 0x78aa, 0x0078, 0x18a6, 0x1078, 0x191b, 0x007c, 0x78a8, - 0xa08c, 0x0e00, 0x00c0, 0x18b0, 0xa084, 0x0100, 0x00c0, 0x18b2, - 0x0078, 0x1878, 0x1078, 0x18f7, 0x00c0, 0x18b8, 0x1078, 0x191b, - 0x007c, 0x78a8, 0xa084, 0x0100, 0x0040, 0x18c0, 0x0078, 0x1878, - 0x78ab, 0x0000, 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, - 0xa005, 0x0040, 0x18dd, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, - 0x0001, 0x0040, 0x18dd, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, - 0x0002, 0x0040, 0x18dd, 0x0078, 0x18f4, 0x1078, 0x169c, 0x2d00, - 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, - 0xffde, 0x680a, 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, - 0x0070, 0x18f4, 0x0078, 0x18e0, 0x1078, 0x1682, 0x007c, 0x78a0, - 0xa06d, 0x00c0, 0x1902, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, - 0x0078, 0x190e, 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, - 0x6002, 0x78a4, 0xad06, 0x00c0, 0x190e, 0x6002, 0x789c, 0x8001, - 0x789e, 0x00c0, 0x191a, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, - 0x2060, 0xa006, 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, - 0x619e, 0x0040, 0x1927, 0x0e7e, 0x1078, 0x2f16, 0x0e7f, 0x6592, - 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, - 0x1078, 0x169c, 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, - 0x1949, 0x2091, 0x8001, 0x1078, 0x16e9, 0x2091, 0x8000, 0x1078, - 0x17d5, 0x2091, 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, - 0x1983, 0x6020, 0xa096, 0x0001, 0x00c0, 0x1950, 0x8000, 0x6022, - 0x6a10, 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x195f, 0x0040, - 0x195f, 0x2039, 0x0200, 0x1078, 0x1984, 0x0078, 0x1983, 0x2c08, - 0x2091, 0x8000, 0x6800, 0xa065, 0x0040, 0x1967, 0x6102, 0x6902, - 0x00c0, 0x196b, 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, - 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x197d, - 0xa086, 0x0040, 0x680a, 0x1078, 0x16f8, 0x1078, 0x1a23, 0x78a7, - 0x0000, 0x78a3, 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, - 0x8000, 0x1078, 0x17d5, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, - 0x1997, 0x6098, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1987, 0x78a3, - 0x0000, 0x78a7, 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, - 0x00c8, 0x19a3, 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, - 0x19b1, 0x8001, 0x7806, 0x00c0, 0x19b1, 0x0068, 0x19b1, 0x2091, - 0x4080, 0x007c, 0x0068, 0x19cc, 0x2029, 0x0000, 0x786c, 0xa065, - 0x0040, 0x19c7, 0x1078, 0x19cd, 0x0040, 0x19c7, 0x057e, 0x1078, - 0x19e3, 0x057f, 0x00c0, 0x19c7, 0x8528, 0x0078, 0x19b6, 0x85ff, - 0x0040, 0x19cc, 0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, - 0x0005, 0x0005, 0x70d4, 0xa206, 0x00c0, 0x19cf, 0x2200, 0xa102, - 0x00c0, 0x19dd, 0x2300, 0xa005, 0x007c, 0x0048, 0x19e1, 0xa302, - 0x007c, 0x8002, 0x007c, 0x1078, 0x1a15, 0x2009, 0x001c, 0x6024, - 0xa005, 0x0040, 0x19ed, 0x2009, 0x0040, 0x1078, 0x161b, 0x0040, - 0x1a06, 0x7894, 0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a14, - 0x2091, 0x8000, 0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085, - 0x0300, 0x789a, 0x2091, 0x8001, 0x0078, 0x1a14, 0x7897, 0x0000, - 0x1078, 0x17fd, 0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a11, - 0xa006, 0x788a, 0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004, - 0x7a90, 0x7b8c, 0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568, - 0x2091, 0x8000, 0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540, - 0x2091, 0x8000, 0x2104, 0xa086, 0x0000, 0x00c0, 0x1a3e, 0x2009, - 0x3512, 0x2104, 0xa005, 0x00c0, 0x1a3e, 0x7830, 0xa084, 0x00c0, - 0x00c0, 0x1a3e, 0x0018, 0x1a3e, 0x781b, 0x0044, 0x2091, 0x8001, - 0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079, - 0x0100, 0x2019, 0x2ddb, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, - 0x1a5a, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, - 0x0078, 0x1a4d, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, - 0x78af, 0x0220, 0x0070, 0x1a66, 0x0078, 0x1a5e, 0x7003, 0x0000, - 0x1078, 0x1b65, 0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, - 0x780f, 0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, - 0x7047, 0x357f, 0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, - 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, - 0x1078, 0x1b65, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, - 0x0070, 0x1a94, 0x0078, 0x1a8f, 0xa18c, 0x0e00, 0x2204, 0xa084, - 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, - 0x8213, 0x0070, 0x1aa5, 0x0078, 0x1aa0, 0xa294, 0x00e0, 0x2104, - 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, - 0x000c, 0x810b, 0x0070, 0x1ab6, 0x0078, 0x1ab1, 0xa18c, 0xf000, - 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, - 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, - 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, - 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, - 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, - 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, - 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, - 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, - 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, - 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x1b43, 0x2061, 0x3f80, - 0x1078, 0x1b4b, 0x0040, 0x1b31, 0x20a9, 0x0000, 0x2061, 0x3e80, - 0x0c7e, 0x1078, 0x1b4b, 0x0040, 0x1b1d, 0x0c7f, 0x8c60, 0x0070, - 0x1b1b, 0x0078, 0x1b10, 0x0078, 0x1b43, 0x007f, 0xa082, 0x3e80, - 0x2071, 0x3540, 0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, - 0x60a7, 0x0000, 0x2001, 0x0004, 0x70a2, 0x1078, 0x1a1e, 0x0078, - 0x1b3f, 0x2071, 0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, - 0x60a7, 0x0000, 0x2001, 0x0006, 0x70a2, 0x1078, 0x1a1e, 0x2001, - 0x0000, 0x0078, 0x1b45, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, - 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x1b62, 0x2060, - 0x600c, 0xa306, 0x00c0, 0x1b5f, 0x6008, 0xa206, 0x00c0, 0x1b5f, - 0x6010, 0xa106, 0x00c0, 0x1b5f, 0xa006, 0x0078, 0x1b64, 0x6000, - 0x0078, 0x1b4c, 0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c, - 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040, - 0x1b80, 0x2019, 0x0112, 0x201b, 0x1000, 0x2021, 0x013a, 0x2122, - 0x2013, 0x0080, 0x2013, 0x008c, 0x2013, 0x0000, 0x201b, 0x0000, - 0x007c, 0x0068, 0x1b81, 0x007e, 0x2071, 0x0000, 0x7018, 0xa084, - 0x0001, 0x00c0, 0x1b86, 0x007f, 0x2e08, 0x2071, 0x0010, 0x70ca, - 0x007f, 0x70c6, 0x70c3, 0x8002, 0x2071, 0x0000, 0x701b, 0x0001, - 0x2091, 0x4080, 0x007f, 0x2070, 0x007f, 0x0078, 0x1b9d, 0x107e, - 0x007e, 0x127e, 0x2091, 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, - 0xa594, 0x003f, 0xa484, 0x4000, 0x0040, 0x1bb4, 0xa784, 0x007c, - 0x00c0, 0x2da7, 0x1078, 0x1b81, 0xa49c, 0x000f, 0xa382, 0x0004, - 0x0050, 0x1bbc, 0x1078, 0x1b81, 0x8507, 0xa084, 0x000f, 0x0079, - 0x1bc1, 0x1fed, 0x209d, 0x20c3, 0x22e9, 0x2576, 0x25be, 0x25f5, - 0x2670, 0x26ca, 0x274f, 0x1be7, 0x1bd1, 0x1e56, 0x1f20, 0x2555, - 0x1bd1, 0x1078, 0x1b81, 0x0018, 0x1ba4, 0x127f, 0x2091, 0x8001, - 0x007f, 0x107f, 0x007c, 0x7003, 0x0000, 0x703f, 0x0000, 0x7030, - 0xa005, 0x0040, 0x1be5, 0x7033, 0x0000, 0x0018, 0x1ba4, 0x705c, - 0xa005, 0x00c0, 0x1ca5, 0x70a0, 0xa084, 0x0007, 0x0079, 0x1bf0, - 0x1cd1, 0x1bf8, 0x1c06, 0x1c27, 0x1c4d, 0x1c79, 0x1c77, 0x1bf8, - 0x7808, 0xa084, 0xfffd, 0x780a, 0x2009, 0x0046, 0x1078, 0x241b, - 0x00c0, 0x1c04, 0x7003, 0x0004, 0x0078, 0x1bd3, 0x1078, 0x2d69, - 0x00c0, 0x1c25, 0x70b4, 0x8007, 0x789b, 0x007e, 0x78aa, 0x789b, - 0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, - 0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c25, 0x7003, - 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078, - 0x2d69, 0x00c0, 0x1c4b, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, - 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, - 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009, - 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c4b, 0x7003, 0x0004, 0x70c3, - 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078, 0x2d69, 0x00c0, - 0x1c75, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, - 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x71b8, - 0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, - 0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c75, 0x7003, - 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x0078, - 0x1c27, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x70bc, 0x2068, 0x789b, - 0x0010, 0x6f10, 0x1078, 0x2cac, 0x2c50, 0x6810, 0x007e, 0x8007, - 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048, - 0x0c7e, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, - 0x007f, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, 0x2041, - 0x0001, 0x2001, 0x0004, 0x0078, 0x1dcc, 0x1078, 0x2d69, 0x00c0, - 0x1bd3, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, 0x2cac, - 0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6820, 0xa005, 0x0040, - 0x1cc1, 0xa082, 0x0006, 0x0048, 0x1cbf, 0x0078, 0x1cc1, 0x6823, - 0x0005, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, - 0x0020, 0x2041, 0x0001, 0x1078, 0x2dc8, 0x2001, 0x0003, 0x0078, - 0x1dcc, 0x0018, 0x1ba4, 0x7440, 0xa485, 0x0000, 0x0040, 0x1ceb, - 0xa080, 0x3580, 0x2030, 0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce2, - 0x2009, 0x3580, 0x2164, 0x6504, 0x85ff, 0x00c0, 0x1cf8, 0x8421, - 0x00c0, 0x1cdc, 0x7146, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, - 0x1bd3, 0x7640, 0xa6b0, 0x3580, 0x7144, 0x2600, 0x0078, 0x1ce7, - 0x7146, 0x2568, 0x2558, 0x753e, 0x2c50, 0x6034, 0xa085, 0x0000, - 0x00c0, 0x1cf5, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, 0x1d2a, - 0xa784, 0x0021, 0x00c0, 0x1cf5, 0xa784, 0x0002, 0x0040, 0x1d17, - 0xa784, 0x0004, 0x0040, 0x1cf5, 0xa7bc, 0xfffb, 0x670a, 0xa784, - 0x0008, 0x00c0, 0x1cf5, 0xa784, 0x0010, 0x00c0, 0x1cf5, 0xa784, - 0x0100, 0x0040, 0x1d2a, 0x6018, 0xa005, 0x00c0, 0x1cf5, 0xa7bc, - 0xfeff, 0x670a, 0x681f, 0x0000, 0x6e18, 0xa684, 0x000e, 0x6118, - 0x0040, 0x1d3a, 0x601c, 0xa102, 0x0048, 0x1d3d, 0x0040, 0x1d3d, - 0x0078, 0x1cf1, 0x81ff, 0x00c0, 0x1cf1, 0xa784, 0x0080, 0x00c0, - 0x1d43, 0x700c, 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307, - 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060, - 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x2a60, 0x0018, - 0x1ba4, 0x789b, 0x0010, 0xa046, 0x1078, 0x2d69, 0x00c0, 0x1bd3, - 0x6b10, 0xa39c, 0x0007, 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, - 0x0040, 0x1d6e, 0xa684, 0x0001, 0x0040, 0x1d74, 0xa39c, 0xffbf, - 0xa684, 0x000e, 0x00c0, 0x2901, 0xa684, 0x0010, 0x0040, 0x1d7e, - 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2907, 0x7baa, 0x8840, - 0xa684, 0x000e, 0x00c0, 0x1d89, 0xa7bd, 0x0010, 0x670a, 0x0078, - 0x1dca, 0x714c, 0xa18c, 0x0800, 0x0040, 0x290d, 0x2011, 0x0021, - 0x8004, 0x8004, 0x0048, 0x1da0, 0x2011, 0x0022, 0x8004, 0x0048, - 0x1da0, 0x2011, 0x0020, 0x8004, 0x0048, 0x1da0, 0x0040, 0x1dca, - 0x7aaa, 0x8840, 0x1078, 0x2d82, 0x6a10, 0x610c, 0x8108, 0xa18c, - 0x00ff, 0xa1e0, 0x3e80, 0x2c64, 0x8cff, 0x0040, 0x1dc1, 0x6010, - 0xa206, 0x00c0, 0x1dab, 0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da6, - 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, - 0x1cd1, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x2a60, 0x610e, 0x79aa, - 0x8840, 0x712e, 0x2001, 0x0001, 0x007e, 0x7150, 0xa184, 0x0018, - 0x0040, 0x1de0, 0xa184, 0x0010, 0x0040, 0x1dda, 0x1078, 0x2ad7, - 0x00c0, 0x1de0, 0xa184, 0x0008, 0x0040, 0x1de0, 0x1078, 0x29f1, - 0x007f, 0x7002, 0xa68c, 0x0060, 0x88ff, 0x0040, 0x1de9, 0xa18d, - 0x0004, 0x795a, 0x69b2, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, - 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, - 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, - 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, - 0x789b, 0x007e, 0x78aa, 0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2, - 0x7eda, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1e18, 0x0098, 0x1e20, - 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2d82, 0x0078, 0x1bdb, - 0x7200, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e2d, 0x781b, - 0x0049, 0x1078, 0x2d82, 0x0078, 0x1e3e, 0x6ab0, 0xa295, 0x2000, - 0x7a5a, 0x781b, 0x0049, 0x1078, 0x2d82, 0x7200, 0x2500, 0xa605, - 0x0040, 0x1e3e, 0xa284, 0x0007, 0x1079, 0x1e4c, 0xad80, 0x0008, - 0x7032, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e4a, 0x6018, - 0x8000, 0x601a, 0x0078, 0x1bd3, 0x1e54, 0x30f3, 0x30f3, 0x30e2, - 0x30f3, 0x1e54, 0x1e54, 0x1e54, 0x1078, 0x1b81, 0x7808, 0xa084, - 0xfffd, 0x780a, 0x0f7e, 0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084, - 0x0001, 0x0040, 0x1e7c, 0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e6b, - 0x70a2, 0x0078, 0x1f04, 0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e7a, - 0x70bc, 0x2068, 0x6817, 0x0004, 0x6813, 0x0000, 0x681c, 0xa085, - 0x0008, 0x681e, 0x70a3, 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, - 0xa186, 0x0001, 0x0040, 0x1e9e, 0xa186, 0x0007, 0x00c0, 0x1e8e, - 0x2009, 0x352b, 0x200b, 0x0005, 0x0078, 0x1e9e, 0x2009, 0x3513, - 0x2104, 0x2009, 0x3512, 0x200a, 0x2009, 0x352b, 0x200b, 0x0001, - 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1ea0, 0x70a3, 0x0000, - 0x1078, 0x2eca, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x2bb1, - 0xa7b8, 0x0100, 0x0070, 0x1eae, 0x0078, 0x1ea6, 0x7000, 0x2020, - 0x0079, 0x1eb2, 0x1ee0, 0x1ec9, 0x1ec9, 0x1ebc, 0x1ee0, 0x1ee0, - 0x1eba, 0x1eba, 0x1078, 0x1b81, 0x2021, 0x3557, 0x2404, 0xa005, - 0x0040, 0x1ec9, 0xad06, 0x00c0, 0x1ec9, 0x6800, 0x2022, 0x0078, - 0x1ed9, 0x681c, 0xa084, 0x0001, 0x00c0, 0x1ed5, 0x6f10, 0x1078, - 0x2cac, 0x1078, 0x28e4, 0x0078, 0x1ed9, 0x7054, 0x2060, 0x6800, - 0x6002, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17e7, - 0x2021, 0x3f80, 0x1078, 0x1f0a, 0x2021, 0x3557, 0x1078, 0x1f0a, - 0x20a9, 0x0000, 0x2021, 0x3e80, 0x1078, 0x1f0a, 0x8420, 0x0070, - 0x1ef3, 0x0078, 0x1eec, 0x20a9, 0x0080, 0x2061, 0x3680, 0x6018, - 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, - 0x1f03, 0x0078, 0x1ef7, 0x157f, 0x7003, 0x0000, 0x703f, 0x0000, - 0x0078, 0x1bd3, 0x047e, 0x2404, 0xa005, 0x0040, 0x1f1c, 0x2068, - 0x6800, 0x007e, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, - 0x17e7, 0x007f, 0x0078, 0x1f0c, 0x047f, 0x2023, 0x0000, 0x007c, - 0xa282, 0x0003, 0x0050, 0x1f26, 0x1078, 0x1b81, 0x2300, 0x0079, - 0x1f29, 0x1f2c, 0x1f9f, 0x1fad, 0xa282, 0x0002, 0x0040, 0x1f32, - 0x1078, 0x1b81, 0x70a0, 0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079, - 0x1f39, 0x1f41, 0x1f41, 0x1f43, 0x1f77, 0x2913, 0x1f41, 0x1f77, - 0x1f41, 0x1078, 0x1b81, 0x77b4, 0x1078, 0x2bb1, 0x77b4, 0xa7bc, - 0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f6e, 0x2021, - 0x3f80, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040, - 0x1f6e, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, - 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f6d, - 0x8420, 0x0070, 0x1f6d, 0x0078, 0x1f5e, 0x157f, 0x8738, 0xa784, - 0x0007, 0x00c0, 0x1f49, 0x0078, 0x1bdb, 0x0078, 0x1bdb, 0x77b4, - 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f9d, 0x2021, 0x3f80, - 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x1fc8, 0x0040, 0x1f9d, - 0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0005, - 0x2011, 0x0020, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f9c, 0x8420, - 0x0070, 0x1f9c, 0x0078, 0x1f8d, 0x157f, 0x0078, 0x1bdb, 0x2200, - 0x0079, 0x1fa2, 0x1fa5, 0x1fa7, 0x1fa7, 0x1078, 0x1b81, 0x70a3, - 0x0000, 0x70a7, 0x0001, 0x0078, 0x1bd3, 0x2200, 0x0079, 0x1fb0, - 0x1fb5, 0x1fa7, 0x1fb3, 0x1078, 0x1b81, 0x1078, 0x2428, 0x7000, - 0xa086, 0x0001, 0x00c0, 0x28ba, 0x1078, 0x28fa, 0x6008, 0xa084, - 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba, 0x0078, 0x1cd1, - 0x2404, 0xa005, 0x0040, 0x1fe9, 0x2068, 0x2d04, 0x007e, 0x6810, - 0xa706, 0x0040, 0x1fd7, 0x2d20, 0x007f, 0x0078, 0x1fc9, 0x007f, - 0x2022, 0x6916, 0x681c, 0xa205, 0x681e, 0x1078, 0x17e7, 0x6010, - 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28fa, - 0x007c, 0xa085, 0x0001, 0x0078, 0x1fe8, 0x2300, 0x0079, 0x1ff0, - 0x1ff5, 0x1ff3, 0x2038, 0x1078, 0x1b81, 0x78e4, 0xa005, 0x00d0, - 0x2018, 0x0018, 0x2018, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2004, - 0x781b, 0x0049, 0x0078, 0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040, - 0x2000, 0x2100, 0xa084, 0x0007, 0x0079, 0x200e, 0x2026, 0x202c, - 0x2020, 0x2016, 0x2d63, 0x2d63, 0x2016, 0x2032, 0x1078, 0x1b81, - 0x7000, 0xa005, 0x0040, 0x1bdb, 0x2001, 0x0003, 0x0078, 0x22fd, - 0x1078, 0x2b94, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b94, - 0x781b, 0x00dc, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x00e3, - 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x009d, 0x0078, 0x1bd3, - 0xa584, 0x000f, 0x00c0, 0x2062, 0x1078, 0x2428, 0x7000, 0x0079, - 0x2041, 0x2049, 0x2056, 0x2049, 0x28ba, 0x204b, 0x28ba, 0x2049, - 0x2049, 0x1078, 0x1b81, 0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004, - 0x00c0, 0x2054, 0x0078, 0x2913, 0x0078, 0x28ba, 0x1078, 0x28fa, - 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba, - 0x0078, 0x1cd1, 0x78e4, 0xa005, 0x00d0, 0x2018, 0x0018, 0x2018, - 0x2008, 0xa084, 0x0030, 0x00c0, 0x2071, 0x781b, 0x0049, 0x0078, - 0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040, 0x206d, 0x2100, 0xa184, - 0x0007, 0x0079, 0x207b, 0x208b, 0x2091, 0x2085, 0x2083, 0x2d63, - 0x2d63, 0x2083, 0x2d5b, 0x1078, 0x1b81, 0x1078, 0x2b9c, 0x781b, - 0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00dc, 0x0078, - 0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00e3, 0x0078, 0x1bd3, 0x1078, - 0x2b9c, 0x781b, 0x009d, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x20a0, - 0x20a5, 0x20a3, 0x20a7, 0x1078, 0x1b81, 0x0078, 0x2670, 0x6817, - 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x2670, - 0x78ec, 0xa084, 0x0003, 0x0040, 0x2670, 0xa184, 0x0007, 0x0079, - 0x20b9, 0x2026, 0x202c, 0x2020, 0x2d3b, 0x2d63, 0x2d63, 0x20c1, - 0x2d5b, 0x1078, 0x1b81, 0xa282, 0x0005, 0x0050, 0x20c9, 0x1078, - 0x1b81, 0x2300, 0x0079, 0x20cc, 0x20cf, 0x22d1, 0x22dd, 0x2200, - 0x0079, 0x20d2, 0x20d7, 0x20d9, 0x20ec, 0x20d7, 0x22b6, 0x1078, - 0x1b81, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, - 0x0048, 0x2b75, 0xa08a, 0x0004, 0x00c8, 0x2b75, 0x0079, 0x20e8, - 0x2b75, 0x2b75, 0x2b75, 0x2b17, 0x789b, 0x0018, 0x79a8, 0xa184, - 0x0080, 0x0040, 0x2101, 0xa184, 0x0018, 0x0040, 0x20fd, 0x0078, - 0x2b75, 0x7000, 0xa005, 0x00c0, 0x20f7, 0x2011, 0x0003, 0x0078, - 0x275d, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x2b75, 0x0079, - 0x2109, 0x211b, 0x2119, 0x2131, 0x2133, 0x21c5, 0x2b75, 0x2b75, - 0x21c7, 0x2b75, 0x2b75, 0x22b2, 0x22b2, 0x2b75, 0x2b75, 0x2b75, - 0x22b4, 0x1078, 0x1b81, 0xa684, 0x1000, 0x0040, 0x2128, 0x2001, - 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x009a, 0x0078, 0x1bd3, - 0x6814, 0xa084, 0x8000, 0x0040, 0x212f, 0x6817, 0x0003, 0x0078, - 0x2d3b, 0x1078, 0x1b81, 0x691c, 0x691e, 0xa684, 0x1800, 0x00c0, - 0x214d, 0x681c, 0xa084, 0x0001, 0x00c0, 0x2155, 0x6814, 0xa086, - 0x0008, 0x00c0, 0x2145, 0x6817, 0x0000, 0xa684, 0x0400, 0x0040, - 0x21c1, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x1000, 0x0040, - 0x2155, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x0060, 0x0040, - 0x21bd, 0xa684, 0x0800, 0x0040, 0x21bd, 0xa684, 0x8000, 0x00c0, - 0x2163, 0x0078, 0x217d, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b, - 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2170, 0x8000, - 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, - 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, 0xa684, 0x4000, 0x0040, - 0x2185, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003, - 0x00c0, 0x2192, 0x1078, 0x2f3d, 0x1078, 0x30e2, 0x781b, 0x0067, - 0x0078, 0x1bd3, 0xa006, 0x1078, 0x3197, 0x6aac, 0x69a8, 0x6c94, - 0x6b90, 0x2200, 0xa105, 0x0040, 0x21a1, 0x2200, 0xa422, 0x2100, - 0xa31b, 0x7cd2, 0x7bd6, 0x2300, 0xa405, 0x00c0, 0x21af, 0xa6b5, - 0x4000, 0x7e5a, 0x6eb2, 0x781b, 0x0067, 0x0078, 0x1bd3, 0x781b, - 0x0067, 0x2200, 0xa115, 0x00c0, 0x21b9, 0x1078, 0x30f3, 0x0078, - 0x1bd3, 0x1078, 0x3120, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, - 0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x0078, - 0x2224, 0x691c, 0xa184, 0x0100, 0x0040, 0x21df, 0xa18c, 0xfeff, - 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002, - 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x2213, 0xa184, - 0x0200, 0x0040, 0x2213, 0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048, - 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef, - 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213, - 0x1078, 0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b, - 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, - 0x0400, 0x00c0, 0x220f, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, - 0x0069, 0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x221c, - 0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, - 0x0078, 0x2b7b, 0x0078, 0x2b7b, 0x2019, 0x0000, 0x7990, 0xa18c, - 0x0007, 0x0040, 0x2222, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, - 0xa286, 0x0001, 0x00c0, 0x2247, 0x2300, 0x7ca8, 0xa400, 0x2018, - 0xa102, 0x0040, 0x223f, 0x0048, 0x223f, 0x0078, 0x2241, 0x0078, - 0x21c9, 0x24a8, 0x7aa8, 0x00f0, 0x2241, 0x0078, 0x222d, 0xa284, - 0x00f0, 0xa086, 0x0020, 0x00c0, 0x22a3, 0x8318, 0x8318, 0x2300, - 0xa102, 0x0040, 0x2257, 0x0048, 0x2257, 0x0078, 0x22a0, 0xa286, - 0x0023, 0x0040, 0x2222, 0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58, - 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, - 0x0010, 0x600a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, - 0x0c7f, 0xa184, 0x0010, 0x0040, 0x227b, 0x1078, 0x2ca8, 0x1078, - 0x2ad7, 0x0078, 0x228a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, - 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213, 0x1078, 0x2ca8, - 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b, 0x0060, 0x2800, - 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x229c, - 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3, - 0x7aa8, 0x0078, 0x222d, 0x8318, 0x2300, 0xa102, 0x0040, 0x22ac, - 0x0048, 0x22ac, 0x0078, 0x222d, 0xa284, 0x0080, 0x00c0, 0x2b81, - 0x0078, 0x2b7b, 0x0078, 0x2b81, 0x0078, 0x2b75, 0x789b, 0x0018, - 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x22c1, 0x1078, - 0x1b81, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, - 0x0004, 0x00c8, 0x2b75, 0x0079, 0x22cd, 0x2b75, 0x2944, 0x2b75, - 0x2a72, 0xa282, 0x0000, 0x00c0, 0x22d7, 0x1078, 0x1b81, 0x1078, - 0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0xa282, 0x0003, 0x00c0, - 0x22e3, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078, - 0x1bd3, 0xa282, 0x0004, 0x0050, 0x22ef, 0x1078, 0x1b81, 0x2300, - 0x0079, 0x22f2, 0x22f5, 0x23d2, 0x2403, 0xa286, 0x0003, 0x0040, - 0x22fb, 0x1078, 0x1b81, 0x2001, 0x0000, 0x703a, 0x7000, 0xa084, - 0x0007, 0x0079, 0x2303, 0x230b, 0x230d, 0x230d, 0x2513, 0x253b, - 0x24dd, 0x230b, 0x230b, 0x1078, 0x1b81, 0xa684, 0x1000, 0x00c0, - 0x2315, 0x1078, 0x2eca, 0x0040, 0x23ac, 0x7868, 0xa08c, 0x00ff, - 0x0040, 0x235d, 0xa186, 0x0008, 0x00c0, 0x232c, 0x1078, 0x28fa, - 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x235d, - 0x1078, 0x2eca, 0x0078, 0x2344, 0xa186, 0x0028, 0x00c0, 0x235d, - 0x1078, 0x2eca, 0x6008, 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, - 0x0040, 0x2344, 0x8001, 0x601a, 0xa005, 0x0040, 0x2344, 0x8001, - 0xa005, 0x0040, 0x2344, 0x601e, 0x681c, 0xa084, 0x0001, 0x0040, - 0x1bdb, 0x681c, 0xa084, 0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060, - 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, - 0x235a, 0x6002, 0x6006, 0x0078, 0x1bdb, 0x017e, 0x1078, 0x2428, - 0x017f, 0xa684, 0xdf00, 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, - 0x0040, 0x23ac, 0xa186, 0x0002, 0x00c0, 0x23a4, 0xa684, 0x0800, - 0x00c0, 0x237a, 0xa684, 0x0060, 0x0040, 0x237a, 0x78d8, 0x7adc, - 0x682e, 0x6a2a, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, - 0xa290, 0x3600, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, - 0x238b, 0x0078, 0x2391, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, - 0x8211, 0xa384, 0x0400, 0x0040, 0x239e, 0x689c, 0xa084, 0x0100, - 0x00c0, 0x239e, 0x1078, 0x249c, 0x0078, 0x1bdb, 0x6008, 0xa085, - 0x0002, 0x600a, 0x0078, 0x23ac, 0xa186, 0x0018, 0x0040, 0x23ac, - 0xa186, 0x0014, 0x0040, 0x1bdb, 0x6912, 0x6814, 0xa084, 0x8000, - 0x0040, 0x23b4, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, - 0x28eb, 0x1078, 0x28fa, 0x00c0, 0x23c1, 0x6008, 0xa084, 0xffef, - 0x600a, 0x681c, 0xa084, 0x0001, 0x00c0, 0x23ca, 0x1078, 0x28e4, - 0x0078, 0x23ce, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17e7, - 0x0078, 0x1bdb, 0xa282, 0x0004, 0x0048, 0x23d8, 0x1078, 0x1b81, - 0x2200, 0x0079, 0x23db, 0x23df, 0x23e1, 0x23ee, 0x23e1, 0x1078, - 0x1b81, 0x7000, 0xa086, 0x0005, 0x0040, 0x23ea, 0x1078, 0x2b94, - 0x781b, 0x0069, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x7890, 0x8007, - 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, - 0x00ff, 0xa186, 0x0003, 0x0040, 0x23ff, 0x0078, 0x2b75, 0x781b, - 0x006a, 0x0078, 0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff, - 0x00c0, 0x240e, 0x1078, 0x2b94, 0x0078, 0x2415, 0x8211, 0x0040, - 0x2413, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078, - 0x1bd3, 0x1078, 0x2d82, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2425, - 0x0018, 0x2425, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, - 0xa684, 0x0060, 0x00c0, 0x2432, 0x682f, 0x0000, 0x682b, 0x0000, - 0x0078, 0x249b, 0xa684, 0x0800, 0x00c0, 0x2441, 0x68b0, 0xa084, - 0x4800, 0xa635, 0xa684, 0x0800, 0x00c0, 0x2441, 0x1078, 0x2eca, - 0x007c, 0xa684, 0x0020, 0x0040, 0x246d, 0x78d0, 0x8003, 0x00c8, - 0x244f, 0xa006, 0x1078, 0x3197, 0x78d4, 0x1078, 0x31fc, 0xa684, - 0x4000, 0x0040, 0x2459, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, - 0x243e, 0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, - 0x2453, 0x7038, 0xa005, 0x00c0, 0x2467, 0x703b, 0x0007, 0x79d8, - 0x7adc, 0x692e, 0x6a2a, 0x0078, 0x243e, 0xa684, 0x4000, 0x0040, - 0x2477, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x243e, 0x68b0, - 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2471, 0x7038, - 0xa005, 0x00c0, 0x2485, 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, - 0x80f3, 0x00c8, 0x248c, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, - 0x0000, 0x692e, 0x6a2a, 0x2100, 0xa205, 0x00c0, 0x2499, 0x0078, - 0x243e, 0x1078, 0x3197, 0x007c, 0xa384, 0x0200, 0x0040, 0x24a4, - 0x6008, 0xa085, 0x0002, 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, - 0x6a3a, 0x693e, 0x682b, 0x0300, 0x682f, 0x0000, 0x6833, 0x2000, - 0x6893, 0x0000, 0x6897, 0x0020, 0x7000, 0x0079, 0x24b7, 0x24bf, - 0x24c1, 0x24ca, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x1078, - 0x1b81, 0x681c, 0xa084, 0x0001, 0x00c0, 0x24ca, 0x1078, 0x28e4, - 0x0078, 0x24d0, 0x7054, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, - 0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x24d9, 0x2020, 0x0078, - 0x24d2, 0x2d22, 0x206b, 0x0000, 0x007c, 0x77b4, 0x1078, 0x2bb1, - 0xa7bc, 0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x250c, - 0x0d7e, 0x2001, 0x3f90, 0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009, - 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040, 0x250c, 0x157e, - 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, - 0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x250b, 0x8420, 0x0070, - 0x250b, 0x0078, 0x24fc, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, - 0x24e2, 0x0078, 0x1bdb, 0x1078, 0x28eb, 0x1078, 0x28fa, 0x6827, - 0x0000, 0x789b, 0x000e, 0x6f10, 0x6813, 0x0002, 0x1078, 0x31cd, - 0xa684, 0x0800, 0x0040, 0x2528, 0x6918, 0xa18d, 0x2000, 0x691a, - 0x6814, 0xa084, 0x8000, 0x0040, 0x252f, 0x6817, 0x0000, 0x2021, - 0x3557, 0x6800, 0x2022, 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, - 0x17e7, 0x0078, 0x1bdb, 0x1078, 0x2428, 0x6827, 0x0000, 0x789b, - 0x000e, 0x6f10, 0x1078, 0x2d87, 0xa08c, 0x00ff, 0x6912, 0x6814, - 0xa084, 0x8000, 0x0040, 0x254e, 0x7038, 0x6816, 0xa68c, 0xdf00, - 0x691a, 0x70a3, 0x0000, 0x0078, 0x1bdb, 0xa006, 0x1078, 0x2eca, - 0x6813, 0x0000, 0x6817, 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, - 0x0000, 0x7000, 0x0079, 0x2564, 0x256c, 0x256e, 0x256e, 0x2570, - 0x2570, 0x2570, 0x256c, 0x256c, 0x1078, 0x1b81, 0x1078, 0x28fa, - 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x28c5, 0x2300, 0x0079, - 0x2579, 0x257c, 0x257e, 0x25bc, 0x1078, 0x1b81, 0x7000, 0x0079, - 0x2581, 0x2589, 0x258b, 0x258b, 0x2596, 0x258b, 0x259d, 0x2589, - 0x2589, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x2596, 0xa6b5, - 0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084, - 0x8000, 0x0040, 0x259d, 0x6817, 0x0007, 0x2009, 0x3518, 0x210c, - 0xa186, 0x0000, 0x0040, 0x25b2, 0xa186, 0x0001, 0x0040, 0x25b6, - 0x2009, 0x352b, 0x200b, 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, - 0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x2009, 0x352b, - 0x200b, 0x000a, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x2300, 0x0079, - 0x25c1, 0x25c4, 0x25c6, 0x25e9, 0x1078, 0x1b81, 0x7000, 0x0079, - 0x25c9, 0x25d1, 0x25d3, 0x25d3, 0x25de, 0x25d3, 0x25e5, 0x25d1, - 0x25d1, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x25de, 0xa6b5, - 0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084, - 0x8000, 0x0040, 0x25e5, 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, - 0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078, - 0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x25f8, - 0x25fb, 0x25fd, 0x25ff, 0x1078, 0x1b81, 0x1078, 0x1b81, 0xa684, - 0x0400, 0x00c0, 0x261e, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, - 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040, - 0x2616, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x261a, 0x2001, 0x0014, - 0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2656, 0x7a90, 0xa294, - 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x2654, 0x789b, - 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x2645, 0x7ba8, 0x7ba8, - 0xa386, 0x0001, 0x00c0, 0x2638, 0x2009, 0xfff7, 0x0078, 0x263e, - 0xa386, 0x0003, 0x00c0, 0x2645, 0x2009, 0xffef, 0x0c7e, 0x7048, - 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, - 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c, - 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b, 0x2026, 0x202c, - 0x2660, 0x2668, 0x265e, 0x265e, 0x265e, 0x2d3b, 0x1078, 0x1b81, - 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d43, - 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b, - 0x79e4, 0xa184, 0x0030, 0x0040, 0x267a, 0x78ec, 0xa084, 0x0003, - 0x00c0, 0x2682, 0x6814, 0xa085, 0x8000, 0x6816, 0x2001, 0x0014, - 0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2686, 0x2d3b, 0x2d3b, - 0x268e, 0x2d3b, 0x2d63, 0x2d63, 0x2d3b, 0x2d3b, 0xa684, 0x0400, - 0x00c0, 0x26bf, 0x681c, 0xa084, 0x0001, 0x0040, 0x2d43, 0xa68c, - 0x2060, 0xa18c, 0xfffb, 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab, - 0x0000, 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, - 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, - 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, - 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, 0x0078, 0x2d43, 0x6814, - 0xa084, 0x8000, 0x0040, 0x26c6, 0x6817, 0x0008, 0x781b, 0x00d8, - 0x0078, 0x1bd3, 0x2300, 0x0079, 0x26cd, 0x26d2, 0x274d, 0x26d0, - 0x1078, 0x1b81, 0x7000, 0xa084, 0x0007, 0x0079, 0x26d7, 0x26df, - 0x26e1, 0x26fd, 0x26df, 0x26df, 0x24dd, 0x26df, 0x26df, 0x1078, - 0x1b81, 0x691c, 0xa18d, 0x0001, 0x691e, 0x6800, 0x6006, 0xa005, - 0x00c0, 0x26eb, 0x6002, 0x6818, 0xa084, 0x000e, 0x0040, 0x26f7, - 0x7014, 0x68b6, 0x712c, 0xa188, 0x3e80, 0x0078, 0x26f9, 0x2009, - 0x3f80, 0x2104, 0x6802, 0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060, - 0x0040, 0x274b, 0xa684, 0x0800, 0x00c0, 0x270f, 0xa684, 0x7fff, - 0x68b2, 0x6890, 0x6894, 0x1078, 0x2eca, 0x0078, 0x274b, 0xa684, - 0x0020, 0x0040, 0x2721, 0xa006, 0x1078, 0x3197, 0x78d0, 0x8003, - 0x00c8, 0x271d, 0x78d4, 0x1078, 0x31fc, 0x79d8, 0x7adc, 0x0078, - 0x2725, 0x1078, 0x2cb9, 0x1078, 0x3197, 0xa684, 0x8000, 0x0040, - 0x274b, 0xa684, 0x7fff, 0x68b2, 0x789b, 0x0074, 0x1078, 0x2d87, - 0x2010, 0x1078, 0x2d87, 0x2008, 0xa684, 0x0020, 0x00c0, 0x2743, - 0x1078, 0x2d87, 0x801b, 0x00c8, 0x273e, 0x8000, 0xa084, 0x003f, - 0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, - 0x2200, 0xa303, 0x68aa, 0x0078, 0x1bdb, 0x0078, 0x2b81, 0x7033, - 0x0000, 0xa282, 0x0005, 0x0050, 0x2757, 0x1078, 0x1b81, 0x2300, - 0x0079, 0x275a, 0x275d, 0x2767, 0x278a, 0x2200, 0x0079, 0x2760, - 0x2765, 0x2b81, 0x2765, 0x27b3, 0x2804, 0x1078, 0x1b81, 0x7000, - 0xa086, 0x0001, 0x00c0, 0x2774, 0x1078, 0x28fa, 0x1078, 0x2eca, - 0x7034, 0x600a, 0x0078, 0x2779, 0x7000, 0xa086, 0x0003, 0x0040, - 0x276e, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, - 0x2200, 0x0079, 0x2783, 0x2b81, 0x2788, 0x27b3, 0x2788, 0x2b81, - 0x1078, 0x1b81, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2797, 0x1078, - 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x279c, 0x7000, - 0xa086, 0x0003, 0x0040, 0x2791, 0x7003, 0x0005, 0x2001, 0x3f90, - 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x27a6, 0x27ad, 0x27ab, - 0x27ad, 0x27ab, 0x27ad, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, - 0x0069, 0x0078, 0x1bd3, 0x7000, 0xa086, 0x0001, 0x00c0, 0x27c0, - 0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x27c5, - 0x7000, 0xa086, 0x0003, 0x0040, 0x27ba, 0x7003, 0x0002, 0x7a80, - 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, - 0x2069, 0x3f80, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, - 0x27e0, 0x6810, 0xa206, 0x0040, 0x27f9, 0x6800, 0x0078, 0x27d3, - 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, - 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, 0x27f1, 0x0078, - 0x27ea, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, - 0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, 0x0040, 0x285a, - 0x1078, 0x2b9c, 0x0078, 0x285a, 0x7000, 0xa086, 0x0001, 0x00c0, - 0x2811, 0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, - 0x2816, 0x7000, 0xa086, 0x0003, 0x0040, 0x280b, 0x7003, 0x0002, - 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, - 0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04, - 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x2835, 0x6810, 0xa206, - 0x0040, 0x284e, 0x6800, 0x0078, 0x2828, 0x7003, 0x0005, 0x2001, - 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003, - 0x0000, 0x8000, 0x0070, 0x2846, 0x0078, 0x283f, 0x157f, 0x6a12, - 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, - 0x681c, 0xa084, 0x0c00, 0x0040, 0x285a, 0x1078, 0x2b98, 0x7e58, - 0x0078, 0x285a, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, - 0x8003, 0xa080, 0x3600, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, - 0x7052, 0xa684, 0x0060, 0x0040, 0x2891, 0x6b94, 0x6c90, 0x69a8, - 0x68ac, 0xa105, 0x00c0, 0x287f, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, - 0xa6b4, 0xb7ff, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2891, 0x68ac, - 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x2891, 0x7bd2, - 0x7bda, 0x7cd6, 0x7cde, 0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078, - 0x3120, 0x077f, 0x1078, 0x2cac, 0x2009, 0x006a, 0xa684, 0x0008, - 0x0040, 0x289c, 0x2009, 0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a, - 0x2d00, 0x703e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xa080, 0x3600, 0x2048, 0x0078, 0x1bd3, 0x6020, 0xa005, 0x0040, - 0x28b9, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, - 0x6026, 0x007c, 0xa006, 0x1078, 0x2eca, 0x6813, 0x0000, 0x6817, - 0x0001, 0x681f, 0x0040, 0x681b, 0x0100, 0x7000, 0xa084, 0x0007, - 0x0079, 0x28ca, 0x28d2, 0x28d4, 0x28d4, 0x28e0, 0x28dc, 0x28d2, - 0x28d2, 0x28d2, 0x1078, 0x1b81, 0x1078, 0x28eb, 0x1078, 0x28e4, - 0x1078, 0x17e7, 0x0078, 0x1bdb, 0x70a3, 0x0000, 0x0078, 0x1bdb, - 0x6817, 0x0000, 0x0078, 0x2513, 0x6800, 0xa005, 0x00c0, 0x28e9, - 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, 0x28f4, 0x8001, - 0x00d0, 0x28f4, 0x1078, 0x1b81, 0x6012, 0x6008, 0xa084, 0xffef, - 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x2900, 0x8001, 0x601a, - 0x007c, 0x1078, 0x2d82, 0x6817, 0x0018, 0x0078, 0x2931, 0x1078, - 0x2d82, 0x6817, 0x0019, 0x0078, 0x2931, 0x1078, 0x2d82, 0x6817, - 0x001a, 0x0078, 0x2931, 0x77b4, 0x1078, 0x2cac, 0x71b8, 0xa18c, - 0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, - 0x2923, 0x0078, 0x1bdb, 0x6810, 0x72b4, 0xa206, 0x0040, 0x292b, - 0x6800, 0x0078, 0x291c, 0x6800, 0x200a, 0x6817, 0x0005, 0x70bf, - 0x0000, 0x1078, 0x28eb, 0x681c, 0xa084, 0x0001, 0x00c0, 0x293a, - 0x1078, 0x28e4, 0x1078, 0x28fa, 0x681b, 0x0000, 0x681f, 0x0020, - 0x1078, 0x17e7, 0x0078, 0x1bdb, 0xa282, 0x0003, 0x00c0, 0x2b75, - 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d, - 0x0080, 0x691e, 0xa184, 0x0100, 0x0040, 0x29a4, 0xa18c, 0xfeff, - 0x691e, 0xa6b4, 0x00ff, 0x0040, 0x298e, 0xa682, 0x000f, 0x0048, - 0x2965, 0x0040, 0x2965, 0x2031, 0x000f, 0x852b, 0x852b, 0x1078, - 0x2c2f, 0x0040, 0x296f, 0x1078, 0x2a3e, 0x0078, 0x2997, 0x1078, - 0x2bea, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, - 0x2a62, 0x0c7f, 0x691c, 0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5, - 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x298a, 0x781b, 0x0055, - 0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e, 0x2960, - 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a62, 0x0c7f, 0x7e58, - 0xa684, 0x0400, 0x00c0, 0x29a0, 0x781b, 0x0058, 0x0078, 0x1bd3, - 0x781b, 0x006a, 0x0078, 0x1bd3, 0x0c7e, 0x7048, 0x2060, 0x6100, - 0xa18c, 0x1000, 0x0040, 0x29e4, 0x6208, 0x8217, 0xa294, 0x00ff, - 0xa282, 0x000f, 0x0048, 0x29b8, 0x0040, 0x29b8, 0x2011, 0x000f, - 0x2600, 0xa202, 0x00c8, 0x29bd, 0x2230, 0x6208, 0xa294, 0x00ff, - 0x7018, 0xa086, 0x0028, 0x00c0, 0x29cd, 0xa282, 0x0019, 0x00c8, - 0x29d3, 0x2011, 0x0019, 0x0078, 0x29d3, 0xa282, 0x000c, 0x00c8, - 0x29d3, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x29d8, 0x2228, - 0x1078, 0x2bee, 0x852b, 0x852b, 0x1078, 0x2c2f, 0x0040, 0x29e4, - 0x1078, 0x2a3e, 0x0078, 0x29e8, 0x1078, 0x2bea, 0x1078, 0x2a62, - 0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078, - 0x1bd3, 0x0c7e, 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x2a0c, - 0x6010, 0xa084, 0x000f, 0x00c0, 0x2a06, 0xa18c, 0x0002, 0x00c0, - 0x2a06, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, - 0x2019, 0x0000, 0x0078, 0x2a2e, 0x6208, 0xa294, 0x00ff, 0x7018, - 0xa086, 0x0028, 0x00c0, 0x2a1c, 0xa282, 0x0019, 0x00c8, 0x2a22, - 0x2011, 0x0019, 0x0078, 0x2a22, 0xa282, 0x000c, 0x00c8, 0x2a22, - 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f, - 0x0048, 0x2a2e, 0x0040, 0x2a2e, 0x2019, 0x000f, 0x78ab, 0x0001, - 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, - 0x681c, 0xa085, 0x0100, 0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148, - 0x2160, 0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, - 0x7eae, 0x6612, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, - 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004, - 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, - 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x6018, 0x789a, 0x78a4, - 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886, - 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0, 0x2b75, 0x7aa8, 0x691c, - 0xa18d, 0x0080, 0x691e, 0xa184, 0x0200, 0x0040, 0x2ab7, 0xa18c, - 0xfdff, 0x691e, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b75, - 0x1078, 0x2afe, 0x1078, 0x2a62, 0xa980, 0x0001, 0x200c, 0x1078, - 0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2aaa, 0x789b, 0x0060, - 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, - 0x00c0, 0x2aa6, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069, - 0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2ab3, 0x781b, - 0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0xa282, - 0x0002, 0x00c8, 0x2abf, 0xa284, 0x0001, 0x0040, 0x2ac9, 0x7148, - 0xa188, 0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x2ac9, 0x2011, - 0x0000, 0x1078, 0x2bdc, 0x1078, 0x2afe, 0x1078, 0x2a62, 0x7858, - 0xa085, 0x0004, 0x785a, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e, - 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, - 0x2aee, 0x6014, 0xa084, 0x0040, 0x00c0, 0x2aec, 0xa18c, 0xffef, - 0x6106, 0xa006, 0x0078, 0x2afb, 0x2011, 0x0000, 0x78ab, 0x0001, - 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c, - 0xa085, 0x0200, 0x681e, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048, - 0x2060, 0x82ff, 0x0040, 0x2b06, 0x2011, 0x0040, 0x6018, 0xa080, - 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016, - 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e, - 0x7000, 0xa086, 0x0003, 0x0040, 0x2b20, 0x007f, 0x0078, 0x2b23, - 0x007f, 0x0078, 0x2b71, 0xa684, 0x0020, 0x0040, 0x2b71, 0x7888, - 0xa084, 0x0040, 0x0040, 0x2b71, 0x78a8, 0x8001, 0x0040, 0x2b30, - 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x2b37, 0x8000, 0xa005, - 0x0040, 0x2b58, 0x831b, 0x00c8, 0x2b40, 0x8001, 0x0040, 0x2b6d, - 0xa006, 0x1078, 0x3197, 0x78b4, 0x1078, 0x31fc, 0x0078, 0x2b71, - 0xa684, 0x4000, 0x0040, 0x2b58, 0x78b8, 0x801b, 0x00c8, 0x2b51, - 0x8000, 0xa084, 0x003f, 0x00c0, 0x2b6d, 0xa6b4, 0xbfff, 0x7e5a, - 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x2b61, 0xa291, - 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x3197, 0x781b, - 0x0067, 0x1078, 0x3061, 0x0078, 0x1bd3, 0x781b, 0x0067, 0x0078, - 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x1078, 0x2ba8, 0x781b, - 0x0069, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x0069, 0x0078, - 0x1bd3, 0x6823, 0x0002, 0x1078, 0x2b9c, 0x691c, 0xa18d, 0x0020, - 0x691e, 0x6814, 0xa084, 0x8000, 0x0040, 0x2b90, 0x6817, 0x0005, - 0x781b, 0x0069, 0x0078, 0x1bd3, 0x2001, 0x0005, 0x0078, 0x2baa, - 0x2001, 0x000c, 0x0078, 0x2baa, 0x2001, 0x0006, 0x0078, 0x2baa, - 0x2001, 0x000d, 0x0078, 0x2baa, 0x2001, 0x0009, 0x0078, 0x2baa, - 0x2001, 0x0007, 0x789b, 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a, - 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, - 0xa0e0, 0x3600, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, - 0x0040, 0x2bca, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, - 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, - 0x0040, 0x2bda, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, - 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, - 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, - 0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, - 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, - 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, - 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, - 0xfff0, 0x2001, 0x3546, 0x2004, 0xa082, 0x0028, 0x0040, 0x2c18, - 0x2021, 0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c1e, - 0x2021, 0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, - 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x2c2d, 0x8420, 0x2300, - 0xa210, 0x0070, 0x2c2d, 0x0078, 0x2c20, 0x157f, 0x007c, 0x157e, - 0x2011, 0x3546, 0x2214, 0xa282, 0x0032, 0x0048, 0x2c43, 0x0040, - 0x2c47, 0x2021, 0x2c81, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, - 0x0032, 0x0078, 0x2c57, 0xa282, 0x0028, 0x0040, 0x2c4f, 0x2021, - 0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c55, 0x2021, - 0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200, - 0xa502, 0x0040, 0x2c67, 0x0048, 0x2c67, 0x8420, 0x2300, 0xa210, - 0x0070, 0x2c64, 0x0078, 0x2c57, 0x157f, 0xa006, 0x007c, 0x157f, - 0xa582, 0x0064, 0x00c8, 0x2c70, 0x7808, 0xa085, 0x0070, 0x780a, - 0x78ec, 0xa084, 0x0300, 0x0040, 0x2c7e, 0x2404, 0xa09e, 0x1201, - 0x00c0, 0x2c7e, 0x2001, 0x2101, 0x0078, 0x2c7f, 0x2404, 0xa005, - 0x007c, 0x1201, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, - 0x6605, 0x6805, 0x7806, 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, - 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, - 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, - 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, - 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, - 0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680, - 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x2cc0, 0x8000, - 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, - 0x0100, 0x2009, 0x3540, 0x2091, 0x8000, 0x2104, 0x0079, 0x2cd0, - 0x2d02, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cd8, 0x2cd8, - 0x1078, 0x1b81, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x00c0, - 0x2cdc, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0, 0x2ce3, - 0x68b0, 0xa085, 0x4000, 0x68b2, 0x7858, 0xa085, 0x4000, 0x785a, - 0x7830, 0xa084, 0x0080, 0x00c0, 0x2d02, 0x0018, 0x2d02, 0x6818, - 0xa084, 0x0020, 0x00c0, 0x2d00, 0x781b, 0x00dd, 0x0078, 0x2d02, - 0x781b, 0x00e4, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810, - 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600, - 0x6004, 0xa084, 0x000a, 0x00c0, 0x2d39, 0x6108, 0xa194, 0xff00, - 0x0040, 0x2d39, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, - 0x2d28, 0x2001, 0x0032, 0xa106, 0x0040, 0x2d2c, 0x0078, 0x2d30, - 0x2009, 0x0020, 0x0078, 0x2d32, 0x2009, 0x003f, 0x0078, 0x2d32, - 0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, - 0x6006, 0x0c7f, 0x007c, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x781b, - 0x0069, 0x0078, 0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b, - 0x0055, 0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x781b, - 0x00dc, 0x0078, 0x1bd3, 0x781b, 0x00e4, 0x0078, 0x1bd3, 0x781b, - 0x00e3, 0x0078, 0x1bd3, 0x781b, 0x009e, 0x0078, 0x1bd3, 0x781b, - 0x009d, 0x0078, 0x1bd3, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, - 0x1bd3, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2d80, 0x7808, - 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, - 0xa084, 0x0021, 0x0040, 0x2d80, 0x7808, 0xa085, 0x0002, 0x780a, - 0x007f, 0x007c, 0x7808, 0xa085, 0x0002, 0x780a, 0x007c, 0x7830, - 0xa084, 0x0040, 0x00c0, 0x2d87, 0x0098, 0x2d90, 0x78ac, 0x007c, - 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, - 0x78ec, 0xa084, 0x0021, 0x0040, 0x2d9f, 0x0098, 0x2d9d, 0x78ac, - 0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, - 0x0070, 0x0040, 0x2dab, 0x6817, 0x0003, 0x7858, 0xa084, 0x3f00, - 0x681a, 0x682f, 0x0000, 0x682b, 0x0000, 0x784b, 0x0008, 0x78e4, - 0xa005, 0x00d0, 0x2018, 0xa084, 0x0020, 0x0040, 0x2018, 0x78ec, - 0xa084, 0x0003, 0x0040, 0x2018, 0x0018, 0x2018, 0x0078, 0x2b7b, - 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, - 0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, - 0x7052, 0x0c7f, 0x007c, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, - 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, - 0x0014, 0x9847, 0x0014, 0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014, - 0x0080, 0x00bf, 0x0100, 0x0402, 0x2008, 0xf880, 0xa20a, 0x0014, - 0x300b, 0xa20c, 0x0014, 0xa200, 0x8838, 0x817e, 0x842a, 0x84a0, - 0x3806, 0x8839, 0x28c2, 0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008, - 0x28c1, 0x9cc3, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, - 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864, - 0xa829, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204, - 0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, - 0xa80f, 0x786e, 0x883e, 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0, - 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa801, 0x883e, - 0x2069, 0x28c1, 0x9cc3, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc, - 0xa207, 0x0014, 0xa203, 0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a, - 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, 0x0704, 0x3008, - 0x9ca0, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, - 0xf848, 0x8174, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6, - 0xa8f1, 0xf861, 0xa8e8, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, - 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, - 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f, - 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000, - 0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7, - 0x8822, 0x0016, 0x8000, 0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000, - 0xa000, 0x2802, 0x1011, 0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011, - 0xa8fd, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, - 0x0014, 0x26e0, 0x873a, 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, - 0x0014, 0xa20d, 0x817e, 0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd, - 0x0704, 0x0000, 0x127e, 0x2091, 0x2200, 0x2049, 0x2eca, 0x7000, - 0x7204, 0xa205, 0x720c, 0xa215, 0x7008, 0xa084, 0xfffd, 0xa205, - 0x0040, 0x2edc, 0x0078, 0x2ee1, 0x7003, 0x0000, 0x127f, 0x2000, - 0x007c, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f0f, 0x7108, 0x8104, - 0x00c8, 0x2eee, 0x1078, 0x2fab, 0x0078, 0x2ee6, 0x700c, 0xa08c, - 0x007f, 0x0040, 0x2f0f, 0x7004, 0x8004, 0x00c8, 0x2f06, 0x7014, - 0xa005, 0x00c0, 0x2f02, 0x7010, 0xa005, 0x0040, 0x2f06, 0xa102, - 0x00c8, 0x2ee6, 0x7007, 0x0010, 0x0078, 0x2f0f, 0x8aff, 0x0040, - 0x2f0f, 0x1078, 0x316e, 0x00c0, 0x2f09, 0x0040, 0x2ee6, 0x1078, - 0x2f59, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, - 0x0040, 0x2f33, 0x2c70, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c, - 0xa630, 0x6808, 0xa529, 0x8421, 0x0040, 0x2f33, 0x8738, 0x2704, - 0xa005, 0x00c0, 0x2f1e, 0x7098, 0xa075, 0x0040, 0x2f33, 0x2039, - 0x2f35, 0x0078, 0x2f1d, 0x007c, 0x0000, 0x0004, 0x0008, 0x000c, - 0x0010, 0x0014, 0x0018, 0x001c, 0x0000, 0x127e, 0x2091, 0x2200, - 0x2079, 0x3500, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, - 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, - 0x7003, 0x0000, 0x2049, 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, - 0x007c, 0x2049, 0x2f59, 0x7004, 0x8004, 0x00c8, 0x2f85, 0x7007, - 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x2f61, 0xa184, 0x0030, - 0x0040, 0x2f6e, 0xa086, 0x0030, 0x00c0, 0x2f61, 0x7000, 0xa084, - 0x0001, 0x00c0, 0x2f85, 0x7008, 0xa084, 0x000c, 0x00c0, 0x2f83, - 0x710c, 0xa184, 0x0300, 0x00c0, 0x2f83, 0xa184, 0x007f, 0x00c0, - 0x2f59, 0x0078, 0x2f85, 0x6817, 0x0003, 0x7007, 0x0012, 0x7007, - 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x2f89, 0x7007, 0x0012, - 0x7108, 0x8104, 0x0048, 0x2f8e, 0x78b3, 0x0000, 0x7003, 0x0000, - 0x2049, 0x0000, 0x007c, 0x107e, 0x007e, 0x127e, 0x157e, 0x2091, - 0x2200, 0x7108, 0x1078, 0x2fab, 0x157f, 0x127f, 0x2091, 0x8001, - 0x007f, 0x107f, 0x007c, 0x7204, 0x2118, 0x7108, 0x700c, 0xa084, - 0x0300, 0x00c0, 0x2fed, 0xa184, 0x000c, 0x00c0, 0x2fed, 0x8213, - 0x8213, 0x8213, 0x8213, 0xa284, 0x0100, 0xa10d, 0x810b, 0x810b, - 0x810f, 0xa184, 0x0007, 0x0079, 0x2fc5, 0x2fcf, 0x2fdf, 0x2fed, - 0x2fdf, 0x3001, 0x3001, 0x2fed, 0x2fff, 0x1078, 0x1b81, 0x7007, - 0x0002, 0x8aff, 0x00c0, 0x2fd8, 0x2049, 0x0000, 0x0078, 0x2fdc, - 0x1078, 0x316e, 0x00c0, 0x2fd8, 0x78b3, 0x0000, 0x007c, 0x7007, - 0x0002, 0x8aff, 0x00c0, 0x2fe6, 0x0078, 0x2fea, 0x1078, 0x316e, - 0x00c0, 0x2fe6, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x1078, - 0x2f59, 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, 0x2ffa, - 0x6817, 0x0002, 0x007c, 0x1078, 0x1b81, 0x1078, 0x1b81, 0x1078, - 0x3053, 0x7210, 0x7114, 0x700c, 0xa09c, 0x007f, 0x2800, 0xa300, - 0xa211, 0xa189, 0x0000, 0x78b0, 0xa005, 0x0040, 0x3013, 0x78b3, - 0x0000, 0x0078, 0x3036, 0x1078, 0x3053, 0x2704, 0x2c58, 0xac60, - 0x630c, 0x2200, 0xa322, 0x6308, 0x2100, 0xa31b, 0x2400, 0xa305, - 0x0040, 0x302c, 0x00c8, 0x302c, 0x8412, 0x8210, 0x830a, 0xa189, - 0x0000, 0x2b60, 0x0078, 0x3013, 0x2b60, 0x8a07, 0xa7ba, 0x2f35, - 0xa73d, 0x2c00, 0x6882, 0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012, - 0x1078, 0x2f59, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x3047, - 0x6098, 0xa005, 0x0040, 0x3050, 0x2060, 0x2039, 0x2f35, 0x8a51, - 0x0040, 0x304f, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c, - 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, - 0x3060, 0x2039, 0x2f3b, 0x6000, 0xa064, 0x00c0, 0x3060, 0x2d60, - 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060, - 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, - 0xa0b8, 0x2f35, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, - 0x0040, 0x307c, 0xa6b5, 0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858, - 0x0f7f, 0xa084, 0x0040, 0x0040, 0x308b, 0xa684, 0x0001, 0x00c0, - 0x308b, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x308d, 0x7000, 0xa005, 0x0040, 0x3098, 0x1078, 0x1b81, - 0x2400, 0xa305, 0x00c0, 0x309e, 0x0078, 0x30db, 0x2c58, 0x2704, - 0xac60, 0x6004, 0xa400, 0x007e, 0x701a, 0x6000, 0xa301, 0x701e, - 0x2009, 0x04fd, 0x2104, 0xa086, 0x04fd, 0x007f, 0x00c0, 0x30cb, - 0xa084, 0x0001, 0x0040, 0x30cb, 0xa684, 0x0001, 0x00c0, 0x30cb, - 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x78b3, - 0x0001, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6004, 0xa400, 0x701a, - 0x6000, 0xa301, 0x701e, 0x620c, 0x2400, 0xa202, 0x7012, 0x6208, - 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, - 0x303b, 0x0078, 0x30dd, 0x1078, 0x316e, 0x00c0, 0x30db, 0x127f, - 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, - 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30e9, 0x7003, 0x0008, - 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, - 0x2049, 0x30f3, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, - 0x30fc, 0x7000, 0xa005, 0x0040, 0x3107, 0x1078, 0x1b81, 0x7e08, - 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3111, 0xa6b5, - 0x0001, 0x6824, 0xa005, 0x0040, 0x311d, 0x2050, 0x2039, 0x2f38, - 0x2d60, 0x1078, 0x316e, 0x00c0, 0x3119, 0x127f, 0x2000, 0x007c, - 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, - 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, - 0x3133, 0xa6b5, 0x0001, 0x2049, 0x3120, 0x6824, 0xa055, 0x0040, - 0x316b, 0x2d70, 0x2e60, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c, - 0xa422, 0x6808, 0xa31b, 0x0048, 0x3158, 0x8a51, 0x00c0, 0x314a, - 0x1078, 0x1b81, 0x8738, 0x2704, 0xa005, 0x00c0, 0x313e, 0x7098, - 0xa075, 0x2060, 0x0040, 0x316b, 0x2039, 0x2f35, 0x0078, 0x313d, - 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x690c, 0x2400, 0xa122, - 0x6908, 0x2300, 0xa11b, 0x00c8, 0x3167, 0x1078, 0x1b81, 0x2071, - 0x0020, 0x0078, 0x308b, 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, - 0x00c0, 0xa086, 0x00c0, 0x0040, 0x3196, 0x2704, 0xac08, 0x2104, - 0x701e, 0x8108, 0x2104, 0x701a, 0x8108, 0x2104, 0x7016, 0x8108, - 0x2104, 0x7012, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, - 0x0040, 0x0040, 0x3191, 0xa684, 0x0001, 0x00c0, 0x3191, 0xa6b5, - 0x0001, 0x7602, 0x7007, 0x0001, 0x1078, 0x303b, 0x007c, 0x127e, - 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x3197, 0x0d7f, 0x087f, - 0x7108, 0xa184, 0x00c0, 0x00c0, 0x31ad, 0x6824, 0xa005, 0x0040, - 0x31bd, 0x0078, 0x2ee1, 0x0078, 0x31bd, 0x7108, 0x8104, 0x00c8, - 0x31b5, 0x1078, 0x2fab, 0x0078, 0x31a0, 0x7007, 0x0010, 0x7108, - 0x8104, 0x00c8, 0x31b7, 0x1078, 0x2fab, 0x7008, 0xa086, 0x0002, - 0x00c0, 0x31a0, 0x7000, 0xa005, 0x00c0, 0x31a0, 0x7003, 0x0000, - 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, - 0x157e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x31cd, 0xad80, - 0x0010, 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x007f, 0x6826, - 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x31eb, - 0x8000, 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x31ed, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, - 0x147f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, - 0x2200, 0x0d7f, 0x2049, 0x31fc, 0x6880, 0x2060, 0x6884, 0x6b88, - 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f35, - 0x7e08, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, - 0x00c0, 0x3215, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, 0x701a, - 0x6000, 0xa301, 0x701e, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, - 0x7007, 0x0001, 0x007f, 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, - 0x322f, 0x7108, 0x7007, 0x0002, 0x810c, 0x00c8, 0x322f, 0x810c, - 0x0048, 0x323c, 0x0078, 0x2fed, 0xa4a0, 0x0001, 0xa399, 0x0000, - 0x6b8a, 0x6c8e, 0x7007, 0x0004, 0x2049, 0x0000, 0x7003, 0x0000, - 0x127f, 0x2000, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, - 0x818e, 0x00c8, 0x3254, 0xa200, 0x00f0, 0x324f, 0x8086, 0x818e, - 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x327a, 0xa11a, - 0x00c8, 0x327a, 0x8213, 0x818d, 0x0048, 0x326d, 0xa11a, 0x00c8, - 0x326e, 0x00f0, 0x3262, 0x0078, 0x3272, 0xa11a, 0x2308, 0x8210, - 0x00f0, 0x3262, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, - 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x3276, - 0x00e0, 0x32c2, 0x2091, 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, - 0x32bc, 0x7824, 0x7822, 0x2091, 0x8000, 0x2069, 0x3540, 0x6800, - 0xa084, 0x0007, 0x0040, 0x32a4, 0xa086, 0x0002, 0x0040, 0x32a4, - 0x6830, 0xa00d, 0x0040, 0x32a4, 0x2104, 0xa005, 0x0040, 0x32a4, - 0x8001, 0x200a, 0x0040, 0x3372, 0x2061, 0x3680, 0x20a9, 0x0080, - 0x6034, 0xa005, 0x0040, 0x32b6, 0x8001, 0x6036, 0x00c0, 0x32b6, - 0x6010, 0xa005, 0x0040, 0x32b6, 0x1078, 0x1a23, 0xace0, 0x0010, - 0x0070, 0x32bc, 0x0078, 0x32a8, 0x1078, 0x32d7, 0x1078, 0x32c5, - 0x1078, 0x32fc, 0x2091, 0x8001, 0x007c, 0x783c, 0x8001, 0x783e, - 0x00c0, 0x32d6, 0x7840, 0x783e, 0x7848, 0xa005, 0x0040, 0x32d6, - 0x8001, 0x784a, 0x00c0, 0x32d6, 0x1078, 0x1a23, 0x007c, 0x7834, - 0x8001, 0x7836, 0x00c0, 0x32fb, 0x7838, 0x7836, 0x2091, 0x8000, - 0x7844, 0xa005, 0x00c0, 0x32e6, 0x2001, 0x0101, 0x8001, 0x7846, - 0xa080, 0x3e80, 0x2040, 0x2004, 0xa065, 0x0040, 0x32fb, 0x6020, - 0xa005, 0x0040, 0x32f7, 0x8001, 0x6022, 0x0040, 0x332b, 0x6000, - 0x2c40, 0x0078, 0x32ec, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, - 0x332a, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x3309, 0x2001, - 0x0080, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, - 0x3680, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x332a, - 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x3322, 0x8001, 0x2012, - 0x00c0, 0x332a, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, - 0x1078, 0x1a23, 0x007c, 0x2069, 0x3540, 0x6800, 0xa005, 0x0040, - 0x3335, 0x683c, 0xac06, 0x0040, 0x3372, 0x6017, 0x0006, 0x60b0, - 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0060, - 0x601e, 0x6000, 0x2042, 0x6710, 0x6fb6, 0x1078, 0x169c, 0x6818, - 0xa005, 0x0040, 0x334d, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, - 0x680a, 0x6810, 0x8001, 0x00d0, 0x3357, 0x1078, 0x1b81, 0x6812, - 0x602f, 0x0000, 0x602b, 0x0000, 0x2c68, 0x1078, 0x17e7, 0x2069, - 0x3540, 0x2001, 0x0006, 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, - 0x336d, 0x69ba, 0x2001, 0x0004, 0x68a2, 0x1078, 0x1a1e, 0x2091, - 0x8001, 0x007c, 0x2009, 0x354f, 0x2164, 0x2069, 0x0100, 0x6017, - 0x0006, 0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, - 0xa085, 0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830, - 0xa084, 0x0040, 0x0040, 0x33ac, 0x684b, 0x0004, 0x20a9, 0x0014, - 0x6848, 0xa084, 0x0004, 0x0040, 0x3399, 0x0070, 0x3399, 0x0078, - 0x3390, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, - 0x0040, 0x33a6, 0x0070, 0x33a6, 0x0078, 0x339d, 0x20a9, 0x00fa, - 0x0070, 0x33ac, 0x0078, 0x33a8, 0x6808, 0xa084, 0xfffd, 0x680a, - 0x681b, 0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a, - 0x2091, 0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3404, 0x1078, - 0x33cc, 0x1078, 0x33e1, 0x1078, 0x33f6, 0x7833, 0x0000, 0x7847, - 0x0000, 0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546, - 0x2204, 0xa086, 0x0032, 0x0040, 0x33de, 0x2019, 0x000c, 0x2204, - 0xa086, 0x003c, 0x0040, 0x33de, 0x2019, 0x0008, 0x7b2a, 0x7b2e, - 0x007c, 0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032, - 0x0040, 0x33f3, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040, - 0x33f3, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, - 0x2011, 0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3401, 0x2019, - 0x000a, 0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546, - 0x2204, 0xa086, 0x0032, 0x0040, 0x3416, 0x2019, 0x3971, 0x2204, - 0xa086, 0x003c, 0x0040, 0x3416, 0x2019, 0x2626, 0x7b22, 0x7b26, - 0x007c, 0xda3e + 0x00d0, 0x3354, 0x1078, 0x1ba5, 0x6812, 0x602f, 0x0000, 0x602b, + 0x0000, 0x2c68, 0x1078, 0x17dd, 0x2069, 0x3540, 0x2001, 0x0006, + 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x336a, 0x69ba, 0x2001, + 0x0004, 0x68a2, 0x1078, 0x1a14, 0x2091, 0x8001, 0x007c, 0x2009, + 0x354f, 0x2164, 0x2069, 0x0100, 0x1078, 0x1b6b, 0x6017, 0x0006, + 0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, + 0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830, 0xa084, + 0x0040, 0x0040, 0x33ab, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, + 0xa084, 0x0004, 0x0040, 0x3398, 0x0070, 0x3398, 0x0078, 0x338f, + 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, + 0x33a5, 0x0070, 0x33a5, 0x0078, 0x339c, 0x20a9, 0x00fa, 0x0070, + 0x33ab, 0x0078, 0x33a7, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, + 0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091, + 0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3403, 0x1078, 0x33cb, + 0x1078, 0x33e0, 0x1078, 0x33f5, 0x7833, 0x0000, 0x7847, 0x0000, + 0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546, 0x2204, + 0xa086, 0x0032, 0x0040, 0x33dd, 0x2019, 0x000c, 0x2204, 0xa086, + 0x003c, 0x0040, 0x33dd, 0x2019, 0x0008, 0x7b2a, 0x7b2e, 0x007c, + 0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032, 0x0040, + 0x33f2, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040, 0x33f2, + 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, 0x2011, + 0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3400, 0x2019, 0x000a, + 0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546, 0x2204, + 0xa086, 0x0032, 0x0040, 0x3415, 0x2019, 0x3971, 0x2204, 0xa086, + 0x003c, 0x0040, 0x3415, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c, + 0x92a7 }; - -unsigned short sbus_risc_code_length01 = 0x241a; +unsigned short sbus_risc_code_length01 = 0x2419; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.3.34/linux/drivers/scsi/scsi.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/scsi.c Sun Dec 26 10:52:04 1999 @@ -1470,9 +1470,6 @@ */ - host->host_busy++; - device->device_busy++; - /* * Our own function scsi_done (which marks the host as not busy, disables * the timeout counter, etc) will be called by us or by the @@ -1575,6 +1572,9 @@ * Since serial_number is now 0, the error handler cound detect this * situation and avoid to call the the low level driver abort routine. * (DB) + * + * FIXME(eric) - I believe that this test is now redundant, due to + * the test of the return status of del_timer(). */ if (SCpnt->state == SCSI_STATE_TIMEOUT) { SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt)); @@ -2020,7 +2020,7 @@ spin_unlock_irqrestore(&device_request_lock, flags); } -static ssize_t proc_scsi_gen_write(struct file * file, const char * buf, +static int proc_scsi_gen_write(struct file * file, const char * buf, unsigned long length, void *data); #ifndef MODULE /* { */ @@ -2215,7 +2215,7 @@ return (len); } -static ssize_t proc_scsi_gen_write(struct file * file, const char * buf, +static int proc_scsi_gen_write(struct file * file, const char * buf, unsigned long length, void *data) { Scsi_Cmnd *SCpnt; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c --- v2.3.34/linux/drivers/scsi/scsi_error.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/scsi_error.c Sun Dec 26 10:52:04 1999 @@ -1778,6 +1778,17 @@ for (SCpnt = SCdone; SCpnt != NULL; SCpnt = SCdone) { SCdone = SCpnt->bh_next; SCpnt->bh_next = NULL; + /* + * Oh, this is a vile hack. scsi_done() expects a timer + * to be running on the command. If there isn't, it assumes + * that the command has actually timed out, and a timer + * handler is running. That may well be how we got into + * this fix, but right now things are stable. We add + * a timer back again so that we can report completion. + * scsi_done() will immediately remove said timer from + * the command, and then process it. + */ + scsi_add_timer(SCpnt, 100, scsi_eh_times_out); scsi_done(SCpnt); } @@ -1809,7 +1820,14 @@ int rtn; DECLARE_MUTEX_LOCKED(sem); + /* + * We only listen to signals if the HA was loaded as a module. + * If the HA was compiled into the kernel, then we don't listen + * to any signals. + */ + if( host->loaded_as_module ) { siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); + } lock_kernel(); @@ -1844,10 +1862,14 @@ * trying to unload a module. */ SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n")); + if( host->loaded_as_module ) { down_interruptible(&sem); if (signal_pending(current)) break; + } else { + down(&sem); + } SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n")); diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c --- v2.3.34/linux/drivers/scsi/scsi_lib.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/scsi_lib.c Sun Dec 26 10:52:05 1999 @@ -607,6 +607,22 @@ if (spnt->blk && spnt->major == major) { return spnt; } + /* + * I am still not entirely satisfied with this solution, + * but it is good enough for now. Disks have a number of + * major numbers associated with them, the primary + * 8, which we test above, and a secondary range of 7 + * different consecutive major numbers. If this ever + * becomes insufficient, then we could add another function + * to the structure, and generalize this completely. + */ + if( spnt->min_major != 0 + && spnt->max_major != 0 + && major >= spnt->min_major + && major <= spnt->max_major ) + { + return spnt; + } } return NULL; } @@ -742,11 +758,16 @@ if (!SCpnt) { break; } - SHpnt->host_busy++; - SDpnt->device_busy++; } /* + * Now bump the usage count for both the host and the + * device. + */ + SHpnt->host_busy++; + SDpnt->device_busy++; + + /* * FIXME(eric) * I am not sure where the best place to do this is. We need * to hook in a place where we are likely to come if in user @@ -821,12 +842,14 @@ * get those allocated here. */ if (!SDpnt->scsi_init_io_fn(SCpnt)) { + spin_lock_irq(&io_request_lock); continue; } /* * Initialize the actual SCSI command for this request. */ if (!STpnt->init_command(SCpnt)) { + spin_lock_irq(&io_request_lock); continue; } } diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c --- v2.3.34/linux/drivers/scsi/scsi_merge.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/scsi_merge.c Sun Dec 26 10:52:05 1999 @@ -290,6 +290,30 @@ count = bh->b_size >> 9; sector = bh->b_rsector; +#if CONFIG_HIGHMEM + /* + * This is a temporary hack for the time being. + * In some cases, the ll_rw_blk layer is creating + * bounce buffers for us - this implies that we don't + * need to down here, but queue management becomes quite + * difficult otherwise. When the ll_rw_blk layer gets + * cleaned up to handle bounce buffers better, then + * this hack can be cleaned up. + */ + if( sector == -1 ) + { + struct buffer_head * bh_new; + bh_new = (struct buffer_head *) bh->b_dev_id; + if( bh_new != NULL ) + { + sector = bh_new->b_rsector; + } + if( sector == -1 ) + { + panic("Unable to merge ambiguous block request"); + } + } +#endif /* * We come in here in one of two cases. The first is that we @@ -765,7 +789,8 @@ if( scsi_dma_free_sectors > 30 ) { for (this_count = 0, bh = SCpnt->request.bh; bh; bh = bh->b_reqnext) { - if( scsi_dma_free_sectors < 30 || this_count == sectors ) + if( scsi_dma_free_sectors - this_count < 30 + || this_count == sectors ) { break; } @@ -831,24 +856,11 @@ * We always force "_VALID" to 1. Eventually clean this up * and get rid of the extra argument. */ -#if 0 -/* Old definitions */ -INITIO(scsi_init_io_, 0, 0, 0) -INITIO(scsi_init_io_d, 0, 0, 1) -INITIO(scsi_init_io_c, 0, 1, 0) -INITIO(scsi_init_io_dc, 0, 1, 1) - -/* Newer redundant definitions. */ -INITIO(scsi_init_io_, 1, 0, 0) -INITIO(scsi_init_io_d, 1, 0, 1) -INITIO(scsi_init_io_c, 1, 1, 0) -INITIO(scsi_init_io_dc, 1, 1, 1) -#endif - INITIO(scsi_init_io_v, 1, 0, 0) INITIO(scsi_init_io_vd, 1, 0, 1) INITIO(scsi_init_io_vc, 1, 1, 0) INITIO(scsi_init_io_vdc, 1, 1, 1) + /* * Function: initialize_merge_fn() * @@ -881,21 +893,12 @@ * If this host has an unlimited tablesize, then don't bother with a * merge manager. The whole point of the operation is to make sure * that requests don't grow too large, and this host isn't picky. - */ - if (SHpnt->sg_tablesize == SG_ALL) { - if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) { - SDpnt->scsi_init_io_fn = scsi_init_io_v; - } else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) { - SDpnt->scsi_init_io_fn = scsi_init_io_vd; - } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) { - SDpnt->scsi_init_io_fn = scsi_init_io_vc; - } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) { - SDpnt->scsi_init_io_fn = scsi_init_io_vdc; - } - return; - } - /* - * Now pick out the correct function. + * + * Note that ll_rw_blk.c is effectively maintaining a segment + * count which is only valid if clustering is used, and it obviously + * doesn't handle the DMA case. In the end, it + * is simply easier to do it ourselves with our own functions + * rather than rely upon the default behavior of ll_rw_blk. */ if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) { q->merge_fn = scsi_merge_fn_; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c --- v2.3.34/linux/drivers/scsi/scsi_proc.c Tue Dec 7 09:32:46 1999 +++ linux/drivers/scsi/scsi_proc.c Mon Dec 20 22:05:10 1999 @@ -91,8 +91,8 @@ * use some slack for overruns */ -static ssize_t proc_scsi_write(struct file * file, const char * buf, - unsigned long count, void *data) +static int proc_scsi_write(struct file * file, const char * buf, + unsigned long count, void *data) { struct Scsi_Host *hpnt = data; ssize_t ret = 0; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.3.34/linux/drivers/scsi/sd.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/sd.c Sun Dec 26 10:52:05 1999 @@ -202,6 +202,11 @@ tag:"sd", scsi_type:TYPE_DISK, major:SCSI_DISK0_MAJOR, + /* + * Secondary range of majors that this driver handles. + */ + min_major:SCSI_DISK1_MAJOR, + max_major:SCSI_DISK7_MAJOR, blk:1, detect:sd_detect, init:sd_init, @@ -229,7 +234,7 @@ Scsi_Disk *dpnt; char nbuff[6]; - devm = MINOR(SCpnt->request.rq_dev); + devm = SD_PARTITION(SCpnt->request.rq_dev); dev = DEVICE_NR(SCpnt->request.rq_dev); block = SCpnt->request.sector; @@ -561,7 +566,7 @@ default: break; } - error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect; + error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect; error_sector &= ~(block_sectors - 1); good_sectors = error_sector - SCpnt->request.sector; if (good_sectors < 0 || good_sectors >= this_count) diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.3.34/linux/drivers/scsi/sg.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/sg.c Sun Dec 26 10:52:05 1999 @@ -101,10 +101,17 @@ static void sg_detach(Scsi_Device *); -struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff, - SCSI_GENERIC_MAJOR, 0, 0, 0, 0, - sg_detect, sg_init, - sg_finish, sg_attach, sg_detach}; +struct Scsi_Device_Template sg_template = +{ + tag:"sg", + scsi_type:0xff, + major:SCSI_GENERIC_MAJOR, + detect:sg_detect, + init:sg_init, + finish:sg_finish, + attach:sg_attach, + detach:sg_detach +}; typedef struct sg_scatter_hold /* holding area for scsi scatter gather info */ diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.3.34/linux/drivers/scsi/st.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/st.c Sun Dec 26 10:52:05 1999 @@ -11,7 +11,7 @@ Copyright 1992 - 1999 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Tue Oct 19 21:39:15 1999 by makisara@kai.makisara.local + Last modified: Thu Dec 16 23:08:29 1999 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 */ @@ -147,10 +147,16 @@ static void st_detach(Scsi_Device *); struct Scsi_Device_Template st_template = -{NULL, "tape", "st", NULL, TYPE_TAPE, - SCSI_TAPE_MAJOR, 0, 0, 0, 0, - st_detect, st_init, - NULL, st_attach, st_detach}; +{ + name:"tape", + tag:"st", + scsi_type:TYPE_TAPE, + major:SCSI_TAPE_MAJOR, + detect:st_detect, + init:st_init, + attach:st_attach, + detach:st_detach +}; static int st_compression(Scsi_Tape *, int); @@ -289,10 +295,14 @@ unsigned char *bp; if (SCpnt == NULL) - SCpnt = scsi_allocate_device(STp->device, 1, FALSE); + SCpnt = scsi_allocate_device(STp->device, 1, TRUE); if (SCpnt == NULL) { - printk(KERN_ERR "st%d: Can't get SCSI request.\n", - TAPE_NR(STp->devt)); + DEBC( printk(KERN_ERR "st%d: Can't get SCSI request.\n", + TAPE_NR(STp->devt)); ); + if (signal_pending(current)) + (STp->buffer)->last_result_fatal = (-EINTR); + else + (STp->buffer)->last_result_fatal = (-EBUSY); return NULL; } @@ -386,7 +396,7 @@ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; scsi_release_command(SCpnt); SCpnt = NULL; @@ -444,7 +454,7 @@ SCpnt = st_do_scsi(NULL, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; STps = &(STp->ps[STp->partition]); if ((STp->buffer)->last_result_fatal != 0) { @@ -656,7 +666,7 @@ __MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module); if (st_template.module) __MOD_DEC_USE_COUNT(st_template.module); - return (-EBUSY); + return (STp->buffer)->last_result_fatal; } if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 && @@ -905,8 +915,10 @@ SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_WRITE_RETRIES, TRUE); - if (!SCpnt) + if (!SCpnt) { + result = (STp->buffer)->last_result_fatal; goto out; + } if ((STp->buffer)->last_result_fatal != 0 && ((SCpnt->sense_buffer[0] & 0x70) != 0x70 || @@ -1184,7 +1196,7 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout, MAX_WRITE_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; if ((STp->buffer)->last_result_fatal != 0) { DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev)); @@ -1300,7 +1312,8 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, (STp->buffer)->writing, STp->timeout, MAX_WRITE_RETRIES, FALSE); if (SCpnt == NULL) - return (-EIO); + return (STp->buffer)->last_result_fatal; + } else if (SCpnt != NULL) { scsi_release_command(SCpnt); SCpnt = NULL; @@ -1360,7 +1373,7 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, STp->timeout, MAX_RETRIES, TRUE); *aSCpnt = SCpnt; if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; (STp->buffer)->read_pointer = 0; STps->at_sm = 0; @@ -1838,7 +1851,8 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE); if (SCpnt == NULL) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; + dev = TAPE_NR(SCpnt->request.rq_dev); if ((STp->buffer)->last_result_fatal != 0) { @@ -2210,7 +2224,7 @@ SCpnt = st_do_scsi(NULL, STp, cmd, datalen, timeout, MAX_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; ioctl_result = (STp->buffer)->last_result_fatal; @@ -2372,7 +2386,7 @@ } SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; if ((STp->buffer)->last_result_fatal != 0 || (STp->device->scsi_level >= SCSI_2 && @@ -2478,7 +2492,7 @@ SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES, TRUE); if (!SCpnt) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; STps->drv_block = STps->drv_file = (-1); STps->eof = ST_NOEOF; @@ -2569,7 +2583,8 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, STp->timeout, MAX_READY_RETRIES, TRUE); if (SCpnt == NULL) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; + scsi_release_command(SCpnt); SCpnt = NULL; @@ -2633,7 +2648,8 @@ SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout, MAX_READY_RETRIES, TRUE); if (SCpnt == NULL) - return (-EBUSY); + return (STp->buffer)->last_result_fatal; + scsi_release_command(SCpnt); SCpnt = NULL; diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.3.34/linux/drivers/scsi/sym53c8xx.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/sym53c8xx.c Mon Dec 20 22:06:42 1999 @@ -679,10 +679,8 @@ #endif #ifdef __sparc__ -#include -# define ioremap(base, size) ((u_long) __va(base)) -# define iounmap(vaddr) -# define pcivtobus(p) ((p) & pci_dvma_mask) +# include +# define pcivtobus(p) bus_dvma_to_mem(p) # define memcpy_to_pci(a, b, c) memcpy_toio((a), (b), (c)) #elif defined(__alpha__) # define pcivtobus(p) ((p) & 0xfffffffful) @@ -11882,11 +11880,10 @@ /* ** Fix-ups for sparc. */ - base = __pa(base); - base_2 = __pa(base_2); - if (!cache_line_size) suggested_cache_line_size = 16; + + driver_setup.pci_fix_up |= 0x7; #endif /* __sparc__ */ #if defined(__i386__) && !defined(MODULE) diff -u --recursive --new-file v2.3.34/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.3.34/linux/drivers/sound/Config.in Tue Dec 7 09:32:46 1999 +++ linux/drivers/sound/Config.in Sun Dec 26 19:34:04 1999 @@ -20,9 +20,7 @@ dep_tristate ' Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND dep_tristate ' Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND dep_tristate ' ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO $CONFIG_SOUND -fi +dep_tristate ' ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND dep_tristate ' S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND if [ "$CONFIG_VISWS" = "y" ]; then dep_tristate ' SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND diff -u --recursive --new-file v2.3.34/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.3.34/linux/drivers/sound/maestro.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/sound/maestro.c Sun Dec 26 19:34:04 1999 @@ -1,6 +1,6 @@ /***************************************************************************** * - * ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.2.x + * ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.[23].x * * 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 @@ -28,25 +28,25 @@ * proprietors of Hack Central for fine lodging. * * Supported devices: - * /dev/dsp0-7 standard /dev/dsp device, (mostly) OSS compatible + * /dev/dsp0-3 standard /dev/dsp device, (mostly) OSS compatible * /dev/mixer standard /dev/mixer device, (mostly) OSS compatible * * Hardware Description * * A working Maestro setup contains the Maestro chip wired to a - * codec or 2. In the Maestro we have the APUs, the ASP, and the + * codec or 2. In the Maestro we have the APUs, the ASSP, and the * Wavecache. The APUs can be though of as virtual audio routing * channels. They can take data from a number of sources and perform * basic encodings of the data. The wavecache is a storehouse for * PCM data. Typically it deals with PCI and interracts with the - * APUs. The ASP is a wacky DSP like device that ESS is loth + * APUs. The ASSP is a wacky DSP like device that ESS is loth * to release docs on. Thankfully it isn't required on the Maestro * until you start doing insane things like FM emulation and surround * encoding. The codecs are almost always AC-97 compliant codecs, * but it appears that early Maestros may have had PT101 (an ESS * part?) wired to them. The only real difference in the Maestro * families is external goop like docking capability, memory for - * the ASP, and initialization differences. + * the ASSP, and initialization differences. * * Driver Operation * @@ -55,25 +55,19 @@ * /dev/dsp? device. 2 channels for output, and 4 channels for * input. * - * For output we maintain a ring buffer of data that we are DMAing - * to the card. In mono operation this is nice and easy. When - * we receive data we tack it onto the ring buffer and make sure - * the APU assigned to it is playing over the data. When we fill - * the ring buffer we put the client to sleep until there is - * room again. Easy. + * Each APU can do a number of things, but we only really use + * 3 basic functions. For playback we use them to convert PCM + * data fetched over PCI by the wavecahche into analog data that + * is handed to the codec. One APU for mono, and a pair for stereo. + * When in stereo, the combination of smarts in the APU and Wavecache + * decide which wavecache gets the left or right channel. * - * However, this starts to stink when we use stereo. The APUs - * supposedly can decode LRLR packed stereo data, but it - * doesn't work. So we're forced to use dual mono APUs walking over - * mono encoded data. This requires us to split the input from - * the client and complicates the buffer maths tremendously. Ick. - * - * This also pollutes the recording paths as well. We have to use - * 2 L/R incoming APUs that are fixed at 16bit/48khz. We then pipe - * these through 2 rate converion apus that mix them down to the - * requested frequency and write them to memory through the wavecache. - * We also apparently need a 512byte region thats used as temp space - * between the incoming APUs and the rate converters. + * For record we still use the old overly mono system. For each in + * coming channel the data comes in from the codec, through a 'input' + * APU, through another rate converter APU, and then into memory via + * the wavecache and PCI. If its stereo, we mash it back into LRLR in + * software. The pass between the 2 APUs is supposedly what requires us + * to have a 512 byte buffer sitting around in wavecache/memory. * * The wavecache makes our life even more fun. First off, it can * only address the first 28 bits of PCI address space, making it @@ -113,9 +107,19 @@ * similar. * * History + * v0.13 - Nov 18 1999 - Zach Brown + * fix nec Versas? man would that be cool. + * v0.12 - Nov 12 1999 - Zach Brown + * brown bag volume max fix.. + * v0.11 - Nov 11 1999 - Zach Brown + * use proper stereo apu decoding, mmap/write should work. + * make volume sliders more useful, tweak rate calculation. + * fix lame 8bit format reporting bug. duh. apm apu saving buglet also + * fix maestro 1 clock freq "bug", remove pt101 support * v0.10 - Oct 28 1999 - Zach Brown * aha, so, sometimes the WP writes a status word to offset 0 * from one of the PCMBARs. rearrange allocation accordingly.. + * cheers again to Eric for being a good hacker in investigating this. * Jeroen Hoogervorst submits 7500 fix out of nowhere. yay. :) * v0.09 - Oct 23 1999 - Zach Brown * added APM support. @@ -159,16 +163,12 @@ * * TODO * some people get indir reg timeouts? - * anyone have a pt101 codec? - * mmap(), but beware stereo encoding nastiness. - * actually post pci writes * fix bob frequency + * endianness * do smart things with ac97 2.0 bits. - * ugh.. non aligned writes in the middle of a data stream.. ugh - * sort out 0x34->0x36 crap in init * docking and dual codecs and 978? - * pcm_sync? - * actually use LRLR + * leave 54->61 open + * resolve 2.3/2.2 stuff * * it also would be fun to have a mode that would not use pci dma at all * but would copy into the wavecache on board memory and use that @@ -189,12 +189,14 @@ #define SILLY_INIT_SEM(SEM) SEM=MUTEX; #define init_waitqueue_head init_waitqueue #define SILLY_MAKE_INIT(FUNC) __initfunc(FUNC) + #define SILLY_OFFSET(VMA) ((VMA)->vm_offset) #else #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->resource[0].start) #define SILLY_INIT_SEM(SEM) init_MUTEX(&SEM) #define SILLY_MAKE_INIT(FUNC) __init FUNC + #define SILLY_OFFSET(VMA) ((VMA)->vm_pgoff) #endif @@ -241,7 +243,7 @@ #endif /* --------------------------------------------------------------------- */ -#define DRIVER_VERSION "0.10" +#define DRIVER_VERSION "0.13" #ifndef PCI_VENDOR_ESS #define PCI_VENDOR_ESS 0x125D @@ -256,6 +258,10 @@ #define ESS_CHAN_HARD 0x100 +/* NEC Versas ? */ +#define NEC_VERSA_SUBID1 0x80581033 +#define NEC_VERSA_SUBID2 0x803c1033 + /* changed so that I could actually find all the references and fix them up. its a little more readable now. */ @@ -271,8 +277,8 @@ #define DAC_RUNNING 1 #define ADC_RUNNING 2 -#define MAX_DSP_ORDER 3 -#define MAX_DSPS (1<<3) +#define MAX_DSP_ORDER 2 +#define MAX_DSPS (1< log */ +unsigned char lin2log[101] = +{ +0, 0 , 15 , 23 , 30 , 34 , 38 , 42 , 45 , 47 , +50 , 52 , 53 , 55 , 57 , 58 , 60 , 61 , 62 , +63 , 65 , 66 , 67 , 68 , 69 , 69 , 70 , 71 , +72 , 73 , 73 , 74 , 75 , 75 , 76 , 77 , 77 , +78 , 78 , 79 , 80 , 80 , 81 , 81 , 82 , 82 , +83 , 83 , 84 , 84 , 84 , 85 , 85 , 86 , 86 , +87 , 87 , 87 , 88 , 88 , 88 , 89 , 89 , 89 , +90 , 90 , 90 , 91 , 91 , 91 , 92 , 92 , 92 , +93 , 93 , 93 , 94 , 94 , 94 , 94 , 95 , 95 , +95 , 95 , 96 , 96 , 96 , 96 , 97 , 97 , 97 , +97 , 98 , 98 , 98 , 98 , 99 , 99 , 99 , 99 , 99 +}; + static void ac97_write_mixer(struct ess_card *card,int mixer, unsigned int left, unsigned int right) { u16 val=0; @@ -614,12 +642,13 @@ right = (right * mh->scale) / 100; left = (left * mh->scale) / 100; if ((left == 0) && (right == 0)) - val |= 0x8000; - } else { - right = ((100 - right) * mh->scale) / 100; - left = ((100 - left) * mh->scale) / 100; - if((left == mh->scale) && (right == mh->scale)) val |= 0x8000; + } else { + /* log conversion for the stereo controls */ + if((left == 0) && (right == 0)) + val = 0x8000; + right = ((100 - lin2log[right]) * mh->scale) / 100; + left = ((100 - lin2log[left]) * mh->scale) / 100; } val |= (left << 8) | right; @@ -772,6 +801,8 @@ return 0; } +#if 0 /* there has been 1 person on the planet with a pt101 that we + know of. If they care, they can put this back in :) */ static u16 maestro_pt101_init(struct ess_card *card,int iobase) { printk(KERN_INFO "maestro: PT101 Codec detected, initializing but _not_ installing mixer device.\n"); @@ -792,6 +823,7 @@ maestro_ac97_set(iobase, 0x0E, 0x801F); return 0; } +#endif /* this is very magic, and very slow.. */ static void @@ -799,6 +831,7 @@ { u16 save_68; u16 w; + u32 vend; outw( inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); outw( inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); @@ -808,6 +841,7 @@ outw(0x0000, ioaddr+0x36); save_68 = inw(ioaddr+0x68); pci_read_config_word(pcidev, 0x58, &w); /* something magical with gpio and bus arb. */ + pci_read_config_dword(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &vend); if( w & 0x1) save_68 |= 0x10; outw(0xfffe, ioaddr + 0x64); /* tickly gpio 0.. */ @@ -861,6 +895,12 @@ } } #endif + if ( vend == NEC_VERSA_SUBID1 || vend == NEC_VERSA_SUBID2) { + /* turn on external amp? */ + outw(0xf9ff, ioaddr + 0x64); + outw(inw(ioaddr+0x68) | 0x600, ioaddr + 0x68); + outw(0x0209, ioaddr + 0x60); + } } /* * Indirect register access. Not all registers are readable so we @@ -1065,13 +1105,12 @@ /* sets the play formats of these apus, should be passed the already shifted format */ static void set_apu_fmt(struct ess_state *s, int apu, int mode) { - if(mode&ESS_FMT_16BIT) { - s->apu_mode[apu] = 0x10; - s->apu_mode[apu+1] = 0x10; - } else { - s->apu_mode[apu] = 0x30; - s->apu_mode[apu+1] = 0x30; - } + int apu_fmt = 0x10; + + if(!(mode&ESS_FMT_16BIT)) apu_fmt+=0x20; + if((mode&ESS_FMT_STEREO)) apu_fmt+=0x10; + s->apu_mode[apu] = apu_fmt; + s->apu_mode[apu+1] = apu_fmt; } /* this only fixes the output apu mode to be later set by start_dac and @@ -1082,18 +1121,21 @@ set_apu_fmt(s, 0, (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK); } -static u16 compute_rate(u32 freq) +/* this is off by a little bit.. */ +static u32 compute_rate(struct ess_state *s, u32 freq) { - if(freq==48000) - return 0xFFFF; - freq<<=16; - freq/=48000; - return freq; + u32 clock = clock_freq[s->card->card_type]; + + if (freq == 48000) return 0x10000; + + return ((freq / clock) <<16 )+ + (((freq % clock) << 16) / clock); } -static void set_dac_rate(struct ess_state *s, unsigned rate) +static void set_dac_rate(struct ess_state *s, unsigned int rate) { u32 freq; + int fmt = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK; if (rate > 48000) rate = 48000; @@ -1102,12 +1144,12 @@ s->ratedac = rate; - if(!((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT)) - rate >>= 1; /* who knows */ + if(! (fmt & ESS_FMT_16BIT) && !(fmt & ESS_FMT_STEREO)) + rate >>= 1; /* M_printk("computing dac rate %d with mode %d\n",rate,s->fmt);*/ - freq = compute_rate(rate); + freq = compute_rate(s, rate); /* Load the frequency, turn on 6dB */ apu_set_register(s, 0, 2,(apu_get_register(s, 0, 2)&0x00FF)| @@ -1122,14 +1164,15 @@ { u32 freq; - if (rate > 48000) - rate = 48000; + /* Sample Rate conversion APUs don't like 0x10000 for their rate */ + if (rate > 47999) + rate = 47999; if (rate < 4000) rate = 4000; s->rateadc = rate; - freq = compute_rate(rate); + freq = compute_rate(s, rate); /* Load the frequency, turn on 6dB */ apu_set_register(s, 2, 2,(apu_get_register(s, 2, 2)&0x00FF)| @@ -1234,27 +1277,21 @@ /* all maestro sizes are in 16bit words */ size >>=1; - /* we're given the full size of the buffer, but - in stereo each channel will only play its half */ if(mode&ESS_FMT_STEREO) { - size >>=1; high_apu++; + /* only 16/stereo gets size divided */ + if(mode&ESS_FMT_16BIT) + size>>=1; } for(channel=0; channel <= high_apu; channel++) { - int i; - - if(!channel) - pa = virt_to_bus(buffer); - else - /* right channel plays its split half. - *2 accomodates for rampant shifting earlier */ - pa = virt_to_bus(buffer + size*2); + pa = virt_to_bus(buffer); /* set the wavecache control reg */ tmpval = (pa - 0x10) & 0xFFF8; - if(!(mode & 2)) tmpval |= 4; /* 8bit */ + if(!(mode & ESS_FMT_16BIT)) tmpval |= 4; + if(mode & ESS_FMT_STEREO) tmpval |= 2; ess->apu_base[channel]=tmpval; wave_set_register(ess, ess->apu[channel]<<3, tmpval); @@ -1262,14 +1299,17 @@ pa>>=1; /* words */ /* base offset of dma calcs when reading the pointer - on this left one */ + on the left one */ if(!channel) ess->dma_dac.base = pa&0xFFFF; pa|=0x00400000; /* System RAM */ - - /* Begin loading the APU */ - for(i=0;i<15;i++) /* clear all PBRs */ - apu_set_register(ess, channel, i, 0x0000); + + /* XXX the 16bit here might not be needed.. */ + if((mode & ESS_FMT_STEREO) && (mode & ESS_FMT_16BIT)) { + if(channel) + pa|=0x00800000; /* Stereo */ + pa>>=1; + } /* XXX think about endianess when writing these registers */ M_printk("maestro: ess_play_setup: APU[%d] pa = 0x%x\n", ess->apu[channel], pa); @@ -1290,16 +1330,17 @@ /* dma on, no envelopes, filter to all 1s) */ apu_set_register(ess, channel, 0, 0x400F); - if(mode&ESS_FMT_STEREO) - /* set panning: left or right */ - apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0)); - else - apu_set_register(ess, channel, 10, 0x8F08); - if(mode&ESS_FMT_16BIT) ess->apu_mode[channel]=0x10; else ess->apu_mode[channel]=0x30; + + if(mode&ESS_FMT_STEREO) { + /* set panning: left or right */ + apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0)); + ess->apu_mode[channel] += 0x10; + } else + apu_set_register(ess, channel, 10, 0x8F08); } /* clear WP interupts */ @@ -1660,29 +1701,20 @@ clear_advance(struct ess_state *s) { unsigned char c = ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT) ? 0 : 0x80; + unsigned char *buf = s->dma_dac.rawbuf; unsigned bsize = s->dma_dac.dmasize; - /* swptr is always in bytes as read from an apu.. */ unsigned bptr = s->dma_dac.swptr; unsigned len = s->dma_dac.fragsize; - int i=1; - - if((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_STEREO) { - i++; - bsize >>=1; - } - - for ( ;i; i-- , buf += bsize) { - - if (bptr + len > bsize) { - unsigned x = bsize - bptr; - memset(buf + bptr, c, x); - /* account for wrapping? */ - bptr = 0; - len -= x; - } - memset(buf + bptr, c, len); + + if (bptr + len > bsize) { + unsigned x = bsize - bptr; + memset(buf + bptr, c, x); + /* account for wrapping? */ + bptr = 0; + len -= x; } + memset(buf + bptr, c, len); } /* call with spinlock held! */ @@ -1725,8 +1757,13 @@ } /* update DAC pointer */ if (s->dma_dac.ready) { - /* this is so gross. */ - hwptr = (/*s->dma_dac.dmasize -*/ get_dmaa(s)) % s->dma_dac.dmasize; + hwptr = get_dmaa(s) % s->dma_dac.dmasize; + /* the apu only reports the length it has seen, not the + length of the memory that has been used (the WP + knows that */ + if ( ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK) == (ESS_FMT_STEREO|ESS_FMT_16BIT)) + hwptr<<=1; + diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; /* M_printk("updating dac: hwptr: %d diff: %d\n",hwptr,diff);*/ s->dma_dac.hwptr = hwptr; @@ -2190,42 +2227,6 @@ return ret; } -/* god this is gross..*/ -/* again, the mode passed is shifted/masked */ -static int -split_stereo(unsigned char *real_buffer,unsigned char *tmp_buffer, int offset, - int count, int bufsize, int mode) -{ - /* oh, bother. stereo decoding APU's don't work in 16bit so we - use dual linear decoders. which means we have to hack up stereo - buffer's we're given. yuck. */ - - unsigned char *so,*left,*right; - int i; - - so = tmp_buffer; - left = real_buffer + offset; - right = real_buffer + bufsize/2 + offset; - - if(mode & ESS_FMT_16BIT) { - for(i=count/4; i ; i--) { - *(right++) = (*(so+2)); - *(right++) = (*(so+3)); - *(left++) = (*so); - *(left++) = (*(so+1)); - so+=4; - } - } else { - for(i=count/2; i ; i--) { - *(right++) = (*(so+1)); - *(left++) = (*so); - so+=2; - } - } - - return 0; -} - static ssize_t ess_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { @@ -2233,9 +2234,7 @@ ssize_t ret; unsigned long flags; unsigned swptr; - unsigned char *splitbuf = NULL; int cnt; - int mode = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK; VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -2246,9 +2245,6 @@ return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; - /* XXX be more clever than this.. */ - if (!(splitbuf = kmalloc(count,GFP_KERNEL))) - return -ENOMEM; ret = 0; calc_bob_rate(s); @@ -2262,12 +2258,8 @@ } swptr = s->dma_dac.swptr; - if(mode & ESS_FMT_STEREO) { - /* in stereo we have the 'dual' buffers.. */ - cnt = ((s->dma_dac.dmasize/2)-swptr)*2; - } else { - cnt = s->dma_dac.dmasize-swptr; - } + cnt = s->dma_dac.dmasize-swptr; + if (s->dma_dac.count + cnt > s->dma_dac.dmasize) cnt = s->dma_dac.dmasize - s->dma_dac.count; @@ -2276,10 +2268,6 @@ if (cnt > count) cnt = count; - /* our goofball stereo splitter can only deal in mults of 4 */ - if (cnt > 0) - cnt &= ~3; - if (cnt <= 0) { start_dac(s); if (file->f_flags & O_NONBLOCK) { @@ -2309,26 +2297,13 @@ } continue; } - if(mode & ESS_FMT_STEREO) { - if (copy_from_user(splitbuf, buffer, cnt)) { - if (!ret) ret = -EFAULT; - goto return_free; - } - split_stereo(s->dma_dac.rawbuf,splitbuf,swptr,cnt,s->dma_dac.dmasize, - mode); - } else { - if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) { - if (!ret) ret = -EFAULT; - goto return_free; - } + if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) { + if (!ret) ret = -EFAULT; + goto return_free; } - if(mode & ESS_FMT_STEREO) { - /* again with the weird pointer magic */ - swptr = (swptr + (cnt/2)) % (s->dma_dac.dmasize/2); - } else { - swptr = (swptr + cnt) % s->dma_dac.dmasize; - } + swptr = (swptr + cnt) % s->dma_dac.dmasize; + spin_lock_irqsave(&s->lock, flags); s->dma_dac.swptr = swptr; s->dma_dac.count += cnt; @@ -2340,7 +2315,6 @@ start_dac(s); } return_free: - if (splitbuf) kfree(splitbuf); return ret; } @@ -2374,8 +2348,6 @@ return mask; } -/* this needs to be fixed to deal with the dual apus/buffers */ -#if 0 static int ess_mmap(struct file *file, struct vm_area_struct *vma) { struct ess_state *s = (struct ess_state *)file->private_data; @@ -2388,13 +2360,18 @@ if ((ret = prog_dmabuf(s, 1)) != 0) return ret; db = &s->dma_dac; - } else if (vma->vm_flags & VM_READ) { + } else +#if 0 + /* if we can have the wp/wc do the combining + we can turn this back on. */ + if (vma->vm_flags & VM_READ) { if ((ret = prog_dmabuf(s, 0)) != 0) return ret; db = &s->dma_adc; - } else + } else +#endif return -EINVAL; - if (vma->vm_pgofft != 0) + if (SILLY_OFFSET(vma) != 0) return -EINVAL; size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << db->buforder)) @@ -2404,7 +2381,6 @@ db->mapped = 1; return 0; } -#endif static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2434,7 +2410,7 @@ return 0; case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER /*| DSP_CAP_MMAP*/, (int *)arg); + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); case SNDCTL_DSP_RESET: if (file->f_mode & FMODE_WRITE) { @@ -2515,7 +2491,7 @@ : (ESS_FMT_STEREO << ESS_DAC_SHIFT))) ? 2 : 1, (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask */ - return put_user(AFMT_S8|AFMT_S16_LE, (int *)arg); + return put_user(AFMT_U8|AFMT_S16_LE, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ get_user_ret(val, (int *)arg, -EFAULT); @@ -2548,7 +2524,7 @@ (ESS_FMT_16BIT << ESS_ADC_SHIFT) : (ESS_FMT_16BIT << ESS_DAC_SHIFT))) ? AFMT_S16_LE : - AFMT_S8, + AFMT_U8, (int *)arg); case SNDCTL_DSP_POST: @@ -2938,7 +2914,7 @@ NULL, /* readdir */ &ess_poll, &ess_ioctl, - NULL, /* XXX &ess_mmap, */ + &ess_mmap, &ess_open, NULL, /* flush */ &ess_release, @@ -3000,7 +2976,7 @@ w&=~(1<<7); /* HWV off */ w&=~(1<<6); /* Debounce off */ w&=~(1<<5); /* GPIO 4:5 */ - w|= (1<<4); /* Disconnect from the CHI. Enabling this in made a dell 7500 work. */ + w|= (1<<4); /* Disconnect from the CHI. Enabling this made a dell 7500 work. */ w&=~(1<<3); /* IDMA off (undocumented) */ w&=~(1<<2); /* MIDI fix off (undoc) */ w&=~(1<<1); /* reserved, always write 0 */ @@ -3303,7 +3279,8 @@ maestro_config(card); if(maestro_ac97_get(iobase, 0x00)==0x0080) { - maestro_pt101_init(card,iobase); + printk(KERN_ERR "maestro: my goodness! you seem to have a pt101 codec, which is quite rare.\n" + "\tyou should tell someone about this.\n"); } else { maestro_ac97_init(card,iobase); } @@ -3451,7 +3428,7 @@ } static int -maestro_apm_suspend(void) +maestro_suspend(void) { struct ess_card *card; unsigned long flags; @@ -3474,7 +3451,7 @@ stop_dac(s); stop_adc(s); for(j=0;j<6;j++) - card->apu_map[s->apu[i]][5]=apu_get_register(s,i,5); + card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5); } @@ -3491,7 +3468,7 @@ return 0; } static int -maestro_apm_resume(void) +maestro_resume(void) { struct ess_card *card; unsigned long flags; @@ -3565,11 +3542,11 @@ case APM_SYS_SUSPEND: case APM_CRITICAL_SUSPEND: case APM_USER_SUSPEND: - maestro_apm_suspend();break; + maestro_suspend();break; case APM_NORMAL_RESUME: case APM_CRITICAL_RESUME: case APM_STANDBY_RESUME: - maestro_apm_resume();break; + maestro_resume();break; default: break; } diff -u --recursive --new-file v2.3.34/linux/drivers/usb/.indent.pro linux/drivers/usb/.indent.pro --- v2.3.34/linux/drivers/usb/.indent.pro Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/.indent.pro Wed Dec 31 16:00:00 1969 @@ -1 +0,0 @@ --i8 -br -nce -npsl diff -u --recursive --new-file v2.3.34/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.34/linux/drivers/usb/Config.in Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/Config.in Mon Dec 27 14:01:53 1999 @@ -7,32 +7,32 @@ tristate 'Support for USB' CONFIG_USB if [ ! "$CONFIG_USB" = "n" ]; then comment 'USB Controllers' - dep_tristate ' UHCI (Intel PIIX4 and others) support' CONFIG_USB_UHCI \ + dep_tristate ' UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI \ $CONFIG_USB - dep_tristate ' OHCI-HCD (compaq and some others) support' \ + dep_tristate ' OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support' \ CONFIG_USB_OHCI_HCD $CONFIG_USB comment 'Miscellaneous USB options' if [ "$CONFIG_PROC_FS" != "n" ]; then bool ' /proc/bus/usb support' CONFIG_USB_PROC fi - dep_tristate ' EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB comment 'USB Devices' - dep_tristate ' USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB - dep_tristate ' USB HP scanner support' CONFIG_USB_HP_SCANNER $CONFIG_USB dep_tristate ' USB keyboard support' CONFIG_USB_KBD $CONFIG_USB + dep_tristate ' USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB + dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB + dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB dep_tristate ' USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB - dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB - dep_tristate ' USB Belkin and Peracom serial support' CONFIG_USB_SERIAL $CONFIG_USB + dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB dep_tristate ' USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB - dep_tristate ' USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB + dep_tristate ' USB SCSI (mass storage) support' CONFIG_USB_SCSI $CONFIG_USB if [ "$CONFIG_USB_SCSI" != "n" ]; then bool ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG fi + dep_tristate ' EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB fi diff -u --recursive --new-file v2.3.34/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.3.34/linux/drivers/usb/Makefile Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/Makefile Mon Dec 27 14:02:31 1999 @@ -53,15 +53,13 @@ endif ifeq ($(CONFIG_USB_MOUSE),m) M_OBJS += mouse.o - MI_OBJS += mouse.o endif -ifeq ($(CONFIG_USB_HP_SCANNER),y) - L_OBJS += hp_scanner.o +ifeq ($(CONFIG_USB_SCANNER),y) + L_OBJS += scanner.o endif -ifeq ($(CONFIG_USB_HP_SCANNER),m) - M_OBJS +=hp_scanner.o - MI_OBJS +=hp_scanner.o +ifeq ($(CONFIG_USB_SCANNER),m) + M_OBJS +=scanner.o endif ifeq ($(CONFIG_USB_ACM),y) @@ -69,7 +67,6 @@ endif ifeq ($(CONFIG_USB_ACM),m) M_OBJS += acm.o - MI_OBJS += acm.o endif ifeq ($(CONFIG_USB_PRINTER),y) @@ -78,7 +75,6 @@ ifeq ($(CONFIG_USB_PRINTER),m) M_OBJS += printer.o - MI_OBJS += printer.o endif ifeq ($(CONFIG_USB_SERIAL),y) @@ -87,7 +83,6 @@ ifeq ($(CONFIG_USB_SERIAL),m) M_OBJS += usb-serial.o - MI_OBJS += usb-serial.o endif ifneq ($(CONFIG_ADB_KEYBOARD),y) @@ -111,7 +106,6 @@ ifeq ($(CONFIG_USB_AUDIO),m) M_OBJS += audio.o - MI_OBJS += audio.o endif ifeq ($(CONFIG_USB_CPIA),y) @@ -120,7 +114,6 @@ ifeq ($(CONFIG_USB_CPIA),m) M_OBJS += cpia.o - MI_OBJS += cpia.o endif ifeq ($(CONFIG_USB_DC2XX),y) @@ -128,7 +121,6 @@ endif ifeq ($(CONFIG_USB_DC2XX),m) M_OBJS += dc2xx.o - MI_OBJS += dc2xx.o endif ifeq ($(CONFIG_USB_SCSI),y) @@ -152,7 +144,6 @@ ifeq ($(CONFIG_USB_EZUSB),m) M_OBJS += ezusb.o - MI_OBJS += ezusb.o endif ifeq ($(CONFIG_USB_USS720),y) @@ -161,7 +152,6 @@ ifeq ($(CONFIG_USB_USS720),m) M_OBJS += uss720.o - MI_OBJS += uss720.o endif ifeq ($(CONFIG_USB_DABUSB),y) @@ -170,7 +160,6 @@ ifeq ($(CONFIG_USB_DABUSB),m) M_OBJS += dabusb.o - MI_OBJS += dabusb.o endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.hp_scanner linux/drivers/usb/README.hp_scanner --- v2.3.34/linux/drivers/usb/README.hp_scanner Tue Sep 7 12:14:07 1999 +++ linux/drivers/usb/README.hp_scanner Wed Dec 31 16:00:00 1969 @@ -1,59 +0,0 @@ -August 30, 1999 - - -Overview - -This README will address issues regarding how to configure the kernel -to access a USB HP Scanner. The scanner should support the Scanner -Control Language (SCL) so that applications such as SANE can access it -properly. Refer to the document README.hp_scanner_sane for guidance -on how to configure SANE to use the USB HP Scanner. - - -Requirements - -A host with a USB port. Ideally, either a UHCI (Intel) or OHCI -(Compaq and others) hardware port should work. However, I've only -been able to really use an OHCI controller. I did have access to a -system with a UHCI controller but some very limited testing did not -produce satisfactory results. - -A Linux kernel with USB support (preferably 2.3.15+). - -A Linux kernel with USB HP Scanner support. - - -Configuration - -Add both USB controller support and USB HP Scanner support using `make -menuconfig`. If you decide to use the ohci-hcd driver, don't forget -to add HUB support. Compile and install the modules. Testing was -performed only as modules, YMMV. - -Add a device for the USB scanner: `mknod /dev/usbscanner c 16 1` - -Set appropriate permissions for /dev/usbscanner. Both read and write -permissions are needed for proper operation. - -Load the appropriate modules: - - OHCI: - - modprobe usb-ohci - modprobe hp_scanner - - OHCI-HCD: - modprobe usb-ohci-hcd - modprobe hub - modprobe hp_scanner - -That's it. SANE should now be able to access the device. - -There is a small test program (hp_scan.c) that can be used to test the -scanner device. It's purpose is to test the driver(s) without having -to retrieve/configure SANE. Hp_scan.c will scan the entire bed and -put the output into a file called out.dat in the current directory. -The data in the file is raw data. - -David /\/elson -dnelson@jump.net diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.hp_scanner_sane linux/drivers/usb/README.hp_scanner_sane --- v2.3.34/linux/drivers/usb/README.hp_scanner_sane Tue Sep 7 12:14:07 1999 +++ linux/drivers/usb/README.hp_scanner_sane Wed Dec 31 16:00:00 1969 @@ -1,67 +0,0 @@ -August 30, 1999 - -NOTE: This is all VERY alpha. Use at your own risk. There is no -warranty expressed nor implied. - - -Introduction - -This document will hopefully provide enough info on how to get SANE -working with a Hewlett Packard USB capable scanner using the USB -interface. The majority of HP Scanners support the Scanner Control -Language (SCL) which is both published by HP and supported by SANE. -The only HP Scanner that I'm aware of that does not support SCL is the -4200C. All other HP scanners with USB interfaces should work (4100C, -5200C, 6200C). Of course as HP releases new scanners this information -may change. - - -Requirements - -In order to get this running you'll need USB support in your kernel in -addition to USB HP Scanner support. Please refer to README.hp_scanner -for issues pertaining to Linux USB and USB HP Scanner support. - -An installed version of SANE which is available from -http://www.mostang.com/sane/. Testing has been performed using -version SANE-1.0.1. For instructions on building and installing SANE, -refer to the various README files within the distribution. - - -Ok, so what do I do? - -NOTE: $INSTALL_DIR is the location where SANE was installed. It may -be /usr/local, /usr, /opt or somewhere else. If you don't know, ask -your system administrator. - -1) Make sure that you have the libsane-hp.* libraries under the -$INSTALL_DIR/lib/sane/ directory. - -2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following -files: dll.conf, hp.conf. - - dll.conf: Make sure that the 'hp' entry is present and uncommented. - - hp.conf: This should contain two lines: - - option connect-device - /dev/usbscanner - -3) You should now be able to use SANE (xscanimage or scanimage). - -Don't forget to read any relevant man pages regarding the usage of -SANE. If you have other entries uncommented in dll.conf, you my have -to specify the device to (x)scanimage. The xscanimage (1) man page -has info on how to get 'The Gimp' to work with xscanimage. Note that -Gimp support must be compiled into SANE for it work. If you are -dealing with a RedHat system, you'll also need to install the -gimp-devel rpm package. - -NOTE: Most of the time xscanimage will run without incident, then on -the next invocation it'll core dump at different locations. I don't -know why yet and I don't have a work around either other than to try -again. But once you get it started, it'll scan without any problems -(or at least it does for me). - -David /\/elson -dnelson@jump.net diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.scanner linux/drivers/usb/README.scanner --- v2.3.34/linux/drivers/usb/README.scanner Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/README.scanner Mon Dec 27 14:01:53 1999 @@ -0,0 +1,231 @@ +Oct 19, 1999 + +CHANGES + +- Ammended for linux-2.3.22+ +- Appended hp_scan.c to end of this README +- Removed most references to HP + + +OVERVIEW + +This README will address issues regarding how to configure the kernel +to access a USB scanner. Although the driver was originally conceived +for USB HP scanners, it's general enough so that it can be used with +other scanners. Also, one can now pass the USB Vendor and +Product ID's using module parameters for unknown scanners. Refer to +the document README.scanner_hp_sane for guidance on how to configure +SANE to use a USB HP Scanner. + + +ADDITIONAL INFORMATION + +http://www.linux-usb.org/ +http://www.dynamine.net/linux-usb/HOWTO/ + + +REQUIREMENTS + +A host with a USB port. Ideally, either a UHCI (Intel) or OHCI +(Compaq and others) hardware port should work. However, I've only +been able to really use an OHCI controller. I did have access to a +system with a UHCI controller but some very limited testing did not +produce satisfactory results. Luke Ordelmans + has reported success using the UHCI host +controller with kernel 2.3.18 and a ChainTech motherboard. Here +lately I've been having better success with the ohci-hcd driver. But +since Linux USB support is still in a state of constant development +that may change at a later date. I am confident that eventually all +the host contollers will perform without incident. + +A Linux kernel with USB support (preferably linux-2.3.18+) + +A Linux kernel with USB Scanner support. + + +CONFIGURATION + +Using `make menuconfig` or your prefered method for configuring the +kernel, select 'Support for USB', 'OHCI/OHCI-HCD/UHCI' depending on +your hardware, 'USB hub support', and 'USB Scanner support'. Compile +and install the modules (you may need to execute `depmod -a` to update +the module dependencies). Testing was performed only as modules, +YMMV. + +Add a device for the USB scanner: + linux-2.3.22 and above: `mknod /dev/usbscanner c 180 48` + linux-2.3.21 and below: `mknod /dev/usbscanner c 16 1` + +Set appropriate permissions for /dev/usbscanner (don't forget about +group and world permissions). Both read and write permissions are +required for proper operation. + +Load the appropriate modules (if compiled as modules): + + OHCI: + modprobe usb-ohci + modprobe scanner + + OHCI-HCD: + modprobe usb-ohci-hcd + modprobe hub + modprobe scanner + + UHCI: + modprobe usb-uhci + modprobe hub (don't know if this is required or not) + modprobe scanner + +That's it. SANE should now be able to access the device. + +There is a small test program (hp_scan.c -- appended below) that can +be used to test the scanner device if it's an HP scanner that supports +SCL. Its purpose is to test the driver without having to +retrieve/configure SANE. Hp_scan.c will scan the entire bed and put +the output into a file called 'out.dat' in the current directory. The +data in the file is raw data so it's not very useful for imaging. + + +MODULE PARAMETERS + +If you have a device that wish to experiment with or try using this +driver with, but the Vendor and Product ID's are not coded in, don't +despair. If the driver was compiled as a module, you can pass options +to the driver. Simply add 'options scanner vendor=0x#### +product=0x****' to the conf.modules/modules.conf file replacing the +#'s and the *'s with the correct ID's. The ID's can be retrieved from +the messages file or using `cat /proc/bus/usb/devices` if USB /proc +support was selected during kernel configuration. + + +BUGS + +If you encounter any problems feel free to drop me an email. + +David /\/elson +dnelson@jump.net +http://www.jump.net/~dnelson + +--------------- snip -- hp_scan.c -- snip --------------- +/* + +This is a really crude attempt at writing a short test program. It's +mostly only to be used to test connectivity with USB HP scanners that +understand SCL. Currently, the supported models are 4100C, 5200C, +6200C, and the 6300C. Note that the 4200C is *NOT* acceptable. + +Copyright (C) David E. Nelson , 1999 + +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 + +/* + Gray Output produces about a 8945400 byte file. + Color Output produces a 26836200 byte file. + + To compile: gcc -o hp_scan hp_scan.c +*/ + +// #define COLOR /* Undef to scan GrayScale */ + +int send_cmd(int, const char *, int); +int read_cmd(int, char *, int); + +int +main(void) { + + ssize_t cnt = 0, total_cnt = 0; + + FILE *fpout; + + int fp; + int data_size = 32768; + + char *data; + + static char reset_cmd[] = {'\x1b','E'}; + +#ifdef COLOR + static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */ + static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */ +#else + static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */ + static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */ +#endif + + static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'}; + static char start_scan_cmd[] = {'\x1b','*','f','0','S'}; + + if(!(data=malloc(data_size))) { + perror("malloc failed"); + exit (1); + } + + if((fp=open("/dev/usbscanner", O_RDWR)) < 0) { + perror("Unable to open scanner device"); + exit (1); + } + + if((fpout=fopen("out.dat", "w+")) == NULL) { + perror("Unable to open ouput file"); + exit(1); + } + + send_cmd(fp, reset_cmd, sizeof(reset_cmd)); + send_cmd(fp, data_type_cmd, sizeof(data_type_cmd)); + send_cmd(fp, data_width_cmd, sizeof(data_width_cmd)); + send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd)); + + while ((cnt = read(fp, data, data_size)) > 0) { + printf("Read: %u\n", cnt); + if(fwrite(data, sizeof(char), cnt, fpout) < 0) { + perror("Write to output file failed"); + exit (1); + } + total_cnt += cnt; + } + if (cnt < 0) { + perror("Read from scanner failed"); + exit (1); + } + + printf("\nRead %lu bytes.\n", total_cnt); + + send_cmd(fp, reset_cmd, sizeof(reset_cmd)); + + close(fp); + fclose(fpout); + return (0); +} + +int +send_cmd(int fp, const char * cmd, int length) { + + int result; + int x; + + if((result = write(fp, cmd, length)) != length) { + printf ("Write warning: %d bytes requested, %d written\n"); + } else if (result < 0) { + perror ("send_cmd failure"); + exit (1); + } + return (result); +} + +int +read_cmd(int fp, char * response, int length) { + + return read(fp, response, length); + +} diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.scanner_hp_sane linux/drivers/usb/README.scanner_hp_sane --- v2.3.34/linux/drivers/usb/README.scanner_hp_sane Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/README.scanner_hp_sane Mon Dec 27 14:01:53 1999 @@ -0,0 +1,69 @@ +Oct. 19, 1999 + +CHANGES + +- Ammended for Linux-2.3.22+ + + +INTRODUCTION + +This document will hopefully provide enough info on how to get SANE +working with a Hewlett Packard USB capable scanner using the USB +interface. The majority of HP Scanners support the Scanner Control +Language (SCL) which is both published by HP and supported by SANE. +The only HP Scanner that I'm aware of that does not support SCL is the +4200C. All other HP scanners with USB interfaces should work (4100C, +5200C, 6200C, and 6300C). Of course as HP releases new scanners this +information may change. + + +REQUIREMENTS + +In order to get this running you'll need USB support in your kernel in +addition to USB Scanner support. Please refer to README.scanner +for issues pertaining to Linux USB and USB Scanner support. + +An installed version of SANE which is available from +http://www.mostang.com/sane/. Testing has been performed using +version SANE-1.0.1. For instructions on building and installing SANE, +refer to the various README files within the SANE distribution. + + +OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW? + +NOTE: $INSTALL_DIR is the location where SANE was installed. It may +be /usr/local, /usr, /opt or somewhere else. If you don't know, ask +your system administrator. + +1) Make sure that you have the libsane-hp.* libraries under the +$INSTALL_DIR/lib/sane/ directory. If you don't, then the HP backend +was either not compiled or installed properly. + +2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following +files: dll.conf, hp.conf. + + dll.conf: Make sure that the 'hp' entry is present and uncommented. + + hp.conf: This should contain two lines: + + /dev/usbscanner + option connect-device + +3) You should now be able to use SANE (xscanimage or scanimage). + +Don't forget to read any relevant man pages regarding the usage of +SANE. If you have other entries uncommented in dll.conf, you may have +to specify the device to (x)scanimage. Again, `man` is your friend. +The xscanimage (1) man page has info on how to get 'The Gimp' to work +with xscanimage. Note that Gimp support must be compiled into SANE +for it work. If you are dealing with a RedHat system, this means that +you'll also need to install the gimp-devel rpm package. + +NOTE: The issues regarding core dumping by (x)scanimage have (or seem +to be thus far) been resolved with version 0.2+ of the USB scanner +driver which should be available in linux-2.3.23. If you notice +otherwise, please contact me. + +David /\/elson +dnelson@jump.net +http://www.jump.net/~dnelson diff -u --recursive --new-file v2.3.34/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.34/linux/drivers/usb/acm.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/acm.c Mon Dec 27 14:03:38 1999 @@ -1,53 +1,34 @@ /* - * USB Abstract Control Model based on Brad Keryan's USB busmouse driver + * acm.c Version 0.10 * - * (C) Copyright 1999 Armin Fuerst - * (C) Copyright 1999 Pavel Machek - * (C) Copyright 1999 Johannes Erdfelt + * Copyright (c) 1999 Armin Fuerst + * Copyright (c) 1999 Pavel Machek + * Copyright (c) 1999 Johannes Erdfelt + * Copyright (c) 1999 Vojtech Pavlik * - * version 0.8: Fixed endianity bug, some cleanups. I really hate to have - * half of driver in form if (...) { info("x"); return y; } - * Pavel Machek + * USB Abstract Control Model driver for USB modems and ISDN adapters * - * version 0.7: Added usb flow control. Fixed bug in uhci.c (what idiot - * wrote this code? ...Oops that was me). Fixed module cleanup. Did some - * testing at 3Com => zmodem uload+download works, pppd had trouble but - * seems to work now. Changed Menuconfig texts "Communications Device - * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch. - * (2/8/99) + * Sponsored by SuSE * - * version 0.6: Modularized driver, added disconnect code, improved - * assignment of device to tty minor number. - * (21/7/99) - * - * version 0.5: Driver now generates a tty instead of a simple character - * device. Moved async bulk transfer to 2.3.10 kernel version. fixed a bug - * in uhci_td_allocate. Commenetd out getstringtable which causes crash. - * (13/7/99) - * - * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in - * uhci.c. Should have the correct interface now. - * (6/6/99) - * - * version 0.3: Major changes. Changed Bulk transfer to interrupt based - * transfer. Using FIFO Buffers now. Consistent handling of open/close - * file state and detected/nondetected device. File operations behave - * according to this. Driver is able to send+receive now! Heureka! - * (27/5/99) - * - * version 0.2: Improved Bulk transfer. TX led now flashes every time data is - * sent. Send Encapsulated Data is not needed, nor does it do anything. - * Why's that ?!? Thanks to Thomas Sailer for his close look at the bulk code. - * He told me about some importand bugs. (5/21/99) + * ChangeLog: + * v0.9 Vojtech Pavlik - thorough cleaning, URBification, almost a rewrite + * v0.10 Vojtech Pavlik - some more cleanups + */ + +/* + * 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. * - * version 0.1: Bulk transfer for uhci seems to work now, no dangling tds any - * more. TX led of the ISDN TA flashed the first time. Does this mean it works? - * The interrupt of the ctrl endpoint crashes the kernel => no read possible - * (5/19/99) + * 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. * - * version 0.0: Driver sets up configuration, sets up data pipes, opens misc - * device. No actual data transfer is done, since we don't have bulk transfer, - * yet. Purely skeleton for now. (5/8/99) + * 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 */ #include @@ -62,581 +43,491 @@ #include #include #include +#include #include "usb.h" -#define NR_PORTS 3 -#define ACM_MAJOR 166 /* Wow, major is now officially allocated */ +#ifdef CONFIG_USB_ACM_DEBUG +#define acm_debug(fmt,arg...) printk(KERN_DEBUG "acm: " fmt "\n" , ##arg) +#else +#define acm_debug(fmt,arg...) do {} while(0) +#endif + +/* + * Major and minor numbers. + */ + +#define ACM_TTY_MAJOR 166 +#define ACM_TTY_MINORS 8 -//#define info(message...) printk(KERN_DEBUG message) -#define info(message...) +/* + * Output control lines. + */ -#define CTRL_STAT_DTR 1 -#define CTRL_STAT_RTS 2 +#define ACM_CTRL_DTR 0x01 +#define ACM_CTRL_RTS 0x02 -static struct usb_driver acm_driver; +/* + * Input control lines and line errors. + */ + +#define ACM_CTRL_DCD 0x01 +#define ACM_CTRL_DSR 0x02 +#define ACM_CTRL_BRK 0x04 +#define ACM_CTRL_RI 0x08 + +#define ACM_CTRL_FRAMING 0x10 +#define ACM_CTRL_PARITY 0x20 +#define ACM_CTRL_OVERRUN 0x40 -static int acm_refcount; +/* + * Line speed and caracter encoding. + */ -static struct tty_driver acm_tty_driver; -static struct tty_struct *acm_tty[NR_PORTS]; -static struct termios *acm_termios[NR_PORTS]; -static struct termios *acm_termios_locked[NR_PORTS]; -static struct acm_state acm_state_table[NR_PORTS]; - -struct acm_state { - struct usb_device *dev; //the coresponding usb device - int cfgnum; //configuration number on this device - struct tty_struct *tty; //the coresponding tty - char present; //a device for this struct was detected => this tty is used - char active; //someone has this acm's device open - unsigned int ctrlstate; //Status of the serial control lines (handshake,...) - unsigned int linecoding; //Status of the line coding (Bits, Stop, Parity) - int writesize, readsize; //size of the usb buffers - char *writebuffer, *readbuffer; //the usb buffers - void *readtransfer, *writetransfer; - void *ctrltransfer; //ptr to HC internal transfer struct - char writing, reading; //flag if transfer is running - unsigned int readendp,writeendp,ctrlendp; //endpoints and - unsigned int readpipe,writepipe,ctrlpipe; //pipes (are one of these obsolete?) - unsigned ctrlinterval; //interval to poll from device +struct acm_coding { + __u32 speed; + __u8 stopbits; + __u8 parity; + __u8 databits; +} __attribute__ ((packed)); + +/* + * Internal driver structures. + */ + +struct acm { + struct usb_device *dev; /* the coresponding usb device */ + struct usb_config_descriptor *cfg; /* configuration number on this device */ + struct tty_struct *tty; /* the coresponding tty */ + unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ + unsigned int ctrlout; /* output control lines (DTR, RTS) */ + struct acm_coding linecoding; /* line coding (bits, stop, parity) */ + unsigned int writesize; /* max packet size for the output bulk endpoint */ + struct urb ctrlurb, readurb, writeurb; /* urbs */ + unsigned char present; /* this device is connected to the usb bus */ + unsigned char used; /* someone has this acm's device open */ }; -#define ACM_READY (acm->present && acm->active) +static struct usb_driver acm_driver; +static struct acm acm_table[ACM_TTY_MINORS]; + +#define ACM_READY(acm) (acm->present && acm->used) -//functions for various ACM requests +/* + * Functions for ACM control messages. + */ -void Set_Control_Line_Status(unsigned int status, struct acm_state *acm) +static void acm_set_control(unsigned int status, struct acm *acm) { - struct usb_device *dev = acm->dev; - int ret; + if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x22, 0x22, status, 0, NULL, 0, HZ) < 0) + acm_debug("acm_set_control() failed"); - info("Set_control_Line_Status\n"); + acm_debug("output control lines: dtr%c rts%c", + acm->ctrlout & ACM_CTRL_DTR ? '+' : '-', acm->ctrlout & ACM_CTRL_RTS ? '+' : '-'); +} - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x22, 0x22, - status, 0, NULL, 0, HZ); - if (ret < 0) - printk(KERN_ERR "acm: Set_Control_Line_Status failed\n"); +#if 0 +static void acm_set_coding(struct acm_coding *coding, struct acm *acm) +{ + if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x22, 0, 0, coding, sizeof(struct acm_coding), HZ) < 0) + acm_debug("acm_set_coding() failed"); +} - acm->ctrlstate = status; +static void acm_send_break(int ms, struct acm *acm) +{ + if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x33, ms, 0, NULL, 0, HZ) < 0) + acm_debug("acm_send_break() failed"); } +#endif -void Set_Line_Coding(unsigned int coding, struct acm_state *acm) +/* + * Interrupt handler for various ACM control events + */ + +static void acm_ctrl_irq(struct urb *urb) { - struct usb_device *dev = acm->dev; - int ret; + struct acm *acm = urb->context; + devrequest *dr = urb->transfer_buffer; + unsigned char *data = (unsigned char *)(dr + 1); - info("Set_Line_Coding\n"); + if (urb->status < 0) { + acm_debug("nonzero ctrl irq status received: %d", urb->status); + return; + } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x30, 0x22, - coding, 0, NULL, 0, HZ); + if (!ACM_READY(acm)) return; - acm->linecoding = coding; -} + switch (dr->request) { -//Interrupt handler for various usb events -static int acm_irq(int state, void *__buffer, int count, void *dev_id) -{ - unsigned char *data; - struct acm_state *acm = (struct acm_state *)dev_id; - devrequest *dr; + case 0x20: /* Set serial line state */ - info("ACM_USB_IRQ\n"); + if ((dr->index != 1) || (dr->length != 2)) { + acm_debug("unknown set serial line request: index %d len %d", dr->index, dr->length); + return; + } - if (state) { - printk(KERN_DEBUG "acm_irq: strange state received: %x\n", state); - return 0; - } + acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8); - if (!acm->present) - return 0; - if (!acm->active) - return 1; + acm_debug("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", + acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', + acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-', + acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', + acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); - dr = __buffer; - data = __buffer; - data += sizeof(dr); - -#if 0 - printk("reqtype: %02X\n",dr->requesttype); - printk("request: %02X\n",dr->request); - printk("wValue: %02X\n",dr->value); - printk("wIndex: %02X\n",dr->index); - printk("wLength: %02X\n",dr->length); -#endif + return; - switch(dr->request) { - case 0x00: /* Network connection */ - printk(KERN_DEBUG "Network connection: "); - if (dr->request==0) printk(KERN_DEBUG "disconnected\n"); - if (dr->request==1) printk(KERN_DEBUG "connected\n"); - break; - - case 0x01: /* Response available */ - printk(KERN_DEBUG "Response available\n"); - break; - - case 0x20: /* Set serial line state */ - printk(KERN_DEBUG "acm.c: Set serial control line state\n"); - if ((dr->index==1) && (dr->length==2)) { - acm->ctrlstate= data[0] || (data[1] << 16); - printk(KERN_DEBUG "Serstate: %02X\n",acm->ctrlstate); - } - break; + default: + acm_debug("unknown control event received: request %d index %d len %d data0 %d data1 %d", + dr->request, dr->index, dr->length, data[0], data[1]); + return; } - return 1; /* Continue transfer */ + return; } -static int acm_read_irq(int state, void *__buffer, int count, void *dev_id) +static void acm_read_bulk(struct urb *urb) { - struct acm_state *acm = (struct acm_state *) dev_id; - struct tty_struct *tty = acm->tty; - unsigned char* data=__buffer; + struct acm *acm = urb->context; + struct tty_struct *tty = acm->tty; + unsigned char *data = urb->transfer_buffer; int i; - info("ACM_READ_IRQ: state %d, %d bytes\n", state, count); - if (state) { - printk( "acm_read_irq: strange state received: %x\n", state ); - return 1; + if (urb->status) { + acm_debug("nonzero read bulk status received: %d", urb->status); + return; } - - if (!ACM_READY) - return 0; /* stop transfer */ - for (i=0;iactual_length; i++) + tty_insert_flip_char(tty, data[i], 0); - return 1; + tty_flip_buffer_push(tty); + + if (usb_submit_urb(urb)) + acm_debug("failed resubmitting read urb"); + + return; } -static int acm_write_irq(int state, void *__buffer, int count, void *dev_id) +static void acm_write_bulk(struct urb *urb) { - struct acm_state *acm = (struct acm_state *) dev_id; - struct tty_struct *tty = acm->tty; + struct acm *acm = (struct acm *)urb->context; + struct tty_struct *tty = acm->tty; - info("ACM_WRITE_IRQ\n"); + if (urb->status) { + acm_debug("nonzero write bulk status received: %d", urb->status); + return; + } - if (!ACM_READY) - return 0; /* stop transfer */ + if (!ACM_READY(acm)) return; - usb_terminate_bulk(acm->dev, acm->writetransfer); - acm->writing = 0; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); - return 0; /* stop tranfer */ + return; } -/*TTY STUFF*/ -static int rs_open(struct tty_struct *tty, struct file *filp) -{ - struct acm_state *acm; - int ret; +/* + * TTY handlers + */ - info("USB_FILE_OPEN\n"); +static int acm_tty_open(struct tty_struct *tty, struct file *filp) +{ + struct acm *acm = &acm_table[MINOR(tty->device)]; - tty->driver_data = acm = - &acm_state_table[MINOR(tty->device) - tty->driver.minor_start]; + tty->driver_data = acm; acm->tty = tty; - - if (!acm->present) - return -EINVAL; - if (acm->active++) + if (!acm->present) return -EINVAL; + + if (acm->used++) { + MOD_INC_USE_COUNT; return 0; - + } + MOD_INC_USE_COUNT; - /* Start reading from the device */ - ret = usb_request_irq(acm->dev, acm->ctrlpipe, acm_irq, - acm->ctrlinterval, acm, &acm->ctrltransfer); - if (ret) - printk(KERN_ERR "usb-acm: usb_request_irq failed (0x%x)\n", ret); - acm->reading = 1; - acm->readtransfer = usb_request_bulk(acm->dev, acm->readpipe, - acm_read_irq, acm->readbuffer, acm->readsize, acm); + if (usb_submit_urb(&acm->ctrlurb)) + acm_debug("usb_submit_urb(ctrl irq) failed"); + + if (usb_submit_urb(&acm->readurb)) + acm_debug("usb_submit_urb(read bulk) failed"); - Set_Control_Line_Status(CTRL_STAT_DTR | CTRL_STAT_RTS, acm); + acm_set_control(acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS, acm); return 0; } -static void rs_close(struct tty_struct *tty, struct file *filp) +static void acm_tty_close(struct tty_struct *tty, struct file *filp) { - struct acm_state *acm = (struct acm_state *) tty->driver_data; + struct acm *acm = tty->driver_data; - info("rs_close\n"); + if (!ACM_READY(acm)) return; - if (!acm->present) + if (--acm->used) { + MOD_DEC_USE_COUNT; return; - - if (--acm->active) - return; - - Set_Control_Line_Status(0, acm); - - if (acm->writing) { - usb_terminate_bulk(acm->dev, acm->writetransfer); - acm->writing = 0; - } - if (acm->reading) { - usb_terminate_bulk(acm->dev, acm->readtransfer); - acm->reading = 0; } -// usb_release_irq(acm->dev, acm->ctrltransfer, acm->ctrlpipe); + + acm_set_control(acm->ctrlout = 0, acm); + usb_unlink_urb(&acm->writeurb); + usb_unlink_urb(&acm->readurb); MOD_DEC_USE_COUNT; } -static int rs_write(struct tty_struct *tty, int from_user, - const unsigned char *buf, int count) +static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) { - struct acm_state *acm = (struct acm_state *)tty->driver_data; - int written; - - info("rs_write\n"); - - if (!ACM_READY) - return -EINVAL; + struct acm *acm = tty->driver_data; - if (acm->writing) { - info("already writing\n"); - return 0; - } + if (!ACM_READY(acm)) return -EINVAL; + if (acm->writeurb.status == -EINPROGRESS) return 0; - written = (count>acm->writesize) ? acm->writesize : count; + count = (count > acm->writesize) ? acm->writesize : count; if (from_user) - copy_from_user(acm->writebuffer, buf, written); + copy_from_user(acm->writeurb.transfer_buffer, buf, count); else - memcpy(acm->writebuffer, buf, written); + memcpy(acm->writeurb.transfer_buffer, buf, count); - //start the transfer - acm->writing = 1; - acm->writetransfer = usb_request_bulk(acm->dev, acm->writepipe, - acm_write_irq, acm->writebuffer, written, acm); + acm->writeurb.transfer_buffer_length = count; - return written; -} + if (usb_submit_urb(&acm->writeurb)) + acm_debug("usb_submit_urb(write bulk) failed"); -static void rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - printk(KERN_DEBUG "acm: rs_put_char: Who called this unsupported routine?\n"); - BUG(); + return count; } -static int rs_write_room(struct tty_struct *tty) +static int acm_tty_write_room(struct tty_struct *tty) { - struct acm_state *acm = (struct acm_state *) tty->driver_data; - - info("rs_write_room\n"); - - if (!ACM_READY) - return -EINVAL; - - return acm->writing ? 0 : acm->writesize; + struct acm *acm = tty->driver_data; + if (!ACM_READY(acm)) return -EINVAL; + return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize; } -static int rs_chars_in_buffer(struct tty_struct *tty) +static int acm_tty_chars_in_buffer(struct tty_struct *tty) { - struct acm_state *acm = (struct acm_state *) tty->driver_data; - -// info("rs_chars_in_buffer\n"); - - if (!ACM_READY) - return -EINVAL; - - return acm->writing ? acm->writesize : 0; + struct acm *acm = tty->driver_data; + if (!ACM_READY(acm)) return -EINVAL; + return acm->writeurb.status == -EINPROGRESS ? acm->writesize : 0; } -static void rs_throttle(struct tty_struct *tty) +static void acm_tty_throttle(struct tty_struct *tty) { - struct acm_state *acm = (struct acm_state *) tty->driver_data; - - info("rs_throttle\n"); - - if (!ACM_READY) - return; -/* - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); -*/ + struct acm *acm = tty->driver_data; + if (!ACM_READY(acm)) return; if (tty->termios->c_cflag & CRTSCTS) - Set_Control_Line_Status(acm->ctrlstate & ~CTRL_STAT_RTS, acm); + acm_set_control(acm->ctrlout &= ~ACM_CTRL_RTS, acm); } -static void rs_unthrottle(struct tty_struct *tty) +static void acm_tty_unthrottle(struct tty_struct *tty) { - struct acm_state *acm = (struct acm_state *) tty->driver_data; + struct acm *acm = tty->driver_data; + if (!ACM_READY(acm)) return; + if (tty->termios->c_cflag & CRTSCTS) + acm_set_control(acm->ctrlout |= ACM_CTRL_RTS, acm); +} - info("rs_unthrottle\n"); +static void acm_tty_set_termios(struct tty_struct *tty, struct termios *old) +{ + acm_debug("set_termios called, but not there yet"); + return; +} - if (!ACM_READY) - return; /* - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); -*/ - if (tty->termios->c_cflag & CRTSCTS) - Set_Control_Line_Status(acm->ctrlstate | CTRL_STAT_RTS, acm); -} + * USB probe and disconnect routines. + */ -static int get_free_acm(void) +static void *acm_probe(struct usb_device *dev, unsigned int ifnum) { - int i; - - for (i = 0; i < NR_PORTS; i++) { - if (!acm_state_table[i].present) - return i; - } - return -1; -} - -static void * acm_probe(struct usb_device *dev, unsigned int ifnum) -{ - struct acm_state *acm; - struct usb_interface_descriptor *interface; - struct usb_endpoint_descriptor *endpoint; - int cfgnum,acmno; - int swapped=0; - - info("acm_probe\n"); - - if (0>(acmno=get_free_acm())) { - info("Too many acm devices connected\n"); + struct acm *acm; + struct usb_interface_descriptor *ifcom, *ifdata; + struct usb_endpoint_descriptor *epctrl, *epread, *epwrite; + int readsize, ctrlsize, minor, i; + unsigned char *buf; + char *s = NULL; + + for (minor = 0; minor < ACM_TTY_MINORS && + (acm_table[minor].present || acm_table[minor].used); minor++); + if (acm_table[minor].present || acm_table[minor].used) { + acm_debug("no more free acm devices"); return NULL; } - acm = &acm_state_table[acmno]; + acm = acm_table + minor; + memset(acm, 0, sizeof(struct acm)); + + acm->dev = dev; - /* Only use CDC */ - if (dev->descriptor.bDeviceClass != 2 || - dev->descriptor.bDeviceSubClass != 0 || - dev->descriptor.bDeviceProtocol != 0) + if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0 + || dev->descriptor.bDeviceProtocol != 0) { return NULL; + } -#define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints)) + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - /* FIXME: should the driver really be doing the configuration - * selecting or should the usbcore? [different configurations - * can have different bandwidth requirements] -greg */ - - /* Now scan all configs for a ACM configuration */ - for (cfgnum=0;cfgnumdescriptor.bNumConfigurations;cfgnum++) { - /* The first one should be Communications interface? */ - interface = &dev->config[cfgnum].interface[0].altsetting[0]; - if (IFCLASS(interface) != 0x02020101) - continue; + acm_debug("probing config %d", i); + acm->cfg = dev->config + i; - /* Which uses an interrupt input */ - endpoint = &interface->endpoint[0]; - if ((endpoint->bEndpointAddress & 0x80) != 0x80 || - (endpoint->bmAttributes & 3) != 3) - continue; - - /* The second one should be a Data interface? */ - interface = &dev->config[cfgnum].interface[1].altsetting[0]; - if (interface->bInterfaceClass != 10 || - interface->bNumEndpoints != 2) + ifcom = acm->cfg->interface[0].altsetting + 0; + if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || + ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1) continue; - /* make sure both interfaces are available for our use */ - if (usb_interface_claimed(&dev->config[cfgnum].interface[0]) || - usb_interface_claimed(&dev->config[cfgnum].interface[1])) { - printk("usb-acm: required interface already has a driver\n"); + epctrl = ifcom->endpoint + 0; + if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3) continue; - } - endpoint = &interface->endpoint[0]; - if ((endpoint->bEndpointAddress & 0x80) != 0x80) - swapped = 1; - - /*With a bulk input */ - endpoint = &interface->endpoint[0^swapped]; - if ((endpoint->bEndpointAddress & 0x80) != 0x80 || - (endpoint->bmAttributes & 3) != 2) + ifdata = acm->cfg->interface[1].altsetting + 0; + if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2) continue; - - /*And a bulk output */ - endpoint = &interface->endpoint[1^swapped]; - if ((endpoint->bEndpointAddress & 0x80) == 0x80 || - (endpoint->bmAttributes & 3) != 2) + + if (usb_interface_claimed(acm->cfg->interface + 0) || + usb_interface_claimed(acm->cfg->interface + 1)) continue; - printk("USB ACM %d found\n",acmno); - usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue); + epread = ifdata->endpoint + 0; + epwrite = ifdata->endpoint + 1; - acm->dev=dev; + if ((epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || + ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) + continue; - acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].bEndpointAddress; - acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp); - acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].wMaxPacketSize,GFP_KERNEL); - acm->reading=0; - if (!acm->readbuffer) { - printk("ACM: Couldn't allocate readbuffer\n"); - return NULL; + if ((epread->bEndpointAddress & 0x80) != 0x80) { + epread = ifdata->endpoint + 1; + epwrite = ifdata->endpoint + 0; } - acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].bEndpointAddress; - acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp); - acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].wMaxPacketSize, GFP_KERNEL); - acm->writing=0; - if (!acm->writebuffer) { - printk("ACM: Couldn't allocate writebuffer\n"); - kfree(acm->readbuffer); + usb_set_configuration(dev, acm->cfg->bConfigurationValue); + + ctrlsize = epctrl->wMaxPacketSize; + readsize = epread->wMaxPacketSize; + acm->writesize = epwrite->wMaxPacketSize; + + if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) return NULL; - } - acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress; - acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp); - acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval; + FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), + buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); - acm->cfgnum = cfgnum; - acm->present=1; - MOD_INC_USE_COUNT; + FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), + buf += ctrlsize, readsize, acm_read_bulk, acm); + + FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), + buf += readsize , acm->writesize, acm_write_bulk, acm); + + printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); + + usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 0, acm); + usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 1, acm); + + acm->present = 1; - usb_driver_claim_interface(&acm_driver, - &dev->config[cfgnum].interface[0], acm); - usb_driver_claim_interface(&acm_driver, - &dev->config[cfgnum].interface[1], acm); return acm; } + return NULL; } static void acm_disconnect(struct usb_device *dev, void *ptr) { - struct acm_state *acm = ptr; + struct acm *acm = ptr; - info("acm_disconnect\n"); - - if (!acm->present) + if (!acm->present) { + acm_debug("disconnect on nonexisting interface"); return; + } - acm->active=0; - acm->present=0; - if (acm->writing){ - usb_terminate_bulk(acm->dev, acm->writetransfer); - acm->writing=0; - } - if (acm->reading){ - usb_terminate_bulk(acm->dev, acm->readtransfer); - acm->reading=0; - } - usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe); - //BUG: What to do if a device is open?? Notify process or not allow cleanup? - kfree(acm->writebuffer); - kfree(acm->readbuffer); - - /* release the interfaces so that other drivers can have at them */ - usb_driver_release_interface(&acm_driver, - &dev->config[acm->cfgnum].interface[0]); - usb_driver_release_interface(&acm_driver, - &dev->config[acm->cfgnum].interface[1]); + acm->present = 0; - MOD_DEC_USE_COUNT; + usb_unlink_urb(&acm->ctrlurb); + usb_unlink_urb(&acm->readurb); + usb_unlink_urb(&acm->writeurb); + + kfree(acm->ctrlurb.transfer_buffer); + + usb_driver_release_interface(&acm_driver, acm->cfg->interface + 0); + usb_driver_release_interface(&acm_driver, acm->cfg->interface + 1); } -/*USB DRIVER STUFF*/ +/* + * USB driver structure. + */ + static struct usb_driver acm_driver = { - "acm", - acm_probe, - acm_disconnect, - { NULL, NULL } + name: "acm", + probe: acm_probe, + disconnect: acm_disconnect +}; + +/* + * TTY driver structures. + */ + +static int acm_tty_refcount; + +static struct tty_struct *acm_tty_table[ACM_TTY_MINORS]; +static struct termios *acm_tty_termios[ACM_TTY_MINORS]; +static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS]; + +static struct tty_driver acm_tty_driver = { + magic: TTY_DRIVER_MAGIC, + driver_name: "usb", + name: "ttyACM", + major: ACM_TTY_MAJOR, + minor_start: 0, + num: ACM_TTY_MINORS, + type: TTY_DRIVER_TYPE_SERIAL, + subtype: SERIAL_TYPE_NORMAL, + flags: TTY_DRIVER_REAL_RAW, + + refcount: &acm_tty_refcount, + + table: acm_tty_table, + termios: acm_tty_termios, + termios_locked: acm_tty_termios_locked, + + open: acm_tty_open, + close: acm_tty_close, + write: acm_tty_write, + write_room: acm_tty_write_room, + set_termios: acm_tty_set_termios, + throttle: acm_tty_throttle, + unthrottle: acm_tty_unthrottle, + chars_in_buffer: acm_tty_chars_in_buffer }; +/* + * Init / cleanup. + */ + +#ifdef MODULE +void cleanup_module(void) +{ + usb_deregister(&acm_driver); + tty_unregister_driver(&acm_tty_driver); +} + +int init_module(void) +#else int usb_acm_init(void) +#endif { - int cnt; + memset(acm_table, 0, sizeof(struct acm) * ACM_TTY_MINORS); - info("usb_acm_init\n"); + acm_tty_driver.init_termios = tty_std_termios; + acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - //INITIALIZE GLOBAL DATA STRUCTURES - for (cnt = 0; cnt < NR_PORTS; cnt++) - memset(&acm_state_table[cnt], 0, sizeof(struct acm_state)); - - //REGISTER TTY DRIVER - memset(&acm_tty_driver, 0, sizeof(struct tty_driver)); - acm_tty_driver.magic = TTY_DRIVER_MAGIC; - acm_tty_driver.driver_name = "usb"; - acm_tty_driver.name = "ttyACM"; - acm_tty_driver.major = ACM_MAJOR; - acm_tty_driver.minor_start = 0; - acm_tty_driver.num = NR_PORTS; - acm_tty_driver.type = TTY_DRIVER_TYPE_SERIAL; - acm_tty_driver.subtype = SERIAL_TYPE_NORMAL; - acm_tty_driver.init_termios = tty_std_termios; - acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - acm_tty_driver.flags = TTY_DRIVER_REAL_RAW; - acm_tty_driver.refcount = &acm_refcount; - acm_tty_driver.table = acm_tty; - acm_tty_driver.termios = acm_termios; - acm_tty_driver.termios_locked = acm_termios_locked; - - acm_tty_driver.open = rs_open; - acm_tty_driver.close = rs_close; - acm_tty_driver.write = rs_write; - acm_tty_driver.put_char = rs_put_char; - acm_tty_driver.flush_chars = NULL; //rs_flush_chars; - acm_tty_driver.write_room = rs_write_room; - acm_tty_driver.ioctl = NULL; //rs_ioctl - acm_tty_driver.set_termios = NULL; //rs_set_termios; - acm_tty_driver.set_ldisc = NULL; - acm_tty_driver.throttle = rs_throttle; - acm_tty_driver.unthrottle = rs_unthrottle; - acm_tty_driver.stop = NULL; //rs_stop; - acm_tty_driver.start = NULL; //rs_start; - acm_tty_driver.hangup = NULL; //rs_hangup; - acm_tty_driver.break_ctl = NULL; //rs_break; - acm_tty_driver.wait_until_sent = NULL; //rs_wait_until_sent; - acm_tty_driver.send_xchar = NULL; //rs_send_xchar; - acm_tty_driver.read_proc = NULL; //rs_read_proc; - acm_tty_driver.chars_in_buffer = rs_chars_in_buffer; - acm_tty_driver.flush_buffer = NULL; //rs_flush_buffer; - if (tty_register_driver(&acm_tty_driver)) { - printk(KERN_ERR "acm: failed to register tty driver\n"); - return -EPERM; - } + if (tty_register_driver(&acm_tty_driver)) + return -1; if (usb_register(&acm_driver) < 0) { tty_unregister_driver(&acm_tty_driver); return -1; } - printk(KERN_INFO "USB ACM registered.\n"); return 0; } -void usb_acm_cleanup(void) -{ - int i; - struct acm_state *acm; - - info("usb_acm_cleanup\n"); - - for (i=0;ipresent) { - printk("disconnecting %d\n",i); - acm_disconnect(acm->dev, acm); - } - } - tty_unregister_driver(&acm_tty_driver); - - usb_deregister(&acm_driver); - -} - -#ifdef MODULE -int init_module(void) -{ - return usb_acm_init(); -} - -void cleanup_module(void) -{ - usb_acm_cleanup(); -} -#endif diff -u --recursive --new-file v2.3.34/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.34/linux/drivers/usb/audio.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/audio.c Tue Dec 28 10:24:11 1999 @@ -56,6 +56,9 @@ * that means they won't play short sounds. Should probably maintain * the ISO datastream even if there's nothing to play. * Fix counting the total_bytes counter, RealPlayer G2 depends on it. + * 1999-12-20: Fix bad bug in conversion to per interface probing. + * disconnect was called multiple times for the audio device, + * leading to a premature freeing of the audio structures * */ @@ -131,6 +134,7 @@ */ /*****************************************************************************/ + #include #include #include @@ -148,7 +152,6 @@ #include #include #include -//#include #include "usb.h" #include "audio.h" @@ -621,137 +624,145 @@ usbin_stop(as); } -static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples) +static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt) { - union { - __s16 s[64]; - unsigned char b[0]; - } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh, cnt, i; + unsigned int cnt, i; __s16 *sp, *sp2, s; unsigned char *bp; - ufmtsh = AFMT_BYTESSHIFT(u->format); - dfmtsh = AFMT_BYTESSHIFT(u->dma.format); - maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; - while (samples > 0) { - scnt = samples; - if (scnt > maxs) - scnt = maxs; - cnt = scnt; - if (AFMT_ISSTEREO(u->format)) - cnt <<= 1; - sp = tmp.s + cnt; - switch (u->format & ~AFMT_STEREO) { - case AFMT_U8: - for (bp = buffer+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = (*bp ^ 0x80) << 8; - } - break; + cnt = scnt; + if (AFMT_ISSTEREO(ifmt)) + cnt <<= 1; + sp = ((__s16 *)tmp) + cnt; + switch (ifmt & ~AFMT_STEREO) { + case AFMT_U8: + for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { + bp--; + sp--; + *sp = (*bp ^ 0x80) << 8; + } + break; + + case AFMT_S8: + for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { + bp--; + sp--; + *sp = *bp << 8; + } + break; + + case AFMT_U16_LE: + for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { + bp -= 2; + sp--; + *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; + } + break; - case AFMT_S8: - for (bp = buffer+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = *bp << 8; - } - break; + case AFMT_U16_BE: + for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { + bp -= 2; + sp--; + *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; + } + break; - case AFMT_U16_LE: - for (bp = buffer+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; - } - break; + case AFMT_S16_LE: + for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { + bp -= 2; + sp--; + *sp = bp[0] | (bp[1] << 8); + } + break; - case AFMT_U16_BE: - for (bp = buffer+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; - } - break; + case AFMT_S16_BE: + for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { + bp -= 2; + sp--; + *sp = bp[1] | (bp[0] << 8); + } + break; + } + if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) { + /* expand from mono to stereo */ + for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) { + sp--; + sp2 -= 2; + sp2[0] = sp2[1] = sp[0]; + } + } + if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) { + /* contract from stereo to mono */ + for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2) + sp[0] = (sp2[0] + sp2[1]) >> 1; + } + cnt = scnt; + if (AFMT_ISSTEREO(ofmt)) + cnt <<= 1; + sp = ((__s16 *)tmp); + bp = ((unsigned char *)obuf); + switch (ofmt & ~AFMT_STEREO) { + case AFMT_U8: + for (i = 0; i < cnt; i++, sp++, bp++) + *bp = (*sp >> 8) ^ 0x80; + break; - case AFMT_S16_LE: - for (bp = buffer+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[0] | (bp[1] << 8); - } - break; + case AFMT_S8: + for (i = 0; i < cnt; i++, sp++, bp++) + *bp = *sp >> 8; + break; - case AFMT_S16_BE: - for (bp = buffer+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[1] | (bp[0] << 8); - } - break; + case AFMT_U16_LE: + for (i = 0; i < cnt; i++, sp++, bp += 2) { + s = *sp; + bp[0] = s; + bp[1] = (s >> 8) ^ 0x80; } - if (!AFMT_ISSTEREO(u->format) && AFMT_ISSTEREO(u->dma.format)) { - /* expand from mono to stereo */ - for (sp = tmp.s+scnt, sp2 = tmp.s+2*scnt, i = 0; i < scnt; i++) { - sp--; - sp2 -= 2; - sp2[0] = sp2[1] = sp[0]; - } - } - if (AFMT_ISSTEREO(u->format) && !AFMT_ISSTEREO(u->dma.format)) { - /* contract from stereo to mono */ - for (sp = sp2 = tmp.s, i = 0; i < scnt; i++, sp++, sp2 += 2) - sp[0] = (sp2[0] + sp2[1]) >> 1; - } - cnt = scnt; - if (AFMT_ISSTEREO(u->dma.format)) - cnt <<= 1; - sp = tmp.s; - bp = tmp.b; - switch (u->dma.format & ~AFMT_STEREO) { - case AFMT_U8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = (*sp >> 8) ^ 0x80; - break; + break; - case AFMT_S8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = *sp >> 8; - break; + case AFMT_U16_BE: + for (i = 0; i < cnt; i++, sp++, bp += 2) { + s = *sp; + bp[1] = s; + bp[0] = (s >> 8) ^ 0x80; + } + break; - case AFMT_U16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = (s >> 8) ^ 0x80; - } - break; + case AFMT_S16_LE: + for (i = 0; i < cnt; i++, sp++, bp += 2) { + s = *sp; + bp[0] = s; + bp[1] = s >> 8; + } + break; - case AFMT_U16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = (s >> 8) ^ 0x80; - } - break; + case AFMT_S16_BE: + for (i = 0; i < cnt; i++, sp++, bp += 2) { + s = *sp; + bp[1] = s; + bp[0] = s >> 8; + } + break; + } + +} - case AFMT_S16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = s >> 8; - } - break; +static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples) +{ + union { + __s16 s[64]; + unsigned char b[0]; + } tmp; + unsigned int scnt, maxs, ufmtsh, dfmtsh; - case AFMT_S16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = s >> 8; - } - break; - } + ufmtsh = AFMT_BYTESSHIFT(u->format); + dfmtsh = AFMT_BYTESSHIFT(u->dma.format); + maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; + while (samples > 0) { + scnt = samples; + if (scnt > maxs) + scnt = maxs; + conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt); dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh); buffer += scnt << ufmtsh; samples -= scnt; @@ -1040,7 +1051,7 @@ i = u->flags; spin_unlock_irqrestore(&as->lock, flags); while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { - set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); + set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); schedule_timeout(1); spin_lock_irqsave(&as->lock, flags); i = u->flags; @@ -1078,7 +1089,6 @@ static void usbout_disc(struct usb_audiodev *as) { struct usbout *u = &as->usbout; - unsigned long flags; spin_lock_irqsave(&as->lock, flags); @@ -1093,9 +1103,7 @@ __s16 s[64]; unsigned char b[0]; } tmp; - unsigned int scnt, maxs, ufmtsh, dfmtsh, cnt, i; - __s16 *sp, *sp2, s; - unsigned char *bp; + unsigned int scnt, maxs, ufmtsh, dfmtsh; ufmtsh = AFMT_BYTESSHIFT(u->format); dfmtsh = AFMT_BYTESSHIFT(u->dma.format); @@ -1104,121 +1112,8 @@ scnt = samples; if (scnt > maxs) scnt = maxs; - cnt = scnt; - if (AFMT_ISSTEREO(u->dma.format)) - cnt <<= 1; dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh); - sp = tmp.s + cnt; - switch (u->dma.format & ~AFMT_STEREO) { - case AFMT_U8: - for (bp = tmp.b+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = (*bp ^ 0x80) << 8; - } - break; - - case AFMT_S8: - for (bp = tmp.b+cnt, i = 0; i < cnt; i++) { - bp--; - sp--; - *sp = *bp << 8; - } - break; - - case AFMT_U16_LE: - for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; - } - break; - - case AFMT_U16_BE: - for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; - } - break; - - case AFMT_S16_LE: - for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[0] | (bp[1] << 8); - } - break; - - case AFMT_S16_BE: - for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) { - bp -= 2; - sp--; - *sp = bp[1] | (bp[0] << 8); - } - break; - } - if (!AFMT_ISSTEREO(u->dma.format) && AFMT_ISSTEREO(u->format)) { - /* expand from mono to stereo */ - for (sp = tmp.s+scnt, sp2 = tmp.s+2*scnt, i = 0; i < scnt; i++) { - sp--; - sp2 -= 2; - sp2[0] = sp2[1] = sp[0]; - } - } - if (AFMT_ISSTEREO(u->dma.format) && !AFMT_ISSTEREO(u->format)) { - /* contract from stereo to mono */ - for (sp = sp2 = tmp.s, i = 0; i < scnt; i++, sp++, sp2 += 2) - sp[0] = (sp2[0] + sp2[1]) >> 1; - } - cnt = scnt; - if (AFMT_ISSTEREO(u->format)) - cnt <<= 1; - sp = tmp.s; - bp = buffer; - switch (u->format & ~AFMT_STEREO) { - case AFMT_U8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = (*sp >> 8) ^ 0x80; - break; - - case AFMT_S8: - for (i = 0; i < cnt; i++, sp++, bp++) - *bp = *sp >> 8; - break; - - case AFMT_U16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = (s >> 8) ^ 0x80; - } - break; - - case AFMT_U16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = (s >> 8) ^ 0x80; - } - break; - - case AFMT_S16_LE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[0] = s; - bp[1] = s >> 8; - } - break; - - case AFMT_S16_BE: - for (i = 0; i < cnt; i++, sp++, bp += 2) { - s = *sp; - bp[1] = s; - bp[0] = s >> 8; - } - break; - } + conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt); buffer += scnt << ufmtsh; samples -= scnt; } @@ -1534,7 +1429,7 @@ struct usb_device *dev = as->state->usbdev; struct usb_config_descriptor *config = dev->actconfig; struct usb_interface_descriptor *alts; - struct usb_interface *iface; + struct usb_interface *iface; struct usbin *u = &as->usbin; struct dmabuf *d = &u->dma; struct audioformat *fmt; @@ -1793,7 +1688,7 @@ (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; return 0; - + case BASS_CONTROL: case MID_CONTROL: case TREBLE_CONTROL: @@ -1808,7 +1703,7 @@ (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0) goto err; return 0; - + default: return -1; } @@ -1816,7 +1711,7 @@ err: printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", - dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector); + dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector); return -1; } @@ -1842,7 +1737,6 @@ while (!list_empty(&s->audiolist)) { as = list_entry(s->audiolist.next, struct usb_audiodev, list); list_del(&as->list); - usbin_release(as); usbout_release(as); dmabuf_release(&as->usbin.dma); @@ -1851,7 +1745,6 @@ } while (!list_empty(&s->mixerlist)) { ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list); - list_del(&ms->list); kfree(ms); } @@ -1956,7 +1849,7 @@ case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ /* don't know how to handle this yet */ return put_user(0, (int *)arg); - + case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ for (val = i = 0; i < ms->numch; i++) val |= 1 << ms->ch[i].osschannel; @@ -1965,7 +1858,7 @@ case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ /* don't know how to handle this yet */ return put_user(0, (int *)arg); - + case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ for (val = i = 0; i < ms->numch; i++) if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) @@ -3240,10 +3133,10 @@ static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr) { -// struct usb_device *dev = state->s->usbdev; + struct usb_device *dev = state->s->usbdev; struct mixerchannel *ch; unsigned short chftr, mchftr; -// unsigned char data[1]; + unsigned char data[1]; usb_audio_recurseunit(state, ftr[4]); if (state->nrchannels == 0) { @@ -3521,12 +3414,12 @@ if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) { if (numifin < USB_MAXINTERFACES) { ifin[numifin++] = j; - usb_driver_claim_interface(&usb_audio_driver, iface, s); + usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); } } else { if (numifout < USB_MAXINTERFACES) { ifout[numifout++] = j; - usb_driver_claim_interface(&usb_audio_driver, iface, s); + usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); } } } @@ -3555,6 +3448,7 @@ down(&open_sem); list_add_tail(&s->audiodev, &audiodevs); up(&open_sem); + printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s); return s; } @@ -3607,7 +3501,7 @@ if (!(buffer = kmalloc(buflen, GFP_KERNEL))) return NULL; ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen); - if (ret<0) { + if (ret < 0) { kfree(buffer); printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d\n", i, dev->devnum); return NULL; @@ -3624,7 +3518,16 @@ struct list_head *list; struct usb_audiodev *as; struct usb_mixerdev *ms; - + + /* we get called with -1 for every audiostreaming interface registered */ + if (s == (struct usb_audio_state *)-1) { + printk(KERN_DEBUG "usb_audio_disconnect: called with -1\n"); + return; + } + if (!s->usbdev) { + printk(KERN_DEBUG "usb_audio_disconnect: already called for %p!\n", s); + return; + } down(&open_sem); list_del(&s->audiodev); INIT_LIST_HEAD(&s->audiodev); diff -u --recursive --new-file v2.3.34/linux/drivers/usb/hp_scanner.c linux/drivers/usb/hp_scanner.c --- v2.3.34/linux/drivers/usb/hp_scanner.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/usb/hp_scanner.c Wed Dec 31 16:00:00 1969 @@ -1,333 +0,0 @@ -/* -*- linux-c -*- */ - -/* - * Driver for USB HP Scanners - * - * David E. Nelson (dnelson@jump.net) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). - * - * History - * 0.1 8/31/1999 - * - * Developed/tested using linux-2.3.15 with minor ohci.c changes to - * support short packes during bulk xfer mode. Some testing was - * done with ohci-hcd but the performace was low. Very limited - * testing was performed with uhci but I was unable to get it to - * work. Initial relase to the linux-usb development effort. - * - * */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "usb.h" - -/* stall/wait timeout for scanner */ -#define NAK_TIMEOUT (HZ) - -/* For some reason, an IBUF_SIZE of 8192 causes REALLY big problems - * with linux-2.3.15. Anything more than 4k seems to not have an - * effect on increasing performance. Anything smaller than 4k hurts - * it. */ -#define IBUF_SIZE 4096 - -/* This is a scanner, so not much data is sent to it. The largest - * stuff may be some kind of maps and stuff but that's kinda rare. */ -#define OBUF_SIZE 128 - -struct hpscan_usb_data { - struct usb_device *hpscan_dev; /* init: probe_scanner */ - __u8 isopen; /* nz if open */ - - __u8 present; /* Device is present on the bus */ - char *obuf; /* transfer buffers */ - char *ibuf; - wait_queue_head_t wait_q; /* for timeouts */ -}; - -static struct hpscan_usb_data hpscan; - -static int -open_scanner(struct inode * inode, struct file * file) -{ - struct hpscan_usb_data *hps = &hpscan; - - if (hps->isopen) { - return -EBUSY; - } - hps->isopen = 1; - - init_waitqueue_head(&hps->wait_q); - - MOD_INC_USE_COUNT; - - return 0; -} - -static int -close_scanner(struct inode * inode, struct file * file) -{ - struct hpscan_usb_data *hps = &hpscan; - - hps->isopen = 0; - - MOD_DEC_USE_COUNT; - - return 0; -} - -static ssize_t -write_scanner(struct file * file, const char * buffer, - size_t count, loff_t *ppos) -{ - struct hpscan_usb_data *hps = &hpscan; - - unsigned long copy_size; - unsigned long bytes_written = 0; - unsigned long partial; - - int result = 0; - int maxretry; - - do { - unsigned long thistime; - char *obuf = hps->obuf; - - thistime = copy_size = (count > OBUF_SIZE) ? OBUF_SIZE : count; - if (copy_from_user(hps->obuf, buffer, copy_size)) - return -EFAULT; - maxretry = 5; - while (thistime) { - if (!hps->hpscan_dev) - return -ENODEV; - if (signal_pending(current)) { - return bytes_written ? bytes_written : -EINTR; - } - - result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, 2), obuf, thistime, &partial, HZ*10); - - //printk(KERN_DEBUG "write stats: result:%d thistime:%lu partial:%lu\n", result, thistime, partial); - - if (result == USB_ST_TIMEOUT) { /* NAK - so hold for a while */ - if(!maxretry--) { - return -ETIME; - } - interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT); - continue; - } else if (!result & partial) { - obuf += partial; - thistime -= partial; - } else - break; - }; - if (result) { - printk("Write Whoops - %x\n", result); - return -EIO; - } - bytes_written += copy_size; - count -= copy_size; - buffer += copy_size; - } while ( count > 0 ); - - return bytes_written ? bytes_written : -EIO; -} - -static ssize_t -read_scanner(struct file * file, char * buffer, - size_t count, loff_t *ppos) -{ - struct hpscan_usb_data *hps = &hpscan; - - ssize_t read_count; - - unsigned long partial; - - int this_read; - int result; - -/* Wait for the scanner to get it's act together. This may involve - * resetting the head, warming up the lamp, etc. maxretry is number - * of seconds. */ - int maxretry = 30; - - char *ibuf = hps->ibuf; - - read_count = 0; - - while (count) { - if (signal_pending(current)) { - return read_count ? read_count : -EINTR; - } - if (!hps->hpscan_dev) - return -ENODEV; - this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count; - - result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, 1), ibuf, this_read, &partial, HZ*10); - - printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", result, this_read, partial); - - if (partial) { - count = this_read = partial; - } else if (result == USB_ST_TIMEOUT || result == 15) { /* FIXME: 15 ??? */ - if(!maxretry--) { - printk(KERN_DEBUG "read_scanner: maxretry timeout\n"); - return -ETIME; - } - interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT); - continue; - } else if (result != USB_ST_DATAUNDERRUN) { - printk("Read Whoops - result:%u partial:%lu this_read:%u\n", result, partial, this_read); - return -EIO; - } else { - return (0); - } - - if (this_read) { - if (copy_to_user(buffer, ibuf, this_read)) - return -EFAULT; - count -= this_read; - read_count += this_read; - buffer += this_read; - } - } - return read_count; -} - -static void * -probe_scanner(struct usb_device *dev, unsigned int ifnum) -{ - struct hpscan_usb_data *hps = &hpscan; - - /* - * Don't bother using an HP 4200C since it does NOT understand - * SCL and HP isn't going to be releasing the specs any time - * soon. */ - if (dev->descriptor.idVendor != 0x3f0 ) { - printk(KERN_INFO "Scanner is not an HP Scanner.\n"); - return NULL; - } - - if (dev->descriptor.idProduct != 0x101 && /* HP 4100C */ - dev->descriptor.idProduct != 0x202 && /* HP 5100C */ - dev->descriptor.idProduct != 0x601) { /* HP 6300C */ - printk(KERN_INFO "Scanner model not supported/tested.\n"); - return NULL; - } - - printk(KERN_DEBUG "USB Scanner found at address %d\n", dev->devnum); - - hps->present = 1; - hps->hpscan_dev = dev; - - if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { - return NULL; - } - - if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { - return NULL; - } - - return hps; -} - -static void -disconnect_scanner(struct usb_device *dev, void *ptr) -{ - struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr; - - if (hps->isopen) { - /* better let it finish - the release will do whats needed */ - hps->hpscan_dev = NULL; - return; - } - kfree(hps->ibuf); - kfree(hps->obuf); - - hps->present = 0; -} - -static struct -file_operations usb_scanner_fops = { - NULL, /* seek */ - read_scanner, - write_scanner, - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - open_scanner, - NULL, /* flush */ - close_scanner, - NULL, - NULL, /* fasync */ -}; - -static struct -usb_driver scanner_driver = { - "usbscanner", - probe_scanner, - disconnect_scanner, - { NULL, NULL }, - &usb_scanner_fops, - 48 -}; - -int -usb_hp_scanner_init(void) -{ - if (usb_register(&scanner_driver) < 0) - return -1; - - printk(KERN_DEBUG "USB Scanner support registered.\n"); - return 0; -} - - -void -usb_hp_scanner_cleanup(void) -{ - struct hpscan_usb_data *hps = &hpscan; - - hps->present = 0; - usb_deregister(&scanner_driver); -} - -#ifdef MODULE - -int -init_module(void) -{ - return usb_hp_scanner_init(); -} - -void -cleanup_module(void) -{ - usb_hp_scanner_cleanup(); -} -#endif - diff -u --recursive --new-file v2.3.34/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.34/linux/drivers/usb/hub.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/hub.c Tue Dec 28 10:24:11 1999 @@ -4,6 +4,8 @@ * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Gregory P. Smith + * + * $Id: hub.c,v 1.15 1999/12/27 15:17:45 acher Exp $ */ #include @@ -45,6 +47,12 @@ USB_DT_HUB << 8, 0, data, size, HZ); } +static int usb_clear_hub_feature(struct usb_device *dev, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ); +} + static int usb_clear_port_feature(struct usb_device *dev, int port, int feature) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -190,7 +198,6 @@ printk(KERN_INFO "hub: enabling power on all ports\n"); for (i = 0; i < hub->nports; i++) usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); - return 0; } @@ -305,7 +312,9 @@ struct usb_device *usb; struct usb_port_status portsts; unsigned short portstatus, portchange; + int tries; + wait_ms(100); /* Check status */ if (usb_get_port_status(hub, port + 1, &portsts)<0) { printk(KERN_ERR "get_port_status failed\n"); @@ -314,7 +323,8 @@ portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); - printk("hub.c: portstatus %x, change %x\n",portstatus,portchange); + printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange, + (portstatus&(1<bus); if (!usb) { printk(KERN_ERR "couldn't allocate usb_device\n"); diff -u --recursive --new-file v2.3.34/linux/drivers/usb/inits.h linux/drivers/usb/inits.h --- v2.3.34/linux/drivers/usb/inits.h Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/inits.h Mon Dec 27 14:01:53 1999 @@ -1,17 +1,24 @@ int usb_acm_init(void); +void usb_acm_cleanup(void); int usb_audio_init(void); +int usb_cpia_init(void); +void usb_cpia_cleanup(void); +int usb_dc2xx_init(void); +void usb_dc2xx_cleanup(void); int usb_hub_init(void); void usb_hub_cleanup(void); int usb_kbd_init(void); +void usb_kbd_cleanup(void); void usb_major_init(void); void usb_major_cleanup(void); +int usb_mouse_init(void); void usb_mouse_cleanup(void); -int usb_hp_scanner_init(void); -void usb_hp_scanner_cleanup(void); +int usb_scanner_init(void); +void usb_scanner_cleanup(void); int usb_printer_init(void); -int proc_usb_init (void); -void proc_usb_cleanup (void); int usb_scsi_init(void); -int usb_serial_init (void); +int usb_serial_init(void); int dabusb_init(void); void dabusb_cleanup(void); +int proc_usb_init(void); +void proc_usb_cleanup(void); diff -u --recursive --new-file v2.3.34/linux/drivers/usb/keymap.c linux/drivers/usb/keymap.c --- v2.3.34/linux/drivers/usb/keymap.c Sat Oct 9 11:47:50 1999 +++ linux/drivers/usb/keymap.c Tue Dec 28 10:25:14 1999 @@ -9,7 +9,7 @@ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, - 0x1b, 0x2b, 0x00, 0x27, 0x28, 0x29, 0x33, 0x34, + 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xb7, 0x46, @@ -18,7 +18,7 @@ 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, - 0x48, 0x49, 0x52, 0x53, 0x00, 0x6d, 0x00, 0x00, + 0x48, 0x49, 0x52, 0x53, 0x56, 0x6d, 0x00, 0x00, 0xbd, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff -u --recursive --new-file v2.3.34/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c --- v2.3.34/linux/drivers/usb/mouse.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/mouse.c Tue Dec 28 10:24:11 1999 @@ -236,22 +236,38 @@ /* * Look like a PS/2 mouse, please.. - * + * In XFree86 (3.3.5 tested) you must select Protocol "NetMousePS/2", + * then use your wheel as Button 4 and 5 via ZAxisMapping 4 5. * The PS/2 protocol is fairly strange, but * oh, well, it's at least common.. */ static ssize_t read_mouse(struct file * file, char * buffer, size_t count, loff_t *ppos) { + DECLARE_WAITQUEUE(wait, current); int retval = 0; static int state = 0; struct mouse_state *mouse = &static_mouse_state; if (!mouse->present) return 0; - /* - * FIXME - Other mouse drivers handle blocking and nonblocking reads - * differently here... - */ + + if (!mouse->ready) { + if (file->f_flags & O_NONBLOCK) return -EAGAIN; + + add_wait_queue(&mouse->wait, &wait); +repeat: + set_current_state(TASK_INTERRUPTIBLE); + if (!mouse->ready && !signal_pending(current)) { + schedule(); + goto repeat; + } + current->state = TASK_RUNNING; + remove_wait_queue(&mouse->wait, &wait); + } + if (signal_pending(current)) return -ERESTARTSYS; + + if (!mouse->present) + return 0; if (count) { mouse->ready = 0; switch (state) { @@ -389,7 +405,7 @@ { printk(KERN_DEBUG "%s(%d): mouse resume\n", __FILE__, __LINE__); /* restart the usb controller's polling of the mouse */ - + pipe = usb_rcvintpipe(mouse->dev, mouse->bEndpointAddress); FILL_INT_URB(mouse->urb,mouse->dev,pipe, mouse->buffer, @@ -411,10 +427,11 @@ static void mouse_disconnect(struct usb_device *dev, void *priv) { struct mouse_state *mouse = priv; - + /* stop the usb interrupt transfer */ if (mouse->present) { - usb_unlink_urb(mouse->urb); + usb_unlink_urb(mouse->urb); + wake_up(&mouse->wait); } /* this might need work */ diff -u --recursive --new-file v2.3.34/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.34/linux/drivers/usb/printer.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/usb/printer.c Mon Dec 27 14:01:05 1999 @@ -1,4 +1,3 @@ - /* Driver for USB Printers * * Copyright 1999 Michael Gee (michael@linuxspecific.com) @@ -22,10 +21,21 @@ #include "usb.h" +/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string. + * This may include the printer's serial number. + * 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: ; + */ +#define IEEE_DEVICE_ID + #define NAK_TIMEOUT (HZ) /* stall wait for printer */ #define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT) /* should not take 1 minute a page! */ #define BIG_BUF_SIZE 8192 +#define SUBCLASS_PRINTERS 1 +#define PROTOCOL_UNIDIRECTIONAL 1 +#define PROTOCOL_BIDIRECTIONAL 2 /* * USB Printer Requests @@ -59,12 +69,16 @@ static unsigned char printer_read_status(struct pp_usb_data *p) { __u8 status; + int err; struct usb_device *dev = p->pusb_dev; - if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0), + err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), USB_PRINTER_REQ_GET_PORT_STATUS, USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN, - 0, 0, &status, 1, HZ)) { + 0, 0, &status, sizeof(status), HZ); + if (err < 0) { + printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n", + p->minor, err); return 0; } return status; @@ -81,36 +95,39 @@ else if ((status & LP_POUTPA)) { if (last != LP_POUTPA) { last = LP_POUTPA; - printk(KERN_INFO "usblp%d out of paper\n", p->minor); + printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status); } } else if (!(status & LP_PSELECD)) { if (last != LP_PSELECD) { last = LP_PSELECD; - printk(KERN_INFO "usblp%d off-line\n", p->minor); + printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status); } } else { if (last != LP_PERRORP) { last = LP_PERRORP; - printk(KERN_INFO "usblp%d on fire\n", p->minor); + printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status); } } p->last_error = last; - return status; } static void printer_reset(struct pp_usb_data *p) { struct usb_device *dev = p->pusb_dev; + int err; - usb_control_msg(dev, usb_sndctrlpipe(dev,0), + err = usb_control_msg(dev, usb_sndctrlpipe(dev,0), USB_PRINTER_REQ_SOFT_RESET, USB_TYPE_CLASS | USB_RECIP_OTHER, 0, 0, NULL, 0, HZ); + if (err < 0) + printk(KERN_ERR "usblp%d: reset control_msg error = %d\n", + p->minor, err); } -static int open_printer(struct inode * inode, struct file * file) +static int open_printer(struct inode *inode, struct file *file) { struct pp_usb_data *p; @@ -123,10 +140,14 @@ p->minor = MINOR(inode->i_rdev); if (p->isopen++) { + printk(KERN_ERR "usblp%d: printer is already open\n", + p->minor); return -EBUSY; } if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) { p->isopen = 0; + printk(KERN_ERR "usblp%d: cannot allocate memory\n", + p->minor); return -ENOMEM; } @@ -140,7 +161,7 @@ return 0; } -static int close_printer(struct inode * inode, struct file * file) +static int close_printer(struct inode *inode, struct file *file) { struct pp_usb_data *p = file->private_data; @@ -156,8 +177,8 @@ return 0; } -static ssize_t write_printer(struct file * file, - const char * buffer, size_t count, loff_t *ppos) +static ssize_t write_printer(struct file *file, + const char *buffer, size_t count, loff_t *ppos) { struct pp_usb_data *p = file->private_data; unsigned long copy_size; @@ -174,6 +195,7 @@ if (copy_from_user(p->obuf, buffer, copy_size)) return -EFAULT; maxretry = MAX_RETRY_COUNT; + while (thistime) { if (!p->pusb_dev) return -ENODEV; @@ -212,8 +234,8 @@ return bytes_written ? bytes_written : -EIO; } -static ssize_t read_printer(struct file * file, - char * buffer, size_t count, loff_t *ppos) +static ssize_t read_printer(struct file *file, + char *buffer, size_t count, loff_t *ppos) { struct pp_usb_data *p = file->private_data; int read_count = 0; @@ -231,11 +253,14 @@ } if (!p->pusb_dev) return -ENODEV; - this_read = (count > sizeof(buf)) ? sizeof(buf) : count; + this_read = (count > sizeof(buf)) ? sizeof(buf) : count; result = usb_bulk_msg(p->pusb_dev, usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep), buf, this_read, &partial, HZ*20); + if (result < 0) + printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n", + p->minor, result); /* unlike writes, we don't retry a NAK, just stop now */ if (!result & partial) @@ -251,14 +276,16 @@ buffer += this_read; } } + return read_count; } -static void * printer_probe(struct usb_device *dev, unsigned int ifnum) +static void *printer_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_interface_descriptor *interface; struct pp_usb_data *pp; int i; + __u8 status; /* * FIXME - this will not cope with combined printer/scanners @@ -274,8 +301,9 @@ /* Let's be paranoid (for the moment). */ if (interface->bInterfaceClass != USB_CLASS_PRINTER || - interface->bInterfaceSubClass != 1 || - (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) || + interface->bInterfaceSubClass != SUBCLASS_PRINTERS || + (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL && + interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) || interface->bNumEndpoints > 2) { return NULL; } @@ -308,75 +336,89 @@ break; } if (i >= MAX_PRINTERS) { - printk("No minor table space available for USB Printer\n"); + printk(KERN_ERR "No minor table space available for new USB printer\n"); return NULL; } - printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum); + printk(KERN_INFO "USB printer found at address %d\n", dev->devnum); if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) { - printk(KERN_DEBUG "usb_printer: no memory!\n"); + printk(KERN_DEBUG "USB printer: no memory!\n"); return NULL; } memset(pp, 0, sizeof(struct pp_usb_data)); minor_data[i] = PPDATA(pp); - minor_data[i]->minor = i; - minor_data[i]->pusb_dev = dev; - minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE; - if (interface->bInterfaceProtocol != 2) /* if not bidirectional */ - minor_data[i]->noinput = 1; - minor_data[i]->bulk_out_index = + pp->minor = i; + pp->pusb_dev = dev; + pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE; + if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL) + pp->noinput = 1; + + pp->bulk_out_index = ((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) ? 0 : 1; - minor_data[i]->bulk_in_index = minor_data[i]->noinput ? -1 : - (minor_data[i]->bulk_out_index == 0) ? 1 : 0; - minor_data[i]->bulk_in_ep = minor_data[i]->noinput ? -1 : - interface->endpoint[minor_data[i]->bulk_in_index].bEndpointAddress & + pp->bulk_in_index = pp->noinput ? -1 : + (pp->bulk_out_index == 0) ? 1 : 0; + pp->bulk_in_ep = pp->noinput ? -1 : + interface->endpoint[pp->bulk_in_index].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - minor_data[i]->bulk_out_ep = - interface->endpoint[minor_data[i]->bulk_out_index].bEndpointAddress & + pp->bulk_out_ep = + interface->endpoint[pp->bulk_out_index].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if (interface->bInterfaceProtocol == 2) { /* if bidirectional */ - minor_data[i]->maxin = - interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize; + if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) { + pp->maxin = + interface->endpoint[pp->bulk_in_index].wMaxPacketSize; } - printk(KERN_INFO "USB Printer Summary:\n"); - printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n", - i, minor_data[i]->maxout, minor_data[i]->noinput); + printk(KERN_INFO "usblp%d Summary:\n", pp->minor); + printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n", + i, pp->maxout, pp->noinput, pp->maxin); printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n", - minor_data[i]->bulk_in_index, - minor_data[i]->bulk_in_ep, - minor_data[i]->bulk_out_index, - minor_data[i]->bulk_out_ep); + pp->bulk_in_index, + pp->bulk_in_ep, + pp->bulk_out_index, + pp->bulk_out_ep); -#if 0 +#ifdef IEEE_DEVICE_ID { - __u8 status; - __u8 ieee_id[64]; + __u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */ + /* This string space may be too short. */ + int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */ + /* This calc. or be16_to_cpu() both get + * some weird results for . */ + int err; /* Let's get the device id if possible. */ - if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0), + err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), USB_PRINTER_REQ_GET_DEVICE_ID, USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN, 0, 0, ieee_id, - sizeof(ieee_id)-1, HZ) == 0) { + sizeof(ieee_id)-1, HZ); + if (err >= 0) { if (ieee_id[1] < sizeof(ieee_id) - 1) ieee_id[ieee_id[1]+2] = '\0'; else ieee_id[sizeof(ieee_id)-1] = '\0'; - printk(KERN_INFO " USB Printer ID is %s\n", - &ieee_id[2]); + printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n", + pp->minor, length, ieee_id[0], ieee_id[1]); + printk(KERN_INFO "usblp%d Device ID=%s\n", + pp->minor, &ieee_id[2]); } - status = printer_read_status(PPDATA(pp)); - printk(KERN_INFO " Status is %s,%s,%s\n", - (status & LP_PSELECD) ? "Selected" : "Not Selected", - (status & LP_POUTPA) ? "No Paper" : "Paper", - (status & LP_PERRORP) ? "No Error" : "Error"); + else + printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n", + pp->minor, err); } #endif + + status = printer_read_status(PPDATA(pp)); + printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n", + pp->minor, status, + (status & LP_PSELECD) ? "Selected" : "Not Selected", + (status & LP_POUTPA) ? "No Paper" : "Paper", + (status & LP_PERRORP) ? "No Error" : "Error"); + return pp; } @@ -422,7 +464,7 @@ if (usb_register(&printer_driver)) return -1; - printk(KERN_INFO "USB Printer support registered.\n"); + printk(KERN_INFO "USB Printer driver registered.\n"); return 0; } diff -u --recursive --new-file v2.3.34/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c --- v2.3.34/linux/drivers/usb/proc_usb.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/proc_usb.c Wed Dec 22 11:04:50 1999 @@ -381,22 +381,12 @@ return start; } -static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index) -{ - if (start > end) - return start; - start += sprintf(start, "Interface:"); - if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index]) - start += sprintf(start, "%s: %s ", id, dev->stringindex[index]); - return start; -} - #endif /* PROC_EXTRA */ /*****************************************************************/ static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev, - int bus, int level, int index, int count) + const struct usb_bus *bus, int level, int index, int count) { int chix; int cnt = 0; @@ -410,7 +400,7 @@ * So the root hub's parent is 0 and any device that is * plugged into the root hub has a parent of 0. */ - start += sprintf(start, format_topo, bus, level, parent_devnum, index, count, + start += sprintf(start, format_topo, bus->busnum-1, level, parent_devnum, index, count, usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild); /* * level = topology-tier level; @@ -418,11 +408,18 @@ * index = parent's connector number; * count = device count at this level */ - /* do not dump descriptors for root hub */ - if (usbdev->devnum >= 0) - start = usb_dump_desc(start, end, usbdev); + /* If this is the root hub, display the bandwidth information */ + if (level == 0) + start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, + FRAME_TIME_MAX_USECS_ALLOC, + (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC, + bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs); + + /* show the descriptor information for this device */ + start = usb_dump_desc(start, end, usbdev); if (start > end) return start + sprintf(start, "(truncated)\n"); + /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { if (start > end) @@ -440,7 +437,6 @@ char *page, *end; ssize_t ret = 0; unsigned int pos, len; - int busnum = 0; if (*ppos < 0) return -EINVAL; @@ -453,13 +449,9 @@ pos = *ppos; usb_bus_list = usb_bus_get_list(); /* enumerate busses */ - for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next, ++busnum) { - /* print bandwidth allocation */ + for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next) { bus = list_entry(buslist, struct usb_bus, bus_list); - len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC, - (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC, - bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs); - end = usb_device_dump(page + len, page + (PAGE_SIZE - 100), bus->root_hub, busnum, 0, 0, 0); + end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0); len = end - page; if (len > pos) { len -= pos; diff -u --recursive --new-file v2.3.34/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.3.34/linux/drivers/usb/scanner.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/scanner.c Mon Dec 27 14:01:53 1999 @@ -0,0 +1,516 @@ +/* -*- linux-c -*- */ + +/* + * Driver for USB Scanners (linux-2.3.33) + * + * David E. Nelson (dnelson@jump.net) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). + * + * History + * 0.1 8/31/1999 + * + * Developed/tested using linux-2.3.15 with minor ohci.c changes to + * support short packes during bulk xfer mode. Some testing was + * done with ohci-hcd but the performace was low. Very limited + * testing was performed with uhci but I was unable to get it to + * work. Initial relase to the linux-usb development effort. + * + * 0.2 10/16/1999 + * + * FIXED: + * - Device can't be opened unless a scanner is plugged into the USB. + * - Finally settled on a reasonable value for the I/O buffer's. + * - Cleaned up write_scanner() + * - Disabled read/write stats + * - A little more code cleanup + * + * 0.3 10/18/1999 + * + * FIXED: + * - Device registration changed to reflect new device + * allocation/registration for linux-2.3.22+. + * - Adopted David Brownell's technique for + * assigning bulk endpoints. + * - Removed unnessesary #include's + * - Scanner model now reported via syslog INFO after being detected + * *and* configured. + * - Added user specified verdor:product USB ID's which can be passed + * as module parameters. + * + * 0.3.1 + * FIXED: + * - Applied patches for linux-2.3.25. + * - Error number reporting changed to reflect negative return codes. + * + * 0.3.2 + * FIXED: + * - Applied patches for linux-2.3.26 to scanner_init(). + * - Debug read/write stats now report values as signed decimal. + * + * + * 0.3.3 + * FIXED: + * - Updated the bulk_msg() calls to usb usb_bulk_msg(). + * - Added a small delay in the write_scanner() method to aid in + * avoiding NULL data reads on HP scanners. We'll see how this works. + * - Return values from usb_bulk_msg() now ignore positive values for + * use with the ohci driver. + * - Added conditional debugging instead of commenting/uncommenting + * all over the place. + * - kfree()'d the pointer after using usb_string() as documented in + * linux-usb-api.txt. + * - Added usb_set_configuration(). It got lost in version 0.3 -- ack! + * - Added the HP 5200C USB Vendor/Product ID's + * + * TODO + * - Simultaneous multiple device attachment + * - ioctl()'s ? + * + * Thanks to: + * - All the folks on the linux-usb list who put up with me. :) This + * has been a great learning experience for me. + * - To Linus Torvalds for this great OS. + * - The GNU folks. + * - The folks that forwarded Vendor:Product ID's to me. + * - And anybody else who chimed in with reports and suggestions. + * + * Performance: + * System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner + * 300 dpi scan of the entire bed + * 24 Bit Color ~ 70 secs - 3.6 Mbit/sec + * 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec + * */ + +#include +#include +#include +#include +#include +#include + +#include "usb.h" + +// #define SCN_DBG /* Enable to print results of read/write_scanner() calls */ +// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */ +// #define WR_DATA_DUMP + +#ifdef SCN_DBG +#define SCN_DEBUG(X) X +#else +#define SCN_DEBUG(X) +#endif + +#define IBUF_SIZE 32768 +#define OBUF_SIZE 4096 + +struct hpscan_usb_data { + struct usb_device *hpscan_dev; + int isopen; /* Not zero if the device is open */ + int present; /* Device is present on the bus */ + char *obuf, *ibuf; /* transfer buffers */ + char iep, oep; /* I/O Endpoints */ +}; + +static struct hpscan_usb_data hpscan; + +MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson"); +MODULE_DESCRIPTION("USB Scanner Driver"); + +static __u16 vendor=0, product=0; +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); + +static int +open_scanner(struct inode * inode, struct file * file) +{ + struct hpscan_usb_data *hps = &hpscan; + + if (!hps->present) { + return -ENODEV; + } + + if (!hps->hpscan_dev) { + return -ENODEV; + } + + if (hps->isopen) { + return -EBUSY; + } + + hps->isopen = 1; + + MOD_INC_USE_COUNT; + + return 0; +} + +static int +close_scanner(struct inode * inode, struct file * file) +{ + struct hpscan_usb_data *hps = &hpscan; + + hps->isopen = 0; + + MOD_DEC_USE_COUNT; + + return 0; +} + +static ssize_t +write_scanner(struct file * file, const char * buffer, + size_t count, loff_t *ppos) +{ + struct hpscan_usb_data *hps = &hpscan; + + unsigned long copy_size; + unsigned long bytes_written = 0; + unsigned long partial; + + ssize_t ret = 0; + + int result = 0; + + char *obuf = hps->obuf; + + set_current_state(TASK_INTERRUPTIBLE); + + while (count > 0) { + + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + copy_size = (count > OBUF_SIZE) ? OBUF_SIZE : count; + + if (copy_from_user(hps->obuf, buffer, copy_size)) { + ret = -EFAULT; + break; + } + + result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, hps->oep), obuf, copy_size, &partial, 30*HZ); + SCN_DEBUG(printk(KERN_DEBUG "write stats: result:%d copy_size:%lu partial:%lu\n", (int)result, copy_size, partial);) + + if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ + printk(KERN_WARNING "write_scanner: NAK recieved.\n"); + ret = -ETIME; + break; + } else if (result < 0) { /* We should not get any I/O errors */ + printk(KERN_WARNING "write_scanner: funky result: %d. Please notify the maintainer.\n", result); + ret = -EIO; + break; + } + +#ifdef WR_DATA_DUMP + if (partial) { + unsigned char cnt, cnt_max; + cnt_max = (partial > 24) ? 24 : partial; + printk(KERN_DEBUG "dump: "); + for (cnt=0; cnt < cnt_max; cnt++) { + printk("%X ", obuf[cnt]); + } + printk("\n"); + } +#endif + if (partial != copy_size) { /* Unable to write complete amount */ + ret = -EIO; + break; + } + + if (partial) { /* Data written */ + obuf += partial; + count -= partial; + bytes_written += partial; + } else { /* No data written */ + ret = 0; + bytes_written = 0; + break; + } + } +// mdelay(5); + set_current_state(TASK_RUNNING); + return ret ? ret : bytes_written; +} + +static ssize_t +read_scanner(struct file * file, char * buffer, + size_t count, loff_t *ppos) +{ + struct hpscan_usb_data *hps = &hpscan; + + ssize_t read_count, ret = 0; + + unsigned long partial; + + int this_read; + int result; + + char *ibuf = hps->ibuf; + + read_count = 0; + set_current_state(TASK_INTERRUPTIBLE); + + while (count) { + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count; + + result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, hps->iep), ibuf, this_read, &partial, 60*HZ); + SCN_DEBUG(printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", (int)result, this_read, partial);) + + if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ + printk(KERN_WARNING "read_scanner: NAK received\n"); + ret = -ETIME; + break; + } else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) { + printk(KERN_WARNING "read_scanner: funky result: %d. Please notify the maintainer.\n", (int)result); + ret = -EIO; + break; + } + +#ifdef RD_DATA_DUMP + if (partial) { + unsigned char cnt, cnt_max; + cnt_max = (partial > 24) ? 24 : partial; + printk(KERN_DEBUG "dump: "); + for (cnt=0; cnt < cnt_max; cnt++) { + printk("%X ", ibuf[cnt]); + } + printk("\n"); + } +#endif + + if (partial) { /* Data returned */ + count = this_read = partial; + } else { + ret = 0; + read_count = 0; + break; + } + + if (this_read) { + if (copy_to_user(buffer, ibuf, this_read)) { + ret = -EFAULT; + break; + } + count -= this_read; + read_count += this_read; + buffer += this_read; + } + } + set_current_state(TASK_RUNNING); + return ret ? ret : read_count; +} + +static void * +probe_scanner(struct usb_device *dev, unsigned int ifnum) +{ + struct hpscan_usb_data *hps = &hpscan; + struct usb_endpoint_descriptor *endpoint; + + char *ident; + + hps->present = 0; + + if (vendor != 0 || product != 0) { + printk(KERN_INFO "USB Scanner Vendor:Product - %x:%x\n", vendor, product); + } + +/* There doesn't seem to be an imaging class defined in the USB + * Spec. (yet). If there is, HP isn't following it and it doesn't + * look like anybody else is either. Therefore, we have to test the + * Vendor and Product ID's to see what we have. This makes this + * driver a high maintenance driver since it has to be updated with + * each release of a product. Also, other scanners may be able to use + * this driver but again, their Vendor and Product ID's must be added. + * + * NOTE: Just because a product is supported here does not mean that + * applications exist that support the product. It's in the hopes + * that this will allow developers a means to produce applications + * that will support USB products. + * + * Until we detect a device which is pleasing, we silently punt. + * */ + + if (dev->descriptor.idVendor != 0x03f0 && /* Hewlett Packard */ + dev->descriptor.idVendor != 0x06bd && /* AGFA */ + dev->descriptor.idVendor != 0x1606 && /* UMAX */ + dev->descriptor.idVendor != vendor ) { /* User specified */ + return NULL; + } + + if (dev->descriptor.idProduct != 0x0101 && /* HP 4100C */ + dev->descriptor.idProduct != 0x0102 && /* HP 4200C & PhotoSmart S20? */ + dev->descriptor.idProduct != 0x0202 && /* HP 5100C */ + dev->descriptor.idProduct != 0x0401 && /* HP 5200C */ + dev->descriptor.idProduct != 0x0201 && /* HP 6200C */ + dev->descriptor.idProduct != 0x0601 && /* HP 6300C */ + dev->descriptor.idProduct != 0x0001 && /* AGFA SnapScan 1212U */ + dev->descriptor.idProduct != 0x0030 && /* Umax 2000U */ + dev->descriptor.idProduct != product) { /* User specified */ + return NULL; + } + +/* After this point we can be a little noisy about what we are trying to + * configure. */ + + if (dev->descriptor.bNumConfigurations != 1 || + dev->config[0].bNumInterfaces != 1) { + printk(KERN_INFO "probe_scanner: only simple configurations supported\n"); + return NULL; + } + + endpoint = dev->config[0].interface[0].altsetting[0].endpoint; + + if (endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK + || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) { + printk(KERN_INFO "probe_scanner: invalid bulk endpoints\n"); + return NULL; + } + + if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { + printk (KERN_INFO "probe_scanner: failed usb_set_configuration\n"); + hps->hpscan_dev = NULL; + return NULL; + } + +/* By the time we get here, we should be dealing with a fairly simple + * device that supports at least two bulk endpoints on endpoints 1 and + * 2. + * + * We determine the bulk endpoints so that the read_*() and write_*() + * procedures can recv/send data to the correct endpoint. + * */ + + hps->iep = hps->oep = 0; + + if ((endpoint[0].bEndpointAddress & 0x80) == 0x80) { + hps->iep = endpoint[0].bEndpointAddress & 0x7f; + } else { + hps->oep = endpoint[0].bEndpointAddress; + } + + if ((endpoint[1].bEndpointAddress & 0x80) == 0x80) { + hps->iep = endpoint[1].bEndpointAddress & 0x7f; + } else { + hps->oep = endpoint[1].bEndpointAddress; + } + + ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */ + printk(KERN_INFO "USB Scanner (%s) found at address %d\n", ident, dev->devnum); + kfree(ident); + + SCN_DEBUG(printk(KERN_DEBUG "probe_scanner: using bulk endpoints - In: %x Out: %x\n", hps->iep, hps->oep);) + + hps->present = 1; + hps->hpscan_dev = dev; + + if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { + return NULL; + } + + if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { + return NULL; + } + + return hps; +} + +static void +disconnect_scanner(struct usb_device *dev, void *ptr) +{ + struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr; + + if (hps->isopen) { + /* better let it finish - the release will do whats needed */ + hps->hpscan_dev = NULL; + return; + } + kfree(hps->ibuf); + kfree(hps->obuf); + + hps->present = 0; +} + +static struct +file_operations usb_scanner_fops = { + NULL, /* seek */ + read_scanner, + write_scanner, + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_scanner, + NULL, /* flush */ + close_scanner, + NULL, + NULL, /* fasync */ +}; + +static struct +usb_driver scanner_driver = { + "usbscanner", + probe_scanner, + disconnect_scanner, + { NULL, NULL }, + &usb_scanner_fops, + 48 +}; + +int +usb_scanner_init(void) +{ + if (usb_register(&scanner_driver) < 0) + return -1; + + printk(KERN_INFO "USB Scanner support registered.\n"); + return 0; +} + + +void +usb_scanner_cleanup(void) +{ + struct hpscan_usb_data *hps = &hpscan; + + hps->present = 0; + usb_deregister(&scanner_driver); +} + +#ifdef MODULE + +int +init_module(void) +{ + return usb_scanner_init(); +} + +void +cleanup_module(void) +{ + usb_scanner_cleanup(); +} +#endif + diff -u --recursive --new-file v2.3.34/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.34/linux/drivers/usb/uhci.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/uhci.c Tue Dec 28 10:24:11 1999 @@ -12,7 +12,7 @@ * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap * - * $Id: uhci.c,v 1.139 1999/12/17 17:50:59 fliegl Exp $ + * $Id: uhci.c,v 1.149 1999/12/26 20:57:14 acher Exp $ */ @@ -646,7 +646,7 @@ /* Build the TDs for the bulk request */ len = purb->transfer_buffer_length; data = purb->transfer_buffer; - dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: len %d\n", len); + dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: pipe %x, len %d\n", pipe, len); while (len > 0) { int pktsze = len; @@ -675,7 +675,7 @@ //dbg("insert td %p, len %i\n",td,pktsze); insert_td (s, qh, td, UHCI_PTR_DEPTH); - + /* Alternate Data0/1 (start with Data0) */ usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); } @@ -701,8 +701,7 @@ unsigned long flags=0; struct list_head *p; - if (!purb) // you never know... - + if (!purb) // you never know... return -1; s = (puhci_t) purb->dev->bus->hcpriv; // get pointer to uhci struct @@ -720,6 +719,8 @@ // URB probably still in work purb_priv = purb->hcpriv; dequeue_urb (s, &purb->urb_list,1); + purb->status = USB_ST_URB_KILLED; // mark urb as killed + if(!in_interrupt()) { spin_unlock_irqrestore (&s->unlink_urb_lock, flags); // allow interrupts from here } @@ -757,8 +758,7 @@ delete_qh (s, qh); // remove it physically } - purb->status = USB_ST_URB_KILLED; // mark urb as killed - + #ifdef _UHCI_SLAB kmem_cache_free(urb_priv_kmem, purb->hcpriv); #else @@ -872,11 +872,13 @@ now, purb->start_frame, purb->number_of_packets, purb->pipe); { puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - struct list_head *p = s->urb_list.next; + struct list_head *p; purb_t u; int a = -1, b = -1; unsigned long flags; + spin_lock_irqsave (&s->urb_list_lock, flags); + p=s->urb_list.next; for (; p != &s->urb_list; p = p->next) { u = list_entry (p, urb_t, urb_list); @@ -1093,9 +1095,10 @@ // we can accept this urb if it is not queued at this time // or if non-iso transfer requests should be scheduled for the same device and pipe if ((usb_pipetype (purb->pipe) != PIPE_ISOCHRONOUS && - tmp->dev == purb->dev && tmp->pipe == purb->pipe) || (purb == tmp)) + tmp->dev == purb->dev && tmp->pipe == purb->pipe) || (purb == tmp)) { + spin_unlock_irqrestore (&s->urb_list_lock, flags); return 1; // found another urb already queued for processing - + } } spin_unlock_irqrestore (&s->urb_list_lock, flags); @@ -1122,7 +1125,7 @@ if (search_dev_ep (s, purb)) { usb_dec_dev_use (purb->dev); - return -ENXIO; // no such address + return -ENXIO; // urb already queued } @@ -1379,7 +1382,7 @@ for (i = 0; i < 8; i++) uhci->rh.c_p_r[i] = 0; - dbg (KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04 %04 %04 %04\n", + dbg(KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x\n", uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength); switch (bmRType_bReq) { @@ -1519,7 +1522,7 @@ } - dbg (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n", + printk (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n", inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2)); purb->actual_length = len; @@ -1681,27 +1684,32 @@ uhci_show_td (desc); // show first TD of each transfer #endif - // go into error condition to keep data_toggle unchanged if short packet occurs - if ((purb->transfer_flags & USB_DISABLE_SPD) && (actual_length < maxlength)) { - ret = USB_ST_SHORT_PACKET; - printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n"); - break; // exit after this TD because SP was detected + // got less data than requested + if ( (actual_length < maxlength)) { + if (purb->transfer_flags & USB_DISABLE_SPD) { + ret = USB_ST_SHORT_PACKET; // treat as real error + printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n"); + break; // exit after this TD because SP was detected + } + // short read during control-IN: re-start status stage + if ((usb_pipetype (purb->pipe) == PIPE_CONTROL)) { + if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) { + uhci_show_td (last_desc); + qh->hw.qh.element = virt_to_bus (last_desc); // re-trigger status stage + printk("uhci: short packet during control transfer, retrigger status stage @ %p\n",last_desc); + purb_priv->short_control_packet=1; + return 0; + } + } + // all other cases: short read is OK + data_toggle = uhci_toggle (desc->hw.td.info); + break; } data_toggle = uhci_toggle (desc->hw.td.info); //printk(KERN_DEBUG MODSTR"process_transfer: len:%d status:%x mapped:%x toggle:%d\n", actual_length, desc->hw.td.status,status, data_toggle); -#if 1 - if ((usb_pipetype (purb->pipe) == PIPE_CONTROL) && (actual_length < maxlength)) { - if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) { - uhci_show_td (last_desc); - qh->hw.qh.element = virt_to_bus (last_desc); // re-trigger status stage - printk("uhci: short packet during control transfer, retrigger status stage\n"); - purb_priv->short_control_packet=1; - return 0; - } - } -#endif + } usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle); transfer_finished: @@ -1714,15 +1722,14 @@ status & TD_CTRL_NAK ) { ret=0; - purb->status=0; + status=0; } unlink_qh (s, qh); delete_qh (s, qh); purb->status = status; - - + dbg(KERN_DEBUG MODSTR"process_transfer: urb %p, wanted len %d, len %d status %x err %d\n", purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count); //dbg(KERN_DEBUG MODSTR"process_transfer: exit\n"); @@ -1748,21 +1755,15 @@ { desc = list_entry (p, uhci_desc_t, desc_list); - if (desc->hw.td.status & TD_CTRL_NAK) { - // NAKed transfer - //printk("TD NAK Status @%p %08x\n",desc,desc->hw.td.status); - goto err; - } - if (desc->hw.td.status & TD_CTRL_ACTIVE) { // do not process active TDs //printk("TD ACT Status @%p %08x\n",desc,desc->hw.td.status); - goto err; + break; } if (!desc->hw.td.status & TD_CTRL_IOC) { - // do not process one-shot TDs - goto err; + // do not process one-shot TDs, no recycling + break; } // extract transfer parameters from TD @@ -1778,7 +1779,7 @@ // if any error occured: ignore this td, and continue if (status != USB_ST_NOERROR) { purb->error_count++; - goto err; + goto recycle; } else purb->actual_length = actual_length; @@ -1794,7 +1795,7 @@ purb->complete ((struct urb *) purb); purb->status = USB_ST_URB_PENDING; } - + recycle: // Recycle INT-TD if interval!=0, else mark TD as one-shot if (purb->interval) { desc->hw.td.status |= TD_CTRL_ACTIVE; @@ -1804,10 +1805,9 @@ usb_dotoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); } else { - desc->hw.td.status &= ~TD_CTRL_IOC; + desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD } - - err: + err: } return ret; @@ -1882,10 +1882,12 @@ _static int process_urb (puhci_t s, struct list_head *p) { int ret = USB_ST_NOERROR; - purb_t purb = list_entry (p, urb_t, urb_list); - spin_lock(&s->urb_list_lock); + purb_t purb; + spin_lock(&s->urb_list_lock); + purb=list_entry (p, urb_t, urb_list); dbg ( /*KERN_DEBUG */ MODSTR "found queued urb: %p\n", purb); + switch (usb_pipetype (purb->pipe)) { case PIPE_CONTROL: case PIPE_BULK: @@ -1933,7 +1935,7 @@ if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) { dbg (KERN_DEBUG MODSTR "process_transfer: calling early completion\n"); purb->complete ((struct urb *) purb); - if (!proceed && is_ring) + if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED)) uhci_submit_urb (purb); } @@ -1942,7 +1944,7 @@ tmp = purb->next; // pointer to first urb do { - if ((tmp->status != USB_ST_URB_PENDING) && uhci_submit_urb (tmp) != USB_ST_NOERROR) + if ((tmp->status != USB_ST_URB_PENDING) && (tmp->status != USB_ST_URB_KILLED) && uhci_submit_urb (tmp) != USB_ST_NOERROR) break; tmp = tmp->next; } @@ -2160,6 +2162,7 @@ start_hc (s); if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) { + printk(MODSTR KERN_ERR"request_irq %d failed!\n",irq); usb_free_bus (bus); reset_hc (s); release_region (s->io_addr, s->io_size); @@ -2204,9 +2207,6 @@ /* Is it already in use? */ if (check_region (io_addr, io_size)) break; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) - pci_enable_device (dev); -#endif /* disable legacy emulation */ pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); @@ -2297,10 +2297,21 @@ if (type != 0) continue; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) + pci_enable_device (dev); +#endif + if(!dev->irq) + { + printk(KERN_ERR MODSTR"Found UHCI device with no IRQ assigned. Check BIOS settings!\n"); + continue; + } + /* Ok set it up */ retval = start_uhci (dev); + if (!retval) i++; + } #ifdef CONFIG_APM diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c --- v2.3.34/linux/drivers/usb/usb-core.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/usb-core.c Mon Dec 27 14:01:53 1999 @@ -43,8 +43,8 @@ # ifdef CONFIG_USB_MOUSE usb_mouse_init(); # endif -# ifdef CONFIG_USB_HP_SCANNER - usb_hp_scanner_init(); +# ifdef CONFIG_USB_SCANNER + usb_scanner_init(); # endif # ifdef CONFIG_USB_KBD usb_kbd_init(); @@ -87,16 +87,28 @@ proc_usb_cleanup (); #endif usb_hub_cleanup(); -#ifndef MODULE +#ifndef MODULE # ifdef CONFIG_USB_MOUSE usb_mouse_cleanup(); # endif -# ifdef CONFIG_USB_HP_SCANNER - usb_hp_scanner_cleanup(); +# ifdef CONFIG_USB_SCANNER + usb_scanner_cleanup(); # endif # ifdef CONFIG_USB_DABUSB dabusb_cleanup(); +# endif +# ifdef CONFIG_USB_KBD + usb_kbd_cleanup(); +# endif +# ifdef CONFIG_USB_ACM + usb_acm_cleanup(); +# endif +# ifdef CONFIG_USB_CPIA + usb_cpia_cleanup(); +# endif +# ifdef CONFIG_USB_DC2XX + usb_dc2xx_cleanup(); # endif #endif } diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c --- v2.3.34/linux/drivers/usb/usb-serial.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/usb-serial.c Wed Dec 22 10:53:51 1999 @@ -14,6 +14,13 @@ * * See README.serial for more information on using this driver. * + * version 0.2.3 (12/21/99) gkh + * Added initial support for the Connect Tech WhiteHEAT converter. + * Incremented the number of ports in expectation of getting the + * WhiteHEAT to work properly (4 ports per connection). + * Added notification on insertion and removal of what port the + * device is/was connected to (and what kind of device it was). + * * version 0.2.2 (12/16/99) gkh * Changed major number to the new allocated number. We're legal now! * @@ -88,12 +95,12 @@ #define BELKIN_SERIAL_CONVERTER 0x8007 #define PERACOM_VENDOR_ID 0x0565 #define PERACOM_SERIAL_CONVERTER 0x0001 +#define CONNECT_TECH_VENDOR_ID 0x0710 +#define CONNECT_TECH_WHITE_HEAT_ID 0x0001 #define SERIAL_MAJOR 188 /* Nice legal number now */ - -#define NUM_PORTS 4 /* Have to pick a number for now. Need to look */ - /* into dynamically creating them at insertion time. */ +#define NUM_PORTS 16 /* Actually we are allowed 255, but this is good for now */ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum); @@ -119,26 +126,6 @@ static void serial_unthrottle (struct tty_struct * tty); -/* function prototypes for the eTek type converters (this included Belkin and Peracom) */ -static int etek_serial_open (struct tty_struct *tty, struct file * filp); -static void etek_serial_close (struct tty_struct *tty, struct file * filp); -static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch); -static int etek_write_room (struct tty_struct *tty); -static int etek_chars_in_buffer (struct tty_struct *tty); -static void etek_throttle (struct tty_struct * tty); -static void etek_unthrottle (struct tty_struct * tty); - - -/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ -static int generic_serial_open (struct tty_struct *tty, struct file * filp); -static void generic_serial_close (struct tty_struct *tty, struct file * filp); -static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); -static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch); -static int generic_write_room (struct tty_struct *tty); -static int generic_chars_in_buffer (struct tty_struct *tty); - - /* This structure defines the individual serial converter. */ struct usb_serial_device_type { char *name; @@ -157,10 +144,17 @@ int (*chars_in_buffer)(struct tty_struct *tty); void (*throttle)(struct tty_struct * tty); void (*unthrottle)(struct tty_struct * tty); - }; +/* function prototypes for the eTek type converters (this included Belkin and Peracom) */ +static int etek_serial_open (struct tty_struct *tty, struct file *filp); +static void etek_serial_close (struct tty_struct *tty, struct file *filp); +static int etek_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch); +static int etek_write_room (struct tty_struct *tty); +static int etek_chars_in_buffer (struct tty_struct *tty); + /* All of the device info needed for the Belkin Serial Converter */ static __u16 belkin_vendor_id = BELKIN_VENDOR_ID; static __u16 belkin_product_id = BELKIN_SERIAL_CONVERTER; @@ -177,8 +171,8 @@ etek_serial_put_char, etek_write_room, etek_chars_in_buffer, - etek_throttle, - etek_unthrottle + NULL, + NULL }; /* All of the device info needed for the Peracom Serial Converter */ @@ -197,10 +191,50 @@ etek_serial_put_char, etek_write_room, etek_chars_in_buffer, - etek_throttle, - etek_unthrottle + NULL, + NULL +}; + + +/* function prototypes for the Connect Tech WhiteHEAT serial converter */ +static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp); +static void whiteheat_serial_close (struct tty_struct *tty, struct file *filp); +static int whiteheat_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch); +static int whiteheat_write_room (struct tty_struct *tty); +static int whiteheat_chars_in_buffer (struct tty_struct *tty); +static void whiteheat_throttle (struct tty_struct *tty); +static void whiteheat_unthrottle (struct tty_struct *tty); + +/* All of the device info needed for the Connect Tech WhiteHEAT */ +static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID; +static __u16 connecttech_whiteheat_product_id = CONNECT_TECH_WHITE_HEAT_ID; +static struct usb_serial_device_type whiteheat_device = { + "Connect Tech - WhiteHEAT", + &connecttech_vendor_id, /* the Connect Tech vendor id */ + &connecttech_whiteheat_product_id, /* the White Heat product id */ + DONT_CARE, /* don't have to have an interrupt in endpoint */ + DONT_CARE, /* don't have to have a bulk in endpoint */ + DONT_CARE, /* don't have to have a bulk out endpoint */ + whiteheat_serial_open, + whiteheat_serial_close, + whiteheat_serial_write, + whiteheat_serial_put_char, + whiteheat_write_room, + whiteheat_chars_in_buffer, + whiteheat_throttle, + whiteheat_unthrottle }; + +/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ +static int generic_serial_open (struct tty_struct *tty, struct file *filp); +static void generic_serial_close (struct tty_struct *tty, struct file *filp); +static int generic_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count); +static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch); +static int generic_write_room (struct tty_struct *tty); +static int generic_chars_in_buffer (struct tty_struct *tty); + /* All of the device info needed for the Generic Serial Converter */ static struct usb_serial_device_type generic_device = { "Generic", @@ -225,6 +259,7 @@ entry is NULL. */ static struct usb_serial_device_type *usb_serial_devices[] = { &generic_device, + &whiteheat_device, &belkin_device, &peracom_device, NULL @@ -238,6 +273,7 @@ void * irq_handle; unsigned int irqpipe; struct tty_struct * tty; /* the coresponding tty for this device */ + unsigned char number; char present; char active; @@ -292,7 +328,7 @@ unsigned char* data = buffer; int i; - debug_info("USB serial: serial_read_irq\n"); + debug_info("USB Serial: serial_read_irq\n"); #ifdef SERIAL_DEBUG if (count) { @@ -340,9 +376,11 @@ } +#if 0 +/* we will need this soon... removed for now to keep the compile warnings down */ static int usb_serial_irq (int state, void *buffer, int len, void *dev_id) { -// struct usb_serial_state *serial = (struct usb_serial_state *) dev_id; + struct usb_serial_state *serial = (struct usb_serial_state *) dev_id; debug_info("USB Serial: usb_serial_irq\n"); @@ -352,7 +390,7 @@ return (1); } - +#endif @@ -753,11 +791,141 @@ } -static void etek_throttle (struct tty_struct * tty) +/***************************************************************************** + * Connect Tech's White Heat specific driver functions + *****************************************************************************/ +static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp) { struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; - debug_info("USB Serial: etek_throttle\n"); + debug_info("USB Serial: whiteheat_serial_open\n"); + + if (!serial->present) { + debug_info("USB Serial: no device registered\n"); + return -EINVAL; + } + + if (serial->active) { + debug_info ("USB Serial: device already open\n"); + return -EINVAL; + } + serial->active = 1; + + /*Start reading from the device*/ + serial->bulk_in_inuse = 1; + serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); + + /* Need to do device specific setup here (control lines, baud rate, etc.) */ + /* FIXME!!! */ + + return (0); +} + + +static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + debug_info("USB Serial: whiteheat_serial_close\n"); + + /* Need to change the control lines here */ + /* FIXME */ + + /* shutdown our bulk reads and writes */ + if (serial->bulk_out_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_out_transfer); + serial->bulk_out_inuse = 0; + } + if (serial->bulk_in_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_in_transfer); + serial->bulk_in_inuse = 0; + } + + /* release the irq? */ + + serial->active = 0; +} + + +static int whiteheat_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + int written; + + debug_info("USB Serial: whiteheat_serial_write\n"); + + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return (0); + } + + written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count; + + if (from_user) { + copy_from_user(serial->bulk_out_buffer, buf, written); + } + else { + memcpy (serial->bulk_out_buffer, buf, written); + } + + /* send the data out the bulk port */ + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial); + + return (written); +} + + +static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: whiteheat_serial_put_char\n"); + + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return; + } + + /* send the single character out the bulk port */ + serial->bulk_out_buffer[0] = ch; + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial); + + return; +} + + +static int whiteheat_write_room (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: whiteheat_write_room\n"); + + if (serial->bulk_out_inuse) { + return (0); + } + + return (serial->bulk_out_size); +} + + +static int whiteheat_chars_in_buffer (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: whiteheat_chars_in_buffer\n"); + + if (serial->bulk_out_inuse) { + return (serial->bulk_out_size); + } + + return (0); +} + + +static void whiteheat_throttle (struct tty_struct * tty) +{ + debug_info("USB Serial: whiteheat_throttle\n"); /* Change the control signals */ /* FIXME!!! */ @@ -766,11 +934,9 @@ } -static void etek_unthrottle (struct tty_struct * tty) +static void whiteheat_unthrottle (struct tty_struct * tty) { - struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; - - debug_info("USB Serial: etek_unthrottle\n"); + debug_info("USB Serial: whiteheat_unthrottle\n"); /* Change the control signals */ /* FIXME!!! */ @@ -953,7 +1119,7 @@ while (usb_serial_devices[device_num] != NULL) { type = usb_serial_devices[device_num]; #ifdef SERIAL_DEBUG - printk ("USB Serial: Looking at %s\nVendor id=%.4x\nProduct id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct)); + printk ("USB Serial: Looking at %s Vendor id=%.4x Product id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct)); #endif /* look at the device descriptor */ @@ -1013,7 +1179,7 @@ (bulk_in_pipe & type->needs_bulk_in) && (bulk_out_pipe & type->needs_bulk_out)) { /* found all that we need */ - printk (KERN_INFO "USB serial converter detected.\n"); + printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name); if (0>(serial_num = Get_Free_Serial())) { debug_info("USB Serial: Too many devices connected\n"); @@ -1025,6 +1191,7 @@ memset(serial, 0, sizeof(struct usb_serial_state)); serial->dev = dev; serial->type = type; + serial->number = serial_num; /* set up the endpoint information */ if (bulk_in_endpoint) { @@ -1086,6 +1253,7 @@ serial->present = 1; MOD_INC_USE_COUNT; + printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num); return serial; } else { printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n"); @@ -1139,11 +1307,15 @@ serial->present = 0; serial->active = 0; + + printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number); + + } else { + printk (KERN_INFO "USB Serial: device disconnected.\n"); } MOD_DEC_USE_COUNT; - printk (KERN_INFO "USB Serial: device disconnected.\n"); } diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.34/linux/drivers/usb/usb.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/usb.c Tue Dec 28 10:24:11 1999 @@ -15,7 +15,7 @@ * It should be considered a slave, with no callbacks. Callbacks * are evil. * - * $Id: usb.c,v 1.37 1999/12/17 10:48:08 fliegl Exp $ + * $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $ */ #ifndef EXPORT_SYMTAB @@ -36,12 +36,9 @@ #define MODSTR "usbcore: " #ifdef USB_DEBUG - #define dbg printk + #define dbg(format, arg...) printk(format, ## arg) #else - #define dbg nix -static void nix(const char *format, ...) -{ -} + #define dbg(format, arg...) #endif /* diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.34/linux/drivers/usb/usb.h Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/usb.h Tue Dec 28 10:24:11 1999 @@ -227,8 +227,8 @@ static __inline__ void wait_ms(unsigned int ms) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(1 + ms * HZ / 1000); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(1 + ms * HZ / 1000); } typedef struct { @@ -371,7 +371,7 @@ int num_altsetting; /* number of alternate settings */ int max_altsetting; /* total memory allocated */ - struct usb_driver *driver; /* driver */ + struct usb_driver *driver; /* driver */ void *private_data; }; @@ -475,35 +475,35 @@ #define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \ do {\ - a->dev=aa;\ - a->pipe=b;\ - a->setup_packet=c;\ - a->transfer_buffer=d;\ - a->transfer_buffer_length=e;\ - a->complete=f;\ - a->context=g;\ + (a)->dev=aa;\ + (a)->pipe=b;\ + (a)->setup_packet=c;\ + (a)->transfer_buffer=d;\ + (a)->transfer_buffer_length=e;\ + (a)->complete=f;\ + (a)->context=g;\ } while (0) #define FILL_BULK_URB(a,aa,b,c,d,e,f) \ do {\ - a->dev=aa;\ - a->pipe=b;\ - a->transfer_buffer=c;\ - a->transfer_buffer_length=d;\ - a->complete=e;\ - a->context=f;\ + (a)->dev=aa;\ + (a)->pipe=b;\ + (a)->transfer_buffer=c;\ + (a)->transfer_buffer_length=d;\ + (a)->complete=e;\ + (a)->context=f;\ } while (0) #define FILL_INT_URB(a,aa,b,c,d,e,f,g) \ do {\ - a->dev=aa;\ - a->pipe=b;\ - a->transfer_buffer=c;\ - a->transfer_buffer_length=d;\ - a->complete=e;\ - a->context=f;\ - a->interval=g;\ - a->start_frame=-1;\ + (a)->dev=aa;\ + (a)->pipe=b;\ + (a)->transfer_buffer=c;\ + (a)->transfer_buffer_length=d;\ + (a)->complete=e;\ + (a)->context=f;\ + (a)->interval=g;\ + (a)->start_frame=-1;\ } while (0) purb_t usb_alloc_urb(int iso_packets); @@ -561,7 +561,6 @@ int bandwidth_isoc_reqs; /* number of Isoc. requesters */ /* procfs entry */ - int proc_busnum; struct proc_dir_entry *proc_entry; }; diff -u --recursive --new-file v2.3.34/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c --- v2.3.34/linux/drivers/usb/uss720.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/usb/uss720.c Wed Dec 22 17:36:47 1999 @@ -363,7 +363,7 @@ return 0; if (change_mode(pp, ECR_EPP)) return 0; - i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buf, length, &rlen, HZ*20); + i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20); if (i) printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen); change_mode(pp, ECR_PS2); @@ -424,7 +424,7 @@ return 0; if (change_mode(pp, ECR_ECP)) return 0; - i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20); + i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20); if (i) printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); change_mode(pp, ECR_PS2); @@ -475,7 +475,7 @@ return 0; if (change_mode(pp, ECR_PPF)) return 0; - i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20); + i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20); if (i) printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); change_mode(pp, ECR_PS2); diff -u --recursive --new-file v2.3.34/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.3.34/linux/drivers/video/Makefile Tue Dec 14 01:27:24 1999 +++ linux/drivers/video/Makefile Mon Dec 20 22:06:42 1999 @@ -131,6 +131,9 @@ clean: rm -f core *.o *.a *.s +../conmakehash: ../conmakehash.c + $(HOSTCC) $(HOSTCFLAGS) -o ../conmakehash ../conmakehash.c + promcon_tbl.c: prom.uni ../char/conmakehash ../char/conmakehash prom.uni | \ sed -e '/#include <[^>]*>/p' -e 's/types/init/' \ diff -u --recursive --new-file v2.3.34/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.3.34/linux/drivers/video/atyfb.c Sun Nov 7 16:37:34 1999 +++ linux/drivers/video/atyfb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 geert Exp $ +/* $Id: atyfb.c,v 1.133 1999/12/09 10:23:13 davem Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -269,8 +269,8 @@ } fbcon_cmap; u8 blitter_may_be_busy; #ifdef __sparc__ - u8 open; u8 mmaped; + int open; int vtconsole; int consolecnt; #endif @@ -2622,10 +2622,8 @@ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { - if (fb->open) - return -EBUSY; + fb->open++; fb->mmaped = 0; - fb->open = 1; fb->vtconsole = -1; } else { fb->consolecnt++; @@ -2635,17 +2633,54 @@ return(0); } +struct fb_var_screeninfo default_var = { + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED +}; + static int atyfb_release(struct fb_info *info, int user) { #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { - if (fb->vtconsole != -1) - vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; - fb->open = 0; - fb->mmaped = 0; - fb->vtconsole = -1; + fb->open--; + udelay(1000); + wait_for_idle(fb); + if (!fb->open) { + int was_mmaped = fb->mmaped; + + fb->mmaped = 0; + if (fb->vtconsole != -1) + vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; + fb->vtconsole = -1; + + if (was_mmaped) { + struct fb_var_screeninfo var; + + /* Now reset the default display config, we have no + * idea what the program(s) which mmap'd the chip did + * to the configuration, nor whether it restored it + * correctly. + */ + var = default_var; + if (noaccel) + var.accel_flags &= ~FB_ACCELF_TEXT; + else + var.accel_flags |= FB_ACCELF_TEXT; + if (var.yres == var.yres_virtual) { + u32 vram = (fb->total_vram - (PAGE_SIZE << 2)); + var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / + var.xres_virtual; + if (var.yres_virtual < var.yres) + var.yres_virtual = var.yres; + } + atyfb_set_var(&var, -1, &fb->fb_info); + } + } } else { fb->consolecnt--; } @@ -2708,15 +2743,6 @@ } -struct fb_var_screeninfo default_var = { - /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, - 0, FB_VMODE_NONINTERLACED -}; - - /* * Get the Fixed Part of the Display */ @@ -4069,6 +4095,14 @@ #endif +#ifdef CONFIG_PMAC_PBOOK + if (first_display == NULL) + pmu_register_sleep_notifier(&aty_sleep_notifier); + info->next = first_display; + first_display = info; +#endif + + #ifdef CONFIG_FB_COMPAT_XPMAC if (!console_fb_info) console_fb_info = &info->fb_info; @@ -4772,6 +4806,98 @@ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif + +#ifdef CONFIG_PMAC_PBOOK +/* + * Save the contents of the frame buffer when we go to sleep, + * and restore it when we wake up again. + */ +int +aty_sleep_notify(struct pmu_sleep_notifier *self, int when) +{ + struct fb_info_aty *info; + unsigned int pm; + + for (info = first_display; info != NULL; info = info->next) { + struct fb_fix_screeninfo fix; + int nb; + + atyfb_get_fix(&fix, fg_console, (struct fb_info *)info); + nb = fb_display[fg_console].var.yres * fix.line_length; + + switch (when) { + case PBOOK_SLEEP_NOW: + /* Stop accel engine (stop bus mastering) */ + if (info->current_par.accel_flags & FB_ACCELF_TEXT) + reset_engine(info); +#if 1 + /* Backup fb content */ + info->save_framebuffer = vmalloc(nb); + if (info->save_framebuffer) + memcpy(info->save_framebuffer, + (void *)info->frame_buffer, nb); +#endif + /* Blank display and LCD */ + atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info); + + /* Set chip to "suspend" mode. Note: There's an HW bug in the + chip which prevents proper resync on wakeup with automatic + power management, we handle suspend manually using the + following (weird) sequence described by ATI. Note2: + We could enable this for all Rage LT Pro chip ids */ + if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~(PWR_BLON | AUTO_PWR_UP); + pm |= SUSPEND_NOW; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + do { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND); + mdelay(500); + } + break; + case PBOOK_WAKE: + /* Wakeup chip */ + if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm &= ~PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= (PWR_BLON | AUTO_PWR_UP); + pm &= ~SUSPEND_NOW; + aty_st_le32(POWER_MANAGEMENT, pm, info); + pm = aty_ld_le32(POWER_MANAGEMENT, info); + pm |= PWR_MGT_ON; + aty_st_le32(POWER_MANAGEMENT, pm, info); + do { + pm = aty_ld_le32(POWER_MANAGEMENT, info); + } while ((pm & PWR_MGT_STATUS_MASK) != 0); + mdelay(500); + } +#if 1 + /* Restore fb content */ + if (info->save_framebuffer) { + memcpy((void *)info->frame_buffer, + info->save_framebuffer, nb); + vfree(info->save_framebuffer); + info->save_framebuffer = 0; + } +#endif + /* Restore display */ + atyfb_set_par(&info->current_par, info); + atyfbcon_blank(0, (struct fb_info *)info); + break; + } + } + return PBOOK_SLEEP_OK; +} +#endif /* CONFIG_PMAC_PBOOK */ #ifdef CONFIG_PMAC_PBOOK /* diff -u --recursive --new-file v2.3.34/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c --- v2.3.34/linux/drivers/video/bwtwofb.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/bwtwofb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: bwtwofb.c,v 1.8 1999/08/26 05:13:09 shadow Exp $ +/* $Id: bwtwofb.c,v 1.11 1999/11/19 09:56:54 davem Exp $ * bwtwofb.c: BWtwo frame buffer driver * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -85,17 +85,33 @@ static void bw2_blank (struct fb_info_sbusfb *fb) { - fb->s.bw2.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(&fb->s.bw2.regs->control); + tmp &= ~BWTWO_CTL_ENABLE_VIDEO; + sbus_writeb(tmp, &fb->s.bw2.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } static void bw2_unblank (struct fb_info_sbusfb *fb) { - fb->s.bw2.regs->control |= BWTWO_CTL_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(&fb->s.bw2.regs->control); + tmp |= BWTWO_CTL_ENABLE_VIDEO; + sbus_writeb(tmp, &fb->s.bw2.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } -static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + ((x_margin - fb->x_margin) >> 3); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + ((x_margin - fb->x_margin) >> 3); } static u8 bw2regs_1600[] __initdata = { @@ -142,17 +158,29 @@ struct fbtype *type = &fb->type; #ifdef CONFIG_SUN4 unsigned long phys = sun4_bwtwo_physaddr; + struct resource res; #else unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; #endif + struct resource *resp; + unsigned int vaddr; #ifndef FBCON_HAS_MFB return NULL; #endif +#ifdef CONFIG_SUN4 + res.start = phys; + res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1; + res.flags = IORESOURE_IO | (fb->iospace & 0xff); + resp = &res; +#else + resp = &fb->sbdp->resource[0]; +#endif if (!fb->s.bw2.regs) { - fb->s.bw2.regs = (struct bw2_regs *)sparc_alloc_io(phys+BWTWO_REGISTER_OFFSET, 0, - sizeof(struct bw2_regs), "bw2_regs", fb->iospace, 0); + fb->s.bw2.regs = (struct bw2_regs *) + sbus_ioremap(resp, BWTWO_REGISTER_OFFSET, + sizeof(struct bw2_regs), "bw2 regs"); if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) { /* Ugh, broken PROM didn't initialize us. * Let's deal with this ourselves. @@ -161,7 +189,7 @@ u8 *p; int sizechange = 0; - status = fb->s.bw2.regs->status; + status = sbus_readb(&fb->s.bw2.regs->status); mon = status & BWTWO_SR_RES_MASK; switch (status & BWTWO_SR_ID_MASK) { case BWTWO_SR_ID_MONO_ECL: @@ -191,21 +219,24 @@ prom_halt(); return NULL; /* fool gcc. */ } - for ( ; *p; p += 2) - ((u8 *)fb->s.bw2.regs)[p[0]] = p[1]; + for ( ; *p; p += 2) { + u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]]; + sbus_writeb(p[1], regp); + } } } strcpy(fb->info.modename, "BWtwo"); strcpy(fix->id, "BWtwo"); - fix->line_length = fb->var.xres_virtual>>3; + fix->line_length = fb->var.xres_virtual >> 3; fix->accel = FB_ACCEL_SUN_BWTWO; disp->scrollmode = SCROLL_YREDRAW; disp->inverse = 1; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys, 0, - type->fb_size, "bw2_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(resp, 0, type->fb_size, "bw2 ram"); + } disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3); fb->dispsw = fbcon_mfb; fix->visual = FB_VISUAL_MONO01; @@ -213,10 +244,13 @@ #ifndef CONFIG_SUN4 fb->blank = bw2_blank; fb->unblank = bw2_unblank; + + prom_getproperty(fb->sbdp->prom_node, "address", + (char *)&vaddr, sizeof(vaddr)); + fb->physbase = __get_phys((unsigned long)vaddr); + #endif fb->margins = bw2_margins; - - fb->physbase = __get_phys(fb->sbdp->sbus_vaddrs[0]); fb->mmap_map = bw2_mmap_map; #ifdef __sparc_v9__ diff -u --recursive --new-file v2.3.34/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c --- v2.3.34/linux/drivers/video/cgfourteenfb.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/cgfourteenfb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: cgfourteenfb.c,v 1.5 1999/08/10 15:56:02 davem Exp $ +/* $Id: cgfourteenfb.c,v 1.7 1999/11/19 09:57:01 davem Exp $ * cgfourteenfb.c: CGfourteen frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -153,10 +153,10 @@ * I currently use the clut instead of the Xlut */ struct cg14_clut { - unsigned int c_clut [256]; - unsigned int c_clutd [256]; /* i wonder what the 'd' is for */ - unsigned int c_clut_inc [256]; - unsigned int c_clutd_inc [256]; + u32 c_clut [256]; + u32 c_clutd [256]; /* i wonder what the 'd' is for */ + u32 c_clut_inc [256]; + u32 c_clutd_inc [256]; }; static struct sbus_mmap_map cg14_mmap_map[] __initdata = { @@ -179,40 +179,55 @@ { 0, 0, 0 } }; -static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) +static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, + int index, int count) { struct cg14_clut *clut = fb->s.cg14.clut; + unsigned long flags; - for (; count--; index++) - clut->c_clut[index] = - (fb->color_map CM(index,2) << 16) | - (fb->color_map CM(index,1) << 8) | - (fb->color_map CM(index,0)); + spin_lock_irqsave(&fb->lock, flags); + for (; count--; index++) { + u32 val; + + val = ((fb->color_map CM(index,2) << 16) | + (fb->color_map CM(index,1) << 8) | + (fb->color_map CM(index,0))); + sbus_writel(val, &clut->c_clut[index]); + } + spin_unlock_irqrestore(&fb->lock, flags); } -static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; - cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16)); - cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16)); + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(((red[0]) | (green[0] << 8) | (blue[0] << 16)), &cur->color0); + sbus_writel(((red[1]) | (green[1] << 8) | (blue[1] << 16)), &cur->color1); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg14_setcurshape (struct fb_info_sbusfb *fb) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++){ - cur->cpl0 [i] = fb->cursor.bits[0][i]; - cur->cpl1 [i] = fb->cursor.bits[1][i]; + sbus_writel(fb->cursor.bits[0][i], &cur->cpl0[i]); + sbus_writel(fb->cursor.bits[1][i], &cur->cpl1[i]); } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -220,40 +235,67 @@ { struct cg_cursor *c = &fb->cursor; struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; - if (c->enable) - cur->ccr |= CG14_CCR_ENABLE; - cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff); - cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff); + spin_lock_irqsave(&fb->lock, flags); + if (c->enable) { + u8 tmp = sbus_readb(&cur->ccr); + + tmp |= CG14_CCR_ENABLE; + sbus_writeb(tmp, &cur->ccr); + } + sbus_writew(((c->cpos.fbx - c->chot.fbx) & 0xfff), &cur->cursx); + sbus_writew(((c->cpos.fby - c->chot.fby) & 0xfff), &cur->cursy); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_switch_from_graph (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + /* Set the 8-bpp mode */ if (fb->open && fb->mmaped){ volatile char *mcr = &fb->s.cg14.regs->mcr; + char tmp; fb->s.cg14.mode = 8; - *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); + tmp = sbus_readb(mcr); + tmp &= ~(CG14_MCR_PIXMODE_MASK); + sbus_writeb(tmp, mcr); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_reset (struct fb_info_sbusfb *fb) { volatile char *mcr = &fb->s.cg14.regs->mcr; + unsigned long flags; + char tmp; - *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); + tmp &= ~(CG14_MCR_PIXMODE_MASK); + sbus_writeb(tmp, mcr); + spin_unlock_irqrestore(&fb->lock, flags); } static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg) { volatile char *mcr = &fb->s.cg14.regs->mcr; struct mdi_cfginfo *mdii; - int mode; + unsigned long flags; + int mode, ret = 0; + char tmp; switch (cmd) { case MDI_RESET: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); + tmp &= ~CG14_MCR_PIXMODE_MASK; + sbus_writeb(tmp, mcr); + spin_unlock_irqrestore(&fb->lock, flags); break; case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; @@ -266,26 +308,35 @@ break; case MDI_SET_PIXELMODE: get_user_ret(mode, (int *)arg, -EFAULT); + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readb(mcr); switch (mode){ case MDI_32_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT); break; case MDI_16_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | 0x20; + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | 0x20; break; case MDI_8_PIX: - *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); + tmp = (tmp & ~CG14_MCR_PIXMODE_MASK); break; default: - return -ENOSYS; + ret = -ENOSYS; + break; + }; + if (ret == 0) { + sbus_writeb(tmp, mcr); + fb->s.cg14.mode = mode; } - fb->s.cg14.mode = mode; + spin_unlock_irqrestore(&fb->lock, flags); break; default: - return -EINVAL; - } - return 0; + ret = -EINVAL; + }; + + return ret; } static unsigned long __init get_phys(unsigned long addr) @@ -372,7 +423,7 @@ fb->reset = cg14_reset; fb->switch_from_graph = cg14_switch_from_graph; fb->ioctl = cg14_ioctl; - + fb->s.cg14.mode = 8; fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000; diff -u --recursive --new-file v2.3.34/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c --- v2.3.34/linux/drivers/video/cgsixfb.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/cgsixfb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.19 1999/08/10 15:56:03 davem Exp $ +/* $Id: cgsixfb.c,v 1.21 1999/11/19 09:56:57 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -31,15 +31,15 @@ * The FBC could be the frame buffer control * The FHC could is the frame buffer hardware control. */ -#define CG6_ROM_OFFSET 0x0 -#define CG6_BROOKTREE_OFFSET 0x200000 -#define CG6_DHC_OFFSET 0x240000 -#define CG6_ALT_OFFSET 0x280000 -#define CG6_FHC_OFFSET 0x300000 -#define CG6_THC_OFFSET 0x301000 -#define CG6_FBC_OFFSET 0x700000 -#define CG6_TEC_OFFSET 0x701000 -#define CG6_RAM_OFFSET 0x800000 +#define CG6_ROM_OFFSET 0x0UL +#define CG6_BROOKTREE_OFFSET 0x200000UL +#define CG6_DHC_OFFSET 0x240000UL +#define CG6_ALT_OFFSET 0x280000UL +#define CG6_FHC_OFFSET 0x300000UL +#define CG6_THC_OFFSET 0x301000UL +#define CG6_FBC_OFFSET 0x700000UL +#define CG6_TEC_OFFSET 0x701000UL +#define CG6_RAM_OFFSET 0x800000UL /* FHC definitions */ #define CG6_FHC_FBID_SHIFT 24 @@ -231,19 +231,21 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int x, y, w, h; int i; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_bgcol_ec(p,conp); - fbc->bg = attr_bgcol_ec(p,conp); - fbc->pixelm = ~(0); - fbc->alu = 0xea80ff00; - fbc->s = 0; - fbc->clip = 0; - fbc->pm = ~(0); + sbus_writel(attr_bgcol_ec(p,conp), &fbc->fg); + sbus_writel(attr_bgcol_ec(p,conp), &fbc->bg); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0xea80ff00, &fbc->alu); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(~0, &fbc->pm); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); @@ -255,13 +257,14 @@ } else { x = sx * fontwidth(p); w = width * fontwidth(p); } - fbc->arecty = y + fb->y_margin; - fbc->arectx = x + fb->x_margin; - fbc->arecty = y + fb->y_margin + h; - fbc->arectx = x + fb->x_margin + w; + sbus_writel(y + fb->y_margin, &fbc->arecty); + sbus_writel(x + fb->x_margin, &fbc->arectx); + sbus_writel(y + fb->y_margin + h, &fbc->arecty); + sbus_writel(x + fb->x_margin + w, &fbc->arectx); do { - i = fbc->draw; + i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -269,36 +272,41 @@ { int i; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_bgcol(p,s); - fbc->bg = attr_bgcol(p,s); - fbc->pixelm = ~(0); - fbc->alu = 0xea80ff00; - fbc->s = 0; - fbc->clip = 0; - fbc->pm = ~(0); + sbus_writel(attr_bgcol(p,s), &fbc->fg); + sbus_writel(attr_bgcol(p,s), &fbc->bg); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0xea80ff00, &fbc->alu); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(~0, &fbc->pm); while (count-- > 0) { - fbc->arecty = boxes[1]; - fbc->arectx = boxes[0]; - fbc->arecty = boxes[3]; - fbc->arectx = boxes[2]; + sbus_writel(boxes[1], &fbc->arecty); + sbus_writel(boxes[0], &fbc->arectx); + sbus_writel(boxes[3], &fbc->arecty); + sbus_writel(boxes[2], &fbc->arectx); boxes += 4; do { - i = fbc->draw; + i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = fb->y_margin + (yy << fontheightlog(p)); i = ((c & p->charmask) << fontheightlog(p)); @@ -315,30 +323,35 @@ else x = fb->x_margin + (xx * fontwidth(p)); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_fgcol(p,c); - fbc->bg = attr_bgcol(p,c); - fbc->mode = 0x140000; - fbc->alu = 0xe880fc30; - fbc->pixelm = ~(0); - fbc->s = 0; - fbc->clip = 0; - fbc->pm = 0xff; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = x + fontwidth(p) - 1; - fbc->y0 = y; + sbus_writel(attr_fgcol(p,c), &fbc->fg); + sbus_writel(attr_bgcol(p,c), &fbc->bg); + sbus_writel(0x140000, &fbc->mode); + sbus_writel(0xe880fc30, &fbc->alu); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(0xff, &fbc->pm); + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel(x + fontwidth(p) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontwidth(p) <= 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd++ << 24; + sbus_writel(val, &fbc->font); + } } else { for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd << 16; + u32 val = *(u16 *)fd << 16; + + sbus_writel(val, &fbc->font); fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -346,20 +359,22 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; + spin_lock_irqsave(&fb->lock, flags); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); - fbc->fg = attr_fgcol(p, scr_readw(s)); - fbc->bg = attr_bgcol(p, scr_readw(s)); - fbc->mode = 0x140000; - fbc->alu = 0xe880fc30; - fbc->pixelm = ~(0); - fbc->s = 0; - fbc->clip = 0; - fbc->pm = 0xff; + sbus_writel(attr_fgcol(p, scr_readw(s)), &fbc->fg); + sbus_writel(attr_bgcol(p, scr_readw(s)), &fbc->bg); + sbus_writel(0x140000, &fbc->mode); + sbus_writel(0xe880fc30, &fbc->alu); + sbus_writel(~0, &fbc->pixelm); + sbus_writel(0, &fbc->s); + sbus_writel(0, &fbc->clip); + sbus_writel(0xff, &fbc->pm); x = fb->x_margin; y = fb->y_margin; if (fontwidthlog(p)) @@ -373,11 +388,11 @@ if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += 4 * fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += 4 * fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); @@ -390,23 +405,36 @@ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { - for (i = 0; i < fontheight(p); i++) - fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) - << 8)) << 8)) << 8); + for (i = 0; i < fontheight(p); i++) { + u32 val = ((u32)*fd4++) | + ((((u32)*fd3++) | + ((((u32)*fd2++) | + (((u32)*fd1++) + << 8)) << 8)) << 8); + sbus_writel(val, &fbc->font); + } } else { - for (i = 0; i < fontheight(p); i++) - fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) - << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); + for (i = 0; i < fontheight(p); i++) { + u32 val = (((u32)*fd4++) | + ((((u32)*fd3++) | + ((((u32)*fd2++) | + (((u32)*fd1++) + << fontwidth(p))) << + fontwidth(p))) << + fontwidth(p))) << + (24 - 3 * fontwidth(p)); + sbus_writel(val, &fbc->font); + } } } } else { while (count >= 2) { count -= 2; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += 2 * fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); @@ -415,34 +443,40 @@ fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { - fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | + ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); + sbus_writel(val, &fbc->font); fd1 += 2; fd2 += 2; } } } while (count) { count--; - fbc->incx = 0; - fbc->incy = 1; - fbc->x0 = x; - fbc->x1 = (x += fontwidth(p)) - 1; - fbc->y0 = y; + sbus_writel(0, &fbc->incx); + sbus_writel(1, &fbc->incy); + sbus_writel(x, &fbc->x0); + sbus_writel((x += fontwidth(p)) - 1, &fbc->x1); + sbus_writel(y, &fbc->y0); if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; - for (i = 0; i < fontheight(p); i++) - fbc->font = *fd1++ << 24; + for (i = 0; i < fontheight(p); i++) { + u32 val = *fd1++ << 24; + sbus_writel(val, &fbc->font); + } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++) { - fbc->font = *(u16 *)fd1 << 16; + u32 val = *(u16 *)fd1 << 16; + sbus_writel(val, &fbc->font); fd1 += 2; } } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_revc(struct display *p, int xx, int yy) @@ -453,24 +487,33 @@ static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); bt->addr = index << 24; for (i = index; count--; i++){ - bt->color_map = fb->color_map CM(i,0) << 24; - bt->color_map = fb->color_map CM(i,1) << 24; - bt->color_map = fb->color_map CM(i,2) << 24; + sbus_writel(fb->color_map CM(i,0) << 24, + &bt->color_map); + sbus_writel(fb->color_map CM(i,1) << 24, + &bt->color_map); + sbus_writel(fb->color_map CM(i,2) << 24, + &bt->color_map); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; - bt->addr = 0; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; - bt->color_map = 0xffffffff; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(0, &bt->addr); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + sbus_writel(0xffffffff, &bt->color_map); + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch cg6_dispsw __initdata = { @@ -481,52 +524,77 @@ static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; - bt->addr = 1 << 24; - bt->cursor = red[0] << 24; - bt->cursor = green[0] << 24; - bt->cursor = blue[0] << 24; - bt->addr = 3 << 24; - bt->cursor = red[1] << 24; - bt->cursor = green[1] << 24; - bt->cursor = blue[1] << 24; + spin_lock_irqsave(&fb->lock, flags); + sbus_writel(1 << 24, &bt->addr); + sbus_writel(red[0] << 24, &bt->cursor); + sbus_writel(green[0] << 24, &bt->cursor); + sbus_writel(blue[0] << 24, &bt->cursor); + sbus_writel(3 << 24, &bt->addr); + sbus_writel(red[1] << 24, &bt->cursor); + sbus_writel(green[1] << 24, &bt->cursor); + sbus_writel(blue[1] << 24, &bt->cursor); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg6_setcurshape (struct fb_info_sbusfb *fb) { struct cg6_thc *thc = fb->s.cg6.thc; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++) { - thc->thc_cursmask [i] = fb->cursor.bits[0][i]; - thc->thc_cursbits [i] = fb->cursor.bits[1][i]; + sbus_writel(fb->cursor.bits[0][i], + &thc->thc_cursmask [i]); + sbus_writel(fb->cursor.bits[1][i], + &thc->thc_cursbits [i]); } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ static void cg6_setcursor (struct fb_info_sbusfb *fb) { unsigned int v; + unsigned long flags; struct cg_cursor *c = &fb->cursor; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); else /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); - fb->s.cg6.thc->thc_cursxy = v; + sbus_writel(v, &fb->s.cg6.thc->thc_cursxy); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_blank (struct fb_info_sbusfb *fb) { - fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); + tmp &= ~CG6_THC_MISC_VIDEO; + sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_unblank (struct fb_info_sbusfb *fb) { - fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO; + unsigned long flags; + u32 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg6.thc->thc_misc); + tmp |= CG6_THC_MISC_VIDEO; + sbus_writel(tmp, &fb->s.cg6.thc->thc_misc); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_reset (struct fb_info_sbusfb *fb) @@ -534,32 +602,35 @@ unsigned int rev, conf; struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; - u32 mode; + unsigned long flags; + u32 mode, tmp; int i; + spin_lock_irqsave(&fb->lock, flags); + /* Turn off stuff in the Transform Engine. */ - tec->tec_matrix = 0; - tec->tec_clip = 0; - tec->tec_vdc = 0; + sbus_writel(0, &tec->tec_matrix); + sbus_writel(0, &tec->tec_clip); + sbus_writel(0, &tec->tec_vdc); /* Take care of bugs in old revisions. */ - rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; + rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; if (rev < 5) { - conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | + conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | CG6_FHC_CPU_68020 | CG6_FHC_TEST | (11 << CG6_FHC_TEST_X_SHIFT) | (11 << CG6_FHC_TEST_Y_SHIFT); if (rev < 2) conf |= CG6_FHC_DST_DISABLE; - *(fb->s.cg6.fhc) = conf; + sbus_writel(conf, fb->s.cg6.fhc); } /* Set things in the FBC. Bad things appear to happen if we do * back to back store/loads on the mode register, so copy it * out instead. */ - mode = fbc->mode; + mode = sbus_readl(&fbc->mode); do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | @@ -569,23 +640,29 @@ CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | CG6_FBC_BDISP_0); - fbc->mode = mode; + sbus_writel(mode, &fbc->mode); + + sbus_writel(0, &fbc->clip); + sbus_writel(0, &fbc->offx); + sbus_writel(0, &fbc->offy); + sbus_writel(0, &fbc->clipminx); + sbus_writel(0, &fbc->clipminy); + sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx); + sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy); - fbc->clip = 0; - fbc->offx = 0; - fbc->offy = 0; - fbc->clipminx = 0; - fbc->clipminy = 0; - fbc->clipmaxx = fb->type.fb_width - 1; - fbc->clipmaxy = fb->type.fb_height - 1; /* Enable cursor in Brooktree DAC. */ - fb->s.cg6.bt->addr = 0x06 << 24; - fb->s.cg6.bt->control |= 0x03 << 24; + sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr); + tmp = sbus_readl(&fb->s.cg6.bt->control); + tmp |= 0x03 << 24; + sbus_writel(tmp, &fb->s.cg6.bt->control); + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static int __init cg6_rasterimg (struct fb_info *info, int start) @@ -595,7 +672,7 @@ int i; do { - i = fbc->s; + i = sbus_readl(&fbc->s); } while (i & 0x10000000); return 0; } @@ -608,7 +685,8 @@ struct fb_var_screeninfo *var = &fb->var; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; u32 conf; char *p; char *cardtype; @@ -616,7 +694,8 @@ struct fb_ops *fbops; fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); - if (!fbops) return NULL; + if (fbops == NULL) + return NULL; *fbops = *fb->info.fbops; fbops->fb_rasterimg = cg6_rasterimg; @@ -633,20 +712,40 @@ var->accel_flags = FB_ACCELF_TEXT; disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, - type->fb_size, "cgsix_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET, + type->fb_size, "cgsix ram"); + } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; - fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, - 4096, "cgsix_fbc", fb->iospace, 0); - fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, - sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0); - fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, - sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0); - fb->s.cg6.bt = bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, - sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0); - fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, - sizeof(u32), "cgsix_fhc", fb->iospace, 0); + fb->s.cg6.fbc = (struct cg6_fbc *) + sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET, + 4096, "cgsix fbc"); + fb->s.cg6.tec = (struct cg6_tec *) + sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET, + sizeof(struct cg6_tec), "cgsix tec"); + fb->s.cg6.thc = (struct cg6_thc *) + sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET, + sizeof(struct cg6_thc), "cgsix thc"); + fb->s.cg6.bt = bt = (struct bt_regs *) + sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET, + sizeof(struct bt_regs), "cgsix dac"); + fb->s.cg6.fhc = (u32 *) + sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET, + sizeof(u32), "cgsix fhc"); +#if 0 + prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n", + sdev->resource[0].start, + sdev->resource[0].end, + sdev->resource[0].flags); + prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n", + fb->s.cg6.fbc, + fb->s.cg6.tec, + fb->s.cg6.thc, + fb->s.cg6.bt, + fb->s.cg6.fhc); + prom_halt(); +#endif fb->dispsw = cg6_dispsw; fb->margins = cg6_margins; @@ -664,16 +763,16 @@ fb->mmap_map = cg6_mmap_map; /* Initialize Brooktree DAC */ - bt->addr = 0x04 << 24; /* color planes */ - bt->control = 0xff << 24; - bt->addr = 0x05 << 24; - bt->control = 0x00 << 24; - bt->addr = 0x06 << 24; /* overlay plane */ - bt->control = 0x73 << 24; - bt->addr = 0x07 << 24; - bt->control = 0x00 << 24; + sbus_writel(0x04 << 24, &bt->addr); /* color planes */ + sbus_writel(0xff << 24, &bt->control); + sbus_writel(0x05 << 24, &bt->addr); + sbus_writel(0x00 << 24, &bt->control); + sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */ + sbus_writel(0x73 << 24, &bt->control); + sbus_writel(0x07 << 24, &bt->addr); + sbus_writel(0x00 << 24, &bt->control); - conf = *fb->s.cg6.fhc; + conf = sbus_readl(fb->s.cg6.fhc); switch(conf & CG6_FHC_CPU_MASK) { case CG6_FHC_CPU_SPARC: p = "sparc"; break; case CG6_FHC_CPU_68020: p = "68020"; break; @@ -696,12 +795,14 @@ sprintf(idstring, #ifdef __sparc_v9__ - "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, + "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, #else - "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, + "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", + fb->iospace, phys, #endif - (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, - p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype); + ((sbus_readl(&fb->s.cg6.thc->thc_misc) >> CG6_THC_MISC_REV_SHIFT) & + CG6_THC_MISC_REV_MASK), + p, (conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK, cardtype); sprintf(fb->info.modename, "CGsix [%s]", cardtype); sprintf(fix->id, "CGsix [%s]", cardtype); diff -u --recursive --new-file v2.3.34/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c --- v2.3.34/linux/drivers/video/cgthreefb.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/cgthreefb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: cgthreefb.c,v 1.5 1999/08/10 15:56:04 davem Exp $ +/* $Id: cgthreefb.c,v 1.8 1999/11/19 09:57:08 davem Exp $ * cgthreefb.c: CGthree frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -71,8 +71,8 @@ }; /* Offset of interesting structures in the OBIO space */ -#define CG3_REGS_OFFSET 0x400000 -#define CG3_RAM_OFFSET 0x800000 +#define CG3_REGS_OFFSET 0x400000UL +#define CG3_RAM_OFFSET 0x800000UL static struct sbus_mmap_map cg3_mmap_map[] = { { CG3_MMAP_OFFSET, CG3_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, @@ -88,30 +88,55 @@ static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = &fb->s.cg3.regs->cmap; + unsigned long flags; u32 *i; + volatile u8 *regp; int steps; + spin_lock_irqsave(&fb->lock, flags); + i = (((u32 *)fb->color_map) + D4M3(index)); steps = D4M3(index+count-1) - D4M3(index)+3; - *(volatile u8 *)&bt->addr = (u8)D4M4(index); - while (steps--) - bt->color_map = *i++; + regp = (volatile u8 *)&bt->addr; + sbus_writeb(D4M4(index), regp); + while (steps--) { + u32 val = *i++; + sbus_writel(val, &bt->color_map); + } + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_blank (struct fb_info_sbusfb *fb) { - fb->s.cg3.regs->control &= ~CG3_CR_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp &= ~CG3_CR_ENABLE_VIDEO; + sbus_writel(tmp, &fb->s.cg3.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_unblank (struct fb_info_sbusfb *fb) { - fb->s.cg3.regs->control |= CG3_CR_ENABLE_VIDEO; + unsigned long flags; + u8 tmp; + + spin_lock_irqsave(&fb->lock, flags); + tmp = sbus_readl(&fb->s.cg3.regs->control); + tmp |= CG3_CR_ENABLE_VIDEO; + sbus_writel(tmp, &fb->s.cg3.regs->control); + spin_unlock_irqrestore(&fb->lock, flags); } -static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, + int x_margin, int y_margin) { - p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); + p->screen_base += (y_margin - fb->y_margin) * + p->line_length + (x_margin - fb->x_margin); } static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */ @@ -150,7 +175,8 @@ struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; - unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + struct sbus_dev *sdev = fb->sbdp; + unsigned long phys = sdev->reg_addrs[0].phys_addr; int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; #ifndef FBCON_HAS_CFB8 @@ -158,8 +184,9 @@ #endif if (!fb->s.cg3.regs) { - fb->s.cg3.regs = (struct cg3_regs *)sparc_alloc_io(phys+CG3_REGS_OFFSET, 0, - sizeof(struct cg3_regs), "cg3_regs", fb->iospace, 0); + fb->s.cg3.regs = (struct cg3_regs *) + sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, + sizeof(struct cg3_regs), "cg3 regs"); if (cgRDI) { char buffer[40]; char *p; @@ -189,9 +216,11 @@ fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; - if (!disp->screen_base) - disp->screen_base = (char *)sparc_alloc_io(phys+CG3_RAM_OFFSET, 0, - type->fb_size, "cg3_ram", fb->iospace, 0); + if (!disp->screen_base) { + disp->screen_base = (char *) + sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET, + type->fb_size, "cg3 ram"); + } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->dispsw = fbcon_cfb8; @@ -219,7 +248,7 @@ if (cgRDI) type = CG3_RDI; else { - u8 status = fb->s.cg3.regs->status, mon; + u8 status = sbus_readb(&fb->s.cg3.regs->status), mon; if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) { mon = status & CG3_SR_RES_MASK; if (mon == CG3_SR_1152_900_76_A || @@ -235,12 +264,17 @@ } } - for (p = cg3_regvals[type]; *p; p += 2) - ((u8 *)fb->s.cg3.regs)[p[0]] = p[1]; - + for (p = cg3_regvals[type]; *p; p += 2) { + u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]]; + sbus_writeb(p[1], regp); + } for (p = cg3_dacvals; *p; p += 2) { - *(volatile u8 *)&fb->s.cg3.regs->cmap.addr = p[0]; - *(volatile u8 *)&fb->s.cg3.regs->cmap.control = p[1]; + volatile u8 *regp; + + regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr; + sbus_writeb(p[0], regp); + regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control; + sbus_writeb(p[1], regp); } } diff -u --recursive --new-file v2.3.34/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c --- v2.3.34/linux/drivers/video/creatorfb.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/creatorfb.c Mon Dec 20 22:06:42 1999 @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $ +/* $Id: creatorfb.c,v 1.31 1999/11/19 09:57:12 davem Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -21,6 +21,8 @@ #include